Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
fix: restrict resize zone to outer border edge and implement layout resize preservation for floating windows
src/server/cursor.rs | 20 ++++++++++++++------
src/server/seat.rs | 9 +++++++++
src/server/window_manager.rs | 41 +++++++++++++++++++++++++++++++++++++++--
3 files changed, 62 insertions(+), 8 deletions(-)
diff --git a/src/server/cursor.rs b/src/server/cursor.rs
index 52f3f79..90aed1f 100644
--- a/src/server/cursor.rs
+++ b/src/server/cursor.rs
@@ -1211,18 +1211,26 @@ pub unsafe fn get_border_zone(window: *mut crate::window::Window, lx: f64, ly: f
}
if rx >= -bw && rx < content_w + bw && ry >= -bw && ry < content_h + bw {
+ let threshold = if bw <= 3.0 { bw / 2.0 } else { 3.0 };
+
let dist_left = rx + bw;
let dist_right = (content_w + bw) - rx;
let dist_top = ry + bw;
let dist_bottom = (content_h + bw) - ry;
- let corner_threshold = bw + 2.0;
- let left = dist_left < corner_threshold;
- let right = dist_right < corner_threshold;
- let top = dist_top < corner_threshold;
- let bottom = dist_bottom < corner_threshold;
+ let min_dist = dist_left.min(dist_right).min(dist_top).min(dist_bottom);
+
+ if min_dist >= 0.0 && min_dist < threshold {
+ let delta = threshold + 1.0;
+ let left = dist_left < delta;
+ let right = dist_right < delta;
+ let top = dist_top < delta;
+ let bottom = dist_bottom < delta;
- return BorderZone::Resize(crate::window::Edges { top, bottom, left, right });
+ return BorderZone::Resize(crate::window::Edges { top, bottom, left, right });
+ } else {
+ return BorderZone::Move;
+ }
}
BorderZone::None
diff --git a/src/server/seat.rs b/src/server/seat.rs
index 38b1b30..fa3a312 100644
--- a/src/server/seat.rs
+++ b/src/server/seat.rs
@@ -856,6 +856,7 @@ impl Seat {
(*win).box_geom.x = new_x;
(*win).box_geom.y = new_y;
+ (*win).wm_requested.resizing = true;
(*win).wm_requested.dimensions = Some(crate::window::Dimensions {
width: new_w,
height: new_h,
@@ -876,6 +877,14 @@ impl Seat {
pub unsafe fn op_end(&mut self) {
if let Some(op) = self.op.take() {
log::debug!("end seat op");
+ let win = op.window_ptr;
+ if !win.is_null() && !(*win).closed {
+ if let PointerOpType::Resize { .. } = op.op_type {
+ (*win).wm_requested.resizing = false;
+ (*win).manage_finish();
+ (*self.server).wm.dirty_windowing();
+ }
+ }
match op.input {
SeatOpInput::Pointer => {
self.cursor.op_end_pointer();
diff --git a/src/server/window_manager.rs b/src/server/window_manager.rs
index 5aff2be..fcef2a1 100644
--- a/src/server/window_manager.rs
+++ b/src/server/window_manager.rs
@@ -583,6 +583,39 @@ impl WindowManager {
self.global_layout
}
+ pub unsafe fn get_active_resize_dimensions(&self, win_ptr: *mut Window) -> Option<(u32, u32)> {
+ let seats_list = &(*self.server).input_manager.seats as *const ffi::wl_list as *const WlList as *mut WlList;
+ let mut curr_seat = (*seats_list).next;
+ while curr_seat != seats_list {
+ let seat = crate::container_of!(curr_seat, crate::seat::Seat, link);
+ if let Some(ref op) = (*seat).op {
+ if op.window_ptr == win_ptr {
+ if let crate::seat::PointerOpType::Resize { edges } = op.op_type {
+ let dx = op.x - op.start_x;
+ let dy = op.y - op.start_y;
+ let mut new_w = op.start_win_w;
+ let mut new_h = op.start_win_h;
+
+ if edges.left {
+ new_w = std::cmp::max(50, op.start_win_w as i32 - dx) as u32;
+ } else if edges.right {
+ new_w = std::cmp::max(50, op.start_win_w as i32 + dx) as u32;
+ }
+
+ if edges.top {
+ new_h = std::cmp::max(50, op.start_win_h as i32 - dy) as u32;
+ } else if edges.bottom {
+ new_h = std::cmp::max(50, op.start_win_h as i32 + dy) as u32;
+ }
+ return Some((new_w, new_h));
+ }
+ }
+ }
+ curr_seat = (*curr_seat).next;
+ }
+ None
+ }
+
pub unsafe fn arrange_views(&mut self) {
log::info!("Monolithic arrange_views triggered. Windows: {}", self.windows.count());
for (idx, &win_ptr) in self.windows.iter().enumerate() {
@@ -938,14 +971,18 @@ impl WindowManager {
};
} else {
let fbw = self.layout.floating_border_width;
- let mut fw = if (*win_ptr).box_geom.width > 0 {
+ let mut fw = if let Some(resize_size) = self.get_active_resize_dimensions(win_ptr) {
+ resize_size.0 as i32
+ } else if (*win_ptr).box_geom.width > 0 {
(*win_ptr).box_geom.width as i32
} else if (*win_ptr).wm_scheduled.dimensions_hint.min_width > 32 {
(*win_ptr).wm_scheduled.dimensions_hint.min_width as i32
} else {
usable_w * 2 / 3
};
- let mut fh = if (*win_ptr).box_geom.height > 0 {
+ let mut fh = if let Some(resize_size) = self.get_active_resize_dimensions(win_ptr) {
+ resize_size.1 as i32
+ } else if (*win_ptr).box_geom.height > 0 {
(*win_ptr).box_geom.height as i32
} else if (*win_ptr).wm_scheduled.dimensions_hint.min_height > 32 {
(*win_ptr).wm_scheduled.dimensions_hint.min_height as i32