mirror of
https://github.com/sezanzeb/input-remapper
synced 2024-11-18 03:25:52 +00:00
horizontal joystick scrolling
This commit is contained in:
parent
4a745eb2e9
commit
03ccb935fe
@ -51,6 +51,8 @@ INITIAL_CONFIG = {
|
||||
'pointer_speed': 80,
|
||||
'left_purpose': MOUSE,
|
||||
'right_purpose': WHEEL,
|
||||
'x_scroll_speed': 2,
|
||||
'y_scroll_speed': 0.5
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ JOYSTICK = [
|
||||
]
|
||||
|
||||
# miniscule movements on the joystick should not trigger a mouse wheel event
|
||||
WHEEL_THRESHOLD = 0.3
|
||||
WHEEL_THRESHOLD = 0.15
|
||||
|
||||
|
||||
def _write(device, ev_type, keycode, value):
|
||||
@ -146,6 +146,8 @@ async def ev_abs_mapper(abs_state, input_device, keymapper_device, mapping):
|
||||
non_linearity = mapping.get('gamepad.joystick.non_linearity')
|
||||
left_purpose = mapping.get('gamepad.joystick.left_purpose')
|
||||
right_purpose = mapping.get('gamepad.joystick.right_purpose')
|
||||
x_scroll_speed = mapping.get('gamepad.joystick.x_scroll_speed')
|
||||
y_scroll_speed = mapping.get('gamepad.joystick.y_scroll_speed')
|
||||
|
||||
logger.info(
|
||||
'Left joystick as %s, right joystick as %s',
|
||||
@ -161,15 +163,15 @@ async def ev_abs_mapper(abs_state, input_device, keymapper_device, mapping):
|
||||
right_purpose
|
||||
)
|
||||
|
||||
if non_linearity != 1:
|
||||
# to make small movements smaller for more precision
|
||||
speed = (mouse_x ** 2 + mouse_y ** 2) ** 0.5
|
||||
factor = (speed / max_speed) ** non_linearity
|
||||
else:
|
||||
factor = 1
|
||||
|
||||
# mouse movements
|
||||
if abs(mouse_x) > 0 or abs(mouse_y) > 0:
|
||||
if non_linearity != 1:
|
||||
# to make small movements smaller for more precision
|
||||
speed = (mouse_x ** 2 + mouse_y ** 2) ** 0.5
|
||||
factor = (speed / max_speed) ** non_linearity
|
||||
else:
|
||||
factor = 1
|
||||
|
||||
rel_x = mouse_x * factor * pointer_speed / max_value
|
||||
rel_y = mouse_y * factor * pointer_speed / max_value
|
||||
pending_x_rel, rel_x = accumulate(pending_x_rel, rel_x)
|
||||
@ -181,15 +183,15 @@ async def ev_abs_mapper(abs_state, input_device, keymapper_device, mapping):
|
||||
|
||||
# wheel movements
|
||||
if abs(wheel_x) > 0:
|
||||
float_rel_rx = wheel_x / max_value
|
||||
float_rel_rx = wheel_x * x_scroll_speed / max_value
|
||||
pending_rx_rel, rel_rx = accumulate(pending_rx_rel, float_rel_rx)
|
||||
if abs(float_rel_rx) > WHEEL_THRESHOLD:
|
||||
_write(keymapper_device, EV_REL, REL_HWHEEL, -rel_rx)
|
||||
if abs(float_rel_rx) > WHEEL_THRESHOLD * x_scroll_speed:
|
||||
_write(keymapper_device, EV_REL, REL_HWHEEL, rel_rx)
|
||||
|
||||
if abs(wheel_y) > 0:
|
||||
float_rel_ry = wheel_y / max_value
|
||||
float_rel_ry = wheel_y * y_scroll_speed / max_value
|
||||
pending_ry_rel, rel_ry = accumulate(pending_ry_rel, float_rel_ry)
|
||||
if abs(float_rel_ry) > WHEEL_THRESHOLD:
|
||||
if abs(float_rel_ry) > WHEEL_THRESHOLD * y_scroll_speed:
|
||||
_write(keymapper_device, EV_REL, REL_WHEEL, -rel_ry)
|
||||
|
||||
# try to do this as close to 60hz as possible
|
||||
|
@ -247,13 +247,13 @@ class KeycodeInjector:
|
||||
capabilities[EV_KEY] += list(macro.get_capabilities())
|
||||
|
||||
if abs_to_rel:
|
||||
# those are the requirements to recognize it as mouse
|
||||
# on my system. REL_X and REL_Y are of course required to
|
||||
# accept the events that the mouse-movement-mapper writes.
|
||||
# REL_WHEEL was also required to recognize the gamepad
|
||||
# as mouse, even if no joystick is used as wheel.
|
||||
capabilities[EV_REL] = [
|
||||
evdev.ecodes.REL_X,
|
||||
evdev.ecodes.REL_Y,
|
||||
evdev.ecodes.REL_WHEEL,
|
||||
evdev.ecodes.REL_HWHEEL,
|
||||
]
|
||||
keys = capabilities.get(EV_KEY)
|
||||
if keys is None:
|
||||
|
@ -97,7 +97,6 @@ def can_read_devices():
|
||||
plugdev_check = check_group('plugdev')
|
||||
|
||||
# ubuntu. funnily, individual devices in /dev/input/ have write permitted.
|
||||
print(is_service_running(), check_injection_rights())
|
||||
if not is_service_running():
|
||||
can_write = check_injection_rights()
|
||||
else:
|
||||
|
@ -56,7 +56,6 @@ class Mapping(ConfigBase):
|
||||
|
||||
def set(self, *args):
|
||||
"""Set a config value. See `ConfigBase.set`."""
|
||||
print('set', args)
|
||||
self.changed = True
|
||||
return super().set(*args)
|
||||
|
||||
|
@ -365,6 +365,9 @@ _fixture_copy = copy.deepcopy(fixtures)
|
||||
|
||||
def cleanup():
|
||||
"""Reset the applications state."""
|
||||
for task in asyncio.Task.all_tasks():
|
||||
task.cancel()
|
||||
|
||||
os.system('pkill -f key-mapper-service')
|
||||
if os.path.exists(tmp):
|
||||
shutil.rmtree(tmp)
|
||||
@ -374,6 +377,7 @@ def cleanup():
|
||||
|
||||
system_mapping.populate()
|
||||
custom_mapping.empty()
|
||||
custom_mapping.clear_config()
|
||||
|
||||
clear_write_history()
|
||||
|
||||
@ -388,6 +392,7 @@ def cleanup():
|
||||
for path in list(_fixture_copy.keys()):
|
||||
if path not in fixtures:
|
||||
fixtures[path] = _fixture_copy[path]
|
||||
|
||||
refresh_devices()
|
||||
|
||||
|
||||
|
@ -30,7 +30,7 @@ from keymapper.mapping import Mapping
|
||||
from keymapper.dev.ev_abs_mapper import MOUSE, WHEEL
|
||||
|
||||
from tests.test import InputDevice, UInput, MAX_ABS, clear_write_history, \
|
||||
uinput_write_history
|
||||
uinput_write_history, cleanup
|
||||
|
||||
|
||||
abs_state = [0, 0, 0, 0]
|
||||
@ -53,21 +53,11 @@ class TestEvAbsMapper(unittest.TestCase):
|
||||
self.mapping
|
||||
))
|
||||
|
||||
config.set('gamepad.joystick.x_scroll_speed', 1)
|
||||
config.set('gamepad.joystick.y_scroll_speed', 1)
|
||||
|
||||
def tearDown(self):
|
||||
config.clear_config()
|
||||
self.mapping.clear_config()
|
||||
loop = asyncio.get_event_loop()
|
||||
|
||||
try:
|
||||
for task in asyncio.Task.all_tasks():
|
||||
task.cancel()
|
||||
|
||||
loop.stop()
|
||||
loop.close()
|
||||
except RuntimeError:
|
||||
pass
|
||||
|
||||
clear_write_history()
|
||||
cleanup()
|
||||
|
||||
def do(self, a, b, c, d, expectation):
|
||||
"""Present fake values to the loop and observe the outcome."""
|
||||
@ -97,9 +87,9 @@ class TestEvAbsMapper(unittest.TestCase):
|
||||
self.do(0, MAX_ABS, 0, 0, (EV_REL, REL_Y, speed))
|
||||
self.do(0, -MAX_ABS, 0, 0, (EV_REL, REL_Y, -speed))
|
||||
|
||||
# wheel event values are negative
|
||||
self.do(0, 0, MAX_ABS, 0, (EV_REL, REL_HWHEEL, -1))
|
||||
self.do(0, 0, -MAX_ABS, 0, (EV_REL, REL_HWHEEL, 1))
|
||||
# vertical wheel event values are negative
|
||||
self.do(0, 0, MAX_ABS, 0, (EV_REL, REL_HWHEEL, 1))
|
||||
self.do(0, 0, -MAX_ABS, 0, (EV_REL, REL_HWHEEL, -1))
|
||||
self.do(0, 0, 0, MAX_ABS, (EV_REL, REL_WHEEL, -1))
|
||||
self.do(0, 0, 0, -MAX_ABS, (EV_REL, REL_WHEEL, 1))
|
||||
|
||||
@ -109,13 +99,15 @@ class TestEvAbsMapper(unittest.TestCase):
|
||||
config.set('gamepad.joystick.pointer_speed', speed)
|
||||
config.set('gamepad.joystick.left_purpose', WHEEL)
|
||||
config.set('gamepad.joystick.right_purpose', MOUSE)
|
||||
config.set('gamepad.joystick.x_scroll_speed', 1)
|
||||
config.set('gamepad.joystick.y_scroll_speed', 2)
|
||||
|
||||
self.do(MAX_ABS, 0, 0, 0, (EV_REL, REL_HWHEEL, -1))
|
||||
self.do(-MAX_ABS, 0, 0, 0, (EV_REL, REL_HWHEEL, 1))
|
||||
self.do(0, MAX_ABS, 0, 0, (EV_REL, REL_WHEEL, -1))
|
||||
self.do(0, -MAX_ABS, 0, 0, (EV_REL, REL_WHEEL, 1))
|
||||
# vertical wheel event values are negative
|
||||
self.do(MAX_ABS, 0, 0, 0, (EV_REL, REL_HWHEEL, 1))
|
||||
self.do(-MAX_ABS, 0, 0, 0, (EV_REL, REL_HWHEEL, -1))
|
||||
self.do(0, MAX_ABS, 0, 0, (EV_REL, REL_WHEEL, -2))
|
||||
self.do(0, -MAX_ABS, 0, 0, (EV_REL, REL_WHEEL, 2))
|
||||
|
||||
# wheel event values are negative
|
||||
self.do(0, 0, MAX_ABS, 0, (EV_REL, REL_X, speed))
|
||||
self.do(0, 0, -MAX_ABS, 0, (EV_REL, REL_X, -speed))
|
||||
self.do(0, 0, 0, MAX_ABS, (EV_REL, REL_Y, speed))
|
||||
@ -133,7 +125,6 @@ class TestEvAbsMapper(unittest.TestCase):
|
||||
self.do(0, MAX_ABS, 0, 0, (EV_REL, REL_Y, speed))
|
||||
self.do(0, -MAX_ABS, 0, 0, (EV_REL, REL_Y, -speed))
|
||||
|
||||
# wheel event values are negative
|
||||
self.do(0, 0, MAX_ABS, 0, (EV_REL, REL_X, speed))
|
||||
self.do(0, 0, -MAX_ABS, 0, (EV_REL, REL_X, -speed))
|
||||
self.do(0, 0, 0, MAX_ABS, (EV_REL, REL_Y, speed))
|
||||
@ -142,17 +133,19 @@ class TestEvAbsMapper(unittest.TestCase):
|
||||
def test_joystick_purpose_4(self):
|
||||
config.set('gamepad.joystick.left_purpose', WHEEL)
|
||||
config.set('gamepad.joystick.right_purpose', WHEEL)
|
||||
self.mapping.set('gamepad.joystick.x_scroll_speed', 2)
|
||||
self.mapping.set('gamepad.joystick.y_scroll_speed', 3)
|
||||
|
||||
self.do(MAX_ABS, 0, 0, 0, (EV_REL, REL_HWHEEL, -1))
|
||||
self.do(-MAX_ABS, 0, 0, 0, (EV_REL, REL_HWHEEL, 1))
|
||||
self.do(0, MAX_ABS, 0, 0, (EV_REL, REL_WHEEL, -1))
|
||||
self.do(0, -MAX_ABS, 0, 0, (EV_REL, REL_WHEEL, 1))
|
||||
self.do(MAX_ABS, 0, 0, 0, (EV_REL, REL_HWHEEL, 2))
|
||||
self.do(-MAX_ABS, 0, 0, 0, (EV_REL, REL_HWHEEL, -2))
|
||||
self.do(0, MAX_ABS, 0, 0, (EV_REL, REL_WHEEL, -3))
|
||||
self.do(0, -MAX_ABS, 0, 0, (EV_REL, REL_WHEEL, 3))
|
||||
|
||||
# wheel event values are negative
|
||||
self.do(0, 0, MAX_ABS, 0, (EV_REL, REL_HWHEEL, -1))
|
||||
self.do(0, 0, -MAX_ABS, 0, (EV_REL, REL_HWHEEL, 1))
|
||||
self.do(0, 0, 0, MAX_ABS, (EV_REL, REL_WHEEL, -1))
|
||||
self.do(0, 0, 0, -MAX_ABS, (EV_REL, REL_WHEEL, 1))
|
||||
# vertical wheel event values are negative
|
||||
self.do(0, 0, MAX_ABS, 0, (EV_REL, REL_HWHEEL, 2))
|
||||
self.do(0, 0, -MAX_ABS, 0, (EV_REL, REL_HWHEEL, -2))
|
||||
self.do(0, 0, 0, MAX_ABS, (EV_REL, REL_WHEEL, -3))
|
||||
self.do(0, 0, 0, -MAX_ABS, (EV_REL, REL_WHEEL, 3))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
@ -174,6 +174,11 @@ class TestInjector(unittest.TestCase):
|
||||
self.assertNotIn(evdev.ecodes.EV_ABS, capabilities)
|
||||
self.assertIn(evdev.ecodes.EV_REL, capabilities)
|
||||
|
||||
self.assertIn(evdev.ecodes.REL_X, capabilities.get(EV_REL))
|
||||
self.assertIn(evdev.ecodes.REL_Y, capabilities.get(EV_REL))
|
||||
self.assertIn(evdev.ecodes.REL_WHEEL, capabilities.get(EV_REL))
|
||||
self.assertIn(evdev.ecodes.REL_HWHEEL, capabilities.get(EV_REL))
|
||||
|
||||
self.assertIn(evdev.ecodes.EV_KEY, capabilities)
|
||||
self.assertEqual(len(capabilities[evdev.ecodes.EV_KEY]), 1)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user