input: Fix minor issue while reporting disable cursor
[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         weston_log("(background) position view %p, x %d, y %d, on output %s\n", view,
81                         woutput->x, woutput->y, output->name);
82
83         view->is_mapped = true;
84         view->surface->is_mapped = true;
85
86         weston_layer_entry_insert(&ivi->background.view_list, &view->layer_link);
87 }
88
89 static void
90 ivi_panel_init(struct ivi_compositor *ivi, struct ivi_output *output,
91                struct ivi_surface *panel)
92 {
93         struct weston_output *woutput = output->output;
94         struct weston_desktop_surface *dsurface;
95         struct weston_view *view;
96         struct weston_geometry geom;
97         int x = woutput->x;
98         int y = woutput->y;
99
100         if (!panel)
101                 return;
102
103         assert(panel->role == IVI_SURFACE_ROLE_PANEL);
104         dsurface = panel->dsurface;
105         view = panel->view;
106         geom = weston_desktop_surface_get_geometry(dsurface);
107
108         weston_log("(panel) geom.width %d, geom.height %d, geom.x %d, geom.y %d\n",
109                         geom.width, geom.height, geom.x, geom.y);
110
111         switch (panel->panel.edge) {
112         case AGL_SHELL_EDGE_TOP:
113                 output->area.y += geom.height;
114                 output->area.height -= geom.height;
115                 break;
116         case AGL_SHELL_EDGE_BOTTOM:
117                 y += woutput->height - geom.height;
118                 output->area.height -= geom.height;
119                 break;
120         case AGL_SHELL_EDGE_LEFT:
121                 output->area.x += geom.width;
122                 output->area.width -= geom.width;
123                 break;
124         case AGL_SHELL_EDGE_RIGHT:
125                 x += woutput->width - geom.width;
126                 output->area.width -= geom.width;
127                 break;
128         }
129
130         x -= geom.x;
131         y -= geom.y;
132
133         weston_view_set_output(view, woutput);
134         weston_view_set_position(view, x, y);
135
136         weston_log("(panel) edge %d position view %p, x %d, y %d\n",
137                         panel->panel.edge, view, x, y);
138
139         view->is_mapped = true;
140         view->surface->is_mapped = true;
141
142         weston_log("panel type %d inited on output %s\n", panel->panel.edge,
143                         output->name);
144
145         weston_layer_entry_insert(&ivi->panel.view_list, &view->layer_link);
146 }
147
148 /*
149  * Initializes all static parts of the layout, i.e. the background and panels.
150  */
151 void
152 ivi_layout_init(struct ivi_compositor *ivi, struct ivi_output *output)
153 {
154         bool use_default_area = true;
155
156         ivi_background_init(ivi, output);
157
158         if (output->area_activation.width ||
159             output->area_activation.height ||
160             output->area_activation.x ||
161             output->area_activation.y) {
162                 /* Sanity check target area is within output bounds */
163                 if ((output->area_activation.x + output->area_activation.width) < output->output->width ||
164                     (output->area_activation.y + output->area_activation.height) < output->output->height) {
165                         weston_log("Using specified area for output %s, ignoring panels\n",
166                                    output->name);
167                         output->area.x = output->area_activation.x;
168                         output->area.y = output->area_activation.y;
169                         output->area.width = output->area_activation.width;
170                         output->area.height = output->area_activation.height;
171                         use_default_area = false;
172                 } else {
173                         weston_log("Invalid activation-area position for output %s, ignoring\n",
174                                    output->name);
175                 }
176         }
177         if (use_default_area) {
178                 output->area.x = 0;
179                 output->area.y = 0;
180                 output->area.width = output->output->width;
181                 output->area.height = output->output->height;
182
183                 ivi_panel_init(ivi, output, output->top);
184                 ivi_panel_init(ivi, output, output->bottom);
185                 ivi_panel_init(ivi, output, output->left);
186                 ivi_panel_init(ivi, output, output->right);
187         }
188
189         weston_compositor_schedule_repaint(ivi->compositor);
190
191         weston_log("Usable area: %dx%d+%d,%d\n",
192                    output->area.width, output->area.height,
193                    output->area.x, output->area.y);
194 }
195
196 struct ivi_surface *
197 ivi_find_app(struct ivi_compositor *ivi, const char *app_id)
198 {
199         struct ivi_surface *surf;
200         const char *id;
201
202         wl_list_for_each(surf, &ivi->surfaces, link) {
203                 id = weston_desktop_surface_get_app_id(surf->dsurface);
204                 if (id && strcmp(app_id, id) == 0)
205                         return surf;
206         }
207
208         return NULL;
209 }
210
211 static void
212 ivi_layout_activate_complete(struct ivi_output *output,
213                              struct ivi_surface *surf)
214 {
215         struct ivi_compositor *ivi = output->ivi;
216         struct weston_output *woutput = output->output;
217         struct weston_view *view = surf->view;
218         struct weston_seat *wseat = get_ivi_shell_weston_first_seat(ivi);
219         struct ivi_shell_seat *ivi_seat = get_ivi_shell_seat(wseat);
220
221         if (weston_view_is_mapped(view)) {
222                 weston_layer_entry_remove(&view->layer_link);
223         } else {
224                 weston_view_update_transform(view);
225         }
226
227         weston_view_set_output(view, woutput);
228
229         if (surf->role != IVI_SURFACE_ROLE_BACKGROUND)
230                 weston_view_set_position(view,
231                                          woutput->x + output->area.x,
232                                          woutput->y + output->area.y);
233
234         view->is_mapped = true;
235         surf->mapped = true;
236         view->surface->is_mapped = true;
237
238         if (output->active) {
239                 /* keep the background surface mapped at all times */
240                 if (output->active->role != IVI_SURFACE_ROLE_BACKGROUND) {
241                         output->active->view->is_mapped = false;
242                         output->active->view->surface->is_mapped = false;
243
244                         weston_layer_entry_remove(&output->active->view->layer_link);
245                 }
246         }
247         output->previous_active = output->active;
248         output->active = surf;
249
250         weston_layer_entry_insert(&ivi->normal.view_list, &view->layer_link);
251         weston_view_geometry_dirty(view);
252         weston_surface_damage(view->surface);
253
254         if (ivi_seat)
255                 ivi_shell_activate_surface(surf, ivi_seat, WESTON_ACTIVATE_FLAG_NONE);
256
257         /*
258          * the 'remote' role now makes use of this part so make sure we don't
259          * trip the enum such that we might end up with a modified output for
260          * 'remote' role
261          */
262         if (surf->role == IVI_SURFACE_ROLE_DESKTOP) {
263                 if (surf->desktop.pending_output)
264                         surf->desktop.last_output = surf->desktop.pending_output;
265                 surf->desktop.pending_output = NULL;
266         }
267
268         weston_log("Activation completed for app_id %s, role %s, output %s\n",
269                         weston_desktop_surface_get_app_id(surf->dsurface),
270                         ivi_layout_get_surface_role_name(surf), output->name);
271 }
272
273 struct ivi_output *
274 ivi_layout_find_with_app_id(const char *app_id, struct ivi_compositor *ivi)
275 {
276         struct ivi_output *out;
277
278         if (!app_id)
279                 return NULL;
280
281         wl_list_for_each(out, &ivi->outputs, link) {
282                 if (!out->app_id)
283                         continue;
284
285                 if (!strcmp(app_id, out->app_id))
286                         return out;
287         }
288
289         return NULL;
290 }
291
292 struct ivi_output *
293 ivi_layout_find_bg_output(struct ivi_compositor *ivi)
294 {
295         struct ivi_output *out;
296
297         wl_list_for_each(out, &ivi->outputs, link) {
298                 if (out->background &&
299                     out->background->role == IVI_SURFACE_ROLE_BACKGROUND)
300                         return out;
301         }
302
303         return NULL;
304 }
305
306
307 static void
308 ivi_layout_add_to_hidden_layer(struct ivi_surface *surf,
309                                struct ivi_output *ivi_output)
310 {
311         struct weston_desktop_surface *dsurf = surf->dsurface;
312         struct weston_view *ev = surf->view;
313         struct ivi_compositor *ivi = surf->ivi;
314         const char *app_id = weston_desktop_surface_get_app_id(dsurf);
315
316         weston_desktop_surface_set_maximized(dsurf, true);
317         weston_desktop_surface_set_size(dsurf,
318                                         ivi_output->area.width,
319                                         ivi_output->area.height);
320
321         weston_log("Setting app_id %s, role %s, set to maximized (%dx%d)\n",
322                         app_id, ivi_layout_get_surface_role_name(surf),
323                         ivi_output->area.width, ivi_output->area.height);
324         /*
325          * If the view isn't mapped, we put it onto the hidden layer so it will
326          * start receiving frame events, and will be able to act on our
327          * configure event.
328          */
329         if (!weston_view_is_mapped(ev)) {
330                 ev->is_mapped = true;
331                 ev->surface->is_mapped = true;
332
333                 weston_view_set_output(ev, ivi_output->output);
334                 weston_layer_entry_insert(&ivi->hidden.view_list, &ev->layer_link);
335                 weston_log("Placed app_id %s, type %s in hidden layer\n",
336                                 app_id, ivi_layout_get_surface_role_name(surf));
337         }
338 }
339
340 void
341 ivi_layout_desktop_committed(struct ivi_surface *surf)
342 {
343         struct weston_desktop_surface *dsurf = surf->dsurface;
344         struct weston_geometry geom = weston_desktop_surface_get_geometry(dsurf);
345         struct ivi_policy *policy = surf->ivi->policy;
346         struct ivi_output *output;
347         const char *app_id = weston_desktop_surface_get_app_id(dsurf);
348
349         assert(surf->role == IVI_SURFACE_ROLE_DESKTOP ||
350                surf->role == IVI_SURFACE_ROLE_REMOTE);
351
352         /*
353          * we can't make use here of the ivi_layout_get_output_from_surface()
354          * due to the fact that we'll always land here when a surface performs
355          * a commit and pending_output will not bet set. This works in tandem
356          * with 'mapped' at this point to avoid tripping over
357          * to a surface that continuously updates its content
358          */
359         if (surf->role == IVI_SURFACE_ROLE_DESKTOP)
360                 output = surf->desktop.pending_output;
361         else
362                 output = surf->remote.output;
363
364         if (surf->role == IVI_SURFACE_ROLE_DESKTOP && !output) {
365                 struct ivi_output *r_output;
366
367                 if (policy && policy->api.surface_activate_by_default &&
368                     !policy->api.surface_activate_by_default(surf, surf->ivi))
369                         return;
370
371                 /* we can only activate it again by using the protocol */
372                 if (surf->mapped)
373                         return;
374
375                 /* check first if there aren't any outputs being set */
376                 r_output = ivi_layout_find_with_app_id(app_id, surf->ivi);
377
378                 if (r_output) {
379                         struct weston_view *view = r_output->fullscreen_view.fs->view;
380                         if (view->is_mapped || view->surface->is_mapped)
381                                 remove_black_surface(r_output);
382                 }
383
384
385                 /* try finding an output with a background and use that */
386                 if (!r_output)
387                         r_output = ivi_layout_find_bg_output(surf->ivi);
388
389                 /* if we couldn't still find an output by this point, there's
390                  * something wrong so we abort with a protocol error */
391                 if (!r_output) {
392                         wl_resource_post_error(surf->ivi->shell_client.resource,
393                                                AGL_SHELL_ERROR_INVALID_ARGUMENT,
394                                                "No valid output found to activate surface by default");
395                         return;
396                 }
397
398                 if (!surf->ivi->activate_by_default) {
399                         weston_log("Refusing to activate surface role %d, app_id %s\n",
400                                         surf->role, app_id);
401
402                         if (!weston_desktop_surface_get_maximized(dsurf) ||
403                             geom.width != r_output->area.width ||
404                             geom.height != r_output->area.height)
405                                 ivi_layout_add_to_hidden_layer(surf, r_output);
406
407                         return;
408                 }
409
410                 /* use the output of the bg to activate the app on start-up by
411                  * default */
412                 if (surf->view && r_output) {
413                         if (app_id && r_output) {
414                                 weston_log("Surface with app_id %s, role %s activating by default\n",
415                                         weston_desktop_surface_get_app_id(surf->dsurface),
416                                         ivi_layout_get_surface_role_name(surf));
417                                 ivi_layout_activate(r_output, app_id);
418                         } else if (!app_id) {
419                                 /*
420                                  * applications not setting an app_id, or
421                                  * setting an app_id but at a later point in
422                                  * time, might fall-back here so give them a
423                                  * chance to receive the configure event and
424                                  * act upon it
425                                  */
426                                 weston_log("Surface no app_id, role %s activating by default\n",
427                                         ivi_layout_get_surface_role_name(surf));
428                                 ivi_layout_activate_by_surf(r_output, surf);
429                         }
430                 }
431
432                 return;
433         }
434
435         if (surf->role == IVI_SURFACE_ROLE_REMOTE && output) {
436                 if (policy && policy->api.surface_activate_by_default &&
437                     !policy->api.surface_activate_by_default(surf, surf->ivi))
438                         return;
439
440                 /* we can only activate it again by using the protocol, but
441                  * additionally the output is not reset when
442                  * ivi_layout_activate_complete() terminates so we use the
443                  * current active surface to avoid hitting this again and again
444                  * */
445                 if (surf->mapped && output->active == surf)
446                         return;
447
448                 if (app_id) {
449                         weston_log("Surface with app_id %s, role %s activating by default\n",
450                                         weston_desktop_surface_get_app_id(surf->dsurface),
451                                         ivi_layout_get_surface_role_name(surf));
452                         ivi_layout_activate(output, app_id);
453                 }
454                 return;
455         }
456
457         if (!weston_desktop_surface_get_maximized(dsurf) ||
458             geom.width != output->area.width ||
459             geom.height != output->area.height)
460                 return;
461
462         ivi_layout_activate_complete(output, surf);
463 }
464
465 void
466 ivi_layout_fullscreen_committed(struct ivi_surface *surface)
467 {
468         struct ivi_compositor *ivi = surface->ivi;
469         struct ivi_policy *policy = ivi->policy;
470
471         struct weston_desktop_surface *dsurface = surface->dsurface;
472         struct weston_surface *wsurface =
473                 weston_desktop_surface_get_surface(dsurface);
474         const char *app_id = weston_desktop_surface_get_app_id(dsurface);
475
476         struct ivi_output *output = surface->split.output;
477         struct weston_output *woutput = output->output;
478         struct ivi_output *bg_output = ivi_layout_find_bg_output(ivi);
479
480         struct weston_view *view = surface->view;
481         struct weston_geometry geom =
482                 weston_desktop_surface_get_geometry(dsurface);
483
484         struct weston_seat *wseat = get_ivi_shell_weston_first_seat(ivi);
485         struct ivi_shell_seat *ivi_seat = get_ivi_shell_seat(wseat);
486
487         bool is_fullscreen = weston_desktop_surface_get_fullscreen(dsurface);
488         bool is_dim_same =
489                 geom.width == bg_output->output->width &&
490                 geom.height == bg_output->output->height;
491
492         if (policy && policy->api.surface_activate_by_default &&
493             !policy->api.surface_activate_by_default(surface, surface->ivi) &&
494             !surface->mapped)
495                 return;
496
497         assert(surface->role == IVI_SURFACE_ROLE_FULLSCREEN);
498
499         if (weston_view_is_mapped(view))
500                 return;
501
502         /* if we still get here but we haven't resized so far, send configure
503          * events to do so */
504         if (surface->state != RESIZING && (!is_fullscreen || !is_dim_same)) {
505                 struct ivi_output *bg_output =
506                         ivi_layout_find_bg_output(surface->ivi);
507
508                 weston_log("Placing fullscreen app_id %s, type %s in hidden layer\n",
509                                 app_id, ivi_layout_get_surface_role_name(surface));
510                 weston_desktop_surface_set_fullscreen(dsurface, true);
511                 weston_desktop_surface_set_size(dsurface,
512                                                 bg_output->output->width,
513                                                 bg_output->output->height);
514
515                 surface->state = RESIZING;
516                 weston_view_set_output(view, output->output);
517                 weston_layer_entry_insert(&ivi->hidden.view_list, &view->layer_link);
518                 return;
519         }
520
521         /* eventually, we would set the surface fullscreen, but the client
522          * hasn't resized correctly by this point, so terminate connection */
523         if (surface->state == RESIZING && is_fullscreen && !is_dim_same) {
524                 struct weston_desktop_client *desktop_client =
525                         weston_desktop_surface_get_client(dsurface);
526                 struct wl_client *client =
527                         weston_desktop_client_get_client(desktop_client);
528                 wl_client_post_implementation_error(client,
529                                 "can not display surface due to invalid geometry."
530                                 " Client should perform a geometry resize!");
531                 return;
532         }
533
534         /* this implies we resized correctly */
535         if (!weston_view_is_mapped(view)) {
536                 weston_layer_entry_remove(&view->layer_link);
537
538                 weston_view_set_output(view, woutput);
539                 weston_view_set_position(view, woutput->x, woutput->y);
540                 weston_layer_entry_insert(&ivi->fullscreen.view_list, &view->layer_link);
541
542                 wsurface->is_mapped = true;
543                 surface->view->is_mapped = true;
544                 surface->state = FULLSCREEN;
545
546                 weston_view_geometry_dirty(view);
547                 weston_surface_damage(view->surface);
548
549                 if (ivi_seat)
550                         ivi_shell_activate_surface(surface, ivi_seat, WESTON_ACTIVATE_FLAG_NONE);
551
552                 shell_advertise_app_state(ivi, app_id,
553                                 NULL, AGL_SHELL_DESKTOP_APP_STATE_ACTIVATED);
554
555                 weston_log("Activation completed for app_id %s, role %s, "
556                            "output %s\n", app_id,
557                            ivi_layout_get_surface_role_name(surface),
558                            output->name);
559
560         }
561 }
562
563 void
564 ivi_layout_desktop_resize(struct ivi_surface *surface,
565                           struct weston_geometry area)
566 {
567         struct weston_desktop_surface *dsurf = surface->dsurface;
568         struct weston_view *view = surface->view;
569
570         int x = area.x;
571         int y = area.y;
572         int width = area.width;
573         int height = area.height;
574
575         weston_desktop_surface_set_size(dsurf,
576                                         width, height);
577
578         weston_view_set_position(view, x, y);
579
580         weston_view_geometry_dirty(view);
581         weston_surface_damage(view->surface);
582 }
583
584 void
585 ivi_layout_split_committed(struct ivi_surface *surface)
586 {
587         struct ivi_compositor *ivi = surface->ivi;
588         struct ivi_policy *policy = ivi->policy;
589
590         struct weston_desktop_surface *dsurface = surface->dsurface;
591         struct weston_surface *wsurface =
592                 weston_desktop_surface_get_surface(dsurface);
593         const char *app_id = weston_desktop_surface_get_app_id(dsurface);
594
595         struct ivi_output *output = surface->split.output;
596         struct weston_output *woutput = output->output;
597
598         struct weston_seat *wseat = get_ivi_shell_weston_first_seat(ivi);
599         struct ivi_shell_seat *ivi_seat = get_ivi_shell_seat(wseat);
600
601         struct weston_view *view = surface->view;
602         struct weston_geometry geom;
603
604         int x, y;
605         int width, height;
606
607         x = woutput->x;
608         y = woutput->y;
609
610         if (policy && policy->api.surface_activate_by_default &&
611             !policy->api.surface_activate_by_default(surface, surface->ivi) &&
612             !surface->mapped)
613                 return;
614
615         if (surface->view->is_mapped)
616                 return;
617
618         geom = weston_desktop_surface_get_geometry(dsurface);
619
620         assert(surface->role == IVI_SURFACE_ROLE_SPLIT_H ||
621                surface->role == IVI_SURFACE_ROLE_SPLIT_V);
622
623         /* save the previous area in order to recover it back when if this kind
624          * of surface is being destroyed/removed */
625         output->area_saved = output->area;
626
627         switch (surface->role) {
628         case IVI_SURFACE_ROLE_SPLIT_V:
629                 geom.width = (output->area.width / 2);
630
631                 x += woutput->width - geom.width;
632                 output->area.width -= geom.width;
633
634                 width = woutput->width - x;
635                 height = output->area.height;
636                 y = output->area.y;
637
638                 break;
639         case IVI_SURFACE_ROLE_SPLIT_H:
640                 geom.height = (output->area.height / 2);
641
642                 y = output->area.y;
643                 output->area.y += geom.height;
644                 output->area.height -= geom.height;
645
646                 width = output->area.width;
647                 height = output->area.height;
648
649                 x = output->area.x;
650
651                 break;
652         default:
653                 assert(!"Invalid split orientation\n");
654         }
655
656         weston_desktop_surface_set_size(dsurface,
657                                         width, height);
658
659         /* resize the active surface first, output->area already contains
660          * correct area to resize to */
661         if (output->active)
662                 ivi_layout_desktop_resize(output->active, output->area);
663
664         weston_view_set_output(view, woutput);
665         weston_view_set_position(view, x, y);
666         weston_layer_entry_insert(&ivi->normal.view_list, &view->layer_link);
667
668         weston_view_geometry_dirty(view);
669         weston_surface_damage(view->surface);
670
671         if (ivi_seat)
672                 ivi_shell_activate_surface(surface, ivi_seat, WESTON_ACTIVATE_FLAG_NONE);
673
674         wsurface->is_mapped = true;
675         surface->view->is_mapped = true;
676
677         shell_advertise_app_state(ivi, app_id,
678                                   NULL, AGL_SHELL_DESKTOP_APP_STATE_ACTIVATED);
679
680         weston_log("Activation completed for app_id %s, role %s, output %s\n",
681                         app_id, ivi_layout_get_surface_role_name(surface), output->name);
682 }
683
684 static void
685 ivi_compute_popup_position(const struct weston_output *output, struct weston_view *view,
686                            int initial_x, int initial_y, int *new_x, int *new_y)
687 {
688         *new_x = output->x + initial_x;
689         *new_y = output->y + initial_y;
690 }
691
692
693 void
694 ivi_layout_popup_committed(struct ivi_surface *surface)
695 {
696         struct ivi_compositor *ivi = surface->ivi;
697         struct ivi_policy *policy = ivi->policy;
698
699         struct weston_desktop_surface *dsurface = surface->dsurface;
700         struct weston_surface *wsurface =
701                 weston_desktop_surface_get_surface(dsurface);
702         const char *app_id = weston_desktop_surface_get_app_id(dsurface);
703
704         int new_x, new_y;
705
706         struct ivi_output *output = surface->popup.output;
707         struct weston_output *woutput = output->output;
708
709         struct weston_seat *wseat = get_ivi_shell_weston_first_seat(ivi);
710         struct ivi_shell_seat *ivi_seat = get_ivi_shell_seat(wseat);
711
712         struct weston_view *view = surface->view;
713
714         if (policy && policy->api.surface_activate_by_default &&
715             !policy->api.surface_activate_by_default(surface, surface->ivi) &&
716             !surface->mapped)
717                 return;
718
719         if (surface->view->is_mapped || surface->state == HIDDEN)
720                 return;
721
722         assert(surface->role == IVI_SURFACE_ROLE_POPUP);
723
724         weston_view_set_output(view, woutput);
725
726         ivi_compute_popup_position(woutput, view,
727                                    surface->popup.x, surface->popup.y, &new_x, &new_y);
728         weston_view_set_position(view, new_x, new_y);
729         weston_view_update_transform(view);
730
731         /* only clip the pop-up dialog window if we have a valid
732          * width and height being passed on. Users might not want to have one
733          * set-up so only enfore it is really passed on. */
734         if (surface->popup.bb.width > 0 && surface->popup.bb.height > 0)
735                 weston_view_set_mask(view, surface->popup.bb.x, surface->popup.bb.y,
736                                      surface->popup.bb.width, surface->popup.bb.height);
737
738         weston_layer_entry_insert(&ivi->popup.view_list, &view->layer_link);
739
740         weston_view_geometry_dirty(view);
741         weston_surface_damage(view->surface);
742
743         if (ivi_seat)
744                 ivi_shell_activate_surface(surface, ivi_seat, WESTON_ACTIVATE_FLAG_NONE);
745
746         wsurface->is_mapped = true;
747         surface->view->is_mapped = true;
748
749         shell_advertise_app_state(ivi, app_id,
750                                   NULL, AGL_SHELL_DESKTOP_APP_STATE_ACTIVATED);
751
752         weston_log("Activation completed for app_id %s, role %s, output %s\n",
753                         app_id, ivi_layout_get_surface_role_name(surface), output->name);
754 }
755
756 static void
757 ivi_layout_popup_re_add(struct ivi_surface *surface)
758 {
759         assert(surface->role == IVI_SURFACE_ROLE_POPUP);
760         struct weston_view *view = surface->view;
761
762         if (weston_view_is_mapped(view)) {
763                 struct weston_desktop_surface *dsurface = surface->dsurface;
764                 struct weston_surface *wsurface =
765                         weston_desktop_surface_get_surface(dsurface);
766
767                 weston_layer_entry_remove(&view->layer_link);
768
769                 wsurface->is_mapped = false;
770                 view->is_mapped = false;
771         }
772
773         /* reset the activate by default in order to (still) allow the surface
774          * to be activaved using the request */
775         if (!surface->mapped)
776                 surface->mapped = true;
777
778         surface->state = NORMAL;
779         ivi_layout_popup_committed(surface);
780 }
781
782 static bool
783 ivi_layout_surface_is_split_or_fullscreen(struct ivi_surface *surf)
784 {
785         struct ivi_compositor *ivi = surf->ivi;
786         struct ivi_surface *is;
787
788         if (surf->role != IVI_SURFACE_ROLE_SPLIT_H &&
789             surf->role != IVI_SURFACE_ROLE_SPLIT_V &&
790             surf->role != IVI_SURFACE_ROLE_FULLSCREEN)
791                 return false;
792
793         /* reset the activate by default in order to (still) allow the surface
794          * to be activaved using the request */
795         if (!surf->mapped)
796                 surf->mapped = true;
797
798         wl_list_for_each(is, &ivi->surfaces, link)
799                 if (is == surf)
800                         return true;
801
802         return false;
803 }
804
805 void
806 ivi_layout_activate_by_surf(struct ivi_output *output, struct ivi_surface *surf)
807 {
808         struct ivi_compositor *ivi = output->ivi;
809         struct weston_desktop_surface *dsurf;
810         struct weston_geometry geom;
811         struct ivi_policy *policy = output->ivi->policy;
812
813         dsurf = surf->dsurface;
814
815         const char *app_id = weston_desktop_surface_get_app_id(dsurf);
816
817         if (!surf)
818                 return;
819
820         if (policy && policy->api.surface_activate &&
821             !policy->api.surface_activate(surf, surf->ivi)) {
822                 return;
823         }
824
825 #ifdef AGL_COMP_DEBUG
826         weston_log("Activating app_id %s, type %s\n", app_id,
827                         ivi_layout_get_surface_role_name(surf));
828 #endif
829
830         if (surf->role == IVI_SURFACE_ROLE_POPUP) {
831                 ivi_layout_popup_re_add(surf);
832                 return;
833         }
834
835         /* do not 're'-activate surfaces that are split or active */
836         if (surf == output->active ||
837             ivi_layout_surface_is_split_or_fullscreen(surf))
838                 return;
839
840         if (surf->role == IVI_SURFACE_ROLE_REMOTE) {
841                 struct ivi_output *remote_output =
842                         ivi_layout_find_with_app_id(app_id, ivi);
843
844                 /* if already active on a remote output do not
845                  * attempt to activate it again */
846                 if (remote_output && remote_output->active == surf)
847                         return;
848         }
849
850
851         geom = weston_desktop_surface_get_geometry(dsurf);
852
853         if (surf->role == IVI_SURFACE_ROLE_DESKTOP)
854                 surf->desktop.pending_output = output;
855         if (weston_desktop_surface_get_maximized(dsurf) &&
856             geom.width == output->area.width &&
857             geom.height == output->area.height) {
858                 ivi_layout_activate_complete(output, surf);
859                 return;
860         }
861
862         /* the background surface is already "maximized" so we don't need to
863          * add to the hidden layer */
864         if (surf->role == IVI_SURFACE_ROLE_BACKGROUND) {
865                 ivi_layout_activate_complete(output, surf);
866                 return;
867         }
868
869         ivi_layout_add_to_hidden_layer(surf, output);
870 }
871
872 void
873 ivi_layout_activate(struct ivi_output *output, const char *app_id)
874 {
875         struct ivi_surface *surf;
876         struct ivi_compositor *ivi = output->ivi;
877
878         if (!app_id)
879                 return;
880
881         surf = ivi_find_app(ivi, app_id);
882         if (!surf)
883                 return;
884
885         ivi_layout_activate_by_surf(output, surf);
886 }
887
888 struct ivi_output *
889 ivi_layout_get_output_from_surface(struct ivi_surface *surf)
890 {
891         struct ivi_output *ivi_output = NULL;
892
893         switch (surf->role) {
894         case IVI_SURFACE_ROLE_DESKTOP:
895                 if (surf->desktop.pending_output)
896                         ivi_output = surf->desktop.pending_output;
897                 else
898                         ivi_output = surf->desktop.last_output;
899                 break;
900         case IVI_SURFACE_ROLE_POPUP:
901                 ivi_output = surf->popup.output;
902                 break;
903         case IVI_SURFACE_ROLE_BACKGROUND:
904                 ivi_output = surf->bg.output;
905                 break;
906         case IVI_SURFACE_ROLE_PANEL:
907                 ivi_output = surf->panel.output;
908                 break;
909         case IVI_SURFACE_ROLE_FULLSCREEN:
910                 ivi_output = surf->fullscreen.output;
911                 break;
912         case IVI_SURFACE_ROLE_SPLIT_H:
913         case IVI_SURFACE_ROLE_SPLIT_V:
914                 ivi_output = surf->split.output;
915                 break;
916         case IVI_SURFACE_ROLE_REMOTE:
917                 ivi_output = surf->remote.output;
918                 break;
919         case IVI_SURFACE_ROLE_NONE:
920         default:
921                 break;
922         }
923
924         return ivi_output;
925 }
926
927 void
928 ivi_layout_deactivate(struct ivi_compositor *ivi, const char *app_id)
929 {
930         struct ivi_surface *surf;
931         struct ivi_output *ivi_output;
932         struct ivi_policy *policy = ivi->policy;
933
934         if (!app_id)
935                 return;
936
937         surf = ivi_find_app(ivi, app_id);
938         if (!surf)
939                 return;
940
941         if (policy && policy->api.surface_deactivate &&
942             !policy->api.surface_deactivate(surf, surf->ivi)) {
943                 return;
944         }
945
946         ivi_output = ivi_layout_get_output_from_surface(surf);
947         weston_log("Deactiving %s, role %s\n", app_id,
948                         ivi_layout_get_surface_role_name(surf));
949
950         if (surf->role == IVI_SURFACE_ROLE_DESKTOP) {
951                 struct ivi_surface *previous_active;
952
953                 previous_active = ivi_output->previous_active;
954                 if (!previous_active) {
955                         /* we don't have a previous active it means we should
956                          * display the bg */
957                         if (ivi_output->active) {
958                                 struct weston_view *view;
959
960                                 view = ivi_output->active->view;
961                                 view->is_mapped = false;
962                                 view->surface->is_mapped = false;
963
964                                 weston_layer_entry_remove(&view->layer_link);
965                                 weston_view_geometry_dirty(view);
966                                 weston_surface_damage(view->surface);
967                                 ivi_output->active = NULL;
968                         }
969                 } else {
970                         struct weston_desktop_surface *dsurface;
971                         const char *previous_active_app_id;
972
973                         dsurface = previous_active->dsurface;
974                         previous_active_app_id =
975                                 weston_desktop_surface_get_app_id(dsurface);
976                         ivi_layout_activate(ivi_output, previous_active_app_id);
977                 }
978         } else if (surf->role == IVI_SURFACE_ROLE_POPUP) {
979                 struct weston_view *view  = surf->view;
980
981                 weston_view_unmap(view);
982                 surf->state = HIDDEN;
983
984                 weston_layer_entry_remove(&view->layer_link);
985                 weston_view_geometry_dirty(view);
986                 weston_surface_damage(view->surface);
987         }
988 }