On 15/10/15 09:39 PM, Peter Hutterer wrote: > Signed-off-by: Peter Hutterer <peter.hutte...@who-t.net> > --- > The client-side is the simplest implementation here, and I went the easy > route since most clients won't care to register a multitude of handlers for > axis events. > > The eventdemo client merely prints the events, it doesn't accumulate them as > they should be. That'd be the job of a slightly more sophisticated toolkit. > > Possibly contentious: there's no notify_axis_stop(), it's folded into > notify_axis(). Easy fix if needed. > > Also, I recommend not merging this one until we have a test implementation > in mutter + GTK to make sure the protocol is sane enough to use from complex > clients. > > clients/eventdemo.c | 55 ++++++++++++++++++++++++++++- > clients/window.c | 91 > +++++++++++++++++++++++++++++++++++++++++++++++- > clients/window.h | 28 +++++++++++++++ > src/compositor-wayland.c | 39 +++++++++++++++++++++ > src/compositor-x11.c | 16 ++++++--- > src/compositor.h | 10 ++++++ > src/input.c | 74 ++++++++++++++++++++++++++++++++++----- > src/libinput-device.c | 63 +++++++++++++++++++++++++++++++-- > 8 files changed, 360 insertions(+), 16 deletions(-) > > diff --git a/clients/eventdemo.c b/clients/eventdemo.c > index bdad6fd..f520233 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 > +axis_frame_handler(struct widget *widget, struct input *input, void *data) > +{ > + printf("axis 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, > + int32_t discrete, void *data) > +{ > + printf("axis discrete value: %d\n", discrete); > +} > + > /** > * \brief CALLBACK function, Waylands informs about pointer motion > * \param widget widget > @@ -348,7 +396,12 @@ eventdemo_create(struct display *d) > widget_set_motion_handler(e->widget, motion_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_frame_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 6d3e944..121037b 100644 > --- a/clients/window.c > +++ b/clients/window.c > @@ -288,6 +288,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_axis_frame_handler_t axis_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; > @@ -1935,6 +1939,21 @@ widget_set_axis_handler(struct widget *widget, > widget->axis_handler = handler; > } > > +void > +widget_set_axis_handlers(struct widget *widget, > + widget_axis_handler_t axis_handler, > + widget_axis_frame_handler_t axis_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) > +{ > + widget->axis_handler = axis_handler; > + widget->axis_frame_handler = axis_frame_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); > > @@ -2816,12 +2835,82 @@ pointer_handle_axis(void *data, struct wl_pointer > *pointer, > widget->user_data); > } > > +static void > +pointer_handle_axis_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->axis_frame_handler) > + (*widget->axis_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, > + 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, > + 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_axis_frame, > + pointer_handle_axis_source, > + pointer_handle_axis_stop, > + pointer_handle_axis_discrete, > }; > > static void > @@ -5225,7 +5314,7 @@ display_add_input(struct display *d, uint32_t id) > input = xzalloc(sizeof *input); > input->display = d; > input->seat = wl_registry_bind(d->registry, id, &wl_seat_interface, > - MIN(d->seat_version, 4)); > + MIN(d->seat_version, 5)); > input->touch_focus = NULL; > input->pointer_focus = NULL; > input->keyboard_focus = NULL; > diff --git a/clients/window.h b/clients/window.h > index b61a62a..c52ed6b 100644 > --- a/clients/window.h > +++ b/clients/window.h > @@ -267,6 +267,26 @@ typedef void (*widget_axis_handler_t)(struct widget > *widget, > wl_fixed_t value, > void *data); > > +typedef void (*widget_axis_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, > + int32_t discrete, > + void *data); > + > struct window * > window_create(struct display *display); > struct window * > @@ -520,6 +540,14 @@ void > widget_set_axis_handler(struct widget *widget, > widget_axis_handler_t handler); > void > +widget_set_axis_handlers(struct widget *widget, > + widget_axis_handler_t axis_handler, > + widget_axis_frame_handler_t axis_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 > widget_schedule_redraw(struct widget *widget); > void > widget_set_use_cairo(struct widget *widget, int use_cairo); > diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c > index 7b11ae4..d3bbcf8 100644 > --- a/src/compositor-wayland.c > +++ b/src/compositor-wayland.c > @@ -1429,12 +1429,51 @@ input_handle_axis(void *data, struct wl_pointer > *pointer, > notify_axis(&input->base, time, axis, value); > } > > +static void > +input_handle_axis_frame(void *data, struct wl_pointer *pointer) > +{ > + struct wayland_input *input = data; > + > + notify_axis_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; > + > + notify_axis(&input->base, time, axis, 0); > +} > + > +static void > +input_handle_axis_discrete(void *data, struct wl_pointer *pointer, > + int32_t discrete) > +{ > + struct wayland_input *input = data; > + > + notify_axis_discrete(&input->base, discrete); > +} > + > static const struct wl_pointer_listener pointer_listener = { > input_handle_pointer_enter, > input_handle_pointer_leave, > input_handle_motion, > input_handle_button, > input_handle_axis, > + input_handle_axis_frame, > + input_handle_axis_source, > + input_handle_axis_stop, > + input_handle_axis_discrete, > }; > > static void > diff --git a/src/compositor-x11.c b/src/compositor-x11.c > index 9a23996..4b5499d 100644 > --- a/src/compositor-x11.c > +++ b/src/compositor-x11.c > @@ -1082,32 +1082,40 @@ x11_backend_deliver_button_event(struct x11_backend > *b, > case 4: > /* Axis are measured in pixels, but the xcb events are discrete > * steps. Therefore move the axis by some pixels every step. */ > - if (state) > + if (state) {
I think notify_axis_discrete() needs an update to the latest version of the proposed protocol spec... > + notify_axis_discrete(&b->core_seat, -1); > notify_axis(&b->core_seat, > weston_compositor_get_time(), > WL_POINTER_AXIS_VERTICAL_SCROLL, > -DEFAULT_AXIS_STEP_DISTANCE); > + } > return; > case 5: > - if (state) > + if (state) { > + notify_axis_discrete(&b->core_seat, 1); > notify_axis(&b->core_seat, > weston_compositor_get_time(), > WL_POINTER_AXIS_VERTICAL_SCROLL, > DEFAULT_AXIS_STEP_DISTANCE); > + } > return; > case 6: > - if (state) > + if (state) { > + notify_axis_discrete(&b->core_seat, -1); > notify_axis(&b->core_seat, > weston_compositor_get_time(), > WL_POINTER_AXIS_HORIZONTAL_SCROLL, > -DEFAULT_AXIS_STEP_DISTANCE); > + } > return; > case 7: > - if (state) > + if (state) { > + notify_axis_discrete(&b->core_seat, 1); > notify_axis(&b->core_seat, > weston_compositor_get_time(), > WL_POINTER_AXIS_HORIZONTAL_SCROLL, > DEFAULT_AXIS_STEP_DISTANCE); > + } > return; > default: > button = button_event->detail + BTN_SIDE - 8; > diff --git a/src/compositor.h b/src/compositor.h > index 2e2a185..1e518e1 100644 > --- a/src/compositor.h > +++ b/src/compositor.h > @@ -1075,6 +1075,16 @@ notify_button(struct weston_seat *seat, uint32_t time, > int32_t button, > void > notify_axis(struct weston_seat *seat, uint32_t time, uint32_t axis, > wl_fixed_t value); > + > +void > +notify_axis_discrete(struct weston_seat *seat, int32_t discrete); > + > +void > +notify_axis_source(struct weston_seat *seat, uint32_t source); > + > +void > +notify_axis_frame(struct weston_seat *seat); > + > void > notify_key(struct weston_seat *seat, uint32_t time, uint32_t key, > enum wl_keyboard_key_state state, > diff --git a/src/input.c b/src/input.c > index 500c39a..4d7ac2b 100644 > --- a/src/input.c > +++ b/src/input.c > @@ -1089,17 +1089,75 @@ notify_axis(struct weston_seat *seat, uint32_t time, > uint32_t axis, > > weston_compositor_wake(compositor); > > - if (!value) > - return; > - > if (weston_compositor_run_axis_binding(compositor, pointer, > time, axis, value)) > return; > > resource_list = &pointer->focus_resource_list; > - wl_resource_for_each(resource, resource_list) > - wl_pointer_send_axis(resource, time, axis, > - value); > + wl_resource_for_each(resource, resource_list) { > + if (value) > + wl_pointer_send_axis(resource, time, axis, value); > + else if (wl_resource_get_version(resource) >= > + WL_POINTER_AXIS_STOP_SINCE_VERSION) > + wl_pointer_send_axis_stop(resource, time, axis); > + } > +} > + > +WL_EXPORT void > +notify_axis_discrete(struct weston_seat *seat, int32_t discrete) > +{ > + struct weston_compositor *compositor = seat->compositor; > + struct weston_pointer *pointer = weston_seat_get_pointer(seat); > + struct wl_resource *resource; > + struct wl_list *resource_list; > + > + weston_compositor_wake(compositor); > + > + resource_list = &pointer->focus_resource_list; > + wl_resource_for_each(resource, resource_list) { > + if (wl_resource_get_version(resource) >= > + WL_POINTER_AXIS_DISCRETE_SINCE_VERSION) { > + wl_pointer_send_axis_discrete(resource, discrete); > + } > + } > +} > + > +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); > + struct wl_resource *resource; > + struct wl_list *resource_list; > + > + weston_compositor_wake(compositor); > + > + resource_list = &pointer->focus_resource_list; > + 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 > +notify_axis_frame(struct weston_seat *seat) > +{ > + struct weston_compositor *compositor = seat->compositor; > + struct weston_pointer *pointer = weston_seat_get_pointer(seat); > + struct wl_resource *resource; > + struct wl_list *resource_list; > + > + weston_compositor_wake(compositor); > + > + resource_list = &pointer->focus_resource_list; > + wl_resource_for_each(resource, resource_list) { > + if (wl_resource_get_version(resource) >= > + WL_POINTER_AXIS_FRAME_SINCE_VERSION) { > + wl_pointer_send_axis_frame(resource); > + } > + } > } > > WL_EXPORT int > @@ -1958,7 +2016,7 @@ bind_seat(struct wl_client *client, void *data, > uint32_t version, uint32_t id) > enum wl_seat_capability caps = 0; > > resource = wl_resource_create(client, > - &wl_seat_interface, MIN(version, 4), id); > + &wl_seat_interface, MIN(version, 5), id); > wl_list_insert(&seat->base_resource_list, > wl_resource_get_link(resource)); > wl_resource_set_implementation(resource, &seat_interface, data, > unbind_resource); > @@ -2361,7 +2419,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 2cbfb88..f7f2eef 100644 > --- a/src/libinput-device.c > +++ b/src/libinput-device.c > @@ -161,6 +161,7 @@ normalize_scroll(struct libinput_event_pointer > *pointer_event, > double value; > > source = libinput_event_pointer_get_axis_source(pointer_event); > + I guess this hunk's superfluous, but I don't care that much. :) > /* libinput < 0.8 sent wheel click events with value 10. Since 0.8 > the value is the angle of the click in degrees. To keep > backwards-compat with existing clients, we just send multiples of > @@ -180,8 +181,7 @@ normalize_scroll(struct libinput_event_pointer > *pointer_event, > default: > value = 0; > if (warned < 5) { > - weston_log("Unknown scroll source %d. Event > discarded\n", > - source); > + weston_log("Unknown scroll source %d.\n", source); Do we no longer discard the event? Derek > warned++; > } > break; > @@ -190,6 +190,23 @@ normalize_scroll(struct libinput_event_pointer > *pointer_event, > return value; > } > > +static bool > +fetch_axis_discrete(struct libinput_event_pointer *pointer_event, > + enum libinput_pointer_axis axis, > + int32_t *discrete) > +{ > + enum libinput_pointer_axis_source source; > + > + source = libinput_event_pointer_get_axis_source(pointer_event); > + > + if (source != LIBINPUT_POINTER_AXIS_SOURCE_WHEEL) > + return false; > + > + *discrete = libinput_event_pointer_get_axis_value_discrete( > + pointer_event, axis); > + return true; > +} > + > static void > handle_pointer_axis(struct libinput_device *libinput_device, > struct libinput_event_pointer *pointer_event) > @@ -197,10 +214,46 @@ handle_pointer_axis(struct libinput_device > *libinput_device, > struct evdev_device *device = > libinput_device_get_user_data(libinput_device); > double value; > + int32_t value_discrete; > enum libinput_pointer_axis axis; > + enum libinput_pointer_axis_source source; > + uint32_t wl_axis_source; > + bool need_axis_source_event = true; > + 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; > + > + 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: > + need_axis_source_event = false; > + break; > + } > + > + if (need_axis_source_event) > + notify_axis_source(device->seat, wl_axis_source); > > axis = LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL; > if (libinput_event_pointer_has_axis(pointer_event, axis)) { > + if (fetch_axis_discrete(pointer_event, axis, > + &value_discrete)) > + notify_axis_discrete(device->seat, value_discrete); > + > value = normalize_scroll(pointer_event, axis); > notify_axis(device->seat, > libinput_event_pointer_get_time(pointer_event), > @@ -210,12 +263,18 @@ handle_pointer_axis(struct libinput_device > *libinput_device, > > axis = LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL; > if (libinput_event_pointer_has_axis(pointer_event, axis)) { > + if (fetch_axis_discrete(pointer_event, axis, > + &value_discrete)) > + notify_axis_discrete(device->seat, value_discrete); > + > value = normalize_scroll(pointer_event, axis); > notify_axis(device->seat, > libinput_event_pointer_get_time(pointer_event), > WL_POINTER_AXIS_HORIZONTAL_SCROLL, > wl_fixed_from_double(value)); > } > + > + notify_axis_frame(device->seat); > } > > static void > _______________________________________________ wayland-devel mailing list wayland-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/wayland-devel