On Mon, Jan 18, 2016 at 04:38:22PM +1000, Peter Hutterer wrote: > Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net>
Re-adding my RB to this and v4 of 1/2. Eventually I think it'd be good to introduce a weston_pointer_event that doesn't make it necessary to emit the unnecessary (though harmless) wl_pointer.frame events that we now emit for example when a notify_motion ended up being constrained and not result in a motion event. Though I think this is good enough for now. Jonas > --- > 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 > _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel