Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
fix: stop panning animation on interaction and use correct module path for animation timer
src/server/cursor.rs | 4 +++
src/server/seat.rs | 22 ++++++++++++++---
src/server/window_manager.rs | 58 ++++++++++++++++++++++++++++++++++++++++++++
src/server/xdg_toplevel.rs | 2 ++
4 files changed, 83 insertions(+), 3 deletions(-)
diff --git a/src/server/cursor.rs b/src/server/cursor.rs
index 5ca86f1..379e0a7 100644
--- a/src/server/cursor.rs
+++ b/src/server/cursor.rs
@@ -659,6 +659,7 @@ unsafe extern "C" fn handle_button(listener: *mut ffi::wl_listener, data: *mut s
};
if let Some(ot) = op_type {
+ (*server).wm.stop_panning_animation();
let cursor_x = (*cursor.wlr_cursor).x;
let cursor_y = (*cursor.wlr_cursor).y;
seat.op = Some(crate::seat::SeatOp {
@@ -718,6 +719,7 @@ unsafe extern "C" fn handle_button(listener: *mut ffi::wl_listener, data: *mut s
}
seat.focus(Focus::Window(border_target_win));
+ (*server).wm.stop_panning_animation();
let cursor_x = (*cursor.wlr_cursor).x;
let cursor_y = (*cursor.wlr_cursor).y;
seat.op = Some(crate::seat::SeatOp {
@@ -754,6 +756,7 @@ unsafe extern "C" fn handle_button(listener: *mut ffi::wl_listener, data: *mut s
}
seat.focus(Focus::Window(border_target_win));
+ (*server).wm.stop_panning_animation();
let cursor_x = (*cursor.wlr_cursor).x;
let cursor_y = (*cursor.wlr_cursor).y;
seat.op = Some(crate::seat::SeatOp {
@@ -885,6 +888,7 @@ unsafe extern "C" fn handle_axis(listener: *mut ffi::wl_listener, data: *mut std
if (modifiers & 0x40) != 0 {
let wm = &mut (*seat.server).wm;
+ wm.stop_panning_animation();
let step = delta / wm.desk_zoom;
match (*event).orientation {
ffi::wl_pointer_axis_WL_POINTER_AXIS_VERTICAL_SCROLL => {
diff --git a/src/server/seat.rs b/src/server/seat.rs
index 477dc0f..ccdba2e 100644
--- a/src/server/seat.rs
+++ b/src/server/seat.rs
@@ -433,9 +433,24 @@ impl Seat {
let wm = &mut (*self.server).wm;
let scale = wm.desk_zoom;
- wm.desk_pan_x = (*window).virtual_x + (fw / 2.0 - viewport_w / 2.0) / scale;
- wm.desk_pan_y = (*window).virtual_y + (fh / 2.0 - viewport_h / 2.0) / scale;
- wm.dirty_windowing();
+ let target_x = (*window).virtual_x + (fw / 2.0 - viewport_w / 2.0) / scale;
+ let target_y = (*window).virtual_y + (fh / 2.0 - viewport_h / 2.0) / scale;
+
+ wm.target_desk_pan_x = Some(target_x);
+ wm.target_desk_pan_y = Some(target_y);
+
+ if wm.animation_timer.is_null() {
+ let event_loop = ffi::wl_display_get_event_loop((*self.server).wl_server);
+ wm.animation_timer = ffi::wl_event_loop_add_timer(
+ event_loop,
+ Some(crate::window_manager::handle_panning_animation_tick),
+ wm as *mut crate::window_manager::WindowManager as *mut _,
+ );
+ }
+
+ if !wm.animation_timer.is_null() {
+ ffi::wl_event_source_timer_update(wm.animation_timer, 16);
+ }
}
}
@@ -1238,6 +1253,7 @@ unsafe extern "C" fn seat_op_start_pointer(
start_win_virtual_x: 0.0,
start_win_virtual_y: 0.0,
});
+ (*(*seat).server).wm.stop_panning_animation();
(*seat).cursor.op_start_pointer();
}
}
diff --git a/src/server/window_manager.rs b/src/server/window_manager.rs
index 4f1603b..2b9be44 100644
--- a/src/server/window_manager.rs
+++ b/src/server/window_manager.rs
@@ -101,6 +101,9 @@ pub struct WindowManager {
pub last_status_update: std::cell::RefCell<Option<crate::status_server::StatusUpdate>>,
pub restore_queue: Vec<SavedWindowState>,
pub shutting_down: bool,
+ pub target_desk_pan_x: Option<f64>,
+ pub target_desk_pan_y: Option<f64>,
+ pub animation_timer: *mut ffi::wl_event_source,
}
impl WindowManager {
@@ -143,6 +146,9 @@ impl WindowManager {
self.dirty_idle = std::ptr::null_mut();
self.desk_pan_x = 0.0;
self.desk_pan_y = 0.0;
+ self.target_desk_pan_x = None;
+ self.target_desk_pan_y = None;
+ self.animation_timer = std::ptr::null_mut();
self.desk_zoom = 1.0;
self.global_layout = crate::tiling::TilingMode::Cascade;
self.restore_queue = Vec::new();
@@ -331,9 +337,18 @@ impl WindowManager {
ffi::wl_event_source_remove(self.timeout);
self.timeout = std::ptr::null_mut();
}
+ if !self.animation_timer.is_null() {
+ ffi::wl_event_source_remove(self.animation_timer);
+ self.animation_timer = std::ptr::null_mut();
+ }
wl_listener_remove(&mut self.server_destroy);
}
+ pub unsafe fn stop_panning_animation(&mut self) {
+ self.target_desk_pan_x = None;
+ self.target_desk_pan_y = None;
+ }
+
pub unsafe fn ensure_windowing(&self) -> bool {
match self.state {
WindowManagerState::Manage => true,
@@ -1274,6 +1289,7 @@ fn get_closest_tag(x: f64, y: f64) -> i32 {
pub unsafe fn execute_action(&mut self, action: &crate::config::Action, command: Option<&str>) {
use crate::config::Action;
+ self.stop_panning_animation();
match action {
Action::None => {}
Action::Spawn => {
@@ -1631,6 +1647,7 @@ fn get_closest_tag(x: f64, y: f64) -> i32 {
}
pub unsafe fn process_ipc_command(&mut self, cmd: &str) -> String {
+ self.stop_panning_animation();
let parts: Vec<&str> = cmd.split_whitespace().collect();
if parts.is_empty() {
return "error: empty command\n".to_string();
@@ -2421,3 +2438,44 @@ unsafe extern "C" fn handle_destroy_wm_resource(resource: *mut ffi::wl_resource)
WindowManagerState::Render => (*wm).render_finish(),
}
}
+
+pub(crate) unsafe extern "C" fn handle_panning_animation_tick(data: *mut std::ffi::c_void) -> std::os::raw::c_int {
+ let wm = data as *mut WindowManager;
+ if wm.is_null() {
+ return 0;
+ }
+
+ let mut done = true;
+ let factor = 0.15;
+
+ if let Some(target_x) = (*wm).target_desk_pan_x {
+ let dx = target_x - (*wm).desk_pan_x;
+ if dx.abs() > 0.5 {
+ (*wm).desk_pan_x += dx * factor;
+ done = false;
+ } else {
+ (*wm).desk_pan_x = target_x;
+ (*wm).target_desk_pan_x = None;
+ }
+ }
+
+ if let Some(target_y) = (*wm).target_desk_pan_y {
+ let dy = target_y - (*wm).desk_pan_y;
+ if dy.abs() > 0.5 {
+ (*wm).desk_pan_y += dy * factor;
+ done = false;
+ } else {
+ (*wm).desk_pan_y = target_y;
+ (*wm).target_desk_pan_y = None;
+ }
+ }
+
+ (*wm).dirty_windowing();
+
+ if !done {
+ if !(*wm).animation_timer.is_null() {
+ ffi::wl_event_source_timer_update((*wm).animation_timer, 16);
+ }
+ }
+ 0
+}
diff --git a/src/server/xdg_toplevel.rs b/src/server/xdg_toplevel.rs
index dc242be..7bde7da 100644
--- a/src/server/xdg_toplevel.rs
+++ b/src/server/xdg_toplevel.rs
@@ -594,6 +594,7 @@ unsafe extern "C" fn handle_request_move(
}
(*seat).focus(crate::seat::Focus::Window(window));
+ (*(*window).server).wm.stop_panning_animation();
let cursor = &mut (*seat).cursor;
let cursor_x = (*cursor.wlr_cursor).x;
let cursor_y = (*cursor.wlr_cursor).y;
@@ -641,6 +642,7 @@ unsafe extern "C" fn handle_request_resize(
}
(*seat).focus(crate::seat::Focus::Window(window));
+ (*(*window).server).wm.stop_panning_animation();
let cursor = &mut (*seat).cursor;
let cursor_x = (*cursor.wlr_cursor).x;
let cursor_y = (*cursor.wlr_cursor).y;