2e27742cd4c2658b7f09d1675fe6c482c7ee9698
[src/agl-compositor.git] / src / shell.c
1 /*
2  * Copyright © 2019, 2022 Collabora, Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sublicense, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial
14  * portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  */
25
26 #include "ivi-compositor.h"
27 #include "policy.h"
28
29 #include <assert.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <signal.h>
33 #include <string.h>
34 #include <sys/socket.h>
35 #include <sys/types.h>
36 #include <sys/wait.h>
37 #include <unistd.h>
38 #include <libweston/libweston.h>
39 #include <libweston/config-parser.h>
40
41 #include <weston.h>
42 #include "shared/os-compatibility.h"
43 #include "shared/helpers.h"
44 #include "shared/process-util.h"
45
46 #include "agl-shell-server-protocol.h"
47 #include "agl-shell-desktop-server-protocol.h"
48
49 static void
50 create_black_curtain_view(struct ivi_output *output);
51
52 static uint32_t
53 reverse_orientation(uint32_t orientation);
54
55 const char *
56 split_orientation_to_string(uint32_t orientation);
57
58 void
59 agl_shell_desktop_advertise_application_id(struct ivi_compositor *ivi,
60                                            struct ivi_surface *surface)
61 {
62         struct desktop_client *dclient;
63         static bool display_adv = false;
64
65         if (surface->advertised_on_launch)
66                 return;
67
68         /* advertise to all desktop clients the new surface */
69         wl_list_for_each(dclient, &ivi->desktop_clients, link) {
70                 const char *app_id =
71                         weston_desktop_surface_get_app_id(surface->dsurface);
72                 if (app_id == NULL) {
73                         if (!display_adv) {
74                                 weston_log("WARNING app_is is null, unable to advertise\n");
75                                 display_adv = true;
76                         }
77                         return;
78                 }
79                 agl_shell_desktop_send_application(dclient->resource, app_id);
80                 surface->advertised_on_launch = true;
81         }
82 }
83
84 void
85 ivi_set_desktop_surface(struct ivi_surface *surface)
86 {
87         struct ivi_compositor *ivi = surface->ivi;
88         assert(surface->role == IVI_SURFACE_ROLE_NONE);
89
90         surface->role = IVI_SURFACE_ROLE_DESKTOP;
91         wl_list_insert(&surface->ivi->surfaces, &surface->link);
92
93         agl_shell_desktop_advertise_application_id(ivi, surface);
94 }
95
96 static void
97 ivi_set_background_surface(struct ivi_surface *surface)
98 {
99         struct ivi_compositor *ivi = surface->ivi;
100         assert(surface->role == IVI_SURFACE_ROLE_BACKGROUND);
101
102         wl_list_insert(&surface->ivi->surfaces, &surface->link);
103         agl_shell_desktop_advertise_application_id(ivi, surface);
104 }
105
106 static void
107 ivi_set_desktop_surface_popup(struct ivi_surface *surface)
108 {
109         struct ivi_compositor *ivi = surface->ivi;
110         assert(surface->role == IVI_SURFACE_ROLE_NONE);
111
112         surface->role = IVI_SURFACE_ROLE_POPUP;
113         wl_list_insert(&ivi->surfaces, &surface->link);
114
115         agl_shell_desktop_advertise_application_id(ivi, surface);
116 }
117
118 static void
119 ivi_set_desktop_surface_fullscreen(struct ivi_surface *surface)
120 {
121         struct ivi_compositor *ivi = surface->ivi;
122         assert(surface->role == IVI_SURFACE_ROLE_NONE);
123
124         surface->role = IVI_SURFACE_ROLE_FULLSCREEN;
125         wl_list_insert(&ivi->surfaces, &surface->link);
126
127         agl_shell_desktop_advertise_application_id(ivi, surface);
128 }
129
130 static void
131 ivi_set_desktop_surface_remote(struct ivi_surface *surface)
132 {
133         struct ivi_compositor *ivi = surface->ivi;
134         struct weston_view *view;
135         struct ivi_output *output = surface->remote.output;
136
137         assert(surface->role == IVI_SURFACE_ROLE_NONE);
138
139         /* remote type are the same as desktop just that client can tell
140          * the compositor to start on another output */
141         surface->role = IVI_SURFACE_ROLE_REMOTE;
142
143         /* if thew black surface view is mapped on the mean we need
144          * to remove it in order to start showing the 'remote' surface
145          * just being added */
146         view = output->fullscreen_view.fs->view;
147         if (view->is_mapped || view->surface->is_mapped)
148                 remove_black_curtain(output);
149
150         wl_list_insert(&ivi->surfaces, &surface->link);
151 }
152
153
154 static void
155 ivi_set_desktop_surface_split(struct ivi_surface *surface)
156 {
157         struct ivi_compositor *ivi = surface->ivi;
158         assert(surface->role == IVI_SURFACE_ROLE_NONE);
159
160         if (surface->split.orientation == AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL)
161                 surface->role = IVI_SURFACE_ROLE_SPLIT_V;
162         else
163                 surface->role = IVI_SURFACE_ROLE_SPLIT_H;
164
165         wl_list_insert(&ivi->surfaces, &surface->link);
166
167         agl_shell_desktop_advertise_application_id(ivi, surface);
168 }
169
170 static struct pending_popup *
171 ivi_ensure_popup(struct ivi_output *ioutput, int x, int y, int bx, int by,
172                  int width, int height, const char *app_id)
173 {
174         struct pending_popup *p_popup = zalloc(sizeof(*p_popup));
175         size_t len_app_id = strlen(app_id);
176
177         if (!p_popup)
178                 return NULL;
179         p_popup->app_id = zalloc(sizeof(char) * (len_app_id + 1));
180         if (!p_popup->app_id) {
181                 free(p_popup);
182                 return NULL;
183         }
184         memcpy(p_popup->app_id, app_id, len_app_id);
185         p_popup->ioutput = ioutput;
186         p_popup->x = x;
187         p_popup->y = y;
188
189         p_popup->bb.x = bx;
190         p_popup->bb.y = by;
191         p_popup->bb.width = width;
192         p_popup->bb.height = height;
193
194         return p_popup;
195 }
196
197 static void
198 ivi_update_popup(struct ivi_output *ioutput, int x, int y, int bx, int by,
199                  int width, int height, const char *app_id, struct pending_popup *p_popup)
200 {
201         size_t len_app_id = strlen(app_id);
202
203         wl_list_remove(&p_popup->link);
204         wl_list_init(&p_popup->link);
205
206         memset(p_popup->app_id, 0, strlen(app_id) + 1);
207         free(p_popup->app_id);
208
209         p_popup->app_id = zalloc(sizeof(char) * (len_app_id + 1));
210         if (!p_popup->app_id)
211                 return;
212         memcpy(p_popup->app_id, app_id, len_app_id);
213
214         p_popup->ioutput = ioutput;
215         p_popup->x = x;
216         p_popup->y = y;
217
218         p_popup->bb.x = bx;
219         p_popup->bb.y = by;
220         p_popup->bb.width = width;
221         p_popup->bb.height = height;
222 }
223
224 static struct pending_fullscreen *
225 ivi_ensure_fullscreen(struct ivi_output *ioutput, const char *app_id)
226 {
227         struct pending_fullscreen *p_fullscreen = zalloc(sizeof(*p_fullscreen));
228         size_t len_app_id = strlen(app_id);
229
230         if (!p_fullscreen)
231                 return NULL;
232         p_fullscreen->app_id = zalloc(sizeof(char) * (len_app_id + 1));
233         if (!p_fullscreen->app_id) {
234                 free(p_fullscreen);
235                 return NULL;
236         }
237         memcpy(p_fullscreen->app_id, app_id, len_app_id);
238
239         p_fullscreen->ioutput = ioutput;
240         return p_fullscreen;
241 }
242
243 static void
244 ivi_update_fullscreen(struct ivi_output *ioutput, const char *app_id,
245                       struct pending_fullscreen *p_fullscreen)
246 {
247         size_t len_app_id = strlen(app_id);
248
249         wl_list_remove(&p_fullscreen->link);
250         wl_list_init(&p_fullscreen->link);
251
252         memset(p_fullscreen->app_id, 0, strlen(app_id) + 1);
253         free(p_fullscreen->app_id);
254
255         p_fullscreen->app_id = zalloc(sizeof(char) * (len_app_id + 1));
256         if (!p_fullscreen->app_id)
257                 return;
258         memcpy(p_fullscreen->app_id, app_id, len_app_id);
259
260         p_fullscreen->ioutput = ioutput;
261 }
262
263 static struct pending_remote *
264 ivi_ensure_remote(struct ivi_output *ioutput, const char *app_id)
265 {
266         struct pending_remote *p_remote = zalloc(sizeof(*p_remote));
267         size_t len_app_id = strlen(app_id);
268
269         if (!p_remote)
270                 return NULL;
271         p_remote->app_id = zalloc(sizeof(char) * (len_app_id + 1));
272         if (!p_remote->app_id) {
273                 free(p_remote);
274                 return NULL;
275         }
276         memcpy(p_remote->app_id, app_id, len_app_id);
277
278         p_remote->ioutput = ioutput;
279         return p_remote;
280 }
281
282 static void
283 ivi_update_remote(struct ivi_output *ioutput, const char *app_id,
284                       struct pending_remote *p_remote)
285 {
286         size_t len_app_id = strlen(app_id);
287
288         wl_list_remove(&p_remote->link);
289         wl_list_init(&p_remote->link);
290
291         memset(p_remote->app_id, 0, strlen(app_id) + 1);
292         free(p_remote->app_id);
293
294         p_remote->app_id = zalloc(sizeof(char) * (len_app_id + 1));
295         if (!p_remote->app_id)
296                 return;
297         memcpy(p_remote->app_id, app_id, len_app_id);
298
299         p_remote->ioutput = ioutput;
300 }
301
302 static void
303 ivi_set_pending_desktop_surface_popup(struct ivi_output *ioutput, int x, int y, int bx,
304                                       int by, int width, int height, const char *app_id)
305 {
306         struct ivi_compositor *ivi = ioutput->ivi;
307         struct pending_popup *p_popup = NULL;
308         struct pending_popup *popup;
309
310         wl_list_for_each(popup, &ivi->popup_pending_apps, link)
311                 if (!strcmp(app_id, popup->app_id))
312                         p_popup = popup;
313
314         if (!p_popup)
315                 p_popup = ivi_ensure_popup(ioutput, x, y, bx, by, width, height, app_id);
316         else
317                 ivi_update_popup(ioutput, x, y, bx, by, width, height, app_id, p_popup);
318         if (!p_popup)
319                 return;
320
321         wl_list_insert(&ivi->popup_pending_apps, &p_popup->link);
322 }
323
324 static void
325 ivi_set_pending_desktop_surface_fullscreen(struct ivi_output *ioutput,
326                                            const char *app_id)
327 {
328         struct ivi_compositor *ivi = ioutput->ivi;
329         struct pending_fullscreen *p_fullscreen = NULL;
330         struct pending_fullscreen *fullscreen;
331
332         wl_list_for_each(fullscreen, &ivi->fullscreen_pending_apps, link)
333                 if (!strcmp(app_id, fullscreen->app_id))
334                         p_fullscreen = fullscreen;
335
336         if (!p_fullscreen)
337                 p_fullscreen = ivi_ensure_fullscreen(ioutput, app_id);
338         else
339                 ivi_update_fullscreen(ioutput, app_id, p_fullscreen);
340
341         if (!p_fullscreen)
342                 return;
343         wl_list_insert(&ivi->fullscreen_pending_apps, &p_fullscreen->link);
344 }
345
346 static void
347 ivi_set_pending_desktop_surface_split(struct ivi_output *ioutput,
348                                       const char *app_id, uint32_t orientation)
349 {
350         struct ivi_compositor *ivi = ioutput->ivi;
351         struct ivi_surface *surf;
352         size_t len_app_id = strlen(app_id);
353         struct pending_split *split;
354
355         if (orientation != AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL &&
356             orientation != AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_HORIZONTAL)
357                 return;
358
359         /* more than one is un-supported, do note we need to do
360          * conversion for surface roles instead of using the protocol ones */
361         wl_list_for_each(surf, &ivi->surfaces, link)
362                 if (surf->role == IVI_SURFACE_ROLE_SPLIT_V ||
363                     surf->role == IVI_SURFACE_ROLE_SPLIT_H)
364                         return;
365
366         split = zalloc(sizeof(*split));
367         if (!split)
368                 return;
369         split->app_id = zalloc(sizeof(char) * (len_app_id + 1));
370         if (!split->app_id) {
371                 free(split);
372                 return;
373         }
374         memcpy(split->app_id, app_id, len_app_id);
375
376         split->ioutput = ioutput;
377         split->orientation = orientation;
378
379         wl_list_insert(&ivi->split_pending_apps, &split->link);
380 }
381
382 void
383 ivi_set_pending_desktop_surface_remote(struct ivi_output *ioutput,
384                 const char *app_id)
385 {
386         struct ivi_compositor *ivi = ioutput->ivi;
387         struct pending_remote *remote;
388         struct pending_remote *p_remote = NULL;
389
390         wl_list_for_each(remote, &ivi->remote_pending_apps, link)
391                 if (!strcmp(app_id, remote->app_id))
392                         p_remote = remote;
393
394         if (!p_remote)
395                 p_remote = ivi_ensure_remote(ioutput, app_id);
396         else
397                 ivi_update_remote(ioutput, app_id, p_remote);
398         if (!p_remote)
399                 return;
400
401         wl_list_insert(&ivi->remote_pending_apps, &p_remote->link);
402 }
403
404
405 static void
406 ivi_remove_pending_desktop_surface_split(struct pending_split *split)
407 {
408         free(split->app_id);
409         wl_list_remove(&split->link);
410         free(split);
411 }
412
413 static void
414 ivi_remove_pending_desktop_surface_fullscreen(struct pending_fullscreen *fs)
415 {
416         free(fs->app_id);
417         wl_list_remove(&fs->link);
418         free(fs);
419 }
420
421 static void
422 ivi_remove_pending_desktop_surface_popup(struct pending_popup *p_popup)
423 {
424         free(p_popup->app_id);
425         wl_list_remove(&p_popup->link);
426         free(p_popup);
427 }
428
429 static void
430 ivi_remove_pending_desktop_surface_remote(struct pending_remote *remote)
431 {
432         free(remote->app_id);
433         wl_list_remove(&remote->link);
434         free(remote);
435 }
436
437 static bool
438 ivi_compositor_keep_pending_surfaces(struct ivi_surface *surface)
439 {
440         return surface->ivi->keep_pending_surfaces;
441 }
442
443 static bool
444 ivi_check_pending_desktop_surface_popup(struct ivi_surface *surface)
445 {
446         struct ivi_compositor *ivi = surface->ivi;
447         struct pending_popup *p_popup, *next_p_popup;
448         const char *_app_id =
449                         weston_desktop_surface_get_app_id(surface->dsurface);
450
451         if (wl_list_empty(&ivi->popup_pending_apps) || !_app_id)
452                 return false;
453
454         wl_list_for_each_safe(p_popup, next_p_popup,
455                               &ivi->popup_pending_apps, link) {
456                 if (!strcmp(_app_id, p_popup->app_id)) {
457                         surface->popup.output = p_popup->ioutput;
458                         surface->popup.x = p_popup->x;
459                         surface->popup.y = p_popup->y;
460
461                         surface->popup.bb.x = p_popup->bb.x;
462                         surface->popup.bb.y = p_popup->bb.y;
463                         surface->popup.bb.width = p_popup->bb.width;
464                         surface->popup.bb.height = p_popup->bb.height;
465
466                         if (!ivi_compositor_keep_pending_surfaces(surface))
467                                 ivi_remove_pending_desktop_surface_popup(p_popup);
468                         return true;
469                 }
470         }
471
472         return false;
473 }
474
475 static bool
476 ivi_check_pending_desktop_surface_split(struct ivi_surface *surface)
477 {
478         struct pending_split *split_surf, *next_split_surf;
479         struct ivi_compositor *ivi = surface->ivi;
480         const char *_app_id =
481                         weston_desktop_surface_get_app_id(surface->dsurface);
482
483         if (wl_list_empty(&ivi->split_pending_apps) || !_app_id)
484                 return false;
485
486         wl_list_for_each_safe(split_surf, next_split_surf,
487                               &ivi->split_pending_apps, link) {
488                 if (!strcmp(_app_id, split_surf->app_id)) {
489                         surface->split.output = split_surf->ioutput;
490                         surface->split.orientation = split_surf->orientation;
491                         if (!ivi_compositor_keep_pending_surfaces(surface))
492                                 ivi_remove_pending_desktop_surface_split(split_surf);
493                         return true;
494                 }
495         }
496
497         return false;
498 }
499
500 static bool
501 ivi_check_pending_desktop_surface_fullscreen(struct ivi_surface *surface)
502 {
503         struct pending_fullscreen *fs_surf, *next_fs_surf;
504         struct ivi_compositor *ivi = surface->ivi;
505         const char *_app_id =
506                         weston_desktop_surface_get_app_id(surface->dsurface);
507
508         if (wl_list_empty(&ivi->fullscreen_pending_apps) || !_app_id)
509                 return false;
510
511         wl_list_for_each_safe(fs_surf, next_fs_surf,
512                               &ivi->fullscreen_pending_apps, link) {
513                 if (!strcmp(_app_id, fs_surf->app_id)) {
514                         surface->fullscreen.output = fs_surf->ioutput;
515                         if (!ivi_compositor_keep_pending_surfaces(surface))
516                                 ivi_remove_pending_desktop_surface_fullscreen(fs_surf);
517                         return true;
518                 }
519         }
520
521         return false;
522 }
523
524 static bool
525 ivi_check_pending_desktop_surface_remote(struct ivi_surface *surface)
526 {
527         struct pending_remote *remote_surf, *next_remote_surf;
528         struct ivi_compositor *ivi = surface->ivi;
529         const char *_app_id =
530                 weston_desktop_surface_get_app_id(surface->dsurface);
531
532         if (wl_list_empty(&ivi->remote_pending_apps) || !_app_id)
533                 return false;
534
535         wl_list_for_each_safe(remote_surf, next_remote_surf,
536                               &ivi->remote_pending_apps, link) {
537                 if (!strcmp(_app_id, remote_surf->app_id)) {
538                         surface->remote.output = remote_surf->ioutput;
539                         if (!ivi_compositor_keep_pending_surfaces(surface))
540                                 ivi_remove_pending_desktop_surface_remote(remote_surf);
541                         return true;
542                 }
543         }
544
545         return false;
546 }
547 void
548 ivi_check_pending_surface_desktop(struct ivi_surface *surface,
549                                   enum ivi_surface_role *role)
550 {
551         struct ivi_compositor *ivi = surface->ivi;
552         struct wl_list *role_pending_list;
553         struct pending_popup *p_popup;
554         struct pending_split *p_split;
555         struct pending_fullscreen *p_fullscreen;
556         struct pending_remote *p_remote;
557         const char *app_id =
558                 weston_desktop_surface_get_app_id(surface->dsurface);
559
560         role_pending_list = &ivi->popup_pending_apps;
561         wl_list_for_each(p_popup, role_pending_list, link) {
562                 if (app_id && !strcmp(app_id, p_popup->app_id)) {
563                         *role = IVI_SURFACE_ROLE_POPUP;
564                         return;
565                 }
566         }
567
568         role_pending_list = &ivi->split_pending_apps;
569         wl_list_for_each(p_split, role_pending_list, link) {
570                 if (app_id && !strcmp(app_id, p_split->app_id)) {
571                         *role = IVI_SURFACE_ROLE_SPLIT_V;
572                         return;
573                 }
574         }
575
576         role_pending_list = &ivi->fullscreen_pending_apps;
577         wl_list_for_each(p_fullscreen, role_pending_list, link) {
578                 if (app_id && !strcmp(app_id, p_fullscreen->app_id)) {
579                         *role = IVI_SURFACE_ROLE_FULLSCREEN;
580                         return;
581                 }
582         }
583
584         role_pending_list = &ivi->remote_pending_apps;
585         wl_list_for_each(p_remote, role_pending_list, link) {
586                 if (app_id && !strcmp(app_id, p_remote->app_id)) {
587                         *role = IVI_SURFACE_ROLE_REMOTE;
588                         return;
589                 }
590         }
591
592         /* else, we are a regular desktop surface */
593         *role = IVI_SURFACE_ROLE_DESKTOP;
594 }
595
596 struct pending_app *
597 ivi_check_pending_app_type(struct ivi_surface *surface, enum ivi_surface_role role)
598 {
599         struct pending_app *papp;
600         const char *app_id = NULL;
601
602         app_id = weston_desktop_surface_get_app_id(surface->dsurface);
603         if (!app_id)
604                 return NULL;
605
606         wl_list_for_each(papp, &surface->ivi->pending_apps, link) {
607                 if (strcmp(app_id, papp->app_id) == 0 && papp->role == role)
608                         return papp;
609         }
610
611         return NULL;
612 }
613  
614
615 void
616 ivi_check_pending_desktop_surface(struct ivi_surface *surface)
617 {
618         bool ret = false;
619
620         ret = ivi_check_pending_desktop_surface_popup(surface);
621         if (ret) {
622                 ivi_set_desktop_surface_popup(surface);
623                 ivi_layout_popup_committed(surface);
624                 return;
625         }
626
627         ret = ivi_check_pending_desktop_surface_split(surface);
628         if (ret) {
629                 ivi_set_desktop_surface_split(surface);
630                 ivi_layout_split_committed(surface);
631                 return;
632         }
633
634         ret = ivi_check_pending_desktop_surface_fullscreen(surface);
635         if (ret) {
636                 ivi_set_desktop_surface_fullscreen(surface);
637                 ivi_layout_fullscreen_committed(surface);
638                 return;
639         }
640
641         ret = ivi_check_pending_desktop_surface_remote(surface);
642         if (ret) {
643                 ivi_set_desktop_surface_remote(surface);
644                 ivi_layout_remote_committed(surface);
645                 return;
646         }
647
648         /* new way of doing it */
649         struct pending_app *papp =
650                 ivi_check_pending_app_type(surface, IVI_SURFACE_ROLE_TILE);
651         if (papp) {
652                 struct pending_app_tile *papp_tile =
653                         container_of(papp, struct pending_app_tile, base);
654
655                 // handle the currently active surface
656                 if (papp->ioutput->active) {
657                         int width_prev_app = 0;
658
659                         if (papp_tile->width > 0) {
660                                 if (papp_tile->orientation == AGL_SHELL_TILE_ORIENTATION_TOP ||
661                                     papp_tile->orientation == AGL_SHELL_TILE_ORIENTATION_BOTTOM)
662                                         width_prev_app = papp->ioutput->area.height - papp_tile->width;
663                                 else
664                                         width_prev_app = papp->ioutput->area.width - papp_tile->width;
665                         }
666                         _ivi_set_shell_surface_split(papp->ioutput->active, NULL,
667                                         reverse_orientation(papp_tile->orientation),
668                                         width_prev_app, false, false);
669                 }
670
671                 surface->role = IVI_SURFACE_ROLE_TILE;
672                 surface->current_completed_output = papp->ioutput;
673                 wl_list_insert(&surface->ivi->surfaces, &surface->link);
674
675                 _ivi_set_shell_surface_split(surface, papp->ioutput,
676                                              papp_tile->orientation, papp_tile->width,
677                                              papp_tile->sticky, true);
678
679                 /* remove it from pending */
680                 wl_list_remove(&papp->link);
681                 free(papp->app_id);
682                 free(papp);
683
684                 return;
685         }
686
687         /* if we end up here means we have a regular desktop app and
688          * try to activate it */
689         ivi_set_desktop_surface(surface);
690         ivi_layout_desktop_committed(surface);
691 }
692
693 void
694 ivi_shell_init_black_fs(struct ivi_compositor *ivi)
695 {
696         struct ivi_output *out;
697
698         wl_list_for_each(out, &ivi->outputs, link) {
699                 create_black_curtain_view(out);
700                 insert_black_curtain(out);
701         }
702 }
703
704 int
705 ivi_shell_init(struct ivi_compositor *ivi)
706 {
707         weston_layer_init(&ivi->hidden, ivi->compositor);
708         weston_layer_init(&ivi->background, ivi->compositor);
709         weston_layer_init(&ivi->normal, ivi->compositor);
710         weston_layer_init(&ivi->panel, ivi->compositor);
711         weston_layer_init(&ivi->popup, ivi->compositor);
712         weston_layer_init(&ivi->fullscreen, ivi->compositor);
713
714         weston_layer_set_position(&ivi->hidden,
715                                   WESTON_LAYER_POSITION_HIDDEN);
716         weston_layer_set_position(&ivi->background,
717                                   WESTON_LAYER_POSITION_BACKGROUND);
718         weston_layer_set_position(&ivi->normal,
719                                   WESTON_LAYER_POSITION_NORMAL);
720         weston_layer_set_position(&ivi->panel,
721                                   WESTON_LAYER_POSITION_UI);
722         weston_layer_set_position(&ivi->popup,
723                                   WESTON_LAYER_POSITION_TOP_UI);
724         weston_layer_set_position(&ivi->fullscreen,
725                                   WESTON_LAYER_POSITION_FULLSCREEN);
726
727         return 0;
728 }
729
730
731 static void
732 ivi_surf_destroy(struct ivi_surface *surf)
733 {
734         struct weston_surface *wsurface = surf->view->surface;
735
736         if (weston_surface_is_mapped(wsurface)) {
737                 weston_desktop_surface_unlink_view(surf->view);
738                 weston_view_destroy(surf->view);
739         }
740
741         wl_list_remove(&surf->link);
742         free(surf);
743 }
744
745 static void
746 ivi_shell_destroy_views_on_layer(struct weston_layer *layer)
747 {
748         struct weston_view *view, *view_next;
749
750         wl_list_for_each_safe(view, view_next, &layer->view_list.link, layer_link.link) {
751                 struct ivi_surface *ivi_surf =
752                         get_ivi_shell_surface(view->surface);
753                 if (ivi_surf)
754                         ivi_surf_destroy(ivi_surf);
755         }
756 }
757
758 void
759 ivi_shell_finalize(struct ivi_compositor *ivi)
760 {
761         struct ivi_output *output;
762
763         ivi_shell_destroy_views_on_layer(&ivi->hidden);
764         weston_layer_fini(&ivi->hidden);
765
766         ivi_shell_destroy_views_on_layer(&ivi->background);
767         weston_layer_fini(&ivi->background);
768
769         ivi_shell_destroy_views_on_layer(&ivi->normal);
770         weston_layer_fini(&ivi->normal);
771
772         ivi_shell_destroy_views_on_layer(&ivi->panel);
773         weston_layer_fini(&ivi->panel);
774
775         ivi_shell_destroy_views_on_layer(&ivi->popup);
776         weston_layer_fini(&ivi->popup);
777
778         wl_list_for_each(output, &ivi->outputs, link) {
779                 if (output->fullscreen_view.fs &&
780                     output->fullscreen_view.fs->view) {
781                         weston_surface_destroy(output->fullscreen_view.fs->view->surface);
782                         output->fullscreen_view.fs->view = NULL;
783                 }
784         }
785         weston_layer_fini(&ivi->fullscreen);
786 }
787
788 static void
789 ivi_shell_advertise_xdg_surfaces(struct ivi_compositor *ivi, struct wl_resource *resource)
790 {
791         struct ivi_surface *surface;
792
793         wl_list_for_each(surface, &ivi->surfaces, link) {
794                 const char *app_id =
795                         weston_desktop_surface_get_app_id(surface->dsurface);
796                 if (app_id == NULL) {
797                         weston_log("WARNING app_is is null, unable to advertise\n");
798                         return;
799                 }
800                 agl_shell_desktop_send_application(resource, app_id);
801         }
802 }
803
804 static struct wl_client *
805 client_launch(struct weston_compositor *compositor,
806                      struct weston_process *proc,
807                      const char *path,
808                      weston_process_cleanup_func_t cleanup)
809 {
810         struct wl_client *client = NULL;
811         struct custom_env child_env;
812         struct fdstr wayland_socket;
813         const char *fail_cloexec = "Couldn't unset CLOEXEC on client socket";
814         const char *fail_seteuid = "Couldn't call seteuid";
815         char *fail_exec;
816         char * const *argp;
817         char * const *envp;
818         sigset_t allsigs;
819         pid_t pid;
820         bool ret;
821         struct ivi_compositor *ivi;
822         size_t written __attribute__((unused));
823
824         weston_log("launching '%s'\n", path);
825         str_printf(&fail_exec, "Error: Couldn't launch client '%s'\n", path);
826
827         custom_env_init_from_environ(&child_env);
828         custom_env_add_from_exec_string(&child_env, path);
829
830         if (os_socketpair_cloexec(AF_UNIX, SOCK_STREAM, 0,
831                                   wayland_socket.fds) < 0) {
832                 weston_log("client_launch: "
833                            "socketpair failed while launching '%s': %s\n",
834                            path, strerror(errno));
835                 custom_env_fini(&child_env);
836                 return NULL;
837         }
838         fdstr_update_str1(&wayland_socket);
839         custom_env_set_env_var(&child_env, "WAYLAND_SOCKET",
840                                wayland_socket.str1);
841
842         argp = custom_env_get_argp(&child_env);
843         envp = custom_env_get_envp(&child_env);
844
845         pid = fork();
846         switch (pid) {
847         case 0:
848                 /* Put the client in a new session so it won't catch signals
849                  * intended for the parent. Sharing a session can be
850                  * confusing when launching weston under gdb, as the ctrl-c
851                  * intended for gdb will pass to the child, and weston
852                  * will cleanly shut down when the child exits.
853                  */
854                 setsid();
855
856                 /* do not give our signal mask to the new process */
857                 sigfillset(&allsigs);
858                 sigprocmask(SIG_UNBLOCK, &allsigs, NULL);
859
860                 /* Launch clients as the user. Do not launch clients with wrong euid. */
861                 if (seteuid(getuid()) == -1) {
862                         written = write(STDERR_FILENO, fail_seteuid, strlen(fail_seteuid));
863                         _exit(EXIT_FAILURE);
864                 }
865
866                 ret = fdstr_clear_cloexec_fd1(&wayland_socket);
867                 if (!ret) {
868                         written = write(STDERR_FILENO, fail_cloexec, strlen(fail_cloexec));
869                         _exit(EXIT_FAILURE);
870                 }
871
872                 execve(argp[0], argp, envp);
873
874                 if (fail_exec)
875                         written = write(STDERR_FILENO, fail_exec, strlen(fail_exec));
876                 _exit(EXIT_FAILURE);
877
878         default:
879                 close(wayland_socket.fds[1]);
880                 ivi = weston_compositor_get_user_data(compositor);
881                 client = wl_client_create(compositor->wl_display,
882                                           wayland_socket.fds[0]);
883                 if (!client) {
884                         custom_env_fini(&child_env);
885                         close(wayland_socket.fds[0]);
886                         free(fail_exec);
887                         weston_log("client_launch: "
888                                 "wl_client_create failed while launching '%s'.\n",
889                                 path);
890                         return NULL;
891                 }
892
893                 proc->pid = pid;
894                 proc->cleanup = cleanup;
895                 wl_list_insert(&ivi->child_process_list, &proc->link);
896                 break;
897
898         case -1:
899                 fdstr_close_all(&wayland_socket);
900                 weston_log("client_launch: "
901                            "fork failed while launching '%s': %s\n", path,
902                            strerror(errno));
903                 break;
904         }
905
906         custom_env_fini(&child_env);
907         free(fail_exec);
908
909         return client;
910 }
911
912 struct process_info {
913         struct weston_process proc;
914         char *path;
915 };
916
917 int
918 sigchld_handler(int signal_number, void *data)
919 {
920         struct weston_process *p;
921         struct ivi_compositor *ivi = data;
922         int status;
923         pid_t pid;
924
925         while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
926                 wl_list_for_each(p, &ivi->child_process_list, link) {
927                         if (p->pid == pid)
928                                 break;
929                 }
930
931                 if (&p->link == &ivi->child_process_list) {
932                         weston_log("unknown child process exited\n");
933                         continue;
934                 }
935
936                 wl_list_remove(&p->link);
937                 wl_list_init(&p->link);
938                 p->cleanup(p, status);
939         }
940
941         if (pid < 0 && errno != ECHILD)
942                 weston_log("waitpid error %s\n", strerror(errno));
943
944         return 1;
945 }
946
947
948 static void
949 process_handle_sigchld(struct weston_process *process, int status)
950 {
951         struct process_info *pinfo =
952                 container_of(process, struct process_info, proc);
953
954         /*
955          * There are no guarantees whether this runs before or after
956          * the wl_client destructor.
957          */
958
959         if (WIFEXITED(status)) {
960                 weston_log("%s exited with status %d\n", pinfo->path,
961                            WEXITSTATUS(status));
962         } else if (WIFSIGNALED(status)) {
963                 weston_log("%s died on signal %d\n", pinfo->path,
964                            WTERMSIG(status));
965         } else {
966                 weston_log("%s disappeared\n", pinfo->path);
967         }
968
969         free(pinfo->path);
970         free(pinfo);
971 }
972
973 int
974 ivi_launch_shell_client(struct ivi_compositor *ivi, const char *cmd_section,
975                         struct wl_client **client)
976 {
977         struct process_info *pinfo;
978         struct weston_config_section *section;
979         char *command = NULL;
980
981         section = weston_config_get_section(ivi->config, cmd_section, NULL, NULL);
982         if (section)
983                 weston_config_section_get_string(section, "command", &command, NULL);
984
985         if (!command)
986                 return -1;
987
988         pinfo = zalloc(sizeof *pinfo);
989         if (!pinfo)
990                 return -1;
991
992         pinfo->path = strdup(command);
993         if (!pinfo->path)
994                 goto out_free;
995
996         *client = client_launch(ivi->compositor, &pinfo->proc, command, process_handle_sigchld);
997         if (!*client)
998                 goto out_str;
999
1000         return 0;
1001
1002 out_str:
1003         free(pinfo->path);
1004
1005 out_free:
1006         free(pinfo);
1007
1008         return -1;
1009 }
1010
1011 static void
1012 destroy_black_curtain_view(struct wl_listener *listener, void *data)
1013 {
1014         struct fullscreen_view *fs =
1015                 wl_container_of(listener, fs, fs_destroy);
1016
1017
1018         if (fs && fs->fs) {
1019                 wl_list_remove(&fs->fs_destroy.link);
1020                 free(fs->fs);
1021         }
1022 }
1023
1024
1025 static void
1026 create_black_curtain_view(struct ivi_output *output)
1027 {
1028         struct weston_surface *surface = NULL;
1029         struct weston_view *view;
1030         struct ivi_compositor *ivi = output->ivi;
1031         struct weston_compositor *wc= ivi->compositor;
1032         struct weston_output *woutput = output->output;
1033
1034         if (!woutput)
1035                 return;
1036
1037         surface = weston_surface_create(wc);
1038         if (!surface)
1039                 return;
1040         view = weston_view_create(surface);
1041         if (!view) {
1042                 weston_surface_destroy(surface);
1043                 return;
1044         }
1045
1046         weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1);
1047         weston_surface_set_size(surface, woutput->width, woutput->height);
1048         weston_view_set_position(view, woutput->x, woutput->y);
1049
1050         output->fullscreen_view.fs = zalloc(sizeof(struct ivi_surface));
1051         if (!output->fullscreen_view.fs) {
1052                 weston_surface_destroy(surface);
1053                 return;
1054         }
1055         output->fullscreen_view.fs->view = view;
1056
1057         output->fullscreen_view.fs_destroy.notify = destroy_black_curtain_view;
1058         wl_signal_add(&woutput->destroy_signal,
1059                       &output->fullscreen_view.fs_destroy);
1060 }
1061
1062 bool
1063 output_has_black_curtain(struct ivi_output *output)
1064 {
1065         return (output->fullscreen_view.fs &&
1066                 output->fullscreen_view.fs->view &&
1067                 output->fullscreen_view.fs->view->is_mapped &&
1068                 output->fullscreen_view.fs->view->surface->is_mapped);
1069 }
1070
1071 void
1072 remove_black_curtain(struct ivi_output *output)
1073 {
1074         struct weston_view *view;
1075
1076         if ((!output &&
1077             !output->fullscreen_view.fs &&
1078             !output->fullscreen_view.fs->view) ||
1079             !output->fullscreen_view.fs) {
1080                 weston_log("Output %s doesn't have a surface installed!\n", output->name);
1081                 return;
1082         }
1083
1084         view = output->fullscreen_view.fs->view;
1085         assert(view->is_mapped == true ||
1086                view->surface->is_mapped == true);
1087
1088         view->is_mapped = false;
1089         view->surface->is_mapped = false;
1090
1091         weston_layer_entry_remove(&view->layer_link);
1092         weston_view_update_transform(view);
1093
1094         weston_view_damage_below(view);
1095
1096         weston_log("Removed black curtain from output %s\n", output->output->name);
1097 }
1098
1099 void
1100 insert_black_curtain(struct ivi_output *output)
1101 {
1102         struct weston_view *view;
1103
1104         if ((!output &&
1105             !output->fullscreen_view.fs &&
1106             !output->fullscreen_view.fs->view) || !output->output ||
1107             !output->fullscreen_view.fs) {
1108                 weston_log("Output %s doesn't have a surface installed!\n", output->name);
1109                 return;
1110         }
1111
1112         view = output->fullscreen_view.fs->view;
1113         if (view->is_mapped || view->surface->is_mapped)
1114                 return;
1115
1116         weston_layer_entry_remove(&view->layer_link);
1117         weston_layer_entry_insert(&output->ivi->fullscreen.view_list,
1118                                   &view->layer_link);
1119
1120         view->is_mapped = true;
1121         view->surface->is_mapped = true;
1122
1123         weston_view_update_transform(view);
1124         weston_view_damage_below(view);
1125
1126         weston_log("Added black curtain to output %s\n", output->output->name);
1127 }
1128
1129 void
1130 shell_send_app_state(struct ivi_compositor *ivi, const char *app_id,
1131                      enum agl_shell_app_state state)
1132 {
1133         if (app_id && wl_resource_get_version(ivi->shell_client.resource) >=
1134             AGL_SHELL_APP_STATE_SINCE_VERSION) {
1135
1136                 agl_shell_send_app_state(ivi->shell_client.resource,
1137                                          app_id, state);
1138
1139                 if (ivi->shell_client.resource_ext)
1140                         agl_shell_send_app_state(ivi->shell_client.resource_ext,
1141                                                  app_id, state);
1142         }
1143 }
1144
1145 void
1146 shell_send_app_on_output(struct ivi_compositor *ivi, const char *app_id,
1147                          const char *output_name)
1148 {
1149         if (app_id && ivi->shell_client.resource &&
1150             wl_resource_get_version(ivi->shell_client.resource) >=
1151             AGL_SHELL_APP_ON_OUTPUT_SINCE_VERSION) {
1152
1153                 agl_shell_send_app_on_output(ivi->shell_client.resource,
1154                                          app_id, output_name);
1155
1156                 if (ivi->shell_client.resource_ext)
1157                         agl_shell_send_app_on_output(ivi->shell_client.resource_ext,
1158                                                  app_id, output_name);
1159         }
1160 }
1161
1162 static void
1163 shell_ready(struct wl_client *client, struct wl_resource *shell_res)
1164 {
1165         struct ivi_compositor *ivi = wl_resource_get_user_data(shell_res);
1166         struct ivi_output *output;
1167         struct ivi_surface *surface, *tmp;
1168
1169         if (wl_resource_get_version(shell_res) >=
1170             AGL_SHELL_BOUND_OK_SINCE_VERSION &&
1171             ivi->shell_client.status == BOUND_FAILED) {
1172                 wl_resource_post_error(shell_res,
1173                                        WL_DISPLAY_ERROR_INVALID_OBJECT,
1174                                        "agl_shell (ready quest) has already "
1175                                        "been bound. Check out bound_fail event");
1176                 return;
1177         }
1178
1179         /* Init already finished. Do nothing */
1180         if (ivi->shell_client.ready)
1181                 return;
1182
1183
1184         ivi->shell_client.ready = true;
1185
1186         wl_list_for_each(output, &ivi->outputs, link) {
1187                 if (output->background &&
1188                     output->background->role == IVI_SURFACE_ROLE_BACKGROUND) {
1189                         /* track the background surface role as a "regular"
1190                          * surface so we can activate it */
1191                         ivi_set_background_surface(output->background);
1192                         remove_black_curtain(output);
1193                 }
1194
1195                 ivi_layout_init(ivi, output);
1196         }
1197
1198         wl_list_for_each_safe(surface, tmp, &ivi->pending_surfaces, link) {
1199                 const char *app_id;
1200
1201                 wl_list_remove(&surface->link);
1202                 wl_list_init(&surface->link);
1203                 ivi_check_pending_desktop_surface(surface);
1204                 surface->checked_pending = true;
1205                 app_id = weston_desktop_surface_get_app_id(surface->dsurface);
1206
1207                 shell_send_app_state(ivi, app_id, AGL_SHELL_APP_STATE_STARTED);
1208         }
1209 }
1210
1211 static void
1212 shell_set_background(struct wl_client *client,
1213                      struct wl_resource *shell_res,
1214                      struct wl_resource *surface_res,
1215                      struct wl_resource *output_res)
1216 {
1217         struct weston_head *head = weston_head_from_resource(output_res);
1218         struct weston_output *woutput = weston_head_get_output(head);
1219         struct ivi_output *output = to_ivi_output(woutput);
1220         struct weston_surface *wsurface = wl_resource_get_user_data(surface_res);
1221         struct ivi_compositor *ivi = wl_resource_get_user_data(shell_res);
1222         struct weston_desktop_surface *dsurface;
1223         struct ivi_surface *surface;
1224
1225         if ((wl_resource_get_version(shell_res) >=
1226             AGL_SHELL_BOUND_OK_SINCE_VERSION &&
1227             ivi->shell_client.status == BOUND_FAILED) ||
1228             ivi->shell_client.resource_ext == shell_res) {
1229                 wl_resource_post_error(shell_res,
1230                                        WL_DISPLAY_ERROR_INVALID_OBJECT,
1231                                        "agl_shell (set_background) has already "
1232                                        "been bound. Check out bound_fail event");
1233                 return;
1234         }
1235
1236         dsurface = weston_surface_get_desktop_surface(wsurface);
1237         if (!dsurface) {
1238                 wl_resource_post_error(shell_res,
1239                                        AGL_SHELL_ERROR_INVALID_ARGUMENT,
1240                                        "surface must be a desktop surface");
1241                 return;
1242         }
1243
1244         surface = weston_desktop_surface_get_user_data(dsurface);
1245         if (surface->role != IVI_SURFACE_ROLE_NONE) {
1246                 wl_resource_post_error(shell_res,
1247                                        AGL_SHELL_ERROR_INVALID_ARGUMENT,
1248                                        "surface already has another ivi role");
1249                 return;
1250         }
1251
1252         if (output->background) {
1253                 wl_resource_post_error(shell_res,
1254                                        AGL_SHELL_ERROR_BACKGROUND_EXISTS,
1255                                        "output already has background");
1256                 return;
1257         }
1258
1259         surface->checked_pending = true;
1260         surface->role = IVI_SURFACE_ROLE_BACKGROUND;
1261         surface->bg.output = output;
1262         wl_list_remove(&surface->link);
1263         wl_list_init(&surface->link);
1264
1265         output->background = surface;
1266
1267         weston_desktop_surface_set_maximized(dsurface, true);
1268         weston_desktop_surface_set_size(dsurface,
1269                                         output->output->width,
1270                                         output->output->height);
1271 }
1272
1273 static void
1274 shell_set_panel(struct wl_client *client,
1275                 struct wl_resource *shell_res,
1276                 struct wl_resource *surface_res,
1277                 struct wl_resource *output_res,
1278                 uint32_t edge)
1279 {
1280         struct weston_head *head = weston_head_from_resource(output_res);
1281         struct weston_output *woutput = weston_head_get_output(head);
1282         struct ivi_output *output = to_ivi_output(woutput);
1283         struct weston_surface *wsurface = wl_resource_get_user_data(surface_res);
1284         struct ivi_compositor *ivi = wl_resource_get_user_data(shell_res);
1285         struct weston_desktop_surface *dsurface;
1286         struct ivi_surface *surface;
1287         struct ivi_surface **member;
1288         int32_t width = 0, height = 0;
1289
1290         if ((wl_resource_get_version(shell_res) >=
1291              AGL_SHELL_BOUND_OK_SINCE_VERSION &&
1292              ivi->shell_client.status == BOUND_FAILED) ||
1293             ivi->shell_client.resource_ext == shell_res) {
1294                 wl_resource_post_error(shell_res,
1295                                        WL_DISPLAY_ERROR_INVALID_OBJECT,
1296                                        "agl_shell (set_panel) has already been bound. "
1297                                        "Check out bound_fail event");
1298                 return;
1299         }
1300
1301         dsurface = weston_surface_get_desktop_surface(wsurface);
1302         if (!dsurface) {
1303                 wl_resource_post_error(shell_res,
1304                                        AGL_SHELL_ERROR_INVALID_ARGUMENT,
1305                                        "surface must be a desktop surface");
1306                 return;
1307         }
1308
1309         surface = weston_desktop_surface_get_user_data(dsurface);
1310         if (surface->role != IVI_SURFACE_ROLE_NONE) {
1311                 wl_resource_post_error(shell_res,
1312                                        AGL_SHELL_ERROR_INVALID_ARGUMENT,
1313                                        "surface already has another ivi role");
1314                 return;
1315         }
1316
1317         switch (edge) {
1318         case AGL_SHELL_EDGE_TOP:
1319                 member = &output->top;
1320                 break;
1321         case AGL_SHELL_EDGE_BOTTOM:
1322                 member = &output->bottom;
1323                 break;
1324         case AGL_SHELL_EDGE_LEFT:
1325                 member = &output->left;
1326                 break;
1327         case AGL_SHELL_EDGE_RIGHT:
1328                 member = &output->right;
1329                 break;
1330         default:
1331                 wl_resource_post_error(shell_res,
1332                                        AGL_SHELL_ERROR_INVALID_ARGUMENT,
1333                                        "invalid edge for panel");
1334                 return;
1335         }
1336
1337         if (*member) {
1338                 wl_resource_post_error(shell_res,
1339                                        AGL_SHELL_ERROR_BACKGROUND_EXISTS,
1340                                        "output already has panel on this edge");
1341                 return;
1342         }
1343
1344         surface->checked_pending = true;
1345         surface->role = IVI_SURFACE_ROLE_PANEL;
1346         surface->panel.output = output;
1347         surface->panel.edge = edge;
1348         wl_list_remove(&surface->link);
1349         wl_list_init(&surface->link);
1350
1351         *member = surface;
1352
1353         switch (surface->panel.edge) {
1354         case AGL_SHELL_EDGE_TOP:
1355         case AGL_SHELL_EDGE_BOTTOM:
1356                 width = woutput->width;
1357                 break;
1358         case AGL_SHELL_EDGE_LEFT:
1359         case AGL_SHELL_EDGE_RIGHT:
1360                 height = woutput->height;
1361                 break;
1362         }
1363
1364         weston_desktop_surface_set_size(dsurface, width, height);
1365 }
1366
1367 void
1368 shell_advertise_app_state(struct ivi_compositor *ivi, const char *app_id,
1369                           const char *data, uint32_t app_state)
1370 {
1371         struct desktop_client *dclient;
1372         uint32_t app_role;
1373         struct ivi_surface *surf = ivi_find_app(ivi, app_id);
1374         struct ivi_policy *policy = ivi->policy;
1375
1376         /* FIXME: should queue it here and see when binding agl-shell-desktop
1377          * if there are any to be sent */
1378         if (!surf)
1379                 return;
1380
1381         if (!app_id)
1382                 return;
1383
1384         if (policy && policy->api.surface_advertise_state_change &&
1385             !policy->api.surface_advertise_state_change(surf, surf->ivi)) {
1386                 return;
1387         }
1388
1389         app_role = surf->role;
1390         if (app_role == IVI_SURFACE_ROLE_POPUP)
1391                 app_role = AGL_SHELL_DESKTOP_APP_ROLE_POPUP;
1392
1393         wl_list_for_each(dclient, &ivi->desktop_clients, link)
1394                 agl_shell_desktop_send_state_app(dclient->resource, app_id,
1395                                                  data, app_state, app_role);
1396 }
1397
1398 static void
1399 shell_activate_app(struct wl_client *client,
1400                    struct wl_resource *shell_res,
1401                    const char *app_id,
1402                    struct wl_resource *output_res)
1403 {
1404         struct weston_head *head;
1405         struct weston_output *woutput;
1406         struct ivi_compositor *ivi;
1407         struct ivi_output *output;
1408
1409         head = weston_head_from_resource(output_res);
1410         if (!head) {
1411                 weston_log("Invalid output to activate '%s' on\n", app_id);
1412                 return;
1413         }
1414
1415         woutput = weston_head_get_output(head);
1416         ivi = wl_resource_get_user_data(shell_res);
1417         output = to_ivi_output(woutput);
1418
1419         if (wl_resource_get_version(shell_res) >=
1420             AGL_SHELL_BOUND_OK_SINCE_VERSION &&
1421             ivi->shell_client.status == BOUND_FAILED) {
1422                 wl_resource_post_error(shell_res,
1423                                        WL_DISPLAY_ERROR_INVALID_OBJECT,
1424                                        "agl_shell has already been bound. "
1425                                        "Check out bound_fail event");
1426                 return;
1427         }
1428
1429         ivi_layout_activate(output, app_id);
1430 }
1431
1432 static void
1433 shell_new_deactivate_app(struct wl_client *client, struct wl_resource *shell_res,
1434                          const char *app_id)
1435 {
1436         struct ivi_compositor *ivi = wl_resource_get_user_data(shell_res);
1437
1438         ivi_layout_deactivate(ivi, app_id);
1439 }
1440
1441 static void
1442 shell_set_app_float(struct wl_client *client, struct wl_resource *shell_res,
1443                    const char *app_id, int32_t x_pos, int32_t y_pos)
1444 {
1445         struct ivi_compositor *ivi = wl_resource_get_user_data(shell_res);
1446         struct weston_output *output = get_focused_output(ivi->compositor);
1447         struct ivi_output *ivi_output;
1448         struct ivi_surface *surf = ivi_find_app(ivi, app_id);
1449
1450         if (!output)
1451                 output = get_default_output(ivi->compositor);
1452
1453         ivi_output = to_ivi_output(output);
1454
1455         /* verify if already mapped as desktop role, regular, unmap it, so we
1456          * can make it float */
1457         if (surf && surf->role == IVI_SURFACE_ROLE_DESKTOP) {
1458                 struct weston_view *ev = surf->view;
1459                 struct weston_desktop_surface *dsurf = surf->dsurface;
1460                 struct ivi_bounding_box bb = {};
1461                 const char *prev_activate_app_id = NULL;
1462
1463                 /* XXX: if this is useful we could bring it as active then make
1464                  * it float, but avoid doing it for the moment */
1465                 if (surf != ivi_output->active)
1466                         return;
1467
1468                 if (ivi_output->previous_active)
1469                         prev_activate_app_id =
1470                                 weston_desktop_surface_get_app_id(ivi_output->previous_active->dsurface);
1471
1472                 /* only deactivate if previous_active is different, otherwise
1473                  * this will blow up, because we're trying to activate the same
1474                  * app_id as the this one! */
1475                 if (prev_activate_app_id && strcmp(app_id, prev_activate_app_id)) {
1476                         ivi_layout_deactivate(ivi, app_id);
1477                 } else if (prev_activate_app_id) {
1478                         weston_layer_entry_remove(&ev->layer_link);
1479                         weston_view_geometry_dirty(ev);
1480                         weston_surface_damage(ev->surface);
1481                 }
1482
1483                 surf->hidden_layer_output = ivi_output;
1484
1485                 /* set attributes */
1486                 surf->popup.output = ivi_output;
1487
1488                 surf->popup.x = x_pos;
1489                 surf->popup.y = y_pos;
1490                 surf->popup.bb = bb;
1491
1492
1493                 /* change the role */
1494                 surf->role = IVI_SURFACE_ROLE_NONE;
1495
1496                 wl_list_remove(&surf->link);
1497                 wl_list_init(&surf->link);
1498
1499                 ivi_set_desktop_surface_popup(surf);
1500
1501                 weston_desktop_surface_set_maximized(dsurf, false);
1502                 weston_desktop_surface_set_size(dsurf, 0, 0);
1503
1504                 /* add to hidden layer */
1505                 weston_layer_entry_insert(&ivi->hidden.view_list, &ev->layer_link);
1506                 weston_compositor_schedule_repaint(ivi->compositor);
1507
1508         } else if (!surf || (surf && surf->role != IVI_SURFACE_ROLE_POPUP)) {
1509                 ivi_set_pending_desktop_surface_popup(ivi_output, x_pos, y_pos, 
1510                                                       0, 0, 0, 0, app_id);
1511         }
1512 }
1513
1514 static void
1515 shell_set_app_fullscreen(struct wl_client *client,
1516                          struct wl_resource *shell_res, const char *app_id)
1517 {
1518         struct ivi_compositor *ivi = wl_resource_get_user_data(shell_res);
1519         struct weston_output *output = get_focused_output(ivi->compositor);
1520         struct ivi_output *ivi_output;
1521         struct ivi_surface *surf = ivi_find_app(ivi, app_id);
1522
1523         if (!output)
1524                 output = get_default_output(ivi->compositor);
1525
1526         ivi_output = to_ivi_output(output);
1527
1528         if (surf && surf->role == IVI_SURFACE_ROLE_DESKTOP) {
1529                 struct weston_view *ev = surf->view;
1530                 struct weston_desktop_surface *dsurf = surf->dsurface;
1531
1532                 if (surf != ivi_output->active)
1533                         return;
1534
1535                 weston_layer_entry_remove(&surf->view->layer_link);
1536                 weston_view_geometry_dirty(surf->view);
1537                 weston_surface_damage(surf->view->surface);
1538
1539                 surf->hidden_layer_output = ivi_output;
1540
1541                 /* set attributes */
1542                 surf->fullscreen.output = ivi_output;
1543
1544                 /* change the role */
1545                 surf->role = IVI_SURFACE_ROLE_NONE;
1546
1547                 wl_list_remove(&surf->link);
1548                 wl_list_init(&surf->link);
1549
1550                 ivi_set_desktop_surface_fullscreen(surf);
1551
1552                 weston_desktop_surface_set_maximized(dsurf, false);
1553                 weston_desktop_surface_set_fullscreen(dsurf, true);
1554                 weston_desktop_surface_set_size(dsurf,
1555                                                 ivi_output->output->width,
1556                                                 ivi_output->output->height);
1557
1558                 /* add to hidden layer */
1559                 weston_layer_entry_insert(&ivi->hidden.view_list, &ev->layer_link);
1560                 weston_compositor_schedule_repaint(ivi->compositor);
1561         } else if (!surf || (surf && surf->role != IVI_SURFACE_ROLE_FULLSCREEN)) {
1562                 ivi_set_pending_desktop_surface_fullscreen(ivi_output, app_id);
1563         }
1564 }
1565
1566
1567 static void
1568 shell_set_app_normal(struct wl_client *client, struct wl_resource *shell_res,
1569                      const char *app_id)
1570 {
1571         struct ivi_compositor *ivi = wl_resource_get_user_data(shell_res);
1572         struct ivi_surface *surf = ivi_find_app(ivi, app_id);
1573         struct weston_output *output = get_focused_output(ivi->compositor);
1574         struct ivi_output *ivi_output;
1575         struct weston_desktop_surface *dsurf;
1576         struct weston_geometry area = {};
1577
1578
1579         if (!surf || (surf && surf->role == IVI_SURFACE_ROLE_DESKTOP))
1580                 return;
1581
1582         if (!output)
1583                 output = get_default_output(ivi->compositor);
1584
1585         dsurf = surf->dsurface;
1586         ivi_output = to_ivi_output(output);
1587
1588         weston_layer_entry_remove(&surf->view->layer_link);
1589         weston_view_geometry_dirty(surf->view);
1590         weston_surface_damage(surf->view->surface);
1591
1592         /* change the role */
1593         surf->role = IVI_SURFACE_ROLE_NONE;
1594         surf->state = NORMAL;
1595         surf->desktop.pending_output = ivi_output;
1596
1597         wl_list_remove(&surf->link);
1598         wl_list_init(&surf->link);
1599
1600         ivi_set_desktop_surface(surf);
1601
1602         if (ivi_output->area_activation.width ||
1603             ivi_output->area_activation.height)
1604                 area = ivi_output->area_activation;
1605         else
1606                 area = ivi_output->area;
1607
1608         if (weston_desktop_surface_get_fullscreen(dsurf))
1609                 weston_desktop_surface_set_fullscreen(dsurf, false);
1610
1611         weston_desktop_surface_set_maximized(dsurf, true);
1612         weston_desktop_surface_set_size(dsurf, area.width, area.height);
1613
1614         /* add to hidden layer */
1615         weston_layer_entry_insert(&ivi->hidden.view_list,
1616                                   &surf->view->layer_link);
1617         weston_compositor_schedule_repaint(ivi->compositor);
1618
1619 }
1620
1621 static void
1622 shell_desktop_activate_app(struct wl_client *client,
1623                            struct wl_resource *shell_res,
1624                            const char *app_id, const char *data,
1625                            struct wl_resource *output_res)
1626 {
1627         struct weston_head *head = weston_head_from_resource(output_res);
1628         struct weston_output *woutput = weston_head_get_output(head);
1629         struct ivi_output *output = to_ivi_output(woutput);
1630
1631         ivi_layout_activate(output, app_id);
1632         shell_advertise_app_state(output->ivi, app_id,
1633                                   data, AGL_SHELL_DESKTOP_APP_STATE_ACTIVATED);
1634 }
1635
1636 static void
1637 shell_deactivate_app(struct wl_client *client,
1638                    struct wl_resource *shell_res,
1639                    const char *app_id)
1640 {
1641         struct desktop_client *dclient = wl_resource_get_user_data(shell_res);
1642         struct ivi_compositor *ivi = dclient->ivi;
1643
1644         ivi_layout_deactivate(ivi, app_id);
1645         shell_advertise_app_state(ivi, app_id,
1646                                   NULL, AGL_SHELL_DESKTOP_APP_STATE_DEACTIVATED);
1647 }
1648
1649 static void
1650 shell_destroy(struct wl_client *client, struct wl_resource *res)
1651 {
1652         struct  ivi_compositor *ivi = wl_resource_get_user_data(res);
1653
1654         /* reset status in case bind_fail was sent */
1655         if (wl_resource_get_version(res) >= AGL_SHELL_BOUND_OK_SINCE_VERSION &&
1656             ivi->shell_client.status == BOUND_FAILED)
1657                 ivi->shell_client.status = BOUND_OK;
1658 }
1659
1660 static void
1661 shell_set_activate_region(struct wl_client *client, struct wl_resource *res,
1662                          struct wl_resource *output, int x, int y,
1663                          int width, int height)
1664 {
1665        struct ivi_compositor *ivi = wl_resource_get_user_data(res);
1666        struct weston_head *head = weston_head_from_resource(output);
1667        struct weston_output *woutput = weston_head_get_output(head);
1668        struct ivi_output *ioutput = to_ivi_output(woutput);
1669
1670        struct weston_geometry area = { .x = x, .y = y,
1671                                        .width = width,
1672                                        .height = height };
1673        if (ivi->shell_client.ready)
1674                return;
1675
1676        ioutput->area_activation = area;
1677 }
1678
1679 static void
1680 shell_set_app_output(struct wl_client *client, struct wl_resource *res,
1681                     const char *app_id, struct wl_resource *output)
1682 {
1683         struct ivi_compositor *ivi = wl_resource_get_user_data(res);
1684         struct weston_head *head = weston_head_from_resource(output);
1685         struct weston_output *woutput = weston_head_get_output(head);
1686         struct ivi_output *ioutput = to_ivi_output(woutput);
1687         struct ivi_surface *surf = ivi_find_app(ivi, app_id);
1688         struct ivi_output *desktop_last_output;
1689         struct ivi_output *current_completed_output;
1690
1691         if (!app_id || !ioutput)
1692                 return;
1693
1694         /* handle the case we're not mapped at all */
1695         if (!surf) {
1696                 ivi_set_pending_desktop_surface_remote(ioutput, app_id);
1697                 shell_send_app_on_output(ivi, app_id, woutput->name);
1698                 return;
1699         }
1700
1701         desktop_last_output = surf->desktop.last_output;
1702         current_completed_output = surf->current_completed_output;
1703
1704         if (surf->remote.output)
1705                 surf->hidden_layer_output = surf->remote.output;
1706         else
1707                 surf->hidden_layer_output = desktop_last_output;
1708         assert(surf->hidden_layer_output);
1709
1710         if (ivi_surface_count_one(current_completed_output, IVI_SURFACE_ROLE_REMOTE) ||
1711             ivi_surface_count_one(current_completed_output, IVI_SURFACE_ROLE_DESKTOP)) {
1712                 if (!current_completed_output->background)
1713                         insert_black_curtain(current_completed_output);
1714         } else {
1715                 ivi_layout_deactivate(ivi, app_id);
1716         }
1717
1718         /* update the remote output */
1719         surf->remote.output = ioutput;
1720
1721         if (surf->role != IVI_SURFACE_ROLE_REMOTE) {
1722                 wl_list_remove(&surf->link);
1723                 wl_list_init(&surf->link);
1724
1725                 surf->role = IVI_SURFACE_ROLE_NONE;
1726                 ivi_set_desktop_surface_remote(surf);
1727         }
1728
1729         shell_send_app_on_output(ivi, app_id, woutput->name);
1730 }
1731
1732 static void
1733 shell_set_app_position(struct wl_client *client, struct wl_resource *res,
1734                     const char *app_id, int32_t x, int32_t y)
1735 {
1736         struct ivi_compositor *ivi = wl_resource_get_user_data(res);
1737         struct ivi_surface *surf = ivi_find_app(ivi, app_id);
1738
1739         if (!surf || !app_id || surf->role != IVI_SURFACE_ROLE_POPUP)
1740                 return;
1741
1742         weston_view_set_position(surf->view, x, y);
1743         weston_compositor_schedule_repaint(ivi->compositor);
1744 }
1745
1746 static void
1747 shell_set_app_scale(struct wl_client *client, struct wl_resource *res,
1748                     const char *app_id, int32_t width, int32_t height)
1749 {
1750
1751         struct ivi_compositor *ivi = wl_resource_get_user_data(res);
1752         struct ivi_surface *surf = ivi_find_app(ivi, app_id);
1753
1754         if (!surf || !app_id || surf->role != IVI_SURFACE_ROLE_POPUP)
1755                 return;
1756
1757         weston_desktop_surface_set_size(surf->dsurface, width, height);
1758         weston_compositor_schedule_repaint(ivi->compositor);
1759 }
1760
1761 static void
1762 _ivi_set_pending_desktop_surface_split(struct wl_resource *output,
1763                                        const char *app_id, uint32_t orientation)
1764 {
1765         weston_log("%s() added split surface for app_id '%s' with "
1766                 "orientation %d to pending\n", __func__, app_id, orientation);
1767
1768         struct weston_head *head = weston_head_from_resource(output);
1769         struct weston_output *woutput = weston_head_get_output(head);
1770         struct ivi_output *ivi_output = to_ivi_output(woutput);
1771
1772         struct pending_app_tile *app_tile = zalloc(sizeof(*app_tile));
1773
1774         app_tile->base.app_id = strdup(app_id);
1775         app_tile->base.ioutput = ivi_output;
1776         app_tile->base.role = IVI_SURFACE_ROLE_TILE;
1777
1778         app_tile->orientation = orientation;
1779         wl_list_insert(&ivi_output->ivi->pending_apps, &app_tile->base.link);
1780 }
1781
1782
1783 const char *
1784 split_orientation_to_string(uint32_t orientation)
1785 {
1786         switch (orientation) {
1787         case AGL_SHELL_TILE_ORIENTATION_LEFT:
1788                 return "tile_left";
1789         break;
1790         case AGL_SHELL_TILE_ORIENTATION_RIGHT:
1791                 return "tile_right";
1792         break;
1793         case AGL_SHELL_TILE_ORIENTATION_TOP:
1794                 return "title_top";
1795         break;
1796         case AGL_SHELL_TILE_ORIENTATION_BOTTOM:
1797                 return "tile_bottom";
1798         break;
1799         default:
1800                 return "none";
1801         }
1802 }
1803
1804 static uint32_t
1805 reverse_orientation(uint32_t orientation)
1806 {
1807
1808         switch (orientation) {
1809         case AGL_SHELL_TILE_ORIENTATION_LEFT:
1810                 return AGL_SHELL_TILE_ORIENTATION_RIGHT;
1811         break;
1812         case AGL_SHELL_TILE_ORIENTATION_RIGHT:
1813                 return AGL_SHELL_TILE_ORIENTATION_LEFT;
1814         break;
1815         case AGL_SHELL_TILE_ORIENTATION_TOP:
1816                 return AGL_SHELL_TILE_ORIENTATION_BOTTOM;
1817         break;
1818         case AGL_SHELL_TILE_ORIENTATION_BOTTOM:
1819                 return AGL_SHELL_TILE_ORIENTATION_TOP;
1820         break;
1821         default:
1822                 return AGL_SHELL_TILE_ORIENTATION_NONE;
1823         }
1824 }
1825
1826 void
1827 _ivi_set_shell_surface_split(struct ivi_surface *surface, struct ivi_output *ioutput,
1828                              uint32_t orientation, uint32_t width, int32_t sticky,
1829                              bool to_activate)
1830 {
1831         struct ivi_compositor *ivi = surface->ivi;
1832         struct weston_geometry geom = {};
1833         struct ivi_output *output = NULL;
1834
1835         int new_width, new_height;
1836         int x, y;
1837
1838         geom = weston_desktop_surface_get_geometry(surface->dsurface);
1839         output = ivi_layout_get_output_from_surface(surface);
1840
1841         if (!output)
1842                 output = ioutput;
1843
1844         // if we don't supply a width we automatically default to doing a half
1845         // split, each window taking half of the current output
1846         switch (orientation) {
1847         case AGL_SHELL_TILE_ORIENTATION_LEFT:
1848         case AGL_SHELL_TILE_ORIENTATION_RIGHT:
1849                 if (width == 0) {
1850                         new_width = output->area.width / 2;
1851                         new_height = output->area.height;
1852                 } else {
1853                         new_width = width;
1854                         new_height = output->area.height;
1855                 }
1856         break;
1857         case AGL_SHELL_TILE_ORIENTATION_TOP:
1858         case AGL_SHELL_TILE_ORIENTATION_BOTTOM:
1859                 if (width == 0) {
1860                         new_width = output->area.width;
1861                         new_height = output->area.height / 2;
1862                 } else {
1863                         new_width = output->area.width;
1864                         new_height = width;
1865                 }
1866         break;
1867         case AGL_SHELL_TILE_ORIENTATION_NONE:
1868                 /* use the current_completed_output because the sticky window
1869                  * might have changed the output area */
1870                 new_width = surface->current_completed_output->area_activation.width;
1871                 new_height = surface->current_completed_output->area_activation.height;
1872
1873                 if (new_width != output->area.width)
1874                         output->area.width = new_width;
1875
1876                 if (new_height != output->area.height)
1877                         output->area.height = new_height;
1878
1879                 weston_log("Adjusting activation area "
1880                            "to %dX%d\n", output->area.width, output->area.height);
1881
1882                 if (surface->sticky) {
1883                         surface->sticky = 0;
1884                         weston_log("Resetting sticky window\n");
1885                 }
1886
1887                 surface->role = IVI_SURFACE_ROLE_DESKTOP;
1888                 weston_log("Resetting tile role to desktop\n");
1889         break;
1890         default:
1891                 /* nothing */
1892                 assert(!"Invalid orientation passed");
1893
1894         }
1895
1896         x = output->area.x - geom.x;
1897         y = output->area.y - geom.y;
1898
1899         if (orientation == AGL_SHELL_TILE_ORIENTATION_RIGHT)
1900                 x += output->area.width - new_width;
1901         else if (orientation == AGL_SHELL_TILE_ORIENTATION_BOTTOM)
1902                 y += output->area.height - new_height;
1903
1904
1905         if (to_activate) {
1906                 struct weston_view *ev = surface->view;
1907                 struct ivi_shell_seat *ivi_seat = NULL;
1908                 struct weston_seat *wseat = get_ivi_shell_weston_first_seat(ivi);
1909
1910                 if (wseat)
1911                         ivi_seat = get_ivi_shell_seat(wseat);
1912
1913                 if (!weston_view_is_mapped(ev))
1914                         weston_view_update_transform(ev);
1915                 else
1916                         weston_layer_entry_remove(&ev->layer_link);
1917
1918
1919                 // mark view as mapped
1920                 ev->is_mapped = true;
1921                 ev->surface->is_mapped = true;
1922                 surface->mapped = true;
1923
1924                 // update older/new active surface
1925                 output->previous_active = output->active;
1926                 output->active = surface;
1927
1928                 // add to the layer and inflict damage
1929                 weston_view_set_output(ev, output->output);
1930                 weston_layer_entry_insert(&ivi->normal.view_list, &ev->layer_link);
1931                 weston_view_geometry_dirty(ev);
1932                 weston_surface_damage(ev->surface);
1933
1934                 // handle input / keyboard
1935                 if (ivi_seat)
1936                         ivi_shell_activate_surface(surface, ivi_seat, WESTON_ACTIVATE_FLAG_NONE);
1937         }
1938
1939
1940         weston_view_set_position(surface->view, x, y);
1941         weston_desktop_surface_set_size(surface->dsurface, new_width, new_height);
1942         weston_desktop_surface_set_orientation(surface->dsurface, orientation);
1943         surface->orientation = orientation;
1944
1945         weston_compositor_schedule_repaint(ivi->compositor);
1946
1947         if (sticky)
1948                 surface->sticky = sticky;
1949
1950         if (orientation != AGL_SHELL_TILE_ORIENTATION_NONE) {
1951                 surface->role = IVI_SURFACE_ROLE_TILE;
1952                 weston_log("Found split orientation different that none, "
1953                            "setting surface role to orientation tile\n");
1954         }
1955
1956         if (surface->sticky) {
1957                 if (orientation == AGL_SHELL_TILE_ORIENTATION_LEFT ||
1958                     orientation == AGL_SHELL_TILE_ORIENTATION_RIGHT)
1959                         output->area.width -= new_width;
1960
1961                 if (orientation == AGL_SHELL_TILE_ORIENTATION_TOP ||
1962                     orientation == AGL_SHELL_TILE_ORIENTATION_BOTTOM)
1963                         output->area.height -= new_height;
1964
1965                 weston_log("Found sticky window, adjusting activation area "
1966                            "to %dX%d\n", output->area.width, output->area.height);
1967         }
1968 }
1969
1970 static int
1971 shell_ivi_surf_count_split_surfaces(struct ivi_compositor *ivi)
1972 {
1973         int count = 0;
1974         struct ivi_surface *surf;
1975
1976         wl_list_for_each(surf, &ivi->surfaces, link) {
1977                 if (surf->orientation > AGL_SHELL_TILE_ORIENTATION_NONE)
1978                         count++;
1979         }
1980
1981         return count;
1982 }
1983
1984
1985 static
1986 void shell_set_app_split(struct wl_client *client, struct wl_resource *res,
1987                          const char *app_id, uint32_t orientation, int32_t width,
1988                          int32_t sticky, struct wl_resource *output_res)
1989 {
1990         struct ivi_surface *surf;
1991         struct ivi_compositor *ivi = wl_resource_get_user_data(res);
1992
1993         struct weston_head *head = weston_head_from_resource(output_res);
1994         struct weston_output *woutput = weston_head_get_output(head);
1995         struct ivi_output *output = to_ivi_output(woutput);
1996
1997         if (!app_id)
1998                 return;
1999
2000         if (shell_ivi_surf_count_split_surfaces(ivi) > 2) {
2001                 weston_log("Found more than two split surfaces in tile orientation.\n");
2002                 return;
2003         }
2004
2005         /* add it as pending until */
2006         surf = ivi_find_app(ivi, app_id);
2007         if (!surf) {
2008                 _ivi_set_pending_desktop_surface_split(output_res, app_id, orientation);
2009                 return;
2010         }
2011
2012         if (output->previous_active && output->background != output->previous_active) {
2013                 struct weston_view *ev = output->previous_active->view;
2014                 int width_prev_app = 0;
2015                 const char *prev_app_id = 
2016                         weston_desktop_surface_get_app_id(output->previous_active->dsurface);
2017
2018                 if (!weston_view_is_mapped(ev))
2019                         weston_view_update_transform(ev);
2020                 else
2021                         weston_layer_entry_remove(&ev->layer_link);
2022
2023                 ev->is_mapped = true;
2024                 ev->surface->is_mapped = true;
2025                 output->previous_active->mapped = true;
2026
2027                 weston_view_set_output(ev, woutput);
2028
2029                 weston_layer_entry_insert(&ivi->normal.view_list, &ev->layer_link);
2030
2031                 /* a 0 width means we have no explicit width set-up */
2032                 if (width > 0) {
2033                         if (orientation == AGL_SHELL_TILE_ORIENTATION_TOP ||
2034                             orientation == AGL_SHELL_TILE_ORIENTATION_BOTTOM)
2035                                 width_prev_app = output->area.height - width;
2036                         else
2037                                 width_prev_app = output->area.width - width;
2038                 }
2039
2040                 weston_log("Setting previous application '%s' to orientation '%s' width %d, not sticky\n",
2041                            prev_app_id, split_orientation_to_string(reverse_orientation(orientation)),
2042                            width_prev_app);
2043
2044                 _ivi_set_shell_surface_split(output->previous_active, NULL,
2045                                              reverse_orientation(orientation),
2046                                              width_prev_app, false, false);
2047
2048                 if (orientation == AGL_SHELL_TILE_ORIENTATION_NONE &&
2049                     output->active == surf) {
2050                         output->active = output->previous_active;
2051                 }
2052         }
2053
2054         weston_log("Setting application '%s' to orientation '%s' width %d, %s\n",
2055                    app_id, split_orientation_to_string(orientation),
2056                    width, sticky == 1 ? "sticky" : "not sticky");
2057         _ivi_set_shell_surface_split(surf, NULL, orientation, width, sticky, false);
2058 }
2059
2060 static void
2061 shell_ext_destroy(struct wl_client *client, struct wl_resource *res)
2062 {
2063         struct  ivi_compositor *ivi = wl_resource_get_user_data(res);
2064
2065         ivi->shell_client_ext.doas_requested = false;
2066         wl_resource_destroy(res);
2067 }
2068
2069 static void
2070 shell_ext_doas(struct wl_client *client, struct wl_resource *res)
2071 {
2072         struct  ivi_compositor *ivi = wl_resource_get_user_data(res);
2073
2074         ivi->shell_client_ext.doas_requested = true;
2075
2076         if (ivi->shell_client_ext.resource && ivi->shell_client.resource) {
2077                 ivi->shell_client_ext.doas_requested_pending_bind = true;
2078
2079                 agl_shell_ext_send_doas_done(ivi->shell_client_ext.resource,
2080                                              AGL_SHELL_EXT_DOAS_SHELL_CLIENT_STATUS_SUCCESS);
2081         } else {
2082                 agl_shell_ext_send_doas_done(ivi->shell_client_ext.resource,
2083                                              AGL_SHELL_EXT_DOAS_SHELL_CLIENT_STATUS_FAILED);
2084         }
2085
2086 }
2087
2088 static const struct agl_shell_interface agl_shell_implementation = {
2089         .ready = shell_ready,
2090         .set_background = shell_set_background,
2091         .set_panel = shell_set_panel,
2092         .activate_app = shell_activate_app,
2093         .destroy = shell_destroy,
2094         .set_activate_region = shell_set_activate_region,
2095         .deactivate_app = shell_new_deactivate_app,
2096         .set_app_float = shell_set_app_float,
2097         .set_app_normal = shell_set_app_normal,
2098         .set_app_fullscreen = shell_set_app_fullscreen,
2099         .set_app_output = shell_set_app_output,
2100         .set_app_position = shell_set_app_position,
2101         .set_app_scale = shell_set_app_scale,
2102         .set_app_split = shell_set_app_split,
2103 };
2104
2105 static const struct agl_shell_ext_interface agl_shell_ext_implementation = {
2106         .destroy = shell_ext_destroy,
2107         .doas_shell_client = shell_ext_doas,
2108 };
2109
2110 static void
2111 shell_desktop_set_app_property(struct wl_client *client,
2112                                struct wl_resource *shell_res,
2113                                const char *app_id, uint32_t role,
2114                                int x, int y, int bx, int by,
2115                                int width, int height,
2116                                struct wl_resource *output_res)
2117 {
2118         struct weston_head *head = weston_head_from_resource(output_res);
2119         struct weston_output *woutput = weston_head_get_output(head);
2120         struct ivi_output *output = to_ivi_output(woutput);
2121
2122         switch (role) {
2123         case AGL_SHELL_DESKTOP_APP_ROLE_POPUP:
2124                 ivi_set_pending_desktop_surface_popup(output, x, y, bx, by,
2125                                                       width, height, app_id);
2126                 break;
2127         case AGL_SHELL_DESKTOP_APP_ROLE_FULLSCREEN:
2128                 ivi_set_pending_desktop_surface_fullscreen(output, app_id);
2129                 break;
2130         case AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_VERTICAL:
2131         case AGL_SHELL_DESKTOP_APP_ROLE_SPLIT_HORIZONTAL:
2132                 ivi_set_pending_desktop_surface_split(output, app_id, role);
2133                 break;
2134         case AGL_SHELL_DESKTOP_APP_ROLE_REMOTE:
2135                 ivi_set_pending_desktop_surface_remote(output, app_id);
2136                 break;
2137         default:
2138                 break;
2139         }
2140 }
2141
2142 void
2143 ivi_compositor_destroy_pending_surfaces(struct ivi_compositor *ivi)
2144 {
2145         struct pending_popup *p_popup, *next_p_popup;
2146         struct pending_split *split_surf, *next_split_surf;
2147         struct pending_fullscreen *fs_surf, *next_fs_surf;
2148         struct pending_remote *remote_surf, *next_remote_surf;
2149
2150         wl_list_for_each_safe(p_popup, next_p_popup,
2151                               &ivi->popup_pending_apps, link)
2152                 ivi_remove_pending_desktop_surface_popup(p_popup);
2153
2154         wl_list_for_each_safe(split_surf, next_split_surf,
2155                               &ivi->split_pending_apps, link)
2156                 ivi_remove_pending_desktop_surface_split(split_surf);
2157
2158         wl_list_for_each_safe(fs_surf, next_fs_surf,
2159                               &ivi->fullscreen_pending_apps, link)
2160                 ivi_remove_pending_desktop_surface_fullscreen(fs_surf);
2161
2162         wl_list_for_each_safe(remote_surf, next_remote_surf,
2163                               &ivi->remote_pending_apps, link)
2164                 ivi_remove_pending_desktop_surface_remote(remote_surf);
2165 }
2166
2167 static void
2168 shell_desktop_set_app_property_mode(struct wl_client *client,
2169                                     struct wl_resource *shell_res, uint32_t perm)
2170 {
2171         struct desktop_client *dclient = wl_resource_get_user_data(shell_res);
2172         if (perm) {
2173                 dclient->ivi->keep_pending_surfaces = true;
2174         } else {
2175                 dclient->ivi->keep_pending_surfaces = false;
2176                 /* remove any previous pending surfaces */
2177                 ivi_compositor_destroy_pending_surfaces(dclient->ivi);
2178         }
2179 }
2180
2181 static const struct agl_shell_desktop_interface agl_shell_desktop_implementation = {
2182         .activate_app = shell_desktop_activate_app,
2183         .set_app_property = shell_desktop_set_app_property,
2184         .deactivate_app = shell_deactivate_app,
2185         .set_app_property_mode = shell_desktop_set_app_property_mode,
2186 };
2187
2188 static void
2189 unbind_agl_shell(struct wl_resource *resource)
2190 {
2191         struct ivi_compositor *ivi;
2192         struct ivi_output *output;
2193         struct ivi_surface *surf, *surf_tmp;
2194
2195         ivi = wl_resource_get_user_data(resource);
2196
2197         /* reset status to allow other clients issue legit requests */
2198         if (wl_resource_get_version(resource) >=
2199             AGL_SHELL_BOUND_OK_SINCE_VERSION &&
2200             ivi->shell_client.status == BOUND_FAILED) {
2201                 ivi->shell_client.status = BOUND_OK;
2202                 return;
2203         }
2204
2205         wl_list_for_each(output, &ivi->outputs, link) {
2206
2207                 /* reset the active surf if there's one present */
2208                 if (output->active) {
2209                         struct weston_geometry area = {};
2210
2211                         output->active->view->is_mapped = false;
2212                         output->active->view->surface->is_mapped = false;
2213
2214                         weston_layer_entry_remove(&output->active->view->layer_link);
2215                         output->active = NULL;
2216
2217                         output->area_activation = area;
2218                 }
2219
2220                 insert_black_curtain(output);
2221         }
2222
2223         wl_list_for_each_safe(surf, surf_tmp, &ivi->surfaces, link) {
2224                 wl_list_remove(&surf->link);
2225                 wl_list_init(&surf->link);
2226         }
2227
2228         wl_list_for_each_safe(surf, surf_tmp, &ivi->pending_surfaces, link) {
2229                 wl_list_remove(&surf->link);
2230                 wl_list_init(&surf->link);
2231         }
2232
2233         wl_list_init(&ivi->surfaces);
2234         wl_list_init(&ivi->pending_surfaces);
2235
2236         ivi->shell_client.ready = false;
2237         ivi->shell_client.resource = NULL;
2238         ivi->shell_client.resource_ext = NULL;
2239         ivi->shell_client.client = NULL;
2240 }
2241
2242 static void
2243 unbind_agl_shell_ext(struct wl_resource *resource)
2244 {
2245         struct ivi_compositor *ivi = wl_resource_get_user_data(resource);
2246
2247         ivi->shell_client_ext.resource = NULL;
2248         ivi->shell_client.resource_ext = NULL;
2249         ivi->shell_client_ext.doas_requested = false;
2250 }
2251
2252 static void
2253 bind_agl_shell(struct wl_client *client,
2254                void *data, uint32_t version, uint32_t id)
2255 {
2256         struct ivi_compositor *ivi = data;
2257         struct wl_resource *resource;
2258         struct ivi_policy *policy;
2259         void *interface;
2260
2261         policy = ivi->policy;
2262         interface = (void *) &agl_shell_interface;
2263         if (policy && policy->api.shell_bind_interface &&
2264             !policy->api.shell_bind_interface(client, interface)) {
2265                 wl_client_post_implementation_error(client,
2266                                        "client not authorized to use agl_shell");
2267                 return;
2268         }
2269
2270         resource = wl_resource_create(client, &agl_shell_interface, version, id);
2271         if (!resource) {
2272                 wl_client_post_no_memory(client);
2273                 return;
2274         }
2275
2276         if (ivi->shell_client.resource && wl_resource_get_version(resource) == 1) {
2277                 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
2278                                 "agl_shell has already been bound (version 1)");
2279                 wl_resource_destroy(resource);
2280                 return;
2281         }
2282
2283         // for agl_shell client proxy
2284         if (ivi->shell_client.resource &&
2285             ivi->shell_client_ext.doas_requested_pending_bind) {
2286
2287                 ivi->shell_client_ext.doas_requested_pending_bind = false;
2288
2289                 // if there's one connected
2290                 if (ivi->shell_client.resource_ext) {
2291                         ivi->shell_client_ext.status = BOUND_FAILED;
2292                         agl_shell_send_bound_fail(ivi->shell_client.resource_ext);
2293                         wl_resource_destroy(resource);
2294                         return;
2295                 }
2296
2297                 wl_resource_set_implementation(resource, &agl_shell_implementation,
2298                                                ivi, NULL);
2299                 ivi->shell_client.resource_ext = resource;
2300                 ivi->shell_client_ext.status = BOUND_OK;
2301                 agl_shell_send_bound_ok(ivi->shell_client.resource_ext);
2302                 return;
2303         }
2304
2305
2306         // if we already have an agl_shell client
2307         if (ivi->shell_client.resource) {
2308                 agl_shell_send_bound_fail(resource);
2309                 ivi->shell_client.status = BOUND_FAILED;
2310                 wl_resource_destroy(resource);
2311                 return;
2312         }
2313
2314         // default agl_shell client
2315         wl_resource_set_implementation(resource, &agl_shell_implementation,
2316                                        ivi, unbind_agl_shell);
2317         ivi->shell_client.resource = resource;
2318
2319         if (wl_resource_get_version(resource) >=
2320             AGL_SHELL_BOUND_OK_SINCE_VERSION) {
2321                 /* if we land here we'll have BOUND_OK by default,
2322                    but still do the assignment */
2323                 ivi->shell_client.status = BOUND_OK;
2324                 agl_shell_send_bound_ok(ivi->shell_client.resource);
2325         }
2326 }
2327
2328 static void
2329 bind_agl_shell_ext(struct wl_client *client,
2330                    void *data, uint32_t version, uint32_t id)
2331 {
2332         struct ivi_compositor *ivi = data;
2333         struct wl_resource *resource;
2334
2335         resource = wl_resource_create(client, &agl_shell_ext_interface, version, id);
2336         if (!resource) {
2337                 wl_client_post_no_memory(client);
2338                 return;
2339         }
2340
2341         if (ivi->shell_client_ext.resource) {
2342                 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
2343                                        "agl_shell_ext has already been bound");
2344                 return;
2345         }
2346
2347         wl_resource_set_implementation(resource, &agl_shell_ext_implementation,
2348                                        ivi, unbind_agl_shell_ext);
2349         ivi->shell_client_ext.resource = resource;
2350 }
2351
2352 static void
2353 unbind_agl_shell_desktop(struct wl_resource *resource)
2354 {
2355         struct desktop_client *dclient = wl_resource_get_user_data(resource);
2356
2357         wl_list_remove(&dclient->link);
2358         free(dclient);
2359 }
2360
2361 static void
2362 bind_agl_shell_desktop(struct wl_client *client,
2363                        void *data, uint32_t version, uint32_t id)
2364 {
2365         struct ivi_compositor *ivi = data;
2366         struct wl_resource *resource;
2367         struct ivi_policy *policy;
2368         struct desktop_client *dclient;
2369         void *interface;
2370
2371         policy = ivi->policy;
2372         interface  = (void *) &agl_shell_desktop_interface;
2373         if (policy && policy->api.shell_bind_interface &&
2374             !policy->api.shell_bind_interface(client, interface)) {
2375                 wl_client_post_implementation_error(client,
2376                                 "client not authorized to use agl_shell_desktop");
2377                 return;
2378         }
2379
2380         dclient = zalloc(sizeof(*dclient));
2381         if (!dclient) {
2382                 wl_client_post_no_memory(client);
2383                 return;
2384         }
2385
2386         resource = wl_resource_create(client, &agl_shell_desktop_interface,
2387                                       version, id);
2388         dclient->ivi = ivi;
2389         if (!resource) {
2390                 wl_client_post_no_memory(client);
2391                 return;
2392         }
2393
2394         wl_resource_set_implementation(resource, &agl_shell_desktop_implementation,
2395                                        dclient, unbind_agl_shell_desktop);
2396
2397         dclient->resource = resource;
2398         wl_list_insert(&ivi->desktop_clients, &dclient->link);
2399
2400         /* advertise xdg surfaces */
2401         ivi_shell_advertise_xdg_surfaces(ivi, resource);
2402 }
2403
2404 int
2405 ivi_shell_create_global(struct ivi_compositor *ivi)
2406 {
2407         ivi->agl_shell = wl_global_create(ivi->compositor->wl_display,
2408                                           &agl_shell_interface, 11,
2409                                           ivi, bind_agl_shell);
2410         if (!ivi->agl_shell) {
2411                 weston_log("Failed to create wayland global.\n");
2412                 return -1;
2413         }
2414
2415         ivi->agl_shell_ext = wl_global_create(ivi->compositor->wl_display,
2416                                               &agl_shell_ext_interface, 1,
2417                                               ivi, bind_agl_shell_ext);
2418         if (!ivi->agl_shell_ext) {
2419                 weston_log("Failed to create agl_shell_ext global.\n");
2420                 return -1;
2421         }
2422
2423         ivi->agl_shell_desktop = wl_global_create(ivi->compositor->wl_display,
2424                                                   &agl_shell_desktop_interface, 2,
2425                                                   ivi, bind_agl_shell_desktop);
2426         if (!ivi->agl_shell_desktop) {
2427                 weston_log("Failed to create wayland global (agl_shell_desktop).\n");
2428                 return -1;
2429         }
2430
2431         return 0;
2432 }