ea1e68403f23acb81d60e58bb38c47c2dff3d71e
[src/agl-compositor.git] / src / layout.c
1 /*
2  * Copyright © 2019 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 #include "shared/helpers.h"
29
30 #include <assert.h>
31 #include <string.h>
32
33 #include <libweston/libweston.h>
34 #include <libweston-desktop/libweston-desktop.h>
35
36 #include "agl-shell-desktop-server-protocol.h"
37
38 #define AGL_COMP_DEBUG
39
40 static const char *ivi_roles_as_string[] = {
41         [IVI_SURFACE_ROLE_NONE]         = "NONE",
42         [IVI_SURFACE_ROLE_BACKGROUND]   = "BACKGROUND",
43         [IVI_SURFACE_ROLE_PANEL]        = "PANEL",
44         [IVI_SURFACE_ROLE_DESKTOP]      = "DESKTOP",
45         [IVI_SURFACE_ROLE_POPUP]        = "POPUP",
46         [IVI_SURFACE_ROLE_SPLIT_H]      = "SPLIT_H",
47         [IVI_SURFACE_ROLE_SPLIT_V]      = "SPLIT_V",
48         [IVI_SURFACE_ROLE_FULLSCREEN]   = "FULLSCREEN",
49         [IVI_SURFACE_ROLE_REMOTE]       = "REMOTE",
50 };
51
52 const char *
53 ivi_layout_get_surface_role_name(struct ivi_surface *surf)
54 {
55         if (surf->role < 0 || surf->role >= ARRAY_LENGTH(ivi_roles_as_string))
56                 return " unknown surface role";
57
58         return ivi_roles_as_string[surf->role];
59 }
60
61 static void
62 ivi_background_init(struct ivi_compositor *ivi, struct ivi_output *output)
63 {
64         struct weston_output *woutput = output->output;
65         struct ivi_surface *bg = output->background;
66         struct weston_view *view;
67
68         if (!bg) {
69                 weston_log("WARNING: Output does not have a background\n");
70                 return;
71         }
72
73         assert(bg->role == IVI_SURFACE_ROLE_BACKGROUND);
74
75         view = bg->view;
76
77         weston_view_set_output(view, woutput);
78         weston_view_set_position(view, woutput->x, woutput->y);
79
80 #ifdef AGL_COMP_DEBUG
81         weston_log("(background) position view %p, x %d, y %d\n", view,
82                         woutput->x, woutput->y);
83 #endif
84
85         view->is_mapped = true;
86         view->surface->is_mapped = true;
87
88         weston_layer_entry_insert(&ivi->background.view_list, &view->layer_link);
89 }
90
91 static void
92 ivi_panel_init(struct ivi_compositor *ivi, struct ivi_output *output,
93                struct ivi_surface *panel)
94 {
95         struct weston_output *woutput = output->output;
96         struct weston_desktop_surface *dsurface;
97         struct weston_view *view;
98         struct weston_geometry geom;
99         int x = woutput->x;
100         int y = woutput->y;
101
102         if (!panel)
103                 return;
104
105         assert(panel->role == IVI_SURFACE_ROLE_PANEL);
106         dsurface = panel->dsurface;
107         view = panel->view;
108         geom = weston_desktop_surface_get_geometry(dsurface);
109 #ifdef AGL_COMP_DEBUG
110         weston_log("(panel) geom.width %d, geom.height %d, geom.x %d, geom.y %d\n",
111                         geom.width, geom.height, geom.x, geom.y);
112 #endif
113         switch (panel->panel.edge) {
114         case AGL_SHELL_EDGE_TOP:
115                 output->area.y += geom.height;
116                 output->area.height -= geom.height;
117                 break;
118         case AGL_SHELL_EDGE_BOTTOM:
119                 y += woutput->height - geom.height;
120                 output->area.height -= geom.height;
121                 break;
122         case AGL_SHELL_EDGE_LEFT:
123                 output->area.x += geom.width;
124                 output->area.width -= geom.width;
125                 break;
126         case AGL_SHELL_EDGE_RIGHT:
127                 x += woutput->width - geom.width;
128                 output->area.width -= geom.width;
129                 break;
130         }
131
132         x -= geom.x;
133         y -= geom.y;
134
135         weston_view_set_output(view, woutput);
136         weston_view_set_position(view, x, y);
137 #ifdef AGL_COMP_DEBUG
138         weston_log("(panel) edge %d position view %p, x %d, y %d\n",
139                         panel->panel.edge, view, x, y);
140 #endif
141
142         /* this is necessary for cases we already mapped it desktop_committed()
143          * but we not running the older qtwayland, so we still have a chance
144          * for this to run at the next test */
145         if (view->surface->is_mapped) {
146                 weston_layer_entry_remove(&view->layer_link);
147
148                 view->is_mapped = false;
149                 view->surface->is_mapped = false;
150         }
151
152         /* give ivi_layout_panel_committed() a chance to map the view/surface
153          * instead */
154         if ((geom.width == geom.height && geom.width == 0) &&
155             (geom.x == geom.y && geom.x == 0) &&
156             panel->panel.edge != AGL_SHELL_EDGE_TOP)
157                 return;
158
159         view->is_mapped = true;
160         view->surface->is_mapped = true;
161 #ifdef AGL_COMP_DEBUG
162         weston_log("panel type %d inited\n", panel->panel.edge);
163 #endif
164         weston_layer_entry_insert(&ivi->panel.view_list, &view->layer_link);
165 }
166
167 /*
168  * Initializes all static parts of the layout, i.e. the background and panels.
169  */
170 void
171 ivi_layout_init(struct ivi_compositor *ivi, struct ivi_output *output)
172 {
173         ivi_background_init(ivi, output);
174
175         output->area.x = 0;
176         output->area.y = 0;
177         output->area.width = output->output->width;
178         output->area.height = output->output->height;
179
180         ivi_panel_init(ivi, output, output->top);
181         ivi_panel_init(ivi, output, output->bottom);
182         ivi_panel_init(ivi, output, output->left);
183         ivi_panel_init(ivi, output, output->right);
184
185         weston_compositor_schedule_repaint(ivi->compositor);
186
187         weston_log("Usable area: %dx%d+%d,%d\n",
188                    output->area.width, output->area.height,
189                    output->area.x, output->area.y);
190 }
191
192 struct ivi_surface *
193 ivi_find_app(struct ivi_compositor *ivi, const char *app_id)
194 {
195         struct ivi_surface *surf;
196         const char *id;
197
198         wl_list_for_each(surf, &ivi->surfaces, link) {
199                 id = weston_desktop_surface_get_app_id(surf->dsurface);
200                 if (id && strcmp(app_id, id) == 0)
201                         return surf;
202         }
203
204         return NULL;
205 }
206
207 static void
208 ivi_layout_activate_complete(struct ivi_output *output,
209                              struct ivi_surface *surf)
210 {
211         struct ivi_compositor *ivi = output->ivi;
212         struct weston_output *woutput = output->output;
213         struct weston_view *view = surf->view;
214
215         if (weston_view_is_mapped(view)) {
216                 weston_layer_entry_remove(&view->layer_link);
217         }
218
219         weston_view_set_output(view, woutput);
220         weston_view_set_position(view,
221                                  woutput->x + output->area.x,
222                                  woutput->y + output->area.y);
223
224         view->is_mapped = true;
225         view->surface->is_mapped = true;
226
227         if (output->active) {
228                 output->active->view->is_mapped = false;
229                 output->active->view->surface->is_mapped = false;
230
231                 weston_layer_entry_remove(&output->active->view->layer_link);
232         }
233         output->previous_active = output->active;
234         output->active = surf;
235
236         weston_layer_entry_insert(&ivi->normal.view_list, &view->layer_link);
237         weston_view_update_transform(view);
238
239         /* force repaint of the entire output */
240         weston_output_damage(output->output);
241
242         /*
243          * the 'remote' role now makes use of this part so make sure we don't
244          * trip the enum such that we might end up with a modified output for
245          * 'remote' role
246          */
247         if (surf->role == IVI_SURFACE_ROLE_DESKTOP) {
248                 if (surf->desktop.pending_output)
249                         surf->desktop.last_output = surf->desktop.pending_output;
250                 surf->desktop.pending_output = NULL;
251         }
252
253         weston_log("Activation completed for app_id %s, role %s\n",
254                         weston_desktop_surface_get_app_id(surf->dsurface),
255                         ivi_layout_get_surface_role_name(surf));
256 }
257
258 static struct ivi_output *
259 ivi_layout_find_app_id(const char *app_id, struct ivi_compositor *ivi)
260 {
261         struct ivi_output *out;
262
263         wl_list_for_each(out, &ivi->outputs, link) {
264                 if (!out->app_id)
265                         continue;
266
267                 if (!strcmp(app_id, out->app_id))
268                         return out;
269         }
270
271         return NULL;
272 }
273
274
275 static struct ivi_output *
276 ivi_layout_find_bg_output(struct ivi_compositor *ivi)
277 {
278         struct ivi_output *out;
279
280         wl_list_for_each(out, &ivi->outputs, link) {
281                 if (out->background &&
282                     out->background->role == IVI_SURFACE_ROLE_BACKGROUND)
283                         return out;
284         }
285
286         return NULL;
287 }
288
289 void
290 ivi_layout_desktop_committed(struct ivi_surface *surf)
291 {
292         struct weston_desktop_surface *dsurf = surf->dsurface;
293         struct weston_geometry geom = weston_desktop_surface_get_geometry(dsurf);
294         struct ivi_policy *policy = surf->ivi->policy;
295         struct ivi_output *output;
296         const char *app_id = weston_desktop_surface_get_app_id(dsurf);
297
298         assert(surf->role == IVI_SURFACE_ROLE_DESKTOP ||
299                surf->role == IVI_SURFACE_ROLE_REMOTE);
300
301         /*
302          * we can't make use here of the ivi_layout_get_output_from_surface()
303          * due to the fact that we'll always land here when a surface performs
304          * a commit and pending_output will not bet set. This works in tandem
305          * with 'activated_by_default' at this point to avoid tripping over
306          * to a surface that continuously updates its content
307          */
308         if (surf->role == IVI_SURFACE_ROLE_DESKTOP)
309                 output = surf->desktop.pending_output;
310         else
311                 output = surf->remote.output;
312
313         if (surf->role == IVI_SURFACE_ROLE_DESKTOP && !output) {
314                 struct ivi_output *r_output;
315
316                 if (policy && policy->api.surface_activate_by_default &&
317                     !policy->api.surface_activate_by_default(surf, surf->ivi))
318                         return;
319
320                 /* we can only activate it again by using the protocol */
321                 if (surf->activated_by_default)
322                         return;
323
324                 /* check first if there aren't any outputs being set */
325                 r_output = ivi_layout_find_app_id(app_id, surf->ivi);
326
327                 if (r_output) {
328                         struct weston_view *view = r_output->fullscreen_view.fs->view;
329                         if (view->is_mapped || view->surface->is_mapped)
330                                 remove_black_surface(r_output);
331                 }
332
333
334                 /* try finding an output with a background and use that */
335                 if (!r_output)
336                         r_output = ivi_layout_find_bg_output(surf->ivi);
337
338                 /* use the output of the bg to activate the app on start-up by
339                  * default */
340                 if (surf->view && r_output) {
341                         if (app_id && r_output) {
342                                 weston_log("Surface with app_id %s, role %s activating by default\n",
343                                         weston_desktop_surface_get_app_id(surf->dsurface),
344                                         ivi_layout_get_surface_role_name(surf));
345                                 ivi_layout_activate(r_output, app_id);
346                                 surf->activated_by_default = true;
347                         }
348                 }
349
350                 return;
351         }
352
353         if (surf->role == IVI_SURFACE_ROLE_REMOTE && output) {
354                 if (policy && policy->api.surface_activate_by_default &&
355                     !policy->api.surface_activate_by_default(surf, surf->ivi))
356                         return;
357
358                 /* we can only activate it again by using the protocol, but
359                  * additionally the output is not reset when
360                  * ivi_layout_activate_complete() terminates so we use the
361                  * current active surface to avoid hitting this again and again
362                  * */
363                 if (surf->activated_by_default && output->active == surf)
364                         return;
365
366                 if (app_id) {
367                         weston_log("Surface with app_id %s, role %s activating by default\n",
368                                         weston_desktop_surface_get_app_id(surf->dsurface),
369                                         ivi_layout_get_surface_role_name(surf));
370                         ivi_layout_activate(output, app_id);
371                         surf->activated_by_default = true;
372                 }
373                 return;
374         }
375
376         if (!weston_desktop_surface_get_maximized(dsurf) ||
377             geom.width != output->area.width ||
378             geom.height != output->area.height)
379                 return;
380
381         ivi_layout_activate_complete(output, surf);
382 }
383
384 void
385 ivi_layout_fullscreen_committed(struct ivi_surface *surface)
386 {
387         struct ivi_compositor *ivi = surface->ivi;
388
389         struct weston_desktop_surface *dsurface = surface->dsurface;
390         struct weston_surface *wsurface =
391                 weston_desktop_surface_get_surface(dsurface);
392
393         struct ivi_output *output = surface->split.output;
394         struct weston_output *woutput = output->output;
395
396         struct weston_view *view = surface->view;
397         struct weston_geometry geom;
398
399         if (surface->view->is_mapped)
400                 return;
401
402         geom = weston_desktop_surface_get_geometry(dsurface);
403         weston_log("(fs) geom x %d, y %d, width %d, height %d\n", geom.x, geom.y,
404                         geom.width, geom.height);
405
406         assert(surface->role == IVI_SURFACE_ROLE_FULLSCREEN);
407
408         weston_desktop_surface_set_fullscreen(dsurface, true);
409
410         weston_view_set_output(view, woutput);
411         weston_view_set_position(view, woutput->x, woutput->y);
412         weston_layer_entry_insert(&ivi->fullscreen.view_list, &view->layer_link);
413
414         weston_view_update_transform(view);
415         weston_view_damage_below(view);
416
417         wsurface->is_mapped = true;
418         surface->view->is_mapped = true;
419 }
420
421 void
422 ivi_layout_desktop_resize(struct ivi_surface *surface,
423                           struct weston_geometry area)
424 {
425         struct weston_desktop_surface *dsurf = surface->dsurface;
426         struct weston_view *view = surface->view;
427
428         int x = area.x;
429         int y = area.y;
430         int width = area.width;
431         int height = area.height;
432
433         weston_desktop_surface_set_size(dsurf,
434                                         width, height);
435
436         weston_view_set_position(view, x, y);
437         weston_view_update_transform(view);
438         weston_view_damage_below(view);
439 }
440
441 void
442 ivi_layout_split_committed(struct ivi_surface *surface)
443 {
444         struct ivi_compositor *ivi = surface->ivi;
445
446         struct weston_desktop_surface *dsurface = surface->dsurface;
447         struct weston_surface *wsurface =
448                 weston_desktop_surface_get_surface(dsurface);
449
450         struct ivi_output *output = surface->split.output;
451         struct weston_output *woutput = output->output;
452
453         struct weston_view *view = surface->view;
454         struct weston_geometry geom;
455
456         int x, y;
457         int width, height;
458
459         x = woutput->x;
460         y = woutput->y;
461
462         if (surface->view->is_mapped)
463                 return;
464
465         geom = weston_desktop_surface_get_geometry(dsurface);
466
467         assert(surface->role == IVI_SURFACE_ROLE_SPLIT_H ||
468                surface->role == IVI_SURFACE_ROLE_SPLIT_V);
469
470         /* save the previous area in order to recover it back when if this kind
471          * of surface is being destroyed/removed */
472         output->area_saved = output->area;
473
474         switch (surface->role) {
475         case IVI_SURFACE_ROLE_SPLIT_V:
476                 if (geom.width == woutput->width &&
477                     geom.height == woutput->height)
478                         geom.width = (output->area.width / 2);
479
480                 x += woutput->width - geom.width;
481                 output->area.width -= geom.width;
482
483                 width = woutput->width - x;
484                 height = output->area.height;
485                 y = output->area.y;
486
487                 break;
488         case IVI_SURFACE_ROLE_SPLIT_H:
489                 if (geom.width == woutput->width &&
490                     geom.height == woutput->height)
491                         geom.height = (output->area.height / 2);
492
493                 y = output->area.y;
494                 output->area.y += geom.height;
495                 output->area.height -= geom.height;
496
497                 width = output->area.width;
498                 height = output->area.height;
499
500                 x = output->area.x;
501
502                 break;
503         default:
504                 assert(!"Invalid split orientation\n");
505         }
506
507         weston_desktop_surface_set_size(dsurface,
508                                         width, height);
509
510         /* resize the active surface first, output->area already contains
511          * correct area to resize to */
512         if (output->active)
513                 ivi_layout_desktop_resize(output->active, output->area);
514
515         weston_view_set_output(view, woutput);
516         weston_view_set_position(view, x, y);
517         weston_layer_entry_insert(&ivi->normal.view_list, &view->layer_link);
518
519         weston_view_update_transform(view);
520         weston_view_damage_below(view);
521
522         wsurface->is_mapped = true;
523         surface->view->is_mapped = true;
524 }
525
526 void
527 ivi_layout_popup_committed(struct ivi_surface *surface)
528 {
529         struct ivi_compositor *ivi = surface->ivi;
530
531         struct weston_desktop_surface *dsurface = surface->dsurface;
532         struct weston_surface *wsurface =
533                 weston_desktop_surface_get_surface(dsurface);
534
535         struct ivi_output *output = surface->popup.output;
536         struct weston_output *woutput = output->output;
537
538         struct weston_view *view = surface->view;
539         struct weston_geometry geom;
540
541         if (surface->view->is_mapped)
542                 return;
543
544         geom = weston_desktop_surface_get_geometry(dsurface);
545         weston_log("(popup) geom x %d, y %d, width %d, height %d\n", geom.x, geom.y,
546                         geom.width, geom.height);
547
548         assert(surface->role == IVI_SURFACE_ROLE_POPUP);
549
550         weston_view_set_output(view, woutput);
551         if (surface->popup.x || surface->popup.y)
552                 weston_view_set_position(view, surface->popup.x, surface->popup.y);
553         else
554                 weston_view_set_position(view, geom.x, geom.y);
555         weston_layer_entry_insert(&ivi->popup.view_list, &view->layer_link);
556
557         weston_view_update_transform(view);
558         weston_view_damage_below(view);
559
560         wsurface->is_mapped = true;
561         surface->view->is_mapped = true;
562 }
563
564 static void
565 ivi_layout_popup_re_add(struct ivi_surface *surface)
566 {
567         assert(surface->role == IVI_SURFACE_ROLE_POPUP);
568         struct weston_view *view = surface->view;
569
570         if (weston_view_is_mapped(view)) {
571                 struct weston_desktop_surface *dsurface = surface->dsurface;
572                 struct weston_surface *wsurface =
573                         weston_desktop_surface_get_surface(dsurface);
574
575                 weston_layer_entry_remove(&view->layer_link);
576
577                 wsurface->is_mapped = false;
578                 view->is_mapped = false;
579         }
580
581         ivi_layout_popup_committed(surface);
582 }
583
584 static bool
585 ivi_layout_surface_is_split_or_fullscreen(struct ivi_surface *surf)
586 {
587         struct ivi_compositor *ivi = surf->ivi;
588         struct ivi_surface *is;
589
590         if (surf->role != IVI_SURFACE_ROLE_SPLIT_H &&
591             surf->role != IVI_SURFACE_ROLE_SPLIT_V &&
592             surf->role != IVI_SURFACE_ROLE_FULLSCREEN)
593                 return false;
594
595         wl_list_for_each(is, &ivi->surfaces, link)
596                 if (is == surf)
597                         return true;
598
599         return false;
600 }
601
602 void
603 ivi_layout_activate(struct ivi_output *output, const char *app_id)
604 {
605         struct ivi_compositor *ivi = output->ivi;
606         struct ivi_surface *surf;
607         struct weston_desktop_surface *dsurf;
608         struct weston_view *view;
609         struct weston_geometry geom;
610         struct ivi_policy *policy = output->ivi->policy;
611
612         surf = ivi_find_app(ivi, app_id);
613         if (!surf)
614                 return;
615
616         if (policy && policy->api.surface_activate &&
617             !policy->api.surface_activate(surf, surf->ivi)) {
618                 return;
619         }
620
621 #ifdef AGL_COMP_DEBUG
622         weston_log("Activating app_id %s, type %s\n", app_id,
623                         ivi_layout_get_surface_role_name(surf));
624 #endif
625
626         if (surf->role == IVI_SURFACE_ROLE_POPUP) {
627                 ivi_layout_popup_re_add(surf);
628                 return;
629         }
630
631         /* do not 're'-activate surfaces that are split or active */
632         if (surf == output->active ||
633             ivi_layout_surface_is_split_or_fullscreen(surf))
634                 return;
635
636
637         dsurf = surf->dsurface;
638         view = surf->view;
639         geom = weston_desktop_surface_get_geometry(dsurf);
640
641         if (surf->role == IVI_SURFACE_ROLE_DESKTOP)
642                 surf->desktop.pending_output = output;
643         if (weston_desktop_surface_get_maximized(dsurf) &&
644             geom.width == output->area.width &&
645             geom.height == output->area.height) {
646                 ivi_layout_activate_complete(output, surf);
647                 return;
648         }
649
650         weston_desktop_surface_set_maximized(dsurf, true);
651         weston_desktop_surface_set_size(dsurf,
652                                         output->area.width,
653                                         output->area.height);
654
655         weston_log("Setting app_id %s, role %s, set to maximized (%dx%d)\n",
656                         app_id, ivi_layout_get_surface_role_name(surf),
657                         output->area.width, output->area.height);
658         /*
659          * If the view isn't mapped, we put it onto the hidden layer so it will
660          * start receiving frame events, and will be able to act on our
661          * configure event.
662          */
663         if (!weston_view_is_mapped(view)) {
664                 view->is_mapped = true;
665                 view->surface->is_mapped = true;
666
667                 weston_view_set_output(view, output->output);
668                 weston_layer_entry_insert(&ivi->hidden.view_list, &view->layer_link);
669                 /* force repaint of the entire output */
670
671                 weston_log("Placed app_id %s, type %s in hidden layer\n",
672                                 app_id, ivi_layout_get_surface_role_name(surf));
673                 weston_output_damage(output->output);
674         }
675 }
676
677 struct ivi_output *
678 ivi_layout_get_output_from_surface(struct ivi_surface *surf)
679 {
680         struct ivi_output *ivi_output = NULL;
681
682         switch (surf->role) {
683         case IVI_SURFACE_ROLE_DESKTOP:
684                 if (surf->desktop.pending_output)
685                         ivi_output = surf->desktop.pending_output;
686                 else
687                         ivi_output = surf->desktop.last_output;
688                 break;
689         case IVI_SURFACE_ROLE_POPUP:
690                 ivi_output = surf->popup.output;
691                 break;
692         case IVI_SURFACE_ROLE_BACKGROUND:
693                 ivi_output = surf->bg.output;
694                 break;
695         case IVI_SURFACE_ROLE_PANEL:
696                 ivi_output = surf->panel.output;
697                 break;
698         case IVI_SURFACE_ROLE_FULLSCREEN:
699                 ivi_output = surf->fullscreen.output;
700                 break;
701         case IVI_SURFACE_ROLE_SPLIT_H:
702         case IVI_SURFACE_ROLE_SPLIT_V:
703                 ivi_output = surf->split.output;
704                 break;
705         case IVI_SURFACE_ROLE_REMOTE:
706                 ivi_output = surf->remote.output;
707                 break;
708         case IVI_SURFACE_ROLE_NONE:
709         default:
710                 break;
711         }
712
713         return ivi_output;
714 }
715
716 void
717 ivi_layout_deactivate(struct ivi_compositor *ivi, const char *app_id)
718 {
719         struct ivi_surface *surf;
720         struct ivi_output *ivi_output;
721         struct ivi_policy *policy = ivi->policy;
722
723         surf = ivi_find_app(ivi, app_id);
724         if (!surf)
725                 return;
726
727         if (policy && policy->api.surface_deactivate &&
728             !policy->api.surface_deactivate(surf, surf->ivi)) {
729                 return;
730         }
731
732         ivi_output = ivi_layout_get_output_from_surface(surf);
733         weston_log("Deactiving %s, role %s\n", app_id,
734                         ivi_layout_get_surface_role_name(surf));
735
736         if (surf->role == IVI_SURFACE_ROLE_DESKTOP) {
737                 struct ivi_surface *previous_active;
738
739                 previous_active = ivi_output->previous_active;
740                 if (!previous_active) {
741                         /* we don't have a previous active it means we should
742                          * display the bg */
743                         if (ivi_output->active) {
744                                 struct weston_view *view;
745
746                                 view = ivi_output->active->view;
747                                 view->is_mapped = false;
748                                 view->surface->is_mapped = false;
749
750                                 weston_layer_entry_remove(&view->layer_link);
751                                 weston_output_damage(ivi_output->output);
752                         }
753                 } else {
754                         struct weston_desktop_surface *dsurface;
755                         const char *previous_active_app_id;
756
757                         dsurface = previous_active->dsurface;
758                         previous_active_app_id =
759                                 weston_desktop_surface_get_app_id(dsurface);
760                         ivi_layout_activate(ivi_output, previous_active_app_id);
761                 }
762         } else if (surf->role == IVI_SURFACE_ROLE_POPUP) {
763                 struct weston_view *view  = surf->view;
764
765                 weston_layer_entry_remove(&view->layer_link);
766                 weston_view_damage_below(view);
767         }
768 }