|  | @@ -1,71 +1,62 @@
 | 
	
		
			
				|  |  |  use ui;
 | 
	
		
			
				|  |  | -use ui::panel;
 | 
	
		
			
				|  |  |  use ui::x11;
 | 
	
		
			
				|  |  |  use xcb;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -use std::rc::Weak;
 | 
	
		
			
				|  |  | +use std::sync::Arc;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  const CLIENT_MESSAGE: u8 = xcb::CLIENT_MESSAGE | 0x80; // 0x80 flag for client messages
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  pub struct Tray {
 | 
	
		
			
				|  |  | -    panel: Weak<panel::Panel>,
 | 
	
		
			
				|  |  | +    conn: Arc<x11::Connection>,
 | 
	
		
			
				|  |  | +    window: xcb::Window,
 | 
	
		
			
				|  |  | +    panel_width: u32,
 | 
	
		
			
				|  |  |      children: Vec<xcb::Window>,
 | 
	
		
			
				|  |  | -    timestamp: xcb::Timestamp
 | 
	
		
			
				|  |  | -}
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -// I'M SO SORRY
 | 
	
		
			
				|  |  | -macro_rules! refs {
 | 
	
		
			
				|  |  | -    ( $slf:ident, $panel:ident, $conn:ident ) => {
 | 
	
		
			
				|  |  | -        let $panel = $slf.panel.upgrade().unwrap();
 | 
	
		
			
				|  |  | -        let $conn = &$panel.conn;
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | +    timestamp: xcb::Timestamp,
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  impl Tray {
 | 
	
		
			
				|  |  | -    pub fn new(panel: Weak<panel::Panel>) -> Tray {
 | 
	
		
			
				|  |  | +    pub fn new(conn: Arc<x11::Connection>, window: xcb::Window, width: u32) -> Tray {
 | 
	
		
			
				|  |  |          Tray {
 | 
	
		
			
				|  |  | -            panel: panel,
 | 
	
		
			
				|  |  | +            conn: conn,
 | 
	
		
			
				|  |  | +            window: window,
 | 
	
		
			
				|  |  | +            panel_width: width,
 | 
	
		
			
				|  |  |              children: vec![],
 | 
	
		
			
				|  |  |              timestamp: 0
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      pub fn take_selection(&mut self, timestamp: xcb::Timestamp) -> bool {
 | 
	
		
			
				|  |  | -        refs!(self, panel, conn);
 | 
	
		
			
				|  |  | -        let window = panel.window;
 | 
	
		
			
				|  |  | -        let selection = conn.atom(x11::_NET_SYSTEM_TRAY_S0);
 | 
	
		
			
				|  |  | -        xcb::set_selection_owner(conn, window, selection, timestamp);
 | 
	
		
			
				|  |  | -        let owner = xcb::get_selection_owner(conn, selection).get_reply().unwrap().owner();
 | 
	
		
			
				|  |  | -        let ok = owner == window;
 | 
	
		
			
				|  |  | +        let selection = self.conn.atom(x11::_NET_SYSTEM_TRAY_S0);
 | 
	
		
			
				|  |  | +        xcb::set_selection_owner(&self.conn, self.window, selection, timestamp);
 | 
	
		
			
				|  |  | +        let owner = xcb::get_selection_owner(&self.conn, selection).get_reply().unwrap().owner();
 | 
	
		
			
				|  |  | +        let ok = owner == self.window;
 | 
	
		
			
				|  |  |          if ok {
 | 
	
		
			
				|  |  |              self.timestamp = timestamp;
 | 
	
		
			
				|  |  | -            let screen = conn.default_screen();
 | 
	
		
			
				|  |  | +            let screen = self.conn.default_screen();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              let client_event = xcb::ClientMessageEvent::new(
 | 
	
		
			
				|  |  |                  32, // 32 bits (refers to data)
 | 
	
		
			
				|  |  |                  screen.root,
 | 
	
		
			
				|  |  | -                conn.atom(x11::MANAGER),
 | 
	
		
			
				|  |  | -                xcb::ClientMessageData::from_data32([timestamp, selection, window, 0, 0])
 | 
	
		
			
				|  |  | +                self.conn.atom(x11::MANAGER),
 | 
	
		
			
				|  |  | +                xcb::ClientMessageData::from_data32([timestamp, selection, self.window, 0, 0])
 | 
	
		
			
				|  |  |              );
 | 
	
		
			
				|  |  | -            xcb::send_event(conn, false, screen.root, xcb::EVENT_MASK_STRUCTURE_NOTIFY, &client_event);
 | 
	
		
			
				|  |  | -            conn.flush();
 | 
	
		
			
				|  |  | +            xcb::send_event(&self.conn, false, screen.root, xcb::EVENT_MASK_STRUCTURE_NOTIFY, &client_event);
 | 
	
		
			
				|  |  | +            self.conn.flush();
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          ok
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      fn x_pos(&self, index: usize) -> u32 {
 | 
	
		
			
				|  |  | -        refs!(self, panel, _conn);
 | 
	
		
			
				|  |  | -        let panel_width = panel.width as u32;
 | 
	
		
			
				|  |  |          let tray_width = (index + 1) as u32 * ui::SIZE as u32;
 | 
	
		
			
				|  |  | -        panel_width - tray_width
 | 
	
		
			
				|  |  | +        self.panel_width - tray_width
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      pub fn adopt(&mut self, window: xcb::Window) {
 | 
	
		
			
				|  |  | -        refs!(self, panel, conn);
 | 
	
		
			
				|  |  | +        let conn = &self.conn;
 | 
	
		
			
				|  |  |          xcb::change_window_attributes(conn, window, &[
 | 
	
		
			
				|  |  |              (xcb::CW_EVENT_MASK, xcb::EVENT_MASK_STRUCTURE_NOTIFY)
 | 
	
		
			
				|  |  |          ]);
 | 
	
		
			
				|  |  | -        xcb::reparent_window(conn, window, panel.window, self.x_pos(self.children.len()) as i16, 0);
 | 
	
		
			
				|  |  | +        xcb::reparent_window(conn, window, self.window, self.x_pos(self.children.len()) as i16, 0);
 | 
	
		
			
				|  |  |          xcb::map_window(conn, window);
 | 
	
		
			
				|  |  |          self.force_size(window, None);
 | 
	
		
			
				|  |  |          conn.flush();
 | 
	
	
		
			
				|  | @@ -79,7 +70,7 @@ impl Tray {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      pub fn force_size(&self, window: xcb::Window, dimensions: Option<(u16, u16)>) {
 | 
	
		
			
				|  |  | -        refs!(self, panel, conn);
 | 
	
		
			
				|  |  | +        let conn = &self.conn;
 | 
	
		
			
				|  |  |          let dimensions = dimensions.unwrap_or_else(|| {
 | 
	
		
			
				|  |  |              let geometry = xcb::get_geometry(conn, window).get_reply().unwrap();
 | 
	
		
			
				|  |  |              (geometry.width(), geometry.height())
 | 
	
	
		
			
				|  | @@ -94,7 +85,7 @@ impl Tray {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      pub fn reposition(&self) {
 | 
	
		
			
				|  |  | -        refs!(self, panel, conn);
 | 
	
		
			
				|  |  | +        let conn = &self.conn;
 | 
	
		
			
				|  |  |          for (index, child) in self.children.iter().enumerate() {
 | 
	
		
			
				|  |  |              let window = *child;
 | 
	
		
			
				|  |  |              xcb::configure_window(conn, window, &[
 | 
	
	
		
			
				|  | @@ -105,7 +96,7 @@ impl Tray {
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      pub fn finish(&mut self) {
 | 
	
		
			
				|  |  | -        refs!(self, panel, conn);
 | 
	
		
			
				|  |  | +        let conn = &self.conn;
 | 
	
		
			
				|  |  |          let screen = conn.default_screen();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          for child in self.children.iter() {
 | 
	
	
		
			
				|  | @@ -116,16 +107,15 @@ impl Tray {
 | 
	
		
			
				|  |  |              xcb::unmap_window(conn, window);
 | 
	
		
			
				|  |  |              xcb::reparent_window(conn, window, screen.root, 0, 0);
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | -        xcb::change_window_attributes(conn, panel.window, &[
 | 
	
		
			
				|  |  | +        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();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    pub fn handle_event(&mut self, event: &xcb::GenericEvent) -> bool {
 | 
	
		
			
				|  |  | -        refs!(self, panel, conn);
 | 
	
		
			
				|  |  | -        if panel.is_finishing() {
 | 
	
		
			
				|  |  | +    pub fn handle_event(&mut self, event: &xcb::GenericEvent, is_finishing: bool) -> bool {
 | 
	
		
			
				|  |  | +        if is_finishing {
 | 
	
		
			
				|  |  |              return false
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |          match event.response_type() {
 | 
	
	
		
			
				|  | @@ -138,7 +128,7 @@ impl Tray {
 | 
	
		
			
				|  |  |              },
 | 
	
		
			
				|  |  |              CLIENT_MESSAGE => {
 | 
	
		
			
				|  |  |                  let event: &xcb::ClientMessageEvent = xcb::cast_event(&event);
 | 
	
		
			
				|  |  | -                if event.type_() == conn.atom(x11::_NET_SYSTEM_TRAY_OPCODE) {
 | 
	
		
			
				|  |  | +                if event.type_() == self.conn.atom(x11::_NET_SYSTEM_TRAY_OPCODE) {
 | 
	
		
			
				|  |  |                      let data = event.data().data32();
 | 
	
		
			
				|  |  |                      let opcode = data[1];
 | 
	
		
			
				|  |  |                      let window = data[2];
 | 
	
	
		
			
				|  | @@ -149,7 +139,7 @@ impl Tray {
 | 
	
		
			
				|  |  |              },
 | 
	
		
			
				|  |  |              xcb::REPARENT_NOTIFY => {
 | 
	
		
			
				|  |  |                  let event: &xcb::ReparentNotifyEvent = xcb::cast_event(&event);
 | 
	
		
			
				|  |  | -                if event.parent() != panel.window {
 | 
	
		
			
				|  |  | +                if event.parent() != self.window {
 | 
	
		
			
				|  |  |                      self.forget(event.window());
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |              },
 | 
	
	
		
			
				|  | @@ -160,7 +150,7 @@ impl Tray {
 | 
	
		
			
				|  |  |              xcb::CONFIGURE_NOTIFY => {
 | 
	
		
			
				|  |  |                  let event: &xcb::ConfigureNotifyEvent = xcb::cast_event(&event);
 | 
	
		
			
				|  |  |                  let window = event.window();
 | 
	
		
			
				|  |  | -                if window != panel.window {
 | 
	
		
			
				|  |  | +                if window != self.window {
 | 
	
		
			
				|  |  |                      self.force_size(window, Some((event.width(), event.height())));
 | 
	
		
			
				|  |  |                  }
 | 
	
		
			
				|  |  |              },
 |