6.0 KiB
WindowMaker Wayland Port — Roadmap
Current State (2026-05-26)
The backend abstraction is complete. The src/ policy layer has zero direct Xlib
calls and zero _x11_raw references. The Wayland backend (wlroots-based, 10K lines)
implements all core window management: stacking, maximize, shade, workspaces,
alt-tab, dock/clip, menus, move/resize, focus, and frame rendering.
WPrefs.app launches on Wayland. WINGs shared widget code has zero X11 executing on the Wayland path. The smoke test suite passes.
What remains is feature completion and production hardening.
Priority 1: Daily-Driver Gaps
These block using the Wayland backend as a primary desktop.
1.1 Session Persistence
src/session.c (614 lines) — verify save/restore works on Wayland. Window
positions are tracked in WWindow (backend-neutral). The only concern is
matching restored sessions to native XDG clients via app_id instead of
WM_CLASS.
- Test: save session, restart compositor, verify window positions restored
- Add
app_idto session file alongsideWM_CLASSfor native XDG clients - Verify dock state persistence (icon layout in
~/GNUstep/Defaults/)
1.2 Multi-Monitor
Currently single-output only. wlroots provides wlr_output_layout and
new_output signal.
- Populate
WScreen.heads[]fromwlr_output_layout_get_boxinscreen_open - Handle output hotplug (migrate windows on disconnect)
- Per-head usable area calculation (dock margins)
- Test with nested multi-output (
WMAKER_WAYLAND_NESTED=1+wlr-randr)
1.3 Clipboard
wlroots advertises wl_data_device_manager and zwp_primary_selection_v1.
XWayland bridge auto-syncs. Needs verification.
- Test copy/paste between native Wayland clients
- Test copy/paste between XWayland and native clients
- Test primary selection (middle-click paste)
1.4 Remaining Vtable Stubs
These vtable slots are stubs or partial implementations:
| Slot | Purpose | Needed For |
|---|---|---|
overlay_draw_* |
Pixman animation buffer | Iconify zoom animation |
client_snapshot |
Window thumbnail capture | Switch panel thumbnails, icon preview |
window_set_border |
Scene rect border nodes | Window borders |
client_synth_configure |
XDG configure scheduling | Resize negotiation |
pointer_change_grab |
Grab parameter update | Menu tracking |
Priority 2: WPrefs.app Full Port
WPrefs launches but still has 11 direct Xlib calls in 4 files. These are small and mechanical:
| File | Calls | What |
|---|---|---|
TexturePanel.c |
7 | Preview window (XCreateSimpleWindow, XCopyArea, XFillRectangle, XOpenDisplay) |
Expert.c |
1 | XGetDefault for X11 resource query |
MouseSettings.c |
1 | XChangePointerControl |
xmodifier.c |
1 | XGetModifierMapping |
The TexturePanel.c preview window is the only substantial item — it creates
a raw X11 window to preview textures. Replace with a WINGs pixmap widget.
- TexturePanel.c: replace X11 preview window with WINGs
WMLabel+ pixmap - Expert.c: guard
XGetDefaultwithif (dpy) - MouseSettings.c: route through backend or use libinput
- xmodifier.c: already has XKB fallback path, verify it works
Priority 3: Visual Completeness
3.1 Iconify/Deiconify Zoom Animation
The X11 path uses XOR GC rubber-band rectangles (XGrabServer + XDrawRectangle).
On Wayland, implement as per-frame pixman overlay buffer.
- Implement
overlay_draw_rectin wl_backend.c using a transientwlr_scene_buffer - Wire
animateResize()in actions.c to use the vtable
3.2 Client Snapshot (Window Thumbnails)
Used by switch panel and icon preview. X11 uses XGetImage. Wayland options:
-
Render last committed
wlr_textureinto an RImage via pixman blit -
Use
wlr_screencopy_manager_v1 -
Implement
client_snapshotvtable slot using last-committed texture
3.3 Window Inspector
src/winspector.c — WINGs-based dialog. Should work on Wayland since WINGs
widgets are ported. Needs testing.
- Test window inspector opens and displays attributes
- Test attribute changes apply correctly
Priority 4: HiDPI & Scaling
- Set
wlr_output_set_scaleper output - Multiply pixman buffer allocations by scale factor
- Set PangoFT2 DPI from
output.scale * 96.0 - Ensure
WScreen.width/heightremain logical coordinates - Test at 2x scale
Priority 5: Protocol Wiring
wlroots already advertises these protocols. Wire them to policy:
| Protocol | Purpose | Effort |
|---|---|---|
ext-session-lock-v1 |
Screen lock | Medium |
xdg_activation_v1 |
Focus stealing prevention | Low |
zwp_idle_inhibit_manager_v1 |
Prevent blank during video | Low |
ext-foreign-toplevel-list-v1 |
Taskbar integration | Low |
zwp_input_method_v2 |
IME support | Medium |
wlr_gamma_control_v1 |
Night light | Low |
Priority 6: DRM/KMS Native Backend
For running without a host compositor:
- Use
wlr_backend_autocreate(replaces headless/nested) - libinput for real hardware input (wlroots handles this)
- VT switching via
wlr_session - Test on real hardware
Architecture Notes
- Rendering pattern: pixman_image_t → wlr_scene_buffer → scene graph position
- Event flow: wlroots signals → wl_backend.c handlers → WMEvent → DispatchEvent
- WINGs on Wayland: compositor-internal views (not wl_surfaces), pixman-rendered, events via ring buffer from compositor hit-testing
- wl_backend.c (420K) should be split into wl_frame.c, wl_menu.c, wl_input.c, wl_toplevel.c, wl_output.c as complexity grows
Reference Documents
| Document | Purpose |
|---|---|
ARCHITECTURE.md |
Codebase structure, data flow, key types |
BACKEND_ABSTRACTION.md |
Historical analysis of X11 leaks (all resolved) |
X11_IMPLEMENTATION.md |
How X11 path works (correctness reference) |
ACTION_PLAN_PROMPTS.md |
Task templates for mechanical porting work |
tools/wm-port/ |
Agent-assisted task dispatch tooling |