diff --git a/keymapper/getdevices.py b/keymapper/getdevices.py index fe1ff5f2..dff7d63d 100644 --- a/keymapper/getdevices.py +++ b/keymapper/getdevices.py @@ -23,7 +23,9 @@ import multiprocessing +import threading import time +import asyncio import evdev @@ -33,14 +35,12 @@ from keymapper.logger import logger _devices = None -class _GetDevicesProcess(multiprocessing.Process): +class _GetDevices(threading.Thread): """Process to get the devices that can be worked with. Since InputDevice destructors take quite some time, do this asynchronously so that they can take as much time as they want without - slowing down the initialization. To avoid evdevs asyncio stuff spamming - errors, do this with multiprocessing and not multithreading. - TODO to threading, make eventloop + slowing down the initialization. """ def __init__(self, pipe): """Construct the process. @@ -55,6 +55,9 @@ class _GetDevicesProcess(multiprocessing.Process): def run(self): """Do what get_devices describes.""" + # evdev needs asyncio to work + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) logger.debug('Discovering device paths') devices = [evdev.InputDevice(path) for path in evdev.list_devices()] @@ -62,6 +65,9 @@ class _GetDevicesProcess(multiprocessing.Process): # "Logitech USB Keyboard" and "Logitech USB Keyboard Consumer Control" grouped = {} for device in devices: + if device.name == 'Power Button': + continue + # only keyboard devices # https://www.kernel.org/doc/html/latest/input/event-codes.html capabilities = device.capabilities().keys() @@ -122,7 +128,7 @@ def get_devices(include_keymapper=False): global _devices if _devices is None: pipe = multiprocessing.Pipe() - _GetDevicesProcess(pipe[1]).start() + _GetDevices(pipe[1]).start() # block until devices are available _devices = pipe[0].recv() if len(_devices) == 0: diff --git a/tests/test.py b/tests/test.py index 645e3a5d..20013c70 100644 --- a/tests/test.py +++ b/tests/test.py @@ -70,12 +70,17 @@ fixtures = { 'name': 'device 2' }, - # something that is completely ignored + # devices that are completely ignored '/dev/input/event30': { 'capabilities': {evdev.ecodes.EV_SYN: []}, 'phys': 'usb-0000:03:00.0-3/input1', 'name': 'device 3' }, + '/dev/input/event31': { + 'capabilities': {evdev.ecodes.EV_SYN: []}, + 'phys': 'usb-0000:03:00.0-4/input1', + 'name': 'Power Button' + }, # key-mapper devices are not displayed in the ui, some instance # of key-mapper started injecting apparently. diff --git a/tests/testcases/getdevices.py b/tests/testcases/getdevices.py index cd5774ef..2df94d1e 100644 --- a/tests/testcases/getdevices.py +++ b/tests/testcases/getdevices.py @@ -21,7 +21,7 @@ import unittest -from keymapper.getdevices import _GetDevicesProcess, get_devices +from keymapper.getdevices import _GetDevices, get_devices class FakePipe: @@ -36,7 +36,7 @@ class TestGetDevices(unittest.TestCase): # don't actually start the process, just use the `run` function. # otherwise the coverage tool can't keep track. pipe = FakePipe() - _GetDevicesProcess(pipe).run() + _GetDevices(pipe).run() self.assertDictEqual(pipe.devices, { 'device 1': { 'paths': [