Commit Graph

322 Commits

Author SHA1 Message Date
Window Maker 0d795bc84a wl_backend: add inotify config-file watching to event loop
The Wayland event loop was missing inotify polling, so theme/style/
background changes from WPrefs (or manual edits to ~/GNUstep/Defaults/)
were never detected. The X11 backend had this since day one.

Now the Wayland event loop checks inotify on every iteration (non-blocking
select with zero timeout). When a config file modification is detected,
wDefaultsCheckDomains() is called, which re-reads the defaults database
and posts appearance-change notifications — triggering immediate visual
refresh of title bars, menus, icons, and backgrounds.
2026-05-24 14:13:14 +02:00
Window Maker 8119bfe098 WPrefs.app: zero X11 deps, zero #ifdef USE_X11_BACKEND
Complete architectural separation: all WPrefs.app panel code is now
backend-neutral. No X11 calls, no X11 types, no X11 includes, no
backend-specific #ifdef guards in shared sources.

New W_EventBackend vtable methods (implemented in X11, stubbed in WL):
  - grab_keyboard / ungrab_keyboard / allow_events
  - grab_pointer / ungrab_pointer / query_pointer
  - get_window_geometry / move_window / translate_coordinates
  - get_root_window / query_tree
  - get_pointer_control / set_pointer_control
  - modifier_from_key / get_modifier_keysyms
  - keysym_to_string / keysym_to_keycode / keycode_to_keysym
  - keysym_convert_case
  - send_wm_command
  - set_window_hints / set_window_property_string / set_window_property_data
  - recolor_cursor
  - set_error_handler / restore_error_handler

Panel changes:
  - xmodifier.c: thin wrapper calling eventBackend->modifier_from_key()
  - main.c: X11 locale init removed (belongs in backend screen_init)
  - WPrefs.c: eventBackend->send_wm_command("Reconfigure")
  - MouseSettings.c: vtable for pointer control + modifier keysyms
  - KeyboardShortcuts.c: vtable for grab/keysym/modifier ops
  - Menu.c: RImage crosshair icon, vtable keyboard grab
  - editmenu.c: vtable for all window/pointer/property ops

Verified: nm audit shows zero X11 symbol refs in WPrefs .o files.
grep shows zero #ifdef USE_X11_BACKEND in WPrefs.app/.
2026-05-24 14:04:14 +02:00
Window Maker b996a0e274 WPrefs.app: TexturePanel.c X11-free in compiled code
Active code: XFillRectangle → renderBackend/WMPaintColorSwatch,
XCopyArea → renderBackend->pixmap_copy, XFreePixmap →
renderBackend->pixmap_free, XParseColor → WMCreateNamedColor,
screen size queries → WMScreenWidth/Height.

7 remaining X11 calls are all inside #if 0 dead-code test blocks
(never compiled). Architecturally clean.
2026-05-24 13:35:07 +02:00
Window Maker 8fe50a7001 WPrefs.app: WPrefs.c X11-free (reconfigure via SIGUSR1 on Wayland)
- XSendEvent/_WINDOWMAKER_COMMAND path guarded with USE_X11_BACKEND
- Wayland path: send SIGUSR1 to wmaker via PID file
- XFlush calls replaced with eventBackend->flush()
- Added X11 includes inside #ifdef guard only

Also: double.c/Paths.c already committed; HotCornerShortcuts.c done.

Remaining panels with X11 calls (all architectural violations):
  editmenu.c (30), Menu.c (14), TexturePanel.c (13),
  KeyboardShortcuts.c (11), MouseSettings.c (5)
2026-05-24 13:30:35 +02:00
Window Maker fabf6c01b2 WPrefs.app: HotCornerShortcuts.c X11-free (RImage quadrant extraction)
Replaced XCreatePixmap/XCopyArea/XCreateGC/XFreeGC/XFreePixmap with
RImage-based quadrant extraction: RLoadImage → RGetSubImage for each
corner → WMCreatePixmapFromRImage → WMSetLabelImage.

panel->quarter[] changed from WMNativePixmap to WMPixmap*.
Cleanup uses WMReleasePixmap instead of XFreePixmap.
2026-05-24 13:28:11 +02:00
Window Maker f8a2ff12d0 WPrefs.app: double.c/Paths.c use render backend instead of Xlib
double.c: XFillRectangle/XClearWindow → renderBackend->fill_rect
Paths.c: XFillRectangle → renderBackend->fill_rect
2026-05-24 13:25:46 +02:00
Window Maker f0d7879b23 WPrefs.app: begin X11/Wayland separation
- WPrefs.h: drop #include <X11/Xlib.h>; ModifierFromKey takes WMScreen*
- main.c: X11 locale calls guarded with #ifdef USE_X11_BACKEND
- xmodifier.c: X11-specific modifier mapping code guarded with
  #ifdef USE_X11_BACKEND; Wayland mode uses sensible defaults
  (Mod1=Alt=Meta, Mod4=Super)
- Appearance.c: all 65 Xlib calls replaced with RImage-based rendering
  (RCreateImage, RDrawLine, RCopyArea, RFillImage, etc.) and
  WMCreatePixmapFromRImage for display. previewNoText/previewBack
  fields changed from WMNativePixmap to RImage*.

Remaining panels still have X11 calls (editmenu, Menu, TexturePanel,
KeyboardShortcuts, HotCornerShortcuts, WPrefs, MouseSettings,
double, Paths) — will be addressed in follow-up commits.
2026-05-24 13:23:47 +02:00
Window Maker 23f0bb320e wm core: shared src/ is now X11-free at the source level
Audit: every "X11 in src/" hit outside src/backend/x11/ and
src/backend/wayland/ is now either:
  - a comment mentioning X11 by name, or
  - a backend-neutral macro/type alias (WM_STATE_*, CW*, P*, etc.)
    whose numeric value happens to match the X11 protocol value.

Zero <X11/...> includes in shared headers/sources.
Zero X11 type uses (XColor/XContext/XEvent/XFontStruct/XGCValues/
XWindowAttributes/XSetWindowAttributes/XErrorEvent etc.).
Zero X11 symbol references in compiled shared object files
(verified: `nm src/*.o | awk '$1=="U"' | grep '^X[A-Z][a-z]'`
returns empty).

Real architectural fixes:

src/backend/backend_types.h — added the missing backend-neutral
constants/types so shared code never names an X11 macro:
  - WM_STATE_WITHDRAWN/NORMAL/ICONIC (ICCCM values 0/1/3).
  - WContextID (typedef int) — XContext analogue.
  - WMColorRGB (XColor-layout-compatible struct).
  - CWX..CWStackMode (ConfigureWindow value-mask bits).
  - ForgetGravity..StaticGravity (ICCCM win_gravity values).
  - PMinSize..PWinGravity (XSizeHints flags) as WNH_* aliases.
  - NoSymbol, NoEventMask, ColormapInstalled/Uninstalled.
  - BitmapSuccess..BitmapNoMemory.
All guarded by #ifndef so the X11 backend's <X11/X.h> include
overrides them with the real X11 values when present.

src/screen.h — w_visual is now `void *` (was `Visual *`).  Added
w_visual_id / w_visual_class so dialog.c's crash panel can read
visual info without dereferencing a Visual struct.  tech_draw_font
is also `void *` with companion tech_draw_font_ascent/descent ints
populated by the backend (X11 from XFontStruct->ascent, Wayland
from a hard-coded bitmap-font metric).

src/WindowMaker.h — XContext fields → WContextID, X11 includes
removed, Time → WMNativeTime.

src/dialog.c — wShowCrashingDialogPanel now uses WMOpenScreen +
WMScreenWidth/Height instead of DefaultScreen()/ScreenOfDisplay()/
WidthOfScreen() so it works in either backend.

Dead-code cleanup found while auditing:

src/event.c — handleUnmapNotify and handleEnterNotify both built
an uninitialized `XEvent ev` and ran it through x11_translate_event
on a peeked queue event.  The translation always read stack garbage
(the local was never populated).  Replaced with the correct flow:
  - unmap handler: skip wUnmanageWindow if a Destroy is already
    queued, the Destroy handler will run it next iteration.
  - enter handler: skip if a Leave for the same window is queued,
    no need to inspect mode/detail (was always reading garbage).
Also dropped the now-unused x11_compat.h / x11_event.h includes
from event.c, dock.c, window.c.

src/misc.c — eatExpose's `XEvent event, foo` were never used; the
function delegates to wm_backend->event_flush_type(WME_EXPOSE).

src/wsmap.c — workspace_map_destroy built an XEvent ClientMessage
but never sent it; the actual notify path is switchpanel_send_enter.
Pass the real root_win argument (was passing literal 0) and drop
the dead XEvent.

src/icon.c — set_dockapp_in_icon's `XWindowAttributes attr` and
cycleColor's `XGCValues gcv` were unused.

src/window.c — windowLanguageClick had a function-signature
mismatch with framewin.h's on_click_language (XEvent* vs WMEvent*).
The framewin code passes a WMEvent.  Fixed the parameter type and
its single use of event->xbutton.button.

src/moveres.c — already-disabled `#if 0` block in showPosition
that called XDrawLine / XSetForeground on the root window: removed.
Replaced tech_draw_font->ascent/descent dereferences with the new
flat int fields.

src/xutil.h — removed declarations of FormatXError (moved to X11
backend long ago) and Request/GetSelection (never implemented).

Mass renames in shared src/:
  IconicState/NormalState/WithdrawnState → WM_STATE_ICONIC/NORMAL/
                                            WITHDRAWN
  IconWindowHint/InputHint/StateHint/IconPixmapHint/IconMaskHint/
  IconPositionHint/WindowGroupHint/UrgencyHint
                                          → WMH_*_HINT
  XColor (in struct fields and locals)    → WMColorRGB
  XContext (in screen.context.{...})      → WContextID
  XPoint                                  → WMShortPoint
  XRectangle                              → WMShortRect
  XFontStruct *                           → void *

Backends translate at the boundary:
  src/backend/x11/x11_backend.c keeps its native XColor/XContext/
  XFontStruct internally and casts to the backend-neutral types
  at the public-API surface (memcpy works because WMColorRGB has
  XColor's exact layout).
  src/backend/wayland/wl_backend.c populates the same fields
  directly without any X11 indirection.

Verified:
  Default build: `Window Maker 0.96.0` runs.
  Shared src/ object files: `nm | grep '^X[A-Z][a-z]'` is empty.
  All shared X11 macro names (CW*, P*, ICCCM hint flags) are
  defined locally in backend_types.h, no X11 dep needed.

Out of scope (separate refactor): wmaker compositor binary itself
still links libX11 because src/backend/x11/* and the XWayland
integration in src/backend/wayland/wl_backend.c need real X11
types.  Both are below the vtable, so shared code is unaffected.
2026-05-24 12:52:31 +02:00
Window Maker a4eb10b2b5 wrlib: split X11 image-conversion path; --disable-x11-wraster
Phase θ — wrlib's X11 image-conversion path (RConvertImage,
RPutXImage, the X11 RCreateContext, libXpm-based RLoadXPM) is now
opt-out via --disable-x11-wraster, mirroring the WINGs phase η work.

Result: with --disable-x11-backend --disable-x11-wraster the WINGs
runtime libraries have ZERO libX11 transitive deps:

  $ ldd WINGs/.libs/libWINGs.so | grep X11
  (empty)
  $ ldd wrlib/.libs/libwraster.so | grep X11
  (empty)

That was the last libX11 transitive dep coming through WINGs — the
goal of the API surgery is now achieved at the library level.

configure.ac:
- New --enable-x11-wraster (default = same as --enable-x11-backend),
  AM_CONDITIONAL([USE_X11_WRASTER]), AC_DEFINE([USE_X11_WRASTER]).
  Forcing --disable-x11-wraster while --enable-x11-backend is rejected
  (X11 backend depends on the X11 conversion path).
- WRASTER_GFXLIBS_NO_XPM: GFXLIBS with -lXpm filtered (libXpm pulls
  libX11; load_xpm_normalized.c is the X11-free XPM loader used in
  the disabled-X11 build).
- WINGS_PANGO_LIBS_NO_XFT: PANGO_LIBS with -lpangoxft-* and -lXft
  filtered (PangoXft depends on libXft -> libX11; pangoft2 path is
  the X11-free Pango variant).

wrlib/Makefile.am:
- Split source list: shared / X11-only / Wayland-only.
- X11 sources (context.c, convert.c, convert_x11.c, xpixmap.c,
  xutil.c, load_xpm.c) only built when USE_X11_WRASTER.
- New context_wl.c (always built) — Wayland-mode RCreateContextWayland
  extracted from context.c.
- New wstubs_no_x11.c (only built when !USE_X11_WRASTER) — empty
  stubs for the public wraster API symbols normally exported from
  the X11 path (RCreateContext, RDestroyContext, RConvertImage,
  RConvertImageMask, RGetClosestXColor, RCreateImageFromDrawable,
  RCreateImageFromXImage, RCreateXImage, RGetXImage, RDestroyXImage,
  RPutXImage, RGetImageFromXPMData, RLoadXPM).
- @XLIBS@/@LIBXMU@ only added to libwraster_la_LIBADD when
  USE_X11_WRASTER; load_xpm.c only built when (USE_XPM and
  USE_X11_WRASTER).
- Added --filter USE_X11_WRASTER to the wraster.h generation rule
  so the @!USE_X11_WRASTER@ lines (forcing WRASTER_NO_XLIB) are
  retained when X11 is disabled.

wrlib/wraster.h.in:
- When USE_X11_WRASTER is undefined at config time, force
  WRASTER_NO_XLIB so consumers see only forward-decl'd opaque types
  (Display/Visual/XImage/etc.) and never <X11/Xlib.h>.
- Added True/False/None defines to the WRASTER_NO_XLIB block (raster.c
  uses them; previously got via Xlib.h).

wrlib/context.c — RCreateContextWayland moved out to context_wl.c.
wrlib/wstubs_no_x11.c — new (157 lines).
wrlib/context_wl.c — new (extracted Wayland branch).

WINGs/Makefile.am:
- libWINGs_la_LIBADD now uses WINGS_PANGO_LIBS, which is @PANGO_LIBS@
  when X11 backend enabled, @WINGS_PANGO_LIBS_NO_XFT@ otherwise.

WINGs/widgets.c — WMCreateScreen + WMCreateSimpleApplicationScreen
moved to widgets_x11.c (they use DefaultScreen() and RCreateContext()
which are X11-only).  Stubs added in WINGs/wstubs_no_x11.c.
WINGs shared rootWin assignment now reads context->drawable instead
of calling X11 RootWindow() macro directly.

WINGs/WINGs/wnative.h — added X11-numeric constants used by shared
WINGs widget code:
- Button1..Button5 (X.h pointer-button numbers)
- KeyPress..LASTEvent (X.h event-type constants)
- CWBackPixmap..CWCursor (X.h CreateWindow/ChangeWindowAttributes
  mask bits)
- WMShortRect (XRectangle layout-compatible struct)
All guarded by #ifndef so X11 headers can override on the X11 build.

WINGs/configuration.c — dropped unused <X11/Xlocale.h> include.
WINGs/wruler.c, wtabview.c, wtext.c — replaced raw XPoint/XRectangle
with WMShortPoint/WMShortRect; replaced lone XSetWindowAttributes
shim with direct view->attribs.cursor access.

src/WindowMaker.h — explicitly include <X11/Xlib.h>, <X11/Xutil.h>,
<X11/Xresource.h>, <X11/Xatom.h>.  The wmaker compositor uses these
extensively in its public headers; previously got them transitively
via WINGs.h.  After the WINGs surgery WINGs.h no longer pulls Xlib,
so the compositor must include them itself.

Verified:
  Default build (--enable-x11-backend, --enable-x11-wraster):
    Window Maker 0.96.0 boots, all features intact.
  Pure-Wayland build (--disable-x11-backend --disable-x11-wraster):
    libwraster.so / libWINGs.so build cleanly, no libX11 in ldd.
    (wmaker compositor binary still has X11 deps from src/* code;
     out of scope for this commit — that's a compositor-level
     refactor.)
2026-05-24 12:24:45 +02:00
Window Maker cff52676c2 wings: add --disable-x11-backend for pure-Wayland WINGs builds
Phase η: completes the WINGs API surgery by adding the configure
option that actually excludes the X11 backend from the build.

  ./configure --enable-wayland-client --disable-x11-backend
    → libWINGs has zero X11 symbol dependencies in its own objects

configure.ac: --enable-x11-backend (default yes) controls the new
USE_X11_BACKEND m4 conditional and #define.

WINGs/Makefile.am: split source list into:
  - backend-neutral / shared sources (always)
  - if USE_X11_BACKEND: dragsource_x11.c / dragdestination_x11.c /
    dragcommon_x11.c / selection_x11.c / wappresource_x11.c /
    wballoon_x11.c / wcolor_x11.c / wcolorpanel_x11.c /
    wevent_x11.c / wfont_x11.c / widgets_x11.c /
    winputmethod_x11.c / wrender_x11.c / wview_x11.c
  - else: wstubs_no_x11.c (new)
XLIBS / XFT_LIBS only added to libWINGs_la_LIBADD when X11 backend
is enabled.

WINGs/wstubs_no_x11.c: empty implementations of every public WINGs
API symbol that normally lives in *_x11.c — DnD setup, selection
handlers, IM context, balloons, color/font panels, application icon
hints, atom helpers.  Each stub is a no-op (returns success-neutral
value); calling them in pure-Wayland mode is silent rather than an
error, so future Wayland equivalents can drop in transparently.

WINGs/widgets.c: WMCreateScreenWithRContext uses weak references
to the W_*BackendX11 instances so they can resolve to NULL when not
linked.  If the caller asked for X11 mode but X11 backend is not
built, falls back to Wayland with a warning.

WINGs/WINGsP.h.in: backend extern decls (W_*BackendX11) marked weak
so links resolve to NULL when X11 backend is excluded.

Verification:
  $ ./configure --disable-x11-backend && make
  $ for f in WINGs/.libs/*.o; do nm $f | grep '^.*U X[A-Z][a-z]'; done
  (empty)

libWINGs.so still pulls libX11 transitively via wrlib (wraster's X11
image-conversion path); that's a separate refactor.  At the WINGs
source level the partition is now complete: shared / X11 / Wayland.
2026-05-24 11:56:57 +02:00
Window Maker 9a02eb658e wings: phase ζ — formal W_PlatformBackend vtable for WMOpenScreen
Replaces the inline if-Wayland-else-X11 dispatch in WMOpenScreen with
a proper vtable.  Each platform-open backend now provides one
W_PlatformBackend instance:

  W_PlatformBackendX11       — widgets_x11.c
  W_PlatformBackendWLClient  — wclient_wl.c

WMOpenScreen walks an ordered registry of weak references to these
instances:

  static const W_PlatformBackend *const wm_platform_backends[] = {
      &W_PlatformBackendWLClient,
      &W_PlatformBackendX11,
      NULL
  };

It first asks each backend's .detect() whether it wants the supplied
display string, and calls .open() on the first to claim it.  If no
backend claims, it falls back to trying each .open() in order.

Weak references mean a build that excludes a backend (e.g. a future
--disable-x11-backend) link cleanly with the symbol resolving to
NULL — WMOpenScreen just skips it.

The detection logic moves out of shared widgets.c entirely:
  x11_detect: explicit non-wayland display string OR $DISPLAY set.
  wlclient_detect: 'wayland' prefix, WMAKER_USE_WAYLAND, or
                   $WAYLAND_DISPLAY set + $DISPLAY unset.

Also replaces WMCreateScreenWithRContext's getenv("WMAKER_USE_WAYLAND")
with an explicit W_SetNextScreenKind(WM_SCREEN_KIND_WAYLAND) flag the
platform backend sets before calling.  No env detection in shared code.

Updated wmaker compositor (src/backend/wayland/wl_backend.c) to call
W_SetNextScreenKind(WM_SCREEN_KIND_WAYLAND) before its own
WMCreateScreenWithRContext call.

Verified: wmaker still starts in compositor mode, version string OK,
build clean, vtable dispatch invokes the right backend.
2026-05-24 11:49:34 +02:00
Window Maker fb817a7b27 wings: revert accidental WNativeWindow rename in strings/comments
The phase-β sed pass renamed every C 'Window' identifier to
WNativeWindow.  That correctly updated typedef uses but also rewrote
the string 'Window Maker', UI labels like 'Window Manager', 'Window
Placement', 'Window Title', 'Window List', 'Window System session',
etc., plus a number of comments referring to 'Window' as English.

Fixed all of those.  The C type uses (WNativeWindow rootWin, etc.)
remain unchanged — only English-language occurrences are reverted.
Verified that wmaker now reports 'Window Maker 0.96.0' again and
build is clean across WINGs/, src/, WPrefs.app/.
2026-05-24 11:42:37 +02:00
Window Maker 5417d3cbbd wprefs: route through WMOpenScreen for Wayland-client autodetect
WPrefs.app/main.c was opening the display directly via XOpenDisplay /
WMCreateScreen.  Replaced with WMOpenScreen, which autodetects
Wayland mode from WAYLAND_DISPLAY / DISPLAY env and dispatches to
W_WLClientInit in WINGs (Wayland) or W_X11OpenDisplay
(widgets_x11.c) accordingly.

The XSupportsLocale / XSetLocaleModifiers calls are now skipped in
Wayland mode (they're X11-only).  This is just startup plumbing; WPrefs's
many tab modules still have direct Xlib calls that won't work as a
pure Wayland client until each is ported through WINGs vtables.  This
commit gets us a minimal Wayland-aware launch path; further work
required to actually run native.
2026-05-24 11:38:55 +02:00
Window Maker ef06f5ad8e wings: phases δ + ε — drop X11/Xlib.h from public WINGs headers
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.
2026-05-24 11:37:18 +02:00
Window Maker 70d8a068e6 wings: route wtextfield XInternAtom through W_NativeInternAtom
Last X11 symbol leak in shared WINGs code: wtextfield.c's selection
request handler called XInternAtom directly to look up TEXT,
COMPOUND_TEXT, and TARGETS atoms.

Replaced with W_NativeInternAtom(scr, name) — implemented in
widgets_x11.c as a thin XInternAtom wrapper.  The Wayland-only
build (future) will provide a stub that returns WM_NATIVE_NONE,
making the requestHandler's downstream comparisons all fall through
to 'no match' cleanly.

Architectural verification: every WINGs shared object file (i.e.
not *_x11.o, not *_wl.o) now has ZERO undefined X11 symbols:

  $ for f in WINGs/.libs/*.o; do
      case $f in *_x11.o|*_wl.o) continue;; esac
      nm $f | awk '$1=="U" {print $2}' | grep -c '^X[A-Z][a-z]'
    done | sort -u
  0

Combined with the *_wl.c files already verified to have zero X11
deps, the WINGs library now cleanly partitions: shared code is
backend-neutral, X11 backend code lives in *_x11.c, Wayland backend
code lives in *_wl.c.  A --disable-x11-backend configure option can
now be added that drops *_x11.c from the build for pure-Wayland
WINGs apps.
2026-05-24 11:13:11 +02:00
Window Maker f7a7142889 wings: drop libXft from wfont.c / wfontpanel.c
The only Xft API used in shared font code was XftXlfdParse — used
to convert legacy X11 XLFD font names to fontconfig FcPatterns so
old WINGs config files keep working.

Replaced with a hand-written parser W_ParseXLFDToFcPattern (defined
in wfont.c, declared in WINGsP.h) that walks the 14 dash-separated
XLFD fields and pulls out family / weight / slant / pixelsize.
This is enough for every XLFD that wmaker / WPrefs has ever used
in practice (~14 different names across all defaults).

Both wfont.c and wfontpanel.c now use W_ParseXLFDToFcPattern, and
neither file includes <X11/Xft/Xft.h> any more.  libXft is now only
pulled in by the X11 font backend (wfont_x11.c), as it should be.

Build clean.  Wayland-only files still have zero X11 symbol
dependencies (verified via nm).
2026-05-24 11:09:39 +02:00
Window Maker 32377afed9 wings: rename wcolorpanel.c → wcolorpanel_x11.c
The color picker dialog uses XGetImage / XGrabPointer / XShape /
XPutImage / XCopyArea to implement the magnify-glass screen picker.
Wayland intentionally does not allow reading pixels from other
windows (security), so the screen-pick feature has no Wayland
equivalent.  The whole file is therefore X11-only.

A future commit will provide a stub that returns a wwarning when
WMShowColorPanel is called in Wayland mode.
2026-05-24 11:04:33 +02:00
Window Maker d2b11eec4c wings: phase γ — rename X11-only files to *_x11.c
Mechanical rename to make architectural intent visible:

  dragsource.c       → dragsource_x11.c
  dragdestination.c  → dragdestination_x11.c
  selection.c        → selection_x11.c
  winputmethod.c     → winputmethod_x11.c
  wballoon.c         → wballoon_x11.c
  wappresource.c     → wappresource_x11.c

Each is essentially a wrapper around X11 features (XDND, X11
selection, XIM, XShape, X11 WM hints) with no Wayland equivalent
yet.  These files keep providing their public WINGs API symbols
unchanged, so build+link is identical at this point.

A future commit will add Wayland counterparts (or no-op stubs) and
wire a configure option that conditionally excludes *_x11.c when
the build is Wayland-client-only.  Doing this now would force a
choice between linkable but Wayland-broken (no stubs) or partial
double-implementation (some functions stubbed); the right answer
needs vtable dispatchers in shared *.c files for each, which is
the next round of surgery.
2026-05-24 11:01:50 +02:00
Window Maker 9545320f9c wings: phase γ (dragcommon) — split X11 XDND wire code into _x11
dragcommon.c now contains only backend-neutral helpers
(WMCreateDragOperationArray/Item, accessors, W_FreeViewXdndPart).

dragcommon_x11.c is new and owns:
  - W_OperationToAction/W_ActionToOperation atom translation
  - windowExists / handleNoWindowXError probe
  - W_SendDnDClientMessage XSendEvent path
  - W_HandleDNDClientMessage XDND wire dispatch
  - handleLeaveMessage

These touch scr->xdnd*Atom fields and call XSendEvent / XGetAtomName /
XSetErrorHandler etc. — strictly X11.  Wayland DnD will be added later
through wl_data_device.

dragsource.c and dragdestination.c still contain Xlib calls; those
splits come next.
2026-05-24 10:58:22 +02:00
Window Maker b5c46870aa wings: phase γ (widgets.c) — split Xlib calls into widgets_x11.c
WINGs/widgets.c is now Xlib-call-free.  All Xlib code moved to a new
WINGs/widgets_x11.c:

  * W_X11PlatformInit (~178 lines): GC creation, modifier-mask probe,
    cut-buffer setup, cursor/atom/IM init.  Hooked from
    W_ViewBackendX11.platform_init exactly as before.
  * W_X11OpenDisplay: XOpenDisplay + WMCreateSimpleApplicationScreen.
    WMOpenScreen() in widgets.c now calls this for the X11 path.

Dead code removed: the static renderPixmap that nothing called and
that was the last X11-direct-draw path in widgets.c.

X11 includes dropped from widgets.c.  Display * typedef still resolves
through WINGsP.h transitively until phase ε removes that.

Build verified clean, wmaker still links and runs.
2026-05-24 10:55:30 +02:00
Window Maker 0f839a9c6d wings: phase β — rename X11 typedefs in shared/Wayland code
Sed pass restricted to files outside src/backend/x11 and outside
*_x11.c — i.e. all code that should not depend on X11 typedefs.

  Window     → WNativeWindow      (existing typedef in WMEvent.h)
  Atom       → WMNativeAtom
  Pixmap     → WMNativePixmap
  Cursor     → WMNativeCursor
  Drawable   → WMDrawable          (existing typedef)
  KeySym     → WMNativeKeysym
  Colormap   → WMNativeColormap

X11 backend files keep using the original Xlib type names because
they make Xlib API calls that take those types.  All typedefs are
ultimately 'unsigned long' so values pass through opaquely between
shared code and the backend.

Public WINGs API affected: WMSelectionCallback, WMSelectionProcs,
and a handful of widget signatures that took Atom/Window arguments
now take WMNativeAtom/WNativeWindow.  Source-compatible at the
binary level; consumers must rebuild.

Time and XID typedefs left for a follow-up — both are heavily used
in field/variable names that need careful auditing.  Display* and
GC stay in W_Screen for now; phase δ moves them into an X11-only
sub-struct.
2026-05-24 10:49:47 +02:00
Window Maker 1a49d6b857 wings: phase α.3 — rename X11 enum/macro values to WM_*
Mass rename of X11 enum values used in shared/Wayland code, with the
numeric values preserved so the wire layout of WMEvent fields and
the X11-backend translation tables remain unchanged.

  NotifyNormal/Grab/Ungrab/WhileGrabbed     → WM_NOTIFY_*
  NotifyAncestor/Virtual/Inferior/Nonlinear/
    NonlinearVirtual/Pointer/PointerRoot/
    DetailNone                              → WM_NOTIFY_*
  PropertyNewValue/Delete                   → WM_PROPERTY_*
  MappingModifier/Keyboard/Pointer          → WM_MAPPING_*
  VisibilityUnobscured/PartiallyObscured/
    FullyObscured                           → WM_VISIBILITY_*
  GrabModeAsync/Sync, GrabSuccess           → WM_GRAB_*
  RevertToParent/PointerRoot/None           → WM_REVERT_TO_*
  CurrentTime                               → WM_CURRENT_TIME
  None                                      → WM_NATIVE_NONE

The 'None' rename was done with conservative regex passes restricted
to clear C-context patterns (= None;, , None,, !=None, etc.) so that
'"None"' string literals in defaults and XPM 'c None' colour names
are preserved untouched.  Comments containing the English word 'None'
are also left alone.  X11 backend files that legitimately use the
X11 macros (Xlib calls returning None, etc.) are unchanged.

Build clean across WINGs, src, WPrefs.app.
2026-05-24 10:47:37 +02:00
Window Maker 82e3c3b65d wings: phase α.2 — rename X11 event masks to WM_EVMASK_*
Sed pass.  KeyPressMask, KeyReleaseMask, ButtonPressMask,
ButtonReleaseMask, EnterWindowMask, LeaveWindowMask,
PointerMotionMask, PointerMotionHintMask, Button{1..5}MotionMask,
ButtonMotionMask, KeymapStateMask, ExposureMask,
VisibilityChangeMask, StructureNotifyMask, ResizeRedirectMask,
SubstructureNotifyMask, SubstructureRedirectMask, FocusChangeMask,
PropertyChangeMask, ColormapChangeMask all renamed to the
corresponding WM_EVMASK_* names defined in wnative.h.

Numeric values still match the X11 layout, so wevent_x11.c's
matching tables and any code that masks bits keep working
unchanged.  Build clean across WINGs/, src/, WPrefs.app/.
2026-05-24 10:43:23 +02:00
Window Maker 5f65867974 wings: introduce wnative.h; phase α.1 (modifier/button masks)
WINGs API surgery, step 1.

New public header WINGs/WINGs/wnative.h declares WINGs-native types
and constants with no X11 header dependency:

  - WMNativePixmap/Atom/Cursor/Keysym/Time/XID/Colormap/Bool typedefs
    (all 'unsigned long' — compatible with the existing wire ABI).
  - WM_MOD_SHIFT/LOCK/CONTROL/MOD{1..5} modifier mask bits.
  - WM_BUTTON{1..5}_MASK pointer button mask bits.
  - WM_ANY_MODIFIER/WM_ANY_BUTTON sentinels.
  - WM_EVMASK_* event-mask bits (forthcoming patches).
  - WM_NOTIFY_* crossing modes/details.
  - WM_PROPERTY_* / WM_MAPPING_* / WM_VISIBILITY_* / WM_GRAB_* /
    WM_REVERT_TO_* / WM_CURRENT_TIME / WM_NATIVE_NONE.

Numeric values intentionally match X11 layout for binary
compatibility with WMEvent fields (which were defined that way
originally).  The architectural property that matters is that NONE
of the symbol *names* below are X11 macros — they belong to WINGs
and are defined without any X11 header.

WMEvent.h, WUtil.h, WINGs.h now #include <WINGs/wnative.h> so every
WINGs consumer picks up the new constants.  X11 headers are still
included from the public WINGs headers; phase ε will drop them.

Phase α.1 — first sed pass:

  ShiftMask     → WM_MOD_SHIFT
  ControlMask   → WM_MOD_CONTROL
  LockMask      → WM_MOD_LOCK
  Mod{1..5}Mask → WM_MOD_MOD{1..5}
  Button{1..5}Mask → WM_BUTTON{1..5}_MASK
  AnyModifier   → WM_ANY_MODIFIER
  AnyButton     → WM_ANY_BUTTON

Applied across WINGs/, src/, WPrefs.app/ via sed with word
boundaries.  Build verified clean; binary identical in size,
re-linked successfully.
2026-05-24 10:42:04 +02:00
Window Maker da3bf4c096 wings(wayland-client): wl_pointer + wl_keyboard input dispatch
Task 5.

wclient_wl.c subscribes to wl_seat.capabilities.  On POINTER capability
it binds wl_pointer with a listener that translates enter/leave/motion/
button events into WMEvent (WME_ENTER, WME_LEAVE, WME_MOTION,
WME_BUTTON_PRESS/RELEASE).  Linux evdev button codes (BTN_LEFT, etc.)
map to X-style numbers (1, 2, 3, 8, 9).  Pointer focus is tracked per
wl_surface and resolved to a top-level W_View via wlc_top_for_surface.

On KEYBOARD capability it binds wl_keyboard.  The keymap event mmaps
the fd, compiles via xkb_keymap_new_from_string, and stashes the result
in WLClientCtx (xkb_keymap + xkb_state).  Subsequent key events use
xkb_state_key_get_one_sym for the keysym and xkb_state_key_get_utf8 for
text — these populate WMEKey.{keycode, keysym, utf8, utf8_len}.
Modifiers update xkb_state and a cached X-style mod mask
(ShiftMask, ControlMask, Mod1Mask, Mod4Mask) used in WMEKey.state and
WMEButton.state.

Focus enter/leave on the keyboard side dispatches WME_FOCUS_IN /
WME_FOCUS_OUT so WINGs widgets get focus tracking.

Events flow via W_WL_EnqueueEvent, the same ring buffer wevent_wl.c
already drains for the compositor side — no separate event-pump
required.  Axis (scroll) events are stubbed out for now and will be
synthesized as button 4/5 in a follow-up.
2026-05-24 10:27:56 +02:00
Window Maker 97b2d03a34 wings(wayland-client): wl_shm buffers + xdg_toplevel surfaces
Tasks 3 + 4.

wclient_wl.c grows a memfd+mmap-backed wl_shm buffer allocator that
wraps the mapped region as a pixman_image_t.  Painting into the pixman
image writes directly into the buffer the compositor will read on
commit, so no copy is needed.  wl_buffer.release marks the buffer as
released for future reuse (currently we just realloc on resize, so the
flag is informational).

Each top-level W_View now acquires a WLClientToplevel with a wl_surface,
xdg_surface, and xdg_toplevel.  The first xdg_surface.configure event
acks and attaches the buffer; subsequent configures with non-zero
dimensions realloc the backing.  xdg_toplevel.close sets a want_close
flag (closure event synthesis is in the next pass).

wview_wl.c now calls three function-pointer hooks for top-level views:

  W_WLClientToplevelRealizeFn(view, w, h)  -> pixman_image_t *
  W_WLClientToplevelResizeFn(view, w, h)
  W_WLClientToplevelDestroyFn(view)

When the hooks are NULL (compositor-internal mode or X11), wview_wl.c
falls back to plain pixman_image_create_bits — preserving every
existing behaviour.  When wclient_wl.c installs them, the same paints
end up on a wl_shm buffer attached to a real Wayland surface.

W_ViewCommitBackingFn and W_ViewDestroyBackingFn are also installed by
W_WLClientInit so wview_wl.c's existing redisplay/destroy plumbing
drives wl_surface_attach / damage / commit / surface destruction.

No input handling yet; that's task 5.
2026-05-24 10:25:29 +02:00
Window Maker 12ae1e48fb gitignore: WINGs scanner-generated xdg-shell, drop stray +cmd
The previous commit accidentally swept in a personal scratch file (+cmd)
and the auto-generated xdg-shell-protocol.c.  Both are now ignored.
Generated files come from $(WAYLAND_SCANNER) at build time.
2026-05-24 10:20:42 +02:00
Window Maker 182617513e wings(wayland-client): build system + connection skeleton
Task 1 + 2 of the WINGs Wayland-client backend.

Adds optional --enable-wayland-client (default auto) which depends on
wayland-client, xkbcommon, wayland-protocols, and wayland-scanner.
configure.ac probes for these and exposes WAYLAND_CLIENT_CFLAGS/LIBS
plus the protocols data dir and scanner path.

WINGs/Makefile.am wires a wayland-scanner rule that generates
xdg-shell-{protocol,client-protocol}.{c,h} at build time and links
libWINGs against wayland-client + xkbcommon when enabled.

WINGs/wclient_wl.c is the new file.  It self-stubs when the feature
is disabled.  When enabled it provides:

  W_WLClientInit(scrPtr, display)
    Connects via wl_display_connect, registers a wl_registry listener,
    binds wl_compositor/wl_shm/wl_seat/xdg_wm_base, creates an xkb_context,
    and hooks the libwayland event pump into the existing
    W_EventBackendWL via W_WL_SetLoopDispatch().  This lets the existing
    ring-buffer event mechanism keep working unchanged: the ring is fed
    by client-side wl_pointer/wl_keyboard listeners (next task) and
    drained by WMNextEvent / WMMaskEvent / waitForEvent.

  W_WLClientShutdown(scrPtr)
    Tears down all bound globals and disconnects the wl_display.

No surfaces / buffers / input dispatch yet — those come in tasks 3-5.
Build verified clean, wmaker still links and runs as before.
2026-05-24 10:20:01 +02:00
Window Maker 852fb2adeb wayland: NULL fb->scene_buf/tree when wlroots auto-destroys cascade
ASan caught a SEGV in wl_list_remove inside wlr_scene_node_destroy
called from wl_view_destroy_backing_impl when closing a dock-icon
rename input dialog.

The flow:
  1. wInputDialog opens.  fake_leader fb_FAKE created with tree+scene_buf;
     panel content fb_PANEL created with scene_buf parented under
     fb_FAKE's tree; wManageInternalWindow wraps fake_leader in a
     WMaker frame fb_FRAME (also with tree).
  2. Dialog closes.  wUnmanageWindow runs wl_frame_destroy on fb_FRAME.
     wlr_scene_node_destroy on fb_FRAME->tree cascades — wlroots
     auto-destroys fb_FAKE->tree, fb_FAKE->scene_buf, AND
     fb_PANEL->scene_buf.
  3. WMDestroyInputPanel later calls destroyView →
     wl_view_destroy_backing_impl(panel_id), which tries
     wlr_scene_node_destroy on fb_PANEL->scene_buf — already destroyed
     and freed.  wl_list_remove on a zeroed link → SEGV.

Fix: register destroy listeners on every fb->scene_buf and fb->tree
when they're created.  When wlroots destroys the node (typically via
parent-tree cascade), the listener fires and NULLs the field.
wl_view_destroy_backing_impl and wl_frame_destroy already check for
NULL before destroying, so the second-destroy is now safely skipped.

Same pattern as the earlier fix for view->scene_node (commit 8cb56fc),
applied to all wl_frame_buf scene-graph fields.
2026-05-24 10:06:36 +02:00
Window Maker c55d42c169 wayland: guard wl_menu_paint_entry against unrealized menus
ASan caught a heap-buffer-overflow at wl_menu_paint_entry:8675 writing
4 bytes BEFORE a pixman-allocated 40-byte region.  The bottom-bevel
loop wrote dst[(y + h - 1) * stride + col] where y=0, h=0 (because
menu->entry_height was still 0 from before wMenuRealize), stride=1
(initial 1×10 buffer), col=0 → offset -1 → write -4 bytes from start
of the pixman bits buffer.

Trigger: updateOptionsMenu (right-click on titlebar) calls
wMenuSetEnabled which paints both the menu and its brother
unconditionally.  The brother had not been realized yet on first
right-click, so menu->entry_height was 0.

This was the corruption that caused the later 'double free' on
pixman_image_unref of unrelated frame buffers (heap was already
trashed by this OOB write).

Fix: bail early in wl_menu_paint_entry if entry_height is zero or
if fb is still at the 1×10 placeholder size — paint will fire again
correctly after wMenuRealize.
2026-05-24 10:01:18 +02:00
Window Maker d6e10203fa wayland: fix use-after-free of WDock during clip restore
ASan caught it: heap-use-after-free at wl_clip_icon_paint:8478 reading
workspace->clip->collapsed.  The flow is:

  wWorkspaceRestoreState()
    if (scr->workspaces[i]->clip)
        wDockDestroy(scr->workspaces[i]->clip);     // frees the WDock
    scr->workspaces[i]->clip = wDockRestoreState(); // creates new
        wDockCreate -> dockIconPaint -> wClipIconPaint
            -> wl_clip_icon_paint
                workspace->clip->collapsed   // ← reads freed pointer

scr->workspaces[i]->clip is dangling between the wDockDestroy and the
assignment from wDockRestoreState.  wl_clip_icon_paint runs inside
that gap (wDockCreate calls dockIconPaint via wClipIconPaint).

Fix: read collapsed state from aicon->dock instead of workspace->clip.
aicon->dock is the dock currently being constructed and is always
valid at this point.

This was masquerading as a 'double free' on right-click of titlebars
(the heap corruption from the early use-after-free corrupted later
allocations that pixman_image_unref then tripped over).  Removed
the diagnostic logs added while debugging.
2026-05-24 09:59:15 +02:00
Window Maker bf56ccb8eb wayland(WIP): reorder unref in wl_frame_configure; add diagnostics
Speculative fix for double-free crash when right-clicking a window
titlebar to open the window menu (WMaker's Options cascade brother
realize).  Stack trace shows pixman_image_unref crashing with
'double free or corruption (out)' on a freshly-created 1x10 image.

This commit:
  * Saves old_image, creates new fb->image, updates metadata, notifies
    wlroots, THEN unrefs old_image — so wlroots' begin_data_ptr_access
    only ever sees the new image during the resize transition.
  * Adds wwarning logging in wl_frame_configure and the buffer destroy
    callback to catch the crash sequence.

Diagnostics will be removed once the root cause is fixed.
2026-05-24 09:45:09 +02:00
Window Maker eeb161c616 wayland: auto-restart on crash; verify info-panel and icon-chooser
E3 (Crash Dialog):
  Showing a UI from a crashed compositor's child process is impossible
  on Wayland — the child cannot connect to the dead parent's display.
  Default to WMRestart instead of WMAbort, so the user's session
  recovers automatically on a wmaker crash (the standard daily-driver
  expectation).  Removed the misleading 'cannot open connection'
  message.

E2 (Info Panel) and E4 (Icon Chooser): both already use the standard
fake_leader_create + wManageInternalWindow pattern that the Exit and
Run dialogs use.  No code changes; user can verify by opening Info
Panel from the root menu and Icon Chooser via right-click on a dock
icon → Settings → Browse.
2026-05-24 09:26:24 +02:00
Window Maker 3ed50c69ec wayland: implement window_get_command for session save
Native Wayland clients had no way to be saved across restarts: the
backend's window_get_command vtable slot was a no-op, so session.c's
makeWindowState early-returned NULL for every native client.

Implementation:
  * Native XDG client: return [app_id] as single-arg command.  Most
    app_ids match the binary name (foot, firefox, gedit, etc.) so
    plain execvp() during session restore finds them on PATH.
  * XWayland client: try WM_COMMAND via wl_state.x_display first
    (most reliable), fall back to instance/class.

Limitation: reverse-DNS app_ids (org.gnome.Terminal, etc.) won't
restore — a follow-up patch should add a desktop-file lookup.
2026-05-24 09:23:03 +02:00
Window Maker a2cb136f8a arch: move wmspec.c (EWMH) and xdnd.c (XDND) into src/backend/x11/
Both files implement X11-specific protocols (EWMH _NET_* and XDND).
They were sitting in shared src/ because they predated the backend
split; the only remaining users in shared code were now via
wm_backend-> dispatch.

To get there, four new vtable slots replace the last direct calls
from shared src/:

  screen_get_head_usable_area  (screen.c was calling wNETWMGetUsableArea)
  window_get_icon_image        (icon.c was calling get_window_image_from_x11)
  netwm_set_frame_extents      (window.c, winspector.c were calling wNETFrameExtents)
  (window_fetch_name and window_get_icon_name extended to consult EWMH first)

Other changes:
  * get_window_image_from_x11 now takes Display* explicitly so the
    Wayland backend can pass wl_state.x_display for XWayland clients
    instead of relying on a global (which is NULL on Wayland).
  * Eight shared .c files lose their now-unused #include "wmspec.h"
    or #include "xdnd.h".
  * Makefile.am moves wmspec.{c,h} and xdnd.{c,h} into the backend/x11
    listing.
  * src/Makefile.am drops the obsolete --disable-xdnd Makefile branch
    and unconditional sources list still references the new paths.

Final state: every Xlib call in the codebase lives in src/backend/x11/
or src/backend/wayland/.  The only remaining "X*(" matches outside
backend/ are six XSetForeground/XDrawLine calls in src/moveres.c
inside an \#if 0 block (dead code; left for now).  src/ has zero
_x11_raw references.
2026-05-24 09:16:39 +02:00
Window Maker 8cb56fc141 wayland: NULL view->scene_node when wlroots auto-destroys it
Crash on closing a toplevel: handle_toplevel_destroy called
wlr_scene_node_destroy on view->scene_node, but the node had
already been destroyed by wlroots a few stack frames earlier when
the WMaker frame's tree was destroyed (frame_destroy → tree
destroy cascades to children).

Fix: register a destroy listener on view->scene_node when it's
created.  When wlroots destroys the node (typically because its
parent tree is destroyed during unmanage), the listener fires and
NULLs view->scene_node, so handle_toplevel_destroy's existing
'if (view->scene_node)' check correctly skips the redestroy.

handle_toplevel_destroy itself removes the listener before its
own wlr_scene_node_destroy call so we don't double-remove the
listener entry from the wlroots signal list.
2026-05-24 09:02:35 +02:00
Window Maker 27fa3f78c6 arch: drop USE_XINERAMA guards from shared src/
Multi-head support comes through WScreen.heads[] (populated by the
backend's screen_open) and the wGetRectForHead / wGetUsableAreaForHead
helpers — both backend-agnostic.  The USE_XINERAMA #ifdefs in shared
src/ were a build-time toggle for X11-extension presence and did not
belong in policy code.

Strip the guards in:
  src/wmspec.c   _NET_WM_FULLSCREEN_MONITORS atom now unconditional.
  src/actions.c  wFullscreenMonitorsWindow now unconditional.
  src/dialog.c   About-dialog 'Xinerama: N head(s) found' string now
                 unconditional.  (The string still references the X11
                 extension by name; on Wayland this is somewhat
                 misleading but cosmetic — proper fix would route
                 'About' info through the backend.)

USE_XINERAMA remains in src/backend/x11/x11_monitor.c, where it
correctly gates the Xinerama-extension code at build time.  The
configure --enable-xinerama option is unchanged.
2026-05-24 08:57:55 +02:00
Window Maker 16561778a4 drop configure~ backup file; ignore in future 2026-05-24 08:55:51 +02:00
Window Maker eaea7464b2 arch: drop USE_DOCK_XDND guards from shared src/
The XDND-on-dock feature was a configure-time toggle (--disable-xdnd)
gating ~25 #ifdef sites across shared src/.  This was a pre-Wayland
feature flag, not a backend distinction, but it polluted the policy
layer with build-time conditionals.

Make it unconditional:

  configure.ac    Remove --disable-xdnd and AM_CONDITIONAL.  XDND on
                  the dock is always built.
  src/Makefile.am Move xdnd.c from the if-USE_DOCK_XDND block into
                  the unconditional wmaker_SOURCES list.
  src/dock.h, dock.c, dockedapp.c, appicon.h, appicon.c, event.c,
  misc.c, startup.c, dialog.c, screen.h
                  Strip all #ifdef USE_DOCK_XDND/#endif pairs.  In
                  dockedapp.c the #else branch (rendering an 'XDnD
                  support was not compiled in' label) is dead and
                  removed.

Backend routing: the X11 backend continues to drive the XDND protocol
through xdnd.c via the existing xdnd_process_client_message /
xdnd_process_selection / xdnd_make_awareness vtable slots.  Wayland's
slots are no-ops (XWayland clients drop into the X11 path naturally
via wl_state.x_display).

src/ is now free of feature-flag guards related to DnD.
2026-05-24 08:55:43 +02:00
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 ee1e5b0f70 arch: move X11 locale init into X11 backend display_open
XSupportsLocale and XSetLocaleModifiers in main.c were the last
direct Xlib calls in src/main.c.  Move them into x11_display_open
(guarded by I18N) where they naturally belong.  The Wayland backend
does not need them — locale handling for native Wayland clients is
just standard libc, and XWayland clients still receive locale-aware
input via the wmaker-attached XWayland server's own setup.

main.c is now Xlib-free.
2026-05-24 08:47:16 +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 9cca44c765 arch: move X11 modifier-keymap discovery into X11 backend
xmodifier.c contained x_reset_modifier_mapping which walked the X
server's modifier map via XGetModifierMapping / XFreeModifiermap to
discover the X11 modifier indices for Meta/Hyper/Super/Alt keysyms.
This was 4 direct Xlib calls in shared src/.

Refactor:
  src/xmodifier.c  — now only holds the modifier-mask state and the
                     portable wXModifierFromKey / wXModifierToShortcut
                     Label / wSetModifierMasks helpers used by shared
                     policy code.  No more Xlib symbols.

  src/backend/x11/x11_backend.c  — owns x11_reset_modifier_mapping,
                     called from x11_extensions_init.  Calls
                     wSetModifierMasks at the end so shared code
                     answers modifier lookups correctly.

  src/xmodifier.h  — drops wXModifierInitialize.  Wayland never needed
                     it; X11 calls the local x11_reset_modifier_mapping
                     directly.

The unused ModeMask static was dropped along the way.
2026-05-24 08:43:32 +02:00
Window Maker a789abc09f arch: eliminate last _x11_raw escape from src/ (winspector)
The Window Inspector's 'select window' feature grabbed the pointer on
the root window then read XEvent.xbutton.subwindow to learn which
window was clicked.  This was the last access to _x11_raw in shared
src/ code.

Add a subwindow field to WMEButton.  The X11 backend's WMEvent
translation populates it from xbutton.subwindow.  The Wayland backend
leaves it 0 (Wayland has no equivalent grab semantic — the click
reports the actual frame as event.window directly).  winspector.c
now uses event.u.button.subwindow with fallback to
event.u.button.window, working on both backends.

Net: src/ has zero _x11_raw escapes from shared code.  Remaining
references are inside the X11 backend (legitimately consuming the
field set by its own event translator).
2026-05-24 08:40:38 +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
Window Maker f2e49a8b67 menu: fix infinite recursion in findMenuWalk via brother
A WMenu's brother is a parallel copy of the same menu used when the
menu is torn off / buttoned.  The brother shares cascade pointers
that reference back into the original tree, so recursing into both
m->brother and m->cascades[i] cycled (brother->cascades[i] == m's
own cascade entry, which has its own brother, etc.) and overflowed
the stack on any cascaded menu.

Inline the brother hit-test instead of recursing into it.  Cascades
themselves are walked recursively as before so sub-sub-menus remain
reachable.
2026-05-24 08:25:14 +02:00
Window Maker 3fb9f3925f menu: recursive findMenu so sub-sub-menus respond to mouse
The previous implementation only checked one level of cascades —
scr->root_menu and scr->root_menu->cascades[i].  Sub-sub-menus
(cascade->cascade->...) were never checked, so hovering over a
sub-sub-menu's entries did not return the menu, and selectEntry
therefore could not open the next-level cascade or react to clicks.

Replace with a recursive walk over each top-level menu's full
cascade tree.  Pick the deepest mapped menu that contains the
pointer (deeper cascades render on top in the scene graph and
should win the hit-test).

X11 sidesteps this with XQueryPointer + XFindContext, which finds
any menu window via the X server's hit-test regardless of nesting.
2026-05-24 08:23:42 +02:00
Window Maker 31576e4b25 wayland: use set_buffer_with_damage for all in-place paints
wlr_scene_buffer_set_buffer treats same-pointer assignment as a
no-op — pixel updates to fb->image are not picked up.  Every paint
function in the backend mutates fb->image (or s->wlr_buf) in place
and then commits with the same pointer, so wlroots never re-rendered
the changed contents.

Convert all 15 sites to wlr_scene_buffer_set_buffer_with_damage(...,
NULL) which forces a full rerender.  This restores the menu paint
fix to its proper general form and addresses the clip workspace
number/title not appearing at startup, as well as latent staleness
in dock/drawer icon and balloon paint paths.
2026-05-24 08:13:57 +02:00
Window Maker e973406d95 framewin: guard handleButtonExpose against unset descriptor parent
wFrameWindowUpdateBorders calls wFrameWindowResize at line 356,
which (since commit f88dfac) calls frame_paint.  On X11,
frame_paint dispatches to wFrameWindowPaint which iterates
button descriptors and calls handleButtonExpose.  But the
descriptors' parent field is set later in wFrameWindowUpdateBorders
(after the resize call) — so during this first paint, fwin
(desc->parent) is NULL and the function segfaults at the
left_button comparison.

The Wayland backend skips wFrameWindowPaint via wl_frame_paint
returning 1, so it never hit this path.
2026-05-23 22:12:53 +02:00
Window Maker a1d9fdf9f1 wayland: fix orphan menu titlebars at startup
Top-level frame trees were enabled by default at creation. When
framewin.c then called wm_backend->window_map_raised(titlebar) at
frame creation time (necessary for X11 decoration semantics), the
titlebar's scene_buf became enabled. Combined with the always-enabled
tree, this made the titlebar visually rendered at the frame's
default spawn position — even for menus and dialogs that had not
been logically mapped yet. The visible orphan reflected whichever
submenu titlebar was painted last (e.g. 'Multimedia').

Fix: top-level frame trees now start DISABLED. wl_window_map and
wl_window_map_raised explicitly enable the tree when called on a
top-level frame_buf. This matches X11 semantics where a child window
is only visible if its parent window is mapped. Decoration children
(titlebar, buttons) being individually 'mapped' no longer produces
orphan visibility because the parent frame's tree gates their
visibility.
2026-05-23 22:07:41 +02:00