cdee0065067dc9b95e80308923d4ab396aba36c2
[profile/ivi/murphy.git] / src / plugins / system-controller / wayland / glm-window-manager.c
1 /*
2  * Copyright (c) 2014, 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 <sys/types.h>
31 #include <sys/stat.h>
32 #include <stdint.h>
33 #include <stdbool.h>
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <unistd.h>
37 #include <fcntl.h>
38 #include <libgen.h>
39 #include <string.h>
40 #include <errno.h>
41
42 #include <murphy/common.h>
43
44 #include <genivi-shell/ivi-controller-client-protocol.h>
45 #include <genivi-shell/ivi-application-client-protocol.h>
46 #include <ico-uxf-weston-plugin/ico_window_mgr-client-protocol.h>
47
48 #include <aul/aul.h>
49
50 #include "glm-window-manager.h"
51 #include "layer.h"
52 #include "output.h"
53 #include "animation.h"
54 #include "window.h"
55 #include "window-manager.h"
56 #include "area.h"
57
58 #define MAX_COORDINATE                  16383
59
60 #define SURFACELESS_TIMEOUT             1000  /* ms */
61 #define CONSTRUCTOR_TIMEOUT             10000 /* ms */
62 #define TITLE_TIMEOUT                   1500  /* ms */
63
64 #define INVALID_INDEX                   (~(uint32_t)0)
65
66 #define SURFACE_TO_NODE(s)              (((s) >> 16) & 0xFF)
67 #define SURFACE_TO_HOST(s)              (((s) >> 24) & 0xFF)
68
69 #define SURFACE_ID_OUR_FLAG             0x70000000
70 #define SURFACE_ID_MAX                  0x00ffffff
71
72 #define VISIBLE                         true
73 #define HIDDEN                          false
74
75 typedef enum constructor_state_e        constructor_state_t;
76 typedef enum match_e                    match_t;
77
78 typedef struct ctrl_surface_s           ctrl_surface_t;
79 typedef struct ctrl_layer_s             ctrl_layer_t;
80 typedef struct ctrl_screen_s            ctrl_screen_t;
81 typedef struct app_surface_s            app_surface_t;
82 typedef struct application_s            application_t;
83 typedef struct ico_extension_s          ico_extension_t;
84 typedef struct constructor_s            constructor_t;
85 typedef struct screen_layer_iterator_s  screen_layer_iterator_t;
86 typedef struct surface_layer_iterator_s surface_layer_iterator_t;
87 typedef struct layer_defaults_s         layer_defaults_t;
88
89 struct mrp_glm_window_manager_s {
90     MRP_WAYLAND_WINDOW_MANAGER_COMMON;
91     application_t *app;
92     ico_extension_t *ico;
93     mrp_list_hook_t constructors;
94     mrp_htbl_t *surfaces;
95     mrp_htbl_t *layers;
96     mrp_htbl_t *screens;
97 };
98
99 struct ctrl_surface_s {
100     mrp_wayland_t *wl;
101     struct ivi_controller_surface *ctrl_surface;
102     struct wl_surface *wl_surface;
103     int32_t nodeid;
104     uint32_t id;
105     int32_t pid;
106     char *appid;
107     char *title;
108     int32_t x, y;
109     int32_t width, height;
110     int32_t requested_x, requested_y;
111     int32_t requested_width, requested_height;
112     double opacity;
113     bool visible;
114     int32_t layerid;
115     mrp_wayland_window_t *win;
116     struct {
117         mrp_timer_t *title;
118     } timer;
119 };
120
121 struct ctrl_layer_s {
122     mrp_wayland_t *wl;
123     struct ivi_controller_layer *ctrl_layer;
124     int32_t id;
125     char *name;
126     struct wl_array surfaces;
127 };
128
129 struct ctrl_screen_s {
130     mrp_wayland_t *wl;
131     struct ivi_controller_screen *ctrl_screen;
132     int32_t id;
133     uint32_t output_index;
134     int32_t width, height;
135 };
136
137 struct app_surface_s {
138     MRP_WAYLAND_OBJECT_COMMON;
139 };
140
141 struct application_s {
142     MRP_WAYLAND_OBJECT_COMMON;
143 };
144
145 struct ico_extension_s {
146     MRP_WAYLAND_OBJECT_COMMON;
147 }; 
148
149 enum constructor_state_e {
150     CONSTRUCTOR_FAILED = 0,     /* handle request failed */
151     CONSTRUCTOR_INCOMPLETE,     /* pid is set but title is missing */
152     CONSTRUCTOR_TITLED,         /* pid and title set */
153     CONSTRUCTOR_SURFACELESS,    /* needs an ivi surface created by us */
154     CONSTRUCTOR_REQUESTED,      /* native handle was requested */
155     CONSTRUCTOR_BOUND,          /* got native handle and ivi surface created */
156 };
157
158 struct constructor_s {
159     mrp_list_hook_t link;
160     mrp_glm_window_manager_t *wm;
161     int32_t pid;
162     char *title;
163     uint32_t id_surface;
164     struct wl_surface *wl_surface;
165     constructor_state_t state;
166     struct {
167         mrp_timer_t *timeout;
168         mrp_timer_t *surfaceless;
169     } timer;
170 };
171
172 enum match_e {
173     DOES_NOT_MATCH = 0,
174     DOES_MATCH = 1
175 };
176
177 struct screen_layer_iterator_s {
178     mrp_glm_window_manager_t *wm;
179     mrp_wayland_output_t *out;
180     ctrl_screen_t *scr;
181     bool need_commit;
182 };
183
184 struct surface_layer_iterator_s {
185     struct ivi_controller_layer *ctrl_layer;
186     ctrl_layer_t *ly;
187 };
188
189 struct layer_defaults_s {
190     int32_t zorder;
191     double opacity;
192     bool visibility;
193 };
194
195
196 static bool window_manager_constructor(mrp_wayland_t *,mrp_wayland_object_t *);
197 static void ctrl_screen_callback(void *, struct ivi_controller *, uint32_t,
198                                  struct ivi_controller_screen *);
199 static void ctrl_layer_callback(void *, struct ivi_controller *, uint32_t);
200 static void ctrl_surface_callback(void *, struct ivi_controller *, uint32_t,
201                                   int32_t, const char *);
202 static void ctrl_error_callback(void *, struct ivi_controller *, int32_t,
203                                 int32_t, int32_t, const char *);
204 static void ctrl_native_handle_callback(void *, struct ivi_controller *,
205                                         struct wl_surface *);
206
207 static ctrl_surface_t *surface_create(mrp_glm_window_manager_t *,
208                                       uint32_t, int32_t, const char *,
209                                       struct wl_surface *);
210 static void surface_destroy(mrp_glm_window_manager_t *, ctrl_surface_t *);
211 static ctrl_surface_t *surface_find(mrp_glm_window_manager_t *, uint32_t);
212
213 static void surface_visibility_callback(void*, struct ivi_controller_surface*,
214                                      int32_t);
215 static void surface_opacity_callback(void *, struct ivi_controller_surface *,
216                                      wl_fixed_t);
217 static void surface_source_rectangle_callback(void *,
218                                            struct ivi_controller_surface *,
219                                            int32_t,int32_t,int32_t,int32_t);
220 static void surface_destination_rectangle_callback(void *,
221                                            struct ivi_controller_surface *,
222                                            int32_t,int32_t, int32_t,int32_t);
223 static void surface_configuration_callback(void *,
224                                    struct ivi_controller_surface *,
225                                    int32_t, int32_t);
226 static void surface_orientation_callback(void *,
227                                  struct ivi_controller_surface *,
228                                  int32_t);
229 static void surface_pixelformat_callback(void *,
230                                  struct ivi_controller_surface *,
231                                  int32_t);
232 static void surface_added_to_layer_callback(void *,
233                                     struct ivi_controller_surface *,
234                                     struct ivi_controller_layer *);
235 static void surface_stats_callback(void *, struct ivi_controller_surface *,
236                                    uint32_t, uint32_t, uint32_t,
237                                    uint32_t, const char *);
238 static void surface_destroyed_callback(void *,struct ivi_controller_surface *);
239 static void surface_content_callback(void *, struct ivi_controller_surface *,
240                                      int32_t);
241 static void surface_input_focus_callback(void *,
242                                  struct ivi_controller_surface *,
243                                  uint32_t, int32_t);
244 static bool surface_is_ready(mrp_glm_window_manager_t *, ctrl_surface_t *);
245 static void surface_set_title(mrp_glm_window_manager_t *, ctrl_surface_t *,
246                               const char *);
247 static void surface_titleless(mrp_timer_t *, void *);
248
249
250 static ctrl_layer_t *layer_create(mrp_glm_window_manager_t *,
251                                   mrp_wayland_layer_t *, ctrl_screen_t *);
252 #if 0
253 static void layer_destroy(mrp_glm_window_manager_t *, ctrl_layer_t *);
254 #endif
255 static void layer_visibility_callback(void *, struct ivi_controller_layer *,
256                                       int32_t);
257 static void layer_opacity_callback(void *, struct ivi_controller_layer *,
258                                    wl_fixed_t opacity);
259 static void layer_source_rectangle_callback(void *,
260                                             struct ivi_controller_layer *,
261                                             int32_t,int32_t, int32_t,int32_t);
262 static void layer_destination_rectangle_callback(void *,
263                                             struct ivi_controller_layer *,
264                                             int32_t,int32_t, int32_t,int32_t);
265 static void layer_configuration_callback(void *, struct ivi_controller_layer *,
266                                          int32_t, int32_t);
267 static void layer_orientation_callback(void *, struct ivi_controller_layer *,
268                                        int32_t);
269 static void layer_added_to_screen_callback(void*, struct ivi_controller_layer*,
270                                            struct wl_output *);
271 static void layer_destroyed_callback(void *, struct ivi_controller_layer *);
272 static bool layer_add_surface_to_top(ctrl_layer_t *, ctrl_surface_t *);
273 #if 0
274 static bool layer_add_surface_to_bottom(ctrl_layer_t *, ctrl_surface_t *);
275 #endif
276 static bool layer_move_surface_to_top(ctrl_layer_t *, ctrl_surface_t *);
277 static bool layer_move_surface_to_bottom(ctrl_layer_t *, ctrl_surface_t *);
278 static bool layer_remove_surface(ctrl_layer_t *, ctrl_surface_t *);
279 static void layer_send_surfaces(ctrl_layer_t *);
280
281
282 static uint32_t surface_id_generate(void);
283 static bool surface_id_is_ours(uint32_t);
284 static char *surface_id_print(uint32_t, char *, size_t);
285
286 static bool application_manager_constructor(mrp_wayland_t *,
287                                             mrp_wayland_object_t *);
288 static void shell_info_callback(void *, struct ivi_application *,
289                                 int32_t, const char *, uint32_t);
290
291 static bool ico_extension_constructor(mrp_wayland_t *,mrp_wayland_object_t *);
292 static void ico_extension_window_active_callback(void*,struct ico_window_mgr*,
293                                                  uint32_t, int32_t);
294 static void ico_extension_map_surface_callback(void *,struct ico_window_mgr *,
295                                                int32_t, uint32_t, uint32_t,
296                                                int32_t,int32_t, int32_t,
297                                                uint32_t);
298 static void ico_extension_update_surface_callback(void *,
299                                                   struct ico_window_mgr *,
300                                                   uint32_t, int32_t,
301                                                   int32_t, int32_t,
302                                                   int32_t, int32_t,
303                                                   int32_t, int32_t);
304 static void ico_extension_destroy_surface_callback(void *,
305                                                    struct ico_window_mgr *,
306                                                    uint32_t);
307
308
309 static constructor_t *constructor_create(mrp_glm_window_manager_t *,
310                                          constructor_state_t,
311                                          int32_t, const char *, uint32_t);
312 static void constructor_destroy(constructor_t *);
313 static void constructor_timeout(mrp_timer_t *, void *);
314 static void constructor_surfaceless(mrp_timer_t *, void *);
315 static constructor_t *constructor_find_first(mrp_glm_window_manager_t *,
316                                              match_t,
317                                              constructor_state_t);
318 static constructor_t *constructor_find_surface(mrp_glm_window_manager_t *,
319                                                uint32_t,int32_t,const char *);
320
321 #if 0
322 static constructor_t *constructor_find_bound(mrp_glm_window_manager_t *,
323                                              uint32_t);
324 #endif
325 static void constructor_set_title(mrp_glm_window_manager_t *,
326                                   constructor_t *, const char *);
327 static void constructor_issue_next_request(mrp_glm_window_manager_t *);
328 static bool constructor_bind_ivi_surface(mrp_glm_window_manager_t *,
329                                          constructor_t *);
330 static char *constructor_state_str(constructor_state_t);
331
332
333 static ctrl_layer_t *layer_find(mrp_glm_window_manager_t *, int32_t);
334 static void layer_request(mrp_wayland_layer_t *,
335                           mrp_wayland_layer_update_t *);
336
337
338 static void window_request(mrp_wayland_window_t *,
339                            mrp_wayland_window_update_t *,
340                            mrp_wayland_animation_t *, uint32_t);
341
342
343 static void buffer_request(mrp_wayland_window_manager_t *, const char *,
344                            uint32_t, uint32_t);
345
346 static uint32_t sid_hash(const void *);
347 static uint32_t lid_hash(const void *);
348 static uint32_t oid_hash(const void *);
349 static int id_compare(const void *, const void *);
350
351 static void get_appid(int32_t, char *, int);
352
353 static layer_defaults_t layer_defaults[MRP_WAYLAND_LAYER_TYPE_MAX] = {
354     /*         layer type                  zorder opacity   visibility */
355     /*---------------------------------------------------------------- */
356     [ MRP_WAYLAND_LAYER_TYPE_UNKNOWN ] = {      2,  0.750,  HIDDEN     },
357     [ MRP_WAYLAND_LAYER_BACKGROUND   ] = {      1,  0.000,  VISIBLE    },
358     [ MRP_WAYLAND_LAYER_APPLICATION  ] = {      3,  1.000,  HIDDEN,    },
359     [ MRP_WAYLAND_LAYER_INPUT        ] = {      4,  1.000,  HIDDEN     },
360     [ MRP_WAYLAND_LAYER_TOUCH        ] = {      5,  1.000,  HIDDEN     },
361     [ MRP_WAYLAND_LAYER_CURSOR       ] = {      6,  1.000,  HIDDEN     },
362     [ MRP_WAYLAND_LAYER_STARTUP      ] = {      7,  1.000,  HIDDEN     },
363     [ MRP_WAYLAND_LAYER_FULLSCREEN   ] = {      8,  1.000,  HIDDEN     },
364 };
365
366
367 bool mrp_glm_window_manager_register(mrp_wayland_t *wl)
368 {
369     mrp_wayland_factory_t factory;
370
371     factory.size = sizeof(mrp_glm_window_manager_t);
372     factory.interface = &ivi_controller_interface;
373     factory.constructor = window_manager_constructor;
374     factory.destructor = NULL;
375     mrp_wayland_register_interface(wl, &factory);
376
377     factory.size = sizeof(application_t);
378     factory.interface = &ivi_application_interface;
379     factory.constructor = application_manager_constructor;
380     factory.destructor = NULL;
381     mrp_wayland_register_interface(wl, &factory);
382
383     factory.size = sizeof(ico_extension_t);
384     factory.interface = &ico_window_mgr_interface;
385     factory.constructor = ico_extension_constructor;
386     factory.destructor = NULL;
387     mrp_wayland_register_interface(wl, &factory);
388
389     return true;
390 }
391
392 static bool window_manager_constructor(mrp_wayland_t *wl,
393                                        mrp_wayland_object_t *obj)
394 {
395     static struct ivi_controller_listener listener = {
396         .screen        = ctrl_screen_callback,
397         .layer         = ctrl_layer_callback,
398         .surface       = ctrl_surface_callback,
399         .error         = ctrl_error_callback,
400         .native_handle = ctrl_native_handle_callback
401     };
402
403     mrp_glm_window_manager_t *wm = (mrp_glm_window_manager_t *)obj;
404     mrp_wayland_interface_t *wif;
405     mrp_htbl_config_t scfg, lcfg, ocfg;
406     application_t *app;
407     int sts;
408
409     MRP_ASSERT(wm, "invalid argument");
410
411     memset(&scfg, 0, sizeof(scfg));
412     scfg.nentry = MRP_WAYLAND_WINDOW_MAX;
413     scfg.comp = id_compare;
414     scfg.hash = sid_hash;
415     scfg.nbucket = MRP_WAYLAND_WINDOW_BUCKETS;
416
417     memset(&lcfg, 0, sizeof(lcfg));
418     lcfg.nentry = MRP_WAYLAND_LAYER_MAX;
419     lcfg.comp = id_compare;
420     lcfg.hash = lid_hash;
421     lcfg.nbucket = MRP_WAYLAND_LAYER_BUCKETS;
422
423     memset(&ocfg, 0, sizeof(ocfg));
424     ocfg.nentry = MRP_WAYLAND_OUTPUT_MAX;
425     ocfg.comp = id_compare;
426     ocfg.hash = oid_hash;
427     ocfg.nbucket = MRP_WAYLAND_OUTPUT_BUCKETS;
428
429     wm->layer_request = layer_request;
430     wm->window_request = window_request;
431     wm->buffer_request = buffer_request;
432
433     mrp_list_init(&wm->constructors);
434
435     wm->surfaces = mrp_htbl_create(&scfg);
436     wm->layers = mrp_htbl_create(&lcfg);
437     wm->screens = mrp_htbl_create(&ocfg);
438
439     MRP_ASSERT(wm->surfaces && wm->layers && wm->screens,
440                "failed to create hash table");
441
442     sts = ivi_controller_add_listener((struct ivi_controller *)wm->proxy,
443                                       &listener, wm);
444
445     if (sts < 0)
446         return false;
447
448     mrp_wayland_register_window_manager(wl, (mrp_wayland_window_manager_t*)wm);
449
450     wif = mrp_htbl_lookup(wl->interfaces,
451                           (void *)ivi_application_interface.name);
452
453     if (wif && !mrp_list_empty(&wif->object_list)) {
454         app = mrp_list_entry(wif->object_list.next,
455                              application_t, interface_link);
456
457         mrp_debug("registering application interface to window manager");
458
459         wm->app = app;
460     }
461
462     return true;
463 }
464
465 static int screen_layer_iterator_cb(void *key, void *object, void *user_data)
466 {
467     mrp_wayland_layer_t *layer = (mrp_wayland_layer_t *)object;
468     screen_layer_iterator_t *it = (screen_layer_iterator_t *)user_data;
469
470     MRP_UNUSED(key);
471
472     if (!strcmp(layer->outputname, it->out->outputname)) {
473         layer_create(it->wm, layer, it->scr);
474         it->need_commit = true;
475     }
476
477     return MRP_HTBL_ITER_MORE;
478 }
479
480 static void ctrl_screen_callback(void *data,
481                                  struct ivi_controller *ivi_controller,
482                                  uint32_t id_screen,
483                                  struct ivi_controller_screen *screen)
484 {
485     mrp_glm_window_manager_t *wm = (mrp_glm_window_manager_t *)data;
486     mrp_wayland_t *wl;
487     mrp_wayland_output_t *output;
488     ctrl_screen_t *s;
489     screen_layer_iterator_t it;
490
491     MRP_ASSERT(wm && wm->interface && wm->interface->wl, "invalid argument");
492     MRP_ASSERT(ivi_controller == (struct ivi_controller *)wm->proxy,
493                "confused with data structures");
494
495     wl = wm->interface->wl;
496
497     mrp_debug("id_screen=%u screen=%p", id_screen, screen);
498
499     if (!(output = mrp_wayland_output_find_by_id(wl, id_screen))) {
500         mrp_log_warning("system-controller: can't find output for screen %u",
501                         id_screen);
502         return;
503     }
504
505     if (!output->name || output->width <= 0 || output->height <= 0) {
506         mrp_log_warning("system-controller: incomplete output (id %u)",
507                         id_screen);
508         return;
509     }
510
511     if (!(s = mrp_allocz(sizeof(ctrl_screen_t)))) {
512         mrp_log_error("system-controller: can't allocate memory for screen");
513         return;
514     }
515
516     s->wl = wl;
517     s->ctrl_screen = screen;
518     s->id = id_screen;
519     s->output_index = output->index;
520     s->width = output->width;
521     s->height = output->height;
522
523     it.wm = wm;
524     it.out = output;
525     it.scr = s;
526     it.need_commit = false;
527     mrp_htbl_foreach(wl->layers.by_type, screen_layer_iterator_cb, &it);
528
529     if (it.need_commit) {
530         mrp_debug("calling ivi_controller_commit_changes()");
531         ivi_controller_commit_changes((struct ivi_controller *)wm->proxy);
532     }
533
534     mrp_wayland_flush(wl);
535 }
536
537 static void ctrl_layer_callback(void *data,
538                                 struct ivi_controller *ivi_controller,
539                                 uint32_t id_layer)
540 {
541     mrp_glm_window_manager_t *wm = (mrp_glm_window_manager_t *)data;
542
543     MRP_ASSERT(wm && wm->interface && wm->interface->wl, "invalid argument");
544     MRP_ASSERT(ivi_controller == (struct ivi_controller *)wm->proxy,
545                "confused with data structures");
546
547     mrp_debug("id_layer=%u", id_layer);
548 }
549
550 static void ctrl_surface_callback(void *data,
551                                   struct ivi_controller *ivi_controller,
552                                   uint32_t id_surface,
553                                   int32_t pid,
554                                   const char *title)
555 {
556     mrp_glm_window_manager_t *wm = (mrp_glm_window_manager_t *)data;
557     constructor_t *c;
558     struct wl_surface *wl_surface;
559     char buf[256];
560
561     MRP_ASSERT(wm && wm->interface && wm->interface->wl, "invalid argument");
562     MRP_ASSERT(ivi_controller == (struct ivi_controller *)wm->proxy,
563                "confused with data structures");
564
565     mrp_debug("id_surface=%s pid=%d title='%s'",
566               surface_id_print(id_surface, buf,sizeof(buf)),
567               pid, title ? title:"<null>");
568
569     wl_surface = NULL;
570
571     if ((c = constructor_find_surface(wm, id_surface, pid, title))) {
572         switch (c->state) {
573
574         case CONSTRUCTOR_BOUND:
575             wl_surface = c->wl_surface;
576             /* intentional fall over */
577
578         case CONSTRUCTOR_TITLED:
579         case CONSTRUCTOR_REQUESTED:
580             if (!title || !title[0])
581                 title = c->title;
582             break;
583
584         default:
585             break;
586         }
587
588         constructor_destroy(c);
589     }
590
591     surface_create(wm, id_surface, pid, title, wl_surface);
592 }
593
594
595 static void ctrl_error_callback(void *data,
596                                 struct ivi_controller *ivi_controller,
597                                 int32_t object_id,
598                                 int32_t object_type,
599                                 int32_t error_code,
600                                 const char *error_text)
601 {
602     mrp_glm_window_manager_t *wm = (mrp_glm_window_manager_t *)data;
603     const char *type_str;
604
605     MRP_ASSERT(wm && wm->interface && wm->interface->wl, "invalid argument");
606     MRP_ASSERT(ivi_controller == (struct ivi_controller *)wm->proxy,
607                "confused with data structures");
608
609     switch (object_type) {
610     case IVI_CONTROLLER_OBJECT_TYPE_SURFACE:   type_str = "surface";     break;
611     case IVI_CONTROLLER_OBJECT_TYPE_LAYER:     type_str = "layer";       break;
612     case IVI_CONTROLLER_OBJECT_TYPE_SCREEN:    type_str = "screen";      break;
613     default:                                   type_str = "<unknown>";   break;
614     }
615
616     if (!error_text)
617         error_text = "???";
618
619     mrp_debug("%s %d error %d: %s", type_str,object_id, error_code,error_text);
620
621     switch (object_type) {
622
623     case IVI_CONTROLLER_OBJECT_TYPE_SURFACE:
624         if (error_code  == IVI_CONTROLLER_ERROR_CODE_NATIVE_HANDLE_END) {
625             mrp_debug("native_handle_list end marker");
626             constructor_issue_next_request(wm);
627         }
628         else {
629             mrp_log_error("system-controller: surface error %d: %s",
630                           error_code, error_text);
631         }
632         break;
633
634     default:
635         break;
636     }
637 }
638
639 static void ctrl_native_handle_callback(void *data,
640                                         struct ivi_controller *ivi_controller,
641                                         struct wl_surface *wl_surface)
642 {
643     mrp_glm_window_manager_t *wm = (mrp_glm_window_manager_t *)data;
644     application_t *app;
645     constructor_t *reqsurf;
646
647     MRP_ASSERT(wm && wm->interface && wm->interface->wl, "invalid argument");
648     MRP_ASSERT(ivi_controller == (struct ivi_controller *)wm->proxy,
649                "confused with data structures");
650
651     mrp_debug("wl_surface=%p", wl_surface);
652
653     if (!(app = wm->app)) {
654         mrp_log_error("system-controller: ivi application interface is down "
655                       "when %s() is called", __FUNCTION__);
656         return;
657     }
658
659     reqsurf = constructor_find_first(wm, DOES_MATCH, CONSTRUCTOR_REQUESTED);
660
661     if (!reqsurf)
662         mrp_debug("no pendig request");
663     else {
664         /* create an ivi-surface and bind it to wl_surface */
665         reqsurf->id_surface = surface_id_generate();
666         reqsurf->wl_surface = wl_surface;
667
668         if (constructor_bind_ivi_surface(wm, reqsurf))
669             reqsurf->state = CONSTRUCTOR_BOUND;
670    }
671 }
672
673
674 static ctrl_surface_t *surface_create(mrp_glm_window_manager_t *wm,
675                                       uint32_t id_surface,
676                                       int32_t pid,
677                                       const char *title,
678                                       struct wl_surface *wl_surface)
679 {
680     static struct ivi_controller_surface_listener listener =  {
681         .visibility            =  surface_visibility_callback,
682         .opacity               =  surface_opacity_callback,
683         .source_rectangle      =  surface_source_rectangle_callback,
684         .destination_rectangle =  surface_destination_rectangle_callback,
685         .configuration         =  surface_configuration_callback,
686         .orientation           =  surface_orientation_callback,
687         .pixelformat           =  surface_pixelformat_callback,
688         .layer                 =  surface_added_to_layer_callback,
689         .stats                 =  surface_stats_callback,
690         .destroyed             =  surface_destroyed_callback,
691         .content               =  surface_content_callback,
692         .input_focus           =  surface_input_focus_callback
693     };
694
695     mrp_wayland_t *wl;
696     struct ivi_controller *ctrl;
697     struct ivi_controller_surface *ctrl_surface;
698     ctrl_surface_t *sf;
699     char appid[1024];
700     char id_str[256];
701
702     MRP_ASSERT(wm && wm->interface && wm->interface->wl, "invalid argument");
703
704     wl = wm->interface->wl;
705     ctrl = (struct ivi_controller *)wm->proxy;
706
707     surface_id_print(id_surface, id_str, sizeof(id_str));
708     get_appid(pid, appid, sizeof(appid));
709
710     mrp_debug("create surface "
711               "(id=%s pid=%d appid='%s' title='%s' wl_surface=%p)",
712               id_str, pid, appid, title ? title : "<null>", wl_surface);
713
714     if (surface_find(wm, id_surface)) {
715         mrp_log_error("system-controller: attempt to create multiple times "
716                       "surface %s", id_str);
717         return NULL;
718     }
719
720     if (!(ctrl_surface = ivi_controller_surface_create(ctrl, id_surface))) {
721         mrp_log_error("system-controller: failed to create controller "
722                       "surface for surface %s", id_str);
723         return NULL;
724     }
725
726     mrp_debug("ctrl_surface %p was created for surface %s",
727               ctrl_surface, id_str);
728
729     if (surface_id_is_ours(id_surface)) {
730         /* The ivi surface was created by us meaning we already had
731            a surfaceless timeout. If title was not set during this
732            time it is pointless to set another timeout to wait for
733            the title. So, we set it to something to prevent furter
734            delays */
735         if (!title)
736             title = "";
737     }
738
739     if (!(sf = mrp_allocz(sizeof(ctrl_surface_t)))) {
740         mrp_log_error("system-controller: failed to allocate memory "
741                       "for surface %s", id_str);
742         return NULL;
743     }
744
745     sf->wl = wl;
746     sf->ctrl_surface = ctrl_surface;
747     sf->wl_surface = wl_surface;
748     sf->id = id_surface;
749     sf->pid = pid;
750     sf->appid = mrp_strdup(appid);
751     sf->title = title ? mrp_strdup(title) : NULL;
752     sf->width = -1;
753     sf->height = -1;
754     sf->requested_x = MAX_COORDINATE+1;
755     sf->requested_y = MAX_COORDINATE+1;
756     sf->requested_width = -1;
757     sf->requested_height = -1;
758     sf->opacity = -1.0;
759     sf->layerid = -1;
760
761     if (!mrp_htbl_insert(wm->surfaces, &sf->id, sf)) {
762         mrp_log_error("system-controller: hashmap insertion error when "
763                       "trying to create surface %s ", id_str);
764         mrp_free(sf);
765         return NULL;
766     }
767
768     if (ivi_controller_surface_add_listener(ctrl_surface, &listener, sf) < 0) {
769         mrp_log_error("system-controller: failed to create surface %s "
770                       "(can't listen to surface)", id_str);
771
772         mrp_htbl_remove(wm->surfaces, &sf->id, false);
773
774         mrp_free(sf->title);
775         mrp_free(sf);
776
777         return NULL;
778     }
779
780     if (!sf->title) {
781         sf->timer.title = mrp_add_timer(wl->ml, TITLE_TIMEOUT,
782                                         surface_titleless, sf);
783     }
784
785     mrp_wayland_flush(wl);
786
787     return sf;
788 }
789
790
791 static void surface_destroy(mrp_glm_window_manager_t *wm, ctrl_surface_t *sf)
792 {
793     ctrl_surface_t *d;
794     char buf[256];
795
796     if (wm && wm->surfaces && sf) {
797         mrp_debug("surface %s going to be destroyed",
798                   surface_id_print(sf->id, buf, sizeof(buf)));
799
800         if (!(d = mrp_htbl_remove(wm->surfaces, &sf->id, false)) || sf != d) {
801             mrp_log_error("system-controller: confused with data structures "
802                           "(surface hashtable entry mismatch)");
803         }
804         else {
805             mrp_del_timer(sf->timer.title);
806
807             if (sf->win)
808                 mrp_wayland_window_destroy(sf->win);
809
810             mrp_free(sf->appid);
811             mrp_free(sf->title);
812             mrp_free(sf);
813         }
814     }
815 }
816
817 static ctrl_surface_t *surface_find(mrp_glm_window_manager_t *wm,
818                                     uint32_t id_surface)
819 {
820     ctrl_surface_t *sf;
821
822     if (!wm || !wm->surfaces)
823         sf = NULL;
824     else
825         sf = mrp_htbl_lookup(wm->surfaces, &id_surface);
826
827     return sf;
828 }
829
830
831 static void surface_visibility_callback(void *data,
832                                  struct ivi_controller_surface *ctrl_surface,
833                                  int32_t visibility)
834 {
835     ctrl_surface_t *sf = (ctrl_surface_t *)data;
836     mrp_wayland_t *wl;
837     mrp_glm_window_manager_t *wm;
838     mrp_wayland_window_update_t u;
839     char buf[256];
840
841     MRP_ASSERT(sf && sf->wl, "invalid argument");
842     MRP_ASSERT(ctrl_surface == sf->ctrl_surface,
843                "confused with data structures");
844
845     wl = sf->wl;
846     wm = (mrp_glm_window_manager_t *)wl->wm;
847
848     MRP_ASSERT(wm, "data inconsitency");
849
850     mrp_debug("ctrl_surface=%p (id=%s) visibility=%d", ctrl_surface,
851               surface_id_print(sf->id, buf, sizeof(buf)), visibility);
852
853     sf->visible = visibility ? true : false;
854
855     if (surface_is_ready(wm, sf)) {
856         memset(&u, 0, sizeof(u));
857         u.mask = MRP_WAYLAND_WINDOW_SURFACEID_MASK |
858                  MRP_WAYLAND_WINDOW_VISIBLE_MASK;
859         u.surfaceid = sf->id;
860         u.visible = sf->visible;
861
862         mrp_wayland_window_update(sf->win, MRP_WAYLAND_WINDOW_VISIBLE, &u);
863     }
864 }
865
866 static void surface_opacity_callback(void *data,
867                                  struct ivi_controller_surface *ctrl_surface,
868                                  wl_fixed_t opacity)
869 {
870     ctrl_surface_t *sf = (ctrl_surface_t *)data;
871     mrp_wayland_t *wl;
872     mrp_glm_window_manager_t *wm;
873     mrp_wayland_window_update_t u;
874     char buf[256];
875
876     MRP_ASSERT(sf && sf->wl, "invalid argument");
877     MRP_ASSERT(ctrl_surface == sf->ctrl_surface,
878                "confused with data structures");
879
880     wl = sf->wl;
881     wm = (mrp_glm_window_manager_t *)wl->wm;
882
883     MRP_ASSERT(wm, "data inconsitency");
884     mrp_debug("ctrl_surface=%p (id=%s) opacity=%d", ctrl_surface,
885               surface_id_print(sf->id, buf, sizeof(buf)), opacity);
886
887     sf->opacity = wl_fixed_to_double(opacity);
888
889     if (surface_is_ready(wm, sf)) {
890         memset(&u, 0, sizeof(u));
891         u.mask = MRP_WAYLAND_WINDOW_SURFACEID_MASK |
892                  MRP_WAYLAND_WINDOW_OPACITY_MASK;
893         u.surfaceid = sf->id;
894         u.opacity = sf->opacity;
895
896         mrp_wayland_window_update(sf->win, MRP_WAYLAND_WINDOW_VISIBLE, &u);
897     }
898 }
899
900 static void surface_source_rectangle_callback(void *data,
901                                    struct ivi_controller_surface *ctrl_surface,
902                                    int32_t x,
903                                    int32_t y,
904                                    int32_t width,
905                                    int32_t height)
906 {
907     ctrl_surface_t *sf = (ctrl_surface_t *)data;
908     mrp_wayland_t *wl;
909     mrp_glm_window_manager_t *wm;
910     char buf[256];
911
912     MRP_ASSERT(sf && sf->wl, "invalid argument");
913     MRP_ASSERT(ctrl_surface == sf->ctrl_surface,
914                "confused with data structures");
915
916     wl = sf->wl;
917     wm = (mrp_glm_window_manager_t *)wl->wm;
918
919     MRP_ASSERT(wm, "data inconsitency");
920
921     mrp_debug("ctrl_surface=%p (id=%s) x=%d y=%d width=%d height=%d",
922               ctrl_surface, surface_id_print(sf->id, buf, sizeof(buf)),
923               x, y, width, height);
924 }
925
926 static void surface_destination_rectangle_callback(void *data,
927                                    struct ivi_controller_surface *ctrl_surface,
928                                    int32_t x,
929                                    int32_t y,
930                                    int32_t width,
931                                    int32_t height)
932 {
933     ctrl_surface_t *sf = (ctrl_surface_t *)data;
934     mrp_wayland_t *wl;
935     mrp_glm_window_manager_t *wm;
936     mrp_wayland_window_update_t u;
937     char buf[256];
938
939     MRP_ASSERT(sf && sf->wl, "invalid argument");
940     MRP_ASSERT(ctrl_surface == sf->ctrl_surface,
941                "confused with data structures");
942
943     wl = sf->wl;
944     wm = (mrp_glm_window_manager_t *)wl->wm;
945
946     MRP_ASSERT(wm, "data inconsitency");
947
948     mrp_debug("ctrl_surface=%p (id=%s) x=%d y=%d width=%d height=%d",
949               ctrl_surface, surface_id_print(sf->id, buf, sizeof(buf)),
950               x, y, width, height);
951
952     sf->x = x;
953     sf->y = y;
954     sf->width = width;
955     sf->height = height;
956
957     if (surface_is_ready(wm, sf)) {
958         /*
959          * system-controller is the sole authority who manages the
960          * destination rectangle. So if a rouge app is is fiddling
961          * with it here we fight back and set it back what it was
962          * requested.
963          *
964          * A quick series of legitime requests might result extra
965          * wayland messages but hopefully will not end up in a infinite
966          * loop ...
967          */
968         if ((sf->requested_x <= MAX_COORDINATE && x != sf->requested_x ) ||
969             (sf->requested_y <= MAX_COORDINATE && x != sf->requested_y ) ||
970             (sf->requested_width  > 0 && width  != sf->requested_width ) ||
971             (sf->requested_height > 0 && height != sf->requested_height)  )
972         {
973             mrp_debug("calling ivi_controller_surface_set_destination_"
974                       "rectangle(ivi_controller_surface=%p, x=%d, y=%d, "
975                       "width=%d height=%d)", sf->ctrl_surface,
976                       sf->requested_x, sf->requested_y,
977                       sf->requested_width, sf->requested_height);
978
979             ivi_controller_surface_set_destination_rectangle(sf->ctrl_surface,
980                                     sf->requested_x, sf->requested_y,
981                                     sf->requested_width, sf->requested_height);
982         }
983
984         memset(&u, 0, sizeof(u));
985         u.mask      =  MRP_WAYLAND_WINDOW_SURFACEID_MASK |
986                        MRP_WAYLAND_WINDOW_POSITION_MASK  |
987                        MRP_WAYLAND_WINDOW_SIZE_MASK      ;
988         u.surfaceid =  sf->id;
989         u.x         =  sf->x;
990         u.y         =  sf->y;
991         u.width     =  sf->width;
992         u.height    =  sf->height;
993
994         mrp_wayland_window_update(sf->win, MRP_WAYLAND_WINDOW_CONFIGURE, &u);
995     }
996 }
997
998 static void surface_configuration_callback(void *data,
999                                    struct ivi_controller_surface *ctrl_surface,
1000                                    int32_t width,
1001                                    int32_t height)
1002 {
1003     ctrl_surface_t *sf = (ctrl_surface_t *)data;
1004     mrp_wayland_t *wl;
1005     mrp_glm_window_manager_t *wm;
1006     char buf[256];
1007
1008     MRP_ASSERT(sf && sf->wl, "invalid argument");
1009     MRP_ASSERT(ctrl_surface == sf->ctrl_surface,
1010                "confused with data structures");
1011
1012     wl = sf->wl;
1013     wm = (mrp_glm_window_manager_t *)wl->wm;
1014
1015     MRP_ASSERT(wm, "data inconsitency");
1016
1017     mrp_debug("ctrl_surface=%p (id=%s) width=%d height=%d", ctrl_surface,
1018               surface_id_print(sf->id, buf, sizeof(buf)), width, height);
1019 }
1020
1021 static void surface_orientation_callback(void *data,
1022                                  struct ivi_controller_surface *ctrl_surface,
1023                                  int32_t orientation)
1024 {
1025     ctrl_surface_t *sf = (ctrl_surface_t *)data;
1026     mrp_wayland_t *wl;
1027     mrp_glm_window_manager_t *wm;
1028     char buf[256];
1029
1030     MRP_ASSERT(sf && sf->wl, "invalid argument");
1031     MRP_ASSERT(ctrl_surface == sf->ctrl_surface,
1032                "confused with data structures");
1033
1034     wl = sf->wl;
1035     wm = (mrp_glm_window_manager_t *)wl->wm;
1036
1037     MRP_ASSERT(wm, "data inconsitency");
1038
1039     mrp_debug("ctrl_surface=%p (id=%s) orientation=%d", ctrl_surface,
1040               surface_id_print(sf->id, buf, sizeof(buf)), orientation);
1041 }
1042
1043 static void surface_pixelformat_callback(void *data,
1044                                  struct ivi_controller_surface *ctrl_surface,
1045                                  int32_t pixelformat)
1046 {
1047     ctrl_surface_t *sf = (ctrl_surface_t *)data;
1048     mrp_wayland_t *wl;
1049     mrp_glm_window_manager_t *wm;
1050     char buf[256];
1051
1052     MRP_ASSERT(sf && sf->wl, "invalid argument");
1053     MRP_ASSERT(ctrl_surface == sf->ctrl_surface,
1054                "confused with data structures");
1055
1056     wl = sf->wl;
1057     wm = (mrp_glm_window_manager_t *)wl->wm;
1058
1059     MRP_ASSERT(wm, "data inconsitency");
1060
1061     mrp_debug("ctrl_surface=%p (id=%s) pixelformat=%d", ctrl_surface,
1062               surface_id_print(sf->id, buf, sizeof(buf)), pixelformat);
1063 }
1064
1065 static int surface_layer_iterator_cb(void *key, void *object, void *user_data)
1066 {
1067     ctrl_layer_t *ly = (ctrl_layer_t *)object;
1068     surface_layer_iterator_t *it = (surface_layer_iterator_t *)user_data;
1069
1070     MRP_UNUSED(key);
1071
1072     if (it->ctrl_layer == ly->ctrl_layer) {
1073         it->ly = ly;
1074         return MRP_HTBL_ITER_STOP;
1075     }
1076
1077     return MRP_HTBL_ITER_MORE;
1078 }
1079
1080 static void surface_added_to_layer_callback(void *data,
1081                                    struct ivi_controller_surface *ctrl_surface,
1082                                    struct ivi_controller_layer *ctrl_layer)
1083 {
1084     ctrl_surface_t *sf = (ctrl_surface_t *)data;
1085     mrp_wayland_t *wl;
1086     mrp_glm_window_manager_t *wm;
1087     mrp_wayland_layer_t *layer;
1088     surface_layer_iterator_t it;
1089     ctrl_layer_t *ly;
1090     mrp_wayland_window_update_t u;
1091     char id_str[256];
1092
1093     MRP_ASSERT(sf && sf->wl, "invalid argument");
1094     MRP_ASSERT(ctrl_surface == sf->ctrl_surface,
1095                "confused with data structures");
1096
1097     wl = sf->wl;
1098     wm = (mrp_glm_window_manager_t *)wl->wm;
1099
1100     MRP_ASSERT(wm, "data inconsitency");
1101
1102     surface_id_print(sf->id, id_str, sizeof(id_str));
1103
1104     mrp_debug("ctrl_surface=%p (id=%s) ctrl_layer=%p", ctrl_surface,
1105               id_str, ctrl_layer);
1106
1107     if (!ctrl_layer) {
1108         /* surface is removed from a layer */
1109 #if 0   /* silently ignore the removal */
1110         sf->layerid = -1;
1111 #endif
1112         return;  /* do not send notification of removal for the time being */
1113     }
1114     else {
1115         /* surface is added/moved to a layer */
1116         memset(&it, 0, sizeof(it));
1117         it.ctrl_layer = ctrl_layer;
1118
1119         mrp_htbl_foreach(wm->layers, surface_layer_iterator_cb, &it);
1120
1121         if (!(ly = it.ly)) {
1122             mrp_log_error("system-controller: can't update layer of surface %s"
1123                           "(ctrl_layer not found)", id_str);
1124             return;
1125         }
1126
1127         if (!(layer = mrp_wayland_layer_find_by_id(wl, ly->id))) {
1128             mrp_log_error("system-controller: can't update layer of surface %s"
1129                           "(layer %d not found)", id_str, ly->id);
1130             return;
1131         }
1132
1133         if (!surface_is_ready(wm, sf)) {
1134             mrp_log_error("system-controller: attempt to update layer "
1135                           "of non-ready surface %s", id_str);
1136             return;
1137         }
1138     }
1139
1140     memset(&u, 0, sizeof(u));
1141     u.mask = MRP_WAYLAND_WINDOW_SURFACEID_MASK | MRP_WAYLAND_WINDOW_LAYER_MASK;
1142     u.surfaceid = sf->id;
1143     u.layer = layer;
1144
1145     mrp_wayland_window_update(sf->win, MRP_WAYLAND_WINDOW_CONFIGURE, &u);
1146 }
1147
1148 static void surface_stats_callback(void *data,
1149                                    struct ivi_controller_surface *ctrl_surface,
1150                                    uint32_t redraw_count,
1151                                    uint32_t frame_count,
1152                                    uint32_t update_count,
1153                                    uint32_t pid,
1154                                    const char *process_name)
1155 {
1156     ctrl_surface_t *sf = (ctrl_surface_t *)data;
1157     mrp_wayland_t *wl;
1158     mrp_glm_window_manager_t *wm;
1159     char buf[256];
1160
1161     MRP_ASSERT(sf && sf->wl, "invalid argument");
1162     MRP_ASSERT(ctrl_surface == sf->ctrl_surface,
1163                "confused with data structures");
1164
1165     wl = sf->wl;
1166     wm = (mrp_glm_window_manager_t *)wl->wm;
1167
1168     MRP_ASSERT(wm, "data inconsitency");
1169
1170     mrp_debug("ctrl_surface=%p (id=%s)"
1171               "redraw_count=%u frame_count=%u update_count=%u "
1172               "pid=%u process_name='%s'",
1173               ctrl_surface, surface_id_print(sf->id, buf, sizeof(buf)),
1174               redraw_count, frame_count, update_count, pid,
1175               process_name ? process_name : "<null>");
1176
1177     if (sf->pid != (int32_t)pid) {
1178         mrp_debug("confused with data structures (mismatching pids)");
1179         return;
1180     }
1181 }
1182
1183
1184 static void surface_destroyed_callback(void *data,
1185                                    struct ivi_controller_surface *ctrl_surface)
1186 {
1187     ctrl_surface_t *sf = (ctrl_surface_t *)data;
1188     mrp_wayland_t *wl;
1189     mrp_glm_window_manager_t *wm;
1190     ctrl_layer_t *ly;
1191     char buf[256];
1192
1193     MRP_ASSERT(sf && sf->wl, "invalid argument");
1194     MRP_ASSERT(ctrl_surface == sf->ctrl_surface,
1195                "confused with data structures");
1196
1197     wl = sf->wl;
1198     wm = (mrp_glm_window_manager_t *)wl->wm;
1199
1200     MRP_ASSERT(wm, "data inconsitency");
1201
1202     mrp_debug("ctrl_surface=%p (id=%s)", ctrl_surface,
1203               surface_id_print(sf->id, buf, sizeof(buf)));
1204
1205     if (sf->layerid >= 0 && (ly = layer_find(wm, sf->layerid))) {
1206         layer_remove_surface(ly, sf);
1207
1208         mrp_debug("calling ivi_controller_commit_changes()");
1209         ivi_controller_commit_changes((struct ivi_controller *)wm->proxy);
1210
1211         mrp_wayland_flush(wl);
1212     }
1213
1214     surface_destroy(wm, sf);
1215 }
1216
1217 static void surface_content_callback(void *data,
1218                              struct ivi_controller_surface *ctrl_surface,
1219                              int32_t content_state)
1220 {
1221     ctrl_surface_t *sf = (ctrl_surface_t *)data;
1222     mrp_wayland_t *wl;
1223     mrp_glm_window_manager_t *wm;
1224     char buf[256];
1225
1226     MRP_ASSERT(sf && sf->wl, "invalid argument");
1227     MRP_ASSERT(ctrl_surface == sf->ctrl_surface,
1228                "confused with data structures");
1229
1230     wl = sf->wl;
1231     wm = (mrp_glm_window_manager_t *)wl->wm;
1232
1233     MRP_ASSERT(wm, "data inconsitency");
1234
1235     mrp_debug("ctrl_surface=%p (id=%s) content_state=%d", ctrl_surface,
1236               surface_id_print(sf->id, buf, sizeof(buf)), content_state);
1237
1238 }
1239
1240 static void surface_input_focus_callback(void *data,
1241                                  struct ivi_controller_surface *ctrl_surface,
1242                                  uint32_t device,
1243                                  int32_t enabled)
1244 {
1245     ctrl_surface_t *sf = (ctrl_surface_t *)data;
1246     mrp_wayland_t *wl;
1247     mrp_glm_window_manager_t *wm;
1248     char buf[256];
1249
1250     MRP_ASSERT(sf && sf->wl, "invalid argument");
1251     MRP_ASSERT(ctrl_surface == sf->ctrl_surface,
1252                "confused with data structures");
1253
1254     wl = sf->wl;
1255     wm = (mrp_glm_window_manager_t *)wl->wm;
1256
1257     MRP_ASSERT(wm, "data inconsitency");
1258
1259     mrp_debug("ctrl_surface=%p (id=%s) device=%u enabled=%d", ctrl_surface,
1260               surface_id_print(sf->id, buf, sizeof(buf)), device, enabled);
1261 }
1262
1263 static bool surface_is_ready(mrp_glm_window_manager_t *wm, ctrl_surface_t *sf)
1264 {
1265     mrp_wayland_t *wl;
1266     mrp_wayland_window_update_t u;
1267     bool ready;
1268
1269     ready = sf->win ? true : false;
1270
1271     if (!ready && wm->interface && wm->interface->wl) {
1272         wl = wm->interface->wl;
1273
1274         if (sf->id     >  0 &&
1275             sf->pid    >  0 &&
1276             sf->appid       &&
1277             sf->title       &&
1278             sf->width  >= 0 &&
1279             sf->height >= 0  )
1280         {
1281             memset(&u, 0, sizeof(u));
1282             u.mask       =  MRP_WAYLAND_WINDOW_SURFACEID_MASK |
1283                             MRP_WAYLAND_WINDOW_NAME_MASK      |
1284                             MRP_WAYLAND_WINDOW_APPID_MASK     |
1285                             MRP_WAYLAND_WINDOW_PID_MASK       |
1286                             MRP_WAYLAND_WINDOW_NODEID_MASK    |
1287                             MRP_WAYLAND_WINDOW_POSITION_MASK  |
1288                             MRP_WAYLAND_WINDOW_SIZE_MASK      ;
1289             u.surfaceid  =  sf->id;
1290             u.name       =  sf->title;
1291             u.appid      =  sf->appid;
1292             u.pid        =  sf->pid;
1293             u.nodeid     =  sf->nodeid;
1294             u.x          =  sf->x;
1295             u.y          =  sf->y;
1296             u.width      =  sf->width;
1297             u.height     =  sf->height;
1298
1299             sf->win = mrp_wayland_window_create(wl, &u);
1300
1301             if (sf->visible || sf->opacity >= 0) {
1302                 memset(&u, 0, sizeof(u));
1303                 u.mask = MRP_WAYLAND_WINDOW_SURFACEID_MASK;
1304                 u.surfaceid = sf->id;
1305
1306                 if (sf->visible) {
1307                     u.mask |= MRP_WAYLAND_WINDOW_VISIBLE_MASK;
1308                     u.visible = sf->visible;
1309                 }
1310
1311                 if (sf->opacity >= 0) {
1312                     u.mask |= MRP_WAYLAND_WINDOW_OPACITY_MASK;
1313                     u.opacity = sf->opacity;
1314                 }
1315
1316                 mrp_wayland_window_update(sf->win, MRP_WAYLAND_WINDOW_VISIBLE,
1317                                           &u);
1318             }
1319         }
1320     }
1321
1322     return ready;
1323 }
1324
1325 static void surface_set_title(mrp_glm_window_manager_t *wm,
1326                               ctrl_surface_t *sf,
1327                               const char *title)
1328 {
1329     mrp_wayland_window_update_t u;
1330
1331     mrp_debug("title='%s'", title);
1332
1333     mrp_del_timer(sf->timer.title);
1334     sf->timer.title = NULL;
1335
1336     if (sf->title && !strcmp(title, sf->title))
1337         mrp_debug("nothing to do (same title)");
1338     else {
1339         mrp_free(sf->title);
1340         sf->title = mrp_strdup(title ? title : "");
1341
1342         if (surface_is_ready(wm, sf)) {
1343             memset(&u, 0, sizeof(u));
1344             u.mask      =  MRP_WAYLAND_WINDOW_SURFACEID_MASK |
1345                            MRP_WAYLAND_WINDOW_NAME_MASK;
1346             u.surfaceid =  sf->id;
1347             u.name      =  sf->title;
1348
1349             mrp_wayland_window_update(sf->win,MRP_WAYLAND_WINDOW_NAMECHANGE,&u);
1350         }
1351     }
1352 }
1353
1354 static void surface_titleless(mrp_timer_t *timer, void *user_data)
1355 {
1356     ctrl_surface_t *sf = (ctrl_surface_t *)user_data;
1357     mrp_glm_window_manager_t *wm;
1358
1359     MRP_ASSERT(timer && sf && sf->wl && sf->wl->wm, "invalid argument");
1360     MRP_ASSERT(timer == sf->timer.title, "confused with data structures");
1361
1362     wm = (mrp_glm_window_manager_t *)sf->wl->wm;
1363
1364     mrp_debug("id=%u pid=%d appid='%s'", sf->id, sf->pid, sf->appid);
1365
1366     mrp_del_timer(sf->timer.title);
1367     sf->timer.title = NULL;
1368
1369     surface_set_title(wm, sf, "");
1370 }
1371
1372
1373 static ctrl_layer_t *layer_create(mrp_glm_window_manager_t *wm,
1374                                   mrp_wayland_layer_t *layer,
1375                                   ctrl_screen_t *s)
1376 {
1377     static struct ivi_controller_layer_listener listener = {
1378         .visibility            =  layer_visibility_callback,
1379         .opacity               =  layer_opacity_callback,
1380         .source_rectangle      =  layer_source_rectangle_callback,
1381         .destination_rectangle =  layer_destination_rectangle_callback,
1382         .configuration         =  layer_configuration_callback,
1383         .orientation           =  layer_orientation_callback,
1384         .screen                =  layer_added_to_screen_callback,
1385         .destroyed             =  layer_destroyed_callback
1386     };
1387
1388     struct ivi_controller_layer *ctrl_layer;
1389     ctrl_layer_t *ly;
1390     layer_defaults_t *def;
1391     wl_fixed_t opacity;
1392
1393     mrp_debug("create and link layer %s (id=0x%08x size=%dx%d) to screen %d",
1394               layer->name, layer->layerid, s->width, s->height, s->id);
1395
1396     ctrl_layer = ivi_controller_layer_create((struct ivi_controller*)wm->proxy,
1397                                              layer->layerid,
1398                                              s->width, s->height);
1399     if (!ctrl_layer) {
1400         mrp_log_error("system-controller: can't create controller layer for "
1401                       "%s layer (0x%08x)", layer->name, layer->layerid);
1402         return NULL;
1403     }
1404
1405     if (layer->type < 0 || layer->type >= MRP_WAYLAND_LAYER_TYPE_MAX)
1406         def = layer_defaults;
1407     else
1408         def = layer_defaults + layer->type;
1409
1410     if (!(ly = mrp_allocz(sizeof(ctrl_layer_t)))) {
1411         mrp_log_error("system-controller: can't allocate memory for layer "
1412                       "%s (0x%08x)", layer->name, layer->layerid);
1413         return NULL;
1414     }
1415
1416     ly->wl = layer->wl;
1417     ly->ctrl_layer = ctrl_layer;
1418     ly->id = layer->layerid;
1419     ly->name = mrp_strdup(layer->name);
1420
1421     if (!mrp_htbl_insert(wm->layers, &ly->id, ly)) {
1422         mrp_log_error("system-controller: failed to instantiate layer %s "
1423                       "(0x%08x): already exists", layer->name, layer->layerid);
1424         mrp_free(ly);
1425         return NULL;
1426     }
1427
1428     if (ivi_controller_layer_add_listener(ctrl_layer, &listener, ly) < 0) {
1429         mrp_debug("can't listen to layer %s (0x%08x)",
1430                   layer->name, layer->layerid);
1431         mrp_htbl_remove(wm->layers, &ly->id, false);
1432         mrp_free(ly);
1433         return NULL;
1434     }
1435
1436     ivi_controller_screen_add_layer(s->ctrl_screen, ctrl_layer);
1437
1438
1439     opacity = wl_fixed_from_double(def->opacity);
1440     mrp_debug("calling ivi_controller_layer_set_opacity"
1441               "(struct ivi_controller_layer=%p, opacity=%d)",
1442               ctrl_layer, opacity);
1443     ivi_controller_layer_set_opacity(ctrl_layer, opacity);
1444
1445
1446     mrp_debug("calling ivi_controller_layer_set_visibility"
1447               "(ivi_controller_layer=%p, visibility=%d)",
1448               ctrl_layer, def->visibility);
1449     ivi_controller_layer_set_visibility(ctrl_layer, def->visibility);
1450
1451
1452     return ly;
1453 }
1454
1455 #if 0
1456 static void layer_destroy(mrp_glm_window_manager_t *wm, ctrl_layer_t *ly)
1457 {
1458     ctrl_layer_t *d;
1459
1460     if (wm && wm->layers && ly) {
1461         mrp_debug("layer %s 0x%08x going to be destroyed", ly->name, ly->id);
1462
1463         if (!(d = mrp_htbl_remove(wm->layers, &ly->id, false)) || ly != d) {
1464             mrp_log_error("system-controller: confused with data structures "
1465                           "(layer hashtable mismatch)");
1466         }
1467         else {
1468             wl_array_release(&ly->surfaces);
1469             mrp_free(ly->name);
1470             mrp_free(ly);
1471         }
1472     }
1473 }
1474 #endif
1475
1476 static void layer_visibility_callback(void *data,
1477                                       struct ivi_controller_layer *ctrl_layer,
1478                                       int32_t visibility)
1479 {
1480     ctrl_layer_t *ly = (ctrl_layer_t *)data;
1481     mrp_wayland_t *wl;
1482     mrp_glm_window_manager_t *wm;
1483
1484     MRP_ASSERT(ly && ly->wl, "invalid argument");
1485     MRP_ASSERT(ctrl_layer == ly->ctrl_layer,
1486                "confused with data structures");
1487
1488     wl = ly->wl;
1489     wm = (mrp_glm_window_manager_t *)wl->wm;
1490
1491     MRP_ASSERT(wm, "data inconsitency");
1492
1493     mrp_debug("ctrl_layer=%p (%s %d) visibility=%d", ctrl_layer,
1494               ly->name, ly->id, visibility);
1495 }
1496
1497 static void layer_opacity_callback(void *data,
1498                                    struct ivi_controller_layer *ctrl_layer,
1499                                    wl_fixed_t opacity)
1500 {
1501     ctrl_layer_t *ly = (ctrl_layer_t *)data;
1502     mrp_wayland_t *wl;
1503     mrp_glm_window_manager_t *wm;
1504
1505     MRP_ASSERT(ly && ly->wl, "invalid argument");
1506     MRP_ASSERT(ctrl_layer == ly->ctrl_layer,
1507                "confused with data structures");
1508
1509     wl = ly->wl;
1510     wm = (mrp_glm_window_manager_t *)wl->wm;
1511
1512     MRP_ASSERT(wm, "data inconsitency");
1513
1514     mrp_debug("ctrl_layer=%p (%s %d) opacity=%d", ctrl_layer,
1515               ly->name, ly->id, opacity);
1516 }
1517
1518 static void layer_source_rectangle_callback(void *data,
1519                                        struct ivi_controller_layer *ctrl_layer,
1520                                        int32_t x,
1521                                        int32_t y,
1522                                        int32_t width,
1523                                        int32_t height)
1524 {
1525     ctrl_layer_t *ly = (ctrl_layer_t *)data;
1526     mrp_wayland_t *wl;
1527     mrp_glm_window_manager_t *wm;
1528
1529     MRP_ASSERT(ly && ly->wl, "invalid argument");
1530     MRP_ASSERT(ctrl_layer == ly->ctrl_layer,
1531                "confused with data structures");
1532
1533     wl = ly->wl;
1534     wm = (mrp_glm_window_manager_t *)wl->wm;
1535
1536     MRP_ASSERT(wm, "data inconsitency");
1537
1538     mrp_debug("ctrl_layer=%p (%s %d) x=%d y=%d width=%d height=%d", ctrl_layer,
1539               ly->name, ly->id, x,y, width,height);
1540 }
1541
1542 static void layer_destination_rectangle_callback(void *data,
1543                                        struct ivi_controller_layer *ctrl_layer,
1544                                        int32_t x,
1545                                        int32_t y,
1546                                        int32_t width,
1547                                        int32_t height)
1548 {
1549     ctrl_layer_t *ly = (ctrl_layer_t *)data;
1550     mrp_wayland_t *wl;
1551     mrp_glm_window_manager_t *wm;
1552
1553     MRP_ASSERT(ly && ly->wl, "invalid argument");
1554     MRP_ASSERT(ctrl_layer == ly->ctrl_layer,
1555                "confused with data structures");
1556
1557     wl = ly->wl;
1558     wm = (mrp_glm_window_manager_t *)wl->wm;
1559
1560     MRP_ASSERT(wm, "data inconsitency");
1561
1562     mrp_debug("ctrl_layer=%p (%s %d) x=%d y=%d width=%d height=%d", ctrl_layer,
1563               ly->name, ly->id, x,y, width,height);
1564 }
1565
1566 static void layer_configuration_callback(void *data,
1567                                       struct ivi_controller_layer *ctrl_layer,
1568                                       int32_t width,
1569                                       int32_t height)
1570 {
1571     ctrl_layer_t *ly = (ctrl_layer_t *)data;
1572     mrp_wayland_t *wl;
1573     mrp_glm_window_manager_t *wm;
1574
1575     MRP_ASSERT(ly && ly->wl, "invalid argument");
1576     MRP_ASSERT(ctrl_layer == ly->ctrl_layer,
1577                "confused with data structures");
1578
1579     wl = ly->wl;
1580     wm = (mrp_glm_window_manager_t *)wl->wm;
1581
1582     MRP_ASSERT(wm, "data inconsitency");
1583
1584     mrp_debug("ctrl_layer=%p (%s %d) width=%d height=%d", ctrl_layer,
1585               ly->name, ly->id, width,height);
1586 }
1587
1588 static void layer_orientation_callback(void *data,
1589                                        struct ivi_controller_layer *ctrl_layer,
1590                                        int32_t orientation)
1591 {
1592     ctrl_layer_t *ly = (ctrl_layer_t *)data;
1593     mrp_wayland_t *wl;
1594     mrp_glm_window_manager_t *wm;
1595
1596     MRP_ASSERT(ly && ly->wl, "invalid argument");
1597     MRP_ASSERT(ctrl_layer == ly->ctrl_layer,
1598                "confused with data structures");
1599
1600     wl = ly->wl;
1601     wm = (mrp_glm_window_manager_t *)wl->wm;
1602
1603     MRP_ASSERT(wm, "data inconsitency");
1604
1605     mrp_debug("ctrl_layer=%p (%s %d) orientation=%d", ctrl_layer,
1606               ly->name, ly->id, orientation);
1607 }
1608
1609 static void layer_added_to_screen_callback(void *data,
1610                                       struct ivi_controller_layer *ctrl_layer,
1611                                       struct wl_output *screen)
1612 {
1613     ctrl_layer_t *ly = (ctrl_layer_t *)data;
1614     mrp_wayland_t *wl;
1615     mrp_glm_window_manager_t *wm;
1616
1617     MRP_ASSERT(ly && ly->wl, "invalid argument");
1618     MRP_ASSERT(ctrl_layer == ly->ctrl_layer,
1619                "confused with data structures");
1620
1621     wl = ly->wl;
1622     wm = (mrp_glm_window_manager_t *)wl->wm;
1623
1624     MRP_ASSERT(wm, "data inconsitency");
1625
1626     mrp_debug("ctrl_layer=%p (%s %d) screen=%p", ctrl_layer,
1627               ly->name, ly->id, screen);
1628 }
1629
1630 static void layer_destroyed_callback(void *data,
1631                                      struct ivi_controller_layer *ctrl_layer)
1632 {
1633     ctrl_layer_t *ly = (ctrl_layer_t *)data;
1634     mrp_wayland_t *wl;
1635     mrp_glm_window_manager_t *wm;
1636
1637     MRP_ASSERT(ly && ly->wl, "invalid argument");
1638     MRP_ASSERT(ctrl_layer == ly->ctrl_layer,
1639                "confused with data structures");
1640
1641     wl = ly->wl;
1642     wm = (mrp_glm_window_manager_t *)wl->wm;
1643
1644     MRP_ASSERT(wm, "data inconsitency");
1645
1646     mrp_debug("ctrl_layer=%p (%s %d)", ctrl_layer, ly->name, ly->id);
1647 }
1648
1649 #if 0
1650 static bool layer_add_surface_to_bottom(ctrl_layer_t *ly, ctrl_surface_t *sf)
1651 {
1652     uint32_t *last, *pos;
1653     char id_str[256];
1654
1655     MRP_ASSERT(ly && sf, "invalid argument");
1656     MRP_ASSERT(ly->id == sf->layerid, "mismatching layer ID's");
1657
1658     surface_id_print(sf->id, id_str, sizeof(id_str));
1659
1660     wl_array_for_each(pos, &ly->surfaces) {
1661         if (*pos == (uint32_t)sf->id) {
1662             mrp_log_error("system-controller: can't add surface %s to the "
1663                           "bottom of layer %d (surface already exists)",
1664                           id_str, sf->layerid);
1665             return false;
1666         }
1667     }
1668
1669     if (!(last = wl_array_add(&ly->surfaces, sizeof(uint32_t)))) {
1670         mrp_log_error("system-controller: can't add surface %s to the bottom "
1671                       "of layer %d (no memory)", id_str, sf->layerid);
1672         return false;
1673     }
1674
1675     for (pos = last;   (void *)pos > ly->surfaces.data;  pos--)
1676         pos[0] = pos[-1];
1677
1678     pos[0] = sf->id;
1679
1680     mrp_debug("surface %s added to the bottom of layer %d",
1681               id_str, sf->layerid);
1682
1683     layer_send_surfaces(ly);
1684
1685     return true;
1686 }
1687 #endif
1688
1689 static bool layer_add_surface_to_top(ctrl_layer_t *ly, ctrl_surface_t *sf)
1690 {
1691     uint32_t *last, *pos;
1692     char id_str[256];
1693
1694     MRP_ASSERT(ly && sf, "invalid argument");
1695     MRP_ASSERT(ly->id == sf->layerid, "mismatching layer ID's");
1696
1697     surface_id_print(sf->id, id_str, sizeof(id_str));
1698
1699     wl_array_for_each(pos, &ly->surfaces) {
1700         if (*pos == (uint32_t)sf->id) {
1701             mrp_log_error("system-controller: can't add surface %s to the "
1702                           "top of layer %d (surface already exists)",
1703                           id_str, sf->layerid);
1704             return false;
1705         }
1706     }
1707
1708     if (!(last = wl_array_add(&ly->surfaces, sizeof(uint32_t)))) {
1709         mrp_log_error("system-controller: can't add surface %s to the top "
1710                       "of layer %d (no memory)", id_str, sf->layerid);
1711         return false;
1712     }
1713
1714     *last = sf->id;
1715
1716     mrp_debug("surface %s added to the top of layer %d", id_str, sf->layerid);
1717
1718     layer_send_surfaces(ly);
1719
1720     return true;
1721 }
1722
1723 static bool layer_move_surface_to_bottom(ctrl_layer_t *ly, ctrl_surface_t *sf)
1724 {
1725     uint32_t *pos, *first, *last;
1726     int dim;
1727     bool removed;
1728     char id_str[256];
1729
1730     MRP_ASSERT(ly && sf, "invalid argument");
1731     MRP_ASSERT(ly->id == sf->layerid, "mismatching layer ID's");
1732
1733     surface_id_print(sf->id, id_str, sizeof(id_str));
1734
1735     dim = ly->surfaces.size / sizeof(uint32_t);
1736     first = (uint32_t *)ly->surfaces.data;
1737     last = first + (dim - 1);
1738
1739     removed = false;
1740
1741     for (pos = last;  pos >= first;  pos--) {
1742         if (pos[0] == (uint32_t)sf->id)
1743             removed = true;
1744         else if (removed)
1745             pos[1] = pos[0];
1746     }
1747
1748     if (!removed) {
1749         mrp_debug("failed to move surface %s to bottom of layer %d "
1750                   "(can't find surface)", id_str, sf->layerid);
1751         return false;
1752     }
1753
1754     *first = (uint32_t)sf->id;
1755
1756     mrp_debug("surface %s moved to bottom of layer %d", id_str, sf->layerid);
1757
1758     layer_send_surfaces(ly);
1759
1760     return true;
1761 }
1762
1763 static bool layer_move_surface_to_top(ctrl_layer_t *ly, ctrl_surface_t *sf)
1764 {
1765     uint32_t *pos, *first, *last;
1766     int dim;
1767     bool removed;
1768     char id_str[256];
1769
1770     MRP_ASSERT(ly && sf, "invalid argument");
1771     MRP_ASSERT(ly->id == sf->layerid, "mismatching layer ID's");
1772
1773     surface_id_print(sf->id, id_str, sizeof(id_str));
1774
1775     dim = ly->surfaces.size / sizeof(uint32_t);
1776     first = (uint32_t *)ly->surfaces.data;
1777     last = first + (dim - 1);
1778
1779     removed = false;
1780
1781     wl_array_for_each(pos, &ly->surfaces) {
1782         if (pos[0] == (uint32_t)sf->id)
1783             removed = true;
1784         else if (removed)
1785             pos[-1] = pos[0];
1786     }
1787
1788     if (!removed) {
1789         mrp_debug("failed to move surface %s to top of layer %d "
1790                   "(can't find surface)", id_str, sf->layerid);
1791         return false;
1792     }
1793
1794     *last = (uint32_t)sf->id;
1795
1796     mrp_debug("surface %s moved to top of layer %d", id_str, sf->layerid);
1797
1798     layer_send_surfaces(ly);
1799
1800     return true;
1801 }
1802
1803 static bool layer_remove_surface(ctrl_layer_t *ly, ctrl_surface_t *sf)
1804 {
1805     uint32_t *pos;
1806     bool removed;
1807     char id_str[256];
1808
1809     MRP_ASSERT(ly && sf, "invalid argument");
1810     MRP_ASSERT(ly->id == sf->layerid, "mismatching layer ID's");
1811
1812     surface_id_print(sf->id, id_str, sizeof(id_str));
1813     removed = false;
1814
1815     wl_array_for_each(pos, &ly->surfaces) {
1816         if (pos[0] == (uint32_t)sf->id)
1817             removed = true;
1818         else if (removed)
1819             pos[-1] = pos[0];
1820     }
1821
1822     if (!removed) {
1823         mrp_debug("failed to remove surface %s from layer %d "
1824                   "(can't find surface)", id_str, sf->layerid);
1825         return false;
1826     }
1827
1828     ly->surfaces.size -= sizeof(uint32_t);
1829
1830     mrp_debug("surface %s removed from layer %d", id_str, sf->layerid);
1831
1832     mrp_debug("calling ivi_controller_layer_remove_surface"
1833               "(ivi_controller_layer=%p, surface=%p)",
1834               ly->ctrl_layer, sf->ctrl_surface);
1835     ivi_controller_layer_remove_surface(ly->ctrl_layer, sf->ctrl_surface);
1836
1837     layer_send_surfaces(ly);
1838
1839     return true;
1840 }
1841
1842 static void layer_send_surfaces(ctrl_layer_t *ly)
1843 {
1844     uint32_t *id_ptr;
1845     char *p, *e, *s;
1846     char buf[8192];
1847
1848     e = (p = buf) + sizeof(buf);
1849     s = "";
1850
1851     wl_array_for_each(id_ptr, &ly->surfaces) {
1852         if (p >= e)
1853             break;
1854         else {
1855             p += snprintf(p, e-p, "%s%u", s, *id_ptr);
1856             s  = ", ";
1857         }
1858     }
1859
1860     mrp_debug("calling ivi_controller_layer_set_render_order"
1861               "(ivi_controller_layer=%p, id_surfaces=[%s])",
1862               ly->ctrl_layer, buf);
1863
1864     ivi_controller_layer_set_render_order(ly->ctrl_layer, &ly->surfaces);
1865 }
1866
1867
1868 static bool application_manager_constructor(mrp_wayland_t *wl,
1869                                             mrp_wayland_object_t *obj)
1870 {
1871     static struct ivi_application_listener listener =  {
1872         .wl_shell_info = shell_info_callback
1873     };
1874
1875     application_t *app = (application_t *)obj;
1876     mrp_glm_window_manager_t *wm;
1877     int sts;
1878
1879     MRP_ASSERT(wl && app, "invalid argument");
1880
1881     sts = ivi_application_add_listener((struct ivi_application *)app->proxy,
1882                                        &listener, app);
1883     if (sts < 0)
1884         return false;
1885
1886     if ((wm = (mrp_glm_window_manager_t *)wl->wm)) {
1887         mrp_debug("registering application interface to window manager");
1888         wm->app = app;
1889     }
1890
1891     return true;
1892 }
1893
1894 static void shell_info_callback(void *data,
1895                                 struct ivi_application *ivi_application,
1896                                 int32_t pid,
1897                                 const char *title,
1898                                 uint32_t id_surface)
1899 {
1900     application_t *app = (application_t *)data;
1901     mrp_wayland_t *wl;
1902     mrp_glm_window_manager_t *wm;
1903     ctrl_surface_t *sf;
1904     mrp_list_hook_t *c, *n;
1905     constructor_t *entry, *found;
1906     constructor_state_t state;
1907     bool has_title;
1908     char buf[256];
1909
1910     MRP_ASSERT(pid > 0 && title, "invalid argument");
1911     MRP_ASSERT(app && app->interface && app->interface->wl,"invalid argument");
1912     MRP_ASSERT(ivi_application == (struct ivi_application *)app->proxy,
1913                "confused with data structures");
1914
1915     wl = app->interface->wl;
1916
1917     mrp_debug("pid=%d title='%s' id_surface=%s",
1918               pid, title ? title : "<null>",
1919               surface_id_print(id_surface, buf, sizeof(buf)));
1920
1921     if (!(wm = (mrp_glm_window_manager_t *)wl->wm)) {
1922         mrp_debug("controller interface is not ready");
1923         return;
1924     }
1925
1926     has_title = (title && title[0]);
1927
1928     if (!id_surface) {
1929         /* no surface ID */
1930
1931         if (!has_title)
1932             constructor_create(wm, CONSTRUCTOR_INCOMPLETE, pid, NULL, 0);
1933         else {
1934             /* try to find an incomplete constructor with a matching pid */
1935             found = NULL;
1936
1937             mrp_list_foreach(&wm->constructors, c, n) {
1938                 entry = mrp_list_entry(c, constructor_t, link);
1939
1940                 if (pid == entry->pid) {
1941                     if ((entry->state == CONSTRUCTOR_INCOMPLETE) ||
1942                         (entry->state == CONSTRUCTOR_TITLED &&
1943                          !strcmp(title, entry->title)          )  )
1944                     {
1945                         found = entry;
1946                         break;
1947                     }
1948                 }
1949             }
1950
1951             if (!found)
1952                 constructor_create(wm, CONSTRUCTOR_TITLED, pid, title, 0);
1953             else
1954                 constructor_set_title(wm, found, title);
1955         }
1956     }
1957     else {
1958         /* we have a surface ID */
1959
1960         if (!(sf = surface_find(wm, id_surface))) {
1961             /* no surface found with the ID */
1962
1963             /* try to find a matching constructor */
1964             found = constructor_find_surface(wm, id_surface, pid, title);
1965
1966             if (!found) {
1967                 if (has_title)
1968                     state = CONSTRUCTOR_TITLED;
1969                 else
1970                     state = CONSTRUCTOR_INCOMPLETE;
1971
1972                 constructor_create(wm, state, pid, title, id_surface);
1973             }
1974             else {
1975                 if (id_surface > 0) {
1976                     /* found a constructor with the ID */
1977                     if (pid != found->pid) {
1978                         mrp_log_error("system-controller: confused with "
1979                                       "surface constructors "
1980                                       "(mismatching PIDs: %d vs. %d)",
1981                                       pid, found->pid);
1982                     }
1983                     else {
1984                         if (has_title)
1985                             constructor_set_title(wm, found, title);
1986                     }
1987                 }
1988                 else {
1989                     mrp_debug("found a constructor with matching pid/title. "
1990                               "Updating it ...");
1991
1992                     found->id_surface = id_surface;
1993
1994                     if (found->timer.surfaceless) {
1995                         mrp_del_timer(found->timer.surfaceless);
1996                         found->timer.surfaceless = NULL;
1997                     }
1998
1999                     if (has_title)
2000                         constructor_set_title(wm, found, title);
2001                 }
2002             }
2003         }
2004         else {
2005             /* found a surface with the ID */
2006             if (pid != sf->pid) {
2007                 mrp_log_error("system-controller: confused with control "
2008                               "surfaces (mismatching PIDs: %d vs. %d)",
2009                               pid, sf->pid);
2010             }
2011             else {
2012                 if (has_title)
2013                     surface_set_title(wm, sf, title);
2014             }
2015         }
2016     }
2017 }
2018
2019
2020 static bool ico_extension_constructor(mrp_wayland_t *wl,
2021                                       mrp_wayland_object_t *obj)
2022 {
2023     static struct ico_window_mgr_listener listener =  {
2024         .window_active   = ico_extension_window_active_callback,
2025         .map_surface     = ico_extension_map_surface_callback,
2026         .update_surface  = ico_extension_update_surface_callback,
2027         .destroy_surface = ico_extension_destroy_surface_callback
2028     };
2029
2030     ico_extension_t *ico = (ico_extension_t *)obj;
2031     mrp_glm_window_manager_t *wm;
2032     int sts;
2033
2034     if (!(wm = (mrp_glm_window_manager_t *)(wl->wm))) {
2035         mrp_log_error("system-controller: phase error in %s(): "
2036                       "window manager does not exist", __FUNCTION__);
2037         return false;
2038     }
2039
2040     sts = ico_window_mgr_add_listener((struct ico_window_mgr *)ico->proxy,
2041                                       &listener, ico);
2042     if (sts < 0)
2043         return false;
2044
2045     wm->ico = ico;
2046
2047     return true;
2048 }
2049
2050
2051 static void ico_extension_window_active_callback(void *data,
2052                               struct ico_window_mgr *ico_window_mgr,
2053                               uint32_t surfaceid,
2054                               int32_t select)
2055 {
2056     ico_extension_t *ico = (ico_extension_t *)data;
2057     mrp_wayland_t *wl;
2058     mrp_glm_window_manager_t *wm;
2059     ctrl_surface_t *sf;
2060     mrp_wayland_window_t *win;
2061     mrp_wayland_window_update_t u;
2062     char id_str[256];
2063
2064     MRP_ASSERT(ico && ico->interface && ico->interface->wl,
2065                "invalid argument");
2066     MRP_ASSERT(ico_window_mgr == (struct ico_window_mgr *)ico->proxy,
2067                "confused with data structures");
2068
2069     wl = ico->interface->wl;
2070     wm = (mrp_glm_window_manager_t *)(wl->wm);
2071
2072     MRP_ASSERT(wm, "data inconsitency");
2073
2074     mrp_debug("surfaceid=%u select=%d", surfaceid, select);
2075
2076     if (!select) {
2077         mrp_debug("ignoring select=0 events");
2078         return;
2079     }
2080
2081     surface_id_print(surfaceid, id_str, sizeof(id_str));
2082
2083     if (!(sf = surface_find(wm, surfaceid))) {
2084         mrp_debug("can't find surface for id=%s", id_str);
2085         return;
2086     }
2087
2088     if (!(win = sf->win)) {
2089         mrp_debug("can't forward selection event for surface id=%s "
2090                   "(no window)", id_str);
2091         return;
2092     }
2093
2094     memset(&u, 0, sizeof(u));
2095     u.mask = MRP_WAYLAND_WINDOW_ACTIVE_MASK;
2096     u.active = 0;
2097
2098     if ((select & ICO_WINDOW_MGR_SELECT_POINTER))
2099         u.active |= MRP_WAYLAND_WINDOW_ACTIVE_POINTER;
2100     if ((select & ICO_WINDOW_MGR_SELECT_TOUCH))
2101         u.active |= MRP_WAYLAND_WINDOW_ACTIVE_TOUCH;
2102
2103     mrp_wayland_window_update(win, MRP_WAYLAND_WINDOW_ACTIVE, &u);
2104 }
2105
2106
2107 static void ico_extension_map_surface_callback(void *data,
2108                               struct ico_window_mgr *ico_window_mgr,
2109                               int32_t event,
2110                               uint32_t surfaceid,
2111                               uint32_t type,
2112                               int32_t width,
2113                               int32_t height,
2114                               int32_t stride,
2115                               uint32_t format)
2116 {
2117     ico_extension_t *ico = (ico_extension_t *)data;
2118     mrp_wayland_t *wl;
2119     mrp_glm_window_manager_t *wm;
2120     ctrl_surface_t *sf;
2121     mrp_wayland_window_t *win;
2122     mrp_wayland_window_update_t u;
2123     mrp_wayland_window_map_t map;
2124     char id_str[256];
2125
2126     MRP_ASSERT(ico && ico->interface && ico->interface->wl,
2127                "invalid argument");
2128     MRP_ASSERT(ico_window_mgr == (struct ico_window_mgr *)ico->proxy,
2129                "confused with data structures");
2130
2131     wl = ico->interface->wl;
2132     wm = (mrp_glm_window_manager_t *)(wl->wm);
2133
2134     MRP_ASSERT(wm, "data inconsitency");
2135
2136     mrp_debug("event=%d surfaceid=%u type=%u width=%d height=%d stride=%d "
2137               "format=%u",
2138               event, surfaceid, type, width,height, stride, format);
2139
2140     surface_id_print(surfaceid, id_str, sizeof(id_str));
2141
2142     if (!(sf = surface_find(wm, surfaceid))) {
2143         mrp_debug("can't find surface for id=%s", id_str);
2144         return;
2145     }
2146
2147     if (!(win = sf->win)) {
2148         mrp_debug("can't forward map event for surface id=%s "
2149                   "(no window)", id_str);
2150         return;
2151     }
2152
2153     memset(&map, 0, sizeof(map));
2154     map.type = type;
2155     map.width = width;
2156     map.height = height;
2157     map.stride = stride;
2158     map.format = format;
2159
2160     memset(&u, 0, sizeof(u));
2161     u.mask = MRP_WAYLAND_WINDOW_MAPPED_MASK | MRP_WAYLAND_WINDOW_MAP_MASK;
2162     u.map  = &map;
2163
2164     switch (event)  {
2165
2166     case ICO_WINDOW_MGR_MAP_SURFACE_EVENT_CONTENTS:
2167     case ICO_WINDOW_MGR_MAP_SURFACE_EVENT_RESIZE:
2168     case ICO_WINDOW_MGR_MAP_SURFACE_EVENT_MAP:
2169         u.mapped = true;
2170         break;
2171
2172     case ICO_WINDOW_MGR_MAP_SURFACE_EVENT_UNMAP:
2173     case ICO_WINDOW_MGR_MAP_SURFACE_EVENT_ERROR:
2174         u.mapped = false;
2175         break;
2176
2177     default:
2178         mrp_debug("ignoring unknown event type %d event", event);
2179         return;
2180     }
2181
2182     mrp_wayland_window_update(win, MRP_WAYLAND_WINDOW_MAP, &u);
2183 }
2184
2185 static void ico_extension_update_surface_callback(void *data,
2186                               struct ico_window_mgr *ico_window_mgr,
2187                               uint32_t surfaceid,
2188                               int32_t visible,
2189                               int32_t srcwidth,
2190                               int32_t srcheight,
2191                               int32_t x,
2192                               int32_t y,
2193                               int32_t width,
2194                               int32_t height)
2195 {
2196     ico_extension_t *ico = (ico_extension_t *)data;
2197     mrp_wayland_t *wl;
2198     mrp_glm_window_manager_t *wm;
2199
2200     MRP_ASSERT(ico && ico->interface && ico->interface->wl,
2201                "invalid argument");
2202     MRP_ASSERT(ico_window_mgr == (struct ico_window_mgr *)ico->proxy,
2203                "confused with data structures");
2204
2205     wl = ico->interface->wl;
2206     wm = (mrp_glm_window_manager_t *)(wl->wm);
2207
2208     MRP_ASSERT(wm, "data inconsitency");
2209
2210     mrp_debug("surfaceid=%u visible=%d srcwidth=%d srcheight=%d x=%d y=%d "
2211               "width=%d height=%d",
2212               surfaceid, visible, srcwidth,srcheight, x,y, width,height);
2213 }
2214
2215
2216 static void ico_extension_destroy_surface_callback(void *data,
2217                                struct ico_window_mgr *ico_window_mgr,
2218                                uint32_t surfaceid)
2219 {
2220     ico_extension_t *ico = (ico_extension_t *)data;
2221     mrp_wayland_t *wl;
2222     mrp_glm_window_manager_t *wm;
2223
2224     MRP_ASSERT(ico && ico->interface && ico->interface->wl,
2225                "invalid argument");
2226     MRP_ASSERT(ico_window_mgr == (struct ico_window_mgr *)ico->proxy,
2227                "confused with data structures");
2228
2229     wl = ico->interface->wl;
2230     wm = (mrp_glm_window_manager_t *)(wl->wm);
2231
2232     MRP_ASSERT(wm, "data inconsitency");
2233
2234     mrp_debug("surfaceid=%u", surfaceid);
2235 }
2236
2237
2238
2239
2240 static uint32_t surface_id_generate(void)
2241 {
2242 #define FIRST_ID   (SURFACE_ID_OUR_FLAG | 1)
2243 #define MAX_ID     (SURFACE_ID_OUR_FLAG | SURFACE_ID_MAX)
2244
2245     static uint32_t id = FIRST_ID;
2246
2247     if (id >= MAX_ID)
2248         id = FIRST_ID;
2249
2250     return id++;
2251
2252 #undef MAX_ID
2253 #undef FIRST_ID
2254 }
2255
2256 static bool surface_id_is_ours(uint32_t id)
2257 {
2258     return ((id & SURFACE_ID_OUR_FLAG) == SURFACE_ID_OUR_FLAG) ? true : false;
2259 }
2260
2261 static char *surface_id_print(uint32_t id, char *buf, size_t len)
2262 {
2263     if (!id)
2264         snprintf(buf, len, "<not set>");
2265     else {
2266         snprintf(buf, len, "%u(%s-id-%u)", id,
2267                  surface_id_is_ours(id) ? "our":"native",
2268                  (id & SURFACE_ID_MAX));
2269     }
2270
2271     return buf;
2272 }
2273
2274 static constructor_t *constructor_create(mrp_glm_window_manager_t *wm,
2275                                          constructor_state_t state,
2276                                          int32_t pid,
2277                                          const char *title,
2278                                          uint32_t id_surface)
2279 {
2280     mrp_wayland_t *wl;
2281     constructor_t *c;
2282     char buf[256];
2283
2284     MRP_ASSERT(wm && wm->interface && wm->interface->wl, "invalid argument");
2285
2286     wl = wm->interface->wl;
2287
2288     if (!(c = mrp_allocz(sizeof(constructor_t)))) {
2289         mrp_log_error("system-controller: can't allocate memory for surface"
2290                       "(pid=%d title='%s' id_surface=%s)",
2291                       pid, title ? title : "<null>",
2292                       surface_id_print(id_surface, buf, sizeof(buf)));
2293         return NULL;
2294     }
2295
2296     mrp_list_init(&c->link);
2297     c->wm = wm;
2298     c->state = state;
2299     c->pid = pid;
2300     c->title = title ? mrp_strdup(title) : NULL;
2301     c->id_surface = id_surface;
2302     c->timer.timeout = mrp_add_timer(wl->ml, CONSTRUCTOR_TIMEOUT,
2303                                      constructor_timeout, c);
2304
2305     if (!id_surface) {
2306         c->timer.surfaceless = mrp_add_timer(wl->ml, SURFACELESS_TIMEOUT,
2307                                              constructor_surfaceless, c);
2308     }
2309
2310     mrp_list_append(&wm->constructors, &c->link);
2311
2312     mrp_debug("constructor created (state=%s, pid=%d, title='%s' "
2313               "id_surface=%u)", constructor_state_str(state), pid,
2314               title ? title: "<null>", id_surface);
2315
2316     return c;
2317 }
2318
2319 static void constructor_destroy(constructor_t *c)
2320 {
2321     char buf[256];
2322
2323     if (c) {
2324         mrp_debug("surface %s of application (pid=%d) destroyed",
2325                   surface_id_print(c->id_surface, buf, sizeof(buf)), c->pid);
2326
2327         mrp_del_timer(c->timer.timeout);
2328         mrp_del_timer(c->timer.surfaceless);
2329
2330         mrp_list_delete(&c->link);
2331         mrp_free(c->title);
2332
2333         mrp_free(c);
2334     }
2335 }
2336
2337 static void constructor_timeout(mrp_timer_t *timer, void *user_data)
2338 {
2339     constructor_t *c = (constructor_t *)user_data;
2340     mrp_glm_window_manager_t *wm;
2341     char buf[256];
2342
2343     MRP_ASSERT(timer && c && c->wm, "invalid argument");
2344     MRP_ASSERT(timer == c->timer.timeout, "confused with data structures");
2345
2346     mrp_debug("pid=%d title='%s' id_surface=%s state=%s",
2347               c->pid, c->title ? c->title : "",
2348               surface_id_print(c->id_surface, buf, sizeof(buf)),
2349               constructor_state_str(c->state));
2350
2351     wm = c->wm;
2352
2353     constructor_destroy(c);
2354     constructor_issue_next_request(wm);
2355 }
2356
2357 static void constructor_surfaceless(mrp_timer_t *timer, void *user_data)
2358 {
2359     constructor_t *c = (constructor_t *)user_data;
2360     mrp_glm_window_manager_t *wm;
2361
2362     MRP_ASSERT(timer && c && c->wm, "invalid argument");
2363     MRP_ASSERT(timer == c->timer.surfaceless, "confused with data structures");
2364
2365     mrp_debug("pid=%d title='%s' state=%s",
2366               c->pid, c->title ? c->title : "<not set>",
2367               constructor_state_str(c->state));
2368
2369     wm = c->wm;
2370
2371     mrp_del_timer(c->timer.surfaceless);
2372     c->timer.surfaceless = NULL;
2373
2374     c->state = CONSTRUCTOR_SURFACELESS;
2375     constructor_issue_next_request(wm);
2376 }
2377
2378 static constructor_t *constructor_find_first(mrp_glm_window_manager_t *wm,
2379                                              match_t match,
2380                                              constructor_state_t state)
2381 {
2382     mrp_list_hook_t *c, *n;
2383     constructor_t *entry;
2384
2385     mrp_list_foreach(&wm->constructors, c, n) {
2386         entry = mrp_list_entry(c, constructor_t, link);
2387
2388         if (( match && state == entry->state) ||
2389             (!match && state != entry->state))
2390             return entry;
2391     }
2392
2393     return NULL;
2394 }
2395
2396 static constructor_t *constructor_find_surface(mrp_glm_window_manager_t *wm,
2397                                                uint32_t id_surface,
2398                                                int32_t pid,
2399                                                const char *title)
2400 {
2401     mrp_list_hook_t *c, *n;
2402     constructor_t *entry, *candidate;
2403     bool candidate_titleless;
2404
2405     candidate = NULL;
2406     candidate_titleless = false;
2407
2408     mrp_list_foreach(&wm->constructors, c, n) {
2409         entry = mrp_list_entry(c, constructor_t, link);
2410
2411         if (id_surface > 0) {
2412             if (id_surface == entry->id_surface)
2413                 return entry;
2414         }
2415
2416         if (pid == entry->pid) {
2417             if (entry->state == CONSTRUCTOR_INCOMPLETE) {
2418                 if (!title && !candidate)
2419                     candidate = entry;
2420             }
2421             else {
2422                 if (title && !strcmp(title, entry->title)) {
2423                     if (!candidate || !candidate_titleless) {
2424                         candidate = entry;
2425                         candidate_titleless = false;
2426                     }
2427                 }
2428             }
2429         }
2430     }
2431
2432     return candidate;
2433 }
2434
2435 #if 0
2436 static constructor_t *constructor_find_bound(mrp_glm_window_manager_t *wm,
2437                                              uint32_t id_surface)
2438 {
2439     mrp_list_hook_t *c, *n;
2440     constructor_t *entry;
2441
2442     if (id_surface > 0) {
2443         mrp_list_foreach(&wm->constructors, c, n) {
2444             entry = mrp_list_entry(c, constructor_t, link);
2445
2446             if (id_surface == entry->id_surface &&
2447                 entry->state == CONSTRUCTOR_BOUND)
2448                 return entry;
2449         }
2450     }
2451
2452     return NULL;
2453 }
2454 #endif
2455
2456 static void constructor_set_title(mrp_glm_window_manager_t *wm,
2457                                   constructor_t *c,
2458                                   const char *title)
2459 {
2460     (void)wm;
2461
2462     if (title && title[0]) {
2463         mrp_free((void *)c->title);
2464         c->title = title ? mrp_strdup(title) : NULL;
2465
2466         mrp_debug("constructor title changed to '%s'", c->title);
2467
2468         if (c->state == CONSTRUCTOR_INCOMPLETE) {
2469             c->state = CONSTRUCTOR_TITLED;
2470             mrp_debug("constructor state changed to %s",
2471                       constructor_state_str(c->state));
2472         }
2473     }
2474 }
2475
2476 static void constructor_issue_next_request(mrp_glm_window_manager_t *wm)
2477 {
2478     mrp_list_hook_t *c, *n;
2479     constructor_t *entry;
2480
2481     mrp_debug("loop through constructors ...");
2482
2483     mrp_list_foreach(&wm->constructors, c, n) {
2484         entry = mrp_list_entry(c, constructor_t, link);
2485
2486         mrp_debug("   state %s", constructor_state_str(entry->state));
2487
2488         if (entry->state == CONSTRUCTOR_SURFACELESS) {
2489             mrp_debug("      call ivi_controller_get_native_handle"
2490                       "(pid=%d title='%s')", entry->pid,
2491                       entry->title ? entry->title : "<not set>");
2492
2493             ivi_controller_get_native_handle((struct ivi_controller*)wm->proxy,
2494                                              entry->pid, entry->title);
2495
2496             entry->state = CONSTRUCTOR_REQUESTED;
2497
2498             mrp_wayland_flush(wm->interface->wl);
2499
2500             return;
2501         }
2502
2503         if (entry->state == CONSTRUCTOR_REQUESTED)
2504             break;
2505     }
2506
2507     mrp_debug("   do not issue native handle request");
2508 }
2509
2510 static bool constructor_bind_ivi_surface(mrp_glm_window_manager_t *wm,
2511                                          constructor_t *c)
2512 {
2513     struct ivi_surface *ivi_surface;
2514     application_t *app;
2515     char buf[256];
2516
2517     if (!wm || !(app = wm->app) || !c)
2518         return false;
2519
2520     if (!c->id_surface) {
2521         mrp_log_error("system-controller: failed to create ivi-surface "
2522                       "(id_surface is not set)");
2523         return false;
2524     }
2525
2526     if (!c->wl_surface) {
2527         mrp_log_error("system-controller: failed to create ivi-surface "
2528                       "(wl_surface not set)");
2529         return false;
2530     }
2531
2532     mrp_debug("call ivi_application_surface_create(id_surface=%s surface=%p)",
2533               surface_id_print(c->id_surface, buf,sizeof(buf)), c->wl_surface);
2534
2535     ivi_surface = ivi_application_surface_create(
2536                                       (struct ivi_application *)app->proxy,
2537                                       c->id_surface, c->wl_surface);
2538     if (!ivi_surface) {
2539         mrp_log_error("system-controller: failed to create "
2540                       "ivi-application-surface (id=%s)",
2541                       surface_id_print(c->id_surface, buf, sizeof(buf)));
2542         return false;
2543     }
2544
2545     return true;
2546 }
2547
2548 static char *constructor_state_str(constructor_state_t state)
2549 {
2550     switch (state) {
2551     case CONSTRUCTOR_FAILED:      return "failed";
2552     case CONSTRUCTOR_INCOMPLETE:  return "incomplete";
2553     case CONSTRUCTOR_TITLED:      return "titled";
2554     case CONSTRUCTOR_SURFACELESS: return "surfaceless";
2555     case CONSTRUCTOR_REQUESTED:   return "requested";
2556     case CONSTRUCTOR_BOUND:       return "bound";
2557     default:                      return "<unknown>";
2558     }
2559 }
2560
2561 static ctrl_layer_t *layer_find(mrp_glm_window_manager_t *wm, int32_t id_layer)
2562 {
2563     ctrl_layer_t *ly;
2564
2565     if (!wm || !wm->layers)
2566         ly = NULL;
2567     else
2568         ly = mrp_htbl_lookup(wm->layers, &id_layer);
2569
2570     return ly;
2571 }
2572
2573 static bool set_layer_visibility(mrp_wayland_layer_t *layer,
2574                                  mrp_wayland_layer_update_mask_t passthrough,
2575                                  mrp_wayland_layer_update_t *u)
2576 {
2577     mrp_glm_window_manager_t *wm = (mrp_glm_window_manager_t *)layer->wm;
2578     ctrl_layer_t *ly;
2579     uint32_t visibility;
2580
2581     (void)passthrough;
2582
2583     if (!(ly = layer_find(wm, layer->layerid))) {
2584         mrp_debug("can't find layer");
2585         return false;
2586     }
2587
2588     visibility = u->visible ? 1 : 0;
2589
2590     mrp_debug("call ivi_controller_layer_set_visibility"
2591               "(ivi_controller_layer=%p, visibility=%u)",
2592               ly->ctrl_layer, visibility);
2593
2594     ivi_controller_layer_set_visibility(ly->ctrl_layer, visibility);
2595
2596     return true;
2597 }
2598
2599 static void layer_request(mrp_wayland_layer_t *layer,
2600                           mrp_wayland_layer_update_t *u)
2601 {
2602     mrp_wayland_t *wl;
2603     mrp_glm_window_manager_t *wm;
2604     mrp_wayland_layer_update_mask_t mask;
2605     mrp_wayland_layer_update_mask_t passthrough;
2606     bool changed;
2607     char buf[2048];
2608
2609     MRP_ASSERT(layer && layer->wm && layer->wm->proxy &&
2610                layer->wm->interface && layer->wm->interface->wl,
2611                "invalid argument");
2612
2613     wm = (mrp_glm_window_manager_t *)layer->wm;
2614     wl = wm->interface->wl;
2615     passthrough = wm->passthrough.layer_request;
2616     mask = u->mask;
2617     changed = false;
2618
2619     mrp_wayland_layer_request_print(u, buf, sizeof(buf));
2620     mrp_debug("request for layer %d update:%s", layer->layerid, buf);
2621
2622     while (mask) {
2623         if ((mask & MRP_WAYLAND_LAYER_VISIBLE_MASK)) {
2624             changed |= set_layer_visibility(layer, passthrough, u);
2625             mask &= ~MRP_WAYLAND_LAYER_VISIBLE_MASK;
2626         }
2627         else {
2628             mask = 0;
2629         }
2630     }
2631
2632
2633     if (changed) {
2634         mrp_debug("calling ivi_controller_commit_changes()");
2635         ivi_controller_commit_changes((struct ivi_controller *)wm->proxy);
2636     }
2637
2638     mrp_wayland_flush(wl);
2639 }
2640
2641
2642 static void set_window_animation(mrp_wayland_window_t *win,
2643                                  mrp_wayland_animation_type_t type,
2644                                  mrp_wayland_animation_t *anims)
2645 {
2646     static int32_t ico_types[MRP_WAYLAND_ANIMATION_MAX] = {
2647         [MRP_WAYLAND_ANIMATION_HIDE]   = ICO_WINDOW_MGR_ANIMATION_TYPE_HIDE,
2648         [MRP_WAYLAND_ANIMATION_SHOW]   = ICO_WINDOW_MGR_ANIMATION_TYPE_SHOW,
2649         [MRP_WAYLAND_ANIMATION_MOVE]   = ICO_WINDOW_MGR_ANIMATION_TYPE_MOVE,
2650         [MRP_WAYLAND_ANIMATION_RESIZE] = ICO_WINDOW_MGR_ANIMATION_TYPE_RESIZE
2651     };
2652
2653     mrp_glm_window_manager_t *wm;
2654     ico_extension_t *ico;
2655     struct ico_window_mgr *ico_window_mgr;
2656     mrp_wayland_animation_t *a;
2657
2658     MRP_ASSERT(win && win->wm, "invalid argument");
2659
2660     wm = (mrp_glm_window_manager_t *)(win->wm);
2661     ico = wm->ico;
2662
2663     if (!ico) {
2664         mrp_debug("can't animate on window %u (ico-extension not available)",
2665                   win->surfaceid);
2666         return;
2667     }
2668
2669     ico_window_mgr = (struct ico_window_mgr *)ico->proxy;
2670
2671     if (anims && type >= 0 && type < MRP_WAYLAND_ANIMATION_MAX) {
2672         a = anims + type;
2673
2674         if (a->name && a->name[0] && a->time > 0) {
2675             mrp_debug("calling ico_window_mgr_set_animation"
2676                       "(surfaceid=%d type=%d, animation='%s' time=%d)",
2677                       win->surfaceid, ico_types[type], a->name, a->time);
2678
2679             ico_window_mgr_set_animation(ico_window_mgr, win->surfaceid,
2680                                          ico_types[type], a->name, a->time);
2681         }
2682     }
2683 }
2684
2685 static bool set_window_layer(mrp_wayland_window_t *win,
2686                              mrp_wayland_window_update_mask_t passthrough,
2687                              mrp_wayland_window_update_t *u)
2688 {
2689     mrp_glm_window_manager_t *wm = (mrp_glm_window_manager_t *)win->wm;
2690     int32_t id_surface;
2691     int32_t id_layer;
2692     ctrl_surface_t *sf;
2693     ctrl_layer_t *ly;
2694     bool changed;
2695     mrp_wayland_window_update_t u2;
2696     char buf[256];
2697
2698     (void)passthrough;
2699
2700     if (!u->layer) {
2701         mrp_log_error("system-controller: broken request (layer is <null>)");
2702         return false;
2703     }
2704
2705     id_surface = win->surfaceid;
2706     id_layer = u->layer->layerid;
2707
2708     if (!(sf = surface_find(wm, id_surface))) {
2709         mrp_debug("can't find surface %s",
2710                   surface_id_print(id_surface, buf, sizeof(buf)));
2711         return false;
2712     }
2713
2714     if (!(ly = layer_find(wm, id_layer))) {
2715         mrp_debug("can't find layer %d", id_layer);
2716         return false;
2717     }
2718
2719     if (sf->layerid == id_layer) {
2720         if ((u->mask & MRP_WAYLAND_WINDOW_RAISE_MASK))
2721             changed = false;
2722         else
2723             changed = layer_move_surface_to_top(ly, sf);
2724     }
2725     else {
2726         sf->layerid = id_layer;
2727         changed = layer_add_surface_to_top(ly, sf);
2728     }
2729
2730     if (changed) {
2731         memset(&u2, 0, sizeof(u2));
2732         u2.mask = MRP_WAYLAND_WINDOW_SURFACEID_MASK |
2733                   MRP_WAYLAND_WINDOW_RAISE_MASK;
2734         u2.surfaceid = win->surfaceid;
2735         u2.raise = 1;
2736
2737         mrp_wayland_window_update(win, MRP_WAYLAND_WINDOW_VISIBLE, &u2);
2738     }
2739
2740     return changed;
2741 }
2742
2743 static bool set_window_mapped(mrp_wayland_window_t *win,
2744                               mrp_wayland_window_update_mask_t passthrough,
2745                               mrp_wayland_window_update_t *u,
2746                               mrp_wayland_animation_t *anims,
2747                               uint32_t framerate)
2748 {
2749     mrp_glm_window_manager_t *wm = (mrp_glm_window_manager_t *)win->wm;
2750     ico_extension_t *ico = wm->ico;
2751     int32_t id_surface;
2752     struct ico_window_mgr *ico_window_mgr;
2753     const char *filepath;
2754     char id_str[256];
2755
2756     ico_window_mgr = ico ? (struct ico_window_mgr *)ico->proxy : NULL;
2757     id_surface = win->surfaceid;
2758
2759     surface_id_print(id_surface, id_str, sizeof(id_str));
2760
2761     if (((u->mapped && win->mapped) || (!u->mapped && !win->mapped)) &&
2762         !(passthrough & MRP_WAYLAND_WINDOW_MAPPED_MASK))
2763     {
2764         mrp_debug("nothing to do");
2765         return false;
2766     }
2767
2768     if (u->mapped) {
2769         if (!anims || !(filepath = anims[MRP_WAYLAND_ANIMATION_MAP].name)) {
2770             mrp_log_error("system-controller: broken map request "
2771                           "(no file path)");
2772             return false;
2773         }
2774
2775         if (!ico_window_mgr) {
2776             mrp_debug("can't map surface %s to file '%s' (ico-extension not "
2777                       "available)", id_str, filepath);
2778             return false;
2779         }
2780
2781         if (framerate == 0)
2782             framerate = -1;
2783
2784         mrp_debug("calling ico_window_mgr_map_surface"
2785                   "(ico_window_mgr=%p, surfaceid=%u, framerate=%d, "
2786                   "filepath='%s')",
2787                   ico_window_mgr, id_surface, framerate, filepath);
2788
2789         ico_window_mgr_map_surface(ico_window_mgr, id_surface, framerate,
2790                                    filepath);
2791     }
2792     else {
2793         if (!ico_window_mgr) {
2794             mrp_debug("can't unmap surface %s (ico-extension not available)",
2795                       id_str);
2796             return false;
2797         }
2798
2799         mrp_debug("calling ico_window_mgr_unmap_surface"
2800                   "(ico_window_mgr=%p, surfaceid=%u)",
2801                   ico_window_mgr, id_surface);
2802
2803         ico_window_mgr_unmap_surface(ico_window_mgr, id_surface);
2804     }
2805
2806     return true;
2807 }
2808
2809 static bool set_window_geometry(mrp_wayland_window_t *win,
2810                                 mrp_wayland_window_update_mask_t passthrough,
2811                                 mrp_wayland_window_update_t *u,
2812                                 mrp_wayland_animation_t *anims)
2813 {
2814     mrp_glm_window_manager_t *wm = (mrp_glm_window_manager_t *)win->wm;
2815     mrp_wayland_window_update_mask_t mask = u->mask;
2816     int32_t id_surface = win->surfaceid;
2817     bool output_changed = false;
2818     ctrl_surface_t *sf;
2819     int32_t x,y;
2820     int32_t w,h;
2821     char buf[256];
2822
2823     (void)passthrough;
2824
2825     if (!output_changed                                        &&
2826         (!(mask & MRP_WAYLAND_WINDOW_POSITION_MASK) ||
2827          (u->x == win->x && u->y == win->y)                  ) &&
2828         (!(mask & MRP_WAYLAND_WINDOW_SIZE_MASK) ||
2829          (u->width == win->width && u->height == win->height))  )
2830     {
2831         mrp_debug("nothing to do");
2832         return false;
2833     }
2834
2835     if (!(sf = surface_find(wm, id_surface))) {
2836         mrp_debug("can't find surface %s",
2837                   surface_id_print(id_surface, buf, sizeof(buf)));
2838         return false;
2839     }
2840
2841     x = (mask & MRP_WAYLAND_WINDOW_X_MASK     )  ?  u->x      : win->x;
2842     y = (mask & MRP_WAYLAND_WINDOW_Y_MASK     )  ?  u->y      : win->y;
2843     w = (mask & MRP_WAYLAND_WINDOW_WIDTH_MASK )  ?  u->width  : win->width;
2844     h = (mask & MRP_WAYLAND_WINDOW_HEIGHT_MASK)  ?  u->height : win->height;
2845
2846     if (x != win->x || y != win->y)
2847         set_window_animation(win, MRP_WAYLAND_ANIMATION_MOVE, anims);
2848     if (w != win->width || h != win->height)
2849         set_window_animation(win, MRP_WAYLAND_ANIMATION_RESIZE, anims);
2850
2851 #if 0
2852     mrp_debug("calling ivi_controller_surface_set_source_rectangle"
2853               "(ivi_controller_surface=%p, x=0, y=0, width=%d height=%d)",
2854               sf->ctrl_surface, w,h);
2855
2856     ivi_controller_surface_set_source_rectangle(sf->ctrl_surface, 0,0, w,h);
2857 #endif
2858
2859
2860     sf->requested_x = x;
2861     sf->requested_y = y;
2862     sf->requested_width = w;
2863     sf->requested_height = h;
2864
2865     mrp_debug("calling ivi_controller_surface_set_destination_rectangle"
2866               "(ivi_controller_surface=%p, x=%d, y=%d, width=%d height=%d)",
2867               sf->ctrl_surface, x,y, w,h);
2868
2869     ivi_controller_surface_set_destination_rectangle(sf->ctrl_surface,
2870                                                      x,y, w,h);
2871
2872     return true;
2873 }
2874
2875
2876 static bool set_window_opacity(mrp_wayland_window_t *win,
2877                                mrp_wayland_window_update_mask_t passthrough,
2878                                mrp_wayland_window_update_t *u)
2879 {
2880     mrp_glm_window_manager_t *wm = (mrp_glm_window_manager_t *)win->wm;
2881     int32_t id_surface = win->surfaceid;
2882     ctrl_surface_t *sf;
2883     wl_fixed_t opacity;
2884     char buf[256];
2885
2886     if (u->opacity == win->opacity &&
2887         !(passthrough & MRP_WAYLAND_WINDOW_OPACITY_MASK))
2888     {
2889         mrp_debug("nothing to do");
2890         return false;
2891     }
2892
2893     if (!(sf = surface_find(wm, id_surface))) {
2894         mrp_debug("can't find surface %s",
2895                   surface_id_print(id_surface, buf, sizeof(buf)));
2896         return false;
2897     }
2898     
2899     opacity = wl_fixed_from_double(u->opacity);
2900
2901     mrp_debug("calling ivi_controller_surface_set_opacity"
2902               "(ivi_controller_surface=%p, opacity=%d)",
2903               sf->ctrl_surface, opacity);
2904
2905     ivi_controller_surface_set_opacity(sf->ctrl_surface, opacity);
2906
2907     return true;
2908 }
2909
2910
2911 static bool raise_window(mrp_wayland_window_t *win,
2912                          mrp_wayland_window_update_mask_t passthrough,
2913                          mrp_wayland_window_update_t *u)
2914 {
2915     mrp_glm_window_manager_t *wm = (mrp_glm_window_manager_t *)win->wm;
2916     mrp_wayland_window_update_t u2;
2917     int32_t id_surface = win->surfaceid;
2918     ctrl_surface_t *sf;
2919     ctrl_layer_t *ly;
2920     bool changed;
2921     char buf[256];
2922
2923     (void)passthrough;
2924
2925     do { /* not a loop */
2926         changed = false;
2927
2928         if (((u->raise && win->raise) || (!u->raise && !win->raise))) {
2929             mrp_debug("no actual change is needed");
2930             break;
2931         }
2932
2933         if (!(sf = surface_find(wm, win->surfaceid))) {
2934             mrp_debug("can't find surface %s",
2935                       surface_id_print(id_surface, buf, sizeof(buf)));
2936             return false;
2937         }
2938
2939         if (!win->layer) {
2940             mrp_debug("layer is not set");
2941             return false;
2942         }
2943
2944         if (!(ly = layer_find(wm, win->layer->layerid))) {
2945             mrp_debug("can't find layer %d", win->layer->layerid);
2946             return false;
2947         }
2948
2949         if (u->raise)
2950             changed = layer_move_surface_to_top(ly, sf);
2951         else
2952             changed = layer_move_surface_to_bottom(ly, sf);
2953
2954     } while (0);
2955
2956
2957     memset(&u2, 0, sizeof(u2));
2958     u2.mask = MRP_WAYLAND_WINDOW_SURFACEID_MASK |
2959               MRP_WAYLAND_WINDOW_RAISE_MASK;
2960     u2.surfaceid = win->surfaceid;
2961     u2.raise = u->raise;
2962     
2963     mrp_wayland_window_update(win, MRP_WAYLAND_WINDOW_VISIBLE, &u2);
2964
2965     return changed;
2966 }
2967
2968
2969 static bool set_window_visibility(mrp_wayland_window_t *win,
2970                                  mrp_wayland_window_update_mask_t passthrough,
2971                                  mrp_wayland_window_update_t *u,
2972                                  mrp_wayland_animation_t *anims)
2973 {
2974     mrp_glm_window_manager_t *wm = (mrp_glm_window_manager_t *)win->wm;
2975     int32_t id_surface;
2976     uint32_t visibility;
2977     ctrl_surface_t *sf;
2978     mrp_wayland_animation_type_t anim_type;
2979     char buf[256];
2980
2981     if ((((u->visible && win->visible) || (!u->visible && !win->visible)) &&
2982          !(passthrough & MRP_WAYLAND_WINDOW_VISIBLE_MASK)))
2983     {
2984         mrp_debug("nothing to do");
2985         return false;
2986     }
2987
2988     id_surface = win->surfaceid;
2989     visibility = u->visible ? 1 : 0;
2990     anim_type  = visibility ? MRP_WAYLAND_ANIMATION_SHOW :
2991                               MRP_WAYLAND_ANIMATION_HIDE;
2992
2993     if (!(sf = surface_find(wm, id_surface))) {
2994         mrp_debug("can't find surface %s",
2995                   surface_id_print(id_surface, buf, sizeof(buf)));
2996         return false;
2997     }
2998
2999     set_window_animation(win, anim_type, anims);
3000
3001     mrp_debug("calling ivi_controller_surface_set_visibility"
3002               "(ivi_controller_surface=%p, visibility=%u)",
3003               sf->ctrl_surface, visibility);
3004
3005     ivi_controller_surface_set_visibility(sf->ctrl_surface, visibility);
3006
3007     return true;
3008 }
3009
3010 static bool set_window_active(mrp_wayland_window_t *win,
3011                               mrp_wayland_window_update_mask_t passthrough,
3012                               mrp_wayland_window_update_t *u)
3013 {
3014     static mrp_wayland_active_t focus_mask = MRP_WAYLAND_WINDOW_ACTIVE_POINTER|
3015                                              MRP_WAYLAND_WINDOW_ACTIVE_TOUCH  ;
3016
3017     mrp_glm_window_manager_t *wm = (mrp_glm_window_manager_t *)win->wm;
3018     int32_t id_surface = win->surfaceid;
3019     ctrl_surface_t *sf;
3020     int32_t focus_enabled;
3021     char id_str[256];
3022
3023     surface_id_print(id_surface, id_str, sizeof(id_str));
3024
3025     if (u->active == win->active &&
3026         !(passthrough & MRP_WAYLAND_WINDOW_ACTIVE_MASK))
3027     {
3028         mrp_debug("nothing to do");
3029         return false;
3030     }
3031
3032     if (!(sf = surface_find(wm, id_surface))) {
3033         mrp_debug("can't find surface %s", id_str);
3034         return false;
3035     }
3036
3037     focus_enabled = (u->active & focus_mask) ? 1 : 0;
3038
3039     mrp_debug("calling ivi_controller_surface_set_input_focus"
3040               "(struct ivi_controller_surface=%p, enabled=%d)",
3041               sf->ctrl_surface, focus_enabled);
3042
3043
3044     ivi_controller_surface_set_input_focus(sf->ctrl_surface,
3045                                       IVI_CONTROLLER_SURFACE_INPUT_DEVICE_ALL,
3046                                       focus_enabled);
3047
3048     return true;
3049 }
3050
3051 static void window_request(mrp_wayland_window_t *win,
3052                            mrp_wayland_window_update_t *u,
3053                            mrp_wayland_animation_t *anims,
3054                            uint32_t framerate)
3055 {
3056 #if 0
3057     static mrp_wayland_window_update_mask_t area_mask =
3058         MRP_WAYLAND_WINDOW_AREA_MASK;
3059 #endif
3060     static mrp_wayland_window_update_mask_t mapped_mask =
3061         MRP_WAYLAND_WINDOW_MAPPED_MASK;
3062     static mrp_wayland_window_update_mask_t geometry_mask =
3063         /* MRP_WAYLAND_WINDOW_NODEID_MASK   | */
3064         MRP_WAYLAND_WINDOW_POSITION_MASK |
3065         MRP_WAYLAND_WINDOW_SIZE_MASK     ;
3066     static mrp_wayland_window_update_mask_t opacity_mask =
3067         MRP_WAYLAND_WINDOW_OPACITY_MASK;
3068     static mrp_wayland_window_update_mask_t raise_mask =
3069         MRP_WAYLAND_WINDOW_RAISE_MASK;
3070     static mrp_wayland_window_update_mask_t layer_mask =
3071         MRP_WAYLAND_WINDOW_LAYER_MASK;
3072     static mrp_wayland_window_update_mask_t visible_mask =
3073         MRP_WAYLAND_WINDOW_VISIBLE_MASK;
3074     static mrp_wayland_window_update_mask_t active_mask =
3075         MRP_WAYLAND_WINDOW_ACTIVE_MASK;
3076
3077
3078     mrp_wayland_t *wl;
3079     mrp_glm_window_manager_t *wm;
3080     mrp_wayland_window_update_mask_t passthrough;
3081     mrp_wayland_window_update_mask_t mask;
3082     bool changed;
3083     char wbuf[2048];
3084     char abuf[1024];
3085
3086     MRP_ASSERT(win && win->wm && win->wm->proxy && win->wm->interface &&
3087                win->wm->interface->wl && u, "invalid argument");
3088
3089     wm = (mrp_glm_window_manager_t *)win->wm;
3090     wl = wm->interface->wl;
3091     passthrough = wm->passthrough.window_request;
3092     mask = u->mask;
3093     changed = false;
3094
3095     mrp_wayland_window_request_print(u, wbuf, sizeof(wbuf));
3096     mrp_wayland_animation_print(anims, abuf, sizeof(abuf));
3097     mrp_debug("request for window %d update:%s\n   animations:%s",
3098               win->surfaceid, wbuf, abuf);
3099
3100     while (mask) {
3101         if ((mask & layer_mask)) {
3102             changed |= set_window_layer(win, passthrough, u);
3103             mask &= ~layer_mask;
3104         }
3105         else if ((mask & mapped_mask))  {
3106             changed |= set_window_mapped(win, passthrough, u,
3107                                          anims, framerate);
3108             mask &= ~(mapped_mask);
3109         }
3110 #if 0
3111         else if ((mask & area_mask))  {
3112             changed |= set_window_area(win, passthrough, u, anims);
3113             mask &= ~(area_mask | geometry_mask);
3114         }
3115 #endif
3116         else if ((mask & geometry_mask)) {
3117             changed |= set_window_geometry(win, passthrough, u, anims);
3118             mask &= ~geometry_mask;
3119         }
3120         else if ((mask & opacity_mask)) {
3121             changed |= set_window_opacity(win, passthrough, u);
3122             mask &= ~opacity_mask;
3123         }
3124         else if ((mask & raise_mask)) {
3125             changed |= raise_window(win, passthrough, u);
3126             mask &= ~raise_mask;
3127         }
3128         else if ((mask & visible_mask)) {
3129             changed |= set_window_visibility(win, passthrough, u, anims);
3130             mask &= ~visible_mask;
3131         }
3132         else if ((mask & active_mask)) {
3133             changed |= set_window_active(win, passthrough, u);
3134             mask &= ~active_mask;
3135         }
3136         else {
3137             mask = 0;
3138         }
3139     }
3140
3141     if (changed) {
3142         mrp_debug("calling ivi_controller_commit_changes()");
3143         ivi_controller_commit_changes((struct ivi_controller *)wm->proxy);
3144     }
3145
3146     mrp_wayland_flush(wl);
3147 }
3148
3149
3150 static void buffer_request(mrp_wayland_window_manager_t *wm,
3151                            const char *shmname,
3152                            uint32_t bufsize,
3153                            uint32_t bufnum)
3154 {
3155     (void)bufnum;
3156     (void)bufsize;
3157
3158     MRP_ASSERT(wm && wm->proxy && shmname, "invalid argument");
3159
3160     mrp_log_warning("system-controller: buffer_request is not supported in "
3161                     "Genivi Layer Management");
3162 }
3163
3164
3165 static uint32_t sid_hash(const void *pkey)
3166 {
3167     uint32_t key = *(uint32_t *)pkey;
3168
3169     return key % MRP_WAYLAND_WINDOW_BUCKETS;
3170 }
3171
3172 static uint32_t lid_hash(const void *pkey)
3173 {
3174     uint32_t key = *(uint32_t *)pkey;
3175
3176     return key % MRP_WAYLAND_LAYER_BUCKETS;
3177 }
3178
3179
3180 static uint32_t oid_hash(const void *pkey)
3181 {
3182     uint32_t key = *(uint32_t *)pkey;
3183
3184     return key % MRP_WAYLAND_OUTPUT_BUCKETS;
3185 }
3186
3187
3188 static int id_compare(const void *pkey1, const void *pkey2)
3189 {
3190     int32_t key1 = *(int32_t *)pkey1;
3191     int32_t key2 = *(int32_t *)pkey2;
3192
3193     return (key1 == key2) ? 0 : ((key1 < key2) ? -1 : 1);
3194 }
3195
3196 static int32_t get_parent_pid(int32_t pid)
3197 {
3198     int fd;
3199     char path[256];
3200     char buf[1024];
3201     ssize_t size;
3202     char *ppid_line, *c, *e;
3203     int32_t ppid;
3204
3205     snprintf(path, sizeof(path), "/proc/%d/status", pid);
3206
3207     if ((fd = open(path, O_RDONLY)) < 0)
3208         return -1;
3209
3210     while ((size = read(fd, buf, sizeof(buf)-1)) <= 0) {
3211         if (errno != EINTR) {
3212             close(fd);
3213             return -1;
3214         }
3215     }
3216
3217     close(fd);
3218
3219     buf[size] = 0;
3220
3221     if ((ppid_line = strstr(buf, "PPid:"))) {
3222         for (c = ppid_line + 5; (*c == ' ' || *c == '\t');  c++)
3223             ;
3224
3225         if ((ppid = strtol(c, &e, 10)) > 0 && e > c && *e == '\n')
3226             return ppid;
3227     }
3228
3229     return -1;
3230 }
3231
3232 static void get_binary_basename(int32_t pid, char *buf, int len)
3233 {
3234     int fd;
3235     char path[256];
3236     char cmdline[1024];
3237     char *bnam;
3238     ssize_t size;
3239
3240     snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
3241
3242     buf[0] = 0;
3243
3244     if ((fd = open(path, O_RDONLY)) < 0)
3245         return;
3246
3247     while ((size = read(fd, cmdline, sizeof(cmdline))) <= 0) {
3248         if (errno != EINTR) {
3249             close(fd);
3250             return;
3251         }
3252     }
3253
3254     close(fd);
3255
3256     cmdline[size] = 0;
3257     bnam = basename(cmdline);
3258
3259     strncpy(buf, bnam, len-1);
3260     buf[len-1] = 0;
3261 }
3262
3263 static void get_appid(int32_t pid, char *buf, int len)
3264 {
3265     int ppid;
3266
3267     if (!buf || len < 2)
3268         return;
3269
3270     buf[0] = 0;
3271
3272     if ((ppid = pid) > 0) {
3273         while (aul_app_get_appid_bypid(ppid, buf, len) != AUL_R_OK) {
3274             if ((ppid = get_parent_pid(ppid)) <= 1) {
3275                 get_binary_basename(pid, buf, len);
3276                 break;
3277             }
3278         }
3279     }
3280 }