From ef6f4bab8245f8f05c67c237e32113f84c082679 Mon Sep 17 00:00:00 2001 From: MCorange Date: Tue, 23 Jul 2024 14:27:31 +0300 Subject: [PATCH] :3 --- .gitignore | 1 + Cargo.lock | 349 ++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 14 ++ build.rs | 6 + src/main.rs | 19 +++ src/server/drw.rs | 103 ++++++++++++++ src/server/mod.rs | 90 ++++++++++++ 7 files changed, 582 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 build.rs create mode 100644 src/main.rs create mode 100644 src/server/drw.rs create mode 100644 src/server/mod.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..e4dace6 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,349 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anstream" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" + +[[package]] +name = "anstyle-parse" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +dependencies = [ + "anstyle", + "windows-sys", +] + +[[package]] +name = "anyhow" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" + +[[package]] +name = "clap" +version = "4.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" + +[[package]] +name = "colorchoice" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" + +[[package]] +name = "env_filter" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" +dependencies = [ + "log", + "regex", +] + +[[package]] +name = "env_logger" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b35839ba51819680ba087cd351788c9a3c476841207e0b8cee0b04722343b9" +dependencies = [ + "anstream", + "anstyle", + "env_filter", + "humantime", + "log", +] + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + +[[package]] +name = "libc" +version = "0.2.155" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "rwm" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "env_logger", + "libc", + "log", + "x11", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "syn" +version = "2.0.72" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "x11" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e" +dependencies = [ + "libc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..e451d16 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "rwm" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +anyhow = "1.0.86" +clap = { version = "4.5.9", features = ["derive"] } +env_logger = "0.11.3" +libc = "0.2.155" +log = "0.4.22" +x11 = { version = "2.21.0", features = ["xlib", "xinerama", "all"] } diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..7c68778 --- /dev/null +++ b/build.rs @@ -0,0 +1,6 @@ + + +fn main() { + println!("cargo::rustc-link-lib=x11"); + +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..2f5b103 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,19 @@ +use clap::Parser; + +mod server; + +#[derive(Parser)] +struct CliArgs {} + + +fn main() { + let _ = CliArgs::parse(); + env_logger::builder() + .filter(None, log::LevelFilter::Trace) + .init(); + + + let mut server = server::Server::new(); + + server.setup(); +} diff --git a/src/server/drw.rs b/src/server/drw.rs new file mode 100644 index 0000000..fb68fd6 --- /dev/null +++ b/src/server/drw.rs @@ -0,0 +1,103 @@ +use std::ffi::{CStr, CString}; + +use anyhow::{anyhow, bail}; +use x11::{xft::{FcPattern, XftColor, XftFont, XftFontOpenName, XftFontOpenPattern, XftNameParse}, xlib::{CapButt, Cursor, Drawable, JoinMiter, LineSolid, Window, XCreateGC, XCreatePixmap, XDefaultDepth, XSetLineAttributes, _XDisplay, GC}}; + + +#[derive(Debug)] +pub struct Drw { + w: i32, + h: i32, + display: *mut _XDisplay, + screen: i32, + drawable: Drawable, + gc: GC, + scheme: *mut Clr, + fontset: Vec, + root: Window, +} + +#[derive(Debug)] +pub struct Cur { + cursor: Cursor, +} + +type Clr = XftColor; + +#[derive(Debug)] +pub struct Fnt { + display: *mut _XDisplay, + h: i32, + xfont: *mut XftFont, + pattern: *mut FcPattern, +} + + + +impl Drw { + pub fn new(display: *mut _XDisplay, screen: i32, root: Window, w: i32, h: i32, fonts: Vec<&str>) -> anyhow::Result { + unsafe { + let mut s = Self { + display, + screen, + root, + w, + h, + drawable: Drawable::from(XCreatePixmap(display, root, w as u32, h as u32, XDefaultDepth(display, screen) as u32)), + gc: XCreateGC(display, root, 0, std::ptr::null_mut()), + fontset: Vec::new(), + scheme: std::ptr::null_mut(), + }; + XSetLineAttributes(display, s.gc, 1, LineSolid, CapButt, JoinMiter); + s.fontset = s.font_set_create(fonts)?; + Ok(s) + } + } + + fn font_set_create(&mut self, fonts: Vec<&str>) -> anyhow::Result> { + let mut set = Vec::new(); + for i in 1..=fonts.len() { + if let Ok(next) = unsafe { self.font_create(Some(fonts[fonts.len() - i]), std::ptr::null_mut()) } { + set.push(next); + } + } + Ok(set) + } + + unsafe fn font_create(&mut self, fontname: Option<&str>, fontpattern: *mut FcPattern) -> anyhow::Result { + let mut font: Fnt = std::mem::zeroed(); + let xfont: *mut XftFont; + let mut pattern: *mut FcPattern = std::ptr::null_mut(); + + if let Some(fontname) = fontname { + let font_name_c = CString::new(fontname)?.as_ptr(); + xfont = XftFontOpenName(self.display, self.screen, font_name_c); + if xfont.is_null() { + log::error!("Cannot load font from name {}", fontname); + bail!(""); + } + + pattern = XftNameParse(font_name_c); + if pattern.is_null() { + log::error!("Cannot parse font name to pattern"); + bail!(""); + } + } else if !fontpattern.is_null() { + xfont = XftFontOpenPattern(self.display, fontpattern); + if xfont.is_null() { + log::error!("Cannot load font from pattern"); + bail!(""); + } + } else { + log::error!("No font name specified"); + bail!(""); + } + + font.xfont = xfont; + font.pattern = pattern; + font.h = (*xfont).ascent + (*xfont).descent; + font.display = self.display; + Ok(font) + } + +} diff --git a/src/server/mod.rs b/src/server/mod.rs new file mode 100644 index 0000000..0706f68 --- /dev/null +++ b/src/server/mod.rs @@ -0,0 +1,90 @@ +use std::ffi::CStr; + +use libc::{setlocale, sigaction, sigemptyset, sigset_t, waitpid, LC_CTYPE, SA_NOCLDSTOP, SA_NOCLDWAIT, SA_RESTART, SIGCHLD, SIG_IGN, WNOHANG}; +use x11::xlib::{SubstructureRedirectMask, XDefaultRootWindow, XDefaultScreen, XDisplayHeight, XDisplayWidth, XErrorEvent, XOpenDisplay, XRootWindow, XSelectInput, XSetErrorHandler, XSupportsLocale, XSync, _XDisplay}; + +mod drw; + +// TODO: Replace with actual configs +const FONT: &'static str = "monospace:size=10"; + +#[derive(Debug)] +pub struct Server { + display: *mut _XDisplay, + screen: Screen, + error_handler: Option, + root: u64, + drw: Option +} + +#[derive(Debug, Default)] +pub struct Screen { + sn: i32, + w: i32, + h: i32, +} + +type ErrorHandler = unsafe extern "C" fn (display: *mut _XDisplay, ev: *mut XErrorEvent) -> i32; + +impl Server { + pub fn new() -> Self { + unsafe { + Self { display: std::ptr::null_mut(), screen: Default::default(), error_handler: None, root: 0, drw: None } + } + } + + pub fn setup(&mut self) { + //sets locale and tests if other wms are runnnig + unsafe { + if setlocale(LC_CTYPE, c"".as_ptr()).is_null() || XSupportsLocale() != 0 { + log::warn!("No locale support"); + } + self.display = XOpenDisplay(std::ptr::null()); + + self.error_handler = XSetErrorHandler(Some(Self::error_wm_exists)); + /* this causes an error if some other window manager is running */ + let drw = XDefaultRootWindow(self.display); + XSelectInput(self.display, drw, SubstructureRedirectMask); + XSync(self.display, false as i32); + XSetErrorHandler(Some(Self::error_handler)); + XSync(self.display, false as i32); + } + // do not transform children into zombies when they terminate + unsafe { + let mut sa: sigaction = std::mem::zeroed(); + sigemptyset(&mut sa.sa_mask as *mut sigset_t); + sa.sa_flags = SA_NOCLDSTOP | SA_NOCLDWAIT | SA_RESTART; + sa.sa_sigaction = SIG_IGN; + sigaction(SIGCHLD, &sa, std::ptr::null_mut()); + } + + // clean up any zombies (inherited from .xinitrc etc) immediately + unsafe { + while waitpid(-1, std::ptr::null_mut(), WNOHANG) > 0 {}; + } + // Init screen + unsafe { + let s = XDefaultScreen(self.display); + self.screen.w = XDisplayWidth(self.display, s); + self.screen.h = XDisplayHeight(self.display, s); + self.root = XRootWindow(self.display, s); + self.drw = Some(drw::Drw::new(self.display, self.screen.sn, self.root, self.screen.w, self.screen.h, vec![FONT]).unwrap()); + + } + } + + fn drw(&mut self) -> drw::Drw { + &a + } + + unsafe extern "C" fn error_wm_exists(_display: *mut _XDisplay, _ev: *mut XErrorEvent) -> i32 { + log::error!("A WM is already running"); + return -1; + } + + unsafe extern "C" fn error_handler(_display: *mut _XDisplay, _ev: *mut XErrorEvent) -> i32 { + log::error!("idk what happened good luck lmao"); + return -1; + } + +}