diff options
-rw-r--r-- | src/main.rs | 94 |
1 files changed, 38 insertions, 56 deletions
diff --git a/src/main.rs b/src/main.rs index 484a6c0..f3540fc 100644 --- a/src/main.rs +++ b/src/main.rs | |||
@@ -3,32 +3,37 @@ use std::time::Duration; | |||
3 | 3 | ||
4 | use serde::{Deserialize, Serialize}; | 4 | use serde::{Deserialize, Serialize}; |
5 | 5 | ||
6 | mod animations; | ||
7 | use animations::Animation; | ||
8 | |||
6 | #[derive(Serialize, Deserialize)] | 9 | #[derive(Serialize, Deserialize)] |
7 | enum Animation { | 10 | enum Kind { |
8 | Grow, | 11 | Grow, |
12 | GrowOutline, | ||
9 | Shrink, | 13 | Shrink, |
14 | ShrinkOutline, | ||
10 | } | 15 | } |
11 | 16 | ||
12 | #[derive(Serialize, Deserialize)] | 17 | #[derive(Serialize, Deserialize)] |
13 | struct IndicatorConfig { | 18 | pub struct IndicatorConfig { |
14 | max_size: u16, // display pixels | 19 | max_size: u16, // display pixels |
15 | duration: u16, // milliseconds | 20 | duration: u64, // milliseconds |
16 | thickness: u32, // display pixels | 21 | thickness: u32, // display pixels |
17 | no_of_circles: u16, // number of circles to display | 22 | framerate: u16, // number of circles to display |
18 | color: u32, // color in hex, eg.: 0x00FECA | 23 | color: u32, // color in hex, eg.: 0x00FECA |
19 | animation: Animation, // 'Grow' | 'Shrink' | 24 | animation: Kind, // 'Grow' | 'Shrink' | 'GrowOutline' | 'ShrinkOutline' |
20 | } | 25 | } |
21 | 26 | ||
22 | // sane defaults | 27 | // sane defaults |
23 | impl std::default::Default for IndicatorConfig { | 28 | impl std::default::Default for IndicatorConfig { |
24 | fn default() -> IndicatorConfig { | 29 | fn default() -> IndicatorConfig { |
25 | IndicatorConfig { | 30 | IndicatorConfig { |
26 | max_size: 200u16, | 31 | max_size: 300u16, |
27 | duration: 500u16, | 32 | duration: 500u64, |
28 | thickness: 1, | 33 | thickness: 1, |
29 | no_of_circles: 5, | 34 | framerate: 30, |
30 | color: 0xFFFFFF, | 35 | color: 0xFFFFFF, |
31 | animation: Animation::Grow, | 36 | animation: Kind::Grow, |
32 | } | 37 | } |
33 | } | 38 | } |
34 | } | 39 | } |
@@ -36,7 +41,7 @@ impl std::default::Default for IndicatorConfig { | |||
36 | fn main() { | 41 | fn main() { |
37 | let config: IndicatorConfig = confy::load("xcursorlocate").unwrap(); | 42 | let config: IndicatorConfig = confy::load("xcursorlocate").unwrap(); |
38 | 43 | ||
39 | let padding = 10; // (???) largest circle gets clipped | 44 | let padding = config.thickness as u16; // (???) largest circle gets clipped |
40 | let win_size = config.max_size + padding; | 45 | let win_size = config.max_size + padding; |
41 | 46 | ||
42 | let (conn, screen_num) = xcb::Connection::connect(None) | 47 | let (conn, screen_num) = xcb::Connection::connect(None) |
@@ -147,25 +152,14 @@ fn main() { | |||
147 | &[win_on_top_atom], | 152 | &[win_on_top_atom], |
148 | ); | 153 | ); |
149 | 154 | ||
150 | let range: Box<dyn DoubleEndedIterator<Item = u16>> = match config.animation { | 155 | let fr = config.framerate; |
151 | Animation::Shrink => Box::new(0..config.no_of_circles), | 156 | let animation = match config.animation { |
152 | Animation::Grow => Box::new((0..config.no_of_circles).rev()), | 157 | Kind::Grow => Animation::circles(config, Box::new((0..fr).rev()), false), |
158 | Kind::GrowOutline => Animation::circles(config, Box::new((0..fr).rev()), true), | ||
159 | Kind::Shrink => Animation::circles(config, Box::new(0..fr), false), | ||
160 | Kind::ShrinkOutline => Animation::circles(config, Box::new(0..fr), true), | ||
153 | }; | 161 | }; |
154 | 162 | ||
155 | let circles = range | ||
156 | .map(|i| { | ||
157 | xcb::Arc::new( | ||
158 | (config.max_size as i16) / (2 * config.no_of_circles as i16) * i as i16, // x | ||
159 | (config.max_size as i16) / (2 * config.no_of_circles as i16) * i as i16, // y | ||
160 | (config.max_size) - (config.max_size / config.no_of_circles) * i as u16, // width | ||
161 | (config.max_size) - (config.max_size / config.no_of_circles) * i as u16, // height | ||
162 | 0, // start angle | ||
163 | 360 << 6, // end angle | ||
164 | ) | ||
165 | }) | ||
166 | .collect::<Vec<xcb::Arc>>() | ||
167 | .into_iter(); | ||
168 | |||
169 | xcb::map_window(&conn, win); | 163 | xcb::map_window(&conn, win); |
170 | conn.flush(); | 164 | conn.flush(); |
171 | 165 | ||
@@ -183,24 +177,8 @@ fn main() { | |||
183 | let p_y = pointer.root_y(); | 177 | let p_y = pointer.root_y(); |
184 | 178 | ||
185 | move_win_to_cursor(&conn, win, win_size, p_x, p_y); | 179 | move_win_to_cursor(&conn, win, win_size, p_x, p_y); |
180 | animation.play(&conn, win, gfx_ctx); | ||
186 | 181 | ||
187 | let circle_duration = | ||
188 | Duration::from_millis((config.duration / config.no_of_circles) as u64); | ||
189 | for c in circles { | ||
190 | let _ = xcb::poly_arc(&conn, win, gfx_ctx, &[c]); | ||
191 | conn.flush(); | ||
192 | thread::sleep(circle_duration); | ||
193 | xcb::clear_area( | ||
194 | &conn, | ||
195 | false, | ||
196 | win, | ||
197 | c.x(), | ||
198 | c.y(), | ||
199 | c.width() + padding + config.thickness as u16, | ||
200 | c.height() + padding + config.thickness as u16, | ||
201 | ); | ||
202 | conn.flush(); | ||
203 | } | ||
204 | thread::sleep(Duration::from_millis(100)); | 182 | thread::sleep(Duration::from_millis(100)); |
205 | } | 183 | } |
206 | _ => eprintln!("how did you even get here: {}", r), | 184 | _ => eprintln!("how did you even get here: {}", r), |
@@ -209,22 +187,26 @@ fn main() { | |||
209 | } | 187 | } |
210 | } | 188 | } |
211 | 189 | ||
212 | fn move_win_to_cursor(conn: &xcb::Connection, win: u32, win_size: u16, p_x: i16, p_y: i16) { | 190 | fn move_win_to_cursor( |
191 | conn: &xcb::Connection, | ||
192 | win: u32, | ||
193 | win_size: u16, | ||
194 | p_x: i16, | ||
195 | p_y: i16, | ||
196 | ) -> (u32, u32) { | ||
213 | let win_x = p_x - (win_size as i16) / 2; | 197 | let win_x = p_x - (win_size as i16) / 2; |
214 | let win_y = p_y - (win_size as i16) / 2; | 198 | let win_y = p_y - (win_size as i16) / 2; |
199 | let win_x = if win_x < 0 { 0 } else { win_x as u32 }; | ||
200 | let win_y = if win_y < 0 { 0 } else { win_y as u32 }; | ||
201 | |||
215 | xcb::configure_window( | 202 | xcb::configure_window( |
216 | &conn, | 203 | &conn, |
217 | win, | 204 | win, |
218 | &[ | 205 | &[ |
219 | ( | 206 | (xcb::CONFIG_WINDOW_X as u16, win_x), |
220 | xcb::CONFIG_WINDOW_X as u16, | 207 | (xcb::CONFIG_WINDOW_Y as u16, win_y), |
221 | if win_x < 0 { 0 } else { win_x as u32 }, | ||
222 | ), | ||
223 | ( | ||
224 | xcb::CONFIG_WINDOW_Y as u16, | ||
225 | if win_y < 0 { 0 } else { win_y as u32 }, | ||
226 | ), | ||
227 | ], | 208 | ], |
228 | ); | 209 | ); |
229 | conn.flush(); | 210 | conn.flush(); |
211 | return (win_x, win_y); | ||
230 | } | 212 | } |