mirror of
https://github.com/hyprwm/wlroots-hyprland.git
synced 2024-11-22 04:45:58 +01:00
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
This commit is contained in:
parent
1689a3503b
commit
3898bb482d
5 changed files with 45 additions and 33 deletions
|
@ -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) {
|
static void data_device_handle_resource_destroy(struct wl_resource *resource) {
|
||||||
wl_list_remove(wl_resource_get_link(resource));
|
wl_list_remove(wl_resource_get_link(resource));
|
||||||
|
wl_list_init(wl_resource_get_link(resource));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,9 @@ static void seat_handle_get_pointer(struct wl_client *client,
|
||||||
struct wl_resource *seat_resource, uint32_t id) {
|
struct wl_resource *seat_resource, uint32_t id) {
|
||||||
struct wlr_seat_client *seat_client =
|
struct wlr_seat_client *seat_client =
|
||||||
wlr_seat_client_from_resource(seat_resource);
|
wlr_seat_client_from_resource(seat_resource);
|
||||||
|
if (!seat_client) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!(seat_client->seat->accumulated_capabilities & WL_SEAT_CAPABILITY_POINTER)) {
|
if (!(seat_client->seat->accumulated_capabilities & WL_SEAT_CAPABILITY_POINTER)) {
|
||||||
wl_resource_post_error(seat_resource, WL_SEAT_ERROR_MISSING_CAPABILITY,
|
wl_resource_post_error(seat_resource, WL_SEAT_ERROR_MISSING_CAPABILITY,
|
||||||
"wl_seat.get_pointer called when no pointer capability has existed");
|
"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 wl_resource *seat_resource, uint32_t id) {
|
||||||
struct wlr_seat_client *seat_client =
|
struct wlr_seat_client *seat_client =
|
||||||
wlr_seat_client_from_resource(seat_resource);
|
wlr_seat_client_from_resource(seat_resource);
|
||||||
|
if (!seat_client) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!(seat_client->seat->accumulated_capabilities & WL_SEAT_CAPABILITY_KEYBOARD)) {
|
if (!(seat_client->seat->accumulated_capabilities & WL_SEAT_CAPABILITY_KEYBOARD)) {
|
||||||
wl_resource_post_error(seat_resource, WL_SEAT_ERROR_MISSING_CAPABILITY,
|
wl_resource_post_error(seat_resource, WL_SEAT_ERROR_MISSING_CAPABILITY,
|
||||||
"wl_seat.get_keyboard called when no keyboard capability has existed");
|
"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 wl_resource *seat_resource, uint32_t id) {
|
||||||
struct wlr_seat_client *seat_client =
|
struct wlr_seat_client *seat_client =
|
||||||
wlr_seat_client_from_resource(seat_resource);
|
wlr_seat_client_from_resource(seat_resource);
|
||||||
|
if (!seat_client) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!(seat_client->seat->accumulated_capabilities & WL_SEAT_CAPABILITY_TOUCH)) {
|
if (!(seat_client->seat->accumulated_capabilities & WL_SEAT_CAPABILITY_TOUCH)) {
|
||||||
wl_resource_post_error(seat_resource, WL_SEAT_ERROR_MISSING_CAPABILITY,
|
wl_resource_post_error(seat_resource, WL_SEAT_ERROR_MISSING_CAPABILITY,
|
||||||
"wl_seat.get_touch called when no touch capability has existed");
|
"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);
|
seat_client_create_touch(seat_client, version, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void seat_client_handle_resource_destroy(
|
static void seat_client_destroy(struct wlr_seat_client *client) {
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_signal_emit_mutable(&client->events.destroy, client);
|
wl_signal_emit_mutable(&client->events.destroy, client);
|
||||||
|
|
||||||
if (client == client->seat->pointer_state.focused_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;
|
struct wl_resource *resource, *tmp;
|
||||||
wl_resource_for_each_safe(resource, tmp, &client->pointers) {
|
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_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_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) {
|
wl_resource_for_each_safe(resource, tmp, &client->data_devices) {
|
||||||
// Make the data device inert
|
// 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);
|
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);
|
wl_list_remove(&client->link);
|
||||||
free(client);
|
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,
|
static void seat_handle_release(struct wl_client *client,
|
||||||
struct wl_resource *resource) {
|
struct wl_resource *resource) {
|
||||||
wl_resource_destroy(resource);
|
wl_resource_destroy(resource);
|
||||||
|
@ -207,19 +227,7 @@ void wlr_seat_destroy(struct wlr_seat *seat) {
|
||||||
|
|
||||||
struct wlr_seat_client *client, *tmp;
|
struct wlr_seat_client *client, *tmp;
|
||||||
wl_list_for_each_safe(client, tmp, &seat->clients, link) {
|
wl_list_for_each_safe(client, tmp, &seat->clients, link) {
|
||||||
struct wl_resource *resource, *next;
|
seat_client_destroy(client);
|
||||||
/* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_global_destroy_safe(seat->global);
|
wlr_global_destroy_safe(seat->global);
|
||||||
|
|
|
@ -59,7 +59,6 @@ static struct wlr_seat_client *seat_client_from_keyboard_resource(
|
||||||
}
|
}
|
||||||
|
|
||||||
static void keyboard_handle_resource_destroy(struct wl_resource *resource) {
|
static void keyboard_handle_resource_destroy(struct wl_resource *resource) {
|
||||||
wl_list_remove(wl_resource_get_link(resource));
|
|
||||||
seat_client_destroy_keyboard(resource);
|
seat_client_destroy_keyboard(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -445,5 +444,7 @@ void seat_client_destroy_keyboard(struct wl_resource *resource) {
|
||||||
if (seat_client == NULL) {
|
if (seat_client == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
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_set_user_data(resource, NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,7 +114,6 @@ static const struct wl_pointer_interface pointer_impl = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static void pointer_handle_resource_destroy(struct wl_resource *resource) {
|
static void pointer_handle_resource_destroy(struct wl_resource *resource) {
|
||||||
wl_list_remove(wl_resource_get_link(resource));
|
|
||||||
seat_client_destroy_pointer(resource);
|
seat_client_destroy_pointer(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -538,6 +537,8 @@ void seat_client_destroy_pointer(struct wl_resource *resource) {
|
||||||
if (seat_client == NULL) {
|
if (seat_client == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
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_set_user_data(resource, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,7 +66,6 @@ static const struct wl_touch_interface touch_impl = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static void touch_handle_resource_destroy(struct wl_resource *resource) {
|
static void touch_handle_resource_destroy(struct wl_resource *resource) {
|
||||||
wl_list_remove(wl_resource_get_link(resource));
|
|
||||||
seat_client_destroy_touch(resource);
|
seat_client_destroy_touch(resource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -449,6 +448,8 @@ void seat_client_destroy_touch(struct wl_resource *resource) {
|
||||||
if (seat_client == NULL) {
|
if (seat_client == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
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_set_user_data(resource, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue