fix: use xdotool for Unicode injection instead of clipboard paste

On X11 (Linux Mint, Ubuntu), clipboard-based Unicode injection was
failing — backspace was sent but the Vietnamese character never
appeared because xclip paste via Ctrl+V wasn't reliable from a
root uinput process.

Now send_string tries xdotool type first (XTest-based, doesn't touch
the user's clipboard), falling back to clipboard paste only on Wayland
or when xdotool is unavailable.
This commit is contained in:
Khoa Vo 2026-07-02 12:03:21 +07:00
parent d48bccd531
commit 4baa460562

View file

@ -222,7 +222,12 @@ impl KeyInjector for UinputInjector {
return InjectResult::Success;
}
// Unicode text: clipboard copy + paste (reliable method)
// Unicode text: try xdotool type first (works on X11, doesn't touch clipboard)
if self.type_via_xdotool(s) {
return InjectResult::Success;
}
// Fallback: clipboard copy + paste
if !self.paste_via_clipboard(s) {
eprintln!(
"[vietc] send_string failed for '{}' (clipboard unavailable)",
@ -388,6 +393,27 @@ impl UinputInjector {
InjectResult::Success
}
/// Type Unicode text via xdotool (X11 only). Returns true on success.
/// More reliable than clipboard paste — doesn't overwrite the user's clipboard
/// and works with XTest directly for proper Unicode key injection.
fn type_via_xdotool(&self, text: &str) -> bool {
let is_wayland = std::env::var("WAYLAND_DISPLAY").is_ok();
if is_wayland {
return false;
}
let mut cmd = Self::user_cmd("xdotool");
cmd.args(["type", "--clearmodifiers", text]);
cmd.stdout(std::process::Stdio::null());
cmd.stderr(std::process::Stdio::null());
match cmd.output() {
Ok(output) => output.status.success(),
Err(e) => {
eprintln!("[vietc] xdotool type failed: {}", e);
false
}
}
}
/// Read the user's current clipboard contents (wl-paste on Wayland, xclip
/// on X11). Returns None if no clipboard tool is available or it is empty.
fn read_clipboard() -> Option<String> {