aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndri Yngvason <andri@yngvason.is>2023-04-02 10:18:28 +0000
committerSimon Ser <contact@emersion.fr>2023-04-18 08:29:30 +0000
commit3898bb482deb06dc999a57e25fed8f11ef2aa627 (patch)
treebcbbc9dc6fba2e19e7449a0c1e1830a18f827322
parent1689a3503b7b2595a6e28b392aeb10ff09dc380a (diff)
seat: Let client manage its own resources
This makes seat_client resources inert when seats and/or input devices are destroyed, rather than destroying the resources. When the client calls e.g. wl_keyboard_release(), it's not expecting the keyboard global to be already destroyed, so this results in an error such as this: wl_display@1: error 0: invalid object 22
-rw-r--r--types/data_device/wlr_data_device.c1
-rw-r--r--types/seat/wlr_seat.c68
-rw-r--r--types/seat/wlr_seat_keyboard.c3
-rw-r--r--types/seat/wlr_seat_pointer.c3
-rw-r--r--types/seat/wlr_seat_touch.c3
5 files changed, 45 insertions, 33 deletions
diff --git a/types/data_device/wlr_data_device.c b/types/data_device/wlr_data_device.c
index 7e674790..428f7906 100644
--- a/types/data_device/wlr_data_device.c
+++ b/types/data_device/wlr_data_device.c
@@ -99,6 +99,7 @@ static const struct wl_data_device_interface data_device_impl = {
static void data_device_handle_resource_destroy(struct wl_resource *resource) {
wl_list_remove(wl_resource_get_link(resource));
+ wl_list_init(wl_resource_get_link(resource));
}
diff --git a/types/seat/wlr_seat.c b/types/seat/wlr_seat.c
index f1bda82e..0b536d59 100644
--- a/types/seat/wlr_seat.c
+++ b/types/seat/wlr_seat.c
@@ -18,6 +18,9 @@ static void seat_handle_get_pointer(struct wl_client *client,
struct wl_resource *seat_resource, uint32_t id) {
struct wlr_seat_client *seat_client =
wlr_seat_client_from_resource(seat_resource);
+ if (!seat_client) {
+ return;
+ }
if (!(seat_client->seat->accumulated_capabilities & WL_SEAT_CAPABILITY_POINTER)) {
wl_resource_post_error(seat_resource, WL_SEAT_ERROR_MISSING_CAPABILITY,
"wl_seat.get_pointer called when no pointer capability has existed");
@@ -32,6 +35,9 @@ static void seat_handle_get_keyboard(struct wl_client *client,
struct wl_resource *seat_resource, uint32_t id) {
struct wlr_seat_client *seat_client =
wlr_seat_client_from_resource(seat_resource);
+ if (!seat_client) {
+ return;
+ }
if (!(seat_client->seat->accumulated_capabilities & WL_SEAT_CAPABILITY_KEYBOARD)) {
wl_resource_post_error(seat_resource, WL_SEAT_ERROR_MISSING_CAPABILITY,
"wl_seat.get_keyboard called when no keyboard capability has existed");
@@ -46,6 +52,9 @@ static void seat_handle_get_touch(struct wl_client *client,
struct wl_resource *seat_resource, uint32_t id) {
struct wlr_seat_client *seat_client =
wlr_seat_client_from_resource(seat_resource);
+ if (!seat_client) {
+ return;
+ }
if (!(seat_client->seat->accumulated_capabilities & WL_SEAT_CAPABILITY_TOUCH)) {
wl_resource_post_error(seat_resource, WL_SEAT_ERROR_MISSING_CAPABILITY,
"wl_seat.get_touch called when no touch capability has existed");
@@ -56,16 +65,7 @@ static void seat_handle_get_touch(struct wl_client *client,
seat_client_create_touch(seat_client, version, id);
}
-static void seat_client_handle_resource_destroy(
- struct wl_resource *seat_resource) {
- struct wlr_seat_client *client =
- wlr_seat_client_from_resource(seat_resource);
-
- wl_list_remove(wl_resource_get_link(seat_resource));
- if (!wl_list_empty(&client->resources)) {
- return;
- }
-
+static void seat_client_destroy(struct wlr_seat_client *client) {
wl_signal_emit_mutable(&client->events.destroy, client);
if (client == client->seat->pointer_state.focused_client) {
@@ -81,27 +81,47 @@ static void seat_client_handle_resource_destroy(
struct wl_resource *resource, *tmp;
wl_resource_for_each_safe(resource, tmp, &client->pointers) {
- wl_resource_destroy(resource);
+ seat_client_destroy_pointer(resource);
}
wl_resource_for_each_safe(resource, tmp, &client->keyboards) {
- wl_resource_destroy(resource);
+ seat_client_destroy_keyboard(resource);
}
wl_resource_for_each_safe(resource, tmp, &client->touches) {
- wl_resource_destroy(resource);
+ seat_client_destroy_touch(resource);
}
wl_resource_for_each_safe(resource, tmp, &client->data_devices) {
// Make the data device inert
+ wl_list_remove(wl_resource_get_link(resource));
+ wl_list_init(wl_resource_get_link(resource));
+ wl_resource_set_user_data(resource, NULL);
+ }
+ wl_resource_for_each_safe(resource, tmp, &client->resources) {
+ // Make the seat resource inert
+ wl_list_remove(wl_resource_get_link(resource));
+ wl_list_init(wl_resource_get_link(resource));
wl_resource_set_user_data(resource, NULL);
-
- struct wl_list *link = wl_resource_get_link(resource);
- wl_list_remove(link);
- wl_list_init(link);
}
wl_list_remove(&client->link);
free(client);
}
+static void seat_client_handle_resource_destroy(
+ struct wl_resource *seat_resource) {
+ struct wlr_seat_client *client =
+ wlr_seat_client_from_resource(seat_resource);
+ if (!client) {
+ return;
+ }
+
+ wl_list_remove(wl_resource_get_link(seat_resource));
+ if (!wl_list_empty(&client->resources)) {
+ return;
+ }
+
+ seat_client_destroy(client);
+}
+
static void seat_handle_release(struct wl_client *client,
struct wl_resource *resource) {
wl_resource_destroy(resource);
@@ -207,19 +227,7 @@ void wlr_seat_destroy(struct wlr_seat *seat) {
struct wlr_seat_client *client, *tmp;
wl_list_for_each_safe(client, tmp, &seat->clients, link) {
- struct wl_resource *resource, *next;
- /* wl_resource_for_each_safe isn't safe to use here, because the last
- * wl_resource_destroy will also destroy the head we cannot do the last
- * 'next' update that usually is harmless here.
- * Work around this by breaking one step ahead
- */
- wl_resource_for_each_safe(resource, next, &client->resources) {
- // will destroy other resources as well
- wl_resource_destroy(resource);
- if (wl_resource_get_link(next) == &client->resources) {
- break;
- }
- }
+ seat_client_destroy(client);
}
wlr_global_destroy_safe(seat->global);
diff --git a/types/seat/wlr_seat_keyboard.c b/types/seat/wlr_seat_keyboard.c
index 51456f8b..874e43ea 100644
--- a/types/seat/wlr_seat_keyboard.c
+++ b/types/seat/wlr_seat_keyboard.c
@@ -59,7 +59,6 @@ static struct wlr_seat_client *seat_client_from_keyboard_resource(
}
static void keyboard_handle_resource_destroy(struct wl_resource *resource) {
- wl_list_remove(wl_resource_get_link(resource));
seat_client_destroy_keyboard(resource);
}
@@ -445,5 +444,7 @@ void seat_client_destroy_keyboard(struct wl_resource *resource) {
if (seat_client == NULL) {
return;
}
+ wl_list_remove(wl_resource_get_link(resource));
+ wl_list_init(wl_resource_get_link(resource));
wl_resource_set_user_data(resource, NULL);
}
diff --git a/types/seat/wlr_seat_pointer.c b/types/seat/wlr_seat_pointer.c
index ffa706bd..cc4fd441 100644
--- a/types/seat/wlr_seat_pointer.c
+++ b/types/seat/wlr_seat_pointer.c
@@ -114,7 +114,6 @@ static const struct wl_pointer_interface pointer_impl = {
};
static void pointer_handle_resource_destroy(struct wl_resource *resource) {
- wl_list_remove(wl_resource_get_link(resource));
seat_client_destroy_pointer(resource);
}
@@ -538,6 +537,8 @@ void seat_client_destroy_pointer(struct wl_resource *resource) {
if (seat_client == NULL) {
return;
}
+ wl_list_remove(wl_resource_get_link(resource));
+ wl_list_init(wl_resource_get_link(resource));
wl_resource_set_user_data(resource, NULL);
}
diff --git a/types/seat/wlr_seat_touch.c b/types/seat/wlr_seat_touch.c
index 9b533c07..a298cf28 100644
--- a/types/seat/wlr_seat_touch.c
+++ b/types/seat/wlr_seat_touch.c
@@ -66,7 +66,6 @@ static const struct wl_touch_interface touch_impl = {
};
static void touch_handle_resource_destroy(struct wl_resource *resource) {
- wl_list_remove(wl_resource_get_link(resource));
seat_client_destroy_touch(resource);
}
@@ -449,6 +448,8 @@ void seat_client_destroy_touch(struct wl_resource *resource) {
if (seat_client == NULL) {
return;
}
+ wl_list_remove(wl_resource_get_link(resource));
+ wl_list_init(wl_resource_get_link(resource));
wl_resource_set_user_data(resource, NULL);
}