use std::{cell::RefCell, rc::Rc}; use wl_proxy::{ object::ObjectCoreApi, protocols::wayland::{wl_buffer::WlBuffer, wl_subsurface::WlSubsurface, wl_surface::WlSurface}, }; use crate::{buffer::SimpleBufferPool, globals::Globals, util::Bounds}; pub struct Deco { bounds: RefCell, top_size: i32, border_size: i32, wl_surface: Rc, subsurface: Rc, pool: RefCell, globals: Rc, } impl Deco { pub fn new(host_surface: &Rc, globals: &Rc) -> Deco { let wl_surface = globals.wl_compositor.new_send_create_surface(); wl_surface.set_forward_to_client(false); let subsurface = globals .wl_subcompositor .new_send_get_subsurface(&wl_surface, host_surface); subsurface.set_forward_to_client(false); subsurface.send_place_below(&host_surface); let pool = SimpleBufferPool::new(globals, 1, 1).unwrap(); Deco { bounds: RefCell::new(Bounds { x: 0, y: 0, width: 10, height: 10, }), top_size: 24, border_size: 8, wl_surface, subsurface, pool: RefCell::new(pool), globals: globals.clone(), } } pub fn handle_window_geometry( &self, x: i32, y: i32, width: i32, height: i32, ) -> eyre::Result<(i32, i32, i32, i32)> { self.bounds.replace(Bounds { x, y, width, height, }); self.draw()?; let width = width + self.border_size * 2; let height = height + self.top_size + self.border_size; Ok((x - self.border_size, y - self.top_size, width, height)) } pub fn transform_configure(&self, width: i32, height: i32) -> (i32, i32) { ( width - self.border_size * 2, height - self.top_size - self.border_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; log::info!("{:?} -> {}x{}", bounds, width, height); let mut pool = self.pool.borrow_mut(); let (buf, map) = pool.buffer(width, height)?; for y in 0..height { for x in 0..width * 4 { map[(y * (width * 4) + x) as usize] = 0xaf; } } self.wl_surface.send_attach(Some(&buf), 0, 0); 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); 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); self.wl_surface.send_commit(); // let _ = self.globals.wl_display.new_send_sync(); Ok(buf) } }