Add xdg positioner fixup

This commit is contained in:
Val Packett 2026-03-06 02:53:15 -03:00
parent 20e16ca508
commit 8dce5e323a
2 changed files with 114 additions and 15 deletions

View file

@ -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<Rc<WlBuffer>> {
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();

View file

@ -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<Globals>,
@ -31,6 +34,11 @@ impl XdgWmBaseHandler for ClientXdgWmBase {
});
slf.send_get_xdg_surface(id, surface);
}
fn handle_create_positioner(&mut self, slf: &Rc<XdgWmBase>, id: &Rc<XdgPositioner>) {
id.set_handler(ClientXdgPositioner::new());
slf.send_create_positioner(id);
}
}
struct ClientXdgSurface {
@ -54,10 +62,18 @@ impl XdgSurfaceHandler for ClientXdgSurface {
parent: Option<&Rc<XdgSurface>>,
positioner: &Rc<XdgPositioner>,
) {
// if let Some(parent) = parent {
// let handler = parent.get_handler_ref::<ClientXdgSurface>();
// self.deco.subsurface.send_place_below(&handler.wl_surface);
// } welp sad
if let Some(parent) = parent {
let parent_handler = parent.get_handler_ref::<ClientXdgSurface>();
// 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::<ClientXdgPositioner>();
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<Rc<Deco>>,
op_queue: Vec<PositionerOp>,
}
impl ClientXdgPositioner {
fn new() -> ClientXdgPositioner {
ClientXdgPositioner {
parent_deco: None,
op_queue: Vec::with_capacity(4),
}
}
fn parent_assigned(&mut self, slf: &Rc<XdgPositioner>, deco: &Rc<Deco>) {
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<XdgPositioner>,
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<XdgPositioner>,
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));
}
}
}