git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commit91da44bbe27671b61fc761c8c6ca06fc179594c5
parent02e905af0b
authorLucas Galante <[email protected]>
date2026-08-04 21:21
feat: focus-follow nudges clipped windows fully into view

Clicking (or otherwise focusing) a window that is mostly visible but
clipped at a viewport edge now slides the clipped edge on-screen via the
policy crate's nudge_into_view — the minimal pan, eased by the existing
animation, instead of the all-or-nothing 75%-threshold behavior where a
focused window could stay partly hanging off-screen forever.

Co-Authored-By: Claude Fable 5 <[email protected]>

 src/server/seat.rs | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/src/server/seat.rs b/src/server/seat.rs
index 9003a3e..ff2cc0f 100644
--- a/src/server/seat.rs
+++ b/src/server/seat.rs
@@ -521,6 +521,22 @@ impl Seat {
                                 wm.target_desk_pan_x = Some(target.pan_x);
                                 wm.target_desk_pan_y = Some(target.pan_y);
                                 wm.start_panning_animation();
+                            } else if let Some(target) = crate::policy::camera::nudge_into_view(
+                                (*window).virtual_x,
+                                (*window).virtual_y,
+                                vw_w,
+                                vw_h,
+                                cam,
+                                viewport_w,
+                                viewport_h,
+                            ) {
+                                // Mostly visible but clipped: slide the
+                                // clipped edge on-screen instead of
+                                // recentering — focusing a window should
+                                // never leave part of it hanging off.
+                                wm.target_desk_pan_x = Some(target.pan_x);
+                                wm.target_desk_pan_y = Some(target.pan_y);
+                                wm.start_panning_animation();
                             }
                         }
                     }