windowmaker-wl/ARCHITECTURE.md

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-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 WCoreWindows 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:

    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:

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 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 Pixmaps or RImages 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 #includes.

  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.