oxwm

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

Added hot reload functionality, and it works.'

Commit
6f540a5d646224005f531ba137f841afd9c8da24
Parent
06c6741
Author
tonybtw <tonybtw@tonybtw.com>
Date
2025-10-04 07:17:05

Diff

diff --git a/src/config.rs b/src/config.rs
index 90905fa..2f8e292 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -84,6 +84,7 @@ pub const KEYBINDINGS: &[Key] = &[
     Key::new(&[MODKEY],        keycodes::D,      KeyAction::Spawn,      Arg::Array(DMENU_CMD)),
     Key::new(&[MODKEY],        keycodes::Q,      KeyAction::KillClient, Arg::None),
     Key::new(&[MODKEY, SHIFT], keycodes::Q,      KeyAction::Quit,       Arg::None),
+    Key::new(&[MODKEY, SHIFT], keycodes::R,      KeyAction::Restart,    Arg::None),
     Key::new(&[MODKEY],        keycodes::J,      KeyAction::FocusStack, Arg::Int(-1)),
     Key::new(&[MODKEY],        keycodes::K,      KeyAction::FocusStack, Arg::Int(1)),
     
@@ -149,3 +150,4 @@ pub const STATUS_BLOCKS: &[BlockConfig] = &[
 ];
 
 const SHIFT: KeyButMask = KeyButMask::SHIFT;
+pub const WM_BINARY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/target/release/oxwm");
diff --git a/src/keyboard/handlers.rs b/src/keyboard/handlers.rs
index 294c724..b9deb25 100644
--- a/src/keyboard/handlers.rs
+++ b/src/keyboard/handlers.rs
@@ -9,6 +9,7 @@ pub enum KeyAction {
     KillClient,
     FocusStack,
     Quit,
+    Restart,
     ViewTag,
     MoveToTag,
     None,
diff --git a/src/keyboard/keycodes.rs b/src/keyboard/keycodes.rs
index 3b57218..a01fd0f 100644
--- a/src/keyboard/keycodes.rs
+++ b/src/keyboard/keycodes.rs
@@ -21,6 +21,7 @@ pub const F: u8 = 41;
 pub const J: u8 = 44;
 pub const K: u8 = 45;
 pub const L: u8 = 46;
+pub const R: u8 = 27;
 
 pub const KEY_1: u8 = 10;
 pub const KEY_2: u8 = 11;
diff --git a/src/main.rs b/src/main.rs
index 2b0cfa7..121bf64 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -6,6 +6,19 @@ mod layout;
 mod window_manager;
 
 fn main() -> Result<()> {
-    let mut window_manager = window_manager::WindowManager::new()?;
-    return window_manager.run();
+    loop {
+        let mut window_manager = window_manager::WindowManager::new()?;
+        let should_restart = window_manager.run()?;
+
+        if !should_restart {
+            break;
+        }
+
+        use std::os::unix::process::CommandExt;
+        let err = std::process::Command::new(config::WM_BINARY).exec();
+        eprintln!("Failed to restart: {}", err);
+        break;
+    }
+
+    Ok(())
 }
diff --git a/src/window_manager.rs b/src/window_manager.rs
index 672dace..3d4f08a 100644
--- a/src/window_manager.rs
+++ b/src/window_manager.rs
@@ -1,13 +1,13 @@
 use crate::bar::Bar;
 use crate::config::{BORDER_FOCUSED, BORDER_UNFOCUSED, BORDER_WIDTH, TAG_COUNT};
 use crate::keyboard::{self, Arg, KeyAction};
-use crate::layout::tiling::TilingLayout;
 use crate::layout::Layout;
+use crate::layout::tiling::TilingLayout;
 use anyhow::Result;
 
 use x11rb::connection::Connection;
-use x11rb::protocol::xproto::*;
 use x11rb::protocol::Event;
+use x11rb::protocol::xproto::*;
 use x11rb::rust_connection::RustConnection;
 
 pub type TagMask = u32;
@@ -48,7 +48,7 @@ impl WindowManager {
 
         let bar = Bar::new(&connection, &screen, screen_number)?;
 
-        return Ok(Self {
+        let mut window_manger = Self {
             connection,
             screen_number,
             root,
@@ -59,21 +59,46 @@ impl WindowManager {
             window_tags: std::collections::HashMap::new(),
             selected_tags: tag_mask(0),
             bar,
-        });
+        };
+
+        window_manger.scan_existing_windows()?;
+
+        Ok(window_manger)
+    }
+
+    fn scan_existing_windows(&mut self) -> Result<()> {
+        let tree = self.connection.query_tree(self.root)?.reply()?;
+
+        for &window in &tree.children {
+            if let Ok(attrs) = self.connection.get_window_attributes(window)?.reply() {
+                if window != self.bar.window()
+                    && attrs.map_state == MapState::VIEWABLE
+                    && !attrs.override_redirect
+                {
+                    self.windows.push(window);
+                    self.window_tags.insert(window, self.selected_tags);
+                }
+            }
+        }
+        if let Some(&first) = self.windows.first() {
+            self.set_focus(Some(first))?;
+        }
+        Ok(())
     }
 
-    pub fn run(&mut self) -> Result<()> {
+    pub fn run(&mut self) -> Result<bool> {
         println!("oxwm started on display {}", self.screen_number);
 
         keyboard::setup_keybinds(&self.connection, self.root)?;
-
         self.update_bar()?;
 
         loop {
             self.bar.update_blocks()?;
 
             if let Ok(Some(event)) = self.connection.poll_for_event() {
-                self.handle_event(event)?;
+                if let Some(should_restart) = self.handle_event(event)? {
+                    return Ok(should_restart);
+                }
             }
 
             if self.bar.needs_redraw() {
@@ -84,19 +109,6 @@ impl WindowManager {
         }
     }
 
-    // pub fn run(&mut self) -> Result<()> {
-    //     println!("oxwm started on display {}", self.screen_number);
-    //
-    //     keyboard::setup_keybinds(&self.connection, self.root)?;
-    //
-    //     self.update_bar()?;
-    //
-    //     loop {
-    //         let event = self.connection.wait_for_event()?;
-    //         self.handle_event(event)?;
-    //     }
-    // }
-
     fn update_bar(&mut self) -> Result<()> {
         let mut occupied_tags: TagMask = 0;
         for &tags in self.window_tags.values() {
@@ -139,8 +151,8 @@ impl WindowManager {
                     self.cycle_focus(*direction)?;
                 }
             }
-            KeyAction::Quit => {
-                std::process::exit(0);
+            KeyAction::Quit | KeyAction::Restart => {
+                //no-op
             }
             KeyAction::ViewTag => {
                 if let Arg::Int(tag_index) = arg {
@@ -280,7 +292,7 @@ impl WindowManager {
         Ok(())
     }
 
-    fn handle_event(&mut self, event: Event) -> Result<()> {
+    fn handle_event(&mut self, event: Event) -> Result<Option<bool>> {
         match event {
             Event::MapRequest(event) => {
                 self.connection.map_window(event.window)?;
@@ -302,7 +314,12 @@ impl WindowManager {
             }
             Event::KeyPress(event) => {
                 let (action, arg) = keyboard::handle_key_press(event)?;
-                self.handle_key_action(action, arg)?;
+
+                match action {
+                    KeyAction::Quit => return Ok(Some(false)),
+                    KeyAction::Restart => return Ok(Some(true)),
+                    _ => self.handle_key_action(action, arg)?,
+                }
             }
             Event::ButtonPress(event) => {
                 if event.event == self.bar.window() {
@@ -319,9 +336,8 @@ impl WindowManager {
             }
             _ => {}
         }
-        Ok(())
+        Ok(None)
     }
-
     fn apply_layout(&self) -> Result<()> {
         let screen_width = self.screen.width_in_pixels as u32;
         let screen_height = self.screen.height_in_pixels as u32;