0c1c75a1de0cc7aab0dc902ffb7874f66fd94847
[profile/ivi/wayland.git] / wayland.c
1 #include <stdlib.h>
2 #include <stdint.h>
3 #include <stddef.h>
4 #include <stdio.h>
5 #include <errno.h>
6 #include <string.h>
7 #include <unistd.h>
8 #include <sys/socket.h>
9 #include <sys/un.h>
10 #include <ffi.h>
11
12 #include "wayland.h"
13 #include "connection.h"
14
15 #define container_of(ptr, type, member) ({                      \
16         const typeof( ((type *)0)->member ) *__mptr = (ptr);    \
17         (type *)( (char *)__mptr - offsetof(type,member) );})
18
19
20 struct wl_list {
21         struct wl_list *prev;
22         struct wl_list *next;
23 };
24
25 void wl_list_init(struct wl_list *list)
26 {
27         list->prev = list;
28         list->next = list;
29 }
30
31 void
32 wl_list_insert(struct wl_list *list, struct wl_list *elm)
33 {
34         elm->prev = list;
35         elm->next = list->next;
36         list->next = elm;
37         elm->next->prev = elm;
38 }
39
40 void
41 wl_list_remove(struct wl_list *elm)
42 {
43         elm->prev->next = elm->next;
44         elm->next->prev = elm->prev;
45 }
46
47 struct wl_client {
48         struct wl_connection *connection;
49         struct wl_event_source *source;
50         struct wl_display *display;
51         struct wl_list object_list;
52         struct wl_list link;
53 };
54
55 struct wl_display {
56         struct wl_object base;
57         struct wl_event_loop *loop;
58         struct wl_hash objects;
59
60         struct wl_object *pointer;
61
62         struct wl_compositor *compositor;
63         struct wl_compositor_interface *compositor_interface;
64
65         struct wl_list surface_list;
66         struct wl_list client_list;
67         uint32_t client_id_range;
68
69         int32_t pointer_x;
70         int32_t pointer_y;
71 };
72
73 struct wl_surface {
74         struct wl_object base;
75
76         /* provided by client */
77         int width, height;
78         int buffer;
79         int stride;
80         
81         struct wl_map map;
82         struct wl_list link;
83
84         /* how to convert buffer contents to pixels in screen format;
85          * yuv->rgb, indexed->rgb, svg->rgb, but mostly just rgb->rgb. */
86
87         /* how to transform/render rectangular contents to polygons. */
88
89         void *compositor_data;
90 };
91
92 struct wl_object_ref {
93         struct wl_object *object;
94         struct wl_list link;
95 };
96                                    
97 static void
98 wl_surface_destroy(struct wl_client *client,
99                    struct wl_surface *surface)
100 {
101         struct wl_compositor_interface *interface;
102
103         interface = client->display->compositor->interface;
104         interface->notify_surface_destroy(client->display->compositor,
105                                           surface);
106         wl_list_remove(&surface->link);
107 }
108
109 static void
110 wl_surface_attach(struct wl_client *client,
111                   struct wl_surface *surface, uint32_t name, 
112                   uint32_t width, uint32_t height, uint32_t stride)
113 {
114         struct wl_compositor_interface *interface;
115
116         interface = client->display->compositor->interface;
117         interface->notify_surface_attach(client->display->compositor,
118                                          surface, name, width, height, stride);
119 }
120
121 static const struct wl_argument attach_arguments[] = {
122         { WL_ARGUMENT_UINT32 },
123         { WL_ARGUMENT_UINT32 },
124         { WL_ARGUMENT_UINT32 },
125         { WL_ARGUMENT_UINT32 },
126 };
127
128 void
129 wl_surface_map(struct wl_client *client, struct wl_surface *surface,
130                int32_t x, int32_t y, int32_t width, int32_t height)
131 {
132         struct wl_compositor_interface *interface;
133
134         /* FIXME: This needs to take a tri-mesh argument... - count
135          * and a list of tris. 0 tris means unmap. */
136
137         surface->map.x = x;
138         surface->map.y = y;
139         surface->map.width = width;
140         surface->map.height = height;
141
142         interface = client->display->compositor->interface;
143         interface->notify_surface_map(client->display->compositor,
144                                       surface, &surface->map);
145 }
146
147 static const struct wl_argument map_arguments[] = {
148         { WL_ARGUMENT_UINT32 },
149         { WL_ARGUMENT_UINT32 },
150         { WL_ARGUMENT_UINT32 },
151         { WL_ARGUMENT_UINT32 },
152 };
153
154 static const struct wl_method surface_methods[] = {
155         { "destroy", wl_surface_destroy,
156           0, NULL },
157         { "attach", wl_surface_attach,
158           ARRAY_LENGTH(attach_arguments), attach_arguments },
159         { "map", wl_surface_map,
160           ARRAY_LENGTH(map_arguments), map_arguments }
161 };
162
163 static const struct wl_interface surface_interface = {
164         "surface", 1,
165         ARRAY_LENGTH(surface_methods),
166         surface_methods,
167 };
168
169 struct wl_surface *
170 wl_surface_create(struct wl_display *display, uint32_t id)
171 {
172         struct wl_surface *surface;
173         struct wl_compositor_interface *interface;
174
175         surface = malloc(sizeof *surface);
176         if (surface == NULL)
177                 return NULL;
178
179         surface->base.id = id;
180         surface->base.interface = &surface_interface;
181
182         wl_list_insert(display->surface_list.prev, &surface->link);
183
184         interface = display->compositor->interface;
185         interface->notify_surface_create(display->compositor, surface);
186
187         return surface;
188 }
189
190 void
191 wl_surface_set_data(struct wl_surface *surface, void *data)
192 {
193         surface->compositor_data = data;
194 }
195
196 void *
197 wl_surface_get_data(struct wl_surface *surface)
198 {
199         return surface->compositor_data;
200 }
201
202 void
203 wl_client_destroy(struct wl_client *client);
204
205 static void
206 wl_client_demarshal(struct wl_client *client, struct wl_object *target,
207                     const struct wl_method *method, size_t size)
208 {
209         ffi_type *types[10];
210         ffi_cif cif;
211         uint32_t *p, result;
212         int i;
213         union {
214                 uint32_t uint32;
215                 const char *string;
216                 void *object;
217                 uint32_t new_id;
218         } values[10];
219         void *args[10];
220         struct wl_object *object;
221         uint32_t data[64];
222
223         if (method->argument_count > ARRAY_LENGTH(types)) {
224                 printf("too many args (%d)\n", method->argument_count);
225                 return;
226         }
227
228         if (sizeof data < size) {
229                 printf("request too big, should malloc tmp buffer here\n");
230                 return;
231         }
232
233         types[0] = &ffi_type_pointer;
234         values[0].object = client;
235         args[0] =  &values[0];
236
237         types[1] = &ffi_type_pointer;
238         values[1].object = target;
239         args[1] =  &values[1];
240
241         wl_connection_copy(client->connection, data, size);
242         p = &data[2];
243         for (i = 0; i < method->argument_count; i++) {
244                 switch (method->arguments[i].type) {
245                 case WL_ARGUMENT_UINT32:
246                         types[i + 2] = &ffi_type_uint32;
247                         values[i + 2].uint32 = *p;
248                         p++;
249                         break;
250                 case WL_ARGUMENT_STRING:
251                         types[i + 2] = &ffi_type_pointer;
252                         /* FIXME */
253                         values[i + 2].uint32 = *p++;
254                         break;
255                 case WL_ARGUMENT_OBJECT:
256                         types[i + 2] = &ffi_type_pointer;
257                         object = wl_hash_lookup(&client->display->objects, *p);
258                         if (object == NULL)
259                                 printf("unknown object (%d)\n", *p);
260                         if (object->interface != method->arguments[i].data)
261                                 printf("wrong object type\n");
262                         values[i + 2].object = object;
263                         p++;
264                         break;
265                 case WL_ARGUMENT_NEW_ID:
266                         types[i + 2] = &ffi_type_uint32;
267                         values[i + 2].new_id = *p;
268                         object = wl_hash_lookup(&client->display->objects, *p);
269                         if (object != NULL)
270                                 printf("object already exists (%d)\n", *p);
271                         p++;
272                         break;
273                 default:
274                         printf("unknown type\n");
275                         break;
276                 }
277                 args[i + 2] = &values[i + 2];
278         }
279
280         ffi_prep_cif(&cif, FFI_DEFAULT_ABI, method->argument_count + 2,
281                      &ffi_type_uint32, types);
282         ffi_call(&cif, FFI_FN(method->func), &result, args);
283 }
284
285 static void
286 wl_client_event(struct wl_client *client, struct wl_object *object, uint32_t event)
287 {
288         uint32_t p[2];
289
290         p[0] = object->id;
291         p[1] = event | (8 << 16);
292         wl_connection_write(client->connection, p, sizeof p);
293 }
294
295 #define WL_DISPLAY_INVALID_OBJECT 0
296 #define WL_DISPLAY_INVALID_METHOD 1
297 #define WL_DISPLAY_NO_MEMORY 2
298
299 static void
300 wl_client_connection_data(int fd, uint32_t mask, void *data)
301 {
302         struct wl_client *client = data;
303         struct wl_connection *connection = client->connection;
304         const struct wl_method *method;
305         struct wl_object *object;
306         uint32_t p[2], opcode, size;
307         uint32_t cmask = 0;
308         int len;
309
310         if (mask & WL_EVENT_READABLE)
311                 cmask |= WL_CONNECTION_READABLE;
312         if (mask & WL_EVENT_WRITEABLE)
313                 cmask |= WL_CONNECTION_WRITABLE;
314
315         len = wl_connection_data(connection, cmask);
316         if (len < 0) {
317                 wl_client_destroy(client);
318                 return;
319         }
320
321         while (len > sizeof p) {
322                 wl_connection_copy(connection, p, sizeof p);
323                 opcode = p[1] & 0xffff;
324                 size = p[1] >> 16;
325                 if (len < size)
326                         break;
327
328                 object = wl_hash_lookup(&client->display->objects,
329                                         p[0]);
330                 if (object == NULL) {
331                         wl_client_event(client, &client->display->base,
332                                         WL_DISPLAY_INVALID_OBJECT);
333                         wl_connection_consume(connection, size);
334                         len -= size;
335                         continue;
336                 }
337                                 
338                 if (opcode >= object->interface->method_count) {
339                         wl_client_event(client, &client->display->base,
340                                         WL_DISPLAY_INVALID_METHOD);
341                         wl_connection_consume(connection, size);
342                         len -= size;
343                         continue;
344                 }
345                                 
346                 method = &object->interface->methods[opcode];
347                 wl_client_demarshal(client, object, method, size);
348                 wl_connection_consume(connection, size);
349                 len -= size;
350         }
351 }
352
353 static int
354 wl_client_connection_update(struct wl_connection *connection,
355                             uint32_t mask, void *data)
356 {
357         struct wl_client *client = data;
358         uint32_t emask = 0;
359
360         if (mask & WL_CONNECTION_READABLE)
361                 emask |= WL_EVENT_READABLE;
362         if (mask & WL_CONNECTION_WRITABLE)
363                 emask |= WL_EVENT_WRITEABLE;
364
365         return wl_event_loop_update_source(client->display->loop,
366                                            client->source, mask);
367 }
368
369 static void
370 advertise_object(struct wl_client *client, struct wl_object *object)
371 {
372         const struct wl_interface *interface;
373         static const char pad[4];
374         uint32_t length, p[2];
375
376         interface = object->interface;
377         length = strlen(interface->name);
378         p[0] = object->id;
379         p[1] = length;
380         wl_connection_write(client->connection, p, sizeof p);
381         wl_connection_write(client->connection, interface->name, length);
382         wl_connection_write(client->connection, pad, -length & 3);
383 }
384
385 struct wl_client *
386 wl_client_create(struct wl_display *display, int fd)
387 {
388         struct wl_client *client;
389
390         client = malloc(sizeof *client);
391         if (client == NULL)
392                 return NULL;
393
394         memset(client, 0, sizeof *client);
395         client->display = display;
396         client->source = wl_event_loop_add_fd(display->loop, fd,
397                                               WL_EVENT_READABLE,
398                                               wl_client_connection_data, client);
399         client->connection = wl_connection_create(fd,
400                                                   wl_client_connection_update, 
401                                                   client);
402         wl_list_init(&client->object_list);
403
404         wl_connection_write(client->connection,
405                             &display->client_id_range,
406                             sizeof display->client_id_range);
407         display->client_id_range += 256;
408
409         advertise_object(client, &display->base);
410
411         wl_list_insert(display->client_list.prev, &client->link);
412
413         return client;
414 }
415
416 void
417 wl_client_destroy(struct wl_client *client)
418 {
419         struct wl_object_ref *ref;
420
421         printf("disconnect from client %p\n", client);
422
423         wl_list_remove(&client->link);
424
425         while (client->object_list.next != &client->object_list) {
426                 ref = container_of(client->object_list.next,
427                                    struct wl_object_ref, link);
428                 wl_list_remove(&ref->link);
429                 wl_surface_destroy(client, (struct wl_surface *) ref->object);
430                 free(ref);
431         }
432
433         wl_event_loop_remove_source(client->display->loop, client->source);
434         wl_connection_destroy(client->connection);
435         free(client);
436 }
437
438 static int
439 wl_display_create_surface(struct wl_client *client,
440                           struct wl_display *display, uint32_t id)
441 {
442         struct wl_surface *surface;
443         struct wl_object_ref *ref;
444
445         surface = wl_surface_create(display, id);
446
447         ref = malloc(sizeof *ref);
448         if (ref == NULL) {
449                 wl_client_event(client, &display->base,
450                                 WL_DISPLAY_NO_MEMORY);
451                 return -1;
452         }
453
454         ref->object = &surface->base;
455         wl_hash_insert(&display->objects, &surface->base);
456         wl_list_insert(client->object_list.prev, &ref->link);
457
458         return 0;
459 }
460
461 static const struct wl_argument create_surface_arguments[] = {
462         { WL_ARGUMENT_NEW_ID }
463 };
464
465 static const struct wl_method display_methods[] = {
466         { "create_surface", wl_display_create_surface,
467           ARRAY_LENGTH(create_surface_arguments), create_surface_arguments },
468 };
469
470 static const struct wl_event display_events[] = {
471         { "invalid_object" },
472         { "invalid_method" },
473 };
474
475 static const struct wl_interface display_interface = {
476         "display", 1,
477         ARRAY_LENGTH(display_methods), display_methods,
478         ARRAY_LENGTH(display_events), display_events,
479 };
480
481 static const char input_device_file[] = 
482         "/dev/input/by-id/usb-Apple__Inc._Apple_Internal_Keyboard_._Trackpad-event-mouse";
483
484 static void
485 wl_display_create_input_devices(struct wl_display *display)
486 {
487         display->pointer = wl_input_device_create(display, input_device_file, 1);
488
489         if (display->pointer != NULL)
490                 wl_hash_insert(&display->objects, display->pointer);
491
492         display->pointer_x = 100;
493         display->pointer_y = 100;
494 }
495
496 struct wl_display *
497 wl_display_create(void)
498 {
499         struct wl_display *display;
500
501         display = malloc(sizeof *display);
502         if (display == NULL)
503                 return NULL;
504
505         display->loop = wl_event_loop_create();
506         if (display->loop == NULL) {
507                 free(display);
508                 return NULL;
509         }
510
511         display->base.id = 0;
512         display->base.interface = &display_interface;
513         wl_hash_insert(&display->objects, &display->base);
514         wl_list_init(&display->surface_list);
515         wl_list_init(&display->client_list);
516
517         wl_display_create_input_devices(display);
518
519         display->client_id_range = 256; /* Gah, arbitrary... */
520
521         return display;         
522 }
523
524 void
525 wl_display_send_event(struct wl_display *display, uint32_t *data, size_t size)
526 {
527         struct wl_client *client;
528
529         client = container_of(display->client_list.next,
530                               struct wl_client, link);
531         while (&client->link != &display->client_list) {
532                 wl_connection_write(client->connection, data, size);
533
534                 client = container_of(client->link.next,
535                                    struct wl_client, link);
536         }
537 }
538
539 #define WL_POINTER_MOTION 0
540 #define WL_POINTER_BUTTON 1
541
542 void
543 wl_display_post_relative_event(struct wl_display *display,
544                                struct wl_object *source, int dx, int dy)
545 {
546         uint32_t p[4];
547
548         display->pointer_x += dx;
549         display->pointer_y += dy;
550
551         p[0] = source->id;
552         p[1] = (sizeof p << 16) | WL_POINTER_MOTION;
553         p[2] = display->pointer_x;
554         p[3] = display->pointer_y;
555
556         wl_display_send_event(display, p, sizeof p);
557 }
558
559 void
560 wl_display_post_absolute_event(struct wl_display *display,
561                                struct wl_object *source, int x, int y)
562 {
563         uint32_t p[4];
564
565         display->pointer_x = x;
566         display->pointer_y = y;
567
568         p[0] = source->id;
569         p[1] = (sizeof p << 16) | WL_POINTER_MOTION;
570         p[2] = display->pointer_x;
571         p[3] = display->pointer_y;
572
573         wl_display_send_event(display, p, sizeof p);
574 }
575
576 void
577 wl_display_post_button_event(struct wl_display *display,
578                              struct wl_object *source, int button, int state)
579 {
580         uint32_t p[4];
581
582         p[0] = source->id;
583         p[1] = (sizeof p << 16) | WL_POINTER_BUTTON;
584         p[2] = button;
585         p[3] = state;
586
587         wl_display_send_event(display, p, sizeof p);
588 }
589
590 void
591 wl_display_set_compositor(struct wl_display *display,
592                           struct wl_compositor *compositor)
593 {
594         display->compositor = compositor;
595 }
596
597 struct wl_event_loop *
598 wl_display_get_event_loop(struct wl_display *display)
599 {
600         return display->loop;
601 }
602
603 void
604 wl_display_run(struct wl_display *display)
605 {
606         while (1)
607                 wl_event_loop_wait(display->loop);
608 }
609
610 /* The plan here is to generate a random anonymous socket name and
611  * advertise that through a service on the session dbus.
612  */
613 static const char socket_name[] = "\0wayland";
614
615 static void
616 socket_data(int fd, uint32_t mask, void *data)
617 {
618         struct wl_display *display = data;
619         struct sockaddr_un name;
620         socklen_t length;
621         int client_fd;
622
623         length = sizeof name;
624         client_fd = accept (fd, (struct sockaddr *) &name, &length);
625         if (client_fd < 0)
626                 fprintf(stderr, "failed to accept\n");
627
628         wl_client_create(display, client_fd);
629 }
630
631 int
632 wl_display_add_socket(struct wl_display *display)
633 {
634         struct sockaddr_un name;
635         int sock;
636         socklen_t size;
637
638         sock = socket(PF_LOCAL, SOCK_STREAM, 0);
639         if (sock < 0)
640                 return -1;
641
642         name.sun_family = AF_LOCAL;
643         memcpy(name.sun_path, socket_name, sizeof socket_name);
644
645         size = offsetof (struct sockaddr_un, sun_path) + sizeof socket_name;
646         if (bind(sock, (struct sockaddr *) &name, size) < 0)
647                 return -1;
648
649         if (listen(sock, 1) < 0)
650                 return -1;
651
652         wl_event_loop_add_fd(display->loop, sock,
653                              WL_EVENT_READABLE,
654                              socket_data, display);
655
656         return 0;
657 }
658
659
660 struct wl_surface_iterator {
661         struct wl_list *head;
662         struct wl_surface *surface;
663         uint32_t mask;
664 };
665
666 struct wl_surface_iterator *
667 wl_surface_iterator_create(struct wl_display *display, uint32_t mask)
668 {
669         struct wl_surface_iterator *iterator;
670
671         iterator = malloc(sizeof *iterator);
672         if (iterator == NULL)
673                 return NULL;
674
675         iterator->head = &display->surface_list;
676         iterator->surface = container_of(display->surface_list.next,
677                                          struct wl_surface, link);
678         iterator->mask = mask;
679
680         return iterator;
681 }
682
683 int
684 wl_surface_iterator_next(struct wl_surface_iterator *iterator,
685                          struct wl_surface **surface)
686 {
687         if (&iterator->surface->link == iterator->head)
688                 return 0;
689
690         *surface = iterator->surface;
691         iterator->surface = container_of(iterator->surface->link.next,
692                                          struct wl_surface, link);
693
694         return 1;
695 }
696
697 void
698 wl_surface_iterator_destroy(struct wl_surface_iterator *iterator)
699 {
700         free(iterator);
701 }
702
703 int main(int argc, char *argv[])
704 {
705         struct wl_display *display;
706         struct wl_compositor *compositor;
707
708         display = wl_display_create();
709
710         if (wl_display_add_socket(display)) {
711                 fprintf(stderr, "failed to add socket: %m\n");
712                 exit(EXIT_FAILURE);
713         }
714
715         compositor = wl_compositor_create(display);
716         wl_display_set_compositor(display, compositor);
717
718         printf("wayland online, display is %p\n", display);
719
720         wl_display_run(display);
721
722         return 0;
723 }