@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,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)
|
|
File without changes
|