From 24f9bc8c7e50e9d65e0ae77b049a62ea0a343c5c Mon Sep 17 00:00:00 2001 From: Khoa Vo Date: Thu, 2 Jul 2026 13:33:41 +0700 Subject: [PATCH] daemon: fall back to X11 capture when evdev produces no events When evdev's EVIOCGRAB works (returns success) but no keyboard events arrive (common in VMs where input bypasses the grabbed device), the daemon previously exited silently after the 30-second safety timeout. Now it falls through to X11 XRecord capture as a fallback, which works reliably in VMs by intercepting keystrokes at the X11 protocol level rather than the evdev level. - run_with_evdev no longer uses 'return', so main() continues to X11 capture after evdev exits (timeout or error) --- daemon/src/main.rs | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/daemon/src/main.rs b/daemon/src/main.rs index 00f8333..48d7bcd 100644 --- a/daemon/src/main.rs +++ b/daemon/src/main.rs @@ -855,20 +855,33 @@ fn main() -> Result<(), Box> { }); } - // Try evdev first (more reliable than X11 XRecord) + // Try evdev first (more reliable than X11 XRecord in most environments). + // If the evdev device opens but produces no events (common in VMs where + // keyboard input bypasses the evdev grab), run_with_evdev will exit via + // the 30-second safety timeout — we fall through to X11 capture. match open_keyboard_device() { Ok((device, path)) => { log_info(&format!("[vietc] Keyboard device: {}", path)); - return run_with_evdev( + match run_with_evdev( device, &mut daemon, - shared_active_window, - shared_window_class, - config_changed, - status_changed, - engine_enabled, + shared_active_window.clone(), + shared_window_class.clone(), + config_changed.clone(), + status_changed.clone(), + engine_enabled.clone(), display, - ); + ) { + Ok(()) => { + log_info("[vietc] evdev returned, trying X11 capture as fallback"); + } + Err(e) => { + log_info(&format!( + "[vietc] evdev exited with error: {} — trying X11 capture", + e + )); + } + } } Err(e) => { log_info(&format!("[vietc] evdev not available: {}", e)); @@ -882,10 +895,10 @@ fn main() -> Result<(), Box> { return run_with_x11( capture, &mut daemon, - shared_active_window.clone(), - config_changed.clone(), - status_changed.clone(), - engine_enabled.clone(), + shared_active_window, + config_changed, + status_changed, + engine_enabled, ); } else { log_info("[vietc] X11 not available, falling back");