mirror of
https://github.com/niri-wm/niri.git
synced 2026-06-24 02:01:18 +07:00
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.
This commit is contained in:
+12
-12
@@ -2608,10 +2608,7 @@ impl<W: LayoutElement> ScrollingSpace<W> {
|
|||||||
|
|
||||||
// Draw the tab indicator on top.
|
// Draw the tab indicator on top.
|
||||||
{
|
{
|
||||||
// This is the "static tile position" so to say: it excludes the tile offset (used
|
let pos = view_off + col_off + col_render_off;
|
||||||
// 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 = pos.to_physical_precise_round(scale).to_logical(scale);
|
let pos = pos.to_physical_precise_round(scale).to_logical(scale);
|
||||||
rv.extend(col.tab_indicator.render(renderer, pos).map(Into::into));
|
rv.extend(col.tab_indicator.render(renderer, pos).map(Into::into));
|
||||||
}
|
}
|
||||||
@@ -3473,14 +3470,14 @@ impl<W: LayoutElement> Column<W> {
|
|||||||
tile.update_render_elements(is_active, tile_view_rect);
|
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 config = self.tab_indicator.config();
|
||||||
let tabs = self.tiles.iter().enumerate().map(|(tile_idx, tile)| {
|
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 is_active = tile_idx == active_idx;
|
||||||
TabInfo::from_tile(tile, is_active, &config)
|
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,
|
// Hide the tab indicator in fullscreen. If you have it configured to overlap the window,
|
||||||
@@ -3489,10 +3486,13 @@ impl<W: LayoutElement> Column<W> {
|
|||||||
// many changes to the code for too little benefit (it's mostly invisible anyway).
|
// 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 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(
|
self.tab_indicator.update_render_elements(
|
||||||
enabled,
|
enabled,
|
||||||
tile.animated_tile_size(),
|
Rectangle::new(self.tiles_origin(), area_size),
|
||||||
tile_view_rect,
|
view_rect,
|
||||||
|
self.tiles.len(),
|
||||||
tabs,
|
tabs,
|
||||||
is_active,
|
is_active,
|
||||||
self.scale,
|
self.scale,
|
||||||
|
|||||||
+25
-16
@@ -20,7 +20,10 @@ pub struct TabIndicator {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TabInfo {
|
pub struct TabInfo {
|
||||||
|
/// Gradient for the tab indicator.
|
||||||
pub gradient: Gradient,
|
pub gradient: Gradient,
|
||||||
|
/// Tab geometry in the same coordinate system as the area.
|
||||||
|
pub geometry: Rectangle<f64, Logical>,
|
||||||
}
|
}
|
||||||
|
|
||||||
niri_render_elements! {
|
niri_render_elements! {
|
||||||
@@ -48,12 +51,17 @@ impl TabIndicator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn update_render_elements(
|
pub fn update_render_elements(
|
||||||
&mut self,
|
&mut self,
|
||||||
enabled: bool,
|
enabled: bool,
|
||||||
tile_size: Size<f64, Logical>,
|
// Geometry of the tabs area.
|
||||||
tile_view_rect: Rectangle<f64, Logical>,
|
area: Rectangle<f64, Logical>,
|
||||||
tabs: impl Iterator<Item = TabInfo> + Clone,
|
// 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?
|
// TODO: do we indicate inactive-but-selected somehow?
|
||||||
_is_active: bool,
|
_is_active: bool,
|
||||||
scale: f64,
|
scale: f64,
|
||||||
@@ -64,16 +72,13 @@ impl TabIndicator {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let count = tabs.clone().count();
|
let count = tab_count;
|
||||||
if self.config.hide_when_single_tab && count == 1 {
|
if self.config.hide_when_single_tab && count == 1 {
|
||||||
self.shader_locs.clear();
|
self.shader_locs.clear();
|
||||||
self.shaders.clear();
|
self.shaders.clear();
|
||||||
return;
|
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 round = |logical: f64| round_logical_in_physical(scale, logical);
|
||||||
|
|
||||||
let width = round(self.config.width.0);
|
let width = round(self.config.width.0);
|
||||||
@@ -81,8 +86,8 @@ impl TabIndicator {
|
|||||||
let gaps_between = round(self.config.gaps_between_tabs.0);
|
let gaps_between = round(self.config.gaps_between_tabs.0);
|
||||||
|
|
||||||
let side = match self.config.position {
|
let side = match self.config.position {
|
||||||
TabIndicatorPosition::Left | TabIndicatorPosition::Right => tile_size.h,
|
TabIndicatorPosition::Left | TabIndicatorPosition::Right => area.size.h,
|
||||||
TabIndicatorPosition::Top | TabIndicatorPosition::Bottom => tile_size.w,
|
TabIndicatorPosition::Top | TabIndicatorPosition::Bottom => area.size.w,
|
||||||
};
|
};
|
||||||
let total_prop = self.config.length.total_proportion.unwrap_or(0.5);
|
let total_prop = self.config.length.total_proportion.unwrap_or(0.5);
|
||||||
let min_length = round(side * total_prop.clamp(0., 2.));
|
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.)));
|
let mut shader_loc = Point::from((-gap - width, round((side - length) / 2.)));
|
||||||
match self.config.position {
|
match self.config.position {
|
||||||
TabIndicatorPosition::Left => (),
|
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::Top => mem::swap(&mut shader_loc.x, &mut shader_loc.y),
|
||||||
TabIndicatorPosition::Bottom => {
|
TabIndicatorPosition::Bottom => {
|
||||||
shader_loc.x = shader_loc.y;
|
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) {
|
for ((shader, loc), tab) in zip(&mut self.shaders, &mut self.shader_locs).zip(tabs) {
|
||||||
*loc = shader_loc;
|
*loc = shader_loc;
|
||||||
@@ -137,8 +143,8 @@ impl TabIndicator {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let mut gradient_area = match tab.gradient.relative_to {
|
let mut gradient_area = match tab.gradient.relative_to {
|
||||||
GradientRelativeTo::Window => tile_geo,
|
GradientRelativeTo::Window => tab.geometry,
|
||||||
GradientRelativeTo::WorkspaceView => tile_view_rect,
|
GradientRelativeTo::WorkspaceView => area_view_rect,
|
||||||
};
|
};
|
||||||
gradient_area.loc -= *loc;
|
gradient_area.loc -= *loc;
|
||||||
|
|
||||||
@@ -161,7 +167,7 @@ impl TabIndicator {
|
|||||||
pub fn render(
|
pub fn render(
|
||||||
&self,
|
&self,
|
||||||
renderer: &mut impl NiriRenderer,
|
renderer: &mut impl NiriRenderer,
|
||||||
tile_pos: Point<f64, Logical>,
|
pos: Point<f64, Logical>,
|
||||||
) -> impl Iterator<Item = TabIndicatorRenderElement> + '_ {
|
) -> impl Iterator<Item = TabIndicatorRenderElement> + '_ {
|
||||||
let has_border_shader = BorderRenderElement::has_shader(renderer);
|
let has_border_shader = BorderRenderElement::has_shader(renderer);
|
||||||
if !has_border_shader {
|
if !has_border_shader {
|
||||||
@@ -169,7 +175,7 @@ impl TabIndicator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let rv = zip(&self.shaders, &self.shader_locs)
|
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);
|
.map(TabIndicatorRenderElement::from);
|
||||||
|
|
||||||
Some(rv).into_iter().flatten()
|
Some(rv).into_iter().flatten()
|
||||||
@@ -216,6 +222,7 @@ impl TabIndicator {
|
|||||||
impl TabInfo {
|
impl TabInfo {
|
||||||
pub fn from_tile<W: LayoutElement>(
|
pub fn from_tile<W: LayoutElement>(
|
||||||
tile: &Tile<W>,
|
tile: &Tile<W>,
|
||||||
|
position: Point<f64, Logical>,
|
||||||
is_active: bool,
|
is_active: bool,
|
||||||
config: &niri_config::TabIndicator,
|
config: &niri_config::TabIndicator,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
@@ -265,6 +272,8 @@ impl TabInfo {
|
|||||||
.or_else(gradient_from_config)
|
.or_else(gradient_from_config)
|
||||||
.unwrap_or_else(gradient_from_border);
|
.unwrap_or_else(gradient_from_border);
|
||||||
|
|
||||||
TabInfo { gradient }
|
let geometry = Rectangle::new(position, tile.animated_tile_size());
|
||||||
|
|
||||||
|
TabInfo { gradient, geometry }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user