Browse Source

Make atoms load on demand

Thomas Dy 8 years ago
parent
commit
2c7e7183c1
2 changed files with 22 additions and 23 deletions
  1. 2 2
      src/wm.rs
  2. 20 21
      src/x11.rs

+ 2 - 2
src/wm.rs

@@ -42,7 +42,7 @@ pub fn wm(tx: &Channel, _config: &Config) {
             match event.response_type() {
                 xcb::PROPERTY_NOTIFY => {
                     let prop_event: &xcb::PropertyNotifyEvent = xcb::cast_event(event);
-                    if prop_event.atom() == conn.atoms._NET_ACTIVE_WINDOW {
+                    if prop_event.atom() == conn.atom(x11::_NET_ACTIVE_WINDOW) {
                         let new_win = screen.get_active_window();
                         conn.watch(last_win, false);
                         conn.watch(new_win, true);
@@ -50,7 +50,7 @@ pub fn wm(tx: &Channel, _config: &Config) {
                         last_win = new_win;
                         comm::send(tx, "title", conn.get_window_name(last_win).as_ref());
                     }
-                    else if prop_event.atom() == conn.atoms._NET_WM_NAME {
+                    else if prop_event.atom() == conn.atom(x11::_NET_WM_NAME) {
                         comm::send(tx, "title", conn.get_window_name(last_win).as_ref());
                     }
                 },

+ 20 - 21
src/x11.rs

@@ -1,24 +1,13 @@
 use xcb;
+use std::cell::RefCell;
+use std::collections::HashMap;
 use std::mem;
 use std::ops::Deref;
 
-fn load_atom(conn: &xcb::Connection, name: &str) -> xcb::Atom {
-    let cookie = xcb::intern_atom(conn, true, name);
-    cookie.get_reply().unwrap().atom()
-}
-
 macro_rules! atoms {
     ( $( $x:ident ),* ) => {
         #[allow(non_snake_case)]
-        pub struct Atoms {
-            $(pub $x: xcb::Atom),*
-        }
-
-        pub fn load_atoms(conn: &xcb::Connection) -> Atoms {
-            Atoms {
-                $($x: load_atom(conn, stringify!($x))),*
-            }
-        }
+        $(pub const $x: &'static str = stringify!($x);)*
     }
 }
 
@@ -36,16 +25,16 @@ pub struct WinClass {
 pub struct Connection {
     conn: xcb::Connection,
     default_screen: i32,
-    pub atoms: Atoms
+    cache: RefCell<HashMap<String, xcb::Atom>>
 }
 
 impl Connection {
     pub fn new() -> Option<Connection> {
         if let Ok((conn, default_screen)) = xcb::Connection::connect(None) {
             Some(Connection {
-                atoms: load_atoms(&conn),
                 default_screen: default_screen,
-                conn: conn
+                conn: conn,
+                cache: RefCell::new(HashMap::new())
             })
         }
         else {
@@ -53,6 +42,18 @@ impl Connection {
         }
     }
 
+    pub fn atom(&self, name: &str) -> xcb::Atom {
+        let mut cache = self.cache.borrow_mut();
+        if cache.contains_key(name) {
+            *cache.get(name).unwrap()
+        }
+        else {
+            let atom = xcb::intern_atom(&self.conn, false, name).get_reply().unwrap().atom();
+            cache.insert(name.to_string(), atom);
+            atom
+        }
+    }
+
     pub fn default_screen<'a>(&'a self) -> Screen<'a> {
         self.screen(self.default_screen as usize)
     }
@@ -62,7 +63,6 @@ impl Connection {
         let screen = setup.roots().nth(index).unwrap();
         Screen {
             conn: &self,
-            atoms: &self.atoms,
             root: screen.root(),
             width: screen.width_in_pixels(),
             index: index
@@ -80,7 +80,7 @@ impl Connection {
     }
 
     pub fn get_window_name(&self, win: xcb::Window) -> String {
-        let cookie = xcb::get_property(&self.conn, false, win, self.atoms._NET_WM_NAME, self.atoms.UTF8_STRING, 0, 100);
+        let cookie = xcb::get_property(&self.conn, false, win, self.atom(_NET_WM_NAME), self.atom(UTF8_STRING), 0, 100);
         let reply = cookie.get_reply();
         let value: &str = match reply {
             Ok(reply) => unsafe { mem::transmute(reply.value()) },
@@ -144,7 +144,6 @@ impl Deref for Connection {
 
 pub struct Screen<'a> {
     conn: &'a Connection,
-    pub atoms: &'a Atoms,
     pub root: xcb::Window,
     pub width: u16,
     pub index: usize
@@ -152,7 +151,7 @@ pub struct Screen<'a> {
 
 impl<'a> Screen<'a> {
     pub fn get_active_window(&self) -> xcb::Window {
-        let cookie = xcb::get_property(self.conn, false, self.root, self.atoms._NET_ACTIVE_WINDOW, xcb::ATOM_WINDOW, 0, 4);
+        let cookie = xcb::get_property(self.conn, false, self.root, self.conn.atom(_NET_ACTIVE_WINDOW), xcb::ATOM_WINDOW, 0, 4);
         let reply = cookie.get_reply().unwrap();
         if reply.value_len() == 0 {
             0