summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--protocol/wayland.xml4
-rw-r--r--src/connection.c7
-rw-r--r--src/wayland-client.c22
-rw-r--r--src/wayland-server.c2
-rw-r--r--src/wayland-util.h2
5 files changed, 34 insertions, 3 deletions
diff --git a/protocol/wayland.xml b/protocol/wayland.xml
index 48ba68a..7e6392a 100644
--- a/protocol/wayland.xml
+++ b/protocol/wayland.xml
@@ -76,6 +76,10 @@
<arg name="name" type="uint" />
</event>
+ <!-- Server has deleted the id and client can now reuse it. -->
+ <event name="delete_id">
+ <arg name="id" type="uint" />
+ </event>
</interface>
<interface name="wl_callback" version="1">
diff --git a/src/connection.c b/src/connection.c
index a10508d..4230f7d 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -587,9 +587,14 @@ wl_connection_demarshal(struct wl_connection *connection,
closure->args[i] = object;
*object = wl_map_lookup(objects, *p);
- if (*object == NULL && *p != 0) {
+ if (*object == WL_ZOMBIE_OBJECT) {
+ /* references object we've already
+ * destroyed client side */
+ *object = NULL;
+ } else if (*object == NULL && *p != 0) {
printf("unknown object (%d), message %s(%s)\n",
*p, message->name, message->signature);
+ *object = NULL;
errno = EINVAL;
goto err;
}
diff --git a/src/wayland-client.c b/src/wayland-client.c
index efb7fe6..8f3e106 100644
--- a/src/wayland-client.c
+++ b/src/wayland-client.c
@@ -141,7 +141,8 @@ wl_proxy_create(struct wl_proxy *factory, const struct wl_interface *interface)
WL_EXPORT void
wl_proxy_destroy(struct wl_proxy *proxy)
{
- wl_map_remove(&proxy->display->objects, proxy->object.id);
+ wl_map_insert_at(&proxy->display->objects,
+ proxy->object.id, WL_ZOMBIE_OBJECT);
free(proxy);
}
@@ -239,10 +240,23 @@ display_handle_global_remove(void *data,
}
}
+static void
+display_handle_delete_id(void *data, struct wl_display *display, uint32_t id)
+{
+ struct wl_proxy *proxy;
+
+ proxy = wl_map_lookup(&display->objects, id);
+ if (proxy != WL_ZOMBIE_OBJECT)
+ fprintf(stderr, "server sent delete_id for live object\n");
+ else
+ wl_map_remove(&display->objects, id);
+}
+
static const struct wl_display_listener display_listener = {
display_handle_error,
display_handle_global,
display_handle_global_remove,
+ display_handle_delete_id
};
static int
@@ -412,7 +426,11 @@ handle_event(struct wl_display *display,
wl_connection_copy(display->connection, p, size);
proxy = wl_map_lookup(&display->objects, id);
- if (proxy == NULL || proxy->object.implementation == NULL) {
+ if (proxy == WL_ZOMBIE_OBJECT) {
+ fprintf(stderr, "Message to zombie object\n");
+ wl_connection_consume(display->connection, size);
+ return;
+ } else if (proxy == NULL || proxy->object.implementation == NULL) {
wl_connection_consume(display->connection, size);
return;
}
diff --git a/src/wayland-server.c b/src/wayland-server.c
index f93aa64..0004c15 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -314,6 +314,8 @@ wl_resource_destroy(struct wl_resource *resource, uint32_t time)
{
struct wl_client *client = resource->client;
+ wl_resource_post_event(resource->client->display_resource,
+ WL_DISPLAY_DELETE_ID, resource->object.id);
wl_map_insert_at(&client->objects, resource->object.id, NULL);
destroy_resource(resource, &time);
}
diff --git a/src/wayland-util.h b/src/wayland-util.h
index 608ea03..083bff8 100644
--- a/src/wayland-util.h
+++ b/src/wayland-util.h
@@ -44,6 +44,8 @@ extern "C" {
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
(type *)( (char *)__mptr - offsetof(type,member) );})
+#define WL_ZOMBIE_OBJECT ((void *) 2)
+
struct wl_message {
const char *name;
const char *signature;