gardesk/gar / 32aaf43

Browse files

Handle dock/desktop windows - don't tile status bars

Authored by espadonne
SHA
32aaf43acd52e5b8a719e3940ac74b7b40053b9e
Parents
ba13c16
Tree
b3552ce

2 changed files

StatusFile+-
M gar/src/x11/connection.rs 39 0
M gar/src/x11/events.rs 8 0
gar/src/x11/connection.rsmodified
@@ -50,6 +50,8 @@ pub struct Connection {
50
     pub net_wm_window_type_toolbar: Atom,
50
     pub net_wm_window_type_toolbar: Atom,
51
     pub net_wm_window_type_splash: Atom,
51
     pub net_wm_window_type_splash: Atom,
52
     pub net_wm_window_type_notification: Atom,
52
     pub net_wm_window_type_notification: Atom,
53
+    pub net_wm_window_type_dock: Atom,
54
+    pub net_wm_window_type_desktop: Atom,
53
     // EWMH atoms for window state
55
     // EWMH atoms for window state
54
     pub net_wm_state: Atom,
56
     pub net_wm_state: Atom,
55
     pub net_wm_state_modal: Atom,
57
     pub net_wm_state_modal: Atom,
@@ -99,6 +101,8 @@ impl Connection {
99
         let net_wm_window_type_toolbar = conn.intern_atom(false, b"_NET_WM_WINDOW_TYPE_TOOLBAR")?.reply()?.atom;
101
         let net_wm_window_type_toolbar = conn.intern_atom(false, b"_NET_WM_WINDOW_TYPE_TOOLBAR")?.reply()?.atom;
100
         let net_wm_window_type_splash = conn.intern_atom(false, b"_NET_WM_WINDOW_TYPE_SPLASH")?.reply()?.atom;
102
         let net_wm_window_type_splash = conn.intern_atom(false, b"_NET_WM_WINDOW_TYPE_SPLASH")?.reply()?.atom;
101
         let net_wm_window_type_notification = conn.intern_atom(false, b"_NET_WM_WINDOW_TYPE_NOTIFICATION")?.reply()?.atom;
103
         let net_wm_window_type_notification = conn.intern_atom(false, b"_NET_WM_WINDOW_TYPE_NOTIFICATION")?.reply()?.atom;
104
+        let net_wm_window_type_dock = conn.intern_atom(false, b"_NET_WM_WINDOW_TYPE_DOCK")?.reply()?.atom;
105
+        let net_wm_window_type_desktop = conn.intern_atom(false, b"_NET_WM_WINDOW_TYPE_DESKTOP")?.reply()?.atom;
102
 
106
 
103
         // Intern EWMH atoms for window state
107
         // Intern EWMH atoms for window state
104
         let net_wm_state = conn.intern_atom(false, b"_NET_WM_STATE")?.reply()?.atom;
108
         let net_wm_state = conn.intern_atom(false, b"_NET_WM_STATE")?.reply()?.atom;
@@ -145,6 +149,8 @@ impl Connection {
145
             net_wm_window_type_toolbar,
149
             net_wm_window_type_toolbar,
146
             net_wm_window_type_splash,
150
             net_wm_window_type_splash,
147
             net_wm_window_type_notification,
151
             net_wm_window_type_notification,
152
+            net_wm_window_type_dock,
153
+            net_wm_window_type_desktop,
148
             net_wm_state,
154
             net_wm_state,
149
             net_wm_state_modal,
155
             net_wm_state_modal,
150
             net_wm_state_fullscreen,
156
             net_wm_state_fullscreen,
@@ -558,6 +564,39 @@ impl Connection {
558
         false
564
         false
559
     }
565
     }
560
 
566
 
567
+    /// Check if a window should be ignored entirely (not managed by the WM).
568
+    /// Returns true for dock windows (status bars like polybar) and desktop windows.
569
+    pub fn should_ignore(&self, window: Window) -> bool {
570
+        // Check _NET_WM_WINDOW_TYPE for dock/desktop types
571
+        if let Ok(cookie) = self.conn.get_property(
572
+            false,
573
+            window,
574
+            self.net_wm_window_type,
575
+            AtomEnum::ATOM,
576
+            0,
577
+            32,
578
+        ) {
579
+            if let Ok(reply) = cookie.reply() {
580
+                if reply.type_ == u32::from(AtomEnum::ATOM) && reply.format == 32 {
581
+                    let ignore_types = [
582
+                        self.net_wm_window_type_dock,
583
+                        self.net_wm_window_type_desktop,
584
+                    ];
585
+
586
+                    for chunk in reply.value.chunks_exact(4) {
587
+                        let atom = u32::from_ne_bytes([chunk[0], chunk[1], chunk[2], chunk[3]]);
588
+                        if ignore_types.contains(&atom) {
589
+                            tracing::debug!("Window {} is dock/desktop type, ignoring", window);
590
+                            return true;
591
+                        }
592
+                    }
593
+                }
594
+            }
595
+        }
596
+
597
+        false
598
+    }
599
+
561
     /// Get WM_CLASS property (instance, class) for a window.
600
     /// Get WM_CLASS property (instance, class) for a window.
562
     pub fn get_wm_class(&self, window: Window) -> Option<(String, String)> {
601
     pub fn get_wm_class(&self, window: Window) -> Option<(String, String)> {
563
         let wm_class_atom = self.conn.intern_atom(false, b"WM_CLASS").ok()?.reply().ok()?.atom;
602
         let wm_class_atom = self.conn.intern_atom(false, b"WM_CLASS").ok()?.reply().ok()?.atom;
gar/src/x11/events.rsmodified
@@ -205,6 +205,14 @@ impl WindowManager {
205
         let window = event.window;
205
         let window = event.window;
206
         tracing::debug!("MapRequest for window {}", window);
206
         tracing::debug!("MapRequest for window {}", window);
207
 
207
 
208
+        // Check for dock/desktop windows (polybar, etc.) - don't manage, just map
209
+        if self.conn.should_ignore(window) {
210
+            tracing::info!("Window {} is dock/desktop, mapping without managing", window);
211
+            self.conn.map_window(window)?;
212
+            self.conn.flush()?;
213
+            return Ok(());
214
+        }
215
+
208
         // Check if we should manage this window
216
         // Check if we should manage this window
209
         if !self.should_manage(window) {
217
         if !self.should_manage(window) {
210
             // Just map it without managing
218
             // Just map it without managing