oxwm

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

Added blocks... lol

Commit
d5b349987daf8bfe52a638a905be493c0e04bcd9
Parent
50d8817
Author
tonybtw <tonybtw@tonybtw.com>
Date
2025-10-04 05:06:49

Diff

diff --git a/Cargo.lock b/Cargo.lock
index c241f04..29e52c0 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2,18 +2,74 @@
 # It is not intended for manual editing.
 version = 4
 
+[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
 [[package]]
 name = "anyhow"
 version = "1.0.99"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
 
+[[package]]
+name = "autocfg"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
+
 [[package]]
 name = "bitflags"
 version = "2.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394"
 
+[[package]]
+name = "bumpalo"
+version = "3.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
+
+[[package]]
+name = "cc"
+version = "1.2.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1d05d92f4b1fd76aad469d46cdd858ca761576082cd37df81416691e50199fb"
+dependencies = [
+ "find-msvc-tools",
+ "shlex",
+]
+
+[[package]]
+name = "cfg-if"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
+
+[[package]]
+name = "chrono"
+version = "0.4.42"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
+dependencies = [
+ "iana-time-zone",
+ "js-sys",
+ "num-traits",
+ "wasm-bindgen",
+ "windows-link",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
+
 [[package]]
 name = "errno"
 version = "0.3.14"
@@ -24,6 +80,12 @@ dependencies = [
  "windows-sys",
 ]
 
+[[package]]
+name = "find-msvc-tools"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0399f9d26e5191ce32c498bebd31e7a3ceabc2745f0ac54af3f335126c3f24b3"
+
 [[package]]
 name = "gethostname"
 version = "1.0.2"
@@ -34,6 +96,40 @@ dependencies = [
  "windows-targets",
 ]
 
+[[package]]
+name = "iana-time-zone"
+version = "0.1.64"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "log",
+ "wasm-bindgen",
+ "windows-core",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
+dependencies = [
+ "cc",
+]
+
+[[package]]
+name = "js-sys"
+version = "0.3.81"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305"
+dependencies = [
+ "once_cell",
+ "wasm-bindgen",
+]
+
 [[package]]
 name = "libc"
 version = "0.2.175"
@@ -46,11 +142,33 @@ version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
 
+[[package]]
+name = "log"
+version = "0.4.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
+
+[[package]]
+name = "num-traits"
+version = "0.2.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.21.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
+
 [[package]]
 name = "oxwm"
 version = "0.1.0"
 dependencies = [
  "anyhow",
+ "chrono",
  "x11",
  "x11rb",
 ]
@@ -61,6 +179,24 @@ version = "0.3.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
 
+[[package]]
+name = "proc-macro2"
+version = "1.0.101"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ce25767e7b499d1b604768e7cde645d14cc8584231ea6b295e9c9eb22c02e1d1"
+dependencies = [
+ "proc-macro2",
+]
+
 [[package]]
 name = "rustix"
 version = "1.1.2"
@@ -74,12 +210,153 @@ dependencies = [
  "windows-sys",
 ]
 
+[[package]]
+name = "rustversion"
+version = "1.0.22"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
+
+[[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
+name = "syn"
+version = "2.0.106"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d"
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.104"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+ "rustversion",
+ "wasm-bindgen-macro",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.104"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19"
+dependencies = [
+ "bumpalo",
+ "log",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.104"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.104"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.104"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "windows-core"
+version = "0.62.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6844ee5416b285084d3d3fffd743b925a6c9385455f64f6d4fa3031c4c2749a9"
+dependencies = [
+ "windows-implement",
+ "windows-interface",
+ "windows-link",
+ "windows-result",
+ "windows-strings",
+]
+
+[[package]]
+name = "windows-implement"
+version = "0.60.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "edb307e42a74fb6de9bf3a02d9712678b22399c87e6fa869d6dfcd8c1b7754e0"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "windows-interface"
+version = "0.59.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0abd1ddbc6964ac14db11c7213d6532ef34bd9aa042c2e5935f59d7908b46a5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "windows-link"
 version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65"
 
+[[package]]
+name = "windows-result"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7084dcc306f89883455a206237404d3eaf961e5bd7e0f312f7c91f57eb44167f"
+dependencies = [
+ "windows-link",
+]
+
+[[package]]
+name = "windows-strings"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7218c655a553b0bed4426cf54b20d7ba363ef543b52d515b3e48d7fd55318dda"
+dependencies = [
+ "windows-link",
+]
+
 [[package]]
 name = "windows-sys"
 version = "0.61.0"
diff --git a/Cargo.toml b/Cargo.toml
index 7d6e1be..9bcfaaf 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,4 +7,4 @@ edition = "2024"
 x11 = { version = "2.21", features = ["xlib", "xft"] }
 x11rb = "0.13"
 anyhow = "1"
-
+chrono = "0.4"
diff --git a/src/bar/bar.rs b/src/bar/bar.rs
index 4de417b..7c022c6 100644
--- a/src/bar/bar.rs
+++ b/src/bar/bar.rs
@@ -1,6 +1,11 @@
+use super::blocks::{Block, Clock, Sep, Uname};
 use super::font::{Font, FontDraw};
-use crate::config::{FONT, SCHEME_NORMAL, SCHEME_OCCUPIED, SCHEME_SELECTED, TAGS};
+use crate::config::{
+    CLOCK_COLOR, CLOCK_FORMAT, FONT, SCHEME_NORMAL, SCHEME_OCCUPIED, SCHEME_SELECTED, SEP_COLOR,
+    SEPARATOR, TAGS, UNAME_COLOR, UNAME_PREFIX,
+};
 use anyhow::Result;
+use std::time::Instant;
 use x11rb::COPY_DEPTH_FROM_PARENT;
 use x11rb::connection::Connection;
 use x11rb::protocol::xproto::*;
@@ -18,6 +23,10 @@ pub struct Bar {
 
     tag_widths: Vec<u16>,
     needs_redraw: bool,
+
+    blocks: Vec<Box<dyn Block>>,
+    block_last_updates: Vec<Instant>,
+    status_text: String,
 }
 
 impl Bar {
@@ -78,6 +87,14 @@ impl Bar {
             })
             .collect();
 
+        let blocks: Vec<Box<dyn Block>> = vec![
+            Box::new(Uname::new(UNAME_PREFIX, UNAME_COLOR)),
+            Box::new(Sep::new(SEPARATOR, SEP_COLOR)),
+            Box::new(Clock::new(CLOCK_FORMAT, CLOCK_COLOR)),
+        ];
+
+        let block_last_updates = vec![Instant::now(); blocks.len()];
+
         Ok(Bar {
             window,
             width,
@@ -88,6 +105,9 @@ impl Bar {
             display,
             tag_widths,
             needs_redraw: true,
+            blocks,
+            block_last_updates,
+            status_text: String::new(),
         })
     }
 
@@ -103,6 +123,35 @@ impl Bar {
         self.needs_redraw = true;
     }
 
+    pub fn update_blocks(&mut self) -> Result<()> {
+        let now = Instant::now();
+        let mut changed = false;
+
+        for (i, block) in self.blocks.iter_mut().enumerate() {
+            let elapsed = now.duration_since(self.block_last_updates[i]);
+
+            if elapsed >= block.interval() {
+                if let Ok(_) = block.content() {
+                    self.block_last_updates[i] = now;
+                    changed = true;
+                }
+            }
+        }
+
+        if changed {
+            let mut parts = Vec::new();
+            for block in &mut self.blocks {
+                if let Ok(text) = block.content() {
+                    parts.push(text);
+                }
+            }
+            self.status_text = parts.join("");
+            self.needs_redraw = true;
+        }
+
+        Ok(())
+    }
+
     pub fn draw(
         &mut self,
         connection: &RustConnection,
@@ -182,6 +231,25 @@ impl Bar {
 
             x_position += tag_width as i16;
         }
+
+        if !self.status_text.is_empty() {
+            let padding = 10;
+            let mut x_position = self.width as i16 - padding;
+
+            for block in self.blocks.iter_mut().rev() {
+                if let Ok(text) = block.content() {
+                    let text_width = self.font.text_width(&text);
+                    x_position -= text_width as i16;
+
+                    let top_padding = 4;
+                    let text_y = top_padding + self.font.ascent();
+
+                    self.font_draw
+                        .draw_text(&self.font, block.color(), x_position, text_y, &text);
+                }
+            }
+        }
+
         connection.flush()?;
 
         unsafe {
@@ -204,4 +272,7 @@ impl Bar {
         }
         None
     }
+    pub fn needs_redraw(&self) -> bool {
+        self.needs_redraw
+    }
 }
diff --git a/src/bar/blocks/clock.rs b/src/bar/blocks/clock.rs
new file mode 100644
index 0000000..0a7f666
--- /dev/null
+++ b/src/bar/blocks/clock.rs
@@ -0,0 +1,30 @@
+use super::Block;
+use anyhow::Result;
+use chrono::Local;
+use std::time::Duration;
+
+pub struct Clock {
+    format: &'static str,
+    color: u32,
+}
+
+impl Clock {
+    pub fn new(format: &'static str, color: u32) -> Self {
+        Self { format, color }
+    }
+}
+
+impl Block for Clock {
+    fn content(&mut self) -> Result<String> {
+        let now = Local::now();
+        Ok(now.format(self.format).to_string())
+    }
+
+    fn interval(&self) -> Duration {
+        Duration::from_secs(1)
+    }
+
+    fn color(&self) -> u32 {
+        self.color
+    }
+}
diff --git a/src/bar/blocks/mod.rs b/src/bar/blocks/mod.rs
new file mode 100644
index 0000000..a36c343
--- /dev/null
+++ b/src/bar/blocks/mod.rs
@@ -0,0 +1,20 @@
+use anyhow::Result;
+use std::time::Duration;
+
+pub mod clock;
+pub mod sep;
+pub mod uname;
+
+pub use clock::Clock;
+pub use sep::Sep;
+pub use uname::Uname;
+
+pub trait Block {
+    fn content(&mut self) -> Result<String>;
+    fn interval(&self) -> Duration;
+    fn color(&self) -> u32;
+
+    fn on_click(&mut self) -> Result<()> {
+        Ok(())
+    }
+}
diff --git a/src/bar/blocks/sep.rs b/src/bar/blocks/sep.rs
new file mode 100644
index 0000000..07f1c7a
--- /dev/null
+++ b/src/bar/blocks/sep.rs
@@ -0,0 +1,28 @@
+use super::Block;
+use anyhow::Result;
+use std::time::Duration;
+
+pub struct Sep {
+    text: &'static str,
+    color: u32,
+}
+
+impl Sep {
+    pub fn new(text: &'static str, color: u32) -> Self {
+        Self { text, color }
+    }
+}
+
+impl Block for Sep {
+    fn content(&mut self) -> Result<String> {
+        Ok(self.text.to_string())
+    }
+
+    fn interval(&self) -> Duration {
+        Duration::from_secs(u64::MAX)
+    }
+
+    fn color(&self) -> u32 {
+        self.color
+    }
+}
diff --git a/src/bar/blocks/uname.rs b/src/bar/blocks/uname.rs
new file mode 100644
index 0000000..5a0bc7e
--- /dev/null
+++ b/src/bar/blocks/uname.rs
@@ -0,0 +1,38 @@
+use super::Block;
+use anyhow::Result;
+use std::process::Command;
+use std::time::Duration;
+
+pub struct Uname {
+    cached_version: String,
+    prefix: &'static str,
+    color: u32,
+}
+
+impl Uname {
+    pub fn new(prefix: &'static str, color: u32) -> Self {
+        Self {
+            cached_version: String::new(),
+            prefix,
+            color,
+        }
+    }
+}
+
+impl Block for Uname {
+    fn content(&mut self) -> Result<String> {
+        if self.cached_version.is_empty() {
+            let output = Command::new("uname").arg("-r").output()?;
+            self.cached_version = String::from_utf8_lossy(&output.stdout).trim().to_string();
+        }
+        Ok(format!("{}{}", self.prefix, self.cached_version))
+    }
+
+    fn interval(&self) -> Duration {
+        Duration::from_secs(u64::MAX)
+    }
+
+    fn color(&self) -> u32 {
+        self.color
+    }
+}
diff --git a/src/bar/mod.rs b/src/bar/mod.rs
index a41bd9b..c3f1d80 100644
--- a/src/bar/mod.rs
+++ b/src/bar/mod.rs
@@ -1,4 +1,5 @@
 mod bar;
+mod blocks;
 mod font;
 // mod widgets;  // TODO: implement later
 
diff --git a/src/config.rs b/src/config.rs
index 38ad5d9..e22ec98 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -24,8 +24,12 @@ pub const MODKEY: KeyButMask = KeyButMask::MOD1;
 const GRAY_DARK: u32 = 0x222222;
 const GRAY_MID: u32 = 0x444444;
 const GRAY_LIGHT: u32 = 0xbbbbbb;
-const CYAN: u32 = 0x6dade3;
+const CYAN: u32 = 0x0db9d7;
 const MAGENTA: u32 = 0xad8ee6;
+const RED: u32 = 0xf7768e;
+const GREEN: u32 = 0x9ece6a;
+const BLUE: u32 = 0x7aa2f7;
+const YELLOW: u32 = 0xe0af68;
 
 pub struct ColorScheme {
     pub foreground: u32,
@@ -103,4 +107,14 @@ pub const KEYBINDINGS: &[Key] = &[
     Key::new(&[MODKEY, SHIFT], keycodes::KEY_9, KeyAction::MoveToTag, Arg::Int(8)),
 ];
 
+// ========================================
+// STATUS BAR BLOCKS
+// ========================================
+pub const CLOCK_FORMAT: &str = " 󰸘 %a, %b %d - %-I:%M %P"; // "Fri, Oct 03 - 7:58 pm"
+pub const SEPARATOR: &str = " | ";
+pub const UNAME_COLOR: u32 = RED;
+pub const UNAME_PREFIX: &str = "  ";
+pub const SEP_COLOR: u32 = GRAY_LIGHT;
+pub const CLOCK_COLOR: u32 = CYAN;
+
 const SHIFT: KeyButMask = KeyButMask::SHIFT;
diff --git a/src/window_manager.rs b/src/window_manager.rs
index 7a59360..672dace 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::Layout;
 use crate::layout::tiling::TilingLayout;
+use crate::layout::Layout;
 use anyhow::Result;
 
 use x11rb::connection::Connection;
-use x11rb::protocol::Event;
 use x11rb::protocol::xproto::*;
+use x11rb::protocol::Event;
 use x11rb::rust_connection::RustConnection;
 
 pub type TagMask = u32;
@@ -70,11 +70,33 @@ impl WindowManager {
         self.update_bar()?;
 
         loop {
-            let event = self.connection.wait_for_event()?;
-            self.handle_event(event)?;
+            self.bar.update_blocks()?;
+
+            if let Ok(Some(event)) = self.connection.poll_for_event() {
+                self.handle_event(event)?;
+            }
+
+            if self.bar.needs_redraw() {
+                self.update_bar()?;
+            }
+
+            std::thread::sleep(std::time::Duration::from_millis(10));
         }
     }
 
+    // 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() {