From b9b3b2de57adca2a9059c0e2578f3bcba8782817 Mon Sep 17 00:00:00 2001 From: Levi Neely Date: Sat, 28 Mar 2026 21:05:39 +0100 Subject: [PATCH] =?UTF-8?q?wayland:=20Phase=2014=20=E2=80=94=20pointer=20m?= =?UTF-8?q?otion/button/frame=20event=20pipeline?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- src/backend/wayland/wl_backend.c | 77 ++++++++++++++++++++++++++++++++ tests/wl-smoke-test.sh | 5 +++ 2 files changed, 82 insertions(+) diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index 7bdfdc0..38ca128 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -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 */ /* ------------------------------------------------------------------ */ diff --git a/tests/wl-smoke-test.sh b/tests/wl-smoke-test.sh index 02ffc35..7e45a64 100755 --- a/tests/wl-smoke-test.sh +++ b/tests/wl-smoke-test.sh @@ -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