57992ca0d1b5dd3a678ba5e65e087313f73ab918
[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                 /* try finding an output with a background and use that */
328                 if (!r_output)
329                         r_output = ivi_layout_find_bg_output(surf->ivi);
330
331                 /* use the output of the bg to activate the app on start-up by
332                  * default */
333                 if (surf->view && r_output) {
334                         if (app_id && r_output) {
335                                 weston_log("Surface with app_id %s, role %s activating by default\n",
336                                         weston_desktop_surface_get_app_id(surf->dsurface),
337                                         ivi_layout_get_surface_role_name(surf));
338                                 ivi_layout_activate(r_output, app_id);
339                                 surf->activated_by_default = true;
340                         }
341                 }
342
343                 return;
344         }
345
346         if (surf->role == IVI_SURFACE_ROLE_REMOTE && output) {
347                 if (policy && policy->api.surface_activate_by_default &&
348                     !policy->api.surface_activate_by_default(surf, surf->ivi))
349                         return;
350
351                 /* we can only activate it again by using the protocol, but
352                  * additionally the output is not reset when
353                  * ivi_layout_activate_complete() terminates so we use the
354                  * current active surface to avoid hitting this again and again
355                  * */
356                 if (surf->activated_by_default && output->active == surf)
357                         return;
358
359                 if (app_id) {
360                         weston_log("Surface with app_id %s, role %s activating by default\n",
361                                         weston_desktop_surface_get_app_id(surf->dsurface),
362                                         ivi_layout_get_surface_role_name(surf));
363                         ivi_layout_activate(output, app_id);
364                         surf->activated_by_default = true;
365                 }
366                 return;
367         }
368
369         if (!weston_desktop_surface_get_maximized(dsurf) ||
370             geom.width != output->area.width ||
371             geom.height != output->area.height)
372                 return;
373
374         ivi_layout_activate_complete(output, surf);
375 }
376
377 void
378 ivi_layout_fullscreen_committed(struct ivi_surface *surface)
379 {
380         struct ivi_compositor *ivi = surface->ivi;
381
382         struct weston_desktop_surface *dsurface = surface->dsurface;
383         struct weston_surface *wsurface =
384                 weston_desktop_surface_get_surface(dsurface);
385
386         struct ivi_output *output = surface->split.output;
387         struct weston_output *woutput = output->output;
388
389         struct weston_view *view = surface->view;
390         struct weston_geometry geom;
391
392         if (surface->view->is_mapped)
393                 return;
394
395         geom = weston_desktop_surface_get_geometry(dsurface);
396         weston_log("(fs) geom x %d, y %d, width %d, height %d\n", geom.x, geom.y,
397                         geom.width, geom.height);
398
399         assert(surface->role == IVI_SURFACE_ROLE_FULLSCREEN);
400
401         weston_desktop_surface_set_fullscreen(dsurface, true);
402
403         weston_view_set_output(view, woutput);
404         weston_view_set_position(view, woutput->x, woutput->y);
405         weston_layer_entry_insert(&ivi->fullscreen.view_list, &view->layer_link);
406
407         weston_view_update_transform(view);
408         weston_view_damage_below(view);
409
410         wsurface->is_mapped = true;
411         surface->view->is_mapped = true;
412 }
413
414 void
415 ivi_layout_desktop_resize(struct ivi_surface *surface,
416                           struct weston_geometry area)
417 {
418         struct weston_desktop_surface *dsurf = surface->dsurface;
419         struct weston_view *view = surface->view;
420
421         int x = area.x;
422         int y = area.y;
423         int width = area.width;
424         int height = area.height;
425
426         weston_desktop_surface_set_size(dsurf,
427                                         width, height);
428
429         weston_view_set_position(view, x, y);
430         weston_view_update_transform(view);
431         weston_view_damage_below(view);
432 }
433
434 void
435 ivi_layout_split_committed(struct ivi_surface *surface)
436 {
437         struct ivi_compositor *ivi = surface->ivi;
438
439         struct weston_desktop_surface *dsurface = surface->dsurface;
440         struct weston_surface *wsurface =
441                 weston_desktop_surface_get_surface(dsurface);
442
443         struct ivi_output *output = surface->split.output;
444         struct weston_output *woutput = output->output;
445
446         struct weston_view *view = surface->view;
447         struct weston_geometry geom;
448
449         int x, y;
450         int width, height;
451
452         x = woutput->x;
453         y = woutput->y;
454
455         if (surface->view->is_mapped)
456                 return;
457
458         geom = weston_desktop_surface_get_geometry(dsurface);
459
460         assert(surface->role == IVI_SURFACE_ROLE_SPLIT_H ||
461                surface->role == IVI_SURFACE_ROLE_SPLIT_V);
462
463         /* save the previous area in order to recover it back when if this kind
464          * of surface is being destroyed/removed */
465         output->area_saved = output->area;
466
467         switch (surface->role) {
468         case IVI_SURFACE_ROLE_SPLIT_V:
469                 if (geom.width == woutput->width &&
470                     geom.height == woutput->height)
471                         geom.width = (output->area.width / 2);
472
473                 x += woutput->width - geom.width;
474                 output->area.width -= geom.width;
475
476                 width = woutput->width - x;
477                 height = output->area.height;
478                 y = output->area.y;
479
480                 break;
481         case IVI_SURFACE_ROLE_SPLIT_H:
482                 if (geom.width == woutput->width &&
483                     geom.height == woutput->height)
484                         geom.height = (output->area.height / 2);
485
486                 y = output->area.y;
487                 output->area.y += geom.height;
488                 output->area.height -= geom.height;
489
490                 width = output->area.width;
491                 height = output->area.height;
492
493                 x = output->area.x;
494
495                 break;
496         default:
497                 assert(!"Invalid split orientation\n");
498         }
499
500         weston_desktop_surface_set_size(dsurface,
501                                         width, height);
502
503         /* resize the active surface first, output->area already contains
504          * correct area to resize to */
505         if (output->active)
506                 ivi_layout_desktop_resize(output->active, output->area);
507
508         weston_view_set_output(view, woutput);
509         weston_view_set_position(view, x, y);
510         weston_layer_entry_insert(&ivi->normal.view_list, &view->layer_link);
511
512         weston_view_update_transform(view);
513         weston_view_damage_below(view);
514
515         wsurface->is_mapped = true;
516         surface->view->is_mapped = true;
517 }
518
519 void
520 ivi_layout_popup_committed(struct ivi_surface *surface)
521 {
522         struct ivi_compositor *ivi = surface->ivi;
523
524         struct weston_desktop_surface *dsurface = surface->dsurface;
525         struct weston_surface *wsurface =
526                 weston_desktop_surface_get_surface(dsurface);
527
528         struct ivi_output *output = surface->popup.output;
529         struct weston_output *woutput = output->output;
530
531         struct weston_view *view = surface->view;
532         struct weston_geometry geom;
533
534         if (surface->view->is_mapped)
535                 return;
536
537         geom = weston_desktop_surface_get_geometry(dsurface);
538         weston_log("(popup) geom x %d, y %d, width %d, height %d\n", geom.x, geom.y,
539                         geom.width, geom.height);
540
541         assert(surface->role == IVI_SURFACE_ROLE_POPUP);
542
543         weston_view_set_output(view, woutput);
544         if (surface->popup.x || surface->popup.y)
545                 weston_view_set_position(view, surface->popup.x, surface->popup.y);
546         else
547                 weston_view_set_position(view, geom.x, geom.y);
548         weston_layer_entry_insert(&ivi->popup.view_list, &view->layer_link);
549
550         weston_view_update_transform(view);
551         weston_view_damage_below(view);
552
553         wsurface->is_mapped = true;
554         surface->view->is_mapped = true;
555 }
556
557 static void
558 ivi_layout_popup_re_add(struct ivi_surface *surface)
559 {
560         assert(surface->role == IVI_SURFACE_ROLE_POPUP);
561         struct weston_view *view = surface->view;
562
563         if (weston_view_is_mapped(view)) {
564                 struct weston_desktop_surface *dsurface = surface->dsurface;
565                 struct weston_surface *wsurface =
566                         weston_desktop_surface_get_surface(dsurface);
567
568                 weston_layer_entry_remove(&view->layer_link);
569
570                 wsurface->is_mapped = false;
571                 view->is_mapped = false;
572         }
573
574         ivi_layout_popup_committed(surface);
575 }
576
577 void
578 ivi_layout_panel_committed(struct ivi_surface *surface)
579 {
580         struct ivi_compositor *ivi = surface->ivi;
581         struct ivi_output *output = surface->bg.output;
582         struct weston_output *woutput = output->output;
583         struct weston_desktop_surface *dsurface = surface->dsurface;
584         struct weston_surface *wsurface =
585                 weston_desktop_surface_get_surface(dsurface);
586         struct weston_geometry geom;
587         int x = woutput->x;
588         int y = woutput->y;
589
590         assert(surface->role == IVI_SURFACE_ROLE_PANEL);
591
592         /*
593          * If the desktop_surface geometry is not set and the panel is not a
594          * top one, we'll give this a chance to run, as some qtwayland version
595          * seem to have a 'problem', where the panel initilization part will
596          * have a desktop surface with 0 as geometry for *all* its members
597          * (width/height). Doing that will result in the panel not being
598          * displayed at all.
599          *
600          * Later versions of qtwayland do have the correct window geometry for
601          * the desktop surface so the weston_surface is already mapped in
602          * ivi_panel_init().
603          */
604         if (wsurface->is_mapped)
605                 return;
606
607         geom = weston_desktop_surface_get_geometry(dsurface);
608
609 #ifdef AGL_COMP_DEBUG
610         weston_log("geom.width %d, geom.height %d, geom.x %d, geom.y %d\n",
611                         geom.width, geom.height, geom.x, geom.y);
612 #endif
613
614         switch (surface->panel.edge) {
615         case AGL_SHELL_EDGE_TOP:
616                 /* Do nothing */
617                 break;
618         case AGL_SHELL_EDGE_BOTTOM:
619                 y += woutput->height - geom.height;
620                 break;
621         case AGL_SHELL_EDGE_LEFT:
622                 /* Do nothing */
623                 break;
624         case AGL_SHELL_EDGE_RIGHT:
625                 x += woutput->width - geom.width;
626                 break;
627         }
628 #ifndef AGL_COMP_DEBUG
629         weston_log("panel type %d commited\n", surface->panel.edge);
630 #endif
631
632         weston_view_set_output(surface->view, woutput);
633         weston_view_set_position(surface->view, x, y);
634         weston_layer_entry_insert(&ivi->panel.view_list,
635                                   &surface->view->layer_link);
636
637         weston_view_update_transform(surface->view);
638         weston_view_schedule_repaint(surface->view);
639
640         wsurface->is_mapped = true;
641         surface->view->is_mapped = true;
642 }
643
644 static bool
645 ivi_layout_surface_is_split_or_fullscreen(struct ivi_surface *surf)
646 {
647         struct ivi_compositor *ivi = surf->ivi;
648         struct ivi_surface *is;
649
650         if (surf->role != IVI_SURFACE_ROLE_SPLIT_H &&
651             surf->role != IVI_SURFACE_ROLE_SPLIT_V &&
652             surf->role != IVI_SURFACE_ROLE_FULLSCREEN)
653                 return false;
654
655         wl_list_for_each(is, &ivi->surfaces, link)
656                 if (is == surf)
657                         return true;
658
659         return false;
660 }
661
662 void
663 ivi_layout_activate(struct ivi_output *output, const char *app_id)
664 {
665         struct ivi_compositor *ivi = output->ivi;
666         struct ivi_surface *surf;
667         struct weston_desktop_surface *dsurf;
668         struct weston_view *view;
669         struct weston_geometry geom;
670         struct ivi_policy *policy = output->ivi->policy;
671
672         surf = ivi_find_app(ivi, app_id);
673         if (!surf)
674                 return;
675
676         if (policy && policy->api.surface_activate &&
677             !policy->api.surface_activate(surf, surf->ivi)) {
678                 return;
679         }
680
681 #ifdef AGL_COMP_DEBUG
682         weston_log("Activating app_id %s, type %s\n", app_id,
683                         ivi_layout_get_surface_role_name(surf));
684 #endif
685
686         if (surf->role == IVI_SURFACE_ROLE_POPUP) {
687                 ivi_layout_popup_re_add(surf);
688                 return;
689         }
690
691         /* do not 're'-activate surfaces that are split or active */
692         if (surf == output->active ||
693             ivi_layout_surface_is_split_or_fullscreen(surf))
694                 return;
695
696
697         dsurf = surf->dsurface;
698         view = surf->view;
699         geom = weston_desktop_surface_get_geometry(dsurf);
700
701         if (surf->role == IVI_SURFACE_ROLE_DESKTOP)
702                 surf->desktop.pending_output = output;
703         if (weston_desktop_surface_get_maximized(dsurf) &&
704             geom.width == output->area.width &&
705             geom.height == output->area.height) {
706                 ivi_layout_activate_complete(output, surf);
707                 return;
708         }
709
710         weston_desktop_surface_set_maximized(dsurf, true);
711         weston_desktop_surface_set_size(dsurf,
712                                         output->area.width,
713                                         output->area.height);
714
715         weston_log("Setting app_id %s, role %s, set to maximized (%dx%d)\n",
716                         app_id, ivi_layout_get_surface_role_name(surf),
717                         output->area.width, output->area.height);
718         /*
719          * If the view isn't mapped, we put it onto the hidden layer so it will
720          * start receiving frame events, and will be able to act on our
721          * configure event.
722          */
723         if (!weston_view_is_mapped(view)) {
724                 view->is_mapped = true;
725                 view->surface->is_mapped = true;
726
727                 weston_view_set_output(view, output->output);
728                 weston_layer_entry_insert(&ivi->hidden.view_list, &view->layer_link);
729                 /* force repaint of the entire output */
730
731                 weston_log("Placed app_id %s, type %s in hidden layer\n",
732                                 app_id, ivi_layout_get_surface_role_name(surf));
733                 weston_output_damage(output->output);
734         }
735 }
736
737 struct ivi_output *
738 ivi_layout_get_output_from_surface(struct ivi_surface *surf)
739 {
740         struct ivi_output *ivi_output = NULL;
741
742         switch (surf->role) {
743         case IVI_SURFACE_ROLE_DESKTOP:
744                 if (surf->desktop.pending_output)
745                         ivi_output = surf->desktop.pending_output;
746                 else
747                         ivi_output = surf->desktop.last_output;
748                 break;
749         case IVI_SURFACE_ROLE_POPUP:
750                 ivi_output = surf->popup.output;
751                 break;
752         case IVI_SURFACE_ROLE_BACKGROUND:
753                 ivi_output = surf->bg.output;
754                 break;
755         case IVI_SURFACE_ROLE_PANEL:
756                 ivi_output = surf->panel.output;
757                 break;
758         case IVI_SURFACE_ROLE_FULLSCREEN:
759                 ivi_output = surf->fullscreen.output;
760                 break;
761         case IVI_SURFACE_ROLE_SPLIT_H:
762         case IVI_SURFACE_ROLE_SPLIT_V:
763                 ivi_output = surf->split.output;
764                 break;
765         case IVI_SURFACE_ROLE_REMOTE:
766                 ivi_output = surf->remote.output;
767                 break;
768         case IVI_SURFACE_ROLE_NONE:
769         default:
770                 break;
771         }
772
773         return ivi_output;
774 }
775
776 void
777 ivi_layout_deactivate(struct ivi_compositor *ivi, const char *app_id)
778 {
779         struct ivi_surface *surf;
780         struct ivi_output *ivi_output;
781         struct ivi_policy *policy = ivi->policy;
782
783         surf = ivi_find_app(ivi, app_id);
784         if (!surf)
785                 return;
786
787         if (policy && policy->api.surface_deactivate &&
788             !policy->api.surface_deactivate(surf, surf->ivi)) {
789                 return;
790         }
791
792         ivi_output = ivi_layout_get_output_from_surface(surf);
793         weston_log("Deactiving %s, role %s\n", app_id,
794                         ivi_layout_get_surface_role_name(surf));
795
796         if (surf->role == IVI_SURFACE_ROLE_DESKTOP) {
797                 struct ivi_surface *previous_active;
798
799                 previous_active = ivi_output->previous_active;
800                 if (!previous_active) {
801                         /* we don't have a previous active it means we should
802                          * display the bg */
803                         if (ivi_output->active) {
804                                 struct weston_view *view;
805
806                                 view = ivi_output->active->view;
807                                 view->is_mapped = false;
808                                 view->surface->is_mapped = false;
809
810                                 weston_layer_entry_remove(&view->layer_link);
811                                 weston_output_damage(ivi_output->output);
812                         }
813                 } else {
814                         struct weston_desktop_surface *dsurface;
815                         const char *previous_active_app_id;
816
817                         dsurface = previous_active->dsurface;
818                         previous_active_app_id =
819                                 weston_desktop_surface_get_app_id(dsurface);
820                         ivi_layout_activate(ivi_output, previous_active_app_id);
821                 }
822         } else if (surf->role == IVI_SURFACE_ROLE_POPUP) {
823                 struct weston_view *view  = surf->view;
824
825                 weston_layer_entry_remove(&view->layer_link);
826                 weston_view_damage_below(view);
827         }
828 }