mirror of
https://github.com/DeeJanuz/frametop.git
synced 2026-10-06 01:00:06 +02:00
Input relay: release keys the desktop has down that no keyboard holds
After a gaze calibration, Meta stayed down in KWin: typing opened the overview, and clicks on the desktop did other things. A key can be left down there when its device vanishes with it held (release_held only let go of it on the relay's own devices; the Z3's keyboard dropped out twice right then) or a release goes astray. The relay now remembers which keys it told ft-screens went down, and once a second releases any no device holds (EVIOCGKEY), and the key combinations forget a Meta or modifier no device holds. A relay that starts releases the modifiers on the desktop, for keys an earlier one left down. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
da3e3d66a7
commit
2ae10a3b65
1 file changed
+38
-1
+38
-1
@@ -790,13 +790,16 @@ def main():
|
||||
return True
|
||||
|
||||
|
||||
screens_down = set() # keys the desktop was told went down and not yet up (see reconcile_desktop_keys)
|
||||
|
||||
def to_screens(code, value):
|
||||
"""A key for the desktop screens (ft-screens decides whether it types)."""
|
||||
if value in (0, 1) and code < BTN_MISC:
|
||||
try:
|
||||
screens_sock.sendto(f"key {code} {value}".encode(), SCREENS)
|
||||
except OSError:
|
||||
pass # ft-screens not running
|
||||
return # ft-screens not running
|
||||
(screens_down.add if value else screens_down.discard)(code)
|
||||
nodes = {} # fd -> Node
|
||||
# Nodes already probed (rejected or open): path -> inode. A device that disconnects and
|
||||
# reconnects between two scans often gets the same event numbers back, so the path alone
|
||||
@@ -878,6 +881,35 @@ def main():
|
||||
mouse.sync()
|
||||
keyboard.sync()
|
||||
|
||||
def physically_down():
|
||||
"""The keys down on every device read here, as the kernel has them (EVIOCGKEY)."""
|
||||
down = set()
|
||||
for node in nodes.values():
|
||||
buf = bytearray((KEY_MAX + 8) // 8)
|
||||
try:
|
||||
fcntl.ioctl(node.fd, EVIOCGKEY, buf)
|
||||
except OSError:
|
||||
continue
|
||||
down.update(i * 8 + bit for i, b in enumerate(buf) if b for bit in range(8) if b >> bit & 1)
|
||||
return down
|
||||
|
||||
def reconcile_desktop_keys():
|
||||
"""A key the desktop has down that no device holds comes up there, and the key
|
||||
combinations forget a Meta or modifier no device holds. A key can be left down when
|
||||
its device vanishes with it held (release_held only lets go of it here) or a release
|
||||
goes astray: on 2026-10-01, after a calibration, Meta stayed down in KWin, so typing
|
||||
opened the overview and clicks on the desktop did other things."""
|
||||
if not screens_down and not held_meta and not held_modifiers:
|
||||
return
|
||||
down = physically_down()
|
||||
for code in sorted(screens_down - down):
|
||||
to_screens(code, 0)
|
||||
log(f"key {code} released on the desktop: no keyboard holds it")
|
||||
for code in [c for c in held_meta if c not in down]:
|
||||
held_meta.discard(code)
|
||||
meta_hidden.discard(code)
|
||||
held_modifiers.intersection_update({MODIFIERS[c] for c in down if c in MODIFIERS})
|
||||
|
||||
def keys_down(node):
|
||||
buf = bytearray((KEY_MAX + 8) // 8)
|
||||
try:
|
||||
@@ -1000,11 +1032,16 @@ def main():
|
||||
|
||||
vr_bind(time.monotonic()) # a helper that's already running keeps its buttons in step
|
||||
waiting = False # a keyboard's grab waits for its keys to come up
|
||||
# A relay that went away with a key down left it down on the desktop, where this one
|
||||
# never sent it: modifiers come up there now (a release of a key that isn't down is nothing).
|
||||
for code in sorted(MODIFIERS):
|
||||
to_screens(code, 0)
|
||||
while True:
|
||||
now = time.monotonic()
|
||||
pointer = state["pointer"]
|
||||
if now >= next_scan:
|
||||
next_scan = now + 1.0
|
||||
reconcile_desktop_keys()
|
||||
current = {}
|
||||
for name in os.listdir("/dev/input"):
|
||||
if name.startswith("event"):
|
||||
|
||||
Reference in new issue
Block a user