diff options
Diffstat (limited to 'src/main.rs')
| -rw-r--r-- | src/main.rs | 137 |
1 files changed, 96 insertions, 41 deletions
diff --git a/src/main.rs b/src/main.rs index 5ad82a4..5b2f853 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,28 +1,31 @@ +use crate::geometry::*; use crate::x::*; +use std::ops::Sub; use std::sync::Arc; use xcb::{ Xid }; use xcb::x::{ ClientMessageData, + Gc, ChangeGc, Cw, CreateWindow, Drawable, EventMask, - PolyFillRectangle, + PolyFillArc, PolyFillRectangle, Screen, WindowClass }; +mod geometry; mod x; -#[derive(Clone, Copy, PartialEq, Eq)] -enum ScreenSide { Top, Bottom, Left, Right } - struct DockConfiguration { thickness: u16, - side: ScreenSide, + side: Side, background_pixel: u32, + use_rounded_inside_corners: bool, + use_rounded_outside_corners: bool, } struct Dock { @@ -36,16 +39,6 @@ impl HasWindow for Dock { } -#[derive(Debug)] -struct Rectangle<T> { - left: T, - top: T, - width: T, - height: T, -} - - - fn main() -> xcb::Result<()> { let display = Arc::new(Display::new()?); @@ -54,14 +47,16 @@ fn main() -> xcb::Result<()> { let dock = Dock::new(Arc::clone(&display), DockConfiguration { thickness: 50, - side: ScreenSide::Bottom, + side: Side::Bottom, background_pixel, + use_rounded_inside_corners: false, + use_rounded_outside_corners: true, })?; loop { match display.wait_for_event()? { xcb::Event::X(xcb::x::Event::Expose(_event)) => { - let _ = dock.redraw(); // TODO + let _ = dock.redraw(); // TODO } xcb::Event::X(xcb::x::Event::ButtonPress(event)) => { @@ -132,10 +127,10 @@ impl Dock { let thickness = self.configuration.thickness as u32; let strut_values = match self.configuration.side { - ScreenSide::Left => &[thickness, 0 as u32, 0 as u32, 0 as u32], - ScreenSide::Right => &[0 as u32, thickness, 0 as u32, 0 as u32], - ScreenSide::Top => &[0 as u32, 0 as u32, thickness, 0 as u32], - ScreenSide::Bottom => &[0 as u32, 0 as u32, 0 as u32, thickness], + Side::Left => &[thickness, 0 as u32, 0 as u32, 0 as u32], + Side::Right => &[0 as u32, thickness, 0 as u32, 0 as u32], + Side::Top => &[0 as u32, 0 as u32, thickness, 0 as u32], + Side::Bottom => &[0 as u32, 0 as u32, 0 as u32, thickness], }; self.set_cardinal_property(&atoms.wm_strut, strut_values)?; @@ -146,22 +141,22 @@ impl Dock { strut_values[3], 0 as u32, - if self.configuration.side == ScreenSide::Left { + if self.configuration.side == Side::Left { screen.height_in_pixels() as u32 } else { 0 as u32 }, 0 as u32, - if self.configuration.side == ScreenSide::Right { + if self.configuration.side == Side::Right { screen.height_in_pixels() as u32 } else { 0 as u32 }, 0 as u32, - if self.configuration.side == ScreenSide::Top { + if self.configuration.side == Side::Top { screen.width_in_pixels() as u32 } else { 0 as u32 }, 0 as u32, - if self.configuration.side == ScreenSide::Bottom { + if self.configuration.side == Side::Bottom { screen.width_in_pixels() as u32 } else { 0 as u32 }, ]; @@ -176,14 +171,14 @@ impl Dock { fn compute_bounds(screen: &Screen, configuration: &DockConfiguration) -> Rectangle<u16> { - if configuration.side == ScreenSide::Top - || configuration.side == ScreenSide::Bottom + if configuration.side == Side::Top + || configuration.side == Side::Bottom { let left = 0; let width = screen.width_in_pixels(); let height = configuration.thickness; - let top = if configuration.side == ScreenSide::Bottom { + let top = if configuration.side == Side::Bottom { screen.height_in_pixels() - height } else { 0 }; @@ -193,7 +188,7 @@ impl Dock { let height = screen.height_in_pixels(); let width = configuration.thickness; - let left = if configuration.side == ScreenSide::Right { + let left = if configuration.side == Side::Right { screen.width_in_pixels() - width } else { 0 }; @@ -203,25 +198,85 @@ impl Dock { fn redraw(&self) -> xcb::Result<()> { - println!("redraw"); - let drawable = Drawable::Window(self.window_id()); let context = GraphicContext::new( - Arc::clone(self.display()), drawable)?; + Arc::clone(self.display()), drawable)?; + + if self.configuration.use_rounded_inside_corners + || self.configuration.use_rounded_outside_corners + { + let black_pixel = self.screen().black_pixel(); + + let mut corner_squares = Vec::new(); + let mut corner_arcs = Vec::new(); + if self.configuration.use_rounded_outside_corners { + for corner in self.configuration.side.corners_on_side() { + let (corner_square, corner_arc) = self.compute_corner_regions(*corner); + + corner_squares.push(corner_square); + corner_arcs.push(corner_arc); + } + } + if self.configuration.use_rounded_inside_corners { + for corner in self.configuration.side.opposite().corners_on_side() { + let (corner_square, corner_arc) = self.compute_corner_regions(*corner); - let black = self.screen().black_pixel(); + corner_squares.push(corner_square); + corner_arcs.push(corner_arc); + } + } - let cookie = self.send_request_checked(&PolyFillRectangle { - drawable: drawable, - gc: context.graphic_context_id(), - rectangles: &[xcb::x::Rectangle { - x: 0, y: 0, width: 25, height: 25 - }], - }); - self.check_request(cookie)?; + let cookie = self.send_request_checked(&ChangeGc { + gc: context.graphic_context_id(), + value_list: &[ + Gc::Foreground(black_pixel), + ], + }); + self.check_request(cookie)?; + + let cookie = self.send_request_checked(&PolyFillRectangle { + drawable: drawable, + gc: context.graphic_context_id(), + rectangles: &corner_squares, + }); + self.check_request(cookie)?; + + let cookie = self.send_request_checked(&ChangeGc { + gc: context.graphic_context_id(), + value_list: &[ + Gc::Foreground(self.configuration.background_pixel), + ], + }); + self.check_request(cookie)?; + + let cookie = self.send_request_checked(&PolyFillArc { + drawable: drawable, + gc: context.graphic_context_id(), + arcs: &corner_arcs, + }); + self.check_request(cookie)?; + } Ok(()) } + + fn compute_corner_regions(&self, corner: Corner) + -> (xcb::x::Rectangle, xcb::x::Arc) + { + let radius = self.configuration.thickness / 2; + let diameter = self.configuration.thickness; + + let bounds = &self.bounds; + + let corner_square = bounds.corner_square(corner, radius) + .to_x_rectangle(); + + let angle1 = corner.first_clockwise_side().to_x_angle(); + let corner_arc = bounds.corner_square(corner, diameter) + .to_x_arc(angle1, X_CLOCKWISE_RIGHT_ANGLE); + + (corner_square, corner_arc) + } } impl HasDisplay for Dock { |