From adc1a56982c70c06a0f8549c2c1b3bddd17930c2 Mon Sep 17 00:00:00 2001 From: srdusr <99972264+srdusr@users.noreply.github.com> Date: Sat, 24 Aug 2024 09:11:00 +0200 Subject: 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. --- crates/config/src/engine/support.rs | 24 ++++++++++++++---------- crates/core/src/manager/mod.rs | 13 +++++++++++++ crates/srdwm/src/main.rs | 4 ++++ crates/wayland/src/input.rs | 32 ++++++++++++++++++++++++++++++++ docs/DEFAULTS.md | 31 ++++++++++++++++--------------- 5 files changed, 79 insertions(+), 25 deletions(-) diff --git a/crates/config/src/engine/support.rs b/crates/config/src/engine/support.rs index 7b42f53..9346499 100644 --- a/crates/config/src/engine/support.rs +++ b/crates/config/src/engine/support.rs @@ -152,9 +152,12 @@ pub(super) fn default_config() -> HashMap { // apart from "user explicitly chose a value" and hand the *unset* case // to whichever backend ends up connecting instead of deciding for it. set("general.focus_follows_mouse", Bool(false)); - set("general.mouse_follows_focus", Bool(true)); set("general.auto_raise", Bool(false)); - set("general.auto_focus", Bool(true)); + // `mouse_follows_focus` (warp the pointer to match a keybinding-driven + // focus change, the reverse of the two above) and `auto_focus` (no + // clear distinct meaning found beyond what plain click-to-focus already + // does) are deliberately not seeded - neither is implemented, same + // reasoning as `workspace.auto_switch`'s own absence. set("monitor.primary_layout", String("dynamic".into())); set("monitor.secondary_layout", String("tiling".into())); @@ -166,14 +169,15 @@ pub(super) fn default_config() -> HashMap { // "this monitor's workspace count" describe a design that doesn't // exist. `workspace.count` is the one knob that actually does anything. - set("window.focus_follows_mouse", Bool(false)); - set("window.mouse_follows_focus", Bool(true)); - set("window.auto_raise", Bool(false)); - set("window.auto_focus", Bool(true)); - set("window.raise_on_focus", Bool(true)); - set("window.remember_position", Bool(true)); - set("window.remember_size", Bool(true)); - set("window.remember_state", Bool(true)); + // The `window.*` namespace this codebase's own `docs/DEFAULTS.md` + // documented (focus_follows_mouse/mouse_follows_focus/auto_raise/ + // auto_focus/raise_on_focus/remember_position/remember_size/ + // remember_state) was a full, entirely unimplemented duplicate of + // `general.*`'s own focus keys plus three genuinely unbuilt + // per-app-window-state-persistence features - removed rather than + // seeded, same reasoning as everything else in this comment block. + // `general.focus_follows_mouse`/`general.auto_raise` above are the + // real, working versions of the one pair that *is* implemented. set("workspace.count", Number(10.0)); set("workspace.names", List(["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"].map(|s| s.to_string()).to_vec())); diff --git a/crates/core/src/manager/mod.rs b/crates/core/src/manager/mod.rs index 609b87f..6285736 100644 --- a/crates/core/src/manager/mod.rs +++ b/crates/core/src/manager/mod.rs @@ -86,6 +86,17 @@ pub struct WindowManager { /// redraws constantly - see `crates/wayland/src/rounded_corners.rs`). /// `Some(_)` only when the user explicitly set it, and wins either way. pub rounded_corners_enabled: Option, + /// Whether hovering a window (no click needed) focuses it, read from + /// `general.focus_follows_mouse`. Off by default - matches + /// `general.focus_follows_mouse`'s own documented default, and every + /// desktop's convention of click-to-focus unless a user explicitly + /// opts into the classic X11 sloppy-focus behaviour. + pub focus_follows_mouse: bool, + /// Whether hover-driven focus (above) also raises the window, not just + /// focuses it - read from `general.auto_raise`. Meaningless (never + /// consulted) while `focus_follows_mouse` is off, since a plain click + /// already raises unconditionally regardless of this. + pub auto_raise: bool, /// Default decoration colours and border width, read from `theme.colors.*`/ /// `theme.decorations.*`. See `ThemeConfig`'s own doc comment. pub theme: ThemeConfig, @@ -131,6 +142,8 @@ impl WindowManager { shadows_enabled: true, resize_margin: RESIZE_MARGIN, rounded_corners_enabled: None, + focus_follows_mouse: false, + auto_raise: false, theme: ThemeConfig::default(), drag: None, resize: None, diff --git a/crates/srdwm/src/main.rs b/crates/srdwm/src/main.rs index 336bb2e..5c2bfea 100644 --- a/crates/srdwm/src/main.rs +++ b/crates/srdwm/src/main.rs @@ -155,6 +155,8 @@ fn apply_general_settings(engine: &Engine, wm: &Rc>) { // - see `WindowManager::rounded_corners_enabled`'s doc comment for why // this can't just be `get_bool(..., true)` like every other flag here. let rounded_corners = engine.get("general.rounded_corners").and_then(|v| v.as_bool()); + let focus_follows_mouse = engine.get_bool("general.focus_follows_mouse", false); + let auto_raise = engine.get_bool("general.auto_raise", false); // Only the three `theme.*` keys with an unambiguous, already-rendered // counterpart are wired - see `srdwm_core::ThemeConfig`'s doc comment. @@ -185,6 +187,8 @@ fn apply_general_settings(engine: &Engine, wm: &Rc>) { wm.shadows_enabled = shadows; wm.resize_margin = resize_margin; wm.rounded_corners_enabled = rounded_corners; + wm.focus_follows_mouse = focus_follows_mouse; + wm.auto_raise = auto_raise; wm.theme = theme; wm.auto_back_and_forth = engine.get_bool("workspace.auto_back_and_forth", false); } 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