|  | @@ -1,4 +1,6 @@
 | 
	
		
			
				|  |  | +use chan;
 | 
	
		
			
				|  |  |  use ui;
 | 
	
		
			
				|  |  | +use ui::widget;
 | 
	
		
			
				|  |  |  use ui::x11;
 | 
	
		
			
				|  |  |  use xcb;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -7,19 +9,19 @@ use std::sync::Arc;
 | 
	
		
			
				|  |  |  const CLIENT_MESSAGE: u8 = xcb::CLIENT_MESSAGE | 0x80; // 0x80 flag for client messages
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  pub struct Tray {
 | 
	
		
			
				|  |  | +    tx: chan::Sender<()>,
 | 
	
		
			
				|  |  |      conn: Arc<x11::Connection>,
 | 
	
		
			
				|  |  |      window: xcb::Window,
 | 
	
		
			
				|  |  | -    panel_width: u32,
 | 
	
		
			
				|  |  |      children: Vec<xcb::Window>,
 | 
	
		
			
				|  |  |      timestamp: xcb::Timestamp,
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  impl Tray {
 | 
	
		
			
				|  |  | -    pub fn new(conn: Arc<x11::Connection>, window: xcb::Window, width: u32) -> Tray {
 | 
	
		
			
				|  |  | +    pub fn new(tx: chan::Sender<()>, conn: Arc<x11::Connection>, window: xcb::Window) -> Tray {
 | 
	
		
			
				|  |  |          Tray {
 | 
	
		
			
				|  |  |              conn: conn,
 | 
	
		
			
				|  |  | +            tx: tx,
 | 
	
		
			
				|  |  |              window: window,
 | 
	
		
			
				|  |  | -            panel_width: width,
 | 
	
		
			
				|  |  |              children: vec![],
 | 
	
		
			
				|  |  |              timestamp: 0
 | 
	
		
			
				|  |  |          }
 | 
	
	
		
			
				|  | @@ -46,27 +48,22 @@ impl Tray {
 | 
	
		
			
				|  |  |          ok
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    fn x_pos(&self, index: usize) -> u32 {
 | 
	
		
			
				|  |  | -        let tray_width = (index + 1) as u32 * ui::SIZE as u32;
 | 
	
		
			
				|  |  | -        self.panel_width - tray_width
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |      pub fn adopt(&mut self, window: xcb::Window) {
 | 
	
		
			
				|  |  |          let conn = &self.conn;
 | 
	
		
			
				|  |  |          xcb::change_window_attributes(conn, window, &[
 | 
	
		
			
				|  |  |              (xcb::CW_EVENT_MASK, xcb::EVENT_MASK_STRUCTURE_NOTIFY)
 | 
	
		
			
				|  |  |          ]);
 | 
	
		
			
				|  |  | -        xcb::reparent_window(conn, window, self.window, self.x_pos(self.children.len()) as i16, 0);
 | 
	
		
			
				|  |  | +        xcb::reparent_window(conn, window, self.window, 0, 0);
 | 
	
		
			
				|  |  |          xcb::map_window(conn, window);
 | 
	
		
			
				|  |  |          self.force_size(window, None);
 | 
	
		
			
				|  |  |          conn.flush();
 | 
	
		
			
				|  |  |          self.children.push(window);
 | 
	
		
			
				|  |  | -        self.reposition();
 | 
	
		
			
				|  |  | +        self.tx.send(());
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      pub fn forget(&mut self, window: xcb::Window) {
 | 
	
		
			
				|  |  |          self.children.retain(|child| *child != window);
 | 
	
		
			
				|  |  | -        self.reposition();
 | 
	
		
			
				|  |  | +        self.tx.send(());
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      pub fn force_size(&self, window: xcb::Window, dimensions: Option<(u16, u16)>) {
 | 
	
	
		
			
				|  | @@ -83,38 +80,25 @@ impl Tray {
 | 
	
		
			
				|  |  |              conn.flush();
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    pub fn reposition(&self) {
 | 
	
		
			
				|  |  | -        let conn = &self.conn;
 | 
	
		
			
				|  |  | -        for (index, child) in self.children.iter().enumerate() {
 | 
	
		
			
				|  |  | -            let window = *child;
 | 
	
		
			
				|  |  | -            xcb::configure_window(conn, window, &[
 | 
	
		
			
				|  |  | -                (xcb::CONFIG_WINDOW_X as u16, self.x_pos(index))
 | 
	
		
			
				|  |  | -            ]);
 | 
	
		
			
				|  |  | -        }
 | 
	
		
			
				|  |  | -        conn.flush();
 | 
	
		
			
				|  |  | +impl widget::Widget for Tray {
 | 
	
		
			
				|  |  | +    fn width(&self) -> u16 {
 | 
	
		
			
				|  |  | +        (self.children.len() * 20) as u16
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    pub fn finish(&mut self) {
 | 
	
		
			
				|  |  | -        let conn = &self.conn;
 | 
	
		
			
				|  |  | -        let screen = conn.default_screen();
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -        for child in self.children.iter() {
 | 
	
		
			
				|  |  | +    fn render(&self, x: u16) {
 | 
	
		
			
				|  |  | +        for (index, child) in self.children.iter().enumerate() {
 | 
	
		
			
				|  |  |              let window = *child;
 | 
	
		
			
				|  |  | -            xcb::change_window_attributes(conn, window, &[
 | 
	
		
			
				|  |  | -                (xcb::CW_EVENT_MASK, xcb::EVENT_MASK_NO_EVENT)
 | 
	
		
			
				|  |  | +            let xpos = x as u32 + index as u32 * 20;
 | 
	
		
			
				|  |  | +            xcb::configure_window(&self.conn, window, &[
 | 
	
		
			
				|  |  | +                (xcb::CONFIG_WINDOW_X as u16, xpos)
 | 
	
		
			
				|  |  |              ]);
 | 
	
		
			
				|  |  | -            xcb::unmap_window(conn, window);
 | 
	
		
			
				|  |  | -            xcb::reparent_window(conn, window, screen.root, 0, 0);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        xcb::change_window_attributes(conn, self.window, &[
 | 
	
		
			
				|  |  | -            (xcb::CW_EVENT_MASK, xcb::EVENT_MASK_STRUCTURE_NOTIFY)
 | 
	
		
			
				|  |  | -        ]);
 | 
	
		
			
				|  |  | -        xcb::set_selection_owner(conn, xcb::NONE, conn.atom(x11::_NET_SYSTEM_TRAY_S0), self.timestamp);
 | 
	
		
			
				|  |  | -        conn.flush();
 | 
	
		
			
				|  |  | +        self.conn.flush();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    pub fn handle_event(&mut self, event: &xcb::GenericEvent, is_finishing: bool) -> bool {
 | 
	
		
			
				|  |  | +    fn handle_event(&mut self, event: &xcb::GenericEvent, is_finishing: bool) -> bool {
 | 
	
		
			
				|  |  |          if is_finishing {
 | 
	
		
			
				|  |  |              return false
 | 
	
		
			
				|  |  |          }
 | 
	
	
		
			
				|  | @@ -161,4 +145,23 @@ impl Tray {
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          false
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    fn finish(&mut self) {
 | 
	
		
			
				|  |  | +        let conn = &self.conn;
 | 
	
		
			
				|  |  | +        let screen = conn.default_screen();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        for child in self.children.iter() {
 | 
	
		
			
				|  |  | +            let window = *child;
 | 
	
		
			
				|  |  | +            xcb::change_window_attributes(conn, window, &[
 | 
	
		
			
				|  |  | +                (xcb::CW_EVENT_MASK, xcb::EVENT_MASK_NO_EVENT)
 | 
	
		
			
				|  |  | +            ]);
 | 
	
		
			
				|  |  | +            xcb::unmap_window(conn, window);
 | 
	
		
			
				|  |  | +            xcb::reparent_window(conn, window, screen.root, 0, 0);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        xcb::change_window_attributes(conn, self.window, &[
 | 
	
		
			
				|  |  | +            (xcb::CW_EVENT_MASK, xcb::EVENT_MASK_STRUCTURE_NOTIFY)
 | 
	
		
			
				|  |  | +        ]);
 | 
	
		
			
				|  |  | +        xcb::set_selection_owner(conn, xcb::NONE, conn.atom(x11::_NET_SYSTEM_TRAY_S0), self.timestamp);
 | 
	
		
			
				|  |  | +        conn.flush();
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  }
 |