Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
fix(input): Super-held adjust mode keeps focus; hover-to-focus is overview only
With Super held at zoom 1 the frame stays on the focused window rather
than following the pointer, so a focus chord pressed next (super+h/j/k/l)
acts on the window the user had. Any window's body still drags; the grab
focuses it on press. Overview is unchanged.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
CLAUDE.md | 6 ++++--
src/server/cursor.rs | 15 ++++++++++-----
2 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/CLAUDE.md b/CLAUDE.md
index ed280b7..3470cbf 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -426,8 +426,10 @@ where the old band sat outside them.
this arrangement exists to prevent. Note the *grab* zone stays the full
even band (the four catcher rects) even where the ring is drawn thin: the
swell is ornament, and a corner you can see but not grab would be worse.
-- **Holding Super is window-adjust mode at zoom 1**: the same handles,
- hover-to-focus and body-drag as overview, gated by one predicate,
+- **Holding Super is window-adjust mode at zoom 1**: the same handles and
+ body-drag as overview (but NOT hover-to-focus — the frame stays on the
+ focused window, so a focus chord pressed next acts on the window the
+ user had), gated by one predicate,
`WindowManager::window_adjust_active()` (overview OR `adjust_held`).
`adjust_held` is refreshed from the keyboard's modifier mask on every
modifiers event (`refresh_adjust_held`), which also re-runs the pointer
diff --git a/src/server/cursor.rs b/src/server/cursor.rs
index 00029c8..686b4b9 100644
--- a/src/server/cursor.rs
+++ b/src/server/cursor.rs
@@ -876,10 +876,11 @@ impl Cursor {
&& !hovered_chrome
&& (*server).wm.window_adjust_active()
{
- // Focus follows the pointer in overview — and while Super is
- // held, which is the same adjust mode at zoom 1: the ring is
- // drawn on the focused window only, so hovering is how it
- // moves between windows without a click. Guarded on an actual change —
+ // Focus follows the pointer in overview: the ring is drawn on
+ // the focused window only, so hovering is how it moves between
+ // windows without a click. (Super-held adjust mode takes this
+ // branch too, for the pointer-focus clear below, but not the
+ // refocus.) Guarded on an actual change —
// seat.focus raises a Floating window BEFORE its same-focus
// short-circuit, so an unguarded call would raise and relayout
// on every motion event. And with the pan suppressed: hovering
@@ -893,7 +894,11 @@ impl Cursor {
// launcher's own first configure — so a stationary pointer
// resting on a world window was refocusing that window and
// dismissing the launcher the instant it mapped.
- if !hovered_toplevel.is_null()
+ // Overview only: with Super held at zoom 1 the frame stays
+ // on the focused window, so a focus chord pressed next acts
+ // on the window the user had, not the one under the pointer.
+ if (*server).wm.mode == crate::window_manager::WindowManagerMode::Overview
+ && !hovered_toplevel.is_null()
&& !(*self.seat).focus_is_chrome()
&& (*self.seat).focused
!= crate::seat::Focus::Window(hovered_toplevel)