diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2023-12-26 17:38:40 +0400 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2023-12-26 17:40:25 +0400 |
| commit | bfc24182670a0b3e17f79d66474fd291b7110732 (patch) | |
| tree | 0674de480fd356f32dbbec1bbbf453884d00d48c | |
| parent | 77b4715e0ba28ab324faa990d6c2b02ade01f2e2 (diff) | |
| download | niri-bfc24182670a0b3e17f79d66474fd291b7110732.tar.gz niri-bfc24182670a0b3e17f79d66474fd291b7110732.tar.bz2 niri-bfc24182670a0b3e17f79d66474fd291b7110732.zip | |
Make LayoutElement more visual-geometry-based
| -rw-r--r-- | src/layout/mod.rs | 85 | ||||
| -rw-r--r-- | src/layout/workspace.rs | 50 |
2 files changed, 91 insertions, 44 deletions
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<i32, Logical>; + /// 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<i32, Logical>; + + /// 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<i32, Logical>; + + /// 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<f64, Logical>) -> 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<R: Renderer + ImportAll>( + &self, + renderer: &mut R, + location: Point<i32, Logical>, + scale: Scale<f64>, + ) -> Vec<WorkspaceRenderElement<R>> + where + <R as Renderer>::TextureId: 'static; + fn request_size(&self, size: Size<i32, Logical>); fn request_fullscreen(&self, size: Size<i32, Logical>); fn min_size(&self) -> Size<i32, Logical>; @@ -156,12 +187,35 @@ impl Options { } impl LayoutElement for Window { - fn geometry(&self) -> Rectangle<i32, Logical> { - SpaceElement::geometry(self) + fn size(&self) -> Size<i32, Logical> { + self.geometry().size + } + + fn buf_loc(&self) -> Point<i32, Logical> { + Point::from((0, 0)) - self.geometry().loc } fn is_in_input_region(&self, point: Point<f64, Logical>) -> 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<R: Renderer + ImportAll>( + &self, + renderer: &mut R, + location: Point<i32, Logical>, + scale: Scale<f64>, + ) -> Vec<WorkspaceRenderElement<R>> + where + <R as Renderer>::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<i32, Logical>) { @@ -394,7 +448,7 @@ impl<W: LayoutElement> Layout<W> { ) -> 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<i32, Logical> { - self.0.bbox.get() + fn size(&self) -> Size<i32, Logical> { + self.0.bbox.get().size + } + + fn buf_loc(&self) -> Point<i32, Logical> { + (0, 0).into() } fn is_in_input_region(&self, _point: Point<f64, Logical>) -> bool { false } + fn render<R: Renderer + ImportAll>( + &self, + _renderer: &mut R, + _location: Point<i32, Logical>, + _scale: Scale<f64>, + ) -> Vec<WorkspaceRenderElement<R>> { + vec![] + } + fn request_size(&self, size: Size<i32, Logical>) { self.0.requested_size.set(Some(size)); } diff --git a/src/layout/workspace.rs b/src/layout/workspace.rs index 3e5f3c8f..2187fee0 100644 --- a/src/layout/workspace.rs +++ b/src/layout/workspace.rs @@ -4,7 +4,6 @@ use std::rc::Rc; use std::time::Duration; use smithay::backend::renderer::element::surface::WaylandSurfaceRenderElement; -use smithay::backend::renderer::element::AsRenderElements; use smithay::backend::renderer::gles::GlesRenderer; use smithay::backend::renderer::ImportAll; use smithay::desktop::space::SpaceElement; @@ -236,7 +235,7 @@ impl<W: LayoutElement> Workspace<W> { if !self.columns.is_empty() { let col = &self.columns[self.active_column_idx]; let active_win = &col.windows[col.active_window_idx]; - let geom = active_win.geometry(); + let size = active_win.size(); let has_ssd = active_win.has_ssd(); let win_pos = Point::from(( @@ -244,7 +243,7 @@ impl<W: LayoutElement> Workspace<W> { col.window_y(col.active_window_idx), )); - self.focus_ring.update(win_pos, geom.size, has_ssd); + self.focus_ring.update(win_pos, size, has_ssd); self.focus_ring.set_active(is_active); } } @@ -742,13 +741,12 @@ impl<W: LayoutElement> Workspace<W> { // Prefer the active window since it's drawn on top. let col = &self.columns[self.active_column_idx]; let active_win = &col.windows[col.active_window_idx]; - let geom = active_win.geometry(); - let buf_pos = Point::from(( + let win_pos = Point::from(( self.column_x(self.active_column_idx) - view_pos, col.window_y(col.active_window_idx), - )) - geom.loc; - if active_win.is_in_input_region(pos - buf_pos.to_f64()) { - return Some((active_win, buf_pos)); + )); + if active_win.is_in_input_region(pos - win_pos.to_f64()) { + return Some((active_win, win_pos + active_win.buf_loc())); } let mut x = -view_pos; @@ -759,10 +757,9 @@ impl<W: LayoutElement> Workspace<W> { continue; } - let geom = win.geometry(); - let buf_pos = Point::from((x, y)) - geom.loc; - if win.is_in_input_region(pos - buf_pos.to_f64()) { - return Some((win, buf_pos)); + let win_pos = Point::from((x, y)); + if win.is_in_input_region(pos - win_pos.to_f64()) { + return Some((win, win_pos + win.buf_loc())); } } @@ -917,14 +914,7 @@ impl Workspace<Window> { )); // Draw the window itself. - let geom = active_win.geometry(); - let buf_pos = win_pos - geom.loc; - rv.extend(active_win.render_elements( - renderer, - buf_pos.to_physical_precise_round(output_scale), - output_scale, - 1., - )); + rv.extend(active_win.render(renderer, win_pos, output_scale)); // Draw the focus ring. rv.extend(self.focus_ring.render(output_scale).map(Into::into)); @@ -937,14 +927,8 @@ impl Workspace<Window> { continue; } - let geom = win.geometry(); - let buf_pos = Point::from((x, y)) - geom.loc; - rv.extend(win.render_elements( - renderer, - buf_pos.to_physical_precise_round(output_scale), - output_scale, - 1., - )); + let win_pos = Point::from((x, y)); + rv.extend(win.render(renderer, win_pos, output_scale)); } x += col.width() + self.options.gaps; @@ -1189,11 +1173,7 @@ impl<W: LayoutElement> Column<W> { } fn width(&self) -> i32 { - self.windows - .iter() - .map(|win| win.geometry().size.w) - .max() - .unwrap() + self.windows.iter().map(|win| win.size().w).max().unwrap() } fn focus_up(&mut self) { @@ -1312,7 +1292,7 @@ impl<W: LayoutElement> Column<W> { fn set_window_height(&mut self, change: SizeChange) { let current = self.heights[self.active_window_idx]; let current_px = match current { - WindowHeight::Auto => self.windows[self.active_window_idx].geometry().size.h, + WindowHeight::Auto => self.windows[self.active_window_idx].size().h, WindowHeight::Fixed(height) => height, }; let current_prop = (current_px + self.options.gaps) as f64 @@ -1372,7 +1352,7 @@ impl<W: LayoutElement> Column<W> { self.windows.iter().map(move |win| { let pos = y; - y += win.geometry().size.h + self.options.gaps; + y += win.size().h + self.options.gaps; pos }) } |
