Commit Graph

698 Commits

Author SHA1 Message Date
lkn 03eede810b fix crash: resolve frame_buf IDs via W_GetFrameBufImageFn
After removing frame_bufs from the view_table, policy code like
update_icon_title still passes frame_buf IDs to WMDrawString.
These IDs (0x10000000 range) were being treated as raw pointers,
causing a segfault. Add W_GetFrameBufImageFn hook that resolves
frame_buf IDs to pixman images via frame_buf_find().
2026-06-23 22:40:49 +02:00
lkn b20197ac91 fix memory leaks: free color description strings and icon paths
WMGetColorRGBDescription() returns wmalloc strings that were passed
directly to allocFrameBorderPixel without freeing. get_default_image()
and get_icon_image() leaked path strings from FindImage/get_icon_filename.
2026-06-23 22:20:40 +02:00
lkn a6f43cdbe1 fix use-after-free: detach reparented children before tree destroy
When destroying a frame_buf tree, any other frame_bufs whose trees
were reparented into it (e.g. fake_leaders) would have their
tree_destroy_handler fire on already-freed memory during cascade.
Detach their listeners and NULL their tree pointers before
destroying the parent tree.
2026-06-23 22:16:42 +02:00
lkn 01904fdb39 fix use-after-free: destroy child tree before dropping buffer
When destroying child frame_bufs, the tree node was not destroyed
before wlr_buffer_drop freed the struct. Later, cascade destruction
of the parent tree would fire fb_tree_destroy_handler on the freed
child, corrupting the heap. Destroy the child tree explicitly first.
2026-06-23 22:08:29 +02:00
lkn 69b08e6cfb add wl_kaboom.c to Makefile.am 2026-06-23 22:04:03 +02:00
lkn 7f6a7b66d1 detach scene buffer before all pixman image replacements
Call wlr_scene_buffer_set_buffer(NULL) before freeing the old pixman
image in every resize path (client configure, frame configure,
workspace badge, balloon). This ensures the scene graph never holds
a dangling reference to freed pixel data.
2026-06-23 21:42:00 +02:00
lkn 711ff08b57 revert unsafe titlebar resize: draw into parent frame instead
The in-place resize of titlebar pixman images continues to cause heap
corruption regardless of scene buffer detach order. Fall back to
drawing into the parent frame buffer when the titlebar is too narrow,
which is always safe since fb->image is already the correct size.
2026-06-23 21:24:52 +02:00
lkn 49a0b50a6d fix widget rendering: stop polluting view_table with frame_buf IDs
Frame_buf IDs (0x10000000-0x1FFFFFFF) were registered in the 256-entry
view_table alongside WINGs views, filling it with tombstones until
lookups failed. Now frame_buf IDs are excluded from the table; the 3
callers that passed frame_buf IDs to WMDrawString pass raw pixman
pointers instead.
2026-06-23 21:22:14 +02:00
lkn f96c847cf7 workspace name: match original bold shadow text rendering
Draw white text at 5x5 offsets to build a shape mask (like the
original XShape-based approach), then draw centered text at (2,2)
and apply the mask as alpha. This gives the same outlined text
appearance as the X11 version.
2026-06-23 20:50:52 +02:00
lkn 6ae9ad3dc5 handle xdg_toplevel unset_fullscreen request
Check toplevel->requested.fullscreen to determine whether the client
wants to enter or leave fullscreen, and call wUnfullscreenWindow
accordingly.
2026-06-23 20:47:04 +02:00
lkn 321df47493 send XDG fullscreen state to Wayland clients
Add client_set_fullscreen backend vtable entry. Call
wlr_xdg_toplevel_set_fullscreen on enter/leave so clients
(e.g. Firefox) know to render content at full size.
2026-06-23 20:40:57 +02:00
lkn dd1302a711 fix titlebar resize: detach buffer from scene before replacing
Call wlr_scene_buffer_set_buffer(NULL) before freeing the old pixman
image so the scene graph cannot access freed data. Re-register the
backing table entry after creating the new image.
2026-06-23 20:35:31 +02:00
lkn c2c3bca41b kaboom: detach buffer from scene before freeing pixel data
Call wlr_scene_buffer_set_buffer(NULL) before destroying the tree
and freeing the pixman images to prevent the scene graph from
accessing freed memory during its next render pass.
2026-06-23 20:32:28 +02:00
lkn ac74064d1c kaboom: match original X11 physics
Use fixed-point x positions, strong upward initial velocity (-15 to
-21), gravity of 1 pixel/frame², only ~50%% of tiles, and run until
all pieces leave the screen. Full-screen scene buffer so pieces
can fly freely.
2026-06-23 20:30:52 +02:00
lkn 503cdb5dca fix crash: heap corruption from unsafe titlebar buffer resize
wl_frame_paint replaced the titlebar pixman image while the scene
graph could still hold a wlr_buffer reference to the old data.
Falling back to the parent frame buffer when the titlebar is too
narrow avoids the use-after-free.
2026-06-23 20:23:24 +02:00
lkn 146f41008d wayland: implement kaboom animation for dock icon removal
Splits icon into PIECE_SIZE tiles, animates them falling with
gravity using a wl_event_loop timer and a single scene buffer.
2026-06-23 20:16:33 +02:00
lkn 976bcce34c fix DnD: drag icon follows cursor, clean up listeners
Update drag_icon_tree position in handle_pointer_motion so the icon
follows the cursor during drag. Use wlr_scene_drag_icon_create for
proper lifecycle. Remove listeners in handle_drag_destroy. Always
forward button releases so drags end correctly.
2026-06-23 20:08:39 +02:00
lkn ce696a72a0 fix DnD crash: do not double-deliver button events during drag
When a drag grab is active, wlroots internally handles button events
via the grab mechanism. Calling wlr_seat_pointer_notify_button
manually during a drag double-delivers the release, causing an
assertion in wlr_data_source_destroy.
2026-06-23 17:33:36 +02:00
lkn 467805da20 render DnD drag icon surface following cursor
When a client starts a drag with an icon surface, create a
wlr_scene_subsurface_tree in the overlay layer and position it
at the cursor. Update position on drag motion, destroy on end.
2026-06-23 17:32:10 +02:00
lkn b90908da6a fix DnD freeze: forward button events during active drag grab
When a Wayland drag is active (seat->drag), always forward button
events so wlroots can properly end the drag. Without this, the
release never reaches the drag grab, causing stuck drags and
assertion failures on client teardown.
2026-06-23 17:29:39 +02:00
lkn 311ccfbdd9 fix drag freeze/crash: implicit grab with motion delivery
Preserve pointer focus while buttons are held (implicit grab) to
ensure the client gets the release. Still deliver motion events to
the focused surface so drag and text selection work correctly.
2026-06-23 13:43:42 +02:00
lkn 10389bbba5 fix crash: only forward button events when seat has pointer focus
wlr_seat_pointer_notify_button asserts unconditionally if no surface
has pointer focus, even for releases. Never call it without a focused
surface. This means clients may miss releases if pointer leaves their
surface during a drag, but avoids the compositor crash.
2026-06-23 13:39:08 +02:00
lkn 8c306b3e3c ignore SIGPIPE to prevent crash on DnD/clipboard pipe close
Wayland data transfers (drag-and-drop, clipboard) use pipes between
clients. If a client disconnects mid-transfer, writing to the pipe
raises SIGPIPE which kills the compositor. Ignore it.
2026-06-23 13:34:07 +02:00
lkn 89393e1782 fix dockapp capture: use XSync, remove crash-prone timer
Use XSync instead of XFlush for the initial capture to give the X
server a round-trip to process the map. Remove the deferred timer
re-capture which could crash if the icon was destroyed before firing.
2026-06-23 13:22:33 +02:00
lkn 074e9a7011 fix drawer right-click menus not responding to mouse input
findMenu() was not searching drawer menus, so pointer motion over
a drawer menu returned NULL causing the event loop to ignore input.
Add iteration over scr->drawers to findMenu().
2026-06-23 13:01:09 +02:00
lkn b6ad1df42e wayland: implement dockapp rendering inside dock icons
XWayland dockapps (wmclock, etc.) now render their content inside the
dock icon tile instead of in a separate window.

Key changes:
- wl_props.c: implement wl_prop_get_wm_hints for XWayland surfaces,
  reading xcb_icccm_wm_hints_t to detect WithdrawnState dockapps
- appicon.c: for is_dockapp windows, use client_win as icon_win
- icon.c: capture icon_window pixels via XGetImage with XShape mask
  for transparency, skip surface embedding when image is captured
- wl_icon.c: create_rimage_from_drawable handles X11 Window IDs via
  XGetImage, applies XShape bounding rectangles as alpha mask
- wl_stubs.c: pixmap_get_size returns actual view dimensions
- wl_window.c: map XWayland dockapp windows and reparent icon_window
  child into main window for compositing
2026-06-23 12:55:48 +02:00
lkn 1728c38fbe wayland: fix resource leaks causing freeze after extended use
Three leaks identified via static analysis:

1. frame_buf_destroy never freed fb->bg_pixmap. Every window with a
   textured titlebar leaked a full pixman_image_t on close.

2. handle_xwayland_destroy did not clean up frame_bufs (unlike the XDG
   path). Every XWayland window close leaked 4-5 pixman images (frame +
   titlebar + resizebar + buttons).

3. wl_deferred_decoration struct leaked if client disconnected before
   initial_commit fired. Added destroy listener to free it.
2026-06-22 18:59:08 +02:00
lkn c244148e31 wayland: route pointer events to layer surfaces
Screenshot tools (slurp) use layer-shell overlay surfaces that need
pointer input. Check if the pointer is over a layer surface before
falling through to the toplevel/frame_buf focus logic.
2026-06-22 00:33:08 +02:00
lkn c1927f0948 wayland: defer layer-shell configure to initial commit
wlroots 0.19 asserts that the surface is initialized before
wlr_layer_surface_v1_configure is called. Defer the configure to the
initial commit, matching the pattern used for xdg_toplevel surfaces.
Fixes screenshot tool crash.
2026-06-22 00:29:28 +02:00
lkn 143b8906bb wayland: fix view_table probe chain corruption on widget reopen
The WINGs view_table (open-addressing hash, size 256) used id=0 as both
"empty" and "deleted". Zeroing a slot on removal broke probe chains for
entries that hashed past that slot. After two dialog open/close cycles
(~40 views created and destroyed), enough chains were broken that
W_GetViewForWindow/W_GetViewBacking returned NULL for valid IDs.

Fix: use a tombstone marker (id=1) for deleted slots. Lookups skip
tombstones (continue probing), inserts reuse them. This is the standard
approach for deletion in open-addressing hash tables (Knuth Vol.3 §6.4).

Also:
- wl_destroy now calls view_table_remove + frees backing pixman image
- wl_frame_destroy cleans up child frame_bufs
- client_reparent existing path re-links backing and recreates scene_buf
- client_reparent to root destroys the child frame_buf
2026-06-22 00:21:42 +02:00
lkn 9f32dc4eef icon: look up freedesktop icon theme for native Wayland clients
Native Wayland clients have no _NET_WM_ICON or WM hints icon.  Before
falling back to the default icon, search the hicolor icon theme at
/usr/share/icons/hicolor/<size>/apps/<app_id>.png and /usr/share/pixmaps/
for a matching icon based on the xdg_toplevel app_id.
2026-06-21 19:24:59 +02:00
lkn bc0446aa7a wayland: account for CSD geometry offset in pointer hit testing
wlr_xdg_surface_surface_at expects surface-local coordinates (including
the shadow region). Add geometry.x/y back when converting from screen
coords to surface-local so the hit test aligns with the actual content.
2026-06-21 19:21:04 +02:00
lkn d7b2c70c7c wayland: sync scene node geometry offset on every commit
CSD clients like Firefox may not set window_geometry until after the
initial map.  Update the scene node offset on every surface commit so
the content stays aligned with the frame as geometry changes.
2026-06-21 19:19:54 +02:00
lkn bb95bd52cd wayland: apply CSD geometry offset in wl_window_move
Without this, moving a CSD client (Firefox) causes the surface to
"pop" out of the WM frame — the scene node was positioned at the
raw frame-relative coords without subtracting geometry.x/y.
2026-06-21 19:18:20 +02:00
lkn 1ee10d37f5 wayland: use xdg geometry instead of surface size for CSD clients
Firefox and other CSD clients include invisible shadow borders in their
surface buffer.  Use xdg_surface->geometry (the client-declared content
rect) for:
- reporting client width/height to the WM frame
- sizing the frame on commit
- offsetting the scene node so shadows are outside the frame bounds

Falls back to surface->current.width/height when geometry is unset.
2026-06-21 19:17:06 +02:00
lkn e0edd782d8 wayland: group all windows with same app_id into one appicon 2026-06-21 19:10:42 +02:00
lkn bebd22cbd7 wayland: group windows by app_id only when appicon is docked 2026-06-21 19:10:07 +02:00
lkn 58bb6f08b4 wayland: use app_id for both wm_class and wm_instance in PropGetWMClass
Previously wm_instance was set to the window title, but docked icons
store app_id as their wm_instance. This mismatch caused
wDockTrackWindowLaunch to fail matching the new window to the docked
icon, resulting in a duplicate free-floating appicon being created.
2026-06-21 19:08:07 +02:00
lkn 134594e0bc wayland: draw title background bar for miniwindow icons
Add the solid colored title background rectangle with light/dim bevel
edges that X11 draws via drawIconTitleBackground. This gives miniwindow
icons their characteristic "flat" title bar appearance, distinguishing
them from appicons which lack this bar.
2026-06-21 19:03:08 +02:00
lkn 69a57062b7 appicon: collapse wAppIconPaint into a thin wrapper over wIconPaint
wIconPaint already handles dock dots/stipple for docked appicons.
wAppIconPaint was redundantly calling appicon_paint_dock_dots again.
Reduce it to just wIconPaint(aicon->icon). Remove dead WS_INDICATOR
code (was #undef in wconfig.h).
2026-06-21 19:00:46 +02:00
lkn 162c0cc4ca client: use wIconPaint instead of raw backend icon_paint
For consistency, route through wIconPaint which handles dock dots
for docked appicons and ensures complete paint path.
2026-06-21 18:59:36 +02:00
lkn aee20f0425 route remaining wm_backend->appicon_paint calls through wAppIconPaint
Same pattern as 7530f1a: application.c, actions.c, client.c, and
defaults.c all called the raw backend paint, missing dock dots.
Now all go through wAppIconPaint for consistent indicator rendering.
2026-06-21 18:58:08 +02:00
lkn 7530f1a50b dock: route all appicon paints through wAppIconPaint
Multiple places in dock.c and dockedapp.c called
wm_backend->appicon_paint directly, bypassing wAppIconPaint which
adds dock dots and launching stipple. Replace all with wAppIconPaint
so indicators are always drawn.
2026-06-21 18:53:30 +02:00
lkn ec0a94e077 wayland: fix dock ghost shadow z-order (render below icon)
The dock_shadow was rendering above the dragged icon because:
1. It was in WL_LAYER_OVERLAY/DOCK, above the dock icons in WL_LAYER_FLOATING
2. wl_stacking_restack could not order nodes across different parent trees
3. wl_window_map auto-raised on map, undoing any prior restack

Fixes:
- Place dock_shadow in WL_LAYER_FLOATING (where WMDockLevel=5 maps)
- Rewrite wl_stacking_restack to reparent nodes into the same tree
  and use wlr_scene_node_place_below for guaranteed ordering
- Remove auto-raise from wl_window_map (explicit wRaiseFrame handles it)
2026-06-21 18:49:19 +02:00
lkn c90355b663 wayland: place dock_shadow below dock icons
The dock ghost shadow was in WL_LAYER_OVERLAY rendering above dock icons.
Move to WL_LAYER_NORMAL and lower to bottom so it renders beneath the
dock icons (WL_LAYER_DOCK) during icon drag, matching X11 behavior
where the ghost shows as a position marker below the real icon.
2026-06-21 18:43:43 +02:00
lkn 1d54ddf255 icon: draw dock dots/stipple at end of wIconPaint for docked appicons
Move the appicon_paint_dock_dots call into wIconPaint itself (after
icon_paint), so that ANY repaint of a docked appicon includes dots
and launching stipple. Previously, the dots were only drawn from
wAppIconPaint and the observers, but other repaint paths (pointer
events, window_clear) would erase them.

Remove the now-redundant calls from appearanceObserver and
tileObserver since wIconPaint handles it.
2026-06-21 18:36:24 +02:00
lkn 4c5855958f dock: call wAppIconPaint from dockIconPaint instead of raw backend
dockIconPaint was calling wm_backend->appicon_paint directly, which
bypasses wAppIconPaint and its appicon_paint_dock_dots call. This meant
docked icons never got their dots drawn at startup.

Call wAppIconPaint instead so the full paint path (tile + dots + stipple)
executes for all docked appicons.
2026-06-21 18:33:19 +02:00
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