From 186584398cba3b7aa01566160fcc4509bff2d3ac Mon Sep 17 00:00:00 2001 From: Val Packett Date: Thu, 19 Mar 2026 21:35:36 -0300 Subject: [PATCH] Draw decorations on commit, skip drawing if params unchanged --- src/deco.rs | 56 ++++++++++++++++++++++++++++++++++++----------------- src/seat.rs | 1 + src/util.rs | 2 +- src/xdg.rs | 25 ++++++++++++++++++++++-- 4 files changed, 63 insertions(+), 21 deletions(-) diff --git a/src/deco.rs b/src/deco.rs index 93b2aad..f3d087b 100644 --- a/src/deco.rs +++ b/src/deco.rs @@ -8,7 +8,6 @@ use wl_proxy::{ WpCursorShapeDeviceV1, WpCursorShapeDeviceV1Shape, }, wayland::{ - wl_buffer::WlBuffer, wl_pointer::WlPointerButtonState, wl_seat::WlSeat, wl_subsurface::WlSubsurface, @@ -20,8 +19,14 @@ use wl_proxy::{ use crate::{buffer::SimpleBufferPool, globals::Globals, util::Bounds}; +#[derive(Default, Debug, Clone, PartialEq)] +struct DecoParams { + bounds: Bounds, +} + pub struct Deco { - bounds: RefCell, + last_params: RefCell, + next_params: RefCell, top_size: i32, border_size: i32, @@ -34,10 +39,11 @@ pub struct Deco { impl Deco { fn resize_anchor(&self, x: i32, y: i32) -> XdgToplevelResizeEdge { + let bounds = &self.last_params.borrow().bounds; let n = y < self.border_size; - let e = x >= self.bounds.borrow().width + self.border_size; + let e = x >= bounds.width + self.border_size; let w = x < self.border_size; - let s = y >= self.bounds.borrow().height + self.border_size; + let s = y >= bounds.height + self.border_size; if n && e { XdgToplevelResizeEdge::TOP_RIGHT } else if n && w { @@ -126,6 +132,7 @@ impl Deco { globals: &Rc, ) -> Rc { let wl_surface = globals.wl_compositor.new_send_create_surface(); + log::debug!("creating deco for surface {host_surface:?} -> {wl_surface:?}"); wl_surface.set_forward_to_client(false); let subsurface = globals .wl_subcompositor @@ -135,12 +142,8 @@ impl Deco { let pool = SimpleBufferPool::new(globals, 1, 1).unwrap(); let args = crate::ARGS.get().unwrap(); let deco = Rc::new(Deco { - bounds: RefCell::new(Bounds { - x: 0, - y: 0, - width: 10, - height: 10, - }), + last_params: RefCell::new(Default::default()), + next_params: RefCell::new(Default::default()), top_size: args.thickness as i32, // TODO: title border_size: args.thickness as i32, wl_surface: wl_surface.clone(), @@ -159,17 +162,24 @@ impl Deco { y: i32, width: i32, height: i32, - ) -> eyre::Result<(i32, i32, i32, i32)> { - self.bounds.replace(Bounds { + ) -> (i32, i32, i32, i32) { + log::debug!( + "decoration {:?} handling geometry {width}x{height} @ {x},{y}", + self.wl_surface + ); + self.next_params.borrow_mut().bounds = Bounds { x, y, width, height, - }); - self.draw()?; + }; let width = width + self.border_size * 2; let height = height + self.top_size + self.border_size; - Ok((x - self.border_size, y - self.top_size, width, height)) + (x - self.border_size, y - self.top_size, width, height) + } + + pub fn handle_commit(&self) -> eyre::Result<()> { + self.draw() } pub fn transform_configure(&self, width: i32, height: i32) -> (i32, i32) { @@ -190,8 +200,18 @@ impl Deco { (x + self.border_size, y + self.top_size) } - fn draw(&self) -> eyre::Result> { - let bounds = self.bounds.borrow(); + fn draw(&self) -> eyre::Result<()> { + let params = self.next_params.borrow(); + if *params == *self.last_params.borrow() { + log::debug!("decoration {:?} unchanged", self.wl_surface); + return Ok(()); + } + log::debug!( + "decoration {:?} changed to {params:?}, drawing", + self.wl_surface + ); + self.last_params.replace(params.clone()); + let bounds = ¶ms.bounds; let (width, height) = self.transform_size(bounds.width, bounds.height); let mut pool = self.pool.borrow_mut(); @@ -224,6 +244,6 @@ impl Deco { .send_set_position(bounds.x - self.border_size, bounds.y - self.top_size); self.wl_surface.send_commit(); // let _ = self.globals.wl_display.new_send_sync(); - Ok(buf) + Ok(()) } } diff --git a/src/seat.rs b/src/seat.rs index 5e0edfd..07fb547 100644 --- a/src/seat.rs +++ b/src/seat.rs @@ -130,6 +130,7 @@ impl WlPointerHandler for ProxyWlPointer { let Some((surface_x, surface_y)) = self.last_xy else { return; }; + log::debug!("pointer button at {surface_x},{surface_y} on {surface:?}"); if let Ok(deco) = surface.try_get_handler_mut::() { deco.pointer_button(&self.seat, serial, surface_x, surface_y, button, state); } diff --git a/src/util.rs b/src/util.rs index 6439773..d624ac6 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,4 +1,4 @@ -#[derive(Default, Debug, Clone)] +#[derive(Default, Debug, Clone, PartialEq)] pub struct Bounds { pub x: i32, pub y: i32, diff --git a/src/xdg.rs b/src/xdg.rs index bad9db3..236c5c1 100644 --- a/src/xdg.rs +++ b/src/xdg.rs @@ -3,7 +3,10 @@ use std::rc::Rc; use wl_proxy::{ object::ObjectUtils, protocols::{ - wayland::{wl_output::WlOutput, wl_surface::WlSurface}, + wayland::{ + wl_output::WlOutput, + wl_surface::{WlSurface, WlSurfaceHandler}, + }, xdg_shell::{ xdg_popup::XdgPopup, xdg_positioner::{XdgPositioner, XdgPositionerHandler}, @@ -16,6 +19,21 @@ use wl_proxy::{ use crate::{deco::Deco, globals::Globals, util::Bounds}; +pub struct ClientWlSurface { + pub xdg_surface: Rc, +} + +impl WlSurfaceHandler for ClientWlSurface { + fn handle_commit(&mut self, slf: &Rc) { + log::debug!("commit {slf:?}"); + let surf_handler = self.xdg_surface.get_handler_ref::(); + if let Some(deco) = surf_handler.deco.as_ref() { + deco.handle_commit().unwrap(); + } + slf.send_commit(); + } +} + pub struct ClientXdgWmBase { pub globals: Rc, } @@ -27,6 +45,9 @@ impl XdgWmBaseHandler for ClientXdgWmBase { id: &Rc, surface: &Rc, ) { + surface.set_handler(ClientWlSurface { + xdg_surface: id.clone(), + }); id.set_handler(ClientXdgSurface { deco: None, globals: self.globals.clone(), @@ -86,7 +107,7 @@ impl XdgSurfaceHandler for ClientXdgSurface { mut height: i32, ) { if let Some(deco) = self.deco.as_ref() { - (x, y, width, height) = deco.handle_window_geometry(x, y, width, height).unwrap(); + (x, y, width, height) = deco.handle_window_geometry(x, y, width, height); } slf.send_set_window_geometry(x, y, width, height); }