Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
fix(gestures): a swipe ends the login settling phase
Restored windows pan the camera on their first focus only once the
session has seen deliberate input, so apps settling in at login do not
drag the view around. Only button and key presses counted, so a login
navigated purely by three-finger swipes left each restored window's
first focus wherever it sat, often half off screen, while a second focus
of the same window panned.
The start of a touchpad swipe or pinch now counts as deliberate input
too. A hold does not, since one begins whenever fingers rest on the pad,
and pointer motion still does not.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CLAUDE.md | 9 +++++++++
src/server/cursor.rs | 16 ++++++++++++++++
2 files changed, 25 insertions(+)
diff --git a/CLAUDE.md b/CLAUDE.md
index cf5c0639..05ba432f 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -668,6 +668,15 @@ what the user pans along (cce-data-editor parked left of the first column
came back mid-view every login before 2026-09-14). The recall is for a
window with no tiled neighbour within a screen.
+Restored windows map unfocused, and their FIRST focus pans the camera only
+once the session has seen deliberate input (`WindowManager::startup_input_seen`,
+gated in `Seat::focus`), so apps settling in at login do not drag the view
+around. Deliberate means a button press, a key press, or the start of a
+touchpad swipe or pinch (`handle_swipe_begin`/`handle_pinch_begin`); pointer
+motion and a hold do not count. Swipes were added on 2026-09-26: a login
+navigated only by three-finger swipes left each restored window's first
+focus wherever it sat, often half off screen, while a second focus panned.
+
### xdg-activation
`handle_request_activate` (`server.rs`) runs for every activation wlroots
diff --git a/src/server/cursor.rs b/src/server/cursor.rs
index 738f86c8..01e9a845 100644
--- a/src/server/cursor.rs
+++ b/src/server/cursor.rs
@@ -3704,6 +3704,14 @@ unsafe extern "C" fn handle_swipe_begin(listener: *mut ffi::wl_listener, data: *
return;
}
seat.handle_activity();
+ // A swipe or pinch is deliberate input, like a click or a key: it ends
+ // the session-restore settling phase (`WindowManager::startup_input_seen`),
+ // so the first focus of a restored window pans to it. Until 2026-09-26
+ // only buttons and keys counted, and after a login navigated purely by
+ // three-finger swipes, each restored window's first focus left it
+ // wherever it sat, often half off screen. Holds do not count: one begins
+ // whenever fingers merely rest on the pad.
+ (*seat.server).wm.startup_input_seen = true;
cursor.gesture_dx = 0.0;
cursor.gesture_dy = 0.0;
@@ -4008,6 +4016,14 @@ unsafe extern "C" fn handle_pinch_begin(listener: *mut ffi::wl_listener, data: *
return;
}
seat.handle_activity();
+ // A swipe or pinch is deliberate input, like a click or a key: it ends
+ // the session-restore settling phase (`WindowManager::startup_input_seen`),
+ // so the first focus of a restored window pans to it. Until 2026-09-26
+ // only buttons and keys counted, and after a login navigated purely by
+ // three-finger swipes, each restored window's first focus left it
+ // wherever it sat, often half off screen. Holds do not count: one begins
+ // whenever fingers merely rest on the pad.
+ (*seat.server).wm.startup_input_seen = true;
cursor.gesture_scale = 1.0;
cursor.gesture_triggered = false;