From 5de26ad8ed962bc7cc753a623f247f7dc4c76a39 Mon Sep 17 00:00:00 2001 From: emersion Date: Sat, 26 Jan 2019 11:04:05 +0100 Subject: [PATCH 1/2] pointer: add a frame event Frame events group logically connected pointer events. It makes sense to make the backend responsible for sending frame events, since once the events are split (ie. once the frame events are stripped) it's not easy to figure out which events belongs to which frame again. This is also how Weston handles frame events. Fixes https://github.com/swaywm/wlroots/issues/1468 --- backend/libinput/pointer.c | 16 ++++++++++------ backend/wayland/backend.c | 5 +---- backend/wayland/wl_seat.c | 9 ++++++++- backend/x11/input_device.c | 2 ++ include/rootston/cursor.h | 3 +++ include/wlr/types/wlr_cursor.h | 1 + include/wlr/types/wlr_pointer.h | 1 + include/wlr/types/wlr_seat.h | 15 +++++++++++++++ rootston/cursor.c | 4 ++++ rootston/seat.c | 11 +++++++++++ types/seat/wlr_seat_pointer.c | 30 ++++++++++++++++++++++++++++-- types/wlr_cursor.c | 11 +++++++++++ types/wlr_pointer.c | 5 +---- types/wlr_relative_pointer_v1.c | 4 ---- 14 files changed, 96 insertions(+), 21 deletions(-) diff --git a/backend/libinput/pointer.c b/backend/libinput/pointer.c index b9cf1dfe..0df16a10 100644 --- a/backend/libinput/pointer.c +++ b/backend/libinput/pointer.c @@ -39,6 +39,7 @@ void handle_pointer_motion(struct libinput_event *event, wlr_event.unaccel_dx = libinput_event_pointer_get_dx_unaccelerated(pevent); wlr_event.unaccel_dy = libinput_event_pointer_get_dy_unaccelerated(pevent); wlr_signal_emit_safe(&wlr_dev->pointer->events.motion, &wlr_event); + wlr_signal_emit_safe(&wlr_dev->pointer->events.frame, wlr_dev->pointer); } void handle_pointer_motion_abs(struct libinput_event *event, @@ -58,6 +59,7 @@ void handle_pointer_motion_abs(struct libinput_event *event, wlr_event.x = libinput_event_pointer_get_absolute_x_transformed(pevent, 1); wlr_event.y = libinput_event_pointer_get_absolute_y_transformed(pevent, 1); wlr_signal_emit_safe(&wlr_dev->pointer->events.motion_absolute, &wlr_event); + wlr_signal_emit_safe(&wlr_dev->pointer->events.frame, wlr_dev->pointer); } void handle_pointer_button(struct libinput_event *event, @@ -84,6 +86,7 @@ void handle_pointer_button(struct libinput_event *event, break; } wlr_signal_emit_safe(&wlr_dev->pointer->events.button, &wlr_event); + wlr_signal_emit_safe(&wlr_dev->pointer->events.frame, wlr_dev->pointer); } void handle_pointer_axis(struct libinput_event *event, @@ -114,13 +117,13 @@ void handle_pointer_axis(struct libinput_event *event, wlr_event.source = WLR_AXIS_SOURCE_WHEEL_TILT; break; } - enum libinput_pointer_axis axies[] = { + const enum libinput_pointer_axis axes[] = { LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL, }; - for (size_t i = 0; i < sizeof(axies) / sizeof(axies[0]); ++i) { - if (libinput_event_pointer_has_axis(pevent, axies[i])) { - switch (axies[i]) { + for (size_t i = 0; i < sizeof(axes) / sizeof(axes[0]); ++i) { + if (libinput_event_pointer_has_axis(pevent, axes[i])) { + switch (axes[i]) { case LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL: wlr_event.orientation = WLR_AXIS_ORIENTATION_VERTICAL; break; @@ -129,10 +132,11 @@ void handle_pointer_axis(struct libinput_event *event, break; } wlr_event.delta = - libinput_event_pointer_get_axis_value(pevent, axies[i]); + libinput_event_pointer_get_axis_value(pevent, axes[i]); wlr_event.delta_discrete = - libinput_event_pointer_get_axis_value_discrete(pevent, axies[i]); + libinput_event_pointer_get_axis_value_discrete(pevent, axes[i]); wlr_signal_emit_safe(&wlr_dev->pointer->events.axis, &wlr_event); } } + wlr_signal_emit_safe(&wlr_dev->pointer->events.frame, wlr_dev->pointer); } diff --git a/backend/wayland/backend.c b/backend/wayland/backend.c index da41af02..2a937de7 100644 --- a/backend/wayland/backend.c +++ b/backend/wayland/backend.c @@ -67,16 +67,13 @@ static void registry_global(void *data, struct wl_registry *registry, if (strcmp(iface, wl_compositor_interface.name) == 0) { wl->compositor = wl_registry_bind(registry, name, &wl_compositor_interface, 4); - } else if (strcmp(iface, wl_seat_interface.name) == 0) { wl->seat = wl_registry_bind(registry, name, - &wl_seat_interface, 2); + &wl_seat_interface, 5); wl_seat_add_listener(wl->seat, &seat_listener, wl); - } else if (strcmp(iface, wl_shm_interface.name) == 0) { wl->shm = wl_registry_bind(registry, name, &wl_shm_interface, 1); - } else if (strcmp(iface, xdg_wm_base_interface.name) == 0) { wl->xdg_wm_base = wl_registry_bind(registry, name, &xdg_wm_base_interface, 1); diff --git a/backend/wayland/wl_seat.c b/backend/wayland/wl_seat.c index b654197a..7efa6eb4 100644 --- a/backend/wayland/wl_seat.c +++ b/backend/wayland/wl_seat.c @@ -126,7 +126,14 @@ static void pointer_handle_axis(void *data, struct wl_pointer *wl_pointer, } static void pointer_handle_frame(void *data, struct wl_pointer *wl_pointer) { - // This space is intentionally left blank + struct wlr_wl_backend *backend = data; + struct wlr_wl_pointer *pointer = backend->current_pointer; + if (pointer == NULL) { + return; + } + + wlr_signal_emit_safe(&pointer->wlr_pointer.events.frame, + &pointer->wlr_pointer); } static void pointer_handle_axis_source(void *data, diff --git a/backend/x11/input_device.c b/backend/x11/input_device.c index 915d9958..3a21f69c 100644 --- a/backend/x11/input_device.c +++ b/backend/x11/input_device.c @@ -50,6 +50,7 @@ static void send_axis_event(struct wlr_x11_output *output, int32_t delta, .delta_discrete = delta, }; wlr_signal_emit_safe(&output->pointer.events.axis, &ev); + wlr_signal_emit_safe(&output->pointer.events.frame, &output->pointer); } static void send_pointer_position_event(struct wlr_x11_output *output, @@ -61,6 +62,7 @@ static void send_pointer_position_event(struct wlr_x11_output *output, .y = (double)y / output->wlr_output.height, }; wlr_signal_emit_safe(&output->pointer.events.motion_absolute, &ev); + wlr_signal_emit_safe(&output->pointer.events.frame, &output->pointer); } void handle_x11_xinput_event(struct wlr_x11_backend *x11, diff --git a/include/rootston/cursor.h b/include/rootston/cursor.h index b5bb682f..d1db6856 100644 --- a/include/rootston/cursor.h +++ b/include/rootston/cursor.h @@ -38,6 +38,7 @@ struct roots_cursor { struct wl_listener motion_absolute; struct wl_listener button; struct wl_listener axis; + struct wl_listener frame; struct wl_listener touch_down; struct wl_listener touch_up; @@ -71,6 +72,8 @@ void roots_cursor_handle_button(struct roots_cursor *cursor, void roots_cursor_handle_axis(struct roots_cursor *cursor, struct wlr_event_pointer_axis *event); +void roots_cursor_handle_frame(struct roots_cursor *cursor); + void roots_cursor_handle_touch_down(struct roots_cursor *cursor, struct wlr_event_touch_down *event); diff --git a/include/wlr/types/wlr_cursor.h b/include/wlr/types/wlr_cursor.h index 44ced1f0..6475669c 100644 --- a/include/wlr/types/wlr_cursor.h +++ b/include/wlr/types/wlr_cursor.h @@ -51,6 +51,7 @@ struct wlr_cursor { struct wl_signal motion_absolute; struct wl_signal button; struct wl_signal axis; + struct wl_signal frame; struct wl_signal touch_up; struct wl_signal touch_down; diff --git a/include/wlr/types/wlr_pointer.h b/include/wlr/types/wlr_pointer.h index 6da4c02a..9dfe7aaa 100644 --- a/include/wlr/types/wlr_pointer.h +++ b/include/wlr/types/wlr_pointer.h @@ -23,6 +23,7 @@ struct wlr_pointer { struct wl_signal motion_absolute; struct wl_signal button; struct wl_signal axis; + struct wl_signal frame; } events; void *data; diff --git a/include/wlr/types/wlr_seat.h b/include/wlr/types/wlr_seat.h index f6df7413..103fa24d 100644 --- a/include/wlr/types/wlr_seat.h +++ b/include/wlr/types/wlr_seat.h @@ -68,6 +68,7 @@ struct wlr_pointer_grab_interface { void (*axis)(struct wlr_seat_pointer_grab *grab, uint32_t time, enum wlr_axis_orientation orientation, double value, int32_t value_discrete, enum wlr_axis_source source); + void (*frame)(struct wlr_seat_pointer_grab *grab); void (*cancel)(struct wlr_seat_pointer_grab *grab); }; @@ -348,6 +349,13 @@ void wlr_seat_pointer_send_axis(struct wlr_seat *wlr_seat, uint32_t time, enum wlr_axis_orientation orientation, double value, int32_t value_discrete, enum wlr_axis_source source); +/** + * Send a frame event to the surface with pointer focus. Compositors should use + * `wlr_seat_pointer_notify_frame()` to send axis events to respect pointer + * grabs. + */ +void wlr_seat_pointer_send_frame(struct wlr_seat *wlr_seat); + /** * Start a grab of the pointer of this seat. The grabber is responsible for * handling all pointer events until the grab ends. @@ -390,6 +398,13 @@ void wlr_seat_pointer_notify_axis(struct wlr_seat *wlr_seat, uint32_t time, enum wlr_axis_orientation orientation, double value, int32_t value_discrete, enum wlr_axis_source source); +/** + * Notify the seat of a frame event. Frame events are sent to end a group of + * events that logically belong together. Motion, button and axis events should + * all be followed by a frame event. + */ +void wlr_seat_pointer_notify_frame(struct wlr_seat *wlr_seat); + /** * Whether or not the pointer has a grab other than the default grab. */ diff --git a/rootston/cursor.c b/rootston/cursor.c index b7ecc813..8ae098de 100644 --- a/rootston/cursor.c +++ b/rootston/cursor.c @@ -386,6 +386,10 @@ void roots_cursor_handle_axis(struct roots_cursor *cursor, event->orientation, event->delta, event->delta_discrete, event->source); } +void roots_cursor_handle_frame(struct roots_cursor *cursor) { + wlr_seat_pointer_notify_frame(cursor->seat->seat); +} + void roots_cursor_handle_touch_down(struct roots_cursor *cursor, struct wlr_event_touch_down *event) { struct roots_desktop *desktop = cursor->seat->input->server->desktop; diff --git a/rootston/seat.c b/rootston/seat.c index 43760a5e..c69be8ab 100644 --- a/rootston/seat.c +++ b/rootston/seat.c @@ -77,6 +77,14 @@ static void handle_cursor_axis(struct wl_listener *listener, void *data) { roots_cursor_handle_axis(cursor, event); } +static void handle_cursor_frame(struct wl_listener *listener, void *data) { + struct roots_cursor *cursor = + wl_container_of(listener, cursor, frame); + struct roots_desktop *desktop = cursor->seat->input->server->desktop; + wlr_idle_notify_activity(desktop->idle, cursor->seat->seat); + roots_cursor_handle_frame(cursor); +} + static void handle_switch_toggle(struct wl_listener *listener, void *data) { struct roots_switch *lid_switch = wl_container_of(listener, lid_switch, toggle); @@ -443,6 +451,9 @@ static void roots_seat_init_cursor(struct roots_seat *seat) { wl_signal_add(&wlr_cursor->events.axis, &seat->cursor->axis); seat->cursor->axis.notify = handle_cursor_axis; + wl_signal_add(&wlr_cursor->events.frame, &seat->cursor->frame); + seat->cursor->frame.notify = handle_cursor_frame; + wl_signal_add(&wlr_cursor->events.touch_down, &seat->cursor->touch_down); seat->cursor->touch_down.notify = handle_touch_down; diff --git a/types/seat/wlr_seat_pointer.c b/types/seat/wlr_seat_pointer.c index 594a5b81..8776457d 100644 --- a/types/seat/wlr_seat_pointer.c +++ b/types/seat/wlr_seat_pointer.c @@ -31,6 +31,10 @@ static void default_pointer_axis(struct wlr_seat_pointer_grab *grab, value_discrete, source); } +static void default_pointer_frame(struct wlr_seat_pointer_grab *grab) { + wlr_seat_pointer_send_frame(grab->seat); +} + static void default_pointer_cancel(struct wlr_seat_pointer_grab *grab) { // cannot be cancelled } @@ -40,6 +44,7 @@ const struct wlr_pointer_grab_interface default_pointer_grab_impl = { .motion = default_pointer_motion, .button = default_pointer_button, .axis = default_pointer_axis, + .frame = default_pointer_frame, .cancel = default_pointer_cancel, }; @@ -212,7 +217,6 @@ void wlr_seat_pointer_send_motion(struct wlr_seat *wlr_seat, uint32_t time, wl_pointer_send_motion(resource, time, wl_fixed_from_double(sx), wl_fixed_from_double(sy)); - pointer_send_frame(resource); } } @@ -231,7 +235,6 @@ uint32_t wlr_seat_pointer_send_button(struct wlr_seat *wlr_seat, uint32_t time, } wl_pointer_send_button(resource, serial, time, button, state); - pointer_send_frame(resource); } return serial; } @@ -267,6 +270,21 @@ void wlr_seat_pointer_send_axis(struct wlr_seat *wlr_seat, uint32_t time, } else if (version >= WL_POINTER_AXIS_STOP_SINCE_VERSION) { wl_pointer_send_axis_stop(resource, time, orientation); } + } +} + +void wlr_seat_pointer_send_frame(struct wlr_seat *wlr_seat) { + 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; + } + pointer_send_frame(resource); } } @@ -336,6 +354,14 @@ void wlr_seat_pointer_notify_axis(struct wlr_seat *wlr_seat, uint32_t time, source); } +void wlr_seat_pointer_notify_frame(struct wlr_seat *wlr_seat) { + clock_gettime(CLOCK_MONOTONIC, &wlr_seat->last_event); + struct wlr_seat_pointer_grab *grab = wlr_seat->pointer_state.grab; + if (grab->interface->frame) { + grab->interface->frame(grab); + } +} + bool wlr_seat_pointer_has_grab(struct wlr_seat *seat) { return seat->pointer_state.grab->interface != &default_pointer_grab_impl; } diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index 8094ff18..5da865e5 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -21,6 +21,7 @@ struct wlr_cursor_device { struct wl_listener motion_absolute; struct wl_listener button; struct wl_listener axis; + struct wl_listener frame; struct wl_listener touch_down; struct wl_listener touch_up; @@ -81,6 +82,7 @@ struct wlr_cursor *wlr_cursor_create(void) { wl_signal_init(&cur->events.motion_absolute); wl_signal_init(&cur->events.button); wl_signal_init(&cur->events.axis); + wl_signal_init(&cur->events.frame); // touch signals wl_signal_init(&cur->events.touch_up); @@ -133,6 +135,7 @@ static void cursor_device_destroy(struct wlr_cursor_device *c_device) { wl_list_remove(&c_device->motion_absolute.link); wl_list_remove(&c_device->button.link); wl_list_remove(&c_device->axis.link); + wl_list_remove(&c_device->frame.link); } else if (dev->type == WLR_INPUT_DEVICE_TOUCH) { wl_list_remove(&c_device->touch_down.link); wl_list_remove(&c_device->touch_up.link); @@ -415,6 +418,11 @@ static void handle_pointer_axis(struct wl_listener *listener, void *data) { wlr_signal_emit_safe(&device->cursor->events.axis, event); } +static void handle_pointer_frame(struct wl_listener *listener, void *data) { + struct wlr_cursor_device *device = wl_container_of(listener, device, frame); + wlr_signal_emit_safe(&device->cursor->events.frame, device->cursor); +} + static void handle_touch_up(struct wl_listener *listener, void *data) { struct wlr_event_touch_up *event = data; struct wlr_cursor_device *device; @@ -538,6 +546,9 @@ static struct wlr_cursor_device *cursor_device_create( wl_signal_add(&device->pointer->events.axis, &c_device->axis); c_device->axis.notify = handle_pointer_axis; + + wl_signal_add(&device->pointer->events.frame, &c_device->frame); + c_device->frame.notify = handle_pointer_frame; } else if (device->type == WLR_INPUT_DEVICE_TOUCH) { wl_signal_add(&device->touch->events.motion, &c_device->touch_motion); c_device->touch_motion.notify = handle_touch_motion; diff --git a/types/wlr_pointer.c b/types/wlr_pointer.c index 20e75731..d7d1515a 100644 --- a/types/wlr_pointer.c +++ b/types/wlr_pointer.c @@ -11,6 +11,7 @@ void wlr_pointer_init(struct wlr_pointer *pointer, wl_signal_init(&pointer->events.motion_absolute); wl_signal_init(&pointer->events.button); wl_signal_init(&pointer->events.axis); + wl_signal_init(&pointer->events.frame); } void wlr_pointer_destroy(struct wlr_pointer *pointer) { @@ -20,10 +21,6 @@ void wlr_pointer_destroy(struct wlr_pointer *pointer) { if (pointer->impl && pointer->impl->destroy) { pointer->impl->destroy(pointer); } else { - wl_list_remove(&pointer->events.motion.listener_list); - wl_list_remove(&pointer->events.motion_absolute.listener_list); - wl_list_remove(&pointer->events.button.listener_list); - wl_list_remove(&pointer->events.axis.listener_list); free(pointer); } } diff --git a/types/wlr_relative_pointer_v1.c b/types/wlr_relative_pointer_v1.c index 2247656e..17e65b67 100644 --- a/types/wlr_relative_pointer_v1.c +++ b/types/wlr_relative_pointer_v1.c @@ -271,9 +271,5 @@ void wlr_relative_pointer_manager_v1_send_relative_motion( (uint32_t)(time_msec >> 32), (uint32_t)time_msec, wl_fixed_from_double(dx), wl_fixed_from_double(dy), wl_fixed_from_double(dx_unaccel), wl_fixed_from_double(dy_unaccel)); - uint32_t version = wl_resource_get_version(pointer->resource); - if (version >= WL_POINTER_FRAME_SINCE_VERSION) { - wl_pointer_send_frame(pointer->pointer_resource); - } } } From b45fc24b1893484c02420fbb33d7ebb69bbf1eae Mon Sep 17 00:00:00 2001 From: emersion Date: Sat, 26 Jan 2019 11:18:47 +0100 Subject: [PATCH 2/2] backend/wayland: handle wl_pointer.axis_stop --- backend/wayland/wl_seat.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/backend/wayland/wl_seat.c b/backend/wayland/wl_seat.c index 7efa6eb4..1229a0ac 100644 --- a/backend/wayland/wl_seat.c +++ b/backend/wayland/wl_seat.c @@ -149,7 +149,21 @@ static void pointer_handle_axis_source(void *data, static void pointer_handle_axis_stop(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis) { - // This space is intentionally left blank + struct wlr_wl_backend *backend = data; + struct wlr_wl_pointer *pointer = backend->current_pointer; + if (pointer == NULL) { + return; + } + + struct wlr_event_pointer_axis event = { + .device = &pointer->input_device->wlr_input_device, + .delta = 0, + .delta_discrete = 0, + .orientation = axis, + .time_msec = time, + .source = pointer->axis_source, + }; + wlr_signal_emit_safe(&pointer->wlr_pointer.events.axis, &event); } static void pointer_handle_axis_discrete(void *data,