diff --git a/keymapper/config.py b/keymapper/config.py index f98d8205..9c20d92e 100644 --- a/keymapper/config.py +++ b/keymapper/config.py @@ -35,8 +35,7 @@ CONFIG_PATH = os.path.join(CONFIG, 'config') # an empty config with basic expected substructures INITIAL_CONFIG = { - 'autoload': {}, - 'map_EV_REL_devices': True + 'autoload': {} } @@ -53,25 +52,6 @@ class _Config: """get tuples of (device, preset).""" return self._config['autoload'].items() - def set_modify_movement_devices(self, active): - """Set if devices that control movements should also be mapped. - - This causes many movements event to be passed through python code, - and if this ever seems to affect the responsiveness of mouse movements, - it can be disabled. This is just an optional precaution. Disabling this - may make mapping some keys of the device impossible. - """ - self._config['map_EV_REL_devices'] = active - - def may_modify_movement_devices(self): - """Get if devices that control movements may be modified as well. - - Since movement events happen quite often and fast, I'd like to - add the option to disabling mapping those if it affects their - performance. TODO figure out which devices to inject to instead? - """ - return self._config['map_EV_REL_devices'] - def load_config(self): """Load the config from the file system.""" if not os.path.exists(CONFIG_PATH): diff --git a/keymapper/getdevices.py b/keymapper/getdevices.py index f1629188..6bf16d8c 100644 --- a/keymapper/getdevices.py +++ b/keymapper/getdevices.py @@ -64,24 +64,16 @@ class _GetDevicesProcess(multiprocessing.Process): # "Logitech USB Keyboard" and "Logitech USB Keyboard Consumer Control" grouped = {} for device in devices: + if device.phys.startswith('key-mapper'): + # injector device, not really periphery + continue + # only keyboard devices # https://www.kernel.org/doc/html/latest/input/event-codes.html capabilities = device.capabilities().keys() if evdev.ecodes.EV_KEY not in capabilities: continue - if ( - not config.may_modify_movement_devices() - and evdev.ecodes.EV_REL in capabilities - ): - # TODO add checkbox to automatically load - # a preset on login - logger.debug( - 'Skipping %s to avoid impairing mouse movement', - device.path - ) - continue - usb = device.phys.split('/')[0] if grouped.get(usb) is None: grouped[usb] = [] @@ -117,7 +109,7 @@ def refresh_devices(): return get_devices() -def get_devices(include_keymapper=False): +def get_devices(): """Group devices and get relevant infos per group. Returns a list containing mappings of @@ -128,6 +120,10 @@ def get_devices(include_keymapper=False): paths is a list of files in /dev/input that belong to the devices. They are grouped by usb port. + + Since this needs to do some stuff with /dev and spawn processes the + result is cached. Use refresh_devices if you need up to date + devices. """ global _devices if _devices is None: @@ -141,13 +137,4 @@ def get_devices(include_keymapper=False): names = [f'"{name}"' for name in _devices] logger.info('Found %s', ', '.join(names)) - # filter the result - result = {} - for device in _devices.keys(): - if include_keymapper and device.startswith('key-mapper'): - result[device] = _devices[device] - continue - - result[device] = _devices[device] - - return result + return _devices diff --git a/keymapper/gtk/window.py b/keymapper/gtk/window.py index f7f81ef0..c35e9fca 100755 --- a/keymapper/gtk/window.py +++ b/keymapper/gtk/window.py @@ -226,6 +226,9 @@ class Window: CTX_APPLY, f'Applied the system default' ) + # restart reading because after injecting the device landscape + # changes a bit + keycode_reader.start_reading(self.selected_device) def on_save_preset_clicked(self, button): """Save changes to a preset to the file system.""" @@ -281,6 +284,10 @@ class Window: f'Could not grab device "{self.selected_device}"' ) + # restart reading because after injecting the device landscape + # changes a bit + keycode_reader.start_reading(self.selected_device) + def on_select_device(self, dropdown): """List all presets, create one if none exist yet.""" if dropdown.get_active_id() == self.selected_device: diff --git a/keymapper/injector.py b/keymapper/injector.py index f20e424d..0da7bfe7 100644 --- a/keymapper/injector.py +++ b/keymapper/injector.py @@ -264,9 +264,6 @@ class KeycodeInjector: if len(self.processes) == 0: raise OSError('Could not grab any device') - # key-mapper devices were added, freshly scan /dev/input - refresh_devices() - @ensure_numlock def stop_injecting(self): """Stop injecting keycodes.""" @@ -278,5 +275,3 @@ class KeycodeInjector: if process.is_alive(): process.terminate() self.processes[i] = None - - refresh_devices() diff --git a/keymapper/reader.py b/keymapper/reader.py index a915c4ff..419bf570 100644 --- a/keymapper/reader.py +++ b/keymapper/reader.py @@ -25,7 +25,7 @@ import evdev from keymapper.logger import logger -from keymapper.getdevices import get_devices +from keymapper.getdevices import get_devices, refresh_devices class _KeycodeReader: @@ -50,25 +50,22 @@ class _KeycodeReader: If read is called without prior start_reading, no keycodes will be available. - - Parameters - ---------- - device : string - The name of the device. """ - groups = get_devices(include_keymapper=True) - for name, group in groups.items(): + # make sure this sees up to date devices + refresh_devices() + + self.virtual_devices = [] + + for name, group in get_devices().items(): # also find stuff like "key-mapper {device}" if device not in name: - return - - paths = group['paths'] + continue # Watch over each one of the potentially multiple devices per # hardware - self.virtual_devices = [ + self.virtual_devices += [ evdev.InputDevice(path) - for path in paths + for path in group['paths'] ] logger.debug( diff --git a/tests/test.py b/tests/test.py index 1ea3c5e1..6c497956 100644 --- a/tests/test.py +++ b/tests/test.py @@ -48,7 +48,7 @@ fixtures = { 'name': 'device 1 foo' }, '/dev/input/event10': { - 'capabilities': {evdev.ecodes.EV_KEY: []}, + 'capabilities': {evdev.ecodes.EV_KEY: list(evdev.ecodes.keys.keys())}, 'phys': 'usb-0000:03:00.0-1/input3', 'name': 'device 1' }, @@ -65,7 +65,7 @@ fixtures = { # device 2 '/dev/input/event20': { - 'capabilities': {evdev.ecodes.EV_KEY: []}, + 'capabilities': {evdev.ecodes.EV_KEY: list(evdev.ecodes.keys.keys())}, 'phys': 'usb-0000:03:00.0-2/input1', 'name': 'device 2' }, @@ -77,10 +77,10 @@ fixtures = { 'name': 'device 3' }, - # key-mapper devices are also ignored, another instance of key-mapper + # key-mapper devices are also ignored, some instance of key-mapper # started injecting apparently. '/dev/input/event40': { - 'capabilities': {evdev.ecodes.EV_KEY: []}, + 'capabilities': {evdev.ecodes.EV_KEY: list(evdev.ecodes.keys.keys())}, 'phys': 'key-mapper/input1', 'name': 'key-mapper device 2' }, @@ -170,6 +170,7 @@ def patch_evdev(): class UInput: def __init__(self, *args, **kwargs): self.fd = 0 + self.device = InputDevice('/dev/input/event40') pass def write(self, type, code, value): diff --git a/tests/testcases/config.py b/tests/testcases/config.py index ac1ab5e8..7f3cf4e5 100644 --- a/tests/testcases/config.py +++ b/tests/testcases/config.py @@ -48,11 +48,9 @@ class TestConfig(unittest.TestCase): def test_save_load(self): config.set_autoload_preset('d1', 'a') config.set_autoload_preset('d2', 'b') - config.set_modify_movement_devices(True) config.save_config() # ignored after load - config.set_modify_movement_devices(False) config.set_autoload_preset('d3', 'c') config.load_config() @@ -60,7 +58,6 @@ class TestConfig(unittest.TestCase): list(config.iterate_autoload_presets()), [('d1', 'a'), ('d2', 'b')] ) - self.assertTrue(config.may_modify_movement_devices()) if __name__ == "__main__": diff --git a/tests/testcases/getdevices.py b/tests/testcases/getdevices.py index 1c36c789..62572de5 100644 --- a/tests/testcases/getdevices.py +++ b/tests/testcases/getdevices.py @@ -22,7 +22,6 @@ import unittest from keymapper.getdevices import _GetDevicesProcess -from keymapper.config import config class FakePipe: @@ -57,29 +56,6 @@ class TestGetDevices(unittest.TestCase): } }) - def test_map_movement_devices(self): - pipe = FakePipe() - config.set_modify_movement_devices(False) - _GetDevicesProcess(pipe).run() - self.assertDictEqual(pipe.devices, { - 'device 1': { - 'paths': [ - '/dev/input/event11', - '/dev/input/event10', - '/dev/input/event13' - ], - 'devices': [ - 'device 1 foo', - 'device 1', - 'device 1' - ] - }, - 'device 2': { - 'paths': ['/dev/input/event20'], - 'devices': ['device 2'] - } - }) - if __name__ == "__main__": unittest.main()