[PATCH v5 weston 2/2] Support axis source, axis discrete, frame and axis stop events
Jonas Ã…dahl
jadahl at gmail.com
Mon Jan 18 21:26:45 PST 2016
This one is now also pushed, with a couple of fixes (resource version
checks before sending wl_pointer.frame when changing pointer focus).
Jonas
On Mon, Jan 18, 2016 at 04:38:22PM +1000, Peter Hutterer wrote:
> Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
> ---
> Changes to v2:
> - don't send frames after focus events, notify_pointer_focus() takes
> care of that
> - add frame events to screen-share
>
> clients/eventdemo.c | 57 ++++++++++++++++-
> clients/window.c | 97 ++++++++++++++++++++++++++++-
> clients/window.h | 31 +++++++++
> desktop-shell/exposay.c | 12 ++++
> desktop-shell/shell.c | 33 ++++++++++
> ivi-shell/hmi-controller.c | 15 +++++
> src/compositor-rdp.c | 20 ++++--
> src/compositor-wayland.c | 84 ++++++++++++++++++++++++-
> src/compositor-x11.c | 10 +++
> src/compositor.h | 16 +++++
> src/data-device.c | 12 ++++
> src/input.c | 93 ++++++++++++++++++++++++---
> src/libinput-device.c | 128 ++++++++++++++++++++++++++++----------
> src/screen-share.c | 4 ++
> tests/weston-test-client-helper.c | 32 ++++++++++
> 15 files changed, 596 insertions(+), 48 deletions(-)
>
> diff --git a/clients/eventdemo.c b/clients/eventdemo.c
> index bdad6fd..e323aa5 100644
> --- a/clients/eventdemo.c
> +++ b/clients/eventdemo.c
> @@ -259,6 +259,54 @@ axis_handler(struct widget *widget, struct input *input, uint32_t time,
> wl_fixed_to_double(value));
> }
>
> +static void
> +pointer_frame_handler(struct widget *widget, struct input *input, void *data)
> +{
> + printf("pointer frame\n");
> +}
> +
> +static void
> +axis_source_handler(struct widget *widget, struct input *input,
> + uint32_t source, void *data)
> +{
> + const char *axis_source;
> +
> + switch (source) {
> + case WL_POINTER_AXIS_SOURCE_WHEEL:
> + axis_source = "wheel";
> + break;
> + case WL_POINTER_AXIS_SOURCE_FINGER:
> + axis_source = "finger";
> + break;
> + case WL_POINTER_AXIS_SOURCE_CONTINUOUS:
> + axis_source = "continuous";
> + break;
> + default:
> + axis_source = "<invalid source value>";
> + break;
> + }
> +
> + printf("axis source: %s\n", axis_source);
> +}
> +
> +static void
> +axis_stop_handler(struct widget *widget, struct input *input,
> + uint32_t time, uint32_t axis,
> + void *data)
> +{
> + printf("axis stop time: %d, axis: %s\n",
> + time,
> + axis == WL_POINTER_AXIS_VERTICAL_SCROLL ? "vertical" :
> + "horizontal");
> +}
> +
> +static void
> +axis_discrete_handler(struct widget *widget, struct input *input,
> + uint32_t axis, int32_t discrete, void *data)
> +{
> + printf("axis discrete axis: %d value: %d\n", axis, discrete);
> +}
> +
> /**
> * \brief CALLBACK function, Waylands informs about pointer motion
> * \param widget widget
> @@ -347,8 +395,15 @@ eventdemo_create(struct display *d)
> /* Set the callback motion handler for the window */
> widget_set_motion_handler(e->widget, motion_handler);
>
> + /* Set the callback pointer frame handler for the window */
> + widget_set_pointer_frame_handler(e->widget, pointer_frame_handler);
> +
> /* Set the callback axis handler for the window */
> - widget_set_axis_handler(e->widget, axis_handler);
> + widget_set_axis_handlers(e->widget,
> + axis_handler,
> + axis_source_handler,
> + axis_stop_handler,
> + axis_discrete_handler);
>
> /* Initial drawing of the window */
> window_schedule_resize(e->window, width, height);
> diff --git a/clients/window.c b/clients/window.c
> index 5d69116..7d45acd 100644
> --- a/clients/window.c
> +++ b/clients/window.c
> @@ -282,6 +282,10 @@ struct widget {
> widget_touch_frame_handler_t touch_frame_handler;
> widget_touch_cancel_handler_t touch_cancel_handler;
> widget_axis_handler_t axis_handler;
> + widget_pointer_frame_handler_t pointer_frame_handler;
> + widget_axis_source_handler_t axis_source_handler;
> + widget_axis_stop_handler_t axis_stop_handler;
> + widget_axis_discrete_handler_t axis_discrete_handler;
> void *user_data;
> int opaque;
> int tooltip_count;
> @@ -1930,6 +1934,26 @@ widget_set_axis_handler(struct widget *widget,
> widget->axis_handler = handler;
> }
>
> +void
> +widget_set_pointer_frame_handler(struct widget *widget,
> + widget_pointer_frame_handler_t handler)
> +{
> + widget->pointer_frame_handler = handler;
> +}
> +
> +void
> +widget_set_axis_handlers(struct widget *widget,
> + widget_axis_handler_t axis_handler,
> + widget_axis_source_handler_t axis_source_handler,
> + widget_axis_stop_handler_t axis_stop_handler,
> + widget_axis_discrete_handler_t axis_discrete_handler)
> +{
> + widget->axis_handler = axis_handler;
> + widget->axis_source_handler = axis_source_handler;
> + widget->axis_stop_handler = axis_stop_handler;
> + widget->axis_discrete_handler = axis_discrete_handler;
> +}
> +
> static void
> window_schedule_redraw_task(struct window *window);
>
> @@ -2780,12 +2804,83 @@ pointer_handle_axis(void *data, struct wl_pointer *pointer,
> widget->user_data);
> }
>
> +static void
> +pointer_handle_frame(void *data, struct wl_pointer *pointer)
> +{
> + struct input *input = data;
> + struct widget *widget;
> +
> + widget = input->focus_widget;
> + if (input->grab)
> + widget = input->grab;
> + if (widget && widget->pointer_frame_handler)
> + (*widget->pointer_frame_handler)(widget,
> + input,
> + widget->user_data);
> +}
> +
> +static void
> +pointer_handle_axis_source(void *data, struct wl_pointer *pointer,
> + uint32_t source)
> +{
> + struct input *input = data;
> + struct widget *widget;
> +
> + widget = input->focus_widget;
> + if (input->grab)
> + widget = input->grab;
> + if (widget && widget->axis_source_handler)
> + (*widget->axis_source_handler)(widget,
> + input,
> + source,
> + widget->user_data);
> +}
> +
> +static void
> +pointer_handle_axis_stop(void *data, struct wl_pointer *pointer,
> + uint32_t time, uint32_t axis)
> +{
> + struct input *input = data;
> + struct widget *widget;
> +
> + widget = input->focus_widget;
> + if (input->grab)
> + widget = input->grab;
> + if (widget && widget->axis_stop_handler)
> + (*widget->axis_stop_handler)(widget,
> + input, time,
> + axis,
> + widget->user_data);
> +}
> +
> +static void
> +pointer_handle_axis_discrete(void *data, struct wl_pointer *pointer,
> + uint32_t axis, int32_t discrete)
> +{
> + struct input *input = data;
> + struct widget *widget;
> +
> + widget = input->focus_widget;
> + if (input->grab)
> + widget = input->grab;
> + if (widget && widget->axis_discrete_handler)
> + (*widget->axis_discrete_handler)(widget,
> + input,
> + axis,
> + discrete,
> + widget->user_data);
> +}
> +
> static const struct wl_pointer_listener pointer_listener = {
> pointer_handle_enter,
> pointer_handle_leave,
> pointer_handle_motion,
> pointer_handle_button,
> pointer_handle_axis,
> + pointer_handle_frame,
> + pointer_handle_axis_source,
> + pointer_handle_axis_stop,
> + pointer_handle_axis_discrete,
> };
>
> static void
> @@ -5178,7 +5273,7 @@ static void
> display_add_input(struct display *d, uint32_t id, int display_seat_version)
> {
> struct input *input;
> - int seat_version = MIN(display_seat_version, 4);
> + int seat_version = MIN(display_seat_version, 5);
>
> input = xzalloc(sizeof *input);
> input->display = d;
> diff --git a/clients/window.h b/clients/window.h
> index b92d10c..ba843cc 100644
> --- a/clients/window.h
> +++ b/clients/window.h
> @@ -267,6 +267,27 @@ typedef void (*widget_axis_handler_t)(struct widget *widget,
> wl_fixed_t value,
> void *data);
>
> +typedef void (*widget_pointer_frame_handler_t)(struct widget *widget,
> + struct input *input,
> + void *data);
> +
> +typedef void (*widget_axis_source_handler_t)(struct widget *widget,
> + struct input *input,
> + uint32_t source,
> + void *data);
> +
> +typedef void (*widget_axis_stop_handler_t)(struct widget *widget,
> + struct input *input,
> + uint32_t time,
> + uint32_t axis,
> + void *data);
> +
> +typedef void (*widget_axis_discrete_handler_t)(struct widget *widget,
> + struct input *input,
> + uint32_t axis,
> + int32_t discrete,
> + void *data);
> +
> struct window *
> window_create(struct display *display);
> struct window *
> @@ -516,6 +537,16 @@ void
> widget_set_axis_handler(struct widget *widget,
> widget_axis_handler_t handler);
> void
> +widget_set_pointer_frame_handler(struct widget *widget,
> + widget_pointer_frame_handler_t handler);
> +void
> +widget_set_axis_handlers(struct widget *widget,
> + widget_axis_handler_t axis_handler,
> + widget_axis_source_handler_t axis_source_handler,
> + widget_axis_stop_handler_t axis_stop_handler,
> + widget_axis_discrete_handler_t axis_discrete_handler);
> +
> +void
> widget_schedule_redraw(struct widget *widget);
> void
> widget_set_use_cairo(struct widget *widget, int use_cairo);
> diff --git a/desktop-shell/exposay.c b/desktop-shell/exposay.c
> index f837859..7aa7630 100644
> --- a/desktop-shell/exposay.c
> +++ b/desktop-shell/exposay.c
> @@ -392,6 +392,16 @@ exposay_axis(struct weston_pointer_grab *grab,
> }
>
> static void
> +exposay_axis_source(struct weston_pointer_grab *grab, uint32_t source)
> +{
> +}
> +
> +static void
> +exposay_frame(struct weston_pointer_grab *grab)
> +{
> +}
> +
> +static void
> exposay_pointer_grab_cancel(struct weston_pointer_grab *grab)
> {
> struct desktop_shell *shell =
> @@ -405,6 +415,8 @@ static const struct weston_pointer_grab_interface exposay_ptr_grab = {
> exposay_motion,
> exposay_button,
> exposay_axis,
> + exposay_axis_source,
> + exposay_frame,
> exposay_pointer_grab_cancel,
> };
>
> diff --git a/desktop-shell/shell.c b/desktop-shell/shell.c
> index 6e74655..5ae83ef 100644
> --- a/desktop-shell/shell.c
> +++ b/desktop-shell/shell.c
> @@ -1603,6 +1603,17 @@ noop_grab_axis(struct weston_pointer_grab *grab,
> }
>
> static void
> +noop_grab_axis_source(struct weston_pointer_grab *grab,
> + uint32_t source)
> +{
> +}
> +
> +static void
> +noop_grab_frame(struct weston_pointer_grab *grab)
> +{
> +}
> +
> +static void
> constrain_position(struct weston_move_grab *move, int *cx, int *cy)
> {
> struct shell_surface *shsurf = move->base.shsurf;
> @@ -1686,6 +1697,8 @@ static const struct weston_pointer_grab_interface move_grab_interface = {
> move_grab_motion,
> move_grab_button,
> noop_grab_axis,
> + noop_grab_axis_source,
> + noop_grab_frame,
> move_grab_cancel,
> };
>
> @@ -1851,6 +1864,8 @@ static const struct weston_pointer_grab_interface resize_grab_interface = {
> resize_grab_motion,
> resize_grab_button,
> noop_grab_axis,
> + noop_grab_axis_source,
> + noop_grab_frame,
> resize_grab_cancel,
> };
>
> @@ -2016,6 +2031,8 @@ static const struct weston_pointer_grab_interface busy_cursor_grab_interface = {
> busy_cursor_grab_motion,
> busy_cursor_grab_button,
> noop_grab_axis,
> + noop_grab_axis_source,
> + noop_grab_frame,
> busy_cursor_grab_cancel,
> };
>
> @@ -3214,6 +3231,18 @@ popup_grab_axis(struct weston_pointer_grab *grab,
> }
>
> static void
> +popup_grab_axis_source(struct weston_pointer_grab *grab, uint32_t source)
> +{
> + weston_pointer_send_axis_source(grab->pointer, source);
> +}
> +
> +static void
> +popup_grab_frame(struct weston_pointer_grab *grab)
> +{
> + weston_pointer_send_frame(grab->pointer);
> +}
> +
> +static void
> popup_grab_cancel(struct weston_pointer_grab *grab)
> {
> popup_grab_end(grab->pointer);
> @@ -3224,6 +3253,8 @@ static const struct weston_pointer_grab_interface popup_grab_interface = {
> popup_grab_motion,
> popup_grab_button,
> popup_grab_axis,
> + popup_grab_axis_source,
> + popup_grab_frame,
> popup_grab_cancel,
> };
>
> @@ -4923,6 +4954,8 @@ static const struct weston_pointer_grab_interface rotate_grab_interface = {
> rotate_grab_motion,
> rotate_grab_button,
> noop_grab_axis,
> + noop_grab_axis_source,
> + noop_grab_frame,
> rotate_grab_cancel,
> };
>
> diff --git a/ivi-shell/hmi-controller.c b/ivi-shell/hmi-controller.c
> index c21b9e0..8da3d3c 100644
> --- a/ivi-shell/hmi-controller.c
> +++ b/ivi-shell/hmi-controller.c
> @@ -1518,6 +1518,19 @@ pointer_default_grab_axis(struct weston_pointer_grab *grab,
> }
>
> static void
> +pointer_default_grab_axis_source(struct weston_pointer_grab *grab,
> + uint32_t source)
> +{
> + weston_pointer_send_axis_source(grab->pointer, source);
> +}
> +
> +static void
> +pointer_default_grab_frame(struct weston_pointer_grab *grab)
> +{
> + weston_pointer_send_frame(grab->pointer);
> +}
> +
> +static void
> move_grab_update(struct move_grab *move, wl_fixed_t pointer[2])
> {
> struct timespec timestamp = {0};
> @@ -1664,6 +1677,8 @@ static const struct weston_pointer_grab_interface pointer_move_grab_workspace_in
> pointer_move_grab_motion,
> pointer_move_workspace_grab_button,
> pointer_default_grab_axis,
> + pointer_default_grab_axis_source,
> + pointer_default_grab_frame,
> pointer_move_workspace_grab_cancel
> };
>
> diff --git a/src/compositor-rdp.c b/src/compositor-rdp.c
> index d6d2fa1..3526ad1 100644
> --- a/src/compositor-rdp.c
> +++ b/src/compositor-rdp.c
> @@ -70,7 +70,7 @@
> #include "pixman-renderer.h"
>
> #define MAX_FREERDP_FDS 32
> -#define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int(10)
> +#define DEFAULT_AXIS_STEP_DISTANCE 10
> #define RDP_MODE_FREQ 60 * 1000
>
> struct rdp_backend_config {
> @@ -942,10 +942,11 @@ static BOOL xf_peer_post_connect(freerdp_peer *client)
> static FREERDP_CB_RET_TYPE
> xf_mouseEvent(rdpInput *input, UINT16 flags, UINT16 x, UINT16 y)
> {
> - wl_fixed_t wl_x, wl_y, axis;
> + wl_fixed_t wl_x, wl_y;
> RdpPeerContext *peerContext = (RdpPeerContext *)input->context;
> struct rdp_output *output;
> uint32_t button = 0;
> + bool need_frame = false;
>
> if (flags & PTR_FLAGS_MOVE) {
> output = peerContext->rdpBackend->output;
> @@ -954,6 +955,7 @@ xf_mouseEvent(rdpInput *input, UINT16 flags, UINT16 x, UINT16 y)
> wl_y = wl_fixed_from_int((int)y);
> notify_motion_absolute(&peerContext->item.seat, weston_compositor_get_time(),
> wl_x, wl_y);
> + need_frame = true;
> }
> }
>
> @@ -968,10 +970,12 @@ xf_mouseEvent(rdpInput *input, UINT16 flags, UINT16 x, UINT16 y)
> notify_button(&peerContext->item.seat, weston_compositor_get_time(), button,
> (flags & PTR_FLAGS_DOWN) ? WL_POINTER_BUTTON_STATE_PRESSED : WL_POINTER_BUTTON_STATE_RELEASED
> );
> + need_frame = true;
> }
>
> if (flags & PTR_FLAGS_WHEEL) {
> struct weston_pointer_axis_event weston_event;
> + double value;
>
> /* DEFAULT_AXIS_STEP_DISTANCE is stolen from compositor-x11.c
> * The RDP specs says the lower bits of flags contains the "the number of rotation
> @@ -979,17 +983,23 @@ xf_mouseEvent(rdpInput *input, UINT16 flags, UINT16 x, UINT16 y)
> *
> * https://blogs.msdn.microsoft.com/oldnewthing/20130123-00/?p=5473 explains the 120 value
> */
> - axis = (DEFAULT_AXIS_STEP_DISTANCE * (flags & 0xff)) / 120;
> + value = (flags & 0xff) / 120.0;
> if (flags & PTR_FLAGS_WHEEL_NEGATIVE)
> - axis = -axis;
> + value = -value;
>
> weston_event.axis = WL_POINTER_AXIS_VERTICAL_SCROLL;
> - weston_event.value = axis;
> + weston_event.value = wl_fixed_from_double(DEFAULT_AXIS_STEP_DISTANCE * value);
> + weston_event.discrete = (int)value;
> + weston_event.has_discrete = true;
>
> notify_axis(&peerContext->item.seat, weston_compositor_get_time(),
> &weston_event);
> + need_frame = true;
> }
>
> + if (need_frame)
> + notify_pointer_frame(&peerContext->item.seat);
> +
> FREERDP_CB_RETURN(TRUE);
> }
>
> diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c
> index 48636fe..d1c020d 100644
> --- a/src/compositor-wayland.c
> +++ b/src/compositor-wayland.c
> @@ -185,6 +185,8 @@ struct wayland_input {
> struct wayland_output *output;
> struct wayland_output *touch_focus;
> struct wayland_output *keyboard_focus;
> +
> + struct weston_pointer_axis_event vert, horiz;
> };
>
> struct gl_renderer_interface *gl_renderer;
> @@ -1340,6 +1342,7 @@ input_handle_motion(void *data, struct wl_pointer *pointer,
> struct wayland_input *input = data;
> int32_t fx, fy;
> enum theme_location location;
> + bool want_frame = false;
>
> if (!input->output)
> return;
> @@ -1364,16 +1367,23 @@ input_handle_motion(void *data, struct wl_pointer *pointer,
> input_set_cursor(input);
> notify_pointer_focus(&input->base, NULL, 0, 0);
> input->has_focus = false;
> + want_frame = true;
> } else if (!input->has_focus &&
> location == THEME_LOCATION_CLIENT_AREA) {
> wl_pointer_set_cursor(input->parent.pointer,
> input->enter_serial, NULL, 0, 0);
> notify_pointer_focus(&input->base, &input->output->base, x, y);
> input->has_focus = true;
> + want_frame = true;
> }
>
> - if (location == THEME_LOCATION_CLIENT_AREA)
> + if (location == THEME_LOCATION_CLIENT_AREA) {
> notify_motion_absolute(&input->base, time, x, y);
> + want_frame = true;
> + }
> +
> + if (want_frame && input->seat_version < WL_POINTER_FRAME_SINCE_VERSION)
> + notify_pointer_frame(&input->base);
> }
>
> static void
> @@ -1422,8 +1432,11 @@ input_handle_button(void *data, struct wl_pointer *pointer,
> location = THEME_LOCATION_CLIENT_AREA;
> }
>
> - if (location == THEME_LOCATION_CLIENT_AREA)
> + if (location == THEME_LOCATION_CLIENT_AREA) {
> notify_button(&input->base, time, button, state);
> + if (input->seat_version < WL_POINTER_FRAME_SINCE_VERSION)
> + notify_pointer_frame(&input->base);
> + }
> }
>
> static void
> @@ -1436,7 +1449,67 @@ input_handle_axis(void *data, struct wl_pointer *pointer,
> weston_event.axis = axis;
> weston_event.value = value;
>
> + if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL &&
> + input->vert.has_discrete) {
> + weston_event.has_discrete = true;
> + weston_event.discrete = input->vert.discrete;
> + input->vert.has_discrete = false;
> + } else if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL &&
> + input->horiz.has_discrete) {
> + weston_event.has_discrete = true;
> + weston_event.discrete = input->horiz.discrete;
> + input->horiz.has_discrete = false;
> + }
> +
> notify_axis(&input->base, time, &weston_event);
> +
> + if (input->seat_version < WL_POINTER_FRAME_SINCE_VERSION)
> + notify_pointer_frame(&input->base);
> +}
> +
> +static void
> +input_handle_frame(void *data, struct wl_pointer *pointer)
> +{
> + struct wayland_input *input = data;
> +
> + notify_pointer_frame(&input->base);
> +}
> +
> +static void
> +input_handle_axis_source(void *data, struct wl_pointer *pointer,
> + uint32_t source)
> +{
> + struct wayland_input *input = data;
> +
> + notify_axis_source(&input->base, source);
> +}
> +
> +static void
> +input_handle_axis_stop(void *data, struct wl_pointer *pointer,
> + uint32_t time, uint32_t axis)
> +{
> + struct wayland_input *input = data;
> + struct weston_pointer_axis_event weston_event;
> +
> + weston_event.axis = axis;
> + weston_event.value = 0;
> +
> + notify_axis(&input->base, time, &weston_event);
> +}
> +
> +static void
> +input_handle_axis_discrete(void *data, struct wl_pointer *pointer,
> + uint32_t axis, int32_t discrete)
> +{
> + struct wayland_input *input = data;
> +
> + if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL) {
> + input->vert.has_discrete = true;
> + input->vert.discrete = discrete;
> + } else if (axis == WL_POINTER_AXIS_HORIZONTAL_SCROLL) {
> + input->horiz.has_discrete = true;
> + input->horiz.discrete = discrete;
> + }
> }
>
> static const struct wl_pointer_listener pointer_listener = {
> @@ -1445,6 +1518,10 @@ static const struct wl_pointer_listener pointer_listener = {
> input_handle_motion,
> input_handle_button,
> input_handle_axis,
> + input_handle_frame,
> + input_handle_axis_source,
> + input_handle_axis_stop,
> + input_handle_axis_discrete,
> };
>
> static void
> @@ -1851,6 +1928,9 @@ display_add_seat(struct wayland_backend *b, uint32_t id, uint32_t available_vers
>
> input->parent.cursor.surface =
> wl_compositor_create_surface(b->parent.compositor);
> +
> + input->vert.axis = WL_POINTER_AXIS_VERTICAL_SCROLL;
> + input->horiz.axis = WL_POINTER_AXIS_HORIZONTAL_SCROLL;
> }
>
> static void
> diff --git a/src/compositor-x11.c b/src/compositor-x11.c
> index 93018da..b70c119 100644
> --- a/src/compositor-x11.c
> +++ b/src/compositor-x11.c
> @@ -1085,6 +1085,8 @@ x11_backend_deliver_button_event(struct x11_backend *b,
> * steps. Therefore move the axis by some pixels every step. */
> if (state) {
> weston_event.value = -DEFAULT_AXIS_STEP_DISTANCE;
> + weston_event.discrete = -1;
> + weston_event.has_discrete = true;
> weston_event.axis =
> WL_POINTER_AXIS_VERTICAL_SCROLL;
> notify_axis(&b->core_seat,
> @@ -1095,6 +1097,8 @@ x11_backend_deliver_button_event(struct x11_backend *b,
> case 5:
> if (state) {
> weston_event.value = DEFAULT_AXIS_STEP_DISTANCE;
> + weston_event.discrete = 1;
> + weston_event.has_discrete = true;
> weston_event.axis =
> WL_POINTER_AXIS_VERTICAL_SCROLL;
> notify_axis(&b->core_seat,
> @@ -1105,6 +1109,8 @@ x11_backend_deliver_button_event(struct x11_backend *b,
> case 6:
> if (state) {
> weston_event.value = -DEFAULT_AXIS_STEP_DISTANCE;
> + weston_event.discrete = -1;
> + weston_event.has_discrete = true;
> weston_event.axis =
> WL_POINTER_AXIS_HORIZONTAL_SCROLL;
> notify_axis(&b->core_seat,
> @@ -1115,6 +1121,8 @@ x11_backend_deliver_button_event(struct x11_backend *b,
> case 7:
> if (state) {
> weston_event.value = DEFAULT_AXIS_STEP_DISTANCE;
> + weston_event.discrete = 1;
> + weston_event.has_discrete = true;
> weston_event.axis =
> WL_POINTER_AXIS_HORIZONTAL_SCROLL;
> notify_axis(&b->core_seat,
> @@ -1131,6 +1139,7 @@ x11_backend_deliver_button_event(struct x11_backend *b,
> weston_compositor_get_time(), button,
> state ? WL_POINTER_BUTTON_STATE_PRESSED :
> WL_POINTER_BUTTON_STATE_RELEASED);
> + notify_pointer_frame(&b->core_seat);
> }
>
> static void
> @@ -1162,6 +1171,7 @@ x11_backend_deliver_motion_event(struct x11_backend *b,
>
> notify_motion(&b->core_seat, weston_compositor_get_time(),
> &motion_event);
> + notify_pointer_frame(&b->core_seat);
>
> b->prev_x = x;
> b->prev_y = y;
> diff --git a/src/compositor.h b/src/compositor.h
> index ddcafc6..5970e57 100644
> --- a/src/compositor.h
> +++ b/src/compositor.h
> @@ -254,6 +254,8 @@ struct weston_pointer_motion_event {
> struct weston_pointer_axis_event {
> uint32_t axis;
> wl_fixed_t value;
> + bool has_discrete;
> + int32_t discrete;
> };
>
> struct weston_pointer_grab;
> @@ -266,6 +268,8 @@ struct weston_pointer_grab_interface {
> void (*axis)(struct weston_pointer_grab *grab,
> uint32_t time,
> struct weston_pointer_axis_event *event);
> + void (*axis_source)(struct weston_pointer_grab *grab, uint32_t source);
> + void (*frame)(struct weston_pointer_grab *grab);
> void (*cancel)(struct weston_pointer_grab *grab);
> };
>
> @@ -404,6 +408,12 @@ weston_pointer_send_axis(struct weston_pointer *pointer,
> uint32_t time,
> struct weston_pointer_axis_event *event);
> void
> +weston_pointer_send_axis_source(struct weston_pointer *pointer,
> + uint32_t source);
> +void
> +weston_pointer_send_frame(struct weston_pointer *pointer);
> +
> +void
> weston_pointer_set_focus(struct weston_pointer *pointer,
> struct weston_view *view,
> wl_fixed_t sx, wl_fixed_t sy);
> @@ -1143,6 +1153,12 @@ void
> notify_axis(struct weston_seat *seat, uint32_t time,
> struct weston_pointer_axis_event *event);
> void
> +notify_axis_source(struct weston_seat *seat, uint32_t source);
> +
> +void
> +notify_pointer_frame(struct weston_seat *seat);
> +
> +void
> notify_key(struct weston_seat *seat, uint32_t time, uint32_t key,
> enum wl_keyboard_key_state state,
> enum weston_key_state_update update_state);
> diff --git a/src/data-device.c b/src/data-device.c
> index 4a1c1b8..545a895 100644
> --- a/src/data-device.c
> +++ b/src/data-device.c
> @@ -417,6 +417,16 @@ drag_grab_axis(struct weston_pointer_grab *grab,
> }
>
> static void
> +drag_grab_axis_source(struct weston_pointer_grab *grab, uint32_t source)
> +{
> +}
> +
> +static void
> +drag_grab_frame(struct weston_pointer_grab *grab)
> +{
> +}
> +
> +static void
> drag_grab_cancel(struct weston_pointer_grab *grab)
> {
> struct weston_pointer_drag *drag =
> @@ -433,6 +443,8 @@ static const struct weston_pointer_grab_interface pointer_drag_grab_interface =
> drag_grab_motion,
> drag_grab_button,
> drag_grab_axis,
> + drag_grab_axis_source,
> + drag_grab_frame,
> drag_grab_cancel,
> };
>
> diff --git a/src/input.c b/src/input.c
> index 9382bb1..f321801 100644
> --- a/src/input.c
> +++ b/src/input.c
> @@ -343,9 +343,51 @@ weston_pointer_send_axis(struct weston_pointer *pointer,
> return;
>
> resource_list = &pointer->focus_client->pointer_resources;
> - wl_resource_for_each(resource, resource_list)
> - wl_pointer_send_axis(resource, time,
> - event->axis, event->value);
> + wl_resource_for_each(resource, resource_list) {
> + if (event->has_discrete &&
> + wl_resource_get_version(resource) >=
> + WL_POINTER_AXIS_DISCRETE_SINCE_VERSION)
> + wl_pointer_send_axis_discrete(resource, event->axis,
> + event->discrete);
> +
> + if (event->value)
> + wl_pointer_send_axis(resource, time,
> + event->axis, event->value);
> + else if (wl_resource_get_version(resource) >=
> + WL_POINTER_AXIS_STOP_SINCE_VERSION)
> + wl_pointer_send_axis_stop(resource, time,
> + event->axis);
> + }
> +}
> +
> +WL_EXPORT void
> +weston_pointer_send_axis_source(struct weston_pointer *pointer, uint32_t source)
> +{
> + struct wl_resource *resource;
> + struct wl_list *resource_list;
> +
> + resource_list = &pointer->focus_client->pointer_resources;
> + wl_resource_for_each(resource, resource_list) {
> + if (wl_resource_get_version(resource) >=
> + WL_POINTER_AXIS_SOURCE_SINCE_VERSION) {
> + wl_pointer_send_axis_source(resource, source);
> + }
> + }
> +}
> +
> +WL_EXPORT void
> +weston_pointer_send_frame(struct weston_pointer *pointer)
> +{
> + struct wl_resource *resource;
> + struct wl_list *resource_list;
> +
> + resource_list = &pointer->focus_client->pointer_resources;
> + wl_resource_for_each(resource, resource_list) {
> + if (wl_resource_get_version(resource) >=
> + WL_POINTER_FRAME_SINCE_VERSION) {
> + wl_pointer_send_frame(resource);
> + }
> + }
> }
>
> static void
> @@ -357,6 +399,19 @@ default_grab_pointer_axis(struct weston_pointer_grab *grab,
> }
>
> static void
> +default_grab_pointer_axis_source(struct weston_pointer_grab *grab,
> + uint32_t source)
> +{
> + weston_pointer_send_axis_source(grab->pointer, source);
> +}
> +
> +static void
> +default_grab_pointer_frame(struct weston_pointer_grab *grab)
> +{
> + weston_pointer_send_frame(grab->pointer);
> +}
> +
> +static void
> default_grab_pointer_cancel(struct weston_pointer_grab *grab)
> {
> }
> @@ -367,6 +422,8 @@ static const struct weston_pointer_grab_interface
> default_grab_pointer_motion,
> default_grab_pointer_button,
> default_grab_pointer_axis,
> + default_grab_pointer_axis_source,
> + default_grab_pointer_frame,
> default_grab_pointer_cancel,
> };
>
> @@ -830,6 +887,7 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
> wl_resource_for_each(resource, focus_resource_list) {
> wl_pointer_send_leave(resource, serial,
> surface_resource);
> + wl_pointer_send_frame(resource);
> }
> }
>
> @@ -856,6 +914,7 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
> serial,
> view->surface->resource,
> sx, sy);
> + wl_pointer_send_frame(resource);
> }
>
> pointer->focus_serial = serial;
> @@ -1277,9 +1336,6 @@ notify_axis(struct weston_seat *seat, uint32_t time,
>
> weston_compositor_wake(compositor);
>
> - if (!event->value)
> - return;
> -
> if (weston_compositor_run_axis_binding(compositor, pointer,
> time, event))
> return;
> @@ -1287,6 +1343,28 @@ notify_axis(struct weston_seat *seat, uint32_t time,
> pointer->grab->interface->axis(pointer->grab, time, event);
> }
>
> +WL_EXPORT void
> +notify_axis_source(struct weston_seat *seat, uint32_t source)
> +{
> + struct weston_compositor *compositor = seat->compositor;
> + struct weston_pointer *pointer = weston_seat_get_pointer(seat);
> +
> + weston_compositor_wake(compositor);
> +
> + pointer->grab->interface->axis_source(pointer->grab, source);
> +}
> +
> +WL_EXPORT void
> +notify_pointer_frame(struct weston_seat *seat)
> +{
> + struct weston_compositor *compositor = seat->compositor;
> + struct weston_pointer *pointer = weston_seat_get_pointer(seat);
> +
> + weston_compositor_wake(compositor);
> +
> + pointer->grab->interface->frame(pointer->grab);
> +}
> +
> WL_EXPORT int
> weston_keyboard_set_locks(struct weston_keyboard *keyboard,
> uint32_t mask, uint32_t value)
> @@ -1979,6 +2057,7 @@ seat_get_pointer(struct wl_client *client, struct wl_resource *resource,
> pointer->focus_serial,
> pointer->focus->surface->resource,
> sx, sy);
> + wl_pointer_send_frame(cr);
> }
> }
>
> @@ -2557,7 +2636,7 @@ weston_seat_init(struct weston_seat *seat, struct weston_compositor *ec,
> wl_signal_init(&seat->destroy_signal);
> wl_signal_init(&seat->updated_caps_signal);
>
> - seat->global = wl_global_create(ec->wl_display, &wl_seat_interface, 4,
> + seat->global = wl_global_create(ec->wl_display, &wl_seat_interface, 5,
> seat, bind_seat);
>
> seat->compositor = ec;
> diff --git a/src/libinput-device.c b/src/libinput-device.c
> index 9860d6e..99b2916 100644
> --- a/src/libinput-device.c
> +++ b/src/libinput-device.c
> @@ -80,7 +80,7 @@ handle_keyboard_key(struct libinput_device *libinput_device,
> STATE_UPDATE_AUTOMATIC);
> }
>
> -static void
> +static bool
> handle_pointer_motion(struct libinput_device *libinput_device,
> struct libinput_event_pointer *pointer_event)
> {
> @@ -97,9 +97,11 @@ handle_pointer_motion(struct libinput_device *libinput_device,
> notify_motion(device->seat,
> libinput_event_pointer_get_time(pointer_event),
> &event);
> +
> + return true;
> }
>
> -static void
> +static bool
> handle_pointer_motion_absolute(
> struct libinput_device *libinput_device,
> struct libinput_event_pointer *pointer_event)
> @@ -112,7 +114,7 @@ handle_pointer_motion_absolute(
> uint32_t width, height;
>
> if (!output)
> - return;
> + return false;
>
> time = libinput_event_pointer_get_time(pointer_event);
> width = device->output->current_mode->width;
> @@ -127,9 +129,11 @@ handle_pointer_motion_absolute(
>
> weston_output_transform_coordinate(device->output, x, y, &x, &y);
> notify_motion_absolute(device->seat, time, x, y);
> +
> + return true;
> }
>
> -static void
> +static bool
> handle_pointer_button(struct libinput_device *libinput_device,
> struct libinput_event_pointer *pointer_event)
> {
> @@ -145,21 +149,21 @@ handle_pointer_button(struct libinput_device *libinput_device,
> seat_button_count != 1) ||
> (button_state == LIBINPUT_BUTTON_STATE_RELEASED &&
> seat_button_count != 0))
> - return;
> + return false;
>
> notify_button(device->seat,
> libinput_event_pointer_get_time(pointer_event),
> libinput_event_pointer_get_button(pointer_event),
> libinput_event_pointer_get_button_state(pointer_event));
> + return true;
> }
>
> static double
> normalize_scroll(struct libinput_event_pointer *pointer_event,
> enum libinput_pointer_axis axis)
> {
> - static int warned;
> enum libinput_pointer_axis_source source;
> - double value;
> + double value = 0.0;
>
> source = libinput_event_pointer_get_axis_source(pointer_event);
> /* libinput < 0.8 sent wheel click events with value 10. Since 0.8
> @@ -178,48 +182,101 @@ normalize_scroll(struct libinput_event_pointer *pointer_event,
> value = libinput_event_pointer_get_axis_value(pointer_event,
> axis);
> break;
> - default:
> - value = 0;
> - if (warned < 5) {
> - weston_log("Unknown scroll source %d. Event discarded\n",
> - source);
> - warned++;
> - }
> - break;
> }
>
> return value;
> }
>
> -static void
> +static int32_t
> +get_axis_discrete(struct libinput_event_pointer *pointer_event,
> + enum libinput_pointer_axis axis)
> +{
> + enum libinput_pointer_axis_source source;
> +
> + source = libinput_event_pointer_get_axis_source(pointer_event);
> +
> + if (source != LIBINPUT_POINTER_AXIS_SOURCE_WHEEL)
> + return 0;
> +
> + return libinput_event_pointer_get_axis_value_discrete(pointer_event,
> + axis);
> +}
> +
> +static bool
> handle_pointer_axis(struct libinput_device *libinput_device,
> struct libinput_event_pointer *pointer_event)
> {
> + static int warned;
> struct evdev_device *device =
> libinput_device_get_user_data(libinput_device);
> - double value;
> + double vert, horiz;
> + int32_t vert_discrete, horiz_discrete;
> enum libinput_pointer_axis axis;
> struct weston_pointer_axis_event weston_event;
> + enum libinput_pointer_axis_source source;
> + uint32_t wl_axis_source;
> + bool has_vert, has_horiz;
> +
> + has_vert = libinput_event_pointer_has_axis(pointer_event,
> + LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
> + has_horiz = libinput_event_pointer_has_axis(pointer_event,
> + LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
> +
> + if (!has_vert && !has_horiz)
> + return false;
> +
> + source = libinput_event_pointer_get_axis_source(pointer_event);
> + switch (source) {
> + case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL:
> + wl_axis_source = WL_POINTER_AXIS_SOURCE_WHEEL;
> + break;
> + case LIBINPUT_POINTER_AXIS_SOURCE_FINGER:
> + wl_axis_source = WL_POINTER_AXIS_SOURCE_FINGER;
> + break;
> + case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS:
> + wl_axis_source = WL_POINTER_AXIS_SOURCE_CONTINUOUS;
> + break;
> + default:
> + if (warned < 5) {
> + weston_log("Unknown scroll source %d.\n", source);
> + warned++;
> + }
> + return false;
> + }
> +
> + notify_axis_source(device->seat, wl_axis_source);
> +
> + if (has_vert) {
> + axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL;
> + vert_discrete = get_axis_discrete(pointer_event, axis);
> + vert = normalize_scroll(pointer_event, axis);
>
> - axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL;
> - if (libinput_event_pointer_has_axis(pointer_event, axis)) {
> - value = normalize_scroll(pointer_event, axis);
> - weston_event.value = wl_fixed_from_double(value);
> weston_event.axis = WL_POINTER_AXIS_VERTICAL_SCROLL;
> + weston_event.value = wl_fixed_from_double(vert);
> + weston_event.discrete = vert_discrete;
> + weston_event.has_discrete = (vert_discrete != 0);
> +
> notify_axis(device->seat,
> libinput_event_pointer_get_time(pointer_event),
> &weston_event);
> }
>
> - axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL;
> - if (libinput_event_pointer_has_axis(pointer_event, axis)) {
> - value = normalize_scroll(pointer_event, axis);
> - weston_event.value = wl_fixed_from_double(value);
> + if (has_horiz) {
> + axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL;
> + horiz_discrete = get_axis_discrete(pointer_event, axis);
> + horiz = normalize_scroll(pointer_event, axis);
> +
> weston_event.axis = WL_POINTER_AXIS_HORIZONTAL_SCROLL;
> + weston_event.value = wl_fixed_from_double(horiz);
> + weston_event.discrete = horiz_discrete;
> + weston_event.has_discrete = (horiz_discrete != 0);
> +
> notify_axis(device->seat,
> libinput_event_pointer_get_time(pointer_event),
> &weston_event);
> }
> +
> + return true;
> }
>
> static void
> @@ -296,7 +353,10 @@ evdev_device_process_event(struct libinput_event *event)
> {
> struct libinput_device *libinput_device =
> libinput_event_get_device(event);
> + struct evdev_device *device =
> + libinput_device_get_user_data(libinput_device);
> int handled = 1;
> + bool need_frame = false;
>
> switch (libinput_event_get_type(event)) {
> case LIBINPUT_EVENT_KEYBOARD_KEY:
> @@ -304,21 +364,22 @@ evdev_device_process_event(struct libinput_event *event)
> libinput_event_get_keyboard_event(event));
> break;
> case LIBINPUT_EVENT_POINTER_MOTION:
> - handle_pointer_motion(libinput_device,
> + need_frame = handle_pointer_motion(libinput_device,
> libinput_event_get_pointer_event(event));
> break;
> case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
> - handle_pointer_motion_absolute(
> - libinput_device,
> - libinput_event_get_pointer_event(event));
> + need_frame = handle_pointer_motion_absolute(
> + libinput_device,
> + libinput_event_get_pointer_event(event));
> break;
> case LIBINPUT_EVENT_POINTER_BUTTON:
> - handle_pointer_button(libinput_device,
> + need_frame = handle_pointer_button(libinput_device,
> libinput_event_get_pointer_event(event));
> break;
> case LIBINPUT_EVENT_POINTER_AXIS:
> - handle_pointer_axis(libinput_device,
> - libinput_event_get_pointer_event(event));
> + need_frame = handle_pointer_axis(
> + libinput_device,
> + libinput_event_get_pointer_event(event));
> break;
> case LIBINPUT_EVENT_TOUCH_DOWN:
> handle_touch_down(libinput_device,
> @@ -342,6 +403,9 @@ evdev_device_process_event(struct libinput_event *event)
> libinput_event_get_type(event));
> }
>
> + if (need_frame)
> + notify_pointer_frame(device->seat);
> +
> return handled;
> }
>
> diff --git a/src/screen-share.c b/src/screen-share.c
> index ab649e3..9b5154b 100644
> --- a/src/screen-share.c
> +++ b/src/screen-share.c
> @@ -143,6 +143,7 @@ ss_seat_handle_motion(void *data, struct wl_pointer *pointer,
> * always receiving the input in the same coordinates as the output. */
>
> notify_motion_absolute(&seat->base, time, x, y);
> + notify_pointer_frame(&seat->base);
> }
>
> static void
> @@ -153,6 +154,7 @@ ss_seat_handle_button(void *data, struct wl_pointer *pointer,
> struct ss_seat *seat = data;
>
> notify_button(&seat->base, time, button, state);
> + notify_pointer_frame(&seat->base);
> }
>
> static void
> @@ -164,8 +166,10 @@ ss_seat_handle_axis(void *data, struct wl_pointer *pointer,
>
> weston_event.axis = axis;
> weston_event.value = value;
> + weston_event.has_discrete = false;
>
> notify_axis(&seat->base, time, &weston_event);
> + notify_pointer_frame(&seat->base);
> }
>
> static const struct wl_pointer_listener ss_seat_pointer_listener = {
> diff --git a/tests/weston-test-client-helper.c b/tests/weston-test-client-helper.c
> index 16786d9..97c4395 100644
> --- a/tests/weston-test-client-helper.c
> +++ b/tests/weston-test-client-helper.c
> @@ -197,12 +197,44 @@ pointer_handle_axis(void *data, struct wl_pointer *wl_pointer,
> axis, wl_fixed_to_double(value));
> }
>
> +static void
> +pointer_handle_frame(void *data, struct wl_pointer *wl_pointer)
> +{
> + fprintf(stderr, "test-client: got pointer frame\n");
> +}
> +
> +static void
> +pointer_handle_axis_source(void *data, struct wl_pointer *wl_pointer,
> + uint32_t source)
> +{
> + fprintf(stderr, "test-client: got pointer axis source %u\n", source);
> +}
> +
> +static void
> +pointer_handle_axis_stop(void *data, struct wl_pointer *wl_pointer,
> + uint32_t time, uint32_t axis)
> +{
> + fprintf(stderr, "test-client: got pointer axis stop\n");
> +}
> +
> +static void
> +pointer_handle_axis_discrete(void *data, struct wl_pointer *wl_pointer,
> + uint32_t axis, int32_t value)
> +{
> + fprintf(stderr, "test-client: got pointer axis discrete %u %d\n",
> + axis, value);
> +}
> +
> static const struct wl_pointer_listener pointer_listener = {
> pointer_handle_enter,
> pointer_handle_leave,
> pointer_handle_motion,
> pointer_handle_button,
> pointer_handle_axis,
> + pointer_handle_frame,
> + pointer_handle_axis_source,
> + pointer_handle_axis_stop,
> + pointer_handle_axis_discrete,
> };
>
> static void
> --
> 2.5.0
>
More information about the wayland-devel
mailing list