windowmaker-wl/ROADMAP.md

9.3 KiB

WindowMaker Wayland Port — Roadmap

Current State (2026-05-28, final)

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.

WINGs X11 call isolation is complete. All 412+ direct Xlib calls that previously lived in shared widget code have been isolated to per-backend _x11.c files with Wayland stubs in wstubs_no_x11.c. The remaining work is feature implementation, not leak cleanup.

What works on Wayland:

  • Window management (stacking, maximize, shade, workspaces, alt-tab, move/resize)
  • DND (compositor-internal with drag image overlay + cursor feedback; cross-client via wl_data_device with basic MIME routing)
  • Clipboard + primary selection (copy/paste between Wayland native and XWayland)
  • Session persistence (save/restore for native Wayland clients)
  • Balloon tooltips (proper leave tracking + multi-line text)
  • Window thumbnails (client_snapshot via buffer read)
  • XWayland client support (DISPLAY=:1 via eager mode startup)
  • WPrefs.app (all preference panels — crashes fixed by X11 call isolation)

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: PropGetWMClass already returns the XDG app_id on Wayland. Session save no longer bails when GetCommandForWindow returns NULL (external Wayland clients have no ICCCM command). Restore matches by app_id via 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[] from wlr_output_layout_get_box in screen_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 ✅ Done — buffer read for native, XGetImage for XWayland
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 X11 Call Isolation — COMPLETE

All 412+ direct Xlib calls in WINGs have been isolated to _x11.c backend files. No active X11 calls remain in non-backend WINGs source files.

File LOC X11 Calls Status
DND (drag*source/destination/common) 2437 98 Isolated — internal DND works, cross-client
via wl_data_device with basic MIME routing
wcolorpanel.c 3556 89 Split into wcolorpanel.c + _x11.c + _wl.c
wwindow.c + widgets.c 1849 76 Already clean — all via vtable dispatch
winputmethod_x11.c 243 40 Isolated — Wayland stub in wstubs_no_x11.c
selection_x11.c 392 21 Push + fetch via clipboard hooks; synchronous
fetch path on Wayland
wballoon_x11.c 476 28 Wayland balloon_draw in wview_wl.c renders
yellow tooltip with multi-line support
wtext.c + wtextfield.c 5577 33 Already clean — all via vtable dispatch
All other _x11.c files ~2000 ~27 Isolated — stubs in wstubs_no_x11.c

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_rect in wl_backend.c using a transient wlr_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_texture into an RImage via pixman blit

  • Use wlr_screencopy_manager_v1

  • Implement client_snapshot vtable 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_scale per output
  • Multiply pixman buffer allocations by scale factor
  • Set PangoFT2 DPI from output.scale * 96.0
  • Ensure WScreen.width/height remain 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