@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,248 @@
1
+ """Provides joypad device implementations."""
2
+
3
+ from collections.abc import Callable
4
+ from enum import IntFlag
5
+
6
+ from . import _core
7
+ from ._core import (
8
+ ControllerButton as CoreButton,
9
+ PS5BatteryState,
10
+ PS5MotionType,
11
+ StickPosition,
12
+ )
13
+ from .base import DeviceDefinition, VirtualDevice
14
+
15
+
16
+ class ControllerButton(IntFlag):
17
+ """Button flags for controller input."""
18
+
19
+ DPAD_UP = CoreButton.DPAD_UP.value
20
+ DPAD_DOWN = CoreButton.DPAD_DOWN.value
21
+ DPAD_LEFT = CoreButton.DPAD_LEFT.value
22
+ DPAD_RIGHT = CoreButton.DPAD_RIGHT.value
23
+
24
+ START = CoreButton.START.value
25
+ BACK = CoreButton.BACK.value
26
+ HOME = CoreButton.HOME.value
27
+
28
+ LEFT_STICK = CoreButton.LEFT_STICK.value
29
+ RIGHT_STICK = CoreButton.RIGHT_STICK.value
30
+ LEFT_BUTTON = CoreButton.LEFT_BUTTON.value
31
+ RIGHT_BUTTON = CoreButton.RIGHT_BUTTON.value
32
+
33
+ SPECIAL = CoreButton.SPECIAL_FLAG.value
34
+ PADDLE1 = CoreButton.PADDLE1_FLAG.value
35
+ PADDLE2 = CoreButton.PADDLE2_FLAG.value
36
+ PADDLE3 = CoreButton.PADDLE3_FLAG.value
37
+ PADDLE4 = CoreButton.PADDLE4_FLAG.value
38
+ TOUCHPAD = CoreButton.TOUCHPAD_FLAG.value
39
+ MISC = CoreButton.MISC_FLAG.value
40
+
41
+ A = CoreButton.A.value
42
+ B = CoreButton.B.value
43
+ X = CoreButton.X.value
44
+ Y = CoreButton.Y.value
45
+
46
+
47
+ class Joypad(VirtualDevice):
48
+ """Base class for all joypad implementations."""
49
+
50
+ def __init__(self, device_def: DeviceDefinition, joypad: _core.Joypad) -> None:
51
+ """Initialize joypad.
52
+
53
+ Args:
54
+ device_def: Device definition for the joypad
55
+ joypad: Core joypad instance
56
+ """
57
+ super().__init__(joypad)
58
+ self._device_def = device_def
59
+ self._joypad = joypad
60
+
61
+ def set_pressed_buttons(self, buttons: ControllerButton) -> None:
62
+ """Set currently pressed buttons.
63
+
64
+ Args:
65
+ buttons: Button flags indicating which buttons are pressed
66
+ """
67
+ self._joypad.set_pressed_buttons(int(buttons))
68
+
69
+ def set_triggers(self, left: int, right: int) -> None:
70
+ """Set trigger values.
71
+
72
+ Args:
73
+ left: Left trigger value (0-65535)
74
+ right: Right trigger value (0-65535)
75
+ """
76
+ self._joypad.set_triggers(left, right)
77
+
78
+ def set_stick(self, stick: StickPosition, x: int, y: int) -> None:
79
+ """Set stick position.
80
+
81
+ Args:
82
+ stick: Which stick to move (LS or RS)
83
+ x: X position (-32768 to 32767)
84
+ y: Y position (-32768 to 32767)
85
+ """
86
+ self._joypad.set_stick(stick, x, y)
87
+
88
+
89
+ DEFAULT_XBOX_ONE_JOYPAD_DEF = DeviceDefinition(
90
+ name="Wolf X-Box One (virtual) pad",
91
+ vendor_id=0x045E,
92
+ product_id=0x02EA,
93
+ version=0x0408,
94
+ )
95
+
96
+
97
+ class XBoxOneJoypad(Joypad):
98
+ """Xbox One controller implementation."""
99
+
100
+ def __init__(
101
+ self, device_def: DeviceDefinition = DEFAULT_XBOX_ONE_JOYPAD_DEF
102
+ ) -> None:
103
+ """Initialize Xbox One controller.
104
+
105
+ Args:
106
+ device_def: Optional device definition.
107
+ """
108
+ joypad = _core.XboxOneJoypad.create(device_def.to_core())
109
+ super().__init__(device_def, joypad)
110
+ self._xbox_joypad = joypad
111
+
112
+ def set_on_rumble(self, callback: Callable[[int, int], None]) -> None:
113
+ """Set rumble feedback callback.
114
+
115
+ Args:
116
+ callback: Function called when rumble event occurs.
117
+ Takes (low_freq, high_freq) as arguments
118
+ """
119
+ self._xbox_joypad.set_on_rumble(callback)
120
+
121
+
122
+ DEFAULT_SWITCH_JOYPAD_DEF = DeviceDefinition(
123
+ name="Wolf Nintendo (virtual) pad",
124
+ vendor_id=0x057E,
125
+ product_id=0x2009,
126
+ version=0x8111,
127
+ )
128
+
129
+
130
+ class SwitchJoypad(Joypad):
131
+ """Nintendo Switch controller implementation."""
132
+
133
+ def __init__(
134
+ self, device_def: DeviceDefinition = DEFAULT_SWITCH_JOYPAD_DEF
135
+ ) -> None:
136
+ """Initialize Switch controller.
137
+
138
+ Args:
139
+ device_def: Optional device definition.
140
+ """
141
+ joypad = _core.SwitchJoypad.create(device_def.to_core())
142
+ super().__init__(device_def, joypad)
143
+ self._switch_joypad = joypad
144
+
145
+ def set_on_rumble(self, callback: Callable[[int, int], None]) -> None:
146
+ """Set rumble feedback callback.
147
+
148
+ Args:
149
+ callback: Function called when rumble event occurs.
150
+ Takes (low_freq, high_freq) as arguments
151
+ """
152
+ self._switch_joypad.set_on_rumble(callback)
153
+
154
+
155
+ DEFAULT_PS5_JOYPAD_DEF = DeviceDefinition(
156
+ name="Wolf DualSense (virtual) pad",
157
+ vendor_id=0x054C,
158
+ product_id=0x0CE6,
159
+ version=0x8111,
160
+ )
161
+
162
+
163
+ class PS5Joypad(Joypad):
164
+ """PlayStation 5 DualSense controller implementation."""
165
+
166
+ def __init__(self, device_def: DeviceDefinition = DEFAULT_PS5_JOYPAD_DEF) -> None:
167
+ """Initialize PS5 controller.
168
+
169
+ Args:
170
+ device_def: Optional device definition.
171
+ """
172
+ joypad = _core.PS5Joypad.create(device_def.to_core())
173
+ super().__init__(device_def, joypad)
174
+ self._ps5_joypad = joypad
175
+
176
+ @property
177
+ def mac_address(self) -> str:
178
+ """Get MAC address of the controller.
179
+
180
+ Returns:
181
+ MAC address string
182
+ """
183
+ return self._ps5_joypad.get_mac_address()
184
+
185
+ @property
186
+ def sys_nodes(self) -> list[str]:
187
+ """Get system device nodes.
188
+
189
+ Returns:
190
+ List of system node paths
191
+ """
192
+ return self._ps5_joypad.get_sys_nodes()
193
+
194
+ def place_finger(self, finger_nr: int, x: int, y: int) -> None:
195
+ """Place finger on touchpad.
196
+
197
+ Args:
198
+ finger_nr: Finger number (multi-touch index)
199
+ x: X position (0-1920)
200
+ y: Y position (0-1080)
201
+ """
202
+ self._ps5_joypad.place_finger(finger_nr, x, y)
203
+
204
+ def release_finger(self, finger_nr: int) -> None:
205
+ """Release finger from touchpad.
206
+
207
+ Args:
208
+ finger_nr: Finger number to release
209
+ """
210
+ self._ps5_joypad.release_finger(finger_nr)
211
+
212
+ def set_motion(self, type_: PS5MotionType, x: float, y: float, z: float) -> None:
213
+ """Set motion sensor values.
214
+
215
+ Args:
216
+ type_: Sensor type (acceleration or gyroscope)
217
+ x: X-axis value (m/s² for accel, deg/s for gyro)
218
+ y: Y-axis value
219
+ z: Z-axis value
220
+ """
221
+ self._ps5_joypad.set_motion(type_, x, y, z)
222
+
223
+ def set_battery(self, state: PS5BatteryState, percentage: int) -> None:
224
+ """Set battery state.
225
+
226
+ Args:
227
+ state: Battery state
228
+ percentage: Battery level percentage (0-100)
229
+ """
230
+ self._ps5_joypad.set_battery(state, percentage)
231
+
232
+ def set_on_rumble(self, callback: Callable[[int, int], None]) -> None:
233
+ """Set rumble feedback callback.
234
+
235
+ Args:
236
+ callback: Function called when rumble event occurs.
237
+ Takes (low_freq, high_freq) as arguments
238
+ """
239
+ self._ps5_joypad.set_on_rumble(callback)
240
+
241
+ def set_on_led(self, callback: Callable[[int, int, int], None]) -> None:
242
+ """Set LED color callback.
243
+
244
+ Args:
245
+ callback: Function called when LED color changes.
246
+ Takes (r, g, b) as arguments
247
+ """
248
+ self._ps5_joypad.set_on_led(callback)
@@ -0,0 +1,256 @@
1
+ """Keyboard input device implementation."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import time
6
+ from enum import IntEnum
7
+
8
+ from typing_extensions import Self
9
+
10
+ from . import _core
11
+ from .base import DeviceDefinition, VirtualDevice
12
+
13
+ # Default device definition for keyboard
14
+ DEFAULT_KEYBOARD = DeviceDefinition(
15
+ name="Wolf (virtual) keyboard",
16
+ vendor_id=0xAB00,
17
+ product_id=0xAB05,
18
+ version=0xAB00,
19
+ )
20
+
21
+
22
+ class Keyboard(VirtualDevice):
23
+ """Virtual keyboard input device.
24
+
25
+ This class provides functionality to simulate keyboard input.
26
+ The device appears as a real keyboard input device to the system.
27
+ Key codes used are Win32 Virtual Key (VK) codes.
28
+
29
+ Example:
30
+ >>> from inputtino.keyboard import Keyboard, KeyCode
31
+ >>> kb = Keyboard()
32
+ >>> kb.press(KeyCode.CTRL)
33
+ >>> kb.press(KeyCode.C)
34
+ >>> kb.release(KeyCode.C)
35
+ >>> kb.release(KeyCode.CTRL)
36
+ """
37
+
38
+ def __init__(
39
+ self,
40
+ device_def: DeviceDefinition = DEFAULT_KEYBOARD,
41
+ millis_repress_key: int = 50,
42
+ ) -> None:
43
+ """Initialize the keyboard device with optional custom device
44
+ definition.
45
+
46
+ Args:
47
+ device_def: Optional device definition for customizing the virtual device properties
48
+ millis_repress_key: Time in milliseconds between key press repeats (default: 50)
49
+
50
+ Raises:
51
+ RuntimeError: If device creation fails
52
+ """
53
+ self._keyboard = _core.Keyboard.create(device_def.to_core(), millis_repress_key)
54
+ super().__init__(self._keyboard)
55
+
56
+ def press(self, key_code: int) -> None:
57
+ """Press a keyboard key.
58
+
59
+ Args:
60
+ key_code: Win32 Virtual Key code of the key to press
61
+ """
62
+ self._keyboard.press(key_code)
63
+
64
+ def release(self, key_code: int) -> None:
65
+ """Release a keyboard key.
66
+
67
+ Args:
68
+ key_code: Win32 Virtual Key code of the key to release
69
+ """
70
+ self._keyboard.release(key_code)
71
+
72
+ def type(self, key_code: int, duration: float = 0.1) -> None:
73
+ """Press and release a key with specified duration.
74
+
75
+ Args:
76
+ key_code: Win32 Virtual Key code of the key
77
+ duration: Time in seconds to hold the key (default: 0.1)
78
+ """
79
+ try:
80
+ self.press(key_code)
81
+ if duration > 0:
82
+ time.sleep(duration)
83
+ finally:
84
+ self.release(key_code)
85
+
86
+
87
+ class KeyCode(IntEnum):
88
+ """KeyCode mapping for virtual key codes.
89
+
90
+ This class provides a mapping between human-readable key names and
91
+ their corresponding virtual key codes used by the input system.
92
+
93
+ Key codes are referred from
94
+ <https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes>
95
+ """
96
+
97
+ # Standard Keys
98
+ BACKSPACE = 0x08
99
+ TAB = 0x09
100
+ CLEAR = 0x0C
101
+ ENTER = 0x0D
102
+ SHIFT = 0x10
103
+ CTRL = 0x11
104
+ ALT = 0x12
105
+ PAUSE = 0x13
106
+ CAPS_LOCK = 0x14
107
+ ESC = 0x1B
108
+ SPACE = 0x20
109
+ PAGE_UP = 0x21
110
+ PAGE_DOWN = 0x22
111
+ END = 0x23
112
+ HOME = 0x24
113
+ LEFT = 0x25
114
+ UP = 0x26
115
+ RIGHT = 0x27
116
+ DOWN = 0x28
117
+ PRINTSCREEN = 0x2C
118
+ INSERT = 0x2D
119
+ DELETE = 0x2E
120
+
121
+ # Numbers
122
+ KEY_0 = 0x30
123
+ KEY_1 = 0x31
124
+ KEY_2 = 0x32
125
+ KEY_3 = 0x33
126
+ KEY_4 = 0x34
127
+ KEY_5 = 0x35
128
+ KEY_6 = 0x36
129
+ KEY_7 = 0x37
130
+ KEY_8 = 0x38
131
+ KEY_9 = 0x39
132
+
133
+ # Letters
134
+ A = 0x41
135
+ B = 0x42
136
+ C = 0x43
137
+ D = 0x44
138
+ E = 0x45
139
+ F = 0x46
140
+ G = 0x47
141
+ H = 0x48
142
+ I = 0x49
143
+ J = 0x4A
144
+ K = 0x4B
145
+ L = 0x4C
146
+ M = 0x4D
147
+ N = 0x4E
148
+ O = 0x4F
149
+ P = 0x50
150
+ Q = 0x51
151
+ R = 0x52
152
+ S = 0x53
153
+ T = 0x54
154
+ U = 0x55
155
+ V = 0x56
156
+ W = 0x57
157
+ X = 0x58
158
+ Y = 0x59
159
+ Z = 0x5A
160
+
161
+ # Windows Keys
162
+ LEFT_WIN = 0x5B
163
+ RIGHT_WIN = 0x5C
164
+ APP = 0x5D
165
+
166
+ # Numpad
167
+ NUMPAD_0 = 0x60
168
+ NUMPAD_1 = 0x61
169
+ NUMPAD_2 = 0x62
170
+ NUMPAD_3 = 0x63
171
+ NUMPAD_4 = 0x64
172
+ NUMPAD_5 = 0x65
173
+ NUMPAD_6 = 0x66
174
+ NUMPAD_7 = 0x67
175
+ NUMPAD_8 = 0x68
176
+ NUMPAD_9 = 0x69
177
+ MULTIPLY = 0x6A
178
+ ADD = 0x6B
179
+ SUBTRACT = 0x6D
180
+ DECIMAL = 0x6E
181
+ DIVIDE = 0x6F
182
+
183
+ # Function Keys
184
+ F1 = 0x70
185
+ F2 = 0x71
186
+ F3 = 0x72
187
+ F4 = 0x73
188
+ F5 = 0x74
189
+ F6 = 0x75
190
+ F7 = 0x76
191
+ F8 = 0x77
192
+ F9 = 0x78
193
+ F10 = 0x79
194
+ F11 = 0x7A
195
+ F12 = 0x7B
196
+ F13 = 0x7C
197
+ F14 = 0x7D
198
+ F15 = 0x7E
199
+ F16 = 0x7F
200
+ F17 = 0x80
201
+ F18 = 0x81
202
+ F19 = 0x82
203
+ F20 = 0x83
204
+ F21 = 0x84
205
+ F22 = 0x85
206
+ F23 = 0x86
207
+ F24 = 0x87
208
+
209
+ # Lock Keys
210
+ NUM_LOCK = 0x90
211
+ SCROLL_LOCK = 0x91
212
+
213
+ # Left/Right Keys
214
+ LEFT_SHIFT = 0xA0
215
+ RIGHT_SHIFT = 0xA1
216
+ LEFT_CONTROL = 0xA2
217
+ RIGHT_CONTROL = 0xA3
218
+ LEFT_ALT = 0xA4
219
+ RIGHT_ALT = 0xA5
220
+
221
+ # Media Keys
222
+ VOLUME_MUTE = 0xAD
223
+ VOLUME_DOWN = 0xAE
224
+ VOLUME_UP = 0xAF
225
+ MEDIA_NEXT = 0xB0
226
+ MEDIA_PREV = 0xB1
227
+ MEDIA_STOP = 0xB2
228
+ MEDIA_PLAY_PAUSE = 0xB3
229
+
230
+ # OEM Keys
231
+ SEMICOLON = 0xBA # ;:
232
+ PLUS = 0xBB # =+
233
+ COMMA = 0xBC # ,<
234
+ MINUS = 0xBD # -_
235
+ PERIOD = 0xBE # .>
236
+ SLASH = 0xBF # /?
237
+ TILDE = 0xC0 # `~
238
+ OPEN_BRACKET = 0xDB # [{
239
+ BACKSLASH = 0xDC # \|
240
+ CLOSE_BRACKET = 0xDD # ]}
241
+ QUOTE = 0xDE # '"
242
+
243
+ @classmethod
244
+ def from_str(cls, string: str) -> Self:
245
+ """Retrieves key code from string.
246
+
247
+ Args:
248
+ string: Key name.
249
+
250
+ Returns:
251
+ KeyCode member.
252
+
253
+ Raises:
254
+ KeyError: If provided name is not in KeyCode enum members.
255
+ """
256
+ return cls[string.upper()]
@@ -0,0 +1,106 @@
1
+ """Mouse input device implementation."""
2
+
3
+ import time
4
+
5
+ from . import _core
6
+ from ._core import MouseButton
7
+ from .base import DeviceDefinition, VirtualDevice
8
+
9
+ # Default device definition for mouse
10
+ DEFAULT_MOUSE = DeviceDefinition(
11
+ name="Wolf mouse virtual device",
12
+ vendor_id=0xAB00,
13
+ product_id=0xAB01,
14
+ version=0xAB00,
15
+ )
16
+
17
+
18
+ class Mouse(VirtualDevice):
19
+ """Virtual mouse input device.
20
+
21
+ This class provides functionality to simulate mouse movements,
22
+ clicks, and scrolling. The device appears as a real mouse input
23
+ device to the system.
24
+ """
25
+
26
+ def __init__(self, device_def: DeviceDefinition = DEFAULT_MOUSE) -> None:
27
+ """Initialize the mouse device with optional custom device definition.
28
+
29
+ Args:
30
+ device_def: Optional device definition for customizing the virtual device properties
31
+
32
+ Raises:
33
+ RuntimeError: If device creation fails
34
+ """
35
+ self._mouse = _core.Mouse.create(device_def.to_core())
36
+ super().__init__(self._mouse)
37
+
38
+ def move(self, delta_x: int, delta_y: int) -> None:
39
+ """Move the mouse cursor relative to its current position.
40
+
41
+ Args:
42
+ delta_x: Horizontal movement (positive is right, negative is left)
43
+ delta_y: Vertical movement (positive is down, negative is up)
44
+ """
45
+ self._mouse.move(delta_x, delta_y)
46
+
47
+ def move_abs(self, x: int, y: int, screen_width: int, screen_height: int) -> None:
48
+ """Move the mouse cursor to an absolute screen position.
49
+
50
+ Args:
51
+ x: Target X coordinate
52
+ y: Target Y coordinate
53
+ screen_width: Width of the screen in pixels
54
+ screen_height: Height of the screen in pixels
55
+ """
56
+ self._mouse.move_abs(x, y, screen_width, screen_height)
57
+
58
+ def press(self, button: MouseButton) -> None:
59
+ """Press a mouse button.
60
+
61
+ Args:
62
+ button: The button to press
63
+ """
64
+ self._mouse.press(button)
65
+
66
+ def release(self, button: MouseButton) -> None:
67
+ """Release a mouse button.
68
+
69
+ Args:
70
+ button: The button to release
71
+ """
72
+ self._mouse.release(button)
73
+
74
+ def scroll_vertical(self, distance: int) -> None:
75
+ """Scroll vertically.
76
+
77
+ Args:
78
+ distance: Scroll distance in high resolution units (±120 per notch).
79
+ Positive values scroll down, negative values scroll up.
80
+ """
81
+ self._mouse.vertical_scroll(distance)
82
+
83
+ def scroll_horizontal(self, distance: int) -> None:
84
+ """Scroll horizontally.
85
+
86
+ Args:
87
+ distance: Scroll distance in high resolution units (±120 per notch).
88
+ Positive values scroll right, negative values scroll left.
89
+ """
90
+ self._mouse.horizontal_scroll(distance)
91
+
92
+ def click(
93
+ self, button: MouseButton = MouseButton.LEFT, duration: float = 0.0
94
+ ) -> None:
95
+ """Perform a mouse click by pressing and releasing a button.
96
+
97
+ Args:
98
+ button: The button to click
99
+ duration: How long to hold the button down in seconds
100
+ """
101
+ try:
102
+ self.press(button)
103
+ if duration > 0:
104
+ time.sleep(duration)
105
+ finally:
106
+ self.release(button)
@@ -0,0 +1,73 @@
1
+ """Pen tablet input device implementation."""
2
+
3
+ from . import _core
4
+ from ._core import PenButtonType, PenToolType
5
+ from .base import DeviceDefinition, VirtualDevice
6
+
7
+ # Default device definition for pen tablet
8
+ DEFAULT_PEN_TABLET = DeviceDefinition(
9
+ name="Wolf (virtual) pen tablet",
10
+ vendor_id=0xAB00,
11
+ product_id=0xAB04,
12
+ version=0xAB00,
13
+ )
14
+
15
+
16
+ class PenTablet(VirtualDevice):
17
+ """Virtual pen tablet input device.
18
+
19
+ This class provides functionality to simulate pen tablet input with
20
+ various tools and buttons. The device appears as a real pen tablet
21
+ input device to the system.
22
+
23
+ implements a pen tablet as defined in libinput
24
+ https://wayland.freedesktop.org/libinput/doc/latest/tablet-support.html
25
+ """
26
+
27
+ def __init__(self, device_def: DeviceDefinition = DEFAULT_PEN_TABLET) -> None:
28
+ """Initialize the pentablet device with optional custom device
29
+ definition.
30
+
31
+ Args:
32
+ device_def: Optional device definition for customizing the virtual device properties
33
+
34
+ Raises:
35
+ RuntimeError: If device creation fails
36
+ """
37
+ self._tablet = _core.PenTablet.create(device_def.to_core())
38
+ super().__init__(self._tablet)
39
+
40
+ def place_tool(
41
+ self,
42
+ tool_type: PenToolType,
43
+ x: float,
44
+ y: float,
45
+ pressure: float,
46
+ distance: float,
47
+ tilt_x: float,
48
+ tilt_y: float,
49
+ ) -> None:
50
+ """Place a tool on the tablet surface.
51
+
52
+ Args:
53
+ tool_type: Type of tool being used
54
+ x: X coordinate in range [0.0, 1.0]
55
+ y: Y coordinate in range [0.0, 1.0]
56
+ pressure: Tool pressure in range [0.0, 1.0]
57
+ distance: Tool distance from surface in range [0.0, 1.0]
58
+ tilt_x: Tool tilt on X axis in range [-90.0, 90.0] degrees
59
+ tilt_y: Tool tilt on Y axis in range [-90.0, 90.0] degrees
60
+
61
+ Refer to the libinput docs to better understand what each param means:
62
+ https://wayland.freedesktop.org/libinput/doc/latest/tablet-support.html#special-axes-on-tablet-tools
63
+ """
64
+ self._tablet.place_tool(tool_type, x, y, pressure, distance, tilt_x, tilt_y)
65
+
66
+ def set_button(self, button: PenButtonType, pressed: bool) -> None:
67
+ """Set the state of a pen button.
68
+
69
+ Args:
70
+ button: The button to modify
71
+ pressed: True if button is pressed, False if released
72
+ """
73
+ self._tablet.set_btn(button, pressed)