[weston,13/17] Introduce wl_relative_pointer interface

Submitted by Jonas Ådahl on Dec. 2, 2014, 1:49 p.m.

Details

Message ID 1417528165-9319-14-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 Dec. 2, 2014, 1:49 p.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>
---
 Makefile.am                   |   7 +-
 protocol/relative-pointer.xml |  90 +++++++++++++++++++++
 src/compositor.c              |   3 +
 src/compositor.h              |   5 ++
 src/input.c                   | 184 +++++++++++++++++++++++++++++++++++++-----
 5 files changed, 266 insertions(+), 23 deletions(-)
 create mode 100644 protocol/relative-pointer.xml

Patch hide | download patch | download mbox

diff --git a/Makefile.am b/Makefile.am
index e942850..860564d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -81,7 +81,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)
 
@@ -1003,7 +1005,8 @@  EXTRA_DIST +=					\
 	protocol/xdg-shell.xml			\
 	protocol/fullscreen-shell.xml		\
 	protocol/presentation_timing.xml	\
-	protocol/scaler.xml
+	protocol/scaler.xml			\
+	protocol/relative-pointer.xml
 
 man_MANS = weston.1 weston.ini.5
 
diff --git a/protocol/relative-pointer.xml b/protocol/relative-pointer.xml
new file mode 100644
index 0000000..f56c912
--- /dev/null
+++ b/protocol/relative-pointer.xml
@@ -0,0 +1,90 @@ 
+<?xml version="1.0" encoding="UTF-8"?>
+<protocol name="relative_pointer">
+
+  <copyright>
+    Copyright © 2014      Jonas Ådahl
+
+    Permission to use, copy, modify, distribute, and sell this
+    software and its documentation for any purpose is hereby granted
+    without fee, provided that the above copyright notice appear in
+    all copies and that both that copyright notice and this permission
+    notice appear in supporting documentation, and that the name of
+    the copyright holders not be used in advertising or publicity
+    pertaining to distribution of the software without specific,
+    written prior permission.  The copyright holders make no
+    representations about the suitability of this software for any
+    purpose.  It is provided "as is" without express or implied
+    warranty.
+
+    THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+    SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+    FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
+    SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
+    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+    THIS 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.
+    </description>
+
+    <request name="get_relative_pointer">
+      <description summary="get a relative pointer object">
+        Create a relative pointer interface for the pointer of the given seat.
+
+        This request only takes effect if the seat has the pointer capability.
+      </description>
+
+      <arg name="id" type="new_id" interface="_wl_relative_pointer"/>
+      <arg name="seat" type="object" interface="wl_seat"/>
+    </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
+      only used for emitting relative pointer events. It will only emit events
+      when the parent pointer 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 pointer motion from the pointer of the seat associated with
+        this object.
+
+        This event contains both the accelerated motion delta and the
+        non-accelerated motion delta. The non-accelerated delta is, when
+        applicable, the regular pointer motion delta as it was before having
+        applied motion acceleration transformations. Note that it does not
+        represent 'raw' events as they were read from some device. What
+        acceleration corresponds to is device specific and may be identical
+        to non-accelerated for some devices, while for others not.
+
+        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.
+      </description>
+
+      <arg name="time" type="uint"
+           summary="timestamp with millisecond granularity"/>
+      <arg name="dx" type="fixed"
+           summary="x component of the motion vector"/>
+      <arg name="dy" type="fixed"
+           summary="y component of the motion vector"/>
+      <arg name="dx_noaccel" type="fixed"
+           summary="x component of the nonaccelerated motion vector"/>
+      <arg name="dy_noaccel" type="fixed"
+           summary="y component of the nonaccelerated motion vector"/>
+    </event>
+  </interface>
+
+</protocol>
diff --git a/src/compositor.c b/src/compositor.c
index 790018a..767cb26 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -4084,6 +4084,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 b622c97..b373ecf 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -330,7 +330,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;
@@ -1485,6 +1487,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 d82628c..9d02eb8 100644
--- a/src/input.c
+++ b/src/input.c
@@ -33,6 +33,7 @@ 
 
 #include "../shared/os-compatibility.h"
 #include "compositor.h"
+#include "protocol/relative-pointer-server-protocol.h"
 
 static void
 empty_region(pixman_region32_t *region)
@@ -47,6 +48,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 = event->x;
+		*y = event->y;
+	} else if (event->mask & WESTON_POINTER_MOTION_REL) {
+		*x = pointer->x + event->dx;
+		*y = pointer->y + 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,
+			     wl_fixed_t *dx, wl_fixed_t *dy,
+			     wl_fixed_t *dx_noaccel, wl_fixed_t *dy_noaccel)
+{
+	if (event->mask & WESTON_POINTER_MOTION_REL &&
+	    event->mask & WESTON_POINTER_MOTION_REL_NOACCEL) {
+		*dx = event->dx;
+		*dy = event->dy;
+		*dx_noaccel = event->dx_noaccel;
+		*dy_noaccel = event->dy_noaccel;
+		return 1;
+	} else if (event->mask & WESTON_POINTER_MOTION_REL) {
+		*dx_noaccel = *dx = event->dx;
+		*dy_noaccel = *dy = event->dy;
+		return 1;
+	} else if (event->mask & WESTON_POINTER_MOTION_REL_NOACCEL) {
+		*dx_noaccel = *dx = event->dx_noaccel;
+		*dy_noaccel = *dy = event->dy_noaccel;
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+WL_EXPORT void
 weston_seat_repick(struct weston_seat *seat)
 {
 	const struct weston_pointer *pointer = seat->pointer;
@@ -162,6 +206,27 @@  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)
+{
+	wl_fixed_t dx, dy;
+	wl_fixed_t dx_noaccel, dy_noaccel;
+	struct wl_list *resource_list;
+	struct wl_resource *resource;
+
+	if (weston_pointer_motion_to_rel(pointer, event,
+					 &dx, &dy,
+					 &dx_noaccel, &dy_noaccel)) {
+		resource_list = &pointer->relative_focus_resource_list;
+		wl_resource_for_each(resource, resource_list) {
+			_wl_relative_pointer_send_relative_motion(
+				resource, time, dx, dy, dx_noaccel, dy_noaccel);
+		}
+	}
+}
+
+static void
 default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
 			    struct weston_pointer_motion_event *event)
 {
@@ -169,6 +234,8 @@  default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
 	struct wl_list *resource_list;
 	struct wl_resource *resource;
 	wl_fixed_t x, y;
+	wl_fixed_t old_sx = pointer->sx;
+	wl_fixed_t old_sy = pointer->sy;
 
 	if (pointer->focus) {
 		weston_pointer_motion_to_abs(pointer, event, &x, &y);
@@ -178,11 +245,15 @@  default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t time,
 
 	weston_pointer_move(pointer, event);
 
-	resource_list = &pointer->focus_resource_list;
-	wl_resource_for_each(resource, resource_list) {
-		wl_pointer_send_motion(resource, time,
-				       pointer->sx, pointer->sy);
+	if (old_sx != pointer->sx || old_sy != pointer->sy) {
+		resource_list = &pointer->focus_resource_list;
+		wl_resource_for_each(resource, resource_list) {
+			wl_pointer_send_motion(resource, time,
+					       pointer->sx, pointer->sy);
+		}
 	}
+
+	weston_pointer_send_relative_motion(pointer, time, event);
 }
 
 static void
@@ -481,7 +552,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);
@@ -643,6 +716,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) ||
@@ -652,6 +726,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);
@@ -661,6 +736,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) {
@@ -678,6 +755,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,
@@ -911,23 +991,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 = event->x;
-		*y = event->y;
-	} else if (event->mask & WESTON_POINTER_MOTION_REL) {
-		*x = pointer->x + event->dx;
-		*y = pointer->y + 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)
 {
@@ -1798,6 +1861,55 @@  seat_get_pointer(struct wl_client *client, struct wl_resource *resource,
 }
 
 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
+seat_get_relative_pointer(struct wl_client *client,
+			  struct wl_resource *resource,
+			  uint32_t id,
+			  struct wl_resource *seat_resource)
+{
+	struct weston_seat *seat = wl_resource_get_user_data(seat_resource);
+	struct wl_resource *cr;
+	struct weston_view *focus;
+
+	if (!seat->pointer)
+		return;
+
+        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(&seat->pointer->relative_resource_list,
+		       wl_resource_get_link(cr));
+	wl_resource_set_implementation(cr, &relative_pointer_interface,
+				       seat->pointer,
+				       unbind_resource);
+
+	focus = seat->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(&seat->pointer->relative_focus_resource_list,
+			       wl_resource_get_link(cr));
+	}
+}
+
+static void
 keyboard_release(struct wl_client *client, struct wl_resource *resource)
 {
 	wl_resource_destroy(resource);
@@ -1941,6 +2053,25 @@  static const struct wl_seat_interface seat_interface = {
 	seat_get_touch,
 };
 
+static const struct _wl_relative_pointer_manager_interface relative_pointer_manager = {
+	seat_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);
+}
+
 static void
 bind_seat(struct wl_client *client, void *data, uint32_t version, uint32_t id)
 {
@@ -2381,3 +2512,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

Haven't looked at the weston implementation but the protocol bits look
pretty good to me.  Sounds like what we discussed.
--Jason

On Tue, Dec 2, 2014 at 5:49 AM, 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.
>
> 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>
> ---
>  Makefile.am                   |   7 +-
>  protocol/relative-pointer.xml |  90 +++++++++++++++++++++
>  src/compositor.c              |   3 +
>  src/compositor.h              |   5 ++
>  src/input.c                   | 184
> +++++++++++++++++++++++++++++++++++++-----
>  5 files changed, 266 insertions(+), 23 deletions(-)
>  create mode 100644 protocol/relative-pointer.xml
>
> diff --git a/Makefile.am b/Makefile.am
> index e942850..860564d 100644
> --- a/Makefile.am
> +++ b/Makefile.am
> @@ -81,7 +81,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)
>
> @@ -1003,7 +1005,8 @@ EXTRA_DIST +=                                     \
>         protocol/xdg-shell.xml                  \
>         protocol/fullscreen-shell.xml           \
>         protocol/presentation_timing.xml        \
> -       protocol/scaler.xml
> +       protocol/scaler.xml                     \
> +       protocol/relative-pointer.xml
>
>  man_MANS = weston.1 weston.ini.5
>
> diff --git a/protocol/relative-pointer.xml b/protocol/relative-pointer.xml
> new file mode 100644
> index 0000000..f56c912
> --- /dev/null
> +++ b/protocol/relative-pointer.xml
> @@ -0,0 +1,90 @@
> +<?xml version="1.0" encoding="UTF-8"?>
> +<protocol name="relative_pointer">
> +
> +  <copyright>
> +    Copyright © 2014      Jonas Ådahl
> +
> +    Permission to use, copy, modify, distribute, and sell this
> +    software and its documentation for any purpose is hereby granted
> +    without fee, provided that the above copyright notice appear in
> +    all copies and that both that copyright notice and this permission
> +    notice appear in supporting documentation, and that the name of
> +    the copyright holders not be used in advertising or publicity
> +    pertaining to distribution of the software without specific,
> +    written prior permission.  The copyright holders make no
> +    representations about the suitability of this software for any
> +    purpose.  It is provided "as is" without express or implied
> +    warranty.
> +
> +    THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
> +    SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
> +    FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
> +    SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
> +    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
> +    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
> +    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
> +    THIS 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.
> +    </description>
> +
> +    <request name="get_relative_pointer">
> +      <description summary="get a relative pointer object">
> +        Create a relative pointer interface for the pointer of the given
> seat.
> +
> +        This request only takes effect if the seat has the pointer
> capability.
> +      </description>
> +
> +      <arg name="id" type="new_id" interface="_wl_relative_pointer"/>
> +      <arg name="seat" type="object" interface="wl_seat"/>
> +    </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
> +      only used for emitting relative pointer events. It will only emit
> events
> +      when the parent pointer has focus.
> +    </description>
> +
> +    <request name="release" type="destructor">
> +      <description summary="release the relative pointer object"/>
> +    </request>
>

Maybe this should be called "destroy".  I know that we call it release on
wl_pointer and friends, but this is something of a historical accident.
The problem is that if you don't have a destructor, it creates a
wl_whatever_destroy function for you that destroys the client-side object
without sending anything over the wire.  In order to not break the API we
had to come up with a new name for the destructor when we added it.  We
don't have that problem now so we can go ahead and call it destroy.  Also
(and I'm not 100% sure on this one), if we create one that's not called
destroy it may create the dummy destructor for us anyway and that would be
bad.

If we can have exactly one and have it called "release" that would be good
for consistency, but we may have to have it called "destroy".  If that's
the case and you really want the consistency, then we can make two.
Double-check what the protocol scanner is generating for us.

+
> +    <event name="relative_motion">
> +      <description summary="relative pointer motion">
> +        Relative pointer motion from the pointer of the seat associated
> with
> +        this object.
> +
> +        This event contains both the accelerated motion delta and the
> +        non-accelerated motion delta. The non-accelerated delta is, when
> +        applicable, the regular pointer motion delta as it was before
> having
> +        applied motion acceleration transformations. Note that it does not
> +        represent 'raw' events as they were read from some device. What
> +        acceleration corresponds to is device specific and may be
> identical
> +        to non-accelerated for some devices, while for others not.
>

It would be nice if we could say something more about those events.  At
least if we could claim that they have roughly the same relative magnitude
across devices.  That said, I'm not an input guy, so I don't know if this
is practical.


> +
> +        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.
>

Thank you for making this explicit!


> +      </description>
> +
> +      <arg name="time" type="uint"
> +           summary="timestamp with millisecond granularity"/>
> +      <arg name="dx" type="fixed"
> +           summary="x component of the motion vector"/>
> +      <arg name="dy" type="fixed"
> +           summary="y component of the motion vector"/>
> +      <arg name="dx_noaccel" type="fixed"
> +           summary="x component of the nonaccelerated motion vector"/>
> +      <arg name="dy_noaccel" type="fixed"
> +           summary="y component of the nonaccelerated motion vector"/>
> +    </event>
> +  </interface>
> +
> +</protocol>
> diff --git a/src/compositor.c b/src/compositor.c
> index 790018a..767cb26 100644
> --- a/src/compositor.c
> +++ b/src/compositor.c
> @@ -4084,6 +4084,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 b622c97..b373ecf 100644
> --- a/src/compositor.h
> +++ b/src/compositor.h
> @@ -330,7 +330,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;
> @@ -1485,6 +1487,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 d82628c..9d02eb8 100644
> --- a/src/input.c
> +++ b/src/input.c
> @@ -33,6 +33,7 @@
>
>  #include "../shared/os-compatibility.h"
>  #include "compositor.h"
> +#include "protocol/relative-pointer-server-protocol.h"
>
>  static void
>  empty_region(pixman_region32_t *region)
> @@ -47,6 +48,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 = event->x;
> +               *y = event->y;
> +       } else if (event->mask & WESTON_POINTER_MOTION_REL) {
> +               *x = pointer->x + event->dx;
> +               *y = pointer->y + 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,
> +                            wl_fixed_t *dx, wl_fixed_t *dy,
> +                            wl_fixed_t *dx_noaccel, wl_fixed_t
> *dy_noaccel)
> +{
> +       if (event->mask & WESTON_POINTER_MOTION_REL &&
> +           event->mask & WESTON_POINTER_MOTION_REL_NOACCEL) {
> +               *dx = event->dx;
> +               *dy = event->dy;
> +               *dx_noaccel = event->dx_noaccel;
> +               *dy_noaccel = event->dy_noaccel;
> +               return 1;
> +       } else if (event->mask & WESTON_POINTER_MOTION_REL) {
> +               *dx_noaccel = *dx = event->dx;
> +               *dy_noaccel = *dy = event->dy;
> +               return 1;
> +       } else if (event->mask & WESTON_POINTER_MOTION_REL_NOACCEL) {
> +               *dx_noaccel = *dx = event->dx_noaccel;
> +               *dy_noaccel = *dy = event->dy_noaccel;
> +               return 1;
> +       } else {
> +               return 0;
> +       }
> +}
> +
> +WL_EXPORT void
>  weston_seat_repick(struct weston_seat *seat)
>  {
>         const struct weston_pointer *pointer = seat->pointer;
> @@ -162,6 +206,27 @@ 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)
> +{
> +       wl_fixed_t dx, dy;
> +       wl_fixed_t dx_noaccel, dy_noaccel;
> +       struct wl_list *resource_list;
> +       struct wl_resource *resource;
> +
> +       if (weston_pointer_motion_to_rel(pointer, event,
> +                                        &dx, &dy,
> +                                        &dx_noaccel, &dy_noaccel)) {
> +               resource_list = &pointer->relative_focus_resource_list;
> +               wl_resource_for_each(resource, resource_list) {
> +                       _wl_relative_pointer_send_relative_motion(
> +                               resource, time, dx, dy, dx_noaccel,
> dy_noaccel);
> +               }
> +       }
> +}
> +
> +static void
>  default_grab_pointer_motion(struct weston_pointer_grab *grab, uint32_t
> time,
>                             struct weston_pointer_motion_event *event)
>  {
> @@ -169,6 +234,8 @@ default_grab_pointer_motion(struct weston_pointer_grab
> *grab, uint32_t time,
>         struct wl_list *resource_list;
>         struct wl_resource *resource;
>         wl_fixed_t x, y;
> +       wl_fixed_t old_sx = pointer->sx;
> +       wl_fixed_t old_sy = pointer->sy;
>
>         if (pointer->focus) {
>                 weston_pointer_motion_to_abs(pointer, event, &x, &y);
> @@ -178,11 +245,15 @@ default_grab_pointer_motion(struct
> weston_pointer_grab *grab, uint32_t time,
>
>         weston_pointer_move(pointer, event);
>
> -       resource_list = &pointer->focus_resource_list;
> -       wl_resource_for_each(resource, resource_list) {
> -               wl_pointer_send_motion(resource, time,
> -                                      pointer->sx, pointer->sy);
> +       if (old_sx != pointer->sx || old_sy != pointer->sy) {
> +               resource_list = &pointer->focus_resource_list;
> +               wl_resource_for_each(resource, resource_list) {
> +                       wl_pointer_send_motion(resource, time,
> +                                              pointer->sx, pointer->sy);
> +               }
>         }
> +
> +       weston_pointer_send_relative_motion(pointer, time, event);
>  }
>
>  static void
> @@ -481,7 +552,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);
> @@ -643,6 +716,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) ||
> @@ -652,6 +726,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);
> @@ -661,6 +736,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) {
> @@ -678,6 +755,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,
> @@ -911,23 +991,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 = event->x;
> -               *y = event->y;
> -       } else if (event->mask & WESTON_POINTER_MOTION_REL) {
> -               *x = pointer->x + event->dx;
> -               *y = pointer->y + 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)
>  {
> @@ -1798,6 +1861,55 @@ seat_get_pointer(struct wl_client *client, struct
> wl_resource *resource,
>  }
>
>  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
> +seat_get_relative_pointer(struct wl_client *client,
> +                         struct wl_resource *resource,
> +                         uint32_t id,
> +                         struct wl_resource *seat_resource)
> +{
> +       struct weston_seat *seat =
> wl_resource_get_user_data(seat_resource);
> +       struct wl_resource *cr;
> +       struct weston_view *focus;
> +
> +       if (!seat->pointer)
> +               return;
> +
> +        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(&seat->pointer->relative_resource_list,
> +                      wl_resource_get_link(cr));
> +       wl_resource_set_implementation(cr, &relative_pointer_interface,
> +                                      seat->pointer,
> +                                      unbind_resource);
> +
> +       focus = seat->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(&seat->pointer->relative_focus_resource_list,
> +                              wl_resource_get_link(cr));
> +       }
> +}
> +
> +static void
>  keyboard_release(struct wl_client *client, struct wl_resource *resource)
>  {
>         wl_resource_destroy(resource);
> @@ -1941,6 +2053,25 @@ static const struct wl_seat_interface
> seat_interface = {
>         seat_get_touch,
>  };
>
> +static const struct _wl_relative_pointer_manager_interface
> relative_pointer_manager = {
> +       seat_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);
> +}
> +
>  static void
>  bind_seat(struct wl_client *client, void *data, uint32_t version,
> uint32_t id)
>  {
> @@ -2381,3 +2512,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;
> +}
> --
> 1.8.5.1
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
>