properly reads keycode device for devices that are being injected into

This commit is contained in:
sezanzeb 2020-11-22 17:46:32 +01:00
parent 06a10c64b4
commit 032347f48c
7 changed files with 53 additions and 16 deletions

View File

@ -64,10 +64,6 @@ class _GetDevicesProcess(multiprocessing.Process):
# "Logitech USB Keyboard" and "Logitech USB Keyboard Consumer Control" # "Logitech USB Keyboard" and "Logitech USB Keyboard Consumer Control"
grouped = {} grouped = {}
for device in devices: for device in devices:
if device.phys.startswith('key-mapper'):
# injector device, not really periphery
continue
# only keyboard devices # only keyboard devices
# https://www.kernel.org/doc/html/latest/input/event-codes.html # https://www.kernel.org/doc/html/latest/input/event-codes.html
capabilities = device.capabilities().keys() capabilities = device.capabilities().keys()
@ -109,7 +105,7 @@ def refresh_devices():
return get_devices() return get_devices()
def get_devices(): def get_devices(include_keymapper=False):
"""Group devices and get relevant infos per group. """Group devices and get relevant infos per group.
Returns a list containing mappings of Returns a list containing mappings of
@ -137,4 +133,12 @@ def get_devices():
names = [f'"{name}"' for name in _devices] names = [f'"{name}"' for name in _devices]
logger.info('Found %s', ', '.join(names)) logger.info('Found %s', ', '.join(names))
return _devices # filter the result
result = {}
for device in _devices.keys():
if not include_keymapper and device.startswith('key-mapper'):
continue
result[device] = _devices[device]
return result

View File

@ -50,9 +50,6 @@ CTX_APPLY = 1
CTX_ERROR = 3 CTX_ERROR = 3
# TODO test on wayland
def get_selected_row_bg(): def get_selected_row_bg():
"""Get the background color that a row is going to have when selected.""" """Get the background color that a row is going to have when selected."""
# ListBoxRows can be selected, but either they are always selectable # ListBoxRows can be selected, but either they are always selectable

View File

@ -103,7 +103,6 @@ class Mapping:
def load(self, device, preset): def load(self, device, preset):
"""Load a dumped JSON from home to overwrite the mappings.""" """Load a dumped JSON from home to overwrite the mappings."""
# TODO test
path = get_config_path(device, preset) path = get_config_path(device, preset)
logger.info('Loading preset from %s', path) logger.info('Loading preset from %s', path)
@ -125,7 +124,6 @@ class Mapping:
def save(self, device, preset): def save(self, device, preset):
"""Dump as JSON into home.""" """Dump as JSON into home."""
# TODO test
path = get_config_path(device, preset) path = get_config_path(device, preset)
logger.info('Saving preset to %s', path) logger.info('Saving preset to %s', path)

View File

@ -51,12 +51,13 @@ class _KeycodeReader:
If read is called without prior start_reading, no keycodes If read is called without prior start_reading, no keycodes
will be available. will be available.
""" """
# make sure this sees up to date devices # make sure this sees up to date devices, including those created
# by key-mapper
refresh_devices() refresh_devices()
self.virtual_devices = [] self.virtual_devices = []
for name, group in get_devices().items(): for name, group in get_devices(include_keymapper=True).items():
# also find stuff like "key-mapper {device}" # also find stuff like "key-mapper {device}"
if device not in name: if device not in name:
continue continue

View File

@ -77,8 +77,8 @@ fixtures = {
'name': 'device 3' 'name': 'device 3'
}, },
# key-mapper devices are also ignored, some instance of key-mapper # key-mapper devices are not displayed in the ui, some instance
# started injecting apparently. # of key-mapper started injecting apparently.
'/dev/input/event40': { '/dev/input/event40': {
'capabilities': {evdev.ecodes.EV_KEY: list(evdev.ecodes.keys.keys())}, 'capabilities': {evdev.ecodes.EV_KEY: list(evdev.ecodes.keys.keys())},
'phys': 'key-mapper/input1', 'phys': 'key-mapper/input1',

View File

@ -21,7 +21,7 @@
import unittest import unittest
from keymapper.getdevices import _GetDevicesProcess from keymapper.getdevices import _GetDevicesProcess, get_devices
class FakePipe: class FakePipe:
@ -38,6 +38,31 @@ class TestGetDevices(unittest.TestCase):
pipe = FakePipe() pipe = FakePipe()
_GetDevicesProcess(pipe).run() _GetDevicesProcess(pipe).run()
self.assertDictEqual(pipe.devices, { 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']
},
'key-mapper device 2': {
'paths': ['/dev/input/event40'],
'devices': ['key-mapper device 2']
},
})
self.assertDictEqual(pipe.devices, get_devices(include_keymapper=True))
def test_get_devices_2(self):
self.assertDictEqual(get_devices(), {
'device 1': { 'device 1': {
'paths': [ 'paths': [
'/dev/input/event11', '/dev/input/event11',

View File

@ -60,6 +60,18 @@ class TestReader(unittest.TestCase):
] ]
self.assertIsNone(keycode_reader.read()) self.assertIsNone(keycode_reader.read())
def test_keymapper_devices(self):
# key-mapper creates devices in /dev, which are also used for
# reading since the original device is in grab-mode
keycode_reader.start_reading('device 2')
pending_events['key-mapper device 2'] = [
Event(evdev.events.EV_KEY, CODE_1, 1),
Event(evdev.events.EV_KEY, CODE_2, 1),
Event(evdev.events.EV_KEY, CODE_3, 1)
]
self.assertEqual(keycode_reader.read(), CODE_3 + 8)
self.assertIsNone(keycode_reader.read())
def test_clear(self): def test_clear(self):
keycode_reader.start_reading('device 1') keycode_reader.start_reading('device 1')
pending_events['device 1'] = [ pending_events['device 1'] = [