Fill out a closure when sending events as well
authorKristian Høgsberg <krh@bitplanet.net>
Wed, 8 Sep 2010 00:57:40 +0000 (20:57 -0400)
committerKristian Høgsberg <krh@bitplanet.net>
Wed, 8 Sep 2010 00:57:40 +0000 (20:57 -0400)
connection.c

index 851a7d1..530e23f 100644 (file)
@@ -331,6 +331,32 @@ wl_connection_write(struct wl_connection *connection,
                                   connection->data);
 }
 
+static int
+wl_message_size_extra(const struct wl_message *message)
+{
+       int i, extra;
+
+       for (i = 0, extra = 0; message->signature[i]; i++) {
+
+               switch (message->signature[i]) {
+               case 's':
+               case 'o':
+                       extra += sizeof (void *);
+                       break;
+               case 'a':
+                       extra += sizeof (void *) + sizeof (struct wl_array);
+                       break;
+               case 'h':
+                       extra += sizeof (uint32_t);
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       return extra;
+}
+
 void
 wl_connection_vmarshal(struct wl_connection *connection,
                       struct wl_object *sender,
@@ -338,36 +364,74 @@ wl_connection_vmarshal(struct wl_connection *connection,
                       const struct wl_message *message)
 {
        struct wl_closure *closure = &connection->closure;
-       struct wl_object *object;
-       uint32_t length, *p, size;
+       struct wl_object **objectp, *object;
+       uint32_t length, *p, *start, size;
        int dup_fd;
-       struct wl_array *array;
-       const char *s;
-       int i, count, fd;
+       struct wl_array **arrayp, *array;
+       const char **sp, *s;
+       char *extra;
+       int i, count, fd, extra_size;
 
-       count = strlen(message->signature);
-       p = &closure->buffer[2];
-       for (i = 0; i < count; i++) {
-               switch (message->signature[i]) {
+       extra_size = wl_message_size_extra(message);
+       closure->message = message;
+       count = strlen(message->signature) + 2;
+       extra = (char *) closure->buffer;
+       start = &closure->buffer[DIV_ROUNDUP(extra_size, sizeof *p)];
+       p = &start[2];
+       for (i = 2; i < count; i++) {
+               switch (message->signature[i - 2]) {
                case 'u':
+                       closure->types[i] = &ffi_type_uint32;
+                       closure->args[i] = p;
                        *p++ = va_arg(ap, uint32_t);
                        break;
                case 'i':
+                       closure->types[i] = &ffi_type_sint32;
+                       closure->args[i] = p;
                        *p++ = va_arg(ap, int32_t);
                        break;
                case 's':
+                       closure->types[i] = &ffi_type_pointer;
+                       closure->args[i] = extra;
+                       sp = (const char **) extra;
+                       extra += sizeof *sp;
+
                        s = va_arg(ap, const char *);
                        length = s ? strlen(s) + 1: 0;
                        *p++ = length;
+
+                       *sp = (const char *) p;
+
                        memcpy(p, s, length);
-                       p += DIV_ROUNDUP(length, sizeof(*p));
+                       p += DIV_ROUNDUP(length, sizeof *p);
                        break;
                case 'o':
-               case 'n':
+                       closure->types[i] = &ffi_type_pointer;
+                       closure->args[i] = extra;
+                       objectp = (struct wl_object **) extra;
+                       extra += sizeof *objectp;
+
                        object = va_arg(ap, struct wl_object *);
+                       *objectp = object;
                        *p++ = object ? object->id : 0;
                        break;
+
+               case 'n':
+                       closure->types[i] = &ffi_type_uint32;
+                       closure->args[i] = p;
+                       object = va_arg(ap, struct wl_object *);
+                       *p++ = object->id;
+                       break;
+
                case 'a':
+                       closure->types[i] = &ffi_type_pointer;
+                       closure->args[i] = extra;
+                       arrayp = (struct wl_array **) extra;
+                       extra += sizeof *arrayp;
+
+                       *arrayp = (struct wl_array *) extra;
+                       extra += sizeof **arrayp;
+
                        array = va_arg(ap, struct wl_array *);
                        if (array == NULL || array->size == 0) {
                                *p++ = 0;
@@ -375,8 +439,14 @@ wl_connection_vmarshal(struct wl_connection *connection,
                        }
                        *p++ = array->size;
                        memcpy(p, array->data, array->size);
-                       p = (void *) p + array->size;
+
+                       (*arrayp)->size = array->size;
+                       (*arrayp)->alloc = array->alloc;
+                       (*arrayp)->data = p;
+
+                       p += DIV_ROUNDUP(array->size, sizeof *p);
                        break;
+
                case 'h':
                        fd = va_arg(ap, int);
                        dup_fd = dup(fd);
@@ -393,35 +463,10 @@ wl_connection_vmarshal(struct wl_connection *connection,
                }
        }
 
-       size = (p - closure->buffer) * sizeof *p;
-       closure->buffer[0] = sender->id;
-       closure->buffer[1] = opcode | (size << 16);
-       wl_connection_write(connection, closure->buffer, size);
-}
-
-static int
-wl_message_size_extra(const struct wl_message *message)
-{
-       int i, extra;
-
-       for (i = 0, extra = 0; message->signature[i]; i++) {
-
-               switch (message->signature[i - 2]) {
-               case 's':
-               case 'o':
-                       extra += sizeof (void *);
-                       break;
-               case 'a':
-                       extra += sizeof (void *) + sizeof (struct wl_array);
-                       break;
-               case 'h':
-                       extra += sizeof (uint32_t);
-               default:
-                       break;
-               }
-       }
-
-       return extra;
+       size = (p - start) * sizeof *p;
+       start[0] = sender->id;
+       start[1] = opcode | (size << 16);
+       wl_connection_write(connection, start, size);
 }
 
 struct wl_closure *