Another shot at squishing this bug.

This commit is contained in:
Storm Dragon
2026-05-12 18:30:23 -04:00
parent fa63ecadbe
commit 5dccdd27c4
3 changed files with 80 additions and 13 deletions
+1 -1
View File
@@ -5,4 +5,4 @@
# By Chrys, Storm Dragon, and contributors.
version = "2026.05.12"
code_name = "master"
code_name = "testing"
@@ -157,6 +157,7 @@ class driver(inputDriver):
self.interesting_keys = set()
self.fenrir_keys = set()
self.failed_grabs = 0
self.modifier_state = 0
def initialize(self, environment):
self.env = environment
@@ -188,6 +189,7 @@ class driver(inputDriver):
)
)
self.num_lock_mask = self.find_num_lock_mask()
self.refresh_modifier_state()
self.refresh_interesting_keys()
self.refresh_grabs(force=True)
self.env["runtime"]["ProcessManager"].add_custom_event_thread(
@@ -306,6 +308,7 @@ class driver(inputDriver):
key_name = input_event["event_name"]
if not self.should_emit_key(key_name):
return
self.update_modifier_state_from_event(input_event)
self.write_debug(
"x11Driver key event "
+ key_name
@@ -360,8 +363,41 @@ class driver(inputDriver):
"event_usec": int((event_time % 1) * 1000000),
"event_state": 1 if event.type == X.KeyPress else 0,
"event_type": event.type,
"event_raw_state": getattr(event, "state", 0),
}
def refresh_modifier_state(self):
try:
pointer = self.root.query_pointer()
self.modifier_state = getattr(pointer, "mask", 0)
except Exception:
self.modifier_state = 0
def update_modifier_state_from_event(self, input_event):
key_name = input_event["event_name"]
event_state = input_event["event_state"]
raw_state = input_event.get("event_raw_state", self.modifier_state)
self.modifier_state = raw_state
if key_name == "KEY_NUMLOCK":
self.update_lock_modifier_state(self.num_lock_mask, event_state)
elif key_name == "KEY_CAPSLOCK":
self.update_lock_modifier_state(X.LockMask, event_state)
else:
modifier_mask = self.modifier_masks.get(key_name, 0)
if modifier_mask:
if event_state == 1:
self.modifier_state |= modifier_mask
elif event_state == 0:
self.modifier_state &= ~modifier_mask
def update_lock_modifier_state(self, modifier_mask, event_state):
if not modifier_mask or event_state != 1:
return
if self.modifier_state & modifier_mask:
self.modifier_state &= ~modifier_mask
else:
self.modifier_state |= modifier_mask
def keycode_to_key_name(self, keycode, state=0):
key_names = []
for keysym_name in self.keycode_to_keysym_names(keycode):
@@ -643,15 +679,13 @@ class driver(inputDriver):
self.ungrab_all_devices()
def get_led_state(self, led=0):
try:
pointer = self.root.query_pointer()
mask = getattr(pointer, "mask", 0)
if led == 0:
return bool(self.num_lock_mask and mask & self.num_lock_mask)
return bool(
self.num_lock_mask
and self.modifier_state & self.num_lock_mask
)
if led == 1:
return bool(mask & X.LockMask)
except Exception:
pass
return bool(self.modifier_state & X.LockMask)
return False
def set_led_state(self, led_dict):
+36 -3
View File
@@ -201,16 +201,49 @@ def test_x11_optional_modifier_masks_can_exclude_numlock():
@pytest.mark.unit
def test_x11_get_led_state_reads_lock_modifiers_from_pointer_mask():
def test_x11_get_led_state_reads_cached_lock_modifiers_without_x_round_trip():
x11 = X11Driver()
x11.num_lock_mask = X.Mod2Mask
pointer = Mock(mask=X.Mod2Mask | X.LockMask)
x11.modifier_state = X.Mod2Mask | X.LockMask
x11.root = Mock()
x11.root.query_pointer.return_value = pointer
assert x11.get_led_state(0) is True
assert x11.get_led_state(1) is True
assert x11.get_led_state(2) is False
x11.root.query_pointer.assert_not_called()
@pytest.mark.unit
def test_x11_update_modifier_state_tracks_event_masks_and_lock_toggles():
x11 = X11Driver()
x11.num_lock_mask = X.Mod2Mask
x11.update_modifier_state_from_event(
{
"event_name": "KEY_KP8",
"event_state": 1,
"event_raw_state": X.Mod2Mask,
}
)
assert x11.get_led_state(0) is True
x11.update_modifier_state_from_event(
{
"event_name": "KEY_NUMLOCK",
"event_state": 1,
"event_raw_state": X.Mod2Mask,
}
)
assert x11.get_led_state(0) is False
x11.update_modifier_state_from_event(
{
"event_name": "KEY_CAPSLOCK",
"event_state": 1,
"event_raw_state": 0,
}
)
assert x11.get_led_state(1) is True
@pytest.mark.unit