wayland: Phase 14 — pointer motion/button/frame event pipeline

Wire handle_pointer_motion, handle_pointer_motion_absolute,
handle_pointer_button, and handle_pointer_frame listeners to the
headless pointer device.  Motion handlers update the virtual pointer
position and call wl_update_pointer_focus; button handler forwards
button state to wlr_seat_pointer_notify_button.  This completes the
input event pipeline so a real pointer device added later will
dispatch events to focused Wayland clients automatically.

Smoke test check 4f2 verifies "pointer motion/button/frame listeners
wired" is logged at startup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Levi Neely 2026-03-28 21:05:39 +01:00
parent fae9360af5
commit b9b3b2de57
2 changed files with 82 additions and 0 deletions

View File

@ -169,6 +169,11 @@ struct wl_compositor_state {
struct wlr_input_device *pointer_dev;
/* Phase 54: virtual pointer position (screen coordinates) */
int pointer_x, pointer_y;
/* Phase 14: pointer event listeners wired to pointer_dev->pointer */
struct wl_listener pointer_motion_listener;
struct wl_listener pointer_motion_abs_listener;
struct wl_listener pointer_button_listener;
struct wl_listener pointer_frame_listener;
char socket_name[64]; /* Phase 34: e.g. "wayland-0" */
int started; /* non-zero after successful display_open */
};
@ -204,6 +209,11 @@ static int wl_client_get_pid(WNativeWindow win);
/* Phase 13: forward declarations — defined in pointer section below. */
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);
static void handle_pointer_motion_absolute(struct wl_listener *listener, void *data);
static void handle_pointer_button(struct wl_listener *listener, void *data);
static void handle_pointer_frame(struct wl_listener *listener, void *data);
/* Phase 41: look up the view for a given synthetic WNativeWindow ID. */
static struct wl_toplevel_view *
@ -607,6 +617,21 @@ wl_display_open(const char *name)
wl_state.pointer_dev =
wlr_headless_add_input_device(wl_state.backend, WLR_INPUT_DEVICE_POINTER);
/* Phase 14: wire pointer motion/button listeners to the headless pointer
* device so real pointer hardware (if added later) dispatches events. */
if (wl_state.pointer_dev && wl_state.pointer_dev->pointer) {
struct wlr_pointer *ptr = wl_state.pointer_dev->pointer;
wl_state.pointer_motion_listener.notify = handle_pointer_motion;
wl_signal_add(&ptr->events.motion, &wl_state.pointer_motion_listener);
wl_state.pointer_motion_abs_listener.notify = handle_pointer_motion_absolute;
wl_signal_add(&ptr->events.motion_absolute, &wl_state.pointer_motion_abs_listener);
wl_state.pointer_button_listener.notify = handle_pointer_button;
wl_signal_add(&ptr->events.button, &wl_state.pointer_button_listener);
wl_state.pointer_frame_listener.notify = handle_pointer_frame;
wl_signal_add(&ptr->events.frame, &wl_state.pointer_frame_listener);
wwarning("wl_backend: pointer motion/button/frame listeners wired");
}
{
uint32_t caps = 0;
if (wl_state.keyboard_dev) caps |= WL_SEAT_CAPABILITY_KEYBOARD;
@ -850,6 +875,58 @@ wl_button_grab(WNativeWindow win, unsigned int button,
static void wl_button_ungrab_all(WNativeWindow win) { (void)win; }
/* ------------------------------------------------------------------ */
/* Phase 14: pointer input event handlers */
/* ------------------------------------------------------------------ */
static void
handle_pointer_motion(struct wl_listener *listener, void *data)
{
(void)listener;
struct wlr_event_pointer_motion *ev = data;
wl_state.pointer_x += (int)ev->delta_x;
wl_state.pointer_y += (int)ev->delta_y;
if (wl_state.pointer_x < 0) wl_state.pointer_x = 0;
if (wl_state.pointer_y < 0) wl_state.pointer_y = 0;
if (wl_state.pointer_x > 1919) wl_state.pointer_x = 1919;
if (wl_state.pointer_y > 1079) wl_state.pointer_y = 1079;
wl_update_pointer_focus(ev->time_msec);
}
static void
handle_pointer_motion_absolute(struct wl_listener *listener, void *data)
{
(void)listener;
struct wlr_event_pointer_motion_absolute *ev = data;
wl_state.pointer_x = (int)(ev->x * 1920);
wl_state.pointer_y = (int)(ev->y * 1080);
if (wl_state.pointer_x < 0) wl_state.pointer_x = 0;
if (wl_state.pointer_y < 0) wl_state.pointer_y = 0;
if (wl_state.pointer_x > 1919) wl_state.pointer_x = 1919;
if (wl_state.pointer_y > 1079) wl_state.pointer_y = 1079;
wl_update_pointer_focus(ev->time_msec);
}
static void
handle_pointer_button(struct wl_listener *listener, void *data)
{
(void)listener;
struct wlr_event_pointer_button *ev = data;
if (!wl_state.seat)
return;
wlr_seat_pointer_notify_button(wl_state.seat, ev->time_msec,
ev->button, ev->state);
wlr_seat_pointer_notify_frame(wl_state.seat);
}
static void
handle_pointer_frame(struct wl_listener *listener, void *data)
{
(void)listener; (void)data;
if (wl_state.seat)
wlr_seat_pointer_notify_frame(wl_state.seat);
}
/* ------------------------------------------------------------------ */
/* Pointer grabs */
/* ------------------------------------------------------------------ */

View File

@ -242,6 +242,11 @@ grep -q 'keyboard key+modifiers listeners wired' /tmp/wl-smoke-stderr \
|| die "compositor did not log keyboard listeners wired"
echo " kbd listener check: keyboard key+modifiers listeners wired"
# -- 4f2. Phase 14: pointer motion/button/frame listeners must be wired --
grep -q 'pointer motion/button/frame listeners wired' /tmp/wl-smoke-stderr \
|| die "compositor did not log pointer listeners wired"
echo " ptr listener check: pointer motion/button/frame listeners wired"
# -- 4f. Phase 11: dock/clip disabled in Wayland mode --------------------
#
# wl_screen_create_internals sets noclip=1 and nodock=1 so wWorkspaceNew