oxwm

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

Added pertag mfacts, layouts, etc

Commit
bea7eeb63b2558d0a94a22bacf5652dd353e015f
Parent
e120f6b
Author
tonybtw <tonybtw@tonybtw.com>
Date
2026-01-11 04:29:56

Diff

diff --git a/justfile b/justfile
index e7c5f23..3befb6f 100644
--- a/justfile
+++ b/justfile
@@ -3,13 +3,13 @@ build:
 
 install: build
     cp target/release/oxwm /usr/bin/oxwm
-	cp resources/oxwm.desktop /usr/share/xsessions/oxwm.desktop
+    cp resources/oxwm.desktop /usr/share/xsessions/oxwm.desktop
     chmod +x /usr/bin/oxwm
     @echo "✓ oxwm installed to /usr/bin/oxwm"
     @echo "  Run 'oxwm --init' to create your config"
 
 checkinstall:
-	checkinstall --pkgname oxwm --exclude /root -y just install
+    checkinstall --pkgname oxwm --exclude /root -y just install
 
 uninstall:
     rm -f /usr/bin/oxwm
diff --git a/src/monitor.rs b/src/monitor.rs
index 8f55a9c..c87299c 100644
--- a/src/monitor.rs
+++ b/src/monitor.rs
@@ -6,6 +6,30 @@ use x11rb::rust_connection::RustConnection;
 
 type WmResult<T> = Result<T, WmError>;
 
+#[derive(Debug, Clone)]
+pub struct Pertag {
+    pub current_tag: usize,
+    pub previous_tag: usize,
+    pub num_masters: Vec<i32>,
+    pub master_factors: Vec<f32>,
+    pub layouts: Vec<String>,
+    pub show_bars: Vec<bool>,
+}
+
+impl Pertag {
+    pub fn new(num_tags: usize, default_num_master: i32, default_master_factor: f32, default_show_bar: bool, default_layout: &str) -> Self {
+        let len = num_tags + 1;
+        Self {
+            current_tag: 1,
+            previous_tag: 1,
+            num_masters: vec![default_num_master; len],
+            master_factors: vec![default_master_factor; len],
+            layouts: vec![default_layout.to_string(); len],
+            show_bars: vec![default_show_bar; len],
+        }
+    }
+}
+
 #[derive(Debug, Clone)]
 pub struct Monitor {
     pub layout_symbol: String,
@@ -35,6 +59,7 @@ pub struct Monitor {
     pub stack_head: Option<Window>,
     pub bar_window: Option<Window>,
     pub layout_indices: [usize; 2],
+    pub pertag: Option<Pertag>,
 }
 
 impl Monitor {
@@ -67,9 +92,20 @@ impl Monitor {
             stack_head: None,
             bar_window: None,
             layout_indices: [0, 1],
+            pertag: None,
         }
     }
 
+    pub fn init_pertag(&mut self, num_tags: usize, default_layout: &str) {
+        self.pertag = Some(Pertag::new(
+            num_tags,
+            self.num_master,
+            self.master_factor,
+            self.show_bar,
+            default_layout,
+        ));
+    }
+
     pub fn contains_point(&self, x: i32, y: i32) -> bool {
         x >= self.screen_x
             && x < self.screen_x + self.screen_width
diff --git a/src/window_manager.rs b/src/window_manager.rs
index 266a3f9..94180b4 100644
--- a/src/window_manager.rs
+++ b/src/window_manager.rs
@@ -243,7 +243,10 @@ impl WindowManager {
             )?;
         }
 
-        let monitors = detect_monitors(&connection, &screen, root)?;
+        let mut monitors = detect_monitors(&connection, &screen, root)?;
+        for monitor in monitors.iter_mut() {
+            monitor.init_pertag(config.tags.len(), "tiling");
+        }
 
         let display = unsafe { x11::xlib::XOpenDisplay(std::ptr::null()) };
         if display.is_null() {
@@ -710,6 +713,9 @@ impl WindowManager {
         if let Some(monitor) = self.monitors.get_mut(self.selected_monitor) {
             let new_mfact = (monitor.master_factor + delta).clamp(0.05, 0.95);
             monitor.master_factor = new_mfact;
+            if let Some(ref mut pertag) = monitor.pertag {
+                pertag.master_factors[pertag.current_tag] = new_mfact;
+            }
             self.apply_layout()?;
         }
         Ok(())
@@ -719,11 +725,27 @@ impl WindowManager {
         if let Some(monitor) = self.monitors.get_mut(self.selected_monitor) {
             let new_nmaster = (monitor.num_master + delta).max(0);
             monitor.num_master = new_nmaster;
+            if let Some(ref mut pertag) = monitor.pertag {
+                pertag.num_masters[pertag.current_tag] = new_nmaster;
+            }
             self.apply_layout()?;
         }
         Ok(())
     }
 
+    fn toggle_bar(&mut self) -> WmResult<()> {
+        if let Some(monitor) = self.monitors.get_mut(self.selected_monitor) {
+            monitor.show_bar = !monitor.show_bar;
+            self.show_bar = monitor.show_bar;
+            if let Some(ref mut pertag) = monitor.pertag {
+                pertag.show_bars[pertag.current_tag] = monitor.show_bar;
+            }
+        }
+        self.apply_layout()?;
+        self.update_bar()?;
+        Ok(())
+    }
+
     fn get_layout_symbol(&self) -> String {
         let layout_name = self.layout.name();
         self.config
@@ -871,6 +893,11 @@ impl WindowManager {
                     match layout_from_str(layout_name) {
                         Ok(layout) => {
                             self.layout = layout;
+                            if let Some(monitor) = self.monitors.get_mut(self.selected_monitor) {
+                                if let Some(ref mut pertag) = monitor.pertag {
+                                    pertag.layouts[pertag.current_tag] = layout_name.to_string();
+                                }
+                            }
                             if layout_name != "normie" && layout_name != "floating" {
                                 self.floating_windows.clear();
                             }
@@ -888,6 +915,11 @@ impl WindowManager {
                 match layout_from_str(next_name) {
                     Ok(layout) => {
                         self.layout = layout;
+                        if let Some(monitor) = self.monitors.get_mut(self.selected_monitor) {
+                            if let Some(ref mut pertag) = monitor.pertag {
+                                pertag.layouts[pertag.current_tag] = next_name.to_string();
+                            }
+                        }
                         if next_name != "normie" && next_name != "floating" {
                             self.floating_windows.clear();
                         }
@@ -1243,21 +1275,48 @@ impl WindowManager {
             return Ok(());
         }
 
-        let monitor = match self.monitors.get_mut(self.selected_monitor) {
-            Some(m) => m,
-            None => return Ok(()),
-        };
-
         let new_tagset = tag_mask(tag_index);
+        let mut layout_name: Option<String> = None;
+        let mut toggle_bar = false;
 
-        if new_tagset == monitor.tagset[monitor.selected_tags_index] {
-            if !self.config.tag_back_and_forth {
-                return Ok(());
+        if let Some(monitor) = self.monitors.get_mut(self.selected_monitor) {
+            if new_tagset == monitor.tagset[monitor.selected_tags_index] {
+                if !self.config.tag_back_and_forth {
+                    return Ok(());
+                }
+                monitor.tagset.swap(0, 1);
+                if let Some(ref mut pertag) = monitor.pertag {
+                    let tmp = pertag.previous_tag;
+                    pertag.previous_tag = pertag.current_tag;
+                    pertag.current_tag = tmp;
+                }
+            } else {
+                monitor.selected_tags_index ^= 1;
+                monitor.tagset[monitor.selected_tags_index] = new_tagset;
+                if let Some(ref mut pertag) = monitor.pertag {
+                    pertag.previous_tag = pertag.current_tag;
+                    pertag.current_tag = tag_index + 1;
+                }
             }
-            monitor.tagset.swap(0, 1);
-        } else {
-            monitor.selected_tags_index ^= 1;
-            monitor.tagset[monitor.selected_tags_index] = new_tagset;
+
+            if let Some(ref pertag) = monitor.pertag {
+                monitor.num_master = pertag.num_masters[pertag.current_tag];
+                monitor.master_factor = pertag.master_factors[pertag.current_tag];
+                layout_name = Some(pertag.layouts[pertag.current_tag].clone());
+                if monitor.show_bar != pertag.show_bars[pertag.current_tag] {
+                    toggle_bar = true;
+                }
+            }
+        }
+
+        if let Some(name) = layout_name {
+            if let Ok(layout) = layout_from_str(&name) {
+                self.layout = layout;
+            }
+        }
+
+        if toggle_bar {
+            self.toggle_bar()?;
         }
 
         self.save_selected_tags()?;
@@ -1273,19 +1332,50 @@ impl WindowManager {
             return Ok(());
         }
 
-        let monitor = match self.monitors.get_mut(self.selected_monitor) {
-            Some(m) => m,
-            None => return Ok(()),
-        };
+        let num_tags = self.config.tags.len();
+        let all_tags_mask = (1u32 << num_tags) - 1;
+        let mut layout_name: Option<String> = None;
+        let mut toggle_bar = false;
 
-        let mask = tag_mask(tag_index);
-        let new_tagset = monitor.tagset[monitor.selected_tags_index] ^ mask;
+        if let Some(monitor) = self.monitors.get_mut(self.selected_monitor) {
+            let mask = tag_mask(tag_index);
+            let new_tagset = monitor.tagset[monitor.selected_tags_index] ^ mask;
 
-        if new_tagset == 0 {
-            return Ok(());
+            if new_tagset == 0 {
+                return Ok(());
+            }
+
+            monitor.tagset[monitor.selected_tags_index] = new_tagset;
+
+            if let Some(ref mut pertag) = monitor.pertag {
+                if new_tagset == all_tags_mask {
+                    pertag.previous_tag = pertag.current_tag;
+                    pertag.current_tag = 0;
+                }
+
+                if pertag.current_tag > 0 && (new_tagset & (1 << (pertag.current_tag - 1))) == 0 {
+                    pertag.previous_tag = pertag.current_tag;
+                    pertag.current_tag = (new_tagset.trailing_zeros() as usize) + 1;
+                }
+
+                monitor.num_master = pertag.num_masters[pertag.current_tag];
+                monitor.master_factor = pertag.master_factors[pertag.current_tag];
+                layout_name = Some(pertag.layouts[pertag.current_tag].clone());
+                if monitor.show_bar != pertag.show_bars[pertag.current_tag] {
+                    toggle_bar = true;
+                }
+            }
         }
 
-        monitor.tagset[monitor.selected_tags_index] = new_tagset;
+        if let Some(name) = layout_name {
+            if let Ok(layout) = layout_from_str(&name) {
+                self.layout = layout;
+            }
+        }
+
+        if toggle_bar {
+            self.toggle_bar()?;
+        }
 
         self.save_selected_tags()?;
         self.focus(None)?;