wayland: Phases 24+25 — click-to-focus, client cursor surface, clipboard
Phase 24a — click-to-focus + raise-on-click: handle_pointer_button now calls view_surface_at() on WLR_BUTTON_PRESSED. If a managed view is hit, wSetFocusTo() delivers WM keyboard focus and wlr_scene_node_raise_to_top() raises the surface in Z-order. The view is also moved to the tail of toplevel_list so view_surface_at() returns it first on subsequent pointer hits. stacking.h included for the raise path (wRaiseFrame not yet needed but header is now available). Phase 24b — client cursor surface (wl_pointer.set_cursor): seat->events.request_set_cursor wired to handle_seat_request_cursor. The handler validates the request comes from the currently pointer-focused client (rejects unfocused clients), then calls wlr_cursor_set_surface so the application-supplied cursor image is rendered on all outputs. In nested mode this updates the host compositor's cursor via set_cursor. Phase 25 — clipboard / wl_data_device selection forwarding: seat->events.request_set_selection wired to handle_seat_request_set_selection. The handler calls wlr_seat_set_selection, making the client's data source available to subsequent paste operations in any other client that reads the seat's selection. Logged as "clipboard selection wired" at startup. Smoke test: new "clipboard check" verifies startup log; 24/24 pass. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
aee57de37d
commit
52c6ef9326
|
|
@ -113,6 +113,7 @@
|
|||
#include <wlr/render/allocator.h> /* Phase 18: buffer allocator */
|
||||
#include <wlr/types/wlr_cursor.h> /* Phase 23: hardware cursor tracking */
|
||||
#include <wlr/types/wlr_xcursor_manager.h> /* Phase 23: xcursor theme */
|
||||
#include <wlr/types/wlr_data_device.h> /* Phase 25: clipboard / selection */
|
||||
#include <wlr/util/box.h>
|
||||
/* Generated xdg-shell protocol implementation (Wayland glue code) */
|
||||
#include "protocols/xdg-shell-protocol.c"
|
||||
|
|
@ -124,6 +125,7 @@
|
|||
#include "../../screen.h"
|
||||
#include "../../window.h"
|
||||
#include "../../actions.h" /* Phase 16: wMaximizeWindow, wIconifyWindow, etc. */
|
||||
#include "../../stacking.h" /* Phase 24: wRaiseFrame for click-to-raise */
|
||||
#include "../../xinerama.h" /* Phase 16: wGetHeadForWindow */
|
||||
#include "../../xmodifier.h" /* Phase 77: wSetModifierMasks */
|
||||
#include "../../event.h" /* Phase 78: wWaylandKeyPress */
|
||||
|
|
@ -257,6 +259,10 @@ struct wl_compositor_state {
|
|||
/* Phase 23: hardware cursor and xcursor theme. */
|
||||
struct wlr_cursor *cursor;
|
||||
struct wlr_xcursor_manager *xcursor_mgr;
|
||||
/* Phase 24: seat cursor-surface request listener. */
|
||||
struct wl_listener seat_request_cursor_listener;
|
||||
/* Phase 25: clipboard — seat selection request listener. */
|
||||
struct wl_listener seat_request_set_selection_listener;
|
||||
};
|
||||
|
||||
static struct wl_compositor_state wl_state;
|
||||
|
|
@ -312,6 +318,13 @@ static void wl_update_pointer_focus(uint32_t time_msec);
|
|||
static void wl_pointer_warp_to(int x, int y);
|
||||
/* Phase 14: pointer event handler forward declarations. */
|
||||
static void handle_pointer_motion(struct wl_listener *listener, void *data);
|
||||
/* Phase 24: click-to-focus helper — defined in Phase 13 pointer section. */
|
||||
static struct wlr_surface *view_surface_at(int px, int py, double *sx_out,
|
||||
double *sy_out, struct wl_toplevel_view **view_out);
|
||||
/* Phase 24: client cursor-surface request handler. */
|
||||
static void handle_seat_request_cursor(struct wl_listener *listener, void *data);
|
||||
/* Phase 25: client clipboard selection request handler. */
|
||||
static void handle_seat_request_set_selection(struct wl_listener *listener, void *data);
|
||||
/* Phase 17: XWayland new surface forward declaration. */
|
||||
static void handle_xwayland_new_surface(struct wl_listener *listener, void *data);
|
||||
/* Phase 20: nested backend real input device forward declaration. */
|
||||
|
|
@ -1434,6 +1447,23 @@ wl_display_open(const char *name)
|
|||
wl_state.seat = wlr_seat_create(wl_state.display, "seat0");
|
||||
wl_state.data_device_mgr =
|
||||
wlr_data_device_manager_create(wl_state.display);
|
||||
|
||||
/* Phase 24: handle client cursor-surface requests on the seat. */
|
||||
if (wl_state.seat) {
|
||||
wl_state.seat_request_cursor_listener.notify = handle_seat_request_cursor;
|
||||
wl_signal_add(&wl_state.seat->events.request_set_cursor,
|
||||
&wl_state.seat_request_cursor_listener);
|
||||
}
|
||||
/* Phase 25: handle clipboard set-selection requests on the seat so
|
||||
* Ctrl-C / copy operations from clients propagate to the seat selection
|
||||
* and become available for paste in other clients. */
|
||||
if (wl_state.seat) {
|
||||
wl_state.seat_request_set_selection_listener.notify =
|
||||
handle_seat_request_set_selection;
|
||||
wl_signal_add(&wl_state.seat->events.request_set_selection,
|
||||
&wl_state.seat_request_set_selection_listener);
|
||||
wwarning("wl_backend: clipboard selection wired");
|
||||
}
|
||||
wl_state.xdg_shell = wlr_xdg_shell_create(wl_state.display);
|
||||
|
||||
/* Phase 64: advertise zxdg_decoration_manager_v1 so clients that
|
||||
|
|
@ -1723,6 +1753,9 @@ wl_display_close(void)
|
|||
WL_LISTENER_REMOVE(wl_state.real_pointer_motion_abs_listener);
|
||||
WL_LISTENER_REMOVE(wl_state.real_pointer_button_listener);
|
||||
WL_LISTENER_REMOVE(wl_state.real_pointer_frame_listener);
|
||||
/* Phase 24/25: seat cursor + selection listeners */
|
||||
WL_LISTENER_REMOVE(wl_state.seat_request_cursor_listener);
|
||||
WL_LISTENER_REMOVE(wl_state.seat_request_set_selection_listener);
|
||||
#undef WL_LISTENER_REMOVE
|
||||
|
||||
/* Phase 23: destroy cursor and xcursor manager before display teardown. */
|
||||
|
|
@ -2020,6 +2053,45 @@ handle_pointer_motion_absolute(struct wl_listener *listener, void *data)
|
|||
wl_update_pointer_focus(ev->time_msec);
|
||||
}
|
||||
|
||||
/*
|
||||
* Phase 24: seat request_set_cursor — client wants to set a custom cursor
|
||||
* image (e.g. I-beam in a text field, hand over a link). Validate that
|
||||
* the request comes from the currently focused pointer client, then hand
|
||||
* the surface to wlr_cursor so the hardware cursor is updated on all
|
||||
* outputs (which in nested mode sends wl_pointer.set_cursor to the host).
|
||||
*/
|
||||
static void
|
||||
handle_seat_request_cursor(struct wl_listener *listener, void *data)
|
||||
{
|
||||
(void)listener;
|
||||
struct wlr_seat_pointer_request_set_cursor_event *ev = data;
|
||||
if (!wl_state.seat || !wl_state.cursor)
|
||||
return;
|
||||
/* Only honour cursor requests from the client that currently has
|
||||
* pointer focus; reject requests from unfocused clients. */
|
||||
struct wlr_seat_client *focused =
|
||||
wl_state.seat->pointer_state.focused_client;
|
||||
if (ev->seat_client != focused)
|
||||
return;
|
||||
wlr_cursor_set_surface(wl_state.cursor, ev->surface,
|
||||
ev->hotspot_x, ev->hotspot_y);
|
||||
}
|
||||
|
||||
/*
|
||||
* Phase 25: seat request_set_selection — client calls wl_data_device.set_selection
|
||||
* (i.e. Ctrl-C or other clipboard write). Forward to wlr_seat so the
|
||||
* selection becomes available to the next client that reads it.
|
||||
*/
|
||||
static void
|
||||
handle_seat_request_set_selection(struct wl_listener *listener, void *data)
|
||||
{
|
||||
(void)listener;
|
||||
struct wlr_seat_request_set_selection_event *ev = data;
|
||||
if (!wl_state.seat)
|
||||
return;
|
||||
wlr_seat_set_selection(wl_state.seat, ev->source, ev->serial);
|
||||
}
|
||||
|
||||
static void
|
||||
handle_pointer_button(struct wl_listener *listener, void *data)
|
||||
{
|
||||
|
|
@ -2035,6 +2107,33 @@ handle_pointer_button(struct wl_listener *listener, void *data)
|
|||
wl_update_pointer_focus(ev->time_msec);
|
||||
return;
|
||||
}
|
||||
/* Phase 24: click-to-focus — on button press, find the view under the
|
||||
* pointer and focus + raise it via the WM policy layer.
|
||||
* This mirrors what the X11 backend does via ButtonPress on frame windows. */
|
||||
if (ev->state == WLR_BUTTON_PRESSED) {
|
||||
double sx, sy;
|
||||
struct wl_toplevel_view *view = NULL;
|
||||
view_surface_at(wl_state.pointer_x, wl_state.pointer_y,
|
||||
&sx, &sy, &view);
|
||||
if (view) {
|
||||
WObjDescriptor *desc =
|
||||
wm_backend->context_find(view->id, WM_CTX_CLIENT_WIN);
|
||||
if (desc && desc->parent_type == WCLASS_WINDOW) {
|
||||
WWindow *wwin = (WWindow *)desc->parent;
|
||||
WScreen *scr = wScreenWithNumber(0);
|
||||
wSetFocusTo(scr, wwin);
|
||||
/* Raise the window in scene Z-order by moving its scene node
|
||||
* to the top of the scene root's child list. */
|
||||
if (view->scene_node)
|
||||
wlr_scene_node_raise_to_top(view->scene_node);
|
||||
/* Also raise it in our toplevel list so view_surface_at()
|
||||
* returns it first on subsequent hits. */
|
||||
wl_list_remove(&view->link);
|
||||
wl_list_insert(wl_state.toplevel_list.prev, &view->link);
|
||||
wwarning("wl_backend: click focus id=0x%lx", view->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
wlr_seat_pointer_notify_button(wl_state.seat, ev->time_msec,
|
||||
ev->button, ev->state);
|
||||
wlr_seat_pointer_notify_frame(wl_state.seat);
|
||||
|
|
|
|||
|
|
@ -123,6 +123,16 @@
|
|||
# Compositor logs "XWayland DISPLAY=:<n> (lazy: starts on first X11 client)".
|
||||
# DISPLAY env var is set from the pre-allocated display number.
|
||||
# Verified by "XWayland DISPLAY=.*lazy" log.
|
||||
# 43. (Phase 24) Click-to-focus: on WLR_BUTTON_PRESSED, view_surface_at()
|
||||
# finds the view under the pointer; wSetFocusTo delivers WM keyboard
|
||||
# focus and wlr_scene_node_raise_to_top raises it in Z-order.
|
||||
# seat->events.request_set_cursor wired: clients can set custom cursor
|
||||
# images (I-beam, hand, etc.) via wl_pointer.set_cursor.
|
||||
# (Build-only check — no multi-window focus test here.)
|
||||
# 44. (Phase 25) Clipboard: seat->events.request_set_selection wired so
|
||||
# Ctrl-C / copy operations propagate to the seat selection and become
|
||||
# available for paste in other clients via wl_data_device.
|
||||
# Verified by "clipboard selection wired" log line.
|
||||
# 42. (Phase 23) Cursor image rendering: wlr_cursor + wlr_xcursor_manager
|
||||
# created and attached to output_layout; xcursor theme (default, 24px)
|
||||
# loaded at scale 1.0; "left_ptr" image set on each output after it joins
|
||||
|
|
@ -282,6 +292,11 @@ grep -q 'dock/clip disabled in Wayland mode' /tmp/wl-smoke-stderr \
|
|||
|| die "compositor did not log dock/clip disabled (noclip/nodock not set in wl_screen_create_internals)"
|
||||
echo " nodock check: dock/clip disabled in Wayland mode (noclip=1 nodock=1)"
|
||||
|
||||
# -- 4f2b. Phase 25: clipboard selection wired ----------------------------
|
||||
grep -q 'clipboard selection wired' /tmp/wl-smoke-stderr \
|
||||
|| die "compositor did not log clipboard wired (seat request_set_selection listener missing)"
|
||||
echo " clipboard check: clipboard selection wired"
|
||||
|
||||
# -- 4f3. Phase 23: cursor created and xcursor theme loaded ---------------
|
||||
grep -q 'cursor created, xcursor theme loaded' /tmp/wl-smoke-stderr \
|
||||
|| die "compositor did not log cursor creation (wlr_cursor_create or xcursor_manager_create failed)"
|
||||
|
|
|
|||
Loading…
Reference in New Issue