Commit Graph

30 Commits

Author SHA1 Message Date
Window Maker d79f7b5243 arch: widen final void* vtable signatures to WMEvent*; event.c is _x11_raw-free
Three more vtable slots that took void* (intended for an XEvent*) widened
to take WMEvent*; the X11 impls extract _x11_raw internally:

  event_handle_extensions(WMEvent*)
  netwm_process_client_message(WMEvent*)
  xdnd_process_client_message(WMEvent*)

Also added a new client_message_forward(WMEvent*, WNativeWindow) slot for
the OffiX DND ClientMessage redirect (icon frame -> real client_win).
The X11 backend rewrites xclient.window and XSendEvent's it; the Wayland
backend does the same on wl_state.x_display for XWayland clients.

After this change, src/event.c contains zero _x11_raw references — the
last X11 escape from the shared event dispatch layer is closed.
2026-05-24 08:49:44 +02:00
Window Maker 60d71f46b4 arch: usermenu key send through vtable; drop dead misc.c code
* usermenu.c notifyClient: replace XSendEvent KeyPress/KeyRelease
  synthesis with two wm_backend->client_send_key calls.

* New vtable slot client_send_key(win, keycode, modifier_mask, press).
  X11: synthesize XKeyEvent and XSendEvent.
  Wayland: same but on wl_state.x_display (XWayland clients).  Native
           Wayland clients deferred (would need
           zwp_virtual_keyboard_v1).

* misc.c: keysymToString was dead code inside #if 0 — removed.

After this change misc.c and usermenu.c carry zero direct Xlib calls.
2026-05-24 08:46:03 +02:00
Window Maker 1c1f261fb2 arch: eliminate _x11_raw escapes from event.c
Five _x11_raw accesses in shared event.c (the worst architectural leak)
removed by widening vtable signatures and moving X11-only logic into
the X11 backend:

  WME_SELECTION_REQUEST / WME_SELECTION_CLEAR
    * handle_selection_request/clear functions deleted from event.c
    * Reimplemented in x11_backend.c as x11_handle_selection_request/clear
      where they read _x11_raw internally and call XChangeProperty etc.
    * New vtable slots handle_selection_request / handle_selection_clear
      (WMEvent*).  Wayland: no-ops (wmaker UI does not own a WM_Sn
      selection on the X server).

  WME_CONFIGURE
    * event_randr_update vtable widened to (WMEvent*).
    * Root-window check (DefaultRootWindow) moved into x11 impl.

  WME_MAPPING
    * Dropped the if (xev) guard — keyboard_mapping_refresh already
      took WMEvent*.

  WME_SELECTION
    * xdnd_process_selection vtable widened to (WMEvent*).

Net: event.c is X11-free except for DefaultRootWindow uses elsewhere
that will be cleaned up in subsequent tasks.
2026-05-24 08:37:50 +02:00
lkn de0300d0fe A4: workspace switching badge for Wayland backend
Workspace switching (map/unmap) already worked via the vtable.
This commit adds the workspace name badge overlay:

- Create badge frame_buf in WL_LAYER_OVERLAY during screen init
- Implement wl_workspace_badge_render (pixman text rendering)
- Implement wl_workspace_badge_update (scene buffer refresh)
- Add workspace_badge_get_background vtable slot
- X11 backend: captures root window background (RGetXImage)
- Wayland backend: returns solid dark background
- workspace.c: replace direct RGetXImage/RCreateImageFromXImage
  with vtable call (zero backend guards in policy code)
2026-05-23 13:24:58 +02:00
Window Maker 245d0077b5 wayland: implement correct stacking model with scene-graph level trees
Three interlocking problems were present in the Wayland stacking
implementation.

1. Wrong scene-graph nodes targeted by stacking operations

Each managed window groups its frame pixels and client surface under a
single wlr_scene_tree (fb->tree):

  fb->tree
    fb->scene_buf       (frame decoration pixels)
    child_frame_bufs    (titlebar / resizebar sub-frames)
    v->scene_node       (client surface, reparented in)

wl_stacking_restack was raising fb->scene_buf -- a child inside fb->tree
-- instead of fb->tree itself, a no-op for inter-window ordering. Three
redundant loops then tried to separately raise the client surface and child
frames, also to no effect. wl_stacking_lower had the same bug.

Fix: raise/lower fb->tree in both functions so the entire window assembly
moves as one atomic unit.

2. Flat scene graph -- no structural level ordering

All nodes were direct children of scene->tree, so creation order and
raise_to_top calls determined Z-order. A normal window could accidentally
render above a floating window after any CommitStacking call.

Fix: introduce 9 wlr_scene_tree level buckets created at scene init time
in bottom-to-top order:

  0 WL_LAYER_BACKGROUND  background rect / wallpaper
  1 WL_LAYER_DESKTOP     WMDesktopLevel
  2 WL_LAYER_SUNKEN      WMSunkenLevel
  3 WL_LAYER_NORMAL      WMNormalLevel  (default for new frames)
  4 WL_LAYER_FLOATING    WMFloatingLevel / WINGs dialogs
  5 WL_LAYER_MENU        WMMainMenuWindowLevel / OR-redirect windows
  6 WL_LAYER_DOCK        WMStatusWindowLevel / dock panel surface
  7 WL_LAYER_FULLSCREEN  WMFullscreenLevel
  8 WL_LAYER_OVERLAY     WMModalPanel / WMPopUp / XOR overlay

Every scene node is assigned to the correct bucket at creation.
A new stacking_set_level vtable slot called from AddToStackList moves
fb->tree to the right bucket whenever a window is added or its level
changes via ChangeStackingLevel. X11 backend implements it as a no-op.

3. XDG client surface not reparented into fb->tree

For XDG toplevels the map handler called wManageWindow before creating
view->scene_node, so the reparent inside wl_client_reparent was a no-op.
The client surface then lived as a flat sibling of fb->tree in
WL_LAYER_NORMAL, never moving with its frame during stacking operations.

Fix: after creating view->scene_node, check if frame_id is already set
and do the deferred reparent immediately.

4. Hit-testing broken by level-tree hierarchy

frame_buf_at walked up from the hit scene node to the first direct child
of scene->tree. With level buckets that stopped at the level_tree node
instead of fb->tree, making every window in the same bucket appear to be
the same window. Client surfaces were not blocking clicks on frames
beneath them, and titlebar sub-frames were not distinguished from the
top-level frame, breaking move and resize initiation.

Fix: rewrite frame_buf_at with a two-pass approach:
  Pass 1 -- exact match: check if the topmost node is a child frame_buf
    scene_buf such as titlebar, resizebar, or button; return it directly.
  Pass 2 -- walk up stopping when parent is a level_tree bucket, then
    match that window-root node to a top-level frame_buf tree.
  Return NULL if the hit was on a client surface.

ROADMAP: mark A1 done.
2026-05-15 09:11:46 +02:00
lkn 98f3175895 wl_backend: fix client resize and frame lifecycle
- Send frame_done after configure so clients can render at new size
- Set activated state on toplevel configure
- Dispatch idle callbacks to flush configure immediately
- Add client_set_maximized vtable entry for XDG toplevel state
- Re-enable frame_buf scene node on unshade
- Raise client scene node on window_map (fixes unshade visibility)
- Reposition client and children in frame_configure
- Schedule output frame after frame_paint
- Remove debug wwarnings from wl_window_resize

This fixes:
- Window shade/unshade (resizebar + client surface visibility)
- Client surface receiving configure events and rendering
- Frame decoration updates on resize/maximize
2026-05-14 23:08:37 +02:00
Levi Neely 4be05c799c Phase 84: eliminate all backend guards from policy code
Remove every is_wayland / !is_wayland guard from WM policy files.
All backend-specific logic now lives exclusively in the backends:

- main.c: display_post_open vtable slot handles fatal check, visual ID,
  display name, and multiHead parsing (X11) or no-ops (Wayland)
- event.c: EventLoop() unconditionally calls event_loop_run(); the X11
  backend's implementation contains the WMNextEvent+inotify loop
- screen.c: screen_init_display vtable slot handles RContext/WMScreen/
  color creation (each backend owns its full init path)
- monitor.c: show_crash_dialog vtable slot (X11 shows panel, Wayland
  returns abort)
- startup.c: InitializeSwitchMenu called unconditionally (it's
  backend-agnostic); defaults polling timer no longer guarded
- shutdown.c: wScreenSaveState called unconditionally
- window.c: client_reparent called unconditionally (Wayland no-ops);
  dead frameless-window code removed

Policy code is now completely backend-agnostic. The only references to
is_wayland are the vtable field definitions in the two backend files.
2026-05-14 12:41:01 +02:00
Levi Neely b4484e05bc Fix Wayland startup: compositor window appears and event loop runs
Three root causes fixed:

1. RCreateContext crash: wScreenInit called RCreateContext(dpy=NULL).
   Fix: add RCreateContextWayland() to wrlib — creates a minimal 32-bit
   ARGB context without X11. Wayland path in screen.c now always taken
   when is_wayland (removed incorrect XWayland fallthrough).

2. Color parsing: parse_color and get_color_for_colormap were no-ops.
   Fix: implement real color parser in wl_backend supporting #RGB,
   #RRGGBB, #RRRRGGGGBBBB, rgb:RR/GG/BB, and common named colors.
   Texture creation (solid, gradient) now works in Wayland mode.

3. RConvertImage crash: wrlib tried XCreateImage with NULL display.
   Fix: RConvertImage/RConvertImageMask return success with pixmap=0
   when context->dpy is NULL. Callers don't use pixmaps in Wayland
   mode (rendering goes through vtable slots to pixman buffers).

4. Workspace crash: Wayland path skipped wWorkspaceNew(), so
   workspace_count=0 when menu tried to access workspace entries.
   Fix: add wWorkspaceNew + netwm_init to Wayland screen init path.

Result: compositor starts, event loop runs, window is visible.
WMAKER_USE_WAYLAND=1 wmaker now shows a compositor window.
2026-05-13 13:51:27 +02:00
Levi Neely 9c48a0c841 Phase 80t: ZERO X11 symbols in policy files — architecture complete
- wmspec.c, xdnd.c, xmodifier.c: pure X11 mechanism code now compiled
  as part of x11_backend.o (included via #include in x11_backend.c).
  Removed from main link (Makefile modified).
- Policy file calls to NETWM/XDND functions replaced with vtable dispatch:
  netwm_process_client_message, xdnd_process_client_message,
  xdnd_process_selection, xdnd_make_awareness,
  netwm_check_client_hint_change, netwm_position_splash,
  netwm_check_initial_frame_state
- x11_prop_get_check_property now returns wfree-able memory (callers
  use wfree instead of XFree)

RESULT: nm -u *.o | grep ' U X' returns ZERO for all non-backend .o files.
The backend abstraction is architecturally complete.
2026-05-13 13:03:14 +02:00
Levi Neely ae499aae87 Phase 80s: clean X11 from menu.c, misc.c
- menu.c: wMenuPaintEntry (172 lines of X11 rendering) replaced with
  vtable dispatch; wMenuDrawFrame inlined into x11_backend;
  XGrabPointer/XGrabKeyboard -> pointer_grab/keyboard_grab;
  XQueryPointer -> pointer_get_position; XLookupKeysym -> keysym_from_keycode
- misc.c: slide_window/slide_windows XMoveWindow -> window_move;
  wGetTextSelection (X11 selection protocol) -> get_text_selection vtable;
  XKeysymToString -> keysym_to_string; XGetCommand -> window_get_command;
  XFree -> wfree (x11_prop_get_check_property now copies to wfree-able mem)

New vtable slots: pointer_get_position, keysym_to_string, window_get_command.
x11_prop_get_check_property now returns wfree-able memory (copies from X11).
Both files verified X11-free with nm.
2026-05-13 12:55:58 +02:00
Levi Neely f1df339f10 Phase 80r: clean X11 from dialog.c
- XCreateSimpleWindow/XReparentWindow (7 pairs) -> fake_leader_create/client_reparent
- XLookupKeysym/XLookupString -> keysym_from_keycode
- XFillRectangle/XDrawLine/XCopyArea/XSetClipMask/XSetClipOrigin ->
  new dialog_paint_icon vtable slot
- XSetInputFocus -> focus_set (existing slot)

New vtable slot: dialog_paint_icon.
dialog.o verified X11-free with nm.
2026-05-13 12:42:18 +02:00
Levi Neely 937a0c2a3a Phase 80q: clean X11 from event.c
- XAllowEvents -> event_allow_async / event_replay_pointer
- XRefreshKeyboardMapping -> keyboard_mapping_refresh
- XCheckTypedWindowEvent -> event_check_window / event_flush_window
- XCheckTypedEvent -> event_check_type / event_flush_type
- XGetGeometry (existence check) -> window_exists
- XGetWindowAttributes (colormap) -> window_get_colormap
- XQueryPointer -> pointer_query_window
- XSendEvent -> client_send_event
- XWarpPointer -> pointer_warp_to (existing)
- XInstallColormap -> colormap_install (existing)

New vtable slots: event_allow_async, event_replay_pointer,
keyboard_mapping_refresh, event_flush_window, event_flush_type,
event_check_window, event_check_type, client_send_event,
window_exists, window_get_colormap, pointer_query_window.
event.o verified X11-free with nm.
2026-05-13 12:39:24 +02:00
Levi Neely 69799ccdab Phase 80p: clean X11 from balloon.c, dock.c
- balloon.c: wBalloonInitialize inlined into x11_balloon_init;
  all rendering functions (drawBalloon, makePixmap, showText,
  show_minipreview) removed — balloon_show vtable dispatches rendering.
  WBalloon struct moved to balloon.h for backend access.
- dock.c: wClipIconPaint/wDrawerIconPaint replaced with vtable dispatch;
  paintClipButtons removed; XGrabPointer -> pointer_grab;
  XChangeActivePointerGrab -> pointer_change_cursor;
  XCheckTypedEvent/XPutBackEvent -> event_check_enter_leave;
  XMoveResizeWindow -> frame_configure; XFillRectangle -> window_fill_stipple

New vtable slots: balloon_show, window_fill_stipple, event_check_enter_leave.
Both files verified X11-free with nm.
2026-05-13 12:25:57 +02:00
Levi Neely ea29b109f7 Phase 80n: clean X11 from icon.c
- drawIconTitleBackground (XFillRectangle/XDrawLine) -> icon_paint_title_bg
- cycleColor/wIconSelect (XChangeGC/XDrawRectangle) -> icon_select_paint
- getSize (XGetGeometry) -> pixmap_get_size
- XGetWindowAttributes -> window_get_event_mask
- XGrabPointer -> pointer_grab
- XChangeActivePointerGrab -> pointer_change_cursor
- XReparentWindow -> client_reparent
- XClearArea -> window_clear (existing)
- XFree -> wfree

New vtable slots: icon_paint_title_bg, icon_select_paint,
window_get_event_mask, pixmap_get_size.
icon.o verified X11-free with nm.
2026-05-13 11:42:49 +02:00
Levi Neely 2bb40cf9fa Phase 80m: clean X11 from appicon.c
- wAppIconPaint: X11 rendering (dock dots, corner triangle, stipple)
  moved to new appicon_paint_dock_dots vtable slot
- XGrabPointer -> pointer_grab vtable
- XChangeActivePointerGrab -> new pointer_change_cursor vtable slot
- drawCorner removed (inlined into x11 backend)

New vtable slots: pointer_change_cursor, appicon_paint_dock_dots.
appicon.o verified X11-free with nm.
2026-05-13 11:31:31 +02:00
Levi Neely 40ac4f252b Phase 80l: clean X11 from defaults.c
- XParseColor (9 calls) -> parse_color vtable slot
- XStringToKeysym -> keysym_from_name (existing slot)
- XReadBitmapFile/XQueryColor/XCreatePixmapCursor -> cursor_create_from_files
- XFreeCursor -> cursor_free
- XDefineCursor -> cursor_set
- XUngrabKey -> key_ungrab_all (existing slot)

New vtable slots: parse_color, cursor_create_from_files, cursor_free,
cursor_set.
defaults.o verified X11-free with nm.
2026-05-13 11:27:07 +02:00
Levi Neely 6f1c499b03 Phase 80k: clean X11 from startup.c
- getOffendingModifiers (XGetModifierMapping/XFreeModifiermap) ->
  setup_modifier_lock_masks vtable slot
- wHackedGrabKey (XGrabKey with NumLock/ScrollLock combos) ->
  key_grab_hacked vtable slot
- wHackedGrabButton (XGrabButton with lock combos) ->
  button_grab_hacked vtable slot
- XUniqueContext calls -> context_init vtable slot
- XQueryTree/XFree in wManageAllWindows -> query_tree vtable slot
  (returns wfree-able array)
- XGetWindowAttributes in wScreenForWindow -> screen_for_window vtable
- _NumLockMask/_ScrollLockMask made non-static (needed by x11_backend)

New vtable slots: setup_modifier_lock_masks, key_grab_hacked,
button_grab_hacked, context_init, query_tree, screen_for_window.
startup.o verified X11-free with nm.
2026-05-13 11:24:45 +02:00
Levi Neely 6d4fc32b28 Phase 80j: clean X11 from shutdown.c, framewin.c, properties.c
- shutdown.c: RestoreDesktop/wWipeDesktop/restoreWindows moved entirely
  to x11_backend.c; policy file contains only vtable dispatch stubs
- framewin.c: wFrameWindowPaint restructured — policy logic stays,
  X11 rendering (resizebar lines, titlebar pixmap ops) dispatched through
  new frame_paint_resizebar/frame_paint_titlebar vtable slots
- properties.c: all 6 functions (PropGetProtocols, PropGetCheckProperty,
  PropSetWMakerProtocols, PropSetIconTileHint, PropGetClientLeader,
  PropGetWindowState, PropCleanUp) replaced with vtable dispatch stubs;
  X11 implementations inlined into x11_backend.c

New vtable slots: frame_paint_resizebar, frame_paint_titlebar,
prop_get_client_leader, prop_get_window_state.
All three files verified X11-free with nm.
2026-05-13 11:18:19 +02:00
Levi Neely d2423f360f Phase 80h: clean X11 from rootmenu.c
- XGrabKey/XUngrabKey -> key_grab/key_ungrab_all vtable dispatch
- XStringToKeysym -> new keysym_from_name vtable slot
  (X11: XStringToKeysym, Wayland: xkb_keysym_from_name)
- XDisplayName -> display_get_name vtable
- DefaultVisual/DefaultDepth/WidthOfScreen/HeightOfScreen replaced
  with WScreen struct fields

New vtable slot: keysym_from_name.
rootmenu.o verified X11-free with nm.
2026-05-13 10:59:18 +02:00
Levi Neely e504141132 Phase 80f: clean X11 from client.c, pixmap.c
- client.c: XFree -> wfree (vtable owns allocation), XGetTransientForHint
  -> prop_get_transient_for, XConfigureWindow -> frame_configure/stacking_restack,
  wFetchName -> window_fetch_name
- pixmap.c: wPixmapCreateFromXBMData and wPixmapCreate dispatch through
  new vtable slots pixmap_create_from_xbm and pixmap_create

New vtable slots: pixmap_create_from_xbm, pixmap_create.
Both files verified X11-free with nm.
2026-05-13 10:48:54 +02:00
Levi Neely b72d527ee7 Phase 80d: clean X11 from appmenu, main, switchpanel, window, xutil, texture
New vtable slots: appmenu_send, display_get_name, switchpanel_send_enter,
format_x_error, draw_bevel.

- appmenu.c: sendMessage dispatches through appmenu_send
- main.c: XDisplayName replaced with display_get_name
- switchpanel.c: XSendEvent replaced with switchpanel_send_enter
- window.c: XFree removed (backend owns cmap_windows lifecycle)
- xutil.c: FormatXError moved entirely to x11_backend.c
- texture.c: wDrawBevel dispatches through draw_bevel (done prev commit)

All 5 files verified X11-free with nm.
2026-05-13 10:42:06 +02:00
Levi Neely b8899b4cb8 Move wDrawBevel X11 rendering to backend via draw_bevel vtable slot
texture.c now dispatches through wm_backend->draw_bevel().
X11 backend contains the XDrawSegments implementation.
texture.o verified X11-free with nm.
2026-05-13 10:34:22 +02:00
Levi Neely dfac01a478 Phase 80c: add vtable slots for cross-mode rendering functions
Add vtable slots: icon_select, icon_change_title, clip_icon_paint,
drawer_icon_paint, balloon_init, do_kaboom, menu_paint_entry,
menu_draw_frame.

Replace policy call sites with vtable dispatch. Make paintEntry and
drawFrame in menu.c non-static as wMenuPaintEntry/wMenuDrawFrame.

X11 backend calls the mechanism functions; Wayland backend is no-op.
wFrameWindowPaint now only reached through X11 backend's frame_paint.
2026-05-13 10:24:21 +02:00
Levi Neely 553d2ca0ba Phase 80: eliminate all 43 if(!dpy) return guards via vtable dispatch
Remove every 'if (!dpy) return' guard from policy files by moving
X11 mechanism code behind WMBackend vtable slots. Call sites now
dispatch through wm_backend->slot(), the X11 backend implements the
mechanism, and the Wayland backend provides no-ops or Wayland-native
implementations.

New vtable slots added to backend.h:
- Frame: frame_alloc_border_pixel, frame_update_texture, frame_paint_button
- NETWM: netwm_init, netwm_cleanup, netwm_update_desktop,
  netwm_get_current_desktop, netwm_update_opacity, netwm_update_actions,
  netwm_check_client_hints, netwm_check_initial_state, netwm_get_pid,
  netwm_cleanup_frame_extents
- Properties: prop_get_protocols, prop_get_check_property,
  prop_set_wmaker_protocols, prop_set_icon_tile, prop_cleanup
- Client: client_restore, client_set_state, client_send_protocol,
  client_kill, client_get_colormap_windows
- Misc: eat_expose, move_window, slide_windows, get_text_selection,
  get_shortcut_string, get_command_for_window
- Icon: icon_update_pixmap, icon_paint
- AppIcon: appicon_show, appicon_paint, appicon_bounce
- Shutdown: restore_desktop, wipe_desktop
- Resources: get_color_for_colormap, free_color, colormap_install
- Protocol: xdnd_init, motif_get_hints
- Startup: manage_all_windows
- Event: event_handle_signal_exit

Structural changes:
- MWMHints moved from motif.c local typedef to motif.h
- WProtocols given struct tag for forward declaration
- Static functions made non-static: wGetTextSelection, wGetCommandForWindow,
  wGetMWMHints, wWipeDesktop, wManageAllWindows, wNETWMUpdateWindowOpacity

Verification: grep -rn 'if (!dpy)' src/*.c returns zero results.
nm wl_backend.o confirms no new X11 symbols in Wayland path.
2026-05-13 10:01:57 +02:00
Levi Neely 499d4fac7e Wayland backend: native frame rendering via pixman + wlr_scene_buffer
Architecture: frames are pixman images committed to wlr_scene_buffer
nodes — no XWayland dependency for WM UI rendering.

Key changes:
- Add wl_frame_buf struct (pixman_image_t + wlr_buffer + scene_buffer)
- Implement wlr_buffer_impl for frame buffers (begin_data_ptr_access)
- frame_create_toplevel: allocates pixman buffer + scene node
- frame_create_child: returns synthetic ID (sub-regions of parent)
- frame_configure: repositions scene node, reallocates on resize
- frame_destroy: destroys scene node and drops buffer
- frame_paint: renders titlebar texture (via wTextureRenderImage),
  title text (via WMDrawString on pixman WMDrawable), and resizebar
  into the pixman buffer, then commits to scene graph
- Add frame_paint vtable slot to WMBackend (backend.h)
- wFrameWindowPaint: calls wm_backend->frame_paint first; falls
  through to Xlib code only if backend returns 0
- window_map/unmap/move: handle frame buffers via scene node ops
- stacking_raise/lower: handle frame buffers
- window_get_rect: return frame buffer geometry
- Remove all XWayland calls from frame/window lifecycle

The OR (override_redirect) surface handling remains for XWayland
client windows that use override_redirect (tooltips, menus from
X11 apps). The WM's own UI is now pure Wayland.
2026-05-13 07:15:57 +02:00
Levi Neely 00deab12f2 wayland: WMBackend vtable — port policy files off direct X11
Move X11-specific calls in policy code behind the wm_backend dispatch
table so the same code paths work with both X11 and Wayland backends.

  backend.h    — extend WMBackend vtable with new entry points
  event.c      — route input events through backend dispatch
  framewin.c   — title-bar rendering via backend surface ops
  icon.c       — icon pixmap handling via backend abstraction
  main.c       — backend selection + initialisation at startup
  misc.c       — miscellaneous X11 helpers moved behind vtable
  pixmap.c     — pixmap creation/destruction via backend ops
  resources.c  — resource loading abstracted over backend
  screen.c     — screen setup routed through WMBackend vtable
  startup.c    — startup sequence uses backend entry points
  texture.c    — texture rendering abstracted for both backends

No functional change on X11; Wayland backend stubs return safe no-ops.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 13:34:05 +02:00
Levi Neely fc0e233865 wayland: Phase 46 — client_close vtable; title updates; protocol guards
Add client_close vtable slot to WMBackend:
  - x11: XKillClient + XFlush
  - wl: wlr_xdg_toplevel_send_close (politely asks client to close)
  - wClientKill: use wm_backend->client_close() for Wayland path

Guard wClientSendProtocol with if (!dpy) return so it is safe to call
on Wayland windows (protocols.DELETE_WINDOW is always 0 for Wayland).

Wire XDG toplevel set_title signal: add title_listener to
wl_toplevel_view; handle_toplevel_title updates wwin->wm_class /
wm_instance when the client changes its title, and calls
wWindowUpdateName (which no-ops on frameless windows but posts
WMNChangedName when a frame is present).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-28 06:46:46 +01:00
Levi Neely f7dfc50f26 wayland: Phase 33 — event_loop_run/atom_intern vtable; wmaker starts and exits cleanly under Wayland
Add display_default_screen, atom_intern, and event_loop_run vtable slots.
Guard all X11-only paths in startup.c/screen.c/shutdown.c/event.c/xdnd.c
with if (!dpy) so the Wayland path reaches wl_display_run() and exits
cleanly (exit 0) on SIGTERM.  wl-smoke-test.sh now PASSES.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 23:02:26 +01:00
Levi Neely d07362b90e wayland: Phase 32 — display_open/close/screen_count through vtable
Add three display-lifecycle slots to WMBackend:
  display_open(name)    — open/init display connection, return Display*
                          (NULL for Wayland; compositor init side-effect)
  display_close()       — tear down display connection
  display_screen_count() — number of logical screens

x11_backend: implement with XOpenDisplay (including close-on-exec fcntl),
XCloseDisplay, ScreenCount(dpy); remove fcntl/FD_CLOEXEC from main.c.

wl_backend: implement display_open() with full wlroots headless compositor
init — wl_display_create, wlr_headless_backend_create, wlr_renderer_autocreate,
wlr_backend_start.  display_close() tears down in reverse order.
Compositor state held in a file-static struct.  Adds -DWLR_USE_UNSTABLE
to WLROOTS_CFLAGS in configure.ac.

main.c: move backend selection before display_open() (was in StartUp()),
call wm_backend->display_open() instead of XOpenDisplay(); guard all
X11-specific post-open code (visual-id, DisplayName, wXModifierInitialize)
in if(dpy != NULL).

startup.c: replace ScreenCount(dpy) with wm_backend->display_screen_count();
remove now-redundant backend-selection block (owned by main.c).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 22:35:54 +01:00
Levi Neely a486329b52 Wayland backend abstraction: WMBackend vtable (Phases 0–30)
Introduce a display-system-agnostic WMBackend vtable that routes all
display operations through function pointers, making the WM policy
layer independent of X11.  The X11 implementation is preserved in
src/backend/x11/ and behaviour is unchanged.

Key structural changes
──────────────────────
• src/backend/backend_types.h — backend-neutral type definitions:
    WNativeWindow, WKeyCode, WContextKey, WBackendScreen,
    WBackendEvent (+typed fields), WNormalHints, WWMHints,
    WNETWindowType, WHeadGeometry, WClientAttributes, WClientVisual,
    WSegment, WPoint, WM_KEY_* keysym constants, WA_* atom IDs,
    WKB_GROUP*_INDEX, WCUR_NONE

• src/backend/backend.h — WMBackend vtable (~100 function-pointer
    slots) covering: frame/context lifecycle, stacking, focus, grabs,
    pointer, keyboard, overlays, properties, ICCCM, EWMH/NETWM,
    monitors, screen setup, cursors, extensions, error handlers.
    No <X11/> headers remain in this file after Phase 30.

• src/backend/x11/ — X11 backend implementation:
    x11_backend.c  full vtable; all display calls confined here
    x11_props.c    WM_NORMAL_HINTS / WM_HINTS translation
    x11_event.c    XEvent → WBackendEvent translation
    x11_monitor.c  Xinerama / RandR monitor query

Policy files cleaned
────────────────────
All 47 files in WM_POLICY_CLEAN_FILES pass check-no-x11-policy
(no direct #include <X11/> anywhere).  X11 types that still appear
in policy structs (Visual*, Colormap, Window, Atom …) arrive only
transitively via WINGs.h; the vtable boundary itself is X11-free.

Tests
─────
• tests/smoke-test.sh — full Xvfb lifecycle test (PASS)
• tests/test_geom.c   — geometry / constraint unit tests
• tests/test_x11_event.c — WBackendEvent field extraction tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 19:20:00 +01:00