diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2025-04-04 11:46:22 +0300 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2025-04-25 02:00:18 -0700 |
| commit | 21630ddb5ebd078c5a6400d6d56c44f0903f1d44 (patch) | |
| tree | 4d65b2b45f43ceba7653b5189d95f877dd55f302 /src/layout/monitor.rs | |
| parent | 9e5e0c85bb3c50d00108a4a2de0fe45bfc4ebb8d (diff) | |
| download | niri-21630ddb5ebd078c5a6400d6d56c44f0903f1d44.tar.gz niri-21630ddb5ebd078c5a6400d6d56c44f0903f1d44.tar.bz2 niri-21630ddb5ebd078c5a6400d6d56c44f0903f1d44.zip | |
layout/monitor: Extract workspaces_render_geo()
Diffstat (limited to 'src/layout/monitor.rs')
| -rw-r--r-- | src/layout/monitor.rs | 146 |
1 files changed, 65 insertions, 81 deletions
diff --git a/src/layout/monitor.rs b/src/layout/monitor.rs index 2c2ea0f8..8f300812 100644 --- a/src/layout/monitor.rs +++ b/src/layout/monitor.rs @@ -1,4 +1,5 @@ use std::cmp::min; +use std::iter::zip; use std::rc::Rc; use std::time::Duration; @@ -20,7 +21,7 @@ use crate::render_helpers::renderer::NiriRenderer; use crate::render_helpers::RenderTarget; use crate::rubber_band::RubberBand; use crate::utils::transaction::Transaction; -use crate::utils::{output_size, round_logical_in_physical, ResizeEdge}; +use crate::utils::{output_size, ResizeEdge}; /// Amount of touchpad movement to scroll the height of one workspace. const WORKSPACE_GESTURE_MOVEMENT: f64 = 300.; @@ -680,31 +681,8 @@ impl<W: LayoutElement> Monitor<W> { } pub fn update_render_elements(&mut self, is_active: bool) { - match &self.workspace_switch { - Some(switch) => { - let render_idx = switch.current_idx(); - let before_idx = render_idx.floor(); - let after_idx = render_idx.ceil(); - - if after_idx < 0. || before_idx as usize >= self.workspaces.len() { - return; - } - - let after_idx = after_idx as usize; - if after_idx < self.workspaces.len() { - self.workspaces[after_idx].update_render_elements(is_active); - - if before_idx < 0. { - return; - } - } - - let before_idx = before_idx as usize; - self.workspaces[before_idx].update_render_elements(is_active); - } - None => { - self.workspaces[self.active_workspace_idx].update_render_elements(is_active); - } + for (ws, _) in self.workspaces_with_render_geo_mut() { + ws.update_render_elements(is_active); } } @@ -855,72 +833,78 @@ impl<W: LayoutElement> Monitor<W> { Some(rect) } - pub fn workspaces_with_render_positions( + pub fn workspaces_render_geo(&self) -> impl Iterator<Item = Rectangle<f64, Logical>> { + let scale = self.output.current_scale().fractional_scale(); + let size = output_size(&self.output); + + // Ceil the workspace size in physical pixels. + let ws_size = size.to_physical_precise_ceil(scale).to_logical(scale); + + let render_idx = if let Some(switch) = &self.workspace_switch { + switch.current_idx() + } else { + self.active_workspace_idx as f64 + }; + + let first_ws_y = -render_idx * ws_size.h; + + (0..self.workspaces.len()).map(move |idx| { + let y = first_ws_y + idx as f64 * ws_size.h; + let loc = Point::from((0., y)); + let loc = loc.to_physical_precise_round(scale).to_logical(scale); + Rectangle::new(loc, ws_size) + }) + } + + pub fn workspaces_with_render_geo( &self, - ) -> impl Iterator<Item = (&Workspace<W>, Point<f64, Logical>)> { - let mut first = None; - let mut second = None; - - match &self.workspace_switch { - Some(switch) => { - let render_idx = switch.current_idx(); - let before_idx = render_idx.floor(); - let after_idx = render_idx.ceil(); - - if after_idx >= 0. && before_idx < self.workspaces.len() as f64 { - let scale = self.output.current_scale().fractional_scale(); - let size = output_size(&self.output); - let offset = - round_logical_in_physical(scale, (render_idx - before_idx) * size.h); - - // Ceil the height in physical pixels. - let height = (size.h * scale).ceil() / scale; - - if before_idx >= 0. { - let before_idx = before_idx as usize; - let before_offset = Point::from((0., -offset)); - first = Some((&self.workspaces[before_idx], before_offset)); - } - - let after_idx = after_idx as usize; - if after_idx < self.workspaces.len() { - let after_offset = Point::from((0., -offset + height)); - second = Some((&self.workspaces[after_idx], after_offset)); - } - } - } - None => { - first = Some(( - &self.workspaces[self.active_workspace_idx], - Point::from((0., 0.)), - )); - } - } + ) -> impl Iterator<Item = (&Workspace<W>, Rectangle<f64, Logical>)> { + let output_size = output_size(&self.output); + let output_geo = Rectangle::new(Point::from((0., 0.)), output_size); + + let geo = self.workspaces_render_geo(); + zip(self.workspaces.iter(), geo) + // Cull out workspaces outside the output. + .filter(move |(_ws, geo)| geo.intersection(output_geo).is_some()) + } - first.into_iter().chain(second) + pub fn workspaces_with_render_geo_mut( + &mut self, + ) -> impl Iterator<Item = (&mut Workspace<W>, Rectangle<f64, Logical>)> { + let output_size = output_size(&self.output); + let output_geo = Rectangle::new(Point::from((0., 0.)), output_size); + + let geo = self.workspaces_render_geo(); + zip(self.workspaces.iter_mut(), geo) + // Cull out workspaces outside the output. + .filter(move |(_ws, geo)| geo.intersection(output_geo).is_some()) } pub fn workspace_under( &self, pos_within_output: Point<f64, Logical>, - ) -> Option<(&Workspace<W>, Point<f64, Logical>)> { + ) -> Option<(&Workspace<W>, Rectangle<f64, Logical>)> { let size = output_size(&self.output); - let (ws, bounds) = self - .workspaces_with_render_positions() - .map(|(ws, offset)| (ws, Rectangle::new(offset, size))) - .find(|(_, bounds)| bounds.contains(pos_within_output))?; - Some((ws, bounds.loc)) + let (ws, geo) = self.workspaces_with_render_geo().find_map(|(ws, geo)| { + // Extend width to entire output. + let loc = Point::from((0., geo.loc.y)); + let size = Size::from((size.w, geo.size.h)); + let bounds = Rectangle::new(loc, size); + + bounds.contains(pos_within_output).then_some((ws, geo)) + })?; + Some((ws, geo)) } pub fn window_under(&self, pos_within_output: Point<f64, Logical>) -> Option<(&W, HitType)> { - let (ws, offset) = self.workspace_under(pos_within_output)?; - let (win, hit) = ws.window_under(pos_within_output - offset)?; - Some((win, hit.offset_win_pos(offset))) + let (ws, geo) = self.workspace_under(pos_within_output)?; + let (win, hit) = ws.window_under(pos_within_output - geo.loc)?; + Some((win, hit.offset_win_pos(geo.loc))) } pub fn resize_edges_under(&self, pos_within_output: Point<f64, Logical>) -> Option<ResizeEdge> { - let (ws, offset) = self.workspace_under(pos_within_output)?; - ws.resize_edges_under(pos_within_output - offset) + let (ws, geo) = self.workspace_under(pos_within_output)?; + ws.resize_edges_under(pos_within_output - geo.loc) } pub fn render_above_top_layer(&self) -> bool { @@ -968,8 +952,8 @@ impl<W: LayoutElement> Monitor<W> { ) }; - self.workspaces_with_render_positions() - .flat_map(move |(ws, offset)| { + self.workspaces_with_render_geo() + .flat_map(move |(ws, geo)| { ws.render_elements(renderer, target, focus_ring) .filter_map(move |elem| { CropRenderElement::from_element(elem, scale, crop_bounds) @@ -980,7 +964,7 @@ impl<W: LayoutElement> Monitor<W> { // The offset we get from workspaces_with_render_positions() is already // rounded to physical pixels, but it's in the logical coordinate // space, so we need to convert it to physical. - offset.to_physical_precise_round(scale), + geo.loc.to_physical_precise_round(scale), Relocate::Relative, ) }) |
