@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,198 @@
|
|
|
1
|
+
"""Tests for pentablet.py."""
|
|
2
|
+
|
|
3
|
+
import math
|
|
4
|
+
import time
|
|
5
|
+
from unittest.mock import MagicMock, patch
|
|
6
|
+
|
|
7
|
+
import pytest
|
|
8
|
+
|
|
9
|
+
from inputtino._core import PenTablet as CorePenTablet
|
|
10
|
+
from inputtino.pentablet import (
|
|
11
|
+
DEFAULT_PEN_TABLET,
|
|
12
|
+
DeviceDefinition,
|
|
13
|
+
PenButtonType,
|
|
14
|
+
PenTablet,
|
|
15
|
+
PenToolType,
|
|
16
|
+
)
|
|
17
|
+
from tests.helpers import mark_practical
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@pytest.fixture
|
|
21
|
+
def mock_core_tablet():
|
|
22
|
+
"""Create a mock for CorePenTablet with basic functionality."""
|
|
23
|
+
with patch("inputtino._core.PenTablet") as mock_tablet_cls:
|
|
24
|
+
mock_instance = MagicMock(spec=CorePenTablet)
|
|
25
|
+
mock_tablet_cls.create.return_value = mock_instance
|
|
26
|
+
yield mock_instance
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_pen_tablet_creation_with_default_device():
|
|
30
|
+
"""Test creating a pen tablet with default device definition."""
|
|
31
|
+
with patch("inputtino._core.PenTablet") as mock_tablet_cls:
|
|
32
|
+
PenTablet()
|
|
33
|
+
|
|
34
|
+
mock_tablet_cls.create.assert_called_once()
|
|
35
|
+
created_def = mock_tablet_cls.create.call_args[0][0]
|
|
36
|
+
assert created_def.name == DEFAULT_PEN_TABLET.name
|
|
37
|
+
assert created_def.vendor_id == DEFAULT_PEN_TABLET.vendor_id
|
|
38
|
+
assert created_def.product_id == DEFAULT_PEN_TABLET.product_id
|
|
39
|
+
assert created_def.version == DEFAULT_PEN_TABLET.version
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def test_pen_tablet_creation_with_custom_device():
|
|
43
|
+
"""Test creating a pen tablet with custom device definition."""
|
|
44
|
+
custom_def = DeviceDefinition(
|
|
45
|
+
name="Custom Pen Tablet",
|
|
46
|
+
vendor_id=0x1234,
|
|
47
|
+
product_id=0x5678,
|
|
48
|
+
version=0x0001,
|
|
49
|
+
device_phys="/dev/input/test",
|
|
50
|
+
device_uniq="unique_id",
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
with patch("inputtino._core.PenTablet") as mock_tablet_cls:
|
|
54
|
+
PenTablet(custom_def)
|
|
55
|
+
|
|
56
|
+
mock_tablet_cls.create.assert_called_once()
|
|
57
|
+
created_def = mock_tablet_cls.create.call_args[0][0]
|
|
58
|
+
assert created_def.name == custom_def.name
|
|
59
|
+
assert created_def.vendor_id == custom_def.vendor_id
|
|
60
|
+
assert created_def.product_id == custom_def.product_id
|
|
61
|
+
assert created_def.version == custom_def.version
|
|
62
|
+
assert created_def.device_phys == custom_def.device_phys
|
|
63
|
+
assert created_def.device_uniq == custom_def.device_uniq
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def test_pen_tablet_place_tool(mock_core_tablet):
|
|
67
|
+
"""Test placing a tool on the tablet surface."""
|
|
68
|
+
tablet = PenTablet()
|
|
69
|
+
tablet.place_tool(
|
|
70
|
+
PenToolType.PEN,
|
|
71
|
+
x=0.5,
|
|
72
|
+
y=0.5,
|
|
73
|
+
pressure=1.0,
|
|
74
|
+
distance=0.0,
|
|
75
|
+
tilt_x=45.0,
|
|
76
|
+
tilt_y=-45.0,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
mock_core_tablet.place_tool.assert_called_once_with(
|
|
80
|
+
PenToolType.PEN, 0.5, 0.5, 1.0, 0.0, 45.0, -45.0
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def test_pen_tablet_set_button(mock_core_tablet):
|
|
85
|
+
"""Test setting pen button states."""
|
|
86
|
+
tablet = PenTablet()
|
|
87
|
+
|
|
88
|
+
for button in [
|
|
89
|
+
PenButtonType.PRIMARY,
|
|
90
|
+
PenButtonType.SECONDARY,
|
|
91
|
+
PenButtonType.TERTIARY,
|
|
92
|
+
]:
|
|
93
|
+
for pressed in (True, False):
|
|
94
|
+
tablet.set_button(button, pressed)
|
|
95
|
+
mock_core_tablet.set_btn.assert_called_with(button, pressed)
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def test_pen_tablet_nodes(mock_core_tablet):
|
|
99
|
+
"""Test getting pen tablet device nodes."""
|
|
100
|
+
expected_nodes = ["/dev/input/event0", "/dev/input/pen0"]
|
|
101
|
+
mock_core_tablet.get_nodes.return_value = expected_nodes
|
|
102
|
+
|
|
103
|
+
tablet = PenTablet()
|
|
104
|
+
assert tablet.nodes == expected_nodes
|
|
105
|
+
mock_core_tablet.get_nodes.assert_called_once()
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def test_pen_tablet_creation_failure():
|
|
109
|
+
"""Test handling of pen tablet creation failure."""
|
|
110
|
+
with patch("inputtino._core.PenTablet") as mock_tablet_cls:
|
|
111
|
+
mock_tablet_cls.create.side_effect = RuntimeError(
|
|
112
|
+
"Failed to create pen tablet device"
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
with pytest.raises(RuntimeError, match="Failed to create pen tablet device"):
|
|
116
|
+
PenTablet()
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@mark_practical
|
|
120
|
+
def test_practical_pen_draw_circle():
|
|
121
|
+
"""Test drawing a circle pattern with the pen tablet.
|
|
122
|
+
|
|
123
|
+
This practical test demonstrates:
|
|
124
|
+
1. Drawing a circle using the pen tool
|
|
125
|
+
2. Varying pressure based on position
|
|
126
|
+
3. Adding tilt effects
|
|
127
|
+
|
|
128
|
+
Note:
|
|
129
|
+
This test requires actual device access (/dev/uinput)
|
|
130
|
+
and may fail if run without proper permissions.
|
|
131
|
+
"""
|
|
132
|
+
tablet = PenTablet()
|
|
133
|
+
|
|
134
|
+
# Ensure we have valid device nodes
|
|
135
|
+
assert len(tablet.nodes) > 0, "No pen tablet device nodes created"
|
|
136
|
+
|
|
137
|
+
# Give system time to register the device
|
|
138
|
+
time.sleep(0.1)
|
|
139
|
+
|
|
140
|
+
# Draw circle pattern
|
|
141
|
+
radius = 0.3 # 30% of tablet width
|
|
142
|
+
center_x = 0.5
|
|
143
|
+
center_y = 0.5
|
|
144
|
+
steps = 50
|
|
145
|
+
try:
|
|
146
|
+
for i in range(steps + 1):
|
|
147
|
+
angle = 2 * math.pi * i / steps
|
|
148
|
+
x = center_x + radius * math.cos(angle)
|
|
149
|
+
y = center_y + radius * math.sin(angle)
|
|
150
|
+
|
|
151
|
+
# Vary pressure based on position (higher on right side)
|
|
152
|
+
pressure = 0.5 + 0.5 * math.cos(angle)
|
|
153
|
+
|
|
154
|
+
# Add tilt effect (tilt towards center)
|
|
155
|
+
tilt_x = -30 * math.cos(angle) # -30 to 30 degrees
|
|
156
|
+
tilt_y = -30 * math.sin(angle) # -30 to 30 degrees
|
|
157
|
+
|
|
158
|
+
tablet.place_tool(
|
|
159
|
+
PenToolType.PEN,
|
|
160
|
+
x=x,
|
|
161
|
+
y=y,
|
|
162
|
+
pressure=pressure,
|
|
163
|
+
distance=0.0, # Pen is touching surface
|
|
164
|
+
tilt_x=tilt_x,
|
|
165
|
+
tilt_y=tilt_y,
|
|
166
|
+
)
|
|
167
|
+
time.sleep(0.02) # Small delay for smooth movement
|
|
168
|
+
|
|
169
|
+
# Test button presses at cardinal points
|
|
170
|
+
for angle in [0, math.pi / 2, math.pi, 3 * math.pi / 2]:
|
|
171
|
+
x = center_x + radius * math.cos(angle)
|
|
172
|
+
y = center_y + radius * math.sin(angle)
|
|
173
|
+
|
|
174
|
+
tablet.place_tool(
|
|
175
|
+
PenToolType.PEN,
|
|
176
|
+
x=x,
|
|
177
|
+
y=y,
|
|
178
|
+
pressure=1.0,
|
|
179
|
+
distance=0.0,
|
|
180
|
+
tilt_x=0,
|
|
181
|
+
tilt_y=0,
|
|
182
|
+
)
|
|
183
|
+
tablet.set_button(PenButtonType.PRIMARY, True)
|
|
184
|
+
time.sleep(0.1)
|
|
185
|
+
tablet.set_button(PenButtonType.PRIMARY, False)
|
|
186
|
+
time.sleep(0.1)
|
|
187
|
+
|
|
188
|
+
finally:
|
|
189
|
+
# Place tool at distance to indicate release
|
|
190
|
+
tablet.place_tool(
|
|
191
|
+
PenToolType.SAME_AS_BEFORE,
|
|
192
|
+
x=center_x,
|
|
193
|
+
y=center_y,
|
|
194
|
+
pressure=0.0,
|
|
195
|
+
distance=1.0, # Pen is far from surface
|
|
196
|
+
tilt_x=0,
|
|
197
|
+
tilt_y=0,
|
|
198
|
+
)
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"""Tests for touchscreen.py."""
|
|
2
|
+
|
|
3
|
+
import time
|
|
4
|
+
from unittest.mock import MagicMock, patch
|
|
5
|
+
|
|
6
|
+
import pytest
|
|
7
|
+
|
|
8
|
+
from inputtino._core import TouchScreen as CoreTouchScreen
|
|
9
|
+
from inputtino.touchscreen import DeviceDefinition, TouchScreen
|
|
10
|
+
from tests.helpers import mark_practical
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest.fixture
|
|
14
|
+
def mock_core_touchscreen():
|
|
15
|
+
"""Create a mock for CoreTouchScreen with basic functionality."""
|
|
16
|
+
with patch("inputtino._core.TouchScreen") as mock_touchscreen_cls:
|
|
17
|
+
mock_instance = MagicMock(spec=CoreTouchScreen)
|
|
18
|
+
mock_touchscreen_cls.create.return_value = mock_instance
|
|
19
|
+
yield mock_instance
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def test_touchscreen_creation_with_default_device():
|
|
23
|
+
"""Test creating a touchscreen with default device definition."""
|
|
24
|
+
with patch("inputtino._core.TouchScreen") as mock_touchscreen_cls:
|
|
25
|
+
TouchScreen()
|
|
26
|
+
|
|
27
|
+
mock_touchscreen_cls.create.assert_called_once()
|
|
28
|
+
created_def = mock_touchscreen_cls.create.call_args[0][0]
|
|
29
|
+
assert created_def.name == "Wolf (virtual) touchscreen"
|
|
30
|
+
assert created_def.vendor_id == 0xAB00
|
|
31
|
+
assert created_def.product_id == 0xAB03
|
|
32
|
+
assert created_def.version == 0xAB00
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def test_touchscreen_creation_with_custom_device():
|
|
36
|
+
"""Test creating a touchscreen with custom device definition."""
|
|
37
|
+
custom_def = DeviceDefinition(
|
|
38
|
+
name="Custom TouchScreen",
|
|
39
|
+
vendor_id=0x1234,
|
|
40
|
+
product_id=0x5678,
|
|
41
|
+
version=0x0001,
|
|
42
|
+
device_phys="/dev/input/test",
|
|
43
|
+
device_uniq="unique_id",
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
with patch("inputtino._core.TouchScreen") as mock_touchscreen_cls:
|
|
47
|
+
TouchScreen(custom_def)
|
|
48
|
+
|
|
49
|
+
mock_touchscreen_cls.create.assert_called_once()
|
|
50
|
+
created_def = mock_touchscreen_cls.create.call_args[0][0]
|
|
51
|
+
assert created_def.name == custom_def.name
|
|
52
|
+
assert created_def.vendor_id == custom_def.vendor_id
|
|
53
|
+
assert created_def.product_id == custom_def.product_id
|
|
54
|
+
assert created_def.version == custom_def.version
|
|
55
|
+
assert created_def.device_phys == custom_def.device_phys
|
|
56
|
+
assert created_def.device_uniq == custom_def.device_uniq
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def test_touchscreen_finger_placement(mock_core_touchscreen):
|
|
60
|
+
"""Test finger placement on touchscreen."""
|
|
61
|
+
touchscreen = TouchScreen()
|
|
62
|
+
|
|
63
|
+
# Test placing a finger with default pressure and orientation
|
|
64
|
+
touchscreen.place_finger(0, 0.5, 0.5)
|
|
65
|
+
mock_core_touchscreen.place_finger.assert_called_with(0, 0.5, 0.5, 1.0, 0)
|
|
66
|
+
|
|
67
|
+
# Test placing a finger with custom pressure and orientation
|
|
68
|
+
touchscreen.place_finger(1, 0.75, 0.25, 0.8, 45)
|
|
69
|
+
mock_core_touchscreen.place_finger.assert_called_with(1, 0.75, 0.25, 0.8, 45)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def test_touchscreen_finger_release(mock_core_touchscreen):
|
|
73
|
+
"""Test finger release from touchscreen."""
|
|
74
|
+
touchscreen = TouchScreen()
|
|
75
|
+
touchscreen.release_finger(0)
|
|
76
|
+
mock_core_touchscreen.release_finger.assert_called_with(0)
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def test_touchscreen_nodes(mock_core_touchscreen):
|
|
80
|
+
"""Test getting touchscreen device nodes."""
|
|
81
|
+
expected_nodes = ["/dev/input/event0"]
|
|
82
|
+
mock_core_touchscreen.get_nodes.return_value = expected_nodes
|
|
83
|
+
|
|
84
|
+
touchscreen = TouchScreen()
|
|
85
|
+
assert touchscreen.nodes == expected_nodes
|
|
86
|
+
mock_core_touchscreen.get_nodes.assert_called_once()
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def test_touchscreen_creation_failure():
|
|
90
|
+
"""Test handling of touchscreen creation failure."""
|
|
91
|
+
with patch("inputtino._core.TouchScreen") as mock_touchscreen_cls:
|
|
92
|
+
mock_touchscreen_cls.create.side_effect = RuntimeError(
|
|
93
|
+
"Failed to create touchscreen device"
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
with pytest.raises(RuntimeError, match="Failed to create touchscreen device"):
|
|
97
|
+
TouchScreen()
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@mark_practical
|
|
101
|
+
def test_practical_touchscreen_draw_circle():
|
|
102
|
+
"""Test drawing a circle pattern with touch input.
|
|
103
|
+
|
|
104
|
+
This practical test demonstrates drawing a circle by:
|
|
105
|
+
1. Moving a single touch point in a circular pattern
|
|
106
|
+
2. Using normalized coordinates
|
|
107
|
+
3. Creating a smooth touch movement pattern
|
|
108
|
+
|
|
109
|
+
Note:
|
|
110
|
+
This test requires actual device access (/dev/uinput)
|
|
111
|
+
and may fail if run without proper permissions.
|
|
112
|
+
"""
|
|
113
|
+
touchscreen = TouchScreen()
|
|
114
|
+
|
|
115
|
+
# Ensure we have valid device nodes
|
|
116
|
+
assert len(touchscreen.nodes) > 0, "No touchscreen device nodes created"
|
|
117
|
+
|
|
118
|
+
# Give system time to register the device
|
|
119
|
+
time.sleep(0.1)
|
|
120
|
+
|
|
121
|
+
# Draw a circle using touch inputs
|
|
122
|
+
from math import cos, pi, sin
|
|
123
|
+
|
|
124
|
+
center_x, center_y = 0.5, 0.5 # Center of the screen
|
|
125
|
+
radius = 0.2 # Circle radius in normalized coordinates
|
|
126
|
+
steps = 36 # Number of points to create the circle
|
|
127
|
+
|
|
128
|
+
try:
|
|
129
|
+
# Draw circle pattern
|
|
130
|
+
for i in range(steps + 1):
|
|
131
|
+
angle = 2 * pi * i / steps
|
|
132
|
+
x = center_x + radius * cos(angle)
|
|
133
|
+
y = center_y + radius * sin(angle)
|
|
134
|
+
|
|
135
|
+
# Ensure coordinates stay within bounds
|
|
136
|
+
x = max(0.0, min(1.0, x))
|
|
137
|
+
y = max(0.0, min(1.0, y))
|
|
138
|
+
|
|
139
|
+
touchscreen.place_finger(0, x, y)
|
|
140
|
+
time.sleep(0.02) # Small delay for smooth movement
|
|
141
|
+
|
|
142
|
+
finally:
|
|
143
|
+
# Ensure we always release the finger
|
|
144
|
+
touchscreen.release_finger(0)
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"""Tests for trackpad.py."""
|
|
2
|
+
|
|
3
|
+
import time
|
|
4
|
+
from unittest.mock import MagicMock, patch
|
|
5
|
+
|
|
6
|
+
import pytest
|
|
7
|
+
|
|
8
|
+
from inputtino._core import Trackpad as CoreTrackpad
|
|
9
|
+
from inputtino.trackpad import DeviceDefinition, Trackpad
|
|
10
|
+
from tests.helpers import mark_practical
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest.fixture
|
|
14
|
+
def mock_core_trackpad():
|
|
15
|
+
"""Create a mock for CoreTrackpad with basic functionality."""
|
|
16
|
+
with patch("inputtino._core.Trackpad") as mock_trackpad_cls:
|
|
17
|
+
mock_instance = MagicMock(spec=CoreTrackpad)
|
|
18
|
+
mock_trackpad_cls.create.return_value = mock_instance
|
|
19
|
+
yield mock_instance
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def test_trackpad_creation_with_default_device():
|
|
23
|
+
"""Test creating a trackpad with default device definition."""
|
|
24
|
+
with patch("inputtino._core.Trackpad") as mock_trackpad_cls:
|
|
25
|
+
Trackpad()
|
|
26
|
+
|
|
27
|
+
mock_trackpad_cls.create.assert_called_once()
|
|
28
|
+
created_def = mock_trackpad_cls.create.call_args[0][0]
|
|
29
|
+
assert created_def.name == "Wolf (virtual) touchpad"
|
|
30
|
+
assert created_def.vendor_id == 0xAB00
|
|
31
|
+
assert created_def.product_id == 0xAB02
|
|
32
|
+
assert created_def.version == 0xAB00
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def test_trackpad_creation_with_custom_device():
|
|
36
|
+
"""Test creating a trackpad with custom device definition."""
|
|
37
|
+
custom_def = DeviceDefinition(
|
|
38
|
+
name="Custom Trackpad",
|
|
39
|
+
vendor_id=0x1234,
|
|
40
|
+
product_id=0x5678,
|
|
41
|
+
version=0x0001,
|
|
42
|
+
device_phys="/dev/input/test",
|
|
43
|
+
device_uniq="unique_id",
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
with patch("inputtino._core.Trackpad") as mock_trackpad_cls:
|
|
47
|
+
Trackpad(custom_def)
|
|
48
|
+
|
|
49
|
+
mock_trackpad_cls.create.assert_called_once()
|
|
50
|
+
created_def = mock_trackpad_cls.create.call_args[0][0]
|
|
51
|
+
assert created_def.name == custom_def.name
|
|
52
|
+
assert created_def.vendor_id == custom_def.vendor_id
|
|
53
|
+
assert created_def.product_id == custom_def.product_id
|
|
54
|
+
assert created_def.version == custom_def.version
|
|
55
|
+
assert created_def.device_phys == custom_def.device_phys
|
|
56
|
+
assert created_def.device_uniq == custom_def.device_uniq
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def test_trackpad_finger_operations(mock_core_trackpad):
|
|
60
|
+
"""Test trackpad finger placement and release operations."""
|
|
61
|
+
trackpad = Trackpad()
|
|
62
|
+
|
|
63
|
+
# Test finger placement
|
|
64
|
+
trackpad.place_finger(0, 0.5, 0.5, 0.8, 45)
|
|
65
|
+
mock_core_trackpad.place_finger.assert_called_once_with(0, 0.5, 0.5, 0.8, 45)
|
|
66
|
+
|
|
67
|
+
# Test finger release
|
|
68
|
+
trackpad.release_finger(0)
|
|
69
|
+
mock_core_trackpad.release_finger.assert_called_once_with(0)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
def test_trackpad_button_operations(mock_core_trackpad):
|
|
73
|
+
"""Test trackpad button operations."""
|
|
74
|
+
trackpad = Trackpad()
|
|
75
|
+
|
|
76
|
+
# Test button press
|
|
77
|
+
trackpad.set_left_button(True)
|
|
78
|
+
mock_core_trackpad.set_left_btn.assert_called_once_with(True)
|
|
79
|
+
|
|
80
|
+
# Test button release
|
|
81
|
+
mock_core_trackpad.set_left_btn.reset_mock()
|
|
82
|
+
trackpad.set_left_button(False)
|
|
83
|
+
mock_core_trackpad.set_left_btn.assert_called_once_with(False)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def test_trackpad_nodes(mock_core_trackpad):
|
|
87
|
+
"""Test getting trackpad device nodes."""
|
|
88
|
+
expected_nodes = ["/dev/input/event1"]
|
|
89
|
+
mock_core_trackpad.get_nodes.return_value = expected_nodes
|
|
90
|
+
|
|
91
|
+
trackpad = Trackpad()
|
|
92
|
+
assert trackpad.nodes == expected_nodes
|
|
93
|
+
mock_core_trackpad.get_nodes.assert_called_once()
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def test_trackpad_creation_failure():
|
|
97
|
+
"""Test handling of trackpad creation failure."""
|
|
98
|
+
with patch("inputtino._core.Trackpad") as mock_trackpad_cls:
|
|
99
|
+
mock_trackpad_cls.create.side_effect = RuntimeError(
|
|
100
|
+
"Failed to create trackpad device"
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
with pytest.raises(RuntimeError, match="Failed to create trackpad device"):
|
|
104
|
+
Trackpad()
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
@mark_practical
|
|
108
|
+
def test_practical_trackpad_gestures():
|
|
109
|
+
"""Test practical trackpad gestures.
|
|
110
|
+
|
|
111
|
+
This practical test demonstrates basic trackpad functionality by:
|
|
112
|
+
1. Simulating single finger tap
|
|
113
|
+
2. Simulating two-finger scroll
|
|
114
|
+
3. Testing button click
|
|
115
|
+
|
|
116
|
+
Note:
|
|
117
|
+
This test requires actual device access (/dev/uinput)
|
|
118
|
+
and may fail if run without proper permissions.
|
|
119
|
+
"""
|
|
120
|
+
trackpad = Trackpad()
|
|
121
|
+
|
|
122
|
+
# Ensure we have valid device nodes
|
|
123
|
+
assert len(trackpad.nodes) > 0, "No trackpad device nodes created"
|
|
124
|
+
|
|
125
|
+
# Give system time to register the device
|
|
126
|
+
time.sleep(0.1)
|
|
127
|
+
|
|
128
|
+
# Single finger tap
|
|
129
|
+
trackpad.place_finger(0, 0.5, 0.5, 1.0, 0)
|
|
130
|
+
time.sleep(0.1)
|
|
131
|
+
trackpad.release_finger(0)
|
|
132
|
+
|
|
133
|
+
# Two-finger scroll (vertical)
|
|
134
|
+
trackpad.place_finger(0, 0.5, 0.3, 1.0, 0)
|
|
135
|
+
trackpad.place_finger(1, 0.5, 0.4, 1.0, 0)
|
|
136
|
+
for y in range(3, 8):
|
|
137
|
+
trackpad.place_finger(0, 0.5, y / 10, 1.0, 0)
|
|
138
|
+
trackpad.place_finger(1, 0.5, (y + 1) / 10, 1.0, 0)
|
|
139
|
+
time.sleep(0.05)
|
|
140
|
+
trackpad.release_finger(0)
|
|
141
|
+
trackpad.release_finger(1)
|
|
142
|
+
|
|
143
|
+
# Button click
|
|
144
|
+
trackpad.set_left_button(True)
|
|
145
|
+
time.sleep(0.1)
|
|
146
|
+
trackpad.set_left_button(False)
|