|
|
|
@ -31,6 +31,7 @@ import multiprocessing
|
|
|
|
|
import evdev
|
|
|
|
|
|
|
|
|
|
from keymapper.logger import logger
|
|
|
|
|
from keymapper.config import config
|
|
|
|
|
from keymapper.getdevices import get_devices
|
|
|
|
|
from keymapper.state import system_mapping, KEYCODE_OFFSET
|
|
|
|
|
from keymapper.dev.macros import parse
|
|
|
|
@ -266,42 +267,8 @@ class KeycodeInjector:
|
|
|
|
|
value
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
async def _injection_loop(self, device, keymapper_device):
|
|
|
|
|
"""Inject keycodes for one of the virtual devices.
|
|
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
|
----------
|
|
|
|
|
device : evdev.InputDevice
|
|
|
|
|
where to read keycodes from
|
|
|
|
|
keymapper_device : evdev.UInput
|
|
|
|
|
where to write keycodes to
|
|
|
|
|
"""
|
|
|
|
|
# TODO this function is too long
|
|
|
|
|
# Parse all macros beforehand
|
|
|
|
|
logger.debug('Parsing macros')
|
|
|
|
|
macros = {}
|
|
|
|
|
for keycode, output in self.mapping:
|
|
|
|
|
if '(' in output and ')' in output and len(output) >= 4:
|
|
|
|
|
# probably a macro
|
|
|
|
|
macros[keycode] = parse(
|
|
|
|
|
output,
|
|
|
|
|
lambda *args: self._macro_write(*args, keymapper_device)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
logger.debug(
|
|
|
|
|
'Started injecting into %s, fd %s',
|
|
|
|
|
keymapper_device.device.path, keymapper_device.fd
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
self.abs_x = 0
|
|
|
|
|
self.abs_y = 0
|
|
|
|
|
|
|
|
|
|
# events only take ints, so a movement of 0.3 needs to add up to
|
|
|
|
|
# 1.2 to affect the cursor.
|
|
|
|
|
self.pending_x_rel = 0
|
|
|
|
|
self.pending_y_rel = 0
|
|
|
|
|
|
|
|
|
|
async def spam_mouse_movements():
|
|
|
|
|
async def spam_mouse_movements(self, keymapper_device):
|
|
|
|
|
"""Keep writing mouse movements based on the gamepad stick position."""
|
|
|
|
|
# TODO get absinfo beforehand
|
|
|
|
|
max_value = 32767
|
|
|
|
|
max_speed = ((max_value ** 2) * 2) ** 0.5
|
|
|
|
@ -311,10 +278,13 @@ class KeycodeInjector:
|
|
|
|
|
abs_y = self.abs_y
|
|
|
|
|
abs_x = self.abs_x
|
|
|
|
|
|
|
|
|
|
non_linearity = config.get('gamepad.non_linearity', 4)
|
|
|
|
|
if non_linearity != 1:
|
|
|
|
|
# to make small movements smaller for more precision
|
|
|
|
|
speed = (abs_x ** 2 + abs_y ** 2) ** 0.5
|
|
|
|
|
non_linearity = 4
|
|
|
|
|
factor = (speed / max_speed) ** non_linearity
|
|
|
|
|
else:
|
|
|
|
|
factor = 1
|
|
|
|
|
|
|
|
|
|
rel_x = abs_x * factor * 80 / max_value
|
|
|
|
|
rel_y = abs_y * factor * 80 / max_value
|
|
|
|
@ -326,6 +296,7 @@ class KeycodeInjector:
|
|
|
|
|
self.pending_x_rel -= rel_x
|
|
|
|
|
self.pending_y_rel -= rel_y
|
|
|
|
|
|
|
|
|
|
if rel_y != 0:
|
|
|
|
|
self._write(
|
|
|
|
|
keymapper_device,
|
|
|
|
|
evdev.ecodes.EV_REL,
|
|
|
|
@ -333,6 +304,7 @@ class KeycodeInjector:
|
|
|
|
|
rel_y
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if rel_x != 0:
|
|
|
|
|
self._write(
|
|
|
|
|
keymapper_device,
|
|
|
|
|
evdev.ecodes.EV_REL,
|
|
|
|
@ -340,7 +312,42 @@ class KeycodeInjector:
|
|
|
|
|
rel_x
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
asyncio.ensure_future(spam_mouse_movements())
|
|
|
|
|
async def _injection_loop(self, device, keymapper_device):
|
|
|
|
|
"""Inject keycodes for one of the virtual devices.
|
|
|
|
|
|
|
|
|
|
Parameters
|
|
|
|
|
----------
|
|
|
|
|
device : evdev.InputDevice
|
|
|
|
|
where to read keycodes from
|
|
|
|
|
keymapper_device : evdev.UInput
|
|
|
|
|
where to write keycodes to
|
|
|
|
|
"""
|
|
|
|
|
# TODO this function is too long
|
|
|
|
|
# Parse all macros beforehand
|
|
|
|
|
logger.debug('Parsing macros')
|
|
|
|
|
macros = {}
|
|
|
|
|
for keycode, output in self.mapping:
|
|
|
|
|
if '(' in output and ')' in output and len(output) >= 4:
|
|
|
|
|
# probably a macro
|
|
|
|
|
macros[keycode] = parse(
|
|
|
|
|
output,
|
|
|
|
|
lambda *args: self._macro_write(*args, keymapper_device)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
logger.debug(
|
|
|
|
|
'Started injecting into %s, fd %s',
|
|
|
|
|
keymapper_device.device.path, keymapper_device.fd
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
self.abs_x = 0
|
|
|
|
|
self.abs_y = 0
|
|
|
|
|
|
|
|
|
|
# events only take ints, so a movement of 0.3 needs to add up to
|
|
|
|
|
# 1.2 to affect the cursor.
|
|
|
|
|
self.pending_x_rel = 0
|
|
|
|
|
self.pending_y_rel = 0
|
|
|
|
|
|
|
|
|
|
asyncio.ensure_future(self.spam_mouse_movements(keymapper_device))
|
|
|
|
|
|
|
|
|
|
async for event in device.async_read_loop():
|
|
|
|
|
if self.map_abs_to_rel() and event.type == evdev.ecodes.EV_ABS:
|
|
|
|
|