From bfc24182670a0b3e17f79d66474fd291b7110732 Mon Sep 17 00:00:00 2001 From: Ivan Molodetskikh Date: Tue, 26 Dec 2023 17:38:40 +0400 Subject: Make LayoutElement more visual-geometry-based --- src/layout/mod.rs | 85 +++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 76 insertions(+), 9 deletions(-) (limited to 'src/layout/mod.rs') diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 79c7cd19..61aaf211 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -33,19 +33,23 @@ use std::mem; use std::rc::Rc; use std::time::Duration; +use smithay::backend::renderer::element::AsRenderElements; +use smithay::backend::renderer::{ImportAll, Renderer}; use smithay::desktop::space::SpaceElement; use smithay::desktop::Window; use smithay::output::Output; use smithay::reexports::wayland_protocols::xdg::decoration::zv1::server::zxdg_toplevel_decoration_v1; use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel; use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface; -use smithay::utils::{Logical, Point, Rectangle, Size, Transform}; +use smithay::utils::{Logical, Point, Rectangle, Scale, Size, Transform}; use smithay::wayland::compositor::{send_surface_state, with_states}; use smithay::wayland::shell::xdg::SurfaceCachedState; pub use self::monitor::MonitorRenderElement; use self::monitor::{Monitor, WorkspaceSwitch, WorkspaceSwitchGesture}; -use self::workspace::{compute_working_area, ColumnWidth, OutputId, Workspace}; +use self::workspace::{ + compute_working_area, ColumnWidth, OutputId, Workspace, WorkspaceRenderElement, +}; use crate::animation::Animation; use crate::config::{self, Config, SizeChange, Struts}; use crate::utils::output_size; @@ -55,8 +59,35 @@ mod monitor; mod workspace; pub trait LayoutElement: PartialEq { - fn geometry(&self) -> Rectangle; + /// Visual size of the element. + /// + /// This is what the user would consider the size, i.e. excluding CSD shadows and whatnot. + /// Corresponds to the Wayland window geometry size. + fn size(&self) -> Size; + + /// Returns the location of the element's buffer relative to the element's visual geometry. + /// + /// I.e. if the element has CSD shadows, its buffer location will have negative coordinates. + fn buf_loc(&self) -> Point; + + /// Checks whether a point is in the element's input region. + /// + /// The point is relative to the element's visual geometry. fn is_in_input_region(&self, point: Point) -> bool; + + /// Renders the element at the given visual location. + /// + /// The element should be rendered in such a way that its visual geometry ends up at the given + /// location. + fn render( + &self, + renderer: &mut R, + location: Point, + scale: Scale, + ) -> Vec> + where + ::TextureId: 'static; + fn request_size(&self, size: Size); fn request_fullscreen(&self, size: Size); fn min_size(&self) -> Size; @@ -156,12 +187,35 @@ impl Options { } impl LayoutElement for Window { - fn geometry(&self) -> Rectangle { - SpaceElement::geometry(self) + fn size(&self) -> Size { + self.geometry().size + } + + fn buf_loc(&self) -> Point { + Point::from((0, 0)) - self.geometry().loc } fn is_in_input_region(&self, point: Point) -> bool { - SpaceElement::is_in_input_region(self, &point) + let surace_local = point + self.geometry().loc.to_f64(); + SpaceElement::is_in_input_region(self, &surace_local) + } + + fn render( + &self, + renderer: &mut R, + location: Point, + scale: Scale, + ) -> Vec> + where + ::TextureId: 'static, + { + let buf_pos = location - self.geometry().loc; + self.render_elements( + renderer, + buf_pos.to_physical_precise_round(scale), + scale, + 1., + ) } fn request_size(&self, size: Size) { @@ -394,7 +448,7 @@ impl Layout { ) -> Option<&Output> { let width = width .or(self.options.default_width) - .unwrap_or_else(|| ColumnWidth::Fixed(window.geometry().size.w)); + .unwrap_or_else(|| ColumnWidth::Fixed(window.size().w)); match &mut self.monitor_set { MonitorSet::Normal { @@ -1356,14 +1410,27 @@ mod tests { } impl LayoutElement for TestWindow { - fn geometry(&self) -> Rectangle { - self.0.bbox.get() + fn size(&self) -> Size { + self.0.bbox.get().size + } + + fn buf_loc(&self) -> Point { + (0, 0).into() } fn is_in_input_region(&self, _point: Point) -> bool { false } + fn render( + &self, + _renderer: &mut R, + _location: Point, + _scale: Scale, + ) -> Vec> { + vec![] + } + fn request_size(&self, size: Size) { self.0.requested_size.set(Some(size)); } -- cgit