Revert "fix: skip non-grabbed evdev on X11, fall through to X11 keymap capture" — X11 keymap + uinput creates feedback loop through XQueryKeymap

This commit is contained in:
Khoa Vo 2026-07-04 16:51:50 +07:00
parent aa8a0624fc
commit 48cd360e37

View file

@ -1309,12 +1309,12 @@ fn run_with_evdev(
_engine_enabled: Arc<AtomicBool>, _engine_enabled: Arc<AtomicBool>,
display: display::DisplayServer, display: display::DisplayServer,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), Box<dyn std::error::Error>> {
let injector = create_injector(display)?; let mut injector = create_injector(display)?;
// Use the first device for grab (only one device can be grabbed at a time) // Use the first device for grab (only one device can be grabbed at a time)
let primary_idx = 0usize; let primary_idx = 0usize;
let mut grabbed = match devices.first() { let mut grabbed = if daemon.grab_enabled && !devices.is_empty() {
Some(_) if daemon.grab_enabled => match devices[primary_idx].0.grab() { match devices[primary_idx].0.grab() {
Ok(()) => { Ok(()) => {
log_info("[vietc] Keyboard grabbed — race condition eliminated"); log_info("[vietc] Keyboard grabbed — race condition eliminated");
true true
@ -1324,28 +1324,27 @@ fn run_with_evdev(
"[vietc] Could not grab keyboard: {} (run as root for grab)", "[vietc] Could not grab keyboard: {} (run as root for grab)",
e e
)); ));
// On X11, fall through to keymap capture instead of non-grabbed evdev log_info("[vietc] Falling back to non-grabbing mode (may have race)");
#[cfg(feature = "x11")]
if display != display::DisplayServer::Wayland {
log_info("[vietc] X11 detected — trying X11 keymap capture");
return Ok(());
}
log_info("[vietc] Falling back to non-grabbing evdev mode (may have race)");
false false
} }
},
_ => {
log_info("[vietc] No keyboard devices available for grab");
false
} }
} else {
if !daemon.grab_enabled {
log_info("[vietc] Keyboard grab disabled (config grab = false)");
log_info("[vietc] Set grab = true in vietc.toml to enable (needs root)");
}
false
}; };
// On X11 without evdev grab, use keymap capture instead of non-grabbed evdev. // Non-grabbed on X11: use XTest injection for fast, synchronous correction
// Reason: XTest backspace events feed back into evdev, corrupting the engine. if !grabbed {
#[cfg(feature = "x11")] #[cfg(feature = "x11")]
if !grabbed && display != display::DisplayServer::Wayland { if display != display::DisplayServer::Wayland {
log_info("[vietc] X11 without evdev grab — switching to X11 keymap capture"); if let Ok(x11_inj) = vietc_protocol::x11_inject::X11Injector::new() {
return Ok(()); injector = Box::new(x11_inj);
log_info("[vietc] Non-grabbed: using X11 injection (faster than uinput)");
}
}
} }
let mut consumed_keys: HashSet<u16> = HashSet::new(); let mut consumed_keys: HashSet<u16> = HashSet::new();
@ -1380,18 +1379,20 @@ fn run_with_evdev(
} }
if grabbed && idle_polls >= 3 && last_event_time.elapsed() > std::time::Duration::from_millis(200) { if grabbed && idle_polls >= 3 && last_event_time.elapsed() > std::time::Duration::from_millis(200) {
#[cfg(feature = "x11")]
if display != display::DisplayServer::Wayland {
log_info("[vietc] No events via grab on X11 — exiting evdev for X11 keymap capture");
let _ = devices[primary_idx].0.ungrab();
return Ok(());
}
log_info( log_info(
"[vietc] No events received via grab — releasing grab, continuing in non-grabbed evdev mode", "[vietc] No events received via grab — releasing grab, continuing in non-grabbed evdev mode",
); );
let _ = devices[primary_idx].0.ungrab(); let _ = devices[primary_idx].0.ungrab();
grabbed = false; grabbed = false;
log_info("[vietc] Non-grabbed mode: polling all evdev devices for keystrokes"); log_info("[vietc] Non-grabbed mode: polling all evdev devices for keystrokes");
// Switch to XTest injection for fast synchronous non-grabbed correction
#[cfg(feature = "x11")]
if display != display::DisplayServer::Wayland {
if let Ok(x11_inj) = vietc_protocol::x11_inject::X11Injector::new() {
injector = Box::new(x11_inj);
log_info("[vietc] Non-grabbed: using X11 injection (faster than uinput)");
}
}
continue; continue;
} }