diff --git a/backend/wayland/pointer.c b/backend/wayland/pointer.c index b61e32cd0..8ee79c079 100644 --- a/backend/wayland/pointer.c +++ b/backend/wayland/pointer.c @@ -211,6 +211,22 @@ static void pointer_handle_axis_relative_direction(void *data, pointer->axis_relative_direction = direction; } +static void pointer_handle_warp(void *data, struct wl_pointer *wl_pointer, + wl_fixed_t sx, wl_fixed_t sy) { + struct wlr_wl_seat *seat = data; + struct wlr_wl_pointer *pointer = seat->active_pointer; + if (pointer == NULL) { + return; + } + + struct wlr_pointer_warp_event event = { + .pointer = &pointer->wlr_pointer, + .sx = wl_fixed_to_double(sx), + .sy = wl_fixed_to_double(sy), + }; + wl_signal_emit_mutable(&pointer->wlr_pointer.events.warp, &event); +} + static const struct wl_pointer_listener pointer_listener = { .enter = pointer_handle_enter, .leave = pointer_handle_leave, @@ -223,6 +239,7 @@ static const struct wl_pointer_listener pointer_listener = { .axis_discrete = pointer_handle_axis_discrete, .axis_value120 = pointer_handle_axis_value120, .axis_relative_direction = pointer_handle_axis_relative_direction, + .warp = pointer_handle_warp, }; static void gesture_swipe_begin(void *data, diff --git a/include/wlr/types/wlr_pointer.h b/include/wlr/types/wlr_pointer.h index 756ffa1f6..eaa669ed5 100644 --- a/include/wlr/types/wlr_pointer.h +++ b/include/wlr/types/wlr_pointer.h @@ -34,6 +34,7 @@ struct wlr_pointer { struct wl_signal button; // struct wlr_pointer_button_event struct wl_signal axis; // struct wlr_pointer_axis_event struct wl_signal frame; + struct wl_signal warp; // struct wlr_pointer_warp_event struct wl_signal swipe_begin; // struct wlr_pointer_swipe_begin_event struct wl_signal swipe_update; // struct wlr_pointer_swipe_update_event @@ -82,7 +83,10 @@ struct wlr_pointer_axis_event { double delta; int32_t delta_discrete; }; - +struct wlr_pointer_warp_event { + struct wlr_pointer *pointer; + double sx, sy; +}; struct wlr_pointer_swipe_begin_event { struct wlr_pointer *pointer; uint32_t time_msec; diff --git a/include/wlr/types/wlr_seat.h b/include/wlr/types/wlr_seat.h index 670b4458b..84bfb5150 100644 --- a/include/wlr/types/wlr_seat.h +++ b/include/wlr/types/wlr_seat.h @@ -432,6 +432,15 @@ void wlr_seat_pointer_send_axis(struct wlr_seat *wlr_seat, uint32_t time_msec, */ void wlr_seat_pointer_send_frame(struct wlr_seat *wlr_seat); +/** + * Send a warp event to the surface with pointer focus. This notifies the client + * that the pointer location has changed due to surface movement or compositor + * action, rather than input device motion. Coordinates are surface-local. + * This function does not respect pointer grabs. + */ +void wlr_seat_pointer_send_warp(struct wlr_seat *wlr_seat, + double sx, double sy); + /** * Notify the seat of a pointer enter event to the given surface and request it * to be the focused surface for the pointer. Pass surface-local coordinates diff --git a/types/seat/wlr_seat.c b/types/seat/wlr_seat.c index 015a57b52..dd7db8c66 100644 --- a/types/seat/wlr_seat.c +++ b/types/seat/wlr_seat.c @@ -11,7 +11,7 @@ #include "types/wlr_seat.h" #include "util/global.h" -#define SEAT_VERSION 9 +#define SEAT_VERSION 11 static void seat_handle_get_pointer(struct wl_client *client, struct wl_resource *seat_resource, uint32_t id) { diff --git a/types/seat/wlr_seat_pointer.c b/types/seat/wlr_seat_pointer.c index 41729dcd9..6e69e658a 100644 --- a/types/seat/wlr_seat_pointer.c +++ b/types/seat/wlr_seat_pointer.c @@ -410,6 +410,28 @@ void wlr_seat_pointer_send_frame(struct wlr_seat *wlr_seat) { } } +void wlr_seat_pointer_send_warp(struct wlr_seat *wlr_seat, + double sx, double sy) { + struct wlr_seat_client *client = wlr_seat->pointer_state.focused_client; + if (client == NULL) { + return; + } + + struct wl_resource *resource; + wl_resource_for_each(resource, &client->pointers) { + if (wlr_seat_client_from_pointer_resource(resource) == NULL) { + continue; + } + + uint32_t version = wl_resource_get_version(resource); + if (version >= 11) { // WL_POINTER_WARP_SINCE_VERSION + wl_pointer_send_warp(resource, + wl_fixed_from_double(sx), + wl_fixed_from_double(sy)); + } + } +} + void wlr_seat_pointer_start_grab(struct wlr_seat *wlr_seat, struct wlr_seat_pointer_grab *grab) { assert(wlr_seat);