fix: non-blocking XPending event loop + auto re-grab on grab loss
- Use XPending() to check for events before XNextEvent (non-blocking) - Add is_grabbed() and has_pending_events() public methods - Auto re-grab keyboard when grab is silently lost (tray, WM focus) - Fixes AppImage daemon receiving zero keystroke events
This commit is contained in:
parent
db3d0cefcd
commit
666f1b400e
4 changed files with 27 additions and 2 deletions
|
|
@ -814,6 +814,12 @@ fn run_with_x11(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Re-grab if the grab was silently lost (tray started, WM took focus, etc.)
|
||||||
|
if !capture.is_grabbed() {
|
||||||
|
eprintln!("[vietc] Keyboard grab lost — re-grabbing");
|
||||||
|
capture.grab_keyboard();
|
||||||
|
}
|
||||||
|
|
||||||
thread::sleep(Duration::from_millis(10));
|
thread::sleep(Duration::from_millis(10));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -208,7 +208,7 @@ fi
|
||||||
if [ -z "$NEED_ROOT" ]; then
|
if [ -z "$NEED_ROOT" ]; then
|
||||||
# X11: no root needed
|
# X11: no root needed
|
||||||
pkill -x vietc 2>/dev/null; sleep 0.3
|
pkill -x vietc 2>/dev/null; sleep 0.3
|
||||||
"$HERE/usr/bin/vietc" >"$HERE/vietc-daemon.log" 2>&1 &
|
"$HERE/usr/bin/vietc" >"$HOME/.config/vietc/vietc-daemon.log" 2>&1 &
|
||||||
DAEMON_PID=$!
|
DAEMON_PID=$!
|
||||||
else
|
else
|
||||||
# Fix Wayland env for root: sudo resets XDG_RUNTIME_DIR, breaking wtype/wl-copy.
|
# Fix Wayland env for root: sudo resets XDG_RUNTIME_DIR, breaking wtype/wl-copy.
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ echo "=== Building Viet+ .deb package v${VERSION} ==="
|
||||||
# Build binaries (all features: x11 + wayland)
|
# Build binaries (all features: x11 + wayland)
|
||||||
echo "[1/5] Building binaries..."
|
echo "[1/5] Building binaries..."
|
||||||
cargo build --release --features "x11,wayland" --manifest-path "$PROJECT_ROOT/Cargo.toml"
|
cargo build --release --features "x11,wayland" --manifest-path "$PROJECT_ROOT/Cargo.toml"
|
||||||
(cd "$PROJECT_ROOT/ui" && cargo build --release) || echo " Warning: UI tray not built (libdbus-1-dev may be missing)"
|
(cd "$PROJECT_ROOT/ui" && export PKG_CONFIG_PATH="/tmp/dbus-dev/extracted/usr/lib/x86_64-linux-gnu/pkgconfig:${PKG_CONFIG_PATH:-}" && export RUSTFLAGS="-L /tmp/dbus-dev/lib" && cargo build --release) || echo " Warning: UI tray not built (libdbus-1-dev may be missing)"
|
||||||
echo " Done."
|
echo " Done."
|
||||||
|
|
||||||
# Clean and create staging
|
# Clean and create staging
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ struct X11Lib {
|
||||||
x_default_root_window: unsafe extern "C" fn(*mut Display) -> Window,
|
x_default_root_window: unsafe extern "C" fn(*mut Display) -> Window,
|
||||||
x_grab_keyboard: unsafe extern "C" fn(*mut Display, Window, c_int, c_int, c_int, Time) -> c_int,
|
x_grab_keyboard: unsafe extern "C" fn(*mut Display, Window, c_int, c_int, c_int, Time) -> c_int,
|
||||||
x_ungrab_keyboard: unsafe extern "C" fn(*mut Display, Time) -> c_int,
|
x_ungrab_keyboard: unsafe extern "C" fn(*mut Display, Time) -> c_int,
|
||||||
|
x_pending: unsafe extern "C" fn(*mut Display) -> c_int,
|
||||||
x_next_event: unsafe extern "C" fn(*mut Display, *mut XEvent),
|
x_next_event: unsafe extern "C" fn(*mut Display, *mut XEvent),
|
||||||
x_lookup_string: unsafe extern "C" fn(*mut XKeyEvent, *mut c_char, c_int, *mut KeySym, *mut c_int) -> c_int,
|
x_lookup_string: unsafe extern "C" fn(*mut XKeyEvent, *mut c_char, c_int, *mut KeySym, *mut c_int) -> c_int,
|
||||||
x_utf8_lookup_string: Option<unsafe extern "C" fn(*mut XKeyEvent, *mut c_char, c_int, *mut KeySym, *mut c_int) -> c_int>,
|
x_utf8_lookup_string: Option<unsafe extern "C" fn(*mut XKeyEvent, *mut c_char, c_int, *mut KeySym, *mut c_int) -> c_int>,
|
||||||
|
|
@ -66,6 +67,7 @@ impl X11Lib {
|
||||||
let x_default_root_window = sym!("XDefaultRootWindow");
|
let x_default_root_window = sym!("XDefaultRootWindow");
|
||||||
let x_grab_keyboard = sym!("XGrabKeyboard");
|
let x_grab_keyboard = sym!("XGrabKeyboard");
|
||||||
let x_ungrab_keyboard = sym!("XUngrabKeyboard");
|
let x_ungrab_keyboard = sym!("XUngrabKeyboard");
|
||||||
|
let x_pending = sym!("XPending");
|
||||||
let x_next_event = sym!("XNextEvent");
|
let x_next_event = sym!("XNextEvent");
|
||||||
let x_lookup_string = sym!("XLookupString");
|
let x_lookup_string = sym!("XLookupString");
|
||||||
let x_utf8_lookup_string = dlsym(handle, b"Xutf8LookupString\0".as_ptr() as *const c_char);
|
let x_utf8_lookup_string = dlsym(handle, b"Xutf8LookupString\0".as_ptr() as *const c_char);
|
||||||
|
|
@ -83,6 +85,7 @@ impl X11Lib {
|
||||||
x_default_root_window,
|
x_default_root_window,
|
||||||
x_grab_keyboard,
|
x_grab_keyboard,
|
||||||
x_ungrab_keyboard,
|
x_ungrab_keyboard,
|
||||||
|
x_pending,
|
||||||
x_next_event,
|
x_next_event,
|
||||||
x_lookup_string,
|
x_lookup_string,
|
||||||
x_utf8_lookup_string,
|
x_utf8_lookup_string,
|
||||||
|
|
@ -212,11 +215,27 @@ impl X11Capture {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn has_pending_events(&self) -> bool {
|
||||||
|
if !self.grabbed {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
unsafe { (self.lib.x_pending)(self.display) > 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_grabbed(&self) -> bool {
|
||||||
|
self.grabbed
|
||||||
|
}
|
||||||
|
|
||||||
pub fn next_event(&mut self) -> Option<X11KeyEvent> {
|
pub fn next_event(&mut self) -> Option<X11KeyEvent> {
|
||||||
if !self.grabbed {
|
if !self.grabbed {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Non-blocking: only read if events are pending
|
||||||
|
if !self.has_pending_events() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
let mut event: XEvent = unsafe { std::mem::zeroed() };
|
let mut event: XEvent = unsafe { std::mem::zeroed() };
|
||||||
unsafe {
|
unsafe {
|
||||||
(self.lib.x_next_event)(self.display, &mut event);
|
(self.lib.x_next_event)(self.display, &mut event);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue