aboutsummaryrefslogtreecommitdiff
path: root/src/layout/focus_ring.rs
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2023-12-24 15:10:09 +0400
committerIvan Molodetskikh <yalterz@gmail.com>2023-12-24 15:10:09 +0400
commited3080d908001bf468789b8f47f893e00306135d (patch)
treeabf3c12eba9e0759fa199781280d33c62891e508 /src/layout/focus_ring.rs
parent461ce5f3631c99e928280935d92f084f4b641b9e (diff)
downloadniri-ed3080d908001bf468789b8f47f893e00306135d.tar.gz
niri-ed3080d908001bf468789b8f47f893e00306135d.tar.bz2
niri-ed3080d908001bf468789b8f47f893e00306135d.zip
Split layout mod into files
No functional change intended.
Diffstat (limited to 'src/layout/focus_ring.rs')
-rw-r--r--src/layout/focus_ring.rs108
1 files changed, 108 insertions, 0 deletions
diff --git a/src/layout/focus_ring.rs b/src/layout/focus_ring.rs
new file mode 100644
index 00000000..9385fc6b
--- /dev/null
+++ b/src/layout/focus_ring.rs
@@ -0,0 +1,108 @@
+use std::iter::zip;
+
+use arrayvec::ArrayVec;
+use smithay::backend::renderer::element::solid::{SolidColorBuffer, SolidColorRenderElement};
+use smithay::backend::renderer::element::Kind;
+use smithay::utils::{Logical, Point, Scale, Size};
+
+use crate::config::{self, Color};
+
+#[derive(Debug)]
+pub struct FocusRing {
+ buffers: [SolidColorBuffer; 4],
+ locations: [Point<i32, Logical>; 4],
+ is_off: bool,
+ is_border: bool,
+ width: i32,
+ active_color: Color,
+ inactive_color: Color,
+}
+
+pub type FocusRingRenderElement = SolidColorRenderElement;
+
+impl FocusRing {
+ pub fn new(config: config::FocusRing) -> Self {
+ Self {
+ buffers: Default::default(),
+ locations: Default::default(),
+ is_off: config.off,
+ is_border: false,
+ width: config.width.into(),
+ active_color: config.active_color,
+ inactive_color: config.inactive_color,
+ }
+ }
+
+ pub fn update_config(&mut self, config: config::FocusRing) {
+ self.is_off = config.off;
+ self.width = config.width.into();
+ self.active_color = config.active_color;
+ self.inactive_color = config.inactive_color;
+ }
+
+ pub fn update(
+ &mut self,
+ win_pos: Point<i32, Logical>,
+ win_size: Size<i32, Logical>,
+ is_border: bool,
+ ) {
+ if is_border {
+ self.buffers[0].resize((win_size.w + self.width * 2, self.width));
+ self.buffers[1].resize((win_size.w + self.width * 2, self.width));
+ self.buffers[2].resize((self.width, win_size.h));
+ self.buffers[3].resize((self.width, win_size.h));
+
+ self.locations[0] = win_pos + Point::from((-self.width, -self.width));
+ self.locations[1] = win_pos + Point::from((-self.width, win_size.h));
+ self.locations[2] = win_pos + Point::from((-self.width, 0));
+ self.locations[3] = win_pos + Point::from((win_size.w, 0));
+ } else {
+ let size = win_size + Size::from((self.width * 2, self.width * 2));
+ self.buffers[0].resize(size);
+ self.locations[0] = win_pos - Point::from((self.width, self.width));
+ }
+
+ self.is_border = is_border;
+ }
+
+ pub fn set_active(&mut self, is_active: bool) {
+ let color = if is_active {
+ self.active_color.into()
+ } else {
+ self.inactive_color.into()
+ };
+
+ for buf in &mut self.buffers {
+ buf.set_color(color);
+ }
+ }
+
+ pub fn render(&self, scale: Scale<f64>) -> impl Iterator<Item = SolidColorRenderElement> {
+ let mut rv = ArrayVec::<_, 4>::new();
+
+ if self.is_off {
+ return rv.into_iter();
+ }
+
+ let mut push = |buffer, location: Point<i32, Logical>| {
+ let elem = SolidColorRenderElement::from_buffer(
+ buffer,
+ location.to_physical_precise_round(scale),
+ scale,
+ 1.,
+ Kind::Unspecified,
+ );
+ rv.push(elem);
+ };
+
+ if self.is_border {
+ for (buf, loc) in zip(&self.buffers, self.locations) {
+ push(buf, loc);
+ }
+ } else {
+ push(&self.buffers[0], self.locations[0]);
+ }
+
+ rv.into_iter()
+ }
+}