diff options
author | tcmal <me@aria.rip> | 2024-06-03 17:06:15 +0100 |
---|---|---|
committer | tcmal <me@aria.rip> | 2024-06-03 17:06:15 +0100 |
commit | dc8094726026c5b56b5600f95da8475561b1073d (patch) | |
tree | b850c5076151feb6d3610a4b66087423cd3882e6 /src/main.rs |
initial commit: basic xorg initialisation
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 103 |
1 files changed, 103 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..ea42009 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,103 @@ +use atoms::InternedAtoms; +use clients::ClientList; +use thiserror::Error; +use xcb::{ + x::{self, ChangeWindowAttributes, Screen, Window}, + Connection, Extension, +}; + +mod atoms; +mod clients; + +type Result<T, E = Error> = std::result::Result<T, E>; + +#[derive(Debug, Error)] +pub enum Error { + #[error("xcb returned screen that doesn't exist")] + NoSuchScreen, + + #[error("other wm is running")] + OtherWMRunning, + + #[error("connection error: {0}")] + ConnectionError(#[from] xcb::ConnError), + + #[error("generic xcb error: {0}")] + XCBError(#[from] xcb::Error), +} + +fn main() -> Result<()> { + // todo: cli stuff + let display_name = ":1"; + + cleanup_process_children(); + + let (conn, screen_num) = + Connection::connect_with_extensions(Some(display_name), &[], &[Extension::Xinerama])?; + + let mut wm = WM::new(&conn, screen_num)?; + wm.event_loop()?; + + Ok(()) +} + +struct WM<'a> { + conn: &'a Connection, + screen_num: i32, + + root: Window, + clients: ClientList, + atoms: InternedAtoms, +} + +impl WM<'_> { + fn new<'a>(conn: &'a Connection, screen_num: i32) -> Result<WM<'a>> { + // Fetch root window + let setup = conn.get_setup(); + let screen = setup + .roots() + .nth(screen_num as usize) + .ok_or(Error::NoSuchScreen)?; + + // Check no other WM is running + let cookie = conn.send_request_checked(&ChangeWindowAttributes { + window: screen.root(), + value_list: &[ + x::Cw::BackPixel(screen.white_pixel()), + x::Cw::EventMask(x::EventMask::SUBSTRUCTURE_REDIRECT), + ], + }); + + conn.check_request(cookie) + .map_err(|_| Error::OtherWMRunning)?; + + Ok(WM { + atoms: InternedAtoms::new_with(conn)?, + clients: Default::default(), + conn, + screen_num, + root: screen.root(), + }) + } + + fn event_loop(&mut self) -> Result<()> { + self.update_geometry()?; + + Ok(()) + } +} +fn cleanup_process_children() { + // todo: dont transform children into zombies when they terminate + // todo: cleanup zombies +} + +impl<'a> std::fmt::Debug for WM<'a> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("WM") + .field("screen_num", &self.screen_num) + .field("root", &self.root) + .field("clients", &self.clients) + .field("atoms", &self.atoms) + .finish() + } +} |