Commit Graph

292 Commits

Author SHA1 Message Date
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
Window Maker ce5cea8679 wayland: destroy fb->tree in wl_frame_destroy
Frame_bufs that owned a wlr_scene_tree (top-level frames and the
fake_leader for dialogs) leaked their tree on destroy.  The scene_buf
was destroyed but the tree remained in the scene graph as an orphan,
causing stale rendering — most visibly as ghost titlebars near the
clip after closing a menu, since the leaked menu frame trees stayed
in the scene.
2026-05-23 21:29:38 +02:00
Window Maker c7e2b7ba88 wayland: fix dialog/menu hit-testing and parenting
Several related fixes for WINGs dialogs and menus that depend on
correct scene graph parenting and hit-testing:

1. fake_leader_create: now creates a wlr_scene_tree (not just a
   scene_buf). When the fake_leader is reparented into a WMaker frame,
   any content inside it (e.g. WINGs panel) is reparented as part of
   the tree, so it follows the WMaker frame's position when moved.

2. wl_client_reparent (frame_buf path): if the source frame_buf has
   a tree, reparent the tree (with all its children) instead of the
   bare scene_buf.

3. frame_buf_update_children_abs: new recursive helper to walk the
   entire descendant tree updating fb->x/y absolute tracking. Used
   by wl_window_move, wl_frame_configure, and wl_client_reparent.
   Without this, grandchildren (e.g. WINGs panel inside a fake_leader
   inside a WMaker frame) had stale fb->x/y after the WMaker frame
   was moved, causing click coordinate translation to be wrong and
   buttons to stop responding after dragging the dialog.

4. frame_buf_button_at: now walks up the scene tree checking ancestor
   enabled state. A frame_buf's scene_buf may be flagged enabled even
   when an ancestor tree is disabled (e.g. menu unmapped). Without this
   check, clicks could be incorrectly routed to ghost frame_bufs from
   recently-unmapped menus, causing root-menu reopen to require
   multiple clicks.
2026-05-23 21:27:19 +02:00
Window Maker bc25aa4b8a wayland: fix click delay after shade and modal dialog parenting
After shading a window, clicks on the lower titlebar would be routed to
the resizebar handler, requiring multiple clicks before one landed in
a region where frame_buf_button_at didn't return the (disabled) resizebar.

Two related bugs:

1. frame_buf_button_at iterated all child frame_bufs without checking
   enabled state. The shaded resizebar's bounds still recorded in
   fb->x/y/width/height but its scene_buf was disabled. Since the
   shaded resizebar was repositioned ON TOP of the titlebar, clicks
   in the overlapping region returned the (smaller, disabled)
   resizebar instead of the titlebar. Added an enabled-state check.

2. wlroots scene graph caches buffer dimensions for hit-testing.
   Mutating fb->base.width/height directly leaves stale bounds. Use
   wlr_scene_buffer_set_dest_size() whenever the buffer is resized.

Also fixes:
- WINGs dialog content was placed in WL_LAYER_FLOATING instead of
  under the parent frame's tree, so the content didn't follow the
  WM-managed decorations on move. Now parented under the frame tree
  and positioned at relative offset.
- wl_window_map called wlr_scene_node_raise_to_top on the client
  scene_node, which raised it above the titlebar within the frame
  tree. After unshade this hid the titlebar. Removed.
- xdg_activation focus path: raise the frame tree, not the client
  scene_node, for the same reason.
2026-05-23 21:08:19 +02:00
Window Maker 13101c53c3 wayland: fix resize by refactoring scene graph to relative coordinates
The scene graph was using absolute coordinates for all nodes with the
frame tree at (0,0). This caused the resizebar to be detached from the
window frame and resize to break because child nodes (titlebar, client
surface, resizebar) had to be manually repositioned on every move/resize.

Refactor to the correct wlroots model:
- Frame tree positioned at (frame_x, frame_y)
- All children use local offsets relative to the tree
- Moving the tree moves everything automatically

Additionally fix interactive resize:
- handle_toplevel_commit now syncs the WM frame to the client's actual
  committed buffer size, ensuring frame and client stay in lockstep
- Ensure client scene_node is always parented under the frame tree
- Simplify wl_window_resize to just send xdg_toplevel.set_size without
  blocking event loop dispatch
- Properly free old pixman images and detach stale buffers on resize
2026-05-23 20:13:07 +02:00
Ollie 2d5c80f332 wl_backend: fix resizebar texture and client frame_rel update on resize
1. Resizebar: wl_frame_paint_resizebar was painting a flat color buffer
   over the textured resizebar rendered by wl_frame_paint. Make it a
   no-op since the parent frame buffer has the correct texture.

2. Resize gap: client_synth_configure updates the client scene_node
   position but was not updating frame_rel_x/y. When frame_configure
   ran next (e.g. on subsequent move), it would recompute the client
   position using stale frame_rel values, causing the surface to jump.
   Now updates frame_rel_x/y from the new absolute position.
2026-05-23 19:34:56 +02:00
Ollie f88dfac8b9 framewin: repaint frame after configure/resize
On X11, resizing a frame triggers an Expose event which repaints the
decorations. On Wayland, no such event is generated, so the frame
(titlebar, resizebar) was never repainted after resize — leaving
stale decorations at the old width.

Call frame_paint after reconfigure in both wFrameWindowConfigure
and wFrameWindowResize.
2026-05-23 19:22:56 +02:00
Ollie 4f70ab6df5 wl_backend: fix resizebar click detection
frame_buf_button_at had a size threshold (width>30 || height>30) that
skipped resizebar frame_bufs during hit-testing. The resizebar is wide
but short (~8px), so it was always skipped. Clicks in the resizebar
area fell through to the parent frame, preventing resize.

Remove the size threshold. The smallest-area heuristic already ensures
buttons (small) are preferred over resizebars (large) when both match.
2026-05-23 19:20:18 +02:00
Ollie 4b338d11d0 wl_backend: fix client surface rendering with proper scene output commit
Client surfaces (e.g. foot terminal) were not updating after initial
map. Two issues:

1. wlr_scene_output_commit(scene_output, NULL) in wlroots 0.19 may
   skip rendering if it determines no damage is pending, even when
   client surfaces have committed new buffers.

2. Frame scheduling was dependent on host compositor timing.

Fix: Replace wlr_scene_output_commit with explicit build_state +
commit_state cycle which properly tracks damage. Also schedule a
frame unconditionally every loop iteration to ensure continuous
rendering in nested mode.
2026-05-23 19:14:57 +02:00
Ollie a438713b92 WINGs/wview_wl: implement internal DnD for Wayland
Implement wl_drag_begin as a simple internal drag-and-drop state machine
for WINGs-to-WINGs drag operations (color wells, text widgets).

On button press, waits for motion to confirm drag intent, then enters
a drag loop tracking the cursor. On release, finds the view under the
cursor and if it has drag destination procs + matching types, fetches
data from the source and calls performDragOperation on the destination.

This handles same-process DnD without needing wl_data_device protocol.
2026-05-23 19:07:54 +02:00
Ollie 1c96a93ac8 menu: add dock/clip/dock-position menus to findMenu lookup
findMenu() only checked root_menu, switch_menu, and window_menu.
Dock and clip menus were never found, so pointer motion over them
could not highlight entries or activate on release.

Add CHECK_MENU calls for scr->dock->menu, scr->clip_menu, and
scr->dock_pos_menu.
2026-05-23 19:04:17 +02:00
Ollie 5558a1edf0 WINGs/wfont_wl: remove stale text comparison in wl_text_width
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).
2026-05-23 16:41:44 +02:00
Ollie 3acf2f6b2b WINGs: implement Wayland selection fetch (middle-click paste)
Add selection_fetch vtable slot for synchronous selection retrieval.
On Wayland, WMRequestSelection uses this to fetch clipboard/primary
selection data directly (via W_ClipboardFetchFn -> seat pipe read)
and calls the callback immediately. On X11, the async path
(selection_request -> SelectionNotify event) is unchanged.

This makes middle-click paste work in WINGs text widgets on Wayland.
2026-05-23 16:37:58 +02:00
Ollie 130fd760b5 docs: mark Phase D complete, add src/ audit results
Phase D (WINGs widget X11 elimination) is complete with 7 commits.
The src/ core audit confirms all X11 is already routed through
wm_backend-> dispatch. The entire codebase has zero X11 executing
on the Wayland path.
2026-05-23 16:31:45 +02:00
Ollie 7077e00d12 WINGs: remove dead X11 code from wtext.c and wmisc.c
- wtext.c: remove unused XEvent variable
- wmisc.c: remove dead #ifndef DOUBLE_BUFFER branches (XClearWindow)
  DOUBLE_BUFFER is always defined; these were unreachable.
2026-05-23 16:19:48 +02:00
Ollie 1ab108f7aa WINGs/wevent: fix NULL toplevel crash on Wayland expose dispatch
W_TopLevelOfView returns NULL for views without a topLevel ancestor
(e.g. geometry display widgets parented directly to root). On X11 this
never triggered because expose events only arrived for mapped windows
with proper widget hierarchy. On Wayland, wl_redisplay synthesizes
expose events for any view, exposing the NULL case.

Fix: fall back to the view itself when no topLevel ancestor exists.
2026-05-23 16:17:18 +02:00
Ollie 8ec338016a WINGs/wcolorpanel: gate magnifier via vtable callback dispatch
The magnifier is X11-backend-specific (screen capture). Instead of a
disguised is_x11 check, the view backend provides the callback directly:
- X11: .magnify_callback = W_ColorPanelMagnify (the magnifier impl)
- Wayland: .magnify_callback = NULL (button does nothing)

The button wiring uses the vtable value as the action callback.
No conditionals, no capability flags, pure vtable dispatch.

Also removes the screen_grab_image vtable slot that was a disguised check.
2026-05-23 16:15:03 +02:00
Ollie 0e26aa878c WINGs/wcolorpanel: replace pixmap/copy/fill X11 calls with render backend
Converts 60 X11 calls (XCreatePixmap, XFreePixmap, XCopyArea,
XFillRectangle) to render backend vtable dispatch. Remaining 40
calls are all in the magnifier feature (screen capture, inherently
platform-specific) and will be handled separately.
2026-05-23 16:09:10 +02:00
Ollie 9ccfd33971 WINGs: route selection acquire/release/request through vtable
- WMDeleteSelectionHandler: X11 grab/release replaced with selection_release vtable
- WMRequestSelection: XGetSelectionOwner+XConvertSelection replaced with selection_request vtable
- x11_selection_release: now properly releases ownership (was no-op)
- x11_selection_request: new vtable impl for X11 selection conversion
- Wayland selection_request: NULL (no-op, returns False)
2026-05-23 16:02:11 +02:00
Ollie 2dce45432d WINGs: route XOR drawing through vtable, remove X11 from wtextfield/wsplitview
- wsplitview.c: XFillRectangle+ixorGC replaced with xor_fill_rect vtable call
- wtextfield.c: removed Display *dpy and XRotateBuffers (cut buffer is dead)
- Added xor_fill_rect to W_ViewBackend (X11 impl, Wayland NULL/no-op)
2026-05-23 15:53:16 +02:00
Window Maker 9eecb2511c WINGs Phase D: port wballoon, wpopupbutton, wtext to vtable
New vtable slots: pointer_grab, pointer_ungrab, bell, balloon_draw, text_init
All implemented in X11 backend, no-ops in Wayland backend.

wballoon.c: XTranslateCoordinates -> get_screen_position, showText -> balloon_draw
wpopupbutton.c: all 7 Xlib calls replaced (grabs, coords, flush)
wtext.c: XMapWindow, XBell, XGrabPointer, XUngrabPointer, cursor, GC init all ported
2026-05-23 15:26:48 +02:00
Window Maker 264679a2d1 WINGs: port wwindow.c to vtable dispatch (Phase D)
Removes all direct Xlib calls from wwindow.c (25 calls eliminated).
ICCM/EWMH property setting dispatched through W_ViewBackend slots:
- window_set_title, window_set_icon_title, window_set_icon_image
- window_realize (WM_CLASS, WM_HINTS, WM_PROTOCOLS, transient-for)
- window_set_geometry (WM_NORMAL_HINTS)
- window_withdraw (XWithdrawWindow)

X11 backend implements full property setting.
Wayland backend is no-op (compositor-internal windows).
Struct moved to wwindow_p.h for backend access.
2026-05-23 15:19:52 +02:00
Window Maker 11c5625d1e WINGs: add Phase D vtable slots, port wballoon.c
Adds window_set_title, window_realize, window_set_geometry,
window_withdraw, pointer_grab, pointer_ungrab, bell, balloon_draw
slots to W_ViewBackend.

Ports wballoon.c:
- XTranslateCoordinates replaced with get_screen_position vtable
- showText replaced with balloon_draw vtable dispatch
- X11 backend calls existing rendering code
- Wayland backend is no-op (WM-level balloon handles dock tooltips)
2026-05-23 15:13:38 +02:00
Window Maker eeda48d24e Fix clipboard free mismatch: XFree -> wfree
x11_clipboard_fetch now returns wmalloc copy (XFree internally).
Callers use wfree uniformly on both backends. Prevents X11 regression
where XFree was called on wmalloc memory or vice versa.
2026-05-23 15:04:15 +02:00
Window Maker 0083654d2e WINGs: route DnD through view backend vtable
Adds drag_begin slot to W_ViewBackend. WMDragImageFromView dispatches
through it. X11 backend sets NULL (falls through to existing XDND
code). Wayland backend is a no-op — prevents crash without guards.
2026-05-23 15:02:30 +02:00
Window Maker cee271f2cd WINGs: cross-client clipboard via wlr_seat selection
Bridges WINGs internal clipboard to the Wayland seat selection so
copy/paste works between compositor-internal dialogs and real
Wayland clients. Store creates a wlr_data_source and sets seat
selection. Fetch reads from foreign selection sources via pipe.
2026-05-23 14:59:42 +02:00
Window Maker 0dc7e33e4b WINGs: route clipboard through view backend vtable
Adds clipboard_store/clipboard_fetch to W_ViewBackend. Replaces
direct XFetchBuffer/XStoreBuffer calls in wtextfield.c and wtext.c
with vtable dispatch. X11 backend wraps Xlib, Wayland backend uses
an internal buffer.
2026-05-23 14:55:59 +02:00
Window Maker e7427f08db WINGs Wayland: implement view ops (move, resize, unmap, raise, lower, reparent)
Replaces all no-ops in wview_wl.c with real implementations:
- move: updates pos, triggers parent redisplay
- resize: reallocates pixman buffer, triggers redisplay
- unmap/unmap_subviews: clears mapped flag, triggers parent redisplay
- raise: moves view to end of sibling list (drawn last = on top)
- lower: moves view to front of sibling list (drawn first = on bottom)
- reparent: moves between parent children lists
2026-05-23 14:51:07 +02:00
Window Maker 4c5f07f9ec Phase C complete: balloon tooltips + window opacity
C1 (slide animations): already works - misc.c calls vtable window_move
C2 (menu scrolling): pure policy code, already works
C3 (balloon tooltips): pixman text render to wlr_scene_buffer overlay
C4 (cursor themes): wlr_xcursor_manager already in place
C5 (window opacity): read _NET_WM_WINDOW_OPACITY, apply to frame +
    child buffers + client surface via wlr_scene_buffer_set_opacity
2026-05-23 14:46:18 +02:00
Window Maker a0a27b56d5 Update ACTION_PLAN.md and WAYLAND_ROADMAP.md 2026-05-23 14:30:29 +02:00
lkn f3cb593d0f fix: button bevel colors derived from titlebar background
Hardcoded white/dark bevel looked wrong against colored titlebars.
Derive highlight and shadow colors from the actual titlebar background
color (+33% for highlight, -33% for shadow) to match the titlebar
bevel style.
2026-05-23 14:18:34 +02:00