Introduce display.bind to request events from a global
[profile/ivi/wayland.git] / wayland / wayland-client.c
1 /*
2  * Copyright © 2008 Kristian Høgsberg
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that copyright
7  * notice and this permission notice appear in supporting documentation, and
8  * that the name of the copyright holders not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission.  The copyright holders make no representations
11  * about the suitability of this software for any purpose.  It is provided "as
12  * is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20  * OF THIS SOFTWARE.
21  */
22
23 #include <stdlib.h>
24 #include <stdint.h>
25 #include <stddef.h>
26 #include <stdio.h>
27 #include <errno.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <sys/socket.h>
31 #include <sys/un.h>
32 #include <ctype.h>
33 #include <assert.h>
34 #include <fcntl.h>
35 #include <sys/poll.h>
36
37 #include "connection.h"
38 #include "wayland-util.h"
39 #include "wayland-client.h"
40
41 struct wl_global_listener {
42         wl_display_global_func_t handler;
43         void *data;
44         struct wl_list link;
45 };
46
47 struct wl_proxy {
48         struct wl_object object;
49         struct wl_display *display;
50         void *user_data;
51 };
52
53 struct wl_sync_handler {
54         wl_display_sync_func_t func;
55         uint32_t key;
56         void *data;
57         struct wl_list link;
58 };
59
60 struct wl_frame_handler {
61         wl_display_frame_func_t func;
62         uint32_t key;
63         void *data;
64         struct wl_surface *surface;
65         struct wl_list link;
66 };
67
68 struct wl_global {
69         uint32_t id;
70         char *interface;
71         uint32_t version;
72         struct wl_list link;
73 };
74
75 struct wl_display {
76         struct wl_proxy proxy;
77         struct wl_connection *connection;
78         int fd;
79         uint32_t id, id_count, next_range;
80         uint32_t mask;
81         struct wl_hash_table *objects;
82         struct wl_list global_listener_list;
83         struct wl_list global_list;
84
85         struct wl_visual *argb_visual;
86         struct wl_visual *premultiplied_argb_visual;
87         struct wl_visual *rgb_visual;
88
89         wl_display_update_func_t update;
90         void *update_data;
91
92         wl_display_global_func_t global_handler;
93         void *global_handler_data;
94
95         struct wl_list sync_list, frame_list;
96         uint32_t key;
97 };
98
99 static int wl_debug = 0;
100
101 static int
102 connection_update(struct wl_connection *connection,
103                   uint32_t mask, void *data)
104 {
105         struct wl_display *display = data;
106
107         display->mask = mask;
108         if (display->update)
109                 return display->update(display->mask,
110                                        display->update_data);
111
112         return 0;
113 }
114
115 WL_EXPORT struct wl_global_listener *
116 wl_display_add_global_listener(struct wl_display *display,
117                                wl_display_global_func_t handler, void *data)
118 {
119         struct wl_global_listener *listener;
120
121         listener = malloc(sizeof *listener);
122         if (listener == NULL)
123                 return NULL;
124
125         listener->handler = handler;
126         listener->data = data;
127         wl_list_insert(display->global_listener_list.prev, &listener->link);
128
129         return listener;
130 }
131
132 WL_EXPORT void
133 wl_display_remove_global_listener(struct wl_display *display,
134                                   struct wl_global_listener *listener)
135 {
136         wl_list_remove(&listener->link);
137         free(listener);
138 }
139
140 WL_EXPORT struct wl_proxy *
141 wl_proxy_create_for_id(struct wl_display *display,
142                        const struct wl_interface *interface, uint32_t id)
143 {
144         struct wl_proxy *proxy;
145
146         proxy = malloc(sizeof *proxy);
147         if (proxy == NULL)
148                 return NULL;
149
150         proxy->object.interface = interface;
151         proxy->object.implementation = NULL;
152         proxy->object.id = id;
153         proxy->display = display;
154         wl_hash_table_insert(display->objects, proxy->object.id, proxy);
155
156         return proxy;
157 }
158
159 WL_EXPORT struct wl_proxy *
160 wl_proxy_create(struct wl_proxy *factory,
161                 const struct wl_interface *interface)
162 {
163         return wl_proxy_create_for_id(factory->display, interface,
164                                       wl_display_allocate_id(factory->display));
165 }
166
167 WL_EXPORT void
168 wl_proxy_destroy(struct wl_proxy *proxy)
169 {
170         wl_hash_table_remove(proxy->display->objects, proxy->object.id);
171         free(proxy);
172 }
173
174 WL_EXPORT int
175 wl_proxy_add_listener(struct wl_proxy *proxy,
176                       void (**implementation)(void), void *data)
177 {
178         if (proxy->object.implementation) {
179                 fprintf(stderr, "proxy already has listener\n");
180                 return -1;
181         }
182
183         proxy->object.implementation = implementation;
184         proxy->user_data = data;
185
186         return 0;
187 }
188
189 WL_EXPORT void
190 wl_proxy_marshal(struct wl_proxy *proxy, uint32_t opcode, ...)
191 {
192         struct wl_closure *closure;
193         va_list ap;
194
195         va_start(ap, opcode);
196         closure = wl_connection_vmarshal(proxy->display->connection,
197                                          &proxy->object, opcode, ap,
198                                          &proxy->object.interface->methods[opcode]);
199         va_end(ap);
200
201         wl_closure_send(closure, proxy->display->connection);
202
203         if (wl_debug) {
204                 fprintf(stderr, " -> ");
205                 wl_closure_print(closure, &proxy->object);
206         }
207
208         wl_closure_destroy(closure);
209 }
210
211 static void
212 add_visual(struct wl_display *display, uint32_t id)
213 {
214         struct wl_visual *visual;
215
216         visual = (struct wl_visual *)
217                 wl_proxy_create_for_id(display, &wl_visual_interface, id);
218         if (display->argb_visual == NULL)
219                 display->argb_visual = visual;
220         else if (display->premultiplied_argb_visual == NULL)
221                 display->premultiplied_argb_visual = visual;
222         else
223                 display->rgb_visual = visual;
224 }
225
226 WL_EXPORT struct wl_visual *
227 wl_display_get_argb_visual(struct wl_display *display)
228 {
229         return display->argb_visual;
230 }
231
232 WL_EXPORT struct wl_visual *
233 wl_display_get_premultiplied_argb_visual(struct wl_display *display)
234 {
235         return display->premultiplied_argb_visual;
236 }
237
238 WL_EXPORT struct wl_visual *
239 wl_display_get_rgb_visual(struct wl_display *display)
240 {
241         return display->rgb_visual;
242 }
243
244 /* Can't do this, there may be more than one instance of an
245  * interface... */
246 WL_EXPORT uint32_t
247 wl_display_get_global(struct wl_display *display,
248                       const char *interface, uint32_t version)
249 {
250         struct wl_global *global;
251
252         wl_list_for_each(global, &display->global_list, link)
253                 if (strcmp(interface, global->interface) == 0 &&
254                     version <= global->version)
255                         return global->id;
256
257         return 0;
258 }
259
260 static void
261 display_handle_invalid_object(void *data,
262                               struct wl_display *display, uint32_t id)
263 {
264         fprintf(stderr, "sent request to invalid object\n");
265         abort();
266 }
267                               
268 static void
269 display_handle_invalid_method(void *data, 
270                               struct wl_display *display,
271                               uint32_t id, uint32_t opcode)
272 {
273         fprintf(stderr, "sent invalid request opcode\n");
274         abort();
275 }
276
277 static void
278 display_handle_no_memory(void *data,
279                          struct wl_display *display)
280 {
281         fprintf(stderr, "server out of memory\n");
282         abort();
283 }
284
285 static void
286 display_handle_global(void *data,
287                       struct wl_display *display,
288                       uint32_t id, const char *interface, uint32_t version)
289 {
290         struct wl_global_listener *listener;
291         struct wl_global *global;
292
293         if (strcmp(interface, "display") == 0)
294                 wl_hash_table_insert(display->objects,
295                                      id, &display->proxy.object);
296         else if (strcmp(interface, "visual") == 0)
297                 add_visual(display, id);
298
299         global = malloc(sizeof *global);
300         global->id = id;
301         global->interface = strdup(interface);
302         global->version = version;
303         wl_list_insert(display->global_list.prev, &global->link);
304
305         wl_list_for_each(listener, &display->global_listener_list, link)
306                 (*listener->handler)(display,
307                                      id, interface, version, listener->data);
308 }
309
310 static void
311 display_handle_range(void *data,
312                      struct wl_display *display, uint32_t range)
313 {
314         display->next_range = range;
315 }
316
317 static void
318 display_handle_key(void *data,
319                    struct wl_display *display, uint32_t key, uint32_t time)
320 {
321         struct wl_sync_handler *sync_handler;
322         struct wl_frame_handler *frame_handler;
323
324         sync_handler = container_of(display->sync_list.next,
325                                     struct wl_sync_handler, link);
326         if (!wl_list_empty(&display->sync_list) && sync_handler->key == key) {
327                 wl_list_remove(&sync_handler->link);
328                 sync_handler->func(sync_handler->data);
329                 free(sync_handler);
330                 return;
331         }
332
333         frame_handler = container_of(display->frame_list. next,
334                                      struct wl_frame_handler, link);
335         if (!wl_list_empty(&display->frame_list) &&
336             frame_handler->key == key) {
337                 wl_list_remove(&frame_handler->link);
338                 frame_handler->func(frame_handler->surface,
339                                     frame_handler->data, time);
340                 free(frame_handler);
341                 return;
342         }
343
344         fprintf(stderr, "unsolicited sync event, client gone?\n");
345 }
346
347 static const struct wl_display_listener display_listener = {
348         display_handle_invalid_object,
349         display_handle_invalid_method,
350         display_handle_no_memory,
351         display_handle_global,
352         display_handle_range,
353         display_handle_key
354 };
355
356 static int
357 connect_to_socket(struct wl_display *display, const char *name)
358 {
359         struct sockaddr_un addr;
360         socklen_t size;
361         const char *runtime_dir;
362         size_t name_size;
363
364         display->fd = socket(PF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
365         if (display->fd < 0)
366                 return -1;
367
368         runtime_dir = getenv("XDG_RUNTIME_DIR");
369         if (runtime_dir == NULL) {
370                 runtime_dir = ".";
371                 fprintf(stderr,
372                         "XDG_RUNTIME_DIR not set, falling back to %s\n",
373                         runtime_dir);
374         }
375
376         if (name == NULL)
377                 name = getenv("WAYLAND_DISPLAY");
378         if (name == NULL)
379                 name = "wayland-0";
380
381         memset(&addr, 0, sizeof addr);
382         addr.sun_family = AF_LOCAL;
383         name_size =
384                 snprintf(addr.sun_path, sizeof addr.sun_path,
385                          "%s/%s", runtime_dir, name) + 1;
386
387         size = offsetof (struct sockaddr_un, sun_path) + name_size;
388
389         if (connect(display->fd, (struct sockaddr *) &addr, size) < 0) {
390                 close(display->fd);
391                 return -1;
392         }
393
394         return 0;
395 }
396
397 WL_EXPORT struct wl_display *
398 wl_display_connect(const char *name)
399 {
400         struct wl_display *display;
401         const char *debug;
402         char *connection, *end;
403         int flags;
404
405         debug = getenv("WAYLAND_DEBUG");
406         if (debug)
407                 wl_debug = 1;
408
409         display = malloc(sizeof *display);
410         if (display == NULL)
411                 return NULL;
412
413         memset(display, 0, sizeof *display);
414         connection = getenv("WAYLAND_SOCKET");
415         if (connection) {
416                 display->fd = strtol(connection, &end, 0);
417                 if (*end != '\0') {
418                         free(display);
419                         return NULL;
420                 }
421                 flags = fcntl(display->fd, F_GETFD);
422                 if (flags != -1)
423                         fcntl(display->fd, F_SETFD, flags | FD_CLOEXEC);
424         } else if (connect_to_socket(display, name) < 0) {
425                 free(display);
426                 return NULL;
427         }
428
429         display->objects = wl_hash_table_create();
430         if (display->objects == NULL) {
431                 close(display->fd);
432                 free(display);
433                 return NULL;
434         }
435         wl_list_init(&display->global_listener_list);
436         wl_list_init(&display->global_list);
437
438         display->proxy.object.interface = &wl_display_interface;
439         display->proxy.object.id = 1;
440         display->proxy.display = display;
441
442         wl_list_init(&display->sync_list);
443         wl_list_init(&display->frame_list);
444
445         display->proxy.object.implementation =
446                 (void(**)(void)) &display_listener;
447         display->proxy.user_data = display;
448
449         display->connection = wl_connection_create(display->fd,
450                                                    connection_update,
451                                                    display);
452         if (display->connection == NULL) {
453                 wl_hash_table_destroy(display->objects);
454                 close(display->fd);
455                 free(display);
456                 return NULL;
457         }
458
459         wl_display_bind(display, 1, "display", 1);
460
461         return display;
462 }
463
464 WL_EXPORT void
465 wl_display_destroy(struct wl_display *display)
466 {
467         wl_connection_destroy(display->connection);
468         wl_hash_table_destroy(display->objects);
469         close(display->fd);
470         free(display);
471 }
472
473 WL_EXPORT int
474 wl_display_get_fd(struct wl_display *display,
475                   wl_display_update_func_t update, void *data)
476 {
477         display->update = update;
478         display->update_data = data;
479
480         display->update(display->mask, display->update_data);
481
482         return display->fd;
483 }
484
485 WL_EXPORT int
486 wl_display_sync_callback(struct wl_display *display,
487                          wl_display_sync_func_t func, void *data)
488 {
489         struct wl_sync_handler *handler;
490
491         handler = malloc(sizeof *handler);
492         if (handler == NULL)
493                 return -1;
494
495         handler->func = func;
496         handler->key = display->key++;
497         handler->data = data;
498
499         wl_list_insert(display->sync_list.prev, &handler->link);
500         wl_display_sync(display, handler->key);
501
502         return 0;
503 }
504
505 WL_EXPORT int
506 wl_display_frame_callback(struct wl_display *display,
507                           struct wl_surface *surface,
508                           wl_display_frame_func_t func, void *data)
509 {
510         struct wl_frame_handler *handler;
511
512         handler = malloc(sizeof *handler);
513         if (handler == NULL)
514                 return -1;
515
516         handler->func = func;
517         handler->key = display->key++;
518         handler->data = data;
519         handler->surface = surface;
520
521         wl_list_insert(display->frame_list.prev, &handler->link);
522         wl_display_frame(display, handler->surface, handler->key);
523
524         return 0;
525 }
526
527 static void
528 handle_event(struct wl_display *display,
529              uint32_t id, uint32_t opcode, uint32_t size)
530 {
531         uint32_t p[32];
532         struct wl_proxy *proxy;
533         struct wl_closure *closure;
534         const struct wl_message *message;
535
536         wl_connection_copy(display->connection, p, size);
537         if (id == 1)
538                 proxy = &display->proxy;
539         else
540                 proxy = wl_hash_table_lookup(display->objects, id);
541
542         if (proxy == NULL || proxy->object.implementation == NULL) {
543                 wl_connection_consume(display->connection, size);
544                 return;
545         }
546
547         message = &proxy->object.interface->events[opcode];
548         closure = wl_connection_demarshal(display->connection,
549                                           size, display->objects, message);
550
551         if (wl_debug)
552                 wl_closure_print(closure, &proxy->object);
553
554         wl_closure_invoke(closure, &proxy->object,
555                           proxy->object.implementation[opcode],
556                           proxy->user_data);
557
558         wl_closure_destroy(closure);
559 }
560
561 WL_EXPORT void
562 wl_display_iterate(struct wl_display *display, uint32_t mask)
563 {
564         uint32_t p[2], object, opcode, size;
565         int len;
566
567         mask &= display->mask;
568         if (mask == 0) {
569                 fprintf(stderr,
570                         "wl_display_iterate called with unsolicited flags");
571                 return;
572         }
573
574         len = wl_connection_data(display->connection, mask);
575         while (len > 0) {
576                 if (len < sizeof p)
577                         break;
578                 
579                 wl_connection_copy(display->connection, p, sizeof p);
580                 object = p[0];
581                 opcode = p[1] & 0xffff;
582                 size = p[1] >> 16;
583                 if (len < size)
584                         break;
585
586                 handle_event(display, object, opcode, size);
587                 len -= size;
588         }
589
590         if (len < 0) {
591                 fprintf(stderr, "read error: %m\n");
592                 exit(EXIT_FAILURE);
593         }
594 }
595
596 WL_EXPORT uint32_t
597 wl_display_allocate_id(struct wl_display *display)
598 {
599         if (display->id_count == 0) {
600                 display->id_count = 256;
601                 display->id = display->next_range;
602         }
603
604         display->id_count--;
605
606         return display->id++;
607 }
608
609 WL_EXPORT void
610 wl_proxy_set_user_data(struct wl_proxy *proxy, void *user_data)
611 {
612         proxy->user_data = user_data;
613 }
614
615 WL_EXPORT void *
616 wl_proxy_get_user_data(struct wl_proxy *proxy)
617 {
618         return proxy->user_data;
619 }