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