diff options
| author | srdusr <[email protected]> | 2024-08-24 09:11:00 +0200 |
|---|---|---|
| committer | srdusr <[email protected]> | 2024-08-24 09:11:00 +0200 |
| commit | adc1a56982c70c06a0f8549c2c1b3bddd17930c2 (patch) | |
| tree | 16cba43721238f88a25b8fd3cadfe3382c399fab /crates/wayland | |
| parent | 281378656bdf9520e5f89d31864b9b2f822d4e3e (diff) | |
| download | srdwm-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')
| -rw-r--r-- | crates/wayland/src/input.rs | 32 |
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); |