[PATCH weston] Support axis source, axis discreet, axis frame and axis stop events

Derek Foreman derekf at osg.samsung.com
Thu Nov 5 10:57:57 PST 2015


On 15/10/15 09:39 PM, Peter Hutterer wrote:
> Signed-off-by: Peter Hutterer <peter.hutterer at 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
> 



More information about the wayland-devel mailing list