965cffea626d5d2aabee84e9a35a6cdab728373a
[profile/ivi/murphy.git] / src / plugins / system-controller / wayland / wayland.c
1 /*
2  * Copyright (c) 2013, Intel Corporation
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *  * Redistributions of source code must retain the above copyright notice,
9  *    this list of conditions and the following disclaimer.
10  *  * Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *  * Neither the name of Intel Corporation nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include <stdint.h>
31 #include <stdbool.h>
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <errno.h>
36
37 #include <murphy/common.h>
38
39 #include "wayland.h"
40 #include "output.h"
41 #include "layer.h"
42 #include "window-manager.h"
43
44
45 static uint32_t oid_hash(const void *);
46 static uint32_t wid_hash(const void *);
47 static uint32_t lid_hash(const void *);
48 static int id_compare(const void *, const void *);
49
50 static const char *get_display_name(mrp_wayland_t *w);
51 static void display_io_watch(mrp_io_watch_t *, int, mrp_io_event_t, void *);
52 static void object_create(mrp_wayland_interface_t *, uint32_t, uint32_t);
53 static void global_available_callback(void *, struct wl_registry *, uint32_t,
54                                       const char *, uint32_t);
55 static void global_remove_callback(void *, struct wl_registry *, uint32_t);
56
57 static mrp_wayland_t **instances;
58 static size_t ninstance;
59
60
61 mrp_wayland_t *mrp_wayland_create(const char *display_name, mrp_mainloop_t *ml)
62 {
63     mrp_wayland_t *wl;
64     mrp_htbl_config_t icfg, ocfg, wcfg, lcfg, acfg;
65
66     MRP_ASSERT(ml, "invalid argument");
67
68     if (!(wl = mrp_allocz(sizeof(mrp_wayland_t))))
69         mrp_log_error("can't allocate memory for wayland");
70     else {
71         memset(&icfg, 0, sizeof(icfg));
72         icfg.nentry = MRP_WAYLAND_INTERFACE_MAX;
73         icfg.comp = mrp_string_comp;
74         icfg.hash = mrp_string_hash;
75         icfg.nbucket = MRP_WAYLAND_INTERFACE_BUCKETS;
76
77         memset(&ocfg, 0, sizeof(ocfg));
78         ocfg.nentry = MRP_WAYLAND_OUTPUT_MAX;
79         ocfg.comp = id_compare;
80         ocfg.hash = oid_hash;
81         ocfg.nbucket = MRP_WAYLAND_OUTPUT_BUCKETS;
82
83         memset(&wcfg, 0, sizeof(wcfg));
84         wcfg.nentry = MRP_WAYLAND_WINDOW_MAX;
85         wcfg.comp = id_compare;
86         wcfg.hash = wid_hash;
87         wcfg.nbucket = MRP_WAYLAND_WINDOW_BUCKETS;
88
89         memset(&lcfg, 0, sizeof(lcfg));
90         lcfg.nentry = MRP_WAYLAND_LAYER_MAX + MRP_WAYLAND_LAYER_BUILTIN;
91         lcfg.comp = id_compare;
92         lcfg.hash = lid_hash;
93         lcfg.nbucket = MRP_WAYLAND_LAYER_BUCKETS;
94
95         memset(&acfg, 0, sizeof(acfg));
96         acfg.nentry = MRP_WAYLAND_AREA_MAX;
97         acfg.comp = mrp_string_comp;
98         acfg.hash = mrp_string_hash;
99         acfg.nbucket = MRP_WAYLAND_AREA_BUCKETS;
100
101         wl->display_name = display_name ? mrp_strdup(display_name) : NULL;
102         wl->ml = ml;
103
104         wl->registry_listener.global = global_available_callback;
105         wl->registry_listener.global_remove = global_remove_callback;
106
107         wl->interfaces = mrp_htbl_create(&icfg);
108         wl->outputs = mrp_htbl_create(&ocfg);
109         wl->windows = mrp_htbl_create(&wcfg);
110         wl->layers = mrp_htbl_create(&lcfg);
111         wl->areas = mrp_htbl_create(&acfg);
112
113         instances = mrp_reallocz(instances, ninstance, ninstance + 2);
114         instances[ninstance++] = wl;
115     }
116
117     return wl;
118 }
119
120 void mrp_wayland_destroy(mrp_wayland_t *wl)
121 {
122     size_t i;
123
124     if (wl) {
125         for (i = 0;  i < ninstance;  i++) {
126             if (instances[i] == wl) {
127                 if (i < ninstance-1) {
128                     memmove(instances + i, instances + i + 1,
129                             (ninstance - (i + 1)) * sizeof(*instances));
130                 }
131                 instances[--ninstance] = NULL;
132                 break;
133             }
134         }
135     }
136 }
137
138 mrp_wayland_t *mrp_wayland_iterate(void **cursor)
139 {
140     ptrdiff_t i;
141
142     if (cursor) {
143         i = *cursor - NULL;
144
145         if (i >= 0 && i < (ptrdiff_t)ninstance) {
146             *cursor = NULL + (i + 1);
147             return instances[i];
148         }
149     }
150
151     return NULL;
152 }
153
154 bool mrp_wayland_connect(mrp_wayland_t *wl)
155 {
156 #define IO_EVENTS MRP_IO_EVENT_IN | MRP_IO_EVENT_ERR | MRP_IO_EVENT_HUP
157
158     struct wl_display *display;
159     struct wl_registry *registry;
160     mrp_io_watch_t *iow;
161     int fd;
162
163     MRP_ASSERT(wl, "invalid argument");
164     MRP_ASSERT(wl->ml, "no mainloop");
165
166     if (wl->iow)
167         return true; /* we are already connected */
168
169     if (!(display = wl_display_connect(wl->display_name))) {
170         mrp_debug("attempt to connect to display '%s' failed",
171                   get_display_name(wl));
172         return false;
173     }
174
175     fd = wl_display_get_fd(display);
176
177     MRP_ASSERT(fd >= 0, "fd for wayland display < 0");
178
179     if (!(registry = wl_display_get_registry(display))) {
180         mrp_log_error("can't get registry for display '%s'",
181                       get_display_name(wl));
182         wl_display_disconnect(display);
183         return false;
184     }
185
186      if (wl_registry_add_listener(registry, &wl->registry_listener, wl) < 0) {
187         mrp_log_error("can't add listener for registry (display '%s')",
188                       get_display_name(wl));
189         wl_registry_destroy(registry);
190         wl_display_disconnect(display);
191         return false;
192     }
193
194      if (!(iow = mrp_add_io_watch(wl->ml,fd,IO_EVENTS,display_io_watch,wl))) {
195         mrp_log_error("can't add io watch for display '%s')",
196                       get_display_name(wl));
197         wl_registry_destroy(registry);
198         wl_display_disconnect(display);
199         return false;
200     }
201
202     wl->iow = iow;
203     wl->display = display;
204     wl->registry = registry;
205
206     mrp_log_info("connecting to wayland display '%s'", get_display_name(wl));
207
208     wl_display_roundtrip(display);
209
210     mrp_debug("queried interfaces");
211
212     wl_display_roundtrip(display);
213
214     mrp_log_info("display '%s' is up and running", get_display_name(wl));
215
216     return true;
217
218 #undef IO_EVENTS
219 }
220
221 void mrp_wayland_flush(mrp_wayland_t *wl)
222 {
223     MRP_ASSERT(wl, "invalid argument");
224
225     if (wl->display) {
226         mrp_debug("calling wl_display_flush()");
227         wl_display_flush(wl->display);
228     }
229 }
230
231
232 static int update_layers(void *key, void *object, void *ud)
233 {
234     mrp_wayland_window_manager_t *wm = (mrp_wayland_window_manager_t *)ud;
235     mrp_wayland_layer_t *layer = (mrp_wayland_layer_t *)object;
236
237     MRP_UNUSED(key);
238
239     mrp_debug("register window manager to layer %u/'%s'",
240               layer->layerid, layer->name);
241
242     layer->wm = wm;
243
244     return MRP_HTBL_ITER_MORE;
245 }
246
247
248 void mrp_wayland_register_window_manager(mrp_wayland_t *wl,
249                                          mrp_wayland_window_manager_t *wm)
250 {
251     wl->wm = wm;
252
253     mrp_htbl_foreach(wl->layers, update_layers, wm);
254
255     if (wl->window_manager_update_callback) {
256         wl->window_manager_update_callback(wl,
257                                            MRP_WAYLAND_WINDOW_MANAGER_CREATE,
258                                            wm);
259     }
260 }
261
262
263 bool mrp_wayland_register_interface(mrp_wayland_t *wl,
264                                     mrp_wayland_factory_t *factory)
265 {
266     mrp_wayland_interface_t *wif;
267     const char *name;
268
269     MRP_ASSERT(wl && factory, "invalid argument");
270     MRP_ASSERT(factory->size >= sizeof(mrp_wayland_object_t),
271                "invalid object size in factory");
272     MRP_ASSERT(factory->interface, "missing factory interface");
273
274     name = factory->interface->name;
275
276     MRP_ASSERT(name, "broken factory interface");
277
278     if (!(wif = mrp_allocz(sizeof(mrp_wayland_interface_t)))) {
279         mrp_log_error("can't allocate memory for wayland interface '%s'",
280                       name);
281         return false;
282     }
283
284     wif->wl = wl;
285     wif->name = mrp_strdup(name);
286     wif->object_factory = *factory;
287
288     mrp_list_init(&wif->object_list);
289
290     if (!mrp_htbl_insert(wl->interfaces, (void *)wif->name, wif)) {
291         mrp_log_error("failed to add interface '%s' to hashtable. "
292                       "Perhaps already registered ...", wif->name);
293         mrp_free((void *)wif->name);
294         mrp_free(wif);
295         return false;
296     }
297
298     mrp_log_info("registered wayland interface '%s'", wif->name);
299
300     return true;
301 }
302
303 void mrp_wayland_register_window_manager_update_callback(mrp_wayland_t *wl,
304                          mrp_wayland_window_manager_update_callback_t callback)
305 {
306     MRP_ASSERT(wl, "invalid aruments");
307
308     mrp_debug("registering window_manager_update_callback");
309
310     wl->window_manager_update_callback = callback;
311 }
312
313 void mrp_wayland_register_output_update_callback(mrp_wayland_t *wl,
314                                mrp_wayland_output_update_callback_t callback)
315 {
316     MRP_ASSERT(wl, "invalid aruments");
317
318     mrp_debug("registering output_update_callback");
319
320     wl->output_update_callback = callback;
321 }
322
323 void mrp_wayland_register_window_update_callback(mrp_wayland_t *wl,
324                                mrp_wayland_window_update_callback_t callback)
325 {
326     MRP_ASSERT(wl, "invalid aruments");
327
328     mrp_debug("registering window_update_callback");
329
330     wl->window_update_callback = callback;
331 }
332
333 void mrp_wayland_register_layer_update_callback(mrp_wayland_t *wl,
334                                mrp_wayland_layer_update_callback_t callback)
335 {
336     MRP_ASSERT(wl, "invalid aruments");
337
338     mrp_debug("registering layer_update_callback");
339
340     wl->layer_update_callback = callback;
341 }
342
343 void mrp_wayland_register_area_update_callback(mrp_wayland_t *wl,
344                                mrp_wayland_area_update_callback_t callback)
345 {
346     MRP_ASSERT(wl, "invalid aruments");
347
348     mrp_debug("registering area_update_callback");
349
350     wl->area_update_callback = callback;
351 }
352
353 void mrp_wayland_set_scripting_data(mrp_wayland_t *wl, void *data)
354 {
355     MRP_ASSERT(wl, "invalid argument");
356
357     mrp_debug("%sset scripting data", data ? "" : "re");
358
359     wl->scripting_data = data;
360 }
361
362 void mrp_wayland_create_scripting_windows(mrp_wayland_t *wl, bool create)
363 {
364     MRP_ASSERT(wl, "invalid argument");
365
366     mrp_debug("%screate scripting windows", create ? "" : "do not ");
367
368     wl->create_scripting_windows = create;
369 }
370
371
372 void mrp_wayland_create_scripting_outputs(mrp_wayland_t *wl, bool create)
373 {
374     MRP_ASSERT(wl, "invalid argument");
375
376     mrp_debug("%screate scripting outputs", create ? "" : "do not ");
377
378     wl->create_scripting_outputs = create;
379 }
380
381
382 void mrp_wayland_create_scripting_areas(mrp_wayland_t *wl, bool create)
383 {
384     MRP_ASSERT(wl, "invalid argument");
385
386     mrp_debug("%screate scripting areas", create ? "" : "do not ");
387
388     wl->create_scripting_areas = create;
389 }
390
391
392 void mrp_wayland_create_scripting_layers(mrp_wayland_t *wl, bool create)
393 {
394     MRP_ASSERT(wl, "invalid argument");
395
396     mrp_debug("%screate scripting layers", create ? "" : "do not ");
397
398     wl->create_scripting_layers = create;
399 }
400
401
402 static uint32_t oid_hash(const void *pkey)
403 {
404     uint32_t key = *(uint32_t *)pkey;
405
406     return key % MRP_WAYLAND_OUTPUT_BUCKETS;
407 }
408
409 static uint32_t wid_hash(const void *pkey)
410 {
411     uint32_t key = *(uint32_t *)pkey;
412
413     return key % MRP_WAYLAND_WINDOW_BUCKETS;
414 }
415
416 static uint32_t lid_hash(const void *pkey)
417 {
418     uint32_t key = *(uint32_t *)pkey;
419
420     return key % MRP_WAYLAND_LAYER_BUCKETS;
421 }
422
423 static int id_compare(const void *pkey1, const void *pkey2)
424 {
425     int32_t key1 = *(int32_t *)pkey1;
426     int32_t key2 = *(int32_t *)pkey2;
427
428     return (key1 == key2) ? 0 : ((key1 < key2) ? -1 : 1);
429 }
430
431 static const char *get_display_name(mrp_wayland_t *wl)
432 {
433     const char *display_name;
434
435     MRP_ASSERT(wl, "invalid argument");
436
437     if (wl->display_name)
438         return wl->display_name;
439
440     if ((display_name = getenv("WAYLAND_DISPLAY")) != NULL)
441         return display_name;
442
443     return "wayland-0";
444 }
445
446 static void display_io_watch(mrp_io_watch_t *iow,
447                              int fd,
448                              mrp_io_event_t events,
449                              void *ud)
450 {
451     mrp_wayland_t *wl = (mrp_wayland_t *)ud;
452     char evnam[32];
453     char evlist[1024];
454     char *p, *e;
455
456     MRP_UNUSED(fd);
457
458     MRP_ASSERT(wl, "invalid user data");
459     MRP_ASSERT(iow == wl->iow, "mismatching io watch");
460
461     if ((events & MRP_IO_EVENT_HUP)) {
462         mrp_log_info("display '%s' is gone", get_display_name(wl));
463
464         wl_registry_destroy(wl->registry);
465         wl_display_disconnect(wl->display);
466
467         return;
468     }
469
470     if ((events & MRP_IO_EVENT_ERR)) {
471         mrp_log_error("I/O error on display '%s'", get_display_name(wl));
472         return;
473     }
474
475     if ((events & MRP_IO_EVENT_IN)) {
476         events &= ~MRP_IO_EVENT_IN;
477
478         mrp_debug("dispatching inputs from display '%s'",get_display_name(wl));
479
480         if (wl_display_dispatch(wl->display) < 0) {
481             mrp_log_error("failed to dispatch events of display '%s'",
482                           get_display_name(wl));
483         }
484
485         wl_display_flush(wl->display);
486     }
487
488     if (events) {
489 #       define PRINT(w)                                                    \
490             if (p < e) {                                                   \
491                 p += snprintf(p, e-p, "%s%s", p > evlist ? " " : "", w);   \
492             }
493 #       define CHECK_EVENT(e)                                              \
494             if ((events & MRP_IO_EVENT_ ## e)) {                           \
495                 char *evnam = #e;                                          \
496                 PRINT(evnam);                                              \
497                 events &= ~MRP_IO_EVENT_ ## e;                             \
498             }
499
500         e = (p = evlist) + (sizeof(evlist) - 1);
501
502         CHECK_EVENT(PRI);
503         CHECK_EVENT(OUT);
504
505         if (events) {
506             snprintf(evnam, sizeof(evnam), "<unknown 0x%x>", events);
507             PRINT(evnam);
508         }
509
510         mrp_debug("unhandled io events: %s", evlist);
511
512 #       undef CHECK_EVENT
513 #       undef PRINT
514     }
515 }
516
517 static void object_create(mrp_wayland_interface_t *wif,
518                           uint32_t name,
519                           uint32_t version)
520 {
521     mrp_wayland_t *wl;
522     mrp_wayland_factory_t *factory;
523     mrp_wayland_object_t *obj;
524     struct wl_proxy *proxy;
525
526     MRP_ASSERT(wif, "invalid argument");
527
528     wl = wif->wl;
529     factory = &wif->object_factory;
530
531     if (!(obj = mrp_allocz(factory->size))) {
532         mrp_log_error("can't allocate %zd byte memory for %u/'%s' object",
533                       factory->size, (unsigned int)name, wif->name);
534         return;
535     }
536
537     proxy = wl_registry_bind(wl->registry, name, factory->interface, 1);
538
539     if (!proxy) {
540         mrp_log_error("failed to create proxy for object %u/'%s' on "
541                       "display '%s'", name, wif->name, get_display_name(wl));
542         mrp_free(obj);
543         return;
544     }
545
546     mrp_list_init(&obj->interface_link);
547     obj->interface = wif;
548     obj->name = name;
549     obj->version = version;
550     obj->proxy = proxy;
551
552     if (factory->constructor) {
553         if (!factory->constructor(wl, obj)) {
554             mrp_log_error("failed to construct object %u/'%s' on "
555                           "display '%s'",name,wif->name, get_display_name(wl));
556             wl_proxy_destroy(proxy);
557             mrp_free(obj);
558         }
559     }
560
561     /* TODO: register the object by name */
562
563     mrp_debug("object %u/'%s' on display '%s' created", name, wif->name,
564               get_display_name(wl));
565 }
566
567
568 static void global_available_callback(void *data,
569                                       struct wl_registry *registry,
570                                       uint32_t name,
571                                       const char *interface,
572                                       uint32_t version)
573 {
574     mrp_wayland_t *wl = (mrp_wayland_t *)data;
575     mrp_wayland_interface_t *wif;
576
577     MRP_ASSERT(wl && registry && interface, "invalid argument");
578     MRP_ASSERT(registry == wl->registry, "confused with data structures");
579
580     wif = mrp_htbl_lookup(wl->interfaces, (void *)interface);
581
582     mrp_debug("object %u/%s is up%s", name, interface,
583               wif ? "" : " (interface unknown)");
584
585     if (wif) {
586         MRP_ASSERT(wif->wl == wl, "confused with data structures");
587         object_create(wif, name, version);
588     }
589 }
590
591 static void global_remove_callback(void *data,
592                                    struct wl_registry *wl_registry,
593                                    uint32_t name)
594 {
595     MRP_UNUSED(data);
596     MRP_UNUSED(wl_registry);
597
598     mrp_debug("object %u is down", name);
599 }