diff --git a/inputremapper/injection/macros/tasks/mouse.py b/inputremapper/injection/macros/tasks/mouse.py index 537e6fec..1f515c3d 100644 --- a/inputremapper/injection/macros/tasks/mouse.py +++ b/inputremapper/injection/macros/tasks/mouse.py @@ -20,14 +20,17 @@ from __future__ import annotations -from evdev._ecodes import REL_Y, REL_X +import asyncio +from typing import Union + +from evdev._ecodes import REL_Y, REL_X, EV_REL from inputremapper.injection.macros.argument import ArgumentConfig from inputremapper.injection.macros.macro import InjectEventCallback -from inputremapper.injection.macros.tasks.mouse_xy import MouseXYTask +from inputremapper.injection.macros.task import Task -class MouseTask(MouseXYTask): +class MouseTask(Task): """Move the mouse cursor.""" argument_configs = [ @@ -67,3 +70,33 @@ async def run(self, callback: InjectEventCallback) -> None: acceleration, callback, ) + + async def axis( + self, + code: int, + speed: Union[int, float], + fractional_acceleration: Union[int, float], + callback: InjectEventCallback, + ) -> None: + acceleration = speed * fractional_acceleration + direction = -1 if speed < 0 else 1 + current_speed = 0.0 + displacement_accumulator = 0.0 + displacement = 0 + if not acceleration: + displacement = speed + + while self.is_holding(): + # Cursors can only move by integers. To get smooth acceleration for + # small acceleration values, the cursor needs to move by a pixel every + # few iterations. This can be achieved by remembering the decimal + # places that were cast away, and using them for the next iteration. + if acceleration and abs(current_speed) < abs(speed): + current_speed += acceleration + current_speed = direction * min(abs(current_speed), abs(speed)) + displacement_accumulator += current_speed + displacement = int(displacement_accumulator) + displacement_accumulator -= displacement + + callback(EV_REL, code, displacement) + await asyncio.sleep(1 / self.mapping.rel_rate) diff --git a/inputremapper/injection/macros/tasks/mouse_xy.py b/inputremapper/injection/macros/tasks/mouse_xy.py index 3205376d..0b541177 100644 --- a/inputremapper/injection/macros/tasks/mouse_xy.py +++ b/inputremapper/injection/macros/tasks/mouse_xy.py @@ -21,17 +21,15 @@ from __future__ import annotations import asyncio -from typing import Union from evdev._ecodes import REL_Y, REL_X -from evdev.ecodes import EV_REL from inputremapper.injection.macros.argument import ArgumentConfig from inputremapper.injection.macros.macro import InjectEventCallback -from inputremapper.injection.macros.task import Task +from inputremapper.injection.macros.tasks.mouse import MouseTask -class MouseXYTask(Task): +class MouseXYTask(MouseTask): """Move the mouse cursor.""" argument_configs = [ @@ -61,33 +59,3 @@ async def run(self, callback: InjectEventCallback) -> None: self.axis(REL_X, x, acceleration, callback), self.axis(REL_Y, y, acceleration, callback), ) - - async def axis( - self, - code: int, - speed: Union[int, float], - fractional_acceleration: Union[int, float], - callback: InjectEventCallback, - ) -> None: - acceleration = speed * fractional_acceleration - direction = -1 if speed < 0 else 1 - current_speed = 0.0 - displacement_accumulator = 0.0 - displacement = 0 - if not acceleration: - displacement = speed - - while self.is_holding(): - # Cursors can only move by integers. To get smooth acceleration for - # small acceleration values, the cursor needs to move by a pixel every - # few iterations. This can be achieved by remembering the decimal - # places that were cast away, and using them for the next iteration. - if acceleration and abs(current_speed) < abs(speed): - current_speed += acceleration - current_speed = direction * min(abs(current_speed), abs(speed)) - displacement_accumulator += current_speed - displacement = int(displacement_accumulator) - displacement_accumulator -= displacement - - callback(EV_REL, code, displacement) - await asyncio.sleep(1 / self.mapping.rel_rate)