fix: non-grabbed evdev on X11 — switch to XTest injection for instant correction

On X11, uinput injection has high latency (kernel → libinput → X server)
compared to XTest' which writes events directly into the X11 event queue.
Physical key events reach the app before the uinput backspace correction,
causing the VNI control key digit to flash on screen.

Fix: when non-grabbed mode is entered on X11 (grab failed or ungrab),
replace the uinput injector with X11Injector (XTest). XTest events
are processed synchronously by X server and take effect before
subsequent physical events.
This commit is contained in:
Khoa Vo 2026-07-04 16:29:48 +07:00
parent 6756340cb0
commit 5f0f059139

View file

@ -1309,7 +1309,7 @@ fn run_with_evdev(
_engine_enabled: Arc<AtomicBool>,
display: display::DisplayServer,
) -> 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)
let primary_idx = 0usize;
@ -1336,6 +1336,17 @@ fn run_with_evdev(
false
};
// Non-grabbed on X11: use XTest injection for fast, synchronous correction
if !grabbed {
#[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)");
}
}
}
let mut consumed_keys: HashSet<u16> = HashSet::new();
let mut last_active_window = String::new();
let mut last_window_class = String::new();
@ -1374,6 +1385,14 @@ fn run_with_evdev(
let _ = devices[primary_idx].0.ungrab();
grabbed = false;
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;
}