Commit Graph

651 Commits

Author SHA1 Message Date
lkn c982a29d2f icon: repaint dock dots after tile/appearance observer notifications
On Wayland there are no Expose events, so when tileObserver or
appearanceObserver repaints an icon (via update_icon_pixmap or
window_clear), the dock dots drawn by appicon_paint_dock_dots
were lost. Explicitly re-trigger dock dots painting for docked
appicons after the observer repaint.
2026-06-21 18:23:36 +02:00
lkn 6611dd4853 wayland: implement appicon dock dots and launching stipple
Replace the no-op wl_noop_appicon_paint_dock_dots with a real
implementation that draws:
- 3 white dots with black shadow for docked+not-running icons
- Checkerboard dimming (stipple) for launching icons

Dot geometry matches the X11 backend: positioned at 4m/9m/14m
horizontally, icon_size-6m vertically (m = icon_size/64, min 1).
2026-06-21 18:19:21 +02:00
lkn 8f45001ffc wayland: fix MakeGhostIcon by handling raw pixman_image_t* drawables
wl_create_rimage_from_drawable only looked up frame_buf IDs, but
icon->pixmap on Wayland is a raw pixman_image_t* from RConvertImage,
not a frame_buf ID. When frame_buf_find fails, fall back to treating
the drawable pointer as a pixman_image_t* directly.

This fixes the ghost dock shadow (semi-transparent overlay shown
during icon drag) which was silently failing because MakeGhostIcon
returned WM_NATIVE_NONE.
2026-06-21 18:15:36 +02:00
lkn 0ace31b8a4 wayland: fix clip icon rendering with filled triangle arrows
The clip icon was not rendering properly because:
1. An early return prevented painting when workspaces were not yet
   initialized (moved the check so base tile always paints)
2. The filled triangle arrows (top-right and bottom-left) drawn by
   X11 paintClipButtons were missing entirely

Add pixel-level triangle drawing matching the X11 implementation
geometry: CLIP_BUTTON_SIZE-based sizing with 5px margins.
2026-06-21 18:12:05 +02:00
lkn a3413a8402 WINGs/wayland: commit correct topLevel view after child widget repaint
The upward compositing walk in render_wl_pixmap_copy, render_wl_fill_rect,
and wl_draw_string traverses from the repainted widget to the root view.
Previously, the commit at the end targeted the root view or searched its
direct children for a topLevel — this found the main window instead of
the dialog containing the widget that actually changed.

Fix: track the topLevel ancestor during the upward walk and commit that
specific view. This ensures dialog widgets (buttons, lists) have their
visual feedback rendered to the correct scene_buf.
2026-06-21 17:55:35 +02:00
lkn c9f0fc8370 wayland: recursive frame_buf_hit resolves WINGs views in dialogs
frame_buf_hit now walks children recursively (up to 4 levels) instead
of only checking immediate children of top-level frames. This resolves
WINGs views nested inside fake_leader frames (icon chooser, message
dialogs), enabling event delivery to the correct WINGs widget.
2026-06-21 17:51:41 +02:00
lkn 5325a51b64 wayland: fix double-free crash when destroying shared WApplication
When main_window_desc is the real WWindow (found via wWindowFor rather
than created by makeMainWindow), wApplicationDestroy must not call
wWindowDestroy on it — the window is still managed and will be destroyed
by wUnmanageWindow. Add shared_main_desc flag to track ownership.
2026-06-21 17:43:42 +02:00
lkn 29550b58cb wayland: fix WApplication to reuse existing WWindow with frame
- application.c: wApplicationCreate now tries wWindowFor(main_window)
  before creating a new frameless WWindow via makeMainWindow. For
  Wayland native clients where main_window == client_win, this returns
  the real WWindow with its frame, title, and updated wm_class/instance.

- window.c: Disable shared_appicon for Wayland native clients (no
  client_leader or group_id). The shared_appicon logic replaces
  main_window with a fake group leader ID, which breaks the
  wWindowFor lookup and produces a frameless duplicate WWindow.

Fixes the kill dialog showing "application" instead of the window title
for Wayland clients.
2026-06-21 17:37:31 +02:00
lkn c027f092c0 cleanup: remove debug wwarning/fprintf output
Remove diagnostic output from wl_framebuf.c (hit debug), wl_handlers.c
(button routing), wl_grabstate.c (grab/ungrab), wl_client.c (reparent),
wl_xdg.c (toplevel unmap), window.c (wWindowMap), wview_wl.c
(map/unmap), superfluous.c (MakeGhostIcon), and appicon.c (move loop).

Also simplify the wl_unmap logic in wview_wl.c.
2026-06-21 17:25:06 +02:00
lkn bf552c9be2 appicon: use wm_class (app_id) in kill dialog instead of wm_instance
For Wayland clients, wm_instance is the window title (often long and
non-descriptive for identification) while wm_class is the app_id which
is the application identifier. Prefer wm_class for the kill confirmation
dialog, falling back to basename(wm_instance) then "application".
2026-06-21 17:21:22 +02:00
lkn 611a886582 menu: fix appicon menu hit detection and edge scrolling during drag
- findMenu(): add icon_menu to the walk list so the appicon right-click
  menu responds to pointer motion during its modal drag loop.

- dragScrollMenuCallback: remove the scrollable_menus gate so menus
  scroll at screen edges during drag-select regardless of the
  scrollable_menus preference (that preference controls the non-modal
  scroll path in handleMotionNotify which does not run during the
  menu modal loop).
2026-06-21 17:06:09 +02:00
lkn 7114da35ba wayland: fix XWayland cursor position offset by titlebar height
view_surface_at() was double-subtracting the frame_rel offset. Since
v->x/v->y already represents the client content position (frame origin
+ frame_rel), the surface-local coordinates are simply px - v->x. The
bounds check now correctly tests against 0..width/height.
2026-06-21 16:59:58 +02:00
lkn 949fc9f94a wayland: destroy XWayland appicons on surface unmap
Call wApplicationDestroy after wUnmanageWindow in the XWayland unmap
handler, matching the XDG and X11 handleDestroyNotify paths. Fixes
XWayland appicons persisting after the application closes.
2026-06-21 16:57:16 +02:00
lkn 3d953339f8 wayland: fix XWayland titlebar actions and cursor
- wl_pointer_focus.c: In view_surface_at(), check frame bounds for
  XWayland views before returning the surface. When pointer is over
  frame decorations (titlebar, buttons, resizebar), continue the loop
  so the frame_buf handles the event. Fixes titlebar buttons (close,
  iconify, shade) not responding for XWayland applications.

- wl_xwayland.c: Set left_ptr cursor on the XWayland root window at
  startup via XDefineCursor. Fixes the default X cursor (big X) showing
  for X11 applications that do not set their own cursor.
2026-06-21 16:55:02 +02:00
lkn 29d183fe8f wayland: implement appicon dock/clip clamping
Enable the full appicon drag-to-dock/clip workflow for native Wayland
clients:

- window.c: Set main_window = client_win for Wayland clients that lack
  client_leader and window_group, so wApplicationCreate runs and
  produces a WAppIcon.

- wl_xdg.c: Call wApplicationDestroy after wUnmanageWindow on toplevel
  unmap, mirroring the X11 handleDestroyNotify path. Fixes appicons
  persisting after app close.

- wl_event.c: Commit the wlroots scene in wl_event_flush so
  slide_windows animation renders intermediate frames.

- backend.h, x11_backend.c, wl_icon.c, superfluous.c: Add
  create_rimage_from_drawable vtable method so MakeGhostIcon can read
  frame_buf pixels on Wayland for the dock shadow overlay.

- wl_icon.c, wl_stubs.c: Implement wl_icon_update_pixmap with
  shadowed (dimmed) overlay for attracted icons.

- wl_dock.c: Disable the placeholder shm_surface dock panel now that
  the real wmaker dock framework operates via frame_bufs.
2026-06-21 16:44:49 +02:00
Levi Neely 50d0cc2c04 cleanup stray files 2026-06-08 16:12:30 +02:00
Levi Neely 5c5cf86f44 wtf 2026-06-08 16:11:56 +02:00
Levi Neely 2afbf97b4c fix build 2026-06-08 16:10:59 +02:00
lkn f2fa6f0529 WME_BUTTON_PRESS on menuView: do not set insideMenu (only motion initiates drag) 2026-06-07 17:47:20 +02:00
lkn 0cba6c4bda popup: insideMenu set by motion/click on menuView, not enter; release guard uses insideMenu only
Three changes to fix press-drag-release vs simple click semantics:

1. WME_ENTER no longer sets insideMenu. On Wayland, the enter event for
the menu surface fires too early (menu overlaps button), incorrectly
marking simple clicks as drag interactions.

2. WME_MOTION on menuView sets insideMenu=1 on the first motion,
initiating drag interaction. This matches the desired semantics:
moving the pointer into the menu after press establishes intent.

3. BUTTON_RELEASE close/select guard checks insideMenu only, not
event->window == menuView. A release on the menu surface without
prior motion (simple click on button where menu happens to be under
the pointer) no longer triggers selection.
2026-06-07 17:42:06 +02:00
lkn cfddd2ebfc BUTTON_RELEASE: capture selection before popDownMenu clears insideMenu/highlightedItem
popDownMenu() resets insideMenu=0 and highlightedItem=-1. When called before
the selection logic, the guard (insideMenu && highlightedItem >= 0) is always
false, so WMSetPopUpButtonSelectedItem is never called and the closed-button
display never updates.

Fix: capture the selection state (insideMenu, highlightedItem, enabled item)
into local variables BEFORE calling popDownMenu. Apply the selection
(WMSetPopUpButtonSelectedItem + action callback) AFTER popDownMenu.
2026-06-07 17:38:05 +02:00
lkn 874f9b1ae0 fix popup reopen: shrink view size on 1x1 unmap; fix cascade commit target
Two concrete bugs fixed:

1. Popup reopen with 1x1 buffer: W_ResizeView returns early when view size
matches requested size. After 1x1 unmap, view->size.width/height was still the
original correct size, so resizeMenu never triggered wl_client_toplevel_resize.
Fix: set view size to 1x1 after replacing the buffer.

2. Selected item not updating button display: render_wl_pixmap_copy cascade
walks up to rootView (no WLClientToplevel) and commits it (no-op). After
paintPopUpButton, the mainAppView backing is updated but never committed.
Fix: when the cascade reaches rootView, fall back to committing the first
topLevel child that has a client backing.
2026-06-07 17:32:44 +02:00
lkn 1229f15a8e wl_client_view_unmap: replace buffer with 1x1 transparent instead of NULL to avoid xdg unmap
NULL-buffer unmap requires a configure/ack cycle before the next real buffer
commit. The compositor may not send a configure event for a NULL unmap,
leaving the surface stuck at configured=0 on reopen.

Fix: replace the popup buffer with a 1x1 transparent buffer on close.
This hides the popup visually without triggering an xdg unmap. The surface
stays configured and alive. On reopen, resizeMenu (now always called in
popUpMenu) creates a correct-size buffer via wl_client_toplevel_resize.
wl_redisplay then paints into the new buffer and commits immediately.
No configure/ack cycle needed.
2026-06-07 17:25:27 +02:00
lkn 93d69639dc add targeted diagnostics to commit_locked, configure, and wl_map dispatch paths 2026-06-07 17:13:24 +02:00
lkn 0b80bc4efb cleanup: remove dispatch from popUpMenu, keep in wl_map 2026-06-07 17:02:32 +02:00
lkn af4d33032a popUpMenu: dispatch pending Wayland events after W_MapView to process configure 2026-06-07 16:59:25 +02:00
lkn 88596112f3 wl_client_view_unmap: NULL buffer without configured=0; surface stays configured after first configure 2026-06-07 16:55:32 +02:00
lkn a6a692baf1 restore NULL-buffer unmap + dispatch pending events in wl_map after redisplay
Revert the 1x1-buffer approach which caused pointer focus issues. Return
to NULL-buffer unmap which correctly hides the popup. The configure event
from the NULL unmap is dispatched in wl_map via W_WLClientDispatchPending
after wl_redisplay and before returning, ensuring the surface is
configured before the user can interact with the popup.
2026-06-07 16:53:06 +02:00
lkn 96dc7fa6a8 WME_BUTTON_PRESS: do not set insideMenu on main button open - only menuView press/enter sets it 2026-06-07 16:49:18 +02:00
lkn 0e9df79182 WME_ENTER: only set insideMenu for real menuView enter, not main button 2026-06-07 16:46:48 +02:00
lkn 6b5b015cd8 popDownMenu: reset insideMenu and highlightedItem to prevent stale state on reopen 2026-06-07 16:42:25 +02:00
lkn 230eefd8d3 wl_client_view_unmap: use 1x1 transparent buffer instead of NULL to avoid xdg unmap
NULL-buffer unmap triggers a wlroots xdg_surface unmap, which requires a
configure/ack cycle before the next buffer attach. This creates a race
window where the popup reopen cannot commit its real buffer yet, causing
the click to hit the main window instead of the popup.

Fix: replace the popup buffer with a 1x1 transparent ARGB buffer instead
of attaching NULL. This hides the popup visually (the tiny buffer is
invisible) without unmapping the xdg_surface. The surface stays configured
and alive, so the next popup open can commit a real buffer immediately
without waiting for a configure event.

Also: always call resizeMenu() in popUpMenu to ensure the backing buffer
is recreated at the correct dimensions after the 1x1 replacement.
2026-06-07 16:39:34 +02:00
lkn 2a335646ea add diagnostics to handleActionEvents for popup close-reopen debugging 2026-06-07 16:31:24 +02:00
lkn bbef21785b popup: all popDownMenu calls in BUTTON_RELEASE now guarded by menuView/insideMenu check 2026-06-07 16:03:50 +02:00
lkn 8c7b201823 popup: only close on BUTTON_RELEASE from menuView or when insideMenu active 2026-06-07 16:00:42 +02:00
lkn 1fce95d0cc add comments clarifying the xdg configure lifecycle after NULL-buffer unmap 2026-06-07 15:54:38 +02:00
lkn 931094cce8 wl_client_view_unmap: reset configured flag so remap waits for configure 2026-06-07 15:52:40 +02:00
lkn d923d9fb83 wl_unmap: send NULL to wl_surface when W_ViewSceneNodeSetEnabledFn unavailable 2026-06-07 15:48:38 +02:00
lkn f95cd3d6d3 Revert "wire W_ViewSceneNodeSetEnabledFn in WINGs client path via recycle/remap"
This reverts commit 340a60927e.
2026-06-07 15:46:53 +02:00
lkn 340a60927e wire W_ViewSceneNodeSetEnabledFn in WINGs client path via recycle/remap
In WINGs client mode (e.g. WPrefs), W_ViewSceneNodeSetEnabledFn was never
set because the compositor-side wl_backend.c does not run in the client
process. When popup close calls wl_unmap, the function pointer was NULL,
so the scene node was never disabled and the popup remained visible.

Fix: during W_WLClientInit, if W_ViewSceneNodeSetEnabledFn is still NULL
(unset by compositor), set it to wl_client_scene_node_set_enabled which
calls recycle (destroy xdg_toplevel + wl_surface) on disable and remap
(recreate from scratch) on enable. This ensures the client-side popup
lifecycle correctly removes and recreates the surface, eliminating stale
pixels without depending on compositor-side function pointers.
2026-06-07 15:44:22 +02:00
lkn 405c481e38 clean up diagnostics in wl_unmap and wl_view_scene_node_set_enabled
Remove duplicate W_ViewSceneNodeSetEnabledFn call, fix malformed debug code.
wl_unmap now logs cleanup diagnostics once. wl_view_scene_node_set_enabled
logs proxy ID lookup, match result, and no-match case properly.
2026-06-07 15:38:19 +02:00
lkn 7b15ded31a add diagnostics to wl_view_scene_node_set_enabled for popup stale-pixel tracing 2026-06-07 15:35:25 +02:00
lkn 2fca1e1df3 add diagnostics to wl_unmap and wl_view_scene_node_set_enabled for popup stale-pixel debugging 2026-06-07 15:34:51 +02:00
lkn 118a7c30a9 wl_unmap: recycle WINGs client wl_surface on popup close to eliminate stale pixels
The stale popup content visible under the main window after close comes from
the wl_redisplay composite of the popup into the parent backing (rootView).
Even though rootView is not committed to any wl_surface, the popup surface
itself retains its last committed buffer. Disabling the scene node is
insufficient for completely eliminating visual artifacts.

Fix: add wl_client_toplevel_recycle which destroys the xdg_toplevel,
xdg_surface, wl_surface, and SHM buffer but preserves the WLClientToplevel
struct and its WINGs window ID mapping. On unmap (wl_unmap), call recycle
for topLevel popups. On remap (wl_map), call wl_client_toplevel_remap which
recreates all Wayland protocol objects from scratch, triggering a fresh
configure cycle. This ensures no stale buffer or state persists between
open/close cycles.
2026-06-07 15:29:33 +02:00
lkn 60efe4db78 wl_view_scene_node_set_enabled: find WINGs client toplevels via wl_proxy_get_id
The function only handled wl_frame_buf entries. WINGs client popup menus have
their own xdg_toplevel surface with a scene_node but no wl_frame_buf. Their
WINGs view window IDs (0x20000000+) differ from compositor view IDs
(0x10000000+), so wl_find_view_by_id could not find them.

Fix: add wlc_top_get_surface_id() in wclient_wl.c which returns the
libwayland-client proxy ID for the wl_surface. In
wl_view_scene_node_set_enabled, use this ID to iterate the compositor
toplevel_list and find the matching wlr_surface resource by object ID.
Then enable/disable the view scene_node directly.
2026-06-07 15:00:08 +02:00
lkn b30cfa31d9 Revert "wl_unmap: send NULL buffer to WINGs client toplevel surfaces on unmap"
This reverts commit 38a0009e03.
2026-06-07 14:56:02 +02:00
lkn 38a0009e03 wl_unmap: send NULL buffer to WINGs client toplevel surfaces on unmap
When a WINGs client popup is unmapped (popDownMenu), the scene node is
disabled via W_ViewSceneNodeSetEnabledFn. But for WINGs client toplevels
(which have their own wl_surface + xdg_toplevel via libwayland-client),
the surface still holds its last committed buffer. Disabling the scene
node is not enough - the compositor still sees the surface as mapped.

Fix: add wl_client_toplevel_unmap which attaches NULL to the wl_surface
and commits, properly unmapping it from the compositor. Wire through
W_WLClientUnmapFn function pointer in wview_wl.c, called from wl_unmap
for topLevel views.
2026-06-07 14:51:30 +02:00
lkn 1b04023591 Revert "wl_unmap: force commit sibling toplevels to clear stale popup pixels"
This reverts commit a9397b8291.
2026-06-07 14:50:58 +02:00
lkn 3e5c594d6f Revert "wl_view_scene_node_set_enabled: also handle WINGs client toplevels (popups)"
This reverts commit 971089b3d9.
2026-06-07 14:50:58 +02:00
lkn a9397b8291 wl_unmap: force commit sibling toplevels to clear stale popup pixels
When a topLevel popup is unmapped, wl_redisplay(view-parent) clears stale popup pixels from the parent backing. But for rootView (common parent), the commit at the end of wl_redisplay is a no-op because rootView has no WLClientToplevel. The cleared backing was never pushed to any surface. Fix: iterate parent child list and force-commit every topLevel sibling, pushing the cleared backing to their wl_buffers.
2026-06-07 14:46:02 +02:00