12 KiB
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-specificbackend_screenpointer. -
WWindow(window.h) — one per managed client. Contains theWFrameWindow, client hints, geometry, state flags. -
WFrameWindow(framewin.h) — the decoration frame. Has childWCoreWindows 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 aWCoreWindow. Contains aWObjDescriptor. -
WObjDescriptor(WindowMaker.h) — the event dispatch target. EveryWCoreWindowcarries one. It has four function pointers:void (*handle_expose)(WObjDescriptor *sender, WBackendEvent *event); void (*handle_mousedown)(...); void (*handle_enternotify)(...); void (*handle_leavenotify)(...);Plus a
parent_type/parentback-pointer so dispatch can reach the owningWWindoworWMenu.
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:
extern const WMBackend *wm_backend; // set in main() before anything else
main.c picks the backend:
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 callsbackend/wayland/wl_backend.c(10109 lines) — wlroots compositorbackend/x11/x11_event.c— X11-specific event translationbackend/x11/x11_props.c— X11 property helpersbackend/x11/x11_monitor.c— Xinerama/XRandR monitor detectionbackend/x11/wmspec.c(2015 lines) — EWMH /_NET_WM_*compliancebackend/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 handlingwrender_wl.c/wrender_x11.c— rendering backend splitwfont.c/wfont_wl.c/wfont_x11.c— font rendering splitwcolor.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 structuresproplist.c— NeXTSTEP-style property list parser (used for defaults database)notification.c— notification centeruserdefaults.c— user defaults systemfindfile.c,string.c,memory.c,misc.c— general utilitieshandlers.c— idle/timer handlersselection.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— convertsRImageto display-system pixmaps - Context:
context.c—RContextwraps 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()producePixmaps orRImages from these.framewin.cpaints the actual window decorations — titlebar, buttons, resizebar — using textures. The backend vtable'sframe_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*.cfile 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.desktopfiles).
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
-
Vtable backend abstraction — all display-system calls go through
wm_backend->*(). Policy code never calls Xlib directly. -
Context-table dispatch — native window →
WObjDescriptorlookup viacontext_find(). This is how events reach the right object. -
WObjDescriptorfunction pointers — per-object event handlers (expose, mousedown, enter, leave). This is the closest thing to polymorphic dispatch in the codebase. -
Flat C module structure — no deep directory nesting. Each
src/*.cfile is a module with a matching.h. Dependencies are explicit#includes. -
Three rendering layers: wrlib (
RImagemanipulation) →WTexture(WM-level texture descriptions) →framewin.c/icon.c(actual decoration painting). -
Wayland as a parallel backend — not a port, but a second implementation behind the same vtable. The
_wl.c/_x11.cfile splits in WINGs show this pattern extending into the widget library too.