summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.rs371
-rw-r--r--src/xtypes.rs269
2 files changed, 347 insertions, 293 deletions
diff --git a/src/main.rs b/src/main.rs
index c80fdb8..436fcfa 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,202 +1,18 @@
-use std::borrow::Borrow;
+use crate::xtypes::*;
+
 use std::sync::Arc;
-use std::ops::Deref;
 
 use xcb::{ Xid };
 use xcb::x::{
   self,
-  Atom,
-  ChangeProperty,
   ClientMessageData,
   Cw, CreateWindow,
   EventMask,
-  InternAtom,
-  MapWindow,
-  PropMode,
   Screen,
   WindowClass
 };
 
-
-struct Connection(xcb::Connection);
-
-struct Display {
-  connection: Connection,
-  screen_index: i32,
-  atoms: Atoms,
-}
-
-struct Window {
-  display: Arc<Display>,
-  window_id: x::Window,
-}
-
-
-trait HasWindow {
-  fn window(&self) -> &Window;
-
-  fn window_id(&self) -> x::Window { self.window().window_id }
-}
-
-impl HasWindow for Window {
-  fn window(&self) -> &Window { self }
-}
-
-impl<T: Deref<Target=Window>> HasWindow for T {
-  fn window(&self) -> &Window { &*self }
-}
-
-
-trait HasConnection {
-  fn connection(&self) -> &Connection;
-}
-
-impl HasConnection for Connection {
-  fn connection(&self) -> &Connection { self }
-}
-
-impl<T: HasDisplay> HasConnection for T {
-  fn connection(&self) -> &Connection { &self.display().connection }
-}
-
-
-trait HasDisplay {
-  fn display(&self) -> &Display;
-
-  fn atoms(&self) -> &Atoms { &self.display().atoms }
-}
-
-impl HasDisplay for Display {
-  fn display(&self) -> &Display { self }
-}
-
-impl<T: HasWindow> HasDisplay for T {
-  fn display(&self) -> &Display { self.window().display.borrow() }
-}
-
-
-trait ConnectionExt: HasConnection {
-  fn get_atom(&self, name: &[u8]) -> xcb::Result<Atom> {
-    let connection = self.connection();
-
-    let cookie = connection.0.send_request(&InternAtom {
-      only_if_exists: true,
-      name: name,
-    });
-
-    Ok(connection.0.wait_for_reply(cookie)?.atom())
-  }
-
-  fn get_atoms(&self) -> xcb::Result<Atoms> {
-    let wm_protocols = self.get_atom(b"WM_PROTOCOLS")?;
-    let wm_delete_window = self.get_atom(b"WM_DELETE_WINDOW")?;
-
-    let wm_type = self.get_atom(b"_NET_WM_WINDOW_TYPE")?;
-    let wm_type_dock = self.get_atom(b"_NET_WM_WINDOW_TYPE_DOCK")?;
-
-    let wm_strut = self.get_atom(b"_NET_WM_STRUT")?;
-    let wm_strut_partial = self.get_atom(b"_NET_WM_STRUT_PARTIAL")?;
-
-    Ok(Atoms {
-      wm_protocols, wm_delete_window,
-      wm_type, wm_type_dock,
-      wm_strut, wm_strut_partial,
-    })
-  }
-}
-
-impl<T: HasConnection> ConnectionExt for T { }
-
-
-trait DisplayExt: HasDisplay + HasConnection {
-  fn screen(&self) -> &Screen {
-    let setup = self.connection().0.get_setup();
-    let screen_index = self.display().screen_index as usize;
-
-    &setup.roots().nth(screen_index).unwrap()
-  }
-}
-
-impl<T: HasDisplay + HasConnection> DisplayExt for T { }
-
-
-trait WindowExt: HasWindow + HasDisplay + HasConnection {
-  fn map_window(&self) -> xcb::Result<()> {
-    let display = self.display();
-
-    let cookie = display.connection.0.send_request_checked(&MapWindow {
-      window: self.window_id()
-    });
-    display.connection.0.check_request(cookie)?;
-
-    Ok(())
-  }
-
-  fn set_string_property(&self, property: &Atom, value: &[u8])
-    -> xcb::Result<()>
-  {
-    let connection = self.connection();
-
-    let cookie = connection.0.send_request_checked(&ChangeProperty {
-      mode: PropMode::Replace,
-      window: self.window_id(),
-      property: *property,
-      r#type: x::ATOM_STRING,
-      data: value,
-    });
-    connection.0.check_request(cookie)?;
-
-    Ok(())
-  }
-
-
-  fn set_atom_property(&self, property: &Atom, values: &[Atom])
-    -> xcb::Result<()>
-  {
-    let connection = self.connection();
-
-    let cookie = connection.0.send_request_checked(&ChangeProperty {
-      mode: PropMode::Replace,
-      window: self.window_id(),
-      property: *property,
-      r#type: x::ATOM_ATOM,
-      data: values,
-    });
-    connection.0.check_request(cookie)?;
-
-    Ok(())
-  }
-
-
-  fn set_cardinal_property(&self, property: &Atom, values: &[u32])
-    -> xcb::Result<()>
-  {
-    let connection = self.connection();
-
-    let cookie = connection.0.send_request_checked(&ChangeProperty {
-      mode: PropMode::Replace,
-      window: self.window_id(),
-      property: *property,
-      r#type: x::ATOM_CARDINAL,
-      data: values,
-    });
-    connection.0.check_request(cookie)?;
-
-    Ok(())
-  }
-}
-
-impl<T: HasWindow + HasDisplay + HasConnection> WindowExt for T { }
-
-
-struct Atoms {
-  wm_protocols: Atom,
-  wm_delete_window: Atom,
-  wm_type: Atom,
-  wm_type_dock: Atom,
-  wm_strut: Atom,
-  wm_strut_partial: Atom,
-}
+mod xtypes;
 
 
 #[derive(Clone, Copy, PartialEq, Eq)]
@@ -226,35 +42,6 @@ struct Rectangle<T> {
 }
 
 
-impl Display {
-  fn new() -> xcb::Result<Display> {
-    let (connection, screen_index) = xcb::Connection::connect(None)?;
-    let connection = Connection(connection);
-
-    let atoms = connection.get_atoms()?;
-
-    Ok(Display { connection, screen_index, atoms })
-  }
-}
-
-
-impl Window {
-  fn new(display: Arc<Display>, create_window: &mut CreateWindow)
-    -> xcb::Result<Window>
-  {
-    let display_ref: &Display = display.borrow();
-    let connection: &Connection = &display_ref.connection;
-
-    let window_id: x::Window = connection.0.generate_id();
-
-    create_window.wid = window_id;
-    let cookie = connection.0.send_request_checked(create_window);
-    connection.0.check_request(cookie)?;
-
-    Ok(Window { display, window_id })
-  }
-}
-
 
 fn main() -> xcb::Result<()> {
   let display = Arc::new(Display::new()?);
@@ -265,14 +52,14 @@ fn main() -> xcb::Result<()> {
   })?;
 
   loop {
-    match display.connection.0.wait_for_event()? {
+    match display.wait_for_event()? {
       xcb::Event::X(x::Event::ButtonPress(event)) => {
         println!("click {:?}", event);
       }
 
       xcb::Event::X(x::Event::ClientMessage(event)) => {
         if let ClientMessageData::Data32([atom, ..]) = event.data() {
-          if atom == display.atoms.wm_delete_window.resource_id() {
+          if atom == display.atoms().wm_delete_window.resource_id() {
             break;
           }
         }
@@ -292,7 +79,7 @@ impl Dock {
   {
     let screen = display.screen();
 
-    let dock_bounds = compute_dock_bounds(&screen, &configuration);
+    let dock_bounds = Dock::compute_bounds(&screen, &configuration);
 
     let window = Window::new(Arc::clone(&display), &mut CreateWindow {
       depth: x::COPY_FROM_PARENT as u8,
@@ -314,96 +101,94 @@ impl Dock {
 
     dock.set_string_property(&x::ATOM_WM_NAME, b"grass bar")?;
 
-    dock.set_atom_property(&display.atoms.wm_protocols,
-                           &[display.atoms.wm_delete_window])?;
+    dock.set_atom_property(&display.atoms().wm_protocols,
+                           &[display.atoms().wm_delete_window])?;
 
-    dock.set_atom_property(&display.atoms.wm_type,
-                           &[display.atoms.wm_type_dock])?;
+    dock.set_atom_property(&display.atoms().wm_type,
+                           &[display.atoms().wm_type_dock])?;
 
-    set_dock_strut_properties(&dock, &screen)?;
+    dock.set_strut_properties(&screen)?;
 
     dock.map_window()?;
 
     Ok(dock)
   }
-}
 
 
-fn compute_dock_bounds(screen: &Screen, configuration: &DockConfiguration)
-  -> Rectangle<u16>
-{
-  if configuration.side == ScreenSide::Top
-     || configuration.side == ScreenSide::Bottom
-  {
-    let left = 0;
-    let width = screen.width_in_pixels();
-    let height = configuration.thickness;
+  fn set_strut_properties(&self, screen: &Screen) -> xcb::Result<()> {
+    let atoms = self.atoms();
 
-    let top = if configuration.side == ScreenSide::Bottom {
-      screen.height_in_pixels() - height
-    } else { 0 };
+    let thickness = self.configuration.thickness as u32;
 
-    Rectangle { left, top, width, height }
-  } else {
-    let top = 0;
-    let height = screen.height_in_pixels();
-    let width = configuration.thickness;
+    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],
+    };
+    self.set_cardinal_property(&atoms.wm_strut, strut_values)?;
 
-    let left = if configuration.side == ScreenSide::Right {
-      screen.width_in_pixels() - width
-    } else { 0 };
+    let strut_partial_values = &[
+      strut_values[0],
+      strut_values[1],
+      strut_values[2],
+      strut_values[3],
 
-    Rectangle { left, top, width, height }
-  }
-}
+      0 as u32,
+      if self.configuration.side == ScreenSide::Left {
+        screen.height_in_pixels() as u32
+      } else { 0 as u32 },
+
+      0 as u32,
+      if self.configuration.side == ScreenSide::Right {
+        screen.height_in_pixels() as u32
+      } else { 0 as u32 },
+
+      0 as u32,
+      if self.configuration.side == ScreenSide::Top {
+        screen.width_in_pixels() as u32
+      } else { 0 as u32 },
 
+      0 as u32,
+      if self.configuration.side == ScreenSide::Bottom {
+        screen.width_in_pixels() as u32
+      } else { 0 as u32 },
+    ];
 
-fn set_dock_strut_properties(dock: &Dock, screen: &Screen)
-  -> xcb::Result<()>
-{
-  let window = dock.window();
-  let atoms = dock.atoms();
-
-  let thickness = dock.configuration.thickness as u32;
-
-  let strut_values = match dock.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],
-  };
-  window.set_cardinal_property(&atoms.wm_strut, strut_values)?;
-
-  let strut_partial_values = &[
-    strut_values[0],
-    strut_values[1],
-    strut_values[2],
-    strut_values[3],
-
-    0 as u32,
-    if dock.configuration.side == ScreenSide::Left {
-      screen.height_in_pixels() as u32
-    } else { 0 as u32 },
-
-    0 as u32,
-    if dock.configuration.side == ScreenSide::Right {
-      screen.height_in_pixels() as u32
-    } else { 0 as u32 },
-
-    0 as u32,
-    if dock.configuration.side == ScreenSide::Top {
-      screen.width_in_pixels() as u32
-    } else { 0 as u32 },
-
-    0 as u32,
-    if dock.configuration.side == ScreenSide::Bottom {
-      screen.width_in_pixels() as u32
-    } else { 0 as u32 },
-  ];
-
-  window.set_cardinal_property(&atoms.wm_strut_partial,
+    self.set_cardinal_property(&atoms.wm_strut_partial,
                                strut_partial_values)?;
 
-  Ok(())
+    Ok(())
+  }
+
+
+  fn compute_bounds(screen: &Screen, configuration: &DockConfiguration)
+    -> Rectangle<u16>
+  {
+    if configuration.side == ScreenSide::Top
+       || configuration.side == ScreenSide::Bottom
+    {
+      let left = 0;
+      let width = screen.width_in_pixels();
+      let height = configuration.thickness;
+
+      let top = if configuration.side == ScreenSide::Bottom {
+        screen.height_in_pixels() - height
+      } else { 0 };
+
+      Rectangle { left, top, width, height }
+    } else {
+      let top = 0;
+      let height = screen.height_in_pixels();
+      let width = configuration.thickness;
+
+      let left = if configuration.side == ScreenSide::Right {
+        screen.width_in_pixels() - width
+      } else { 0 };
+
+      Rectangle { left, top, width, height }
+    }
+  }
+
 }
 
diff --git a/src/xtypes.rs b/src/xtypes.rs
new file mode 100644
index 0000000..3f67e58
--- /dev/null
+++ b/src/xtypes.rs
@@ -0,0 +1,269 @@
+use std::borrow::Borrow;
+use std::sync::Arc;
+use std::ops::Deref;
+
+use xcb::x::{
+  self,
+  Atom,
+  ChangeProperty,
+  CreateWindow,
+  InternAtom,
+  MapWindow,
+  PropMode,
+  Screen
+};
+
+
+pub struct Atoms {
+  pub wm_protocols: Atom,
+  pub wm_delete_window: Atom,
+  pub wm_type: Atom,
+  pub wm_type_dock: Atom,
+  pub wm_strut: Atom,
+  pub wm_strut_partial: Atom,
+}
+
+
+pub struct Connection(xcb::Connection);
+
+pub struct Display {
+  connection: Connection,
+  screen_index: i32,
+  atoms: Atoms,
+}
+
+pub struct Window {
+  display: Arc<Display>,
+  window_id: x::Window,
+}
+
+
+impl Connection {
+  pub fn connect(display_name: Option<&str>)
+    -> xcb::ConnResult<(Connection, i32)>
+  {
+    let (connection, screen_index)
+        = xcb::Connection::connect(display_name)?;
+
+    Ok((Connection(connection), screen_index))
+  }
+}
+
+
+impl Display {
+  pub fn new() -> xcb::Result<Display> {
+    let (connection, screen_index) = Connection::connect(None)?;
+
+    let atoms = connection.get_atoms()?;
+
+    Ok(Display { connection, screen_index, atoms })
+  }
+
+  pub fn screen_index(&self) -> i32 {
+    self.screen_index
+  }
+}
+
+
+impl Window {
+  pub fn new(display: Arc<Display>, create_window: &mut CreateWindow)
+    -> xcb::Result<Window>
+  {
+    let display_ref: &Display = display.borrow();
+    let connection: &Connection = &display_ref.connection;
+
+    let window_id: x::Window = connection.0.generate_id();
+
+    create_window.wid = window_id;
+    let cookie = connection.send_request_checked(create_window);
+    connection.check_request(cookie)?;
+
+    Ok(Window { display, window_id })
+  }
+}
+
+
+pub trait HasWindow {
+  fn window(&self) -> &Window;
+
+  fn window_id(&self) -> x::Window { self.window().window_id }
+}
+
+impl HasWindow for Window {
+  fn window(&self) -> &Window { self }
+}
+
+impl<T: Deref<Target=Window>> HasWindow for T {
+  fn window(&self) -> &Window { &*self }
+}
+
+
+pub trait HasConnection {
+  fn connection(&self) -> &Connection;
+
+  fn get_setup(&self) -> &xcb::x::Setup {
+    self.connection().0.get_setup()
+  }
+
+  fn send_request<R: xcb::Request>(&self, request: &R) -> R::Cookie {
+    self.connection().0.send_request(request)
+  }
+
+  fn wait_for_reply<C: xcb::CookieWithReplyChecked>(&self, cookie: C)
+    -> xcb::Result<C::Reply>
+  {
+    self.connection().0.wait_for_reply(cookie)
+  }
+
+  fn send_request_checked<R: xcb::RequestWithoutReply>(&self, request: &R)
+    -> xcb::VoidCookieChecked
+  {
+    self.connection().0.send_request_checked(request)
+  }
+
+  fn check_request(&self, cookie: xcb::VoidCookieChecked)
+    -> xcb::ProtocolResult<()>
+  {
+    self.connection().0.check_request(cookie)
+  }
+
+  fn wait_for_event(&self) -> xcb::Result<xcb::Event> {
+    self.connection().0.wait_for_event()
+  }
+}
+
+impl HasConnection for Connection {
+  fn connection(&self) -> &Connection { self }
+}
+
+impl<T: HasDisplay> HasConnection for T {
+  fn connection(&self) -> &Connection { &self.display().connection }
+}
+
+
+pub trait HasDisplay {
+  fn display(&self) -> &Display;
+
+  fn atoms(&self) -> &Atoms { &self.display().atoms }
+}
+
+impl HasDisplay for Display {
+  fn display(&self) -> &Display { self }
+}
+
+impl<T: HasWindow> HasDisplay for T {
+  fn display(&self) -> &Display { self.window().display.borrow() }
+}
+
+
+pub trait ConnectionExt: HasConnection {
+  fn get_atom(&self, name: &[u8]) -> xcb::Result<Atom> {
+    let connection = self.connection();
+
+    let cookie = connection.send_request(&InternAtom {
+      only_if_exists: true,
+      name: name,
+    });
+
+    Ok(connection.wait_for_reply(cookie)?.atom())
+  }
+
+  fn get_atoms(&self) -> xcb::Result<Atoms> {
+    let wm_protocols = self.get_atom(b"WM_PROTOCOLS")?;
+    let wm_delete_window = self.get_atom(b"WM_DELETE_WINDOW")?;
+
+    let wm_type = self.get_atom(b"_NET_WM_WINDOW_TYPE")?;
+    let wm_type_dock = self.get_atom(b"_NET_WM_WINDOW_TYPE_DOCK")?;
+
+    let wm_strut = self.get_atom(b"_NET_WM_STRUT")?;
+    let wm_strut_partial = self.get_atom(b"_NET_WM_STRUT_PARTIAL")?;
+
+    Ok(Atoms {
+      wm_protocols, wm_delete_window,
+      wm_type, wm_type_dock,
+      wm_strut, wm_strut_partial,
+    })
+  }
+}
+
+impl<T: HasConnection> ConnectionExt for T { }
+
+
+pub trait DisplayExt: HasDisplay + HasConnection {
+  fn screen(&self) -> &Screen {
+    let setup = self.connection().get_setup();
+    let screen_index = self.display().screen_index() as usize;
+
+    &setup.roots().nth(screen_index).unwrap()
+  }
+}
+
+impl<T: HasDisplay + HasConnection> DisplayExt for T { }
+
+
+pub trait WindowExt: HasWindow + HasDisplay + HasConnection {
+  fn map_window(&self) -> xcb::Result<()> {
+    let cookie = self.send_request_checked(&MapWindow {
+      window: self.window_id()
+    });
+    self.check_request(cookie)?;
+
+    Ok(())
+  }
+
+  fn set_string_property(&self, property: &Atom, value: &[u8])
+    -> xcb::Result<()>
+  {
+    let connection = self.connection();
+
+    let cookie = connection.send_request_checked(&ChangeProperty {
+      mode: PropMode::Replace,
+      window: self.window_id(),
+      property: *property,
+      r#type: x::ATOM_STRING,
+      data: value,
+    });
+    connection.check_request(cookie)?;
+
+    Ok(())
+  }
+
+
+  fn set_atom_property(&self, property: &Atom, values: &[Atom])
+    -> xcb::Result<()>
+  {
+    let connection = self.connection();
+
+    let cookie = connection.send_request_checked(&ChangeProperty {
+      mode: PropMode::Replace,
+      window: self.window_id(),
+      property: *property,
+      r#type: x::ATOM_ATOM,
+      data: values,
+    });
+    connection.check_request(cookie)?;
+
+    Ok(())
+  }
+
+
+  fn set_cardinal_property(&self, property: &Atom, values: &[u32])
+    -> xcb::Result<()>
+  {
+    let connection = self.connection();
+
+    let cookie = connection.send_request_checked(&ChangeProperty {
+      mode: PropMode::Replace,
+      window: self.window_id(),
+      property: *property,
+      r#type: x::ATOM_CARDINAL,
+      data: values,
+    });
+    connection.check_request(cookie)?;
+
+    Ok(())
+  }
+}
+
+impl<T: HasWindow + HasDisplay + HasConnection> WindowExt for T { }
+