diff options
| author | Ivan Molodetskikh <yalterz@gmail.com> | 2024-05-04 11:10:02 +0400 |
|---|---|---|
| committer | Ivan Molodetskikh <yalterz@gmail.com> | 2024-05-04 11:10:02 +0400 |
| commit | 73cc0079d628e66b1d64168ed1a10b13b23ab5d0 (patch) | |
| tree | 168aa5d885c2061c8ec9090e1cd46b865a6f2a42 /src/layout/focus_ring.rs | |
| parent | 69aeba2a4d93b34eb24319c3694ad354dc608a87 (diff) | |
| download | niri-73cc0079d628e66b1d64168ed1a10b13b23ab5d0.tar.gz niri-73cc0079d628e66b1d64168ed1a10b13b23ab5d0.tar.bz2 niri-73cc0079d628e66b1d64168ed1a10b13b23ab5d0.zip | |
Split update_render_elements() from advance_animations()
advance_animations() is called from places like input, whereas
update_render_elements() is strictly for rendering.
Diffstat (limited to 'src/layout/focus_ring.rs')
| -rw-r--r-- | src/layout/focus_ring.rs | 189 |
1 files changed, 88 insertions, 101 deletions
diff --git a/src/layout/focus_ring.rs b/src/layout/focus_ring.rs index a0d0acfe..b198e838 100644 --- a/src/layout/focus_ring.rs +++ b/src/layout/focus_ring.rs @@ -1,9 +1,8 @@ -use std::cell::RefCell; use std::cmp::{max, min}; use std::iter::zip; use arrayvec::ArrayVec; -use niri_config::{CornerRadius, GradientRelativeTo}; +use niri_config::{CornerRadius, Gradient, GradientRelativeTo}; use smithay::backend::renderer::element::solid::{SolidColorBuffer, SolidColorRenderElement}; use smithay::backend::renderer::element::Kind; use smithay::utils::{Logical, Point, Rectangle, Scale, Size}; @@ -17,11 +16,10 @@ pub struct FocusRing { buffers: [SolidColorBuffer; 8], locations: [Point<i32, Logical>; 8], sizes: [Size<i32, Logical>; 8], - borders: RefCell<[BorderRenderElement; 8]>, + borders: [BorderRenderElement; 8], full_size: Size<i32, Logical>, - is_active: bool, is_border: bool, - radius: CornerRadius, + use_border_shader: bool, config: niri_config::FocusRing, } @@ -40,9 +38,8 @@ impl FocusRing { sizes: Default::default(), borders: Default::default(), full_size: Default::default(), - is_active: false, is_border: false, - radius: Default::default(), + use_border_shader: false, config, } } @@ -52,18 +49,64 @@ impl FocusRing { } pub fn update_shaders(&mut self) { - let mut borders = self.borders.borrow_mut(); - for elem in &mut *borders { + for elem in &mut self.borders { elem.damage_all(); } } - pub fn update(&mut self, win_size: Size<i32, Logical>, is_border: bool, radius: CornerRadius) { + pub fn update_render_elements( + &mut self, + win_size: Size<i32, Logical>, + is_active: bool, + is_border: bool, + view_rect: Rectangle<i32, Logical>, + radius: CornerRadius, + ) { let width = i32::from(self.config.width); self.full_size = win_size + Size::from((width * 2, width * 2)); + let color = if is_active { + self.config.active_color + } else { + self.config.inactive_color + }; + + for buf in &mut self.buffers { + buf.set_color(color.into()); + } + let radius = radius.fit_to(self.full_size.w as f32, self.full_size.h as f32); + let gradient = if is_active { + self.config.active_gradient + } else { + self.config.inactive_gradient + }; + + self.use_border_shader = radius != CornerRadius::default() || gradient.is_some(); + + // Set the defaults for solid color + rounded corners. + let gradient = gradient.unwrap_or(Gradient { + from: color, + to: color, + angle: 0, + relative_to: GradientRelativeTo::Window, + }); + + let full_rect = Rectangle::from_loc_and_size((-width, -width), self.full_size); + let gradient_area = match gradient.relative_to { + GradientRelativeTo::Window => full_rect, + GradientRelativeTo::WorkspaceView => view_rect, + }; + + let rounded_corner_border_width = if self.is_border { + // HACK: increase the border width used for the inner rounded corners a tiny bit to + // reduce background bleed. + width as f32 + 0.5 + } else { + 0. + }; + if is_border { let top_left = max(width, radius.top_left.ceil() as i32); let top_right = min( @@ -121,28 +164,40 @@ impl FocusRing { for (buf, size) in zip(&mut self.buffers, self.sizes) { buf.resize(size); } + + for (border, (loc, size)) in zip(&mut self.borders, zip(self.locations, self.sizes)) { + border.update( + size, + Rectangle::from_loc_and_size(gradient_area.loc - loc, gradient_area.size), + gradient.from.into(), + gradient.to.into(), + ((gradient.angle as f32) - 90.).to_radians(), + Rectangle::from_loc_and_size(full_rect.loc - loc, full_rect.size), + rounded_corner_border_width, + radius, + ); + } } else { self.sizes[0] = self.full_size; self.buffers[0].resize(self.sizes[0]); self.locations[0] = Point::from((-width, -width)); - } - - self.is_border = is_border; - self.radius = radius; - } - pub fn set_active(&mut self, is_active: bool) { - let color = if is_active { - self.config.active_color.into() - } else { - self.config.inactive_color.into() - }; - - for buf in &mut self.buffers { - buf.set_color(color); + self.borders[0].update( + self.sizes[0], + Rectangle::from_loc_and_size( + gradient_area.loc - self.locations[0], + gradient_area.size, + ), + gradient.from.into(), + gradient.to.into(), + ((gradient.angle as f32) - 90.).to_radians(), + Rectangle::from_loc_and_size(full_rect.loc - self.locations[0], full_rect.size), + rounded_corner_border_width, + radius, + ); } - self.is_active = is_active; + self.is_border = is_border; } pub fn render( @@ -150,7 +205,6 @@ impl FocusRing { renderer: &mut impl NiriRenderer, location: Point<i32, Logical>, scale: Scale<f64>, - view_size: Size<i32, Logical>, ) -> impl Iterator<Item = FocusRingRenderElement> { let mut rv = ArrayVec::<_, 8>::new(); @@ -165,75 +219,12 @@ impl FocusRing { return rv.into_iter(); } - let gradient = if self.is_active { - self.config.active_gradient - } else { - self.config.inactive_gradient - }; - let color = if self.is_active { - self.config.active_color - } else { - self.config.inactive_color - }; - - let offset = Point::from((border_width, border_width)); - let full_rect = Rectangle::from_loc_and_size(location - offset, self.full_size); - let view_rect = Rectangle::from_loc_and_size((0, 0), view_size); - - let border_width = if self.is_border { - // HACK: increase the border width used for the inner rounded corners a tiny bit to - // reduce background bleed. - border_width as f32 + 0.5 / scale.x as f32 - } else { - 0. - }; let has_border_shader = BorderRenderElement::has_shader(renderer); - let mut borders = self.borders.borrow_mut(); - - let mut push = |buffer, - border: &mut BorderRenderElement, - location: Point<i32, Logical>, - size: Size<i32, Logical>| { - let full_rect = Rectangle::from_loc_and_size(full_rect.loc - location, full_rect.size); - let view_rect = Rectangle::from_loc_and_size(view_rect.loc - location, view_rect.size); - - let elem = if has_border_shader { - if let Some(gradient) = gradient { - let gradient_area = match gradient.relative_to { - GradientRelativeTo::Window => full_rect, - GradientRelativeTo::WorkspaceView => view_rect, - }; - border.update( - size, - gradient_area, - gradient.from.into(), - gradient.to.into(), - ((gradient.angle as f32) - 90.).to_radians(), - full_rect, - border_width, - self.radius, - ); - Some(border.clone().with_location(location).into()) - } else if self.radius != CornerRadius::default() { - border.update( - size, - full_rect, - color.into(), - color.into(), - 0., - full_rect, - border_width, - self.radius, - ); - Some(border.clone().with_location(location).into()) - } else { - None - } - } else { - None - }; - let elem = elem.unwrap_or_else(|| { + let mut push = |buffer, border: &BorderRenderElement, location: Point<i32, Logical>| { + let elem = if self.use_border_shader && has_border_shader { + border.clone().with_location(location).into() + } else { SolidColorRenderElement::from_buffer( buffer, location.to_physical_precise_round(scale), @@ -242,23 +233,19 @@ impl FocusRing { Kind::Unspecified, ) .into() - }); + }; rv.push(elem); }; if self.is_border { - for ((buf, border), (loc, size)) in zip( - zip(&self.buffers, &mut *borders), - zip(self.locations, self.sizes), - ) { - push(buf, border, location + loc, size); + for ((buf, border), loc) in zip(zip(&self.buffers, &self.borders), self.locations) { + push(buf, border, location + loc); } } else { push( &self.buffers[0], - &mut borders[0], + &self.borders[0], location + self.locations[0], - self.sizes[0], ); } |
