Skip to content

Commit 44fc26a

Browse files
committed
fix hotkeys not grabbing sometimes
recent regression bug
1 parent 2f2537d commit 44fc26a

File tree

1 file changed

+22
-6
lines changed

1 file changed

+22
-6
lines changed

src/run/display/x11.cr

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ module Run
229229
end
230230

231231
@key_handler : Proc(::X11::KeyEvent, UInt64, Char?, Nil)?
232+
@flush_event_queue = Channel(Nil).new
232233
def run(*, key_handler)
233234
@key_handler = key_handler
234235
record = @record
@@ -249,7 +250,18 @@ module Run
249250
# Even if XTst Record obliterates the need to read key events, we still need to
250251
# keep the event loop running or otherwise the hotkeys aren't even grabbed
251252
# and use it to get updates on the active window.
252-
event_fd = IO::FileDescriptor.new @display.connection_number
253+
spawn same_thread: true do
254+
event_fd = IO::FileDescriptor.new @display.connection_number
255+
loop do
256+
# Instead of this, running `next_event` (blocking) in a loop also works but requires a separate thread.
257+
# But that somehow messes up `::exit` so we don't do that.
258+
# This very solution, `wait_readable`, has shown to *sometimes* be unreliable, i.e. hotkeys aren't
259+
# grabbed properly because some pending events somehow aren't visible. To solve this,
260+
# `flush_event_queue` is also called from a few other places.
261+
event_fd.wait_readable
262+
@flush_event_queue.send(nil)
263+
end
264+
end
253265
loop do
254266
while @display.pending != 0
255267
@mutex.lock
@@ -263,10 +275,10 @@ module Run
263275
if active_win > 0
264276
# The mutex doesn't protect against nonsense here yet but the chance for
265277
# this to happen is fairly small
266-
@mutex.unlock
267-
@hotkeys.each { |h| ungrab_hotkey(h, from_window: active_window_before, unsubscribe: false) }
268-
@hotkeys.each { |h| grab_hotkey(h, subscribe: false) }
269-
@mutex.lock
278+
spawn same_thread: true do
279+
@hotkeys.each { |h| ungrab_hotkey(h, from_window: active_window_before, unsubscribe: false) }
280+
@hotkeys.each { |h| grab_hotkey(h, subscribe: false) }
281+
end
270282
end
271283
end
272284
end
@@ -279,7 +291,7 @@ module Run
279291
end
280292
end
281293
end
282-
event_fd.wait_readable
294+
@flush_event_queue.receive
283295
end
284296
end
285297

@@ -326,6 +338,7 @@ module Run
326338
end
327339
end
328340
@mutex.unlock
341+
@flush_event_queue.send(nil)
329342
end
330343
# :ditto:
331344
def ungrab_hotkey(hotkey, *, from_window = @last_active_window, unsubscribe = true)
@@ -335,16 +348,19 @@ module Run
335348
@display.ungrab_key(hotkey.keycode, mod, grab_window: from_window)
336349
end
337350
@mutex.unlock
351+
@flush_event_queue.send(nil)
338352
end
339353
def grab_keyboard
340354
@mutex.lock
341355
@display.grab_keyboard(grab_window: @last_active_window, owner_events: true, pointer_mode: ::X11::GrabModeAsync, keyboard_mode: ::X11::GrabModeAsync, time: ::X11::CurrentTime)
342356
@mutex.unlock
357+
@flush_event_queue.send(nil)
343358
end
344359
def ungrab_keyboard
345360
@mutex.lock
346361
@display.ungrab_keyboard(time: ::X11::CurrentTime)
347362
@mutex.unlock
363+
@flush_event_queue.send(nil)
348364
end
349365
end
350366
end

0 commit comments

Comments
 (0)