Improve inert resource handling

This commit is contained in:
Markus Ongyerth 2018-05-17 11:10:31 +02:00
parent b79d11395c
commit 2155c976f6
2 changed files with 83 additions and 51 deletions

View file

@ -0,0 +1,20 @@
#ifndef TYPES_WLR_TABLET_V2_H
#define TYPES_WLR_TABLET_V2_H
#include "tablet-unstable-v2-protocol.h"
#include <wayland-server.h>
#include <wlr/types/wlr_tablet_v2.h>
struct wlr_tablet_client_v2 *tablet_client_from_resource(struct wl_resource *resource);
void destroy_tablet_v2(struct wl_resource *resource);
void destroy_tablet_pad_v2(struct wl_resource *resource);
struct wlr_tablet_pad_client_v2 *tablet_pad_client_from_resource(struct wl_resource *resource);
void destroy_tablet_tool_v2(struct wl_resource *resource);
struct wlr_tablet_tool_client_v2 *tablet_tool_client_from_resource(struct wl_resource *resource);
struct wlr_tablet_seat_client_v2 *tablet_seat_client_from_resource(struct wl_resource *resource);
static void wlr_tablet_seat_client_v2_destroy(struct wl_resource *resource);
#endif /* TYPES_WLR_TABLET_V2_H */

View file

@ -7,6 +7,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <wayland-server.h> #include <wayland-server.h>
#include <types/wlr_tablet_v2.h>
#include <wlr/config.h> #include <wlr/config.h>
#include <wlr/types/wlr_seat.h> #include <wlr/types/wlr_seat.h>
#include <wlr/types/wlr_tablet_tool.h> #include <wlr/types/wlr_tablet_tool.h>
@ -104,18 +105,23 @@ struct tablet_pad_auxiliary_user_data {
static struct zwp_tablet_v2_interface tablet_impl; static struct zwp_tablet_v2_interface tablet_impl;
static struct wlr_tablet_client_v2 *tablet_client_from_resource(struct wl_resource *resource) { struct wlr_tablet_client_v2 *tablet_client_from_resource(struct wl_resource *resource) {
assert(wl_resource_instance_of(resource, &zwp_tablet_v2_interface, assert(wl_resource_instance_of(resource, &zwp_tablet_v2_interface,
&tablet_impl)); &tablet_impl));
return wl_resource_get_user_data(resource); return wl_resource_get_user_data(resource);
} }
static void destroy_tablet_v2(struct wl_resource *resource) { void destroy_tablet_v2(struct wl_resource *resource) {
struct wlr_tablet_client_v2 *tablet = tablet_client_from_resource(resource); struct wlr_tablet_client_v2 *tablet = tablet_client_from_resource(resource);
if (!tablet) {
return;
}
wl_list_remove(&tablet->seat_link); wl_list_remove(&tablet->seat_link);
wl_list_remove(&tablet->tablet_link); wl_list_remove(&tablet->tablet_link);
free(tablet); free(tablet);
wl_resource_set_user_data(resource, NULL);
} }
static void handle_tablet_v2_destroy(struct wl_client *client, static void handle_tablet_v2_destroy(struct wl_client *client,
@ -127,33 +133,6 @@ static struct zwp_tablet_v2_interface tablet_impl = {
.destroy = handle_tablet_v2_destroy, .destroy = handle_tablet_v2_destroy,
}; };
static void destroy_tablet_seat_client(struct wlr_tablet_seat_client_v2 *client) {
/* This is only called when the seat or client gets destroyed.
* The client is liable to make a request on a deleted resource either
* way, so we don't do the removed->destroy process, but just remove
* all structs immediatly.
*/
struct wlr_tablet_client_v2 *tablet;
struct wlr_tablet_client_v2 *tmp_tablet;
wl_list_for_each_safe(tablet, tmp_tablet, &client->tablets, seat_link) {
wl_resource_destroy(tablet->resource);
}
struct wlr_tablet_pad_client_v2 *pad;
struct wlr_tablet_pad_client_v2 *tmp_pad;
wl_list_for_each_safe(pad, tmp_pad, &client->pads, seat_link) {
wl_resource_destroy(pad->resource);
}
struct wlr_tablet_tool_client_v2 *tool;
struct wlr_tablet_tool_client_v2 *tmp_tool;
wl_list_for_each_safe(tool, tmp_tool, &client->tools, seat_link) {
wl_resource_destroy(tool->resource);
}
wl_resource_destroy(client->resource);
}
static void handle_wlr_seat_destroy(struct wl_listener *listener, void *data) { static void handle_wlr_seat_destroy(struct wl_listener *listener, void *data) {
struct wlr_tablet_seat_v2 *seat = struct wlr_tablet_seat_v2 *seat =
wl_container_of(listener, seat, seat_destroy); wl_container_of(listener, seat, seat_destroy);
@ -163,13 +142,8 @@ static void handle_wlr_seat_destroy(struct wl_listener *listener, void *data) {
struct wlr_tablet_seat_client_v2 *client; struct wlr_tablet_seat_client_v2 *client;
struct wlr_tablet_seat_client_v2 *tmp; struct wlr_tablet_seat_client_v2 *tmp;
/* wl_seat doesn't have a removed event/destroy request, so we can just
* destroy all attached tablet_seat_clients -> tablet_v2 resources.
* The client can call requests on gone resources either way
*/
wl_list_for_each_safe(client, tmp, &seat->clients, seat_link) { wl_list_for_each_safe(client, tmp, &seat->clients, seat_link) {
destroy_tablet_seat_client(client); wlr_tablet_seat_client_v2_destroy(client->resource);
} }
} }
@ -271,7 +245,7 @@ static void handle_tablet_tool_v2_set_cursor(struct wl_client *client,
struct wl_resource *resource, uint32_t serial, struct wl_resource *resource, uint32_t serial,
struct wl_resource *surface_resource, struct wl_resource *surface_resource,
int32_t hotspot_x, int32_t hotspot_y) { int32_t hotspot_x, int32_t hotspot_y) {
struct wlr_tablet_tool_client_v2 *tool = wl_resource_get_user_data(resource); struct wlr_tablet_tool_client_v2 *tool = tablet_tool_client_from_resource(resource);
if (!tool) { if (!tool) {
return; return;
} }
@ -327,9 +301,13 @@ static enum zwp_tablet_tool_v2_type tablet_type_from_wlr_type(
assert(false && "Unreachable"); assert(false && "Unreachable");
} }
static void destroy_tablet_tool(struct wl_resource *resource) { void destroy_tablet_tool_v2(struct wl_resource *resource) {
struct wlr_tablet_tool_client_v2 *client = struct wlr_tablet_tool_client_v2 *client =
wl_resource_get_user_data(resource); tablet_tool_client_from_resource(resource);
if (!client) {
return;
}
if (client->frame_source) { if (client->frame_source) {
wl_event_source_remove(client->frame_source); wl_event_source_remove(client->frame_source);
@ -342,6 +320,8 @@ static void destroy_tablet_tool(struct wl_resource *resource) {
wl_list_remove(&client->seat_link); wl_list_remove(&client->seat_link);
wl_list_remove(&client->tool_link); wl_list_remove(&client->tool_link);
free(client); free(client);
wl_resource_set_user_data(resource, NULL);
} }
static void add_tablet_tool_client(struct wlr_tablet_seat_client_v2 *seat, static void add_tablet_tool_client(struct wlr_tablet_seat_client_v2 *seat,
@ -361,7 +341,7 @@ static void add_tablet_tool_client(struct wlr_tablet_seat_client_v2 *seat,
return; return;
} }
wl_resource_set_implementation(client->resource, &tablet_tool_impl, wl_resource_set_implementation(client->resource, &tablet_tool_impl,
client, destroy_tablet_tool); client, destroy_tablet_tool_v2);
zwp_tablet_seat_v2_send_tool_added(seat->resource, client->resource); zwp_tablet_seat_v2_send_tool_added(seat->resource, client->resource);
// Send the expected events // Send the expected events
@ -506,17 +486,21 @@ struct wlr_tablet_v2_tablet_tool *wlr_tablet_tool_create(
static struct zwp_tablet_pad_v2_interface tablet_pad_impl; static struct zwp_tablet_pad_v2_interface tablet_pad_impl;
static struct wlr_tablet_pad_client_v2 *tablet_pad_client_from_resource(struct wl_resource *resource) { struct wlr_tablet_pad_client_v2 *tablet_pad_client_from_resource(struct wl_resource *resource) {
assert(wl_resource_instance_of(resource, &zwp_tablet_pad_v2_interface, assert(wl_resource_instance_of(resource, &zwp_tablet_pad_v2_interface,
&tablet_pad_impl)); &tablet_pad_impl));
return wl_resource_get_user_data(resource); return wl_resource_get_user_data(resource);
} }
static void destroy_tablet_pad_v2(struct wl_resource *resource) { void destroy_tablet_pad_v2(struct wl_resource *resource) {
struct wlr_tablet_pad_client_v2 *pad = struct wlr_tablet_pad_client_v2 *pad =
tablet_pad_client_from_resource(resource); tablet_pad_client_from_resource(resource);
if (!pad) {
return;
}
wl_list_remove(&pad->seat_link); wl_list_remove(&pad->seat_link);
wl_list_remove(&pad->pad_link); wl_list_remove(&pad->pad_link);
@ -547,6 +531,7 @@ static void destroy_tablet_pad_v2(struct wl_resource *resource) {
free(pad->strips); free(pad->strips);
free(pad); free(pad);
wl_resource_set_user_data(resource, NULL);
} }
static void handle_tablet_pad_v2_destroy(struct wl_client *client, static void handle_tablet_pad_v2_destroy(struct wl_client *client,
@ -633,7 +618,10 @@ static struct zwp_tablet_pad_strip_v2_interface tablet_pad_strip_impl = {
static void handle_tablet_pad_v2_set_feedback( struct wl_client *client, static void handle_tablet_pad_v2_set_feedback( struct wl_client *client,
struct wl_resource *resource, uint32_t button, struct wl_resource *resource, uint32_t button,
const char *description, uint32_t serial) { const char *description, uint32_t serial) {
struct wlr_tablet_v2_tablet_pad *pad = wl_resource_get_user_data(resource); struct wlr_tablet_pad_client_v2 *pad = tablet_pad_client_from_resource(resource);
if (!pad) {
return;
}
struct wlr_tablet_v2_event_feedback evt = { struct wlr_tablet_v2_event_feedback evt = {
.serial = serial, .serial = serial,
@ -641,7 +629,7 @@ static void handle_tablet_pad_v2_set_feedback( struct wl_client *client,
.description = description, .description = description,
}; };
wl_signal_emit(&pad->events.button_feedback, &evt); wl_signal_emit(&pad->pad->events.button_feedback, &evt);
} }
static struct zwp_tablet_pad_v2_interface tablet_pad_impl = { static struct zwp_tablet_pad_v2_interface tablet_pad_impl = {
@ -891,31 +879,49 @@ static struct zwp_tablet_seat_v2_interface seat_impl = {
.destroy = tablet_seat_destroy, .destroy = tablet_seat_destroy,
}; };
static struct wlr_tablet_seat_client_v2 *tablet_seat_from_resource ( struct wlr_tablet_seat_client_v2 *tablet_seat_client_from_resource(
struct wl_resource *resource) { struct wl_resource *resource) {
assert(wl_resource_instance_of(resource, &zwp_tablet_seat_v2_interface, assert(wl_resource_instance_of(resource, &zwp_tablet_seat_v2_interface,
&seat_impl)); &seat_impl));
return wl_resource_get_user_data(resource); return wl_resource_get_user_data(resource);
} }
static void wlr_tablet_seat_client_v2_destroy(struct wl_resource *resource) { void wlr_tablet_seat_client_v2_destroy(struct wl_resource *resource) {
struct wlr_tablet_seat_client_v2 *seat = tablet_seat_from_resource(resource); struct wlr_tablet_seat_client_v2 *seat = tablet_seat_client_from_resource(resource);
if (!seat) {
return;
}
/* XXX: Evaluate whether we should have a way to access structs */ struct wlr_tablet_client_v2 *tablet;
wl_list_remove(&seat->tools); struct wlr_tablet_client_v2 *tmp_tablet;
wl_list_remove(&seat->tablets); wl_list_for_each_safe(tablet, tmp_tablet, &seat->tablets, seat_link) {
wl_list_remove(&seat->pads); destroy_tablet_v2(tablet->resource);
}
struct wlr_tablet_pad_client_v2 *pad;
struct wlr_tablet_pad_client_v2 *tmp_pad;
wl_list_for_each_safe(pad, tmp_pad, &seat->pads, seat_link) {
destroy_tablet_pad_v2(pad->resource);
}
struct wlr_tablet_tool_client_v2 *tool;
struct wlr_tablet_tool_client_v2 *tmp_tool;
wl_list_for_each_safe(tool, tmp_tool, &seat->tools, seat_link) {
destroy_tablet_tool_v2(tool->resource);
}
wl_list_remove(&seat->seat_link); wl_list_remove(&seat->seat_link);
wl_list_remove(&seat->client_link); wl_list_remove(&seat->client_link);
wl_list_remove(&seat->seat_client_destroy.link);
free(seat); free(seat);
wl_resource_set_user_data(resource, NULL);
} }
static void handle_seat_client_destroy(struct wl_listener *listener, void *data) { static void handle_seat_client_destroy(struct wl_listener *listener, void *data) {
struct wlr_tablet_seat_client_v2 *seat = struct wlr_tablet_seat_client_v2 *seat =
wl_container_of(listener, seat, seat_client_destroy); wl_container_of(listener, seat, seat_client_destroy);
destroy_tablet_seat_client(seat); wlr_tablet_seat_client_v2_destroy(seat->resource);
} }
static void tablet_manager_destroy(struct wl_client *client, static void tablet_manager_destroy(struct wl_client *client,
@ -1426,3 +1432,9 @@ bool wlr_surface_accepts_tablet_v2(struct wlr_tablet_v2_tablet *tablet,
return false; return false;
} }
struct wlr_tablet_tool_client_v2 *tablet_tool_client_from_resource(struct wl_resource *resource) {
assert(wl_resource_instance_of(resource, &zwp_tablet_tool_v2_interface,
&tablet_tool_impl));
return wl_resource_get_user_data(resource);
}