[v3,weston] Introduce wl_relative_pointer interface

Submitted by Jonas Ådahl on June 26, 2015, 4:38 a.m.

Details

Message ID 1435293482-20979-8-git-send-email-jadahl@gmail.com
State Superseded
Delegated to: Daniel Stone
Headers show

Not browsing as part of any series.

Commit Message

Jonas Ådahl June 26, 2015, 4:38 a.m.
A wl_relative_pointer object is an extension to the wl_pointer interface
only used for emitting relative pointer events. It will only emit events
when the parent pointer has focus.

To get a relative pointer object, use the get_relative_pointer request
of the global wl_relative_pointer_manager object. When stabilizing it
might make more sense to just add it to wl_seat instead of having a
single use global interface.

All interface names are currently prefixed with underscore in order to
avoid any future conflicts with stable protocol.

Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
---

Changes since v2:

 * Updated copyright.
 * Updated the license text to corrected one.
 * Clarified that relative motion events are unaffected by clamping.
 * Clarified that pointer acceleration behaviour is device specific.
 * Clarified that the order of relative_motion and motion is not
   guaranteed.
 * Explained that button events etc are to be fetched from the
   corresponding wl_pointer object.
 * Clarified that relative motion events are in x/y coordinate space.
 * Added an 'unstable protocol' warning explaining compatibility etc.


 Makefile.am                   |   7 +-
 protocol/relative-pointer.xml | 127 ++++++++++++++++++++++++++++
 src/compositor.c              |   3 +
 src/compositor.h              |   5 ++
 src/input.c                   | 186 ++++++++++++++++++++++++++++++++++++++----
 5 files changed, 309 insertions(+), 19 deletions(-)
 create mode 100644 protocol/relative-pointer.xml

Patch hide | download patch | download mbox

diff --git a/Makefile.am b/Makefile.am
index 0a30cb4..70c436f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -105,7 +105,9 @@  nodist_weston_SOURCES =					\
 	protocol/presentation_timing-protocol.c		\
 	protocol/presentation_timing-server-protocol.h	\
 	protocol/scaler-protocol.c			\
-	protocol/scaler-server-protocol.h
+	protocol/scaler-server-protocol.h		\
+	protocol/relative-pointer-protocol.c		\
+	protocol/relative-pointer-server-protocol.h
 
 BUILT_SOURCES += $(nodist_weston_SOURCES)
 
@@ -1183,7 +1185,8 @@  EXTRA_DIST +=					\
 	protocol/presentation_timing.xml	\
 	protocol/scaler.xml			\
 	protocol/ivi-application.xml		\
-	protocol/ivi-hmi-controller.xml
+	protocol/ivi-hmi-controller.xml		\
+	protocol/relative-pointer.xml
 
 #
 # manual test modules in tests subdirectory
diff --git a/protocol/relative-pointer.xml b/protocol/relative-pointer.xml
new file mode 100644
index 0000000..185d33b
--- /dev/null
+++ b/protocol/relative-pointer.xml
@@ -0,0 +1,127 @@ 
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="relative_pointer">
+
+  <copyright>
+    Copyright © 2014      Jonas Ådahl
+    Copyright © 2015      Red Hat Inc.
+
+    Permission is hereby granted, free of charge, to any person obtaining a
+    copy of this software and associated documentation files (the "Software"),
+    to deal in the Software without restriction, including without limitation
+    the rights to use, copy, modify, merge, publish, distribute, sublicense,
+    and/or sell copies of the Software, and to permit persons to whom the
+    Software is furnished to do so, subject to the following conditions:
+
+    The above copyright notice and this permission notice (including the next
+    paragraph) shall be included in all copies or substantial portions of the
+    Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+    DEALINGS IN THE SOFTWARE.
+  </copyright>
+
+  <interface name="_wl_relative_pointer_manager" version="1">
+    <description summary="get relative pointer objects">
+      A global interface used for getting the relative pointer object for a
+      given seat.
+
+      Warning! The protocol described in this file is experimental. Each version
+      of this protocol should be considered incompatible with any other version,
+      and a client binding to a version different to the one advertised will be
+      terminated. When the protocol is stabalized, backward compatibility is
+      guaranteed, the '_' prefix will be removed from the name and the version
+      will be reset to 1.
+    </description>
+
+    <request name="get_relative_pointer">
+      <description summary="get a relative pointer object">
+        Create a relative pointer interface given a wl_pointer object. See
+        the wl_relative_pointer interface for more details.
+      </description>
+
+      <arg name="id" type="new_id" interface="_wl_relative_pointer"/>
+      <arg name="pointer" type="object" interface="wl_pointer"/>
+    </request>
+  </interface>
+
+  <interface name="_wl_relative_pointer" version="1">
+    <description summary="relative pointer object">
+      A wl_relative_pointer object is an extension to the wl_pointer interface
+      used for emitting relative pointer events. It shares the same focus as
+      wl_pointer objects of the same seat and will only emit events when it
+      has focus.
+    </description>
+
+    <request name="release" type="destructor">
+      <description summary="release the relative pointer object"/>
+    </request>
+
+    <event name="relative_motion">
+      <description summary="relative pointer motion">
+        Relative x/y pointer motion in from the pointer of the seat associated
+        with this object.
+
+        A relative motion is in the same dimension as regular wl_pointer motion
+        events, except they do not represent an absolute position. For example,
+        moving a pointer from (x, y) to (x', y') would have the equivalent
+        relative motion (x' - x, y' - y). If a pointer motion caused the
+        absolute pointer position to be clipped by for example the edge of the
+        monitor, the relative motion is unaffected by the clipping and will
+        represent the unclipped motion.
+
+        This event also contains non-accelerated motion deltas. The
+        non-accelerated delta is, when applicable, the regular pointer motion
+        delta as it was before having applied motion acceleration
+        transformations. The compositor will have applied the same processing
+        (such as normalization) meaning the events will have roughly the same
+        magnitude as accelerated motion events.
+
+        Note that the non-accelerated delta does not represent 'raw' events as
+        they were read from some device. Pointer motion acceleration is device-
+        and configuration-specific and non-accelerated deltas and accelerated
+        deltas may have the same value on some devices.
+
+        Relative motions are not coupled to wl_pointer.motion events, and can
+        be sent in combination with such events, but also independently. There
+        may also be scenarious where wl_pointer.motion is sent, but there is no
+        relative motion. The order of an absolute and relative motion event
+        originating from the same physical motion is not guaranteed.
+
+        The motion vectors are encoded as double fixed point values.
+
+        A double fixed point value is a 64 bit data type encoded as two separate
+        signed 32 bit integers. The integral part of the value is stored in one
+        of the integers and the fractional part in the other.
+
+        If the client needs button events, it can receive them from a wl_pointer
+        object of the same seat that the wl_relative_pointer object is
+        associated with.
+      </description>
+
+      <arg name="time" type="uint"
+           summary="timestamp with millisecond granularity"/>
+      <arg name="dx_int" type="int"
+           summary="integral part of the x component of the motion vector"/>
+      <arg name="dx_frac" type="int"
+           summary="fractional part of the x component of the motion vector"/>
+      <arg name="dy_int" type="int"
+           summary="integral part of the y component of the motion vector"/>
+      <arg name="dy_frac" type="int"
+           summary="fractional part of the y component of the motion vector"/>
+      <arg name="dx_unaccel_int" type="int"
+           summary="integral part of the x component of the unaccelerated motion vector"/>
+      <arg name="dx_unaccel_frac" type="int"
+           summary="fractional part of the x component of the unaccelerated motion vector"/>
+      <arg name="dy_unaccel_int" type="int"
+           summary="integral part of the y component of the unaccelerated motion vector"/>
+      <arg name="dy_unaccel_frac" type="int"
+           summary="fractional part of the y component of the unaccelerated motion vector"/>
+    </event>
+  </interface>
+
+</protocol>
diff --git a/src/compositor.c b/src/compositor.c
index 5594d30..b462531 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -4560,6 +4560,9 @@  weston_compositor_init(struct weston_compositor *ec,
 	weston_plane_init(&ec->primary_plane, ec, 0, 0);
 	weston_compositor_stack_plane(ec, &ec->primary_plane, NULL);
 
+	if (weston_input_init(ec) != 0)
+		return -1;
+
 	s = weston_config_get_section(ec->config, "keyboard", NULL, NULL);
 	weston_config_section_get_string(s, "keymap_rules",
 					 (char **) &xkb_names.rules, NULL);
diff --git a/src/compositor.h b/src/compositor.h
index 331b758..55cc88f 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -340,7 +340,9 @@  struct weston_pointer {
 	struct weston_seat *seat;
 
 	struct wl_list resource_list;
+	struct wl_list relative_resource_list;
 	struct wl_list focus_resource_list;
+	struct wl_list relative_focus_resource_list;
 	struct weston_view *focus;
 	uint32_t focus_serial;
 	struct wl_listener focus_view_listener;
@@ -1584,6 +1586,9 @@  weston_output_mode_switch_to_native(struct weston_output *output);
 int
 noop_renderer_init(struct weston_compositor *ec);
 
+int
+weston_input_init(struct weston_compositor *compositor);
+
 struct weston_compositor *
 backend_init(struct wl_display *display, int *argc, char *argv[],
 	     struct weston_config *config);
diff --git a/src/input.c b/src/input.c
index 9131287..b48a6c9 100644
--- a/src/input.c
+++ b/src/input.c
@@ -32,7 +32,9 @@ 
 #include <limits.h>
 
 #include "../shared/os-compatibility.h"
+#include "../shared/util.h"
 #include "compositor.h"
+#include "protocol/relative-pointer-server-protocol.h"
 
 static void
 empty_region(pixman_region32_t *region)
@@ -47,6 +49,49 @@  static void unbind_resource(struct wl_resource *resource)
 }
 
 WL_EXPORT void
+weston_pointer_motion_to_abs(struct weston_pointer *pointer,
+			     struct weston_pointer_motion_event *event,
+			     wl_fixed_t *x, wl_fixed_t *y)
+{
+	if (event->mask & WESTON_POINTER_MOTION_ABS) {
+		*x = wl_fixed_from_double(event->x);
+		*y = wl_fixed_from_double(event->y);
+	} else if (event->mask & WESTON_POINTER_MOTION_REL) {
+		*x = pointer->x + wl_fixed_from_double(event->dx);
+		*y = pointer->y + wl_fixed_from_double(event->dy);
+	} else {
+		assert(!"invalid motion event");
+		*x = *y = 0;
+	}
+}
+
+static int
+weston_pointer_motion_to_rel(struct weston_pointer *pointer,
+			     struct weston_pointer_motion_event *event,
+			     double *dx, double *dy,
+			     double *dx_unaccel, double *dy_unaccel)
+{
+	if (event->mask & WESTON_POINTER_MOTION_REL &&
+	    event->mask & WESTON_POINTER_MOTION_REL_NOACCEL) {
+		*dx = event->dx;
+		*dy = event->dy;
+		*dx_unaccel = event->dx_unaccel;
+		*dy_unaccel = event->dy_unaccel;
+		return 1;
+	} else if (event->mask & WESTON_POINTER_MOTION_REL) {
+		*dx_unaccel = *dx = event->dx;
+		*dy_unaccel = *dy = event->dy;
+		return 1;
+	} else if (event->mask & WESTON_POINTER_MOTION_REL_NOACCEL) {
+		*dx_unaccel = *dx = event->dx_unaccel;
+		*dy_unaccel = *dy = event->dy_unaccel;
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+WL_EXPORT void
 weston_seat_repick(struct weston_seat *seat)
 {
 	const struct weston_pointer *pointer = seat->pointer;
@@ -162,6 +207,42 @@  default_grab_pointer_focus(struct weston_pointer_grab *grab)
 }
 
 static void
+weston_pointer_send_relative_motion(struct weston_pointer *pointer,
+				    uint32_t time,
+				    struct weston_pointer_motion_event *event)
+{
+	double dx, dy, dx_unaccel, dy_unaccel;
+	int32_t dx_int, dx_frac;
+	int32_t dy_int, dy_frac;
+	int32_t dx_unaccel_int, dx_unaccel_frac;
+	int32_t dy_unaccel_int, dy_unaccel_frac;
+	struct wl_list *resource_list;
+	struct wl_resource *resource;
+
+	if (weston_pointer_motion_to_rel(pointer, event,
+					 &dx, &dy,
+					 &dx_unaccel, &dy_unaccel)) {
+		resource_list = &pointer->relative_focus_resource_list;
+		wl_double_fixed_from_double(dx, &dx_int, &dx_frac);
+		wl_double_fixed_from_double(dy, &dy_int, &dy_frac);
+		wl_double_fixed_from_double(dx_unaccel,
+					    &dx_unaccel_int,
+					    &dx_unaccel_frac);
+		wl_double_fixed_from_double(dy_unaccel,
+					    &dy_unaccel_int,
+					    &dy_unaccel_frac);
+		wl_resource_for_each(resource, resource_list) {
+			_wl_relative_pointer_send_relative_motion(
+				resource, time,
+				dx_int, dx_frac,
+				dy_int, dy_frac,
+				dx_unaccel_int, dx_unaccel_frac,
+				dy_unaccel_int, dy_unaccel_frac);
+		}
+	}
+}
+
+static void
 default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
 			    struct weston_pointer_motion_event *event)
 {
@@ -187,6 +268,8 @@  default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
 					       pointer->sx, pointer->sy);
 		}
 	}
+
+	weston_pointer_send_relative_motion(pointer, time, event);
 }
 
 static void
@@ -503,7 +586,9 @@  weston_pointer_create(struct weston_seat *seat)
 		return NULL;
 
 	wl_list_init(&pointer->resource_list);
+	wl_list_init(&pointer->relative_resource_list);
 	wl_list_init(&pointer->focus_resource_list);
+	wl_list_init(&pointer->relative_focus_resource_list);
 	weston_pointer_set_default_grab(pointer,
 					seat->compositor->default_pointer_grab);
 	wl_list_init(&pointer->focus_resource_listener.link);
@@ -665,6 +750,7 @@  weston_pointer_set_focus(struct weston_pointer *pointer,
 	struct wl_display *display = pointer->seat->compositor->wl_display;
 	uint32_t serial;
 	struct wl_list *focus_resource_list;
+	struct wl_list *relative_focus_resource_list;
 	int refocus = 0;
 
 	if ((!pointer->focus && view) ||
@@ -674,6 +760,7 @@  weston_pointer_set_focus(struct weston_pointer *pointer,
 		refocus = 1;
 
 	focus_resource_list = &pointer->focus_resource_list;
+	relative_focus_resource_list = &pointer->relative_focus_resource_list;
 
 	if (!wl_list_empty(focus_resource_list) && refocus) {
 		serial = wl_display_next_serial(display);
@@ -683,6 +770,8 @@  weston_pointer_set_focus(struct weston_pointer *pointer,
 		}
 
 		move_resources(&pointer->resource_list, focus_resource_list);
+		move_resources(&pointer->relative_resource_list,
+			       relative_focus_resource_list);
 	}
 
 	if (find_resource_for_view(&pointer->resource_list, view) && refocus) {
@@ -700,6 +789,9 @@  weston_pointer_set_focus(struct weston_pointer *pointer,
 		move_resources_for_client(focus_resource_list,
 					  &pointer->resource_list,
 					  surface_client);
+		move_resources_for_client(relative_focus_resource_list,
+					  &pointer->relative_resource_list,
+					  surface_client);
 
 		wl_resource_for_each(resource, focus_resource_list) {
 			wl_pointer_send_enter(resource,
@@ -932,23 +1024,6 @@  weston_pointer_move_to(struct weston_pointer *pointer,
 }
 
 WL_EXPORT void
-weston_pointer_motion_to_abs(struct weston_pointer *pointer,
-			     struct weston_pointer_motion_event *event,
-			     wl_fixed_t *x, wl_fixed_t *y)
-{
-	if (event->mask & WESTON_POINTER_MOTION_ABS) {
-		*x = wl_fixed_from_double(event->x);
-		*y = wl_fixed_from_double(event->y);
-	} else if (event->mask & WESTON_POINTER_MOTION_REL) {
-		*x = pointer->x + wl_fixed_from_double(event->dx);
-		*y = pointer->y + wl_fixed_from_double(event->dy);
-	} else {
-		assert(!"invalid motion event");
-		*x = *y = 0;
-	}
-}
-
-WL_EXPORT void
 weston_pointer_move(struct weston_pointer *pointer,
 		    struct weston_pointer_motion_event *event)
 {
@@ -2008,6 +2083,72 @@  bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
 		wl_seat_send_name(resource, seat->seat_name);
 }
 
+static void
+relative_pointer_release(struct wl_client *client,
+			 struct wl_resource *resource)
+{
+	wl_resource_destroy(resource);
+}
+
+static const struct _wl_relative_pointer_interface relative_pointer_interface = {
+	relative_pointer_release
+};
+
+static void
+relative_pointer_manager_get_relative_pointer(struct wl_client *client,
+					      struct wl_resource *resource,
+					      uint32_t id,
+					      struct wl_resource *pointer_resource)
+{
+	struct weston_pointer *pointer =
+		wl_resource_get_user_data(pointer_resource);
+	struct wl_resource *cr;
+	struct weston_view *focus;
+
+	cr = wl_resource_create(client, &_wl_relative_pointer_interface,
+				wl_resource_get_version(resource), id);
+	if (cr == NULL) {
+		wl_client_post_no_memory(client);
+		return;
+	}
+
+	/* May be moved to focused list later by either
+	 * weston_pointer_set_focus or directly if this client is already
+	 * focused */
+	wl_list_insert(&pointer->relative_resource_list,
+		       wl_resource_get_link(cr));
+	wl_resource_set_implementation(cr, &relative_pointer_interface,
+				       pointer,
+				       unbind_resource);
+
+	focus = pointer->focus;
+	if (focus && focus->surface->resource &&
+	    wl_resource_get_client(focus->surface->resource) == client) {
+		wl_list_remove(wl_resource_get_link(cr));
+		wl_list_insert(&pointer->relative_focus_resource_list,
+			       wl_resource_get_link(cr));
+	}
+}
+
+static const struct _wl_relative_pointer_manager_interface relative_pointer_manager = {
+	relative_pointer_manager_get_relative_pointer,
+};
+
+static void
+bind_relative_pointer_manager(struct wl_client *client, void *data,
+			      uint32_t version, uint32_t id)
+{
+	struct weston_compositor *compositor = data;
+	struct wl_resource *resource;
+
+	resource = wl_resource_create(client,
+				      &_wl_relative_pointer_manager_interface,
+				      1, id);
+	wl_resource_set_implementation(resource, &relative_pointer_manager,
+				       compositor,
+				       NULL);
+}
+
 #ifdef ENABLE_XKBCOMMON
 int
 weston_compositor_xkb_init(struct weston_compositor *ec,
@@ -2429,3 +2570,14 @@  weston_seat_release(struct weston_seat *seat)
 
 	wl_signal_emit(&seat->destroy_signal, seat);
 }
+
+int
+weston_input_init(struct weston_compositor *compositor)
+{
+	if (!wl_global_create(compositor->wl_display,
+			      &_wl_relative_pointer_manager_interface, 1,
+			      compositor, bind_relative_pointer_manager))
+		return -1;
+
+	return 0;
+}

Comments

On Thu, Jun 25, 2015 at 9:38 PM, Jonas Ådahl <jadahl@gmail.com> wrote:

> A wl_relative_pointer object is an extension to the wl_pointer interface
> only used for emitting relative pointer events. It will only emit events
> when the parent pointer has focus.
>
> To get a relative pointer object, use the get_relative_pointer request
> of the global wl_relative_pointer_manager object. When stabilizing it
> might make more sense to just add it to wl_seat instead of having a
> single use global interface.
>

Could it be a method on wl_pointer? That would seem to make a lot more
sense.
On Fri, Jun 26, 2015 at 12:38:01PM +0800, Jonas Ådahl wrote:
> A wl_relative_pointer object is an extension to the wl_pointer interface
> only used for emitting relative pointer events. It will only emit events
> when the parent pointer has focus.
> 
> To get a relative pointer object, use the get_relative_pointer request
> of the global wl_relative_pointer_manager object. When stabilizing it
> might make more sense to just add it to wl_seat instead of having a
> single use global interface.
> 
> All interface names are currently prefixed with underscore in order to
> avoid any future conflicts with stable protocol.
> 
> Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
> ---
> 
> Changes since v2:
> 
>  * Updated copyright.
>  * Updated the license text to corrected one.
>  * Clarified that relative motion events are unaffected by clamping.
>  * Clarified that pointer acceleration behaviour is device specific.
>  * Clarified that the order of relative_motion and motion is not
>    guaranteed.
>  * Explained that button events etc are to be fetched from the
>    corresponding wl_pointer object.
>  * Clarified that relative motion events are in x/y coordinate space.
>  * Added an 'unstable protocol' warning explaining compatibility etc.
> 
> 
>  Makefile.am                   |   7 +-
>  protocol/relative-pointer.xml | 127 ++++++++++++++++++++++++++++
>  src/compositor.c              |   3 +
>  src/compositor.h              |   5 ++
>  src/input.c                   | 186 ++++++++++++++++++++++++++++++++++++++----
>  5 files changed, 309 insertions(+), 19 deletions(-)
>  create mode 100644 protocol/relative-pointer.xml
> 
> diff --git a/Makefile.am b/Makefile.am
> index 0a30cb4..70c436f 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -105,7 +105,9 @@ nodist_weston_SOURCES =					\
>  	protocol/presentation_timing-protocol.c		\
>  	protocol/presentation_timing-server-protocol.h	\
>  	protocol/scaler-protocol.c			\
> -	protocol/scaler-server-protocol.h
> +	protocol/scaler-server-protocol.h		\
> +	protocol/relative-pointer-protocol.c		\
> +	protocol/relative-pointer-server-protocol.h
>  
>  BUILT_SOURCES += $(nodist_weston_SOURCES)
>  
> @@ -1183,7 +1185,8 @@ EXTRA_DIST +=					\
>  	protocol/presentation_timing.xml	\
>  	protocol/scaler.xml			\
>  	protocol/ivi-application.xml		\
> -	protocol/ivi-hmi-controller.xml
> +	protocol/ivi-hmi-controller.xml		\
> +	protocol/relative-pointer.xml
>  
>  #
>  # manual test modules in tests subdirectory
> diff --git a/protocol/relative-pointer.xml b/protocol/relative-pointer.xml
> new file mode 100644
> index 0000000..185d33b
> --- /dev/null
> +++ b/protocol/relative-pointer.xml
> @@ -0,0 +1,127 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +<protocol name="relative_pointer">
> +
> +  <copyright>
> +    Copyright © 2014      Jonas Ådahl
> +    Copyright © 2015      Red Hat Inc.
> +
> +    Permission is hereby granted, free of charge, to any person obtaining a
> +    copy of this software and associated documentation files (the "Software"),
> +    to deal in the Software without restriction, including without limitation
> +    the rights to use, copy, modify, merge, publish, distribute, sublicense,
> +    and/or sell copies of the Software, and to permit persons to whom the
> +    Software is furnished to do so, subject to the following conditions:
> +
> +    The above copyright notice and this permission notice (including the next
> +    paragraph) shall be included in all copies or substantial portions of the
> +    Software.
> +
> +    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> +    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> +    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> +    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> +    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> +    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> +    DEALINGS IN THE SOFTWARE.
> +  </copyright>
> +
> +  <interface name="_wl_relative_pointer_manager" version="1">
> +    <description summary="get relative pointer objects">
> +      A global interface used for getting the relative pointer object for a
> +      given seat.
> +
> +      Warning! The protocol described in this file is experimental. Each version
> +      of this protocol should be considered incompatible with any other version,
> +      and a client binding to a version different to the one advertised will be
> +      terminated. When the protocol is stabalized, backward compatibility is

typo: stabilized, but I would say "once the protocol is declared stable"
anyway

Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
otherwise

Cheers,
   Peter

> +      guaranteed, the '_' prefix will be removed from the name and the version
> +      will be reset to 1.
> +    </description>
> +
> +    <request name="get_relative_pointer">
> +      <description summary="get a relative pointer object">
> +        Create a relative pointer interface given a wl_pointer object. See
> +        the wl_relative_pointer interface for more details.
> +      </description>
> +
> +      <arg name="id" type="new_id" interface="_wl_relative_pointer"/>
> +      <arg name="pointer" type="object" interface="wl_pointer"/>
> +    </request>
> +  </interface>
> +
> +  <interface name="_wl_relative_pointer" version="1">
> +    <description summary="relative pointer object">
> +      A wl_relative_pointer object is an extension to the wl_pointer interface
> +      used for emitting relative pointer events. It shares the same focus as
> +      wl_pointer objects of the same seat and will only emit events when it
> +      has focus.
> +    </description>
> +
> +    <request name="release" type="destructor">
> +      <description summary="release the relative pointer object"/>
> +    </request>
> +
> +    <event name="relative_motion">
> +      <description summary="relative pointer motion">
> +        Relative x/y pointer motion in from the pointer of the seat associated
> +        with this object.
> +
> +        A relative motion is in the same dimension as regular wl_pointer motion
> +        events, except they do not represent an absolute position. For example,
> +        moving a pointer from (x, y) to (x', y') would have the equivalent
> +        relative motion (x' - x, y' - y). If a pointer motion caused the
> +        absolute pointer position to be clipped by for example the edge of the
> +        monitor, the relative motion is unaffected by the clipping and will
> +        represent the unclipped motion.
> +
> +        This event also contains non-accelerated motion deltas. The
> +        non-accelerated delta is, when applicable, the regular pointer motion
> +        delta as it was before having applied motion acceleration
> +        transformations. The compositor will have applied the same processing
> +        (such as normalization) meaning the events will have roughly the same
> +        magnitude as accelerated motion events.
> +
> +        Note that the non-accelerated delta does not represent 'raw' events as
> +        they were read from some device. Pointer motion acceleration is device-
> +        and configuration-specific and non-accelerated deltas and accelerated
> +        deltas may have the same value on some devices.
> +
> +        Relative motions are not coupled to wl_pointer.motion events, and can
> +        be sent in combination with such events, but also independently. There
> +        may also be scenarious where wl_pointer.motion is sent, but there is no
> +        relative motion. The order of an absolute and relative motion event
> +        originating from the same physical motion is not guaranteed.
> +
> +        The motion vectors are encoded as double fixed point values.
> +
> +        A double fixed point value is a 64 bit data type encoded as two separate
> +        signed 32 bit integers. The integral part of the value is stored in one
> +        of the integers and the fractional part in the other.
> +
> +        If the client needs button events, it can receive them from a wl_pointer
> +        object of the same seat that the wl_relative_pointer object is
> +        associated with.
> +      </description>
> +
> +      <arg name="time" type="uint"
> +           summary="timestamp with millisecond granularity"/>
> +      <arg name="dx_int" type="int"
> +           summary="integral part of the x component of the motion vector"/>
> +      <arg name="dx_frac" type="int"
> +           summary="fractional part of the x component of the motion vector"/>
> +      <arg name="dy_int" type="int"
> +           summary="integral part of the y component of the motion vector"/>
> +      <arg name="dy_frac" type="int"
> +           summary="fractional part of the y component of the motion vector"/>
> +      <arg name="dx_unaccel_int" type="int"
> +           summary="integral part of the x component of the unaccelerated motion vector"/>
> +      <arg name="dx_unaccel_frac" type="int"
> +           summary="fractional part of the x component of the unaccelerated motion vector"/>
> +      <arg name="dy_unaccel_int" type="int"
> +           summary="integral part of the y component of the unaccelerated motion vector"/>
> +      <arg name="dy_unaccel_frac" type="int"
> +           summary="fractional part of the y component of the unaccelerated motion vector"/>
> +    </event>
> +  </interface>
> +
> +</protocol>
> diff --git a/src/compositor.c b/src/compositor.c
> index 5594d30..b462531 100644
> --- a/src/compositor.c
> +++ b/src/compositor.c
> @@ -4560,6 +4560,9 @@ weston_compositor_init(struct weston_compositor *ec,
>  	weston_plane_init(&ec->primary_plane, ec, 0, 0);
>  	weston_compositor_stack_plane(ec, &ec->primary_plane, NULL);
>  
> +	if (weston_input_init(ec) != 0)
> +		return -1;
> +
>  	s = weston_config_get_section(ec->config, "keyboard", NULL, NULL);
>  	weston_config_section_get_string(s, "keymap_rules",
>  					 (char **) &xkb_names.rules, NULL);
> diff --git a/src/compositor.h b/src/compositor.h
> index 331b758..55cc88f 100644
> --- a/src/compositor.h
> +++ b/src/compositor.h
> @@ -340,7 +340,9 @@ struct weston_pointer {
>  	struct weston_seat *seat;
>  
>  	struct wl_list resource_list;
> +	struct wl_list relative_resource_list;
>  	struct wl_list focus_resource_list;
> +	struct wl_list relative_focus_resource_list;
>  	struct weston_view *focus;
>  	uint32_t focus_serial;
>  	struct wl_listener focus_view_listener;
> @@ -1584,6 +1586,9 @@ weston_output_mode_switch_to_native(struct weston_output *output);
>  int
>  noop_renderer_init(struct weston_compositor *ec);
>  
> +int
> +weston_input_init(struct weston_compositor *compositor);
> +
>  struct weston_compositor *
>  backend_init(struct wl_display *display, int *argc, char *argv[],
>  	     struct weston_config *config);
> diff --git a/src/input.c b/src/input.c
> index 9131287..b48a6c9 100644
> --- a/src/input.c
> +++ b/src/input.c
> @@ -32,7 +32,9 @@
>  #include <limits.h>
>  
>  #include "../shared/os-compatibility.h"
> +#include "../shared/util.h"
>  #include "compositor.h"
> +#include "protocol/relative-pointer-server-protocol.h"
>  
>  static void
>  empty_region(pixman_region32_t *region)
> @@ -47,6 +49,49 @@ static void unbind_resource(struct wl_resource *resource)
>  }
>  
>  WL_EXPORT void
> +weston_pointer_motion_to_abs(struct weston_pointer *pointer,
> +			     struct weston_pointer_motion_event *event,
> +			     wl_fixed_t *x, wl_fixed_t *y)
> +{
> +	if (event->mask & WESTON_POINTER_MOTION_ABS) {
> +		*x = wl_fixed_from_double(event->x);
> +		*y = wl_fixed_from_double(event->y);
> +	} else if (event->mask & WESTON_POINTER_MOTION_REL) {
> +		*x = pointer->x + wl_fixed_from_double(event->dx);
> +		*y = pointer->y + wl_fixed_from_double(event->dy);
> +	} else {
> +		assert(!"invalid motion event");
> +		*x = *y = 0;
> +	}
> +}
> +
> +static int
> +weston_pointer_motion_to_rel(struct weston_pointer *pointer,
> +			     struct weston_pointer_motion_event *event,
> +			     double *dx, double *dy,
> +			     double *dx_unaccel, double *dy_unaccel)
> +{
> +	if (event->mask & WESTON_POINTER_MOTION_REL &&
> +	    event->mask & WESTON_POINTER_MOTION_REL_NOACCEL) {
> +		*dx = event->dx;
> +		*dy = event->dy;
> +		*dx_unaccel = event->dx_unaccel;
> +		*dy_unaccel = event->dy_unaccel;
> +		return 1;
> +	} else if (event->mask & WESTON_POINTER_MOTION_REL) {
> +		*dx_unaccel = *dx = event->dx;
> +		*dy_unaccel = *dy = event->dy;
> +		return 1;
> +	} else if (event->mask & WESTON_POINTER_MOTION_REL_NOACCEL) {
> +		*dx_unaccel = *dx = event->dx_unaccel;
> +		*dy_unaccel = *dy = event->dy_unaccel;
> +		return 1;
> +	} else {
> +		return 0;
> +	}
> +}
> +
> +WL_EXPORT void
>  weston_seat_repick(struct weston_seat *seat)
>  {
>  	const struct weston_pointer *pointer = seat->pointer;
> @@ -162,6 +207,42 @@ default_grab_pointer_focus(struct weston_pointer_grab *grab)
>  }
>  
>  static void
> +weston_pointer_send_relative_motion(struct weston_pointer *pointer,
> +				    uint32_t time,
> +				    struct weston_pointer_motion_event *event)
> +{
> +	double dx, dy, dx_unaccel, dy_unaccel;
> +	int32_t dx_int, dx_frac;
> +	int32_t dy_int, dy_frac;
> +	int32_t dx_unaccel_int, dx_unaccel_frac;
> +	int32_t dy_unaccel_int, dy_unaccel_frac;
> +	struct wl_list *resource_list;
> +	struct wl_resource *resource;
> +
> +	if (weston_pointer_motion_to_rel(pointer, event,
> +					 &dx, &dy,
> +					 &dx_unaccel, &dy_unaccel)) {
> +		resource_list = &pointer->relative_focus_resource_list;
> +		wl_double_fixed_from_double(dx, &dx_int, &dx_frac);
> +		wl_double_fixed_from_double(dy, &dy_int, &dy_frac);
> +		wl_double_fixed_from_double(dx_unaccel,
> +					    &dx_unaccel_int,
> +					    &dx_unaccel_frac);
> +		wl_double_fixed_from_double(dy_unaccel,
> +					    &dy_unaccel_int,
> +					    &dy_unaccel_frac);
> +		wl_resource_for_each(resource, resource_list) {
> +			_wl_relative_pointer_send_relative_motion(
> +				resource, time,
> +				dx_int, dx_frac,
> +				dy_int, dy_frac,
> +				dx_unaccel_int, dx_unaccel_frac,
> +				dy_unaccel_int, dy_unaccel_frac);
> +		}
> +	}
> +}
> +
> +static void
>  default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
>  			    struct weston_pointer_motion_event *event)
>  {
> @@ -187,6 +268,8 @@ default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
>  					       pointer->sx, pointer->sy);
>  		}
>  	}
> +
> +	weston_pointer_send_relative_motion(pointer, time, event);
>  }
>  
>  static void
> @@ -503,7 +586,9 @@ weston_pointer_create(struct weston_seat *seat)
>  		return NULL;
>  
>  	wl_list_init(&pointer->resource_list);
> +	wl_list_init(&pointer->relative_resource_list);
>  	wl_list_init(&pointer->focus_resource_list);
> +	wl_list_init(&pointer->relative_focus_resource_list);
>  	weston_pointer_set_default_grab(pointer,
>  					seat->compositor->default_pointer_grab);
>  	wl_list_init(&pointer->focus_resource_listener.link);
> @@ -665,6 +750,7 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
>  	struct wl_display *display = pointer->seat->compositor->wl_display;
>  	uint32_t serial;
>  	struct wl_list *focus_resource_list;
> +	struct wl_list *relative_focus_resource_list;
>  	int refocus = 0;
>  
>  	if ((!pointer->focus && view) ||
> @@ -674,6 +760,7 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
>  		refocus = 1;
>  
>  	focus_resource_list = &pointer->focus_resource_list;
> +	relative_focus_resource_list = &pointer->relative_focus_resource_list;
>  
>  	if (!wl_list_empty(focus_resource_list) && refocus) {
>  		serial = wl_display_next_serial(display);
> @@ -683,6 +770,8 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
>  		}
>  
>  		move_resources(&pointer->resource_list, focus_resource_list);
> +		move_resources(&pointer->relative_resource_list,
> +			       relative_focus_resource_list);
>  	}
>  
>  	if (find_resource_for_view(&pointer->resource_list, view) && refocus) {
> @@ -700,6 +789,9 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
>  		move_resources_for_client(focus_resource_list,
>  					  &pointer->resource_list,
>  					  surface_client);
> +		move_resources_for_client(relative_focus_resource_list,
> +					  &pointer->relative_resource_list,
> +					  surface_client);
>  
>  		wl_resource_for_each(resource, focus_resource_list) {
>  			wl_pointer_send_enter(resource,
> @@ -932,23 +1024,6 @@ weston_pointer_move_to(struct weston_pointer *pointer,
>  }
>  
>  WL_EXPORT void
> -weston_pointer_motion_to_abs(struct weston_pointer *pointer,
> -			     struct weston_pointer_motion_event *event,
> -			     wl_fixed_t *x, wl_fixed_t *y)
> -{
> -	if (event->mask & WESTON_POINTER_MOTION_ABS) {
> -		*x = wl_fixed_from_double(event->x);
> -		*y = wl_fixed_from_double(event->y);
> -	} else if (event->mask & WESTON_POINTER_MOTION_REL) {
> -		*x = pointer->x + wl_fixed_from_double(event->dx);
> -		*y = pointer->y + wl_fixed_from_double(event->dy);
> -	} else {
> -		assert(!"invalid motion event");
> -		*x = *y = 0;
> -	}
> -}
> -
> -WL_EXPORT void
>  weston_pointer_move(struct weston_pointer *pointer,
>  		    struct weston_pointer_motion_event *event)
>  {
> @@ -2008,6 +2083,72 @@ bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
>  		wl_seat_send_name(resource, seat->seat_name);
>  }
>  
> +static void
> +relative_pointer_release(struct wl_client *client,
> +			 struct wl_resource *resource)
> +{
> +	wl_resource_destroy(resource);
> +}
> +
> +static const struct _wl_relative_pointer_interface relative_pointer_interface = {
> +	relative_pointer_release
> +};
> +
> +static void
> +relative_pointer_manager_get_relative_pointer(struct wl_client *client,
> +					      struct wl_resource *resource,
> +					      uint32_t id,
> +					      struct wl_resource *pointer_resource)
> +{
> +	struct weston_pointer *pointer =
> +		wl_resource_get_user_data(pointer_resource);
> +	struct wl_resource *cr;
> +	struct weston_view *focus;
> +
> +	cr = wl_resource_create(client, &_wl_relative_pointer_interface,
> +				wl_resource_get_version(resource), id);
> +	if (cr == NULL) {
> +		wl_client_post_no_memory(client);
> +		return;
> +	}
> +
> +	/* May be moved to focused list later by either
> +	 * weston_pointer_set_focus or directly if this client is already
> +	 * focused */
> +	wl_list_insert(&pointer->relative_resource_list,
> +		       wl_resource_get_link(cr));
> +	wl_resource_set_implementation(cr, &relative_pointer_interface,
> +				       pointer,
> +				       unbind_resource);
> +
> +	focus = pointer->focus;
> +	if (focus && focus->surface->resource &&
> +	    wl_resource_get_client(focus->surface->resource) == client) {
> +		wl_list_remove(wl_resource_get_link(cr));
> +		wl_list_insert(&pointer->relative_focus_resource_list,
> +			       wl_resource_get_link(cr));
> +	}
> +}
> +
> +static const struct _wl_relative_pointer_manager_interface relative_pointer_manager = {
> +	relative_pointer_manager_get_relative_pointer,
> +};
> +
> +static void
> +bind_relative_pointer_manager(struct wl_client *client, void *data,
> +			      uint32_t version, uint32_t id)
> +{
> +	struct weston_compositor *compositor = data;
> +	struct wl_resource *resource;
> +
> +	resource = wl_resource_create(client,
> +				      &_wl_relative_pointer_manager_interface,
> +				      1, id);
> +	wl_resource_set_implementation(resource, &relative_pointer_manager,
> +				       compositor,
> +				       NULL);
> +}
> +
>  #ifdef ENABLE_XKBCOMMON
>  int
>  weston_compositor_xkb_init(struct weston_compositor *ec,
> @@ -2429,3 +2570,14 @@ weston_seat_release(struct weston_seat *seat)
>  
>  	wl_signal_emit(&seat->destroy_signal, seat);
>  }
> +
> +int
> +weston_input_init(struct weston_compositor *compositor)
> +{
> +	if (!wl_global_create(compositor->wl_display,
> +			      &_wl_relative_pointer_manager_interface, 1,
> +			      compositor, bind_relative_pointer_manager))
> +		return -1;
> +
> +	return 0;
> +}
> -- 
> 2.1.4
> 
> _______________________________________________
> wayland-devel mailing list
> wayland-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
>
Hi,

Just a quick questions:

1) Is there any way to un-normalize the values?

2) What happens with >1000hz gaming mice for example which need
microsecond granularity timestamps?


On Mon, Jun 29, 2015 at 3:54 PM, Peter Hutterer
<peter.hutterer@who-t.net> wrote:
> On Fri, Jun 26, 2015 at 12:38:01PM +0800, Jonas Ådahl wrote:
>> A wl_relative_pointer object is an extension to the wl_pointer interface
>> only used for emitting relative pointer events. It will only emit events
>> when the parent pointer has focus.
>>
>> To get a relative pointer object, use the get_relative_pointer request
>> of the global wl_relative_pointer_manager object. When stabilizing it
>> might make more sense to just add it to wl_seat instead of having a
>> single use global interface.
>>
>> All interface names are currently prefixed with underscore in order to
>> avoid any future conflicts with stable protocol.
>>
>> Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
>> ---
>>
>> Changes since v2:
>>
>>  * Updated copyright.
>>  * Updated the license text to corrected one.
>>  * Clarified that relative motion events are unaffected by clamping.
>>  * Clarified that pointer acceleration behaviour is device specific.
>>  * Clarified that the order of relative_motion and motion is not
>>    guaranteed.
>>  * Explained that button events etc are to be fetched from the
>>    corresponding wl_pointer object.
>>  * Clarified that relative motion events are in x/y coordinate space.
>>  * Added an 'unstable protocol' warning explaining compatibility etc.
>>
>>
>>  Makefile.am                   |   7 +-
>>  protocol/relative-pointer.xml | 127 ++++++++++++++++++++++++++++
>>  src/compositor.c              |   3 +
>>  src/compositor.h              |   5 ++
>>  src/input.c                   | 186 ++++++++++++++++++++++++++++++++++++++----
>>  5 files changed, 309 insertions(+), 19 deletions(-)
>>  create mode 100644 protocol/relative-pointer.xml
>>
>> diff --git a/Makefile.am b/Makefile.am
>> index 0a30cb4..70c436f 100644
>> --- a/Makefile.am
>> +++ b/Makefile.am
>> @@ -105,7 +105,9 @@ nodist_weston_SOURCES =                                   \
>>       protocol/presentation_timing-protocol.c         \
>>       protocol/presentation_timing-server-protocol.h  \
>>       protocol/scaler-protocol.c                      \
>> -     protocol/scaler-server-protocol.h
>> +     protocol/scaler-server-protocol.h               \
>> +     protocol/relative-pointer-protocol.c            \
>> +     protocol/relative-pointer-server-protocol.h
>>
>>  BUILT_SOURCES += $(nodist_weston_SOURCES)
>>
>> @@ -1183,7 +1185,8 @@ EXTRA_DIST +=                                   \
>>       protocol/presentation_timing.xml        \
>>       protocol/scaler.xml                     \
>>       protocol/ivi-application.xml            \
>> -     protocol/ivi-hmi-controller.xml
>> +     protocol/ivi-hmi-controller.xml         \
>> +     protocol/relative-pointer.xml
>>
>>  #
>>  # manual test modules in tests subdirectory
>> diff --git a/protocol/relative-pointer.xml b/protocol/relative-pointer.xml
>> new file mode 100644
>> index 0000000..185d33b
>> --- /dev/null
>> +++ b/protocol/relative-pointer.xml
>> @@ -0,0 +1,127 @@
>> +<?xml version="1.0" encoding="UTF-8"?>
>> +<protocol name="relative_pointer">
>> +
>> +  <copyright>
>> +    Copyright © 2014      Jonas Ådahl
>> +    Copyright © 2015      Red Hat Inc.
>> +
>> +    Permission is hereby granted, free of charge, to any person obtaining a
>> +    copy of this software and associated documentation files (the "Software"),
>> +    to deal in the Software without restriction, including without limitation
>> +    the rights to use, copy, modify, merge, publish, distribute, sublicense,
>> +    and/or sell copies of the Software, and to permit persons to whom the
>> +    Software is furnished to do so, subject to the following conditions:
>> +
>> +    The above copyright notice and this permission notice (including the next
>> +    paragraph) shall be included in all copies or substantial portions of the
>> +    Software.
>> +
>> +    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>> +    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>> +    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
>> +    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>> +    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>> +    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
>> +    DEALINGS IN THE SOFTWARE.
>> +  </copyright>
>> +
>> +  <interface name="_wl_relative_pointer_manager" version="1">
>> +    <description summary="get relative pointer objects">
>> +      A global interface used for getting the relative pointer object for a
>> +      given seat.
>> +
>> +      Warning! The protocol described in this file is experimental. Each version
>> +      of this protocol should be considered incompatible with any other version,
>> +      and a client binding to a version different to the one advertised will be
>> +      terminated. When the protocol is stabalized, backward compatibility is
>
> typo: stabilized, but I would say "once the protocol is declared stable"
> anyway
>
> Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
> otherwise
>
> Cheers,
>    Peter
>
>> +      guaranteed, the '_' prefix will be removed from the name and the version
>> +      will be reset to 1.
>> +    </description>
>> +
>> +    <request name="get_relative_pointer">
>> +      <description summary="get a relative pointer object">
>> +        Create a relative pointer interface given a wl_pointer object. See
>> +        the wl_relative_pointer interface for more details.
>> +      </description>
>> +
>> +      <arg name="id" type="new_id" interface="_wl_relative_pointer"/>
>> +      <arg name="pointer" type="object" interface="wl_pointer"/>
>> +    </request>
>> +  </interface>
>> +
>> +  <interface name="_wl_relative_pointer" version="1">
>> +    <description summary="relative pointer object">
>> +      A wl_relative_pointer object is an extension to the wl_pointer interface
>> +      used for emitting relative pointer events. It shares the same focus as
>> +      wl_pointer objects of the same seat and will only emit events when it
>> +      has focus.
>> +    </description>
>> +
>> +    <request name="release" type="destructor">
>> +      <description summary="release the relative pointer object"/>
>> +    </request>
>> +
>> +    <event name="relative_motion">
>> +      <description summary="relative pointer motion">
>> +        Relative x/y pointer motion in from the pointer of the seat associated
>> +        with this object.
>> +
>> +        A relative motion is in the same dimension as regular wl_pointer motion
>> +        events, except they do not represent an absolute position. For example,
>> +        moving a pointer from (x, y) to (x', y') would have the equivalent
>> +        relative motion (x' - x, y' - y). If a pointer motion caused the
>> +        absolute pointer position to be clipped by for example the edge of the
>> +        monitor, the relative motion is unaffected by the clipping and will
>> +        represent the unclipped motion.
>> +
>> +        This event also contains non-accelerated motion deltas. The
>> +        non-accelerated delta is, when applicable, the regular pointer motion
>> +        delta as it was before having applied motion acceleration
>> +        transformations. The compositor will have applied the same processing
>> +        (such as normalization) meaning the events will have roughly the same
>> +        magnitude as accelerated motion events.
>> +
>> +        Note that the non-accelerated delta does not represent 'raw' events as
>> +        they were read from some device. Pointer motion acceleration is device-
>> +        and configuration-specific and non-accelerated deltas and accelerated
>> +        deltas may have the same value on some devices.
>> +
>> +        Relative motions are not coupled to wl_pointer.motion events, and can
>> +        be sent in combination with such events, but also independently. There
>> +        may also be scenarious where wl_pointer.motion is sent, but there is no
>> +        relative motion. The order of an absolute and relative motion event
>> +        originating from the same physical motion is not guaranteed.
>> +
>> +        The motion vectors are encoded as double fixed point values.
>> +
>> +        A double fixed point value is a 64 bit data type encoded as two separate
>> +        signed 32 bit integers. The integral part of the value is stored in one
>> +        of the integers and the fractional part in the other.
>> +
>> +        If the client needs button events, it can receive them from a wl_pointer
>> +        object of the same seat that the wl_relative_pointer object is
>> +        associated with.
>> +      </description>
>> +
>> +      <arg name="time" type="uint"
>> +           summary="timestamp with millisecond granularity"/>
>> +      <arg name="dx_int" type="int"
>> +           summary="integral part of the x component of the motion vector"/>
>> +      <arg name="dx_frac" type="int"
>> +           summary="fractional part of the x component of the motion vector"/>
>> +      <arg name="dy_int" type="int"
>> +           summary="integral part of the y component of the motion vector"/>
>> +      <arg name="dy_frac" type="int"
>> +           summary="fractional part of the y component of the motion vector"/>
>> +      <arg name="dx_unaccel_int" type="int"
>> +           summary="integral part of the x component of the unaccelerated motion vector"/>
>> +      <arg name="dx_unaccel_frac" type="int"
>> +           summary="fractional part of the x component of the unaccelerated motion vector"/>
>> +      <arg name="dy_unaccel_int" type="int"
>> +           summary="integral part of the y component of the unaccelerated motion vector"/>
>> +      <arg name="dy_unaccel_frac" type="int"
>> +           summary="fractional part of the y component of the unaccelerated motion vector"/>
>> +    </event>
>> +  </interface>
>> +
>> +</protocol>
>> diff --git a/src/compositor.c b/src/compositor.c
>> index 5594d30..b462531 100644
>> --- a/src/compositor.c
>> +++ b/src/compositor.c
>> @@ -4560,6 +4560,9 @@ weston_compositor_init(struct weston_compositor *ec,
>>       weston_plane_init(&ec->primary_plane, ec, 0, 0);
>>       weston_compositor_stack_plane(ec, &ec->primary_plane, NULL);
>>
>> +     if (weston_input_init(ec) != 0)
>> +             return -1;
>> +
>>       s = weston_config_get_section(ec->config, "keyboard", NULL, NULL);
>>       weston_config_section_get_string(s, "keymap_rules",
>>                                        (char **) &xkb_names.rules, NULL);
>> diff --git a/src/compositor.h b/src/compositor.h
>> index 331b758..55cc88f 100644
>> --- a/src/compositor.h
>> +++ b/src/compositor.h
>> @@ -340,7 +340,9 @@ struct weston_pointer {
>>       struct weston_seat *seat;
>>
>>       struct wl_list resource_list;
>> +     struct wl_list relative_resource_list;
>>       struct wl_list focus_resource_list;
>> +     struct wl_list relative_focus_resource_list;
>>       struct weston_view *focus;
>>       uint32_t focus_serial;
>>       struct wl_listener focus_view_listener;
>> @@ -1584,6 +1586,9 @@ weston_output_mode_switch_to_native(struct weston_output *output);
>>  int
>>  noop_renderer_init(struct weston_compositor *ec);
>>
>> +int
>> +weston_input_init(struct weston_compositor *compositor);
>> +
>>  struct weston_compositor *
>>  backend_init(struct wl_display *display, int *argc, char *argv[],
>>            struct weston_config *config);
>> diff --git a/src/input.c b/src/input.c
>> index 9131287..b48a6c9 100644
>> --- a/src/input.c
>> +++ b/src/input.c
>> @@ -32,7 +32,9 @@
>>  #include <limits.h>
>>
>>  #include "../shared/os-compatibility.h"
>> +#include "../shared/util.h"
>>  #include "compositor.h"
>> +#include "protocol/relative-pointer-server-protocol.h"
>>
>>  static void
>>  empty_region(pixman_region32_t *region)
>> @@ -47,6 +49,49 @@ static void unbind_resource(struct wl_resource *resource)
>>  }
>>
>>  WL_EXPORT void
>> +weston_pointer_motion_to_abs(struct weston_pointer *pointer,
>> +                          struct weston_pointer_motion_event *event,
>> +                          wl_fixed_t *x, wl_fixed_t *y)
>> +{
>> +     if (event->mask & WESTON_POINTER_MOTION_ABS) {
>> +             *x = wl_fixed_from_double(event->x);
>> +             *y = wl_fixed_from_double(event->y);
>> +     } else if (event->mask & WESTON_POINTER_MOTION_REL) {
>> +             *x = pointer->x + wl_fixed_from_double(event->dx);
>> +             *y = pointer->y + wl_fixed_from_double(event->dy);
>> +     } else {
>> +             assert(!"invalid motion event");
>> +             *x = *y = 0;
>> +     }
>> +}
>> +
>> +static int
>> +weston_pointer_motion_to_rel(struct weston_pointer *pointer,
>> +                          struct weston_pointer_motion_event *event,
>> +                          double *dx, double *dy,
>> +                          double *dx_unaccel, double *dy_unaccel)
>> +{
>> +     if (event->mask & WESTON_POINTER_MOTION_REL &&
>> +         event->mask & WESTON_POINTER_MOTION_REL_NOACCEL) {
>> +             *dx = event->dx;
>> +             *dy = event->dy;
>> +             *dx_unaccel = event->dx_unaccel;
>> +             *dy_unaccel = event->dy_unaccel;
>> +             return 1;
>> +     } else if (event->mask & WESTON_POINTER_MOTION_REL) {
>> +             *dx_unaccel = *dx = event->dx;
>> +             *dy_unaccel = *dy = event->dy;
>> +             return 1;
>> +     } else if (event->mask & WESTON_POINTER_MOTION_REL_NOACCEL) {
>> +             *dx_unaccel = *dx = event->dx_unaccel;
>> +             *dy_unaccel = *dy = event->dy_unaccel;
>> +             return 1;
>> +     } else {
>> +             return 0;
>> +     }
>> +}
>> +
>> +WL_EXPORT void
>>  weston_seat_repick(struct weston_seat *seat)
>>  {
>>       const struct weston_pointer *pointer = seat->pointer;
>> @@ -162,6 +207,42 @@ default_grab_pointer_focus(struct weston_pointer_grab *grab)
>>  }
>>
>>  static void
>> +weston_pointer_send_relative_motion(struct weston_pointer *pointer,
>> +                                 uint32_t time,
>> +                                 struct weston_pointer_motion_event *event)
>> +{
>> +     double dx, dy, dx_unaccel, dy_unaccel;
>> +     int32_t dx_int, dx_frac;
>> +     int32_t dy_int, dy_frac;
>> +     int32_t dx_unaccel_int, dx_unaccel_frac;
>> +     int32_t dy_unaccel_int, dy_unaccel_frac;
>> +     struct wl_list *resource_list;
>> +     struct wl_resource *resource;
>> +
>> +     if (weston_pointer_motion_to_rel(pointer, event,
>> +                                      &dx, &dy,
>> +                                      &dx_unaccel, &dy_unaccel)) {
>> +             resource_list = &pointer->relative_focus_resource_list;
>> +             wl_double_fixed_from_double(dx, &dx_int, &dx_frac);
>> +             wl_double_fixed_from_double(dy, &dy_int, &dy_frac);
>> +             wl_double_fixed_from_double(dx_unaccel,
>> +                                         &dx_unaccel_int,
>> +                                         &dx_unaccel_frac);
>> +             wl_double_fixed_from_double(dy_unaccel,
>> +                                         &dy_unaccel_int,
>> +                                         &dy_unaccel_frac);
>> +             wl_resource_for_each(resource, resource_list) {
>> +                     _wl_relative_pointer_send_relative_motion(
>> +                             resource, time,
>> +                             dx_int, dx_frac,
>> +                             dy_int, dy_frac,
>> +                             dx_unaccel_int, dx_unaccel_frac,
>> +                             dy_unaccel_int, dy_unaccel_frac);
>> +             }
>> +     }
>> +}
>> +
>> +static void
>>  default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
>>                           struct weston_pointer_motion_event *event)
>>  {
>> @@ -187,6 +268,8 @@ default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
>>                                              pointer->sx, pointer->sy);
>>               }
>>       }
>> +
>> +     weston_pointer_send_relative_motion(pointer, time, event);
>>  }
>>
>>  static void
>> @@ -503,7 +586,9 @@ weston_pointer_create(struct weston_seat *seat)
>>               return NULL;
>>
>>       wl_list_init(&pointer->resource_list);
>> +     wl_list_init(&pointer->relative_resource_list);
>>       wl_list_init(&pointer->focus_resource_list);
>> +     wl_list_init(&pointer->relative_focus_resource_list);
>>       weston_pointer_set_default_grab(pointer,
>>                                       seat->compositor->default_pointer_grab);
>>       wl_list_init(&pointer->focus_resource_listener.link);
>> @@ -665,6 +750,7 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
>>       struct wl_display *display = pointer->seat->compositor->wl_display;
>>       uint32_t serial;
>>       struct wl_list *focus_resource_list;
>> +     struct wl_list *relative_focus_resource_list;
>>       int refocus = 0;
>>
>>       if ((!pointer->focus && view) ||
>> @@ -674,6 +760,7 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
>>               refocus = 1;
>>
>>       focus_resource_list = &pointer->focus_resource_list;
>> +     relative_focus_resource_list = &pointer->relative_focus_resource_list;
>>
>>       if (!wl_list_empty(focus_resource_list) && refocus) {
>>               serial = wl_display_next_serial(display);
>> @@ -683,6 +770,8 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
>>               }
>>
>>               move_resources(&pointer->resource_list, focus_resource_list);
>> +             move_resources(&pointer->relative_resource_list,
>> +                            relative_focus_resource_list);
>>       }
>>
>>       if (find_resource_for_view(&pointer->resource_list, view) && refocus) {
>> @@ -700,6 +789,9 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
>>               move_resources_for_client(focus_resource_list,
>>                                         &pointer->resource_list,
>>                                         surface_client);
>> +             move_resources_for_client(relative_focus_resource_list,
>> +                                       &pointer->relative_resource_list,
>> +                                       surface_client);
>>
>>               wl_resource_for_each(resource, focus_resource_list) {
>>                       wl_pointer_send_enter(resource,
>> @@ -932,23 +1024,6 @@ weston_pointer_move_to(struct weston_pointer *pointer,
>>  }
>>
>>  WL_EXPORT void
>> -weston_pointer_motion_to_abs(struct weston_pointer *pointer,
>> -                          struct weston_pointer_motion_event *event,
>> -                          wl_fixed_t *x, wl_fixed_t *y)
>> -{
>> -     if (event->mask & WESTON_POINTER_MOTION_ABS) {
>> -             *x = wl_fixed_from_double(event->x);
>> -             *y = wl_fixed_from_double(event->y);
>> -     } else if (event->mask & WESTON_POINTER_MOTION_REL) {
>> -             *x = pointer->x + wl_fixed_from_double(event->dx);
>> -             *y = pointer->y + wl_fixed_from_double(event->dy);
>> -     } else {
>> -             assert(!"invalid motion event");
>> -             *x = *y = 0;
>> -     }
>> -}
>> -
>> -WL_EXPORT void
>>  weston_pointer_move(struct weston_pointer *pointer,
>>                   struct weston_pointer_motion_event *event)
>>  {
>> @@ -2008,6 +2083,72 @@ bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
>>               wl_seat_send_name(resource, seat->seat_name);
>>  }
>>
>> +static void
>> +relative_pointer_release(struct wl_client *client,
>> +                      struct wl_resource *resource)
>> +{
>> +     wl_resource_destroy(resource);
>> +}
>> +
>> +static const struct _wl_relative_pointer_interface relative_pointer_interface = {
>> +     relative_pointer_release
>> +};
>> +
>> +static void
>> +relative_pointer_manager_get_relative_pointer(struct wl_client *client,
>> +                                           struct wl_resource *resource,
>> +                                           uint32_t id,
>> +                                           struct wl_resource *pointer_resource)
>> +{
>> +     struct weston_pointer *pointer =
>> +             wl_resource_get_user_data(pointer_resource);
>> +     struct wl_resource *cr;
>> +     struct weston_view *focus;
>> +
>> +     cr = wl_resource_create(client, &_wl_relative_pointer_interface,
>> +                             wl_resource_get_version(resource), id);
>> +     if (cr == NULL) {
>> +             wl_client_post_no_memory(client);
>> +             return;
>> +     }
>> +
>> +     /* May be moved to focused list later by either
>> +      * weston_pointer_set_focus or directly if this client is already
>> +      * focused */
>> +     wl_list_insert(&pointer->relative_resource_list,
>> +                    wl_resource_get_link(cr));
>> +     wl_resource_set_implementation(cr, &relative_pointer_interface,
>> +                                    pointer,
>> +                                    unbind_resource);
>> +
>> +     focus = pointer->focus;
>> +     if (focus && focus->surface->resource &&
>> +         wl_resource_get_client(focus->surface->resource) == client) {
>> +             wl_list_remove(wl_resource_get_link(cr));
>> +             wl_list_insert(&pointer->relative_focus_resource_list,
>> +                            wl_resource_get_link(cr));
>> +     }
>> +}
>> +
>> +static const struct _wl_relative_pointer_manager_interface relative_pointer_manager = {
>> +     relative_pointer_manager_get_relative_pointer,
>> +};
>> +
>> +static void
>> +bind_relative_pointer_manager(struct wl_client *client, void *data,
>> +                           uint32_t version, uint32_t id)
>> +{
>> +     struct weston_compositor *compositor = data;
>> +     struct wl_resource *resource;
>> +
>> +     resource = wl_resource_create(client,
>> +                                   &_wl_relative_pointer_manager_interface,
>> +                                   1, id);
>> +     wl_resource_set_implementation(resource, &relative_pointer_manager,
>> +                                    compositor,
>> +                                    NULL);
>> +}
>> +
>>  #ifdef ENABLE_XKBCOMMON
>>  int
>>  weston_compositor_xkb_init(struct weston_compositor *ec,
>> @@ -2429,3 +2570,14 @@ weston_seat_release(struct weston_seat *seat)
>>
>>       wl_signal_emit(&seat->destroy_signal, seat);
>>  }
>> +
>> +int
>> +weston_input_init(struct weston_compositor *compositor)
>> +{
>> +     if (!wl_global_create(compositor->wl_display,
>> +                           &_wl_relative_pointer_manager_interface, 1,
>> +                           compositor, bind_relative_pointer_manager))
>> +             return -1;
>> +
>> +     return 0;
>> +}
>> --
>> 2.1.4
>>
>> _______________________________________________
>> wayland-devel mailing list
>> wayland-devel@lists.freedesktop.org
>> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
>>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
On Wed, Jul 15, 2015 at 08:23:09AM +0900, x414e54 wrote:
> Hi,
> 
> Just a quick questions:
> 
> 1) Is there any way to un-normalize the values?

not at this point, no. 
fwiw as of libinput 0.19 the normalization only applies to the accelerated
delta, the unaccelerated one is generally in device-specific units. Except
on touchpads, where we still normalize it to a 1000dpi mouse, we may review
that at some point. but since the normalization is "magic", you can't
unnormalize them.

> 2) What happens with >1000hz gaming mice for example which need
> microsecond granularity timestamps?

naïve question: do people notice the difference between 1000Hz and 2000Hz?

Cheers,
   Peter
 
> On Mon, Jun 29, 2015 at 3:54 PM, Peter Hutterer
> <peter.hutterer@who-t.net> wrote:
> > On Fri, Jun 26, 2015 at 12:38:01PM +0800, Jonas Ådahl wrote:
> >> A wl_relative_pointer object is an extension to the wl_pointer interface
> >> only used for emitting relative pointer events. It will only emit events
> >> when the parent pointer has focus.
> >>
> >> To get a relative pointer object, use the get_relative_pointer request
> >> of the global wl_relative_pointer_manager object. When stabilizing it
> >> might make more sense to just add it to wl_seat instead of having a
> >> single use global interface.
> >>
> >> All interface names are currently prefixed with underscore in order to
> >> avoid any future conflicts with stable protocol.
> >>
> >> Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
> >> ---
> >>
> >> Changes since v2:
> >>
> >>  * Updated copyright.
> >>  * Updated the license text to corrected one.
> >>  * Clarified that relative motion events are unaffected by clamping.
> >>  * Clarified that pointer acceleration behaviour is device specific.
> >>  * Clarified that the order of relative_motion and motion is not
> >>    guaranteed.
> >>  * Explained that button events etc are to be fetched from the
> >>    corresponding wl_pointer object.
> >>  * Clarified that relative motion events are in x/y coordinate space.
> >>  * Added an 'unstable protocol' warning explaining compatibility etc.
> >>
> >>
> >>  Makefile.am                   |   7 +-
> >>  protocol/relative-pointer.xml | 127 ++++++++++++++++++++++++++++
> >>  src/compositor.c              |   3 +
> >>  src/compositor.h              |   5 ++
> >>  src/input.c                   | 186 ++++++++++++++++++++++++++++++++++++++----
> >>  5 files changed, 309 insertions(+), 19 deletions(-)
> >>  create mode 100644 protocol/relative-pointer.xml
> >>
> >> diff --git a/Makefile.am b/Makefile.am
> >> index 0a30cb4..70c436f 100644
> >> --- a/Makefile.am
> >> +++ b/Makefile.am
> >> @@ -105,7 +105,9 @@ nodist_weston_SOURCES =                                   \
> >>       protocol/presentation_timing-protocol.c         \
> >>       protocol/presentation_timing-server-protocol.h  \
> >>       protocol/scaler-protocol.c                      \
> >> -     protocol/scaler-server-protocol.h
> >> +     protocol/scaler-server-protocol.h               \
> >> +     protocol/relative-pointer-protocol.c            \
> >> +     protocol/relative-pointer-server-protocol.h
> >>
> >>  BUILT_SOURCES += $(nodist_weston_SOURCES)
> >>
> >> @@ -1183,7 +1185,8 @@ EXTRA_DIST +=                                   \
> >>       protocol/presentation_timing.xml        \
> >>       protocol/scaler.xml                     \
> >>       protocol/ivi-application.xml            \
> >> -     protocol/ivi-hmi-controller.xml
> >> +     protocol/ivi-hmi-controller.xml         \
> >> +     protocol/relative-pointer.xml
> >>
> >>  #
> >>  # manual test modules in tests subdirectory
> >> diff --git a/protocol/relative-pointer.xml b/protocol/relative-pointer.xml
> >> new file mode 100644
> >> index 0000000..185d33b
> >> --- /dev/null
> >> +++ b/protocol/relative-pointer.xml
> >> @@ -0,0 +1,127 @@
> >> +<?xml version="1.0" encoding="UTF-8"?>
> >> +<protocol name="relative_pointer">
> >> +
> >> +  <copyright>
> >> +    Copyright © 2014      Jonas Ådahl
> >> +    Copyright © 2015      Red Hat Inc.
> >> +
> >> +    Permission is hereby granted, free of charge, to any person obtaining a
> >> +    copy of this software and associated documentation files (the "Software"),
> >> +    to deal in the Software without restriction, including without limitation
> >> +    the rights to use, copy, modify, merge, publish, distribute, sublicense,
> >> +    and/or sell copies of the Software, and to permit persons to whom the
> >> +    Software is furnished to do so, subject to the following conditions:
> >> +
> >> +    The above copyright notice and this permission notice (including the next
> >> +    paragraph) shall be included in all copies or substantial portions of the
> >> +    Software.
> >> +
> >> +    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> >> +    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> >> +    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> >> +    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> >> +    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> >> +    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> >> +    DEALINGS IN THE SOFTWARE.
> >> +  </copyright>
> >> +
> >> +  <interface name="_wl_relative_pointer_manager" version="1">
> >> +    <description summary="get relative pointer objects">
> >> +      A global interface used for getting the relative pointer object for a
> >> +      given seat.
> >> +
> >> +      Warning! The protocol described in this file is experimental. Each version
> >> +      of this protocol should be considered incompatible with any other version,
> >> +      and a client binding to a version different to the one advertised will be
> >> +      terminated. When the protocol is stabalized, backward compatibility is
> >
> > typo: stabilized, but I would say "once the protocol is declared stable"
> > anyway
> >
> > Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
> > otherwise
> >
> > Cheers,
> >    Peter
> >
> >> +      guaranteed, the '_' prefix will be removed from the name and the version
> >> +      will be reset to 1.
> >> +    </description>
> >> +
> >> +    <request name="get_relative_pointer">
> >> +      <description summary="get a relative pointer object">
> >> +        Create a relative pointer interface given a wl_pointer object. See
> >> +        the wl_relative_pointer interface for more details.
> >> +      </description>
> >> +
> >> +      <arg name="id" type="new_id" interface="_wl_relative_pointer"/>
> >> +      <arg name="pointer" type="object" interface="wl_pointer"/>
> >> +    </request>
> >> +  </interface>
> >> +
> >> +  <interface name="_wl_relative_pointer" version="1">
> >> +    <description summary="relative pointer object">
> >> +      A wl_relative_pointer object is an extension to the wl_pointer interface
> >> +      used for emitting relative pointer events. It shares the same focus as
> >> +      wl_pointer objects of the same seat and will only emit events when it
> >> +      has focus.
> >> +    </description>
> >> +
> >> +    <request name="release" type="destructor">
> >> +      <description summary="release the relative pointer object"/>
> >> +    </request>
> >> +
> >> +    <event name="relative_motion">
> >> +      <description summary="relative pointer motion">
> >> +        Relative x/y pointer motion in from the pointer of the seat associated
> >> +        with this object.
> >> +
> >> +        A relative motion is in the same dimension as regular wl_pointer motion
> >> +        events, except they do not represent an absolute position. For example,
> >> +        moving a pointer from (x, y) to (x', y') would have the equivalent
> >> +        relative motion (x' - x, y' - y). If a pointer motion caused the
> >> +        absolute pointer position to be clipped by for example the edge of the
> >> +        monitor, the relative motion is unaffected by the clipping and will
> >> +        represent the unclipped motion.
> >> +
> >> +        This event also contains non-accelerated motion deltas. The
> >> +        non-accelerated delta is, when applicable, the regular pointer motion
> >> +        delta as it was before having applied motion acceleration
> >> +        transformations. The compositor will have applied the same processing
> >> +        (such as normalization) meaning the events will have roughly the same
> >> +        magnitude as accelerated motion events.
> >> +
> >> +        Note that the non-accelerated delta does not represent 'raw' events as
> >> +        they were read from some device. Pointer motion acceleration is device-
> >> +        and configuration-specific and non-accelerated deltas and accelerated
> >> +        deltas may have the same value on some devices.
> >> +
> >> +        Relative motions are not coupled to wl_pointer.motion events, and can
> >> +        be sent in combination with such events, but also independently. There
> >> +        may also be scenarious where wl_pointer.motion is sent, but there is no
> >> +        relative motion. The order of an absolute and relative motion event
> >> +        originating from the same physical motion is not guaranteed.
> >> +
> >> +        The motion vectors are encoded as double fixed point values.
> >> +
> >> +        A double fixed point value is a 64 bit data type encoded as two separate
> >> +        signed 32 bit integers. The integral part of the value is stored in one
> >> +        of the integers and the fractional part in the other.
> >> +
> >> +        If the client needs button events, it can receive them from a wl_pointer
> >> +        object of the same seat that the wl_relative_pointer object is
> >> +        associated with.
> >> +      </description>
> >> +
> >> +      <arg name="time" type="uint"
> >> +           summary="timestamp with millisecond granularity"/>
> >> +      <arg name="dx_int" type="int"
> >> +           summary="integral part of the x component of the motion vector"/>
> >> +      <arg name="dx_frac" type="int"
> >> +           summary="fractional part of the x component of the motion vector"/>
> >> +      <arg name="dy_int" type="int"
> >> +           summary="integral part of the y component of the motion vector"/>
> >> +      <arg name="dy_frac" type="int"
> >> +           summary="fractional part of the y component of the motion vector"/>
> >> +      <arg name="dx_unaccel_int" type="int"
> >> +           summary="integral part of the x component of the unaccelerated motion vector"/>
> >> +      <arg name="dx_unaccel_frac" type="int"
> >> +           summary="fractional part of the x component of the unaccelerated motion vector"/>
> >> +      <arg name="dy_unaccel_int" type="int"
> >> +           summary="integral part of the y component of the unaccelerated motion vector"/>
> >> +      <arg name="dy_unaccel_frac" type="int"
> >> +           summary="fractional part of the y component of the unaccelerated motion vector"/>
> >> +    </event>
> >> +  </interface>
> >> +
> >> +</protocol>
> >> diff --git a/src/compositor.c b/src/compositor.c
> >> index 5594d30..b462531 100644
> >> --- a/src/compositor.c
> >> +++ b/src/compositor.c
> >> @@ -4560,6 +4560,9 @@ weston_compositor_init(struct weston_compositor *ec,
> >>       weston_plane_init(&ec->primary_plane, ec, 0, 0);
> >>       weston_compositor_stack_plane(ec, &ec->primary_plane, NULL);
> >>
> >> +     if (weston_input_init(ec) != 0)
> >> +             return -1;
> >> +
> >>       s = weston_config_get_section(ec->config, "keyboard", NULL, NULL);
> >>       weston_config_section_get_string(s, "keymap_rules",
> >>                                        (char **) &xkb_names.rules, NULL);
> >> diff --git a/src/compositor.h b/src/compositor.h
> >> index 331b758..55cc88f 100644
> >> --- a/src/compositor.h
> >> +++ b/src/compositor.h
> >> @@ -340,7 +340,9 @@ struct weston_pointer {
> >>       struct weston_seat *seat;
> >>
> >>       struct wl_list resource_list;
> >> +     struct wl_list relative_resource_list;
> >>       struct wl_list focus_resource_list;
> >> +     struct wl_list relative_focus_resource_list;
> >>       struct weston_view *focus;
> >>       uint32_t focus_serial;
> >>       struct wl_listener focus_view_listener;
> >> @@ -1584,6 +1586,9 @@ weston_output_mode_switch_to_native(struct weston_output *output);
> >>  int
> >>  noop_renderer_init(struct weston_compositor *ec);
> >>
> >> +int
> >> +weston_input_init(struct weston_compositor *compositor);
> >> +
> >>  struct weston_compositor *
> >>  backend_init(struct wl_display *display, int *argc, char *argv[],
> >>            struct weston_config *config);
> >> diff --git a/src/input.c b/src/input.c
> >> index 9131287..b48a6c9 100644
> >> --- a/src/input.c
> >> +++ b/src/input.c
> >> @@ -32,7 +32,9 @@
> >>  #include <limits.h>
> >>
> >>  #include "../shared/os-compatibility.h"
> >> +#include "../shared/util.h"
> >>  #include "compositor.h"
> >> +#include "protocol/relative-pointer-server-protocol.h"
> >>
> >>  static void
> >>  empty_region(pixman_region32_t *region)
> >> @@ -47,6 +49,49 @@ static void unbind_resource(struct wl_resource *resource)
> >>  }
> >>
> >>  WL_EXPORT void
> >> +weston_pointer_motion_to_abs(struct weston_pointer *pointer,
> >> +                          struct weston_pointer_motion_event *event,
> >> +                          wl_fixed_t *x, wl_fixed_t *y)
> >> +{
> >> +     if (event->mask & WESTON_POINTER_MOTION_ABS) {
> >> +             *x = wl_fixed_from_double(event->x);
> >> +             *y = wl_fixed_from_double(event->y);
> >> +     } else if (event->mask & WESTON_POINTER_MOTION_REL) {
> >> +             *x = pointer->x + wl_fixed_from_double(event->dx);
> >> +             *y = pointer->y + wl_fixed_from_double(event->dy);
> >> +     } else {
> >> +             assert(!"invalid motion event");
> >> +             *x = *y = 0;
> >> +     }
> >> +}
> >> +
> >> +static int
> >> +weston_pointer_motion_to_rel(struct weston_pointer *pointer,
> >> +                          struct weston_pointer_motion_event *event,
> >> +                          double *dx, double *dy,
> >> +                          double *dx_unaccel, double *dy_unaccel)
> >> +{
> >> +     if (event->mask & WESTON_POINTER_MOTION_REL &&
> >> +         event->mask & WESTON_POINTER_MOTION_REL_NOACCEL) {
> >> +             *dx = event->dx;
> >> +             *dy = event->dy;
> >> +             *dx_unaccel = event->dx_unaccel;
> >> +             *dy_unaccel = event->dy_unaccel;
> >> +             return 1;
> >> +     } else if (event->mask & WESTON_POINTER_MOTION_REL) {
> >> +             *dx_unaccel = *dx = event->dx;
> >> +             *dy_unaccel = *dy = event->dy;
> >> +             return 1;
> >> +     } else if (event->mask & WESTON_POINTER_MOTION_REL_NOACCEL) {
> >> +             *dx_unaccel = *dx = event->dx_unaccel;
> >> +             *dy_unaccel = *dy = event->dy_unaccel;
> >> +             return 1;
> >> +     } else {
> >> +             return 0;
> >> +     }
> >> +}
> >> +
> >> +WL_EXPORT void
> >>  weston_seat_repick(struct weston_seat *seat)
> >>  {
> >>       const struct weston_pointer *pointer = seat->pointer;
> >> @@ -162,6 +207,42 @@ default_grab_pointer_focus(struct weston_pointer_grab *grab)
> >>  }
> >>
> >>  static void
> >> +weston_pointer_send_relative_motion(struct weston_pointer *pointer,
> >> +                                 uint32_t time,
> >> +                                 struct weston_pointer_motion_event *event)
> >> +{
> >> +     double dx, dy, dx_unaccel, dy_unaccel;
> >> +     int32_t dx_int, dx_frac;
> >> +     int32_t dy_int, dy_frac;
> >> +     int32_t dx_unaccel_int, dx_unaccel_frac;
> >> +     int32_t dy_unaccel_int, dy_unaccel_frac;
> >> +     struct wl_list *resource_list;
> >> +     struct wl_resource *resource;
> >> +
> >> +     if (weston_pointer_motion_to_rel(pointer, event,
> >> +                                      &dx, &dy,
> >> +                                      &dx_unaccel, &dy_unaccel)) {
> >> +             resource_list = &pointer->relative_focus_resource_list;
> >> +             wl_double_fixed_from_double(dx, &dx_int, &dx_frac);
> >> +             wl_double_fixed_from_double(dy, &dy_int, &dy_frac);
> >> +             wl_double_fixed_from_double(dx_unaccel,
> >> +                                         &dx_unaccel_int,
> >> +                                         &dx_unaccel_frac);
> >> +             wl_double_fixed_from_double(dy_unaccel,
> >> +                                         &dy_unaccel_int,
> >> +                                         &dy_unaccel_frac);
> >> +             wl_resource_for_each(resource, resource_list) {
> >> +                     _wl_relative_pointer_send_relative_motion(
> >> +                             resource, time,
> >> +                             dx_int, dx_frac,
> >> +                             dy_int, dy_frac,
> >> +                             dx_unaccel_int, dx_unaccel_frac,
> >> +                             dy_unaccel_int, dy_unaccel_frac);
> >> +             }
> >> +     }
> >> +}
> >> +
> >> +static void
> >>  default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
> >>                           struct weston_pointer_motion_event *event)
> >>  {
> >> @@ -187,6 +268,8 @@ default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
> >>                                              pointer->sx, pointer->sy);
> >>               }
> >>       }
> >> +
> >> +     weston_pointer_send_relative_motion(pointer, time, event);
> >>  }
> >>
> >>  static void
> >> @@ -503,7 +586,9 @@ weston_pointer_create(struct weston_seat *seat)
> >>               return NULL;
> >>
> >>       wl_list_init(&pointer->resource_list);
> >> +     wl_list_init(&pointer->relative_resource_list);
> >>       wl_list_init(&pointer->focus_resource_list);
> >> +     wl_list_init(&pointer->relative_focus_resource_list);
> >>       weston_pointer_set_default_grab(pointer,
> >>                                       seat->compositor->default_pointer_grab);
> >>       wl_list_init(&pointer->focus_resource_listener.link);
> >> @@ -665,6 +750,7 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
> >>       struct wl_display *display = pointer->seat->compositor->wl_display;
> >>       uint32_t serial;
> >>       struct wl_list *focus_resource_list;
> >> +     struct wl_list *relative_focus_resource_list;
> >>       int refocus = 0;
> >>
> >>       if ((!pointer->focus && view) ||
> >> @@ -674,6 +760,7 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
> >>               refocus = 1;
> >>
> >>       focus_resource_list = &pointer->focus_resource_list;
> >> +     relative_focus_resource_list = &pointer->relative_focus_resource_list;
> >>
> >>       if (!wl_list_empty(focus_resource_list) && refocus) {
> >>               serial = wl_display_next_serial(display);
> >> @@ -683,6 +770,8 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
> >>               }
> >>
> >>               move_resources(&pointer->resource_list, focus_resource_list);
> >> +             move_resources(&pointer->relative_resource_list,
> >> +                            relative_focus_resource_list);
> >>       }
> >>
> >>       if (find_resource_for_view(&pointer->resource_list, view) && refocus) {
> >> @@ -700,6 +789,9 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
> >>               move_resources_for_client(focus_resource_list,
> >>                                         &pointer->resource_list,
> >>                                         surface_client);
> >> +             move_resources_for_client(relative_focus_resource_list,
> >> +                                       &pointer->relative_resource_list,
> >> +                                       surface_client);
> >>
> >>               wl_resource_for_each(resource, focus_resource_list) {
> >>                       wl_pointer_send_enter(resource,
> >> @@ -932,23 +1024,6 @@ weston_pointer_move_to(struct weston_pointer *pointer,
> >>  }
> >>
> >>  WL_EXPORT void
> >> -weston_pointer_motion_to_abs(struct weston_pointer *pointer,
> >> -                          struct weston_pointer_motion_event *event,
> >> -                          wl_fixed_t *x, wl_fixed_t *y)
> >> -{
> >> -     if (event->mask & WESTON_POINTER_MOTION_ABS) {
> >> -             *x = wl_fixed_from_double(event->x);
> >> -             *y = wl_fixed_from_double(event->y);
> >> -     } else if (event->mask & WESTON_POINTER_MOTION_REL) {
> >> -             *x = pointer->x + wl_fixed_from_double(event->dx);
> >> -             *y = pointer->y + wl_fixed_from_double(event->dy);
> >> -     } else {
> >> -             assert(!"invalid motion event");
> >> -             *x = *y = 0;
> >> -     }
> >> -}
> >> -
> >> -WL_EXPORT void
> >>  weston_pointer_move(struct weston_pointer *pointer,
> >>                   struct weston_pointer_motion_event *event)
> >>  {
> >> @@ -2008,6 +2083,72 @@ bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
> >>               wl_seat_send_name(resource, seat->seat_name);
> >>  }
> >>
> >> +static void
> >> +relative_pointer_release(struct wl_client *client,
> >> +                      struct wl_resource *resource)
> >> +{
> >> +     wl_resource_destroy(resource);
> >> +}
> >> +
> >> +static const struct _wl_relative_pointer_interface relative_pointer_interface = {
> >> +     relative_pointer_release
> >> +};
> >> +
> >> +static void
> >> +relative_pointer_manager_get_relative_pointer(struct wl_client *client,
> >> +                                           struct wl_resource *resource,
> >> +                                           uint32_t id,
> >> +                                           struct wl_resource *pointer_resource)
> >> +{
> >> +     struct weston_pointer *pointer =
> >> +             wl_resource_get_user_data(pointer_resource);
> >> +     struct wl_resource *cr;
> >> +     struct weston_view *focus;
> >> +
> >> +     cr = wl_resource_create(client, &_wl_relative_pointer_interface,
> >> +                             wl_resource_get_version(resource), id);
> >> +     if (cr == NULL) {
> >> +             wl_client_post_no_memory(client);
> >> +             return;
> >> +     }
> >> +
> >> +     /* May be moved to focused list later by either
> >> +      * weston_pointer_set_focus or directly if this client is already
> >> +      * focused */
> >> +     wl_list_insert(&pointer->relative_resource_list,
> >> +                    wl_resource_get_link(cr));
> >> +     wl_resource_set_implementation(cr, &relative_pointer_interface,
> >> +                                    pointer,
> >> +                                    unbind_resource);
> >> +
> >> +     focus = pointer->focus;
> >> +     if (focus && focus->surface->resource &&
> >> +         wl_resource_get_client(focus->surface->resource) == client) {
> >> +             wl_list_remove(wl_resource_get_link(cr));
> >> +             wl_list_insert(&pointer->relative_focus_resource_list,
> >> +                            wl_resource_get_link(cr));
> >> +     }
> >> +}
> >> +
> >> +static const struct _wl_relative_pointer_manager_interface relative_pointer_manager = {
> >> +     relative_pointer_manager_get_relative_pointer,
> >> +};
> >> +
> >> +static void
> >> +bind_relative_pointer_manager(struct wl_client *client, void *data,
> >> +                           uint32_t version, uint32_t id)
> >> +{
> >> +     struct weston_compositor *compositor = data;
> >> +     struct wl_resource *resource;
> >> +
> >> +     resource = wl_resource_create(client,
> >> +                                   &_wl_relative_pointer_manager_interface,
> >> +                                   1, id);
> >> +     wl_resource_set_implementation(resource, &relative_pointer_manager,
> >> +                                    compositor,
> >> +                                    NULL);
> >> +}
> >> +
> >>  #ifdef ENABLE_XKBCOMMON
> >>  int
> >>  weston_compositor_xkb_init(struct weston_compositor *ec,
> >> @@ -2429,3 +2570,14 @@ weston_seat_release(struct weston_seat *seat)
> >>
> >>       wl_signal_emit(&seat->destroy_signal, seat);
> >>  }
> >> +
> >> +int
> >> +weston_input_init(struct weston_compositor *compositor)
> >> +{
> >> +     if (!wl_global_create(compositor->wl_display,
> >> +                           &_wl_relative_pointer_manager_interface, 1,
> >> +                           compositor, bind_relative_pointer_manager))
> >> +             return -1;
> >> +
> >> +     return 0;
> >> +}
> >> --
> >> 2.1.4
On Wed, Jul 15, 2015 at 11:55 AM, Peter Hutterer
<peter.hutterer@who-t.net> wrote:
> On Wed, Jul 15, 2015 at 08:23:09AM +0900, x414e54 wrote:
>> Hi,
>>
>> Just a quick questions:
>>
>> 1) Is there any way to un-normalize the values?
>
> not at this point, no.
> fwiw as of libinput 0.19 the normalization only applies to the accelerated
> delta, the unaccelerated one is generally in device-specific units. Except
> on touchpads, where we still normalize it to a 1000dpi mouse, we may review
> that at some point. but since the normalization is "magic", you can't
> unnormalize them.

Unaccelerated un-normalzied is fine. But it would be nice to have this
reflected in the wayland spec just to make sure it is consistent
between window managers.

>
>> 2) What happens with >1000hz gaming mice for example which need
>> microsecond granularity timestamps?
>
> naïve question: do people notice the difference between 1000Hz and 2000Hz?

You could probably say the same for 500hz and 1000hz mice. I do not
think it is your/our place to say if someone would notice or not, some
people may some people might not.

Not necessarily mice but definitely when using head tracking and eye
tracking it is noticeable. Also it helps you to create more accurate
prediction and allows you to render frames ahead.

Considering the original events are reported in nanoseconds/ktime if
it came from evdev? (I may be wrong). It does not seem like too much
trouble just to pass the original nanosecond time along even if it is
in two 32 bit integers sec and nsec.

There is one mouse available called the Asus ROG Gladius. So there are
definitely people using it now.

>
> Cheers,
>    Peter
>
>> On Mon, Jun 29, 2015 at 3:54 PM, Peter Hutterer
>> <peter.hutterer@who-t.net> wrote:
>> > On Fri, Jun 26, 2015 at 12:38:01PM +0800, Jonas Ådahl wrote:
>> >> A wl_relative_pointer object is an extension to the wl_pointer interface
>> >> only used for emitting relative pointer events. It will only emit events
>> >> when the parent pointer has focus.
>> >>
>> >> To get a relative pointer object, use the get_relative_pointer request
>> >> of the global wl_relative_pointer_manager object. When stabilizing it
>> >> might make more sense to just add it to wl_seat instead of having a
>> >> single use global interface.
>> >>
>> >> All interface names are currently prefixed with underscore in order to
>> >> avoid any future conflicts with stable protocol.
>> >>
>> >> Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
>> >> ---
>> >>
>> >> Changes since v2:
>> >>
>> >>  * Updated copyright.
>> >>  * Updated the license text to corrected one.
>> >>  * Clarified that relative motion events are unaffected by clamping.
>> >>  * Clarified that pointer acceleration behaviour is device specific.
>> >>  * Clarified that the order of relative_motion and motion is not
>> >>    guaranteed.
>> >>  * Explained that button events etc are to be fetched from the
>> >>    corresponding wl_pointer object.
>> >>  * Clarified that relative motion events are in x/y coordinate space.
>> >>  * Added an 'unstable protocol' warning explaining compatibility etc.
>> >>
>> >>
>> >>  Makefile.am                   |   7 +-
>> >>  protocol/relative-pointer.xml | 127 ++++++++++++++++++++++++++++
>> >>  src/compositor.c              |   3 +
>> >>  src/compositor.h              |   5 ++
>> >>  src/input.c                   | 186 ++++++++++++++++++++++++++++++++++++++----
>> >>  5 files changed, 309 insertions(+), 19 deletions(-)
>> >>  create mode 100644 protocol/relative-pointer.xml
>> >>
>> >> diff --git a/Makefile.am b/Makefile.am
>> >> index 0a30cb4..70c436f 100644
>> >> --- a/Makefile.am
>> >> +++ b/Makefile.am
>> >> @@ -105,7 +105,9 @@ nodist_weston_SOURCES =                                   \
>> >>       protocol/presentation_timing-protocol.c         \
>> >>       protocol/presentation_timing-server-protocol.h  \
>> >>       protocol/scaler-protocol.c                      \
>> >> -     protocol/scaler-server-protocol.h
>> >> +     protocol/scaler-server-protocol.h               \
>> >> +     protocol/relative-pointer-protocol.c            \
>> >> +     protocol/relative-pointer-server-protocol.h
>> >>
>> >>  BUILT_SOURCES += $(nodist_weston_SOURCES)
>> >>
>> >> @@ -1183,7 +1185,8 @@ EXTRA_DIST +=                                   \
>> >>       protocol/presentation_timing.xml        \
>> >>       protocol/scaler.xml                     \
>> >>       protocol/ivi-application.xml            \
>> >> -     protocol/ivi-hmi-controller.xml
>> >> +     protocol/ivi-hmi-controller.xml         \
>> >> +     protocol/relative-pointer.xml
>> >>
>> >>  #
>> >>  # manual test modules in tests subdirectory
>> >> diff --git a/protocol/relative-pointer.xml b/protocol/relative-pointer.xml
>> >> new file mode 100644
>> >> index 0000000..185d33b
>> >> --- /dev/null
>> >> +++ b/protocol/relative-pointer.xml
>> >> @@ -0,0 +1,127 @@
>> >> +<?xml version="1.0" encoding="UTF-8"?>
>> >> +<protocol name="relative_pointer">
>> >> +
>> >> +  <copyright>
>> >> +    Copyright © 2014      Jonas Ådahl
>> >> +    Copyright © 2015      Red Hat Inc.
>> >> +
>> >> +    Permission is hereby granted, free of charge, to any person obtaining a
>> >> +    copy of this software and associated documentation files (the "Software"),
>> >> +    to deal in the Software without restriction, including without limitation
>> >> +    the rights to use, copy, modify, merge, publish, distribute, sublicense,
>> >> +    and/or sell copies of the Software, and to permit persons to whom the
>> >> +    Software is furnished to do so, subject to the following conditions:
>> >> +
>> >> +    The above copyright notice and this permission notice (including the next
>> >> +    paragraph) shall be included in all copies or substantial portions of the
>> >> +    Software.
>> >> +
>> >> +    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>> >> +    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>> >> +    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
>> >> +    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>> >> +    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>> >> +    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
>> >> +    DEALINGS IN THE SOFTWARE.
>> >> +  </copyright>
>> >> +
>> >> +  <interface name="_wl_relative_pointer_manager" version="1">
>> >> +    <description summary="get relative pointer objects">
>> >> +      A global interface used for getting the relative pointer object for a
>> >> +      given seat.
>> >> +
>> >> +      Warning! The protocol described in this file is experimental. Each version
>> >> +      of this protocol should be considered incompatible with any other version,
>> >> +      and a client binding to a version different to the one advertised will be
>> >> +      terminated. When the protocol is stabalized, backward compatibility is
>> >
>> > typo: stabilized, but I would say "once the protocol is declared stable"
>> > anyway
>> >
>> > Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
>> > otherwise
>> >
>> > Cheers,
>> >    Peter
>> >
>> >> +      guaranteed, the '_' prefix will be removed from the name and the version
>> >> +      will be reset to 1.
>> >> +    </description>
>> >> +
>> >> +    <request name="get_relative_pointer">
>> >> +      <description summary="get a relative pointer object">
>> >> +        Create a relative pointer interface given a wl_pointer object. See
>> >> +        the wl_relative_pointer interface for more details.
>> >> +      </description>
>> >> +
>> >> +      <arg name="id" type="new_id" interface="_wl_relative_pointer"/>
>> >> +      <arg name="pointer" type="object" interface="wl_pointer"/>
>> >> +    </request>
>> >> +  </interface>
>> >> +
>> >> +  <interface name="_wl_relative_pointer" version="1">
>> >> +    <description summary="relative pointer object">
>> >> +      A wl_relative_pointer object is an extension to the wl_pointer interface
>> >> +      used for emitting relative pointer events. It shares the same focus as
>> >> +      wl_pointer objects of the same seat and will only emit events when it
>> >> +      has focus.
>> >> +    </description>
>> >> +
>> >> +    <request name="release" type="destructor">
>> >> +      <description summary="release the relative pointer object"/>
>> >> +    </request>
>> >> +
>> >> +    <event name="relative_motion">
>> >> +      <description summary="relative pointer motion">
>> >> +        Relative x/y pointer motion in from the pointer of the seat associated
>> >> +        with this object.
>> >> +
>> >> +        A relative motion is in the same dimension as regular wl_pointer motion
>> >> +        events, except they do not represent an absolute position. For example,
>> >> +        moving a pointer from (x, y) to (x', y') would have the equivalent
>> >> +        relative motion (x' - x, y' - y). If a pointer motion caused the
>> >> +        absolute pointer position to be clipped by for example the edge of the
>> >> +        monitor, the relative motion is unaffected by the clipping and will
>> >> +        represent the unclipped motion.
>> >> +
>> >> +        This event also contains non-accelerated motion deltas. The
>> >> +        non-accelerated delta is, when applicable, the regular pointer motion
>> >> +        delta as it was before having applied motion acceleration
>> >> +        transformations. The compositor will have applied the same processing
>> >> +        (such as normalization) meaning the events will have roughly the same
>> >> +        magnitude as accelerated motion events.
>> >> +
>> >> +        Note that the non-accelerated delta does not represent 'raw' events as
>> >> +        they were read from some device. Pointer motion acceleration is device-
>> >> +        and configuration-specific and non-accelerated deltas and accelerated
>> >> +        deltas may have the same value on some devices.
>> >> +
>> >> +        Relative motions are not coupled to wl_pointer.motion events, and can
>> >> +        be sent in combination with such events, but also independently. There
>> >> +        may also be scenarious where wl_pointer.motion is sent, but there is no
>> >> +        relative motion. The order of an absolute and relative motion event
>> >> +        originating from the same physical motion is not guaranteed.
>> >> +
>> >> +        The motion vectors are encoded as double fixed point values.
>> >> +
>> >> +        A double fixed point value is a 64 bit data type encoded as two separate
>> >> +        signed 32 bit integers. The integral part of the value is stored in one
>> >> +        of the integers and the fractional part in the other.
>> >> +
>> >> +        If the client needs button events, it can receive them from a wl_pointer
>> >> +        object of the same seat that the wl_relative_pointer object is
>> >> +        associated with.
>> >> +      </description>
>> >> +
>> >> +      <arg name="time" type="uint"
>> >> +           summary="timestamp with millisecond granularity"/>
>> >> +      <arg name="dx_int" type="int"
>> >> +           summary="integral part of the x component of the motion vector"/>
>> >> +      <arg name="dx_frac" type="int"
>> >> +           summary="fractional part of the x component of the motion vector"/>
>> >> +      <arg name="dy_int" type="int"
>> >> +           summary="integral part of the y component of the motion vector"/>
>> >> +      <arg name="dy_frac" type="int"
>> >> +           summary="fractional part of the y component of the motion vector"/>
>> >> +      <arg name="dx_unaccel_int" type="int"
>> >> +           summary="integral part of the x component of the unaccelerated motion vector"/>
>> >> +      <arg name="dx_unaccel_frac" type="int"
>> >> +           summary="fractional part of the x component of the unaccelerated motion vector"/>
>> >> +      <arg name="dy_unaccel_int" type="int"
>> >> +           summary="integral part of the y component of the unaccelerated motion vector"/>
>> >> +      <arg name="dy_unaccel_frac" type="int"
>> >> +           summary="fractional part of the y component of the unaccelerated motion vector"/>
>> >> +    </event>
>> >> +  </interface>
>> >> +
>> >> +</protocol>
>> >> diff --git a/src/compositor.c b/src/compositor.c
>> >> index 5594d30..b462531 100644
>> >> --- a/src/compositor.c
>> >> +++ b/src/compositor.c
>> >> @@ -4560,6 +4560,9 @@ weston_compositor_init(struct weston_compositor *ec,
>> >>       weston_plane_init(&ec->primary_plane, ec, 0, 0);
>> >>       weston_compositor_stack_plane(ec, &ec->primary_plane, NULL);
>> >>
>> >> +     if (weston_input_init(ec) != 0)
>> >> +             return -1;
>> >> +
>> >>       s = weston_config_get_section(ec->config, "keyboard", NULL, NULL);
>> >>       weston_config_section_get_string(s, "keymap_rules",
>> >>                                        (char **) &xkb_names.rules, NULL);
>> >> diff --git a/src/compositor.h b/src/compositor.h
>> >> index 331b758..55cc88f 100644
>> >> --- a/src/compositor.h
>> >> +++ b/src/compositor.h
>> >> @@ -340,7 +340,9 @@ struct weston_pointer {
>> >>       struct weston_seat *seat;
>> >>
>> >>       struct wl_list resource_list;
>> >> +     struct wl_list relative_resource_list;
>> >>       struct wl_list focus_resource_list;
>> >> +     struct wl_list relative_focus_resource_list;
>> >>       struct weston_view *focus;
>> >>       uint32_t focus_serial;
>> >>       struct wl_listener focus_view_listener;
>> >> @@ -1584,6 +1586,9 @@ weston_output_mode_switch_to_native(struct weston_output *output);
>> >>  int
>> >>  noop_renderer_init(struct weston_compositor *ec);
>> >>
>> >> +int
>> >> +weston_input_init(struct weston_compositor *compositor);
>> >> +
>> >>  struct weston_compositor *
>> >>  backend_init(struct wl_display *display, int *argc, char *argv[],
>> >>            struct weston_config *config);
>> >> diff --git a/src/input.c b/src/input.c
>> >> index 9131287..b48a6c9 100644
>> >> --- a/src/input.c
>> >> +++ b/src/input.c
>> >> @@ -32,7 +32,9 @@
>> >>  #include <limits.h>
>> >>
>> >>  #include "../shared/os-compatibility.h"
>> >> +#include "../shared/util.h"
>> >>  #include "compositor.h"
>> >> +#include "protocol/relative-pointer-server-protocol.h"
>> >>
>> >>  static void
>> >>  empty_region(pixman_region32_t *region)
>> >> @@ -47,6 +49,49 @@ static void unbind_resource(struct wl_resource *resource)
>> >>  }
>> >>
>> >>  WL_EXPORT void
>> >> +weston_pointer_motion_to_abs(struct weston_pointer *pointer,
>> >> +                          struct weston_pointer_motion_event *event,
>> >> +                          wl_fixed_t *x, wl_fixed_t *y)
>> >> +{
>> >> +     if (event->mask & WESTON_POINTER_MOTION_ABS) {
>> >> +             *x = wl_fixed_from_double(event->x);
>> >> +             *y = wl_fixed_from_double(event->y);
>> >> +     } else if (event->mask & WESTON_POINTER_MOTION_REL) {
>> >> +             *x = pointer->x + wl_fixed_from_double(event->dx);
>> >> +             *y = pointer->y + wl_fixed_from_double(event->dy);
>> >> +     } else {
>> >> +             assert(!"invalid motion event");
>> >> +             *x = *y = 0;
>> >> +     }
>> >> +}
>> >> +
>> >> +static int
>> >> +weston_pointer_motion_to_rel(struct weston_pointer *pointer,
>> >> +                          struct weston_pointer_motion_event *event,
>> >> +                          double *dx, double *dy,
>> >> +                          double *dx_unaccel, double *dy_unaccel)
>> >> +{
>> >> +     if (event->mask & WESTON_POINTER_MOTION_REL &&
>> >> +         event->mask & WESTON_POINTER_MOTION_REL_NOACCEL) {
>> >> +             *dx = event->dx;
>> >> +             *dy = event->dy;
>> >> +             *dx_unaccel = event->dx_unaccel;
>> >> +             *dy_unaccel = event->dy_unaccel;
>> >> +             return 1;
>> >> +     } else if (event->mask & WESTON_POINTER_MOTION_REL) {
>> >> +             *dx_unaccel = *dx = event->dx;
>> >> +             *dy_unaccel = *dy = event->dy;
>> >> +             return 1;
>> >> +     } else if (event->mask & WESTON_POINTER_MOTION_REL_NOACCEL) {
>> >> +             *dx_unaccel = *dx = event->dx_unaccel;
>> >> +             *dy_unaccel = *dy = event->dy_unaccel;
>> >> +             return 1;
>> >> +     } else {
>> >> +             return 0;
>> >> +     }
>> >> +}
>> >> +
>> >> +WL_EXPORT void
>> >>  weston_seat_repick(struct weston_seat *seat)
>> >>  {
>> >>       const struct weston_pointer *pointer = seat->pointer;
>> >> @@ -162,6 +207,42 @@ default_grab_pointer_focus(struct weston_pointer_grab *grab)
>> >>  }
>> >>
>> >>  static void
>> >> +weston_pointer_send_relative_motion(struct weston_pointer *pointer,
>> >> +                                 uint32_t time,
>> >> +                                 struct weston_pointer_motion_event *event)
>> >> +{
>> >> +     double dx, dy, dx_unaccel, dy_unaccel;
>> >> +     int32_t dx_int, dx_frac;
>> >> +     int32_t dy_int, dy_frac;
>> >> +     int32_t dx_unaccel_int, dx_unaccel_frac;
>> >> +     int32_t dy_unaccel_int, dy_unaccel_frac;
>> >> +     struct wl_list *resource_list;
>> >> +     struct wl_resource *resource;
>> >> +
>> >> +     if (weston_pointer_motion_to_rel(pointer, event,
>> >> +                                      &dx, &dy,
>> >> +                                      &dx_unaccel, &dy_unaccel)) {
>> >> +             resource_list = &pointer->relative_focus_resource_list;
>> >> +             wl_double_fixed_from_double(dx, &dx_int, &dx_frac);
>> >> +             wl_double_fixed_from_double(dy, &dy_int, &dy_frac);
>> >> +             wl_double_fixed_from_double(dx_unaccel,
>> >> +                                         &dx_unaccel_int,
>> >> +                                         &dx_unaccel_frac);
>> >> +             wl_double_fixed_from_double(dy_unaccel,
>> >> +                                         &dy_unaccel_int,
>> >> +                                         &dy_unaccel_frac);
>> >> +             wl_resource_for_each(resource, resource_list) {
>> >> +                     _wl_relative_pointer_send_relative_motion(
>> >> +                             resource, time,
>> >> +                             dx_int, dx_frac,
>> >> +                             dy_int, dy_frac,
>> >> +                             dx_unaccel_int, dx_unaccel_frac,
>> >> +                             dy_unaccel_int, dy_unaccel_frac);
>> >> +             }
>> >> +     }
>> >> +}
>> >> +
>> >> +static void
>> >>  default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
>> >>                           struct weston_pointer_motion_event *event)
>> >>  {
>> >> @@ -187,6 +268,8 @@ default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
>> >>                                              pointer->sx, pointer->sy);
>> >>               }
>> >>       }
>> >> +
>> >> +     weston_pointer_send_relative_motion(pointer, time, event);
>> >>  }
>> >>
>> >>  static void
>> >> @@ -503,7 +586,9 @@ weston_pointer_create(struct weston_seat *seat)
>> >>               return NULL;
>> >>
>> >>       wl_list_init(&pointer->resource_list);
>> >> +     wl_list_init(&pointer->relative_resource_list);
>> >>       wl_list_init(&pointer->focus_resource_list);
>> >> +     wl_list_init(&pointer->relative_focus_resource_list);
>> >>       weston_pointer_set_default_grab(pointer,
>> >>                                       seat->compositor->default_pointer_grab);
>> >>       wl_list_init(&pointer->focus_resource_listener.link);
>> >> @@ -665,6 +750,7 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
>> >>       struct wl_display *display = pointer->seat->compositor->wl_display;
>> >>       uint32_t serial;
>> >>       struct wl_list *focus_resource_list;
>> >> +     struct wl_list *relative_focus_resource_list;
>> >>       int refocus = 0;
>> >>
>> >>       if ((!pointer->focus && view) ||
>> >> @@ -674,6 +760,7 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
>> >>               refocus = 1;
>> >>
>> >>       focus_resource_list = &pointer->focus_resource_list;
>> >> +     relative_focus_resource_list = &pointer->relative_focus_resource_list;
>> >>
>> >>       if (!wl_list_empty(focus_resource_list) && refocus) {
>> >>               serial = wl_display_next_serial(display);
>> >> @@ -683,6 +770,8 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
>> >>               }
>> >>
>> >>               move_resources(&pointer->resource_list, focus_resource_list);
>> >> +             move_resources(&pointer->relative_resource_list,
>> >> +                            relative_focus_resource_list);
>> >>       }
>> >>
>> >>       if (find_resource_for_view(&pointer->resource_list, view) && refocus) {
>> >> @@ -700,6 +789,9 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
>> >>               move_resources_for_client(focus_resource_list,
>> >>                                         &pointer->resource_list,
>> >>                                         surface_client);
>> >> +             move_resources_for_client(relative_focus_resource_list,
>> >> +                                       &pointer->relative_resource_list,
>> >> +                                       surface_client);
>> >>
>> >>               wl_resource_for_each(resource, focus_resource_list) {
>> >>                       wl_pointer_send_enter(resource,
>> >> @@ -932,23 +1024,6 @@ weston_pointer_move_to(struct weston_pointer *pointer,
>> >>  }
>> >>
>> >>  WL_EXPORT void
>> >> -weston_pointer_motion_to_abs(struct weston_pointer *pointer,
>> >> -                          struct weston_pointer_motion_event *event,
>> >> -                          wl_fixed_t *x, wl_fixed_t *y)
>> >> -{
>> >> -     if (event->mask & WESTON_POINTER_MOTION_ABS) {
>> >> -             *x = wl_fixed_from_double(event->x);
>> >> -             *y = wl_fixed_from_double(event->y);
>> >> -     } else if (event->mask & WESTON_POINTER_MOTION_REL) {
>> >> -             *x = pointer->x + wl_fixed_from_double(event->dx);
>> >> -             *y = pointer->y + wl_fixed_from_double(event->dy);
>> >> -     } else {
>> >> -             assert(!"invalid motion event");
>> >> -             *x = *y = 0;
>> >> -     }
>> >> -}
>> >> -
>> >> -WL_EXPORT void
>> >>  weston_pointer_move(struct weston_pointer *pointer,
>> >>                   struct weston_pointer_motion_event *event)
>> >>  {
>> >> @@ -2008,6 +2083,72 @@ bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
>> >>               wl_seat_send_name(resource, seat->seat_name);
>> >>  }
>> >>
>> >> +static void
>> >> +relative_pointer_release(struct wl_client *client,
>> >> +                      struct wl_resource *resource)
>> >> +{
>> >> +     wl_resource_destroy(resource);
>> >> +}
>> >> +
>> >> +static const struct _wl_relative_pointer_interface relative_pointer_interface = {
>> >> +     relative_pointer_release
>> >> +};
>> >> +
>> >> +static void
>> >> +relative_pointer_manager_get_relative_pointer(struct wl_client *client,
>> >> +                                           struct wl_resource *resource,
>> >> +                                           uint32_t id,
>> >> +                                           struct wl_resource *pointer_resource)
>> >> +{
>> >> +     struct weston_pointer *pointer =
>> >> +             wl_resource_get_user_data(pointer_resource);
>> >> +     struct wl_resource *cr;
>> >> +     struct weston_view *focus;
>> >> +
>> >> +     cr = wl_resource_create(client, &_wl_relative_pointer_interface,
>> >> +                             wl_resource_get_version(resource), id);
>> >> +     if (cr == NULL) {
>> >> +             wl_client_post_no_memory(client);
>> >> +             return;
>> >> +     }
>> >> +
>> >> +     /* May be moved to focused list later by either
>> >> +      * weston_pointer_set_focus or directly if this client is already
>> >> +      * focused */
>> >> +     wl_list_insert(&pointer->relative_resource_list,
>> >> +                    wl_resource_get_link(cr));
>> >> +     wl_resource_set_implementation(cr, &relative_pointer_interface,
>> >> +                                    pointer,
>> >> +                                    unbind_resource);
>> >> +
>> >> +     focus = pointer->focus;
>> >> +     if (focus && focus->surface->resource &&
>> >> +         wl_resource_get_client(focus->surface->resource) == client) {
>> >> +             wl_list_remove(wl_resource_get_link(cr));
>> >> +             wl_list_insert(&pointer->relative_focus_resource_list,
>> >> +                            wl_resource_get_link(cr));
>> >> +     }
>> >> +}
>> >> +
>> >> +static const struct _wl_relative_pointer_manager_interface relative_pointer_manager = {
>> >> +     relative_pointer_manager_get_relative_pointer,
>> >> +};
>> >> +
>> >> +static void
>> >> +bind_relative_pointer_manager(struct wl_client *client, void *data,
>> >> +                           uint32_t version, uint32_t id)
>> >> +{
>> >> +     struct weston_compositor *compositor = data;
>> >> +     struct wl_resource *resource;
>> >> +
>> >> +     resource = wl_resource_create(client,
>> >> +                                   &_wl_relative_pointer_manager_interface,
>> >> +                                   1, id);
>> >> +     wl_resource_set_implementation(resource, &relative_pointer_manager,
>> >> +                                    compositor,
>> >> +                                    NULL);
>> >> +}
>> >> +
>> >>  #ifdef ENABLE_XKBCOMMON
>> >>  int
>> >>  weston_compositor_xkb_init(struct weston_compositor *ec,
>> >> @@ -2429,3 +2570,14 @@ weston_seat_release(struct weston_seat *seat)
>> >>
>> >>       wl_signal_emit(&seat->destroy_signal, seat);
>> >>  }
>> >> +
>> >> +int
>> >> +weston_input_init(struct weston_compositor *compositor)
>> >> +{
>> >> +     if (!wl_global_create(compositor->wl_display,
>> >> +                           &_wl_relative_pointer_manager_interface, 1,
>> >> +                           compositor, bind_relative_pointer_manager))
>> >> +             return -1;
>> >> +
>> >> +     return 0;
>> >> +}
>> >> --
>> >> 2.1.4
On Thu, Jul 16, 2015 at 03:37:30PM +0900, x414e54 wrote:
> On Wed, Jul 15, 2015 at 11:55 AM, Peter Hutterer
> <peter.hutterer@who-t.net> wrote:
> > On Wed, Jul 15, 2015 at 08:23:09AM +0900, x414e54 wrote:
> >> Hi,
> >>
> >> Just a quick questions:
> >>
> >> 1) Is there any way to un-normalize the values?
> >
> > not at this point, no.
> > fwiw as of libinput 0.19 the normalization only applies to the accelerated
> > delta, the unaccelerated one is generally in device-specific units. Except
> > on touchpads, where we still normalize it to a 1000dpi mouse, we may review
> > that at some point. but since the normalization is "magic", you can't
> > unnormalize them.
> 
> Unaccelerated un-normalzied is fine. But it would be nice to have this
> reflected in the wayland spec just to make sure it is consistent
> between window managers.

I have no objections to removing the note about the compositor having
applied the normalizations, partly because it is not correct when
running on libinput anymore, but also because it might not be a good
idea to be to specific about how they look as at some backends we might
not be able to provide exactly that type of information (remote desktop
for example).

> 
> >
> >> 2) What happens with >1000hz gaming mice for example which need
> >> microsecond granularity timestamps?
> >
> > naïve question: do people notice the difference between 1000Hz and 2000Hz?
> 
> You could probably say the same for 500hz and 1000hz mice. I do not
> think it is your/our place to say if someone would notice or not, some
> people may some people might not.
> 
> Not necessarily mice but definitely when using head tracking and eye
> tracking it is noticeable. Also it helps you to create more accurate
> prediction and allows you to render frames ahead.
> 
> Considering the original events are reported in nanoseconds/ktime if
> it came from evdev? (I may be wrong). It does not seem like too much
> trouble just to pass the original nanosecond time along even if it is
> in two 32 bit integers sec and nsec.

Libinput exposes the time value as a uint32_t in milleseconds. It gets
the timestamp from a 'struct timeval' which is in microseconds. In other
words, we'd need to expose the lost time data via additional API in
libinput. I'm no input device expert so I'm not going to have any strong
objections to adding more information, unless someone have an objective
objection to it.

How correct are the timestamps from the kernel for such devices?


Jonas

> 
> There is one mouse available called the Asus ROG Gladius. So there are
> definitely people using it now.
> 
> >
> > Cheers,
> >    Peter
> >
> >> On Mon, Jun 29, 2015 at 3:54 PM, Peter Hutterer
> >> <peter.hutterer@who-t.net> wrote:
> >> > On Fri, Jun 26, 2015 at 12:38:01PM +0800, Jonas Ådahl wrote:
> >> >> A wl_relative_pointer object is an extension to the wl_pointer interface
> >> >> only used for emitting relative pointer events. It will only emit events
> >> >> when the parent pointer has focus.
> >> >>
> >> >> To get a relative pointer object, use the get_relative_pointer request
> >> >> of the global wl_relative_pointer_manager object. When stabilizing it
> >> >> might make more sense to just add it to wl_seat instead of having a
> >> >> single use global interface.
> >> >>
> >> >> All interface names are currently prefixed with underscore in order to
> >> >> avoid any future conflicts with stable protocol.
> >> >>
> >> >> Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
> >> >> ---
> >> >>
> >> >> Changes since v2:
> >> >>
> >> >>  * Updated copyright.
> >> >>  * Updated the license text to corrected one.
> >> >>  * Clarified that relative motion events are unaffected by clamping.
> >> >>  * Clarified that pointer acceleration behaviour is device specific.
> >> >>  * Clarified that the order of relative_motion and motion is not
> >> >>    guaranteed.
> >> >>  * Explained that button events etc are to be fetched from the
> >> >>    corresponding wl_pointer object.
> >> >>  * Clarified that relative motion events are in x/y coordinate space.
> >> >>  * Added an 'unstable protocol' warning explaining compatibility etc.
> >> >>
> >> >>
> >> >>  Makefile.am                   |   7 +-
> >> >>  protocol/relative-pointer.xml | 127 ++++++++++++++++++++++++++++
> >> >>  src/compositor.c              |   3 +
> >> >>  src/compositor.h              |   5 ++
> >> >>  src/input.c                   | 186 ++++++++++++++++++++++++++++++++++++++----
> >> >>  5 files changed, 309 insertions(+), 19 deletions(-)
> >> >>  create mode 100644 protocol/relative-pointer.xml
> >> >>
> >> >> diff --git a/Makefile.am b/Makefile.am
> >> >> index 0a30cb4..70c436f 100644
> >> >> --- a/Makefile.am
> >> >> +++ b/Makefile.am
> >> >> @@ -105,7 +105,9 @@ nodist_weston_SOURCES =                                   \
> >> >>       protocol/presentation_timing-protocol.c         \
> >> >>       protocol/presentation_timing-server-protocol.h  \
> >> >>       protocol/scaler-protocol.c                      \
> >> >> -     protocol/scaler-server-protocol.h
> >> >> +     protocol/scaler-server-protocol.h               \
> >> >> +     protocol/relative-pointer-protocol.c            \
> >> >> +     protocol/relative-pointer-server-protocol.h
> >> >>
> >> >>  BUILT_SOURCES += $(nodist_weston_SOURCES)
> >> >>
> >> >> @@ -1183,7 +1185,8 @@ EXTRA_DIST +=                                   \
> >> >>       protocol/presentation_timing.xml        \
> >> >>       protocol/scaler.xml                     \
> >> >>       protocol/ivi-application.xml            \
> >> >> -     protocol/ivi-hmi-controller.xml
> >> >> +     protocol/ivi-hmi-controller.xml         \
> >> >> +     protocol/relative-pointer.xml
> >> >>
> >> >>  #
> >> >>  # manual test modules in tests subdirectory
> >> >> diff --git a/protocol/relative-pointer.xml b/protocol/relative-pointer.xml
> >> >> new file mode 100644
> >> >> index 0000000..185d33b
> >> >> --- /dev/null
> >> >> +++ b/protocol/relative-pointer.xml
> >> >> @@ -0,0 +1,127 @@
> >> >> +<?xml version="1.0" encoding="UTF-8"?>
> >> >> +<protocol name="relative_pointer">
> >> >> +
> >> >> +  <copyright>
> >> >> +    Copyright © 2014      Jonas Ådahl
> >> >> +    Copyright © 2015      Red Hat Inc.
> >> >> +
> >> >> +    Permission is hereby granted, free of charge, to any person obtaining a
> >> >> +    copy of this software and associated documentation files (the "Software"),
> >> >> +    to deal in the Software without restriction, including without limitation
> >> >> +    the rights to use, copy, modify, merge, publish, distribute, sublicense,
> >> >> +    and/or sell copies of the Software, and to permit persons to whom the
> >> >> +    Software is furnished to do so, subject to the following conditions:
> >> >> +
> >> >> +    The above copyright notice and this permission notice (including the next
> >> >> +    paragraph) shall be included in all copies or substantial portions of the
> >> >> +    Software.
> >> >> +
> >> >> +    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> >> >> +    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> >> >> +    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> >> >> +    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> >> >> +    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> >> >> +    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> >> >> +    DEALINGS IN THE SOFTWARE.
> >> >> +  </copyright>
> >> >> +
> >> >> +  <interface name="_wl_relative_pointer_manager" version="1">
> >> >> +    <description summary="get relative pointer objects">
> >> >> +      A global interface used for getting the relative pointer object for a
> >> >> +      given seat.
> >> >> +
> >> >> +      Warning! The protocol described in this file is experimental. Each version
> >> >> +      of this protocol should be considered incompatible with any other version,
> >> >> +      and a client binding to a version different to the one advertised will be
> >> >> +      terminated. When the protocol is stabalized, backward compatibility is
> >> >
> >> > typo: stabilized, but I would say "once the protocol is declared stable"
> >> > anyway
> >> >
> >> > Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
> >> > otherwise
> >> >
> >> > Cheers,
> >> >    Peter
> >> >
> >> >> +      guaranteed, the '_' prefix will be removed from the name and the version
> >> >> +      will be reset to 1.
> >> >> +    </description>
> >> >> +
> >> >> +    <request name="get_relative_pointer">
> >> >> +      <description summary="get a relative pointer object">
> >> >> +        Create a relative pointer interface given a wl_pointer object. See
> >> >> +        the wl_relative_pointer interface for more details.
> >> >> +      </description>
> >> >> +
> >> >> +      <arg name="id" type="new_id" interface="_wl_relative_pointer"/>
> >> >> +      <arg name="pointer" type="object" interface="wl_pointer"/>
> >> >> +    </request>
> >> >> +  </interface>
> >> >> +
> >> >> +  <interface name="_wl_relative_pointer" version="1">
> >> >> +    <description summary="relative pointer object">
> >> >> +      A wl_relative_pointer object is an extension to the wl_pointer interface
> >> >> +      used for emitting relative pointer events. It shares the same focus as
> >> >> +      wl_pointer objects of the same seat and will only emit events when it
> >> >> +      has focus.
> >> >> +    </description>
> >> >> +
> >> >> +    <request name="release" type="destructor">
> >> >> +      <description summary="release the relative pointer object"/>
> >> >> +    </request>
> >> >> +
> >> >> +    <event name="relative_motion">
> >> >> +      <description summary="relative pointer motion">
> >> >> +        Relative x/y pointer motion in from the pointer of the seat associated
> >> >> +        with this object.
> >> >> +
> >> >> +        A relative motion is in the same dimension as regular wl_pointer motion
> >> >> +        events, except they do not represent an absolute position. For example,
> >> >> +        moving a pointer from (x, y) to (x', y') would have the equivalent
> >> >> +        relative motion (x' - x, y' - y). If a pointer motion caused the
> >> >> +        absolute pointer position to be clipped by for example the edge of the
> >> >> +        monitor, the relative motion is unaffected by the clipping and will
> >> >> +        represent the unclipped motion.
> >> >> +
> >> >> +        This event also contains non-accelerated motion deltas. The
> >> >> +        non-accelerated delta is, when applicable, the regular pointer motion
> >> >> +        delta as it was before having applied motion acceleration
> >> >> +        transformations. The compositor will have applied the same processing
> >> >> +        (such as normalization) meaning the events will have roughly the same
> >> >> +        magnitude as accelerated motion events.
> >> >> +
> >> >> +        Note that the non-accelerated delta does not represent 'raw' events as
> >> >> +        they were read from some device. Pointer motion acceleration is device-
> >> >> +        and configuration-specific and non-accelerated deltas and accelerated
> >> >> +        deltas may have the same value on some devices.
> >> >> +
> >> >> +        Relative motions are not coupled to wl_pointer.motion events, and can
> >> >> +        be sent in combination with such events, but also independently. There
> >> >> +        may also be scenarious where wl_pointer.motion is sent, but there is no
> >> >> +        relative motion. The order of an absolute and relative motion event
> >> >> +        originating from the same physical motion is not guaranteed.
> >> >> +
> >> >> +        The motion vectors are encoded as double fixed point values.
> >> >> +
> >> >> +        A double fixed point value is a 64 bit data type encoded as two separate
> >> >> +        signed 32 bit integers. The integral part of the value is stored in one
> >> >> +        of the integers and the fractional part in the other.
> >> >> +
> >> >> +        If the client needs button events, it can receive them from a wl_pointer
> >> >> +        object of the same seat that the wl_relative_pointer object is
> >> >> +        associated with.
> >> >> +      </description>
> >> >> +
> >> >> +      <arg name="time" type="uint"
> >> >> +           summary="timestamp with millisecond granularity"/>
> >> >> +      <arg name="dx_int" type="int"
> >> >> +           summary="integral part of the x component of the motion vector"/>
> >> >> +      <arg name="dx_frac" type="int"
> >> >> +           summary="fractional part of the x component of the motion vector"/>
> >> >> +      <arg name="dy_int" type="int"
> >> >> +           summary="integral part of the y component of the motion vector"/>
> >> >> +      <arg name="dy_frac" type="int"
> >> >> +           summary="fractional part of the y component of the motion vector"/>
> >> >> +      <arg name="dx_unaccel_int" type="int"
> >> >> +           summary="integral part of the x component of the unaccelerated motion vector"/>
> >> >> +      <arg name="dx_unaccel_frac" type="int"
> >> >> +           summary="fractional part of the x component of the unaccelerated motion vector"/>
> >> >> +      <arg name="dy_unaccel_int" type="int"
> >> >> +           summary="integral part of the y component of the unaccelerated motion vector"/>
> >> >> +      <arg name="dy_unaccel_frac" type="int"
> >> >> +           summary="fractional part of the y component of the unaccelerated motion vector"/>
> >> >> +    </event>
> >> >> +  </interface>
> >> >> +
> >> >> +</protocol>
> >> >> diff --git a/src/compositor.c b/src/compositor.c
> >> >> index 5594d30..b462531 100644
> >> >> --- a/src/compositor.c
> >> >> +++ b/src/compositor.c
> >> >> @@ -4560,6 +4560,9 @@ weston_compositor_init(struct weston_compositor *ec,
> >> >>       weston_plane_init(&ec->primary_plane, ec, 0, 0);
> >> >>       weston_compositor_stack_plane(ec, &ec->primary_plane, NULL);
> >> >>
> >> >> +     if (weston_input_init(ec) != 0)
> >> >> +             return -1;
> >> >> +
> >> >>       s = weston_config_get_section(ec->config, "keyboard", NULL, NULL);
> >> >>       weston_config_section_get_string(s, "keymap_rules",
> >> >>                                        (char **) &xkb_names.rules, NULL);
> >> >> diff --git a/src/compositor.h b/src/compositor.h
> >> >> index 331b758..55cc88f 100644
> >> >> --- a/src/compositor.h
> >> >> +++ b/src/compositor.h
> >> >> @@ -340,7 +340,9 @@ struct weston_pointer {
> >> >>       struct weston_seat *seat;
> >> >>
> >> >>       struct wl_list resource_list;
> >> >> +     struct wl_list relative_resource_list;
> >> >>       struct wl_list focus_resource_list;
> >> >> +     struct wl_list relative_focus_resource_list;
> >> >>       struct weston_view *focus;
> >> >>       uint32_t focus_serial;
> >> >>       struct wl_listener focus_view_listener;
> >> >> @@ -1584,6 +1586,9 @@ weston_output_mode_switch_to_native(struct weston_output *output);
> >> >>  int
> >> >>  noop_renderer_init(struct weston_compositor *ec);
> >> >>
> >> >> +int
> >> >> +weston_input_init(struct weston_compositor *compositor);
> >> >> +
> >> >>  struct weston_compositor *
> >> >>  backend_init(struct wl_display *display, int *argc, char *argv[],
> >> >>            struct weston_config *config);
> >> >> diff --git a/src/input.c b/src/input.c
> >> >> index 9131287..b48a6c9 100644
> >> >> --- a/src/input.c
> >> >> +++ b/src/input.c
> >> >> @@ -32,7 +32,9 @@
> >> >>  #include <limits.h>
> >> >>
> >> >>  #include "../shared/os-compatibility.h"
> >> >> +#include "../shared/util.h"
> >> >>  #include "compositor.h"
> >> >> +#include "protocol/relative-pointer-server-protocol.h"
> >> >>
> >> >>  static void
> >> >>  empty_region(pixman_region32_t *region)
> >> >> @@ -47,6 +49,49 @@ static void unbind_resource(struct wl_resource *resource)
> >> >>  }
> >> >>
> >> >>  WL_EXPORT void
> >> >> +weston_pointer_motion_to_abs(struct weston_pointer *pointer,
> >> >> +                          struct weston_pointer_motion_event *event,
> >> >> +                          wl_fixed_t *x, wl_fixed_t *y)
> >> >> +{
> >> >> +     if (event->mask & WESTON_POINTER_MOTION_ABS) {
> >> >> +             *x = wl_fixed_from_double(event->x);
> >> >> +             *y = wl_fixed_from_double(event->y);
> >> >> +     } else if (event->mask & WESTON_POINTER_MOTION_REL) {
> >> >> +             *x = pointer->x + wl_fixed_from_double(event->dx);
> >> >> +             *y = pointer->y + wl_fixed_from_double(event->dy);
> >> >> +     } else {
> >> >> +             assert(!"invalid motion event");
> >> >> +             *x = *y = 0;
> >> >> +     }
> >> >> +}
> >> >> +
> >> >> +static int
> >> >> +weston_pointer_motion_to_rel(struct weston_pointer *pointer,
> >> >> +                          struct weston_pointer_motion_event *event,
> >> >> +                          double *dx, double *dy,
> >> >> +                          double *dx_unaccel, double *dy_unaccel)
> >> >> +{
> >> >> +     if (event->mask & WESTON_POINTER_MOTION_REL &&
> >> >> +         event->mask & WESTON_POINTER_MOTION_REL_NOACCEL) {
> >> >> +             *dx = event->dx;
> >> >> +             *dy = event->dy;
> >> >> +             *dx_unaccel = event->dx_unaccel;
> >> >> +             *dy_unaccel = event->dy_unaccel;
> >> >> +             return 1;
> >> >> +     } else if (event->mask & WESTON_POINTER_MOTION_REL) {
> >> >> +             *dx_unaccel = *dx = event->dx;
> >> >> +             *dy_unaccel = *dy = event->dy;
> >> >> +             return 1;
> >> >> +     } else if (event->mask & WESTON_POINTER_MOTION_REL_NOACCEL) {
> >> >> +             *dx_unaccel = *dx = event->dx_unaccel;
> >> >> +             *dy_unaccel = *dy = event->dy_unaccel;
> >> >> +             return 1;
> >> >> +     } else {
> >> >> +             return 0;
> >> >> +     }
> >> >> +}
> >> >> +
> >> >> +WL_EXPORT void
> >> >>  weston_seat_repick(struct weston_seat *seat)
> >> >>  {
> >> >>       const struct weston_pointer *pointer = seat->pointer;
> >> >> @@ -162,6 +207,42 @@ default_grab_pointer_focus(struct weston_pointer_grab *grab)
> >> >>  }
> >> >>
> >> >>  static void
> >> >> +weston_pointer_send_relative_motion(struct weston_pointer *pointer,
> >> >> +                                 uint32_t time,
> >> >> +                                 struct weston_pointer_motion_event *event)
> >> >> +{
> >> >> +     double dx, dy, dx_unaccel, dy_unaccel;
> >> >> +     int32_t dx_int, dx_frac;
> >> >> +     int32_t dy_int, dy_frac;
> >> >> +     int32_t dx_unaccel_int, dx_unaccel_frac;
> >> >> +     int32_t dy_unaccel_int, dy_unaccel_frac;
> >> >> +     struct wl_list *resource_list;
> >> >> +     struct wl_resource *resource;
> >> >> +
> >> >> +     if (weston_pointer_motion_to_rel(pointer, event,
> >> >> +                                      &dx, &dy,
> >> >> +                                      &dx_unaccel, &dy_unaccel)) {
> >> >> +             resource_list = &pointer->relative_focus_resource_list;
> >> >> +             wl_double_fixed_from_double(dx, &dx_int, &dx_frac);
> >> >> +             wl_double_fixed_from_double(dy, &dy_int, &dy_frac);
> >> >> +             wl_double_fixed_from_double(dx_unaccel,
> >> >> +                                         &dx_unaccel_int,
> >> >> +                                         &dx_unaccel_frac);
> >> >> +             wl_double_fixed_from_double(dy_unaccel,
> >> >> +                                         &dy_unaccel_int,
> >> >> +                                         &dy_unaccel_frac);
> >> >> +             wl_resource_for_each(resource, resource_list) {
> >> >> +                     _wl_relative_pointer_send_relative_motion(
> >> >> +                             resource, time,
> >> >> +                             dx_int, dx_frac,
> >> >> +                             dy_int, dy_frac,
> >> >> +                             dx_unaccel_int, dx_unaccel_frac,
> >> >> +                             dy_unaccel_int, dy_unaccel_frac);
> >> >> +             }
> >> >> +     }
> >> >> +}
> >> >> +
> >> >> +static void
> >> >>  default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
> >> >>                           struct weston_pointer_motion_event *event)
> >> >>  {
> >> >> @@ -187,6 +268,8 @@ default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
> >> >>                                              pointer->sx, pointer->sy);
> >> >>               }
> >> >>       }
> >> >> +
> >> >> +     weston_pointer_send_relative_motion(pointer, time, event);
> >> >>  }
> >> >>
> >> >>  static void
> >> >> @@ -503,7 +586,9 @@ weston_pointer_create(struct weston_seat *seat)
> >> >>               return NULL;
> >> >>
> >> >>       wl_list_init(&pointer->resource_list);
> >> >> +     wl_list_init(&pointer->relative_resource_list);
> >> >>       wl_list_init(&pointer->focus_resource_list);
> >> >> +     wl_list_init(&pointer->relative_focus_resource_list);
> >> >>       weston_pointer_set_default_grab(pointer,
> >> >>                                       seat->compositor->default_pointer_grab);
> >> >>       wl_list_init(&pointer->focus_resource_listener.link);
> >> >> @@ -665,6 +750,7 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
> >> >>       struct wl_display *display = pointer->seat->compositor->wl_display;
> >> >>       uint32_t serial;
> >> >>       struct wl_list *focus_resource_list;
> >> >> +     struct wl_list *relative_focus_resource_list;
> >> >>       int refocus = 0;
> >> >>
> >> >>       if ((!pointer->focus && view) ||
> >> >> @@ -674,6 +760,7 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
> >> >>               refocus = 1;
> >> >>
> >> >>       focus_resource_list = &pointer->focus_resource_list;
> >> >> +     relative_focus_resource_list = &pointer->relative_focus_resource_list;
> >> >>
> >> >>       if (!wl_list_empty(focus_resource_list) && refocus) {
> >> >>               serial = wl_display_next_serial(display);
> >> >> @@ -683,6 +770,8 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
> >> >>               }
> >> >>
> >> >>               move_resources(&pointer->resource_list, focus_resource_list);
> >> >> +             move_resources(&pointer->relative_resource_list,
> >> >> +                            relative_focus_resource_list);
> >> >>       }
> >> >>
> >> >>       if (find_resource_for_view(&pointer->resource_list, view) && refocus) {
> >> >> @@ -700,6 +789,9 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
> >> >>               move_resources_for_client(focus_resource_list,
> >> >>                                         &pointer->resource_list,
> >> >>                                         surface_client);
> >> >> +             move_resources_for_client(relative_focus_resource_list,
> >> >> +                                       &pointer->relative_resource_list,
> >> >> +                                       surface_client);
> >> >>
> >> >>               wl_resource_for_each(resource, focus_resource_list) {
> >> >>                       wl_pointer_send_enter(resource,
> >> >> @@ -932,23 +1024,6 @@ weston_pointer_move_to(struct weston_pointer *pointer,
> >> >>  }
> >> >>
> >> >>  WL_EXPORT void
> >> >> -weston_pointer_motion_to_abs(struct weston_pointer *pointer,
> >> >> -                          struct weston_pointer_motion_event *event,
> >> >> -                          wl_fixed_t *x, wl_fixed_t *y)
> >> >> -{
> >> >> -     if (event->mask & WESTON_POINTER_MOTION_ABS) {
> >> >> -             *x = wl_fixed_from_double(event->x);
> >> >> -             *y = wl_fixed_from_double(event->y);
> >> >> -     } else if (event->mask & WESTON_POINTER_MOTION_REL) {
> >> >> -             *x = pointer->x + wl_fixed_from_double(event->dx);
> >> >> -             *y = pointer->y + wl_fixed_from_double(event->dy);
> >> >> -     } else {
> >> >> -             assert(!"invalid motion event");
> >> >> -             *x = *y = 0;
> >> >> -     }
> >> >> -}
> >> >> -
> >> >> -WL_EXPORT void
> >> >>  weston_pointer_move(struct weston_pointer *pointer,
> >> >>                   struct weston_pointer_motion_event *event)
> >> >>  {
> >> >> @@ -2008,6 +2083,72 @@ bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
> >> >>               wl_seat_send_name(resource, seat->seat_name);
> >> >>  }
> >> >>
> >> >> +static void
> >> >> +relative_pointer_release(struct wl_client *client,
> >> >> +                      struct wl_resource *resource)
> >> >> +{
> >> >> +     wl_resource_destroy(resource);
> >> >> +}
> >> >> +
> >> >> +static const struct _wl_relative_pointer_interface relative_pointer_interface = {
> >> >> +     relative_pointer_release
> >> >> +};
> >> >> +
> >> >> +static void
> >> >> +relative_pointer_manager_get_relative_pointer(struct wl_client *client,
> >> >> +                                           struct wl_resource *resource,
> >> >> +                                           uint32_t id,
> >> >> +                                           struct wl_resource *pointer_resource)
> >> >> +{
> >> >> +     struct weston_pointer *pointer =
> >> >> +             wl_resource_get_user_data(pointer_resource);
> >> >> +     struct wl_resource *cr;
> >> >> +     struct weston_view *focus;
> >> >> +
> >> >> +     cr = wl_resource_create(client, &_wl_relative_pointer_interface,
> >> >> +                             wl_resource_get_version(resource), id);
> >> >> +     if (cr == NULL) {
> >> >> +             wl_client_post_no_memory(client);
> >> >> +             return;
> >> >> +     }
> >> >> +
> >> >> +     /* May be moved to focused list later by either
> >> >> +      * weston_pointer_set_focus or directly if this client is already
> >> >> +      * focused */
> >> >> +     wl_list_insert(&pointer->relative_resource_list,
> >> >> +                    wl_resource_get_link(cr));
> >> >> +     wl_resource_set_implementation(cr, &relative_pointer_interface,
> >> >> +                                    pointer,
> >> >> +                                    unbind_resource);
> >> >> +
> >> >> +     focus = pointer->focus;
> >> >> +     if (focus && focus->surface->resource &&
> >> >> +         wl_resource_get_client(focus->surface->resource) == client) {
> >> >> +             wl_list_remove(wl_resource_get_link(cr));
> >> >> +             wl_list_insert(&pointer->relative_focus_resource_list,
> >> >> +                            wl_resource_get_link(cr));
> >> >> +     }
> >> >> +}
> >> >> +
> >> >> +static const struct _wl_relative_pointer_manager_interface relative_pointer_manager = {
> >> >> +     relative_pointer_manager_get_relative_pointer,
> >> >> +};
> >> >> +
> >> >> +static void
> >> >> +bind_relative_pointer_manager(struct wl_client *client, void *data,
> >> >> +                           uint32_t version, uint32_t id)
> >> >> +{
> >> >> +     struct weston_compositor *compositor = data;
> >> >> +     struct wl_resource *resource;
> >> >> +
> >> >> +     resource = wl_resource_create(client,
> >> >> +                                   &_wl_relative_pointer_manager_interface,
> >> >> +                                   1, id);
> >> >> +     wl_resource_set_implementation(resource, &relative_pointer_manager,
> >> >> +                                    compositor,
> >> >> +                                    NULL);
> >> >> +}
> >> >> +
> >> >>  #ifdef ENABLE_XKBCOMMON
> >> >>  int
> >> >>  weston_compositor_xkb_init(struct weston_compositor *ec,
> >> >> @@ -2429,3 +2570,14 @@ weston_seat_release(struct weston_seat *seat)
> >> >>
> >> >>       wl_signal_emit(&seat->destroy_signal, seat);
> >> >>  }
> >> >> +
> >> >> +int
> >> >> +weston_input_init(struct weston_compositor *compositor)
> >> >> +{
> >> >> +     if (!wl_global_create(compositor->wl_display,
> >> >> +                           &_wl_relative_pointer_manager_interface, 1,
> >> >> +                           compositor, bind_relative_pointer_manager))
> >> >> +             return -1;
> >> >> +
> >> >> +     return 0;
> >> >> +}
> >> >> --
> >> >> 2.1.4
On Thu, Jul 16, 2015 at 03:23:20PM +0800, Jonas Ådahl wrote:
> On Thu, Jul 16, 2015 at 03:37:30PM +0900, x414e54 wrote:
> > On Wed, Jul 15, 2015 at 11:55 AM, Peter Hutterer
> > <peter.hutterer@who-t.net> wrote:
> > > On Wed, Jul 15, 2015 at 08:23:09AM +0900, x414e54 wrote:
> > >> Hi,
> > >>
> > >> Just a quick questions:
> > >>
> > >> 1) Is there any way to un-normalize the values?
> > >
> > > not at this point, no.
> > > fwiw as of libinput 0.19 the normalization only applies to the accelerated
> > > delta, the unaccelerated one is generally in device-specific units. Except
> > > on touchpads, where we still normalize it to a 1000dpi mouse, we may review
> > > that at some point. but since the normalization is "magic", you can't
> > > unnormalize them.
> > 
> > Unaccelerated un-normalzied is fine. But it would be nice to have this
> > reflected in the wayland spec just to make sure it is consistent
> > between window managers.
> 
> I have no objections to removing the note about the compositor having
> applied the normalizations, partly because it is not correct when
> running on libinput anymore, but also because it might not be a good
> idea to be to specific about how they look as at some backends we might
> not be able to provide exactly that type of information (remote desktop
> for example).
> 
> > 
> > >
> > >> 2) What happens with >1000hz gaming mice for example which need
> > >> microsecond granularity timestamps?
> > >
> > > naïve question: do people notice the difference between 1000Hz and 2000Hz?
> > 
> > You could probably say the same for 500hz and 1000hz mice. I do not
> > think it is your/our place to say if someone would notice or not, some
> > people may some people might not.
> > 
> > Not necessarily mice but definitely when using head tracking and eye
> > tracking it is noticeable. Also it helps you to create more accurate
> > prediction and allows you to render frames ahead.
> > 
> > Considering the original events are reported in nanoseconds/ktime if
> > it came from evdev? (I may be wrong). It does not seem like too much
> > trouble just to pass the original nanosecond time along even if it is
> > in two 32 bit integers sec and nsec.
> 
> Libinput exposes the time value as a uint32_t in milleseconds. It gets
> the timestamp from a 'struct timeval' which is in microseconds. In other
> words, we'd need to expose the lost time data via additional API in
> libinput. I'm no input device expert so I'm not going to have any strong
> objections to adding more information, unless someone have an objective
> objection to it.
> 
> How correct are the timestamps from the kernel for such devices?

honestly not sure, but even if they're not as precise now any increase in
precision would automatically feed through to everything else in the stack
if we expose the time in finer-grained units. so adding a get_time_usec()
for all the events seems sensible. not sure about nsec being worthwhile
though.
Benjamin, what's the precision in HID?

Cheers,
   Peter

> > There is one mouse available called the Asus ROG Gladius. So there are
> > definitely people using it now.
> > 
> > >
> > > Cheers,
> > >    Peter
> > >
> > >> On Mon, Jun 29, 2015 at 3:54 PM, Peter Hutterer
> > >> <peter.hutterer@who-t.net> wrote:
> > >> > On Fri, Jun 26, 2015 at 12:38:01PM +0800, Jonas Ådahl wrote:
> > >> >> A wl_relative_pointer object is an extension to the wl_pointer interface
> > >> >> only used for emitting relative pointer events. It will only emit events
> > >> >> when the parent pointer has focus.
> > >> >>
> > >> >> To get a relative pointer object, use the get_relative_pointer request
> > >> >> of the global wl_relative_pointer_manager object. When stabilizing it
> > >> >> might make more sense to just add it to wl_seat instead of having a
> > >> >> single use global interface.
> > >> >>
> > >> >> All interface names are currently prefixed with underscore in order to
> > >> >> avoid any future conflicts with stable protocol.
> > >> >>
> > >> >> Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
> > >> >> ---
> > >> >>
> > >> >> Changes since v2:
> > >> >>
> > >> >>  * Updated copyright.
> > >> >>  * Updated the license text to corrected one.
> > >> >>  * Clarified that relative motion events are unaffected by clamping.
> > >> >>  * Clarified that pointer acceleration behaviour is device specific.
> > >> >>  * Clarified that the order of relative_motion and motion is not
> > >> >>    guaranteed.
> > >> >>  * Explained that button events etc are to be fetched from the
> > >> >>    corresponding wl_pointer object.
> > >> >>  * Clarified that relative motion events are in x/y coordinate space.
> > >> >>  * Added an 'unstable protocol' warning explaining compatibility etc.
> > >> >>
> > >> >>
> > >> >>  Makefile.am                   |   7 +-
> > >> >>  protocol/relative-pointer.xml | 127 ++++++++++++++++++++++++++++
> > >> >>  src/compositor.c              |   3 +
> > >> >>  src/compositor.h              |   5 ++
> > >> >>  src/input.c                   | 186 ++++++++++++++++++++++++++++++++++++++----
> > >> >>  5 files changed, 309 insertions(+), 19 deletions(-)
> > >> >>  create mode 100644 protocol/relative-pointer.xml
> > >> >>
> > >> >> diff --git a/Makefile.am b/Makefile.am
> > >> >> index 0a30cb4..70c436f 100644
> > >> >> --- a/Makefile.am
> > >> >> +++ b/Makefile.am
> > >> >> @@ -105,7 +105,9 @@ nodist_weston_SOURCES =                                   \
> > >> >>       protocol/presentation_timing-protocol.c         \
> > >> >>       protocol/presentation_timing-server-protocol.h  \
> > >> >>       protocol/scaler-protocol.c                      \
> > >> >> -     protocol/scaler-server-protocol.h
> > >> >> +     protocol/scaler-server-protocol.h               \
> > >> >> +     protocol/relative-pointer-protocol.c            \
> > >> >> +     protocol/relative-pointer-server-protocol.h
> > >> >>
> > >> >>  BUILT_SOURCES += $(nodist_weston_SOURCES)
> > >> >>
> > >> >> @@ -1183,7 +1185,8 @@ EXTRA_DIST +=                                   \
> > >> >>       protocol/presentation_timing.xml        \
> > >> >>       protocol/scaler.xml                     \
> > >> >>       protocol/ivi-application.xml            \
> > >> >> -     protocol/ivi-hmi-controller.xml
> > >> >> +     protocol/ivi-hmi-controller.xml         \
> > >> >> +     protocol/relative-pointer.xml
> > >> >>
> > >> >>  #
> > >> >>  # manual test modules in tests subdirectory
> > >> >> diff --git a/protocol/relative-pointer.xml b/protocol/relative-pointer.xml
> > >> >> new file mode 100644
> > >> >> index 0000000..185d33b
> > >> >> --- /dev/null
> > >> >> +++ b/protocol/relative-pointer.xml
> > >> >> @@ -0,0 +1,127 @@
> > >> >> +<?xml version="1.0" encoding="UTF-8"?>
> > >> >> +<protocol name="relative_pointer">
> > >> >> +
> > >> >> +  <copyright>
> > >> >> +    Copyright © 2014      Jonas Ådahl
> > >> >> +    Copyright © 2015      Red Hat Inc.
> > >> >> +
> > >> >> +    Permission is hereby granted, free of charge, to any person obtaining a
> > >> >> +    copy of this software and associated documentation files (the "Software"),
> > >> >> +    to deal in the Software without restriction, including without limitation
> > >> >> +    the rights to use, copy, modify, merge, publish, distribute, sublicense,
> > >> >> +    and/or sell copies of the Software, and to permit persons to whom the
> > >> >> +    Software is furnished to do so, subject to the following conditions:
> > >> >> +
> > >> >> +    The above copyright notice and this permission notice (including the next
> > >> >> +    paragraph) shall be included in all copies or substantial portions of the
> > >> >> +    Software.
> > >> >> +
> > >> >> +    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> > >> >> +    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> > >> >> +    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> > >> >> +    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> > >> >> +    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> > >> >> +    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> > >> >> +    DEALINGS IN THE SOFTWARE.
> > >> >> +  </copyright>
> > >> >> +
> > >> >> +  <interface name="_wl_relative_pointer_manager" version="1">
> > >> >> +    <description summary="get relative pointer objects">
> > >> >> +      A global interface used for getting the relative pointer object for a
> > >> >> +      given seat.
> > >> >> +
> > >> >> +      Warning! The protocol described in this file is experimental. Each version
> > >> >> +      of this protocol should be considered incompatible with any other version,
> > >> >> +      and a client binding to a version different to the one advertised will be
> > >> >> +      terminated. When the protocol is stabalized, backward compatibility is
> > >> >
> > >> > typo: stabilized, but I would say "once the protocol is declared stable"
> > >> > anyway
> > >> >
> > >> > Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
> > >> > otherwise
> > >> >
> > >> > Cheers,
> > >> >    Peter
> > >> >
> > >> >> +      guaranteed, the '_' prefix will be removed from the name and the version
> > >> >> +      will be reset to 1.
> > >> >> +    </description>
> > >> >> +
> > >> >> +    <request name="get_relative_pointer">
> > >> >> +      <description summary="get a relative pointer object">
> > >> >> +        Create a relative pointer interface given a wl_pointer object. See
> > >> >> +        the wl_relative_pointer interface for more details.
> > >> >> +      </description>
> > >> >> +
> > >> >> +      <arg name="id" type="new_id" interface="_wl_relative_pointer"/>
> > >> >> +      <arg name="pointer" type="object" interface="wl_pointer"/>
> > >> >> +    </request>
> > >> >> +  </interface>
> > >> >> +
> > >> >> +  <interface name="_wl_relative_pointer" version="1">
> > >> >> +    <description summary="relative pointer object">
> > >> >> +      A wl_relative_pointer object is an extension to the wl_pointer interface
> > >> >> +      used for emitting relative pointer events. It shares the same focus as
> > >> >> +      wl_pointer objects of the same seat and will only emit events when it
> > >> >> +      has focus.
> > >> >> +    </description>
> > >> >> +
> > >> >> +    <request name="release" type="destructor">
> > >> >> +      <description summary="release the relative pointer object"/>
> > >> >> +    </request>
> > >> >> +
> > >> >> +    <event name="relative_motion">
> > >> >> +      <description summary="relative pointer motion">
> > >> >> +        Relative x/y pointer motion in from the pointer of the seat associated
> > >> >> +        with this object.
> > >> >> +
> > >> >> +        A relative motion is in the same dimension as regular wl_pointer motion
> > >> >> +        events, except they do not represent an absolute position. For example,
> > >> >> +        moving a pointer from (x, y) to (x', y') would have the equivalent
> > >> >> +        relative motion (x' - x, y' - y). If a pointer motion caused the
> > >> >> +        absolute pointer position to be clipped by for example the edge of the
> > >> >> +        monitor, the relative motion is unaffected by the clipping and will
> > >> >> +        represent the unclipped motion.
> > >> >> +
> > >> >> +        This event also contains non-accelerated motion deltas. The
> > >> >> +        non-accelerated delta is, when applicable, the regular pointer motion
> > >> >> +        delta as it was before having applied motion acceleration
> > >> >> +        transformations. The compositor will have applied the same processing
> > >> >> +        (such as normalization) meaning the events will have roughly the same
> > >> >> +        magnitude as accelerated motion events.
> > >> >> +
> > >> >> +        Note that the non-accelerated delta does not represent 'raw' events as
> > >> >> +        they were read from some device. Pointer motion acceleration is device-
> > >> >> +        and configuration-specific and non-accelerated deltas and accelerated
> > >> >> +        deltas may have the same value on some devices.
> > >> >> +
> > >> >> +        Relative motions are not coupled to wl_pointer.motion events, and can
> > >> >> +        be sent in combination with such events, but also independently. There
> > >> >> +        may also be scenarious where wl_pointer.motion is sent, but there is no
> > >> >> +        relative motion. The order of an absolute and relative motion event
> > >> >> +        originating from the same physical motion is not guaranteed.
> > >> >> +
> > >> >> +        The motion vectors are encoded as double fixed point values.
> > >> >> +
> > >> >> +        A double fixed point value is a 64 bit data type encoded as two separate
> > >> >> +        signed 32 bit integers. The integral part of the value is stored in one
> > >> >> +        of the integers and the fractional part in the other.
> > >> >> +
> > >> >> +        If the client needs button events, it can receive them from a wl_pointer
> > >> >> +        object of the same seat that the wl_relative_pointer object is
> > >> >> +        associated with.
> > >> >> +      </description>
> > >> >> +
> > >> >> +      <arg name="time" type="uint"
> > >> >> +           summary="timestamp with millisecond granularity"/>
> > >> >> +      <arg name="dx_int" type="int"
> > >> >> +           summary="integral part of the x component of the motion vector"/>
> > >> >> +      <arg name="dx_frac" type="int"
> > >> >> +           summary="fractional part of the x component of the motion vector"/>
> > >> >> +      <arg name="dy_int" type="int"
> > >> >> +           summary="integral part of the y component of the motion vector"/>
> > >> >> +      <arg name="dy_frac" type="int"
> > >> >> +           summary="fractional part of the y component of the motion vector"/>
> > >> >> +      <arg name="dx_unaccel_int" type="int"
> > >> >> +           summary="integral part of the x component of the unaccelerated motion vector"/>
> > >> >> +      <arg name="dx_unaccel_frac" type="int"
> > >> >> +           summary="fractional part of the x component of the unaccelerated motion vector"/>
> > >> >> +      <arg name="dy_unaccel_int" type="int"
> > >> >> +           summary="integral part of the y component of the unaccelerated motion vector"/>
> > >> >> +      <arg name="dy_unaccel_frac" type="int"
> > >> >> +           summary="fractional part of the y component of the unaccelerated motion vector"/>
> > >> >> +    </event>
> > >> >> +  </interface>
> > >> >> +
> > >> >> +</protocol>
> > >> >> diff --git a/src/compositor.c b/src/compositor.c
> > >> >> index 5594d30..b462531 100644
> > >> >> --- a/src/compositor.c
> > >> >> +++ b/src/compositor.c
> > >> >> @@ -4560,6 +4560,9 @@ weston_compositor_init(struct weston_compositor *ec,
> > >> >>       weston_plane_init(&ec->primary_plane, ec, 0, 0);
> > >> >>       weston_compositor_stack_plane(ec, &ec->primary_plane, NULL);
> > >> >>
> > >> >> +     if (weston_input_init(ec) != 0)
> > >> >> +             return -1;
> > >> >> +
> > >> >>       s = weston_config_get_section(ec->config, "keyboard", NULL, NULL);
> > >> >>       weston_config_section_get_string(s, "keymap_rules",
> > >> >>                                        (char **) &xkb_names.rules, NULL);
> > >> >> diff --git a/src/compositor.h b/src/compositor.h
> > >> >> index 331b758..55cc88f 100644
> > >> >> --- a/src/compositor.h
> > >> >> +++ b/src/compositor.h
> > >> >> @@ -340,7 +340,9 @@ struct weston_pointer {
> > >> >>       struct weston_seat *seat;
> > >> >>
> > >> >>       struct wl_list resource_list;
> > >> >> +     struct wl_list relative_resource_list;
> > >> >>       struct wl_list focus_resource_list;
> > >> >> +     struct wl_list relative_focus_resource_list;
> > >> >>       struct weston_view *focus;
> > >> >>       uint32_t focus_serial;
> > >> >>       struct wl_listener focus_view_listener;
> > >> >> @@ -1584,6 +1586,9 @@ weston_output_mode_switch_to_native(struct weston_output *output);
> > >> >>  int
> > >> >>  noop_renderer_init(struct weston_compositor *ec);
> > >> >>
> > >> >> +int
> > >> >> +weston_input_init(struct weston_compositor *compositor);
> > >> >> +
> > >> >>  struct weston_compositor *
> > >> >>  backend_init(struct wl_display *display, int *argc, char *argv[],
> > >> >>            struct weston_config *config);
> > >> >> diff --git a/src/input.c b/src/input.c
> > >> >> index 9131287..b48a6c9 100644
> > >> >> --- a/src/input.c
> > >> >> +++ b/src/input.c
> > >> >> @@ -32,7 +32,9 @@
> > >> >>  #include <limits.h>
> > >> >>
> > >> >>  #include "../shared/os-compatibility.h"
> > >> >> +#include "../shared/util.h"
> > >> >>  #include "compositor.h"
> > >> >> +#include "protocol/relative-pointer-server-protocol.h"
> > >> >>
> > >> >>  static void
> > >> >>  empty_region(pixman_region32_t *region)
> > >> >> @@ -47,6 +49,49 @@ static void unbind_resource(struct wl_resource *resource)
> > >> >>  }
> > >> >>
> > >> >>  WL_EXPORT void
> > >> >> +weston_pointer_motion_to_abs(struct weston_pointer *pointer,
> > >> >> +                          struct weston_pointer_motion_event *event,
> > >> >> +                          wl_fixed_t *x, wl_fixed_t *y)
> > >> >> +{
> > >> >> +     if (event->mask & WESTON_POINTER_MOTION_ABS) {
> > >> >> +             *x = wl_fixed_from_double(event->x);
> > >> >> +             *y = wl_fixed_from_double(event->y);
> > >> >> +     } else if (event->mask & WESTON_POINTER_MOTION_REL) {
> > >> >> +             *x = pointer->x + wl_fixed_from_double(event->dx);
> > >> >> +             *y = pointer->y + wl_fixed_from_double(event->dy);
> > >> >> +     } else {
> > >> >> +             assert(!"invalid motion event");
> > >> >> +             *x = *y = 0;
> > >> >> +     }
> > >> >> +}
> > >> >> +
> > >> >> +static int
> > >> >> +weston_pointer_motion_to_rel(struct weston_pointer *pointer,
> > >> >> +                          struct weston_pointer_motion_event *event,
> > >> >> +                          double *dx, double *dy,
> > >> >> +                          double *dx_unaccel, double *dy_unaccel)
> > >> >> +{
> > >> >> +     if (event->mask & WESTON_POINTER_MOTION_REL &&
> > >> >> +         event->mask & WESTON_POINTER_MOTION_REL_NOACCEL) {
> > >> >> +             *dx = event->dx;
> > >> >> +             *dy = event->dy;
> > >> >> +             *dx_unaccel = event->dx_unaccel;
> > >> >> +             *dy_unaccel = event->dy_unaccel;
> > >> >> +             return 1;
> > >> >> +     } else if (event->mask & WESTON_POINTER_MOTION_REL) {
> > >> >> +             *dx_unaccel = *dx = event->dx;
> > >> >> +             *dy_unaccel = *dy = event->dy;
> > >> >> +             return 1;
> > >> >> +     } else if (event->mask & WESTON_POINTER_MOTION_REL_NOACCEL) {
> > >> >> +             *dx_unaccel = *dx = event->dx_unaccel;
> > >> >> +             *dy_unaccel = *dy = event->dy_unaccel;
> > >> >> +             return 1;
> > >> >> +     } else {
> > >> >> +             return 0;
> > >> >> +     }
> > >> >> +}
> > >> >> +
> > >> >> +WL_EXPORT void
> > >> >>  weston_seat_repick(struct weston_seat *seat)
> > >> >>  {
> > >> >>       const struct weston_pointer *pointer = seat->pointer;
> > >> >> @@ -162,6 +207,42 @@ default_grab_pointer_focus(struct weston_pointer_grab *grab)
> > >> >>  }
> > >> >>
> > >> >>  static void
> > >> >> +weston_pointer_send_relative_motion(struct weston_pointer *pointer,
> > >> >> +                                 uint32_t time,
> > >> >> +                                 struct weston_pointer_motion_event *event)
> > >> >> +{
> > >> >> +     double dx, dy, dx_unaccel, dy_unaccel;
> > >> >> +     int32_t dx_int, dx_frac;
> > >> >> +     int32_t dy_int, dy_frac;
> > >> >> +     int32_t dx_unaccel_int, dx_unaccel_frac;
> > >> >> +     int32_t dy_unaccel_int, dy_unaccel_frac;
> > >> >> +     struct wl_list *resource_list;
> > >> >> +     struct wl_resource *resource;
> > >> >> +
> > >> >> +     if (weston_pointer_motion_to_rel(pointer, event,
> > >> >> +                                      &dx, &dy,
> > >> >> +                                      &dx_unaccel, &dy_unaccel)) {
> > >> >> +             resource_list = &pointer->relative_focus_resource_list;
> > >> >> +             wl_double_fixed_from_double(dx, &dx_int, &dx_frac);
> > >> >> +             wl_double_fixed_from_double(dy, &dy_int, &dy_frac);
> > >> >> +             wl_double_fixed_from_double(dx_unaccel,
> > >> >> +                                         &dx_unaccel_int,
> > >> >> +                                         &dx_unaccel_frac);
> > >> >> +             wl_double_fixed_from_double(dy_unaccel,
> > >> >> +                                         &dy_unaccel_int,
> > >> >> +                                         &dy_unaccel_frac);
> > >> >> +             wl_resource_for_each(resource, resource_list) {
> > >> >> +                     _wl_relative_pointer_send_relative_motion(
> > >> >> +                             resource, time,
> > >> >> +                             dx_int, dx_frac,
> > >> >> +                             dy_int, dy_frac,
> > >> >> +                             dx_unaccel_int, dx_unaccel_frac,
> > >> >> +                             dy_unaccel_int, dy_unaccel_frac);
> > >> >> +             }
> > >> >> +     }
> > >> >> +}
> > >> >> +
> > >> >> +static void
> > >> >>  default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
> > >> >>                           struct weston_pointer_motion_event *event)
> > >> >>  {
> > >> >> @@ -187,6 +268,8 @@ default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
> > >> >>                                              pointer->sx, pointer->sy);
> > >> >>               }
> > >> >>       }
> > >> >> +
> > >> >> +     weston_pointer_send_relative_motion(pointer, time, event);
> > >> >>  }
> > >> >>
> > >> >>  static void
> > >> >> @@ -503,7 +586,9 @@ weston_pointer_create(struct weston_seat *seat)
> > >> >>               return NULL;
> > >> >>
> > >> >>       wl_list_init(&pointer->resource_list);
> > >> >> +     wl_list_init(&pointer->relative_resource_list);
> > >> >>       wl_list_init(&pointer->focus_resource_list);
> > >> >> +     wl_list_init(&pointer->relative_focus_resource_list);
> > >> >>       weston_pointer_set_default_grab(pointer,
> > >> >>                                       seat->compositor->default_pointer_grab);
> > >> >>       wl_list_init(&pointer->focus_resource_listener.link);
> > >> >> @@ -665,6 +750,7 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
> > >> >>       struct wl_display *display = pointer->seat->compositor->wl_display;
> > >> >>       uint32_t serial;
> > >> >>       struct wl_list *focus_resource_list;
> > >> >> +     struct wl_list *relative_focus_resource_list;
> > >> >>       int refocus = 0;
> > >> >>
> > >> >>       if ((!pointer->focus && view) ||
> > >> >> @@ -674,6 +760,7 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
> > >> >>               refocus = 1;
> > >> >>
> > >> >>       focus_resource_list = &pointer->focus_resource_list;
> > >> >> +     relative_focus_resource_list = &pointer->relative_focus_resource_list;
> > >> >>
> > >> >>       if (!wl_list_empty(focus_resource_list) && refocus) {
> > >> >>               serial = wl_display_next_serial(display);
> > >> >> @@ -683,6 +770,8 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
> > >> >>               }
> > >> >>
> > >> >>               move_resources(&pointer->resource_list, focus_resource_list);
> > >> >> +             move_resources(&pointer->relative_resource_list,
> > >> >> +                            relative_focus_resource_list);
> > >> >>       }
> > >> >>
> > >> >>       if (find_resource_for_view(&pointer->resource_list, view) && refocus) {
> > >> >> @@ -700,6 +789,9 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
> > >> >>               move_resources_for_client(focus_resource_list,
> > >> >>                                         &pointer->resource_list,
> > >> >>                                         surface_client);
> > >> >> +             move_resources_for_client(relative_focus_resource_list,
> > >> >> +                                       &pointer->relative_resource_list,
> > >> >> +                                       surface_client);
> > >> >>
> > >> >>               wl_resource_for_each(resource, focus_resource_list) {
> > >> >>                       wl_pointer_send_enter(resource,
> > >> >> @@ -932,23 +1024,6 @@ weston_pointer_move_to(struct weston_pointer *pointer,
> > >> >>  }
> > >> >>
> > >> >>  WL_EXPORT void
> > >> >> -weston_pointer_motion_to_abs(struct weston_pointer *pointer,
> > >> >> -                          struct weston_pointer_motion_event *event,
> > >> >> -                          wl_fixed_t *x, wl_fixed_t *y)
> > >> >> -{
> > >> >> -     if (event->mask & WESTON_POINTER_MOTION_ABS) {
> > >> >> -             *x = wl_fixed_from_double(event->x);
> > >> >> -             *y = wl_fixed_from_double(event->y);
> > >> >> -     } else if (event->mask & WESTON_POINTER_MOTION_REL) {
> > >> >> -             *x = pointer->x + wl_fixed_from_double(event->dx);
> > >> >> -             *y = pointer->y + wl_fixed_from_double(event->dy);
> > >> >> -     } else {
> > >> >> -             assert(!"invalid motion event");
> > >> >> -             *x = *y = 0;
> > >> >> -     }
> > >> >> -}
> > >> >> -
> > >> >> -WL_EXPORT void
> > >> >>  weston_pointer_move(struct weston_pointer *pointer,
> > >> >>                   struct weston_pointer_motion_event *event)
> > >> >>  {
> > >> >> @@ -2008,6 +2083,72 @@ bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
> > >> >>               wl_seat_send_name(resource, seat->seat_name);
> > >> >>  }
> > >> >>
> > >> >> +static void
> > >> >> +relative_pointer_release(struct wl_client *client,
> > >> >> +                      struct wl_resource *resource)
> > >> >> +{
> > >> >> +     wl_resource_destroy(resource);
> > >> >> +}
> > >> >> +
> > >> >> +static const struct _wl_relative_pointer_interface relative_pointer_interface = {
> > >> >> +     relative_pointer_release
> > >> >> +};
> > >> >> +
> > >> >> +static void
> > >> >> +relative_pointer_manager_get_relative_pointer(struct wl_client *client,
> > >> >> +                                           struct wl_resource *resource,
> > >> >> +                                           uint32_t id,
> > >> >> +                                           struct wl_resource *pointer_resource)
> > >> >> +{
> > >> >> +     struct weston_pointer *pointer =
> > >> >> +             wl_resource_get_user_data(pointer_resource);
> > >> >> +     struct wl_resource *cr;
> > >> >> +     struct weston_view *focus;
> > >> >> +
> > >> >> +     cr = wl_resource_create(client, &_wl_relative_pointer_interface,
> > >> >> +                             wl_resource_get_version(resource), id);
> > >> >> +     if (cr == NULL) {
> > >> >> +             wl_client_post_no_memory(client);
> > >> >> +             return;
> > >> >> +     }
> > >> >> +
> > >> >> +     /* May be moved to focused list later by either
> > >> >> +      * weston_pointer_set_focus or directly if this client is already
> > >> >> +      * focused */
> > >> >> +     wl_list_insert(&pointer->relative_resource_list,
> > >> >> +                    wl_resource_get_link(cr));
> > >> >> +     wl_resource_set_implementation(cr, &relative_pointer_interface,
> > >> >> +                                    pointer,
> > >> >> +                                    unbind_resource);
> > >> >> +
> > >> >> +     focus = pointer->focus;
> > >> >> +     if (focus && focus->surface->resource &&
> > >> >> +         wl_resource_get_client(focus->surface->resource) == client) {
> > >> >> +             wl_list_remove(wl_resource_get_link(cr));
> > >> >> +             wl_list_insert(&pointer->relative_focus_resource_list,
> > >> >> +                            wl_resource_get_link(cr));
> > >> >> +     }
> > >> >> +}
> > >> >> +
> > >> >> +static const struct _wl_relative_pointer_manager_interface relative_pointer_manager = {
> > >> >> +     relative_pointer_manager_get_relative_pointer,
> > >> >> +};
> > >> >> +
> > >> >> +static void
> > >> >> +bind_relative_pointer_manager(struct wl_client *client, void *data,
> > >> >> +                           uint32_t version, uint32_t id)
> > >> >> +{
> > >> >> +     struct weston_compositor *compositor = data;
> > >> >> +     struct wl_resource *resource;
> > >> >> +
> > >> >> +     resource = wl_resource_create(client,
> > >> >> +                                   &_wl_relative_pointer_manager_interface,
> > >> >> +                                   1, id);
> > >> >> +     wl_resource_set_implementation(resource, &relative_pointer_manager,
> > >> >> +                                    compositor,
> > >> >> +                                    NULL);
> > >> >> +}
> > >> >> +
> > >> >>  #ifdef ENABLE_XKBCOMMON
> > >> >>  int
> > >> >>  weston_compositor_xkb_init(struct weston_compositor *ec,
> > >> >> @@ -2429,3 +2570,14 @@ weston_seat_release(struct weston_seat *seat)
> > >> >>
> > >> >>       wl_signal_emit(&seat->destroy_signal, seat);
> > >> >>  }
> > >> >> +
> > >> >> +int
> > >> >> +weston_input_init(struct weston_compositor *compositor)
> > >> >> +{
> > >> >> +     if (!wl_global_create(compositor->wl_display,
> > >> >> +                           &_wl_relative_pointer_manager_interface, 1,
> > >> >> +                           compositor, bind_relative_pointer_manager))
> > >> >> +             return -1;
> > >> >> +
> > >> >> +     return 0;
> > >> >> +}
> > >> >> --
> > >> >> 2.1.4
On Thu, Jul 16, 2015 at 3:37 AM, Peter Hutterer
<peter.hutterer@who-t.net> wrote:
> On Thu, Jul 16, 2015 at 03:23:20PM +0800, Jonas Ådahl wrote:
>> On Thu, Jul 16, 2015 at 03:37:30PM +0900, x414e54 wrote:
>> > On Wed, Jul 15, 2015 at 11:55 AM, Peter Hutterer
>> > <peter.hutterer@who-t.net> wrote:
>> > > On Wed, Jul 15, 2015 at 08:23:09AM +0900, x414e54 wrote:
>> > >> Hi,
>> > >>
>> > >> Just a quick questions:
>> > >>
>> > >> 1) Is there any way to un-normalize the values?
>> > >
>> > > not at this point, no.
>> > > fwiw as of libinput 0.19 the normalization only applies to the accelerated
>> > > delta, the unaccelerated one is generally in device-specific units. Except
>> > > on touchpads, where we still normalize it to a 1000dpi mouse, we may review
>> > > that at some point. but since the normalization is "magic", you can't
>> > > unnormalize them.
>> >
>> > Unaccelerated un-normalzied is fine. But it would be nice to have this
>> > reflected in the wayland spec just to make sure it is consistent
>> > between window managers.
>>
>> I have no objections to removing the note about the compositor having
>> applied the normalizations, partly because it is not correct when
>> running on libinput anymore, but also because it might not be a good
>> idea to be to specific about how they look as at some backends we might
>> not be able to provide exactly that type of information (remote desktop
>> for example).
>>
>> >
>> > >
>> > >> 2) What happens with >1000hz gaming mice for example which need
>> > >> microsecond granularity timestamps?
>> > >
>> > > naïve question: do people notice the difference between 1000Hz and 2000Hz?
>> >
>> > You could probably say the same for 500hz and 1000hz mice. I do not
>> > think it is your/our place to say if someone would notice or not, some
>> > people may some people might not.
>> >
>> > Not necessarily mice but definitely when using head tracking and eye
>> > tracking it is noticeable. Also it helps you to create more accurate
>> > prediction and allows you to render frames ahead.
>> >
>> > Considering the original events are reported in nanoseconds/ktime if
>> > it came from evdev? (I may be wrong). It does not seem like too much
>> > trouble just to pass the original nanosecond time along even if it is
>> > in two 32 bit integers sec and nsec.
>>
>> Libinput exposes the time value as a uint32_t in milleseconds. It gets
>> the timestamp from a 'struct timeval' which is in microseconds. In other
>> words, we'd need to expose the lost time data via additional API in
>> libinput. I'm no input device expert so I'm not going to have any strong
>> objections to adding more information, unless someone have an objective
>> objection to it.
>>
>> How correct are the timestamps from the kernel for such devices?
>
> honestly not sure, but even if they're not as precise now any increase in
> precision would automatically feed through to everything else in the stack
> if we expose the time in finer-grained units. so adding a get_time_usec()
> for all the events seems sensible. not sure about nsec being worthwhile
> though.
> Benjamin, what's the precision in HID?
>

There is no formal rule for HID. It depends on the USB connection and speed.
For most of generic unifying Logitech devices they are reporting one
report every 8 ms (125Hz). But Logitech had to develop special
receivers for their gaming mice to be able to report 1000Hz. And those
1000Hz mice are still using HID.
So I believe if the hardware makers were capable of reporting 100K Hz,
they would do it :)

Cheers,
Benjamin

> Cheers,
>    Peter
>
>> > There is one mouse available called the Asus ROG Gladius. So there are
>> > definitely people using it now.
>> >
>> > >
>> > > Cheers,
>> > >    Peter
>> > >
>> > >> On Mon, Jun 29, 2015 at 3:54 PM, Peter Hutterer
>> > >> <peter.hutterer@who-t.net> wrote:
>> > >> > On Fri, Jun 26, 2015 at 12:38:01PM +0800, Jonas Ådahl wrote:
>> > >> >> A wl_relative_pointer object is an extension to the wl_pointer interface
>> > >> >> only used for emitting relative pointer events. It will only emit events
>> > >> >> when the parent pointer has focus.
>> > >> >>
>> > >> >> To get a relative pointer object, use the get_relative_pointer request
>> > >> >> of the global wl_relative_pointer_manager object. When stabilizing it
>> > >> >> might make more sense to just add it to wl_seat instead of having a
>> > >> >> single use global interface.
>> > >> >>
>> > >> >> All interface names are currently prefixed with underscore in order to
>> > >> >> avoid any future conflicts with stable protocol.
>> > >> >>
>> > >> >> Signed-off-by: Jonas Ådahl <jadahl@gmail.com>
>> > >> >> ---
>> > >> >>
>> > >> >> Changes since v2:
>> > >> >>
>> > >> >>  * Updated copyright.
>> > >> >>  * Updated the license text to corrected one.
>> > >> >>  * Clarified that relative motion events are unaffected by clamping.
>> > >> >>  * Clarified that pointer acceleration behaviour is device specific.
>> > >> >>  * Clarified that the order of relative_motion and motion is not
>> > >> >>    guaranteed.
>> > >> >>  * Explained that button events etc are to be fetched from the
>> > >> >>    corresponding wl_pointer object.
>> > >> >>  * Clarified that relative motion events are in x/y coordinate space.
>> > >> >>  * Added an 'unstable protocol' warning explaining compatibility etc.
>> > >> >>
>> > >> >>
>> > >> >>  Makefile.am                   |   7 +-
>> > >> >>  protocol/relative-pointer.xml | 127 ++++++++++++++++++++++++++++
>> > >> >>  src/compositor.c              |   3 +
>> > >> >>  src/compositor.h              |   5 ++
>> > >> >>  src/input.c                   | 186 ++++++++++++++++++++++++++++++++++++++----
>> > >> >>  5 files changed, 309 insertions(+), 19 deletions(-)
>> > >> >>  create mode 100644 protocol/relative-pointer.xml
>> > >> >>
>> > >> >> diff --git a/Makefile.am b/Makefile.am
>> > >> >> index 0a30cb4..70c436f 100644
>> > >> >> --- a/Makefile.am
>> > >> >> +++ b/Makefile.am
>> > >> >> @@ -105,7 +105,9 @@ nodist_weston_SOURCES =                                   \
>> > >> >>       protocol/presentation_timing-protocol.c         \
>> > >> >>       protocol/presentation_timing-server-protocol.h  \
>> > >> >>       protocol/scaler-protocol.c                      \
>> > >> >> -     protocol/scaler-server-protocol.h
>> > >> >> +     protocol/scaler-server-protocol.h               \
>> > >> >> +     protocol/relative-pointer-protocol.c            \
>> > >> >> +     protocol/relative-pointer-server-protocol.h
>> > >> >>
>> > >> >>  BUILT_SOURCES += $(nodist_weston_SOURCES)
>> > >> >>
>> > >> >> @@ -1183,7 +1185,8 @@ EXTRA_DIST +=                                   \
>> > >> >>       protocol/presentation_timing.xml        \
>> > >> >>       protocol/scaler.xml                     \
>> > >> >>       protocol/ivi-application.xml            \
>> > >> >> -     protocol/ivi-hmi-controller.xml
>> > >> >> +     protocol/ivi-hmi-controller.xml         \
>> > >> >> +     protocol/relative-pointer.xml
>> > >> >>
>> > >> >>  #
>> > >> >>  # manual test modules in tests subdirectory
>> > >> >> diff --git a/protocol/relative-pointer.xml b/protocol/relative-pointer.xml
>> > >> >> new file mode 100644
>> > >> >> index 0000000..185d33b
>> > >> >> --- /dev/null
>> > >> >> +++ b/protocol/relative-pointer.xml
>> > >> >> @@ -0,0 +1,127 @@
>> > >> >> +<?xml version="1.0" encoding="UTF-8"?>
>> > >> >> +<protocol name="relative_pointer">
>> > >> >> +
>> > >> >> +  <copyright>
>> > >> >> +    Copyright © 2014      Jonas Ådahl
>> > >> >> +    Copyright © 2015      Red Hat Inc.
>> > >> >> +
>> > >> >> +    Permission is hereby granted, free of charge, to any person obtaining a
>> > >> >> +    copy of this software and associated documentation files (the "Software"),
>> > >> >> +    to deal in the Software without restriction, including without limitation
>> > >> >> +    the rights to use, copy, modify, merge, publish, distribute, sublicense,
>> > >> >> +    and/or sell copies of the Software, and to permit persons to whom the
>> > >> >> +    Software is furnished to do so, subject to the following conditions:
>> > >> >> +
>> > >> >> +    The above copyright notice and this permission notice (including the next
>> > >> >> +    paragraph) shall be included in all copies or substantial portions of the
>> > >> >> +    Software.
>> > >> >> +
>> > >> >> +    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
>> > >> >> +    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
>> > >> >> +    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
>> > >> >> +    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
>> > >> >> +    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
>> > >> >> +    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
>> > >> >> +    DEALINGS IN THE SOFTWARE.
>> > >> >> +  </copyright>
>> > >> >> +
>> > >> >> +  <interface name="_wl_relative_pointer_manager" version="1">
>> > >> >> +    <description summary="get relative pointer objects">
>> > >> >> +      A global interface used for getting the relative pointer object for a
>> > >> >> +      given seat.
>> > >> >> +
>> > >> >> +      Warning! The protocol described in this file is experimental. Each version
>> > >> >> +      of this protocol should be considered incompatible with any other version,
>> > >> >> +      and a client binding to a version different to the one advertised will be
>> > >> >> +      terminated. When the protocol is stabalized, backward compatibility is
>> > >> >
>> > >> > typo: stabilized, but I would say "once the protocol is declared stable"
>> > >> > anyway
>> > >> >
>> > >> > Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
>> > >> > otherwise
>> > >> >
>> > >> > Cheers,
>> > >> >    Peter
>> > >> >
>> > >> >> +      guaranteed, the '_' prefix will be removed from the name and the version
>> > >> >> +      will be reset to 1.
>> > >> >> +    </description>
>> > >> >> +
>> > >> >> +    <request name="get_relative_pointer">
>> > >> >> +      <description summary="get a relative pointer object">
>> > >> >> +        Create a relative pointer interface given a wl_pointer object. See
>> > >> >> +        the wl_relative_pointer interface for more details.
>> > >> >> +      </description>
>> > >> >> +
>> > >> >> +      <arg name="id" type="new_id" interface="_wl_relative_pointer"/>
>> > >> >> +      <arg name="pointer" type="object" interface="wl_pointer"/>
>> > >> >> +    </request>
>> > >> >> +  </interface>
>> > >> >> +
>> > >> >> +  <interface name="_wl_relative_pointer" version="1">
>> > >> >> +    <description summary="relative pointer object">
>> > >> >> +      A wl_relative_pointer object is an extension to the wl_pointer interface
>> > >> >> +      used for emitting relative pointer events. It shares the same focus as
>> > >> >> +      wl_pointer objects of the same seat and will only emit events when it
>> > >> >> +      has focus.
>> > >> >> +    </description>
>> > >> >> +
>> > >> >> +    <request name="release" type="destructor">
>> > >> >> +      <description summary="release the relative pointer object"/>
>> > >> >> +    </request>
>> > >> >> +
>> > >> >> +    <event name="relative_motion">
>> > >> >> +      <description summary="relative pointer motion">
>> > >> >> +        Relative x/y pointer motion in from the pointer of the seat associated
>> > >> >> +        with this object.
>> > >> >> +
>> > >> >> +        A relative motion is in the same dimension as regular wl_pointer motion
>> > >> >> +        events, except they do not represent an absolute position. For example,
>> > >> >> +        moving a pointer from (x, y) to (x', y') would have the equivalent
>> > >> >> +        relative motion (x' - x, y' - y). If a pointer motion caused the
>> > >> >> +        absolute pointer position to be clipped by for example the edge of the
>> > >> >> +        monitor, the relative motion is unaffected by the clipping and will
>> > >> >> +        represent the unclipped motion.
>> > >> >> +
>> > >> >> +        This event also contains non-accelerated motion deltas. The
>> > >> >> +        non-accelerated delta is, when applicable, the regular pointer motion
>> > >> >> +        delta as it was before having applied motion acceleration
>> > >> >> +        transformations. The compositor will have applied the same processing
>> > >> >> +        (such as normalization) meaning the events will have roughly the same
>> > >> >> +        magnitude as accelerated motion events.
>> > >> >> +
>> > >> >> +        Note that the non-accelerated delta does not represent 'raw' events as
>> > >> >> +        they were read from some device. Pointer motion acceleration is device-
>> > >> >> +        and configuration-specific and non-accelerated deltas and accelerated
>> > >> >> +        deltas may have the same value on some devices.
>> > >> >> +
>> > >> >> +        Relative motions are not coupled to wl_pointer.motion events, and can
>> > >> >> +        be sent in combination with such events, but also independently. There
>> > >> >> +        may also be scenarious where wl_pointer.motion is sent, but there is no
>> > >> >> +        relative motion. The order of an absolute and relative motion event
>> > >> >> +        originating from the same physical motion is not guaranteed.
>> > >> >> +
>> > >> >> +        The motion vectors are encoded as double fixed point values.
>> > >> >> +
>> > >> >> +        A double fixed point value is a 64 bit data type encoded as two separate
>> > >> >> +        signed 32 bit integers. The integral part of the value is stored in one
>> > >> >> +        of the integers and the fractional part in the other.
>> > >> >> +
>> > >> >> +        If the client needs button events, it can receive them from a wl_pointer
>> > >> >> +        object of the same seat that the wl_relative_pointer object is
>> > >> >> +        associated with.
>> > >> >> +      </description>
>> > >> >> +
>> > >> >> +      <arg name="time" type="uint"
>> > >> >> +           summary="timestamp with millisecond granularity"/>
>> > >> >> +      <arg name="dx_int" type="int"
>> > >> >> +           summary="integral part of the x component of the motion vector"/>
>> > >> >> +      <arg name="dx_frac" type="int"
>> > >> >> +           summary="fractional part of the x component of the motion vector"/>
>> > >> >> +      <arg name="dy_int" type="int"
>> > >> >> +           summary="integral part of the y component of the motion vector"/>
>> > >> >> +      <arg name="dy_frac" type="int"
>> > >> >> +           summary="fractional part of the y component of the motion vector"/>
>> > >> >> +      <arg name="dx_unaccel_int" type="int"
>> > >> >> +           summary="integral part of the x component of the unaccelerated motion vector"/>
>> > >> >> +      <arg name="dx_unaccel_frac" type="int"
>> > >> >> +           summary="fractional part of the x component of the unaccelerated motion vector"/>
>> > >> >> +      <arg name="dy_unaccel_int" type="int"
>> > >> >> +           summary="integral part of the y component of the unaccelerated motion vector"/>
>> > >> >> +      <arg name="dy_unaccel_frac" type="int"
>> > >> >> +           summary="fractional part of the y component of the unaccelerated motion vector"/>
>> > >> >> +    </event>
>> > >> >> +  </interface>
>> > >> >> +
>> > >> >> +</protocol>
>> > >> >> diff --git a/src/compositor.c b/src/compositor.c
>> > >> >> index 5594d30..b462531 100644
>> > >> >> --- a/src/compositor.c
>> > >> >> +++ b/src/compositor.c
>> > >> >> @@ -4560,6 +4560,9 @@ weston_compositor_init(struct weston_compositor *ec,
>> > >> >>       weston_plane_init(&ec->primary_plane, ec, 0, 0);
>> > >> >>       weston_compositor_stack_plane(ec, &ec->primary_plane, NULL);
>> > >> >>
>> > >> >> +     if (weston_input_init(ec) != 0)
>> > >> >> +             return -1;
>> > >> >> +
>> > >> >>       s = weston_config_get_section(ec->config, "keyboard", NULL, NULL);
>> > >> >>       weston_config_section_get_string(s, "keymap_rules",
>> > >> >>                                        (char **) &xkb_names.rules, NULL);
>> > >> >> diff --git a/src/compositor.h b/src/compositor.h
>> > >> >> index 331b758..55cc88f 100644
>> > >> >> --- a/src/compositor.h
>> > >> >> +++ b/src/compositor.h
>> > >> >> @@ -340,7 +340,9 @@ struct weston_pointer {
>> > >> >>       struct weston_seat *seat;
>> > >> >>
>> > >> >>       struct wl_list resource_list;
>> > >> >> +     struct wl_list relative_resource_list;
>> > >> >>       struct wl_list focus_resource_list;
>> > >> >> +     struct wl_list relative_focus_resource_list;
>> > >> >>       struct weston_view *focus;
>> > >> >>       uint32_t focus_serial;
>> > >> >>       struct wl_listener focus_view_listener;
>> > >> >> @@ -1584,6 +1586,9 @@ weston_output_mode_switch_to_native(struct weston_output *output);
>> > >> >>  int
>> > >> >>  noop_renderer_init(struct weston_compositor *ec);
>> > >> >>
>> > >> >> +int
>> > >> >> +weston_input_init(struct weston_compositor *compositor);
>> > >> >> +
>> > >> >>  struct weston_compositor *
>> > >> >>  backend_init(struct wl_display *display, int *argc, char *argv[],
>> > >> >>            struct weston_config *config);
>> > >> >> diff --git a/src/input.c b/src/input.c
>> > >> >> index 9131287..b48a6c9 100644
>> > >> >> --- a/src/input.c
>> > >> >> +++ b/src/input.c
>> > >> >> @@ -32,7 +32,9 @@
>> > >> >>  #include <limits.h>
>> > >> >>
>> > >> >>  #include "../shared/os-compatibility.h"
>> > >> >> +#include "../shared/util.h"
>> > >> >>  #include "compositor.h"
>> > >> >> +#include "protocol/relative-pointer-server-protocol.h"
>> > >> >>
>> > >> >>  static void
>> > >> >>  empty_region(pixman_region32_t *region)
>> > >> >> @@ -47,6 +49,49 @@ static void unbind_resource(struct wl_resource *resource)
>> > >> >>  }
>> > >> >>
>> > >> >>  WL_EXPORT void
>> > >> >> +weston_pointer_motion_to_abs(struct weston_pointer *pointer,
>> > >> >> +                          struct weston_pointer_motion_event *event,
>> > >> >> +                          wl_fixed_t *x, wl_fixed_t *y)
>> > >> >> +{
>> > >> >> +     if (event->mask & WESTON_POINTER_MOTION_ABS) {
>> > >> >> +             *x = wl_fixed_from_double(event->x);
>> > >> >> +             *y = wl_fixed_from_double(event->y);
>> > >> >> +     } else if (event->mask & WESTON_POINTER_MOTION_REL) {
>> > >> >> +             *x = pointer->x + wl_fixed_from_double(event->dx);
>> > >> >> +             *y = pointer->y + wl_fixed_from_double(event->dy);
>> > >> >> +     } else {
>> > >> >> +             assert(!"invalid motion event");
>> > >> >> +             *x = *y = 0;
>> > >> >> +     }
>> > >> >> +}
>> > >> >> +
>> > >> >> +static int
>> > >> >> +weston_pointer_motion_to_rel(struct weston_pointer *pointer,
>> > >> >> +                          struct weston_pointer_motion_event *event,
>> > >> >> +                          double *dx, double *dy,
>> > >> >> +                          double *dx_unaccel, double *dy_unaccel)
>> > >> >> +{
>> > >> >> +     if (event->mask & WESTON_POINTER_MOTION_REL &&
>> > >> >> +         event->mask & WESTON_POINTER_MOTION_REL_NOACCEL) {
>> > >> >> +             *dx = event->dx;
>> > >> >> +             *dy = event->dy;
>> > >> >> +             *dx_unaccel = event->dx_unaccel;
>> > >> >> +             *dy_unaccel = event->dy_unaccel;
>> > >> >> +             return 1;
>> > >> >> +     } else if (event->mask & WESTON_POINTER_MOTION_REL) {
>> > >> >> +             *dx_unaccel = *dx = event->dx;
>> > >> >> +             *dy_unaccel = *dy = event->dy;
>> > >> >> +             return 1;
>> > >> >> +     } else if (event->mask & WESTON_POINTER_MOTION_REL_NOACCEL) {
>> > >> >> +             *dx_unaccel = *dx = event->dx_unaccel;
>> > >> >> +             *dy_unaccel = *dy = event->dy_unaccel;
>> > >> >> +             return 1;
>> > >> >> +     } else {
>> > >> >> +             return 0;
>> > >> >> +     }
>> > >> >> +}
>> > >> >> +
>> > >> >> +WL_EXPORT void
>> > >> >>  weston_seat_repick(struct weston_seat *seat)
>> > >> >>  {
>> > >> >>       const struct weston_pointer *pointer = seat->pointer;
>> > >> >> @@ -162,6 +207,42 @@ default_grab_pointer_focus(struct weston_pointer_grab *grab)
>> > >> >>  }
>> > >> >>
>> > >> >>  static void
>> > >> >> +weston_pointer_send_relative_motion(struct weston_pointer *pointer,
>> > >> >> +                                 uint32_t time,
>> > >> >> +                                 struct weston_pointer_motion_event *event)
>> > >> >> +{
>> > >> >> +     double dx, dy, dx_unaccel, dy_unaccel;
>> > >> >> +     int32_t dx_int, dx_frac;
>> > >> >> +     int32_t dy_int, dy_frac;
>> > >> >> +     int32_t dx_unaccel_int, dx_unaccel_frac;
>> > >> >> +     int32_t dy_unaccel_int, dy_unaccel_frac;
>> > >> >> +     struct wl_list *resource_list;
>> > >> >> +     struct wl_resource *resource;
>> > >> >> +
>> > >> >> +     if (weston_pointer_motion_to_rel(pointer, event,
>> > >> >> +                                      &dx, &dy,
>> > >> >> +                                      &dx_unaccel, &dy_unaccel)) {
>> > >> >> +             resource_list = &pointer->relative_focus_resource_list;
>> > >> >> +             wl_double_fixed_from_double(dx, &dx_int, &dx_frac);
>> > >> >> +             wl_double_fixed_from_double(dy, &dy_int, &dy_frac);
>> > >> >> +             wl_double_fixed_from_double(dx_unaccel,
>> > >> >> +                                         &dx_unaccel_int,
>> > >> >> +                                         &dx_unaccel_frac);
>> > >> >> +             wl_double_fixed_from_double(dy_unaccel,
>> > >> >> +                                         &dy_unaccel_int,
>> > >> >> +                                         &dy_unaccel_frac);
>> > >> >> +             wl_resource_for_each(resource, resource_list) {
>> > >> >> +                     _wl_relative_pointer_send_relative_motion(
>> > >> >> +                             resource, time,
>> > >> >> +                             dx_int, dx_frac,
>> > >> >> +                             dy_int, dy_frac,
>> > >> >> +                             dx_unaccel_int, dx_unaccel_frac,
>> > >> >> +                             dy_unaccel_int, dy_unaccel_frac);
>> > >> >> +             }
>> > >> >> +     }
>> > >> >> +}
>> > >> >> +
>> > >> >> +static void
>> > >> >>  default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
>> > >> >>                           struct weston_pointer_motion_event *event)
>> > >> >>  {
>> > >> >> @@ -187,6 +268,8 @@ default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
>> > >> >>                                              pointer->sx, pointer->sy);
>> > >> >>               }
>> > >> >>       }
>> > >> >> +
>> > >> >> +     weston_pointer_send_relative_motion(pointer, time, event);
>> > >> >>  }
>> > >> >>
>> > >> >>  static void
>> > >> >> @@ -503,7 +586,9 @@ weston_pointer_create(struct weston_seat *seat)
>> > >> >>               return NULL;
>> > >> >>
>> > >> >>       wl_list_init(&pointer->resource_list);
>> > >> >> +     wl_list_init(&pointer->relative_resource_list);
>> > >> >>       wl_list_init(&pointer->focus_resource_list);
>> > >> >> +     wl_list_init(&pointer->relative_focus_resource_list);
>> > >> >>       weston_pointer_set_default_grab(pointer,
>> > >> >>                                       seat->compositor->default_pointer_grab);
>> > >> >>       wl_list_init(&pointer->focus_resource_listener.link);
>> > >> >> @@ -665,6 +750,7 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
>> > >> >>       struct wl_display *display = pointer->seat->compositor->wl_display;
>> > >> >>       uint32_t serial;
>> > >> >>       struct wl_list *focus_resource_list;
>> > >> >> +     struct wl_list *relative_focus_resource_list;
>> > >> >>       int refocus = 0;
>> > >> >>
>> > >> >>       if ((!pointer->focus && view) ||
>> > >> >> @@ -674,6 +760,7 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
>> > >> >>               refocus = 1;
>> > >> >>
>> > >> >>       focus_resource_list = &pointer->focus_resource_list;
>> > >> >> +     relative_focus_resource_list = &pointer->relative_focus_resource_list;
>> > >> >>
>> > >> >>       if (!wl_list_empty(focus_resource_list) && refocus) {
>> > >> >>               serial = wl_display_next_serial(display);
>> > >> >> @@ -683,6 +770,8 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
>> > >> >>               }
>> > >> >>
>> > >> >>               move_resources(&pointer->resource_list, focus_resource_list);
>> > >> >> +             move_resources(&pointer->relative_resource_list,
>> > >> >> +                            relative_focus_resource_list);
>> > >> >>       }
>> > >> >>
>> > >> >>       if (find_resource_for_view(&pointer->resource_list, view) && refocus) {
>> > >> >> @@ -700,6 +789,9 @@ weston_pointer_set_focus(struct weston_pointer *pointer,
>> > >> >>               move_resources_for_client(focus_resource_list,
>> > >> >>                                         &pointer->resource_list,
>> > >> >>                                         surface_client);
>> > >> >> +             move_resources_for_client(relative_focus_resource_list,
>> > >> >> +                                       &pointer->relative_resource_list,
>> > >> >> +                                       surface_client);
>> > >> >>
>> > >> >>               wl_resource_for_each(resource, focus_resource_list) {
>> > >> >>                       wl_pointer_send_enter(resource,
>> > >> >> @@ -932,23 +1024,6 @@ weston_pointer_move_to(struct weston_pointer *pointer,
>> > >> >>  }
>> > >> >>
>> > >> >>  WL_EXPORT void
>> > >> >> -weston_pointer_motion_to_abs(struct weston_pointer *pointer,
>> > >> >> -                          struct weston_pointer_motion_event *event,
>> > >> >> -                          wl_fixed_t *x, wl_fixed_t *y)
>> > >> >> -{
>> > >> >> -     if (event->mask & WESTON_POINTER_MOTION_ABS) {
>> > >> >> -             *x = wl_fixed_from_double(event->x);
>> > >> >> -             *y = wl_fixed_from_double(event->y);
>> > >> >> -     } else if (event->mask & WESTON_POINTER_MOTION_REL) {
>> > >> >> -             *x = pointer->x + wl_fixed_from_double(event->dx);
>> > >> >> -             *y = pointer->y + wl_fixed_from_double(event->dy);
>> > >> >> -     } else {
>> > >> >> -             assert(!"invalid motion event");
>> > >> >> -             *x = *y = 0;
>> > >> >> -     }
>> > >> >> -}
>> > >> >> -
>> > >> >> -WL_EXPORT void
>> > >> >>  weston_pointer_move(struct weston_pointer *pointer,
>> > >> >>                   struct weston_pointer_motion_event *event)
>> > >> >>  {
>> > >> >> @@ -2008,6 +2083,72 @@ bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
>> > >> >>               wl_seat_send_name(resource, seat->seat_name);
>> > >> >>  }
>> > >> >>
>> > >> >> +static void
>> > >> >> +relative_pointer_release(struct wl_client *client,
>> > >> >> +                      struct wl_resource *resource)
>> > >> >> +{
>> > >> >> +     wl_resource_destroy(resource);
>> > >> >> +}
>> > >> >> +
>> > >> >> +static const struct _wl_relative_pointer_interface relative_pointer_interface = {
>> > >> >> +     relative_pointer_release
>> > >> >> +};
>> > >> >> +
>> > >> >> +static void
>> > >> >> +relative_pointer_manager_get_relative_pointer(struct wl_client *client,
>> > >> >> +                                           struct wl_resource *resource,
>> > >> >> +                                           uint32_t id,
>> > >> >> +                                           struct wl_resource *pointer_resource)
>> > >> >> +{
>> > >> >> +     struct weston_pointer *pointer =
>> > >> >> +             wl_resource_get_user_data(pointer_resource);
>> > >> >> +     struct wl_resource *cr;
>> > >> >> +     struct weston_view *focus;
>> > >> >> +
>> > >> >> +     cr = wl_resource_create(client, &_wl_relative_pointer_interface,
>> > >> >> +                             wl_resource_get_version(resource), id);
>> > >> >> +     if (cr == NULL) {
>> > >> >> +             wl_client_post_no_memory(client);
>> > >> >> +             return;
>> > >> >> +     }
>> > >> >> +
>> > >> >> +     /* May be moved to focused list later by either
>> > >> >> +      * weston_pointer_set_focus or directly if this client is already
>> > >> >> +      * focused */
>> > >> >> +     wl_list_insert(&pointer->relative_resource_list,
>> > >> >> +                    wl_resource_get_link(cr));
>> > >> >> +     wl_resource_set_implementation(cr, &relative_pointer_interface,
>> > >> >> +                                    pointer,
>> > >> >> +                                    unbind_resource);
>> > >> >> +
>> > >> >> +     focus = pointer->focus;
>> > >> >> +     if (focus && focus->surface->resource &&
>> > >> >> +         wl_resource_get_client(focus->surface->resource) == client) {
>> > >> >> +             wl_list_remove(wl_resource_get_link(cr));
>> > >> >> +             wl_list_insert(&pointer->relative_focus_resource_list,
>> > >> >> +                            wl_resource_get_link(cr));
>> > >> >> +     }
>> > >> >> +}
>> > >> >> +
>> > >> >> +static const struct _wl_relative_pointer_manager_interface relative_pointer_manager = {
>> > >> >> +     relative_pointer_manager_get_relative_pointer,
>> > >> >> +};
>> > >> >> +
>> > >> >> +static void
>> > >> >> +bind_relative_pointer_manager(struct wl_client *client, void *data,
>> > >> >> +                           uint32_t version, uint32_t id)
>> > >> >> +{
>> > >> >> +     struct weston_compositor *compositor = data;
>> > >> >> +     struct wl_resource *resource;
>> > >> >> +
>> > >> >> +     resource = wl_resource_create(client,
>> > >> >> +                                   &_wl_relative_pointer_manager_interface,
>> > >> >> +                                   1, id);
>> > >> >> +     wl_resource_set_implementation(resource, &relative_pointer_manager,
>> > >> >> +                                    compositor,
>> > >> >> +                                    NULL);
>> > >> >> +}
>> > >> >> +
>> > >> >>  #ifdef ENABLE_XKBCOMMON
>> > >> >>  int
>> > >> >>  weston_compositor_xkb_init(struct weston_compositor *ec,
>> > >> >> @@ -2429,3 +2570,14 @@ weston_seat_release(struct weston_seat *seat)
>> > >> >>
>> > >> >>       wl_signal_emit(&seat->destroy_signal, seat);
>> > >> >>  }
>> > >> >> +
>> > >> >> +int
>> > >> >> +weston_input_init(struct weston_compositor *compositor)
>> > >> >> +{
>> > >> >> +     if (!wl_global_create(compositor->wl_display,
>> > >> >> +                           &_wl_relative_pointer_manager_interface, 1,
>> > >> >> +                           compositor, bind_relative_pointer_manager))
>> > >> >> +             return -1;
>> > >> >> +
>> > >> >> +     return 0;
>> > >> >> +}
>> > >> >> --
>> > >> >> 2.1.4