Commit Graph

761 Commits

Author SHA1 Message Date
Levi Neely 15f19afeb4 Fix VT switching and multi-keyboard support
- Use wrapper struct to track keyboard pointer per-listener
- Get keyboard from listener that fired event, not from seat
- Properly clean up listeners on keyboard disconnect
2026-06-29 11:48:49 +02:00
Levi Neely 1d3843f62a Fix keyboard input in direct rendering mode
- Create XKB keymap before wlr_backend_start() so it's available when
  libinput detects keyboards synchronously during startup
- Support multiple keyboards by allocating per-device listeners instead
  of replacing listeners on each new keyboard
- Remove duplicate keymap creation code that ran too late
2026-06-29 11:45:20 +02:00
lkn 00d330fe88 wayland: add wmaker-dockapp-v1 native protocol
Defines a Wayland protocol for native dock applications (dockapps).
Clients create a wl_surface, wrap it with wmaker_dockapp_v1, and
render ARGB content at the compositor-specified tile size. The
compositor places the surface in a dock slot with full transparency
support, eliminating the opaque-black-background issue of XWayland.

Protocol:
- wmaker_dockapp_manager_v1: global, get_dockapp(surface)
- wmaker_dockapp_v1: set_app_id, configure event, closed event

Compositor implementation registers the global and handles surface
commit by placing the dockapp in its assigned dock tile frame_buf
tree.
2026-06-28 02:04:44 +02:00
lkn 77c1687f4a wayland: fix dockapp positioning in dock tile
When reparenting the XWayland toplevel surface into the dock tile,
use (0,0) position and icon_size dimensions. The getSize call on
the non-existent icon_window returned garbage causing integer overflow
in the centering calculation.
2026-06-28 01:58:33 +02:00
lkn 3098a7c2f8 Revert "wayland: dockapp rendering (WIP - XWayland surface shown as-is)"
This reverts commit e109979dcb.
2026-06-28 01:53:27 +02:00
lkn e109979dcb wayland: dockapp rendering (WIP - XWayland surface shown as-is)
Shows the XWayland toplevel surface in the dock tile. Black background
is an inherent limitation of X11 opaque windows under XWayland.
Next step: native Wayland dockapp protocol for proper transparency.
2026-06-28 01:53:00 +02:00
lkn 2cfbd7d34b wayland: fix dockapp drag-to-dock and pointer input routing
- appIconMouseDown: allow drag (Button1) even when icon->owner is NULL,
  which happens for dockapps whose WWindow is unmanaged after docking
- canBeDocked: fall back to aicon->wm_class/wm_instance when owner is
  NULL so dockapps can be snapped into dock slots
- wl_pointer_focus: don't give seat pointer focus to views embedded in
  frame_bufs (dockapps) — let WM handle input via frame_buf path
- wl_handlers button hittest: route clicks on embedded views to their
  parent frame_buf instead of the client surface
- wl_window_unmap: don't disable scene_node if view is reparented into
  a frame (docked)
2026-06-28 01:49:50 +02:00
lkn 5ead98b986 wayland: resize dockapp surface to fit dock tile
The owner's toplevel surface may be larger than icon_size. Resize it
before reparenting into the dock tile frame_buf so it fits properly.
2026-06-28 01:01:46 +02:00
lkn 14db9aecb3 wayland: fix dockapp rendering in dock tiles (WIP)
- Reparent owner's client_win surface into dock tile frame_buf tree
- Raise client scene_node above tile background
- Don't disable scene_node on unmap if reparented into a frame
- Handle OR views and XWayland child windows in client_reparent
- Diagnostics still in place
2026-06-28 00:59:34 +02:00
lkn f9f65613ba wayland: fix dockapp icon_window rendering
Dock apps (e.g. wmclock) use override_redirect icon_windows that get
reparented into dock tile frame_bufs. The reparent code only searched
toplevel_list, missing OR views in or_list. The icon_window's scene
node was never moved to the dock tile's scene tree, so it rendered
invisibly at (0,0) in the wrong layer.

- wl_client_reparent: search or_list for OR views and reparent their
  scene_node into the parent frame_buf's tree
- wl_window_map: handle OR view enable so window_map(icon_win) works
2026-06-28 00:47:52 +02:00
lkn 958bb8f4a9 appicon: fix crash on right-click of dock icon without running app
aicon->icon->owner is NULL for stored dock apps that aren't running.
Add null check before dereferencing.
2026-06-28 00:38:18 +02:00
lkn 6011f4226f wayland: implement xdg_popup support for context menus
- Listen for xdg_shell new_popup signal
- Create scene tree for popups as children of parent toplevel
- Unconstrain popup geometry on initial commit
- Store xdg_surface->data for parent lookup by nested popups
- Remove redundant wl_update_pointer_focus from button handler,
  let wlr_seat manage implicit grabs internally
2026-06-28 00:36:54 +02:00
lkn 4a58fd90eb wayland: add XWayland set_hints listener, remove hardcoded initial configure
- Listen for set_hints signal on XWayland surfaces so hints
  (including dockapp initial_state) are available at map time.
- Remove the hardcoded 640x480 initial configure — let clients
  request their own geometry via request_configure.
- Link xcb for future dockapp icon_window operations.
2026-06-27 20:30:11 +02:00
lkn 04f9a36da7 wayland: fix XWayland startup speed and swapchain exhaustion
Two fixes:

1. Handle request_configure for XWayland surfaces. Without this,
   X clients block waiting for ConfigureNotify on startup (5s timeout).
   Now we immediately ACK with wlr_xwayland_surface_configure.

2. Replace direct wlr_scene_output_commit in wl_event_flush with
   wlr_output_schedule_frame. Rendering happens in handle_output_frame
   when the output is ready. Eliminates 'No free output buffer slot'
   spam and prevents reentrant dispatch crashes.
2026-06-27 19:14:55 +02:00
lkn 0e0847b48b wayland: remove persistent X display connection
wlroots manages XWayland internally via its own xcb connection.
Our second Xlib connection (XOpenDisplay) interfered with XWayland's
event routing, preventing WM_DELETE_WINDOW from reaching X clients
and causing slow XWayland startup.

Removed:
- Persistent wl_state.x_display / x11_event_source
- X11 event pump (wl_handle_x11_events)
- Xlib-based icon capture, GC creation, key/message forwarding
- XSetErrorHandler on our connection
- Reentrant wl_event_loop_dispatch in wl_event_flush (caused UAF)

Root cursor now set via wlr_xwayland_set_cursor (wlroots API).
XWayland close button now works correctly.
2026-06-27 19:09:53 +02:00
lkn e3c19bd103 fix UAF: destroy WApplication before wUnmanageWindow in XWayland unmap
Same fix as commit 2581233 for XDG toplevels — wApplicationDestroy
needs main_window_desc (the wwin) to clean up the appicon. Call it
before wUnmanageWindow which frees wwin.
2026-06-27 18:40:30 +02:00
lkn 5b5617844a wayland: handle XWayland fullscreen requests
The XWayland backend was not listening for request_fullscreen events
from wlr_xwayland_surface. Wine/Proton games that request fullscreen
via _NET_WM_STATE_FULLSCREEN had the signal silently ignored, leaving
them in a tiny window.

Add handle_xwayland_request_fullscreen listener that calls
wFullscreenWindow/wUnfullscreenWindow, matching the XDG toplevel path.
2026-06-27 14:47:46 +02:00
lkn 53d8d82e3a wayland: use PIXMAN_OP_SRC for fill_rect to replace stale content
fill_rect used PIXMAN_OP_OVER which blends over existing pixels.
Uninitialized view backing images retained stale pixel data (e.g.
from icon tiles previously in that heap region), causing visual
artifacts like appicons showing through editmenu entries in WPrefs.

SRC fully replaces destination pixels, eliminating bleed-through.
2026-06-26 07:29:02 +02:00
lkn 09d3895642 wayland: fix use-after-free in popup resource destroy callback
ASAN found the heap corruption bug. When a toplevel is destroyed, the
view is freed but the wmaker-popup-v1 wl_resource still exists. When
the client later disconnects, wayland-server calls the resource
destroy callback which accessed the freed view (writing to
view->popup). This corrupted whatever was subsequently allocated in
that memory region, causing the SIGSEGV-in-malloc crashes.

Fix: NULL out the resource user_data before freeing the view.
2026-06-26 07:18:26 +02:00
lkn 46f0defabd wayland: guard event_flush commit against inactive session
The wl_event_loop_dispatch in event_flush could process a session
deactivation event (VT switch) while mid-animation, triggering a
wlroots assertion in wlr_backend_finish. Skip the commit and dispatch
when the DRM session is inactive.
2026-06-26 07:11:34 +02:00
lkn 01fb5f9e92 wayland: add canary-based heap overflow detection to frame_bufs
Each frame_buf gets a canary field (0xDEADBEEF) set at creation.
Before every frame_paint, all canaries are checked. If one is
trashed, dumps all frame_buf IDs/sizes/addresses to /tmp/wm-canary.log
before aborting.

Set canary in ALL frame_buf creation paths:
- wl_frame_create_toplevel, wl_frame_create_child
- wl_fake_leader_create
- wl_client_reparent (WINGs view frame_buf creation)
- wl_view_commit_backing_impl (WINGs toplevel)
- wl_screen dock_shadow and icon frame_bufs
- wl_window pixmap-to-frame_buf path
2026-06-26 07:07:06 +02:00
lkn 9752672367 wayland: fix animation rendering — dispatch after scene commit
Animation loops (iconify/shade zoom) call event_flush repeatedly
with wusleep delays. The scene commit returned immediately without
waiting for the DRM page flip, so only the final frame was visible.

After committing, flush clients and dispatch the event loop once to
process the page-flip completion. This allows the next commit in the
animation loop to succeed, producing smooth multi-frame animations.
2026-06-25 09:49:07 +02:00
lkn 9f86c6091c wayland: remove manual CSD geometry offset from scene positioning
wlr_scene_xdg_surface_create handles geometry offset internally.
Our manual subtraction of geometry.x/y in handle_toplevel_commit,
handle_toplevel_map, and wl_window_move was double-subtracting,
causing client surfaces to render behind their frames.

Remove all manual geometry offset from scene node positioning.
2026-06-25 08:05:13 +02:00
lkn 09b1ed5edf wayland: implement draw_bevel + render button bg with wTextureRenderImage
Two fixes for button/titlebar bevel consistency:

1. Implement the draw_bevel noop with real light/dim border drawing
   from the WTexSolid colors.

2. Render button backgrounds using wTextureRenderImage with WREL_RAISED
   (same function the titlebar uses). This produces the identical
   2-pixel wrlib bevel (RBevelImage/RBEV_RAISED2) that the titlebar
   gets, ensuring buttons and titlebar match exactly.
2026-06-25 08:03:22 +02:00
lkn 06dd22254d wayland: auto-contrast menu text color for dark themes
When MenuTextColor is not explicitly set (defaults to black), dark
widget themes render invisible black-on-dark menu text. Compute
luminance contrast between text color and background; if insufficient
(< 64 difference), substitute white text on dark backgrounds or black
text on light backgrounds.
2026-06-25 07:52:58 +02:00
lkn 72d6e31f24 wayland: fix button background color mismatch with titlebar
When the titlebar is rendered into the parent frame buffer (fallback
for undersized titlebar child), buttons sampled their background
color from the stale titlebar child buffer. This caused color
mismatch in inactive state or after theme changes.

Fix: detect when the titlebar child is too small and sample the
button background from the parent frame buffer instead.
2026-06-25 07:51:21 +02:00
lkn db96843a2f wayland: reset cursor to left_ptr when entering frame decorations
When the pointer moves over WM frame_bufs (titlebar, resizebar,
buttons), reset the cursor image to left_ptr. Without this, the
cursor stayed as whatever the last client set it to (e.g. text beam
from a text editor).
2026-06-25 07:50:19 +02:00
lkn 140d120718 wayland: use wlr_scene_xdg_surface_create for XDG toplevels
Switch from wlr_scene_subsurface_tree_create (which only handles
wl_subsurfaces) to wlr_scene_xdg_surface_create (which also creates
scene nodes for XDG popups). This makes right-click menus, tooltips,
and dropdown menus from native Wayland clients (LibreWolf, etc.)
visible in the scene graph.
2026-06-25 07:48:05 +02:00
lkn a16797edd8 geomview: fix sizing format mismatch with paint format
The geometry view was sized using "%+05i,  %+05i" but painted with
"%+5i , %+5i    " (wider due to trailing spaces). This caused the
rendered text to exceed the view width. Use the same format for both
so the backing pixman image is correctly sized.
2026-06-25 07:41:15 +02:00
lkn f4af1df31e wayland: persist background across VT switch / output re-creation
When switching VTs and returning, the DRM output may be destroyed and
recreated. Two issues caused the background to revert:

1. pending_background was freed after first application, so subsequent
   output creation had nothing to reapply.

2. A new bg_rect (default purple) was created for each new output and
   rendered on top of the existing bg_image scene buffer.

Fix: keep pending_background permanently, and disable the new bg_rect
when a background image is already active in the scene graph.
2026-06-25 07:28:54 +02:00
lkn 9da620d443 wayland: implement pointer warp via pointer-constraints hint
Native Wayland clients (e.g. plan9port acme/devdraw) warp the pointer
by locking it via zwp_pointer_constraints_v1, setting a
cursor_position_hint, then immediately destroying the lock. The
compositor is expected to warp the cursor to the hint on unlock.

Our handler just activated the constraint and ignored the hint. Now we
listen for the constraint destroy event and warp the cursor to the
hint position (converted from surface-local to global coordinates).
2026-06-25 07:20:05 +02:00
lkn 1ef79265e7 wayland: fix pointer warp using wlr_cursor_warp_closest
wlr_cursor_warp with NULL device silently fails (returns false) if the
target coordinates fall outside the output layout bounds. This made
pointer warping appear completely broken.

Switch to wlr_cursor_warp_closest which clamps to the nearest valid
point on the output layout, ensuring the cursor always moves.
2026-06-25 07:12:57 +02:00
lkn ab933c6565 wayland: fix close button for internal window panels
The close button on internal windows (dock app settings, etc.) did
nothing because:

1. wwin->protocols.DELETE_WINDOW was never set for internal windows,
   so windowCloseClick skipped the wClientSendProtocol call.

2. Even if it were called, wl_client_send_protocol just called
   client_close which looks for an XDG/XWayland surface. Internal
   windows have synthetic WINGs view IDs, not real surfaces.

Fix: set DELETE_WINDOW protocol flag in wManageInternalWindow, and
handle internal windows in wl_client_send_protocol by calling
wUnmanageWindow directly.
2026-06-24 22:25:11 +02:00
lkn 62f8cb5c77 wayland: add overflow guard to titlebar blit in frame_paint
Add runtime bounds check before the titlebar texture blit. If the
destination pixman image is smaller than the blit dimensions, log a
diagnostic warning with the exact sizes and skip the blit instead of
corrupting the heap. This will help identify the conditions that
trigger the remaining heap overflow.
2026-06-24 22:21:28 +02:00
lkn e00bc6b25a wayland: fix titlebar height overflow in frame_paint
The titlebar child frame_buf can have a height smaller than tb_h
(fwin->top_width clamped to total_h). The existing bounds check only
verified width, not height. The blit loop wrote tb_h rows into a
shorter pixman image, overflowing into adjacent heap allocations.

This caused 100%% reproducible SIGSEGV in malloc (heap corruption
detected by glibc) on any operation following a frame paint where the
titlebar child was shorter than expected — e.g. opening the Run dialog
after a menu frame was painted.

Fix: check both width AND height before using the titlebar child buffer.
Fall back to drawing into the parent frame buffer (which is correctly
sized) when either dimension is insufficient.
2026-06-24 22:06:30 +02:00
lkn de15ca2282 wayland: fix heap corruption — update backing table after frame resize
wl_frame_configure and wl_window_resize reallocate fb->image (unref
old pixman image, create new one) but never updated the WINGs backing
table. W_GetViewBacking() continued returning the freed pointer.

Any subsequent draw into that backing (e.g. WMDrawString for titlebar
text) wrote into freed memory, corrupting the heap. The corruption
manifested as SIGSEGV/SIGABRT at the next malloc or free — in
fontconfig, Mesa, RReleaseImage, etc. depending on timing.

Fix: call W_RegisterBacking(fb->id, fb->image) after reallocation in
both resize paths.
2026-06-24 21:59:53 +02:00
lkn e6acdbf0f1 wayland: fix shade crash and titlebar visibility when shaded
Two issues with window shading:

1. wShadeWindow resizes the frame to top_width-1 tall. wl_frame_paint
   used the unclamped fwin->top_width as titlebar blit height, writing
   one row past the pixman buffer. Heap corruption detected by glibc on
   next free (RReleaseImage) caused SIGABRT. Fix: clamp tb_h to total_h.

2. The parent frame scene_buf was only enabled when show_resizebar was
   true. When the titlebar child buffer is too narrow (falls back to
   drawing into the parent), the shaded frame had its scene_buf disabled
   and the titlebar was invisible. Fix: also enable the parent scene_buf
   when the titlebar was drawn into it (no titlebar child found).
2026-06-24 21:49:32 +02:00
lkn d8b10988d0 fix: add client.h include for wClientSendProtocol/wClientKill 2026-06-24 19:50:37 +02:00
lkn f4c73fd6dd fix noop violations: implement wipe_desktop, get_shortcut_string, icon_select/change_title
wipe_desktop: iterate windows sending DELETE_WINDOW or killing (needed for
proper compositor shutdown).

get_shortcut_string, icon_select, icon_change_title: delegate to pure
WM functions that have no X11 dependency.
2026-06-24 19:49:47 +02:00
lkn 9b148c63ce fix noop violations: implement get_shortcut_string, icon_select, icon_change_title
These were noops hiding calls to pure functions with no X11 deps:
- get_shortcut_string: calls GetShortcutKey (fixes missing menu shortcuts)
- icon_select: calls wIconSelect
- icon_change_title: calls wIconChangeTitle
2026-06-24 19:45:42 +02:00
lkn b9c37c6629 fix animation architecture: delegate slide/move to backend vtable
Core code must not call backend directly. misc.c:slide_windows and
move_window now delegate to wm_backend->slide_windows/move_window.
Wayland backend implements both using scene node moves + event_flush.
2026-06-24 19:41:41 +02:00
lkn 1331103ce7 perf: skip frame repaint during resize grab, paint on release
wl_frame_paint is expensive (pixman blit per motion event).
Decorations content does not change during resize, only geometry.
Skip repaint while grab_type==2; repaint once on grab release.
2026-06-24 19:28:30 +02:00
lkn 12d49c6642 perf: block event loop with -1 timeout instead of spinning
Use epoll blocking dispatch so the compositor sleeps when idle.
WINGs timers and frame callbacks still wake the loop as needed.
2026-06-24 19:26:16 +02:00
lkn 4897e1637b perf: schedule frame after every grab motion for 144Hz smoothness
Without schedule_frame, drag/resize updates sit in the scene graph
until the next natural vsync. At 144Hz this is 7ms max. Scheduling
after each motion ensures the next frame picks up the move/resize.
2026-06-24 19:22:43 +02:00
lkn c37fd28572 perf: reduce event loop timeout to 4ms, remove polling schedule_frame
The 16ms dispatch timeout added up to 16ms of input latency.
4ms reduces this to ~4ms maximum.

Removing unconditional wlr_output_schedule_frame from the main loop
stops flooding the swapchain. The output frame callback in
handle_output_frame drives rendering at vsync naturally.
2026-06-24 19:15:31 +02:00
lkn 70659969d6 debug: log xcursor output scale 2026-06-24 19:13:07 +02:00
lkn 0c295dcf09 wayland: fix shade crash and titlebar visibility when shaded
Two issues with window shading:

1. wShadeWindow resizes the frame to top_width-1 tall. wl_frame_paint
   used the unclamped fwin->top_width as titlebar blit height, writing
   one row past the pixman buffer. Heap corruption detected by glibc on
   next free (RReleaseImage) caused SIGABRT. Fix: clamp tb_h to total_h.

2. The parent frame scene_buf was only enabled when show_resizebar was
   true. When the titlebar child buffer is too narrow (falls back to
   drawing into the parent), the shaded frame had its scene_buf disabled
   and the titlebar was invisible. Fix: always commit and enable the
   parent scene_buf (cleared to transparent, so unused areas are safe).
2026-06-24 19:02:52 +02:00
lkn 144b089dff fix UAF: NULL last_hovered_view when view is destroyed
W_ViewDestroyedFn hook clears last_hovered_view when the pointed-to
view is destroyed. Prevents use-after-free in motion handler when
the hovering over a view inside a dialog that is then closed.
2026-06-24 00:20:07 +02:00
lkn 9c954de71e load xcursor manager for scale 1 and 2 2026-06-23 23:57:34 +02:00
lkn f73630be43 fix cursor: dont reset to left_ptr over WINGs/WM frame_bufs
wl_update_pointer_focus reset cursor to left_ptr on every motion
event when no Wayland surface was under the pointer. WINGs compositor
views are pixman scene nodes, not Wayland surfaces, so surface was
always NULL over dialogs. Now preserve cursor when over frame_bufs.
2026-06-23 23:54:33 +02:00