9.4 KiB
WindowMaker Wayland Port — Roadmap
Current State (2026-05-28, updated)
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 but crashes are still observed — the root cause is WINGs widget library, which still has 412 direct Xlib calls in 15 non-split widget files that bypass the vtable dispatch (see Priority 2).
DND progress: compositor-internal drag-and-drop (WINGs view ↔ WINGs view) is now fully functional. Drag images render as scene-graph overlays, cursor changes to "plus" over valid drop targets. Cross-client DND (external Wayland client ↔ WINGs) has basic wiring in place — accepts drags, tracks motion/drop — but needs MIME type routing to WINGs destination procs to be fully functional.
The smoke test suite passes for core WM features.
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.
- Save/restore state for Wayland native clients:
PropGetWMClassalready returns the XDGapp_idon Wayland. Session save no longer bails whenGetCommandForWindowreturns NULL (external Wayland clients have no ICCCM command). Restore matches byapp_idvia instance+class without requiring a command. - Save/restore works for Wayland native clients (foot). XWayland (xterm) needs WM_COMMAND matching — lower priority.
- 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.
- Copy/paste between native Wayland clients — works
- Copy/paste between XWayland and native clients — works
- Primary selection (middle-click paste) — works (both directions)
1.4 Remaining Vtable Stubs
| Slot | Status |
|---|---|
overlay_draw_* |
✅ Done — real pixman overlay implementation |
client_snapshot |
❌ Stub — needs last-committed texture → RImage |
window_set_border |
✅ No-op (borders drawn into frame buffer) |
client_synth_configure |
✅ Done — XDG configure + XWayland configure |
pointer_change_grab |
⚠️ No-op — menu tracking may need this |
Priority 2: WPrefs.app Full Port
Status: Direct X11 Calls Resolved
All 11 direct Xlib calls previously reported in WPrefs.app have been audited:
| File | Previously Reported | Actual Status |
|---|---|---|
TexturePanel.c |
7 calls | 0 active — all inside #if 0 dead code blocks |
Expert.c |
1 (XGetDefault) | 0 active — call already removed |
MouseSettings.c |
1 (XChangePointerControl) | 0 active — call already removed |
xmodifier.c |
1 (XGetModifierMapping) | 0 active — only in a comment |
WPrefs.app itself now has zero direct Xlib calls. The crash source is in WINGs widget library, which WPrefs links against.
Root Cause: WINGs X11 Leaks (412 calls)
WINGs still has 412 direct Xlib calls across 15 non-split widget files that
bypass the 5-vtable dispatch (W_ViewBackend, W_EventBackend, W_RenderBackend,
W_FontBackend, W_ColorBackend). These are the crash sites when WPrefs calls
WINGs APIs on the Wayland path.
| WINGs File | X11 Calls | What It Does |
|---|---|---|
wcolorpanel.c |
89 | Pixmap manipulation, XGetImage, pointer grabs, cursor recoloring |
dragsource.c |
45 | XDND protocol (XSendEvent, XInternAtom, grabs) |
wwindow.c |
41 | ICCCM window properties (XSetWMName, XSetWMHints, etc.) |
winputmethod.c |
40 | XIM/XIC lifecycle (XOpenIM, XCreateIC, XLookupString) |
dragdestination.c |
37 | XDND protocol (receive side) |
widgets.c |
35 | Screen init, GC/cursor creation, modifier mapping |
wballoon.c |
28 | Tooltip drawing, shape extension |
wtext.c |
23 | Clipboard, grabs |
selection.c |
21 | X selection protocol |
dragcommon.c |
16 | XDND shared atom/property helpers |
wappresource.c |
15 | App icon property reading |
wtextfield.c |
10 | Clipboard, grabs |
wpopupbutton.c |
7 | Pointer grabs |
wruler.c |
3 | XRectangle type usage |
wmisc.c |
2 | Coordinate translation |
These files need backend abstraction — either routing through the existing 5 vtables, or adding new vtables for DND, selection, and input methods.
WINGs Porting Strategy
-
DND subsystem (
dragsource.c+dragdestination.c+dragcommon.c, 2437 LOC, 98 calls) — done. Compositor-internal DND fully functional (drag image, cursor feedback, hit-testing via W_FindViewAtPoint, modal drag loop in wl_drag_begin). Cross-client DND (wl_data_device) has basic wiring — needs MIME type → WINGs type routing to complete. -
wcolorpanel.c(3556 LOC, 89 calls) — done. Split into three files:wcolorpanel.c(backend-neutral, 2997 lines),wcolorpanel_x11.c(X11 magnifying glass, 601 lines),wcolorpanel_wl.c(Wayland stub). Magnify button shows "not available" dialog on Wayland. All 89 X11 calls isolated towcolorpanel_x11.c.
-
wwindow.c+widgets.c(1849 LOC, 76 calls) — window property management needs backend dispatch (ICCCM is X11-only; Wayland properties differ). -
winputmethod.c(243 LOC, 40 calls) — replace XIM/XIC withzwp_text_input_v3or use xkbcommon directly. -
selection.c(392 LOC, 21 calls) — replace X selection protocol withwl_data_device/zwp_primary_selection_v1. -
wballoon.c(476 LOC, 28 calls) — route drawing throughW_RenderBackend. -
wtext.c+wtextfield.c(5577 LOC, 33 calls) — route clipboard and grabs through backends.
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 |