Major architectural milestone: WINGs Wayland-only files now have ZERO
transitive X11 header dependency at the preprocessor level (verified by
gcc -E grep: 0 mentions of X11/Xlib.h after preprocessing).
Changes:
1. WUtil.h, WINGs.h: stop including <X11/Xlib.h>. wnative.h provides
forward declarations for Display, GC, XftDraw, XftFont; opaque
pointer-only typedefs that don't conflict with Xlib.h's actual
definitions when the X11 backend later includes it.
2. WINGsP.h.in: stop including <X11/Xlib.h>, <X11/Xutil.h>. Drop or
re-route every X11-typed prototype:
- W_HandleDNDClientMessage / W_DragSourceStateHandler /
W_DragDestinationStoreEnterMsgInfo / etc.
→ moved to new private header WINGs/WINGsX11.h
- W_HandleSelectionEvent → moved
- W_LookupString / W_KeycodeToKeysym → moved
- W_DndState typedef → moved (renamed to W_X11DndState)
- XClientMessageEvent / XEvent / XKeyPressedEvent in prototypes
→ use void * in shared protos, cast in WINGsX11.h
3. W_View struct: replaces XSetWindowAttributes by-value field with a
small backend-neutral 'attribs' struct holding only the fields
wmaker/WPrefs actually use (background_pixmap, background_pixel,
border_pixel, colormap, cursor, override_redirect, save_under,
event_mask, do_not_propagate_mask). The X11 view backend
translates to XSetWindowAttributes when calling XCreateWindow.
XIC xic field replaced with void *xic.
4. W_Color struct: replaces XColor by-value with a same-layout
anonymous struct (pixel/red/green/blue/flags/pad). X11 backend
uses memcpy to populate from XColor.
5. WINGs/WINGsX11.h (new): private header for X11 backend. Includes
<X11/Xlib.h>, declares X11-typed internal prototypes used by drag*,
selection, IME, x11_backend, KeyboardShortcuts. Required by every
*_x11.c file plus a handful of cross-component callers
(KeyboardShortcuts.c, MouseSettings.c, xmodifier.c, wmiv.c,
x11_backend.c).
6. wraster.h.in: gain a WRASTER_NO_XLIB compile-time switch. When
defined the header skips <X11/Xlib.h> and provides forward decls
for Display/Visual/XImage/GC/XftFont/etc. All Wayland-only WINGs
files (wclient_wl.c, w*_wl.c) define WRASTER_NO_XLIB on line 1.
7. wfont.c: adds W_ParseXLFDToFcPattern (a hand-written XLFD parser)
replacing XftXlfdParse. Removes <X11/Xft/Xft.h> include from the
shared font dispatcher (and from wfontpanel.c too).
Verification:
$ for f in WINGs/.libs/{*_wl.o,wclient_wl.o}; do
nm $f | awk '$1=="U"{print $2}' | grep -cE '^X[A-Z][a-z]'
done
0 for every Wayland file
$ for f in WINGs/.libs/*.o; do
case $f in *_x11.o|*_wl.o|wclient_wl.o) continue;; esac
c=$(nm $f | awk '$1=="U"{print $2}' | grep -cE '^X[A-Z][a-z]')
[ $c -gt 0 ] && echo "$c $f"
done
(empty — no shared file leaks an X11 symbol either)
$ gcc -E ... wclient_wl.c | grep -c X11/Xlib.h
0 (no transitive Xlib include)
The library still pulls libX11 through the *_x11.c files when those are
linked in. A future configure flag --disable-x11-backend will exclude
*_x11.c entirely; at that point libWINGs will be a pure-Wayland library
with zero libX11 dependency.
The optimization that skipped pango_layout_set_text when the text
matched the previous layout content used pango_layout_get_text()
which returns an internal pointer. This pointer comparison with
arbitrary input text could read freed memory or trigger heap
corruption in Pango internals when the layout state was stale.
Always call pango_layout_set_text unconditionally. The cost is
negligible (Pango internally short-circuits if text is identical).
Three bugs fixed:
1. Close and iconify buttons broken after frame rendering model change
Buttons are composited into the titlebar buffer, so their scene_buf
nodes carry no committed buffer and are invisible to wlr_scene_node_at.
frame_buf_at() returned the titlebar fb for all button-area clicks,
routing them to titlebarMouseDown instead of buttonMouseDown.
Fix: add frame_buf_button_at() -- coordinate walk of frame_list entries
with scene_buf->buffer == NULL -- and frame_buf_hit() which tries button
resolution first then falls back to the scene graph. Replace all
frame_buf_at() calls in button and motion handlers with frame_buf_hit().
Also emit synthetic WME_LEAVE/WME_ENTER events on sub-window boundary
crossings so buttonMouseDown's press-track loop works correctly.
2. Iconify crash (SIGSEGV in update_icon_title)
WMDrawString() was passed icon->core->window (a frame_buf synthetic ID,
0x10000000+) as the drawable. wl_font_resolve_drawable() only recognised
WINGs view IDs (0x20000000+), so it cast the frame_buf ID directly as a
pixman_image_t* -- wild pointer -- SIGSEGV.
Fix: add W_RegisterBacking()/W_UnregisterBacking() to wview_wl.c.
Register each frame_buf's pixman image in the backing table on creation
and unregister on destroy. Extend the ID range check in wfont_wl.c and
wrender_wl.c from 0x20000000 down to 0x10000000 so frame_buf IDs resolve
correctly via W_GetViewBacking().
3. Resizebar visible after iconify + miniwindow not rendering
wl_window_unmap() disabled fb->scene_buf->node individually, but a
subsequent wl_frame_paint() could re-enable and re-commit it while the
window was still iconified.
Fix: for top-level frames, disable fb->tree->node -- hides the entire
scene tree (frame buffer, titlebar, resizebar, client surface) atomically.
Symmetric enable in wl_window_map().
Miniwindow icons were invisible: icon_paint was a noop so the frame_buf
image was never committed to the scene graph. Add wl_icon_paint() mirroring
wl_appicon_paint(): tile + file_image composite + title text, committed
via wlr_scene_buffer_set_buffer(). Wire into wIconPaint() in icon.c so
the backend finalises the surface after policy-layer setup.
Don't add ascent offset — pango_ft2_render_layout renders from the
top of the layout, not from the baseline. The extra ascent was
pushing text below the visible area of the text field.
All WINGs render backend functions (draw_line, draw_rect, fill_rect,
pixmap_copy, composite_pixmap) now use resolve_drawable() to handle
WINGs view IDs (0x20000000+) by looking up the backing pixman image.
Also fixes:
- wfont_wl.c: resolve view IDs in draw_string/draw_image_string
- wtextfield.c paintCursor: use render backend draw_line (not XDrawLine)
- dialog.c wShowInfoPanel: guard scr->w_visual for Wayland mode
- wl_draw_string: remove ascent subtraction, y is TOP position (matches
X11 Pango behavior where pango_xft_render_layout takes top-left)
- Menu entry text: pass top position (y+3) not baseline (y+3+fh-1)
- Icon title: pass y=0 (top) not y=fh (baseline)
- frame_paint_titlebar: pass centered top not baseline
- frame_configure: compute absolute position from parent for children
(was setting absolute pos to relative coords, warping to 0,0)
- Titlebar buffer: always render full frame width, resize if needed
- Frame scene node: disable when no resizebar (transparent, not needed)
- Always call frame_paint after show/hide button (TS_NEW was skipping it)
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.