• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
2From: Lloyd Pique <lpique@google.com>
3Date: Fri, 29 Jan 2021 15:01:46 -0800
4Subject: [PATCH 3/3] client+server: Safe casts from wl_object *
5
6This allows client or server code to safely convert an opaque pointer to a
7wl_object, which has no accessors, into an opaque pointer to either wl_proxy
8(client) or wl_resource (server), which does have some useful accessors.
9
10This is helpful in implementing callbacks that are given a raw "union
11wl_argument *" array, and that want to inspect the ".o" field beyond getting
12the raw pointer value.
13
14Right now the callback would have to assume that the "wl_resource *" or
15"wl_proxy *" could be constructed by a simple cast from the "wl_object *" value,
16as the wl_object is the first thing in both structures.
17
18With these two conversion functions, clients and servers could be cleaned up to
19no longer make that assumption, and maybe some day the core code could do
20make a change that would break that assumption.
21
22Signed-off-by: Lloyd Pique <lpique@google.com>
23
24diff --git a/src/wayland-client-core.h b/src/wayland-client-core.h
25index 547ae04..94c25e3 100644
26--- a/src/wayland-client-core.h
27+++ b/src/wayland-client-core.h
28@@ -204,6 +204,9 @@ wl_proxy_get_class(struct wl_proxy *proxy);
29 void
30 wl_proxy_set_queue(struct wl_proxy *proxy, struct wl_event_queue *queue);
31
32+struct wl_proxy *
33+wl_proxy_from_object(struct wl_object *object);
34+
35 struct wl_display *
36 wl_display_connect(const char *name);
37
38diff --git a/src/wayland-client.c b/src/wayland-client.c
39index 7f5a651..74d4861 100644
40--- a/src/wayland-client.c
41+++ b/src/wayland-client.c
42@@ -2307,6 +2307,28 @@ wl_proxy_wrapper_destroy(void *proxy_wrapper)
43 	free(wrapper);
44 }
45
46+/** Safely converts an object into its corresponding proxy
47+ *
48+ * \param object The object to convert
49+ * \return A corresponding proxy, or NULL on failure
50+ *
51+ * Safely converts an object into its corresponding proxy.
52+ *
53+ * This is useful for implementing functions that are given a \c wl_argument
54+ * array, and that need to do further introspection on the ".o" field, as it
55+ * is otherwise an opaque type.
56+ *
57+ * \memberof wl_proxy
58+ */
59+WL_EXPORT struct wl_proxy *
60+wl_proxy_from_object(struct wl_object *object)
61+{
62+	struct wl_proxy *proxy;
63+	if (object == NULL)
64+		return NULL;
65+	return wl_container_of(object, proxy, object);
66+}
67+
68 WL_EXPORT void
69 wl_log_set_handler_client(wl_log_func_t handler)
70 {
71diff --git a/src/wayland-server-core.h b/src/wayland-server-core.h
72index 64d7169..e5f4e43 100644
73--- a/src/wayland-server-core.h
74+++ b/src/wayland-server-core.h
75@@ -587,6 +587,9 @@ struct wl_listener *
76 wl_resource_get_destroy_listener(struct wl_resource *resource,
77 				 wl_notify_func_t notify);
78
79+struct wl_resource *
80+wl_resource_from_object(struct wl_object *object);
81+
82 #define wl_resource_for_each(resource, list)					\
83 	for (resource = 0, resource = wl_resource_from_link((list)->next);	\
84 	     wl_resource_get_link(resource) != (list);				\
85diff --git a/src/wayland-server.c b/src/wayland-server.c
86index d83bdec..ca0d98d 100644
87--- a/src/wayland-server.c
88+++ b/src/wayland-server.c
89@@ -858,6 +858,28 @@ wl_resource_get_class(struct wl_resource *resource)
90 	return resource->object.interface->name;
91 }
92
93+/** Safely converts an object into its corresponding resource
94+ *
95+ * \param object The object to convert
96+ * \return A corresponding resource, or NULL on failure
97+ *
98+ * Safely converts an object into its corresponding resource.
99+ *
100+ * This is useful for implementing functions that are given a \c wl_argument
101+ * array, and that need to do further introspection on the ".o" field, as it
102+ * is otherwise an opaque type.
103+ *
104+ * \memberof wl_resource
105+ */
106+WL_EXPORT struct wl_resource *
107+wl_resource_from_object(struct wl_object *object)
108+{
109+	struct wl_resource *resource;
110+	if (object == NULL)
111+		return NULL;
112+	return wl_container_of(object, resource, object);
113+}
114+
115 WL_EXPORT void
116 wl_client_add_destroy_listener(struct wl_client *client,
117 			       struct wl_listener *listener)
118diff --git a/tests/protocol-logger-test.c b/tests/protocol-logger-test.c
119index d0bca41..b66e761 100644
120--- a/tests/protocol-logger-test.c
121+++ b/tests/protocol-logger-test.c
122@@ -225,10 +225,10 @@ client_log_to_stderr_demo(void *user_data,
123 			break;
124 		case 'o':
125 			if (args[i].o) {
126-				// Note: server logger should instead cast to
127-				// wl_resource, and use wl_resource_get_class
128-				// and wl_resource_get_id.
129-				arg_proxy = (struct wl_proxy *)(args[i].o);
130+				// Note: server logger should instead use
131+				// wl_resource_from_object, and then
132+				// wl_resource_get_class and wl_resource_get_id.
133+				arg_proxy = wl_proxy_from_object(args[i].o);
134 				arg_class = wl_proxy_get_class(arg_proxy);
135
136 				fprintf(stderr, "%s@%u",
137