2026-01-24 16:17:47 +01:00
<!DOCTYPE html>
< html lang = "en" >
< head >
< meta charset = "UTF-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
< title > Architecture - DWN Documentation< / title >
< link rel = "stylesheet" href = "css/style.css" >
< / head >
< body >
< button class = "mobile-menu-btn" > Menu< / button >
< div class = "layout" >
< aside class = "sidebar" >
< div class = "sidebar-header" >
< h1 > DWN< / h1 >
2026-02-07 13:04:52 +01:00
< span class = "version" > v2.0.0< / span >
2026-01-24 16:17:47 +01:00
< / div >
< div class = "search-box" >
< input type = "text" class = "search-input" placeholder = "Search docs..." >
< / div >
< nav class = "sidebar-nav" >
< div class = "nav-section" >
< div class = "nav-section-title" > Getting Started< / div >
< a href = "index.html" class = "nav-link" > Introduction< / a >
< a href = "installation.html" class = "nav-link" > Installation< / a >
< a href = "quickstart.html" class = "nav-link" > Quick Start< / a >
< / div >
< div class = "nav-section" >
< div class = "nav-section-title" > User Guide< / div >
< a href = "features.html" class = "nav-link" > Features< / a >
< a href = "shortcuts.html" class = "nav-link" > Keyboard Shortcuts< / a >
< a href = "configuration.html" class = "nav-link" > Configuration< / a >
< a href = "layouts.html" class = "nav-link" > Layouts< / a >
< a href = "ai-features.html" class = "nav-link" > AI Integration< / a >
< / div >
< div class = "nav-section" >
< div class = "nav-section-title" > API Reference< / div >
< a href = "api-overview.html" class = "nav-link" > API Overview< / a >
< a href = "api-reference.html" class = "nav-link" > API Reference< / a >
< a href = "api-examples.html" class = "nav-link" > API Examples< / a >
< / div >
< div class = "nav-section" >
< div class = "nav-section-title" > Advanced< / div >
< a href = "architecture.html" class = "nav-link active" > Architecture< / a >
2026-02-07 13:04:52 +01:00
< a href = "abstraction-layer.html" class = "nav-link" > Abstraction Layer< / a >
< a href = "plugin-development.html" class = "nav-link" > Plugin Development< / a >
2026-01-24 16:17:47 +01:00
< a href = "building.html" class = "nav-link" > Building from Source< / a >
< / div >
< / nav >
< / aside >
< main class = "main-content" >
< div class = "content" >
< div class = "page-header" >
< h1 > Architecture< / h1 >
< p class = "lead" > Technical overview of DWN's design and implementation< / p >
< / div >
< div class = "toc" >
< div class = "toc-title" > On this page< / div >
< ul class = "toc-list" >
< li > < a href = "#overview" > Overview< / a > < / li >
2026-02-07 13:04:52 +01:00
< li > < a href = "#abstraction" > Abstraction Layer< / a > < / li >
2026-01-24 16:17:47 +01:00
< li > < a href = "#modules" > Module Structure< / a > < / li >
< li > < a href = "#event-loop" > Event Loop< / a > < / li >
< li > < a href = "#data-structures" > Core Data Structures< / a > < / li >
< li > < a href = "#protocols" > X11 Protocols< / a > < / li >
< li > < a href = "#design-patterns" > Design Patterns< / a > < / li >
< / ul >
< / div >
< h2 id = "overview" > Overview< / h2 >
2026-02-07 13:04:52 +01:00
< p > DWN is written in ANSI C for X11/Xorg. It uses a modular architecture with a global state singleton and event-driven design. Version 2.0 introduces a comprehensive abstraction layer enabling backend portability and plugin extensibility.< / p >
< h2 id = "abstraction" > Abstraction Layer (v2.0)< / h2 >
< p > The new abstraction layer provides backend-agnostic types and a plugin system:< / p >
2026-01-24 16:17:47 +01:00
< div class = "code-block" >
< pre > < code > ┌─────────────────────────────────────────────────────────┐
2026-02-07 13:04:52 +01:00
│ DWN Application │
2026-01-24 16:17:47 +01:00
├─────────────────────────────────────────────────────────┤
2026-02-07 13:04:52 +01:00
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
│ │ Layout │ │ Widget │ │ AI Provider │ │
│ │ Plugin │ │ Plugin │ │ API │ │
│ │ System │ │ System │ │ (future) │ │
│ └──────┬──────┘ └──────┬──────┘ └─────────────────┘ │
│ │ │ │
│ ┌──────┴────────────────┴───────────────────────────┐ │
│ │ Abstract Client Manager │ │
│ │ (wm_client.h/c - bidirectional sync) │ │
│ └───────────────────────┬───────────────────────────┘ │
│ │ │
│ ┌───────────────────────┴───────────────────────────┐ │
│ │ Backend Abstraction Interface │ │
│ │ (backend_interface.h - vtable-based) │ │
│ └───────────────────────┬───────────────────────────┘ │
│ │ │
│ ┌───────────────────────┴───────────────────────────┐ │
│ │ X11 Backend │ Wayland Backend │ Headless │ │
│ │ (complete) │ (future) │ (future) │ │
│ └───────────────────────────────────────────────────┘ │
2026-01-24 16:17:47 +01:00
└─────────────────────────────────────────────────────────┘< / code > < / pre >
< / div >
2026-02-07 13:04:52 +01:00
< h3 > Core Abstractions< / h3 >
< ul >
< li > < strong > wm_types.h< / strong > - Abstract handles, geometry, colors, events< / li >
< li > < strong > wm_string.h/c< / strong > - Safe dynamic strings< / li >
< li > < strong > wm_list.h/c< / strong > - Dynamic arrays< / li >
< li > < strong > wm_hashmap.h/c< / strong > - Hash tables< / li >
< li > < strong > wm_client.h/c< / strong > - Abstract client type< / li >
< / ul >
< h3 > Plugin System< / h3 >
< ul >
< li > < strong > Layout Plugins< / strong > - Custom window arrangements (tiling, floating, monocle, grid)< / li >
< li > < strong > Widget Plugins< / strong > - Panel components (taskbar, clock, system stats)< / li >
< li > < strong > Dynamic Loading< / strong > - Load plugins from shared libraries< / li >
< / ul >
< h3 > Backend Interface< / h3 >
< p > The backend interface defines 80+ operations for window management, events, and rendering. Current implementations:< / p >
< ul >
< li > < strong > X11< / strong > - Full implementation with event translation< / li >
< li > < strong > Wayland< / strong > - Planned for future< / li >
< li > < strong > Headless< / strong > - For testing and CI< / li >
< / ul >
2026-01-24 16:17:47 +01:00
< h2 id = "modules" > Module Structure< / h2 >
< p > Each module has a header in < code > include/< / code > and implementation in < code > src/< / code > .< / p >
< div class = "table-container" >
< table >
< thead >
< tr >
< th > Module< / th >
< th > Responsibility< / th >
< / tr >
< / thead >
< tbody >
< tr >
< td > < code > main.c< / code > < / td >
< td > X11 initialization, event loop, signal handling< / td >
< / tr >
< tr >
< td > < code > client.c< / code > < / td >
< td > Window management, focus, frame creation< / td >
< / tr >
< tr >
< td > < code > workspace.c< / code > < / td >
< td > 9 virtual desktops, per-workspace state< / td >
< / tr >
< tr >
< td > < code > layout.c< / code > < / td >
< td > Tiling, floating, monocle algorithms< / td >
< / tr >
< tr >
< td > < code > decorations.c< / code > < / td >
< td > Window title bars and borders< / td >
< / tr >
< tr >
< td > < code > panel.c< / code > < / td >
< td > Top/bottom panels, taskbar, workspace indicators< / td >
< / tr >
< tr >
< td > < code > systray.c< / code > < / td >
< td > XEmbed system tray, WiFi/audio/battery widgets< / td >
< / tr >
< tr >
< td > < code > notifications.c< / code > < / td >
< td > D-Bus notification daemon< / td >
< / tr >
< tr >
< td > < code > atoms.c< / code > < / td >
< td > X11 EWMH/ICCCM atom management< / td >
< / tr >
< tr >
< td > < code > keys.c< / code > < / td >
< td > Keyboard shortcut capture and callbacks< / td >
< / tr >
< tr >
< td > < code > config.c< / code > < / td >
< td > INI-style config loading< / td >
< / tr >
< tr >
< td > < code > api.c< / code > < / td >
< td > WebSocket JSON API server< / td >
< / tr >
< tr >
< td > < code > screenshot.c< / code > < / td >
< td > X11 capture + PNG encoding< / td >
< / tr >
< tr >
< td > < code > ocr.c< / code > < / td >
< td > Tesseract OCR integration< / td >
< / tr >
< tr >
< td > < code > ai.c< / code > < / td >
< td > OpenRouter API, Exa search< / td >
< / tr >
< tr >
< td > < code > util.c< / code > < / td >
< td > Logging, memory, string utilities< / td >
< / tr >
< / tbody >
< / table >
< / div >
< h2 id = "event-loop" > Event Loop< / h2 >
< p > The main event loop uses < code > select()< / code > for multiplexed I/O across X11, D-Bus, and timers.< / p >
< div class = "code-block" >
< pre > < code > void dwn_run(void) {
int x11_fd = ConnectionNumber(dwn->display);
int dbus_fd = /* from dbus_connection */;
while (dwn->running) {
// 1. Process all pending X11 events
while (XPending(dwn->display)) {
XEvent ev;
XNextEvent(dwn->display, &ev);
dwn_handle_event(&ev);
}
// 2. Process D-Bus messages
notifications_process_messages();
// 3. Process async AI/Exa requests
ai_process_pending();
// 4. Check notification timeouts
notifications_update();
// 5. Handle delayed focus (focus-follow mode)
handle_pending_focus();
// 6. Periodic updates (animation, clock)
if (now - last_update >= 16) { // 60fps
news_update();
panel_render_all();
}
// 7. Wait for events with timeout
fd_set fds;
FD_SET(x11_fd, &fds);
FD_SET(dbus_fd, &fds);
struct timeval tv = {0, 16000}; // 16ms
select(max_fd + 1, & fds, NULL, NULL, &tv);
}
}< / code > < / pre >
< / div >
< h3 > X11 Event Dispatch< / h3 >
< div class = "table-container" >
< table >
< thead >
< tr >
< th > Event< / th >
< th > Handler< / th >
< / tr >
< / thead >
< tbody >
< tr >
< td > < code > MapRequest< / code > < / td >
< td > New window → client_manage()< / td >
< / tr >
< tr >
< td > < code > UnmapNotify< / code > < / td >
< td > Window hidden → possibly client_unmanage()< / td >
< / tr >
< tr >
< td > < code > DestroyNotify< / code > < / td >
< td > Window destroyed → client_unmanage()< / td >
< / tr >
< tr >
< td > < code > ConfigureRequest< / code > < / td >
< td > Window resize request< / td >
< / tr >
< tr >
< td > < code > PropertyNotify< / code > < / td >
< td > Property changed → update title< / td >
< / tr >
< tr >
< td > < code > Expose< / code > < / td >
< td > Repaint needed → render< / td >
< / tr >
< tr >
< td > < code > ButtonPress< / code > < / td >
< td > Mouse click → focus, drag, panel click< / td >
< / tr >
< tr >
< td > < code > MotionNotify< / code > < / td >
< td > Mouse move → window drag/resize< / td >
< / tr >
< tr >
< td > < code > KeyPress< / code > < / td >
< td > Key pressed → shortcut callback< / td >
< / tr >
< tr >
< td > < code > ClientMessage< / code > < / td >
< td > EWMH requests, systray dock< / td >
< / tr >
< / tbody >
< / table >
< / div >
< h2 id = "data-structures" > Core Data Structures< / h2 >
< h3 > DWNState< / h3 >
< p > Global singleton containing all window manager state.< / p >
< div class = "code-block" >
< pre > < code > typedef struct {
Display *display; // X11 connection
int screen; // Default screen
Window root; // Root window
int screen_width, screen_height;
Monitor monitors[MAX_MONITORS];
int monitor_count;
Workspace workspaces[MAX_WORKSPACES]; // 9 workspaces
int current_workspace;
Client *client_list; // Doubly-linked list head
int client_count;
Panel *top_panel;
Panel *bottom_panel;
Config *config;
bool running;
bool ai_enabled;
// Drag state
Client *drag_client;
int drag_start_x, drag_start_y;
bool resizing;
// Alt-Tab state
bool is_alt_tabbing;
Client *alt_tab_client;
} DWNState;< / code > < / pre >
< / div >
< h3 > Client< / h3 >
< p > Represents a managed window with decoration frame.< / p >
< div class = "code-block" >
< pre > < code > struct Client {
Window window; // Application window
Window frame; // Decoration frame (parent)
int x, y, width, height; // Current geometry
int old_x, old_y; // Saved for restore
int old_width, old_height;
uint32_t flags; // CLIENT_FLOATING, etc.
unsigned int workspace; // Workspace index (0-8)
char title[256];
char class[64];
SnapConstraint snap; // Snap state
Client *next, *prev; // Global list
Client *mru_next, *mru_prev; // MRU stack
};< / code > < / pre >
< / div >
< h3 > Workspace< / h3 >
< p > Per-workspace layout and window state.< / p >
< div class = "code-block" >
< pre > < code > struct Workspace {
Client *clients; // Workspace client list
Client *focused; // Currently focused
Client *mru_head, *mru_tail; // MRU stack
LayoutType layout; // tiling/floating/monocle
float master_ratio; // 0.1 to 0.9
int master_count; // 1 to 10
char name[32];
};< / code > < / pre >
< / div >
< h3 > Client Flags< / h3 >
< div class = "code-block" >
< pre > < code > #define CLIENT_NORMAL 0
#define CLIENT_FLOATING (1 < < 0 )
#define CLIENT_FULLSCREEN (1 < < 1 )
#define CLIENT_URGENT (1 < < 2 )
#define CLIENT_MINIMIZED (1 < < 3 )
#define CLIENT_STICKY (1 < < 4 )
#define CLIENT_MAXIMIZED (1 < < 5 )
// Usage
if (c->flags & CLIENT_FLOATING) { ... }
c->flags |= CLIENT_FLOATING; // Set
c->flags & = ~CLIENT_FLOATING; // Clear< / code > < / pre >
< / div >
< h2 id = "protocols" > X11 Protocols< / h2 >
< h3 > EWMH (Extended Window Manager Hints)< / h3 >
< p > Standard hints for modern window manager features.< / p >
< ul >
< li > < code > _NET_SUPPORTED< / code > - List of supported atoms< / li >
< li > < code > _NET_CLIENT_LIST< / code > - List of managed windows< / li >
< li > < code > _NET_CURRENT_DESKTOP< / code > - Current workspace< / li >
< li > < code > _NET_ACTIVE_WINDOW< / code > - Focused window< / li >
< li > < code > _NET_WM_STATE< / code > - Window state (fullscreen, etc.)< / li >
< li > < code > _NET_WM_WINDOW_TYPE< / code > - Window type (dialog, etc.)< / li >
< / ul >
< h3 > ICCCM (Inter-Client Communication)< / h3 >
< p > Core X11 window manager protocol.< / p >
< ul >
< li > < code > WM_PROTOCOLS< / code > - Supported protocols (WM_DELETE_WINDOW)< / li >
< li > < code > WM_NAME< / code > - Window title< / li >
< li > < code > WM_CLASS< / code > - Application class< / li >
< li > < code > WM_HINTS< / code > - Input model, icons< / li >
< li > < code > WM_NORMAL_HINTS< / code > - Size constraints< / li >
< / ul >
< h3 > XEmbed (System Tray)< / h3 >
< p > Protocol for embedding application icons in system tray.< / p >
< ul >
< li > Acquire < code > _NET_SYSTEM_TRAY_S0< / code > selection< / li >
< li > Handle < code > SYSTEM_TRAY_REQUEST_DOCK< / code > messages< / li >
< li > Send < code > XEMBED_EMBEDDED_NOTIFY< / code > to docked icons< / li >
< / ul >
< h2 id = "design-patterns" > Design Patterns< / h2 >
< h3 > Opaque Pointers< / h3 >
< p > Hide implementation details. Header exposes typedef, source defines struct.< / p >
< div class = "code-block" >
< pre > < code > // header.h
typedef struct module_t* Module;
Module module_create(void);
void module_destroy(Module m);
// source.c
struct module_t {
int private_field;
};< / code > < / pre >
< / div >
< h3 > Return Code Error Handling< / h3 >
< p > Functions return status codes, pass results via output parameters.< / p >
< div class = "code-block" >
< pre > < code > typedef enum {
STATUS_OK = 0,
STATUS_ERROR_INVALID_ARG,
STATUS_ERROR_NO_MEMORY
} Status;
Status do_work(int input, int *output);< / code > < / pre >
< / div >
< h3 > Goto Cleanup< / h3 >
< p > Centralized resource cleanup for functions with multiple allocations.< / p >
< div class = "code-block" >
< pre > < code > int process(void) {
char *buf = NULL;
int status = -1;
buf = malloc(1024);
if (!buf) goto cleanup;
// ... work ...
status = 0;
cleanup:
free(buf);
return status;
}< / code > < / pre >
< / div >
< h3 > Module Prefix Convention< / h3 >
< p > All public functions prefixed with module name.< / p >
< div class = "code-block" >
< pre > < code > // client.h
void client_focus(Client *c);
void client_move(Client *c, int x, int y);
void client_resize(Client *c, int w, int h);
// workspace.h
void workspace_switch(int index);
void workspace_arrange(int index);< / code > < / pre >
< / div >
< h2 > Key Constants< / h2 >
< div class = "table-container" >
< table >
< thead >
< tr >
< th > Constant< / th >
< th > Value< / th >
< th > Description< / th >
< / tr >
< / thead >
< tbody >
< tr >
< td > < code > MAX_CLIENTS< / code > < / td >
< td > 256< / td >
< td > Maximum managed windows< / td >
< / tr >
< tr >
< td > < code > MAX_WORKSPACES< / code > < / td >
< td > 9< / td >
< td > Virtual desktops< / td >
< / tr >
< tr >
< td > < code > MAX_MONITORS< / code > < / td >
< td > 8< / td >
< td > Multi-monitor support< / td >
< / tr >
< tr >
< td > < code > MAX_NOTIFICATIONS< / code > < / td >
< td > 32< / td >
< td > Visible notifications< / td >
< / tr >
< tr >
< td > < code > MAX_KEYBINDINGS< / code > < / td >
< td > 64< / td >
< td > Keyboard shortcuts< / td >
< / tr >
< tr >
< td > < code > MAX_TRAY_ICONS< / code > < / td >
< td > 32< / td >
< td > System tray icons< / td >
< / tr >
< / tbody >
< / table >
< / div >
< footer >
< p > DWN Window Manager - retoor < retoor@molodetz.nl> < / p >
< / footer >
< / div >
< / main >
< / div >
< script src = "js/main.js" > < / script >
< / body >
< / html >