diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2024-02-04 22:10:26 +0400 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-02-04 22:10:26 +0400 |
| commit | b824cf90ab10f4ba5e1e0b23e0b2cf840814c02a (patch) | |
| tree | 9937888dc8edfa72b71c1f94a26909a467b73c83 /src | |
| parent | 7a4bb8ba8ae9022c572c5d4b66182f1af7fd3fb7 (diff) | |
| download | niri-b824cf90ab10f4ba5e1e0b23e0b2cf840814c02a.tar.gz niri-b824cf90ab10f4ba5e1e0b23e0b2cf840814c02a.tar.bz2 niri-b824cf90ab10f4ba5e1e0b23e0b2cf840814c02a.zip | |
layout: Generalize traversal between rendering and input
Diffstat (limited to 'src')
| -rw-r--r-- | src/layout/workspace.rs | 99 |
1 files changed, 48 insertions, 51 deletions
diff --git a/src/layout/workspace.rs b/src/layout/workspace.rs index 5ecd25e0..70237f06 100644 --- a/src/layout/workspace.rs +++ b/src/layout/workspace.rs @@ -1,5 +1,6 @@ use std::cmp::{max, min}; use std::iter::zip; +use std::ops::ControlFlow; use std::rc::Rc; use std::time::Duration; @@ -913,46 +914,36 @@ impl<W: LayoutElement> Workspace<W> { self.column_x(self.active_column_idx) + self.view_offset } - pub fn window_under( - &self, - pos: Point<f64, Logical>, - ) -> Option<(&W, Option<Point<i32, Logical>>)> { - if self.columns.is_empty() { - return None; - } - + fn with_tiles_in_render_order<'a, F, B>(&'a self, mut f: F) -> Option<B> + where + F: FnMut(&'a Tile<W>, Point<i32, Logical>) -> ControlFlow<B>, + { let view_pos = self.view_pos(); - // Prefer the active window since it's drawn on top. + // Start with the active window since it's drawn on top. let col = &self.columns[self.active_column_idx]; - let active_tile = &col.tiles[col.active_tile_idx]; + let tile = &col.tiles[col.active_tile_idx]; let tile_pos = Point::from(( self.column_x(self.active_column_idx) - view_pos, col.tile_y(col.active_tile_idx), )); - let pos_within_tile = pos - tile_pos.to_f64(); - if active_tile.is_in_input_region(pos_within_tile) { - let pos_within_surface = tile_pos + active_tile.buf_loc(); - return Some((active_tile.window(), Some(pos_within_surface))); - } else if active_tile.is_in_activation_region(pos_within_tile) { - return Some((active_tile.window(), None)); + + if let ControlFlow::Break(rv) = f(tile, tile_pos) { + return Some(rv); } let mut x = -view_pos; - for col in &self.columns { - for (tile, y) in zip(&col.tiles, col.tile_ys()) { - if tile.window() == active_tile.window() { + for (col_idx, col) in self.columns.iter().enumerate() { + for (tile_idx, (tile, y)) in zip(&col.tiles, col.tile_ys()).enumerate() { + if col_idx == self.active_column_idx && tile_idx == col.active_tile_idx { // Already handled it above. continue; } let tile_pos = Point::from((x, y)); - let pos_within_tile = pos - tile_pos.to_f64(); - if tile.is_in_input_region(pos_within_tile) { - let pos_within_surface = tile_pos + tile.buf_loc(); - return Some((tile.window(), Some(pos_within_surface))); - } else if tile.is_in_activation_region(pos_within_tile) { - return Some((tile.window(), None)); + + if let ControlFlow::Break(rv) = f(tile, tile_pos) { + return Some(rv); } } @@ -962,6 +953,28 @@ impl<W: LayoutElement> Workspace<W> { None } + pub fn window_under( + &self, + pos: Point<f64, Logical>, + ) -> Option<(&W, Option<Point<i32, Logical>>)> { + if self.columns.is_empty() { + return None; + } + + self.with_tiles_in_render_order(|tile, tile_pos| { + let pos_within_tile = pos - tile_pos.to_f64(); + + if tile.is_in_input_region(pos_within_tile) { + let pos_within_surface = tile_pos + tile.buf_loc(); + return ControlFlow::Break((tile.window(), Some(pos_within_surface))); + } else if tile.is_in_activation_region(pos_within_tile) { + return ControlFlow::Break((tile.window(), None)); + } + + ControlFlow::Continue(()) + }) + } + pub fn toggle_width(&mut self) { if self.columns.is_empty() { return; @@ -1079,36 +1092,20 @@ impl<W: LayoutElement> Workspace<W> { .unwrap_or(Scale::from(1.)); let mut rv = vec![]; - let view_pos = self.view_pos(); - - // Draw the active window on top. - let col = &self.columns[self.active_column_idx]; - let active_tile = &col.tiles[col.active_tile_idx]; - let tile_pos = Point::from(( - self.column_x(self.active_column_idx) - view_pos, - col.tile_y(col.active_tile_idx), - )); - - // Draw the window itself. - rv.extend(active_tile.render(renderer, tile_pos, output_scale)); + let mut first = true; - // Draw the focus ring. - rv.extend(self.focus_ring.render(output_scale).map(Into::into)); + self.with_tiles_in_render_order(|tile, tile_pos| { + // Draw the window itself. + rv.extend(tile.render(renderer, tile_pos, output_scale)); - let mut x = -view_pos; - for col in &self.columns { - for (tile, y) in zip(&col.tiles, col.tile_ys()) { - if tile.window() == active_tile.window() { - // Already handled it above. - continue; - } - - let tile_pos = Point::from((x, y)); - rv.extend(tile.render(renderer, tile_pos, output_scale)); + // For the active tile (which comes first), draw the focus ring. + if first { + rv.extend(self.focus_ring.render(output_scale).map(Into::into)); + first = false; } - x += col.width() + self.options.gaps; - } + ControlFlow::<()>::Continue(()) + }); rv } |
