From c3bc35ddceb830ce390a2d16f9b91bafb518de18 Mon Sep 17 00:00:00 2001 From: vndangkhoa Date: Wed, 24 Jun 2026 17:33:13 +0700 Subject: [PATCH] Fix garbled text: correct AppRun Wayland detection + atomic injection - AppRun no longer sets WAYLAND_DISPLAY on X11 (checks for wayland socket) - execute_commands now uses ydotool for both backspaces+text (same device) - Merged execute_commands and execute_commands_with_grab into one function - grab defaults to true in AppImage config --- daemon/src/main.rs | 38 +++++++++------------------- packaging/appimage/build-appimage.sh | 7 +++-- 2 files changed, 17 insertions(+), 28 deletions(-) diff --git a/daemon/src/main.rs b/daemon/src/main.rs index 5903dcc..7a1a620 100644 --- a/daemon/src/main.rs +++ b/daemon/src/main.rs @@ -428,7 +428,7 @@ fn run_with_evdev( } if let Some(ch) = key_to_char(key) { let commands = daemon.process_key(ch); - execute_commands(&*injector, &commands); + execute_commands(&*injector, &commands, false); } } else { // Grabbing mode: all output goes through uinput only. @@ -445,7 +445,7 @@ fn run_with_evdev( let commands = daemon.process_key(ch); if !commands.is_empty() { consumed_keys.insert(keycode); - execute_commands_with_grab(&*injector, &commands); + execute_commands(&*injector, &commands, true); } else { injector.send_char(ch); } @@ -554,7 +554,7 @@ fn run_stdin_mode( Ok(_) => { let ch = buffer[0] as char; let commands = daemon.process_key(ch); - execute_commands(&*injector, &commands); + execute_commands(&*injector, &commands, false); } Err(e) => { eprintln!("[vietc] Read error: {}", e); @@ -566,35 +566,21 @@ fn run_stdin_mode( Ok(()) } -fn execute_commands(injector: &dyn vietc_protocol::KeyInjector, commands: &[OutputCommand]) { - for cmd in commands { - match cmd { - OutputCommand::Type(text) => { - injector.send_string(text); - } - OutputCommand::Backspace(count) => { - injector.send_backspaces(*count); - } - } - } - injector.flush(); -} - -/// Execute commands with keyboard grabbing active. -/// Uses inject_replacement to send backspaces + text through a single -/// injection call (wtype), avoiding compositor reordering between -/// uinput (backspaces) and wtype (text). -fn execute_commands_with_grab(injector: &dyn vietc_protocol::KeyInjector, commands: &[OutputCommand]) { +/// Execute commands — accumulate backspaces and text, then inject through +/// a single channel (ydotool or wtype) to avoid reordering between backspaces +/// (uinput) and text (ydotool). +fn execute_commands(injector: &dyn vietc_protocol::KeyInjector, commands: &[OutputCommand], grabbed: bool) { let mut pending_backspaces: usize = 0; let mut pending_text = String::new(); for cmd in commands { match cmd { OutputCommand::Backspace(count) => { - // The engine adds +1 to account for the current character key, - // but with grabbing that key was never forwarded to the app, - // so we subtract 1. - let adjusted = count.saturating_sub(1); + // The engine adds +1 to account for the current character key. + // With grabbing that key was never forwarded to the app, so + // we subtract 1. Without grab, the key WAS forwarded, so we + // use the full count. + let adjusted = if grabbed { count.saturating_sub(1) } else { *count }; pending_backspaces += adjusted; } OutputCommand::Type(text) => { diff --git a/packaging/appimage/build-appimage.sh b/packaging/appimage/build-appimage.sh index 146fa72..d331ada 100644 --- a/packaging/appimage/build-appimage.sh +++ b/packaging/appimage/build-appimage.sh @@ -139,11 +139,14 @@ export PATH="$HERE/usr/bin:$PATH" # Start daemon (kill old non-root one first if we have root) SUDO_CMD="" -# Fix Wayland env for root: sudo resets XDG_RUNTIME_DIR, breaking wl-copy +# Fix Wayland env for root: sudo resets XDG_RUNTIME_DIR, breaking wtype/wl-copy. +# Only set WAYLAND_DISPLAY if the user actually has a Wayland session. if [ "$(id -u)" = "0" ] && [ -z "$XDG_RUNTIME_DIR" ] && [ -n "$SUDO_USER" ]; then USER_UID=$(id -u "$SUDO_USER" 2>/dev/null || echo 1000) export XDG_RUNTIME_DIR="/run/user/$USER_UID" - export WAYLAND_DISPLAY="${WAYLAND_DISPLAY:-wayland-0}" + if [ -d "/run/user/$USER_UID" ] && ls "/run/user/$USER_UID/wayland-*" >/dev/null 2>&1; then + export WAYLAND_DISPLAY="${WAYLAND_DISPLAY:-wayland-0}" + fi fi if command -v pkexec >/dev/null && [ -z "$WAYLAND_DISPLAY" ]; then