[RFC wayland] seat: add wl_relative_pointer

Philipp Brüschweiler blei42 at gmail.com
Sat Sep 1 08:49:50 PDT 2012


This pointer is equivalent to the "normal" pointer, except that it sends
relative motion events.
---
 protocol/wayland.xml |  93 +++++++++++++++++++++++++++++++++++++++++++++++
 src/data-device.c    |   3 +-
 src/wayland-server.c | 101 +++++++++++++++++++++++++++++++++++++++------------
 src/wayland-server.h |  16 ++++++--
 4 Dateien geändert, 185 Zeilen hinzugefügt(+), 28 Zeilen entfernt(-)

diff --git a/protocol/wayland.xml b/protocol/wayland.xml
index 5e56cb8..a789ac3 100644
--- a/protocol/wayland.xml
+++ b/protocol/wayland.xml
@@ -755,6 +755,14 @@
       <arg name="id" type="new_id" interface="wl_pointer"/>
     </request>
 
+    <request name="get_relative_pointer">
+      <description summary="return pointer object">
+        The ID provided will be initialized to the wl_relative_pointer
+        interface for this seat.
+      </description>
+      <arg name="id" type="new_id" interface="wl_relative_pointer"/>
+    </request>
+
     <request name="get_keyboard">
       <description summary="return pointer object">
         The ID provided will be initialized to the wl_keyboard interface
@@ -872,6 +880,91 @@
     </event>
   </interface>
 
+  <interface name="wl_relative_pointer" version="1">
+    <request name="set_cursor">
+      <description summary="set the pointer surface">
+	Set the pointer surface, i.e., the surface that contains the
+	pointer image. This request only takes effect if the pointer
+	focus for this device is one of the requesting client surfaces
+	or the surface parameter is the current pointer surface. If
+	there was a previous surface set with this request it is
+	replaced. If surface is NULL, the pointer image is hidden.
+
+	The parameters hotspot_x and hotspot_y define the position of
+	the pointer surface relative to the pointer location. Its
+	top-left corner is always at (x, y) - (hotspot_x, hotspot_y),
+	where (x, y) are the coordinates of the pointer location.
+
+	On surface.attach requests to the pointer surface, hotspot_x
+	and hotspot_y are decremented by the x and y parameters
+	passed to the request.
+
+	The hotspot can also be updated by passing the current set
+	pointer surface to this request with new values for hotspot_x
+	and/or hotspot_y.
+      </description>
+
+      <arg name="serial" type="uint"/>
+      <arg name="surface" type="object" interface="wl_surface" allow-null="true"/>
+      <arg name="hotspot_x" type="int"/>
+      <arg name="hotspot_y" type="int"/>
+    </request>
+
+    <event name="enter">
+      <description summary="enter event">
+	Notification that this seat's pointer is focused on a certain
+	surface. When an seat's focus enters a surface, the pointer image
+	is undefined and a client should respond to this event by setting
+	an appropriate pointer image.
+      </description>
+
+      <arg name="serial" type="uint"/>
+      <arg name="surface" type="object" interface="wl_surface"/>
+      <arg name="surface_x" type="fixed"/>
+      <arg name="surface_y" type="fixed"/>
+    </event>
+
+    <event name="leave">
+      <description summary="leave event">
+      </description>
+      <arg name="serial" type="uint"/>
+      <arg name="surface" type="object" interface="wl_surface"/>
+    </event>
+
+    <event name="motion">
+      <description summary="pointer motion event">
+	Notification of pointer location change. The arguments d[xy]
+        are the location relative to the last position that triggered an event.
+      </description>
+
+      <arg name="time" type="uint"/>
+      <arg name="dx" type="fixed"/>
+      <arg name="dy" type="fixed"/>
+    </event>
+
+    <event name="button">
+      <description summary="pointer button event">
+	Mouse button click and release notifications.  The location
+	of the click is given by the last motion or pointer_focus event.
+      </description>
+
+      <arg name="serial" type="uint"/>
+      <arg name="time" type="uint"/>
+      <arg name="button" type="uint"/>
+      <arg name="state" type="uint"/>
+    </event>
+
+    <event name="axis">
+      <description summary="axis event">
+	Scroll and other axis notifications.
+      </description>
+
+      <arg name="time" type="uint"/>
+      <arg name="axis" type="uint"/>
+      <arg name="value" type="fixed"/>
+    </event>
+  </interface>
+
   <interface name="wl_keyboard" version="1">
     <description summary="keyboard input device">
     </description>
diff --git a/src/data-device.c b/src/data-device.c
index 82020af..f2d0b21 100644
--- a/src/data-device.c
+++ b/src/data-device.c
@@ -216,7 +216,8 @@ drag_grab_focus(struct wl_pointer_grab *grab,
 
 static void
 drag_grab_motion(struct wl_pointer_grab *grab,
-		 uint32_t time, wl_fixed_t x, wl_fixed_t y)
+		 uint32_t time, wl_fixed_t x, wl_fixed_t y,
+		 wl_fixed_t dx, wl_fixed_t dy)
 {
 	struct wl_seat *seat = container_of(grab, struct wl_seat, drag_grab);
 
diff --git a/src/wayland-server.c b/src/wayland-server.c
index 88e8433..a30df41 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -488,7 +488,8 @@ lose_pointer_focus(struct wl_listener *listener, void *data)
 	struct wl_pointer *pointer =
 		container_of(listener, struct wl_pointer, focus_listener);
 
-	pointer->focus_resource = NULL;
+	pointer->abs.focus_resource = NULL;
+	pointer->rel.focus_resource = NULL;
 }
 
 static void
@@ -523,13 +524,18 @@ default_grab_focus(struct wl_pointer_grab *grab,
 
 static void
 default_grab_motion(struct wl_pointer_grab *grab,
-		    uint32_t time, wl_fixed_t x, wl_fixed_t y)
+		    uint32_t time, wl_fixed_t x, wl_fixed_t y,
+		    wl_fixed_t dx, wl_fixed_t dy)
 {
 	struct wl_resource *resource;
 
-	resource = grab->pointer->focus_resource;
+	resource = grab->pointer->abs.focus_resource;
 	if (resource)
 		wl_pointer_send_motion(resource, time, x, y);
+
+	resource = grab->pointer->rel.focus_resource;
+	if (resource)
+		wl_relative_pointer_send_motion(resource, time, dx, dy);
 }
 
 static void
@@ -537,15 +543,27 @@ default_grab_button(struct wl_pointer_grab *grab,
 		    uint32_t time, uint32_t button, uint32_t state_w)
 {
 	struct wl_pointer *pointer = grab->pointer;
-	struct wl_resource *resource;
+	struct wl_resource *resource, *rel_resource;
 	uint32_t serial;
 	enum wl_pointer_button_state state = state_w;
 
-	resource = pointer->focus_resource;
-	if (resource) {
+	resource = pointer->abs.focus_resource;
+	rel_resource = pointer->rel.focus_resource;
+
+	assert(!resource || !rel_resource ||
+	       resource->client == rel_resource->client);
+
+	if (resource)
 		serial = wl_display_next_serial(resource->client->display);
+	else if (rel_resource)
+		serial = wl_display_next_serial(rel_resource->client->display);
+
+	if (resource)
 		wl_pointer_send_button(resource, serial, time, button, state_w);
-	}
+
+	if (rel_resource)
+		wl_relative_pointer_send_button(rel_resource, serial, time,
+						button, state_w);
 
 	if (pointer->button_count == 0 &&
 	    state == WL_POINTER_BUTTON_STATE_RELEASED)
@@ -631,7 +649,8 @@ WL_EXPORT void
 wl_pointer_init(struct wl_pointer *pointer)
 {
 	memset(pointer, 0, sizeof *pointer);
-	wl_list_init(&pointer->resource_list);
+	wl_list_init(&pointer->abs.resource_list);
+	wl_list_init(&pointer->rel.resource_list);
 	pointer->focus_listener.notify = lose_pointer_focus;
 	pointer->default_grab.interface = &default_pointer_grab_interface;
 	pointer->default_grab.pointer = pointer;
@@ -646,8 +665,8 @@ wl_pointer_init(struct wl_pointer *pointer)
 WL_EXPORT void
 wl_pointer_release(struct wl_pointer *pointer)
 {
-	/* XXX: What about pointer->resource_list? */
-	if (pointer->focus_resource)
+	/* XXX: What about pointer->{abs,rel}.resource_list? */
+	if (pointer->abs.focus_resource || pointer->rel.focus_resource)
 		wl_list_remove(&pointer->focus_listener.link);
 }
 
@@ -783,23 +802,48 @@ wl_pointer_set_focus(struct wl_pointer *pointer, struct wl_surface *surface,
 		     wl_fixed_t sx, wl_fixed_t sy)
 {
 	struct wl_keyboard *kbd = pointer->seat->keyboard;
-	struct wl_resource *resource, *kr;
+	struct wl_resource *resource, *rel_resource, *kr;
 	uint32_t serial;
 
-	resource = pointer->focus_resource;
-	if (resource && pointer->focus != surface) {
-		serial = wl_display_next_serial(resource->client->display);
-		wl_pointer_send_leave(resource, serial,
-				      &pointer->focus->resource);
-		wl_list_remove(&pointer->focus_listener.link);
+	resource = pointer->abs.focus_resource;
+	rel_resource = pointer->rel.focus_resource;
+	if (pointer->focus != surface) {
+		if (resource)
+			serial = wl_display_next_serial(resource->client->display);
+		else if (rel_resource)
+			serial = wl_display_next_serial(rel_resource->client->display);
+
+		if (resource)
+			wl_pointer_send_leave(resource, serial,
+					      &pointer->focus->resource);
+
+		if (rel_resource)
+			wl_relative_pointer_send_leave(rel_resource, serial,
+						       &pointer->focus->resource);
+
+		if (resource || rel_resource)
+			wl_list_remove(&pointer->focus_listener.link);
 	}
 
-	resource = find_resource_for_surface(&pointer->resource_list,
+	resource = find_resource_for_surface(&pointer->abs.resource_list,
 					     surface);
-	if (resource &&
+	rel_resource = find_resource_for_surface(&pointer->rel.resource_list,
+						 surface);
+
+	if ((resource || rel_resource) &&
 	    (pointer->focus != surface ||
-	     pointer->focus_resource != resource)) {
-		serial = wl_display_next_serial(resource->client->display);
+	     (resource && pointer->abs.focus_resource != resource ) ||
+	     (rel_resource && pointer->rel.focus_resource != rel_resource))) {
+		assert(!resource || !rel_resource ||
+		       resource->client == rel_resource->client);
+
+		if (resource)
+			serial = wl_display_next_serial(
+			    resource->client->display);
+		else
+			serial = wl_display_next_serial(
+			    rel_resource->client->display);
+
 		if (kbd) {
 			kr = find_resource_for_surface(&kbd->resource_list,
 						       surface);
@@ -812,14 +856,23 @@ wl_pointer_set_focus(struct wl_pointer *pointer, struct wl_surface *surface,
 							   kbd->modifiers.group);
 			}
 		}
-		wl_pointer_send_enter(resource, serial, &surface->resource,
-				      sx, sy);
+
+		if (resource)
+			wl_pointer_send_enter(resource, serial, &surface->resource,
+					      sx, sy);
+
+		if (rel_resource)
+			wl_relative_pointer_send_enter(rel_resource, serial,
+						       &surface->resource,
+						       sx, sy);
+
 		wl_signal_add(&resource->destroy_signal,
 			      &pointer->focus_listener);
 		pointer->focus_serial = serial;
 	}
 
-	pointer->focus_resource = resource;
+	pointer->abs.focus_resource = resource;
+	pointer->rel.focus_resource = rel_resource;
 	pointer->focus = surface;
 	pointer->default_grab.focus = surface;
 	wl_signal_emit(&pointer->focus_signal, pointer);
diff --git a/src/wayland-server.h b/src/wayland-server.h
index cd79801..151a277 100644
--- a/src/wayland-server.h
+++ b/src/wayland-server.h
@@ -194,7 +194,9 @@ struct wl_pointer_grab_interface {
 	void (*motion)(struct wl_pointer_grab *grab,
 		       uint32_t time,
 		       wl_fixed_t x,
-		       wl_fixed_t y);
+		       wl_fixed_t y,
+		       wl_fixed_t dx,
+		       wl_fixed_t dy);
 	void (*button)(struct wl_pointer_grab *grab,
 		       uint32_t time, uint32_t button, uint32_t state);
 };
@@ -242,13 +244,21 @@ struct wl_data_source {
 struct wl_pointer {
 	struct wl_seat *seat;
 
-	struct wl_list resource_list;
 	struct wl_surface *focus;
-	struct wl_resource *focus_resource;
 	struct wl_listener focus_listener;
 	uint32_t focus_serial;
 	struct wl_signal focus_signal;
 
+	struct {
+		struct wl_resource *focus_resource;
+		struct wl_list resource_list;
+	} abs;
+
+	struct {
+		struct wl_resource *focus_resource;
+		struct wl_list resource_list;
+	} rel;
+
 	struct wl_pointer_grab *grab;
 	struct wl_pointer_grab default_grab;
 	wl_fixed_t grab_x, grab_y;
-- 
1.7.12



More information about the wayland-devel mailing list