Commit Graph

133 Commits

Author SHA1 Message Date
Levi Neely 1905fdf08a Fix frame buffer: clear to transparent so children show through
The frame buffer was cleared to opaque black, covering the menu
content child buffer. Now cleared to alpha=0 (transparent).
2026-05-13 16:59:47 +02:00
Levi Neely baca61df68 Fix menu title bar: implement frame_buf resize in window_resize
The menu frame was created at 1x1 and resized via wFrameWindowResize
which calls window_resize. But wl_window_resize didn't handle
frame_bufs — it only handled toplevel views. Now it reallocates the
pixman image when dimensions change, so the frame has the correct
size when wl_frame_paint renders the title bar.
2026-05-13 16:55:45 +02:00
Levi Neely 40a10a0785 Improve menu rendering: separators, bevel edges, cascade arrows, title
- Entry separators: light line on top, dark line on bottom between entries
- Left/right bevel edges on each entry
- Cascade arrow (triangle) for submenu entries
- Paint menu frame title bar (wl_frame_paint) when menu is shown
- Matches X11 menu_draw_frame behavior
2026-05-13 16:52:06 +02:00
Levi Neely b9dbd23dfc Remove XEvent from dock.c and appicon.c click handlers
All dock/clip/appicon mouse handlers now use WMEvent directly:
- openDockMenu, iconDblClick, handleDockMove, handleClipChangeWorkspace
- wHandleAppIconMove (appicon.c)
- Removed x11_translate_event hack in dock menu forwarding
- dock.o and appicon.o verified X11-free with nm
2026-05-13 16:45:01 +02:00
Levi Neely 110a555cfa Fix spurious menu visibility: don't map child if parent is hidden
In X11, child windows are only visible when the parent is mapped.
In Wayland, all frame_bufs are independent scene nodes. The menu
content window was being mapped at creation time (wMenuCreate),
making it visible even though the parent frame was offscreen/hidden.

Fix: wl_window_map skips enabling a child node if its parent's
scene node is not yet enabled.
2026-05-13 16:31:34 +02:00
Levi Neely 7921d2def8 Fix menu rendering: create real frame_bufs for child windows
Child windows (menu content area, titlebar, resizebar) need their own
pixman buffers for painting. Previously frame_create_child returned a
bare synthetic ID with no buffer, so menu_paint_entry found nothing.

Also add parent-child tracking: when a parent frame moves or maps,
all children are repositioned/enabled automatically. Children store
their relative offset and parent ID.
2026-05-13 16:29:06 +02:00
Levi Neely 01bed8bdd3 Paint menu after mapping (no Expose events in Wayland)
In X11, mapping a window triggers Expose which causes repainting.
In Wayland there are no Expose events, so wMenuPaint must be called
explicitly after the menu is mapped in wMenuMapAt.
2026-05-13 16:24:32 +02:00
Levi Neely d93f4935ca Fix input dispatch: custom event loop + modal menu support
The deadlock: frame_timer_cb called WMHandleEvent which entered
menuMouseDown's modal WMMaskEvent loop. That blocked inside
wl_event_loop_dispatch (reentrant), preventing new events.

Fix:
1. Replace wl_display_run() with custom loop that drains WINGs
   events BETWEEN wl_event_loop_dispatch calls (not inside timer)
2. Make WINGs wl_flush() pump wlroots (call dispatch_fn) so
   WMMaskEvent modal loops get new events without reentrancy
3. Fix wBalloonHide NULL dereference (scr->balloon not allocated)
4. Remove XEvent dependency from wSelectWindows (takes x,y now)
5. Remove debug traces

Right-click on background now opens the root menu.
2026-05-13 16:22:13 +02:00
Levi Neely ac739a1a5c Implement input dispatch: hit-test pointer events to WM windows
- frame_buf_at(): hit-test finds which WM frame_buf is under pointer
- Button/motion events set window field to frame_buf ID or root_win
- Root window gets synthetic ID (0x0FFFFFFF) in Wayland mode
- Right-click on background → handleButtonPress → OpenRootMenu path
- wSelectWindows: remove XEvent dependency, take (x, y) coordinates
- Zero X11 symbols in event.o and moveres.o (verified with nm)
2026-05-13 15:57:40 +02:00
Levi Neely fe8f7a923f Use default WindowMaker background color (rgb:50/50/75)
The dark blue-grey matches the classic WindowMaker desktop appearance.
2026-05-13 14:28:15 +02:00
Levi Neely b663ab8360 Implement Wayland text rendering + frame titlebar/resizebar
Text rendering uses the existing WINGs PangoFT2 backend — WMDrawString
renders directly into the frame buffer's pixman_image_t.

- Menu entries: real text via PangoFT2 (entry text + shortcut labels)
- Dock/clip icon titles: rendered with icon_title_font
- Frame titlebar: solid background + centered title text
- Frame resizebar: beveled grey bar

All text is anti-aliased (PangoFT2 alpha compositing onto pixman).
2026-05-13 14:27:11 +02:00
Levi Neely 582e527aea Implement Wayland clip icon + menu rendering
- Clip/drawer icons: reuse wl_appicon_paint (tile rendering)
- Menu entries: solid background fill (grey normal, blue selected)
  with placeholder text line. Full text rendering TODO.
- Menu frame: beveled border (light top/left, dark bottom/right)
- All rendering commits to scene graph via wlr_scene_buffer_set_buffer
2026-05-13 14:20:24 +02:00
Levi Neely 7e1da342be Fix XWayland crash: switch to lazy mode
XWayland was started eagerly (at compositor init) which caused a
segfault when XWayland couldn't connect back to the Wayland socket
(race condition in nested mode). Since the WM UI is now pure Wayland
(no X11 rendering), XWayland is only needed for X11 client apps.

Switch to lazy mode: XWayland starts only when the first X11 client
connects. This eliminates the startup wait loop and the associated
crash. Also set xwayland_ready=true in the server destroy handler
as a safety net.
2026-05-13 14:16:47 +02:00
Levi Neely faf4c76085 Fix clean build: add RCreateContextWayland to wraster.h.in
wraster.h is generated from wraster.h.in — the declaration was only
in the generated file, not the template. Also includes the Wayland
no-op for RConvertImage/RConvertImageMask (context->dpy == NULL).
2026-05-13 14:12:33 +02:00
Levi Neely bca128d593 Implement Wayland dock icon rendering
- wl_appicon_paint: renders dock icons by compositing the icon tile
  (RImage) with the app image, then blitting RGBA→ARGB32 into the
  frame buffer's pixman image and committing to the scene graph.

- Color parser: add grayNN/greyNN pattern support (gray0-gray100)
  and rgb:RR/GG/BB X11 color format. All default textures now parse.

- Dock paint trigger: add explicit dockIconPaint calls at end of
  wDockCreate and wDockRestoreState since Wayland has no Expose
  events on window map.

The dock icon tile is now visible in the compositor window.
2026-05-13 14:03:35 +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 530e1a91f9 Phase 80o: clean X11 from superfluous.c
- DoKaboom: body replaced with vtable dispatch (do_kaboom slot);
  X11 animation temporarily disabled in backend (cosmetic only)
- doAppBounce: XRaiseWindow -> stacking_raise, XMoveWindow -> window_move
- MakeGhostIcon: kept in superfluous.c (uses wrlib, not direct X11)

superfluous.o verified X11-free with nm.
2026-05-13 11:46:40 +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 a5d6720a1c Phase 80i: clean X11 from winspector.c, wsmap.c
- winspector.c: XGrabPointer -> pointer_grab, XCreateSimpleWindow ->
  fake_leader_create, XReparentWindow -> client_reparent,
  XUngrabKey -> key_ungrab_all, XSetTransientForHint removed
- wsmap.c: XGetImage -> client_snapshot, XGrabPointer -> pointer_grab,
  XSendEvent -> switchpanel_send_enter, XLookupString ->
  keysym_from_keycode, WidthOfScreen -> scr->scr_width

All three files verified X11-free with nm. Zero dpy references.
2026-05-13 11:04:26 +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 90fc12c252 Phase 80g: clean X11 from motif.c, colormap.c, resources.c
- motif.c: wGetMWMHints moved entirely to x11_backend.c (inlined into
  x11_motif_get_hints)
- colormap.c: wColormapInstallForWindow inlined into x11_colormap_install;
  policy file now contains only vtable dispatch stubs
- resources.c: wGetColorForColormap and wFreeColor now dispatch through
  vtable; X11 implementation inlined into x11_backend.c
- xmodifier.c: wXModifierInitialize now called from x11_extensions_init
  (removed from main.c)

motif.o, colormap.o, resources.o verified X11-free with nm.
xmodifier.o retains X11 symbols (mechanism code, only reached through
X11 backend — candidate for physical move to backend/ directory).
2026-05-13 10:55:30 +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 008da962fe Phase 80e: clean X11 from dockedapp.c, monitor.c
- dockedapp.c: XCreateSimpleWindow -> fake_leader_create,
  XReparentWindow -> client_reparent
- monitor.c: XOpenDisplay/XCloseDisplay removed from crash dialog
  (dialog function handles connection internally)

Both files verified X11-free with nm.
2026-05-13 10:44:25 +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 d87a7f9941 Fix FREE_PIXMAP macro to use vtable instead of direct XFreePixmap
Replace XFreePixmap(dpy, p) in the FREE_PIXMAP macro with
wm_backend->pixmap_free((unsigned long)p). This eliminates a
hidden dpy dependency from every file that uses FREE_PIXMAP.
2026-05-13 10:32:47 +02:00
Levi Neely 759225007c Phase 80d: remove remaining if(dpy) conditionals from screen.c
Replace dpy-based conditional in wScreenInit with root_win check.
Remaining dpy references in policy files are all in X11 mechanism
code (rendering functions, event handlers, XWayland setup) that is
only reached through the X11 backend path.
2026-05-13 10:25:41 +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 9cfe322573 Phase 80b: eliminate if(dpy) guards and replace X11 calls with vtable dispatch
- Remove all 20 'if (dpy &&' guards from policy files
- Replace XMapWindow, XUnmapWindow, XMoveWindow, XClearWindow,
  XFreePixmap, XFlush, XSync, XResizeWindow, XSetWindowBackground,
  XSetWindowBackgroundPixmap, XMoveResizeWindow, XSelectInput,
  XMapRaised, XUngrabPointer, XUngrabKeyboard, XGrabKeyboard,
  XGrabServer, XUngrabServer, XRestackWindows, XDestroyWindow,
  XReparentWindow, XAddToSaveSet, XSetWindowBorderWidth
  with vtable dispatch across all policy files
- Make wFrameWindowPaint mechanism code: X11 backend's frame_paint
  now calls it; all policy call sites dispatch through vtable
- Replace dpy feature-gating in main.c/startup.c with is_wayland

Remaining: 278 dpy refs in policy files, mostly in rendering functions
(wIconPaint, wAppIconPaint, paintEntry, drawFrame, balloon, dock,
dialog, superfluous, event) that are X11 mechanism code reachable
only through the X11 backend path.
2026-05-13 10:21:00 +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 803666fd5e WIP: Pure Wayland WINGs screen init (no X11 in WM path)
- WMCreateScreenWithRContext: add Wayland path that skips all X11 calls
  (no GCs, no atoms, no XListProperties, no XCreateGC)
- screen.c: skip RCreateContext in Wayland mode (pass NULL rcontext)
- Wayland path initializes: font/event/render backends, colors, fonts

Current issue: W_RealizeView tries to create X11 windows for WINGs
widgets. Need to make view realization work without X11 (views should
be pixman buffers in Wayland mode, not X windows).

The grey background + cursor render correctly. Startup reaches
WINGs init but crashes when widgets try to realize without a display.
2026-05-13 07:38:38 +02:00
Levi Neely 74647423c5 Fix screen init: create RContext + WINGs screen on XWayland in Wayland mode
- wScreenInit Wayland fast path now creates RContext on XWayland display
  (needed for wTextureRenderImage and wraster image loading)
- Also creates WINGs screen (wmscreen) so WMDrawString/WMFontHeight work
- Add wl_get_x_display() accessor for screen.c to get XWayland Display*
- Remove if(dpy) guard around wScreenRestoreState in startup.c so dock,
  clip, menus, and window management run in Wayland mode

Status: startup reaches menu creation but hangs in wMenuCreate due to
Xlib operations on XWayland during WINGs font/screen init. The pump
thread is running but something in the menu creation path is spinning.
Next step: identify and eliminate the remaining XWayland dependency in
the menu creation path.
2026-05-13 07:33:25 +02:00
Levi Neely cc3655d2fd Fix: set global dpy=NULL in Wayland mode
The global 'dpy' variable was set to the XWayland Display*, causing
120+ direct Xlib calls in the WM core (XMapWindow, XClearWindow, etc.)
to pass synthetic frame buffer IDs to XWayland — hanging the startup.

Fix: wl_display_open returns NULL so global dpy=NULL. All existing
'if (dpy)' guards in the WM core now correctly skip Xlib calls.
The Wayland backend uses wl_state.x_display directly for the few
XWayland operations it needs (atom interning, screen info, GC alloc
for the no-focus window).

This unblocks startup — the event loop now runs successfully.
2026-05-13 07:23:02 +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 9b2448dd7f WIP: Wayland backend - fix atoms, OR surface compositing, frame/window ops
Key changes in wl_backend.c:
- wl_atom_intern: call XInternAtom on XWayland display (was returning 0)
- Add wl_or_view struct to track override_redirect XWayland surfaces
- handle_xwayland_new_surface: composite OR surfaces via scene graph
- frame_create_toplevel/child: create real X11 windows on XWayland
- frame_destroy/configure: delegate to Xlib
- window_map/unmap/move/resize: fall through to Xlib for frame windows
- stacking_raise/lower: update scene graph + Xlib fallback
- event_flush/sync: call XFlush/XSync on XWayland display
- window_set_border/border_width/clear: delegate to Xlib
- window_get_rect: query XWayland geometry for non-toplevel windows

Note: frame creation via XWayland is a temporary bridge. The correct
architectural approach is native scene-buffer rendering with pixman.
2026-05-13 07:05:22 +02:00
Levi Neely 2fc7e45ffa wayland: XWayland bridge — block on ready signal, return Display* for full WM UI
wl_display_open now pumps the Wayland event loop until XWayland fires its
"ready" signal, then calls XOpenDisplay() and returns the Display* to the
core WM.  This makes dpy non-NULL so screen.c takes the full X11 code path:
RCreateContext, WINGs screen, workspaces, root menus, and EWMH hints all
initialise via the WM's own XWayland connection.

- wl_handle_x11_events: new fd watcher registered on ConnectionNumber(dpy)
  so WINGs menus, dialogs, and keyboard events are dispatched during
  wl_display_run() via XPending/XNextEvent/WMHandleEvent
- wl_screen_open: sets root_win/depth/colormap from DefaultRootWindow(dpy)
  when bridge is active so RCreateContext gets valid X11 screen values
- wl_screen_create_internals: creates a 1x1 info_window on XWayland for
  _NET_SUPPORTING_WM_CHECK and clipboard selection ownership
- handle_xwayland_map: guard against w_global.screen_count==0 (fires before
  StartUp() in edge cases) to avoid assert in wScreenWithNumber
- wl_display_close: removes fd watcher and calls XCloseDisplay before
  killing XWayland to avoid stale fd events

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 06:52:29 +02:00
Levi Neely 398d467880 wayland: fix nested mode crash — null seat + 0×0 output on backend_start
Two bugs prevented nested Wayland mode (inside sway) from starting:

1. The wlr_wl_backend fires new_input during wlr_backend_start(), before
   wl_state.seat exists (seat is created later in wl_display_open).
   wlr_seat_set_keyboard(NULL, kb) → SIGSEGV.  Guard with if (seat).

2. Sway's initial xdg-shell configure sends width=height=0 ("compositor
   chooses").  Without an explicit mode, wlr_output_commit_state tries to
   create a 0×0 GBM swapchain → crash in gbm_bo_create.  Fall back to
   1920×1080 when no preferred mode is available.

Also install XSetErrorHandler at the top of wl_display_open so the monitor
process's crash-dialog BadMatch (from sway's internal XWayland at :0) is
suppressed rather than printed in Xlib default format.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-11 04:32:02 +02:00
Levi Neely 5f21e8069b wayland: install X error handler for XWayland connection
The Wayland backend runs with a live XWayland Display* once XWayland
fires its ready signal.  Without an error handler, benign X errors
(BadMatch on X_SetInputFocus, BadWindow during window teardown) reach
Xlib's default handler and produce noisy output.

Add wl_catch_xwayland_error() — same permissive policy as the X11
backend's x11_catch_error() — and install it via XSetErrorHandler in
wl_register_error_handlers().  Include <X11/Xproto.h> for the
X_SetInputFocus request code constant.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 20:34:59 +02:00
Levi Neely 2d9b9b76c5 wayland: migrate wlroots 0.16 API to 0.19 + animation overlay system
Port from wlroots ~0.16 to 0.19 (Gentoo slotted packages) and add the
Phase 81 XOR animation overlay.  Fixes Gentoo build from scratch.

configure.ac: detect wlroots-0.19 versioned slot before falling back to
unversioned; fixes "Package wlroots was not found" on Gentoo.

startup.c: add missing <X11/Xresource.h> for XrmUniqueQuark on Gentoo's
stricter X11 headers.

wl_backend.c — wlroots 0.16→0.19 API migration:
- Backend creation: display* → wl_event_loop* (get_event_loop)
- wlr_output_layout_create gains display* arg
- Output configuration: wlr_output_enable/commit/set_mode → wlr_output_state API
- wlr_output_layout_get_box: returns void, writes to caller-supplied box
- Scene graph: scene root is scene->tree (wlr_scene_tree*); create
  functions return/accept wlr_scene_tree*; scene_node.state.x/y → .x/.y
- wlr_scene_output_commit gains options arg (NULL)
- Protocol globals gain version args: compositor(6), xdg_shell(3),
  layer_shell(4), linux_dmabuf_with_renderer(4), presentation(1)
- Input: dev->keyboard/pointer embedded fields removed; use
  wlr_keyboard/pointer_from_input_device(); headless backend no longer
  has input devices; XKB keymap created independently at startup
- Keyboard: wlr_event_keyboard_key → wlr_keyboard_key_event;
  wlr_seat_set_keyboard takes wlr_keyboard* directly
- Pointer: all wlr_event_pointer_* → wlr_pointer_*_event;
  wlr_seat_pointer_notify_axis gains relative_direction arg;
  wlr_cursor_warp_absolute uses &ev->pointer->base
- Cursor: wlr_xcursor_manager_set_cursor_image → wlr_cursor_set_xcursor
- XDG shell: xdg_surface->events.map/unmap → surface->events.map/unmap;
  xdg_surface->mapped → surface->mapped; toplevel_set_size/send_close/
  parent take wlr_xdg_toplevel*
- XWayland: events.map/unmap → events.associate/dissociate;
  xw->mapped → xw->surface->mapped; size_hints is xcb_size_hints_t*
- Layer shell: ls->events.map/unmap → ls->surface->events.map/unmap
- wlr_buffer: include wlr/interfaces/wlr_buffer.h for wlr_buffer_init
- Remove wlr_input_inhibitor and wlr_idle (dropped in wlroots 0.18)

wl_backend.c — Phase 81 XOR animation overlay:
- Full-screen pixman SHM overlay surface for move/resize rubber-band
  guides and miniaturize animations
- Embedded 5×9 bitmap font (96 printable ASCII glyphs)
- Bresenham line drawing; hline/vline fast paths
- overlay_ensure: lazy alloc/resize tied to WScreen dimensions
- server_ungrab flushes overlay to scene graph

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-10 18:51:05 +02:00
Levi Neely 2bcc676202 wayland: fix XWayland window visibility
Two bugs prevented XWayland client windows from appearing:

1. flags.mapped never set for XWayland windows (window.c)
   The condition `else if (!dpy)` is false when dpy is the XWayland
   Display* (it is only true for pure native-Wayland mode with no X11).
   Changed to `else if (!dpy || wm_backend->is_wayland)` so XWayland
   windows also get flags.mapped=1 after wManageWindow, matching the
   semantics of XDG toplevel windows.

2. scene node positioned at xw->x,xw->y before configure round-trip
   handle_xwayland_map used xw->x,xw->y for the initial scene node
   position.  These values may not yet reflect the configure sent in
   handle_new_xwayland_surface (the X11 round-trip is async).  Changed
   to use view->x,view->y which are set to output/4 in
   handle_new_xwayland_surface and kept in sync by set_geometry listener.

Also added a log line when xw->surface is NULL at map time so the cause
is diagnosable from wmaker stderr.

Note: if xterm connects to the wrong DISPLAY (e.g. Sway's :1 instead of
wmaker's :2), no handle_xwayland_map fires at all.  Check wmaker's
"XWayland ready on :X" log line for the correct display number.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 16:54:21 +02:00
Levi Neely fa26a31209 wayland: workspace switching + dock icon rendering
Workspace switching (wl_window_map / wl_window_unmap):
  wl_window_map and wl_window_unmap were stubs.  Both now look up the
  wl_toplevel_view by its WNativeWindow ID and call
  wlr_scene_node_set_enabled(scene_node, true/false).  The policy layer
  (workspace.c wWorkspaceForceChange) already calls wWindowMap/wWindowUnmap
  for each window on workspace switch, so no policy changes are needed —
  the scene node enable/disable is the only missing piece.

Dock icon rendering (Phase 30+):
  Added a 32-entry dock_apps[] array to wl_compositor_state tracking
  each managed window's ID and ARGB8888 icon pixels.

  wm_dock_load_icon() reads _NET_WM_ICON from XWayland windows via
  get_window_image_from_x11() (wmspec.c), converts wrlib RImage RGBA
  bytes to ARGB8888, and returns a heap buffer.  XDG native Wayland
  clients (no X11 connection) get NULL → empty tile placeholder.

  wm_dock_refresh() repaints the dock background + tiles, then for each
  managed app composites its icon into the tile using pixman BILINEAR
  scaling (icon_w × icon_h → tile_sz-2 inset area), then calls
  wm_shm_surface_repaint() which destroys and recreates the scene_buffer
  node to force wlroots 0.15 to upload the fresh texture on the next
  frame (wlroots caches textures by wlr_buffer pointer; destroy+recreate
  is the safe invalidation path for this API version).

  wm_dock_app_add() is called from handle_toplevel_map and
  handle_xwayland_map after wManageWindow succeeds.
  wm_dock_app_remove() is called from handle_toplevel_unmap and
  handle_xwayland_unmap before wUnmanageWindow.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 14:21:31 +02:00