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