@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.
Files changed (142) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +44 -0
  3. package/README.md +266 -0
  4. package/bin/desklink-host.mjs +113 -0
  5. package/dist/bridge.d.ts +57 -0
  6. package/dist/bridge.d.ts.map +1 -0
  7. package/dist/bridge.js +208 -0
  8. package/dist/bridge.js.map +1 -0
  9. package/dist/engineProcess.d.ts +82 -0
  10. package/dist/engineProcess.d.ts.map +1 -0
  11. package/dist/engineProcess.js +243 -0
  12. package/dist/engineProcess.js.map +1 -0
  13. package/dist/index.d.ts +12 -0
  14. package/dist/index.d.ts.map +1 -0
  15. package/dist/index.js +12 -0
  16. package/dist/index.js.map +1 -0
  17. package/dist/protocol.d.ts +169 -0
  18. package/dist/protocol.d.ts.map +1 -0
  19. package/dist/protocol.js +18 -0
  20. package/dist/protocol.js.map +1 -0
  21. package/dist/resolveEngine.d.ts +34 -0
  22. package/dist/resolveEngine.d.ts.map +1 -0
  23. package/dist/resolveEngine.js +103 -0
  24. package/dist/resolveEngine.js.map +1 -0
  25. package/docs/BOUNDARY.md +145 -0
  26. package/docs/PROTOCOL.md +363 -0
  27. package/engine/Cargo.lock +3077 -0
  28. package/engine/Cargo.toml +37 -0
  29. package/engine/build.rs +107 -0
  30. package/engine/native/inputtino_shim.cpp +11 -0
  31. package/engine/native/vpx_shim.c +184 -0
  32. package/engine/native/wrapper.h +7 -0
  33. package/engine/src/capture.rs +510 -0
  34. package/engine/src/clipboard.rs +132 -0
  35. package/engine/src/convert.rs +299 -0
  36. package/engine/src/encoder.rs +204 -0
  37. package/engine/src/input.rs +355 -0
  38. package/engine/src/keymap.rs +338 -0
  39. package/engine/src/main.rs +614 -0
  40. package/engine/src/peer.rs +775 -0
  41. package/engine/src/portal.rs +115 -0
  42. package/engine/src/protocol.rs +331 -0
  43. package/engine/src/session.rs +2159 -0
  44. package/engine/src/x11.rs +244 -0
  45. package/engine/vendor/inputtino/.clang-format +166 -0
  46. package/engine/vendor/inputtino/.clang-tidy +30 -0
  47. package/engine/vendor/inputtino/.dockerignore +11 -0
  48. package/engine/vendor/inputtino/.github/workflows/mirror-repo.yml +14 -0
  49. package/engine/vendor/inputtino/.github/workflows/python-lint-format-test-typecheck.yml +124 -0
  50. package/engine/vendor/inputtino/.github/workflows/python-test-install.yaml +49 -0
  51. package/engine/vendor/inputtino/.github/workflows/rust.yml +40 -0
  52. package/engine/vendor/inputtino/CMakeLists.txt +187 -0
  53. package/engine/vendor/inputtino/LICENSE +21 -0
  54. package/engine/vendor/inputtino/README.md +110 -0
  55. package/engine/vendor/inputtino/bindings/python/.devcontainer/Dockerfile +23 -0
  56. package/engine/vendor/inputtino/bindings/python/.devcontainer/devcontainer.json +28 -0
  57. package/engine/vendor/inputtino/bindings/python/.python-version +1 -0
  58. package/engine/vendor/inputtino/bindings/python/CMakeLists.txt +23 -0
  59. package/engine/vendor/inputtino/bindings/python/CPPLINT.cfg +2 -0
  60. package/engine/vendor/inputtino/bindings/python/Makefile +49 -0
  61. package/engine/vendor/inputtino/bindings/python/README.md +215 -0
  62. package/engine/vendor/inputtino/bindings/python/pyproject.toml +178 -0
  63. package/engine/vendor/inputtino/bindings/python/src/inputtino/__init__.py +43 -0
  64. package/engine/vendor/inputtino/bindings/python/src/inputtino/_core.pyi +533 -0
  65. package/engine/vendor/inputtino/bindings/python/src/inputtino/base.py +63 -0
  66. package/engine/vendor/inputtino/bindings/python/src/inputtino/joypad.py +248 -0
  67. package/engine/vendor/inputtino/bindings/python/src/inputtino/keyboard.py +256 -0
  68. package/engine/vendor/inputtino/bindings/python/src/inputtino/mouse.py +106 -0
  69. package/engine/vendor/inputtino/bindings/python/src/inputtino/pentablet.py +73 -0
  70. package/engine/vendor/inputtino/bindings/python/src/inputtino/py.typed +0 -0
  71. package/engine/vendor/inputtino/bindings/python/src/inputtino/touchscreen.py +61 -0
  72. package/engine/vendor/inputtino/bindings/python/src/inputtino/trackpad.py +74 -0
  73. package/engine/vendor/inputtino/bindings/python/src/main.cpp +217 -0
  74. package/engine/vendor/inputtino/bindings/python/tests/__init__.py +0 -0
  75. package/engine/vendor/inputtino/bindings/python/tests/helpers.py +3 -0
  76. package/engine/vendor/inputtino/bindings/python/tests/test_base.py +60 -0
  77. package/engine/vendor/inputtino/bindings/python/tests/test_inputtino.py +5 -0
  78. package/engine/vendor/inputtino/bindings/python/tests/test_joypad.py +332 -0
  79. package/engine/vendor/inputtino/bindings/python/tests/test_keyboard.py +164 -0
  80. package/engine/vendor/inputtino/bindings/python/tests/test_mouse.py +185 -0
  81. package/engine/vendor/inputtino/bindings/python/tests/test_pentablet.py +198 -0
  82. package/engine/vendor/inputtino/bindings/python/tests/test_touchscreen.py +144 -0
  83. package/engine/vendor/inputtino/bindings/python/tests/test_trackpad.py +146 -0
  84. package/engine/vendor/inputtino/bindings/python/uv.lock +390 -0
  85. package/engine/vendor/inputtino/bindings/rust/Cargo.toml +6 -0
  86. package/engine/vendor/inputtino/bindings/rust/inputtino/.dockerignore +1 -0
  87. package/engine/vendor/inputtino/bindings/rust/inputtino/Cargo.toml +18 -0
  88. package/engine/vendor/inputtino/bindings/rust/inputtino/examples/keyboard.rs +33 -0
  89. package/engine/vendor/inputtino/bindings/rust/inputtino/examples/mouse.rs +17 -0
  90. package/engine/vendor/inputtino/bindings/rust/inputtino/src/common.rs +116 -0
  91. package/engine/vendor/inputtino/bindings/rust/inputtino/src/error.rs +17 -0
  92. package/engine/vendor/inputtino/bindings/rust/inputtino/src/joypad.rs +74 -0
  93. package/engine/vendor/inputtino/bindings/rust/inputtino/src/joypad_nintendo.rs +135 -0
  94. package/engine/vendor/inputtino/bindings/rust/inputtino/src/joypad_ps5.rs +280 -0
  95. package/engine/vendor/inputtino/bindings/rust/inputtino/src/joypad_xbox.rs +134 -0
  96. package/engine/vendor/inputtino/bindings/rust/inputtino/src/keyboard.rs +76 -0
  97. package/engine/vendor/inputtino/bindings/rust/inputtino/src/lib.rs +32 -0
  98. package/engine/vendor/inputtino/bindings/rust/inputtino/src/mouse.rs +178 -0
  99. package/engine/vendor/inputtino/bindings/rust/inputtino/tests/common.rs +38 -0
  100. package/engine/vendor/inputtino/bindings/rust/inputtino/tests/joypads.rs +150 -0
  101. package/engine/vendor/inputtino/bindings/rust/inputtino/tests/keyboard.rs +73 -0
  102. package/engine/vendor/inputtino/bindings/rust/inputtino/tests/mouse.rs +139 -0
  103. package/engine/vendor/inputtino/bindings/rust/inputtino-sys/.dockerignore +1 -0
  104. package/engine/vendor/inputtino/bindings/rust/inputtino-sys/Cargo.toml +12 -0
  105. package/engine/vendor/inputtino/bindings/rust/inputtino-sys/build.rs +48 -0
  106. package/engine/vendor/inputtino/bindings/rust/inputtino-sys/src/lib.rs +5 -0
  107. package/engine/vendor/inputtino/bindings/rust/inputtino-sys/wrapper.h +1 -0
  108. package/engine/vendor/inputtino/cmake/utils.cmake +9 -0
  109. package/engine/vendor/inputtino/docker/Dockerfile +70 -0
  110. package/engine/vendor/inputtino/include/inputtino/input.h +324 -0
  111. package/engine/vendor/inputtino/include/inputtino/input.hpp +466 -0
  112. package/engine/vendor/inputtino/include/inputtino/result.hpp +37 -0
  113. package/engine/vendor/inputtino/share/pkgconfig/libinputtino.pc.in +17 -0
  114. package/engine/vendor/inputtino/src/c-bindings/helpers.hpp +19 -0
  115. package/engine/vendor/inputtino/src/c-bindings/joypad_ps5.cpp +115 -0
  116. package/engine/vendor/inputtino/src/c-bindings/joypad_switch.cpp +63 -0
  117. package/engine/vendor/inputtino/src/c-bindings/joypad_xone.cpp +62 -0
  118. package/engine/vendor/inputtino/src/c-bindings/keyboard.cpp +42 -0
  119. package/engine/vendor/inputtino/src/c-bindings/mouse.cpp +67 -0
  120. package/engine/vendor/inputtino/src/c-bindings/pen_tablet.cpp +50 -0
  121. package/engine/vendor/inputtino/src/c-bindings/touchscreen.cpp +43 -0
  122. package/engine/vendor/inputtino/src/c-bindings/trackpad.cpp +49 -0
  123. package/engine/vendor/inputtino/src/uhid/README.adoc +63 -0
  124. package/engine/vendor/inputtino/src/uhid/include/crc32.hpp +38 -0
  125. package/engine/vendor/inputtino/src/uhid/include/uhid/protected_types.hpp +36 -0
  126. package/engine/vendor/inputtino/src/uhid/include/uhid/ps5.hpp +550 -0
  127. package/engine/vendor/inputtino/src/uhid/include/uhid/uhid.hpp +168 -0
  128. package/engine/vendor/inputtino/src/uhid/joypad_ps5.cpp +580 -0
  129. package/engine/vendor/inputtino/src/uinput/include/inputtino/keyboard.hpp +84 -0
  130. package/engine/vendor/inputtino/src/uinput/include/inputtino/protected_ps5_types.hpp +7 -0
  131. package/engine/vendor/inputtino/src/uinput/include/inputtino/protected_types.hpp +110 -0
  132. package/engine/vendor/inputtino/src/uinput/joypad_nintendo.cpp +190 -0
  133. package/engine/vendor/inputtino/src/uinput/joypad_ps.cpp +203 -0
  134. package/engine/vendor/inputtino/src/uinput/joypad_utils.hpp +246 -0
  135. package/engine/vendor/inputtino/src/uinput/joypad_xbox.cpp +190 -0
  136. package/engine/vendor/inputtino/src/uinput/keyboard.cpp +120 -0
  137. package/engine/vendor/inputtino/src/uinput/mouse.cpp +199 -0
  138. package/engine/vendor/inputtino/src/uinput/pentablet.cpp +162 -0
  139. package/engine/vendor/inputtino/src/uinput/touchscreen.cpp +140 -0
  140. package/engine/vendor/inputtino/src/uinput/trackpad.cpp +192 -0
  141. package/examples/reference-client.html +428 -0
  142. 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
+ }