Ver Fonte

Move event handling inside tray

Thomas Dy há 7 anos atrás
pai
commit
62d46e5467
2 ficheiros alterados com 62 adições e 46 exclusões
  1. 3 33
      src/main.rs
  2. 59 13
      src/tray.rs

+ 3 - 33
src/main.rs

@@ -17,8 +17,6 @@ const EXIT_WRONG_ARGS: i32 = 1;
 const EXIT_FAILED_CONNECT: i32 = 10;
 const EXIT_FAILED_SELECT: i32 = 11;
 
-const CLIENT_MESSAGE: u8 = xcb::CLIENT_MESSAGE | 0x80;
-
 fn main() {
     process::exit(real_main());
 }
@@ -90,46 +88,18 @@ fn real_main() -> i32 {
 
         tray.create();
 
-        let mut ready = false;
         loop {
             chan_select!(
                 rx.recv() -> event => {
-                    let event = event.unwrap();
-                    match event.response_type() {
-                        xcb::PROPERTY_NOTIFY if !ready => {
-                            ready = true;
-                            let event: &xcb::PropertyNotifyEvent = xcb::cast_event(&event);
-                            if !tray.take_selection(event.time()) {
-                                println!("Could not take ownership of tray selection. Maybe another tray is also running?");
-                                return EXIT_FAILED_SELECT
-                            }
-                        },
-                        CLIENT_MESSAGE => {
-                            let event: &xcb::ClientMessageEvent = xcb::cast_event(&event);
-                            let data = event.data().data32();
-                            let window = data[2];
-                            tray.adopt(window);
-                        },
-                        xcb::DESTROY_NOTIFY => {
-                            let event: &xcb::DestroyNotifyEvent = xcb::cast_event(&event);
-                            tray.forget(event.window());
-                        },
-                        xcb::CONFIGURE_NOTIFY => {
-                            let event: &xcb::ConfigureNotifyEvent = xcb::cast_event(&event);
-                            tray.force_size(event.window(), Some((event.width(), event.height())));
-                        },
-                        _ => {}
+                    if let Some(code) = tray.handle_event(event.unwrap()) {
+                        return code
                     }
                 },
                 signal.recv() => {
-                    break;
+                    tray.finish();
                 }
             );
         }
-
-        // cleanup code
-        tray.cleanup();
-        return 0
     }
     else {
         println!("Could not connect to X server!");

+ 59 - 13
src/tray.rs

@@ -18,6 +18,8 @@ pub const TOP_RIGHT: Position = (VerticalAlign::Top, HorizontalAlign::Right);
 pub const BOTTOM_LEFT: Position = (VerticalAlign::Bottom, HorizontalAlign::Left);
 pub const BOTTOM_RIGHT: Position = (VerticalAlign::Bottom, HorizontalAlign::Right);
 
+const CLIENT_MESSAGE: u8 = xcb::CLIENT_MESSAGE | 0x80;
+
 pub struct Tray<'a> {
     conn: &'a xcb::Connection,
     atoms: &'a atom::Atoms<'a>,
@@ -26,7 +28,8 @@ pub struct Tray<'a> {
     position: Position,
     window: xcb::Window,
     children: Vec<xcb::Window>,
-    timestamp: xcb::Timestamp
+    timestamp: xcb::Timestamp,
+    finishing: bool
 }
 
 impl<'a> Tray<'a> {
@@ -45,7 +48,8 @@ impl<'a> Tray<'a> {
             position: position,
             window: conn.generate_id(),
             children: vec![],
-            timestamp: 0
+            timestamp: 0,
+            finishing: false
         }
     }
 
@@ -168,7 +172,8 @@ impl<'a> Tray<'a> {
         self.conn.flush();
     }
 
-    pub fn cleanup(&mut self) {
+    pub fn finish(&mut self) {
+        self.finishing = true;
         let setup = self.conn.get_setup();
         let screen = setup.roots().nth(self.screen).unwrap();
         let root = screen.root();
@@ -180,21 +185,62 @@ impl<'a> Tray<'a> {
         }
         xcb::destroy_window(self.conn, self.window);
         self.conn.flush();
+    }
+
+    pub fn handle_event(&mut self, event: xcb::GenericEvent) -> Option<i32> {
+        if self.finishing {
+            self.handle_event_finishing(event)
+        }
+        else {
+            self.handle_event_normal(event)
+        }
+    }
 
-        // wait for all children to finish reparenting or destroyed
-        loop {
-            let event = self.conn.wait_for_event().unwrap();
-            if event.response_type() == xcb::REPARENT_NOTIFY {
+    fn handle_event_normal(&mut self, event: xcb::GenericEvent) -> Option<i32> {
+        match event.response_type() {
+            xcb::PROPERTY_NOTIFY if self.timestamp == 0 => {
+                let event: &xcb::PropertyNotifyEvent = xcb::cast_event(&event);
+                if !self.take_selection(event.time()) {
+                    println!("Could not take ownership of tray selection. Maybe another tray is also running?");
+                    return Some(::EXIT_FAILED_SELECT)
+                }
+            },
+            CLIENT_MESSAGE => {
+                let event: &xcb::ClientMessageEvent = xcb::cast_event(&event);
+                let data = event.data().data32();
+                let window = data[2];
+                self.adopt(window);
+            },
+            xcb::DESTROY_NOTIFY => {
+                let event: &xcb::DestroyNotifyEvent = xcb::cast_event(&event);
+                self.forget(event.window());
+            },
+            xcb::CONFIGURE_NOTIFY => {
+                let event: &xcb::ConfigureNotifyEvent = xcb::cast_event(&event);
+                self.force_size(event.window(), Some((event.width(), event.height())));
+            },
+            _ => {}
+        }
+        None
+    }
+
+    fn handle_event_finishing(&mut self, event: xcb::GenericEvent) -> Option<i32> {
+        match event.response_type() {
+            xcb::REPARENT_NOTIFY => {
                 let event: &xcb::ReparentNotifyEvent = xcb::cast_event(&event);
                 self.children.retain(|child| *child != event.window());
-            }
-            if event.response_type() == xcb::DESTROY_NOTIFY {
+            },
+            xcb::DESTROY_NOTIFY => {
                 let event: &xcb::DestroyNotifyEvent = xcb::cast_event(&event);
                 self.children.retain(|child| *child != event.window());
-            }
-            if self.children.is_empty() {
-                break;
-            }
+            },
+            _ => {}
+        }
+        if self.children.is_empty() {
+            Some(0)
+        }
+        else {
+            None
         }
     }
 }