1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
use std::iter::zip;
use arrayvec::ArrayVec;
use niri_config::{self, Color};
use smithay::backend::renderer::element::solid::{SolidColorBuffer, SolidColorRenderElement};
use smithay::backend::renderer::element::Kind;
use smithay::utils::{Logical, Point, Scale, Size};
#[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: niri_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: niri_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 = FocusRingRenderElement> {
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()
}
pub fn width(&self) -> i32 {
self.width
}
pub fn is_off(&self) -> bool {
self.is_off
}
}
|