Răsfoiți Sursa

Set window type as dock

Also use this as timestamp for acquiring selection
Thomas Dy 8 ani în urmă
părinte
comite
3e404157b1
4 a modificat fișierele cu 31 adăugiri și 10 ștergeri
  1. 3 1
      src/atom.rs
  2. 7 1
      src/event.rs
  3. 8 5
      src/main.rs
  4. 13 3
      src/tray.rs

+ 3 - 1
src/atom.rs

@@ -10,7 +10,9 @@ macro_rules! atoms {
 }
 
 atoms!(
-    _NET_SYSTEM_TRAY_S0
+    _NET_SYSTEM_TRAY_S0,
+    _NET_WM_WINDOW_TYPE,
+    _NET_WM_WINDOW_TYPE_DOCK
 );
 
 pub struct Atoms<'a> {

+ 7 - 1
src/event.rs

@@ -2,6 +2,7 @@ use chan;
 use xcb;
 
 pub enum Event {
+    Ready(xcb::Timestamp),
     ChildRequest(xcb::Window),
     ChildDestroyed(xcb::Window),
     ChildConfigured(xcb::Window)
@@ -10,10 +11,15 @@ pub enum Event {
 const CLIENT_MESSAGE: u8 = xcb::CLIENT_MESSAGE | 0x80;
 
 pub fn event_loop(conn: &xcb::Connection, tx: chan::Sender<Event>) {
+    let mut ready = false;
     loop {
         match conn.wait_for_event() {
             Some(event) => match event.response_type() {
-                xcb::EXPOSE => { println!("expose") },
+                xcb::PROPERTY_NOTIFY if !ready => {
+                    ready = true;
+                    let event: &xcb::PropertyNotifyEvent = xcb::cast_event(&event);
+                    tx.send(Event::Ready(event.time()));
+                },
                 CLIENT_MESSAGE => {
                     let event: &xcb::ClientMessageEvent = xcb::cast_event(&event);
                     let data = event.data().data32();

+ 8 - 5
src/main.rs

@@ -32,11 +32,6 @@ fn main() {
         };
 
         let mut tray = tray::Tray::new(&conn, &atoms, preferred as usize, 20, dir);
-        tray.create();
-        if !tray.take_selection() {
-            println!("Could not take ownership of tray selection. Maybe another tray is also running?");
-            return
-        }
 
         let (tx, rx) = chan::sync::<event::Event>(0);
         {
@@ -46,10 +41,18 @@ fn main() {
             });
         }
 
+        tray.create();
+
         loop {
             use event::Event::*;
             chan_select!(
                 rx.recv() -> event => match event.unwrap() {
+                    Ready(timestamp) => {
+                        if !tray.take_selection(timestamp) {
+                            println!("Could not take ownership of tray selection. Maybe another tray is also running?");
+                            return
+                        }
+                    },
                     ChildRequest(window) => {
                         tray.adopt(window);
                     },

+ 13 - 3
src/tray.rs

@@ -63,14 +63,24 @@ impl<'a> Tray<'a> {
             screen.root_visual(),
             &[
                 (xcb::CW_BACK_PIXEL, screen.black_pixel()),
-                (xcb::CW_EVENT_MASK, xcb::EVENT_MASK_EXPOSURE)
+                (xcb::CW_EVENT_MASK, xcb::EVENT_MASK_PROPERTY_CHANGE)
             ]
         );
+        xcb::change_property(
+            self.conn,
+            xcb::PROP_MODE_REPLACE as u8,
+            self.window,
+            self.atoms.get(atom::_NET_WM_WINDOW_TYPE),
+            xcb::ATOM_ATOM,
+            32,
+            &[self.atoms.get(atom::_NET_WM_WINDOW_TYPE_DOCK)]
+        );
+        self.conn.flush();
     }
 
-    pub fn take_selection(&self) -> bool {
+    pub fn take_selection(&mut self, timestamp: xcb::Timestamp) -> bool {
         let selection = self.atoms.get(atom::_NET_SYSTEM_TRAY_S0);
-        xcb::set_selection_owner(self.conn, self.window, selection, xcb::CURRENT_TIME);
+        xcb::set_selection_owner(self.conn, self.window, selection, timestamp);
         let owner = xcb::get_selection_owner(self.conn, selection).get_reply().unwrap().owner();
         owner == self.window
     }