fix: listen on all matching input devices, not just the first keyboard
This commit is contained in:
+24
-14
@@ -13,18 +13,22 @@ logger = logging.getLogger(__name__)
|
|||||||
AsyncCallback = Callable[[], Coroutine]
|
AsyncCallback = Callable[[], Coroutine]
|
||||||
|
|
||||||
|
|
||||||
def find_keyboard_device() -> InputDevice:
|
def find_keyboard_devices(key_name: str) -> list[InputDevice]:
|
||||||
"""Findet das erste Keyboard-Device in /dev/input/."""
|
"""Findet alle Devices die den angegebenen Key unterstützen."""
|
||||||
devices = [InputDevice(path) for path in evdev.list_devices()]
|
matches = []
|
||||||
for device in devices:
|
for path in evdev.list_devices():
|
||||||
|
device = InputDevice(path)
|
||||||
capabilities = device.capabilities(verbose=True)
|
capabilities = device.capabilities(verbose=True)
|
||||||
for (etype_name, _etype_code), events in capabilities.items():
|
for (etype_name, _etype_code), events in capabilities.items():
|
||||||
if etype_name == "EV_KEY":
|
if etype_name == "EV_KEY":
|
||||||
key_names = [name for name, _code in events]
|
key_names = [name for name, _code in events]
|
||||||
if "KEY_A" in key_names:
|
if key_name in key_names:
|
||||||
logger.info("Keyboard gefunden: %s (%s)", device.name, device.path)
|
logger.info("Device mit %s gefunden: %s (%s)", key_name, device.name, device.path)
|
||||||
return device
|
matches.append(device)
|
||||||
raise RuntimeError("Kein Keyboard-Device gefunden in /dev/input/")
|
break
|
||||||
|
if not matches:
|
||||||
|
raise RuntimeError(f"Kein Device mit {key_name} gefunden in /dev/input/")
|
||||||
|
return matches
|
||||||
|
|
||||||
|
|
||||||
class HotkeyListener:
|
class HotkeyListener:
|
||||||
@@ -43,15 +47,21 @@ class HotkeyListener:
|
|||||||
elif not key_down and self.on_release:
|
elif not key_down and self.on_release:
|
||||||
await self.on_release()
|
await self.on_release()
|
||||||
|
|
||||||
async def listen(self) -> None:
|
async def _read_device(self, device: InputDevice) -> None:
|
||||||
"""Lauscht auf evdev-Events der konfigurierten Taste."""
|
"""Liest Events von einem einzelnen Device."""
|
||||||
device = find_keyboard_device()
|
|
||||||
logger.info("Lausche auf %s auf %s", self.key_name, device.name)
|
|
||||||
async for event in device.async_read_loop():
|
async for event in device.async_read_loop():
|
||||||
if event.type == ecodes.EV_KEY and event.code == self.key_code:
|
if event.type == ecodes.EV_KEY and event.code == self.key_code:
|
||||||
if event.value == 1: # Key down
|
if event.value == 1: # Key down
|
||||||
logger.debug("%s gedrückt", self.key_name)
|
logger.debug("%s gedrückt (via %s)", self.key_name, device.path)
|
||||||
await self._handle_key_event(key_down=True)
|
await self._handle_key_event(key_down=True)
|
||||||
elif event.value == 0: # Key up
|
elif event.value == 0: # Key up
|
||||||
logger.debug("%s losgelassen", self.key_name)
|
logger.debug("%s losgelassen (via %s)", self.key_name, device.path)
|
||||||
await self._handle_key_event(key_down=False)
|
await self._handle_key_event(key_down=False)
|
||||||
|
|
||||||
|
async def listen(self) -> None:
|
||||||
|
"""Lauscht auf evdev-Events der konfigurierten Taste auf allen passenden Devices."""
|
||||||
|
devices = find_keyboard_devices(self.key_name)
|
||||||
|
for dev in devices:
|
||||||
|
logger.info("Lausche auf %s auf %s (%s)", self.key_name, dev.name, dev.path)
|
||||||
|
tasks = [asyncio.create_task(self._read_device(dev)) for dev in devices]
|
||||||
|
await asyncio.gather(*tasks)
|
||||||
|
|||||||
Reference in New Issue
Block a user