aboutsummaryrefslogtreecommitdiff
path: root/src/layout/focus_ring.rs
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-05-04 11:10:02 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2024-05-04 11:10:02 +0400
commit73cc0079d628e66b1d64168ed1a10b13b23ab5d0 (patch)
tree168aa5d885c2061c8ec9090e1cd46b865a6f2a42 /src/layout/focus_ring.rs
parent69aeba2a4d93b34eb24319c3694ad354dc608a87 (diff)
downloadniri-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.rs189
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],
);
}