summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/clients/client.rs2
-rw-r--r--src/clients/hints.rs5
-rw-r--r--src/clients/mod.rs11
-rw-r--r--src/clients/tile.rs2
-rw-r--r--src/config.rs7
-rw-r--r--src/conn_info/atoms.rs1
-rw-r--r--src/conn_info/mod.rs7
-rw-r--r--src/focus.rs2
-rw-r--r--src/keys.rs4
l---------src/lib.rs1
-rw-r--r--src/main.rs44
11 files changed, 72 insertions, 14 deletions
diff --git a/src/clients/client.rs b/src/clients/client.rs
index 3b33b5f..394c319 100644
--- a/src/clients/client.rs
+++ b/src/clients/client.rs
@@ -133,7 +133,7 @@ impl Client {
/// Sync the non-geometry related properties with EWMH hints
pub fn sync_properties(&mut self, conn: &Connection<'_>, focused: bool) {
- let Some(mut hints) = hints::Xwm::get(conn, self.window) else {
+ let Some(mut hints) = hints::Ewm::get(conn, self.window) else {
return;
};
diff --git a/src/clients/hints.rs b/src/clients/hints.rs
index dd5bcf7..bd3ef76 100644
--- a/src/clients/hints.rs
+++ b/src/clients/hints.rs
@@ -5,7 +5,8 @@ use xcb::{
use crate::conn_info::Connection;
-pub struct Xwm {
+/// EWM Hints set on a window.
+pub struct Ewm {
flags: u32,
input: bool,
initial_state: i32,
@@ -17,7 +18,7 @@ pub struct Xwm {
window_group: u32,
}
-impl Xwm {
+impl Ewm {
/// Get the EWM hints for the given window, if they exist and are valid.
pub fn get(conn: &Connection<'_>, window: Window) -> Option<Self> {
// https://github.com/mirror/libX11/blob/ff8706a5eae25b8bafce300527079f68a201d27f/src/GetHints.c#L106
diff --git a/src/clients/mod.rs b/src/clients/mod.rs
index c7df881..ca9ed91 100644
--- a/src/clients/mod.rs
+++ b/src/clients/mod.rs
@@ -1,3 +1,5 @@
+//! Tracking and managing windows.
+
use crate::{
config::BORDER_WIDTH,
conn_info::Connection,
@@ -14,12 +16,19 @@ use xcb::{
BaseEvent, Extension,
};
-pub use client::Client;
+pub use client::*;
+pub use hints::*;
pub use monitors::*;
+#[doc(hidden)]
mod client;
+
+#[doc(hidden)]
mod hints;
+
+#[doc(hidden)]
mod monitors;
+
mod tile;
impl WM<'_> {
diff --git a/src/clients/tile.rs b/src/clients/tile.rs
index 4a2d4fc..e089c3f 100644
--- a/src/clients/tile.rs
+++ b/src/clients/tile.rs
@@ -1,3 +1,5 @@
+//! Tiling functions
+
use std::cmp::min;
use crate::conn_info::Connection;
diff --git a/src/config.rs b/src/config.rs
index e6478b3..246fe12 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -1,4 +1,6 @@
+//! User configuration
#![allow(clippy::unreadable_literal)] // Colours are more readable this way imo
+
use std::process::Command;
use xcb::x::ModMask;
@@ -9,8 +11,13 @@ use crate::{
keys::{Keybind, Keybinds},
};
+/// Width of the border around windows
pub const BORDER_WIDTH: u16 = 3;
+
+/// Default border for windows
pub const BORDER_NORMAL: Colour = Colour::from_hex(0x000000);
+
+/// Border around currently focused window
pub const BORDER_FOCUSED: Colour = Colour::from_hex(0xff0000);
/// The keybinds to use.
diff --git a/src/conn_info/atoms.rs b/src/conn_info/atoms.rs
index 9b3a78a..ca715ef 100644
--- a/src/conn_info/atoms.rs
+++ b/src/conn_info/atoms.rs
@@ -1,4 +1,5 @@
xcb::atoms_struct! {
+ /// Interned atoms, mostly for window properties
#[derive(Copy, Clone, Debug)]
pub struct Atoms {
pub wm_protocols => b"WM_PROTOCOLS" only_if_exists = false,
diff --git a/src/conn_info/mod.rs b/src/conn_info/mod.rs
index 183f691..c1d768d 100644
--- a/src/conn_info/mod.rs
+++ b/src/conn_info/mod.rs
@@ -1,3 +1,5 @@
+//! Global resources and utilities
+
use std::fmt::Debug;
use xcb::{
x::{
@@ -7,9 +9,13 @@ use xcb::{
Connection as RawConnection, Cookie, VoidCookieChecked,
};
+#[doc(hidden)]
mod atoms;
+#[doc(hidden)]
mod colours;
+#[doc(hidden)]
mod cursors;
+#[doc(hidden)]
mod keys;
pub use self::{
@@ -49,6 +55,7 @@ pub struct Connection<'a> {
pub keyboard_state: KeyboardInfo,
}
+/// Helper macro to log a request / cookie when debug_assertions are on
macro_rules! debug_req {
($req:ident) => {
#[cfg(debug_assertions)]
diff --git a/src/focus.rs b/src/focus.rs
index 65bf65e..da3b81a 100644
--- a/src/focus.rs
+++ b/src/focus.rs
@@ -1,3 +1,5 @@
+//! Event handlers for dealing with window focus.
+
use xcb::x::{EnterNotifyEvent, FocusInEvent, NotifyDetail, NotifyMode};
use crate::WM;
diff --git a/src/keys.rs b/src/keys.rs
index 3103f41..51d005d 100644
--- a/src/keys.rs
+++ b/src/keys.rs
@@ -1,3 +1,5 @@
+//! Keybind-related code
+
use crate::{config::KEYBINDS, conn_info::Connection, error::Result, WM};
use xcb::x::{
GrabKey, GrabMode, KeyPressEvent, Mapping, MappingNotifyEvent, ModMask, UngrabKey, GRAB_ANY,
@@ -34,7 +36,7 @@ impl WM<'_> {
}
/// Refresh our keyboard info, and ensure that we get events for bound keys.
-fn grab_keys(conn: &mut Connection<'_>) -> Result<()> {
+pub fn grab_keys(conn: &mut Connection<'_>) -> Result<()> {
// Refresh keyboard state
conn.refresh_keyboard_info()?;
diff --git a/src/lib.rs b/src/lib.rs
new file mode 120000
index 0000000..f61f281
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1 @@
+src/main.rs \ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
index 54d893c..64e9203 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,4 +1,20 @@
//! A lightweight X11 window manager, inspired by dwm.
+//!
+//! # Structure
+//!
+//! The main thing a WM has to do is respond to events: this is done in the [`WM::event_loop`] function, which dispatches to the `handle_*` methods of that struct.
+//!
+//! [`conn_info`] wraps XCB's [`xcb::Connection`] type and caches common resources such as atoms, colours, cursors, and keyboard layout info.
+//!
+//! `focus.rs`, [`keys`], and [`clients`] all add some event handlers to [`WM`], but most of the important code is in [`clients`].
+//!
+//! [`config`] holds all of the variables that a user might want to change.
+//!
+//! # XCB
+//!
+//! Unlike dwm, blow uses XCB rather than Xlib. This means requests are asynchronous by default.
+//! In most places, we avoid checking for errors unless we need to see the response to a request.
+//! Errors will be caught and logged in the event loop instead. See [`xcb`] documentation for more details.
#![deny(clippy::all, clippy::pedantic, clippy::nursery)]
use clients::ClientState;
@@ -9,12 +25,14 @@ use xcb::{
Connection as RawConnection, Event, Extension,
};
-mod clients;
-mod config;
-mod conn_info;
+pub mod clients;
+pub mod config;
+pub mod conn_info;
+#[doc(hidden)]
mod error;
+#[doc(hidden)]
mod focus;
-mod keys;
+pub mod keys;
fn main() -> Result<()> {
cleanup_process_children();
@@ -29,12 +47,14 @@ fn main() -> Result<()> {
Ok(())
}
-struct WM<'a> {
+/// All of the state used by the window manager
+pub struct WM<'a> {
conn: Connection<'a>,
clients: ClientState,
}
impl<'a> WM<'a> {
+ /// Prepare to start the window manager, using the given connection and scren number.
pub fn new(conn: &'a RawConnection, screen_num: usize) -> Result<Self> {
let mut this = Self {
conn: Connection::new(conn, screen_num)?,
@@ -45,6 +65,8 @@ impl<'a> WM<'a> {
Ok(this)
}
+ /// Run the main event loop until we encounter a non-recoverable error (usually connection).
+ /// This will only ever return an error.
pub fn event_loop(&mut self) -> Result<()> {
loop {
match self.conn.wait_for_event() {
@@ -68,15 +90,19 @@ impl<'a> WM<'a> {
Event::X(x::Event::PropertyNotify(e)) => self.handle_property_notify(&e),
_ => {}
},
+ Err(Error::Xcb(xcb::Error::Protocol(e))) => {
+ eprintln!("protocol error in event loop: {e:#?}\ncontinuing anyway");
+ }
Err(e) => {
- eprintln!("error in event loop: {e:#?}\ncontinuing anyway");
+ eprintln!("unrecoverable error: {e:#?}\nexiting event loop");
+ return Err(e);
}
};
self.conn.flush()?;
}
}
- /// Handle a property notify event, by doing *todo*
+ /// Update client properties when they change in X11.
fn handle_property_notify(&mut self, e: &PropertyNotifyEvent) {
if x::ATOM_WM_HINTS == e.atom() {
let focused = self.clients.is_focused(e.window());
@@ -88,9 +114,9 @@ impl<'a> WM<'a> {
}
/// Cleanup this process' children and set some flags.
-/// This is necessary when used with `startx`
+/// This is necessary when used with `startx`.
fn cleanup_process_children() {
// TODO: dont transform children into zombies when they terminate
// TODO: cleanup zombies
- todo!()
+ // todo!()
}