|  | @@ -0,0 +1,66 @@
 | 
	
		
			
				|  |  | +extern crate xcb;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +use std::mem;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +const ATOMS: [&'static str; 3] = [
 | 
	
		
			
				|  |  | +    "_NET_ACTIVE_WINDOW",
 | 
	
		
			
				|  |  | +    "_NET_WM_NAME",
 | 
	
		
			
				|  |  | +    "UTF8_STRING"
 | 
	
		
			
				|  |  | +];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#[allow(non_snake_case)]
 | 
	
		
			
				|  |  | +pub struct EWMH<'a> {
 | 
	
		
			
				|  |  | +    pub conn: &'a xcb::Connection,
 | 
	
		
			
				|  |  | +    pub root: xcb::Window,
 | 
	
		
			
				|  |  | +    pub _NET_ACTIVE_WINDOW: xcb::Atom,
 | 
	
		
			
				|  |  | +    pub _NET_WM_NAME: xcb::Atom,
 | 
	
		
			
				|  |  | +    pub UTF8_STRING: xcb::Atom
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +pub fn connect<'a>(conn: &'a xcb::Connection, screen_num: i32) -> EWMH {
 | 
	
		
			
				|  |  | +    let setup = conn.get_setup();
 | 
	
		
			
				|  |  | +    let screen = setup.roots().nth(screen_num as usize).unwrap();
 | 
	
		
			
				|  |  | +    let atoms: Vec<xcb::Atom> = ATOMS
 | 
	
		
			
				|  |  | +        .iter()
 | 
	
		
			
				|  |  | +        .map(|name| xcb::intern_atom(&conn, false, name))
 | 
	
		
			
				|  |  | +        .map(|cookie| cookie.get_reply().unwrap().atom())
 | 
	
		
			
				|  |  | +        .collect();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    EWMH {
 | 
	
		
			
				|  |  | +        conn: conn,
 | 
	
		
			
				|  |  | +        root: screen.root(),
 | 
	
		
			
				|  |  | +        _NET_ACTIVE_WINDOW: atoms[0],
 | 
	
		
			
				|  |  | +        _NET_WM_NAME: atoms[1],
 | 
	
		
			
				|  |  | +        UTF8_STRING: atoms[2]
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +impl<'a> EWMH<'a> {
 | 
	
		
			
				|  |  | +    pub fn get_active_window(&self) -> xcb::Window {
 | 
	
		
			
				|  |  | +        let cookie = xcb::get_property(&self.conn, false, self.root, self._NET_ACTIVE_WINDOW, xcb::ATOM_WINDOW, 0, 4);
 | 
	
		
			
				|  |  | +        let reply = cookie.get_reply().unwrap();
 | 
	
		
			
				|  |  | +        let value: &xcb::Window = unsafe { mem::transmute(&(reply.value()[0])) };
 | 
	
		
			
				|  |  | +        *value
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    pub fn get_window_name(&self, win: xcb::Window) -> String {
 | 
	
		
			
				|  |  | +        let cookie = xcb::get_property(&self.conn, false, win, self._NET_WM_NAME, self.UTF8_STRING, 0, 100);
 | 
	
		
			
				|  |  | +        let reply = cookie.get_reply();
 | 
	
		
			
				|  |  | +        let value: &str = match reply {
 | 
	
		
			
				|  |  | +            Ok(reply) => unsafe { mem::transmute(reply.value()) },
 | 
	
		
			
				|  |  | +            _ => ""
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +        value.to_string()
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    pub fn watch(&self, win: xcb::Window, enabled: bool) {
 | 
	
		
			
				|  |  | +        let value = if enabled {
 | 
	
		
			
				|  |  | +            xcb::EVENT_MASK_PROPERTY_CHANGE
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        else {
 | 
	
		
			
				|  |  | +            xcb::EVENT_MASK_NO_EVENT
 | 
	
		
			
				|  |  | +        };
 | 
	
		
			
				|  |  | +        xcb::change_window_attributes(&self.conn, win, &[(xcb::CW_EVENT_MASK, value)]);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 |