Draw decorations on commit, skip drawing if params unchanged

This commit is contained in:
Val Packett 2026-03-19 21:35:36 -03:00
parent 35d4419c04
commit 186584398c
4 changed files with 63 additions and 21 deletions

View file

@ -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<Bounds>,
last_params: RefCell<DecoParams>,
next_params: RefCell<DecoParams>,
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<Globals>,
) -> Rc<Deco> {
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<Rc<WlBuffer>> {
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 = &params.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(())
}
}