summaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
authortcmal <me@aria.rip>2024-06-03 17:06:15 +0100
committertcmal <me@aria.rip>2024-06-03 17:06:15 +0100
commitdc8094726026c5b56b5600f95da8475561b1073d (patch)
treeb850c5076151feb6d3610a4b66087423cd3882e6 /src/main.rs
initial commit: basic xorg initialisation
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs103
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()
+ }
+}