mirror of
https://github.com/sezanzeb/input-remapper
synced 2024-11-02 15:40:19 +00:00
RX and RY movements as mouse wheel
This commit is contained in:
parent
1e10f0bd35
commit
28854888a3
@ -26,7 +26,7 @@ import asyncio
|
|||||||
import time
|
import time
|
||||||
|
|
||||||
import evdev
|
import evdev
|
||||||
from evdev.ecodes import EV_ABS, EV_REL
|
from evdev.ecodes import EV_ABS, EV_REL, REL_X, REL_Y, REL_WHEEL, REL_HWHEEL
|
||||||
|
|
||||||
from keymapper.logger import logger
|
from keymapper.logger import logger
|
||||||
from keymapper.config import config
|
from keymapper.config import config
|
||||||
@ -40,6 +40,9 @@ JOYSTICK = [
|
|||||||
evdev.ecodes.ABS_RY,
|
evdev.ecodes.ABS_RY,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# miniscule movements on the joystick should not trigger a mouse wheel event
|
||||||
|
WHEEL_THRESHOLD = 0.3
|
||||||
|
|
||||||
|
|
||||||
def _write(device, ev_type, keycode, value):
|
def _write(device, ev_type, keycode, value):
|
||||||
"""Inject."""
|
"""Inject."""
|
||||||
@ -47,6 +50,19 @@ def _write(device, ev_type, keycode, value):
|
|||||||
device.syn()
|
device.syn()
|
||||||
|
|
||||||
|
|
||||||
|
def accumulate(pending, current):
|
||||||
|
"""Since devices can't do float values, stuff has to be accumulated.
|
||||||
|
|
||||||
|
If pending is 0.6 and current is 0.5, return 0.1 and 1.
|
||||||
|
Because 1 may move 1px, and 0.1px is rememberd for the next value in
|
||||||
|
pending.
|
||||||
|
"""
|
||||||
|
pending += current
|
||||||
|
current = int(pending)
|
||||||
|
pending -= current
|
||||||
|
return pending, current
|
||||||
|
|
||||||
|
|
||||||
async def ev_abs_mapper(abs_state, input_device, keymapper_device):
|
async def ev_abs_mapper(abs_state, input_device, keymapper_device):
|
||||||
"""Keep writing mouse movements based on the gamepad stick position.
|
"""Keep writing mouse movements based on the gamepad stick position.
|
||||||
|
|
||||||
@ -59,8 +75,11 @@ async def ev_abs_mapper(abs_state, input_device, keymapper_device):
|
|||||||
"""
|
"""
|
||||||
# events only take ints, so a movement of 0.3 needs to add
|
# events only take ints, so a movement of 0.3 needs to add
|
||||||
# up to 1.2 to affect the cursor.
|
# up to 1.2 to affect the cursor.
|
||||||
|
#
|
||||||
pending_x_rel = 0
|
pending_x_rel = 0
|
||||||
pending_y_rel = 0
|
pending_y_rel = 0
|
||||||
|
pending_rx_rel = 0
|
||||||
|
pending_ry_rel = 0
|
||||||
|
|
||||||
logger.info('Mapping gamepad to mouse movements')
|
logger.info('Mapping gamepad to mouse movements')
|
||||||
max_value = input_device.absinfo(EV_ABS).max
|
max_value = input_device.absinfo(EV_ABS).max
|
||||||
@ -71,7 +90,7 @@ async def ev_abs_mapper(abs_state, input_device, keymapper_device):
|
|||||||
|
|
||||||
while True:
|
while True:
|
||||||
start = time.time()
|
start = time.time()
|
||||||
abs_x, abs_y = abs_state
|
abs_x, abs_y, abs_rx, abs_ry = abs_state
|
||||||
|
|
||||||
if non_linearity != 1:
|
if non_linearity != 1:
|
||||||
# to make small movements smaller for more precision
|
# to make small movements smaller for more precision
|
||||||
@ -80,31 +99,26 @@ async def ev_abs_mapper(abs_state, input_device, keymapper_device):
|
|||||||
else:
|
else:
|
||||||
factor = 1
|
factor = 1
|
||||||
|
|
||||||
|
# mouse movements
|
||||||
rel_x = abs_x * factor * pointer_speed / max_value
|
rel_x = abs_x * factor * pointer_speed / max_value
|
||||||
rel_y = abs_y * factor * pointer_speed / max_value
|
rel_y = abs_y * factor * pointer_speed / max_value
|
||||||
|
pending_x_rel, rel_x = accumulate(pending_x_rel, rel_x)
|
||||||
pending_x_rel += rel_x
|
pending_y_rel, rel_y = accumulate(pending_y_rel, rel_y)
|
||||||
pending_y_rel += rel_y
|
|
||||||
rel_x = int(pending_x_rel)
|
|
||||||
rel_y = int(pending_y_rel)
|
|
||||||
pending_x_rel -= rel_x
|
|
||||||
pending_y_rel -= rel_y
|
|
||||||
|
|
||||||
if rel_y != 0:
|
|
||||||
_write(
|
|
||||||
keymapper_device,
|
|
||||||
EV_REL,
|
|
||||||
evdev.ecodes.ABS_Y,
|
|
||||||
rel_y
|
|
||||||
)
|
|
||||||
|
|
||||||
if rel_x != 0:
|
if rel_x != 0:
|
||||||
_write(
|
_write(keymapper_device, EV_REL, REL_X, rel_x)
|
||||||
keymapper_device,
|
if rel_y != 0:
|
||||||
EV_REL,
|
_write(keymapper_device, EV_REL, REL_Y, rel_y)
|
||||||
evdev.ecodes.ABS_X,
|
|
||||||
rel_x
|
# wheel movements
|
||||||
)
|
float_rel_rx = abs_rx / 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)
|
||||||
|
|
||||||
|
float_rel_ry = abs_ry / max_value
|
||||||
|
pending_ry_rel, rel_ry = accumulate(pending_ry_rel, float_rel_ry)
|
||||||
|
if abs(float_rel_ry) > WHEEL_THRESHOLD:
|
||||||
|
_write(keymapper_device, EV_REL, REL_WHEEL, -rel_ry)
|
||||||
|
|
||||||
# try to do this as close to 60hz as possible
|
# try to do this as close to 60hz as possible
|
||||||
time_taken = time.time() - start
|
time_taken = time.time() - start
|
||||||
|
@ -29,7 +29,7 @@ import subprocess
|
|||||||
import multiprocessing
|
import multiprocessing
|
||||||
|
|
||||||
import evdev
|
import evdev
|
||||||
from evdev.ecodes import EV_KEY, EV_ABS
|
from evdev.ecodes import EV_KEY, EV_ABS, EV_REL
|
||||||
|
|
||||||
from keymapper.logger import logger
|
from keymapper.logger import logger
|
||||||
from keymapper.getdevices import get_devices
|
from keymapper.getdevices import get_devices
|
||||||
@ -103,7 +103,7 @@ class KeycodeInjector:
|
|||||||
self._msg_pipe = multiprocessing.Pipe()
|
self._msg_pipe = multiprocessing.Pipe()
|
||||||
|
|
||||||
# some EV_ABS mapping stuff
|
# some EV_ABS mapping stuff
|
||||||
self.abs_state = [0, 0]
|
self.abs_state = [0, 0, 0, 0]
|
||||||
|
|
||||||
def start_injecting(self):
|
def start_injecting(self):
|
||||||
"""Start injecting keycodes."""
|
"""Start injecting keycodes."""
|
||||||
@ -204,7 +204,7 @@ class KeycodeInjector:
|
|||||||
# those are the requirements to recognize it as mouse
|
# those are the requirements to recognize it as mouse
|
||||||
# on my system. REL_X and REL_Y are of course required to
|
# on my system. REL_X and REL_Y are of course required to
|
||||||
# accept the events that the mouse-movement-mapper writes.
|
# accept the events that the mouse-movement-mapper writes.
|
||||||
capabilities[ecodes.EV_REL] = [
|
capabilities[EV_REL] = [
|
||||||
evdev.ecodes.REL_X,
|
evdev.ecodes.REL_X,
|
||||||
evdev.ecodes.REL_Y,
|
evdev.ecodes.REL_Y,
|
||||||
evdev.ecodes.REL_WHEEL,
|
evdev.ecodes.REL_WHEEL,
|
||||||
@ -352,8 +352,12 @@ class KeycodeInjector:
|
|||||||
if abs_to_rel and event.type == EV_ABS and event.code in JOYSTICK:
|
if abs_to_rel and event.type == EV_ABS and event.code in JOYSTICK:
|
||||||
if event.code == evdev.ecodes.ABS_X:
|
if event.code == evdev.ecodes.ABS_X:
|
||||||
self.abs_state[0] = event.value
|
self.abs_state[0] = event.value
|
||||||
if event.code == evdev.ecodes.ABS_Y:
|
elif event.code == evdev.ecodes.ABS_Y:
|
||||||
self.abs_state[1] = event.value
|
self.abs_state[1] = event.value
|
||||||
|
elif event.code == evdev.ecodes.ABS_RX:
|
||||||
|
self.abs_state[2] = event.value
|
||||||
|
elif event.code == evdev.ecodes.ABS_RY:
|
||||||
|
self.abs_state[3] = event.value
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if should_map_event_as_btn(event.type, event.code):
|
if should_map_event_as_btn(event.type, event.code):
|
||||||
|
Loading…
Reference in New Issue
Block a user