extern crate xcb; mod ewmh; 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 Ok((conn, screen_num)) = xcb::Connection::connect(None) { let ewmh = ewmh::connect(&conn, screen_num); let mut last_win = ewmh.get_active_window(); comm::send(tx, "title", ewmh.get_window_name(last_win).as_ref()); ewmh.watch(ewmh.root, true); ewmh.watch(last_win, true); let stalonetray = wait_for(|| ewmh.search_by_class("stalonetray")); let panel = wait_for(|| ewmh.search_by_name("__panel_top")); xcb::configure_window(&conn, stalonetray, &[(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.flush(); loop { let event = conn.wait_for_event(); match event { None => { break; } Some(event) => { match event.response_type() { xcb::PROPERTY_NOTIFY => { let prop_event: &xcb::PropertyNotifyEvent = xcb::cast_event(&event); if prop_event.atom() == ewmh._NET_ACTIVE_WINDOW { let new_win = ewmh.get_active_window(); ewmh.watch(last_win, false); ewmh.watch(new_win, true); conn.flush(); last_win = new_win; comm::send(tx, "title", ewmh.get_window_name(last_win).as_ref()); } else if prop_event.atom() == ewmh._NET_WM_NAME { comm::send(tx, "title", ewmh.get_window_name(last_win).as_ref()); } }, xcb::CONFIGURE_NOTIFY => { let event: &xcb::ConfigureNotifyEvent = 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!"); } }