# WindowMaker 0.96.0 — Architecture Overview ## Top-Level Directory Map | Directory | Role | LOC (`.c`) | |---|---|---| | **`src/`** | **Window manager core** — policy, layout, event dispatch | ~26k | | **`src/backend/`** | Display-system abstraction (X11 + Wayland vtable) | ~18k | | **`WINGs/`** | Widget library (buttons, text fields, panels, etc.) + utility library (WUtil) | ~40k | | **`wrlib/`** | **Raster graphics library** — image loading, scaling, gradients, format codecs | ~9k | | **`wmlib/`** | Tiny helper library for external apps to talk to the WM (menus, events) | ~500 | | **`WPrefs.app/`** | Preferences GUI application (uses WINGs) | ~15k | | **`util/`** | CLI utilities: `wmsetbg`, `wmagnify`, `wmiv`, `getstyle`, `setstyle`, etc. | ~7k | | **`WindowMaker/`** | Runtime data: default menus, themes, icon sets, pixmaps (no code) | — | | **`doc/`** | Documentation | — | | **`po/`** | Translations (gettext) | — | ## 1. The Core — `src/` This is the window manager itself. The biggest files reveal the hotspots: | File | LOC | Responsibility | |---|---|---| | `dock.c` | 4884 | Dock & clip (app launcher bar) | | `defaults.c` | 3470 | Reading/writing the defaults database (user prefs) | | `window.c` | 2891 | `WWindow` lifecycle — manage, unmanage, configure | | `moveres.c` | 2448 | Interactive move/resize (rubber-banding, snap) | | `menu.c` | 2410 | Menu data structure, drawing, keyboard navigation | | `actions.c` | 2338 | High-level window actions (maximize, shade, close…) | | `event.c` | 1953 | **Main event loop + dispatch** | | `framewin.c` | 1251 | Frame window (titlebar, buttons, resizebar) drawing | | `icon.c` | 971 | Miniwindow / app icon rendering | | `workspace.c` | 914 | Virtual desktop management | | `screen.c` | 641 | Per-screen state (`WScreen`) init/teardown | | `startup.c` | 645 | `StartUp()` — full WM initialization sequence | | `main.c` | 801 | `main()` — arg parsing, backend selection, enters `EventLoop()` | ### Key Data Structures - **`WScreen`** (`screen.h`, 352 lines) — god object for a physical screen. Holds the root window, stacking lists, colormap, default pixmaps, the dock, the clip, workspace list, and the backend-specific `backend_screen` pointer. - **`WWindow`** (`window.h`) — one per managed client. Contains the `WFrameWindow`, client hints, geometry, state flags. - **`WFrameWindow`** (`framewin.h`) — the decoration frame. Has child `WCoreWindow`s for the titlebar, left/right buttons, and resizebar. - **`WCoreWindow`** (`wcore.h`) — lowest-level wrapper around a native window. Every WM-owned window (frames, icons, menus) is a `WCoreWindow`. Contains a `WObjDescriptor`. - **`WObjDescriptor`** (`WindowMaker.h`) — the **event dispatch target**. Every `WCoreWindow` carries one. It has four function pointers: ```c void (*handle_expose)(WObjDescriptor *sender, WBackendEvent *event); void (*handle_mousedown)(...); void (*handle_enternotify)(...); void (*handle_leavenotify)(...); ``` Plus a `parent_type` / `parent` back-pointer so dispatch can reach the owning `WWindow` or `WMenu`. ## 2. Event Dispatch — `src/event.c` The flow is: ``` main() → StartUp() // init screens, load defaults, manage existing windows → EventLoop() // never returns → wm_backend->event_loop_run() // X11: WINGs event pump (WMNextEvent + WMHandleEvent) // Wayland: wl_display_run() ``` Inside the X11 path, each event ends up at: ``` DispatchEvent(WMEvent *event) → switch (event->type) WME_MAP_REQUEST → handleMapRequest() WME_KEY_PRESS → handleKeyPress() WME_BUTTON_PRESS → handleButtonPress() WME_EXPOSE → handleExpose() WME_PROPERTY → handlePropertyNotify() WME_CONFIGURE_REQUEST → handleConfigureRequest() ... ``` Most handlers look up the target window via `wm_backend->context_find(win, WM_CTX_CLIENT_WIN)` to get the `WObjDescriptor`, then call its function pointers (e.g., `desc->handle_mousedown(desc, event)`). **Signal handling** is also routed through `DispatchEvent` — `SIGTERM` sets `WSTATE_NEED_EXIT`, `SIGHUP` sets `WSTATE_NEED_RESTART`, and the top of `DispatchEvent` checks these flags before processing the event. ## 3. Backend Abstraction — `src/backend/` A **vtable pattern** (`WMBackend` struct, 1915-line header with ~250 function pointer slots) with a single global pointer: ```c extern const WMBackend *wm_backend; // set in main() before anything else ``` `main.c` picks the backend: ```c wm_backend = &wl_backend; // or wm_backend = &x11_backend; ``` The vtable covers **everything** the display system does: | Category | Example slots | |---|---| | Display lifecycle | `display_open`, `display_close`, `display_post_open` | | Screen lifecycle | `screen_open`, `screen_init_display`, `screen_close` | | Frame windows | `frame_create_toplevel`, `frame_create_child`, `frame_destroy`, `frame_configure`, `frame_paint` | | Context table | `context_save`, `context_find`, `context_delete` | | Event loop | `event_loop_run`, `event_loop_terminate`, `event_sync`, `event_pending` | | Focus & grabs | `focus_set`, pointer/keyboard grab | | Atoms & properties | `atom_intern`, property get/set | Implementations: - **`backend/x11/x11_backend.c`** (4998 lines) — wraps Xlib calls - **`backend/wayland/wl_backend.c`** (10109 lines) — wlroots compositor - **`backend/x11/x11_event.c`** — X11-specific event translation - **`backend/x11/x11_props.c`** — X11 property helpers - **`backend/x11/x11_monitor.c`** — Xinerama/XRandR monitor detection - **`backend/x11/wmspec.c`** (2015 lines) — EWMH / `_NET_WM_*` compliance - **`backend/x11/xdnd.c`** (323 lines) — X11 drag-and-drop protocol The event type itself is backend-neutral: `WMEvent` / `WBackendEvent` defined in `WINGs/WINGs/WMEvent.h` with an enum (`WME_KEY_PRESS`, `WME_BUTTON_PRESS`, `WME_MAP_REQUEST`, etc.). ## 4. WINGs — Widget Library (`WINGs/`) Two sub-libraries in one directory: ### WINGs widgets (`WINGs/WINGs/WINGs.h`, 1933 lines) Full GUI toolkit with an NeXTSTEP flavor: | Widget file | What | |---|---| | `wwindow.c` | Top-level windows | | `wbutton.c` | Buttons | | `wtextfield.c` | Single-line text input | | `wtext.c` | Multi-line rich text (3998 lines — the biggest widget) | | `wlist.c` | List boxes | | `wbrowser.c` | Column browser (NeXT-style) | | `wscroller.c` / `wscrollview.c` | Scrollbars and scroll containers | | `wslider.c` | Sliders | | `wpopupbutton.c` | Popup/dropdown buttons | | `wcolorpanel.c` | Color picker panel | | `wcolorwell.c` | Color swatch | | `wfontpanel.c` | Font chooser | | `wfilepanel.c` | Open/save file dialogs | | `wtabview.c` | Tab views | | `wsplitview.c` | Split panes | | `wruler.c` | Text ruler | | `wframe.c` | Group boxes | | `wlabel.c` | Labels | | `wballoon.c` | Tooltip balloons | | `wpanel.c` | Alert/input panels | Core plumbing: - **`wview.c`** / `wview_wl.c` / `wview_x11.c` — the view hierarchy (WINGs' equivalent of a "widget base class") - **`wevent.c`** / `wevent_wl.c` / `wevent_x11.c` — WINGs event handling - **`wrender_wl.c`** / `wrender_x11.c` — rendering backend split - **`wfont.c`** / `wfont_wl.c` / `wfont_x11.c` — font rendering split - **`wcolor.c`** / `wcolor_wl.c` / `wcolor_x11.c` — color allocation split ### WUtil (`WINGs/WINGs/WUtil.h`, 959 lines) Utility library used everywhere: - `array.c`, `bagtree.c`, `hashtable.c`, `tree.c` — data structures - `proplist.c` — NeXTSTEP-style property list parser (used for defaults database) - `notification.c` — notification center - `userdefaults.c` — user defaults system - `findfile.c`, `string.c`, `memory.c`, `misc.c` — general utilities - `handlers.c` — idle/timer handlers - `selection.c` — X selection (clipboard) - `menuparser.c` — menu file parser ## 5. Rendering — `wrlib/` **wrlib** (Window Maker Raster Library) is a standalone image manipulation library: - **Image formats**: PNG, JPEG, TIFF, GIF, XPM, PPM, WebP, ImageMagick (each in `load_*.c` / `save_*.c`) - **Operations**: `scale.c`, `rotate.c`, `flip.c`, `gradient.c`, `convolve.c`, `draw.c`, `alpha_combine.c` - **Display bridge**: `convert.c` / `convert_x11.c` / `convert_wl.c` — converts `RImage` to display-system pixmaps - **Context**: `context.c` — `RContext` wraps the display connection + visual for rendering The WM core uses wrlib for all texture/icon rendering (via `texture.c` and `icon.c` in `src/`). ## 6. Rendering in the WM Core — `src/texture.c`, `src/framewin.c` - **`WTexture`** (`texture.h`) is a union of solid color, gradients, and pixmap-based textures. `wTextureRender()` / `wTextureRenderImage()` produce `Pixmap`s or `RImage`s from these. - **`framewin.c`** paints the actual window decorations — titlebar, buttons, resizebar — using textures. The backend vtable's `frame_paint()` slot allows the Wayland backend to override the entire paint path. - **`WPixmap`** (`pixmap.h`) is a simple image+mask pair used for icons and button pixmaps. ## 7. Stacking `stacking.c` / `stacking.h` — manages the window stacking order using **window levels** (defined in `WindowMaker.h`): ``` WMBackLevel → WMDesktopLevel → WMNormalLevel → WMFloatingLevel → WMDockLevel → WMSubmenuLevel → WMMainMenuLevel → WMFullscreenLevel → WMPopUpLevel → ... ``` ## 8. Supporting Programs - **`WPrefs.app/`** — full preferences editor. Each `*.c` file is a preference panel (Appearance, Focus, Docks, Icons, Keyboard, Mouse, etc.). Uses WINGs widgets. - **`util/`** — CLI tools: `wmsetbg` (set background), `wmagnify` (screen magnifier), `wmiv` (image viewer), `getstyle`/`setstyle` (theme import/export), `wmgenmenu`/`wmmenugen` (auto-generate menus from `.desktop` files). ## Dependency Graph ``` ┌─────────────────────────────────────────────────────┐ │ WPrefs.app │ │ util/ │ └──────────────┬──────────────────┬───────────────────┘ │ │ ▼ ▼ ┌──────────────────┐ ┌─────────────────┐ │ WINGs widgets │ │ src/ (WM core)│ │ WINGs/w*.c │ │ policy + layout│ └───────┬──────────┘ └──┬──────────────┘ │ │ │ ┌─────────────┘ ▼ ▼ ┌──────────────────┐ ┌─────────────────────────┐ │ WUtil │ │ src/backend/ │ │ (data structs, │ │ backend.h vtable │ │ proplist, etc) │ │ ┌─────────┬───────────┐ │ └───────┬──────────┘ │ │ x11/ │ wayland/ │ │ │ │ └─────────┴───────────┘ │ ▼ └────────────┬──────────────┘ ┌──────────────────┐ │ │ wrlib │◄────────────────┘ │ (image loading, │ │ rendering) │ └──────────────────┘ ``` ## Key Architectural Patterns 1. **Vtable backend abstraction** — all display-system calls go through `wm_backend->*()`. Policy code never calls Xlib directly. 2. **Context-table dispatch** — native window → `WObjDescriptor` lookup via `context_find()`. This is how events reach the right object. 3. **`WObjDescriptor` function pointers** — per-object event handlers (expose, mousedown, enter, leave). This is the closest thing to polymorphic dispatch in the codebase. 4. **Flat C module structure** — no deep directory nesting. Each `src/*.c` file is a module with a matching `.h`. Dependencies are explicit `#include`s. 5. **Three rendering layers**: wrlib (`RImage` manipulation) → `WTexture` (WM-level texture descriptions) → `framewin.c` / `icon.c` (actual decoration painting). 6. **Wayland as a parallel backend** — not a port, but a second implementation behind the same vtable. The `_wl.c` / `_x11.c` file splits in WINGs show this pattern extending into the widget library too.