oxwm

https://git.tonybtw.com/oxwm.git git://git.tonybtw.com/oxwm.git

Fixed reloadsig, and actually persist using NET_CLIENT_INFO

Commit
2188e271b935668a9692a07bb3c43930860ce0e6
Parent
99cb352
Author
tonybtw <tonybtw@tonybtw.com>
Date
2025-10-05 05:39:05

Diff

diff --git a/src/window_manager.rs b/src/window_manager.rs
index b6216e6..a9f276d 100644
--- a/src/window_manager.rs
+++ b/src/window_manager.rs
@@ -71,39 +71,32 @@ impl WindowManager {
 
         println!("=== Scanning existing windows ===");
         println!("Total children: {}", tree.children.len());
-        println!("Current selected_tags: {:b}", self.selected_tags);
+
+        let net_client_info = self
+            .connection
+            .intern_atom(false, b"_NET_CLIENT_INFO")?
+            .reply()?
+            .atom;
 
         for &window in &tree.children {
             if window == self.bar.window() {
-                println!("Skipping bar window: {}", window);
                 continue;
             }
 
             let attrs = match self.connection.get_window_attributes(window)?.reply() {
                 Ok(attrs) => attrs,
-                Err(_) => {
-                    println!("Failed to get attributes for window: {}", window);
-                    continue;
-                }
+                Err(_) => continue,
             };
 
-            println!(
-                "Window {}: override_redirect={}, map_state={:?}",
-                window, attrs.override_redirect, attrs.map_state
-            );
-
             if attrs.override_redirect {
-                println!("  -> Skipped (override_redirect)");
                 continue;
             }
 
             if attrs.map_state == MapState::VIEWABLE {
-                println!(
-                    "  -> Managing VIEWABLE window, tagging with {:b}",
-                    self.selected_tags
-                );
+                let tag = self.get_saved_tag(window, net_client_info)?;
+                println!("Managing VIEWABLE window: {} with tag {:b}", window, tag);
                 self.windows.push(window);
-                self.window_tags.insert(window, self.selected_tags);
+                self.window_tags.insert(window, tag);
                 continue;
             }
 
@@ -118,17 +111,11 @@ impl WindowManager {
                 };
 
                 if has_wm_class {
-                    println!(
-                        "  -> Managing UNMAPPED window (has WM_CLASS), tagging with {:b}",
-                        self.selected_tags
-                    );
+                    let tag = self.get_saved_tag(window, net_client_info)?;
+                    println!("Managing UNMAPPED window: {} with tag {:b}", window, tag);
                     self.windows.push(window);
-                    self.window_tags.insert(window, self.selected_tags);
-                } else {
-                    println!("  -> Skipped UNMAPPED (no WM_CLASS)");
+                    self.window_tags.insert(window, tag);
                 }
-            } else {
-                println!("  -> Skipped (map_state={:?})", attrs.map_state);
             }
         }
 
@@ -142,6 +129,53 @@ impl WindowManager {
         Ok(())
     }
 
+    fn get_saved_tag(&self, window: Window, net_client_info: Atom) -> Result<TagMask> {
+        match self
+            .connection
+            .get_property(false, window, net_client_info, AtomEnum::CARDINAL, 0, 2)?
+            .reply()
+        {
+            Ok(prop) if prop.value.len() >= 4 => {
+                let tags = u32::from_ne_bytes([
+                    prop.value[0],
+                    prop.value[1],
+                    prop.value[2],
+                    prop.value[3],
+                ]);
+                println!("  Restored tag from _NET_CLIENT_INFO: {:b}", tags);
+                return Ok(tags);
+            }
+            _ => {}
+        }
+
+        println!("  No saved tag, using current: {:b}", self.selected_tags);
+        Ok(self.selected_tags)
+    }
+
+    fn save_client_tag(&self, window: Window, tag: TagMask) -> Result<()> {
+        let net_client_info = self
+            .connection
+            .intern_atom(false, b"_NET_CLIENT_INFO")?
+            .reply()?
+            .atom;
+
+        let data = [tag, 0u32];
+        let bytes: Vec<u8> = data.iter().flat_map(|&v| v.to_ne_bytes()).collect();
+
+        self.connection.change_property(
+            PropMode::REPLACE,
+            window,
+            net_client_info,
+            AtomEnum::CARDINAL,
+            32,
+            2,
+            &bytes,
+        )?;
+
+        self.connection.flush()?;
+        Ok(())
+    }
+
     pub fn run(&mut self) -> Result<bool> {
         println!("oxwm started on display {}", self.screen_number);
 
@@ -279,6 +313,9 @@ impl WindowManager {
         if let Some(focused) = self.focused_window {
             let mask = tag_mask(tag_index);
             self.window_tags.insert(focused, mask);
+
+            let _ = self.save_client_tag(focused, mask);
+
             self.update_window_visibility()?;
             self.apply_layout()?;
             self.update_bar()?;
@@ -354,6 +391,9 @@ impl WindowManager {
                 self.connection.map_window(event.window)?;
                 self.windows.push(event.window);
                 self.window_tags.insert(event.window, self.selected_tags);
+
+                let _ = self.save_client_tag(event.window, self.selected_tags);
+
                 self.apply_layout()?;
                 self.update_bar()?;
                 self.set_focus(Some(event.window))?;