|
@@ -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
|