Architecture

Technical documentation for developers and contributors.

Overview

DWN is written in ANSI C (C99) and follows a modular single-responsibility architecture. A global DWNState singleton manages all state, and the main event loop dispatches X11 events to specialized modules.

Project Statistics

~10K
Lines of Code
13
Core Modules
C99
Standard
MIT
License

Directory Structure

Project Layout
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

Core Modules

Module File Responsibility
Main main.c X11 initialization, event loop, signal handling, module orchestration
Client client.c Window lifecycle, focus management, frame creation, client list
Workspace workspace.c 9 virtual desktops, per-workspace state, window assignment
Layout layout.c Tiling (master+stack), floating, monocle layout algorithms
Decorations decorations.c Window title bars, borders, decoration rendering
Panel panel.c Top panel (taskbar, workspace indicators), bottom panel (clock)
Systray systray.c System tray with WiFi/audio/battery indicators, dropdowns
Notifications notifications.c D-Bus notification daemon (org.freedesktop.Notifications)
Atoms atoms.c X11 EWMH/ICCCM atom management and property handling
Keys keys.c Keyboard shortcut capture, keybinding registry, callbacks
Config config.c INI-style config loading and parsing
AI ai.c Async OpenRouter API integration, Exa semantic search
News news.c News ticker with API integration, scrolling animation, article navigation
Autostart autostart.c XDG Autostart support, .desktop file parsing, concurrent app launch
Services services.c Background service management, process lifecycle control
Demo demo.c Automated feature demonstration mode, tutorial system
API api.c WebSocket server, JSON-RPC command handler, remote control interface
Util util.c Logging, memory allocation, string utilities, file helpers

Module Dependencies

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

Global State (DWNState)

All window manager state is centralized in a single DWNState structure. This simplifies state management and makes the codebase easier to understand.

include/dwn.h (simplified)
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

Event Loop

DWN uses a traditional X11 event loop with XNextEvent. Events are dispatched to appropriate handlers based on type.

main.c (simplified)
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;
}

Key Constants

Constant Value Purpose
MAX_CLIENTS 256 Maximum managed windows
MAX_WORKSPACES 9 Number of virtual desktops
MAX_MONITORS 8 Multi-monitor support limit
MAX_NOTIFICATIONS 32 Concurrent notifications
MAX_KEYBINDINGS 64 Registered keyboard shortcuts

Coding Conventions

Naming

  • snake_case for functions and variables
  • CamelCase for types and structs
  • Module prefix for functions (e.g., client_focus())
  • Constants in UPPER_SNAKE_CASE

Style

  • 4-space indentation
  • K&R brace style
  • Max 100 characters per line
  • clang-format for consistency
Example Function
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);
}

EWMH/ICCCM Support

DWN implements key Extended Window Manager Hints and ICCCM protocols for compatibility with modern applications.

EWMH Atoms

  • _NET_SUPPORTED
  • _NET_CLIENT_LIST
  • _NET_CLIENT_LIST_STACKING
  • _NET_ACTIVE_WINDOW
  • _NET_CURRENT_DESKTOP
  • _NET_NUMBER_OF_DESKTOPS
  • _NET_WM_STATE
  • _NET_WM_STATE_FULLSCREEN
  • _NET_WM_STATE_MAXIMIZED_*
  • _NET_WM_WINDOW_TYPE
  • _NET_WM_NAME

ICCCM Support

  • WM_STATE
  • WM_PROTOCOLS
  • WM_DELETE_WINDOW
  • WM_TAKE_FOCUS
  • WM_NORMAL_HINTS
  • WM_SIZE_HINTS
  • WM_CLASS
  • WM_NAME
  • WM_TRANSIENT_FOR

Build System

DWN uses a simple Makefile-based build system with pkg-config for dependency detection.

Target Command Description
Build (release) make Optimized build with -O2
Build (debug) make debug Debug symbols, -DDEBUG flag
Install sudo make install Install to PREFIX (/usr/local)
Clean make clean Remove build artifacts
Format make format Run clang-format on sources
Check make check Run cppcheck static analysis
Test make run Run in Xephyr nested server
Dependencies make deps Auto-install for your distro

Contributing

Contributions are welcome! Here's how to get started:

1

Fork & Clone

Fork the repository and clone your fork locally.

2

Create a Branch

Create a feature branch: git checkout -b feature/my-feature

3

Make Changes

Follow coding conventions. Run make format and make check.

4

Test

Test your changes with make run in a nested X server.

5

Submit PR

Push your branch and open a pull request with a clear description.