mirror of
https://github.com/4yn/slidershim.git
synced 2024-11-14 09:47:40 +01:00
use statically linked interception library for directinput emulation
This commit is contained in:
parent
0e75256520
commit
571eec24d3
1
src-interception/.gitignore
vendored
Normal file
1
src-interception/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
target/
|
140
src-interception/Cargo.lock
generated
Normal file
140
src-interception/Cargo.lock
generated
Normal file
@ -0,0 +1,140 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 3
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cc"
|
||||||
|
version = "1.0.73"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "interception"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"cc",
|
||||||
|
"num_enum",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_enum"
|
||||||
|
version = "0.5.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9"
|
||||||
|
dependencies = [
|
||||||
|
"num_enum_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_enum_derive"
|
||||||
|
version = "0.5.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-crate",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-crate"
|
||||||
|
version = "1.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror",
|
||||||
|
"toml",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.40"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde"
|
||||||
|
version = "1.0.140"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fc855a42c7967b7c369eb5860f7164ef1f6f81c20c7cc1141f2a604e18723b03"
|
||||||
|
dependencies = [
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive"
|
||||||
|
version = "1.0.140"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f2122636b9fe3b81f1cb25099fcf2d3f542cdb1d45940d56c713158884a05da"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "1.0.98"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "1.0.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "1.0.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.5.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7"
|
13
src-interception/Cargo.toml
Normal file
13
src-interception/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "interception"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2018"
|
||||||
|
publish = false
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
cc = "1.0"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
bitflags = "1.2.1"
|
||||||
|
num_enum = "0.5.0"
|
||||||
|
serde = { version = "1.0.114", features = ["derive"] }
|
173
src-interception/README.md
Normal file
173
src-interception/README.md
Normal file
@ -0,0 +1,173 @@
|
|||||||
|
Derived from https://github.com/bozbez/interception-sys and https://github.com/bozbez/interception-rs
|
||||||
|
|
||||||
|
Repackaged to link statically with https://github.com/oblitum/Interception 1.0.1 instead of using dynamic library.
|
||||||
|
|
||||||
|
Interception is licensed under LGPL 3.0 for non-commercial use. Interception-sys and interception-rs according to its Cargo.toml are licensed under LGPL 3.0.
|
||||||
|
|
||||||
|
```
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
|
||||||
|
This version of the GNU Lesser General Public License incorporates
|
||||||
|
the terms and conditions of version 3 of the GNU General Public
|
||||||
|
License, supplemented by the additional permissions listed below.
|
||||||
|
|
||||||
|
0. Additional Definitions.
|
||||||
|
|
||||||
|
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||||
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||||
|
General Public License.
|
||||||
|
|
||||||
|
"The Library" refers to a covered work governed by this License,
|
||||||
|
other than an Application or a Combined Work as defined below.
|
||||||
|
|
||||||
|
An "Application" is any work that makes use of an interface provided
|
||||||
|
by the Library, but which is not otherwise based on the Library.
|
||||||
|
Defining a subclass of a class defined by the Library is deemed a mode
|
||||||
|
of using an interface provided by the Library.
|
||||||
|
|
||||||
|
A "Combined Work" is a work produced by combining or linking an
|
||||||
|
Application with the Library. The particular version of the Library
|
||||||
|
with which the Combined Work was made is also called the "Linked
|
||||||
|
Version".
|
||||||
|
|
||||||
|
The "Minimal Corresponding Source" for a Combined Work means the
|
||||||
|
Corresponding Source for the Combined Work, excluding any source code
|
||||||
|
for portions of the Combined Work that, considered in isolation, are
|
||||||
|
based on the Application, and not on the Linked Version.
|
||||||
|
|
||||||
|
The "Corresponding Application Code" for a Combined Work means the
|
||||||
|
object code and/or source code for the Application, including any data
|
||||||
|
and utility programs needed for reproducing the Combined Work from the
|
||||||
|
Application, but excluding the System Libraries of the Combined Work.
|
||||||
|
|
||||||
|
1. Exception to Section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
You may convey a covered work under sections 3 and 4 of this License
|
||||||
|
without being bound by section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
2. Conveying Modified Versions.
|
||||||
|
|
||||||
|
If you modify a copy of the Library, and, in your modifications, a
|
||||||
|
facility refers to a function or data to be supplied by an Application
|
||||||
|
that uses the facility (other than as an argument passed when the
|
||||||
|
facility is invoked), then you may convey a copy of the modified
|
||||||
|
version:
|
||||||
|
|
||||||
|
a) under this License, provided that you make a good faith effort to
|
||||||
|
ensure that, in the event an Application does not supply the
|
||||||
|
function or data, the facility still operates, and performs
|
||||||
|
whatever part of its purpose remains meaningful, or
|
||||||
|
|
||||||
|
b) under the GNU GPL, with none of the additional permissions of
|
||||||
|
this License applicable to that copy.
|
||||||
|
|
||||||
|
3. Object Code Incorporating Material from Library Header Files.
|
||||||
|
|
||||||
|
The object code form of an Application may incorporate material from
|
||||||
|
a header file that is part of the Library. You may convey such object
|
||||||
|
code under terms of your choice, provided that, if the incorporated
|
||||||
|
material is not limited to numerical parameters, data structure
|
||||||
|
layouts and accessors, or small macros, inline functions and templates
|
||||||
|
(ten or fewer lines in length), you do both of the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the object code that the
|
||||||
|
Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
4. Combined Works.
|
||||||
|
|
||||||
|
You may convey a Combined Work under terms of your choice that,
|
||||||
|
taken together, effectively do not restrict modification of the
|
||||||
|
portions of the Library contained in the Combined Work and reverse
|
||||||
|
engineering for debugging such modifications, if you also do each of
|
||||||
|
the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the Combined Work that
|
||||||
|
the Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
c) For a Combined Work that displays copyright notices during
|
||||||
|
execution, include the copyright notice for the Library among
|
||||||
|
these notices, as well as a reference directing the user to the
|
||||||
|
copies of the GNU GPL and this license document.
|
||||||
|
|
||||||
|
d) Do one of the following:
|
||||||
|
|
||||||
|
0) Convey the Minimal Corresponding Source under the terms of this
|
||||||
|
License, and the Corresponding Application Code in a form
|
||||||
|
suitable for, and under terms that permit, the user to
|
||||||
|
recombine or relink the Application with a modified version of
|
||||||
|
the Linked Version to produce a modified Combined Work, in the
|
||||||
|
manner specified by section 6 of the GNU GPL for conveying
|
||||||
|
Corresponding Source.
|
||||||
|
|
||||||
|
1) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (a) uses at run time
|
||||||
|
a copy of the Library already present on the user's computer
|
||||||
|
system, and (b) will operate properly with a modified version
|
||||||
|
of the Library that is interface-compatible with the Linked
|
||||||
|
Version.
|
||||||
|
|
||||||
|
e) Provide Installation Information, but only if you would otherwise
|
||||||
|
be required to provide such information under section 6 of the
|
||||||
|
GNU GPL, and only to the extent that such information is
|
||||||
|
necessary to install and execute a modified version of the
|
||||||
|
Combined Work produced by recombining or relinking the
|
||||||
|
Application with a modified version of the Linked Version. (If
|
||||||
|
you use option 4d0, the Installation Information must accompany
|
||||||
|
the Minimal Corresponding Source and Corresponding Application
|
||||||
|
Code. If you use option 4d1, you must provide the Installation
|
||||||
|
Information in the manner specified by section 6 of the GNU GPL
|
||||||
|
for conveying Corresponding Source.)
|
||||||
|
|
||||||
|
5. Combined Libraries.
|
||||||
|
|
||||||
|
You may place library facilities that are a work based on the
|
||||||
|
Library side by side in a single library together with other library
|
||||||
|
facilities that are not Applications and are not covered by this
|
||||||
|
License, and convey such a combined library under terms of your
|
||||||
|
choice, if you do both of the following:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work based
|
||||||
|
on the Library, uncombined with any other library facilities,
|
||||||
|
conveyed under the terms of this License.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library that part of it
|
||||||
|
is a work based on the Library, and explaining where to find the
|
||||||
|
accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
6. Revised Versions of the GNU Lesser General Public License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the GNU Lesser General Public License from time to time. Such new
|
||||||
|
versions will be similar in spirit to the present version, but may
|
||||||
|
differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Library as you received it specifies that a certain numbered version
|
||||||
|
of the GNU Lesser General Public License "or any later version"
|
||||||
|
applies to it, you have the option of following the terms and
|
||||||
|
conditions either of that published version or of any later version
|
||||||
|
published by the Free Software Foundation. If the Library as you
|
||||||
|
received it does not specify a version number of the GNU Lesser
|
||||||
|
General Public License, you may choose any version of the GNU Lesser
|
||||||
|
General Public License ever published by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Library as you received it specifies that a proxy can decide
|
||||||
|
whether future versions of the GNU Lesser General Public License shall
|
||||||
|
apply, that proxy's public statement of acceptance of any version is
|
||||||
|
permanent authorization for you to choose that version for the
|
||||||
|
Library.
|
||||||
|
```
|
11
src-interception/build.rs
Normal file
11
src-interception/build.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fn main() {
|
||||||
|
println!("cargo:rerun-if-changed=include/interception.h");
|
||||||
|
println!("cargo:rerun-if-changed=src/interception.c");
|
||||||
|
cc::Build::new()
|
||||||
|
.define("INTERCEPTION_STATIC", None)
|
||||||
|
.file("src/interception.c")
|
||||||
|
.include("include/")
|
||||||
|
.compile("interception");
|
||||||
|
|
||||||
|
println!("cargo:rustc-link-lib=static=interception");
|
||||||
|
}
|
194
src-interception/include/interception.h
Normal file
194
src-interception/include/interception.h
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
#ifndef _INTERCEPTION_H_
|
||||||
|
#define _INTERCEPTION_H_
|
||||||
|
|
||||||
|
#ifdef INTERCEPTION_STATIC
|
||||||
|
#define INTERCEPTION_API
|
||||||
|
#else
|
||||||
|
#if defined _WIN32 || defined __CYGWIN__
|
||||||
|
#ifdef INTERCEPTION_EXPORT
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define INTERCEPTION_API __attribute__((dllexport))
|
||||||
|
#else
|
||||||
|
#define INTERCEPTION_API __declspec(dllexport)
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#define INTERCEPTION_API __attribute__((dllimport))
|
||||||
|
#else
|
||||||
|
#define INTERCEPTION_API __declspec(dllimport)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#if __GNUC__ >= 4
|
||||||
|
#define INTERCEPTION_API __attribute__ ((visibility("default")))
|
||||||
|
#else
|
||||||
|
#define INTERCEPTION_API
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define INTERCEPTION_MAX_KEYBOARD 10
|
||||||
|
|
||||||
|
#define INTERCEPTION_MAX_MOUSE 10
|
||||||
|
|
||||||
|
#define INTERCEPTION_MAX_DEVICE ((INTERCEPTION_MAX_KEYBOARD) + (INTERCEPTION_MAX_MOUSE))
|
||||||
|
|
||||||
|
#define INTERCEPTION_KEYBOARD(index) ((index) + 1)
|
||||||
|
|
||||||
|
#define INTERCEPTION_MOUSE(index) ((INTERCEPTION_MAX_KEYBOARD) + (index) + 1)
|
||||||
|
|
||||||
|
typedef void *InterceptionContext;
|
||||||
|
|
||||||
|
typedef int InterceptionDevice;
|
||||||
|
|
||||||
|
typedef int InterceptionPrecedence;
|
||||||
|
|
||||||
|
typedef unsigned short InterceptionFilter;
|
||||||
|
|
||||||
|
typedef int (*InterceptionPredicate)(InterceptionDevice device);
|
||||||
|
|
||||||
|
enum InterceptionKeyState
|
||||||
|
{
|
||||||
|
INTERCEPTION_KEY_DOWN = 0x00,
|
||||||
|
INTERCEPTION_KEY_UP = 0x01,
|
||||||
|
INTERCEPTION_KEY_E0 = 0x02,
|
||||||
|
INTERCEPTION_KEY_E1 = 0x04,
|
||||||
|
INTERCEPTION_KEY_TERMSRV_SET_LED = 0x08,
|
||||||
|
INTERCEPTION_KEY_TERMSRV_SHADOW = 0x10,
|
||||||
|
INTERCEPTION_KEY_TERMSRV_VKPACKET = 0x20
|
||||||
|
};
|
||||||
|
|
||||||
|
enum InterceptionFilterKeyState
|
||||||
|
{
|
||||||
|
INTERCEPTION_FILTER_KEY_NONE = 0x0000,
|
||||||
|
INTERCEPTION_FILTER_KEY_ALL = 0xFFFF,
|
||||||
|
INTERCEPTION_FILTER_KEY_DOWN = INTERCEPTION_KEY_UP,
|
||||||
|
INTERCEPTION_FILTER_KEY_UP = INTERCEPTION_KEY_UP << 1,
|
||||||
|
INTERCEPTION_FILTER_KEY_E0 = INTERCEPTION_KEY_E0 << 1,
|
||||||
|
INTERCEPTION_FILTER_KEY_E1 = INTERCEPTION_KEY_E1 << 1,
|
||||||
|
INTERCEPTION_FILTER_KEY_TERMSRV_SET_LED = INTERCEPTION_KEY_TERMSRV_SET_LED << 1,
|
||||||
|
INTERCEPTION_FILTER_KEY_TERMSRV_SHADOW = INTERCEPTION_KEY_TERMSRV_SHADOW << 1,
|
||||||
|
INTERCEPTION_FILTER_KEY_TERMSRV_VKPACKET = INTERCEPTION_KEY_TERMSRV_VKPACKET << 1
|
||||||
|
};
|
||||||
|
|
||||||
|
enum InterceptionMouseState
|
||||||
|
{
|
||||||
|
INTERCEPTION_MOUSE_LEFT_BUTTON_DOWN = 0x001,
|
||||||
|
INTERCEPTION_MOUSE_LEFT_BUTTON_UP = 0x002,
|
||||||
|
INTERCEPTION_MOUSE_RIGHT_BUTTON_DOWN = 0x004,
|
||||||
|
INTERCEPTION_MOUSE_RIGHT_BUTTON_UP = 0x008,
|
||||||
|
INTERCEPTION_MOUSE_MIDDLE_BUTTON_DOWN = 0x010,
|
||||||
|
INTERCEPTION_MOUSE_MIDDLE_BUTTON_UP = 0x020,
|
||||||
|
|
||||||
|
INTERCEPTION_MOUSE_BUTTON_1_DOWN = INTERCEPTION_MOUSE_LEFT_BUTTON_DOWN,
|
||||||
|
INTERCEPTION_MOUSE_BUTTON_1_UP = INTERCEPTION_MOUSE_LEFT_BUTTON_UP,
|
||||||
|
INTERCEPTION_MOUSE_BUTTON_2_DOWN = INTERCEPTION_MOUSE_RIGHT_BUTTON_DOWN,
|
||||||
|
INTERCEPTION_MOUSE_BUTTON_2_UP = INTERCEPTION_MOUSE_RIGHT_BUTTON_UP,
|
||||||
|
INTERCEPTION_MOUSE_BUTTON_3_DOWN = INTERCEPTION_MOUSE_MIDDLE_BUTTON_DOWN,
|
||||||
|
INTERCEPTION_MOUSE_BUTTON_3_UP = INTERCEPTION_MOUSE_MIDDLE_BUTTON_UP,
|
||||||
|
|
||||||
|
INTERCEPTION_MOUSE_BUTTON_4_DOWN = 0x040,
|
||||||
|
INTERCEPTION_MOUSE_BUTTON_4_UP = 0x080,
|
||||||
|
INTERCEPTION_MOUSE_BUTTON_5_DOWN = 0x100,
|
||||||
|
INTERCEPTION_MOUSE_BUTTON_5_UP = 0x200,
|
||||||
|
|
||||||
|
INTERCEPTION_MOUSE_WHEEL = 0x400,
|
||||||
|
INTERCEPTION_MOUSE_HWHEEL = 0x800
|
||||||
|
};
|
||||||
|
|
||||||
|
enum InterceptionFilterMouseState
|
||||||
|
{
|
||||||
|
INTERCEPTION_FILTER_MOUSE_NONE = 0x0000,
|
||||||
|
INTERCEPTION_FILTER_MOUSE_ALL = 0xFFFF,
|
||||||
|
|
||||||
|
INTERCEPTION_FILTER_MOUSE_LEFT_BUTTON_DOWN = INTERCEPTION_MOUSE_LEFT_BUTTON_DOWN,
|
||||||
|
INTERCEPTION_FILTER_MOUSE_LEFT_BUTTON_UP = INTERCEPTION_MOUSE_LEFT_BUTTON_UP,
|
||||||
|
INTERCEPTION_FILTER_MOUSE_RIGHT_BUTTON_DOWN = INTERCEPTION_MOUSE_RIGHT_BUTTON_DOWN,
|
||||||
|
INTERCEPTION_FILTER_MOUSE_RIGHT_BUTTON_UP = INTERCEPTION_MOUSE_RIGHT_BUTTON_UP,
|
||||||
|
INTERCEPTION_FILTER_MOUSE_MIDDLE_BUTTON_DOWN = INTERCEPTION_MOUSE_MIDDLE_BUTTON_DOWN,
|
||||||
|
INTERCEPTION_FILTER_MOUSE_MIDDLE_BUTTON_UP = INTERCEPTION_MOUSE_MIDDLE_BUTTON_UP,
|
||||||
|
|
||||||
|
INTERCEPTION_FILTER_MOUSE_BUTTON_1_DOWN = INTERCEPTION_MOUSE_BUTTON_1_DOWN,
|
||||||
|
INTERCEPTION_FILTER_MOUSE_BUTTON_1_UP = INTERCEPTION_MOUSE_BUTTON_1_UP,
|
||||||
|
INTERCEPTION_FILTER_MOUSE_BUTTON_2_DOWN = INTERCEPTION_MOUSE_BUTTON_2_DOWN,
|
||||||
|
INTERCEPTION_FILTER_MOUSE_BUTTON_2_UP = INTERCEPTION_MOUSE_BUTTON_2_UP,
|
||||||
|
INTERCEPTION_FILTER_MOUSE_BUTTON_3_DOWN = INTERCEPTION_MOUSE_BUTTON_3_DOWN,
|
||||||
|
INTERCEPTION_FILTER_MOUSE_BUTTON_3_UP = INTERCEPTION_MOUSE_BUTTON_3_UP,
|
||||||
|
|
||||||
|
INTERCEPTION_FILTER_MOUSE_BUTTON_4_DOWN = INTERCEPTION_MOUSE_BUTTON_4_DOWN,
|
||||||
|
INTERCEPTION_FILTER_MOUSE_BUTTON_4_UP = INTERCEPTION_MOUSE_BUTTON_4_UP,
|
||||||
|
INTERCEPTION_FILTER_MOUSE_BUTTON_5_DOWN = INTERCEPTION_MOUSE_BUTTON_5_DOWN,
|
||||||
|
INTERCEPTION_FILTER_MOUSE_BUTTON_5_UP = INTERCEPTION_MOUSE_BUTTON_5_UP,
|
||||||
|
|
||||||
|
INTERCEPTION_FILTER_MOUSE_WHEEL = INTERCEPTION_MOUSE_WHEEL,
|
||||||
|
INTERCEPTION_FILTER_MOUSE_HWHEEL = INTERCEPTION_MOUSE_HWHEEL,
|
||||||
|
|
||||||
|
INTERCEPTION_FILTER_MOUSE_MOVE = 0x1000
|
||||||
|
};
|
||||||
|
|
||||||
|
enum InterceptionMouseFlag
|
||||||
|
{
|
||||||
|
INTERCEPTION_MOUSE_MOVE_RELATIVE = 0x000,
|
||||||
|
INTERCEPTION_MOUSE_MOVE_ABSOLUTE = 0x001,
|
||||||
|
INTERCEPTION_MOUSE_VIRTUAL_DESKTOP = 0x002,
|
||||||
|
INTERCEPTION_MOUSE_ATTRIBUTES_CHANGED = 0x004,
|
||||||
|
INTERCEPTION_MOUSE_MOVE_NOCOALESCE = 0x008,
|
||||||
|
INTERCEPTION_MOUSE_TERMSRV_SRC_SHADOW = 0x100
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned short state;
|
||||||
|
unsigned short flags;
|
||||||
|
short rolling;
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
unsigned int information;
|
||||||
|
} InterceptionMouseStroke;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned short code;
|
||||||
|
unsigned short state;
|
||||||
|
unsigned int information;
|
||||||
|
} InterceptionKeyStroke;
|
||||||
|
|
||||||
|
typedef char InterceptionStroke[sizeof(InterceptionMouseStroke)];
|
||||||
|
|
||||||
|
InterceptionContext INTERCEPTION_API interception_create_context(void);
|
||||||
|
|
||||||
|
void INTERCEPTION_API interception_destroy_context(InterceptionContext context);
|
||||||
|
|
||||||
|
InterceptionPrecedence INTERCEPTION_API interception_get_precedence(InterceptionContext context, InterceptionDevice device);
|
||||||
|
|
||||||
|
void INTERCEPTION_API interception_set_precedence(InterceptionContext context, InterceptionDevice device, InterceptionPrecedence precedence);
|
||||||
|
|
||||||
|
InterceptionFilter INTERCEPTION_API interception_get_filter(InterceptionContext context, InterceptionDevice device);
|
||||||
|
|
||||||
|
void INTERCEPTION_API interception_set_filter(InterceptionContext context, InterceptionPredicate predicate, InterceptionFilter filter);
|
||||||
|
|
||||||
|
InterceptionDevice INTERCEPTION_API interception_wait(InterceptionContext context);
|
||||||
|
|
||||||
|
InterceptionDevice INTERCEPTION_API interception_wait_with_timeout(InterceptionContext context, unsigned long milliseconds);
|
||||||
|
|
||||||
|
int INTERCEPTION_API interception_send(InterceptionContext context, InterceptionDevice device, const InterceptionStroke *stroke, unsigned int nstroke);
|
||||||
|
|
||||||
|
int INTERCEPTION_API interception_receive(InterceptionContext context, InterceptionDevice device, InterceptionStroke *stroke, unsigned int nstroke);
|
||||||
|
|
||||||
|
unsigned int INTERCEPTION_API interception_get_hardware_id(InterceptionContext context, InterceptionDevice device, void *hardware_id_buffer, unsigned int buffer_size);
|
||||||
|
|
||||||
|
int INTERCEPTION_API interception_is_invalid(InterceptionDevice device);
|
||||||
|
|
||||||
|
int INTERCEPTION_API interception_is_keyboard(InterceptionDevice device);
|
||||||
|
|
||||||
|
int INTERCEPTION_API interception_is_mouse(InterceptionDevice device);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
315
src-interception/src/bindings.rs
Normal file
315
src-interception/src/bindings.rs
Normal file
@ -0,0 +1,315 @@
|
|||||||
|
/* automatically generated by rust-bindgen 0.54.1 */
|
||||||
|
|
||||||
|
pub const INTERCEPTION_MAX_KEYBOARD: u32 = 10;
|
||||||
|
pub const INTERCEPTION_MAX_MOUSE: u32 = 10;
|
||||||
|
pub const INTERCEPTION_MAX_DEVICE: u32 = 20;
|
||||||
|
pub type InterceptionContext = *mut ::std::os::raw::c_void;
|
||||||
|
pub type InterceptionDevice = ::std::os::raw::c_int;
|
||||||
|
pub type InterceptionPrecedence = ::std::os::raw::c_int;
|
||||||
|
pub type InterceptionFilter = ::std::os::raw::c_ushort;
|
||||||
|
pub type InterceptionPredicate = ::std::option::Option<
|
||||||
|
unsafe extern "C" fn(device: InterceptionDevice) -> ::std::os::raw::c_int,
|
||||||
|
>;
|
||||||
|
pub const InterceptionKeyState_INTERCEPTION_KEY_DOWN: InterceptionKeyState = 0;
|
||||||
|
pub const InterceptionKeyState_INTERCEPTION_KEY_UP: InterceptionKeyState = 1;
|
||||||
|
pub const InterceptionKeyState_INTERCEPTION_KEY_E0: InterceptionKeyState = 2;
|
||||||
|
pub const InterceptionKeyState_INTERCEPTION_KEY_E1: InterceptionKeyState = 4;
|
||||||
|
pub const InterceptionKeyState_INTERCEPTION_KEY_TERMSRV_SET_LED: InterceptionKeyState = 8;
|
||||||
|
pub const InterceptionKeyState_INTERCEPTION_KEY_TERMSRV_SHADOW: InterceptionKeyState = 16;
|
||||||
|
pub const InterceptionKeyState_INTERCEPTION_KEY_TERMSRV_VKPACKET: InterceptionKeyState = 32;
|
||||||
|
pub type InterceptionKeyState = u32;
|
||||||
|
pub const InterceptionFilterKeyState_INTERCEPTION_FILTER_KEY_NONE: InterceptionFilterKeyState = 0;
|
||||||
|
pub const InterceptionFilterKeyState_INTERCEPTION_FILTER_KEY_ALL: InterceptionFilterKeyState =
|
||||||
|
65535;
|
||||||
|
pub const InterceptionFilterKeyState_INTERCEPTION_FILTER_KEY_DOWN: InterceptionFilterKeyState = 1;
|
||||||
|
pub const InterceptionFilterKeyState_INTERCEPTION_FILTER_KEY_UP: InterceptionFilterKeyState = 2;
|
||||||
|
pub const InterceptionFilterKeyState_INTERCEPTION_FILTER_KEY_E0: InterceptionFilterKeyState = 4;
|
||||||
|
pub const InterceptionFilterKeyState_INTERCEPTION_FILTER_KEY_E1: InterceptionFilterKeyState = 8;
|
||||||
|
pub const InterceptionFilterKeyState_INTERCEPTION_FILTER_KEY_TERMSRV_SET_LED:
|
||||||
|
InterceptionFilterKeyState = 16;
|
||||||
|
pub const InterceptionFilterKeyState_INTERCEPTION_FILTER_KEY_TERMSRV_SHADOW:
|
||||||
|
InterceptionFilterKeyState = 32;
|
||||||
|
pub const InterceptionFilterKeyState_INTERCEPTION_FILTER_KEY_TERMSRV_VKPACKET:
|
||||||
|
InterceptionFilterKeyState = 64;
|
||||||
|
pub type InterceptionFilterKeyState = u32;
|
||||||
|
pub const InterceptionMouseState_INTERCEPTION_MOUSE_LEFT_BUTTON_DOWN: InterceptionMouseState = 1;
|
||||||
|
pub const InterceptionMouseState_INTERCEPTION_MOUSE_LEFT_BUTTON_UP: InterceptionMouseState = 2;
|
||||||
|
pub const InterceptionMouseState_INTERCEPTION_MOUSE_RIGHT_BUTTON_DOWN: InterceptionMouseState = 4;
|
||||||
|
pub const InterceptionMouseState_INTERCEPTION_MOUSE_RIGHT_BUTTON_UP: InterceptionMouseState = 8;
|
||||||
|
pub const InterceptionMouseState_INTERCEPTION_MOUSE_MIDDLE_BUTTON_DOWN: InterceptionMouseState = 16;
|
||||||
|
pub const InterceptionMouseState_INTERCEPTION_MOUSE_MIDDLE_BUTTON_UP: InterceptionMouseState = 32;
|
||||||
|
pub const InterceptionMouseState_INTERCEPTION_MOUSE_BUTTON_1_DOWN: InterceptionMouseState = 1;
|
||||||
|
pub const InterceptionMouseState_INTERCEPTION_MOUSE_BUTTON_1_UP: InterceptionMouseState = 2;
|
||||||
|
pub const InterceptionMouseState_INTERCEPTION_MOUSE_BUTTON_2_DOWN: InterceptionMouseState = 4;
|
||||||
|
pub const InterceptionMouseState_INTERCEPTION_MOUSE_BUTTON_2_UP: InterceptionMouseState = 8;
|
||||||
|
pub const InterceptionMouseState_INTERCEPTION_MOUSE_BUTTON_3_DOWN: InterceptionMouseState = 16;
|
||||||
|
pub const InterceptionMouseState_INTERCEPTION_MOUSE_BUTTON_3_UP: InterceptionMouseState = 32;
|
||||||
|
pub const InterceptionMouseState_INTERCEPTION_MOUSE_BUTTON_4_DOWN: InterceptionMouseState = 64;
|
||||||
|
pub const InterceptionMouseState_INTERCEPTION_MOUSE_BUTTON_4_UP: InterceptionMouseState = 128;
|
||||||
|
pub const InterceptionMouseState_INTERCEPTION_MOUSE_BUTTON_5_DOWN: InterceptionMouseState = 256;
|
||||||
|
pub const InterceptionMouseState_INTERCEPTION_MOUSE_BUTTON_5_UP: InterceptionMouseState = 512;
|
||||||
|
pub const InterceptionMouseState_INTERCEPTION_MOUSE_WHEEL: InterceptionMouseState = 1024;
|
||||||
|
pub const InterceptionMouseState_INTERCEPTION_MOUSE_HWHEEL: InterceptionMouseState = 2048;
|
||||||
|
pub type InterceptionMouseState = u32;
|
||||||
|
pub const InterceptionFilterMouseState_INTERCEPTION_FILTER_MOUSE_NONE:
|
||||||
|
InterceptionFilterMouseState = 0;
|
||||||
|
pub const InterceptionFilterMouseState_INTERCEPTION_FILTER_MOUSE_ALL: InterceptionFilterMouseState =
|
||||||
|
65535;
|
||||||
|
pub const InterceptionFilterMouseState_INTERCEPTION_FILTER_MOUSE_LEFT_BUTTON_DOWN:
|
||||||
|
InterceptionFilterMouseState = 1;
|
||||||
|
pub const InterceptionFilterMouseState_INTERCEPTION_FILTER_MOUSE_LEFT_BUTTON_UP:
|
||||||
|
InterceptionFilterMouseState = 2;
|
||||||
|
pub const InterceptionFilterMouseState_INTERCEPTION_FILTER_MOUSE_RIGHT_BUTTON_DOWN:
|
||||||
|
InterceptionFilterMouseState = 4;
|
||||||
|
pub const InterceptionFilterMouseState_INTERCEPTION_FILTER_MOUSE_RIGHT_BUTTON_UP:
|
||||||
|
InterceptionFilterMouseState = 8;
|
||||||
|
pub const InterceptionFilterMouseState_INTERCEPTION_FILTER_MOUSE_MIDDLE_BUTTON_DOWN:
|
||||||
|
InterceptionFilterMouseState = 16;
|
||||||
|
pub const InterceptionFilterMouseState_INTERCEPTION_FILTER_MOUSE_MIDDLE_BUTTON_UP:
|
||||||
|
InterceptionFilterMouseState = 32;
|
||||||
|
pub const InterceptionFilterMouseState_INTERCEPTION_FILTER_MOUSE_BUTTON_1_DOWN:
|
||||||
|
InterceptionFilterMouseState = 1;
|
||||||
|
pub const InterceptionFilterMouseState_INTERCEPTION_FILTER_MOUSE_BUTTON_1_UP:
|
||||||
|
InterceptionFilterMouseState = 2;
|
||||||
|
pub const InterceptionFilterMouseState_INTERCEPTION_FILTER_MOUSE_BUTTON_2_DOWN:
|
||||||
|
InterceptionFilterMouseState = 4;
|
||||||
|
pub const InterceptionFilterMouseState_INTERCEPTION_FILTER_MOUSE_BUTTON_2_UP:
|
||||||
|
InterceptionFilterMouseState = 8;
|
||||||
|
pub const InterceptionFilterMouseState_INTERCEPTION_FILTER_MOUSE_BUTTON_3_DOWN:
|
||||||
|
InterceptionFilterMouseState = 16;
|
||||||
|
pub const InterceptionFilterMouseState_INTERCEPTION_FILTER_MOUSE_BUTTON_3_UP:
|
||||||
|
InterceptionFilterMouseState = 32;
|
||||||
|
pub const InterceptionFilterMouseState_INTERCEPTION_FILTER_MOUSE_BUTTON_4_DOWN:
|
||||||
|
InterceptionFilterMouseState = 64;
|
||||||
|
pub const InterceptionFilterMouseState_INTERCEPTION_FILTER_MOUSE_BUTTON_4_UP:
|
||||||
|
InterceptionFilterMouseState = 128;
|
||||||
|
pub const InterceptionFilterMouseState_INTERCEPTION_FILTER_MOUSE_BUTTON_5_DOWN:
|
||||||
|
InterceptionFilterMouseState = 256;
|
||||||
|
pub const InterceptionFilterMouseState_INTERCEPTION_FILTER_MOUSE_BUTTON_5_UP:
|
||||||
|
InterceptionFilterMouseState = 512;
|
||||||
|
pub const InterceptionFilterMouseState_INTERCEPTION_FILTER_MOUSE_WHEEL:
|
||||||
|
InterceptionFilterMouseState = 1024;
|
||||||
|
pub const InterceptionFilterMouseState_INTERCEPTION_FILTER_MOUSE_HWHEEL:
|
||||||
|
InterceptionFilterMouseState = 2048;
|
||||||
|
pub const InterceptionFilterMouseState_INTERCEPTION_FILTER_MOUSE_MOVE:
|
||||||
|
InterceptionFilterMouseState = 4096;
|
||||||
|
pub type InterceptionFilterMouseState = u32;
|
||||||
|
pub const InterceptionMouseFlag_INTERCEPTION_MOUSE_MOVE_RELATIVE: InterceptionMouseFlag = 0;
|
||||||
|
pub const InterceptionMouseFlag_INTERCEPTION_MOUSE_MOVE_ABSOLUTE: InterceptionMouseFlag = 1;
|
||||||
|
pub const InterceptionMouseFlag_INTERCEPTION_MOUSE_VIRTUAL_DESKTOP: InterceptionMouseFlag = 2;
|
||||||
|
pub const InterceptionMouseFlag_INTERCEPTION_MOUSE_ATTRIBUTES_CHANGED: InterceptionMouseFlag = 4;
|
||||||
|
pub const InterceptionMouseFlag_INTERCEPTION_MOUSE_MOVE_NOCOALESCE: InterceptionMouseFlag = 8;
|
||||||
|
pub const InterceptionMouseFlag_INTERCEPTION_MOUSE_TERMSRV_SRC_SHADOW: InterceptionMouseFlag = 256;
|
||||||
|
pub type InterceptionMouseFlag = u32;
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
|
pub struct InterceptionMouseStroke {
|
||||||
|
pub state: ::std::os::raw::c_ushort,
|
||||||
|
pub flags: ::std::os::raw::c_ushort,
|
||||||
|
pub rolling: ::std::os::raw::c_short,
|
||||||
|
pub x: ::std::os::raw::c_int,
|
||||||
|
pub y: ::std::os::raw::c_int,
|
||||||
|
pub information: ::std::os::raw::c_uint,
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn bindgen_test_layout_InterceptionMouseStroke() {
|
||||||
|
assert_eq!(
|
||||||
|
::std::mem::size_of::<InterceptionMouseStroke>(),
|
||||||
|
20usize,
|
||||||
|
concat!("Size of: ", stringify!(InterceptionMouseStroke))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
::std::mem::align_of::<InterceptionMouseStroke>(),
|
||||||
|
4usize,
|
||||||
|
concat!("Alignment of ", stringify!(InterceptionMouseStroke))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
unsafe { &(*(::std::ptr::null::<InterceptionMouseStroke>())).state as *const _ as usize },
|
||||||
|
0usize,
|
||||||
|
concat!(
|
||||||
|
"Offset of field: ",
|
||||||
|
stringify!(InterceptionMouseStroke),
|
||||||
|
"::",
|
||||||
|
stringify!(state)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
unsafe { &(*(::std::ptr::null::<InterceptionMouseStroke>())).flags as *const _ as usize },
|
||||||
|
2usize,
|
||||||
|
concat!(
|
||||||
|
"Offset of field: ",
|
||||||
|
stringify!(InterceptionMouseStroke),
|
||||||
|
"::",
|
||||||
|
stringify!(flags)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
unsafe { &(*(::std::ptr::null::<InterceptionMouseStroke>())).rolling as *const _ as usize },
|
||||||
|
4usize,
|
||||||
|
concat!(
|
||||||
|
"Offset of field: ",
|
||||||
|
stringify!(InterceptionMouseStroke),
|
||||||
|
"::",
|
||||||
|
stringify!(rolling)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
unsafe { &(*(::std::ptr::null::<InterceptionMouseStroke>())).x as *const _ as usize },
|
||||||
|
8usize,
|
||||||
|
concat!(
|
||||||
|
"Offset of field: ",
|
||||||
|
stringify!(InterceptionMouseStroke),
|
||||||
|
"::",
|
||||||
|
stringify!(x)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
unsafe { &(*(::std::ptr::null::<InterceptionMouseStroke>())).y as *const _ as usize },
|
||||||
|
12usize,
|
||||||
|
concat!(
|
||||||
|
"Offset of field: ",
|
||||||
|
stringify!(InterceptionMouseStroke),
|
||||||
|
"::",
|
||||||
|
stringify!(y)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
unsafe {
|
||||||
|
&(*(::std::ptr::null::<InterceptionMouseStroke>())).information as *const _ as usize
|
||||||
|
},
|
||||||
|
16usize,
|
||||||
|
concat!(
|
||||||
|
"Offset of field: ",
|
||||||
|
stringify!(InterceptionMouseStroke),
|
||||||
|
"::",
|
||||||
|
stringify!(information)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Debug, Default, Copy, Clone)]
|
||||||
|
pub struct InterceptionKeyStroke {
|
||||||
|
pub code: ::std::os::raw::c_ushort,
|
||||||
|
pub state: ::std::os::raw::c_ushort,
|
||||||
|
pub information: ::std::os::raw::c_uint,
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn bindgen_test_layout_InterceptionKeyStroke() {
|
||||||
|
assert_eq!(
|
||||||
|
::std::mem::size_of::<InterceptionKeyStroke>(),
|
||||||
|
8usize,
|
||||||
|
concat!("Size of: ", stringify!(InterceptionKeyStroke))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
::std::mem::align_of::<InterceptionKeyStroke>(),
|
||||||
|
4usize,
|
||||||
|
concat!("Alignment of ", stringify!(InterceptionKeyStroke))
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
unsafe { &(*(::std::ptr::null::<InterceptionKeyStroke>())).code as *const _ as usize },
|
||||||
|
0usize,
|
||||||
|
concat!(
|
||||||
|
"Offset of field: ",
|
||||||
|
stringify!(InterceptionKeyStroke),
|
||||||
|
"::",
|
||||||
|
stringify!(code)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
unsafe { &(*(::std::ptr::null::<InterceptionKeyStroke>())).state as *const _ as usize },
|
||||||
|
2usize,
|
||||||
|
concat!(
|
||||||
|
"Offset of field: ",
|
||||||
|
stringify!(InterceptionKeyStroke),
|
||||||
|
"::",
|
||||||
|
stringify!(state)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
unsafe {
|
||||||
|
&(*(::std::ptr::null::<InterceptionKeyStroke>())).information as *const _ as usize
|
||||||
|
},
|
||||||
|
4usize,
|
||||||
|
concat!(
|
||||||
|
"Offset of field: ",
|
||||||
|
stringify!(InterceptionKeyStroke),
|
||||||
|
"::",
|
||||||
|
stringify!(information)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
pub type InterceptionStroke = [::std::os::raw::c_char; 20usize];
|
||||||
|
extern "C" {
|
||||||
|
pub fn interception_create_context() -> InterceptionContext;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn interception_destroy_context(context: InterceptionContext);
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn interception_get_precedence(
|
||||||
|
context: InterceptionContext,
|
||||||
|
device: InterceptionDevice,
|
||||||
|
) -> InterceptionPrecedence;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn interception_set_precedence(
|
||||||
|
context: InterceptionContext,
|
||||||
|
device: InterceptionDevice,
|
||||||
|
precedence: InterceptionPrecedence,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn interception_get_filter(
|
||||||
|
context: InterceptionContext,
|
||||||
|
device: InterceptionDevice,
|
||||||
|
) -> InterceptionFilter;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn interception_set_filter(
|
||||||
|
context: InterceptionContext,
|
||||||
|
predicate: InterceptionPredicate,
|
||||||
|
filter: InterceptionFilter,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn interception_wait(context: InterceptionContext) -> InterceptionDevice;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn interception_wait_with_timeout(
|
||||||
|
context: InterceptionContext,
|
||||||
|
milliseconds: ::std::os::raw::c_ulong,
|
||||||
|
) -> InterceptionDevice;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn interception_send(
|
||||||
|
context: InterceptionContext,
|
||||||
|
device: InterceptionDevice,
|
||||||
|
stroke: *const InterceptionStroke,
|
||||||
|
nstroke: ::std::os::raw::c_uint,
|
||||||
|
) -> ::std::os::raw::c_int;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn interception_receive(
|
||||||
|
context: InterceptionContext,
|
||||||
|
device: InterceptionDevice,
|
||||||
|
stroke: *mut InterceptionStroke,
|
||||||
|
nstroke: ::std::os::raw::c_uint,
|
||||||
|
) -> ::std::os::raw::c_int;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn interception_get_hardware_id(
|
||||||
|
context: InterceptionContext,
|
||||||
|
device: InterceptionDevice,
|
||||||
|
hardware_id_buffer: *mut ::std::os::raw::c_void,
|
||||||
|
buffer_size: ::std::os::raw::c_uint,
|
||||||
|
) -> ::std::os::raw::c_uint;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn interception_is_invalid(device: InterceptionDevice) -> ::std::os::raw::c_int;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn interception_is_keyboard(device: InterceptionDevice) -> ::std::os::raw::c_int;
|
||||||
|
}
|
||||||
|
extern "C" {
|
||||||
|
pub fn interception_is_mouse(device: InterceptionDevice) -> ::std::os::raw::c_int;
|
||||||
|
}
|
328
src-interception/src/interception.c
Normal file
328
src-interception/src/interception.c
Normal file
@ -0,0 +1,328 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <windows.h>
|
||||||
|
#include <winioctl.h>
|
||||||
|
|
||||||
|
#include "interception.h"
|
||||||
|
|
||||||
|
#define IOCTL_SET_PRECEDENCE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
|
#define IOCTL_GET_PRECEDENCE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
|
#define IOCTL_SET_FILTER CTL_CODE(FILE_DEVICE_UNKNOWN, 0x804, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
|
#define IOCTL_GET_FILTER CTL_CODE(FILE_DEVICE_UNKNOWN, 0x808, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
|
#define IOCTL_SET_EVENT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x810, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
|
#define IOCTL_WRITE CTL_CODE(FILE_DEVICE_UNKNOWN, 0x820, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
|
#define IOCTL_READ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x840, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
|
#define IOCTL_GET_HARDWARE_ID CTL_CODE(FILE_DEVICE_UNKNOWN, 0x880, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||||
|
|
||||||
|
typedef struct _KEYBOARD_INPUT_DATA
|
||||||
|
{
|
||||||
|
USHORT UnitId;
|
||||||
|
USHORT MakeCode;
|
||||||
|
USHORT Flags;
|
||||||
|
USHORT Reserved;
|
||||||
|
ULONG ExtraInformation;
|
||||||
|
} KEYBOARD_INPUT_DATA, *PKEYBOARD_INPUT_DATA;
|
||||||
|
|
||||||
|
typedef struct _MOUSE_INPUT_DATA
|
||||||
|
{
|
||||||
|
USHORT UnitId;
|
||||||
|
USHORT Flags;
|
||||||
|
USHORT ButtonFlags;
|
||||||
|
USHORT ButtonData;
|
||||||
|
ULONG RawButtons;
|
||||||
|
LONG LastX;
|
||||||
|
LONG LastY;
|
||||||
|
ULONG ExtraInformation;
|
||||||
|
} MOUSE_INPUT_DATA, *PMOUSE_INPUT_DATA;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
void *handle;
|
||||||
|
void *unempty;
|
||||||
|
} *InterceptionDeviceArray;
|
||||||
|
|
||||||
|
InterceptionContext interception_create_context(void)
|
||||||
|
{
|
||||||
|
InterceptionDeviceArray device_array = 0;
|
||||||
|
char device_name[] = "\\\\.\\interception00";
|
||||||
|
DWORD bytes_returned;
|
||||||
|
InterceptionDevice i;
|
||||||
|
|
||||||
|
device_array = (InterceptionDeviceArray)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INTERCEPTION_MAX_DEVICE * sizeof(*((InterceptionDeviceArray) 0)));
|
||||||
|
if(!device_array) return 0;
|
||||||
|
|
||||||
|
for(i = 0; i < INTERCEPTION_MAX_DEVICE; ++i)
|
||||||
|
{
|
||||||
|
HANDLE zero_padded_handle[2] = {0};
|
||||||
|
|
||||||
|
sprintf(&device_name[sizeof(device_name) - 3], "%02d", i);
|
||||||
|
|
||||||
|
device_array[i].handle = CreateFileA(device_name, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||||
|
|
||||||
|
if (device_array[i].handle == INVALID_HANDLE_VALUE) {
|
||||||
|
interception_destroy_context(device_array);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
device_array[i].unempty = CreateEventA(NULL, TRUE, FALSE, NULL);
|
||||||
|
|
||||||
|
if(device_array[i].unempty == NULL)
|
||||||
|
{
|
||||||
|
interception_destroy_context(device_array);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
zero_padded_handle[0] = device_array[i].unempty;
|
||||||
|
|
||||||
|
if(!DeviceIoControl(device_array[i].handle, IOCTL_SET_EVENT, zero_padded_handle, sizeof(zero_padded_handle), NULL, 0, &bytes_returned, NULL))
|
||||||
|
{
|
||||||
|
interception_destroy_context(device_array);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return device_array;
|
||||||
|
}
|
||||||
|
|
||||||
|
void interception_destroy_context(InterceptionContext context)
|
||||||
|
{
|
||||||
|
InterceptionDeviceArray device_array = (InterceptionDeviceArray)context;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if(!context) return;
|
||||||
|
|
||||||
|
for(i = 0; i < INTERCEPTION_MAX_DEVICE; ++i)
|
||||||
|
{
|
||||||
|
if(device_array[i].handle != INVALID_HANDLE_VALUE)
|
||||||
|
CloseHandle(device_array[i].handle);
|
||||||
|
|
||||||
|
if(device_array[i].unempty != NULL)
|
||||||
|
CloseHandle(device_array[i].unempty);
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
InterceptionPrecedence interception_get_precedence(InterceptionContext context, InterceptionDevice device)
|
||||||
|
{
|
||||||
|
InterceptionDeviceArray device_array = (InterceptionDeviceArray)context;
|
||||||
|
InterceptionPrecedence precedence = 0;
|
||||||
|
DWORD bytes_returned;
|
||||||
|
|
||||||
|
if(context && device_array[device - 1].handle)
|
||||||
|
DeviceIoControl(device_array[device - 1].handle, IOCTL_GET_PRECEDENCE, NULL, 0, (LPVOID)&precedence, sizeof(InterceptionPrecedence), &bytes_returned, NULL);
|
||||||
|
|
||||||
|
return precedence;
|
||||||
|
}
|
||||||
|
|
||||||
|
void interception_set_precedence(InterceptionContext context, InterceptionDevice device, InterceptionPrecedence precedence)
|
||||||
|
{
|
||||||
|
InterceptionDeviceArray device_array = (InterceptionDeviceArray)context;
|
||||||
|
DWORD bytes_returned;
|
||||||
|
|
||||||
|
if(context && device_array[device - 1].handle)
|
||||||
|
DeviceIoControl(device_array[device - 1].handle, IOCTL_SET_PRECEDENCE, (LPVOID)&precedence, sizeof(InterceptionPrecedence), NULL, 0, &bytes_returned, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
InterceptionFilter interception_get_filter(InterceptionContext context, InterceptionDevice device)
|
||||||
|
{
|
||||||
|
InterceptionDeviceArray device_array = (InterceptionDeviceArray)context;
|
||||||
|
InterceptionFilter filter = 0;
|
||||||
|
DWORD bytes_returned;
|
||||||
|
|
||||||
|
if(context && device_array[device - 1].handle)
|
||||||
|
DeviceIoControl(device_array[device - 1].handle, IOCTL_GET_FILTER, NULL, 0, (LPVOID)&filter, sizeof(InterceptionFilter), &bytes_returned, NULL);
|
||||||
|
|
||||||
|
return filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void interception_set_filter(InterceptionContext context, InterceptionPredicate interception_predicate, InterceptionFilter filter)
|
||||||
|
{
|
||||||
|
InterceptionDeviceArray device_array = (InterceptionDeviceArray)context;
|
||||||
|
InterceptionDevice i;
|
||||||
|
DWORD bytes_returned;
|
||||||
|
|
||||||
|
if(context)
|
||||||
|
for(i = 0; i < INTERCEPTION_MAX_DEVICE; ++i)
|
||||||
|
if(device_array[i].handle && interception_predicate(i + 1))
|
||||||
|
DeviceIoControl(device_array[i].handle, IOCTL_SET_FILTER, (LPVOID)&filter, sizeof(InterceptionFilter), NULL, 0, &bytes_returned, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
InterceptionDevice interception_wait(InterceptionContext context)
|
||||||
|
{
|
||||||
|
return interception_wait_with_timeout(context, INFINITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
InterceptionDevice interception_wait_with_timeout(InterceptionContext context, unsigned long milliseconds)
|
||||||
|
{
|
||||||
|
InterceptionDeviceArray device_array = (InterceptionDeviceArray)context;
|
||||||
|
HANDLE wait_handles[INTERCEPTION_MAX_DEVICE];
|
||||||
|
DWORD i, j, k;
|
||||||
|
|
||||||
|
if(!context) return 0;
|
||||||
|
|
||||||
|
for(i = 0, j = 0; i < INTERCEPTION_MAX_DEVICE; ++i)
|
||||||
|
{
|
||||||
|
if (device_array[i].unempty)
|
||||||
|
wait_handles[j++] = device_array[i].unempty;
|
||||||
|
}
|
||||||
|
|
||||||
|
k = WaitForMultipleObjects(j, wait_handles, FALSE, milliseconds);
|
||||||
|
|
||||||
|
if(k == WAIT_FAILED || k == WAIT_TIMEOUT) return 0;
|
||||||
|
|
||||||
|
for(i = 0, j = 0; i < INTERCEPTION_MAX_DEVICE; ++i)
|
||||||
|
{
|
||||||
|
if (device_array[i].unempty)
|
||||||
|
if (k == j++)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int interception_send(InterceptionContext context, InterceptionDevice device, const InterceptionStroke *stroke, unsigned int nstroke)
|
||||||
|
{
|
||||||
|
InterceptionDeviceArray device_array = (InterceptionDeviceArray)context;
|
||||||
|
DWORD strokeswritten = 0;
|
||||||
|
|
||||||
|
if(context == 0 || nstroke == 0 || interception_is_invalid(device) || !device_array[device - 1].handle) return 0;
|
||||||
|
|
||||||
|
if(interception_is_keyboard(device))
|
||||||
|
{
|
||||||
|
PKEYBOARD_INPUT_DATA rawstrokes = (PKEYBOARD_INPUT_DATA)HeapAlloc(GetProcessHeap(), 0, nstroke * sizeof(KEYBOARD_INPUT_DATA));
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if(!rawstrokes) return 0;
|
||||||
|
|
||||||
|
for(i = 0; i < nstroke; ++i)
|
||||||
|
{
|
||||||
|
InterceptionKeyStroke *key_stroke = (InterceptionKeyStroke *) stroke;
|
||||||
|
|
||||||
|
rawstrokes[i].UnitId = 0;
|
||||||
|
rawstrokes[i].MakeCode = key_stroke[i].code;
|
||||||
|
rawstrokes[i].Flags = key_stroke[i].state;
|
||||||
|
rawstrokes[i].Reserved = 0;
|
||||||
|
rawstrokes[i].ExtraInformation = key_stroke[i].information;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceIoControl(device_array[device - 1].handle, IOCTL_WRITE, rawstrokes,(DWORD)nstroke * sizeof(KEYBOARD_INPUT_DATA), NULL, 0, &strokeswritten, NULL);
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, rawstrokes);
|
||||||
|
|
||||||
|
strokeswritten /= sizeof(KEYBOARD_INPUT_DATA);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PMOUSE_INPUT_DATA rawstrokes = (PMOUSE_INPUT_DATA)HeapAlloc(GetProcessHeap(), 0, nstroke * sizeof(MOUSE_INPUT_DATA));
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if(!rawstrokes) return 0;
|
||||||
|
|
||||||
|
for(i = 0; i < nstroke; ++i)
|
||||||
|
{
|
||||||
|
InterceptionMouseStroke *mouse_stroke = (InterceptionMouseStroke *) stroke;
|
||||||
|
|
||||||
|
rawstrokes[i].UnitId = 0;
|
||||||
|
rawstrokes[i].Flags = mouse_stroke[i].flags;
|
||||||
|
rawstrokes[i].ButtonFlags = mouse_stroke[i].state;
|
||||||
|
rawstrokes[i].ButtonData = mouse_stroke[i].rolling;
|
||||||
|
rawstrokes[i].RawButtons = 0;
|
||||||
|
rawstrokes[i].LastX = mouse_stroke[i].x;
|
||||||
|
rawstrokes[i].LastY = mouse_stroke[i].y;
|
||||||
|
rawstrokes[i].ExtraInformation = mouse_stroke[i].information;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceIoControl(device_array[device - 1].handle, IOCTL_WRITE, rawstrokes, (DWORD)nstroke * sizeof(MOUSE_INPUT_DATA), NULL, 0, &strokeswritten, NULL);
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, rawstrokes);
|
||||||
|
|
||||||
|
strokeswritten /= sizeof(MOUSE_INPUT_DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
return strokeswritten;
|
||||||
|
}
|
||||||
|
|
||||||
|
int interception_receive(InterceptionContext context, InterceptionDevice device, InterceptionStroke *stroke, unsigned int nstroke)
|
||||||
|
{
|
||||||
|
InterceptionDeviceArray device_array = (InterceptionDeviceArray)context;
|
||||||
|
DWORD strokesread = 0;
|
||||||
|
|
||||||
|
if(context == 0 || nstroke == 0 || interception_is_invalid(device) || !device_array[device - 1].handle) return 0;
|
||||||
|
|
||||||
|
if(interception_is_keyboard(device))
|
||||||
|
{
|
||||||
|
PKEYBOARD_INPUT_DATA rawstrokes = (PKEYBOARD_INPUT_DATA)HeapAlloc(GetProcessHeap(), 0, nstroke * sizeof(KEYBOARD_INPUT_DATA));
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if(!rawstrokes) return 0;
|
||||||
|
|
||||||
|
DeviceIoControl(device_array[device - 1].handle, IOCTL_READ, NULL, 0, rawstrokes, (DWORD)nstroke * sizeof(KEYBOARD_INPUT_DATA), &strokesread, NULL);
|
||||||
|
|
||||||
|
strokesread /= sizeof(KEYBOARD_INPUT_DATA);
|
||||||
|
|
||||||
|
for(i = 0; i < (unsigned int)strokesread; ++i)
|
||||||
|
{
|
||||||
|
InterceptionKeyStroke *key_stroke = (InterceptionKeyStroke *) stroke;
|
||||||
|
|
||||||
|
key_stroke[i].code = rawstrokes[i].MakeCode;
|
||||||
|
key_stroke[i].state = rawstrokes[i].Flags;
|
||||||
|
key_stroke[i].information = rawstrokes[i].ExtraInformation;
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, rawstrokes);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PMOUSE_INPUT_DATA rawstrokes = (PMOUSE_INPUT_DATA)HeapAlloc(GetProcessHeap(), 0, nstroke * sizeof(MOUSE_INPUT_DATA));
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
if(!rawstrokes) return 0;
|
||||||
|
|
||||||
|
DeviceIoControl(device_array[device - 1].handle, IOCTL_READ, NULL, 0, rawstrokes, (DWORD)nstroke * sizeof(MOUSE_INPUT_DATA), &strokesread, NULL);
|
||||||
|
|
||||||
|
strokesread /= sizeof(MOUSE_INPUT_DATA);
|
||||||
|
|
||||||
|
for(i = 0; i < (unsigned int)strokesread; ++i)
|
||||||
|
{
|
||||||
|
InterceptionMouseStroke *mouse_stroke = (InterceptionMouseStroke *) stroke;
|
||||||
|
|
||||||
|
mouse_stroke[i].flags = rawstrokes[i].Flags;
|
||||||
|
mouse_stroke[i].state = rawstrokes[i].ButtonFlags;
|
||||||
|
mouse_stroke[i].rolling = rawstrokes[i].ButtonData;
|
||||||
|
mouse_stroke[i].x = rawstrokes[i].LastX;
|
||||||
|
mouse_stroke[i].y = rawstrokes[i].LastY;
|
||||||
|
mouse_stroke[i].information = rawstrokes[i].ExtraInformation;
|
||||||
|
}
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, rawstrokes);
|
||||||
|
}
|
||||||
|
|
||||||
|
return strokesread;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int interception_get_hardware_id(InterceptionContext context, InterceptionDevice device, void *hardware_id_buffer, unsigned int buffer_size)
|
||||||
|
{
|
||||||
|
InterceptionDeviceArray device_array = (InterceptionDeviceArray)context;
|
||||||
|
DWORD output_size = 0;
|
||||||
|
|
||||||
|
if(context == 0 || interception_is_invalid(device) || !device_array[device - 1].handle) return 0;
|
||||||
|
|
||||||
|
DeviceIoControl(device_array[device - 1].handle, IOCTL_GET_HARDWARE_ID, NULL, 0, hardware_id_buffer, buffer_size, &output_size, NULL);
|
||||||
|
|
||||||
|
return output_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
int interception_is_invalid(InterceptionDevice device)
|
||||||
|
{
|
||||||
|
return !interception_is_keyboard(device) && !interception_is_mouse(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
int interception_is_keyboard(InterceptionDevice device)
|
||||||
|
{
|
||||||
|
return device >= INTERCEPTION_KEYBOARD(0) && device <= INTERCEPTION_KEYBOARD(INTERCEPTION_MAX_KEYBOARD - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int interception_is_mouse(InterceptionDevice device)
|
||||||
|
{
|
||||||
|
return device >= INTERCEPTION_MOUSE(0) && device <= INTERCEPTION_MOUSE(INTERCEPTION_MAX_MOUSE - 1);
|
||||||
|
}
|
373
src-interception/src/lib.rs
Normal file
373
src-interception/src/lib.rs
Normal file
@ -0,0 +1,373 @@
|
|||||||
|
#[macro_use]
|
||||||
|
extern crate bitflags;
|
||||||
|
|
||||||
|
mod bindings;
|
||||||
|
use bindings as raw;
|
||||||
|
pub mod scancode;
|
||||||
|
|
||||||
|
pub use scancode::ScanCode;
|
||||||
|
|
||||||
|
use std::convert::{TryFrom, TryInto};
|
||||||
|
use std::default::Default;
|
||||||
|
use std::time::Duration;
|
||||||
|
use std::vec::Vec;
|
||||||
|
|
||||||
|
pub type Device = i32;
|
||||||
|
pub type Precedence = i32;
|
||||||
|
|
||||||
|
pub enum Filter {
|
||||||
|
MouseFilter(MouseFilter),
|
||||||
|
KeyFilter(KeyFilter),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type Predicate = extern "C" fn(device: Device) -> bool;
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
pub struct MouseState: u16 {
|
||||||
|
const LEFT_BUTTON_DOWN = 1;
|
||||||
|
const LEFT_BUTTON_UP = 2;
|
||||||
|
|
||||||
|
const RIGHT_BUTTON_DOWN = 4;
|
||||||
|
const RIGHT_BUTTON_UP = 8;
|
||||||
|
|
||||||
|
const MIDDLE_BUTTON_DOWN = 16;
|
||||||
|
const MIDDLE_BUTTON_UP = 32;
|
||||||
|
|
||||||
|
const BUTTON_4_DOWN = 64;
|
||||||
|
const BUTTON_4_UP = 128;
|
||||||
|
|
||||||
|
const BUTTON_5_DOWN = 256;
|
||||||
|
const BUTTON_5_UP = 512;
|
||||||
|
|
||||||
|
const WHEEL = 1024;
|
||||||
|
const HWHEEL = 2048;
|
||||||
|
|
||||||
|
// MouseFilter only
|
||||||
|
const MOVE = 4096;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type MouseFilter = MouseState;
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
pub struct MouseFlags: u16 {
|
||||||
|
const MOVE_RELATIVE = 0;
|
||||||
|
const MOVE_ABSOLUTE = 1;
|
||||||
|
|
||||||
|
const VIRTUAL_DESKTOP = 2;
|
||||||
|
const ATTRIBUTES_CHANGED = 4;
|
||||||
|
|
||||||
|
const MOVE_NO_COALESCE = 8;
|
||||||
|
|
||||||
|
const TERMSRV_SRC_SHADOW = 256;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
pub struct KeyState: u16 {
|
||||||
|
const DOWN = 0;
|
||||||
|
const UP = 1;
|
||||||
|
|
||||||
|
const E0 = 2;
|
||||||
|
const E1 = 3;
|
||||||
|
|
||||||
|
const TERMSRV_SET_LED = 8;
|
||||||
|
const TERMSRV_SHADOW = 16;
|
||||||
|
const TERMSRV_VKPACKET = 32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
pub struct KeyFilter: u16 {
|
||||||
|
const DOWN = 1;
|
||||||
|
const UP = 2;
|
||||||
|
|
||||||
|
const E0 = 4;
|
||||||
|
const E1 = 8;
|
||||||
|
|
||||||
|
const TERMSRV_SET_LED = 16;
|
||||||
|
const TERMSRV_SHADOW = 32;
|
||||||
|
const TERMSRV_VKPACKET = 64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone)]
|
||||||
|
pub enum Stroke {
|
||||||
|
Mouse {
|
||||||
|
state: MouseState,
|
||||||
|
flags: MouseFlags,
|
||||||
|
rolling: i16,
|
||||||
|
x: i32,
|
||||||
|
y: i32,
|
||||||
|
information: u32,
|
||||||
|
},
|
||||||
|
|
||||||
|
Keyboard {
|
||||||
|
code: ScanCode,
|
||||||
|
state: KeyState,
|
||||||
|
information: u32,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<raw::InterceptionMouseStroke> for Stroke {
|
||||||
|
type Error = &'static str;
|
||||||
|
|
||||||
|
fn try_from(raw_stroke: raw::InterceptionMouseStroke) -> Result<Self, Self::Error> {
|
||||||
|
let state = match MouseState::from_bits(raw_stroke.state) {
|
||||||
|
Some(state) => state,
|
||||||
|
None => return Err("Extra bits in raw mouse state"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let flags = match MouseFlags::from_bits(raw_stroke.flags) {
|
||||||
|
Some(flags) => flags,
|
||||||
|
None => return Err("Extra bits in raw mouse flags"),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Stroke::Mouse {
|
||||||
|
state: state,
|
||||||
|
flags: flags,
|
||||||
|
rolling: raw_stroke.rolling,
|
||||||
|
x: raw_stroke.x,
|
||||||
|
y: raw_stroke.y,
|
||||||
|
information: raw_stroke.information,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<raw::InterceptionKeyStroke> for Stroke {
|
||||||
|
type Error = &'static str;
|
||||||
|
|
||||||
|
fn try_from(raw_stroke: raw::InterceptionKeyStroke) -> Result<Self, Self::Error> {
|
||||||
|
let state = match KeyState::from_bits(raw_stroke.state) {
|
||||||
|
Some(state) => state,
|
||||||
|
None => return Err("Extra bits in raw keyboard state"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let code = match ScanCode::try_from(raw_stroke.code) {
|
||||||
|
Ok(code) => code,
|
||||||
|
Err(_) => ScanCode::Esc,
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Stroke::Keyboard {
|
||||||
|
code: code,
|
||||||
|
state: state,
|
||||||
|
information: raw_stroke.information,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<Stroke> for raw::InterceptionMouseStroke {
|
||||||
|
type Error = &'static str;
|
||||||
|
|
||||||
|
fn try_from(stroke: Stroke) -> Result<Self, Self::Error> {
|
||||||
|
if let Stroke::Mouse {
|
||||||
|
state,
|
||||||
|
flags,
|
||||||
|
rolling,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
information,
|
||||||
|
} = stroke
|
||||||
|
{
|
||||||
|
Ok(raw::InterceptionMouseStroke {
|
||||||
|
state: state.bits(),
|
||||||
|
flags: flags.bits(),
|
||||||
|
rolling: rolling,
|
||||||
|
x: x,
|
||||||
|
y: y,
|
||||||
|
information: information,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Err("Stroke must be a mouse stroke")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFrom<Stroke> for raw::InterceptionKeyStroke {
|
||||||
|
type Error = &'static str;
|
||||||
|
|
||||||
|
fn try_from(stroke: Stroke) -> Result<Self, Self::Error> {
|
||||||
|
if let Stroke::Keyboard {
|
||||||
|
code,
|
||||||
|
state,
|
||||||
|
information,
|
||||||
|
} = stroke
|
||||||
|
{
|
||||||
|
Ok(raw::InterceptionKeyStroke {
|
||||||
|
code: code as u16,
|
||||||
|
state: state.bits(),
|
||||||
|
information: information,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
Err("Stroke must be a keyboard stroke")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Interception {
|
||||||
|
ctx: raw::InterceptionContext,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Interception {
|
||||||
|
pub fn new() -> Option<Self> {
|
||||||
|
let ctx = unsafe { raw::interception_create_context() };
|
||||||
|
|
||||||
|
if ctx == std::ptr::null_mut() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(Interception { ctx: ctx })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_precedence(&self, device: Device) -> Precedence {
|
||||||
|
unsafe { raw::interception_get_precedence(self.ctx, device) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_precedence(&self, device: Device, precedence: Precedence) {
|
||||||
|
unsafe { raw::interception_set_precedence(self.ctx, device, precedence) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_filter(&self, device: Device) -> Filter {
|
||||||
|
if is_invalid(device) {
|
||||||
|
return Filter::KeyFilter(KeyFilter::empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
let raw_filter = unsafe { raw::interception_get_filter(self.ctx, device) };
|
||||||
|
if is_mouse(device) {
|
||||||
|
let filter = match MouseFilter::from_bits(raw_filter) {
|
||||||
|
Some(filter) => filter,
|
||||||
|
None => MouseFilter::empty(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Filter::MouseFilter(filter)
|
||||||
|
} else {
|
||||||
|
let filter = match KeyFilter::from_bits(raw_filter) {
|
||||||
|
Some(filter) => filter,
|
||||||
|
None => KeyFilter::empty(),
|
||||||
|
};
|
||||||
|
|
||||||
|
Filter::KeyFilter(filter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_filter(&self, predicate: Predicate, filter: Filter) {
|
||||||
|
let filter = match filter {
|
||||||
|
Filter::MouseFilter(filter) => filter.bits(),
|
||||||
|
Filter::KeyFilter(filter) => filter.bits(),
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let predicate = std::mem::transmute(Some(predicate));
|
||||||
|
raw::interception_set_filter(self.ctx, predicate, filter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn wait(&self) -> Device {
|
||||||
|
unsafe { raw::interception_wait(self.ctx) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn wait_with_timeout(&self, duration: Duration) -> Device {
|
||||||
|
let millis = match u32::try_from(duration.as_millis()) {
|
||||||
|
Ok(m) => m,
|
||||||
|
Err(_) => u32::MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe { raw::interception_wait_with_timeout(self.ctx, millis) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send(&self, device: Device, strokes: &[Stroke]) -> i32 {
|
||||||
|
if is_mouse(device) {
|
||||||
|
self.send_internal::<raw::InterceptionMouseStroke>(device, strokes)
|
||||||
|
} else if is_keyboard(device) {
|
||||||
|
self.send_internal::<raw::InterceptionKeyStroke>(device, strokes)
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_internal<T: TryFrom<Stroke>>(&self, device: Device, strokes: &[Stroke]) -> i32 {
|
||||||
|
let mut raw_strokes = Vec::new();
|
||||||
|
|
||||||
|
for stroke in strokes {
|
||||||
|
if let Ok(raw_stroke) = T::try_from(*stroke) {
|
||||||
|
raw_strokes.push(raw_stroke)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let ptr = raw_strokes.as_ptr();
|
||||||
|
let len = match u32::try_from(raw_strokes.len()) {
|
||||||
|
Ok(l) => l,
|
||||||
|
Err(_) => u32::MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe { raw::interception_send(self.ctx, device, std::mem::transmute(ptr), len) }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn receive(&self, device: Device, strokes: &mut [Stroke]) -> i32 {
|
||||||
|
if is_mouse(device) {
|
||||||
|
self.receive_internal::<raw::InterceptionMouseStroke>(device, strokes)
|
||||||
|
} else if is_keyboard(device) {
|
||||||
|
self.receive_internal::<raw::InterceptionKeyStroke>(device, strokes)
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn receive_internal<T: TryInto<Stroke> + Default + Copy>(
|
||||||
|
&self,
|
||||||
|
device: Device,
|
||||||
|
strokes: &mut [Stroke],
|
||||||
|
) -> i32 {
|
||||||
|
let mut raw_strokes: Vec<T> = Vec::with_capacity(strokes.len());
|
||||||
|
raw_strokes.resize_with(strokes.len(), Default::default);
|
||||||
|
|
||||||
|
let ptr = raw_strokes.as_ptr();
|
||||||
|
let len = match u32::try_from(raw_strokes.len()) {
|
||||||
|
Ok(l) => l,
|
||||||
|
Err(_) => u32::MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
let num_read =
|
||||||
|
unsafe { raw::interception_receive(self.ctx, device, std::mem::transmute(ptr), len) };
|
||||||
|
|
||||||
|
let mut num_valid: i32 = 0;
|
||||||
|
for i in 0..num_read {
|
||||||
|
if let Ok(stroke) = raw_strokes[i as usize].try_into() {
|
||||||
|
strokes[num_valid as usize] = stroke;
|
||||||
|
num_valid += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
num_valid
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_hardware_id(&self, device: Device, buffer: &mut [u8]) -> u32 {
|
||||||
|
let ptr = buffer.as_mut_ptr();
|
||||||
|
let len = match u32::try_from(buffer.len()) {
|
||||||
|
Ok(l) => l,
|
||||||
|
Err(_) => u32::MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
raw::interception_get_hardware_id(self.ctx, device, std::mem::transmute(ptr), len)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for Interception {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe { raw::interception_destroy_context(self.ctx) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub extern "C" fn is_invalid(device: Device) -> bool {
|
||||||
|
unsafe { raw::interception_is_invalid(device) != 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub extern "C" fn is_keyboard(device: Device) -> bool {
|
||||||
|
unsafe { raw::interception_is_keyboard(device) != 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub extern "C" fn is_mouse(device: Device) -> bool {
|
||||||
|
unsafe { raw::interception_is_mouse(device) != 0 }
|
||||||
|
}
|
147
src-interception/src/scancode.rs
Normal file
147
src-interception/src/scancode.rs
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
use num_enum::TryFromPrimitive;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
// ref: https://handmade.network/wiki/2823-keyboard_inputs_-_scancodes,_raw_input,_text_input,_key_names
|
||||||
|
#[derive(Serialize, Deserialize, Hash, Debug, Eq, PartialEq, Copy, Clone, TryFromPrimitive)]
|
||||||
|
#[repr(u16)]
|
||||||
|
pub enum ScanCode {
|
||||||
|
Esc = 0x01,
|
||||||
|
|
||||||
|
Num1 = 0x02,
|
||||||
|
Num2 = 0x03,
|
||||||
|
Num3 = 0x04,
|
||||||
|
Num4 = 0x05,
|
||||||
|
Num5 = 0x06,
|
||||||
|
Num6 = 0x07,
|
||||||
|
Num7 = 0x08,
|
||||||
|
Num8 = 0x09,
|
||||||
|
Num9 = 0x0A,
|
||||||
|
Num0 = 0x0B,
|
||||||
|
|
||||||
|
Minus = 0x0C,
|
||||||
|
Equals = 0x0D,
|
||||||
|
Backspace = 0x0E,
|
||||||
|
|
||||||
|
Tab = 0x0F,
|
||||||
|
|
||||||
|
Q = 0x10,
|
||||||
|
W = 0x11,
|
||||||
|
E = 0x12,
|
||||||
|
R = 0x13,
|
||||||
|
T = 0x14,
|
||||||
|
Y = 0x15,
|
||||||
|
U = 0x16,
|
||||||
|
I = 0x17,
|
||||||
|
O = 0x18,
|
||||||
|
P = 0x19,
|
||||||
|
|
||||||
|
LeftBracket = 0x1A,
|
||||||
|
RightBracket = 0x1B,
|
||||||
|
Enter = 0x1C,
|
||||||
|
|
||||||
|
LeftControl = 0x1D,
|
||||||
|
|
||||||
|
A = 0x1E,
|
||||||
|
S = 0x1F,
|
||||||
|
D = 0x20,
|
||||||
|
F = 0x21,
|
||||||
|
G = 0x22,
|
||||||
|
H = 0x23,
|
||||||
|
J = 0x24,
|
||||||
|
K = 0x25,
|
||||||
|
L = 0x26,
|
||||||
|
|
||||||
|
SemiColon = 0x27,
|
||||||
|
Apostrophe = 0x28,
|
||||||
|
Grave = 0x29,
|
||||||
|
LeftShift = 0x2A,
|
||||||
|
BackSlash = 0x2B,
|
||||||
|
|
||||||
|
Z = 0x2C,
|
||||||
|
X = 0x2D,
|
||||||
|
C = 0x2E,
|
||||||
|
V = 0x2F,
|
||||||
|
B = 0x30,
|
||||||
|
N = 0x31,
|
||||||
|
M = 0x32,
|
||||||
|
|
||||||
|
Comma = 0x33,
|
||||||
|
Period = 0x34,
|
||||||
|
Slash = 0x35,
|
||||||
|
RightShift = 0x36,
|
||||||
|
NumpadMultiply = 0x37,
|
||||||
|
LeftAlt = 0x38,
|
||||||
|
Space = 0x39,
|
||||||
|
CapsLock = 0x3A,
|
||||||
|
|
||||||
|
F1 = 0x3B,
|
||||||
|
F2 = 0x3C,
|
||||||
|
F3 = 0x3D,
|
||||||
|
F4 = 0x3E,
|
||||||
|
F5 = 0x3F,
|
||||||
|
F6 = 0x40,
|
||||||
|
F7 = 0x41,
|
||||||
|
F8 = 0x42,
|
||||||
|
F9 = 0x43,
|
||||||
|
F10 = 0x44,
|
||||||
|
|
||||||
|
NumLock = 0x45,
|
||||||
|
ScrollLock = 0x46,
|
||||||
|
|
||||||
|
Numpad7 = 0x47,
|
||||||
|
Numpad8 = 0x48,
|
||||||
|
Numpad9 = 0x49,
|
||||||
|
|
||||||
|
NumpadMinus = 0x4A,
|
||||||
|
|
||||||
|
Numpad4 = 0x4B,
|
||||||
|
Numpad5 = 0x4C,
|
||||||
|
Numpad6 = 0x4D,
|
||||||
|
|
||||||
|
NumpadPlus = 0x4E,
|
||||||
|
|
||||||
|
Numpad1 = 0x4F,
|
||||||
|
Numpad2 = 0x50,
|
||||||
|
Numpad3 = 0x51,
|
||||||
|
Numpad0 = 0x52,
|
||||||
|
|
||||||
|
NumpadPeriod = 0x53,
|
||||||
|
AltPrintScreen = 0x54, /* Alt + print screen. */
|
||||||
|
Int1 = 0x56, /* Key between the left shift and Z. */
|
||||||
|
|
||||||
|
F11 = 0x57,
|
||||||
|
F12 = 0x58,
|
||||||
|
|
||||||
|
Oem1 = 0x5A, /* VK_OEM_WSCTRL */
|
||||||
|
Oem2 = 0x5B, /* VK_OEM_FINISH */
|
||||||
|
Oem3 = 0x5C, /* VK_OEM_JUMP */
|
||||||
|
|
||||||
|
EraseEOF = 0x5D,
|
||||||
|
|
||||||
|
Oem4 = 0x5E, /* VK_OEM_BACKTAB */
|
||||||
|
Oem5 = 0x5F, /* VK_OEM_AUTO */
|
||||||
|
|
||||||
|
Zoom = 0x62,
|
||||||
|
Help = 0x63,
|
||||||
|
|
||||||
|
F13 = 0x64,
|
||||||
|
F14 = 0x65,
|
||||||
|
F15 = 0x66,
|
||||||
|
F16 = 0x67,
|
||||||
|
F17 = 0x68,
|
||||||
|
F18 = 0x69,
|
||||||
|
F19 = 0x6A,
|
||||||
|
F20 = 0x6B,
|
||||||
|
F21 = 0x6C,
|
||||||
|
F22 = 0x6D,
|
||||||
|
F23 = 0x6E,
|
||||||
|
|
||||||
|
Oem6 = 0x6F, /* VK_OEM_PA3 */
|
||||||
|
Katakana = 0x70,
|
||||||
|
Oem7 = 0x71, /* VK_OEM_RESET */
|
||||||
|
F24 = 0x76,
|
||||||
|
|
||||||
|
SBCSChar = 0x77,
|
||||||
|
Convert = 0x79,
|
||||||
|
NonConvert = 0x7B, /* VK_OEM_PA1 */
|
||||||
|
}
|
46
src-slider_io/Cargo.lock
generated
46
src-slider_io/Cargo.lock
generated
@ -613,6 +613,20 @@ dependencies = [
|
|||||||
"hashbrown",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "interception"
|
||||||
|
version = "0.1.2"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"interception-sys",
|
||||||
|
"num_enum",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "interception-sys"
|
||||||
|
version = "0.1.3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ipconfig"
|
name = "ipconfig"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
@ -864,6 +878,27 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_enum"
|
||||||
|
version = "0.5.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf5395665662ef45796a4ff5486c5d41d29e0c09640af4c5f17fd94ee2c119c9"
|
||||||
|
dependencies = [
|
||||||
|
"num_enum_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_enum_derive"
|
||||||
|
version = "0.5.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3b0498641e53dd6ac1a4f22547548caa6864cc4933784319cd1775271c5a46ce"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro-crate",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.9.0"
|
version = "1.9.0"
|
||||||
@ -1053,6 +1088,16 @@ version = "0.2.16"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
|
checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro-crate"
|
||||||
|
version = "1.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror",
|
||||||
|
"toml",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-hack"
|
name = "proc-macro-hack"
|
||||||
version = "0.5.19"
|
version = "0.5.19"
|
||||||
@ -1308,6 +1353,7 @@ dependencies = [
|
|||||||
"futures-util",
|
"futures-util",
|
||||||
"hyper",
|
"hyper",
|
||||||
"image",
|
"image",
|
||||||
|
"interception",
|
||||||
"ipconfig",
|
"ipconfig",
|
||||||
"log",
|
"log",
|
||||||
"palette",
|
"palette",
|
||||||
|
@ -31,6 +31,7 @@ serialport = "4.0.1"
|
|||||||
wwserial = {path = "../src-wwserial" }
|
wwserial = {path = "../src-wwserial" }
|
||||||
vigem-client = { version = "0.1.2", features = ["unstable"] }
|
vigem-client = { version = "0.1.2", features = ["unstable"] }
|
||||||
winapi = "0.3.9"
|
winapi = "0.3.9"
|
||||||
|
interception = {path = "../src-interception-rs" }
|
||||||
ipconfig = "0.3.0"
|
ipconfig = "0.3.0"
|
||||||
|
|
||||||
# webserver
|
# webserver
|
||||||
|
42
src-slider_io/src/bin/test_directinput.rs
Normal file
42
src-slider_io/src/bin/test_directinput.rs
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
extern crate slider_io;
|
||||||
|
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
use slider_io::{config::Config, context::Context};
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() {
|
||||||
|
env_logger::Builder::new()
|
||||||
|
.filter_level(log::LevelFilter::Debug)
|
||||||
|
.init();
|
||||||
|
|
||||||
|
let config = Config::from_str(
|
||||||
|
r##"{
|
||||||
|
"deviceMode": "brokenithm",
|
||||||
|
"outputMode": "kb-32-tasoller",
|
||||||
|
"ledMode": "none",
|
||||||
|
"disableAirStrings": false,
|
||||||
|
"divaSerialPort": "COM1",
|
||||||
|
"divaBrightness": 63,
|
||||||
|
"brokenithmPort": 1606,
|
||||||
|
"keyboardSensitivity": 20,
|
||||||
|
"keyboardDirectInput": true,
|
||||||
|
"outputPolling": "100",
|
||||||
|
"outputWebsocketUrl": "localhost:3000",
|
||||||
|
"ledFaster": false,
|
||||||
|
"ledColorActive": "#ff00ff",
|
||||||
|
"ledColorInactive": "#ffff00",
|
||||||
|
"ledSensitivity": 20,
|
||||||
|
"ledWebsocketUrl": "localhost:3001",
|
||||||
|
"ledSerialPort": "COM5"
|
||||||
|
}"##,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
println!("{:?}", config);
|
||||||
|
|
||||||
|
let ctx = Context::new(config);
|
||||||
|
|
||||||
|
println!("Press enter to quit");
|
||||||
|
let mut input = String::new();
|
||||||
|
io::stdin().read_line(&mut input).unwrap();
|
||||||
|
}
|
@ -37,6 +37,7 @@ impl Config {
|
|||||||
"divaBrightness": 63,
|
"divaBrightness": 63,
|
||||||
"brokenithmPort": 1606,
|
"brokenithmPort": 1606,
|
||||||
"keyboardSensitivity": 20,
|
"keyboardSensitivity": 20,
|
||||||
|
"keyboardDirectInput": false,
|
||||||
"outputPolling": "100",
|
"outputPolling": "100",
|
||||||
"outputWebsocketUrl": "localhost:3000",
|
"outputWebsocketUrl": "localhost:3000",
|
||||||
"ledFaster": false,
|
"ledFaster": false,
|
||||||
|
@ -41,6 +41,7 @@ pub enum OutputMode {
|
|||||||
layout: KeyboardLayout,
|
layout: KeyboardLayout,
|
||||||
polling: PollingRate,
|
polling: PollingRate,
|
||||||
sensitivity: u8,
|
sensitivity: u8,
|
||||||
|
direct_input: bool,
|
||||||
},
|
},
|
||||||
Gamepad {
|
Gamepad {
|
||||||
layout: GamepadLayout,
|
layout: GamepadLayout,
|
||||||
@ -89,46 +90,55 @@ impl OutputMode {
|
|||||||
layout: KeyboardLayout::Tasoller,
|
layout: KeyboardLayout::Tasoller,
|
||||||
polling: PollingRate::from_str(v["outputPolling"].as_str()?)?,
|
polling: PollingRate::from_str(v["outputPolling"].as_str()?)?,
|
||||||
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
||||||
|
direct_input: v["keyboardDirectInput"].as_bool()?,
|
||||||
},
|
},
|
||||||
"kb-32-yuancon" => OutputMode::Keyboard {
|
"kb-32-yuancon" => OutputMode::Keyboard {
|
||||||
layout: KeyboardLayout::Yuancon,
|
layout: KeyboardLayout::Yuancon,
|
||||||
polling: PollingRate::from_str(v["outputPolling"].as_str()?)?,
|
polling: PollingRate::from_str(v["outputPolling"].as_str()?)?,
|
||||||
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
||||||
|
direct_input: v["keyboardDirectInput"].as_bool()?,
|
||||||
},
|
},
|
||||||
"kb-32-umiguri" => OutputMode::Keyboard {
|
"kb-32-umiguri" => OutputMode::Keyboard {
|
||||||
layout: KeyboardLayout::Umiguri,
|
layout: KeyboardLayout::Umiguri,
|
||||||
polling: PollingRate::from_str(v["outputPolling"].as_str()?)?,
|
polling: PollingRate::from_str(v["outputPolling"].as_str()?)?,
|
||||||
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
||||||
|
direct_input: v["keyboardDirectInput"].as_bool()?,
|
||||||
},
|
},
|
||||||
"kb-16" => OutputMode::Keyboard {
|
"kb-16" => OutputMode::Keyboard {
|
||||||
layout: KeyboardLayout::TasollerHalf,
|
layout: KeyboardLayout::TasollerHalf,
|
||||||
polling: PollingRate::from_str(v["outputPolling"].as_str()?)?,
|
polling: PollingRate::from_str(v["outputPolling"].as_str()?)?,
|
||||||
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
||||||
|
direct_input: v["keyboardDirectInput"].as_bool()?,
|
||||||
},
|
},
|
||||||
"kb-8" => OutputMode::Keyboard {
|
"kb-8" => OutputMode::Keyboard {
|
||||||
layout: KeyboardLayout::EightK,
|
layout: KeyboardLayout::EightK,
|
||||||
polling: PollingRate::from_str(v["outputPolling"].as_str()?)?,
|
polling: PollingRate::from_str(v["outputPolling"].as_str()?)?,
|
||||||
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
||||||
|
direct_input: v["keyboardDirectInput"].as_bool()?,
|
||||||
},
|
},
|
||||||
"kb-6" => OutputMode::Keyboard {
|
"kb-6" => OutputMode::Keyboard {
|
||||||
layout: KeyboardLayout::SixK,
|
layout: KeyboardLayout::SixK,
|
||||||
polling: PollingRate::from_str(v["outputPolling"].as_str()?)?,
|
polling: PollingRate::from_str(v["outputPolling"].as_str()?)?,
|
||||||
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
||||||
|
direct_input: v["keyboardDirectInput"].as_bool()?,
|
||||||
},
|
},
|
||||||
"kb-4" => OutputMode::Keyboard {
|
"kb-4" => OutputMode::Keyboard {
|
||||||
layout: KeyboardLayout::FourK,
|
layout: KeyboardLayout::FourK,
|
||||||
polling: PollingRate::from_str(v["outputPolling"].as_str()?)?,
|
polling: PollingRate::from_str(v["outputPolling"].as_str()?)?,
|
||||||
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
||||||
|
direct_input: v["keyboardDirectInput"].as_bool()?,
|
||||||
},
|
},
|
||||||
"kb-voltex" => OutputMode::Keyboard {
|
"kb-voltex" => OutputMode::Keyboard {
|
||||||
layout: KeyboardLayout::Voltex,
|
layout: KeyboardLayout::Voltex,
|
||||||
polling: PollingRate::from_str(v["outputPolling"].as_str()?)?,
|
polling: PollingRate::from_str(v["outputPolling"].as_str()?)?,
|
||||||
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
||||||
|
direct_input: v["keyboardDirectInput"].as_bool()?,
|
||||||
},
|
},
|
||||||
"kb-neardayo" => OutputMode::Keyboard {
|
"kb-neardayo" => OutputMode::Keyboard {
|
||||||
layout: KeyboardLayout::Neardayo,
|
layout: KeyboardLayout::Neardayo,
|
||||||
polling: PollingRate::from_str(v["outputPolling"].as_str()?)?,
|
polling: PollingRate::from_str(v["outputPolling"].as_str()?)?,
|
||||||
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
sensitivity: u8::try_from(v["keyboardSensitivity"].as_i64()?).ok()?,
|
||||||
|
direct_input: v["keyboardDirectInput"].as_bool()?,
|
||||||
},
|
},
|
||||||
"gamepad-voltex" => OutputMode::Gamepad {
|
"gamepad-voltex" => OutputMode::Gamepad {
|
||||||
layout: GamepadLayout::Voltex,
|
layout: GamepadLayout::Voltex,
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
|
use interception::{Interception, KeyState, ScanCode, Stroke};
|
||||||
|
use log::{error, info};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use winapi::{
|
use winapi::{
|
||||||
ctypes::c_int,
|
ctypes::c_int,
|
||||||
um::winuser::{SendInput, INPUT, INPUT_KEYBOARD, KEYBDINPUT, KEYEVENTF_KEYUP},
|
um::winuser::{
|
||||||
|
MapVirtualKeyA, SendInput, INPUT, INPUT_KEYBOARD, KEYBDINPUT, KEYEVENTF_KEYUP, MAPVK_VK_TO_VSC,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{config::KeyboardLayout, output::OutputHandler};
|
||||||
config::KeyboardLayout,
|
|
||||||
output::OutputHandler
|
|
||||||
};
|
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
const TASOLLER_KB_MAP: [usize; 41] = [
|
const TASOLLER_KB_MAP: [usize; 41] = [
|
||||||
@ -126,18 +127,25 @@ const VOLTEX_KB_MAP_NEARDAYO: [usize; 41] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
pub struct KeyboardOutput {
|
pub struct KeyboardOutput {
|
||||||
ground_to_idx: [usize; 41],
|
input_to_idx: [usize; 41],
|
||||||
idx_to_keycode: [u16; 41],
|
key_idx_to_keycode: [u16; 41],
|
||||||
// keycode_to_idx: [usize; 256],
|
key_idx_to_scancode: [Option<ScanCode>; 41],
|
||||||
next_keys: [bool; 41],
|
next_keys: [bool; 41],
|
||||||
last_keys: [bool; 41],
|
last_keys: [bool; 41],
|
||||||
|
|
||||||
|
direct_input: bool,
|
||||||
|
interception_handle: Option<Interception>,
|
||||||
|
|
||||||
kb_buf: [INPUT; 41],
|
kb_buf: [INPUT; 41],
|
||||||
|
kb_direct_buf: [Stroke; 41],
|
||||||
n_kb_buf: u32,
|
n_kb_buf: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// interception isn't send, but lazy to wrap
|
||||||
|
unsafe impl Send for KeyboardOutput {}
|
||||||
|
|
||||||
impl KeyboardOutput {
|
impl KeyboardOutput {
|
||||||
pub fn new(layout: KeyboardLayout) -> Self {
|
pub fn new(layout: KeyboardLayout, direct_input: bool) -> Self {
|
||||||
let kb_map = match layout {
|
let kb_map = match layout {
|
||||||
KeyboardLayout::Tasoller => &TASOLLER_KB_MAP,
|
KeyboardLayout::Tasoller => &TASOLLER_KB_MAP,
|
||||||
KeyboardLayout::Yuancon => &YUANCON_KB_MAP,
|
KeyboardLayout::Yuancon => &YUANCON_KB_MAP,
|
||||||
@ -150,20 +158,43 @@ impl KeyboardOutput {
|
|||||||
KeyboardLayout::Neardayo => &VOLTEX_KB_MAP_NEARDAYO,
|
KeyboardLayout::Neardayo => &VOLTEX_KB_MAP_NEARDAYO,
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut ground_to_idx = [0 as usize; 41];
|
let mut input_to_key_idx = [0 as usize; 41];
|
||||||
let mut idx_to_keycode = [0 as u16; 41];
|
let mut key_idx_to_keycode = [0 as u16; 41];
|
||||||
|
let mut key_idx_to_scancode = [None as Option<ScanCode>; 41];
|
||||||
let mut keycode_to_idx = [0xffff as usize; 256];
|
let mut keycode_to_idx = [0xffff as usize; 256];
|
||||||
let mut keycode_count: usize = 0;
|
let mut keycode_count: usize = 0;
|
||||||
|
|
||||||
for (ground, keycode) in kb_map.iter().enumerate() {
|
for (ground, keycode) in kb_map.iter().enumerate() {
|
||||||
if keycode_to_idx[*keycode] == 0xffff {
|
if keycode_to_idx[*keycode] == 0xffff {
|
||||||
keycode_to_idx[*keycode] = keycode_count;
|
keycode_to_idx[*keycode] = keycode_count;
|
||||||
idx_to_keycode[keycode_count] = *keycode as u16;
|
key_idx_to_keycode[keycode_count] = *keycode as u16;
|
||||||
|
key_idx_to_scancode[keycode_count] =
|
||||||
|
ScanCode::try_from(unsafe { MapVirtualKeyA((*keycode) as u32, MAPVK_VK_TO_VSC) as u16 })
|
||||||
|
.ok();
|
||||||
|
// info!(
|
||||||
|
// "mapped {:?} to {:?}",
|
||||||
|
// key_idx_to_keycode[keycode_count], key_idx_to_scancode[keycode_count]
|
||||||
|
// );
|
||||||
keycode_count += 1;
|
keycode_count += 1;
|
||||||
}
|
}
|
||||||
ground_to_idx[ground] = keycode_to_idx[*keycode]
|
input_to_key_idx[ground] = keycode_to_idx[*keycode]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let interception_handle = match direct_input {
|
||||||
|
true => {
|
||||||
|
let inner_handle = Interception::new();
|
||||||
|
|
||||||
|
if inner_handle.is_some() {
|
||||||
|
info!("Keyboard emulation with interception loaded");
|
||||||
|
} else {
|
||||||
|
error!("Keyboard emulation cannot load interception, falling back to SendKeys()");
|
||||||
|
}
|
||||||
|
inner_handle
|
||||||
|
}
|
||||||
|
false => None,
|
||||||
|
};
|
||||||
|
let direct_input = interception_handle.is_some();
|
||||||
|
|
||||||
let mut kb_buf = [INPUT {
|
let mut kb_buf = [INPUT {
|
||||||
type_: INPUT_KEYBOARD,
|
type_: INPUT_KEYBOARD,
|
||||||
u: unsafe { mem::zeroed() },
|
u: unsafe { mem::zeroed() },
|
||||||
@ -178,13 +209,24 @@ impl KeyboardOutput {
|
|||||||
inner.dwExtraInfo = 0;
|
inner.dwExtraInfo = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let kb_direct_buf = [Stroke::Keyboard {
|
||||||
|
code: ScanCode::Esc,
|
||||||
|
state: KeyState::UP,
|
||||||
|
information: 0,
|
||||||
|
}; 41];
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
ground_to_idx,
|
input_to_idx: input_to_key_idx,
|
||||||
idx_to_keycode,
|
key_idx_to_keycode,
|
||||||
// keycode_to_idx,
|
key_idx_to_scancode,
|
||||||
next_keys: [false; 41],
|
next_keys: [false; 41],
|
||||||
last_keys: [false; 41],
|
last_keys: [false; 41],
|
||||||
|
|
||||||
|
direct_input,
|
||||||
|
interception_handle,
|
||||||
|
|
||||||
kb_buf,
|
kb_buf,
|
||||||
|
kb_direct_buf,
|
||||||
n_kb_buf: 0,
|
n_kb_buf: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -198,24 +240,52 @@ impl KeyboardOutput {
|
|||||||
.zip(self.last_keys.iter_mut())
|
.zip(self.last_keys.iter_mut())
|
||||||
.enumerate()
|
.enumerate()
|
||||||
{
|
{
|
||||||
let keycode = self.idx_to_keycode[i];
|
let keycode = self.key_idx_to_keycode[i];
|
||||||
if keycode == 0 {
|
let scancode = self.key_idx_to_scancode[i];
|
||||||
|
|
||||||
|
if (!self.direct_input && keycode == 0) || (self.direct_input && scancode.is_none()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
match (*n, *l) {
|
match (self.direct_input, *n, *l) {
|
||||||
(true, false) => {
|
(false, true, false) => {
|
||||||
let inner: &mut KEYBDINPUT = unsafe { self.kb_buf[self.n_kb_buf as usize].u.ki_mut() };
|
let inner: &mut KEYBDINPUT = unsafe { self.kb_buf[self.n_kb_buf as usize].u.ki_mut() };
|
||||||
inner.wVk = keycode;
|
inner.wVk = keycode;
|
||||||
inner.dwFlags = 0;
|
inner.dwFlags = 0;
|
||||||
self.n_kb_buf += 1;
|
self.n_kb_buf += 1;
|
||||||
// println!("{} down", keycode);
|
|
||||||
}
|
}
|
||||||
(false, true) => {
|
(false, false, true) => {
|
||||||
let inner: &mut KEYBDINPUT = unsafe { self.kb_buf[self.n_kb_buf as usize].u.ki_mut() };
|
let inner: &mut KEYBDINPUT = unsafe { self.kb_buf[self.n_kb_buf as usize].u.ki_mut() };
|
||||||
inner.wVk = keycode;
|
inner.wVk = keycode;
|
||||||
inner.dwFlags = KEYEVENTF_KEYUP;
|
inner.dwFlags = KEYEVENTF_KEYUP;
|
||||||
self.n_kb_buf += 1;
|
self.n_kb_buf += 1;
|
||||||
// println!("{} up", keycode);
|
}
|
||||||
|
(true, true, false) => {
|
||||||
|
// info!("keydown {:?}", scancode);
|
||||||
|
let inner: &mut Stroke = &mut self.kb_direct_buf[self.n_kb_buf as usize];
|
||||||
|
if let Stroke::Keyboard {
|
||||||
|
code,
|
||||||
|
state,
|
||||||
|
information: _,
|
||||||
|
} = inner
|
||||||
|
{
|
||||||
|
*code = scancode.unwrap();
|
||||||
|
*state = KeyState::DOWN;
|
||||||
|
self.n_kb_buf += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(true, false, true) => {
|
||||||
|
// info!("keyup {:?}", scancode);
|
||||||
|
let inner: &mut Stroke = &mut self.kb_direct_buf[self.n_kb_buf as usize];
|
||||||
|
if let Stroke::Keyboard {
|
||||||
|
code,
|
||||||
|
state,
|
||||||
|
information: _,
|
||||||
|
} = inner
|
||||||
|
{
|
||||||
|
*code = scancode.unwrap();
|
||||||
|
*state = KeyState::UP;
|
||||||
|
self.n_kb_buf += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@ -223,12 +293,19 @@ impl KeyboardOutput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if self.n_kb_buf != 0 {
|
if self.n_kb_buf != 0 {
|
||||||
unsafe {
|
match self.direct_input {
|
||||||
SendInput(
|
false => unsafe {
|
||||||
self.n_kb_buf,
|
SendInput(
|
||||||
self.kb_buf.as_mut_ptr(),
|
self.n_kb_buf,
|
||||||
mem::size_of::<INPUT>() as c_int,
|
self.kb_buf.as_mut_ptr(),
|
||||||
);
|
mem::size_of::<INPUT>() as c_int,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
true => {
|
||||||
|
if let Some(handle) = self.interception_handle.as_mut() {
|
||||||
|
handle.send(1, &self.kb_direct_buf[0..self.n_kb_buf as usize]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -239,7 +316,7 @@ impl OutputHandler for KeyboardOutput {
|
|||||||
self.next_keys.fill(false);
|
self.next_keys.fill(false);
|
||||||
for (idx, x) in flat_input.iter().enumerate() {
|
for (idx, x) in flat_input.iter().enumerate() {
|
||||||
if *x {
|
if *x {
|
||||||
self.next_keys[self.ground_to_idx[idx]] = true;
|
self.next_keys[self.input_to_idx[idx]] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.send();
|
self.send();
|
||||||
|
@ -42,9 +42,10 @@ impl AsyncJob for OutputJob {
|
|||||||
layout,
|
layout,
|
||||||
polling,
|
polling,
|
||||||
sensitivity,
|
sensitivity,
|
||||||
|
direct_input,
|
||||||
} => {
|
} => {
|
||||||
self.sensitivity = sensitivity;
|
self.sensitivity = sensitivity;
|
||||||
self.handler = Some(Box::new(KeyboardOutput::new(layout.clone())));
|
self.handler = Some(Box::new(KeyboardOutput::new(layout.clone(), direct_input)));
|
||||||
self.timer = interval(Duration::from_micros(polling.to_t_u64()));
|
self.timer = interval(Duration::from_micros(polling.to_t_u64()));
|
||||||
|
|
||||||
true
|
true
|
||||||
|
15
src-tauri/Cargo.lock
generated
15
src-tauri/Cargo.lock
generated
@ -1497,6 +1497,20 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "interception"
|
||||||
|
version = "0.1.2"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"interception-sys",
|
||||||
|
"num_enum",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "interception-sys"
|
||||||
|
version = "0.1.3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ipconfig"
|
name = "ipconfig"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
@ -2954,6 +2968,7 @@ dependencies = [
|
|||||||
"futures-util",
|
"futures-util",
|
||||||
"hyper",
|
"hyper",
|
||||||
"image 0.23.14",
|
"image 0.23.14",
|
||||||
|
"interception",
|
||||||
"ipconfig",
|
"ipconfig",
|
||||||
"log",
|
"log",
|
||||||
"palette",
|
"palette",
|
||||||
|
@ -38,6 +38,7 @@ fn main() {
|
|||||||
env_logger::Builder::new()
|
env_logger::Builder::new()
|
||||||
.filter_level(log::LevelFilter::Debug)
|
.filter_level(log::LevelFilter::Debug)
|
||||||
.init();
|
.init();
|
||||||
|
info!("Starting slidershim");
|
||||||
|
|
||||||
#[cfg(not(debug_assertions))]
|
#[cfg(not(debug_assertions))]
|
||||||
{
|
{
|
||||||
@ -45,7 +46,9 @@ fn main() {
|
|||||||
simple_logging::log_to_file(log_file_path.as_path(), log::LevelFilter::Debug).unwrap();
|
simple_logging::log_to_file(log_file_path.as_path(), log::LevelFilter::Debug).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info!("Loading config");
|
||||||
let config = Arc::new(Mutex::new(Some(slider_io::Config::load())));
|
let config = Arc::new(Mutex::new(Some(slider_io::Config::load())));
|
||||||
|
info!("Loading manager");
|
||||||
let manager = Arc::new(Mutex::new(slider_io::Manager::new()));
|
let manager = Arc::new(Mutex::new(slider_io::Manager::new()));
|
||||||
{
|
{
|
||||||
let config_handle = config.lock();
|
let config_handle = config.lock();
|
||||||
@ -55,6 +58,7 @@ fn main() {
|
|||||||
manager_handle.update_config(config_handle_ref.clone());
|
manager_handle.update_config(config_handle_ref.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info!("Running tauri");
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.system_tray(
|
.system_tray(
|
||||||
// System tray content
|
// System tray content
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
let divaBrightness = 63;
|
let divaBrightness = 63;
|
||||||
let brokenithmPort = 1606;
|
let brokenithmPort = 1606;
|
||||||
let keyboardSensitivity = 20;
|
let keyboardSensitivity = 20;
|
||||||
|
let keyboardDirectInput = false;
|
||||||
let outputPolling = "100";
|
let outputPolling = "100";
|
||||||
let outputWebsocketUrl = "http://localhost:3000";
|
let outputWebsocketUrl = "http://localhost:3000";
|
||||||
let ledFaster = false;
|
let ledFaster = false;
|
||||||
@ -69,6 +70,7 @@
|
|||||||
divaBrightness = payload.divaBrightness || 63;
|
divaBrightness = payload.divaBrightness || 63;
|
||||||
brokenithmPort = payload.brokenithmPort || 1606;
|
brokenithmPort = payload.brokenithmPort || 1606;
|
||||||
keyboardSensitivity = payload.keyboardSensitivity || 20;
|
keyboardSensitivity = payload.keyboardSensitivity || 20;
|
||||||
|
keyboardDirectInput = payload.keyboardDirectInput || false;
|
||||||
outputPolling = payload.outputPolling || "100";
|
outputPolling = payload.outputPolling || "100";
|
||||||
outputWebsocketUrl =
|
outputWebsocketUrl =
|
||||||
payload.outputWebsocketUrl || "http://localhost:3000/";
|
payload.outputWebsocketUrl || "http://localhost:3000/";
|
||||||
@ -125,6 +127,7 @@
|
|||||||
divaBrightness,
|
divaBrightness,
|
||||||
brokenithmPort,
|
brokenithmPort,
|
||||||
keyboardSensitivity,
|
keyboardSensitivity,
|
||||||
|
keyboardDirectInput,
|
||||||
outputPolling,
|
outputPolling,
|
||||||
outputWebsocketUrl,
|
outputWebsocketUrl,
|
||||||
ledFaster,
|
ledFaster,
|
||||||
@ -386,6 +389,28 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if outputMode.slice(0, 2) === "kb"}
|
||||||
|
<div class="row">
|
||||||
|
<div class="label" title="Larger means harder to trigger">
|
||||||
|
Use DirectInput emulation
|
||||||
|
</div>
|
||||||
|
<div class="input">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
bind:checked={keyboardDirectInput}
|
||||||
|
on:change={markDirty}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="label" />
|
||||||
|
<div class="input comment">
|
||||||
|
DirectInput emulation requires <Link
|
||||||
|
href="https://github.com/oblitum/Interception/releases/tag/v1.0.1">Interception</Link
|
||||||
|
> to be installed
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
{#if outputMode === "websocket"}
|
{#if outputMode === "websocket"}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="label">Output URL</div>
|
<div class="label">Output URL</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user