diff --git a/src/deco.rs b/src/deco.rs index 09dcc56..c1539e9 100644 --- a/src/deco.rs +++ b/src/deco.rs @@ -26,6 +26,7 @@ use crate::{ #[derive(Default, Debug, Clone, PartialEq)] struct DecoParams { has_geometry: bool, + prefers_ssd: bool, is_active: bool, bounds: Bounds, restricted_edges: Edges, @@ -34,7 +35,6 @@ struct DecoParams { pub struct Deco { last_params: RefCell, next_params: RefCell, - top_size: i32, border_size: i32, wl_surface: Rc, @@ -133,6 +133,15 @@ impl DecoSurface { } impl Deco { + fn top_size(&self) -> i32 { + let params = self.last_params.borrow(); + if params.prefers_ssd { + self.border_size + 24 + } else { + self.border_size + } + } + pub fn new( host_surface: &Rc, toplevel: &Rc, @@ -151,7 +160,6 @@ impl Deco { let deco = Rc::new(Deco { 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(), subsurface, @@ -200,8 +208,8 @@ impl Deco { height, }; let width = width + self.border_size * 2; - let height = height + self.top_size + self.border_size; - (x - self.border_size, y - self.top_size, width, height) + let height = height + self.top_size() + self.border_size; + (x - self.border_size, y - self.top_size(), width, height) } pub fn set_restricted_edges(&self, edges: Edges) { @@ -214,6 +222,11 @@ impl Deco { params.is_active = is_active; } + pub fn set_prefers_ssd(&self, prefers_ssd: bool) { + let mut params = self.next_params.borrow_mut(); + params.prefers_ssd = prefers_ssd; + } + pub fn handle_commit(&self) -> eyre::Result<()> { self.draw() } @@ -221,19 +234,19 @@ impl Deco { pub fn transform_configure(&self, width: i32, height: i32) -> (i32, i32) { ( width - self.border_size * 2, - height - self.top_size - self.border_size, + height - self.top_size() - self.border_size, ) } pub fn transform_size(&self, width: i32, height: i32) -> (i32, i32) { ( width + self.border_size * 2, - height + self.top_size + self.border_size, + 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) + (x + self.border_size, y + self.top_size()) } fn draw(&self) -> eyre::Result<()> { @@ -273,13 +286,13 @@ impl Deco { self.wl_surface.send_damage_buffer(0, 0, width, height); let input_region = self.globals.wl_compositor.new_send_create_region(); input_region.set_forward_to_client(false); - input_region.send_add(0, 0, width, self.top_size); + input_region.send_add(0, 0, width, self.top_size()); input_region.send_add(0, 0, self.border_size, height); input_region.send_add(width - self.border_size, 0, self.border_size, height); input_region.send_add(0, height - self.border_size, width, self.border_size); self.wl_surface.send_set_input_region(Some(&input_region)); self.subsurface - .send_set_position(bounds.x - self.border_size, bounds.y - self.top_size); + .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(()) diff --git a/src/main.rs b/src/main.rs index 609dbb6..99fdb97 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,13 +3,16 @@ use std::{process::Command, rc::Rc, sync::OnceLock}; use clap::{CommandFactory, Parser}; use wl_proxy::{ baseline::Baseline, + global_mapper::GlobalMapper, object::{ConcreteObject, Object, ObjectCoreApi, ObjectRcUtils}, protocols::{ + ObjectInterface, linux_dmabuf_v1::zwp_linux_dmabuf_v1::ZwpLinuxDmabufV1, wayland::{ wl_registry::{WlRegistry, WlRegistryHandler}, wl_shm::WlShm, }, + xdg_decoration_unstable_v1::zxdg_decoration_manager_v1::ZxdgDecorationManagerV1, xdg_shell::xdg_wm_base::XdgWmBase, }, simple::{SimpleCommandExt, SimpleProxy}, @@ -27,12 +30,16 @@ mod xdg; struct ClientWlRegistry { globals: Rc, + globals_requested: bool, + mapper: GlobalMapper, } impl ClientWlRegistry { fn new(globals: &Rc) -> Self { Self { globals: globals.clone(), + globals_requested: false, + mapper: GlobalMapper::default(), } } } @@ -45,6 +52,12 @@ impl WlRegistryHandler for ClientWlRegistry { .set_handler(xdg::ClientXdgWmBase { globals: self.globals.clone(), }), + ZxdgDecorationManagerV1::INTERFACE => { + id.set_forward_to_server(false); + id.downcast::() + .set_handler(xdg::ClientZxdgDecorationManagerV1); + return; + } WlShm::INTERFACE => id .downcast::() .set_handler(client_buffer::ClientWlShm), @@ -53,7 +66,34 @@ impl WlRegistryHandler for ClientWlRegistry { .set_handler(client_buffer::ClientZwpLinuxDmabufV1), _ => {} } - slf.send_bind(name, id); + self.mapper.forward_bind(slf, name, &id); + } + + fn handle_global( + &mut self, + slf: &Rc, + name: u32, + interface: ObjectInterface, + version: u32, + ) { + use ObjectInterface::*; + if !self.globals_requested { + self.globals_requested = true; + self.mapper + .add_synthetic_global(slf, ZxdgDecorationManagerV1, 1); + } + match interface { + ZxdgDecorationManagerV1 | WpSecurityContextManagerV1 => { + self.mapper.ignore_global(name); + } + _ => { + self.mapper.forward_global(slf, name, interface, version); + } + } + } + + fn handle_global_remove(&mut self, slf: &Rc, name: u32) { + self.mapper.forward_global_remove(slf, name); } } diff --git a/src/xdg.rs b/src/xdg.rs index 155b0d2..75c7f10 100644 --- a/src/xdg.rs +++ b/src/xdg.rs @@ -1,13 +1,20 @@ use std::rc::Rc; use wl_proxy::{ - object::ObjectUtils, + object::{ObjectCoreApi, ObjectUtils}, protocols::{ wayland::{ wl_buffer::WlBuffer, wl_output::{WlOutput, WlOutputTransform}, wl_surface::{WlSurface, WlSurfaceHandler}, }, + xdg_decoration_unstable_v1::{ + zxdg_decoration_manager_v1::{ZxdgDecorationManagerV1, ZxdgDecorationManagerV1Handler}, + zxdg_toplevel_decoration_v1::{ + ZxdgToplevelDecorationV1, ZxdgToplevelDecorationV1Handler, + ZxdgToplevelDecorationV1Mode, + }, + }, xdg_shell::{ xdg_popup::XdgPopup, xdg_positioner::{XdgPositioner, XdgPositionerHandler}, @@ -90,6 +97,54 @@ impl WlSurfaceHandler for ClientWlSurface { } } +pub struct ClientZxdgDecorationManagerV1; + +impl ZxdgDecorationManagerV1Handler for ClientZxdgDecorationManagerV1 { + fn handle_destroy(&mut self, slf: &Rc) { + slf.delete_id(); + } + + fn handle_get_toplevel_decoration( + &mut self, + _slf: &Rc, + id: &Rc, + toplevel: &Rc, + ) { + id.set_handler(ClientZxdgToplevelDecorationV1 { + toplevel: toplevel.clone(), + }); + // TODO: send_configure here if a force mode is picked + } +} + +pub struct ClientZxdgToplevelDecorationV1 { + toplevel: Rc, +} + +impl ZxdgToplevelDecorationV1Handler for ClientZxdgToplevelDecorationV1 { + fn handle_destroy(&mut self, slf: &Rc) { + slf.delete_id(); + } + + fn handle_set_mode( + &mut self, + slf: &Rc, + mode: ZxdgToplevelDecorationV1Mode, + ) { + let toplevel_handler = self.toplevel.get_handler_ref::(); + toplevel_handler + .deco + .set_prefers_ssd(mode == ZxdgToplevelDecorationV1Mode::SERVER_SIDE); + slf.send_configure(mode); + } + + fn handle_unset_mode(&mut self, slf: &Rc) { + let toplevel_handler = self.toplevel.get_handler_ref::(); + toplevel_handler.deco.set_prefers_ssd(false); + slf.send_configure(ZxdgToplevelDecorationV1Mode::CLIENT_SIDE); + } +} + pub struct ClientXdgWmBase { pub globals: Rc, }