[PATCH 2/2] Terminate grabs when the client that initiated them exits

Ander Conselvan de Oliveira conselvan2 at gmail.com
Fri Mar 2 05:45:57 PST 2012


Add a client parameter to wl_input_device_start_pointer_focus(). If
it is non-nil, if that client terminates while the grab is still
active, the grab is ended and the current focus is set to NULL.
---
 src/data-device.c    |    3 ++-
 src/wayland-server.c |   28 +++++++++++++++++++++++++++-
 src/wayland-server.h |    4 +++-
 3 files changed, 32 insertions(+), 3 deletions(-)

diff --git a/src/data-device.c b/src/data-device.c
index be2360c..93ad4e7 100644
--- a/src/data-device.c
+++ b/src/data-device.c
@@ -326,7 +326,8 @@ data_device_start_drag(struct wl_client *client, struct wl_resource *resource,
 			       &device->drag_icon_listener.link);
 	}
 
-	wl_input_device_start_pointer_grab(device, &device->drag_grab, time);
+	wl_input_device_start_pointer_grab(device, &device->drag_grab, time,
+					   source_resource->client);
 }
 
 static void
diff --git a/src/wayland-server.c b/src/wayland-server.c
index 6a8cbcb..6538a29 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -649,12 +649,38 @@ wl_input_device_end_keyboard_grab(struct wl_input_device *device, uint32_t time)
 	device->keyboard_grab = &device->default_keyboard_grab;
 }
 
+static void
+destroy_grab_client(struct wl_listener *listener,
+		    struct wl_resource *resource, uint32_t time)
+{
+	struct wl_input_device *device =
+		container_of(listener, struct wl_input_device,
+			     grab_client_listener);
+
+	wl_input_device_end_pointer_grab(device, time);
+
+	/* if the client died, it is very likely the user is still holding a
+	 * button that caused the grab to start and this probably happened
+	 * when the focus was in one of the client's surfaces. Since the
+	 * button down prevents the default grab from resetting the focus and
+	 * the default grab will have the focus saved as that surfaces,
+	 * set the focus to NULL here. */
+	wl_input_device_set_pointer_focus(device, NULL, time, 0, 0);
+}
+
 WL_EXPORT void
 wl_input_device_start_pointer_grab(struct wl_input_device *device,
-			   struct wl_pointer_grab *grab, uint32_t time)
+				   struct wl_pointer_grab *grab, uint32_t time,
+				   struct wl_client *client)
 {
 	const struct wl_pointer_grab_interface *interface;
 
+	if (client) {
+		device->grab_client_listener.func = destroy_grab_client;
+		wl_list_insert(client->display_resource->destroy_listener_list.prev,
+			       &device->grab_client_listener.link);
+	}
+
 	device->pointer_grab = grab;
 	interface = device->pointer_grab->interface;
 	grab->input_device = device;
diff --git a/src/wayland-server.h b/src/wayland-server.h
index a1ddc68..0ae4bce 100644
--- a/src/wayland-server.h
+++ b/src/wayland-server.h
@@ -224,6 +224,7 @@ struct wl_input_device {
 	uint32_t grab_button;
 	uint32_t grab_key;
 	struct wl_listener grab_listener;
+	struct wl_listener grab_client_listener;
 
 	struct wl_list drag_resource_list;
 	struct wl_data_source *drag_data_source;
@@ -309,7 +310,8 @@ wl_input_device_end_keyboard_grab(struct wl_input_device *device, uint32_t time)
 
 void
 wl_input_device_start_pointer_grab(struct wl_input_device *device,
-			   struct wl_pointer_grab *grab, uint32_t time);
+				   struct wl_pointer_grab *grab, uint32_t time,
+				   struct wl_client *client);
 void
 wl_input_device_end_pointer_grab(struct wl_input_device *device, uint32_t time);
 
-- 
1.7.5.4



More information about the wayland-devel mailing list