From 3f17a7b63239ddecfcf010da6f4c892a9cb78b05 Mon Sep 17 00:00:00 2001 From: Stephen Waits Date: Sun, 5 Apr 2026 13:15:43 -0600 Subject: [PATCH] fix: add focus click with hold time before drag to activate target window --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/wayland.rs | 16 +++++++++++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b8a5dd9..498cc27 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -196,7 +196,7 @@ dependencies = [ [[package]] name = "mousefree" -version = "1.0.2" +version = "1.0.3" dependencies = [ "anyhow", "fontdue", diff --git a/Cargo.toml b/Cargo.toml index 1ef3a61..f1b8d3c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "mousefree" -version = "1.0.2" +version = "1.0.3" edition = "2021" license = "MIT" description = "Keyboard-driven mouse navigation for Wayland" diff --git a/src/wayland.rs b/src/wayland.rs index cc9e7ae..d2d4043 100644 --- a/src/wayland.rs +++ b/src/wayland.rs @@ -43,6 +43,8 @@ const MOD_ALT: u32 = 8; // Drag animation timing. const DRAG_SETTLE_MS: u64 = 25; +const DRAG_FOCUS_CLICK_HOLD_MS: u64 = 50; +const DRAG_FOCUS_CLICK_PAUSE_MS: u64 = 500; const DRAG_PRESS_SETTLE_MS: u64 = 60; const DRAG_INTERP_STEPS: u32 = 12; const DRAG_STEP_DELAY_MS: u64 = 2; @@ -311,11 +313,23 @@ impl WaylandBackend { self.teardown_surface()?; let (sw, sh) = (self.state.screen_w, self.state.screen_h); - // 1. Move to the drag origin and let focus settle. + // 1. Click at the drag origin to activate/focus the target window. + // Without this, apps like zellij ignore the drag because the + // surface isn't activated yet. self.send_motion(x1, y1, sw, sh)?; self.roundtrip("motion to drag start")?; sleep(Duration::from_millis(DRAG_SETTLE_MS)); + self.send_button(BTN_LEFT, ButtonState::Pressed)?; + self.roundtrip("focus click press")?; + sleep(Duration::from_millis(DRAG_FOCUS_CLICK_HOLD_MS)); + self.send_button(BTN_LEFT, ButtonState::Released)?; + self.roundtrip("focus click release")?; + + // Wait past the double-click window so the focus click and the + // upcoming press-and-hold are never interpreted as a double-click. + sleep(Duration::from_millis(DRAG_FOCUS_CLICK_PAUSE_MS)); + // 2. Press and hold — give the app time to register the press. self.send_button(BTN_LEFT, ButtonState::Pressed)?; self.roundtrip("press at drag start")?;