[PATCH v3 weston 2/2] Support axis source, axis discrete, frame and axis stop events

Peter Hutterer peter.hutterer at who-t.net
Sun Jan 17 20:54:31 PST 2016


On Sun, Jan 17, 2016 at 05:59:50PM +0800, Jonas Ã…dahl wrote:
> On Tue, Dec 08, 2015 at 11:15:01AM +1000, Peter Hutterer wrote:
> > Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
> 
> Took another look at this patch. I noticed a few things.
> 
> First, it doesn't build when screen-share and the RDP backend is
> enabled, because of the API changes in the first patch.
> 
> The other thing is that if weston runs on top of a compositor that
> doesn't support the .frame event, it will fail to implement support on
> its own. In other words, if compositor-wayland runs on an older wl_seat,
> it needs to emit wl_pointer.frame events by itself. The same applies to
> screen-share. The RDP backend also wasn't updated to emit the new .frame
> event.

sorry about that, I'll send the missing pieces asap. However: screen-share
only registers seat version 1, which means it will never get frame events
anyway. Fixing that is a larger issue that I'd like to keep out of
the current patchset.

Cheers,
   Peter

> > ---
> > Changes to v2: 
> > - use the new weston axis event struct, client-side is still a per-event
> >   handler (could be done at some later point)
> > - couple of minor improvements to extracting the information out of libinput
> > 
> >  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-wayland.c          |  66 ++++++++++++++++++++
> >  src/compositor-x11.c              |  13 ++++
> >  src/compositor.h                  |  16 +++++
> >  src/data-device.c                 |  12 ++++
> >  src/input.c                       |  93 ++++++++++++++++++++++++---
> >  src/libinput-device.c             | 128 ++++++++++++++++++++++++++++----------
> >  tests/weston-test-client-helper.c |  32 ++++++++++
> >  13 files changed, 564 insertions(+), 41 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 8d168ea..14853bf 100644
> > --- a/desktop-shell/shell.c
> > +++ b/desktop-shell/shell.c
> > @@ -1598,6 +1598,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;
> > @@ -1681,6 +1692,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,
> >  };
> >  
> > @@ -1845,6 +1858,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,
> >  };
> >  
> > @@ -2010,6 +2025,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,
> >  };
> >  
> > @@ -3208,6 +3225,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);
> > @@ -3218,6 +3247,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,
> >  };
> >  
> > @@ -4921,6 +4952,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 354fa4d..15e4bda 100644
> > --- a/ivi-shell/hmi-controller.c
> > +++ b/ivi-shell/hmi-controller.c
> > @@ -1331,6 +1331,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};
> > @@ -1477,6 +1490,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-wayland.c b/src/compositor-wayland.c
> > index f94d166..9ee74c6 100644
> > --- a/src/compositor-wayland.c
> > +++ b/src/compositor-wayland.c
> > @@ -181,6 +181,8 @@ struct wayland_input {
> >  
> >  	struct wayland_output *output;
> >  	struct wayland_output *keyboard_focus;
> > +
> > +	struct weston_pointer_axis_event vert, horiz;
> >  };
> >  
> >  struct gl_renderer_interface *gl_renderer;
> > @@ -1432,15 +1434,76 @@ 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);
> >  }
> >  
> > +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 = {
> >  	input_handle_pointer_enter,
> >  	input_handle_pointer_leave,
> >  	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
> > @@ -1680,6 +1743,9 @@ display_add_seat(struct wayland_backend *b, uint32_t id, uint32_t version)
> >  
> >  	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..44ac078 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;
> > @@ -1189,6 +1199,7 @@ x11_backend_deliver_enter_event(struct x11_backend *b,
> >  					   wl_fixed_from_int(enter_notify->event_y), &x, &y);
> >  
> >  	notify_pointer_focus(&b->core_seat, &output->base, x, y);
> > +	notify_pointer_frame(&b->core_seat);
> >  
> >  	b->prev_x = x;
> >  	b->prev_y = y;
> > @@ -1342,6 +1353,7 @@ x11_backend_handle_event(int fd, uint32_t mask, void *data)
> >  
> >  		case XCB_ENTER_NOTIFY:
> >  			x11_backend_deliver_enter_event(b, event);
> > +			notify_pointer_frame(&b->core_seat);
> >  			break;
> >  
> >  		case XCB_LEAVE_NOTIFY:
> > @@ -1351,6 +1363,7 @@ x11_backend_handle_event(int fd, uint32_t mask, void *data)
> >  			if (!b->has_xkb)
> >  				update_xkb_state_from_core(b, enter_notify->state);
> >  			notify_pointer_focus(&b->core_seat, NULL, 0, 0);
> > +			notify_pointer_frame(&b->core_seat);
> >  			break;
> >  
> >  		case XCB_CLIENT_MESSAGE:
> > diff --git a/src/compositor.h b/src/compositor.h
> > index bf38784..c9e61a5 100644
> > --- a/src/compositor.h
> > +++ b/src/compositor.h
> > @@ -256,6 +256,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;
> > @@ -268,6 +270,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);
> >  };
> >  
> > @@ -406,6 +410,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 9bb4472..02a9fa7 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 b87c51c..de0fba1 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)
> > @@ -1970,6 +2048,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);
> >  	}
> >  }
> >  
> > @@ -2548,7 +2627,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/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 at lists.freedesktop.org
> > http://lists.freedesktop.org/mailman/listinfo/wayland-devel


More information about the wayland-devel mailing list