gdritter repos knurling / 8813b20
cargo fmt Getty Ritter 3 years ago
4 changed file(s) with 92 addition(s) and 80 deletion(s). Collapse all Expand all
6666 }
6767
6868 if let Some(color) = table.get("background") {
69 conf.bg_color = color_from_hex(color.as_str().ok_or(format_err!("`background` not a str"))?)?;
69 conf.bg_color = color_from_hex(
70 color
71 .as_str()
72 .ok_or(format_err!("`background` not a str"))?,
73 )?;
7074 }
7175 if let Some(color) = table.get("foreground") {
72 conf.fg_color = color_from_hex(color.as_str().ok_or(format_err!("`foreground` not a str"))?)?;
76 conf.fg_color = color_from_hex(
77 color
78 .as_str()
79 .ok_or(format_err!("`foreground` not a str"))?,
80 )?;
7381 }
7482 if let Some(font) = table.get("font") {
75 conf.font = font.as_str().ok_or(format_err!("`font` not a str"))?.to_string();
83 conf.font = font
84 .as_str()
85 .ok_or(format_err!("`font` not a str"))?
86 .to_string();
7687 }
7788 conf.right.reverse();
7889
96107 Err(format_err!("Unable to find `knurling.toml`"))
97108 }
98109
99 pub fn draw(&self, ctx: &cairo::Context, layout: &pango::Layout, stdin: &str, size: w::Size) -> Result<(), failure::Error>{
110 pub fn draw(
111 &self,
112 ctx: &cairo::Context,
113 layout: &pango::Layout,
114 stdin: &str,
115 size: w::Size,
116 ) -> Result<(), failure::Error> {
100117 // paint the background
101118 {
102119 let (r, g, b) = self.bg_color;
135152 &self.font
136153 }
137154
138 pub fn get_height(&self) -> i32{
155 pub fn get_height(&self) -> i32 {
139156 self.height
140157 }
141158
144161
145162 // we get the height here by making a fake surface, rendering
146163 // some text using our chosen font to it, and seeing how big it ends up being
147 let surf = cairo::ImageSurface::create(
148 cairo::Format::Rgb24, 0, 0).unwrap();
164 let surf = cairo::ImageSurface::create(cairo::Format::Rgb24, 0, 0).unwrap();
149165 let ctx = cairo::Context::new(&surf);
150166 let layout = pangocairo::functions::create_layout(&ctx).unwrap();
151167 layout.set_width(800 * pango::SCALE);
55 mod widgets;
66 mod window;
77
8 use pango::LayoutExt;
89 use std::os::unix::io::AsRawFd;
9 use pango::LayoutExt;
1010
1111 use widgets::Size;
12 use window::{Display,Event,Window};
12 use window::{Display, Event, Window};
1313
1414 fn main() -> Result<(), failure::Error> {
1515 // set up the display and the window
2020 let mut ws = Vec::new();
2121
2222 for (x_off, wd) in d.get_widths()? {
23 let size = Size { wd, ht: height, xo: x_off, yo: 0 };
23 let size = Size {
24 wd,
25 ht: height,
26 xo: x_off,
27 yo: 0,
28 };
2429 let mut w = Window::create(&d, size)?;
2530 // set some window-manager properties: this is a dock
2631 w.change_property("_NET_WM_WINDOW_TYPE", &["_NET_WM_WINDOW_TYPE_DOCK"])?;
2833 w.change_property("_NET_WM_STRUT", &[x_off as i64, 0, size.ht as i64, 0])?;
2934 w.change_property(
3035 "_NET_WM_STRUT_PARTIAL",
31 &[ 0, 0, size.ht as i64, 0,
32 0, 0, 0, 0,
33 0, size.wd as i64, 0, 0,
34 ],
36 &[0, 0, size.ht as i64, 0, 0, 0, 0, 0, 0, size.wd as i64, 0, 0],
3537 )?;
3638
3739 // we won't ever see this, but for good measure.
6971 let surf = w.get_cairo_surface();
7072 let ctx = cairo::Context::new(&surf);
7173
72
7374 let layout = pangocairo::functions::create_layout(&ctx)
7475 .ok_or(format_err!("unable to create layout"))?;
7576
8586
8687 ctxs.push((ctx, layout, w.size()));
8788 }
88
8989
9090 let max_fd = window_fds.iter().max().unwrap_or(&0) + 1;
9191 // we're gonna keep looping until we don't
11 use pango::LayoutExt;
22
3 #[derive(Debug,Clone,Copy)]
3 #[derive(Debug, Clone, Copy)]
44 pub struct Size {
55 pub wd: i32,
66 pub ht: i32,
88 pub yo: i32,
99 }
1010
11 #[derive(Debug,Clone,Copy)]
11 #[derive(Debug, Clone, Copy)]
1212 pub enum Located {
1313 FromLeft(i32),
1414 FromRight(i32),
5151 impl Time {
5252 pub fn new() -> Time {
5353 Time {
54 fmt: format!("%a %b %d %H:%M")
54 fmt: format!("%a %b %d %H:%M"),
5555 }
5656 }
5757 }
6262 loc.draw_text(d, &format!("{}", &now.format(&self.fmt)))
6363 }
6464 }
65
6665
6766 #[derive(Debug)]
6867 pub struct Stdin;
7877 loc.draw_text(d, &d.stdin)
7978 }
8079 }
81
8280
8381 pub struct SmallBox;
8482
106104
107105 pub struct Battery {
108106 file_list: Vec<std::path::PathBuf>,
109 charging: Option<std::path::PathBuf>
107 charging: Option<std::path::PathBuf>,
110108 }
111109
112110 impl Battery {
136134
137135 fn is_charging(&self) -> Result<bool, failure::Error> {
138136 if let Some(path) = &self.charging {
139 let is_connected: i32 =
140 std::fs::read_to_string(path)?.trim().parse()?;
137 let is_connected: i32 = std::fs::read_to_string(path)?.trim().parse()?;
141138 Ok(is_connected != 0)
142139 } else {
143140 Ok(false)
145142 }
146143
147144 fn read_status(&self) -> Result<f64, failure::Error> {
148 let charges: Result<Vec<i32>, failure::Error> =
149 self.file_list.iter().map(|path| {
150 Ok(std::fs::read_to_string(path)?.trim().parse()?)
151 }).collect();
145 let charges: Result<Vec<i32>, failure::Error> = self
146 .file_list
147 .iter()
148 .map(|path| Ok(std::fs::read_to_string(path)?.trim().parse()?))
149 .collect();
152150 let charges = charges?;
153151
154152 let len = charges.len() as f64;
163161 let sz = d.size.ht - (d.buffer as i32 * 2);
164162 let x = loc.target_x(d, sz);
165163 match amt {
166 _ if self.is_charging().unwrap_or(false) =>
167 d.ctx.set_source_rgb(0.5, 0.5, 1.0),
168 Ok(x) if x < 0.1 =>
169 d.ctx.set_source_rgb(1.0, 0.0, 0.0),
170 Ok(x) if x < 0.5 =>
171 d.ctx.set_source_rgb(1.0, 1.0, 0.0),
172 Ok(_) =>
173 d.ctx.set_source_rgb(0.0, 1.0, 0.5),
174 Err(_) =>
175 d.ctx.set_source_rgb(0.0, 0.0, 0.0),
164 _ if self.is_charging().unwrap_or(false) => d.ctx.set_source_rgb(0.5, 0.5, 1.0),
165 Ok(x) if x < 0.1 => d.ctx.set_source_rgb(1.0, 0.0, 0.0),
166 Ok(x) if x < 0.5 => d.ctx.set_source_rgb(1.0, 1.0, 0.0),
167 Ok(_) => d.ctx.set_source_rgb(0.0, 1.0, 0.5),
168 Err(_) => d.ctx.set_source_rgb(0.0, 0.0, 0.0),
176169 }
177170
178171 d.ctx.rectangle(
184177 d.ctx.fill();
185178
186179 d.ctx.set_source_rgb(1.0, 1.0, 1.0);
187 d.ctx.rectangle(x, d.buffer * 2.0, sz as f64, sz as f64 - (d.buffer * 2.0));
180 d.ctx
181 .rectangle(x, d.buffer * 2.0, sz as f64, sz as f64 - (d.buffer * 2.0));
188182 d.ctx.stroke();
189183
190184 sz
1 use x11::{xlib,xinput2};
1 use x11::{xinput2, xlib};
22
33 use std::ffi::CString;
4 use std::{mem,ptr};
5 use std::os::raw::{c_int,c_uchar};
4 use std::os::raw::{c_int, c_uchar};
5 use std::{mem, ptr};
66
77 use crate::widgets::Size;
88
2828 }
2929 }
3030
31 pub fn get_widths(&mut self) -> Result<Vec<(i32,i32)>, failure::Error> {
31 pub fn get_widths(&mut self) -> Result<Vec<(i32, i32)>, failure::Error> {
3232 if unsafe { x11::xinerama::XineramaIsActive(self.display) != 0 } {
3333 let mut screens = 0;
34 let screen_info = unsafe { x11::xinerama::XineramaQueryScreens(self.display, &mut screens) };
34 let screen_info =
35 unsafe { x11::xinerama::XineramaQueryScreens(self.display, &mut screens) };
3536 let mut widths = Vec::new();
3637 for i in 0..screens {
3738 unsafe {
38 let si = screen_info.offset(i as isize).as_ref().ok_or(format_err!("bad pointer"))?;
39 let si = screen_info
40 .offset(i as isize)
41 .as_ref()
42 .ok_or(format_err!("bad pointer"))?;
3943 widths.push((si.x_org as i32, si.width as i32));
4044 }
4145 }
7579 /// width and height
7680 pub fn create(
7781 display: &'t Display,
78 Size { wd: width, ht: height, xo, yo }: Size,
82 Size {
83 wd: width,
84 ht: height,
85 xo,
86 yo,
87 }: Size,
7988 ) -> Result<Window<'t>, failure::Error> {
8089 unsafe {
8190 let screen = display.screen;
128137 );
129138 }
130139
131 let mut mask: [c_uchar;1] = [0];
140 let mut mask: [c_uchar; 1] = [0];
132141 let mut input_event_mask = xinput2::XIEventMask {
133142 deviceid: xinput2::XIAllMasterDevices,
134143 mask_len: mask.len() as i32,
135144 mask: mask.as_mut_ptr(),
136145 };
137 let events = &[
138 xinput2::XI_ButtonPress,
139 xinput2::XI_ButtonRelease,
140 ];
146 let events = &[xinput2::XI_ButtonPress, xinput2::XI_ButtonRelease];
141147 for &event in events {
142148 xinput2::XISetMask(&mut mask, event);
143149 }
144150
145151 match unsafe {
146 xinput2::XISelectEvents(
147 self.display.display,
148 self.window,
149 &mut input_event_mask,
150 1,
151 )
152 xinput2::XISelectEvents(self.display.display, self.window, &mut input_event_mask, 1)
152153 } {
153154 status if status as u8 == xlib::Success => (),
154 err => bail!("Failed to select events {:?}", err)
155 err => bail!("Failed to select events {:?}", err),
155156 }
156157
157158 Ok(())
201202 pub fn change_property<T: XProperty>(
202203 &mut self,
203204 prop: &str,
204 val: &[T]
205 ) -> Result<(), failure::Error>
206 {
205 val: &[T],
206 ) -> Result<(), failure::Error> {
207207 let prop = self.intern(prop)?;
208208 unsafe {
209209 let len = val.len();
268268 xlib::GenericEvent => {
269269 let mut cookie: xlib::XGenericEventCookie = unsafe { From::from(*e.as_ptr()) };
270270 unsafe { xlib::XGetEventData(self.display.display, &mut cookie) };
271 match cookie.evtype {
272 xinput2::XI_ButtonPress => {
273 let data: &xinput2::XIDeviceEvent =
274 unsafe { mem::transmute(cookie.data) };
275 return Some(Event::MouseEvent { x: data.event_x, y: data.event_y });
276 }
277 _ => (),
271 match cookie.evtype {
272 xinput2::XI_ButtonPress => {
273 let data: &xinput2::XIDeviceEvent = unsafe { mem::transmute(cookie.data) };
274 return Some(Event::MouseEvent {
275 x: data.event_x,
276 y: data.event_y,
277 });
278278 }
279 _ => (),
280 }
279281 }
280282 _ => (),
281283 }
285287
286288 /// True if there are any pending events.
287289 pub fn has_events(&mut self) -> bool {
288 unsafe {
289 xlib::XPending(self.display.display) != 0
290 }
290 unsafe { xlib::XPending(self.display.display) != 0 }
291291 }
292292
293293 /// Did you know that X11 uses a file descriptor underneath the
294294 /// surface to wait on events? This lets us use select on it!
295295 pub fn get_fd(&mut self) -> i32 {
296 unsafe {
297 xlib::XConnectionNumber(self.display.display)
298 }
296 unsafe { xlib::XConnectionNumber(self.display.display) }
299297 }
300298
301299 pub fn size(&self) -> Size {
302 Size { wd: self.width, ht: self.height, xo: 0, yo: 0 }
300 Size {
301 wd: self.width,
302 ht: self.height,
303 xo: 0,
304 yo: 0,
305 }
303306 }
304307 }
305308
306309 /// A trait for abstracting over different values which are allowed
307310 /// for xlib properties
308 pub trait XProperty : Sized {
311 pub trait XProperty: Sized {
309312 fn with_ptr(
310313 xs: &[Self],
311314 w: &mut Window,
312315 f: impl FnOnce(&mut Window, u64, *const u8),
313 ) -> Result<(), failure::Error> ;
316 ) -> Result<(), failure::Error>;
314317 }
315318
316319 impl XProperty for i64 {
330333 w: &mut Window,
331334 f: impl FnOnce(&mut Window, u64, *const u8),
332335 ) -> Result<(), failure::Error> {
333 let xs: Result<Vec<u64>, failure::Error> =
334 xs.iter().map(|s| w.intern(s)).collect();
336 let xs: Result<Vec<u64>, failure::Error> = xs.iter().map(|s| w.intern(s)).collect();
335337 f(w, xlib::XA_ATOM, unsafe { mem::transmute(xs?.as_ptr()) });
336338 Ok(())
337339 }
341343 /// way
342344 #[derive(Debug)]
343345 pub enum Event {
344 MouseEvent { x:f64, y: f64 },
346 MouseEvent { x: f64, y: f64 },
345347 ShowEvent,
346348 QuitEvent,
347349 }