224 lines
6.7 KiB
Rust
224 lines
6.7 KiB
Rust
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<Globals>,
|
|
}
|
|
|
|
impl XdgWmBaseHandler for ClientXdgWmBase {
|
|
fn handle_get_xdg_surface(
|
|
&mut self,
|
|
slf: &Rc<XdgWmBase>,
|
|
id: &Rc<XdgSurface>,
|
|
surface: &Rc<WlSurface>,
|
|
) {
|
|
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<XdgWmBase>, id: &Rc<XdgPositioner>) {
|
|
id.set_handler(ClientXdgPositioner::new());
|
|
slf.send_create_positioner(id);
|
|
}
|
|
}
|
|
|
|
struct ClientXdgSurface {
|
|
globals: Rc<Globals>,
|
|
surface: Rc<WlSurface>,
|
|
deco: Option<Rc<Deco>>,
|
|
}
|
|
|
|
impl XdgSurfaceHandler for ClientXdgSurface {
|
|
fn handle_get_toplevel(&mut self, slf: &Rc<XdgSurface>, id: &Rc<XdgToplevel>) {
|
|
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<XdgSurface>,
|
|
id: &Rc<XdgPopup>,
|
|
parent: Option<&Rc<XdgSurface>>,
|
|
positioner: &Rc<XdgPositioner>,
|
|
) {
|
|
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);
|
|
}
|
|
|
|
fn handle_set_window_geometry(
|
|
&mut self,
|
|
slf: &Rc<XdgSurface>,
|
|
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<XdgSurface>, serial: u32) {
|
|
slf.send_ack_configure(serial);
|
|
}
|
|
|
|
fn handle_configure(&mut self, slf: &Rc<XdgSurface>, serial: u32) {
|
|
slf.send_configure(serial);
|
|
}
|
|
}
|
|
|
|
struct ClientXdgToplevel {
|
|
deco: Rc<Deco>,
|
|
}
|
|
|
|
impl ClientXdgToplevel {
|
|
fn new(deco: &Rc<Deco>) -> ClientXdgToplevel {
|
|
ClientXdgToplevel { deco: deco.clone() }
|
|
}
|
|
}
|
|
|
|
impl XdgToplevelHandler for ClientXdgToplevel {
|
|
fn handle_set_title(&mut self, slf: &Rc<XdgToplevel>, title: &str) {
|
|
slf.send_set_title(title);
|
|
}
|
|
|
|
fn handle_set_max_size(&mut self, slf: &Rc<XdgToplevel>, width: i32, height: i32) {
|
|
slf.send_set_max_size(width, height);
|
|
}
|
|
|
|
fn handle_set_min_size(&mut self, slf: &Rc<XdgToplevel>, width: i32, height: i32) {
|
|
slf.send_set_min_size(width, height);
|
|
}
|
|
|
|
fn handle_set_maximized(&mut self, slf: &Rc<XdgToplevel>) {
|
|
slf.send_set_maximized();
|
|
}
|
|
|
|
fn handle_unset_maximized(&mut self, slf: &Rc<XdgToplevel>) {
|
|
slf.send_unset_maximized();
|
|
}
|
|
|
|
fn handle_set_fullscreen(&mut self, slf: &Rc<XdgToplevel>, output: Option<&Rc<WlOutput>>) {
|
|
slf.send_set_fullscreen(output);
|
|
}
|
|
|
|
fn handle_unset_fullscreen(&mut self, slf: &Rc<XdgToplevel>) {
|
|
slf.send_unset_fullscreen();
|
|
}
|
|
|
|
fn handle_configure(&mut self, slf: &Rc<XdgToplevel>, 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<XdgToplevel>, width: i32, height: i32) {
|
|
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));
|
|
}
|
|
}
|
|
}
|