Send client id range as an event.
authorKristian Høgsberg <krh@redhat.com>
Mon, 22 Dec 2008 03:45:33 +0000 (22:45 -0500)
committerKristian Høgsberg <krh@redhat.com>
Mon, 22 Dec 2008 03:45:33 +0000 (22:45 -0500)
This also makes the server send the event again when the client is
about to exhaust its current client range.

wayland-client.c
wayland-protocol.c
wayland-protocol.h
wayland.c

index a898fd2..8a597f5 100644 (file)
@@ -57,7 +57,7 @@ struct wl_display {
        struct wl_proxy proxy;
        struct wl_connection *connection;
        int fd;
-       uint32_t id;
+       uint32_t id, id_count, next_range;
        uint32_t mask;
        struct wl_list global_list;
        struct wl_list visual_list;
@@ -162,10 +162,6 @@ wl_display_create(const char *name, size_t name_size)
                return NULL;
        }
 
-       /* FIXME: We'll need a protocol for getting a new range, I
-        * guess... */
-       read(display->fd, &display->id, sizeof display->id);
-
        wl_list_init(&display->global_list);
        wl_list_init(&display->visual_list);
 
@@ -222,29 +218,50 @@ wl_display_get_fd(struct wl_display *display,
 }
 
 static void
-handle_global(struct wl_display *display, uint32_t *p, uint32_t size)
+handle_display_event(struct wl_display *display,
+                    uint32_t opcode, uint32_t *p, uint32_t size)
 {
        struct wl_global *global;
        uint32_t length;
 
-       global = malloc(sizeof *global);
-       if (global == NULL)
-               return;
-
-       global->id = p[0];
-       length = p[1];
-       global->interface = malloc(length + 1);
-       if (global->interface == NULL) {
-               free(global);
-               return;
+       switch (opcode) {
+       case WL_DISPLAY_INVALID_OBJECT:
+               fprintf(stderr, "sent request to invalid object\n");
+               break;
+
+       case WL_DISPLAY_INVALID_METHOD:
+               fprintf(stderr, "sent invalid request opcode\n");
+               break;
+
+       case WL_DISPLAY_NO_MEMORY:
+               fprintf(stderr, "server out of memory\n");
+               break;
+
+       case WL_DISPLAY_GLOBAL:
+               global = malloc(sizeof *global);
+               if (global == NULL)
+                       return;
+
+               global->id = p[0];
+               length = p[1];
+               global->interface = malloc(length + 1);
+               if (global->interface == NULL) {
+                       free(global);
+                       return;
+               }
+               memcpy(global->interface, &p[2], length);
+               global->interface[length] = '\0';
+               global->version = p[2 + DIV_ROUNDUP(length, sizeof *p)];
+               wl_list_insert(display->global_list.prev, &global->link);
+
+               if (strcmp(global->interface, "visual") == 0)
+                       add_visual(display, global);
+               break;
+
+       case WL_DISPLAY_RANGE:
+               display->next_range = p[0];
+               break;
        }
-       memcpy(global->interface, &p[2], length);
-       global->interface[length] = '\0';
-       global->version = p[2 + DIV_ROUNDUP(length, sizeof *p)];
-       wl_list_insert(display->global_list.prev, &global->link);
-
-       if (strcmp(global->interface, "visual") == 0)
-               add_visual(display, global);
 }
 
 static void
@@ -254,8 +271,8 @@ handle_event(struct wl_display *display,
        uint32_t p[32];
 
        wl_connection_copy(display->connection, p, size);
-       if (object == 1 && opcode == WL_DISPLAY_GLOBAL) {
-               handle_global(display, p + 2, size);
+       if (object == 1) {
+               handle_display_event(display, opcode, p + 2, size);
        } else if (display->event_handler != NULL)
                display->event_handler(display, object, opcode, size, p + 2,
                                       display->event_handler_data);
@@ -303,6 +320,13 @@ wl_display_set_event_handler(struct wl_display *display,
 WL_EXPORT uint32_t
 wl_display_allocate_id(struct wl_display *display)
 {
+       if (display->id_count == 0) {
+               display->id_count = 256;
+               display->id = display->next_range;
+       }
+
+       display->id_count--;
+
        return display->id++;
 }
 
index 5b20154..4c61810 100644 (file)
@@ -30,6 +30,7 @@ static const struct wl_message display_events[] = {
        { "invalid_method", "uu" },
        { "no_memory", "" },
        { "global", "osu" },
+       { "range", "u" },
 };
 
 WL_EXPORT const struct wl_interface wl_display_interface = {
index f5deea3..c71cfdc 100644 (file)
@@ -49,6 +49,7 @@ struct wl_interface {
 #define WL_DISPLAY_INVALID_METHOD      1
 #define WL_DISPLAY_NO_MEMORY           2
 #define WL_DISPLAY_GLOBAL              3
+#define WL_DISPLAY_RANGE               4
 
 extern const struct wl_interface wl_display_interface;
 
index 48e1513..6ad1887 100644 (file)
--- a/wayland.c
+++ b/wayland.c
@@ -44,6 +44,7 @@ struct wl_client {
        struct wl_display *display;
        struct wl_list object_list;
        struct wl_list link;
+       uint32_t id_count;
 };
 
 struct wl_display {
@@ -270,6 +271,15 @@ wl_client_connection_update(struct wl_connection *connection,
        return wl_event_source_fd_update(client->source, mask);
 }
 
+static void
+wl_display_post_range(struct wl_display *display, struct wl_client *client)
+{
+       wl_client_marshal(client, &client->display->base,
+                         WL_DISPLAY_RANGE, display->client_id_range);
+       display->client_id_range += 256;
+       client->id_count += 256;
+}
+
 static struct wl_client *
 wl_client_create(struct wl_display *display, int fd)
 {
@@ -285,16 +295,13 @@ wl_client_create(struct wl_display *display, int fd)
        client->source = wl_event_loop_add_fd(display->loop, fd,
                                              WL_EVENT_READABLE,
                                              wl_client_connection_data, client);
-       client->connection = wl_connection_create(fd,
-                                                 wl_client_connection_update, 
-                                                 client);
+       client->connection =
+               wl_connection_create(fd, wl_client_connection_update, client);
+
        wl_list_init(&client->object_list);
        wl_list_init(&client->link);
 
-       wl_connection_write(client->connection,
-                           &display->client_id_range,
-                           sizeof display->client_id_range);
-       display->client_id_range += 256;
+       wl_display_post_range(display, client);
 
        ref = container_of(display->global_list.next,
                           struct wl_object_ref, link);
@@ -353,6 +360,9 @@ wl_client_add_surface(struct wl_client *client,
        struct wl_display *display = client->display;
        struct wl_object_ref *ref;
 
+       if (client->id_count-- < 64)
+               wl_display_post_range(display, client);
+
        surface->base.id = id;
        surface->base.interface = &wl_surface_interface;
        surface->base.implementation = (void (**)(void)) implementation;