srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/wayland/src/input.rs
diff options
context:
space:
mode:
authorsrdusr <[email protected]>2024-08-24 09:11:00 +0200
committersrdusr <[email protected]>2024-08-24 09:11:00 +0200
commitadc1a56982c70c06a0f8549c2c1b3bddd17930c2 (patch)
tree16cba43721238f88a25b8fd3cadfe3382c399fab /crates/wayland/src/input.rs
parent281378656bdf9520e5f89d31864b9b2f822d4e3e (diff)
downloadsrdwm-adc1a56982c70c06a0f8549c2c1b3bddd17930c2.tar.gz
srdwm-adc1a56982c70c06a0f8549c2c1b3bddd17930c2.zip
Implement general.focus_follows_mouse/auto_raise; remove the rest as dead
Auditing "clicking behavior and basics": general.focus_follows_mouse, general.mouse_follows_focus, general.auto_raise, general.auto_focus, the entire window.* namespace (8 more keys, a full duplicate of the same four plus remember_position/size/state), and general. smart_placement/border_width were all seeded into default_config() and documented in DEFAULTS.md, but none were read anywhere - srd.set()/ srd.get() on any of them silently succeeded while doing nothing. focus_follows_mouse is real, well-defined, and directly relevant to clicking basics - implemented it plus auto_raise (raise, not just focus, on hover) rather than just deleting the promise like the others. WindowManager gained focus_follows_mouse/auto_raise bools, wired from apply_general_settings the same way every other general.* flag is. handle_pointer_position now tracks whichever window (content or decoration) is under the pointer and, when the setting is on and that differs from the currently-focused window, focuses it through the same focus_window() free function every click-driven focus change already uses (real keyboard focus, not just core state) - skipped entirely while dragging/resizing or over a layer-shell surface, so the pointer sweeping over other windows mid-drag or hovering a bar can't steal focus from what's actually being manipulated. mouse_follows_focus (pointer warp on keybinding-driven focus change) and auto_focus (no clear distinct meaning beyond click-to-focus) stay unimplemented and are now undocumented rather than promised.
Diffstat (limited to 'crates/wayland/src/input.rs')
-rw-r--r--crates/wayland/src/input.rs32
1 files changed, 32 insertions, 0 deletions
diff --git a/crates/wayland/src/input.rs b/crates/wayland/src/input.rs
index 264c986..4b98a8a 100644
--- a/crates/wayland/src/input.rs
+++ b/crates/wayland/src/input.rs
@@ -133,6 +133,12 @@ pub(crate) fn handle_pointer_position(state: &mut CompState, pos: Point<f64, Log
let hit = state.wm.borrow().hit_test(pos.x as i32, pos.y as i32);
let under = state.space.element_under(pos).map(|(w, loc)| (w.clone(), loc));
let over_content = under.is_some();
+ // Whichever core window the pointer is over right now, decoration or
+ // content, for `general.focus_follows_mouse` below - `None` while over
+ // a layer-shell surface or bare desktop, same as everything else here.
+ let hovered_id = hit
+ .map(|(id, _)| id)
+ .or_else(|| under.as_ref().and_then(|(window, _)| dwindow_wl_surface(window)).and_then(|s| state.surface_to_id.get(&s).copied()));
let Some(pointer) = state.seat.get_pointer() else { return };
if let Some((surface, loc)) = layer_hit {
@@ -198,7 +204,33 @@ pub(crate) fn handle_pointer_position(state: &mut CompState, pos: Point<f64, Log
wm.update_resize(pos.x as i32, pos.y as i32);
}
let focused = wm.focused_id();
+ // `general.focus_follows_mouse`: hovering a *different* window focuses
+ // it, no click needed - classic X11 sloppy focus. Gated on `hit`/
+ // `under` actually landing on a window (not a layer surface or bare
+ // desktop) and on not already being mid-drag/resize, where the pointer
+ // sweeps over unrelated windows constantly and none of that should
+ // steal focus from whatever's actually being dragged. `hovered_id !=
+ // focused` both skips redundant work on every one of the many motion
+ // events a stationary pointer over an already-focused window still
+ // generates, and is what makes `auto_raise` (below) only fire on an
+ // actual focus change rather than every motion tick too.
+ let focus_follow_target =
+ (wm.focus_follows_mouse && !dragging_or_resizing && !over_layer_surface).then_some(hovered_id).flatten().filter(|id| Some(*id) != focused);
+ if let Some(id) = focus_follow_target {
+ if wm.auto_raise {
+ // `raise_window` alone here, not `focus_window` - the actual
+ // core + real Wayland/X11 keyboard focus change happens once,
+ // below, through the same `focus_window` free function every
+ // click-driven focus change already goes through (sets real
+ // keyboard focus too, which `WindowManager::focus_window`
+ // alone does not).
+ wm.raise_window(id);
+ }
+ }
drop(wm);
+ if let Some(id) = focus_follow_target {
+ focus_window(state, id);
+ }
if dragging_or_resizing {
if let Some(id) = focused {
state.sync_geometry(id);