use std::rc::Rc; 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, util::Bounds}; pub struct ClientXdgWmBase { pub globals: Rc, } impl XdgWmBaseHandler for ClientXdgWmBase { fn handle_get_xdg_surface( &mut self, slf: &Rc, id: &Rc, surface: &Rc, ) { id.set_handler(ClientXdgSurface { deco: None, globals: self.globals.clone(), surface: surface.clone(), }); 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 { globals: Rc, surface: Rc, deco: Option>, } impl XdgSurfaceHandler for ClientXdgSurface { fn handle_get_toplevel(&mut self, slf: &Rc, id: &Rc) { let deco = Deco::new(&self.surface, id, &self.globals); id.set_handler(ClientXdgToplevel::new(&deco)); self.deco = Some(deco); slf.send_get_toplevel(id); } fn handle_get_popup( &mut self, slf: &Rc, id: &Rc, parent: Option<&Rc>, positioner: &Rc, ) { 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); } fn handle_set_window_geometry( &mut self, slf: &Rc, mut x: i32, mut y: i32, mut width: i32, mut height: i32, ) { if let Some(deco) = self.deco.as_ref() { (x, y, width, height) = deco.handle_window_geometry(x, y, width, height).unwrap(); } slf.send_set_window_geometry(x, y, width, height); } fn handle_ack_configure(&mut self, slf: &Rc, serial: u32) { slf.send_ack_configure(serial); } fn handle_configure(&mut self, slf: &Rc, serial: u32) { slf.send_configure(serial); } } struct ClientXdgToplevel { deco: Rc, } impl ClientXdgToplevel { fn new(deco: &Rc) -> ClientXdgToplevel { ClientXdgToplevel { deco: deco.clone() } } } impl XdgToplevelHandler for ClientXdgToplevel { fn handle_set_title(&mut self, slf: &Rc, title: &str) { slf.send_set_title(title); } fn handle_set_max_size(&mut self, slf: &Rc, width: i32, height: i32) { slf.send_set_max_size(width, height); } fn handle_set_min_size(&mut self, slf: &Rc, width: i32, height: i32) { slf.send_set_min_size(width, height); } fn handle_set_maximized(&mut self, slf: &Rc) { slf.send_set_maximized(); } fn handle_unset_maximized(&mut self, slf: &Rc) { slf.send_unset_maximized(); } fn handle_set_fullscreen(&mut self, slf: &Rc, output: Option<&Rc>) { slf.send_set_fullscreen(output); } fn handle_unset_fullscreen(&mut self, slf: &Rc) { slf.send_unset_fullscreen(); } fn handle_configure(&mut self, slf: &Rc, width: i32, height: i32, _states: &[u8]) { let states = (1u64 << 32 | XdgToplevelState::TILED_TOP.0 as u64).to_ne_bytes(); let (width, height) = self.deco.transform_configure(width, height); slf.send_configure(width, height, &states[..]); } fn handle_configure_bounds(&mut self, slf: &Rc, width: i32, height: i32) { 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)); } } }