diff --git a/tests/test_tray.py b/tests/test_tray.py index 8e257da..80c6c85 100644 --- a/tests/test_tray.py +++ b/tests/test_tray.py @@ -375,3 +375,41 @@ class TestRecordHotkeyEvdev: record_hotkey(lambda n, c: results.append((n, c)), cancel) assert results == [("KEY_F12", False)] + + def test_skips_unknown_keycodes(self): + import threading + from unittest.mock import MagicMock, patch + + unknown_event = MagicMock() + unknown_event.type = 1 # EV_KEY + unknown_event.code = 9999 # unbekannter Keycode + unknown_event.value = 1 # Keydown + + known_event = MagicMock() + known_event.type = 1 # EV_KEY + known_event.code = 88 # KEY_F12 + known_event.value = 1 # Keydown + + fake_device = MagicMock() + fake_device.fd = 42 + fake_device.read.return_value = iter([unknown_event, known_event]) + fake_device.close = MagicMock() + + cancel = threading.Event() + results: list[tuple[str, bool]] = [] + + with patch( + "whisper_local.tray._hotkey_record_evdev.find_all_keyboards", + return_value=[fake_device], + ), patch( + "whisper_local.tray._hotkey_record_evdev.selectors.DefaultSelector" + ) as mock_sel_cls: + mock_sel = MagicMock() + mock_sel_cls.return_value = mock_sel + sel_key = MagicMock() + sel_key.data = fake_device + mock_sel.select.return_value = [(sel_key, None)] + from whisper_local.tray._hotkey_record_evdev import record_hotkey + record_hotkey(lambda n, c: results.append((n, c)), cancel) + + assert results == [("KEY_F12", False)] diff --git a/whisper_local/tray/_hotkey_record_evdev.py b/whisper_local/tray/_hotkey_record_evdev.py index bff99fb..f24ee5a 100644 --- a/whisper_local/tray/_hotkey_record_evdev.py +++ b/whisper_local/tray/_hotkey_record_evdev.py @@ -11,16 +11,25 @@ from evdev import InputDevice, ecodes def find_all_keyboards() -> list[InputDevice]: """Gibt alle Input-Devices zurück, die EV_KEY-Events liefern können.""" keyboards: list[InputDevice] = [] - for path in evdev.list_devices(): - try: - device = InputDevice(path) - except (PermissionError, OSError): - continue - capabilities = device.capabilities() - if ecodes.EV_KEY in capabilities: - keyboards.append(device) - else: - device.close() + try: + for path in evdev.list_devices(): + try: + device = InputDevice(path) + except (PermissionError, OSError): + continue + try: + capabilities = device.capabilities() + except OSError: + device.close() + continue + if ecodes.EV_KEY in capabilities: + keyboards.append(device) + else: + device.close() + except BaseException: + for dev in keyboards: + dev.close() + raise return keyboards @@ -58,8 +67,10 @@ def record_hotkey( dev: InputDevice = key.data for event in dev.read(): if event.type == ecodes.EV_KEY and event.value == 1: - captured = _keycode_to_name(event.code) - break + name = _keycode_to_name(event.code) + if name: + captured = name + break if captured: break