Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Input event with origin #550

Merged
merged 37 commits into from
Dec 15, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
fdbe5d4
Update InputEvent to include origin and analog threshold
jonasBoss Nov 20, 2022
4738843
preset save file migration
jonasBoss Nov 20, 2022
df386bd
Merge branch 'beta' into input-event-with-origin
jonasBoss Nov 21, 2022
5b321f0
Use the InputEvent.analog_threshold field instead of value
jonasBoss Nov 22, 2022
fb1d407
Merge branch 'beta' into input-event-with-origin
jonasBoss Nov 24, 2022
56501b8
Make tests start in pycharm again
jonasBoss Nov 24, 2022
2fadc1f
Seperate InputEvent and InputConfiguration
jonasBoss Nov 24, 2022
db652a5
integration tests
jonasBoss Nov 26, 2022
3f6e81d
simplyfied InputEvent
jonasBoss Nov 26, 2022
af96ce1
move find_analog_input_event to InputCombination
jonasBoss Nov 26, 2022
53f2a49
rename InputConfiguration to InputConfig
jonasBoss Nov 26, 2022
b41bcce
move input_configuration.py to configs/input_config.py
jonasBoss Nov 26, 2022
0b88d79
simplified imports
jonasBoss Nov 26, 2022
e76c30b
rename event_combination to input_combination
jonasBoss Nov 26, 2022
705d97b
mypy
jonasBoss Dec 1, 2022
e518a05
use event origin information
jonasBoss Dec 2, 2022
0f724e4
fix reader-service and use md5 hashing
jonasBoss Dec 2, 2022
fc95635
Updated Mapping handlers
jonasBoss Dec 2, 2022
9da39c6
Updated Tests
jonasBoss Dec 2, 2022
2f168a1
Merge branch 'beta' into input-event-with-origin
jonasBoss Dec 6, 2022
11dce4c
fix test_injector
jonasBoss Dec 6, 2022
b7ca337
mypy
jonasBoss Dec 6, 2022
d67dd32
integration tests
jonasBoss Dec 7, 2022
c3b30cf
added unit tests
jonasBoss Dec 9, 2022
e5f0159
usage.md
jonasBoss Dec 10, 2022
9af4a59
refactor injector grab deviece logic
jonasBoss Dec 11, 2022
6c1d8f9
InputConfig docstring
jonasBoss Dec 11, 2022
6067285
refactor migrations._input_combination_from_string
jonasBoss Dec 11, 2022
f94e5e7
amend
jonasBoss Dec 11, 2022
61fe702
refactor temprary preset migration
jonasBoss Dec 11, 2022
5943fd0
made notify_callbacks private
jonasBoss Dec 12, 2022
925ffad
constrain origin to lowercase
jonasBoss Dec 12, 2022
7639422
tabs 'n spaces
jonasBoss Dec 12, 2022
7010955
mypy
jonasBoss Dec 12, 2022
aa3d868
mypy
jonasBoss Dec 13, 2022
699a6f8
Signal no longer inherits Message protocol
jonasBoss Dec 13, 2022
a1d1641
rename origin to origin_hash
jonasBoss Dec 14, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Updated Mapping handlers
  • Loading branch information
jonasBoss committed Dec 2, 2022
commit fc95635381a723a2f95e22d841f2ec18d3500aa4
5 changes: 4 additions & 1 deletion inputremapper/gui/messages/message_broker.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@ def publish(self, data: Message):

def signal(self, signal: MessageType):
"""Send a signal without any data payload."""
self.publish(Signal(signal))
# This is different from calling self.publish because self.get_caller()
# looks back at the current stack 3 frames
self._messages.append((Signal(signal), *self.get_caller()))
self._publish_all()

def _publish(self, data: Message, file: str, line: int):
logger.debug(
Expand Down
1 change: 0 additions & 1 deletion inputremapper/injection/injector.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,6 @@ def _find_input_device(
devices: List[evdev.InputDevice], input_config: InputConfig
) -> Optional[evdev.InputDevice]:
devices_by_hash = {get_device_hash(device): device for device in devices}
logger.debug(f"possible devices: {devices_by_hash}")

def has_type_and_code(device, type, code) -> bool:
return code in device.capabilities(absinfo=False).get(type, [])
Expand Down
10 changes: 5 additions & 5 deletions inputremapper/injection/mapping_handlers/abs_to_abs_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import evdev
from evdev.ecodes import EV_ABS

from inputremapper.configs.input_config import InputCombination
from inputremapper.configs.input_config import InputCombination, InputConfig
from inputremapper import exceptions
from inputremapper.configs.mapping import Mapping
from inputremapper.injection.global_uinputs import global_uinputs
Expand All @@ -40,7 +40,7 @@
class AbsToAbsHandler(MappingHandler):
"""Handler which transforms EV_ABS to EV_ABS events."""

_map_axis: Tuple[int, int] # the (type, code) of the axis we map
_map_axis: InputConfig # the InputConfig for the axis we map
_output_axis: Tuple[int, int] # the (type, code) of the output axis
_transform: Optional[Transformation]
_target_absinfo: evdev.AbsInfo
Expand All @@ -56,7 +56,7 @@ def __init__(
# find the input event we are supposed to map. If the input combination is
# BTN_A + ABS_X + BTN_B, then use the value of ABS_X for the transformation
assert (map_axis := combination.find_analog_input_config(type_=EV_ABS))
self._map_axis = map_axis.type_and_code
self._map_axis = map_axis

assert mapping.output_code is not None
assert mapping.output_type == EV_ABS
Expand All @@ -69,7 +69,7 @@ def __init__(
self._transform = None

def __str__(self):
name = get_evdev_constant_name(*self._map_axis)
name = get_evdev_constant_name(*self._map_axis.type_and_code)
return f'AbsToAbsHandler for "{name}" {self._map_axis} <{id(self)}>:'

def __repr__(self):
Expand All @@ -91,7 +91,7 @@ def notify(
suppress: bool = False,
) -> bool:

if event.type_and_code != self._map_axis:
if event.input_match_hash != self._map_axis.input_match_hash:
return False

if EventActions.recenter in event.actions:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def notify(
forward: evdev.UInput,
suppress: bool = False,
) -> bool:
if event.type_and_code != self._input_config.type_and_code:
if event.input_match_hash != self._input_config.input_match_hash:
return False

absinfo = {
Expand Down
10 changes: 5 additions & 5 deletions inputremapper/injection/mapping_handlers/abs_to_rel_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
REL_HWHEEL_HI_RES,
)

from inputremapper.configs.input_config import InputCombination
from inputremapper.configs.input_config import InputCombination, InputConfig
from inputremapper.configs.mapping import (
Mapping,
REL_XY_SCALING,
Expand Down Expand Up @@ -124,7 +124,7 @@ async def _run_wheel_output(self, codes: Tuple[int, int]) -> None:
class AbsToRelHandler(MappingHandler):
"""Handler which transforms an EV_ABS to EV_REL events."""

_map_axis: Tuple[int, int] # the input (type, code) of the axis we map
_map_axis: InputConfig # the InputConfig for the axis we map
_value: float # the current output value
_running: bool # if the run method is active
_stop: bool # if the run loop should return
Expand All @@ -140,7 +140,7 @@ def __init__(

# find the input event we are supposed to map
assert (map_axis := combination.find_analog_input_config(type_=EV_ABS))
self._map_axis = map_axis.type_and_code
self._map_axis = map_axis

self._value = 0
self._running = False
Expand All @@ -165,7 +165,7 @@ def __init__(
self._run = partial(_run_normal_output, self)

def __str__(self):
name = get_evdev_constant_name(*self._map_axis)
name = get_evdev_constant_name(*self._map_axis.type_and_code)
return f'AbsToRelHandler for "{name}" {self._map_axis} <{id(self)}>:'

def __repr__(self):
Expand All @@ -186,7 +186,7 @@ def notify(
forward: evdev.UInput = None,
suppress: bool = False,
) -> bool:
if event.type_and_code != self._map_axis:
if event.input_match_hash != self._map_axis.input_match_hash:
return False

if EventActions.recenter in event.actions:
Expand Down
25 changes: 14 additions & 11 deletions inputremapper/injection/mapping_handlers/axis_switch_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@
#
# You should have received a copy of the GNU General Public License
# along with input-remapper. If not, see <https://www.gnu.org/licenses/>.
from typing import Dict, Tuple
from typing import Dict, Tuple, Hashable

import evdev
from inputremapper.configs.input_config import InputConfig

from inputremapper.configs.input_config import InputCombination
from inputremapper.configs.mapping import Mapping
Expand All @@ -42,8 +43,8 @@ class AxisSwitchHandler(MappingHandler):
output.
"""

_map_axis: Tuple[int, int] # the axis we switch on or off (type and code)
_trigger_key: Tuple[Tuple[int, int]] # all events that can switch the axis
_map_axis: InputConfig # the InputConfig for the axis we switch on or off
_trigger_keys: Tuple[Hashable] # all events that can switch the axis
_active: bool # whether the axis is on or off
_last_value: int # the value of the last axis event that arrived
_axis_source: evdev.InputDevice # the cached source of the axis input events
Expand All @@ -58,13 +59,13 @@ def __init__(
):
super().__init__(combination, mapping)
trigger_keys = [
event.type_and_code
event.input_match_hash
for event in combination
if not event.defines_analog_input
]
assert len(trigger_keys) >= 1
assert (map_axis := combination.find_analog_input_config())
self._map_axis = map_axis.type_and_code
self._map_axis = map_axis
self._trigger_keys = tuple(trigger_keys)
self._active = False

Expand All @@ -73,7 +74,7 @@ def __init__(
self._forward_device = None

def __str__(self):
return f"AxisSwitchHandler for {self._map_axis} <{id(self)}>"
return f"AxisSwitchHandler for {self._map_axis.type_and_code} <{id(self)}>"

def __repr__(self):
return self.__str__()
Expand Down Expand Up @@ -104,22 +105,24 @@ def _handle_key_input(self, event: InputEvent):
event = InputEvent(
0,
0,
*self._map_axis,
*self._map_axis.type_and_code,
0,
actions=(EventActions.recenter,),
origin=self._map_axis.origin,
)
self._sub_handler.notify(event, self._axis_source, self._forward_device)
return True

if self._map_axis[0] == evdev.ecodes.EV_ABS:
if self._map_axis.type == evdev.ecodes.EV_ABS:
# send the last cached value so that the abs axis
# is at the correct position
logger.debug_key(self.mapping.input_combination, "starting axis")
event = InputEvent(
0,
0,
*self._map_axis,
*self._map_axis.type_and_code,
self._last_value,
origin=self._map_axis.origin,
)
self._sub_handler.notify(event, self._axis_source, self._forward_device)
return True
Expand All @@ -128,8 +131,8 @@ def _handle_key_input(self, event: InputEvent):

def _should_map(self, event: InputEvent):
return (
event.type_and_code in self._trigger_keys
or event.type_and_code == self._map_axis
event.input_match_hash in self._trigger_keys
or event.input_match_hash == self._map_axis.input_match_hash
)

def notify(
Expand Down
22 changes: 13 additions & 9 deletions inputremapper/injection/mapping_handlers/combination_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
# You should have received a copy of the GNU General Public License
# along with input-remapper. If not, see <https://www.gnu.org/licenses/>.

from typing import Dict, Tuple
from typing import Dict, Tuple, Hashable

import evdev
from evdev.ecodes import EV_ABS, EV_REL
Expand All @@ -36,8 +36,8 @@
class CombinationHandler(MappingHandler):
"""Keeps track of a combination and notifies a sub handler."""

# map of (event.type, event.code) -> bool , keep track of the combination state
_pressed_keys: Dict[Tuple[int, int], bool]
# map of InputEvent.input_match_hash -> bool , keep track of the combination state
_pressed_keys: Dict[Hashable, bool]
_output_state: bool # the last update we sent to a sub-handler
_sub_handler: InputEventHandler

Expand All @@ -55,7 +55,7 @@ def __init__(
# prepare a key map for all events with non-zero value
for input_config in combination:
assert not input_config.defines_analog_input
self._pressed_keys[input_config.type_and_code] = False
self._pressed_keys[input_config.input_match_hash] = False

assert len(self._pressed_keys) > 0 # no combination handler without a key

Expand All @@ -79,12 +79,11 @@ def notify(
forward: evdev.UInput,
suppress: bool = False,
) -> bool:
type_code = event.type_and_code
if type_code not in self._pressed_keys.keys():
if event.input_match_hash not in self._pressed_keys.keys():
return False # we are not responsible for the event

last_state = self.get_active()
self._pressed_keys[type_code] = event.value == 1
self._pressed_keys[event.input_match_hash] = event.value == 1

if self.get_active() == last_state or self.get_active() == self._output_state:
# nothing changed
Expand Down Expand Up @@ -136,8 +135,13 @@ def forward_release(self, forward: evdev.UInput) -> None:
"""
if len(self._pressed_keys) == 1 or not self.mapping.release_combination_keys:
return
for type_and_code in self._pressed_keys:
forward.write(*type_and_code, 0)

keys_to_release = filter(
lambda cfg: self._pressed_keys.get(cfg.input_match_hash),
self.mapping.input_combination,
)
for input_config in keys_to_release:
forward.write(*input_config.type_and_code, 0)
forward.syn()

def needs_ranking(self) -> bool:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def notify(
forward: evdev.UInput = None,
suppress: bool = False,
) -> bool:
if event.type_and_code != self._input_config.type_and_code:
if event.input_match_hash != self._input_config.input_match_hash:
return False

success = False
Expand Down
2 changes: 1 addition & 1 deletion inputremapper/injection/mapping_handlers/key_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def __repr__(self):

@property
def child(self): # used for logging
name = get_evdev_constant_name(*self._map_axis)
name = get_evdev_constant_name(*self._maps_to)
return f"maps to: {name} {self._maps_to} on {self.mapping.target_uinput}"

def notify(self, event: InputEvent, *_, **__) -> bool:
Expand Down
1 change: 0 additions & 1 deletion inputremapper/injection/mapping_handlers/macro_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ async def run_macro(self, handler: Callable):
logger.error('Macro "%s" failed: %s', self._macro.code, exception)

def notify(self, event: InputEvent, *_, **__) -> bool:

if event.value == 1:
self._active = True
self._macro.press_trigger()
Expand Down
12 changes: 6 additions & 6 deletions inputremapper/injection/mapping_handlers/rel_to_abs_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
REL_WHEEL_HI_RES,
)

from inputremapper.configs.input_config import InputCombination
from inputremapper.configs.input_config import InputCombination, InputConfig
from inputremapper import exceptions
from inputremapper.configs.mapping import (
Mapping,
Expand Down Expand Up @@ -58,7 +58,7 @@ class RelToAbsHandler(MappingHandler):
release_timeout.
"""

_map_axis: Tuple[int, int] # (type, code) of the relative movement we map
_map_axis: InputConfig # InputConfig for the relative movement we map
_output_axis: Tuple[int, int] # the (type, code) of the output axis
_transform: Transformation
_target_absinfo: evdev.AbsInfo
Expand All @@ -81,7 +81,7 @@ def __init__(
# find the input event we are supposed to map. If the input combination is
# BTN_A + REL_X + BTN_B, then use the value of REL_X for the transformation
assert (map_axis := combination.find_analog_input_config(type_=EV_REL))
self._map_axis = map_axis.type_and_code
self._map_axis = map_axis

assert mapping.output_code is not None
assert mapping.output_type == EV_ABS
Expand Down Expand Up @@ -139,10 +139,10 @@ def _observe_rate(self, event: InputEvent):

def _get_default_cutoff(self):
"""Get the cutoff value assuming the default input rate."""
if self._map_axis[1] in [REL_WHEEL, REL_HWHEEL]:
if self._map_axis.code in [REL_WHEEL, REL_HWHEEL]:
return self.mapping.rel_to_abs_input_cutoff * WHEEL_SCALING

if self._map_axis[1] in [REL_WHEEL_HI_RES, REL_HWHEEL_HI_RES]:
if self._map_axis.code in [REL_WHEEL_HI_RES, REL_HWHEEL_HI_RES]:
return self.mapping.rel_to_abs_input_cutoff * WHEEL_HI_RES_SCALING

return self.mapping.rel_to_abs_input_cutoff * REL_XY_SCALING
Expand All @@ -166,7 +166,7 @@ def notify(
) -> bool:
self._observe_rate(event)

if event.type_and_code != self._map_axis:
if event.input_match_hash != self._map_axis.input_match_hash:
return False

if EventActions.recenter in event.actions:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ async def _stage_release(
*self._input_config.type_and_code,
value=0,
actions=(EventActions.as_key,),
origin=self._input_config.origin,
)
logger.debug_key(event.event_tuple, "sending to sub_handler")
self._sub_handler.notify(event, source, forward, suppress)
Expand All @@ -103,7 +104,7 @@ def notify(
) -> bool:

assert event.type == EV_REL
if event.type_and_code != self._input_config.type_and_code:
if event.input_match_hash != self._input_config.input_match_hash:
return False

threshold = self._input_config.analog_threshold
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ def __init__(

# find the input event we are supposed to map. If the input combination is
# BTN_A + REL_X + BTN_B, then use the value of REL_X for the transformation
input_event = combination.find_analog_input_config(type_=EV_REL)
assert input_event is not None
self._input_config = input_event
input_config = combination.find_analog_input_config(type_=EV_REL)
assert input_config is not None
self._input_config = input_config

self._max_observed_input = 1

Expand Down Expand Up @@ -127,7 +127,7 @@ def child(self): # used for logging

def _should_map(self, event: InputEvent):
"""Check if this input event is relevant for this handler."""
return event.type_and_code == self._input_config.type_and_code
return event.input_match_hash == self._input_config.input_match_hash

def notify(
self,
Expand Down