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

Instructing python-evdev upgrade #346

Merged
merged 11 commits into from
Mar 18, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ input-remapper is now part of [Debian Unstable](https://packages.debian.org/sid/

##### pip

Dependencies from your distros repo: `python3-evdev`, `gtksourceview4`, `python3-devel`, `python3-pydantic`
Dependencies: `python3-evdev` (>=1.3.0), `gtksourceview4`, `python3-devel`, `python3-pydantic`

```bash
sudo pip uninstall key-mapper
Expand Down
10 changes: 9 additions & 1 deletion inputremapper/gui/user_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
from inputremapper.event_combination import EventCombination
from inputremapper.gui.reader import reader
from inputremapper.gui.helper import is_helper_running
from inputremapper.injection.injector import RUNNING, FAILED, NO_GRAB
from inputremapper.injection.injector import RUNNING, FAILED, NO_GRAB, UPGRADE_EVDEV
from inputremapper.daemon import Daemon
from inputremapper.configs.global_config import global_config
from inputremapper.injection.macros.parse import is_this_a_macro, parse
Expand Down Expand Up @@ -629,6 +629,14 @@ def show_injection_result(self):
)
return False

if state == UPGRADE_EVDEV:
self.show_status(
CTX_ERROR,
"Upgrade python-evdev",
"Your python-evdev version is too old.",
)
return False

# keep the timeout running until a relevant state is found
return True

Expand Down
47 changes: 22 additions & 25 deletions inputremapper/injection/injector.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"""Keeps injecting keycodes in the background based on the preset."""

import os
import sys
import asyncio
import time
import multiprocessing
Expand All @@ -48,6 +49,7 @@
# messages
CLOSE = 0
OK = 1
UPGRADE_EVDEV = 7

# states
UNKNOWN = -1
Expand Down Expand Up @@ -80,18 +82,6 @@ def get_udev_name(name: str, suffix: str) -> str:
return name


def create_uinput(*args, **kwargs):
"""Safely create an UInput, compatible with various versions of evdev."""
try:
return evdev.UInput(*args, **kwargs)
except TypeError as e:
if "input_props" in str(e):
del kwargs["input_props"]
return evdev.UInput(*args, **kwargs)

raise e


class Injector(multiprocessing.Process):
"""Initializes, starts and stops injections.

Expand Down Expand Up @@ -340,19 +330,26 @@ def run(self) -> None:
# copy as much information as possible, because libinput uses the extra
# information to enable certain features like "Disable touchpad while
# typing"
forward_to = create_uinput(
name=get_udev_name(source.name, "forwarded"),
events=self._copy_capabilities(source),
# phys=source.phys, # this leads to confusion. the appearance of an uinput with this "phys" property
# causes the udev rule to autoload for the original device, overwriting our previous attempts at
# starting an injection.
vendor=source.info.vendor,
product=source.info.product,
version=source.info.version,
bustype=source.info.bustype,
# input_props has been missing in one case
input_props=getattr(source, "input_props", lambda: None)(),
)
try:
forward_to = evdev.UInput(
name=get_udev_name(source.name, "forwarded"),
events=self._copy_capabilities(source),
# phys=source.phys, # this leads to confusion. the appearance of an uinput with this "phys"
# property causes the udev rule to autoload for the original device, overwriting our previous
# attempts at starting an injection.
vendor=source.info.vendor,
product=source.info.product,
version=source.info.version,
bustype=source.info.bustype,
input_props=source.input_props(),
)
except TypeError as e:
if "input_props" in str(e):
logger.error('Please upgrade your python-evdev version. Exiting')
self._msg_pipe[0].send(UPGRADE_EVDEV)
sezanzeb marked this conversation as resolved.
Show resolved Hide resolved
sys.exit(12)

raise e

# actually doing things
consumer_control = ConsumerControl(self.context, source, forward_to)
Expand Down
21 changes: 0 additions & 21 deletions tests/unit/test_injector.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,27 +129,6 @@ def find_joystick_to_mouse(self):
if isinstance(consumer, JoystickToMouse)
][0]

def test_create_uinput(self):
# can create an uinput with an input_props argument,
# which is ignored if it fails
def patch(
events=None,
name="py-evdev-uinput",
vendor=0x1,
product=0x1,
version=0x1,
bustype=0x3,
devnode="/dev/uinput",
phys="py-evdev-uinput",
):
# act like some outdated python-evdev version or something that doesn't
# support input_props
pass

with mock.patch.object(evdev, "UInput", patch):
# should not raise an error
create_uinput(input_props=[])

def test_grab(self):
# path is from the fixtures
path = "/dev/input/event10"
Expand Down