From 096919a2da70fd17b59dd03053486c10cc871358 Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Thu, 14 May 2026 21:45:30 -0400 Subject: [PATCH] Hopefully fixed bug where keys like super weren't being forwarded with bypass mode. --- .../inputDriver/x11Driver.py | 21 ++++++++ tests/unit/test_x11_terminal_mode.py | 52 ++++++++++++++++++- 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/src/fenrirscreenreader/inputDriver/x11Driver.py b/src/fenrirscreenreader/inputDriver/x11Driver.py index ec78a434..2f39b2be 100644 --- a/src/fenrirscreenreader/inputDriver/x11Driver.py +++ b/src/fenrirscreenreader/inputDriver/x11Driver.py @@ -368,6 +368,7 @@ class driver(inputDriver): "event_state": 1 if event.type == X.KeyPress else 0, "event_type": event.type, "event_raw_state": getattr(event, "state", 0), + "event_x_time": getattr(event, "time", X.CurrentTime), } def refresh_modifier_state(self): @@ -650,8 +651,28 @@ class driver(inputDriver): self.clear_event_buffer() def write_event_buffer(self): + if self.display: + for event in self.env["input"]["event_buffer"]: + self.replay_key_event(event) self.clear_event_buffer() + def replay_key_event(self, event): + if not isinstance(event, dict): + return + if event.get("event_type") != X.KeyPress: + return + try: + self.display.allow_events( + X.ReplayKeyboard, + event.get("event_x_time", X.CurrentTime), + ) + self.display.flush() + except Exception as e: + self.write_debug( + "x11Driver replay key event failed: " + str(e), + debug.DebugLevel.ERROR, + ) + def clear_event_buffer(self): if not self._initialized: return diff --git a/tests/unit/test_x11_terminal_mode.py b/tests/unit/test_x11_terminal_mode.py index c9fed7c2..c9233c76 100644 --- a/tests/unit/test_x11_terminal_mode.py +++ b/tests/unit/test_x11_terminal_mode.py @@ -284,16 +284,64 @@ def test_x11_parse_window_id_accepts_decimal_and_hex(): @pytest.mark.unit -def test_x11_write_event_buffer_clears_buffer(): +def test_x11_write_event_buffer_replays_grabbed_key_press(): x11 = X11Driver() x11._initialized = True - x11.env = {"input": {"event_buffer": ["KEY_KP0"]}} + x11.display = Mock() + x11.env = { + "input": { + "event_buffer": [ + { + "event_name": "KEY_LEFTMETA", + "event_state": 1, + "event_type": X.KeyPress, + "event_x_time": 1234, + } + ] + } + } x11.write_event_buffer() + x11.display.allow_events.assert_called_once_with(X.ReplayKeyboard, 1234) assert x11.env["input"]["event_buffer"] == [] +@pytest.mark.unit +def test_x11_write_event_buffer_does_not_replay_key_release(): + x11 = X11Driver() + x11._initialized = True + x11.display = Mock() + x11.env = { + "input": { + "event_buffer": [ + { + "event_name": "KEY_LEFTMETA", + "event_state": 0, + "event_type": X.KeyRelease, + "event_x_time": 1235, + } + ] + } + } + + x11.write_event_buffer() + + x11.display.allow_events.assert_not_called() + assert x11.env["input"]["event_buffer"] == [] + + +@pytest.mark.unit +def test_x11_map_event_keeps_x_event_time_for_replay(): + x11 = X11Driver() + x11.keycode_to_key_name = Mock(return_value="KEY_LEFTMETA") + event = Mock(type=X.KeyPress, detail=133, state=X.Mod4Mask, time=5678) + + input_event = x11.map_event(event) + + assert input_event["event_x_time"] == 5678 + + @pytest.mark.unit def test_x11_find_num_lock_mask_uses_modifier_mapping(): x11 = X11Driver()