diff options
author | Andri Yngvason <andri@yngvason.is> | 2023-04-02 10:18:28 +0000 |
---|---|---|
committer | Simon Ser <contact@emersion.fr> | 2023-04-18 08:29:30 +0000 |
commit | 3898bb482deb06dc999a57e25fed8f11ef2aa627 (patch) | |
tree | bcbbc9dc6fba2e19e7449a0c1e1830a18f827322 | |
parent | 1689a3503b7b2595a6e28b392aeb10ff09dc380a (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.c | 1 | ||||
-rw-r--r-- | types/seat/wlr_seat.c | 68 | ||||
-rw-r--r-- | types/seat/wlr_seat_keyboard.c | 3 | ||||
-rw-r--r-- | types/seat/wlr_seat_pointer.c | 3 | ||||
-rw-r--r-- | types/seat/wlr_seat_touch.c | 3 |
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); } |