@desklink/host 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/NOTICE +44 -0
- package/README.md +266 -0
- package/bin/desklink-host.mjs +113 -0
- package/dist/bridge.d.ts +57 -0
- package/dist/bridge.d.ts.map +1 -0
- package/dist/bridge.js +208 -0
- package/dist/bridge.js.map +1 -0
- package/dist/engineProcess.d.ts +82 -0
- package/dist/engineProcess.d.ts.map +1 -0
- package/dist/engineProcess.js +243 -0
- package/dist/engineProcess.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/protocol.d.ts +169 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +18 -0
- package/dist/protocol.js.map +1 -0
- package/dist/resolveEngine.d.ts +34 -0
- package/dist/resolveEngine.d.ts.map +1 -0
- package/dist/resolveEngine.js +103 -0
- package/dist/resolveEngine.js.map +1 -0
- package/docs/BOUNDARY.md +145 -0
- package/docs/PROTOCOL.md +363 -0
- package/engine/Cargo.lock +3077 -0
- package/engine/Cargo.toml +37 -0
- package/engine/build.rs +107 -0
- package/engine/native/inputtino_shim.cpp +11 -0
- package/engine/native/vpx_shim.c +184 -0
- package/engine/native/wrapper.h +7 -0
- package/engine/src/capture.rs +510 -0
- package/engine/src/clipboard.rs +132 -0
- package/engine/src/convert.rs +299 -0
- package/engine/src/encoder.rs +204 -0
- package/engine/src/input.rs +355 -0
- package/engine/src/keymap.rs +338 -0
- package/engine/src/main.rs +614 -0
- package/engine/src/peer.rs +775 -0
- package/engine/src/portal.rs +115 -0
- package/engine/src/protocol.rs +331 -0
- package/engine/src/session.rs +2159 -0
- package/engine/src/x11.rs +244 -0
- package/engine/vendor/inputtino/.clang-format +166 -0
- package/engine/vendor/inputtino/.clang-tidy +30 -0
- package/engine/vendor/inputtino/.dockerignore +11 -0
- package/engine/vendor/inputtino/.github/workflows/mirror-repo.yml +14 -0
- package/engine/vendor/inputtino/.github/workflows/python-lint-format-test-typecheck.yml +124 -0
- package/engine/vendor/inputtino/.github/workflows/python-test-install.yaml +49 -0
- package/engine/vendor/inputtino/.github/workflows/rust.yml +40 -0
- package/engine/vendor/inputtino/CMakeLists.txt +187 -0
- package/engine/vendor/inputtino/LICENSE +21 -0
- package/engine/vendor/inputtino/README.md +110 -0
- package/engine/vendor/inputtino/bindings/python/.devcontainer/Dockerfile +23 -0
- package/engine/vendor/inputtino/bindings/python/.devcontainer/devcontainer.json +28 -0
- package/engine/vendor/inputtino/bindings/python/.python-version +1 -0
- package/engine/vendor/inputtino/bindings/python/CMakeLists.txt +23 -0
- package/engine/vendor/inputtino/bindings/python/CPPLINT.cfg +2 -0
- package/engine/vendor/inputtino/bindings/python/Makefile +49 -0
- package/engine/vendor/inputtino/bindings/python/README.md +215 -0
- package/engine/vendor/inputtino/bindings/python/pyproject.toml +178 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/__init__.py +43 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/_core.pyi +533 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/base.py +63 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/joypad.py +248 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/keyboard.py +256 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/mouse.py +106 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/pentablet.py +73 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/py.typed +0 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/touchscreen.py +61 -0
- package/engine/vendor/inputtino/bindings/python/src/inputtino/trackpad.py +74 -0
- package/engine/vendor/inputtino/bindings/python/src/main.cpp +217 -0
- package/engine/vendor/inputtino/bindings/python/tests/__init__.py +0 -0
- package/engine/vendor/inputtino/bindings/python/tests/helpers.py +3 -0
- package/engine/vendor/inputtino/bindings/python/tests/test_base.py +60 -0
- package/engine/vendor/inputtino/bindings/python/tests/test_inputtino.py +5 -0
- package/engine/vendor/inputtino/bindings/python/tests/test_joypad.py +332 -0
- package/engine/vendor/inputtino/bindings/python/tests/test_keyboard.py +164 -0
- package/engine/vendor/inputtino/bindings/python/tests/test_mouse.py +185 -0
- package/engine/vendor/inputtino/bindings/python/tests/test_pentablet.py +198 -0
- package/engine/vendor/inputtino/bindings/python/tests/test_touchscreen.py +144 -0
- package/engine/vendor/inputtino/bindings/python/tests/test_trackpad.py +146 -0
- package/engine/vendor/inputtino/bindings/python/uv.lock +390 -0
- package/engine/vendor/inputtino/bindings/rust/Cargo.toml +6 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/.dockerignore +1 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/Cargo.toml +18 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/examples/keyboard.rs +33 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/examples/mouse.rs +17 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/common.rs +116 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/error.rs +17 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/joypad.rs +74 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/joypad_nintendo.rs +135 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/joypad_ps5.rs +280 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/joypad_xbox.rs +134 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/keyboard.rs +76 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/lib.rs +32 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/src/mouse.rs +178 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/tests/common.rs +38 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/tests/joypads.rs +150 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/tests/keyboard.rs +73 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino/tests/mouse.rs +139 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino-sys/.dockerignore +1 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino-sys/Cargo.toml +12 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino-sys/build.rs +48 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino-sys/src/lib.rs +5 -0
- package/engine/vendor/inputtino/bindings/rust/inputtino-sys/wrapper.h +1 -0
- package/engine/vendor/inputtino/cmake/utils.cmake +9 -0
- package/engine/vendor/inputtino/docker/Dockerfile +70 -0
- package/engine/vendor/inputtino/include/inputtino/input.h +324 -0
- package/engine/vendor/inputtino/include/inputtino/input.hpp +466 -0
- package/engine/vendor/inputtino/include/inputtino/result.hpp +37 -0
- package/engine/vendor/inputtino/share/pkgconfig/libinputtino.pc.in +17 -0
- package/engine/vendor/inputtino/src/c-bindings/helpers.hpp +19 -0
- package/engine/vendor/inputtino/src/c-bindings/joypad_ps5.cpp +115 -0
- package/engine/vendor/inputtino/src/c-bindings/joypad_switch.cpp +63 -0
- package/engine/vendor/inputtino/src/c-bindings/joypad_xone.cpp +62 -0
- package/engine/vendor/inputtino/src/c-bindings/keyboard.cpp +42 -0
- package/engine/vendor/inputtino/src/c-bindings/mouse.cpp +67 -0
- package/engine/vendor/inputtino/src/c-bindings/pen_tablet.cpp +50 -0
- package/engine/vendor/inputtino/src/c-bindings/touchscreen.cpp +43 -0
- package/engine/vendor/inputtino/src/c-bindings/trackpad.cpp +49 -0
- package/engine/vendor/inputtino/src/uhid/README.adoc +63 -0
- package/engine/vendor/inputtino/src/uhid/include/crc32.hpp +38 -0
- package/engine/vendor/inputtino/src/uhid/include/uhid/protected_types.hpp +36 -0
- package/engine/vendor/inputtino/src/uhid/include/uhid/ps5.hpp +550 -0
- package/engine/vendor/inputtino/src/uhid/include/uhid/uhid.hpp +168 -0
- package/engine/vendor/inputtino/src/uhid/joypad_ps5.cpp +580 -0
- package/engine/vendor/inputtino/src/uinput/include/inputtino/keyboard.hpp +84 -0
- package/engine/vendor/inputtino/src/uinput/include/inputtino/protected_ps5_types.hpp +7 -0
- package/engine/vendor/inputtino/src/uinput/include/inputtino/protected_types.hpp +110 -0
- package/engine/vendor/inputtino/src/uinput/joypad_nintendo.cpp +190 -0
- package/engine/vendor/inputtino/src/uinput/joypad_ps.cpp +203 -0
- package/engine/vendor/inputtino/src/uinput/joypad_utils.hpp +246 -0
- package/engine/vendor/inputtino/src/uinput/joypad_xbox.cpp +190 -0
- package/engine/vendor/inputtino/src/uinput/keyboard.cpp +120 -0
- package/engine/vendor/inputtino/src/uinput/mouse.cpp +199 -0
- package/engine/vendor/inputtino/src/uinput/pentablet.cpp +162 -0
- package/engine/vendor/inputtino/src/uinput/touchscreen.cpp +140 -0
- package/engine/vendor/inputtino/src/uinput/trackpad.cpp +192 -0
- package/examples/reference-client.html +428 -0
- package/package.json +38 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
use std::ffi::{c_int, c_void};
|
|
2
|
+
use std::path::PathBuf;
|
|
3
|
+
|
|
4
|
+
use crate::common::{get_nodes, make_device, DeviceDefinition};
|
|
5
|
+
use crate::sys::{
|
|
6
|
+
inputtino_joypad_xone_create, inputtino_joypad_xone_destroy, inputtino_joypad_xone_get_nodes,
|
|
7
|
+
inputtino_joypad_xone_set_on_rumble, inputtino_joypad_xone_set_pressed_buttons,
|
|
8
|
+
inputtino_joypad_xone_set_stick, inputtino_joypad_xone_set_triggers,
|
|
9
|
+
};
|
|
10
|
+
use crate::{InputtinoError, JoypadStickPosition};
|
|
11
|
+
|
|
12
|
+
/// Emulated XBox One joypad.
|
|
13
|
+
pub struct XboxOneJoypad {
|
|
14
|
+
joypad: *mut crate::sys::InputtinoXOneJoypad,
|
|
15
|
+
on_rumble_fn: *mut c_void,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
impl XboxOneJoypad {
|
|
19
|
+
/// Create a new emulated XBox One joypad device with the given device definition.
|
|
20
|
+
///
|
|
21
|
+
/// # Examples
|
|
22
|
+
///
|
|
23
|
+
/// ```
|
|
24
|
+
/// let definition = inputtino::DeviceDefinition::new(
|
|
25
|
+
/// "Inputtino XBox One controller",
|
|
26
|
+
/// 0x045E,
|
|
27
|
+
/// 0x02DD,
|
|
28
|
+
/// 0x0100,
|
|
29
|
+
/// "00:11:22:33:44",
|
|
30
|
+
/// "00:11:22:33:44",
|
|
31
|
+
/// );
|
|
32
|
+
/// let device = inputtino::SwitchJoypad::new(&definition);
|
|
33
|
+
/// ```
|
|
34
|
+
pub fn new(device: &DeviceDefinition) -> Result<Self, InputtinoError> {
|
|
35
|
+
make_device(inputtino_joypad_xone_create, device).map(|joypad| XboxOneJoypad {
|
|
36
|
+
joypad,
|
|
37
|
+
on_rumble_fn: std::ptr::null_mut(),
|
|
38
|
+
})
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/// Set the state of all buttons.
|
|
42
|
+
///
|
|
43
|
+
/// Any buttons that are not set are released if they were set before.
|
|
44
|
+
///
|
|
45
|
+
/// # Examples
|
|
46
|
+
///
|
|
47
|
+
/// ```ignore
|
|
48
|
+
/// device.set_pressed(inputtino::JoypadButton::A | inputtino::JoypadButton::B);
|
|
49
|
+
/// ```
|
|
50
|
+
pub fn set_pressed(&self, buttons: i32) {
|
|
51
|
+
unsafe {
|
|
52
|
+
inputtino_joypad_xone_set_pressed_buttons(self.joypad, buttons);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/// Set the state of the triggers.
|
|
57
|
+
///
|
|
58
|
+
/// # Examples
|
|
59
|
+
///
|
|
60
|
+
/// ```ignore
|
|
61
|
+
/// device.set_triggers(0, -i16::MAX);
|
|
62
|
+
/// ```
|
|
63
|
+
pub fn set_triggers(&self, left_trigger: i16, right_trigger: i16) {
|
|
64
|
+
unsafe {
|
|
65
|
+
inputtino_joypad_xone_set_triggers(self.joypad, left_trigger, right_trigger);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/// Set the state of the joysticks.
|
|
70
|
+
///
|
|
71
|
+
/// # Examples
|
|
72
|
+
///
|
|
73
|
+
/// ```ignore
|
|
74
|
+
/// device.set_stick(inputtino::JoypadStickPosition::LS, 0, -i16::MAX);
|
|
75
|
+
/// ```
|
|
76
|
+
pub fn set_stick(&self, stick_type: JoypadStickPosition, x: i16, y: i16) {
|
|
77
|
+
unsafe {
|
|
78
|
+
inputtino_joypad_xone_set_stick(self.joypad, stick_type, x, y);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/// Sets a callback to be called when this device receives a rumble event.
|
|
83
|
+
///
|
|
84
|
+
/// # Examples
|
|
85
|
+
///
|
|
86
|
+
/// ```ignore
|
|
87
|
+
/// device.set_on_rumble(|low, high| {
|
|
88
|
+
/// println!("Received rumble event with frequencies low: {low}, high: {high}");
|
|
89
|
+
/// });
|
|
90
|
+
/// ```
|
|
91
|
+
pub fn set_on_rumble(&mut self, on_rumble_fn: impl FnMut(i32, i32) + 'static) {
|
|
92
|
+
let on_rumble_fn = Box::new(RumbleFunction {
|
|
93
|
+
on_rumble_fn: Box::new(on_rumble_fn),
|
|
94
|
+
});
|
|
95
|
+
self.on_rumble_fn = Box::into_raw(on_rumble_fn) as *mut c_void;
|
|
96
|
+
unsafe {
|
|
97
|
+
inputtino_joypad_xone_set_on_rumble(
|
|
98
|
+
self.joypad,
|
|
99
|
+
Some(on_rumble_c_fn),
|
|
100
|
+
self.on_rumble_fn,
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
pub fn get_nodes(&self) -> Result<Vec<PathBuf>, InputtinoError> {
|
|
106
|
+
get_nodes(inputtino_joypad_xone_get_nodes, self.joypad)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
impl Drop for XboxOneJoypad {
|
|
111
|
+
fn drop(&mut self) {
|
|
112
|
+
unsafe {
|
|
113
|
+
inputtino_joypad_xone_destroy(self.joypad);
|
|
114
|
+
if !self.on_rumble_fn.is_null() {
|
|
115
|
+
drop(Box::from_raw(self.on_rumble_fn as *mut RumbleFunction));
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
struct RumbleFunction {
|
|
122
|
+
on_rumble_fn: Box<dyn FnMut(i32, i32)>,
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
unsafe extern "C" fn on_rumble_c_fn(
|
|
126
|
+
left_motor: c_int,
|
|
127
|
+
right_motor: c_int,
|
|
128
|
+
user_data: *mut ::core::ffi::c_void,
|
|
129
|
+
) {
|
|
130
|
+
let on_rumble_fn = user_data as *mut RumbleFunction;
|
|
131
|
+
((*on_rumble_fn).on_rumble_fn)(left_motor, right_motor);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
unsafe impl Send for XboxOneJoypad {}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
use std::path::PathBuf;
|
|
2
|
+
|
|
3
|
+
use crate::common::{get_nodes, make_device, DeviceDefinition};
|
|
4
|
+
use crate::sys::{
|
|
5
|
+
inputtino_keyboard_create, inputtino_keyboard_destroy, inputtino_keyboard_get_nodes,
|
|
6
|
+
inputtino_keyboard_press, inputtino_keyboard_release,
|
|
7
|
+
};
|
|
8
|
+
use crate::InputtinoError;
|
|
9
|
+
|
|
10
|
+
/// Emulated keyboard device.
|
|
11
|
+
pub struct Keyboard {
|
|
12
|
+
kb: *mut crate::sys::InputtinoKeyboard,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
impl Keyboard {
|
|
16
|
+
/// Create a new emulated keyboard device with the given device definition.
|
|
17
|
+
///
|
|
18
|
+
/// # Examples
|
|
19
|
+
///
|
|
20
|
+
/// ```
|
|
21
|
+
/// let definition = inputtino::DeviceDefinition::new(
|
|
22
|
+
/// "Inputtino Keyboard",
|
|
23
|
+
/// 0xBEEF,
|
|
24
|
+
/// 0xDEAD,
|
|
25
|
+
/// 0x111,
|
|
26
|
+
/// "00:11:22:33:44",
|
|
27
|
+
/// "00:11:22:33:44",
|
|
28
|
+
/// );
|
|
29
|
+
/// let device = inputtino::Keyboard::new(&definition);
|
|
30
|
+
/// ```
|
|
31
|
+
pub fn new(device: &DeviceDefinition) -> Result<Self, InputtinoError> {
|
|
32
|
+
make_device(inputtino_keyboard_create, device).map(|kb| Keyboard { kb })
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
pub fn get_nodes(&self) -> Result<Vec<PathBuf>, InputtinoError> {
|
|
36
|
+
get_nodes(inputtino_keyboard_get_nodes, self.kb)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/// Simulate a keypress on this keyboard device.
|
|
40
|
+
///
|
|
41
|
+
/// # Examples
|
|
42
|
+
///
|
|
43
|
+
/// ```ignore
|
|
44
|
+
/// device.press_key(0x41); // KEY_A
|
|
45
|
+
/// ```
|
|
46
|
+
pub fn press_key(&self, key: i16) {
|
|
47
|
+
// TODO: Export key mapping in Rust.
|
|
48
|
+
unsafe {
|
|
49
|
+
inputtino_keyboard_press(self.kb, key);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/// Simulate a release of a key from this keyboard device.
|
|
54
|
+
///
|
|
55
|
+
/// # Examples
|
|
56
|
+
///
|
|
57
|
+
/// ```ignore
|
|
58
|
+
/// device.release_key(0x41); // KEY_A
|
|
59
|
+
/// ```
|
|
60
|
+
pub fn release_key(&self, key: i16) {
|
|
61
|
+
// TODO: Export key mapping in Rust.
|
|
62
|
+
unsafe {
|
|
63
|
+
inputtino_keyboard_release(self.kb, key);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
impl Drop for Keyboard {
|
|
69
|
+
fn drop(&mut self) {
|
|
70
|
+
unsafe {
|
|
71
|
+
inputtino_keyboard_destroy(self.kb);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
unsafe impl Send for Keyboard {}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
mod common;
|
|
2
|
+
pub use common::DeviceDefinition;
|
|
3
|
+
|
|
4
|
+
mod error;
|
|
5
|
+
pub use error::InputtinoError;
|
|
6
|
+
|
|
7
|
+
mod mouse;
|
|
8
|
+
pub use mouse::Mouse;
|
|
9
|
+
|
|
10
|
+
mod keyboard;
|
|
11
|
+
pub use keyboard::Keyboard;
|
|
12
|
+
|
|
13
|
+
mod joypad;
|
|
14
|
+
pub use joypad::Joypad;
|
|
15
|
+
|
|
16
|
+
mod joypad_ps5;
|
|
17
|
+
pub use joypad_ps5::PS5Joypad;
|
|
18
|
+
|
|
19
|
+
mod joypad_nintendo;
|
|
20
|
+
pub use joypad_nintendo::SwitchJoypad;
|
|
21
|
+
|
|
22
|
+
pub use joypad_xbox::XboxOneJoypad;
|
|
23
|
+
mod joypad_xbox;
|
|
24
|
+
|
|
25
|
+
pub use inputtino_sys::{
|
|
26
|
+
INPUTTINO_JOYPAD_BTN as JoypadButton, INPUTTINO_JOYPAD_MOTION_TYPE as JoypadMotionType,
|
|
27
|
+
INPUTTINO_JOYPAD_STICK_POSITION as JoypadStickPosition, INPUTTINO_MOUSE_BUTTON as MouseButton,
|
|
28
|
+
BATTERY_STATE as BatteryState,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
// Low level automatic c bindings.
|
|
32
|
+
pub use inputtino_sys as sys;
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
use std::path::PathBuf;
|
|
2
|
+
|
|
3
|
+
use crate::common::{get_nodes, make_device, DeviceDefinition};
|
|
4
|
+
use crate::sys::{
|
|
5
|
+
inputtino_mouse_create, inputtino_mouse_destroy, inputtino_mouse_get_nodes,
|
|
6
|
+
inputtino_mouse_move, inputtino_mouse_move_absolute, inputtino_mouse_press_button,
|
|
7
|
+
inputtino_mouse_release_button, inputtino_mouse_scroll_horizontal,
|
|
8
|
+
inputtino_mouse_scroll_vertical,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
use crate::{InputtinoError, MouseButton};
|
|
12
|
+
|
|
13
|
+
pub struct Mouse {
|
|
14
|
+
mouse: *mut crate::sys::InputtinoMouse,
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
impl Mouse {
|
|
18
|
+
/// Create a new emulated mouse device with the given device definition.
|
|
19
|
+
///
|
|
20
|
+
/// # Examples
|
|
21
|
+
///
|
|
22
|
+
/// ```
|
|
23
|
+
/// let definition = inputtino::DeviceDefinition::new(
|
|
24
|
+
/// "Inputtino Mouse",
|
|
25
|
+
/// 0x0,
|
|
26
|
+
/// 0x0,
|
|
27
|
+
/// 0x0,
|
|
28
|
+
/// "00:11:22:33:44",
|
|
29
|
+
/// "00:11:22:33:44",
|
|
30
|
+
/// );
|
|
31
|
+
/// let device = inputtino::Mouse::new(&definition);
|
|
32
|
+
/// ```
|
|
33
|
+
pub fn new(device: &DeviceDefinition) -> Result<Self, InputtinoError> {
|
|
34
|
+
make_device(inputtino_mouse_create, device).map(|mouse| Mouse { mouse })
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
pub fn get_nodes(&self) -> Result<Vec<PathBuf>, InputtinoError> {
|
|
38
|
+
get_nodes(inputtino_mouse_get_nodes, self.mouse)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/// Move the mouse relative to its current position.
|
|
42
|
+
///
|
|
43
|
+
/// # Examples
|
|
44
|
+
///
|
|
45
|
+
/// ```ignore
|
|
46
|
+
/// device.move_rel(10, -10);
|
|
47
|
+
/// ```
|
|
48
|
+
pub fn move_rel(&self, x: i32, y: i32) {
|
|
49
|
+
unsafe {
|
|
50
|
+
inputtino_mouse_move(self.mouse, x, y);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/// Move the mouse to absolute coordinates on the screen.
|
|
55
|
+
///
|
|
56
|
+
/// # Examples
|
|
57
|
+
///
|
|
58
|
+
/// ```ignore
|
|
59
|
+
/// device.move_abs(100, 100, 1920, 1080);
|
|
60
|
+
/// ```
|
|
61
|
+
pub fn move_abs(&self, x: i32, y: i32, screen_width: i32, screen_height: i32) {
|
|
62
|
+
unsafe {
|
|
63
|
+
inputtino_mouse_move_absolute(self.mouse, x, y, screen_width, screen_height);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/// Simulate a button press.
|
|
68
|
+
///
|
|
69
|
+
/// # Examples
|
|
70
|
+
///
|
|
71
|
+
/// ```ignore
|
|
72
|
+
/// device.press_button(inputtino::MouseButton::LEFT);
|
|
73
|
+
/// ```
|
|
74
|
+
pub fn press_button(&self, button: MouseButton) {
|
|
75
|
+
unsafe {
|
|
76
|
+
inputtino_mouse_press_button(self.mouse, button);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/// Simulate the release of a button.
|
|
81
|
+
///
|
|
82
|
+
/// # Examples
|
|
83
|
+
///
|
|
84
|
+
/// ```ignore
|
|
85
|
+
/// device.release_button(inputtino::MouseButton::LEFT);
|
|
86
|
+
/// ```
|
|
87
|
+
pub fn release_button(&self, button: MouseButton) {
|
|
88
|
+
unsafe {
|
|
89
|
+
inputtino_mouse_release_button(self.mouse, button);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/// Simulate scrolling vertically for an amount of ticks.
|
|
94
|
+
///
|
|
95
|
+
/// # Examples
|
|
96
|
+
///
|
|
97
|
+
/// ```ignore
|
|
98
|
+
/// device.scroll_vertical(10);
|
|
99
|
+
/// ```
|
|
100
|
+
pub fn scroll_vertical(&self, amount: i32) {
|
|
101
|
+
unsafe {
|
|
102
|
+
inputtino_mouse_scroll_vertical(self.mouse, amount);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/// Simulate scrolling horizontally for an amount of ticks.
|
|
107
|
+
///
|
|
108
|
+
/// # Examples
|
|
109
|
+
///
|
|
110
|
+
/// ```ignore
|
|
111
|
+
/// device.scroll_horizontal(-10);
|
|
112
|
+
/// ```
|
|
113
|
+
pub fn scroll_horizontal(&self, amount: i32) {
|
|
114
|
+
unsafe {
|
|
115
|
+
inputtino_mouse_scroll_horizontal(self.mouse, amount);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
impl Drop for Mouse {
|
|
121
|
+
fn drop(&mut self) {
|
|
122
|
+
unsafe {
|
|
123
|
+
inputtino_mouse_destroy(self.mouse);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
unsafe impl Send for Mouse {}
|
|
129
|
+
|
|
130
|
+
#[cfg(test)]
|
|
131
|
+
mod tests {
|
|
132
|
+
use crate::common::error_handler_fn;
|
|
133
|
+
use std::ffi::CString;
|
|
134
|
+
|
|
135
|
+
use super::*;
|
|
136
|
+
|
|
137
|
+
#[test]
|
|
138
|
+
fn test_inputtino_c_mouse() {
|
|
139
|
+
let device_name = CString::new("Rusty Mouse").unwrap();
|
|
140
|
+
let device_phys = CString::new("Rusty Mouse Phys").unwrap();
|
|
141
|
+
let device_uniq = CString::new("Rusty Mouse Uniq").unwrap();
|
|
142
|
+
let def = crate::sys::InputtinoDeviceDefinition {
|
|
143
|
+
name: device_name.as_ptr(),
|
|
144
|
+
vendor_id: 0,
|
|
145
|
+
product_id: 0,
|
|
146
|
+
version: 0,
|
|
147
|
+
device_phys: device_phys.as_ptr(),
|
|
148
|
+
device_uniq: device_uniq.as_ptr(),
|
|
149
|
+
};
|
|
150
|
+
// TODO: test this somehow
|
|
151
|
+
let error_str = std::ptr::null_mut();
|
|
152
|
+
let error_handler = crate::sys::InputtinoErrorHandler {
|
|
153
|
+
eh: Some(error_handler_fn),
|
|
154
|
+
user_data: error_str,
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
unsafe {
|
|
158
|
+
let mouse = inputtino_mouse_create(&def, &error_handler);
|
|
159
|
+
assert!(!mouse.is_null());
|
|
160
|
+
|
|
161
|
+
let mut nodes_count: core::ffi::c_int = 0;
|
|
162
|
+
let nodes = inputtino_mouse_get_nodes(mouse, &mut nodes_count);
|
|
163
|
+
assert_eq!(nodes_count, 2);
|
|
164
|
+
assert!(!nodes.is_null());
|
|
165
|
+
// Check that the nodes start with /dev/input/event
|
|
166
|
+
assert!(CString::from_raw(*nodes.offset(0))
|
|
167
|
+
.to_str()
|
|
168
|
+
.unwrap()
|
|
169
|
+
.starts_with("/dev/input/event"));
|
|
170
|
+
assert!(CString::from_raw(*nodes.offset(1))
|
|
171
|
+
.to_str()
|
|
172
|
+
.unwrap()
|
|
173
|
+
.starts_with("/dev/input/event"));
|
|
174
|
+
|
|
175
|
+
inputtino_mouse_destroy(mouse);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
use input::{Event, Libinput, LibinputInterface};
|
|
2
|
+
use rustix::fs::{open, Mode, OFlags};
|
|
3
|
+
use std::os::fd::OwnedFd;
|
|
4
|
+
use std::path::Path;
|
|
5
|
+
|
|
6
|
+
pub struct NixInterface;
|
|
7
|
+
|
|
8
|
+
impl LibinputInterface for NixInterface {
|
|
9
|
+
fn open_restricted(&mut self, path: &Path, flags: i32) -> Result<OwnedFd, i32> {
|
|
10
|
+
open(
|
|
11
|
+
path,
|
|
12
|
+
OFlags::from_bits_truncate(flags as u32),
|
|
13
|
+
Mode::empty(),
|
|
14
|
+
)
|
|
15
|
+
.map_err(|err| err.raw_os_error())
|
|
16
|
+
}
|
|
17
|
+
fn close_restricted(&mut self, fd: OwnedFd) {
|
|
18
|
+
let _ = fd;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
pub trait SyncEvent {
|
|
23
|
+
fn wait_next_event(&mut self) -> Option<Event>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
impl SyncEvent for Libinput {
|
|
27
|
+
fn wait_next_event(&mut self) -> Option<Event> {
|
|
28
|
+
for _ in 0..10 {
|
|
29
|
+
// loop maximum 10 times to avoid infinite loop
|
|
30
|
+
self.dispatch().unwrap();
|
|
31
|
+
if let Some(event) = self.next() {
|
|
32
|
+
return Some(event);
|
|
33
|
+
}
|
|
34
|
+
std::thread::sleep(std::time::Duration::from_millis(50));
|
|
35
|
+
}
|
|
36
|
+
None
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
use inputtino::{DeviceDefinition, JoypadButton, JoypadStickPosition, SwitchJoypad};
|
|
2
|
+
use serial_test::serial;
|
|
3
|
+
|
|
4
|
+
#[test]
|
|
5
|
+
#[serial]
|
|
6
|
+
fn test_switch_joypad() {
|
|
7
|
+
let device = DeviceDefinition::new(
|
|
8
|
+
"Rusty Switch controller",
|
|
9
|
+
// https://github.com/torvalds/linux/blob/276f98efb64a2c31c099465ace78d3054c662a0f/drivers/hid/hid-ids.h#L990
|
|
10
|
+
0x057e,
|
|
11
|
+
0x2009,
|
|
12
|
+
0x8111,
|
|
13
|
+
"00:11:22:33:44",
|
|
14
|
+
"00:11:22:33:44",
|
|
15
|
+
);
|
|
16
|
+
let mut joypad = SwitchJoypad::new(&device).unwrap();
|
|
17
|
+
|
|
18
|
+
let nodes = joypad.get_nodes().unwrap();
|
|
19
|
+
{
|
|
20
|
+
assert_eq!(nodes.len(), 2);
|
|
21
|
+
assert!(nodes[0]
|
|
22
|
+
.to_str()
|
|
23
|
+
.expect("valid utf-8")
|
|
24
|
+
.starts_with("/dev/input/event"));
|
|
25
|
+
assert!(nodes[1]
|
|
26
|
+
.to_str()
|
|
27
|
+
.expect("valid utf-8")
|
|
28
|
+
.starts_with("/dev/input/js"));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Sleep to let the system detect the anew device
|
|
32
|
+
std::thread::sleep(std::time::Duration::from_millis(500));
|
|
33
|
+
|
|
34
|
+
let sdl = sdl2::init().unwrap();
|
|
35
|
+
let joystick_subsystem = sdl.game_controller().unwrap();
|
|
36
|
+
|
|
37
|
+
assert_eq!(joystick_subsystem.num_joysticks().unwrap(), 1);
|
|
38
|
+
|
|
39
|
+
let mut sdl_js = joystick_subsystem.open(0).unwrap();
|
|
40
|
+
let mut event_pump = sdl.event_pump().unwrap();
|
|
41
|
+
|
|
42
|
+
for event in event_pump.poll_iter() {
|
|
43
|
+
match event {
|
|
44
|
+
sdl2::event::Event::JoyDeviceAdded { which, .. } => {
|
|
45
|
+
assert_eq!(which, 0);
|
|
46
|
+
}
|
|
47
|
+
sdl2::event::Event::ControllerDeviceAdded { which, .. } => {
|
|
48
|
+
assert_eq!(which, 0);
|
|
49
|
+
}
|
|
50
|
+
_ => panic!("Unexpected event : {:?}", event),
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
assert_eq!(sdl_js.name(), "Nintendo Switch Pro Controller");
|
|
55
|
+
assert!(sdl_js.has_rumble());
|
|
56
|
+
|
|
57
|
+
{
|
|
58
|
+
joypad.set_pressed(JoypadButton::A as i32);
|
|
59
|
+
for event in event_pump.wait_timeout_iter(50) {
|
|
60
|
+
match event {
|
|
61
|
+
sdl2::event::Event::ControllerButtonDown { button, .. } => {
|
|
62
|
+
assert_eq!(button, sdl2::controller::Button::A);
|
|
63
|
+
}
|
|
64
|
+
sdl2::event::Event::JoyButtonDown { button_idx, .. } => {
|
|
65
|
+
// Old joystick API uses the "xbox" layout for indexes
|
|
66
|
+
// A on a switch pad is on the same position as B on an xbox pad
|
|
67
|
+
assert_eq!(button_idx, sdl2::controller::Button::B as u8);
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
_ => panic!("Unexpected event : {:?}", event),
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
{
|
|
76
|
+
joypad.set_triggers(0, 0);
|
|
77
|
+
for event in event_pump.wait_timeout_iter(50) {
|
|
78
|
+
match event {
|
|
79
|
+
sdl2::event::Event::ControllerAxisMotion { axis, value, .. } => {
|
|
80
|
+
assert_eq!(axis, sdl2::controller::Axis::TriggerLeft);
|
|
81
|
+
assert_eq!(value, 0);
|
|
82
|
+
}
|
|
83
|
+
sdl2::event::Event::JoyAxisMotion {
|
|
84
|
+
axis_idx, value, ..
|
|
85
|
+
} => {
|
|
86
|
+
assert_eq!(axis_idx, sdl2::controller::Axis::TriggerLeft as u8);
|
|
87
|
+
assert_eq!(value, 0);
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
sdl2::event::Event::Unknown { .. } => {}
|
|
91
|
+
_ => panic!("Unexpected event : {:?}", event),
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
{
|
|
97
|
+
joypad.set_stick(JoypadStickPosition::LS, 0, 0);
|
|
98
|
+
for event in event_pump.wait_timeout_iter(50) {
|
|
99
|
+
match event {
|
|
100
|
+
sdl2::event::Event::ControllerAxisMotion { axis, value, .. } => {
|
|
101
|
+
assert_eq!(axis, sdl2::controller::Axis::LeftX);
|
|
102
|
+
assert_eq!(value, 0);
|
|
103
|
+
}
|
|
104
|
+
sdl2::event::Event::JoyAxisMotion {
|
|
105
|
+
axis_idx, value, ..
|
|
106
|
+
} => {
|
|
107
|
+
assert_eq!(axis_idx, sdl2::controller::Axis::LeftX as u8);
|
|
108
|
+
assert_eq!(value, 0);
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
_ => panic!("Unexpected event : {:?}", event),
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
{
|
|
117
|
+
joypad.set_stick(JoypadStickPosition::RS, 0, 0);
|
|
118
|
+
for event in event_pump.wait_timeout_iter(50) {
|
|
119
|
+
match event {
|
|
120
|
+
sdl2::event::Event::ControllerAxisMotion { axis, value, .. } => {
|
|
121
|
+
assert_eq!(axis, sdl2::controller::Axis::RightX);
|
|
122
|
+
assert_eq!(value, 0);
|
|
123
|
+
}
|
|
124
|
+
sdl2::event::Event::JoyAxisMotion {
|
|
125
|
+
axis_idx, value, ..
|
|
126
|
+
} => {
|
|
127
|
+
assert_eq!(axis_idx, sdl2::controller::Axis::RightX as u8);
|
|
128
|
+
assert_eq!(value, 0);
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
_ => panic!("Unexpected event : {:?}", event),
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
{
|
|
137
|
+
joypad.set_on_rumble(move |left, right| {
|
|
138
|
+
assert_eq!(left, 100);
|
|
139
|
+
assert_eq!(right, 200);
|
|
140
|
+
});
|
|
141
|
+
let res = sdl_js.set_rumble(100, 200, 150);
|
|
142
|
+
assert!(res.is_ok());
|
|
143
|
+
std::thread::sleep(std::time::Duration::from_millis(25));
|
|
144
|
+
joypad.set_on_rumble(move |left, right| {
|
|
145
|
+
assert_eq!(left, 0);
|
|
146
|
+
assert_eq!(right, 0);
|
|
147
|
+
});
|
|
148
|
+
std::thread::sleep(std::time::Duration::from_millis(125));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
use input::event::keyboard::KeyboardEventTrait;
|
|
2
|
+
use input::event::DeviceEvent;
|
|
3
|
+
use input::{Event, Libinput};
|
|
4
|
+
use inputtino::{DeviceDefinition, Keyboard};
|
|
5
|
+
mod common;
|
|
6
|
+
use crate::common::{NixInterface, SyncEvent};
|
|
7
|
+
|
|
8
|
+
#[test]
|
|
9
|
+
fn test_inputtino_keyboard() {
|
|
10
|
+
let device = DeviceDefinition::new(
|
|
11
|
+
"Rusty Keyboard",
|
|
12
|
+
0xAB,
|
|
13
|
+
0xCD,
|
|
14
|
+
0xEF,
|
|
15
|
+
"Rusty Keyboard Phys",
|
|
16
|
+
"Rusty Keyboard Uniq",
|
|
17
|
+
);
|
|
18
|
+
let keyboard = Keyboard::new(&device).unwrap();
|
|
19
|
+
let nodes = keyboard.get_nodes().unwrap();
|
|
20
|
+
{
|
|
21
|
+
assert_eq!(nodes.len(), 1);
|
|
22
|
+
|
|
23
|
+
// Check that the node start with /dev/input/event
|
|
24
|
+
assert!(nodes[0]
|
|
25
|
+
.to_str()
|
|
26
|
+
.expect("valid utf-8")
|
|
27
|
+
.starts_with("/dev/input/event"));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let mut input = Libinput::new_from_path(NixInterface);
|
|
31
|
+
let kb_dev = input
|
|
32
|
+
.path_add_device(nodes[0].to_str().expect("valid utf-8"))
|
|
33
|
+
.expect("to get the device");
|
|
34
|
+
|
|
35
|
+
{
|
|
36
|
+
assert_eq!(kb_dev.name(), "Rusty Keyboard");
|
|
37
|
+
assert_eq!(kb_dev.id_vendor(), 0xAB);
|
|
38
|
+
assert_eq!(kb_dev.id_product(), 0xCD);
|
|
39
|
+
for event in &mut input {
|
|
40
|
+
assert!(matches!(event, Event::Device(DeviceEvent::Added(_))));
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
{
|
|
45
|
+
// Test keyboard key press
|
|
46
|
+
keyboard.press_key(0x41); // KEY_A
|
|
47
|
+
|
|
48
|
+
let ev = input.wait_next_event();
|
|
49
|
+
assert!(matches!(ev, Some(Event::Keyboard(_))));
|
|
50
|
+
match ev {
|
|
51
|
+
Some(Event::Keyboard(ev)) => {
|
|
52
|
+
assert_eq!(ev.key(), 30); // KEY_A
|
|
53
|
+
assert_eq!(ev.key_state(), input::event::keyboard::KeyState::Pressed);
|
|
54
|
+
}
|
|
55
|
+
_ => unreachable!(),
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
{
|
|
60
|
+
// Test keyboard key release
|
|
61
|
+
keyboard.release_key(0x41);
|
|
62
|
+
|
|
63
|
+
let ev = input.wait_next_event().unwrap();
|
|
64
|
+
assert!(matches!(ev, Event::Keyboard(_)));
|
|
65
|
+
match ev {
|
|
66
|
+
Event::Keyboard(ev) => {
|
|
67
|
+
assert_eq!(ev.key(), 30); // KEY_A
|
|
68
|
+
assert_eq!(ev.key_state(), input::event::keyboard::KeyState::Released);
|
|
69
|
+
}
|
|
70
|
+
_ => unreachable!(),
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|