diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2025-02-09 19:14:04 +0300 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2025-02-10 07:29:33 -0800 |
| commit | 6bd92ab926b53d8da916966798213fcc9b0bf0b2 (patch) | |
| tree | ad6e48d83f87eb64f5bf097ff3b950143236e270 /src | |
| parent | 02eccf7762bf01cca0bf066d769e2533e2d5a3d2 (diff) | |
| download | niri-6bd92ab926b53d8da916966798213fcc9b0bf0b2.tar.gz niri-6bd92ab926b53d8da916966798213fcc9b0bf0b2.tar.bz2 niri-6bd92ab926b53d8da916966798213fcc9b0bf0b2.zip | |
tab indicator: Fix gradient area computation
The gradient area should be relative to each tab's geometry. In most cases
these geometries will all match, but not when some tabs have a different size,
for example when they have a fixed size.
Diffstat (limited to 'src')
| -rw-r--r-- | src/layout/scrolling.rs | 28 | ||||
| -rw-r--r-- | src/layout/tab_indicator.rs | 41 |
2 files changed, 39 insertions, 30 deletions
diff --git a/src/layout/scrolling.rs b/src/layout/scrolling.rs index 59681cdf..45323ec7 100644 --- a/src/layout/scrolling.rs +++ b/src/layout/scrolling.rs @@ -2608,10 +2608,7 @@ impl<W: LayoutElement> ScrollingSpace<W> { // Draw the tab indicator on top. { - // This is the "static tile position" so to say: it excludes the tile offset (used - // for e.g. centering smaller tiles in always-center) and the tile render offset - // (used for tile-specific animations). - let pos = view_off + col_off + col_render_off + col.tiles_origin(); + let pos = view_off + col_off + col_render_off; let pos = pos.to_physical_precise_round(scale).to_logical(scale); rv.extend(col.tab_indicator.render(renderer, pos).map(Into::into)); } @@ -3473,15 +3470,15 @@ impl<W: LayoutElement> Column<W> { tile.update_render_elements(is_active, tile_view_rect); } - let (tile, tile_off) = self.tiles().nth(self.active_tile_idx).unwrap(); - let mut tile_view_rect = view_rect; - tile_view_rect.loc -= tile_off + tile.render_offset(); - let config = self.tab_indicator.config(); - let tabs = self.tiles.iter().enumerate().map(|(tile_idx, tile)| { - let is_active = tile_idx == active_idx; - TabInfo::from_tile(tile, is_active, &config) - }); + let offsets = self.tile_offsets_iter(self.data.iter().copied()); + let tabs = zip(&self.tiles, offsets) + .enumerate() + .map(|(tile_idx, (tile, tile_off))| { + let is_active = tile_idx == active_idx; + let tile_pos = tile_off + tile.render_offset(); + TabInfo::from_tile(tile, tile_pos, is_active, &config) + }); // Hide the tab indicator in fullscreen. If you have it configured to overlap the window, // you don't want that to happen in fullscreen. Also, laying things out correctly when the @@ -3489,10 +3486,13 @@ impl<W: LayoutElement> Column<W> { // many changes to the code for too little benefit (it's mostly invisible anyway). let enabled = self.display_mode == ColumnDisplay::Tabbed && !self.is_fullscreen; + let area_size = self.tiles[active_idx].animated_tile_size(); + self.tab_indicator.update_render_elements( enabled, - tile.animated_tile_size(), - tile_view_rect, + Rectangle::new(self.tiles_origin(), area_size), + view_rect, + self.tiles.len(), tabs, is_active, self.scale, diff --git a/src/layout/tab_indicator.rs b/src/layout/tab_indicator.rs index 84e65dfc..952e2ef6 100644 --- a/src/layout/tab_indicator.rs +++ b/src/layout/tab_indicator.rs @@ -20,7 +20,10 @@ pub struct TabIndicator { #[derive(Debug)] pub struct TabInfo { + /// Gradient for the tab indicator. pub gradient: Gradient, + /// Tab geometry in the same coordinate system as the area. + pub geometry: Rectangle<f64, Logical>, } niri_render_elements! { @@ -48,12 +51,17 @@ impl TabIndicator { } } + #[allow(clippy::too_many_arguments)] pub fn update_render_elements( &mut self, enabled: bool, - tile_size: Size<f64, Logical>, - tile_view_rect: Rectangle<f64, Logical>, - tabs: impl Iterator<Item = TabInfo> + Clone, + // Geometry of the tabs area. + area: Rectangle<f64, Logical>, + // View rect relative to the tabs area. + area_view_rect: Rectangle<f64, Logical>, + // Tab count, should match the tabs iterator length. + tab_count: usize, + tabs: impl Iterator<Item = TabInfo>, // TODO: do we indicate inactive-but-selected somehow? _is_active: bool, scale: f64, @@ -64,16 +72,13 @@ impl TabIndicator { return; } - let count = tabs.clone().count(); + let count = tab_count; if self.config.hide_when_single_tab && count == 1 { self.shader_locs.clear(); self.shaders.clear(); return; } - // Tab indicators are rendered relative to the tile geometry. - let tile_geo = Rectangle::new(Point::from((0., 0.)), tile_size); - let round = |logical: f64| round_logical_in_physical(scale, logical); let width = round(self.config.width.0); @@ -81,8 +86,8 @@ impl TabIndicator { let gaps_between = round(self.config.gaps_between_tabs.0); let side = match self.config.position { - TabIndicatorPosition::Left | TabIndicatorPosition::Right => tile_size.h, - TabIndicatorPosition::Top | TabIndicatorPosition::Bottom => tile_size.w, + TabIndicatorPosition::Left | TabIndicatorPosition::Right => area.size.h, + TabIndicatorPosition::Top | TabIndicatorPosition::Bottom => area.size.w, }; let total_prop = self.config.length.total_proportion.unwrap_or(0.5); let min_length = round(side * total_prop.clamp(0., 2.)); @@ -101,13 +106,14 @@ impl TabIndicator { let mut shader_loc = Point::from((-gap - width, round((side - length) / 2.))); match self.config.position { TabIndicatorPosition::Left => (), - TabIndicatorPosition::Right => shader_loc.x = tile_size.w + gap, + TabIndicatorPosition::Right => shader_loc.x = area.size.w + gap, TabIndicatorPosition::Top => mem::swap(&mut shader_loc.x, &mut shader_loc.y), TabIndicatorPosition::Bottom => { shader_loc.x = shader_loc.y; - shader_loc.y = tile_size.h + gap; + shader_loc.y = area.size.h + gap; } } + shader_loc += area.loc; for ((shader, loc), tab) in zip(&mut self.shaders, &mut self.shader_locs).zip(tabs) { *loc = shader_loc; @@ -137,8 +143,8 @@ impl TabIndicator { }; let mut gradient_area = match tab.gradient.relative_to { - GradientRelativeTo::Window => tile_geo, - GradientRelativeTo::WorkspaceView => tile_view_rect, + GradientRelativeTo::Window => tab.geometry, + GradientRelativeTo::WorkspaceView => area_view_rect, }; gradient_area.loc -= *loc; @@ -161,7 +167,7 @@ impl TabIndicator { pub fn render( &self, renderer: &mut impl NiriRenderer, - tile_pos: Point<f64, Logical>, + pos: Point<f64, Logical>, ) -> impl Iterator<Item = TabIndicatorRenderElement> + '_ { let has_border_shader = BorderRenderElement::has_shader(renderer); if !has_border_shader { @@ -169,7 +175,7 @@ impl TabIndicator { } let rv = zip(&self.shaders, &self.shader_locs) - .map(move |(shader, loc)| shader.clone().with_location(tile_pos + *loc)) + .map(move |(shader, loc)| shader.clone().with_location(pos + *loc)) .map(TabIndicatorRenderElement::from); Some(rv).into_iter().flatten() @@ -216,6 +222,7 @@ impl TabIndicator { impl TabInfo { pub fn from_tile<W: LayoutElement>( tile: &Tile<W>, + position: Point<f64, Logical>, is_active: bool, config: &niri_config::TabIndicator, ) -> Self { @@ -265,6 +272,8 @@ impl TabInfo { .or_else(gradient_from_config) .unwrap_or_else(gradient_from_border); - TabInfo { gradient } + let geometry = Rectangle::new(position, tile.animated_tile_size()); + + TabInfo { gradient, geometry } } } |
