tenseleyflow/hyprkvm / f3f6977

Browse files

Fix capture-side: query actual key state and send smart events

Previous fix blindly sent key-UPs for all modifiers, which broke the
case where user is still holding Super - they'd have to release and
re-press it.

Now we query the actual physical key state after ungrab:
- Arrow keys: if NOT pressed, send UP (clear stale state)
- Modifiers: if STILL pressed, send UP+DOWN (give fresh edge)

This ensures:
1. Stale arrow key state is cleared
2. Held modifiers get a fresh edge so keybindings fire
3. Released modifiers stay released
Authored by espadonne
SHA
f3f6977fc5e2d24870668562e33595ec0014cc7e
Parents
9739926
Tree
5450d83

2 changed files

StatusFile+-
M LOG.txt 359 257
M hyprkvm-daemon/src/input/evdev_grab.rs 55 27
LOG.txtmodified
@@ -1,260 +1,3 @@
1
-2026-01-04T11:35:37.652161Z DEBUG Connecting to left at 192.168.0.84:24850...
2
-2026-01-04T11:35:37.652171Z  INFO Connecting to 192.168.0.84:24850
3
-2026-01-04T11:35:37.652754Z DEBUG Failed to connect to left (192.168.0.84:24850): IO error: Connection refused (os error 111)
4
-2026-01-04T11:35:40.653765Z DEBUG Connecting to left at 192.168.0.84:24850...
5
-2026-01-04T11:35:40.653775Z  INFO Connecting to 192.168.0.84:24850
6
-2026-01-04T11:35:40.654366Z DEBUG Failed to connect to left (192.168.0.84:24850): IO error: Connection refused (os error 111)
7
-2026-01-04T11:35:41.206615Z DEBUG IPC: connection accepted
8
-2026-01-04T11:35:41.206643Z DEBUG IPC: received Move { direction: Right }
9
-2026-01-04T11:35:41.206650Z DEBUG IPC: sent to main loop, awaiting response
10
-2026-01-04T11:35:41.206657Z  INFO IPC Move Right: state=Local
11
-2026-01-04T11:35:41.206836Z  INFO   edge_check: has monitor in direction Right
12
-2026-01-04T11:35:41.206839Z  INFO IPC Move Right: at_edge=false, has_peer=false, neighbor=None
13
-2026-01-04T11:35:41.206842Z  INFO IPC Move Right: doing local movefocus r
14
-2026-01-04T11:35:41.207371Z  INFO   movefocus succeeded
15
-2026-01-04T11:35:41.207413Z DEBUG IPC: got response, sending to client
16
-2026-01-04T11:35:41.500272Z DEBUG IPC: connection accepted
17
-2026-01-04T11:35:41.500294Z DEBUG IPC: received Move { direction: Right }
18
-2026-01-04T11:35:41.500298Z DEBUG IPC: sent to main loop, awaiting response
19
-2026-01-04T11:35:41.500303Z  INFO IPC Move Right: state=Local
20
-2026-01-04T11:35:41.500422Z  INFO   edge_check: has monitor in direction Right
21
-2026-01-04T11:35:41.500426Z  INFO IPC Move Right: at_edge=false, has_peer=false, neighbor=None
22
-2026-01-04T11:35:41.500429Z  INFO IPC Move Right: doing local movefocus r
23
-2026-01-04T11:35:41.501028Z  INFO   movefocus succeeded
24
-2026-01-04T11:35:41.501037Z DEBUG IPC: got response, sending to client
25
-2026-01-04T11:35:42.039601Z DEBUG IPC: connection accepted
26
-2026-01-04T11:35:42.039623Z DEBUG IPC: received Move { direction: Right }
27
-2026-01-04T11:35:42.039627Z DEBUG IPC: sent to main loop, awaiting response
28
-2026-01-04T11:35:42.039632Z  INFO IPC Move Right: state=Local
29
-2026-01-04T11:35:42.039752Z  INFO   edge_check: has monitor in direction Right
30
-2026-01-04T11:35:42.039757Z  INFO IPC Move Right: at_edge=false, has_peer=false, neighbor=None
31
-2026-01-04T11:35:42.039759Z  INFO IPC Move Right: doing local movefocus r
32
-2026-01-04T11:35:42.040123Z  INFO   movefocus succeeded
33
-2026-01-04T11:35:42.040138Z DEBUG IPC: got response, sending to client
34
-^C2026-01-04T11:35:43.343470Z  INFO Shutting down...
35
-
36
-hyprKVM on  trunk is 📦 v0.1.0 via  v1.91.1 took 1m5s
37
-❯ nix develop --command cargo run --release -p hyprkvm-daemon -- -v daemon
38
-warning: Git tree '/home/mfwolffe/GithubOrgs/tenseleyFlow/hyprKVM' is dirty
39
-HyprKVM development shell
40
-Rust: rustc 1.92.0 (ded5c06cf 2025-12-08)
41
-
42
-Run 'cargo build' to compile
43
-    Finished `release` profile [optimized] target(s) in 0.10s
44
-     Running `target/release/hyprkvm -v daemon`
45
-2026-01-04T11:41:43.640644Z  INFO Starting HyprKVM daemon...
46
-2026-01-04T11:41:43.640710Z  INFO Machine name: nixos
47
-2026-01-04T11:41:43.640713Z  INFO Listening on port: 24850
48
-2026-01-04T11:41:43.640715Z  INFO Connecting to Hyprland...
49
-2026-01-04T11:41:43.640864Z  INFO Connected to Hyprland. Monitors: 3
50
-2026-01-04T11:41:43.640866Z  INFO   HDMI-A-1 at (4480, 0) 3840x2160
51
-2026-01-04T11:41:43.640868Z  INFO   HDMI-A-2 at (1920, 0) 2560x1440
52
-2026-01-04T11:41:43.640870Z  INFO   DP-3 at (0, 0) 1920x1080
53
-2026-01-04T11:41:43.640874Z  INFO   Network neighbor: cachyos (left) at 192.168.0.84:24850
54
-2026-01-04T11:41:43.640879Z  INFO Starting edge capture for: [Left]
55
-2026-01-04T11:41:43.640934Z  INFO Server listening on 0.0.0.0:24850
56
-2026-01-04T11:41:43.640938Z  INFO Listening for connections on 0.0.0.0:24850
57
-2026-01-04T11:41:43.640958Z DEBUG Connecting to left at 192.168.0.84:24850...
58
-2026-01-04T11:41:43.640968Z  INFO Connecting to 192.168.0.84:24850
59
-2026-01-04T11:41:43.640972Z  INFO Daemon running. Move mouse to screen edges to trigger transfer. Press Ctrl+C to stop.
60
-2026-01-04T11:41:43.641007Z  INFO IPC server listening on /run/user/1000/hyprkvm.sock
61
-2026-01-04T11:41:43.641018Z DEBUG Found input device: Keychron Keychron K8 HE at /dev/input/event2 (keys=true, rel=false)
62
-2026-01-04T11:41:43.641072Z DEBUG Bound new global [63] wl_output v4
63
-2026-01-04T11:41:43.641077Z DEBUG Bound new global [64] wl_output v4
64
-2026-01-04T11:41:43.641079Z DEBUG Bound new global [65] wl_output v4
65
-2026-01-04T11:41:43.641081Z DEBUG Bound new global [9] zxdg_output_manager_v1 v3
66
-2026-01-04T11:41:43.641087Z DEBUG Bound new global [1] wl_seat v7
67
-2026-01-04T11:41:43.641192Z DEBUG supported wl_shm format Argb8888
68
-2026-01-04T11:41:43.641197Z DEBUG supported wl_shm format Xrgb8888
69
-2026-01-04T11:41:43.641199Z DEBUG supported wl_shm format Xbgr8888
70
-2026-01-04T11:41:43.641201Z DEBUG supported wl_shm format Abgr8888
71
-2026-01-04T11:41:43.641202Z DEBUG supported wl_shm format Xrgb2101010
72
-2026-01-04T11:41:43.641204Z DEBUG supported wl_shm format Argb2101010
73
-2026-01-04T11:41:43.641206Z DEBUG supported wl_shm format Xbgr2101010
74
-2026-01-04T11:41:43.641207Z DEBUG supported wl_shm format Abgr2101010
75
-2026-01-04T11:41:43.641249Z  INFO After roundtrips: 3 outputs detected
76
-2026-01-04T11:41:43.641265Z DEBUG Multiple candidates for output 2560x1440: ["HDMI-A-1", "HDMI-A-2"]
77
-2026-01-04T11:41:43.641268Z DEBUG Multiple candidates for output 1920x1080: ["HDMI-A-1", "DP-3"]
78
-2026-01-04T11:41:43.641270Z  INFO Assigned remaining output 2560x1440 to monitor HDMI-A-1 at (4480, 0)
79
-2026-01-04T11:41:43.641272Z  INFO Assigned remaining output 1920x1080 to monitor DP-3 at (0, 0)
80
-2026-01-04T11:41:43.641274Z  INFO Creating barriers with 3 outputs:
81
-2026-01-04T11:41:43.641275Z  INFO   Output at (0, 0) size 3072x1728
82
-2026-01-04T11:41:43.641277Z  INFO   Output at (4480, 0) size 2560x1440
83
-2026-01-04T11:41:43.641278Z  INFO   Output at (0, 0) size 1920x1080
84
-2026-01-04T11:41:43.641279Z  INFO Screen bounds: (0, 0) to (7040, 1728)
85
-2026-01-04T11:41:43.641281Z  INFO   Left edge -> output at Some((0, 0, 3072, 1728))
86
-2026-01-04T11:41:43.641289Z  INFO Creating Left barrier on output Some("at (0, 0)"), size 1x1728
87
-2026-01-04T11:41:43.641389Z  INFO Edge capture running with 1 barriers
88
-2026-01-04T11:41:43.641455Z DEBUG Failed to connect to left (192.168.0.84:24850): IO error: Connection refused (os error 111)
89
-2026-01-04T11:41:43.641785Z  INFO Poll #0: state=Local, peers=[]
90
-2026-01-04T11:41:43.700610Z DEBUG Found input device: Sony Interactive Entertainment DualSense Wireless Controller at /dev/input/event16 (k
91
-2026-01-04T11:41:43.744597Z DEBUG Found input device: HP, Inc HyperX QuadCast S Consumer Control at /dev/input/event14 (keys=true, rel=true
92
-2026-01-04T11:41:43.805601Z DEBUG Found input device: HP, Inc HyperX QuadCast S Consumer Control at /dev/input/event7 (keys=true, rel=false
93
-2026-01-04T11:41:43.817611Z DEBUG Found input device: Asus WMI hotkeys at /dev/input/event6 (keys=true, rel=false)
94
-2026-01-04T11:41:43.829589Z DEBUG Found input device: Power Button at /dev/input/event5 (keys=true, rel=false)
95
-2026-01-04T11:41:43.841627Z DEBUG Found input device: Power Button at /dev/input/event4 (keys=true, rel=false)
96
-2026-01-04T11:41:43.857591Z DEBUG Found input device: Sleep Button at /dev/input/event3 (keys=true, rel=false)
97
-2026-01-04T11:41:43.872590Z  INFO Found 13 input device paths
98
-2026-01-04T11:41:43.872596Z DEBUG   /dev/input/event12
99
-2026-01-04T11:41:43.872597Z DEBUG   /dev/input/event13
100
-2026-01-04T11:41:43.872598Z DEBUG   /dev/input/event1
101
-2026-01-04T11:41:43.872599Z DEBUG   /dev/input/event0
102
-2026-01-04T11:41:43.872600Z DEBUG   /dev/input/event18
103
-2026-01-04T11:41:43.872601Z DEBUG   /dev/input/event2
104
-2026-01-04T11:41:43.872601Z DEBUG   /dev/input/event16
105
-2026-01-04T11:41:43.872602Z DEBUG   /dev/input/event14
106
-2026-01-04T11:41:43.872603Z DEBUG   /dev/input/event7
107
-2026-01-04T11:41:43.872604Z DEBUG   /dev/input/event6
108
-2026-01-04T11:41:43.872605Z DEBUG   /dev/input/event5
109
-2026-01-04T11:41:43.872606Z DEBUG   /dev/input/event4
110
-2026-01-04T11:41:43.872607Z DEBUG   /dev/input/event3
111
-2026-01-04T11:41:46.642481Z DEBUG Connecting to left at 192.168.0.84:24850...
112
-2026-01-04T11:41:46.642494Z  INFO Connecting to 192.168.0.84:24850
113
-2026-01-04T11:41:46.643022Z DEBUG Failed to connect to left (192.168.0.84:24850): IO error: Connection refused (os error 111)
114
-2026-01-04T11:41:49.643893Z DEBUG Connecting to left at 192.168.0.84:24850...
115
-2026-01-04T11:41:49.643904Z  INFO Connecting to 192.168.0.84:24850
116
-2026-01-04T11:41:49.644374Z DEBUG Failed to connect to left (192.168.0.84:24850): IO error: Connection refused (os error 111)
117
-2026-01-04T11:41:52.645426Z DEBUG Connecting to left at 192.168.0.84:24850...
118
-2026-01-04T11:41:52.645436Z  INFO Connecting to 192.168.0.84:24850
119
-2026-01-04T11:41:52.645848Z  INFO Connected to 192.168.0.84:24850
120
-2026-01-04T11:41:52.646469Z  INFO Connected to cachyos (left)
121
-2026-01-04T11:41:53.678368Z DEBUG Received from Left: Enter(EnterPayload { from_direction: Left, cursor_pos: EdgeRelative(0.340277777777777
122
-2026-01-04T11:41:53.678385Z  INFO Received Enter from Left
123
-2026-01-04T11:41:53.678388Z  INFO Receiving control from Left, cursor at (0, 735)
124
-2026-01-04T11:41:53.678392Z  INFO Positioned cursor at (0, 735)
125
-2026-01-04T11:41:53.678398Z  INFO Starting input injection from Left
126
-2026-01-04T11:41:53.685823Z  INFO Input emulator created
127
-2026-01-04T11:41:53.685851Z  INFO Sending EnterAck(EnterAckPayload { success: true, transfer_id: 1, actual_cursor_pos: Some((0, 735)), erro
128
-2026-01-04T11:41:53.687185Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 0, timestamp_us: 1767526913686379, event: Ke
129
-2026-01-04T11:41:53.687198Z DEBUG RECV KeyDown: keycode=125 (LEFTMETA)
130
-2026-01-04T11:41:53.687202Z DEBUG INJECT KEY: LEFTMETA DOWN (keycode=125, modifiers: depressed=0x0, super=false)
131
-2026-01-04T11:41:53.687212Z DEBUG INJECT MODIFIERS: depressed=0x40 (super=true)
132
-2026-01-04T11:41:53.860449Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 1, timestamp_us: 1767526913860533, event: Ke
133
-2026-01-04T11:41:53.860459Z DEBUG RECV KeyUp: keycode=106 (RIGHT)
134
-2026-01-04T11:41:53.860461Z DEBUG INJECT KEY: RIGHT UP (keycode=106, modifiers: depressed=0x40, super=true)
135
-2026-01-04T11:41:54.823493Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 2, timestamp_us: 1767526914823512, event: Ke
136
-2026-01-04T11:41:54.823504Z DEBUG RECV KeyDown: keycode=106 (RIGHT)
137
-2026-01-04T11:41:54.823508Z DEBUG INJECT KEY: RIGHT DOWN (keycode=106, modifiers: depressed=0x40, super=true)
138
-2026-01-04T11:41:54.830973Z DEBUG IPC: connection accepted
139
-2026-01-04T11:41:54.830999Z DEBUG IPC: received Move { direction: Right }
140
-2026-01-04T11:41:54.831003Z DEBUG IPC: sent to main loop, awaiting response
141
-2026-01-04T11:41:54.831009Z  INFO IPC Move Right: state=ReceivedControl { from: Left, transfer_id: 1, entered_at: Instant { tv_sec: 468699,
142
-2026-01-04T11:41:54.831135Z  INFO   edge_check: has monitor in direction Right
143
-2026-01-04T11:41:54.831139Z  INFO IPC Move Right: at_edge=false, has_peer=false, neighbor=None
144
-2026-01-04T11:41:54.831142Z  INFO IPC Move Right: doing local movefocus r
145
-2026-01-04T11:41:54.831471Z  INFO   movefocus succeeded
146
-2026-01-04T11:41:54.831480Z DEBUG IPC: got response, sending to client
147
-2026-01-04T11:41:55.040554Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 3, timestamp_us: 1767526915040621, event: Ke
148
-2026-01-04T11:41:55.040565Z DEBUG RECV KeyUp: keycode=106 (RIGHT)
149
-2026-01-04T11:41:55.040567Z DEBUG INJECT KEY: RIGHT UP (keycode=106, modifiers: depressed=0x40, super=true)
150
-2026-01-04T11:41:55.838810Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 4, timestamp_us: 1767526915838729, event: Ke
151
-2026-01-04T11:41:55.838821Z DEBUG RECV KeyDown: keycode=105 (LEFT)
152
-2026-01-04T11:41:55.838823Z DEBUG INJECT KEY: LEFT DOWN (keycode=105, modifiers: depressed=0x40, super=true)
153
-2026-01-04T11:41:55.846307Z DEBUG IPC: connection accepted
154
-2026-01-04T11:41:55.846332Z DEBUG IPC: received Move { direction: Left }
155
-2026-01-04T11:41:55.846336Z DEBUG IPC: sent to main loop, awaiting response
156
-2026-01-04T11:41:55.846340Z  INFO IPC Move Left: state=ReceivedControl { from: Left, transfer_id: 1, entered_at: Instant { tv_sec: 468699,
157
-2026-01-04T11:41:55.846529Z  INFO   edge_check: has monitor in direction Left
158
-2026-01-04T11:41:55.846534Z  INFO IPC Move Left: at_edge=false, has_peer=true, neighbor=Some("cachyos")
159
-2026-01-04T11:41:55.846541Z  INFO IPC Move Left: doing local movefocus l
160
-2026-01-04T11:41:55.847070Z  INFO   movefocus succeeded
161
-2026-01-04T11:41:55.847085Z DEBUG IPC: got response, sending to client
162
-2026-01-04T11:41:55.995833Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 5, timestamp_us: 1767526915994811, event: Ke
163
-2026-01-04T11:41:55.995844Z DEBUG RECV KeyUp: keycode=105 (LEFT)
164
-2026-01-04T11:41:55.995846Z DEBUG INJECT KEY: LEFT UP (keycode=105, modifiers: depressed=0x40, super=true)
165
-2026-01-04T11:41:56.198245Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 6, timestamp_us: 1767526916198271, event: Ke
166
-2026-01-04T11:41:56.198255Z DEBUG RECV KeyDown: keycode=105 (LEFT)
167
-2026-01-04T11:41:56.198257Z DEBUG INJECT KEY: LEFT DOWN (keycode=105, modifiers: depressed=0x40, super=true)
168
-2026-01-04T11:41:56.205673Z DEBUG IPC: connection accepted
169
-2026-01-04T11:41:56.205700Z DEBUG IPC: received Move { direction: Left }
170
-2026-01-04T11:41:56.205707Z DEBUG IPC: sent to main loop, awaiting response
171
-2026-01-04T11:41:56.206790Z  INFO IPC Move Left: state=ReceivedControl { from: Left, transfer_id: 1, entered_at: Instant { tv_sec: 468699,
172
-2026-01-04T11:41:56.206962Z  INFO   edge_check: has monitor in direction Left
173
-2026-01-04T11:41:56.206966Z  INFO IPC Move Left: at_edge=false, has_peer=true, neighbor=Some("cachyos")
174
-2026-01-04T11:41:56.206968Z  INFO IPC Move Left: doing local movefocus l
175
-2026-01-04T11:41:56.207387Z  INFO   movefocus succeeded
176
-2026-01-04T11:41:56.207398Z DEBUG IPC: got response, sending to client
177
-2026-01-04T11:41:56.362048Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 7, timestamp_us: 1767526916362058, event: Ke
178
-2026-01-04T11:41:56.362059Z DEBUG RECV KeyUp: keycode=105 (LEFT)
179
-2026-01-04T11:41:56.362060Z DEBUG INJECT KEY: LEFT UP (keycode=105, modifiers: depressed=0x40, super=true)
180
-2026-01-04T11:41:56.635121Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 8, timestamp_us: 1767526916635149, event: Ke
181
-2026-01-04T11:41:56.635133Z DEBUG RECV KeyDown: keycode=105 (LEFT)
182
-2026-01-04T11:41:56.635135Z DEBUG INJECT KEY: LEFT DOWN (keycode=105, modifiers: depressed=0x40, super=true)
183
-2026-01-04T11:41:56.643108Z DEBUG IPC: connection accepted
184
-2026-01-04T11:41:56.643131Z DEBUG IPC: received Move { direction: Left }
185
-2026-01-04T11:41:56.643136Z DEBUG IPC: sent to main loop, awaiting response
186
-2026-01-04T11:41:56.643141Z  INFO IPC Move Left: state=ReceivedControl { from: Left, transfer_id: 1, entered_at: Instant { tv_sec: 468699,
187
-2026-01-04T11:41:56.643362Z  INFO   edge_check: has monitor in direction Left
188
-2026-01-04T11:41:56.643368Z  INFO IPC Move Left: at_edge=false, has_peer=true, neighbor=Some("cachyos")
189
-2026-01-04T11:41:56.643371Z  INFO IPC Move Left: doing local movefocus l
190
-2026-01-04T11:41:56.644129Z  INFO   movefocus succeeded
191
-2026-01-04T11:41:56.644168Z DEBUG IPC: got response, sending to client
192
-2026-01-04T11:41:56.816630Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 9, timestamp_us: 1767526916816636, event: Ke
193
-2026-01-04T11:41:56.816640Z DEBUG RECV KeyUp: keycode=105 (LEFT)
194
-2026-01-04T11:41:56.816643Z DEBUG INJECT KEY: LEFT UP (keycode=105, modifiers: depressed=0x40, super=true)
195
-2026-01-04T11:41:57.157528Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 10, timestamp_us: 1767526917157382, event: K
196
-2026-01-04T11:41:57.157543Z DEBUG RECV KeyDown: keycode=105 (LEFT)
197
-2026-01-04T11:41:57.157546Z DEBUG INJECT KEY: LEFT DOWN (keycode=105, modifiers: depressed=0x40, super=true)
198
-2026-01-04T11:41:57.165167Z DEBUG IPC: connection accepted
199
-2026-01-04T11:41:57.165188Z DEBUG IPC: received Move { direction: Left }
200
-2026-01-04T11:41:57.165192Z DEBUG IPC: sent to main loop, awaiting response
201
-2026-01-04T11:41:57.165196Z  INFO IPC Move Left: state=ReceivedControl { from: Left, transfer_id: 1, entered_at: Instant { tv_sec: 468699,
202
-2026-01-04T11:41:57.165616Z  INFO   edge_check: active window at (967,52) size 931x1006, 3 clients on monitor
203
-2026-01-04T11:41:57.165623Z  INFO   edge_check: has_window_in_direction=true -> at_edge=false
204
-2026-01-04T11:41:57.165645Z  INFO IPC Move Left: at_edge=false, has_peer=true, neighbor=Some("cachyos")
205
-2026-01-04T11:41:57.165648Z  INFO IPC Move Left: doing local movefocus l
206
-2026-01-04T11:41:57.166028Z  INFO   movefocus succeeded
207
-2026-01-04T11:41:57.166037Z DEBUG IPC: got response, sending to client
208
-2026-01-04T11:41:57.340275Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 11, timestamp_us: 1767526917340289, event: K
209
-2026-01-04T11:41:57.340286Z DEBUG RECV KeyUp: keycode=105 (LEFT)
210
-2026-01-04T11:41:57.340288Z DEBUG INJECT KEY: LEFT UP (keycode=105, modifiers: depressed=0x40, super=true)
211
-2026-01-04T11:41:58.958287Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 12, timestamp_us: 1767526918958306, event: P
212
-2026-01-04T11:41:59.441743Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 13, timestamp_us: 1767526919441775, event: K
213
-2026-01-04T11:41:59.441753Z DEBUG RECV KeyDown: keycode=105 (LEFT)
214
-2026-01-04T11:41:59.441755Z DEBUG INJECT KEY: LEFT DOWN (keycode=105, modifiers: depressed=0x40, super=true)
215
-2026-01-04T11:41:59.449106Z DEBUG IPC: connection accepted
216
-2026-01-04T11:41:59.449128Z DEBUG IPC: received Move { direction: Left }
217
-2026-01-04T11:41:59.449131Z DEBUG IPC: sent to main loop, awaiting response
218
-2026-01-04T11:41:59.449134Z  INFO IPC Move Left: state=ReceivedControl { from: Left, transfer_id: 1, entered_at: Instant { tv_sec: 468699,
219
-2026-01-04T11:41:59.449472Z  INFO   edge_check: active window at (22,52) size 931x439, 3 clients on monitor
220
-2026-01-04T11:41:59.449476Z  INFO   edge_check: has_window_in_direction=false -> at_edge=true
221
-2026-01-04T11:41:59.449498Z  INFO IPC Move Left: at_edge=true, has_peer=true, neighbor=Some("cachyos")
222
-2026-01-04T11:41:59.449501Z  INFO Keyboard return: at edge, returning control to Left
223
-2026-01-04T11:41:59.449503Z  INFO Returning control to Left
224
-2026-01-04T11:41:59.449509Z  INFO Sending Leave(LeavePayload { to_direction: Left, cursor_pos: EdgeRelative(0.5), modifiers: ModifierState
225
-2026-01-04T11:41:59.449513Z DEBUG IPC: got response, sending to client
226
-2026-01-04T11:41:59.449542Z  INFO Stopping input injection
227
-2026-01-04T11:41:59.449544Z DEBUG RESET: Releasing key 125 (LEFTMETA)
228
-2026-01-04T11:41:59.449549Z DEBUG RESET: Releasing key 105 (LEFT)
229
-2026-01-04T11:41:59.449553Z DEBUG All keys reset complete
230
-2026-01-04T11:41:59.466206Z DEBUG Received from Left: LeaveAck
231
-2026-01-04T11:41:59.466211Z  INFO Received LeaveAck
232
-2026-01-04T11:42:08.246754Z DEBUG Received from Left: Enter(EnterPayload { from_direction: Left, cursor_pos: EdgeRelative(0.340277777777777
233
-2026-01-04T11:42:08.246768Z  INFO Received Enter from Left
234
-2026-01-04T11:42:08.246770Z  INFO Receiving control from Left, cursor at (0, 735)
235
-2026-01-04T11:42:08.246772Z  INFO Positioned cursor at (0, 735)
236
-2026-01-04T11:42:08.246775Z  INFO Starting input injection from Left
237
-2026-01-04T11:42:08.246778Z  INFO Sending EnterAck(EnterAckPayload { success: true, transfer_id: 2, actual_cursor_pos: Some((0, 735)), erro
238
-2026-01-04T11:42:08.248475Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 14, timestamp_us: 1767526928248545, event: K
239
-2026-01-04T11:42:08.248480Z DEBUG RECV KeyDown: keycode=125 (LEFTMETA)
240
-2026-01-04T11:42:08.248481Z DEBUG INJECT KEY: LEFTMETA DOWN (keycode=125, modifiers: depressed=0x0, super=false)
241
-2026-01-04T11:42:08.248486Z DEBUG INJECT MODIFIERS: depressed=0x40 (super=true)
242
-2026-01-04T11:42:08.443199Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 15, timestamp_us: 1767526928443254, event: K
243
-2026-01-04T11:42:08.443210Z DEBUG RECV KeyUp: keycode=106 (RIGHT)
244
-2026-01-04T11:42:08.443212Z DEBUG INJECT KEY: RIGHT UP (keycode=106, modifiers: depressed=0x40, super=true)
245
-2026-01-04T11:42:11.734849Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 16, timestamp_us: 1767526931734888, event: P
246
-2026-01-04T11:42:13.252205Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 17, timestamp_us: 1767526933252227, event: K
247
-2026-01-04T11:42:13.252217Z DEBUG RECV KeyDown: keycode=105 (LEFT)
248
-2026-01-04T11:42:13.252218Z DEBUG INJECT KEY: LEFT DOWN (keycode=105, modifiers: depressed=0x40, super=true)
249
-2026-01-04T11:42:13.259555Z DEBUG IPC: connection accepted
250
-2026-01-04T11:42:13.259576Z DEBUG IPC: received Move { direction: Left }
251
-2026-01-04T11:42:13.259580Z DEBUG IPC: sent to main loop, awaiting response
252
-2026-01-04T11:42:13.259584Z  INFO IPC Move Left: state=ReceivedControl { from: Left, transfer_id: 2, entered_at: Instant { tv_sec: 468713,
253
-2026-01-04T11:42:13.259920Z  INFO   edge_check: active window at (22,52) size 931x439, 3 clients on monitor
254
-2026-01-04T11:42:13.259924Z  INFO   edge_check: has_window_in_direction=false -> at_edge=true
255
-2026-01-04T11:42:13.259947Z  INFO IPC Move Left: at_edge=true, has_peer=true, neighbor=Some("cachyos")
256
-2026-01-04T11:42:13.259949Z  INFO Keyboard return: at edge, returning control to Left
257
-2026-01-04T11:42:13.259951Z  INFO Returning control to Left
2581
 2026-01-04T11:42:13.259957Z  INFO Sending Leave(LeavePayload { to_direction: Left, cursor_pos: EdgeRelative(0.5), modifiers: ModifierState
2592
 2026-01-04T11:42:13.259960Z DEBUG IPC: got response, sending to client
2603
 2026-01-04T11:42:13.259980Z  INFO Stopping input injection
@@ -299,3 +42,362 @@ Run 'cargo build' to compile
29942
 2026-01-04T11:42:33.656948Z DEBUG Failed to connect to left (192.168.0.84:24850): IO error: Connection refused (os error 111)
30043
 ^C2026-01-04T11:42:34.020915Z  INFO Shutting down...
30144
 
45
+hyprKVM on  trunk [!] is 📦 v0.1.0 via  v1.91.1 took 51s
46
+❯ nix develop --command cargo build --release --package hyprkvm-daemon
47
+HyprKVM development shell
48
+Rust: rustc 1.92.0 (ded5c06cf 2025-12-08)
49
+
50
+Run 'cargo build' to compile
51
+   Compiling hyprkvm-daemon v0.1.0 (/home/mfwolffe/GithubOrgs/tenseleyFlow/hyprKVM/hyprkvm-daemon)
52
+    Finished `release` profile [optimized] target(s) in 4.51s
53
+
54
+hyprKVM on  trunk [$] is 📦 v0.1.0 via  v1.91.1 took 5s
55
+❯ nix develop --command cargo run --release -p hyprkvm-daemon -- -v daemon
56
+HyprKVM development shell
57
+Rust: rustc 1.92.0 (ded5c06cf 2025-12-08)
58
+
59
+Run 'cargo build' to compile
60
+    Finished `release` profile [optimized] target(s) in 0.06s
61
+     Running `target/release/hyprkvm -v daemon`
62
+2026-01-04T11:54:06.020632Z  INFO Starting HyprKVM daemon...
63
+2026-01-04T11:54:06.020691Z  INFO Machine name: nixos
64
+2026-01-04T11:54:06.020694Z  INFO Listening on port: 24850
65
+2026-01-04T11:54:06.020696Z  INFO Connecting to Hyprland...
66
+2026-01-04T11:54:06.020840Z  INFO Connected to Hyprland. Monitors: 3
67
+2026-01-04T11:54:06.020843Z  INFO   HDMI-A-1 at (4480, 0) 3840x2160
68
+2026-01-04T11:54:06.020844Z  INFO   HDMI-A-2 at (1920, 0) 2560x1440
69
+2026-01-04T11:54:06.020846Z  INFO   DP-3 at (0, 0) 1920x1080
70
+2026-01-04T11:54:06.020848Z  INFO   Network neighbor: cachyos (left) at 192.168.0.84:24850
71
+2026-01-04T11:54:06.020852Z  INFO Starting edge capture for: [Left]
72
+2026-01-04T11:54:06.020900Z  INFO Server listening on 0.0.0.0:24850
73
+2026-01-04T11:54:06.020903Z  INFO Listening for connections on 0.0.0.0:24850
74
+2026-01-04T11:54:06.020920Z DEBUG Connecting to left at 192.168.0.84:24850...
75
+2026-01-04T11:54:06.020928Z  INFO Connecting to 192.168.0.84:24850
76
+2026-01-04T11:54:06.020930Z  INFO Daemon running. Move mouse to screen edges to trigger transfer. Press Ctrl+C to stop.
77
+2026-01-04T11:54:06.020962Z  INFO IPC server listening on /run/user/1000/hyprkvm.sock
78
+2026-01-04T11:54:06.020994Z DEBUG Found input device: Keychron Keychron K8 HE at /dev/input/event2 (keys=true, rel=false)
79
+2026-01-04T11:54:06.021016Z DEBUG Bound new global [63] wl_output v4
80
+2026-01-04T11:54:06.021022Z DEBUG Bound new global [64] wl_output v4
81
+2026-01-04T11:54:06.021023Z DEBUG Bound new global [65] wl_output v4
82
+2026-01-04T11:54:06.021026Z DEBUG Bound new global [9] zxdg_output_manager_v1 v3
83
+2026-01-04T11:54:06.021031Z DEBUG Bound new global [1] wl_seat v7
84
+2026-01-04T11:54:06.021147Z DEBUG supported wl_shm format Argb8888
85
+2026-01-04T11:54:06.021150Z DEBUG supported wl_shm format Xrgb8888
86
+2026-01-04T11:54:06.021152Z DEBUG supported wl_shm format Xbgr8888
87
+2026-01-04T11:54:06.021153Z DEBUG supported wl_shm format Abgr8888
88
+2026-01-04T11:54:06.021155Z DEBUG supported wl_shm format Xrgb2101010
89
+2026-01-04T11:54:06.021157Z DEBUG supported wl_shm format Argb2101010
90
+2026-01-04T11:54:06.021159Z DEBUG supported wl_shm format Xbgr2101010
91
+2026-01-04T11:54:06.021160Z DEBUG supported wl_shm format Abgr2101010
92
+2026-01-04T11:54:06.021203Z  INFO After roundtrips: 3 outputs detected
93
+2026-01-04T11:54:06.021217Z DEBUG Multiple candidates for output 2560x1440: ["HDMI-A-1", "HDMI-A-2"]
94
+2026-01-04T11:54:06.021220Z DEBUG Multiple candidates for output 1920x1080: ["HDMI-A-1", "DP-3"]
95
+2026-01-04T11:54:06.021222Z  INFO Assigned remaining output 2560x1440 to monitor HDMI-A-1 at (4480, 0)
96
+2026-01-04T11:54:06.021224Z  INFO Assigned remaining output 1920x1080 to monitor DP-3 at (0, 0)
97
+2026-01-04T11:54:06.021225Z  INFO Creating barriers with 3 outputs:
98
+2026-01-04T11:54:06.021227Z  INFO   Output at (0, 0) size 3072x1728
99
+2026-01-04T11:54:06.021228Z  INFO   Output at (4480, 0) size 2560x1440
100
+2026-01-04T11:54:06.021229Z  INFO   Output at (0, 0) size 1920x1080
101
+2026-01-04T11:54:06.021230Z  INFO Screen bounds: (0, 0) to (7040, 1728)
102
+2026-01-04T11:54:06.021232Z  INFO   Left edge -> output at Some((0, 0, 3072, 1728))
103
+2026-01-04T11:54:06.021239Z  INFO Creating Left barrier on output Some("at (0, 0)"), size 1x1728
104
+2026-01-04T11:54:06.021339Z  INFO Edge capture running with 1 barriers
105
+2026-01-04T11:54:06.021365Z DEBUG Failed to connect to left (192.168.0.84:24850): IO error: Connection refused (os error 111)
106
+2026-01-04T11:54:06.021747Z  INFO Poll #0: state=Local, peers=[]
107
+2026-01-04T11:54:06.075598Z DEBUG Found input device: Sony Interactive Entertainment DualSense Wireless Controller at /dev/input/event16 (k
108
+2026-01-04T11:54:06.119590Z DEBUG Found input device: HP, Inc HyperX QuadCast S Consumer Control at /dev/input/event14 (keys=true, rel=true
109
+2026-01-04T11:54:06.197562Z DEBUG Found input device: HP, Inc HyperX QuadCast S Consumer Control at /dev/input/event7 (keys=true, rel=false
110
+2026-01-04T11:54:06.210608Z DEBUG Found input device: Asus WMI hotkeys at /dev/input/event6 (keys=true, rel=false)
111
+2026-01-04T11:54:06.218559Z DEBUG Found input device: Power Button at /dev/input/event5 (keys=true, rel=false)
112
+2026-01-04T11:54:06.230560Z DEBUG Found input device: Power Button at /dev/input/event4 (keys=true, rel=false)
113
+2026-01-04T11:54:06.240575Z DEBUG Found input device: Sleep Button at /dev/input/event3 (keys=true, rel=false)
114
+2026-01-04T11:54:06.249560Z  INFO Found 13 input device paths
115
+2026-01-04T11:54:06.249572Z DEBUG   /dev/input/event12
116
+2026-01-04T11:54:06.249575Z DEBUG   /dev/input/event13
117
+2026-01-04T11:54:06.249578Z DEBUG   /dev/input/event1
118
+2026-01-04T11:54:06.249580Z DEBUG   /dev/input/event0
119
+2026-01-04T11:54:06.249582Z DEBUG   /dev/input/event18
120
+2026-01-04T11:54:06.249585Z DEBUG   /dev/input/event2
121
+2026-01-04T11:54:06.249586Z DEBUG   /dev/input/event16
122
+2026-01-04T11:54:06.249589Z DEBUG   /dev/input/event14
123
+2026-01-04T11:54:06.249591Z DEBUG   /dev/input/event7
124
+2026-01-04T11:54:06.249593Z DEBUG   /dev/input/event6
125
+2026-01-04T11:54:06.249595Z DEBUG   /dev/input/event5
126
+2026-01-04T11:54:06.249597Z DEBUG   /dev/input/event4
127
+2026-01-04T11:54:06.249599Z DEBUG   /dev/input/event3
128
+2026-01-04T11:54:09.023089Z DEBUG Connecting to left at 192.168.0.84:24850...
129
+2026-01-04T11:54:09.023100Z  INFO Connecting to 192.168.0.84:24850
130
+2026-01-04T11:54:09.023667Z DEBUG Failed to connect to left (192.168.0.84:24850): IO error: Connection refused (os error 111)
131
+2026-01-04T11:54:12.024315Z DEBUG Connecting to left at 192.168.0.84:24850...
132
+2026-01-04T11:54:12.024324Z  INFO Connecting to 192.168.0.84:24850
133
+2026-01-04T11:54:12.024969Z DEBUG Failed to connect to left (192.168.0.84:24850): IO error: Connection refused (os error 111)
134
+2026-01-04T11:54:15.025449Z DEBUG Connecting to left at 192.168.0.84:24850...
135
+2026-01-04T11:54:15.025459Z  INFO Connecting to 192.168.0.84:24850
136
+2026-01-04T11:54:15.025895Z  INFO Connected to 192.168.0.84:24850
137
+2026-01-04T11:54:15.026611Z  INFO Connected to cachyos (left)
138
+2026-01-04T11:54:18.628421Z DEBUG Received from Left: Enter(EnterPayload { from_direction: Left, cursor_pos: EdgeRelative(0.340277777777777
139
+2026-01-04T11:54:18.628434Z  INFO Received Enter from Left
140
+2026-01-04T11:54:18.628437Z  INFO Receiving control from Left, cursor at (0, 735)
141
+2026-01-04T11:54:18.628441Z  INFO Positioned cursor at (0, 735)
142
+2026-01-04T11:54:18.628445Z  INFO Starting input injection from Left
143
+2026-01-04T11:54:18.632822Z  INFO Input emulator created
144
+2026-01-04T11:54:18.632848Z  INFO Sending EnterAck(EnterAckPayload { success: true, transfer_id: 1, actual_cursor_pos: Some((0, 735)), erro
145
+2026-01-04T11:54:18.634550Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 0, timestamp_us: 1767527658635474, event: Ke
146
+2026-01-04T11:54:18.634560Z DEBUG RECV KeyDown: keycode=125 (LEFTMETA)
147
+2026-01-04T11:54:18.634563Z DEBUG INJECT KEY: LEFTMETA DOWN (keycode=125, modifiers: depressed=0x0, super=false)
148
+2026-01-04T11:54:18.634570Z DEBUG INJECT MODIFIERS: depressed=0x40 (super=true)
149
+2026-01-04T11:54:18.816986Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 1, timestamp_us: 1767527658817924, event: Ke
150
+2026-01-04T11:54:18.816996Z DEBUG RECV KeyUp: keycode=106 (RIGHT)
151
+2026-01-04T11:54:18.816998Z DEBUG INJECT KEY: RIGHT UP (keycode=106, modifiers: depressed=0x40, super=true)
152
+2026-01-04T11:54:19.854118Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 2, timestamp_us: 1767527659853964, event: Ke
153
+2026-01-04T11:54:19.854128Z DEBUG RECV KeyDown: keycode=105 (LEFT)
154
+2026-01-04T11:54:19.854130Z DEBUG INJECT KEY: LEFT DOWN (keycode=105, modifiers: depressed=0x40, super=true)
155
+2026-01-04T11:54:19.861556Z DEBUG IPC: connection accepted
156
+2026-01-04T11:54:19.861584Z DEBUG IPC: received Move { direction: Left }
157
+2026-01-04T11:54:19.861589Z DEBUG IPC: sent to main loop, awaiting response
158
+2026-01-04T11:54:19.861597Z  INFO IPC Move Left: state=ReceivedControl { from: Left, transfer_id: 1, entered_at: Instant { tv_sec: 469444,
159
+2026-01-04T11:54:19.861734Z  INFO   edge_check: has monitor in direction Left
160
+2026-01-04T11:54:19.861738Z  INFO IPC Move Left: at_edge=false, has_peer=true, neighbor=Some("cachyos")
161
+2026-01-04T11:54:19.861740Z  INFO IPC Move Left: doing local movefocus l
162
+2026-01-04T11:54:19.862188Z  INFO   movefocus succeeded
163
+2026-01-04T11:54:19.862204Z DEBUG IPC: got response, sending to client
164
+2026-01-04T11:54:20.054344Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 3, timestamp_us: 1767527660055230, event: Ke
165
+2026-01-04T11:54:20.054355Z DEBUG RECV KeyUp: keycode=105 (LEFT)
166
+2026-01-04T11:54:20.054357Z DEBUG INJECT KEY: LEFT UP (keycode=105, modifiers: depressed=0x40, super=true)
167
+2026-01-04T11:54:21.108408Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 4, timestamp_us: 1767527661109285, event: Ke
168
+2026-01-04T11:54:21.108419Z DEBUG RECV KeyDown: keycode=105 (LEFT)
169
+2026-01-04T11:54:21.108421Z DEBUG INJECT KEY: LEFT DOWN (keycode=105, modifiers: depressed=0x40, super=true)
170
+2026-01-04T11:54:21.115997Z DEBUG IPC: connection accepted
171
+2026-01-04T11:54:21.116022Z DEBUG IPC: received Move { direction: Left }
172
+2026-01-04T11:54:21.116026Z DEBUG IPC: sent to main loop, awaiting response
173
+2026-01-04T11:54:21.117086Z  INFO IPC Move Left: state=ReceivedControl { from: Left, transfer_id: 1, entered_at: Instant { tv_sec: 469444,
174
+2026-01-04T11:54:21.117218Z  INFO   edge_check: has monitor in direction Left
175
+2026-01-04T11:54:21.117222Z  INFO IPC Move Left: at_edge=false, has_peer=true, neighbor=Some("cachyos")
176
+2026-01-04T11:54:21.117224Z  INFO IPC Move Left: doing local movefocus l
177
+2026-01-04T11:54:21.117852Z  INFO   movefocus succeeded
178
+2026-01-04T11:54:21.117864Z DEBUG IPC: got response, sending to client
179
+2026-01-04T11:54:21.277987Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 5, timestamp_us: 1767527661278909, event: Ke
180
+2026-01-04T11:54:21.277997Z DEBUG RECV KeyUp: keycode=105 (LEFT)
181
+2026-01-04T11:54:21.277999Z DEBUG INJECT KEY: LEFT UP (keycode=105, modifiers: depressed=0x40, super=true)
182
+2026-01-04T11:54:22.175215Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 6, timestamp_us: 1767527662176117, event: Ke
183
+2026-01-04T11:54:22.175225Z DEBUG RECV KeyDown: keycode=105 (LEFT)
184
+2026-01-04T11:54:22.175227Z DEBUG INJECT KEY: LEFT DOWN (keycode=105, modifiers: depressed=0x40, super=true)
185
+2026-01-04T11:54:22.182621Z DEBUG IPC: connection accepted
186
+2026-01-04T11:54:22.182642Z DEBUG IPC: received Move { direction: Left }
187
+2026-01-04T11:54:22.182646Z DEBUG IPC: sent to main loop, awaiting response
188
+2026-01-04T11:54:22.182649Z  INFO IPC Move Left: state=ReceivedControl { from: Left, transfer_id: 1, entered_at: Instant { tv_sec: 469444,
189
+2026-01-04T11:54:22.183046Z  INFO   edge_check: active window at (967,52) size 931x1006, 3 clients on monitor
190
+2026-01-04T11:54:22.183051Z  INFO   edge_check: has_window_in_direction=true -> at_edge=false
191
+2026-01-04T11:54:22.183074Z  INFO IPC Move Left: at_edge=false, has_peer=true, neighbor=Some("cachyos")
192
+2026-01-04T11:54:22.183077Z  INFO IPC Move Left: doing local movefocus l
193
+2026-01-04T11:54:22.183482Z  INFO   movefocus succeeded
194
+2026-01-04T11:54:22.183500Z DEBUG IPC: got response, sending to client
195
+2026-01-04T11:54:22.360566Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 7, timestamp_us: 1767527662361486, event: Ke
196
+2026-01-04T11:54:22.360577Z DEBUG RECV KeyUp: keycode=105 (LEFT)
197
+2026-01-04T11:54:22.360579Z DEBUG INJECT KEY: LEFT UP (keycode=105, modifiers: depressed=0x40, super=true)
198
+2026-01-04T11:54:24.951285Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 8, timestamp_us: 1767527664952186, event: Ke
199
+2026-01-04T11:54:24.951296Z DEBUG RECV KeyDown: keycode=105 (LEFT)
200
+2026-01-04T11:54:24.951298Z DEBUG INJECT KEY: LEFT DOWN (keycode=105, modifiers: depressed=0x40, super=true)
201
+2026-01-04T11:54:24.958722Z DEBUG IPC: connection accepted
202
+2026-01-04T11:54:24.958766Z DEBUG IPC: received Move { direction: Left }
203
+2026-01-04T11:54:24.958771Z DEBUG IPC: sent to main loop, awaiting response
204
+2026-01-04T11:54:24.959830Z  INFO IPC Move Left: state=ReceivedControl { from: Left, transfer_id: 1, entered_at: Instant { tv_sec: 469444,
205
+2026-01-04T11:54:24.960190Z  INFO   edge_check: active window at (22,52) size 931x439, 3 clients on monitor
206
+2026-01-04T11:54:24.960195Z  INFO   edge_check: has_window_in_direction=false -> at_edge=true
207
+2026-01-04T11:54:24.960211Z  INFO IPC Move Left: at_edge=true, has_peer=true, neighbor=Some("cachyos")
208
+2026-01-04T11:54:24.960214Z  INFO Keyboard return: at edge, returning control to Left
209
+2026-01-04T11:54:24.960216Z  INFO Returning control to Left
210
+2026-01-04T11:54:24.960223Z  INFO Sending Leave(LeavePayload { to_direction: Left, cursor_pos: EdgeRelative(0.5), modifiers: ModifierState
211
+2026-01-04T11:54:24.960228Z DEBUG IPC: got response, sending to client
212
+2026-01-04T11:54:24.960251Z  INFO Stopping input injection
213
+2026-01-04T11:54:24.960255Z DEBUG RESET: Releasing key 105 (LEFT)
214
+2026-01-04T11:54:24.960260Z DEBUG RESET: Releasing key 125 (LEFTMETA)
215
+2026-01-04T11:54:24.960264Z DEBUG All keys reset complete
216
+2026-01-04T11:54:24.975397Z DEBUG Received from Left: LeaveAck
217
+2026-01-04T11:54:24.975403Z  INFO Received LeaveAck
218
+2026-01-04T11:54:39.222090Z DEBUG Received from Left: Enter(EnterPayload { from_direction: Left, cursor_pos: EdgeRelative(0.340277777777777
219
+2026-01-04T11:54:39.222103Z  INFO Received Enter from Left
220
+2026-01-04T11:54:39.222105Z  INFO Receiving control from Left, cursor at (0, 735)
221
+2026-01-04T11:54:39.222107Z  INFO Positioned cursor at (0, 735)
222
+2026-01-04T11:54:39.222111Z  INFO Starting input injection from Left
223
+2026-01-04T11:54:39.222113Z  INFO Sending EnterAck(EnterAckPayload { success: true, transfer_id: 2, actual_cursor_pos: Some((0, 735)), erro
224
+2026-01-04T11:54:39.223700Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 9, timestamp_us: 1767527679224727, event: Ke
225
+2026-01-04T11:54:39.223705Z DEBUG RECV KeyDown: keycode=125 (LEFTMETA)
226
+2026-01-04T11:54:39.223707Z DEBUG INJECT KEY: LEFTMETA DOWN (keycode=125, modifiers: depressed=0x0, super=false)
227
+2026-01-04T11:54:39.223712Z DEBUG INJECT MODIFIERS: depressed=0x40 (super=true)
228
+2026-01-04T11:54:39.418488Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 10, timestamp_us: 1767527679419491, event: K
229
+2026-01-04T11:54:39.418499Z DEBUG RECV KeyUp: keycode=106 (RIGHT)
230
+2026-01-04T11:54:39.418501Z DEBUG INJECT KEY: RIGHT UP (keycode=106, modifiers: depressed=0x40, super=true)
231
+2026-01-04T11:54:41.461649Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 11, timestamp_us: 1767527681462608, event: K
232
+2026-01-04T11:54:41.461659Z DEBUG RECV KeyDown: keycode=106 (RIGHT)
233
+2026-01-04T11:54:41.461661Z DEBUG INJECT KEY: RIGHT DOWN (keycode=106, modifiers: depressed=0x40, super=true)
234
+2026-01-04T11:54:41.468991Z DEBUG IPC: connection accepted
235
+2026-01-04T11:54:41.469013Z DEBUG IPC: received Move { direction: Right }
236
+2026-01-04T11:54:41.469017Z DEBUG IPC: sent to main loop, awaiting response
237
+2026-01-04T11:54:41.469021Z  INFO IPC Move Right: state=ReceivedControl { from: Left, transfer_id: 2, entered_at: Instant { tv_sec: 469464,
238
+2026-01-04T11:54:41.469165Z  INFO   edge_check: has monitor in direction Right
239
+2026-01-04T11:54:41.469169Z  INFO IPC Move Right: at_edge=false, has_peer=false, neighbor=None
240
+2026-01-04T11:54:41.469171Z  INFO IPC Move Right: doing local movefocus r
241
+2026-01-04T11:54:41.469584Z  INFO   movefocus succeeded
242
+2026-01-04T11:54:41.469596Z DEBUG IPC: got response, sending to client
243
+2026-01-04T11:54:41.658384Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 12, timestamp_us: 1767527681659448, event: K
244
+2026-01-04T11:54:41.658395Z DEBUG RECV KeyUp: keycode=106 (RIGHT)
245
+2026-01-04T11:54:41.658398Z DEBUG INJECT KEY: RIGHT UP (keycode=106, modifiers: depressed=0x40, super=true)
246
+2026-01-04T11:54:42.972616Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 13, timestamp_us: 1767527682973657, event: K
247
+2026-01-04T11:54:42.972627Z DEBUG RECV KeyDown: keycode=106 (RIGHT)
248
+2026-01-04T11:54:42.972629Z DEBUG INJECT KEY: RIGHT DOWN (keycode=106, modifiers: depressed=0x40, super=true)
249
+2026-01-04T11:54:42.979947Z DEBUG IPC: connection accepted
250
+2026-01-04T11:54:42.979971Z DEBUG IPC: received Move { direction: Right }
251
+2026-01-04T11:54:42.979976Z DEBUG IPC: sent to main loop, awaiting response
252
+2026-01-04T11:54:42.979980Z  INFO IPC Move Right: state=ReceivedControl { from: Left, transfer_id: 2, entered_at: Instant { tv_sec: 469464,
253
+2026-01-04T11:54:42.980154Z  INFO   edge_check: has monitor in direction Right
254
+2026-01-04T11:54:42.980158Z  INFO IPC Move Right: at_edge=false, has_peer=false, neighbor=None
255
+2026-01-04T11:54:42.980159Z  INFO IPC Move Right: doing local movefocus r
256
+2026-01-04T11:54:42.980794Z  INFO   movefocus succeeded
257
+2026-01-04T11:54:42.980804Z DEBUG IPC: got response, sending to client
258
+2026-01-04T11:54:43.189868Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 14, timestamp_us: 1767527683190869, event: K
259
+2026-01-04T11:54:43.189880Z DEBUG RECV KeyUp: keycode=106 (RIGHT)
260
+2026-01-04T11:54:43.189883Z DEBUG INJECT KEY: RIGHT UP (keycode=106, modifiers: depressed=0x40, super=true)
261
+2026-01-04T11:54:45.193254Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 15, timestamp_us: 1767527685194247, event: K
262
+2026-01-04T11:54:45.193265Z DEBUG RECV KeyDown: keycode=105 (LEFT)
263
+2026-01-04T11:54:45.193266Z DEBUG INJECT KEY: LEFT DOWN (keycode=105, modifiers: depressed=0x40, super=true)
264
+2026-01-04T11:54:45.200701Z DEBUG IPC: connection accepted
265
+2026-01-04T11:54:45.200723Z DEBUG IPC: received Move { direction: Left }
266
+2026-01-04T11:54:45.200727Z DEBUG IPC: sent to main loop, awaiting response
267
+2026-01-04T11:54:45.201788Z  INFO IPC Move Left: state=ReceivedControl { from: Left, transfer_id: 2, entered_at: Instant { tv_sec: 469464,
268
+2026-01-04T11:54:45.201914Z  INFO   edge_check: has monitor in direction Left
269
+2026-01-04T11:54:45.201917Z  INFO IPC Move Left: at_edge=false, has_peer=true, neighbor=Some("cachyos")
270
+2026-01-04T11:54:45.201920Z  INFO IPC Move Left: doing local movefocus l
271
+2026-01-04T11:54:45.202548Z  INFO   movefocus succeeded
272
+2026-01-04T11:54:45.202566Z DEBUG IPC: got response, sending to client
273
+2026-01-04T11:54:45.382879Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 16, timestamp_us: 1767527685382826, event: K
274
+2026-01-04T11:54:45.382890Z DEBUG RECV KeyUp: keycode=105 (LEFT)
275
+2026-01-04T11:54:45.382893Z DEBUG INJECT KEY: LEFT UP (keycode=105, modifiers: depressed=0x40, super=true)
276
+2026-01-04T11:54:46.024027Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 17, timestamp_us: 1767527686025045, event: K
277
+2026-01-04T11:54:46.024037Z DEBUG RECV KeyDown: keycode=105 (LEFT)
278
+2026-01-04T11:54:46.024040Z DEBUG INJECT KEY: LEFT DOWN (keycode=105, modifiers: depressed=0x40, super=true)
279
+2026-01-04T11:54:46.031433Z DEBUG IPC: connection accepted
280
+2026-01-04T11:54:46.031455Z DEBUG IPC: received Move { direction: Left }
281
+2026-01-04T11:54:46.031459Z DEBUG IPC: sent to main loop, awaiting response
282
+2026-01-04T11:54:46.031462Z  INFO IPC Move Left: state=ReceivedControl { from: Left, transfer_id: 2, entered_at: Instant { tv_sec: 469464,
283
+2026-01-04T11:54:46.031841Z  INFO   edge_check: active window at (967,52) size 931x1006, 3 clients on monitor
284
+2026-01-04T11:54:46.031845Z  INFO   edge_check: has_window_in_direction=true -> at_edge=false
285
+2026-01-04T11:54:46.031861Z  INFO IPC Move Left: at_edge=false, has_peer=true, neighbor=Some("cachyos")
286
+2026-01-04T11:54:46.031863Z  INFO IPC Move Left: doing local movefocus l
287
+2026-01-04T11:54:46.032267Z  INFO   movefocus succeeded
288
+2026-01-04T11:54:46.032281Z DEBUG IPC: got response, sending to client
289
+2026-01-04T11:54:46.218217Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 18, timestamp_us: 1767527686219226, event: K
290
+2026-01-04T11:54:46.218228Z DEBUG RECV KeyUp: keycode=105 (LEFT)
291
+2026-01-04T11:54:46.218229Z DEBUG INJECT KEY: LEFT UP (keycode=105, modifiers: depressed=0x40, super=true)
292
+2026-01-04T11:54:47.389179Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 19, timestamp_us: 1767527687389175, event: K
293
+2026-01-04T11:54:47.389190Z DEBUG RECV KeyDown: keycode=105 (LEFT)
294
+2026-01-04T11:54:47.389192Z DEBUG INJECT KEY: LEFT DOWN (keycode=105, modifiers: depressed=0x40, super=true)
295
+2026-01-04T11:54:47.396966Z DEBUG IPC: connection accepted
296
+2026-01-04T11:54:47.396990Z DEBUG IPC: received Move { direction: Left }
297
+2026-01-04T11:54:47.396996Z DEBUG IPC: sent to main loop, awaiting response
298
+2026-01-04T11:54:47.398056Z  INFO IPC Move Left: state=ReceivedControl { from: Left, transfer_id: 2, entered_at: Instant { tv_sec: 469464,
299
+2026-01-04T11:54:47.398466Z  INFO   edge_check: active window at (22,52) size 931x439, 3 clients on monitor
300
+2026-01-04T11:54:47.398471Z  INFO   edge_check: has_window_in_direction=false -> at_edge=true
301
+2026-01-04T11:54:47.398487Z  INFO IPC Move Left: at_edge=true, has_peer=true, neighbor=Some("cachyos")
302
+2026-01-04T11:54:47.398489Z  INFO Keyboard return: at edge, returning control to Left
303
+2026-01-04T11:54:47.398491Z  INFO Returning control to Left
304
+2026-01-04T11:54:47.398497Z  INFO Sending Leave(LeavePayload { to_direction: Left, cursor_pos: EdgeRelative(0.5), modifiers: ModifierState
305
+2026-01-04T11:54:47.398503Z DEBUG IPC: got response, sending to client
306
+2026-01-04T11:54:47.398523Z  INFO Stopping input injection
307
+2026-01-04T11:54:47.398527Z DEBUG RESET: Releasing key 105 (LEFT)
308
+2026-01-04T11:54:47.398532Z DEBUG RESET: Releasing key 125 (LEFTMETA)
309
+2026-01-04T11:54:47.398544Z DEBUG All keys reset complete
310
+2026-01-04T11:54:47.400069Z DEBUG Received from Left: LeaveAck
311
+2026-01-04T11:54:47.400072Z  INFO Received LeaveAck
312
+2026-01-04T11:55:15.861901Z DEBUG Received from Left: Enter(EnterPayload { from_direction: Left, cursor_pos: EdgeRelative(0.340277777777777
313
+2026-01-04T11:55:15.861913Z  INFO Received Enter from Left
314
+2026-01-04T11:55:15.861915Z  INFO Receiving control from Left, cursor at (0, 735)
315
+2026-01-04T11:55:15.861917Z  INFO Positioned cursor at (0, 735)
316
+2026-01-04T11:55:15.861920Z  INFO Starting input injection from Left
317
+2026-01-04T11:55:15.861923Z  INFO Sending EnterAck(EnterAckPayload { success: true, transfer_id: 3, actual_cursor_pos: Some((0, 735)), erro
318
+2026-01-04T11:55:15.865819Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 20, timestamp_us: 1767527715867034, event: K
319
+2026-01-04T11:55:15.865826Z DEBUG RECV KeyDown: keycode=125 (LEFTMETA)
320
+2026-01-04T11:55:15.865828Z DEBUG INJECT KEY: LEFTMETA DOWN (keycode=125, modifiers: depressed=0x0, super=false)
321
+2026-01-04T11:55:15.865832Z DEBUG INJECT MODIFIERS: depressed=0x40 (super=true)
322
+2026-01-04T11:55:16.032614Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 21, timestamp_us: 1767527716033822, event: K
323
+2026-01-04T11:55:16.032624Z DEBUG RECV KeyUp: keycode=106 (RIGHT)
324
+2026-01-04T11:55:16.032628Z DEBUG INJECT KEY: RIGHT UP (keycode=106, modifiers: depressed=0x40, super=true)
325
+2026-01-04T11:55:17.651996Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 22, timestamp_us: 1767527717652155, event: K
326
+2026-01-04T11:55:17.652007Z DEBUG RECV KeyDown: keycode=106 (RIGHT)
327
+2026-01-04T11:55:17.652009Z DEBUG INJECT KEY: RIGHT DOWN (keycode=106, modifiers: depressed=0x40, super=true)
328
+2026-01-04T11:55:17.659514Z DEBUG IPC: connection accepted
329
+2026-01-04T11:55:17.659540Z DEBUG IPC: received Move { direction: Right }
330
+2026-01-04T11:55:17.659544Z DEBUG IPC: sent to main loop, awaiting response
331
+2026-01-04T11:55:17.659547Z  INFO IPC Move Right: state=ReceivedControl { from: Left, transfer_id: 3, entered_at: Instant { tv_sec: 469501,
332
+2026-01-04T11:55:17.659725Z  INFO   edge_check: has monitor in direction Right
333
+2026-01-04T11:55:17.659729Z  INFO IPC Move Right: at_edge=false, has_peer=false, neighbor=None
334
+2026-01-04T11:55:17.659731Z  INFO IPC Move Right: doing local movefocus r
335
+2026-01-04T11:55:17.660151Z  INFO   movefocus succeeded
336
+2026-01-04T11:55:17.660167Z DEBUG IPC: got response, sending to client
337
+2026-01-04T11:55:17.838115Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 23, timestamp_us: 1767527717838265, event: K
338
+2026-01-04T11:55:17.838125Z DEBUG RECV KeyUp: keycode=106 (RIGHT)
339
+2026-01-04T11:55:17.838127Z DEBUG INJECT KEY: RIGHT UP (keycode=106, modifiers: depressed=0x40, super=true)
340
+2026-01-04T11:55:18.350254Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 24, timestamp_us: 1767527718351457, event: K
341
+2026-01-04T11:55:18.350264Z DEBUG RECV KeyDown: keycode=105 (LEFT)
342
+2026-01-04T11:55:18.350267Z DEBUG INJECT KEY: LEFT DOWN (keycode=105, modifiers: depressed=0x40, super=true)
343
+2026-01-04T11:55:18.358019Z DEBUG IPC: connection accepted
344
+2026-01-04T11:55:18.358042Z DEBUG IPC: received Move { direction: Left }
345
+2026-01-04T11:55:18.358046Z DEBUG IPC: sent to main loop, awaiting response
346
+2026-01-04T11:55:18.358056Z  INFO IPC Move Left: state=ReceivedControl { from: Left, transfer_id: 3, entered_at: Instant { tv_sec: 469501,
347
+2026-01-04T11:55:18.358457Z  INFO   edge_check: active window at (967,52) size 931x1006, 3 clients on monitor
348
+2026-01-04T11:55:18.358462Z  INFO   edge_check: has_window_in_direction=true -> at_edge=false
349
+2026-01-04T11:55:18.358478Z  INFO IPC Move Left: at_edge=false, has_peer=true, neighbor=Some("cachyos")
350
+2026-01-04T11:55:18.358480Z  INFO IPC Move Left: doing local movefocus l
351
+2026-01-04T11:55:18.358887Z  INFO   movefocus succeeded
352
+2026-01-04T11:55:18.358901Z DEBUG IPC: got response, sending to client
353
+2026-01-04T11:55:18.497240Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 25, timestamp_us: 1767527718497368, event: K
354
+2026-01-04T11:55:18.497250Z DEBUG RECV KeyUp: keycode=105 (LEFT)
355
+2026-01-04T11:55:18.497252Z DEBUG INJECT KEY: LEFT UP (keycode=105, modifiers: depressed=0x40, super=true)
356
+2026-01-04T11:55:19.962967Z DEBUG Received from Left: InputEvent(InputEventPayload { sequence: 26, timestamp_us: 1767527719963103, event: K
357
+2026-01-04T11:55:19.962977Z DEBUG RECV KeyDown: keycode=105 (LEFT)
358
+2026-01-04T11:55:19.962980Z DEBUG INJECT KEY: LEFT DOWN (keycode=105, modifiers: depressed=0x40, super=true)
359
+2026-01-04T11:55:19.970234Z DEBUG IPC: connection accepted
360
+2026-01-04T11:55:19.970259Z DEBUG IPC: received Move { direction: Left }
361
+2026-01-04T11:55:19.970265Z DEBUG IPC: sent to main loop, awaiting response
362
+2026-01-04T11:55:19.970271Z  INFO IPC Move Left: state=ReceivedControl { from: Left, transfer_id: 3, entered_at: Instant { tv_sec: 469501,
363
+2026-01-04T11:55:19.970667Z  INFO   edge_check: active window at (22,52) size 931x439, 3 clients on monitor
364
+2026-01-04T11:55:19.970672Z  INFO   edge_check: has_window_in_direction=false -> at_edge=true
365
+2026-01-04T11:55:19.970690Z  INFO IPC Move Left: at_edge=true, has_peer=true, neighbor=Some("cachyos")
366
+2026-01-04T11:55:19.970693Z  INFO Keyboard return: at edge, returning control to Left
367
+2026-01-04T11:55:19.970695Z  INFO Returning control to Left
368
+2026-01-04T11:55:19.970702Z  INFO Sending Leave(LeavePayload { to_direction: Left, cursor_pos: EdgeRelative(0.5), modifiers: ModifierState
369
+2026-01-04T11:55:19.970706Z DEBUG IPC: got response, sending to client
370
+2026-01-04T11:55:19.970732Z  INFO Stopping input injection
371
+2026-01-04T11:55:19.970735Z DEBUG RESET: Releasing key 105 (LEFT)
372
+2026-01-04T11:55:19.970741Z DEBUG RESET: Releasing key 125 (LEFTMETA)
373
+2026-01-04T11:55:19.970746Z DEBUG All keys reset complete
374
+2026-01-04T11:55:19.971257Z DEBUG Received from Left: LeaveAck
375
+2026-01-04T11:55:19.971260Z  INFO Received LeaveAck
376
+2026-01-04T11:55:38.160099Z  INFO Peer Left disconnected
377
+2026-01-04T11:55:43.048919Z DEBUG Connecting to left at 192.168.0.84:24850...
378
+2026-01-04T11:55:43.048928Z  INFO Connecting to 192.168.0.84:24850
379
+2026-01-04T11:55:43.049615Z DEBUG Failed to connect to left (192.168.0.84:24850): IO error: Connection refused (os error 111)
380
+2026-01-04T11:55:45.360438Z  INFO Poll #50000: state=Local, peers=[]
381
+2026-01-04T11:55:46.050825Z DEBUG Connecting to left at 192.168.0.84:24850...
382
+2026-01-04T11:55:46.050834Z  INFO Connecting to 192.168.0.84:24850
383
+2026-01-04T11:55:46.051288Z DEBUG Failed to connect to left (192.168.0.84:24850): IO error: Connection refused (os error 111)
384
+2026-01-04T11:55:49.053234Z DEBUG Connecting to left at 192.168.0.84:24850...
385
+2026-01-04T11:55:49.053243Z  INFO Connecting to 192.168.0.84:24850
386
+2026-01-04T11:55:49.053671Z DEBUG Failed to connect to left (192.168.0.84:24850): IO error: Connection refused (os error 111)
387
+2026-01-04T11:55:52.054856Z DEBUG Connecting to left at 192.168.0.84:24850...
388
+2026-01-04T11:55:52.054868Z  INFO Connecting to 192.168.0.84:24850
389
+2026-01-04T11:55:52.055360Z DEBUG Failed to connect to left (192.168.0.84:24850): IO error: Connection refused (os error 111)
390
+2026-01-04T11:55:55.056192Z DEBUG Connecting to left at 192.168.0.84:24850...
391
+2026-01-04T11:55:55.056202Z  INFO Connecting to 192.168.0.84:24850
392
+2026-01-04T11:55:55.056854Z DEBUG Failed to connect to left (192.168.0.84:24850): IO error: Connection refused (os error 111)
393
+2026-01-04T11:55:58.058007Z DEBUG Connecting to left at 192.168.0.84:24850...
394
+2026-01-04T11:55:58.058016Z  INFO Connecting to 192.168.0.84:24850
395
+2026-01-04T11:55:58.058439Z DEBUG Failed to connect to left (192.168.0.84:24850): IO error: Connection refused (os error 111)
396
+2026-01-04T11:56:01.060241Z DEBUG Connecting to left at 192.168.0.84:24850...
397
+2026-01-04T11:56:01.060257Z  INFO Connecting to 192.168.0.84:24850
398
+2026-01-04T11:56:01.060676Z DEBUG Failed to connect to left (192.168.0.84:24850): IO error: Connection refused (os error 111)
399
+2026-01-04T11:56:04.061825Z DEBUG Connecting to left at 192.168.0.84:24850...
400
+2026-01-04T11:56:04.061834Z  INFO Connecting to 192.168.0.84:24850
401
+2026-01-04T11:56:04.062343Z DEBUG Failed to connect to left (192.168.0.84:24850): IO error: Connection refused (os error 111)
402
+^C2026-01-04T11:56:05.707382Z  INFO Shutting down...
403
+
hyprkvm-daemon/src/input/evdev_grab.rsmodified
@@ -197,12 +197,14 @@ fn run_evdev_grabber(
197197
                 // Ungrab and close all devices
198198
                 tracing::info!("Releasing {} input devices", devices.len());
199199
 
200
-                // Key codes for modifiers and arrow keys that might be held
201
-                let keys_to_release: &[u16] = &[
202
-                    125, 126,           // KEY_LEFTMETA, KEY_RIGHTMETA (Super)
203
-                    42, 54,             // KEY_LEFTSHIFT, KEY_RIGHTSHIFT
204
-                    29, 97,             // KEY_LEFTCTRL, KEY_RIGHTCTRL
205
-                    56, 100,            // KEY_LEFTALT, KEY_RIGHTALT
200
+                // Keys we care about: modifiers and arrows
201
+                let modifier_keys: &[u16] = &[
202
+                    125, 126,  // KEY_LEFTMETA, KEY_RIGHTMETA (Super)
203
+                    42, 54,    // KEY_LEFTSHIFT, KEY_RIGHTSHIFT
204
+                    29, 97,    // KEY_LEFTCTRL, KEY_RIGHTCTRL
205
+                    56, 100,   // KEY_LEFTALT, KEY_RIGHTALT
206
+                ];
207
+                let arrow_keys: &[u16] = &[
206208
                     103, 108, 105, 106, // KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT
207209
                 ];
208210
 
@@ -210,29 +212,55 @@ fn run_evdev_grabber(
210212
                     // First ungrab so libinput can receive events
211213
                     if let Err(e) = dev.ungrab() {
212214
                         tracing::warn!("Failed to ungrab {}: {}", path.display(), e);
213
-                    } else {
214
-                        tracing::debug!("Released {}", path.display());
215
+                        continue;
215216
                     }
217
+                    tracing::debug!("Released {}", path.display());
216218
 
217
-                    // CRITICAL FIX: Synthesize key-up events AFTER ungrabbing!
218
-                    // When we grabbed the device, the user was holding Super+Arrow.
219
-                    // If they're STILL holding those keys, libinput's state from
220
-                    // before the grab still has those keys pressed. By sending
221
-                    // synthetic key-ups now (after ungrab), libinput sees them
222
-                    // as releases, and subsequent presses will be fresh edges.
223
-                    for &keycode in keys_to_release {
224
-                        let key_event = evdev::InputEvent::new(
225
-                            evdev::EventType::KEY,
226
-                            keycode,
227
-                            0, // 0 = released
228
-                        );
229
-                        let syn_event = evdev::InputEvent::new(
230
-                            evdev::EventType::SYNCHRONIZATION,
231
-                            0, // SYN_REPORT
232
-                            0,
233
-                        );
234
-                        // Ignore errors - not all devices support all keys
235
-                        let _ = dev.send_events(&[key_event, syn_event]);
219
+                    // Query actual physical key state AFTER ungrab
220
+                    let key_state = match dev.get_key_state() {
221
+                        Ok(state) => state,
222
+                        Err(e) => {
223
+                            tracing::debug!("Could not query key state for {}: {}", path.display(), e);
224
+                            continue;
225
+                        }
226
+                    };
227
+
228
+                    // For ARROW keys: if NOT pressed, send UP to clear stale state
229
+                    // (Hyprland thought they were pressed from before grab)
230
+                    for &keycode in arrow_keys {
231
+                        let key = evdev::Key::new(keycode);
232
+                        if !key_state.contains(key) {
233
+                            // Key is not pressed - send UP to clear stale state
234
+                            let key_event = evdev::InputEvent::new(
235
+                                evdev::EventType::KEY, keycode, 0,
236
+                            );
237
+                            let syn_event = evdev::InputEvent::new(
238
+                                evdev::EventType::SYNCHRONIZATION, 0, 0,
239
+                            );
240
+                            let _ = dev.send_events(&[key_event, syn_event]);
241
+                        }
242
+                        // If key IS pressed, don't send anything - user is still holding it
243
+                    }
244
+
245
+                    // For MODIFIER keys: if pressed, send UP then DOWN (fresh edge)
246
+                    // This gives Hyprland a clean state transition
247
+                    for &keycode in modifier_keys {
248
+                        let key = evdev::Key::new(keycode);
249
+                        if key_state.contains(key) {
250
+                            // Key is pressed - send UP then DOWN for fresh edge
251
+                            let up_event = evdev::InputEvent::new(
252
+                                evdev::EventType::KEY, keycode, 0,
253
+                            );
254
+                            let down_event = evdev::InputEvent::new(
255
+                                evdev::EventType::KEY, keycode, 1,
256
+                            );
257
+                            let syn_event = evdev::InputEvent::new(
258
+                                evdev::EventType::SYNCHRONIZATION, 0, 0,
259
+                            );
260
+                            let _ = dev.send_events(&[up_event, syn_event, down_event, syn_event]);
261
+                            tracing::debug!("Sent UP+DOWN for held modifier key {}", keycode);
262
+                        }
263
+                        // If not pressed, don't send anything - already released
236264
                     }
237265
 
238266
                     // Device is dropped here, closing the fd