use xcb; use x11; use comm; use comm::Channel; use config::Config; use std::thread; use std::time::Duration; pub fn wait_for(f: F) -> xcb::Window where F: Fn() -> xcb::Window { loop { let w = f(); if w == 0 { thread::sleep(Duration::from_millis(100)); } else { return w; } } } pub fn wm(tx: &Channel, _config: &Config) { if let Some(conn) = x11::Connection::new() { let screen = conn.default_screen(); let mut last_win = screen.get_active_window(); comm::send(tx, "title", conn.get_window_name(last_win).as_ref()); let stalonetray = wait_for(|| screen.search_by_class("stalonetray")); let panel = wait_for(|| screen.search_by_name("__panel_top")); let width = xcb::get_geometry(&conn, stalonetray).get_reply().unwrap().width(); xcb::configure_window(&conn, stalonetray, &[ (xcb::CONFIG_WINDOW_X as u16, (screen.width - width) as u32), (xcb::CONFIG_WINDOW_SIBLING as u16, panel), (xcb::CONFIG_WINDOW_STACK_MODE as u16, xcb::STACK_MODE_ABOVE) ]); xcb::change_window_attributes(&conn, stalonetray, &[(xcb::CW_EVENT_MASK, xcb::EVENT_MASK_STRUCTURE_NOTIFY)]); conn.watch(screen.root, true); conn.watch(last_win, true); conn.flush(); conn.event_loop(&mut |event: &xcb::GenericEvent| { match event.response_type() { xcb::PROPERTY_NOTIFY => { let prop_event: &xcb::PropertyNotifyEvent = xcb::cast_event(event); 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); conn.flush(); last_win = new_win; comm::send(tx, "title", conn.get_window_name(last_win).as_ref()); } else if prop_event.atom() == conn.atom(x11::_NET_WM_NAME) { comm::send(tx, "title", conn.get_window_name(last_win).as_ref()); } }, xcb::CONFIGURE_NOTIFY => { let event: &xcb::ConfigureNotifyEvent = unsafe { xcb::cast_event(&event) }; let spacer = format!("%{{O{}}}", event.width()+5); comm::send(tx, "spacer", spacer.as_ref()); }, _ => () } }); } else { println!("Could not connect to X!"); } }