summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@bitplanet.net>2013-07-08 18:45:41 -0400
committerKristian Høgsberg <krh@bitplanet.net>2013-07-09 01:15:37 -0400
commit4cffa0fd61fde7760f2506b154b2af7d24b8c25f (patch)
tree657e54e2742ef0d5d3da5ee43823dce66d0d0619
parent40fc79d5b095e330ab6f851e35ba54a65781679f (diff)
wayland-server: Add wl_global_create/destroy()
This patch introduces wl_global_create() and wl_global_destroy() as replacements for wl_display_add_global() and wl_display_remove_global(). The add/remove_global API did not allow a compositor to indicate the implemented version of a global, it just took the version from the interface meta data. The problem is that the meta data (which lives in libwayland-server.so) can get out of sync with a compositor implementation. The compositor will then advertise a higher version of a global than what it actually implements. The new API lets a compositor pass in a version when it registers a global, which solves the problem. The add/remove API is deprecated with this patch and will be removed.
-rw-r--r--src/wayland-server.c53
-rw-r--r--src/wayland-server.h24
2 files changed, 60 insertions, 17 deletions
diff --git a/src/wayland-server.c b/src/wayland-server.c
index 32310b1..0a6e112 100644
--- a/src/wayland-server.c
+++ b/src/wayland-server.c
@@ -95,8 +95,10 @@ struct wl_display {
};
struct wl_global {
+ struct wl_display *display;
const struct wl_interface *interface;
uint32_t name;
+ uint32_t version;
void *data;
wl_global_bind_func_t bind;
struct wl_list link;
@@ -589,7 +591,8 @@ registry_bind(struct wl_client *client,
if (global->name == name)
break;
- if (&global->link == &display->global_list)
+ if (&global->link == &display->global_list ||
+ global->version < version)
wl_resource_post_error(resource,
WL_DISPLAY_ERROR_INVALID_OBJECT,
"invalid global %d", name);
@@ -652,7 +655,7 @@ display_get_registry(struct wl_client *client,
WL_REGISTRY_GLOBAL,
global->name,
global->interface->name,
- global->interface->version);
+ global->version);
}
static const struct wl_display_interface display_interface = {
@@ -714,8 +717,8 @@ wl_display_create(void)
display->id = 1;
display->serial = 0;
- if (!wl_display_add_global(display, &wl_display_interface,
- display, bind_display)) {
+ if (!wl_global_create(display, &wl_display_interface, 1,
+ display, bind_display)) {
wl_event_loop_destroy(display->loop);
free(display);
return NULL;
@@ -749,19 +752,27 @@ wl_display_destroy(struct wl_display *display)
}
WL_EXPORT struct wl_global *
-wl_display_add_global(struct wl_display *display,
- const struct wl_interface *interface,
- void *data, wl_global_bind_func_t bind)
+wl_global_create(struct wl_display *display,
+ const struct wl_interface *interface, int version,
+ void *data, wl_global_bind_func_t bind)
{
struct wl_global *global;
struct wl_resource *resource;
+ if (interface->version < version) {
+ wl_log("wl_global_create: implemented version higher "
+ "than interface version%m\n");
+ return NULL;
+ }
+
global = malloc(sizeof *global);
if (global == NULL)
return NULL;
+ global->display = display;
global->name = display->id++;
global->interface = interface;
+ global->version = version;
global->data = data;
global->bind = bind;
wl_list_insert(display->global_list.prev, &global->link);
@@ -771,14 +782,15 @@ wl_display_add_global(struct wl_display *display,
WL_REGISTRY_GLOBAL,
global->name,
global->interface->name,
- global->interface->version);
+ global->version);
return global;
}
WL_EXPORT void
-wl_display_remove_global(struct wl_display *display, struct wl_global *global)
+wl_global_destroy(struct wl_global *global)
{
+ struct wl_display *display = global->display;
struct wl_resource *resource;
wl_list_for_each(resource, &display->registry_resource_list, link)
@@ -1139,3 +1151,26 @@ wl_client_new_object(struct wl_client *client,
return resource;
}
+
+struct wl_global *
+wl_display_add_global(struct wl_display *display,
+ const struct wl_interface *interface,
+ void *data, wl_global_bind_func_t bind) WL_DEPRECATED;
+
+WL_EXPORT struct wl_global *
+wl_display_add_global(struct wl_display *display,
+ const struct wl_interface *interface,
+ void *data, wl_global_bind_func_t bind)
+{
+ return wl_global_create(display, interface, interface->version, data, bind);
+}
+
+void
+wl_display_remove_global(struct wl_display *display,
+ struct wl_global *global) WL_DEPRECATED;
+
+WL_EXPORT void
+wl_display_remove_global(struct wl_display *display, struct wl_global *global)
+{
+ wl_global_destroy(global);
+}
diff --git a/src/wayland-server.h b/src/wayland-server.h
index 0a798f4..9e16d0e 100644
--- a/src/wayland-server.h
+++ b/src/wayland-server.h
@@ -99,14 +99,6 @@ void wl_display_flush_clients(struct wl_display *display);
typedef void (*wl_global_bind_func_t)(struct wl_client *client, void *data,
uint32_t version, uint32_t id);
-struct wl_global *wl_display_add_global(struct wl_display *display,
- const struct wl_interface *interface,
- void *data,
- wl_global_bind_func_t bind);
-
-void wl_display_remove_global(struct wl_display *display,
- struct wl_global *global);
-
uint32_t wl_display_get_serial(struct wl_display *display);
uint32_t wl_display_next_serial(struct wl_display *display);
@@ -115,6 +107,12 @@ void wl_display_add_destroy_listener(struct wl_display *display,
struct wl_listener *wl_display_get_destroy_listener(struct wl_display *display,
wl_notify_func_t notify);
+struct wl_global *wl_global_create(struct wl_display *display,
+ const struct wl_interface *interface,
+ int version,
+ void *data, wl_global_bind_func_t bind);
+void wl_global_destroy(struct wl_global *global);
+
struct wl_client *wl_client_create(struct wl_display *display, int fd);
void wl_client_destroy(struct wl_client *client);
void wl_client_flush(struct wl_client *client);
@@ -213,6 +211,16 @@ wl_client_new_object(struct wl_client *client,
const struct wl_interface *interface,
const void *implementation, void *data) WL_DEPRECATED;
+struct wl_global *
+wl_display_add_global(struct wl_display *display,
+ const struct wl_interface *interface,
+ void *data,
+ wl_global_bind_func_t bind) WL_DEPRECATED;
+
+void
+wl_display_remove_global(struct wl_display *display,
+ struct wl_global *global) WL_DEPRECATED;
+
#endif
/*