<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<meta name="description" content="Technical architecture documentation for DWN window manager - codebase structure, modules, and internals.">
|
|
<title>Architecture - DWN Window Manager</title>
|
|
<link rel="stylesheet" href="css/style.css">
|
|
</head>
|
|
<body>
|
|
<header>
|
|
<nav>
|
|
<a href="index.html" class="logo">
|
|
<span class="logo-icon">D</span>
|
|
<span>DWN</span>
|
|
</a>
|
|
<ul class="nav-links">
|
|
<li><a href="index.html">Home</a></li>
|
|
<li><a href="features.html">Features</a></li>
|
|
<li><a href="installation.html">Install</a></li>
|
|
<li class="dropdown">
|
|
<a href="documentation.html" class="active">Docs</a>
|
|
<div class="dropdown-menu">
|
|
<a href="documentation.html">Getting Started</a>
|
|
<a href="shortcuts.html">Keyboard Shortcuts</a>
|
|
<a href="configuration.html">Configuration</a>
|
|
<a href="ai-features.html">AI Features</a>
|
|
<a href="architecture.html">Architecture</a>
|
|
<a href="design-patterns.html">Design Patterns</a>
|
|
</div>
|
|
</li>
|
|
<li><a href="https://retoor.molodetz.nl/retoor/dwn">Git</a></li>
|
|
</ul>
|
|
<div class="nav-toggle" onclick="toggleNav()">
|
|
<span></span>
|
|
<span></span>
|
|
<span></span>
|
|
</div>
|
|
</nav>
|
|
</header>
|
|
<main>
|
|
<section class="hero" style="padding: 8rem 0 4rem;">
|
|
<div class="container hero-content">
|
|
<h1>Architecture</h1>
|
|
<p class="subtitle">
|
|
Technical documentation for developers and contributors.
|
|
</p>
|
|
</div>
|
|
</section>
|
|
<section class="section">
|
|
<div class="container">
|
|
<h2>Overview</h2>
|
|
<p>
|
|
DWN is written in ANSI C (C99) and follows a modular single-responsibility architecture.
|
|
A global <code>DWNState</code> singleton manages all state, and the main event loop
|
|
dispatches X11 events to specialized modules.
|
|
</p>
|
|
<div class="card" style="margin: 2rem 0;">
|
|
<h3>Project Statistics</h3>
|
|
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 1rem; text-align: center;">
|
|
<div>
|
|
<div style="font-size: 2rem; font-weight: 700; color: var(--primary);">~10K</div>
|
|
<div style="color: var(--text-muted);">Lines of Code</div>
|
|
</div>
|
|
<div>
|
|
<div style="font-size: 2rem; font-weight: 700; color: var(--primary);">13</div>
|
|
<div style="color: var(--text-muted);">Core Modules</div>
|
|
</div>
|
|
<div>
|
|
<div style="font-size: 2rem; font-weight: 700; color: var(--primary);">C99</div>
|
|
<div style="color: var(--text-muted);">Standard</div>
|
|
</div>
|
|
<div>
|
|
<div style="font-size: 2rem; font-weight: 700; color: var(--primary);">MIT</div>
|
|
<div style="color: var(--text-muted);">License</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<h2 id="structure" style="margin-top: 3rem;">Directory Structure</h2>
|
|
<div class="code-header">
|
|
<span>Project Layout</span>
|
|
</div>
|
|
<pre><code>dwn/
|
|
├── src/ # Source files (.c)
|
|
│ ├── main.c # Entry point, event loop
|
|
│ ├── client.c # Window management
|
|
│ ├── workspace.c # Virtual desktops
|
|
│ ├── layout.c # Tiling algorithms
|
|
│ ├── decorations.c # Title bars, borders
|
|
│ ├── panel.c # Top/bottom panels
|
|
│ ├── systray.c # System tray widgets
|
|
│ ├── notifications.c # D-Bus notifications
|
|
│ ├── atoms.c # X11 atoms (EWMH/ICCCM)
|
|
│ ├── keys.c # Keyboard handling
|
|
│ ├── config.c # INI parser
|
|
│ ├── ai.c # AI integration
|
|
│ └── util.c # Utilities
|
|
├── include/ # Header files (.h)
|
|
├── site/ # Documentation website
|
|
├── Makefile # Build system
|
|
├── CLAUDE.md # AI assistant context
|
|
└── README.md # Project readme</code></pre>
|
|
<h2 id="modules" style="margin-top: 3rem;">Core Modules</h2>
|
|
<div class="table-wrapper">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Module</th>
|
|
<th>File</th>
|
|
<th>Responsibility</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td><strong>Main</strong></td>
|
|
<td><code>main.c</code></td>
|
|
<td>X11 initialization, event loop, signal handling, module orchestration</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Client</strong></td>
|
|
<td><code>client.c</code></td>
|
|
<td>Window lifecycle, focus management, frame creation, client list</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Workspace</strong></td>
|
|
<td><code>workspace.c</code></td>
|
|
<td>9 virtual desktops, per-workspace state, window assignment</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Layout</strong></td>
|
|
<td><code>layout.c</code></td>
|
|
<td>Tiling (master+stack), floating, monocle layout algorithms</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Decorations</strong></td>
|
|
<td><code>decorations.c</code></td>
|
|
<td>Window title bars, borders, decoration rendering</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Panel</strong></td>
|
|
<td><code>panel.c</code></td>
|
|
<td>Top panel (taskbar, workspace indicators), bottom panel (clock)</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Systray</strong></td>
|
|
<td><code>systray.c</code></td>
|
|
<td>System tray with WiFi/audio/battery indicators, dropdowns</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Notifications</strong></td>
|
|
<td><code>notifications.c</code></td>
|
|
<td>D-Bus notification daemon (org.freedesktop.Notifications)</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Atoms</strong></td>
|
|
<td><code>atoms.c</code></td>
|
|
<td>X11 EWMH/ICCCM atom management and property handling</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Keys</strong></td>
|
|
<td><code>keys.c</code></td>
|
|
<td>Keyboard shortcut capture, keybinding registry, callbacks</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Config</strong></td>
|
|
<td><code>config.c</code></td>
|
|
<td>INI-style config loading and parsing</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>AI</strong></td>
|
|
<td><code>ai.c</code></td>
|
|
<td>Async OpenRouter API integration, Exa semantic search</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>News</strong></td>
|
|
<td><code>news.c</code></td>
|
|
<td>News ticker with API integration, scrolling animation, article navigation</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Autostart</strong></td>
|
|
<td><code>autostart.c</code></td>
|
|
<td>XDG Autostart support, .desktop file parsing, concurrent app launch</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Services</strong></td>
|
|
<td><code>services.c</code></td>
|
|
<td>Background service management, process lifecycle control</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Demo</strong></td>
|
|
<td><code>demo.c</code></td>
|
|
<td>Automated feature demonstration mode, tutorial system</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>API</strong></td>
|
|
<td><code>api.c</code></td>
|
|
<td>WebSocket server, JSON-RPC command handler, remote control interface</td>
|
|
</tr>
|
|
<tr>
|
|
<td><strong>Util</strong></td>
|
|
<td><code>util.c</code></td>
|
|
<td>Logging, memory allocation, string utilities, file helpers</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<h2 id="dependencies" style="margin-top: 3rem;">Module Dependencies</h2>
|
|
<div class="card">
|
|
<pre style="margin: 0; background: transparent; border: none; padding: 0;"><code>main.c (orchestrator)
|
|
├── client.c
|
|
│ ├── decorations.c
|
|
│ ├── config.c
|
|
│ └── atoms.c
|
|
├── workspace.c
|
|
│ ├── client.c
|
|
│ ├── layout.c
|
|
│ └── atoms.c
|
|
├── panel.c
|
|
│ ├── client.c
|
|
│ └── config.c
|
|
├── systray.c
|
|
│ └── config.c
|
|
├── notifications.c (independent)
|
|
├── ai.c (independent)
|
|
├── autostart.c
|
|
│ └── config.c
|
|
└── keys.c
|
|
└── config.c</code></pre>
|
|
</div>
|
|
<h2 id="state" style="margin-top: 3rem;">Global State (DWNState)</h2>
|
|
<p>
|
|
All window manager state is centralized in a single <code>DWNState</code> structure.
|
|
This simplifies state management and makes the codebase easier to understand.
|
|
</p>
|
|
<div class="code-header">
|
|
<span>include/dwn.h (simplified)</span>
|
|
</div>
|
|
<pre><code>typedef struct {
|
|
Display *display; // X11 connection
|
|
Window root; // Root window
|
|
int screen; // Default screen
|
|
Client *clients[MAX_CLIENTS]; // All managed windows
|
|
int client_count;
|
|
Workspace workspaces[MAX_WORKSPACES]; // Virtual desktops
|
|
int current_workspace;
|
|
Panel top_panel;
|
|
Panel bottom_panel;
|
|
Config config; // User configuration
|
|
KeyBinding keys[MAX_KEYBINDINGS];
|
|
// EWMH atoms
|
|
Atom atoms[ATOM_COUNT];
|
|
} DWNState;
|
|
extern DWNState *dwn; // Global singleton</code></pre>
|
|
<h2 id="events" style="margin-top: 3rem;">Event Loop</h2>
|
|
<p>
|
|
DWN uses a traditional X11 event loop with XNextEvent. Events are dispatched
|
|
to appropriate handlers based on type.
|
|
</p>
|
|
<div class="code-header">
|
|
<span>main.c (simplified)</span>
|
|
</div>
|
|
<pre><code>int main(int argc, char *argv[]) {
|
|
dwn_init(); // Initialize X11, atoms, config
|
|
setup_keybindings(); // Register keyboard shortcuts
|
|
setup_panels(); // Create panel windows
|
|
XEvent event;
|
|
while (running) {
|
|
XNextEvent(dwn->display, &event);
|
|
switch (event.type) {
|
|
case MapRequest:
|
|
handle_map_request(&event.xmaprequest);
|
|
break;
|
|
case UnmapNotify:
|
|
handle_unmap_notify(&event.xunmap);
|
|
break;
|
|
case KeyPress:
|
|
handle_key_press(&event.xkey);
|
|
break;
|
|
case ButtonPress:
|
|
handle_button_press(&event.xbutton);
|
|
break;
|
|
case ConfigureRequest:
|
|
handle_configure_request(&event.xconfigurerequest);
|
|
break;
|
|
// ... more event types
|
|
}
|
|
}
|
|
dwn_cleanup();
|
|
return 0;
|
|
}</code></pre>
|
|
<h2 id="constants" style="margin-top: 3rem;">Key Constants</h2>
|
|
<div class="table-wrapper">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Constant</th>
|
|
<th>Value</th>
|
|
<th>Purpose</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>Number of virtual desktops</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>MAX_MONITORS</code></td>
|
|
<td>8</td>
|
|
<td>Multi-monitor support limit</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>MAX_NOTIFICATIONS</code></td>
|
|
<td>32</td>
|
|
<td>Concurrent notifications</td>
|
|
</tr>
|
|
<tr>
|
|
<td><code>MAX_KEYBINDINGS</code></td>
|
|
<td>64</td>
|
|
<td>Registered keyboard shortcuts</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<h2 id="conventions" style="margin-top: 3rem;">Coding Conventions</h2>
|
|
<div class="features-grid" style="grid-template-columns: repeat(2, 1fr);">
|
|
<div class="card">
|
|
<h3>Naming</h3>
|
|
<ul style="padding-left: 1.25rem;">
|
|
<li><code>snake_case</code> for functions and variables</li>
|
|
<li><code>CamelCase</code> for types and structs</li>
|
|
<li>Module prefix for functions (e.g., <code>client_focus()</code>)</li>
|
|
<li>Constants in <code>UPPER_SNAKE_CASE</code></li>
|
|
</ul>
|
|
</div>
|
|
<div class="card">
|
|
<h3>Style</h3>
|
|
<ul style="padding-left: 1.25rem;">
|
|
<li>4-space indentation</li>
|
|
<li>K&R brace style</li>
|
|
<li>Max 100 characters per line</li>
|
|
<li>clang-format for consistency</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="code-header" style="margin-top: 1.5rem;">
|
|
<span>Example Function</span>
|
|
</div>
|
|
<pre><code>void client_focus(Client *c) {
|
|
if (!c) return;
|
|
// Unfocus previous
|
|
if (dwn->focused && dwn->focused != c) {
|
|
client_unfocus(dwn->focused);
|
|
}
|
|
dwn->focused = c;
|
|
XSetInputFocus(dwn->display, c->window, RevertToPointerRoot, CurrentTime);
|
|
XRaiseWindow(dwn->display, c->frame);
|
|
decorations_update(c);
|
|
atoms_set_active_window(c->window);
|
|
}</code></pre>
|
|
<h2 id="protocols" style="margin-top: 3rem;">EWMH/ICCCM Support</h2>
|
|
<p>
|
|
DWN implements key Extended Window Manager Hints and ICCCM protocols
|
|
for compatibility with modern applications.
|
|
</p>
|
|
<div class="features-grid" style="grid-template-columns: repeat(2, 1fr);">
|
|
<div class="card">
|
|
<h3>EWMH Atoms</h3>
|
|
<ul style="padding-left: 1.25rem; font-family: var(--font-mono); font-size: 0.875rem;">
|
|
<li>_NET_SUPPORTED</li>
|
|
<li>_NET_CLIENT_LIST</li>
|
|
<li>_NET_CLIENT_LIST_STACKING</li>
|
|
<li>_NET_ACTIVE_WINDOW</li>
|
|
<li>_NET_CURRENT_DESKTOP</li>
|
|
<li>_NET_NUMBER_OF_DESKTOPS</li>
|
|
<li>_NET_WM_STATE</li>
|
|
<li>_NET_WM_STATE_FULLSCREEN</li>
|
|
<li>_NET_WM_STATE_MAXIMIZED_*</li>
|
|
<li>_NET_WM_WINDOW_TYPE</li>
|
|
<li>_NET_WM_NAME</li>
|
|
</ul>
|
|
</div>
|
|
<div class="card">
|
|
<h3>ICCCM Support</h3>
|
|
<ul style="padding-left: 1.25rem; font-family: var(--font-mono); font-size: 0.875rem;">
|
|
<li>WM_STATE</li>
|
|
<li>WM_PROTOCOLS</li>
|
|
<li>WM_DELETE_WINDOW</li>
|
|
<li>WM_TAKE_FOCUS</li>
|
|
<li>WM_NORMAL_HINTS</li>
|
|
<li>WM_SIZE_HINTS</li>
|
|
<li>WM_CLASS</li>
|
|
<li>WM_NAME</li>
|
|
<li>WM_TRANSIENT_FOR</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<h2 id="build" style="margin-top: 3rem;">Build System</h2>
|
|
<p>
|
|
DWN uses a simple Makefile-based build system with pkg-config for dependency detection.
|
|
</p>
|
|
<div class="table-wrapper">
|
|
<table>
|
|
<thead>
|
|
<tr>
|
|
<th>Target</th>
|
|
<th>Command</th>
|
|
<th>Description</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr>
|
|
<td>Build (release)</td>
|
|
<td><code>make</code></td>
|
|
<td>Optimized build with -O2</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Build (debug)</td>
|
|
<td><code>make debug</code></td>
|
|
<td>Debug symbols, -DDEBUG flag</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Install</td>
|
|
<td><code>sudo make install</code></td>
|
|
<td>Install to PREFIX (/usr/local)</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Clean</td>
|
|
<td><code>make clean</code></td>
|
|
<td>Remove build artifacts</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Format</td>
|
|
<td><code>make format</code></td>
|
|
<td>Run clang-format on sources</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Check</td>
|
|
<td><code>make check</code></td>
|
|
<td>Run cppcheck static analysis</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Test</td>
|
|
<td><code>make run</code></td>
|
|
<td>Run in Xephyr nested server</td>
|
|
</tr>
|
|
<tr>
|
|
<td>Dependencies</td>
|
|
<td><code>make deps</code></td>
|
|
<td>Auto-install for your distro</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<h2 id="contributing" style="margin-top: 3rem;">Contributing</h2>
|
|
<p>
|
|
Contributions are welcome! Here's how to get started:
|
|
</p>
|
|
<div class="steps">
|
|
<div class="step">
|
|
<div class="step-number">1</div>
|
|
<div class="step-content">
|
|
<h4>Fork & Clone</h4>
|
|
<p>Fork the repository and clone your fork locally.</p>
|
|
</div>
|
|
</div>
|
|
<div class="step">
|
|
<div class="step-number">2</div>
|
|
<div class="step-content">
|
|
<h4>Create a Branch</h4>
|
|
<p>Create a feature branch: <code>git checkout -b feature/my-feature</code></p>
|
|
</div>
|
|
</div>
|
|
<div class="step">
|
|
<div class="step-number">3</div>
|
|
<div class="step-content">
|
|
<h4>Make Changes</h4>
|
|
<p>Follow coding conventions. Run <code>make format</code> and <code>make check</code>.</p>
|
|
</div>
|
|
</div>
|
|
<div class="step">
|
|
<div class="step-number">4</div>
|
|
<div class="step-content">
|
|
<h4>Test</h4>
|
|
<p>Test your changes with <code>make run</code> in a nested X server.</p>
|
|
</div>
|
|
</div>
|
|
<div class="step">
|
|
<div class="step-number">5</div>
|
|
<div class="step-content">
|
|
<h4>Submit PR</h4>
|
|
<p>Push your branch and open a pull request with a clear description.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</main>
|
|
<footer>
|
|
<div class="container">
|
|
<div class="footer-grid">
|
|
<div class="footer-section">
|
|
<h4>DWN Window Manager</h4>
|
|
<p style="color: var(--text-muted);">
|
|
A modern, production-ready X11 window manager with XFCE-like
|
|
functionality and optional AI integration.
|
|
</p>
|
|
</div>
|
|
<div class="footer-section">
|
|
<h4>Documentation</h4>
|
|
<ul>
|
|
<li><a href="documentation.html">Getting Started</a></li>
|
|
<li><a href="shortcuts.html">Keyboard Shortcuts</a></li>
|
|
<li><a href="configuration.html">Configuration</a></li>
|
|
<li><a href="architecture.html">Architecture</a></li>
|
|
<li><a href="design-patterns.html">Design Patterns</a></li>
|
|
</ul>
|
|
</div>
|
|
<div class="footer-section">
|
|
<h4>Resources</h4>
|
|
<ul>
|
|
<li><a href="features.html">Features</a></li>
|
|
<li><a href="installation.html">Installation</a></li>
|
|
<li><a href="ai-features.html">AI Integration</a></li>
|
|
<li><a href="https://retoor.molodetz.nl/retoor/dwn">Git</a></li>
|
|
</ul>
|
|
</div>
|
|
<div class="footer-section">
|
|
<h4>Community</h4>
|
|
<ul>
|
|
<li><a href="https://retoor.molodetz.nl/retoor/dwn/issues">Issue Tracker</a></li>
|
|
<li><a href="https://retoor.molodetz.nl/retoor/dwn/discussions">Discussions</a></li>
|
|
<li><a href="https://retoor.molodetz.nl/retoor/dwn/blob/main/CONTRIBUTING.md">Contributing</a></li>
|
|
<li><a href="https://retoor.molodetz.nl/retoor/dwn/blob/main/LICENSE">License (MIT)</a></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="footer-bottom">
|
|
<p>DWN Window Manager by retoor <retoor@molodetz.nl> - MIT License</p>
|
|
</div>
|
|
</div>
|
|
</footer>
|
|
<script src="js/main.js"></script>
|
|
</body>
|
|
</html>
|