wayland-server: Add wl_global_create/destroy()
authorKristian Høgsberg <krh@bitplanet.net>
Mon, 8 Jul 2013 22:45:41 +0000 (18:45 -0400)
committerKristian Høgsberg <krh@bitplanet.net>
Tue, 9 Jul 2013 05:15:37 +0000 (01:15 -0400)
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.

src/wayland-server.c
src/wayland-server.h

index 32310b1..0a6e112 100644 (file)
@@ -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);
+}
index 0a798f4..9e16d0e 100644 (file)
@@ -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
 
 /*