First dwm

This commit is contained in:
BitHeaven 2025-03-15 22:03:13 +05:00
parent bf2d6651de
commit f05b8d8766
3 changed files with 194 additions and 0 deletions

5
.gitignore vendored
View File

@ -20,3 +20,8 @@ Cargo.lock
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
# Added by cargo
/target

6
Cargo.toml Normal file
View File

@ -0,0 +1,6 @@
[package]
name = "rwm"
version = "0.1.0"
edition = "2021"
[dependencies]

183
src/main.rs Normal file
View File

@ -0,0 +1,183 @@
use x11rb::connection::Connection;
use x11rb::protocol::xproto::*;
use x11rb::wrapper::ConnectionExt;
use x11rb::errors::ConnectionError;
use std::collections::HashMap;
type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
#[derive(Debug, Clone)]
struct Client {
win: Window,
name: String,
floating: bool,
tags: u32,
geometry: Rectangle,
}
#[derive(Debug)]
struct Monitor {
id: usize,
clients: Vec<Client>,
layout: Layout,
// Add more monitor properties
}
#[derive(Debug)]
enum Layout {
Tiled,
Floating,
Monocle,
}
struct DwmState {
conn: XCBConnection,
screen_num: usize,
root: Window,
clients: HashMap<Window, Client>,
monitors: Vec<Monitor>,
// Add more state properties
}
impl DwmState {
fn new() -> Result<Self> {
let (conn, screen_num) = XCBConnection::connect(None)?;
let screen = &conn.setup().roots[screen_num];
Ok(Self {
conn,
screen_num,
root: screen.root,
clients: HashMap::new(),
monitors: vec![Monitor {
id: 0,
clients: vec![],
layout: Layout::Tiled,
}],
})
}
fn setup(&self) -> Result<()> {
// Set up window manager properties
self.conn.change_window_attributes(
self.root,
&ChangeWindowAttributesAux::default()
.event_mask(EventMask::SUBSTRUCTURE_REDIRECT | EventMask::SUBSTRUCTURE_NOTIFY),
)?;
self.grab_keys()?;
Ok(())
}
fn grab_keys(&self) -> Result<()> {
// Example key grab (Alt+Return)
let keysym = x11rb::keysym::XK_Return;
let modifier = ModMask::MOD1;
self.conn.grab_key(
true,
self.root,
modifier,
keysym,
GrabMode::ASYNC,
GrabMode::ASYNC,
)?;
Ok(())
}
fn handle_event(&mut self, event: x11rb::protocol::Event) -> Result<()> {
match event {
Event::MapRequest(event) => self.handle_map_request(event.window),
Event::ConfigureRequest(event) => self.handle_configure_request(event),
Event::KeyPress(event) => self.handle_key_press(event.detail, event.state),
_ => Ok(()),
}
}
fn handle_map_request(&mut self, window: Window) -> Result<()> {
// Create new client
let geometry = self.conn.get_geometry(window)?.reply()?;
let client = Client {
win: window,
name: String::new(),
floating: false,
tags: 1,
geometry: Rectangle {
x: 0,
y: 0,
width: geometry.width,
height: geometry.height,
},
};
self.clients.insert(window, client.clone());
self.monitors[0].clients.push(client);
self.conn.map_window(window)?;
self.arrange_windows()
}
fn handle_configure_request(&mut self, event: ConfigureRequestEvent) -> Result<()> {
// Handle window configuration requests
let mut values = ConfigureWindowAux::new()
.x(event.x as i32)
.y(event.y as i32)
.width(event.width)
.height(event.height);
self.conn.configure_window(event.window, &values)?;
Ok(())
}
fn handle_key_press(&mut self, keycode: u8, state: u16) -> Result<()> {
// Handle key bindings
if state == ModMask::MOD1.into() {
match keycode {
36 => self.spawn_terminal(), // Enter key
_ => (),
}
}
Ok(())
}
fn arrange_windows(&self) -> Result<()> {
// Simple tiling layout
let monitor = &self.monitors[0];
let num_clients = monitor.clients.len();
let width = 800 / num_clients as u16; // Simplified screen size
for (i, client) in monitor.clients.iter().enumerate() {
let x = (i as u16) * width;
self.conn.configure_window(
client.win,
&ConfigureWindowAux::new()
.x(x as i32)
.y(0)
.width(width)
.height(600),
)?;
}
Ok(())
}
fn spawn_terminal(&self) -> Result<()> {
// Spawn a terminal using std::process
std::process::Command::new("x-terminal-emulator")
.spawn()
.map_err(|e| Box::new(e) as Box<dyn std::error::Error>)?;
Ok(())
}
fn run(&mut self) -> Result<()> {
self.setup()?;
loop {
let event = self.conn.wait_for_event()?;
self.handle_event(event)?;
}
}
}
fn main() -> Result<()> {
let mut dwm = DwmState::new()?;
dwm.run()
}