Three related fixes for the Wayland backend:
wl_handlers.c: populate u.button.state with keyboard modifiers
Button events were built with state=0 after memset, so all modifier-
dependent logic in window.c (resizebarMouseDown, frameMouseDown,
titlebarMouseDown) received no modifier information. Read the current
depressed modifier mask from the seat keyboard and copy it directly --
wlroots WLR_MODIFIER_* bits match the WM_MOD_* layout exactly.
wl_framebuf.c: fix frame_buf_hit to resolve child sub-windows
frame_buf_at() uses wlr_scene_node_at() which skips frame_buf children
whose scene_buf has no committed buffer (resizebar, titlebar pixels are
composited into the parent frame buffer). The hit always resolved to
the top-level frame, so events were dispatched to frameMouseDown instead
of resizebarMouseDown, and resize never started. After frame_buf_at
returns a top-level frame, do a coordinate-based child search and return
the smallest (most specific) child that contains the pointer -- the same
strategy frame_buf_button_at uses for buttons.
wl_events.c: fix wl_coords_translate to return frame-relative coords
The stub was a pass-through returning root-relative coordinates unchanged.
wMouseResizeWindow calls coords_translate(root, frame->core->window, ...)
to get frame-relative click coordinates for getResizeDirection(). Look up
the dst window in the frame_buf list and subtract its absolute position.
Three interrelated bugs caused clicks to land in the wrong place when
the compositor spanned multiple outputs (e.g. two 1920x1080 monitors
side by side in nested Wayland mode):
1. real_pointer_update_global() added lo->x to coordinates that were
already in layout space from wlr_cursor_absolute_to_layout_coords,
double-counting the output offset. It also omitted lo->y entirely,
breaking vertical monitor layouts. Fix: read position from
wlr_cursor->x/y which is always authoritative layout-space.
2. real_pointer_handle_motion() accumulated ev->delta into local_x/y
then set pointer_x/y, after which handle_pointer_motion() added
the same delta again -- doubling every relative motion. Fix: let
handle_pointer_motion() be the sole authority; use wlr_cursor_move()
which respects output layout geometry.
3. Pointer devices from nested Wayland outputs (WL-1, WL-2) were never
registered with wlr_cursor via wlr_cursor_attach_input_device() or
mapped to their output via wlr_cursor_map_input_to_output(). Without
this mapping, wlr_cursor_absolute_to_layout_coords treated the 0..1
range as spanning the entire layout (0..3840) instead of the
device's specific output (e.g. 1920..3840 for WL-2). A previous
workaround disabled absolute motion entirely for nested multi-output,
which left only relative deltas that had no concept of which host
window the mouse was in. Fix: register devices with wlr_cursor and
map them to their outputs; remove the early-return.
All pointer paths now follow the same pattern: mutate position via
wlr_cursor_move()/wlr_cursor_warp(), then read back cursor->x/y into
wl_state.pointer_x/y. Manual bounding-box clamping is retained only
for the no-cursor fallback (headless/test mode).