pointer_get_position was a noop returning (0,0), causing findMenu to
always return NULL. This made the menu close on every button release
regardless of pointer position. Now returns wl_state.pointer_x/y which
are updated on every pointer motion event.
With this fix, the root menu stays open when the pointer is over it on
release (matching X11 behavior), allowing entry selection or titlebar
pinning.
findMenu was returning y relative to the frame top (including titlebar).
getEntryAt expects y relative to the content area. Subtracting top_width
means pointer in titlebar gives y<0 → entry_no=-1 (no selection), which
is correct behavior matching the X11 path.
Add wl_frame_paint_button which renders button icons from XPM data
into the parent frame buffer. Called both from the vtable slot and
from wl_frame_paint during titlebar rendering. Uses PRED_CLOSE_XPM
and PRED_ICONIFY_XPM parsed lazily via RGetImageFromXPMData.
Also removes XEvent from all WFrameWindow callbacks (on_click_left,
on_click_right, on_dblclick_right, on_mousedown_resizebar) — they
now take WMEvent*.
wl_window_unmap now disables child scene nodes when the parent is
hidden. This fixes the menu entries staying visible after the menu
frame (titlebar) was unmapped. The entire menu now disappears
together, matching X11 behavior where the brother menu closes on
button release.
The root menu uses a 'brother' copy for the live instance. findMenu
was only checking the original, not the brother, so it returned NULL
when the pointer was over the active menu copy. This caused the menu
to close immediately on button release (closeCascade triggered by
!smenu condition).
All WFrameWindow callbacks (on_mousedown_titlebar, on_dblclick_titlebar,
on_mousedown_resizebar, on_click_left, on_click_right, on_dblclick_right)
now take WMEvent* instead of XEvent*. This fixes the crash when clicking
the menu titlebar in Wayland mode (_x11_raw was NULL).
Affected files: framewin.h, framewin.c, menu.c, window.c, dialog.c,
winspector.c. All verified X11-free with nm.
findMenu always returned NULL because the refactored code set win=0
then checked 'if (win == None) return NULL'. Replace with geometric
bounds checking against mapped menus. This fixes the menu disappearing
on button release (closeCascade was called because smenu was NULL).
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.
- 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
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
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.
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.
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.
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.
- 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)
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).
- 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
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.
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).
- 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.
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.
- 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.
- 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).
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.
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.
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.
- 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.
- 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.
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.
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.