Browse Source

Simplify tray / panel composition

Thomas Dy 8 years ago
parent
commit
a4182b725f
3 changed files with 55 additions and 69 deletions
  1. 1 1
      src/ui/mod.rs
  2. 24 28
      src/ui/panel.rs
  3. 30 40
      src/ui/tray.rs

+ 1 - 1
src/ui/mod.rs

@@ -28,7 +28,7 @@ pub fn ui_main(signal: chan::Receiver<chan_signal::Signal>, cfg: &Config) -> i32
             });
         }
 
-        let panel = panel::Panel::new(conn, cfg);
+        let mut panel = panel::Panel::new(conn, cfg);
         panel.create();
 
         loop {

+ 24 - 28
src/ui/panel.rs

@@ -6,21 +6,24 @@ use ui::font;
 use ui::tray;
 use ui::x11;
 
-use std::cell::RefCell;
-use std::rc::Rc;
+use std::sync::Arc;
 
 pub struct Panel {
-    pub conn: x11::Connection,
+    pub conn: Arc<x11::Connection>,
     pub window: xcb::Window,
     pub width: u16,
-    tray: RefCell<Option<tray::Tray>>,
+    tray: tray::Tray,
     fonts: font::FontLoader,
     picture: xcb::render::Picture,
-    finishing: RefCell<bool>
+    finishing: bool
 }
 
 impl Panel {
-    pub fn new(conn: x11::Connection, cfg: &Config) -> Rc<Panel> {
+    pub fn new(conn: x11::Connection, cfg: &Config) -> Panel {
+        let conn = Arc::new(conn);
+        let window = conn.generate_id();
+        let picture = conn.generate_id();
+
         let val = cfg.lookup("bar.fonts").unwrap();
         let fonts = val.as_slice().unwrap();
         let fonts = fonts.iter().flat_map(|elem| elem.as_str());
@@ -29,21 +32,18 @@ impl Panel {
             font_loader.load(font);
         }
 
-        let window = conn.generate_id();
-        let picture = conn.generate_id();
+        let width = conn.default_screen().width;
+        let tray = tray::Tray::new(conn.clone(), window, width as u32);
 
-        let panel = Rc::new(Panel {
+        Panel {
+            conn: conn,
+            width: width,
             window: window,
-            width: conn.default_screen().width,
             fonts: font_loader,
-            conn: conn,
-            tray: RefCell::new(None),
+            tray: tray,
             picture: picture,
-            finishing: RefCell::new(false)
-        });
-        let tray = tray::Tray::new(Rc::downgrade(&panel));
-        *panel.tray.borrow_mut() = Some(tray);
-        panel
+            finishing: false
+        }
     }
 
     pub fn create(&self) {
@@ -91,18 +91,18 @@ impl Panel {
         );
     }
 
-    pub fn handle_event(&self, event: xcb::GenericEvent) -> bool {
-        let tray = self.tray.borrow_mut().as_mut().unwrap().handle_event(&event);
+    pub fn handle_event(&mut self, event: xcb::GenericEvent) -> bool {
+        let should_exit = self.tray.handle_event(&event, self.finishing);
         if event.response_type() == xcb::EXPOSE {
             self.draw_text("Hello 世界!");
         }
-        if self.is_finishing() && event.response_type() == xcb::DESTROY_NOTIFY {
+        if self.finishing && event.response_type() == xcb::DESTROY_NOTIFY {
             let event: &xcb::DestroyNotifyEvent = xcb::cast_event(&event);
             if event.window() == self.window {
                 return true
             }
         }
-        tray
+        should_exit
     }
 
     pub fn create_pen(&self, r: u16, g: u16, b: u16, a: u16) -> xcb::render::Picture {
@@ -138,13 +138,9 @@ impl Panel {
         self.conn.flush();
     }
 
-    pub fn is_finishing(&self) -> bool {
-        *self.finishing.borrow()
-    }
-
-    pub fn finish(&self) {
-        *self.finishing.borrow_mut() = true;
-        self.tray.borrow_mut().as_mut().unwrap().finish();
+    pub fn finish(&mut self) {
+        self.finishing = true;
+        self.tray.finish();
         xcb::destroy_window(&self.conn, self.window);
         self.conn.flush();
     }

+ 30 - 40
src/ui/tray.rs

@@ -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())));
                 }
             },