aboutsummaryrefslogtreecommitdiff
path: root/src/layout/monitor.rs
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2025-04-04 11:46:22 +0300
committerIvan Molodetskikh <yalterz@gmail.com>2025-04-25 02:00:18 -0700
commit21630ddb5ebd078c5a6400d6d56c44f0903f1d44 (patch)
tree4d65b2b45f43ceba7653b5189d95f877dd55f302 /src/layout/monitor.rs
parent9e5e0c85bb3c50d00108a4a2de0fe45bfc4ebb8d (diff)
downloadniri-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.rs146
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,
)
})