Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
fix: layer popups above pinned windows & add smooth 3-finger swipe zoom
src/server/cursor.rs | 43 ++++++++++++++++++++++++++++++++++++++++++-
src/server/window_manager.rs | 9 ++++++---
2 files changed, 48 insertions(+), 4 deletions(-)
diff --git a/src/server/cursor.rs b/src/server/cursor.rs
index 1d4e9cd..1946d71 100644
--- a/src/server/cursor.rs
+++ b/src/server/cursor.rs
@@ -1007,7 +1007,7 @@ unsafe extern "C" fn handle_axis(listener: *mut ffi::wl_listener, data: *mut std
wm.desk_pan_x += (cx - phys_x) * (1.0 / old_zoom - 1.0 / new_zoom);
wm.desk_pan_y += (cy - phys_y) * (1.0 / old_zoom - 1.0 / new_zoom);
wm.desk_zoom = new_zoom;
- wm.mode = if new_zoom < 0.999 { crate::window_manager::WindowManagerMode::Overview } else { crate::window_manager::WindowManagerMode::Normal };
+ wm.mode = if (new_zoom - 1.0).abs() > 0.001 { crate::window_manager::WindowManagerMode::Overview } else { crate::window_manager::WindowManagerMode::Normal };
wm.dirty_windowing();
}
}
@@ -1369,6 +1369,47 @@ unsafe extern "C" fn handle_swipe_update(listener: *mut ffi::wl_listener, data:
let seat = &mut *cursor.seat;
seat.handle_activity();
+ if (*event).fingers == 3 {
+ let wm = &mut (*seat.server).wm;
+ wm.stop_panning_animation();
+
+ let dy = (*event).dy;
+ let zoom_factor = 1.005_f64.powf(-dy);
+ let old_zoom = wm.desk_zoom;
+ let new_zoom = (old_zoom * zoom_factor).clamp(0.1, 10.0);
+
+ if new_zoom != old_zoom {
+ let cx = cursor.x();
+ let cy = cursor.y();
+ let wlr_output = (*(*seat).server).om.output_at(cx, cy);
+ let (phys_x, phys_y) = if !wlr_output.is_null() {
+ let mut output_box = ffi::wlr_box { x: 0, y: 0, width: 0, height: 0 };
+ ffi::wlr_output_layout_get_box((*(*seat).server).om.output_layout, wlr_output, &mut output_box);
+ (output_box.x as f64, output_box.y as f64)
+ } else {
+ (0.0, 0.0)
+ };
+ wm.desk_pan_x += (cx - phys_x) * (1.0 / old_zoom - 1.0 / new_zoom);
+ wm.desk_pan_y += (cy - phys_y) * (1.0 / old_zoom - 1.0 / new_zoom);
+ wm.desk_zoom = new_zoom;
+ wm.mode = if (new_zoom - 1.0).abs() > 0.001 { crate::window_manager::WindowManagerMode::Overview } else { crate::window_manager::WindowManagerMode::Normal };
+ wm.dirty_windowing();
+ }
+
+ let server = seat.server;
+ let pointer_gestures = (*server).input_manager.pointer_gestures;
+ if !pointer_gestures.is_null() {
+ ffi::wlr_pointer_gestures_v1_send_swipe_update(
+ pointer_gestures,
+ seat.wlr_seat,
+ (*event).time_msec,
+ (*event).dx,
+ (*event).dy,
+ );
+ }
+ return;
+ }
+
if cursor.gesture_triggered {
return;
}
diff --git a/src/server/window_manager.rs b/src/server/window_manager.rs
index c510d26..a1c3cf9 100644
--- a/src/server/window_manager.rs
+++ b/src/server/window_manager.rs
@@ -224,7 +224,7 @@ impl WindowManager {
self.desk_pan_x = state.desk_pan_x;
self.desk_pan_y = state.desk_pan_y;
self.desk_zoom = state.desk_zoom;
- self.mode = if state.desk_zoom < 0.999 { WindowManagerMode::Overview } else { WindowManagerMode::Normal };
+ self.mode = if (state.desk_zoom - 1.0).abs() > 0.001 { WindowManagerMode::Overview } else { WindowManagerMode::Normal };
self.global_layout = state.global_layout;
self.restore_queue = state.windows;
self.has_restored_focused_window = self.restore_queue.iter().any(|w| w.focused);
@@ -688,6 +688,9 @@ impl WindowManager {
ffi::wlr_scene_node_reparent((*window).tree as *mut _, (*self.server).scene.layers.fullscreen);
ffi::wlr_scene_node_raise_to_top((*window).tree as *mut _);
found_fullscreen = true;
+ } else if (*window).tiling_mode == crate::tiling::TilingMode::Popup {
+ ffi::wlr_scene_node_reparent((*window).tree as *mut _, (*self.server).scene.layers.popups);
+ ffi::wlr_scene_node_raise_to_top((*window).tree as *mut _);
} else if (*window).rendering_requested.circular {
ffi::wlr_scene_node_reparent((*window).tree as *mut _, (*self.server).scene.layers.top);
ffi::wlr_scene_node_raise_to_top((*window).tree as *mut _);
@@ -1657,7 +1660,7 @@ fn get_closest_tag(x: f64, y: f64) -> i32 {
self.desk_pan_x = cx - (viewport_w / 2.0) / new_zoom;
self.desk_pan_y = cy - (viewport_h / 2.0) / new_zoom;
self.desk_zoom = new_zoom;
- self.mode = if new_zoom < 0.999 { WindowManagerMode::Overview } else { WindowManagerMode::Normal };
+ self.mode = if (new_zoom - 1.0).abs() > 0.001 { WindowManagerMode::Overview } else { WindowManagerMode::Normal };
self.dirty_windowing();
}
Action::PanLeft | Action::PanRight | Action::PanUp | Action::PanDown => {
@@ -1898,7 +1901,7 @@ fn get_closest_tag(x: f64, y: f64) -> i32 {
self.desk_pan_x = cx - (viewport_w / 2.0) / new_zoom;
self.desk_pan_y = cy - (viewport_h / 2.0) / new_zoom;
self.desk_zoom = new_zoom;
- self.mode = if new_zoom < 0.999 { WindowManagerMode::Overview } else { WindowManagerMode::Normal };
+ self.mode = if (new_zoom - 1.0).abs() > 0.001 { WindowManagerMode::Overview } else { WindowManagerMode::Normal };
self.dirty_windowing();
return "ok\n".to_string();
}