mirror of
				https://gitlab.freedesktop.org/wlroots/wlroots.git
				synced 2025-11-03 09:01:40 -05:00 
			
		
		
		
	Improve inert resource handling
This commit is contained in:
		
							parent
							
								
									b79d11395c
								
							
						
					
					
						commit
						2155c976f6
					
				
					 2 changed files with 83 additions and 51 deletions
				
			
		
							
								
								
									
										20
									
								
								include/types/wlr_tablet_v2.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								include/types/wlr_tablet_v2.h
									
										
									
									
									
										Normal 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 */
 | 
				
			||||||
| 
						 | 
					@ -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);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue