From 8dce5e323a3f5744c6395148a04a6dee4139ae44 Mon Sep 17 00:00:00 2001 From: Val Packett Date: Fri, 6 Mar 2026 02:53:15 -0300 Subject: [PATCH] Add xdg positioner fixup --- src/deco.rs | 14 ++++++- src/xdg.rs | 115 ++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 114 insertions(+), 15 deletions(-) diff --git a/src/deco.rs b/src/deco.rs index 0b8f914..a791d16 100644 --- a/src/deco.rs +++ b/src/deco.rs @@ -178,10 +178,20 @@ impl Deco { ) } + pub fn transform_size(&self, width: i32, height: i32) -> (i32, i32) { + ( + width + self.border_size * 2, + height + self.top_size + self.border_size, + ) + } + + pub fn transform_anchor(&self, x: i32, y: i32) -> (i32, i32) { + (x + self.border_size, y + self.top_size) + } + fn draw(&self) -> eyre::Result> { let bounds = self.bounds.borrow(); - let width = bounds.width + 2 * self.border_size; - let height = bounds.height + self.top_size + self.border_size; + let (width, height) = self.transform_size(bounds.width, bounds.height); log::info!("{:?} -> {}x{}", bounds, width, height); let mut pool = self.pool.borrow_mut(); diff --git a/src/xdg.rs b/src/xdg.rs index 87d0d42..bad9db3 100644 --- a/src/xdg.rs +++ b/src/xdg.rs @@ -1,17 +1,20 @@ use std::rc::Rc; -use wl_proxy::protocols::{ - wayland::{wl_output::WlOutput, wl_surface::WlSurface}, - xdg_shell::{ - xdg_popup::XdgPopup, - xdg_positioner::XdgPositioner, - xdg_surface::{XdgSurface, XdgSurfaceHandler}, - xdg_toplevel::{XdgToplevel, XdgToplevelHandler, XdgToplevelState}, - xdg_wm_base::{XdgWmBase, XdgWmBaseHandler}, +use wl_proxy::{ + object::ObjectUtils, + protocols::{ + wayland::{wl_output::WlOutput, wl_surface::WlSurface}, + xdg_shell::{ + xdg_popup::XdgPopup, + xdg_positioner::{XdgPositioner, XdgPositionerHandler}, + xdg_surface::{XdgSurface, XdgSurfaceHandler}, + xdg_toplevel::{XdgToplevel, XdgToplevelHandler, XdgToplevelState}, + xdg_wm_base::{XdgWmBase, XdgWmBaseHandler}, + }, }, }; -use crate::{deco::Deco, globals::Globals}; +use crate::{deco::Deco, globals::Globals, util::Bounds}; pub struct ClientXdgWmBase { pub globals: Rc, @@ -31,6 +34,11 @@ impl XdgWmBaseHandler for ClientXdgWmBase { }); slf.send_get_xdg_surface(id, surface); } + + fn handle_create_positioner(&mut self, slf: &Rc, id: &Rc) { + id.set_handler(ClientXdgPositioner::new()); + slf.send_create_positioner(id); + } } struct ClientXdgSurface { @@ -54,10 +62,18 @@ impl XdgSurfaceHandler for ClientXdgSurface { parent: Option<&Rc>, positioner: &Rc, ) { - // if let Some(parent) = parent { - // let handler = parent.get_handler_ref::(); - // self.deco.subsurface.send_place_below(&handler.wl_surface); - // } welp sad + if let Some(parent) = parent { + let parent_handler = parent.get_handler_ref::(); + // self.deco.subsurface.send_place_below(&handler.wl_surface); .. welp + if let Some(ref deco) = parent_handler.deco { + let mut pos_handler = positioner.get_handler_mut::(); + pos_handler.parent_assigned(positioner, deco); + } else { + log::warn!("no parent toplevel decoration for popup"); + } + } else { + log::warn!("no parent for popup"); + } slf.send_get_popup(id, parent, positioner); } @@ -133,3 +149,76 @@ impl XdgToplevelHandler for ClientXdgToplevel { slf.send_configure_bounds(width, height); } } + +enum PositionerOp { + SetAnchorRect(Bounds), + SetParentSize(i32, i32), +} + +struct ClientXdgPositioner { + parent_deco: Option>, + op_queue: Vec, +} + +impl ClientXdgPositioner { + fn new() -> ClientXdgPositioner { + ClientXdgPositioner { + parent_deco: None, + op_queue: Vec::with_capacity(4), + } + } + + fn parent_assigned(&mut self, slf: &Rc, deco: &Rc) { + self.parent_deco = Some(deco.clone()); + while let Some(op) = self.op_queue.drain(..).next() { + match op { + PositionerOp::SetAnchorRect(bounds) => { + let (x, y) = deco.transform_anchor(bounds.x, bounds.y); + slf.send_set_anchor_rect(x, y, bounds.width, bounds.height); + } + PositionerOp::SetParentSize(mut width, mut height) => { + (width, height) = deco.transform_size(width, height); + slf.send_set_parent_size(width, height); + } + } + } + } +} + +impl XdgPositionerHandler for ClientXdgPositioner { + fn handle_set_anchor_rect( + &mut self, + slf: &Rc, + mut x: i32, + mut y: i32, + width: i32, + height: i32, + ) { + if let Some(ref deco) = self.parent_deco { + (x, y) = deco.transform_anchor(x, y); + slf.send_set_anchor_rect(x, y, width, height); + } else { + self.op_queue.push(PositionerOp::SetAnchorRect(Bounds { + x, + y, + width, + height, + })); + } + } + + fn handle_set_parent_size( + &mut self, + slf: &Rc, + mut parent_width: i32, + mut parent_height: i32, + ) { + if let Some(ref deco) = self.parent_deco { + (parent_width, parent_height) = deco.transform_size(parent_width, parent_height); + slf.send_set_parent_size(parent_width, parent_height); + } else { + self.op_queue + .push(PositionerOp::SetParentSize(parent_width, parent_height)); + } + } +}