aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main.rs94
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
4use serde::{Deserialize, Serialize}; 4use serde::{Deserialize, Serialize};
5 5
6mod animations;
7use animations::Animation;
8
6#[derive(Serialize, Deserialize)] 9#[derive(Serialize, Deserialize)]
7enum Animation { 10enum 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)]
13struct IndicatorConfig { 18pub 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
23impl std::default::Default for IndicatorConfig { 28impl 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 {
36fn main() { 41fn 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
212fn move_win_to_cursor(conn: &xcb::Connection, win: u32, win_size: u16, p_x: i16, p_y: i16) { 190fn 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}