libweston: Rename weston_surface::configure to ::committed
[platform/upstream/weston.git] / desktop-shell / shell.c
1 /*
2  * Copyright © 2010-2012 Intel Corporation
3  * Copyright © 2011-2012 Collabora, Ltd.
4  * Copyright © 2013 Raspberry Pi Foundation
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the "Software"),
8  * to deal in the Software without restriction, including without limitation
9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  * and/or sell copies of the Software, and to permit persons to whom the
11  * Software is furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the next
14  * paragraph) shall be included in all copies or substantial portions of the
15  * Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23  * DEALINGS IN THE SOFTWARE.
24  */
25
26 #include "config.h"
27
28 #include <stdlib.h>
29 #include <stdint.h>
30 #include <stdio.h>
31 #include <string.h>
32 #include <unistd.h>
33 #include <linux/input.h>
34 #include <assert.h>
35 #include <signal.h>
36 #include <math.h>
37 #include <sys/types.h>
38
39 #include "shell.h"
40 #include "compositor/weston.h"
41 #include "weston-desktop-shell-server-protocol.h"
42 #include "shared/config-parser.h"
43 #include "shared/helpers.h"
44 #include "xdg-shell-unstable-v5-server-protocol.h"
45
46 #define DEFAULT_NUM_WORKSPACES 1
47 #define DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH 200
48
49 #ifndef static_assert
50 #define static_assert(cond, msg)
51 #endif
52
53 struct focus_state {
54         struct weston_seat *seat;
55         struct workspace *ws;
56         struct weston_surface *keyboard_focus;
57         struct wl_list link;
58         struct wl_listener seat_destroy_listener;
59         struct wl_listener surface_destroy_listener;
60 };
61
62 enum shell_surface_type {
63         SHELL_SURFACE_NONE,
64         SHELL_SURFACE_TOPLEVEL,
65         SHELL_SURFACE_POPUP,
66         SHELL_SURFACE_XWAYLAND
67 };
68
69 struct shell_client;
70
71 /*
72  * Surface stacking and ordering.
73  *
74  * This is handled using several linked lists of surfaces, organised into
75  * ‘layers’. The layers are ordered, and each of the surfaces in one layer are
76  * above all of the surfaces in the layer below. The set of layers is static and
77  * in the following order (top-most first):
78  *  • Lock layer (only ever displayed on its own)
79  *  • Cursor layer
80  *  • Input panel layer
81  *  • Fullscreen layer
82  *  • Panel layer
83  *  • Workspace layers
84  *  • Background layer
85  *
86  * The list of layers may be manipulated to remove whole layers of surfaces from
87  * display. For example, when locking the screen, all layers except the lock
88  * layer are removed.
89  *
90  * A surface’s layer is modified on configuring the surface, in
91  * set_surface_type() (which is only called when the surface’s type change is
92  * _committed_). If a surface’s type changes (e.g. when making a window
93  * fullscreen) its layer changes too.
94  *
95  * In order to allow popup and transient surfaces to be correctly stacked above
96  * their parent surfaces, each surface tracks both its parent surface, and a
97  * linked list of its children. When a surface’s layer is updated, so are the
98  * layers of its children. Note that child surfaces are *not* the same as
99  * subsurfaces — child/parent surfaces are purely for maintaining stacking
100  * order.
101  *
102  * The children_link list of siblings of a surface (i.e. those surfaces which
103  * have the same parent) only contains weston_surfaces which have a
104  * shell_surface. Stacking is not implemented for non-shell_surface
105  * weston_surfaces. This means that the following implication does *not* hold:
106  *     (shsurf->parent != NULL) ⇒ !wl_list_is_empty(shsurf->children_link)
107  */
108
109 struct shell_surface {
110         struct wl_resource *resource;
111         struct wl_signal destroy_signal;
112         struct shell_client *owner;
113         struct wl_resource *owner_resource;
114
115         struct weston_surface *surface;
116         struct weston_view *view;
117         int32_t last_width, last_height;
118         struct wl_listener surface_destroy_listener;
119         struct wl_listener resource_destroy_listener;
120
121         struct weston_surface *parent;
122         struct wl_list children_list;  /* child surfaces of this one */
123         struct wl_list children_link;  /* sibling surfaces of this one */
124         struct desktop_shell *shell;
125
126         enum shell_surface_type type;
127         char *title, *class;
128         int32_t saved_x, saved_y;
129         bool saved_position_valid;
130         bool saved_rotation_valid;
131         int unresponsive, grabbed;
132         uint32_t resize_edges;
133
134         struct {
135                 struct weston_transform transform;
136                 struct weston_matrix rotation;
137         } rotation;
138
139         struct {
140                 struct wl_list grab_link;
141                 int32_t x, y;
142                 struct shell_seat *shseat;
143                 uint32_t serial;
144         } popup;
145
146         struct {
147                 int32_t x, y;
148                 uint32_t flags;
149         } transient;
150
151         struct {
152                 enum wl_shell_surface_fullscreen_method type;
153                 struct weston_transform transform; /* matrix from x, y */
154                 uint32_t framerate;
155                 struct weston_view *black_view;
156         } fullscreen;
157
158         struct weston_transform workspace_transform;
159
160         struct weston_output *fullscreen_output;
161         struct weston_output *output;
162         struct wl_list link;
163
164         const struct weston_shell_client *client;
165
166         struct surface_state {
167                 bool maximized;
168                 bool fullscreen;
169                 bool relative;
170                 bool lowered;
171         } state, next_state, requested_state; /* surface states */
172         bool state_changed;
173         bool state_requested;
174
175         struct {
176                 int32_t x, y, width, height;
177         } geometry, next_geometry;
178         bool has_set_geometry, has_next_geometry;
179
180         int focus_count;
181
182         bool destroying;
183 };
184
185 struct shell_grab {
186         struct weston_pointer_grab grab;
187         struct shell_surface *shsurf;
188         struct wl_listener shsurf_destroy_listener;
189 };
190
191 struct shell_touch_grab {
192         struct weston_touch_grab grab;
193         struct shell_surface *shsurf;
194         struct wl_listener shsurf_destroy_listener;
195         struct weston_touch *touch;
196 };
197
198 struct weston_move_grab {
199         struct shell_grab base;
200         wl_fixed_t dx, dy;
201         bool client_initiated;
202 };
203
204 struct weston_touch_move_grab {
205         struct shell_touch_grab base;
206         int active;
207         wl_fixed_t dx, dy;
208 };
209
210 struct rotate_grab {
211         struct shell_grab base;
212         struct weston_matrix rotation;
213         struct {
214                 float x;
215                 float y;
216         } center;
217 };
218
219 struct shell_seat {
220         struct weston_seat *seat;
221         struct wl_listener seat_destroy_listener;
222         struct weston_surface *focused_surface;
223
224         struct wl_listener caps_changed_listener;
225         struct wl_listener pointer_focus_listener;
226         struct wl_listener keyboard_focus_listener;
227
228         struct {
229                 struct weston_pointer_grab grab;
230                 struct weston_touch_grab touch_grab;
231                 struct wl_list surfaces_list;
232                 struct wl_client *client;
233                 int32_t initial_up;
234                 enum { POINTER, TOUCH } type;
235         } popup_grab;
236 };
237
238 struct shell_client {
239         struct wl_resource *resource;
240         struct wl_client *client;
241         struct desktop_shell *shell;
242         struct wl_listener destroy_listener;
243         struct wl_event_source *ping_timer;
244         uint32_t ping_serial;
245         int unresponsive;
246         struct wl_list surface_list;
247 };
248
249 static struct desktop_shell *
250 shell_surface_get_shell(struct shell_surface *shsurf);
251
252 static void
253 surface_rotate(struct shell_surface *surface, struct weston_pointer *pointer);
254
255 static void
256 shell_fade_startup(struct desktop_shell *shell);
257
258 static struct shell_seat *
259 get_shell_seat(struct weston_seat *seat);
260
261 static void
262 get_output_panel_size(struct desktop_shell *shell,
263                       struct weston_output *output,
264                       int *width, int *height);
265
266 static void
267 shell_surface_update_child_surface_layers(struct shell_surface *shsurf);
268
269 static bool
270 shell_surface_is_wl_shell_surface(struct shell_surface *shsurf);
271
272 static bool
273 shell_surface_is_xdg_surface(struct shell_surface *shsurf);
274
275 static bool
276 shell_surface_is_xdg_popup(struct shell_surface *shsurf);
277
278 static void
279 shell_surface_set_parent(struct shell_surface *shsurf,
280                          struct weston_surface *parent);
281
282 static int
283 shell_surface_get_label(struct weston_surface *surface, char *buf, size_t len)
284 {
285         struct shell_surface *shsurf;
286         const char *typestr[] = {
287                 [SHELL_SURFACE_NONE] = "unidentified",
288                 [SHELL_SURFACE_TOPLEVEL] = "top-level",
289                 [SHELL_SURFACE_POPUP] = "popup",
290                 [SHELL_SURFACE_XWAYLAND] = "Xwayland",
291         };
292         const char *t, *c;
293
294         shsurf = get_shell_surface(surface);
295         if (!shsurf)
296                 return snprintf(buf, len, "unidentified window");
297
298         t = shsurf->title;
299         c = shsurf->class;
300
301         return snprintf(buf, len, "%s window%s%s%s%s%s",
302                 typestr[shsurf->type],
303                 t ? " '" : "", t ?: "", t ? "'" : "",
304                 c ? " of " : "", c ?: "");
305 }
306
307 static bool
308 shell_surface_is_top_fullscreen(struct shell_surface *shsurf)
309 {
310         struct desktop_shell *shell;
311         struct weston_view *view;
312         struct shell_surface *top_fs_shsurf = NULL;
313
314         shell = shell_surface_get_shell(shsurf);
315
316         if (wl_list_empty(&shell->fullscreen_layer.view_list.link))
317                 return false;
318
319         /* Find topmost shsurf on the same fullscreen output on which shsurf
320          * is displaying. We don't care about other outputs.
321          */
322         wl_list_for_each(view, &shell->fullscreen_layer.view_list.link,
323                                          layer_link.link) {
324                 struct shell_surface *cand_shsurf = get_shell_surface(view->surface);
325
326                 if (cand_shsurf &&
327                         (cand_shsurf->fullscreen_output == shsurf->fullscreen_output)) {
328                         top_fs_shsurf = cand_shsurf;
329                         break;
330                 }
331         }
332
333         return (shsurf == top_fs_shsurf);
334 }
335
336 static void
337 destroy_shell_grab_shsurf(struct wl_listener *listener, void *data)
338 {
339         struct shell_grab *grab;
340
341         grab = container_of(listener, struct shell_grab,
342                             shsurf_destroy_listener);
343
344         grab->shsurf = NULL;
345 }
346
347 struct weston_view *
348 get_default_view(struct weston_surface *surface)
349 {
350         struct shell_surface *shsurf;
351         struct weston_view *view;
352
353         if (!surface || wl_list_empty(&surface->views))
354                 return NULL;
355
356         shsurf = get_shell_surface(surface);
357         if (shsurf)
358                 return shsurf->view;
359
360         wl_list_for_each(view, &surface->views, surface_link)
361                 if (weston_view_is_mapped(view))
362                         return view;
363
364         return container_of(surface->views.next, struct weston_view, surface_link);
365 }
366
367 static void
368 popup_grab_end(struct weston_pointer *pointer);
369 static void
370 touch_popup_grab_end(struct weston_touch *touch);
371
372 static void
373 shell_grab_start(struct shell_grab *grab,
374                  const struct weston_pointer_grab_interface *interface,
375                  struct shell_surface *shsurf,
376                  struct weston_pointer *pointer,
377                  enum weston_desktop_shell_cursor cursor)
378 {
379         struct desktop_shell *shell = shsurf->shell;
380         struct weston_touch *touch = weston_seat_get_touch(pointer->seat);
381
382         popup_grab_end(pointer);
383         if (touch)
384                 touch_popup_grab_end(touch);
385
386         grab->grab.interface = interface;
387         grab->shsurf = shsurf;
388         grab->shsurf_destroy_listener.notify = destroy_shell_grab_shsurf;
389         wl_signal_add(&shsurf->destroy_signal,
390                       &grab->shsurf_destroy_listener);
391
392         shsurf->grabbed = 1;
393         weston_pointer_start_grab(pointer, &grab->grab);
394         if (shell->child.desktop_shell) {
395                 weston_desktop_shell_send_grab_cursor(shell->child.desktop_shell,
396                                                cursor);
397                 weston_pointer_set_focus(pointer,
398                                          get_default_view(shell->grab_surface),
399                                          wl_fixed_from_int(0),
400                                          wl_fixed_from_int(0));
401         }
402 }
403
404 static void
405 get_output_panel_size(struct desktop_shell *shell,
406                       struct weston_output *output,
407                       int *width,
408                       int *height)
409 {
410         struct weston_view *view;
411
412         *width = 0;
413         *height = 0;
414
415         if (!output)
416                 return;
417
418         wl_list_for_each(view, &shell->panel_layer.view_list.link, layer_link.link) {
419                 float x, y;
420
421                 if (view->surface->output != output)
422                         continue;
423
424                 switch (shell->panel_position) {
425                 case WESTON_DESKTOP_SHELL_PANEL_POSITION_TOP:
426                 case WESTON_DESKTOP_SHELL_PANEL_POSITION_BOTTOM:
427                         weston_view_to_global_float(view,
428                                                     view->surface->width, 0,
429                                                     &x, &y);
430
431                         *width = (int)x - output->x;
432                         *height = view->surface->height + (int) y - output->y;
433                         return;
434
435                 case WESTON_DESKTOP_SHELL_PANEL_POSITION_LEFT:
436                 case WESTON_DESKTOP_SHELL_PANEL_POSITION_RIGHT:
437                         weston_view_to_global_float(view,
438                                                     0, view->surface->height,
439                                                     &x, &y);
440
441                         *width = view->surface->width + (int)x - output->x;
442                         *height = (int)y - output->y;
443                         return;
444
445                 default:
446                         /* we've already set width and height to
447                          * fallback values. */
448                         break;
449                 }
450         }
451
452         /* the correct view wasn't found */
453 }
454
455 static void
456 get_output_work_area(void *data,
457                      struct weston_output *output,
458                      pixman_rectangle32_t *area)
459 {
460         struct desktop_shell *shell = data;
461         int32_t panel_width = 0, panel_height = 0;
462
463         area->x = output->x;
464         area->y = output->y;
465
466         get_output_panel_size(shell, output, &panel_width, &panel_height);
467         switch (shell->panel_position) {
468         case WESTON_DESKTOP_SHELL_PANEL_POSITION_TOP:
469         default:
470                 area->y += panel_height;
471         case WESTON_DESKTOP_SHELL_PANEL_POSITION_BOTTOM:
472                 area->width = output->width;
473                 area->height = output->height - panel_height;
474                 break;
475         case WESTON_DESKTOP_SHELL_PANEL_POSITION_LEFT:
476                 area->x += panel_width;
477         case WESTON_DESKTOP_SHELL_PANEL_POSITION_RIGHT:
478                 area->width = output->width - panel_width;
479                 area->height = output->height;
480                 break;
481         }
482 }
483
484 static struct shell_surface *
485 find_toplevel_surface(struct shell_surface *in_surface)
486 {
487         struct shell_surface *surface = in_surface;
488
489         while (surface) {
490                 if (surface->type == SHELL_SURFACE_TOPLEVEL)
491                         return surface;
492                 surface = get_shell_surface(surface->parent);
493         }
494
495         /* If no top level surface was found, just use whatever surface was
496            originally provided. */
497         return in_surface;
498 }
499
500 static void
501 send_configure_for_surface(struct shell_surface *shsurf)
502 {
503         int32_t width, height;
504         struct surface_state *state;
505
506         if (shsurf->state_requested)
507                 state = &shsurf->requested_state;
508         else if (shsurf->state_changed)
509                 state = &shsurf->next_state;
510         else
511                 state = &shsurf->state;
512
513         if (state->fullscreen) {
514                 width = shsurf->output->width;
515                 height = shsurf->output->height;
516         } else if (state->maximized) {
517                 struct desktop_shell *shell;
518                 pixman_rectangle32_t area;
519
520                 shell = shell_surface_get_shell(shsurf);
521                 get_output_work_area(shell, shsurf->output, &area);
522
523                 width = area.width;
524                 height = area.height;
525         } else if (shsurf->resize_edges) {
526                 width = shsurf->geometry.width;
527                 height = shsurf->geometry.height;
528         } else {
529                 width = 0;
530                 height = 0;
531         }
532
533         shsurf->client->send_configure(shsurf->surface, width, height);
534 }
535
536 static void
537 shell_surface_state_changed(struct shell_surface *shsurf)
538 {
539         if (shell_surface_is_xdg_surface(shsurf))
540                 send_configure_for_surface(shsurf);
541 }
542
543 static void
544 shell_grab_end(struct shell_grab *grab)
545 {
546         if (grab->shsurf) {
547                 wl_list_remove(&grab->shsurf_destroy_listener.link);
548                 grab->shsurf->grabbed = 0;
549
550                 if (grab->shsurf->resize_edges) {
551                         grab->shsurf->resize_edges = 0;
552                         shell_surface_state_changed(grab->shsurf);
553                 }
554         }
555
556         weston_pointer_end_grab(grab->grab.pointer);
557 }
558
559 static void
560 shell_touch_grab_start(struct shell_touch_grab *grab,
561                        const struct weston_touch_grab_interface *interface,
562                        struct shell_surface *shsurf,
563                        struct weston_touch *touch)
564 {
565         struct desktop_shell *shell = shsurf->shell;
566         struct weston_pointer *pointer = weston_seat_get_pointer(touch->seat);
567
568         touch_popup_grab_end(touch);
569         if (pointer)
570                 popup_grab_end(pointer);
571
572         grab->grab.interface = interface;
573         grab->shsurf = shsurf;
574         grab->shsurf_destroy_listener.notify = destroy_shell_grab_shsurf;
575         wl_signal_add(&shsurf->destroy_signal,
576                       &grab->shsurf_destroy_listener);
577
578         grab->touch = touch;
579         shsurf->grabbed = 1;
580
581         weston_touch_start_grab(touch, &grab->grab);
582         if (shell->child.desktop_shell)
583                 weston_touch_set_focus(touch,
584                                        get_default_view(shell->grab_surface));
585 }
586
587 static void
588 shell_touch_grab_end(struct shell_touch_grab *grab)
589 {
590         if (grab->shsurf) {
591                 wl_list_remove(&grab->shsurf_destroy_listener.link);
592                 grab->shsurf->grabbed = 0;
593         }
594
595         weston_touch_end_grab(grab->touch);
596 }
597
598 static void
599 center_on_output(struct weston_view *view,
600                  struct weston_output *output);
601
602 static enum weston_keyboard_modifier
603 get_modifier(char *modifier)
604 {
605         if (!modifier)
606                 return MODIFIER_SUPER;
607
608         if (!strcmp("ctrl", modifier))
609                 return MODIFIER_CTRL;
610         else if (!strcmp("alt", modifier))
611                 return MODIFIER_ALT;
612         else if (!strcmp("super", modifier))
613                 return MODIFIER_SUPER;
614         else if (!strcmp("none", modifier))
615                 return 0;
616         else
617                 return MODIFIER_SUPER;
618 }
619
620 static enum animation_type
621 get_animation_type(char *animation)
622 {
623         if (!animation)
624                 return ANIMATION_NONE;
625
626         if (!strcmp("zoom", animation))
627                 return ANIMATION_ZOOM;
628         else if (!strcmp("fade", animation))
629                 return ANIMATION_FADE;
630         else if (!strcmp("dim-layer", animation))
631                 return ANIMATION_DIM_LAYER;
632         else
633                 return ANIMATION_NONE;
634 }
635
636 static void
637 shell_configuration(struct desktop_shell *shell)
638 {
639         struct weston_config_section *section;
640         char *s, *client;
641         int ret;
642         int allow_zap;
643
644         section = weston_config_get_section(wet_get_config(shell->compositor),
645                                             "shell", NULL, NULL);
646         ret = asprintf(&client, "%s/%s", weston_config_get_libexec_dir(),
647                        WESTON_SHELL_CLIENT);
648         if (ret < 0)
649                 client = NULL;
650         weston_config_section_get_string(section,
651                                          "client", &s, client);
652         free(client);
653         shell->client = s;
654
655         weston_config_section_get_bool(section,
656                                        "allow-zap", &allow_zap, true);
657         shell->allow_zap = allow_zap;
658
659         weston_config_section_get_string(section,
660                                          "binding-modifier", &s, "super");
661         shell->binding_modifier = get_modifier(s);
662         free(s);
663
664         weston_config_section_get_string(section,
665                                          "exposay-modifier", &s, "none");
666         shell->exposay_modifier = get_modifier(s);
667         free(s);
668
669         weston_config_section_get_string(section, "animation", &s, "none");
670         shell->win_animation_type = get_animation_type(s);
671         free(s);
672         weston_config_section_get_string(section, "close-animation", &s, "fade");
673         shell->win_close_animation_type = get_animation_type(s);
674         free(s);
675         weston_config_section_get_string(section,
676                                          "startup-animation", &s, "fade");
677         shell->startup_animation_type = get_animation_type(s);
678         free(s);
679         if (shell->startup_animation_type == ANIMATION_ZOOM)
680                 shell->startup_animation_type = ANIMATION_NONE;
681         weston_config_section_get_string(section, "focus-animation", &s, "none");
682         shell->focus_animation_type = get_animation_type(s);
683         free(s);
684         weston_config_section_get_uint(section, "num-workspaces",
685                                        &shell->workspaces.num,
686                                        DEFAULT_NUM_WORKSPACES);
687 }
688
689 struct weston_output *
690 get_default_output(struct weston_compositor *compositor)
691 {
692         if (wl_list_empty(&compositor->output_list))
693                 return NULL;
694
695         return container_of(compositor->output_list.next,
696                             struct weston_output, link);
697 }
698
699 static int
700 focus_surface_get_label(struct weston_surface *surface, char *buf, size_t len)
701 {
702         return snprintf(buf, len, "focus highlight effect for output %s",
703                         surface->output->name);
704 }
705
706 /* no-op func for checking focus surface */
707 static void
708 focus_surface_committed(struct weston_surface *es, int32_t sx, int32_t sy)
709 {
710 }
711
712 static struct focus_surface *
713 get_focus_surface(struct weston_surface *surface)
714 {
715         if (surface->committed == focus_surface_committed)
716                 return surface->committed_private;
717         else
718                 return NULL;
719 }
720
721 static bool
722 is_focus_surface (struct weston_surface *es)
723 {
724         return (es->committed == focus_surface_committed);
725 }
726
727 static bool
728 is_focus_view (struct weston_view *view)
729 {
730         return is_focus_surface (view->surface);
731 }
732
733 static struct focus_surface *
734 create_focus_surface(struct weston_compositor *ec,
735                      struct weston_output *output)
736 {
737         struct focus_surface *fsurf = NULL;
738         struct weston_surface *surface = NULL;
739
740         fsurf = malloc(sizeof *fsurf);
741         if (!fsurf)
742                 return NULL;
743
744         fsurf->surface = weston_surface_create(ec);
745         surface = fsurf->surface;
746         if (surface == NULL) {
747                 free(fsurf);
748                 return NULL;
749         }
750
751         surface->committed = focus_surface_committed;
752         surface->output = output;
753         surface->is_mapped = true;
754         surface->committed_private = fsurf;
755         weston_surface_set_label_func(surface, focus_surface_get_label);
756
757         fsurf->view = weston_view_create(surface);
758         if (fsurf->view == NULL) {
759                 weston_surface_destroy(surface);
760                 free(fsurf);
761                 return NULL;
762         }
763         fsurf->view->output = output;
764         fsurf->view->is_mapped = true;
765
766         weston_surface_set_size(surface, output->width, output->height);
767         weston_view_set_position(fsurf->view, output->x, output->y);
768         weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1.0);
769         pixman_region32_fini(&surface->opaque);
770         pixman_region32_init_rect(&surface->opaque, output->x, output->y,
771                                   output->width, output->height);
772         pixman_region32_fini(&surface->input);
773         pixman_region32_init(&surface->input);
774
775         wl_list_init(&fsurf->workspace_transform.link);
776
777         return fsurf;
778 }
779
780 static void
781 focus_surface_destroy(struct focus_surface *fsurf)
782 {
783         weston_surface_destroy(fsurf->surface);
784         free(fsurf);
785 }
786
787 static void
788 focus_animation_done(struct weston_view_animation *animation, void *data)
789 {
790         struct workspace *ws = data;
791
792         ws->focus_animation = NULL;
793 }
794
795 static void
796 focus_state_destroy(struct focus_state *state)
797 {
798         wl_list_remove(&state->seat_destroy_listener.link);
799         wl_list_remove(&state->surface_destroy_listener.link);
800         free(state);
801 }
802
803 static void
804 focus_state_seat_destroy(struct wl_listener *listener, void *data)
805 {
806         struct focus_state *state = container_of(listener,
807                                                  struct focus_state,
808                                                  seat_destroy_listener);
809
810         wl_list_remove(&state->link);
811         focus_state_destroy(state);
812 }
813
814 static void
815 focus_state_surface_destroy(struct wl_listener *listener, void *data)
816 {
817         struct focus_state *state = container_of(listener,
818                                                  struct focus_state,
819                                                  surface_destroy_listener);
820         struct desktop_shell *shell;
821         struct weston_surface *main_surface;
822         struct weston_view *next;
823         struct weston_view *view;
824
825         main_surface = weston_surface_get_main_surface(state->keyboard_focus);
826
827         next = NULL;
828         wl_list_for_each(view,
829                          &state->ws->layer.view_list.link, layer_link.link) {
830                 if (view->surface == main_surface)
831                         continue;
832                 if (is_focus_view(view))
833                         continue;
834
835                 next = view;
836                 break;
837         }
838
839         /* if the focus was a sub-surface, activate its main surface */
840         if (main_surface != state->keyboard_focus)
841                 next = get_default_view(main_surface);
842
843         shell = state->seat->compositor->shell_interface.shell;
844         if (next) {
845                 state->keyboard_focus = NULL;
846                 activate(shell, next, state->seat,
847                          WESTON_ACTIVATE_FLAG_CONFIGURE);
848         } else {
849                 if (shell->focus_animation_type == ANIMATION_DIM_LAYER) {
850                         if (state->ws->focus_animation)
851                                 weston_view_animation_destroy(state->ws->focus_animation);
852
853                         state->ws->focus_animation = weston_fade_run(
854                                 state->ws->fsurf_front->view,
855                                 state->ws->fsurf_front->view->alpha, 0.0, 300,
856                                 focus_animation_done, state->ws);
857                 }
858
859                 wl_list_remove(&state->link);
860                 focus_state_destroy(state);
861         }
862 }
863
864 static struct focus_state *
865 focus_state_create(struct weston_seat *seat, struct workspace *ws)
866 {
867         struct focus_state *state;
868
869         state = malloc(sizeof *state);
870         if (state == NULL)
871                 return NULL;
872
873         state->keyboard_focus = NULL;
874         state->ws = ws;
875         state->seat = seat;
876         wl_list_insert(&ws->focus_list, &state->link);
877
878         state->seat_destroy_listener.notify = focus_state_seat_destroy;
879         state->surface_destroy_listener.notify = focus_state_surface_destroy;
880         wl_signal_add(&seat->destroy_signal,
881                       &state->seat_destroy_listener);
882         wl_list_init(&state->surface_destroy_listener.link);
883
884         return state;
885 }
886
887 static struct focus_state *
888 ensure_focus_state(struct desktop_shell *shell, struct weston_seat *seat)
889 {
890         struct workspace *ws = get_current_workspace(shell);
891         struct focus_state *state;
892
893         wl_list_for_each(state, &ws->focus_list, link)
894                 if (state->seat == seat)
895                         break;
896
897         if (&state->link == &ws->focus_list)
898                 state = focus_state_create(seat, ws);
899
900         return state;
901 }
902
903 static void
904 focus_state_set_focus(struct focus_state *state,
905                       struct weston_surface *surface)
906 {
907         if (state->keyboard_focus) {
908                 wl_list_remove(&state->surface_destroy_listener.link);
909                 wl_list_init(&state->surface_destroy_listener.link);
910         }
911
912         state->keyboard_focus = surface;
913         if (surface)
914                 wl_signal_add(&surface->destroy_signal,
915                               &state->surface_destroy_listener);
916 }
917
918 static void
919 restore_focus_state(struct desktop_shell *shell, struct workspace *ws)
920 {
921         struct focus_state *state, *next;
922         struct weston_surface *surface;
923         struct wl_list pending_seat_list;
924         struct weston_seat *seat, *next_seat;
925
926         /* Temporarily steal the list of seats so that we can keep
927          * track of the seats we've already processed */
928         wl_list_init(&pending_seat_list);
929         wl_list_insert_list(&pending_seat_list, &shell->compositor->seat_list);
930         wl_list_init(&shell->compositor->seat_list);
931
932         wl_list_for_each_safe(state, next, &ws->focus_list, link) {
933                 struct weston_keyboard *keyboard =
934                         weston_seat_get_keyboard(state->seat);
935
936                 wl_list_remove(&state->seat->link);
937                 wl_list_insert(&shell->compositor->seat_list,
938                                &state->seat->link);
939
940                 if (!keyboard)
941                         continue;
942
943                 surface = state->keyboard_focus;
944
945                 weston_keyboard_set_focus(keyboard, surface);
946         }
947
948         /* For any remaining seats that we don't have a focus state
949          * for we'll reset the keyboard focus to NULL */
950         wl_list_for_each_safe(seat, next_seat, &pending_seat_list, link) {
951                 struct weston_keyboard *keyboard =
952                         weston_seat_get_keyboard(seat);
953
954                 wl_list_insert(&shell->compositor->seat_list, &seat->link);
955
956                 if (!keyboard)
957                         continue;
958
959                 weston_keyboard_set_focus(keyboard, NULL);
960         }
961 }
962
963 static void
964 replace_focus_state(struct desktop_shell *shell, struct workspace *ws,
965                     struct weston_seat *seat)
966 {
967         struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
968         struct focus_state *state;
969
970         wl_list_for_each(state, &ws->focus_list, link) {
971                 if (state->seat == seat) {
972                         focus_state_set_focus(state, keyboard->focus);
973                         return;
974                 }
975         }
976 }
977
978 static void
979 drop_focus_state(struct desktop_shell *shell, struct workspace *ws,
980                  struct weston_surface *surface)
981 {
982         struct focus_state *state;
983
984         wl_list_for_each(state, &ws->focus_list, link)
985                 if (state->keyboard_focus == surface)
986                         focus_state_set_focus(state, NULL);
987 }
988
989 static void
990 animate_focus_change(struct desktop_shell *shell, struct workspace *ws,
991                      struct weston_view *from, struct weston_view *to)
992 {
993         struct weston_output *output;
994         bool focus_surface_created = false;
995
996         /* FIXME: Only support dim animation using two layers */
997         if (from == to || shell->focus_animation_type != ANIMATION_DIM_LAYER)
998                 return;
999
1000         output = get_default_output(shell->compositor);
1001         if (ws->fsurf_front == NULL && (from || to)) {
1002                 ws->fsurf_front = create_focus_surface(shell->compositor, output);
1003                 if (ws->fsurf_front == NULL)
1004                         return;
1005                 ws->fsurf_front->view->alpha = 0.0;
1006
1007                 ws->fsurf_back = create_focus_surface(shell->compositor, output);
1008                 if (ws->fsurf_back == NULL) {
1009                         focus_surface_destroy(ws->fsurf_front);
1010                         return;
1011                 }
1012                 ws->fsurf_back->view->alpha = 0.0;
1013
1014                 focus_surface_created = true;
1015         } else {
1016                 weston_layer_entry_remove(&ws->fsurf_front->view->layer_link);
1017                 weston_layer_entry_remove(&ws->fsurf_back->view->layer_link);
1018         }
1019
1020         if (ws->focus_animation) {
1021                 weston_view_animation_destroy(ws->focus_animation);
1022                 ws->focus_animation = NULL;
1023         }
1024
1025         if (to)
1026                 weston_layer_entry_insert(&to->layer_link,
1027                                           &ws->fsurf_front->view->layer_link);
1028         else if (from)
1029                 weston_layer_entry_insert(&ws->layer.view_list,
1030                                           &ws->fsurf_front->view->layer_link);
1031
1032         if (focus_surface_created) {
1033                 ws->focus_animation = weston_fade_run(
1034                         ws->fsurf_front->view,
1035                         ws->fsurf_front->view->alpha, 0.4, 300,
1036                         focus_animation_done, ws);
1037         } else if (from) {
1038                 weston_layer_entry_insert(&from->layer_link,
1039                                           &ws->fsurf_back->view->layer_link);
1040                 ws->focus_animation = weston_stable_fade_run(
1041                         ws->fsurf_front->view, 0.0,
1042                         ws->fsurf_back->view, 0.4,
1043                         focus_animation_done, ws);
1044         } else if (to) {
1045                 weston_layer_entry_insert(&ws->layer.view_list,
1046                                           &ws->fsurf_back->view->layer_link);
1047                 ws->focus_animation = weston_stable_fade_run(
1048                         ws->fsurf_front->view, 0.0,
1049                         ws->fsurf_back->view, 0.4,
1050                         focus_animation_done, ws);
1051         }
1052 }
1053
1054 static void
1055 workspace_destroy(struct workspace *ws)
1056 {
1057         struct focus_state *state, *next;
1058
1059         wl_list_for_each_safe(state, next, &ws->focus_list, link)
1060                 focus_state_destroy(state);
1061
1062         if (ws->fsurf_front)
1063                 focus_surface_destroy(ws->fsurf_front);
1064         if (ws->fsurf_back)
1065                 focus_surface_destroy(ws->fsurf_back);
1066
1067         free(ws);
1068 }
1069
1070 static void
1071 seat_destroyed(struct wl_listener *listener, void *data)
1072 {
1073         struct weston_seat *seat = data;
1074         struct focus_state *state, *next;
1075         struct workspace *ws = container_of(listener,
1076                                             struct workspace,
1077                                             seat_destroyed_listener);
1078
1079         wl_list_for_each_safe(state, next, &ws->focus_list, link)
1080                 if (state->seat == seat)
1081                         wl_list_remove(&state->link);
1082 }
1083
1084 static struct workspace *
1085 workspace_create(void)
1086 {
1087         struct workspace *ws = malloc(sizeof *ws);
1088         if (ws == NULL)
1089                 return NULL;
1090
1091         weston_layer_init(&ws->layer, NULL);
1092
1093         wl_list_init(&ws->focus_list);
1094         wl_list_init(&ws->seat_destroyed_listener.link);
1095         ws->seat_destroyed_listener.notify = seat_destroyed;
1096         ws->fsurf_front = NULL;
1097         ws->fsurf_back = NULL;
1098         ws->focus_animation = NULL;
1099
1100         return ws;
1101 }
1102
1103 static int
1104 workspace_is_empty(struct workspace *ws)
1105 {
1106         return wl_list_empty(&ws->layer.view_list.link);
1107 }
1108
1109 static struct workspace *
1110 get_workspace(struct desktop_shell *shell, unsigned int index)
1111 {
1112         struct workspace **pws = shell->workspaces.array.data;
1113         assert(index < shell->workspaces.num);
1114         pws += index;
1115         return *pws;
1116 }
1117
1118 struct workspace *
1119 get_current_workspace(struct desktop_shell *shell)
1120 {
1121         return get_workspace(shell, shell->workspaces.current);
1122 }
1123
1124 static void
1125 activate_workspace(struct desktop_shell *shell, unsigned int index)
1126 {
1127         struct workspace *ws;
1128
1129         ws = get_workspace(shell, index);
1130         wl_list_insert(&shell->panel_layer.link, &ws->layer.link);
1131
1132         shell->workspaces.current = index;
1133 }
1134
1135 static unsigned int
1136 get_output_height(struct weston_output *output)
1137 {
1138         return abs(output->region.extents.y1 - output->region.extents.y2);
1139 }
1140
1141 static void
1142 view_translate(struct workspace *ws, struct weston_view *view, double d)
1143 {
1144         struct weston_transform *transform;
1145
1146         if (is_focus_view(view)) {
1147                 struct focus_surface *fsurf = get_focus_surface(view->surface);
1148                 transform = &fsurf->workspace_transform;
1149         } else {
1150                 struct shell_surface *shsurf = get_shell_surface(view->surface);
1151                 transform = &shsurf->workspace_transform;
1152         }
1153
1154         if (wl_list_empty(&transform->link))
1155                 wl_list_insert(view->geometry.transformation_list.prev,
1156                                &transform->link);
1157
1158         weston_matrix_init(&transform->matrix);
1159         weston_matrix_translate(&transform->matrix,
1160                                 0.0, d, 0.0);
1161         weston_view_geometry_dirty(view);
1162 }
1163
1164 static void
1165 workspace_translate_out(struct workspace *ws, double fraction)
1166 {
1167         struct weston_view *view;
1168         unsigned int height;
1169         double d;
1170
1171         wl_list_for_each(view, &ws->layer.view_list.link, layer_link.link) {
1172                 height = get_output_height(view->surface->output);
1173                 d = height * fraction;
1174
1175                 view_translate(ws, view, d);
1176         }
1177 }
1178
1179 static void
1180 workspace_translate_in(struct workspace *ws, double fraction)
1181 {
1182         struct weston_view *view;
1183         unsigned int height;
1184         double d;
1185
1186         wl_list_for_each(view, &ws->layer.view_list.link, layer_link.link) {
1187                 height = get_output_height(view->surface->output);
1188
1189                 if (fraction > 0)
1190                         d = -(height - height * fraction);
1191                 else
1192                         d = height + height * fraction;
1193
1194                 view_translate(ws, view, d);
1195         }
1196 }
1197
1198 static void
1199 reverse_workspace_change_animation(struct desktop_shell *shell,
1200                                    unsigned int index,
1201                                    struct workspace *from,
1202                                    struct workspace *to)
1203 {
1204         shell->workspaces.current = index;
1205
1206         shell->workspaces.anim_to = to;
1207         shell->workspaces.anim_from = from;
1208         shell->workspaces.anim_dir = -1 * shell->workspaces.anim_dir;
1209         shell->workspaces.anim_timestamp = 0;
1210
1211         weston_compositor_schedule_repaint(shell->compositor);
1212 }
1213
1214 static void
1215 workspace_deactivate_transforms(struct workspace *ws)
1216 {
1217         struct weston_view *view;
1218         struct weston_transform *transform;
1219
1220         wl_list_for_each(view, &ws->layer.view_list.link, layer_link.link) {
1221                 if (is_focus_view(view)) {
1222                         struct focus_surface *fsurf = get_focus_surface(view->surface);
1223                         transform = &fsurf->workspace_transform;
1224                 } else {
1225                         struct shell_surface *shsurf = get_shell_surface(view->surface);
1226                         transform = &shsurf->workspace_transform;
1227                 }
1228
1229                 if (!wl_list_empty(&transform->link)) {
1230                         wl_list_remove(&transform->link);
1231                         wl_list_init(&transform->link);
1232                 }
1233                 weston_view_geometry_dirty(view);
1234         }
1235 }
1236
1237 static void
1238 finish_workspace_change_animation(struct desktop_shell *shell,
1239                                   struct workspace *from,
1240                                   struct workspace *to)
1241 {
1242         struct weston_view *view;
1243
1244         weston_compositor_schedule_repaint(shell->compositor);
1245
1246         /* Views that extend past the bottom of the output are still
1247          * visible after the workspace animation ends but before its layer
1248          * is hidden. In that case, we need to damage below those views so
1249          * that the screen is properly repainted. */
1250         wl_list_for_each(view, &from->layer.view_list.link, layer_link.link)
1251                 weston_view_damage_below(view);
1252
1253         wl_list_remove(&shell->workspaces.animation.link);
1254         workspace_deactivate_transforms(from);
1255         workspace_deactivate_transforms(to);
1256         shell->workspaces.anim_to = NULL;
1257
1258         wl_list_remove(&shell->workspaces.anim_from->layer.link);
1259 }
1260
1261 static void
1262 animate_workspace_change_frame(struct weston_animation *animation,
1263                                struct weston_output *output, uint32_t msecs)
1264 {
1265         struct desktop_shell *shell =
1266                 container_of(animation, struct desktop_shell,
1267                              workspaces.animation);
1268         struct workspace *from = shell->workspaces.anim_from;
1269         struct workspace *to = shell->workspaces.anim_to;
1270         uint32_t t;
1271         double x, y;
1272
1273         if (workspace_is_empty(from) && workspace_is_empty(to)) {
1274                 finish_workspace_change_animation(shell, from, to);
1275                 return;
1276         }
1277
1278         if (shell->workspaces.anim_timestamp == 0) {
1279                 if (shell->workspaces.anim_current == 0.0)
1280                         shell->workspaces.anim_timestamp = msecs;
1281                 else
1282                         shell->workspaces.anim_timestamp =
1283                                 msecs -
1284                                 /* Invers of movement function 'y' below. */
1285                                 (asin(1.0 - shell->workspaces.anim_current) *
1286                                  DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH *
1287                                  M_2_PI);
1288         }
1289
1290         t = msecs - shell->workspaces.anim_timestamp;
1291
1292         /*
1293          * x = [0, π/2]
1294          * y(x) = sin(x)
1295          */
1296         x = t * (1.0/DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH) * M_PI_2;
1297         y = sin(x);
1298
1299         if (t < DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH) {
1300                 weston_compositor_schedule_repaint(shell->compositor);
1301
1302                 workspace_translate_out(from, shell->workspaces.anim_dir * y);
1303                 workspace_translate_in(to, shell->workspaces.anim_dir * y);
1304                 shell->workspaces.anim_current = y;
1305
1306                 weston_compositor_schedule_repaint(shell->compositor);
1307         }
1308         else
1309                 finish_workspace_change_animation(shell, from, to);
1310 }
1311
1312 static void
1313 animate_workspace_change(struct desktop_shell *shell,
1314                          unsigned int index,
1315                          struct workspace *from,
1316                          struct workspace *to)
1317 {
1318         struct weston_output *output;
1319
1320         int dir;
1321
1322         if (index > shell->workspaces.current)
1323                 dir = -1;
1324         else
1325                 dir = 1;
1326
1327         shell->workspaces.current = index;
1328
1329         shell->workspaces.anim_dir = dir;
1330         shell->workspaces.anim_from = from;
1331         shell->workspaces.anim_to = to;
1332         shell->workspaces.anim_current = 0.0;
1333         shell->workspaces.anim_timestamp = 0;
1334
1335         output = container_of(shell->compositor->output_list.next,
1336                               struct weston_output, link);
1337         wl_list_insert(&output->animation_list,
1338                        &shell->workspaces.animation.link);
1339
1340         wl_list_insert(from->layer.link.prev, &to->layer.link);
1341
1342         workspace_translate_in(to, 0);
1343
1344         restore_focus_state(shell, to);
1345
1346         weston_compositor_schedule_repaint(shell->compositor);
1347 }
1348
1349 static void
1350 update_workspace(struct desktop_shell *shell, unsigned int index,
1351                  struct workspace *from, struct workspace *to)
1352 {
1353         shell->workspaces.current = index;
1354         wl_list_insert(&from->layer.link, &to->layer.link);
1355         wl_list_remove(&from->layer.link);
1356 }
1357
1358 static void
1359 change_workspace(struct desktop_shell *shell, unsigned int index)
1360 {
1361         struct workspace *from;
1362         struct workspace *to;
1363         struct focus_state *state;
1364
1365         if (index == shell->workspaces.current)
1366                 return;
1367
1368         /* Don't change workspace when there is any fullscreen surfaces. */
1369         if (!wl_list_empty(&shell->fullscreen_layer.view_list.link))
1370                 return;
1371
1372         from = get_current_workspace(shell);
1373         to = get_workspace(shell, index);
1374
1375         if (shell->workspaces.anim_from == to &&
1376             shell->workspaces.anim_to == from) {
1377                 restore_focus_state(shell, to);
1378                 reverse_workspace_change_animation(shell, index, from, to);
1379                 return;
1380         }
1381
1382         if (shell->workspaces.anim_to != NULL)
1383                 finish_workspace_change_animation(shell,
1384                                                   shell->workspaces.anim_from,
1385                                                   shell->workspaces.anim_to);
1386
1387         restore_focus_state(shell, to);
1388
1389         if (shell->focus_animation_type != ANIMATION_NONE) {
1390                 wl_list_for_each(state, &from->focus_list, link)
1391                         if (state->keyboard_focus)
1392                                 animate_focus_change(shell, from,
1393                                                      get_default_view(state->keyboard_focus), NULL);
1394
1395                 wl_list_for_each(state, &to->focus_list, link)
1396                         if (state->keyboard_focus)
1397                                 animate_focus_change(shell, to,
1398                                                      NULL, get_default_view(state->keyboard_focus));
1399         }
1400
1401         if (workspace_is_empty(to) && workspace_is_empty(from))
1402                 update_workspace(shell, index, from, to);
1403         else
1404                 animate_workspace_change(shell, index, from, to);
1405 }
1406
1407 static bool
1408 workspace_has_only(struct workspace *ws, struct weston_surface *surface)
1409 {
1410         struct wl_list *list = &ws->layer.view_list.link;
1411         struct wl_list *e;
1412
1413         if (wl_list_empty(list))
1414                 return false;
1415
1416         e = list->next;
1417
1418         if (e->next != list)
1419                 return false;
1420
1421         return container_of(e, struct weston_view, layer_link.link)->surface == surface;
1422 }
1423
1424 static void
1425 surface_keyboard_focus_lost(struct weston_surface *surface)
1426 {
1427         struct weston_compositor *compositor = surface->compositor;
1428         struct weston_seat *seat;
1429         struct weston_surface *focus;
1430
1431         wl_list_for_each(seat, &compositor->seat_list, link) {
1432                 struct weston_keyboard *keyboard =
1433                         weston_seat_get_keyboard(seat);
1434
1435                 if (!keyboard)
1436                         continue;
1437
1438                 focus = weston_surface_get_main_surface(keyboard->focus);
1439                 if (focus == surface)
1440                         weston_keyboard_set_focus(keyboard, NULL);
1441         }
1442 }
1443
1444 static void
1445 take_surface_to_workspace_by_seat(struct desktop_shell *shell,
1446                                   struct weston_seat *seat,
1447                                   unsigned int index)
1448 {
1449         struct weston_keyboard *keyboard = weston_seat_get_keyboard(seat);
1450         struct weston_surface *surface;
1451         struct weston_view *view;
1452         struct shell_surface *shsurf;
1453         struct workspace *from;
1454         struct workspace *to;
1455         struct focus_state *state;
1456
1457         surface = weston_surface_get_main_surface(keyboard->focus);
1458         view = get_default_view(surface);
1459         if (view == NULL ||
1460             index == shell->workspaces.current ||
1461             is_focus_view(view))
1462                 return;
1463
1464         from = get_current_workspace(shell);
1465         to = get_workspace(shell, index);
1466
1467         weston_layer_entry_remove(&view->layer_link);
1468         weston_layer_entry_insert(&to->layer.view_list, &view->layer_link);
1469
1470         shsurf = get_shell_surface(surface);
1471         if (shsurf != NULL)
1472                 shell_surface_update_child_surface_layers(shsurf);
1473
1474         replace_focus_state(shell, to, seat);
1475         drop_focus_state(shell, from, surface);
1476
1477         if (shell->workspaces.anim_from == to &&
1478             shell->workspaces.anim_to == from) {
1479                 wl_list_remove(&to->layer.link);
1480                 wl_list_insert(from->layer.link.prev, &to->layer.link);
1481
1482                 reverse_workspace_change_animation(shell, index, from, to);
1483
1484                 return;
1485         }
1486
1487         if (shell->workspaces.anim_to != NULL)
1488                 finish_workspace_change_animation(shell,
1489                                                   shell->workspaces.anim_from,
1490                                                   shell->workspaces.anim_to);
1491
1492         if (workspace_is_empty(from) &&
1493             workspace_has_only(to, surface))
1494                 update_workspace(shell, index, from, to);
1495         else {
1496                 if (shsurf != NULL &&
1497                     wl_list_empty(&shsurf->workspace_transform.link))
1498                         wl_list_insert(&shell->workspaces.anim_sticky_list,
1499                                        &shsurf->workspace_transform.link);
1500
1501                 animate_workspace_change(shell, index, from, to);
1502         }
1503
1504         state = ensure_focus_state(shell, seat);
1505         if (state != NULL)
1506                 focus_state_set_focus(state, surface);
1507 }
1508
1509 static void
1510 touch_move_grab_down(struct weston_touch_grab *grab, uint32_t time,
1511                      int touch_id, wl_fixed_t x, wl_fixed_t y)
1512 {
1513 }
1514
1515 static void
1516 touch_move_grab_up(struct weston_touch_grab *grab, uint32_t time, int touch_id)
1517 {
1518         struct weston_touch_move_grab *move =
1519                 (struct weston_touch_move_grab *) container_of(
1520                         grab, struct shell_touch_grab, grab);
1521
1522         if (touch_id == 0)
1523                 move->active = 0;
1524
1525         if (grab->touch->num_tp == 0) {
1526                 shell_touch_grab_end(&move->base);
1527                 free(move);
1528         }
1529 }
1530
1531 static void
1532 touch_move_grab_motion(struct weston_touch_grab *grab, uint32_t time,
1533                        int touch_id, wl_fixed_t x, wl_fixed_t y)
1534 {
1535         struct weston_touch_move_grab *move = (struct weston_touch_move_grab *) grab;
1536         struct shell_surface *shsurf = move->base.shsurf;
1537         struct weston_surface *es;
1538         int dx = wl_fixed_to_int(grab->touch->grab_x + move->dx);
1539         int dy = wl_fixed_to_int(grab->touch->grab_y + move->dy);
1540
1541         if (!shsurf || !move->active)
1542                 return;
1543
1544         es = shsurf->surface;
1545
1546         weston_view_set_position(shsurf->view, dx, dy);
1547
1548         weston_compositor_schedule_repaint(es->compositor);
1549 }
1550
1551 static void
1552 touch_move_grab_frame(struct weston_touch_grab *grab)
1553 {
1554 }
1555
1556 static void
1557 touch_move_grab_cancel(struct weston_touch_grab *grab)
1558 {
1559         struct weston_touch_move_grab *move =
1560                 (struct weston_touch_move_grab *) container_of(
1561                         grab, struct shell_touch_grab, grab);
1562
1563         shell_touch_grab_end(&move->base);
1564         free(move);
1565 }
1566
1567 static const struct weston_touch_grab_interface touch_move_grab_interface = {
1568         touch_move_grab_down,
1569         touch_move_grab_up,
1570         touch_move_grab_motion,
1571         touch_move_grab_frame,
1572         touch_move_grab_cancel,
1573 };
1574
1575 static int
1576 surface_touch_move(struct shell_surface *shsurf, struct weston_touch *touch)
1577 {
1578         struct weston_touch_move_grab *move;
1579
1580         if (!shsurf)
1581                 return -1;
1582
1583         if (shsurf->state.fullscreen || shsurf->state.maximized)
1584                 return 0;
1585
1586         move = malloc(sizeof *move);
1587         if (!move)
1588                 return -1;
1589
1590         move->active = 1;
1591         move->dx = wl_fixed_from_double(shsurf->view->geometry.x) -
1592                         touch->grab_x;
1593         move->dy = wl_fixed_from_double(shsurf->view->geometry.y) -
1594                         touch->grab_y;
1595
1596         shell_touch_grab_start(&move->base, &touch_move_grab_interface, shsurf,
1597                                touch);
1598
1599         return 0;
1600 }
1601
1602 static void
1603 noop_grab_focus(struct weston_pointer_grab *grab)
1604 {
1605 }
1606
1607 static void
1608 noop_grab_axis(struct weston_pointer_grab *grab,
1609                uint32_t time, struct weston_pointer_axis_event *event)
1610 {
1611 }
1612
1613 static void
1614 noop_grab_axis_source(struct weston_pointer_grab *grab,
1615                       uint32_t source)
1616 {
1617 }
1618
1619 static void
1620 noop_grab_frame(struct weston_pointer_grab *grab)
1621 {
1622 }
1623
1624 static void
1625 constrain_position(struct weston_move_grab *move, int *cx, int *cy)
1626 {
1627         struct shell_surface *shsurf = move->base.shsurf;
1628         struct weston_pointer *pointer = move->base.grab.pointer;
1629         int x, y, bottom;
1630         const int safety = 50;
1631         pixman_rectangle32_t area;
1632
1633         x = wl_fixed_to_int(pointer->x + move->dx);
1634         y = wl_fixed_to_int(pointer->y + move->dy);
1635
1636         if (shsurf->shell->panel_position ==
1637             WESTON_DESKTOP_SHELL_PANEL_POSITION_TOP) {
1638                 get_output_work_area(shsurf->shell,
1639                                      shsurf->surface->output,
1640                                      &area);
1641
1642                 bottom = y + shsurf->geometry.height + shsurf->geometry.y;
1643                 if (bottom - safety < area.y)
1644                         y = area.y + safety - shsurf->geometry.height
1645                           - shsurf->geometry.y;
1646
1647                 if (move->client_initiated &&
1648                     y + shsurf->geometry.y < area.y)
1649                         y = area.y - shsurf->geometry.y;
1650
1651         }
1652
1653         *cx = x;
1654         *cy = y;
1655 }
1656
1657 static void
1658 move_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
1659                  struct weston_pointer_motion_event *event)
1660 {
1661         struct weston_move_grab *move = (struct weston_move_grab *) grab;
1662         struct weston_pointer *pointer = grab->pointer;
1663         struct shell_surface *shsurf = move->base.shsurf;
1664         int cx, cy;
1665
1666         weston_pointer_move(pointer, event);
1667         if (!shsurf)
1668                 return;
1669
1670         constrain_position(move, &cx, &cy);
1671
1672         weston_view_set_position(shsurf->view, cx, cy);
1673
1674         weston_compositor_schedule_repaint(shsurf->surface->compositor);
1675 }
1676
1677 static void
1678 move_grab_button(struct weston_pointer_grab *grab,
1679                  uint32_t time, uint32_t button, uint32_t state_w)
1680 {
1681         struct shell_grab *shell_grab = container_of(grab, struct shell_grab,
1682                                                     grab);
1683         struct weston_pointer *pointer = grab->pointer;
1684         enum wl_pointer_button_state state = state_w;
1685
1686         if (pointer->button_count == 0 &&
1687             state == WL_POINTER_BUTTON_STATE_RELEASED) {
1688                 shell_grab_end(shell_grab);
1689                 free(grab);
1690         }
1691 }
1692
1693 static void
1694 move_grab_cancel(struct weston_pointer_grab *grab)
1695 {
1696         struct shell_grab *shell_grab =
1697                 container_of(grab, struct shell_grab, grab);
1698
1699         shell_grab_end(shell_grab);
1700         free(grab);
1701 }
1702
1703 static const struct weston_pointer_grab_interface move_grab_interface = {
1704         noop_grab_focus,
1705         move_grab_motion,
1706         move_grab_button,
1707         noop_grab_axis,
1708         noop_grab_axis_source,
1709         noop_grab_frame,
1710         move_grab_cancel,
1711 };
1712
1713 static int
1714 surface_move(struct shell_surface *shsurf, struct weston_pointer *pointer,
1715              bool client_initiated)
1716 {
1717         struct weston_move_grab *move;
1718
1719         if (!shsurf)
1720                 return -1;
1721
1722         shsurf = find_toplevel_surface(shsurf);
1723
1724         if (shsurf->grabbed ||
1725             shsurf->state.fullscreen || shsurf->state.maximized)
1726                 return 0;
1727
1728         move = malloc(sizeof *move);
1729         if (!move)
1730                 return -1;
1731
1732         move->dx = wl_fixed_from_double(shsurf->view->geometry.x) -
1733                         pointer->grab_x;
1734         move->dy = wl_fixed_from_double(shsurf->view->geometry.y) -
1735                         pointer->grab_y;
1736         move->client_initiated = client_initiated;
1737
1738         shell_grab_start(&move->base, &move_grab_interface, shsurf,
1739                          pointer, WESTON_DESKTOP_SHELL_CURSOR_MOVE);
1740
1741         return 0;
1742 }
1743
1744 static void
1745 common_surface_move(struct wl_resource *resource,
1746                     struct wl_resource *seat_resource, uint32_t serial)
1747 {
1748         struct weston_seat *seat = wl_resource_get_user_data(seat_resource);
1749         struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1750         struct weston_touch *touch = weston_seat_get_touch(seat);
1751         struct shell_surface *shsurf = wl_resource_get_user_data(resource);
1752         struct weston_surface *surface;
1753
1754         if (pointer &&
1755             pointer->focus &&
1756             pointer->button_count > 0 &&
1757             pointer->grab_serial == serial) {
1758                 surface = weston_surface_get_main_surface(pointer->focus->surface);
1759                 if ((surface == shsurf->surface) &&
1760                     (surface_move(shsurf, pointer, true) < 0))
1761                         wl_resource_post_no_memory(resource);
1762         } else if (touch &&
1763                    touch->focus &&
1764                    touch->grab_serial == serial) {
1765                 surface = weston_surface_get_main_surface(touch->focus->surface);
1766                 if ((surface == shsurf->surface) &&
1767                     (surface_touch_move(shsurf, touch) < 0))
1768                         wl_resource_post_no_memory(resource);
1769         }
1770 }
1771
1772 static void
1773 shell_surface_move(struct wl_client *client, struct wl_resource *resource,
1774                    struct wl_resource *seat_resource, uint32_t serial)
1775 {
1776         common_surface_move(resource, seat_resource, serial);
1777 }
1778
1779 struct weston_resize_grab {
1780         struct shell_grab base;
1781         uint32_t edges;
1782         int32_t width, height;
1783 };
1784
1785 static void
1786 resize_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
1787                    struct weston_pointer_motion_event *event)
1788 {
1789         struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
1790         struct weston_pointer *pointer = grab->pointer;
1791         struct shell_surface *shsurf = resize->base.shsurf;
1792         int32_t width, height;
1793         wl_fixed_t from_x, from_y;
1794         wl_fixed_t to_x, to_y;
1795
1796         weston_pointer_move(pointer, event);
1797
1798         if (!shsurf)
1799                 return;
1800
1801         weston_view_from_global_fixed(shsurf->view,
1802                                       pointer->grab_x, pointer->grab_y,
1803                                       &from_x, &from_y);
1804         weston_view_from_global_fixed(shsurf->view,
1805                                       pointer->x, pointer->y, &to_x, &to_y);
1806
1807         width = resize->width;
1808         if (resize->edges & WL_SHELL_SURFACE_RESIZE_LEFT) {
1809                 width += wl_fixed_to_int(from_x - to_x);
1810         } else if (resize->edges & WL_SHELL_SURFACE_RESIZE_RIGHT) {
1811                 width += wl_fixed_to_int(to_x - from_x);
1812         }
1813
1814         height = resize->height;
1815         if (resize->edges & WL_SHELL_SURFACE_RESIZE_TOP) {
1816                 height += wl_fixed_to_int(from_y - to_y);
1817         } else if (resize->edges & WL_SHELL_SURFACE_RESIZE_BOTTOM) {
1818                 height += wl_fixed_to_int(to_y - from_y);
1819         }
1820
1821         if (width < 1)
1822                 width = 1;
1823         if (height < 1)
1824                 height = 1;
1825         shsurf->client->send_configure(shsurf->surface, width, height);
1826 }
1827
1828 static void
1829 send_configure(struct weston_surface *surface, int32_t width, int32_t height)
1830 {
1831         struct shell_surface *shsurf = get_shell_surface(surface);
1832
1833         assert(shsurf);
1834
1835         if (shsurf->resource)
1836                 wl_shell_surface_send_configure(shsurf->resource,
1837                                                 shsurf->resize_edges,
1838                                                 width, height);
1839 }
1840
1841 static const struct weston_shell_client shell_client = {
1842         send_configure,
1843         NULL
1844 };
1845
1846 static void
1847 resize_grab_button(struct weston_pointer_grab *grab,
1848                    uint32_t time, uint32_t button, uint32_t state_w)
1849 {
1850         struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
1851         struct weston_pointer *pointer = grab->pointer;
1852         enum wl_pointer_button_state state = state_w;
1853
1854         if (pointer->button_count == 0 &&
1855             state == WL_POINTER_BUTTON_STATE_RELEASED) {
1856                 shell_grab_end(&resize->base);
1857                 free(grab);
1858         }
1859 }
1860
1861 static void
1862 resize_grab_cancel(struct weston_pointer_grab *grab)
1863 {
1864         struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
1865
1866         shell_grab_end(&resize->base);
1867         free(grab);
1868 }
1869
1870 static const struct weston_pointer_grab_interface resize_grab_interface = {
1871         noop_grab_focus,
1872         resize_grab_motion,
1873         resize_grab_button,
1874         noop_grab_axis,
1875         noop_grab_axis_source,
1876         noop_grab_frame,
1877         resize_grab_cancel,
1878 };
1879
1880 /*
1881  * Returns the bounding box of a surface and all its sub-surfaces,
1882  * in surface-local coordinates. */
1883 static void
1884 surface_subsurfaces_boundingbox(struct weston_surface *surface, int32_t *x,
1885                                 int32_t *y, int32_t *w, int32_t *h) {
1886         pixman_region32_t region;
1887         pixman_box32_t *box;
1888         struct weston_subsurface *subsurface;
1889
1890         pixman_region32_init_rect(&region, 0, 0,
1891                                   surface->width,
1892                                   surface->height);
1893
1894         wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) {
1895                 pixman_region32_union_rect(&region, &region,
1896                                            subsurface->position.x,
1897                                            subsurface->position.y,
1898                                            subsurface->surface->width,
1899                                            subsurface->surface->height);
1900         }
1901
1902         box = pixman_region32_extents(&region);
1903         if (x)
1904                 *x = box->x1;
1905         if (y)
1906                 *y = box->y1;
1907         if (w)
1908                 *w = box->x2 - box->x1;
1909         if (h)
1910                 *h = box->y2 - box->y1;
1911
1912         pixman_region32_fini(&region);
1913 }
1914
1915 static int
1916 surface_resize(struct shell_surface *shsurf,
1917                struct weston_pointer *pointer, uint32_t edges)
1918 {
1919         struct weston_resize_grab *resize;
1920         const unsigned resize_topbottom =
1921                 WL_SHELL_SURFACE_RESIZE_TOP | WL_SHELL_SURFACE_RESIZE_BOTTOM;
1922         const unsigned resize_leftright =
1923                 WL_SHELL_SURFACE_RESIZE_LEFT | WL_SHELL_SURFACE_RESIZE_RIGHT;
1924         const unsigned resize_any = resize_topbottom | resize_leftright;
1925
1926         if (shsurf->grabbed ||
1927             shsurf->state.fullscreen || shsurf->state.maximized)
1928                 return 0;
1929
1930         /* Check for invalid edge combinations. */
1931         if (edges == WL_SHELL_SURFACE_RESIZE_NONE || edges > resize_any ||
1932             (edges & resize_topbottom) == resize_topbottom ||
1933             (edges & resize_leftright) == resize_leftright)
1934                 return 0;
1935
1936         resize = malloc(sizeof *resize);
1937         if (!resize)
1938                 return -1;
1939
1940         resize->edges = edges;
1941
1942         resize->width = shsurf->geometry.width;
1943         resize->height = shsurf->geometry.height;
1944
1945         shsurf->resize_edges = edges;
1946         shell_surface_state_changed(shsurf);
1947         shell_grab_start(&resize->base, &resize_grab_interface, shsurf,
1948                          pointer, edges);
1949
1950         return 0;
1951 }
1952
1953 static void
1954 common_surface_resize(struct wl_resource *resource,
1955                       struct wl_resource *seat_resource, uint32_t serial,
1956                       uint32_t edges)
1957 {
1958         struct weston_seat *seat = wl_resource_get_user_data(seat_resource);
1959         struct weston_pointer *pointer = weston_seat_get_pointer(seat);
1960         struct shell_surface *shsurf = wl_resource_get_user_data(resource);
1961         struct weston_surface *surface;
1962
1963         if (!pointer ||
1964             pointer->button_count == 0 ||
1965             pointer->grab_serial != serial ||
1966             pointer->focus == NULL)
1967                 return;
1968
1969         surface = weston_surface_get_main_surface(pointer->focus->surface);
1970         if (surface != shsurf->surface)
1971                 return;
1972
1973         if (surface_resize(shsurf, pointer, edges) < 0)
1974                 wl_resource_post_no_memory(resource);
1975 }
1976
1977 static void
1978 shell_surface_resize(struct wl_client *client, struct wl_resource *resource,
1979                      struct wl_resource *seat_resource, uint32_t serial,
1980                      uint32_t edges)
1981 {
1982         common_surface_resize(resource, seat_resource, serial, edges);
1983 }
1984
1985 static void
1986 busy_cursor_grab_focus(struct weston_pointer_grab *base)
1987 {
1988         struct shell_grab *grab = (struct shell_grab *) base;
1989         struct weston_pointer *pointer = base->pointer;
1990         struct weston_view *view;
1991         wl_fixed_t sx, sy;
1992
1993         view = weston_compositor_pick_view(pointer->seat->compositor,
1994                                            pointer->x, pointer->y,
1995                                            &sx, &sy);
1996
1997         if (!grab->shsurf || grab->shsurf->surface != view->surface) {
1998                 shell_grab_end(grab);
1999                 free(grab);
2000         }
2001 }
2002
2003 static void
2004 busy_cursor_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
2005                         struct weston_pointer_motion_event *event)
2006 {
2007         weston_pointer_move(grab->pointer, event);
2008 }
2009
2010 static void
2011 busy_cursor_grab_button(struct weston_pointer_grab *base,
2012                         uint32_t time, uint32_t button, uint32_t state)
2013 {
2014         struct shell_grab *grab = (struct shell_grab *) base;
2015         struct shell_surface *shsurf = grab->shsurf;
2016         struct weston_pointer *pointer = grab->grab.pointer;
2017         struct weston_seat *seat = pointer->seat;
2018
2019         if (shsurf && button == BTN_LEFT && state) {
2020                 activate(shsurf->shell, shsurf->view, seat,
2021                          WESTON_ACTIVATE_FLAG_CONFIGURE);
2022                 surface_move(shsurf, pointer, false);
2023         } else if (shsurf && button == BTN_RIGHT && state) {
2024                 activate(shsurf->shell, shsurf->view, seat,
2025                          WESTON_ACTIVATE_FLAG_CONFIGURE);
2026                 surface_rotate(shsurf, pointer);
2027         }
2028 }
2029
2030 static void
2031 busy_cursor_grab_cancel(struct weston_pointer_grab *base)
2032 {
2033         struct shell_grab *grab = (struct shell_grab *) base;
2034
2035         shell_grab_end(grab);
2036         free(grab);
2037 }
2038
2039 static const struct weston_pointer_grab_interface busy_cursor_grab_interface = {
2040         busy_cursor_grab_focus,
2041         busy_cursor_grab_motion,
2042         busy_cursor_grab_button,
2043         noop_grab_axis,
2044         noop_grab_axis_source,
2045         noop_grab_frame,
2046         busy_cursor_grab_cancel,
2047 };
2048
2049 static void
2050 set_busy_cursor(struct shell_surface *shsurf, struct weston_pointer *pointer)
2051 {
2052         struct shell_grab *grab;
2053
2054         if (pointer->grab->interface == &busy_cursor_grab_interface)
2055                 return;
2056
2057         grab = malloc(sizeof *grab);
2058         if (!grab)
2059                 return;
2060
2061         shell_grab_start(grab, &busy_cursor_grab_interface, shsurf, pointer,
2062                          WESTON_DESKTOP_SHELL_CURSOR_BUSY);
2063         /* Mark the shsurf as ungrabbed so that button binding is able
2064          * to move it. */
2065         shsurf->grabbed = 0;
2066 }
2067
2068 static void
2069 end_busy_cursor(struct weston_compositor *compositor, struct wl_client *client)
2070 {
2071         struct shell_grab *grab;
2072         struct weston_seat *seat;
2073
2074         wl_list_for_each(seat, &compositor->seat_list, link) {
2075                 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
2076
2077                 if (!pointer)
2078                         continue;
2079
2080                 grab = (struct shell_grab *) pointer->grab;
2081                 if (grab->grab.interface == &busy_cursor_grab_interface &&
2082                     grab->shsurf->resource &&
2083                     wl_resource_get_client(grab->shsurf->resource) == client) {
2084                         shell_grab_end(grab);
2085                         free(grab);
2086                 }
2087         }
2088 }
2089
2090 static void
2091 handle_shell_client_destroy(struct wl_listener *listener, void *data);
2092
2093 static int
2094 xdg_ping_timeout_handler(void *data)
2095 {
2096         struct shell_client *sc = data;
2097         struct weston_seat *seat;
2098         struct shell_surface *shsurf;
2099
2100         /* Client is not responding */
2101         sc->unresponsive = 1;
2102         wl_list_for_each(seat, &sc->shell->compositor->seat_list, link) {
2103                 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
2104
2105                 if (!pointer ||
2106                     !pointer->focus ||
2107                     !pointer->focus->surface->resource)
2108                         continue;
2109
2110                 shsurf = get_shell_surface(pointer->focus->surface);
2111                 if (shsurf && shsurf->resource &&
2112                     wl_resource_get_client(shsurf->resource) == sc->client)
2113                         set_busy_cursor(shsurf, pointer);
2114         }
2115
2116         return 1;
2117 }
2118
2119 static void
2120 handle_xdg_ping(struct shell_surface *shsurf, uint32_t serial)
2121 {
2122         struct weston_compositor *compositor = shsurf->shell->compositor;
2123         struct shell_client *sc = shsurf->owner;
2124         struct wl_event_loop *loop;
2125         static const int ping_timeout = 200;
2126
2127         if (sc->unresponsive) {
2128                 xdg_ping_timeout_handler(sc);
2129                 return;
2130         }
2131
2132         sc->ping_serial = serial;
2133         loop = wl_display_get_event_loop(compositor->wl_display);
2134         if (sc->ping_timer == NULL)
2135                 sc->ping_timer =
2136                         wl_event_loop_add_timer(loop,
2137                                                 xdg_ping_timeout_handler, sc);
2138         if (sc->ping_timer == NULL)
2139                 return;
2140
2141         wl_event_source_timer_update(sc->ping_timer, ping_timeout);
2142
2143         if (shell_surface_is_xdg_surface(shsurf) ||
2144             shell_surface_is_xdg_popup(shsurf))
2145                 xdg_shell_send_ping(sc->resource, serial);
2146         else if (shell_surface_is_wl_shell_surface(shsurf)
2147                  && shsurf->resource)
2148                 wl_shell_surface_send_ping(shsurf->resource, serial);
2149 }
2150
2151 static void
2152 ping_handler(struct weston_surface *surface, uint32_t serial)
2153 {
2154         struct shell_surface *shsurf = get_shell_surface(surface);
2155
2156         if (!shsurf)
2157                 return;
2158         if (!shsurf->resource)
2159                 return;
2160         if (shsurf->surface == shsurf->shell->grab_surface)
2161                 return;
2162         if (!shsurf->owner)
2163                 return;
2164
2165         handle_xdg_ping(shsurf, serial);
2166 }
2167
2168 static void
2169 handle_pointer_focus(struct wl_listener *listener, void *data)
2170 {
2171         struct weston_pointer *pointer = data;
2172         struct weston_view *view = pointer->focus;
2173         struct weston_compositor *compositor;
2174         uint32_t serial;
2175
2176         if (!view)
2177                 return;
2178
2179         compositor = view->surface->compositor;
2180         serial = wl_display_next_serial(compositor->wl_display);
2181         ping_handler(view->surface, serial);
2182 }
2183
2184 static void
2185 shell_surface_lose_keyboard_focus(struct shell_surface *shsurf)
2186 {
2187         if (--shsurf->focus_count == 0)
2188                 shell_surface_state_changed(shsurf);
2189 }
2190
2191 static void
2192 shell_surface_gain_keyboard_focus(struct shell_surface *shsurf)
2193 {
2194         if (shsurf->focus_count++ == 0)
2195                 shell_surface_state_changed(shsurf);
2196 }
2197
2198 static void
2199 handle_keyboard_focus(struct wl_listener *listener, void *data)
2200 {
2201         struct weston_keyboard *keyboard = data;
2202         struct shell_seat *seat = get_shell_seat(keyboard->seat);
2203
2204         if (seat->focused_surface) {
2205                 struct shell_surface *shsurf = get_shell_surface(seat->focused_surface);
2206                 if (shsurf)
2207                         shell_surface_lose_keyboard_focus(shsurf);
2208         }
2209
2210         seat->focused_surface = keyboard->focus;
2211
2212         if (seat->focused_surface) {
2213                 struct shell_surface *shsurf = get_shell_surface(seat->focused_surface);
2214                 if (shsurf)
2215                         shell_surface_gain_keyboard_focus(shsurf);
2216         }
2217 }
2218
2219 static void
2220 shell_client_pong(struct shell_client *sc, uint32_t serial)
2221 {
2222         if (sc->ping_serial != serial)
2223                 return;
2224
2225         sc->unresponsive = 0;
2226         end_busy_cursor(sc->shell->compositor, sc->client);
2227
2228         if (sc->ping_timer) {
2229                 wl_event_source_remove(sc->ping_timer);
2230                 sc->ping_timer = NULL;
2231         }
2232
2233 }
2234
2235 static void
2236 shell_surface_pong(struct wl_client *client,
2237                    struct wl_resource *resource, uint32_t serial)
2238 {
2239         struct shell_surface *shsurf = wl_resource_get_user_data(resource);
2240         struct shell_client *sc = shsurf->owner;
2241
2242         shell_client_pong(sc, serial);
2243 }
2244
2245 static void
2246 set_title(struct shell_surface *shsurf, const char *title)
2247 {
2248         free(shsurf->title);
2249         shsurf->title = strdup(title);
2250         shsurf->surface->timeline.force_refresh = 1;
2251 }
2252
2253 static void
2254 set_pid(struct shell_surface *shsurf, pid_t pid)
2255 {
2256         /* We have no use for it */
2257 }
2258
2259 static void
2260 set_type(struct shell_surface *shsurf, enum shell_surface_type t)
2261 {
2262         shsurf->type = t;
2263         shsurf->surface->timeline.force_refresh = 1;
2264 }
2265
2266 static void
2267 set_window_geometry(struct shell_surface *shsurf,
2268                     int32_t x, int32_t y, int32_t width, int32_t height)
2269 {
2270         shsurf->next_geometry.x = x;
2271         shsurf->next_geometry.y = y;
2272         shsurf->next_geometry.width = width;
2273         shsurf->next_geometry.height = height;
2274         shsurf->has_next_geometry = true;
2275 }
2276
2277 static void
2278 shell_surface_set_title(struct wl_client *client,
2279                         struct wl_resource *resource, const char *title)
2280 {
2281         struct shell_surface *shsurf = wl_resource_get_user_data(resource);
2282
2283         set_title(shsurf, title);
2284 }
2285
2286 static void
2287 shell_surface_set_class(struct wl_client *client,
2288                         struct wl_resource *resource, const char *class)
2289 {
2290         struct shell_surface *shsurf = wl_resource_get_user_data(resource);
2291
2292         free(shsurf->class);
2293         shsurf->class = strdup(class);
2294         shsurf->surface->timeline.force_refresh = 1;
2295 }
2296
2297 static void
2298 restore_output_mode(struct weston_output *output)
2299 {
2300         if (output && output->original_mode)
2301                 weston_output_mode_switch_to_native(output);
2302 }
2303
2304 static void
2305 restore_all_output_modes(struct weston_compositor *compositor)
2306 {
2307         struct weston_output *output;
2308
2309         wl_list_for_each(output, &compositor->output_list, link)
2310                 restore_output_mode(output);
2311 }
2312
2313 /* The surface will be inserted into the list immediately after the link
2314  * returned by this function (i.e. will be stacked immediately above the
2315  * returned link). */
2316 static struct weston_layer_entry *
2317 shell_surface_calculate_layer_link (struct shell_surface *shsurf)
2318 {
2319         struct workspace *ws;
2320         struct weston_view *parent;
2321
2322         switch (shsurf->type) {
2323         case SHELL_SURFACE_XWAYLAND:
2324                 return &shsurf->shell->fullscreen_layer.view_list;
2325
2326         case SHELL_SURFACE_NONE:
2327                 return NULL;
2328
2329         case SHELL_SURFACE_POPUP:
2330         case SHELL_SURFACE_TOPLEVEL:
2331                 if (shsurf->state.fullscreen && !shsurf->state.lowered) {
2332                         return &shsurf->shell->fullscreen_layer.view_list;
2333                 } else if (shsurf->parent) {
2334                         /* Move the surface to its parent layer so
2335                          * that surfaces which are transient for
2336                          * fullscreen surfaces don't get hidden by the
2337                          * fullscreen surfaces. */
2338
2339                         /* TODO: Handle a parent with multiple views */
2340                         parent = get_default_view(shsurf->parent);
2341                         if (parent)
2342                                 return container_of(parent->layer_link.link.prev,
2343                                                     struct weston_layer_entry, link);
2344                 }
2345
2346                 /* Move the surface to a normal workspace layer so that surfaces
2347                  * which were previously fullscreen or transient are no longer
2348                  * rendered on top. */
2349                 ws = get_current_workspace(shsurf->shell);
2350                 return &ws->layer.view_list;
2351         }
2352
2353         assert(0 && "Unknown shell surface type");
2354 }
2355
2356 static void
2357 shell_surface_update_child_surface_layers (struct shell_surface *shsurf)
2358 {
2359         struct shell_surface *child;
2360         struct weston_layer_entry *prev;
2361
2362         /* Move the child layers to the same workspace as shsurf. They will be
2363          * stacked above shsurf. */
2364         wl_list_for_each_reverse(child, &shsurf->children_list, children_link) {
2365                 if (shsurf->view->layer_link.link.prev != &child->view->layer_link.link) {
2366                         weston_view_damage_below(child->view);
2367                         weston_view_geometry_dirty(child->view);
2368                         prev = container_of(shsurf->view->layer_link.link.prev,
2369                                             struct weston_layer_entry, link);
2370                         weston_layer_entry_remove(&child->view->layer_link);
2371                         weston_layer_entry_insert(prev,
2372                                                   &child->view->layer_link);
2373                         weston_view_geometry_dirty(child->view);
2374                         weston_surface_damage(child->surface);
2375
2376                         /* Recurse. We don’t expect this to recurse very far (if
2377                          * at all) because that would imply we have transient
2378                          * (or popup) children of transient surfaces, which
2379                          * would be unusual. */
2380                         shell_surface_update_child_surface_layers(child);
2381                 }
2382         }
2383 }
2384
2385 /* Update the surface’s layer. Mark both the old and new views as having dirty
2386  * geometry to ensure the changes are redrawn.
2387  *
2388  * If any child surfaces exist and are mapped, ensure they’re in the same layer
2389  * as this surface. */
2390 static void
2391 shell_surface_update_layer(struct shell_surface *shsurf)
2392 {
2393         struct weston_layer_entry *new_layer_link;
2394
2395         new_layer_link = shell_surface_calculate_layer_link(shsurf);
2396
2397         if (new_layer_link == NULL)
2398                 return;
2399         if (new_layer_link == &shsurf->view->layer_link)
2400                 return;
2401
2402         weston_view_geometry_dirty(shsurf->view);
2403         weston_layer_entry_remove(&shsurf->view->layer_link);
2404         weston_layer_entry_insert(new_layer_link, &shsurf->view->layer_link);
2405         weston_view_geometry_dirty(shsurf->view);
2406         weston_surface_damage(shsurf->surface);
2407
2408         shell_surface_update_child_surface_layers(shsurf);
2409 }
2410
2411 static void
2412 shell_surface_set_parent(struct shell_surface *shsurf,
2413                          struct weston_surface *parent)
2414 {
2415         shsurf->parent = parent;
2416
2417         wl_list_remove(&shsurf->children_link);
2418         wl_list_init(&shsurf->children_link);
2419
2420         /* Insert into the parent surface’s child list. */
2421         if (parent != NULL) {
2422                 struct shell_surface *parent_shsurf = get_shell_surface(parent);
2423                 if (parent_shsurf != NULL)
2424                         wl_list_insert(&parent_shsurf->children_list,
2425                                        &shsurf->children_link);
2426         }
2427 }
2428
2429 static void
2430 shell_surface_set_output(struct shell_surface *shsurf,
2431                          struct weston_output *output)
2432 {
2433         struct weston_surface *es = shsurf->surface;
2434
2435         /* get the default output, if the client set it as NULL
2436            check whether the ouput is available */
2437         if (output)
2438                 shsurf->output = output;
2439         else if (es->output)
2440                 shsurf->output = es->output;
2441         else
2442                 shsurf->output = get_default_output(es->compositor);
2443 }
2444
2445 static void
2446 surface_clear_next_states(struct shell_surface *shsurf)
2447 {
2448         shsurf->next_state.maximized = false;
2449         shsurf->next_state.fullscreen = false;
2450
2451         if ((shsurf->next_state.maximized != shsurf->state.maximized) ||
2452             (shsurf->next_state.fullscreen != shsurf->state.fullscreen))
2453                 shsurf->state_changed = true;
2454 }
2455
2456 static void
2457 set_toplevel(struct shell_surface *shsurf)
2458 {
2459         shell_surface_set_parent(shsurf, NULL);
2460         surface_clear_next_states(shsurf);
2461         set_type(shsurf, SHELL_SURFACE_TOPLEVEL);
2462
2463         /* The layer_link is updated in set_surface_type(),
2464          * called from configure. */
2465 }
2466
2467 static void
2468 shell_surface_set_toplevel(struct wl_client *client,
2469                            struct wl_resource *resource)
2470 {
2471         struct shell_surface *surface = wl_resource_get_user_data(resource);
2472
2473         set_toplevel(surface);
2474 }
2475
2476 static void
2477 set_transient(struct shell_surface *shsurf,
2478               struct weston_surface *parent, int x, int y, uint32_t flags)
2479 {
2480         assert(parent != NULL);
2481
2482         shell_surface_set_parent(shsurf, parent);
2483
2484         surface_clear_next_states(shsurf);
2485
2486         shsurf->transient.x = x;
2487         shsurf->transient.y = y;
2488         shsurf->transient.flags = flags;
2489
2490         shsurf->next_state.relative = true;
2491         shsurf->state_changed = true;
2492         set_type(shsurf, SHELL_SURFACE_TOPLEVEL);
2493
2494         /* The layer_link is updated in set_surface_type(),
2495          * called from configure. */
2496 }
2497
2498 static void
2499 shell_surface_set_transient(struct wl_client *client,
2500                             struct wl_resource *resource,
2501                             struct wl_resource *parent_resource,
2502                             int x, int y, uint32_t flags)
2503 {
2504         struct shell_surface *shsurf = wl_resource_get_user_data(resource);
2505         struct weston_surface *parent =
2506                 wl_resource_get_user_data(parent_resource);
2507
2508         set_transient(shsurf, parent, x, y, flags);
2509 }
2510
2511 static void
2512 set_fullscreen(struct shell_surface *shsurf,
2513                uint32_t method,
2514                uint32_t framerate,
2515                struct weston_output *output)
2516 {
2517         shell_surface_set_output(shsurf, output);
2518         set_type(shsurf, SHELL_SURFACE_TOPLEVEL);
2519
2520         shsurf->fullscreen_output = shsurf->output;
2521         shsurf->fullscreen.type = method;
2522         shsurf->fullscreen.framerate = framerate;
2523
2524         send_configure_for_surface(shsurf);
2525 }
2526
2527 static void
2528 weston_view_set_initial_position(struct weston_view *view,
2529                                  struct desktop_shell *shell);
2530
2531 static void
2532 unset_fullscreen(struct shell_surface *shsurf)
2533 {
2534         /* Unset the fullscreen output, driver configuration and transforms. */
2535         if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
2536             shell_surface_is_top_fullscreen(shsurf)) {
2537                 restore_output_mode(shsurf->fullscreen_output);
2538         }
2539
2540         shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
2541         shsurf->fullscreen.framerate = 0;
2542
2543         wl_list_remove(&shsurf->fullscreen.transform.link);
2544         wl_list_init(&shsurf->fullscreen.transform.link);
2545
2546         if (shsurf->fullscreen.black_view)
2547                 weston_surface_destroy(shsurf->fullscreen.black_view->surface);
2548         shsurf->fullscreen.black_view = NULL;
2549
2550         if (shsurf->saved_position_valid)
2551                 weston_view_set_position(shsurf->view,
2552                                          shsurf->saved_x, shsurf->saved_y);
2553         else
2554                 weston_view_set_initial_position(shsurf->view, shsurf->shell);
2555
2556         if (shsurf->saved_rotation_valid) {
2557                 wl_list_insert(&shsurf->view->geometry.transformation_list,
2558                                &shsurf->rotation.transform.link);
2559                 shsurf->saved_rotation_valid = false;
2560         }
2561
2562         /* Layer is updated in set_surface_type(). */
2563 }
2564
2565 static void
2566 shell_surface_set_fullscreen(struct wl_client *client,
2567                              struct wl_resource *resource,
2568                              uint32_t method,
2569                              uint32_t framerate,
2570                              struct wl_resource *output_resource)
2571 {
2572         struct shell_surface *shsurf = wl_resource_get_user_data(resource);
2573         struct weston_output *output;
2574
2575         if (shsurf->fullscreen_output == shsurf->output &&
2576             shsurf->fullscreen.type == method &&
2577             shsurf->fullscreen.framerate == framerate) {
2578                 send_configure_for_surface(shsurf);
2579                 return;
2580         }
2581
2582         if (output_resource)
2583                 output = wl_resource_get_user_data(output_resource);
2584         else
2585                 output = NULL;
2586
2587         shell_surface_set_parent(shsurf, NULL);
2588
2589         surface_clear_next_states(shsurf);
2590         shsurf->next_state.fullscreen = true;
2591         shsurf->state_changed = true;
2592         set_fullscreen(shsurf, method, framerate, output);
2593 }
2594
2595 static void
2596 set_popup(struct shell_surface *shsurf,
2597           struct weston_surface *parent,
2598           struct weston_seat *seat,
2599           uint32_t serial,
2600           int32_t x,
2601           int32_t y)
2602 {
2603         assert(parent != NULL);
2604
2605         shsurf->popup.shseat = get_shell_seat(seat);
2606         shsurf->popup.serial = serial;
2607         shsurf->popup.x = x;
2608         shsurf->popup.y = y;
2609
2610         set_type(shsurf, SHELL_SURFACE_POPUP);
2611 }
2612
2613 static void
2614 shell_surface_set_popup(struct wl_client *client,
2615                         struct wl_resource *resource,
2616                         struct wl_resource *seat_resource,
2617                         uint32_t serial,
2618                         struct wl_resource *parent_resource,
2619                         int32_t x, int32_t y, uint32_t flags)
2620 {
2621         struct shell_surface *shsurf = wl_resource_get_user_data(resource);
2622         struct weston_surface *parent =
2623                 wl_resource_get_user_data(parent_resource);
2624
2625         shell_surface_set_parent(shsurf, parent);
2626
2627         surface_clear_next_states(shsurf);
2628         set_popup(shsurf,
2629                   parent,
2630                   wl_resource_get_user_data(seat_resource),
2631                   serial, x, y);
2632 }
2633
2634 static void
2635 unset_maximized(struct shell_surface *shsurf)
2636 {
2637         /* undo all maximized things here */
2638         shsurf->output = get_default_output(shsurf->surface->compositor);
2639
2640         if (shsurf->saved_position_valid)
2641                 weston_view_set_position(shsurf->view,
2642                                          shsurf->saved_x, shsurf->saved_y);
2643         else
2644                 weston_view_set_initial_position(shsurf->view, shsurf->shell);
2645
2646         if (shsurf->saved_rotation_valid) {
2647                 wl_list_insert(&shsurf->view->geometry.transformation_list,
2648                                &shsurf->rotation.transform.link);
2649                 shsurf->saved_rotation_valid = false;
2650         }
2651
2652         /* Layer is updated in set_surface_type(). */
2653 }
2654
2655 static void
2656 set_minimized(struct weston_surface *surface)
2657 {
2658         struct shell_surface *shsurf;
2659         struct workspace *current_ws;
2660         struct weston_view *view;
2661
2662         view = get_default_view(surface);
2663         if (!view)
2664                 return;
2665
2666         assert(weston_surface_get_main_surface(view->surface) == view->surface);
2667
2668         shsurf = get_shell_surface(surface);
2669         current_ws = get_current_workspace(shsurf->shell);
2670
2671         weston_layer_entry_remove(&view->layer_link);
2672         weston_layer_entry_insert(&shsurf->shell->minimized_layer.view_list, &view->layer_link);
2673
2674         drop_focus_state(shsurf->shell, current_ws, view->surface);
2675         surface_keyboard_focus_lost(surface);
2676
2677         shell_surface_update_child_surface_layers(shsurf);
2678         weston_view_damage_below(view);
2679 }
2680
2681 static void
2682 shell_surface_set_maximized(struct wl_client *client,
2683                             struct wl_resource *resource,
2684                             struct wl_resource *output_resource)
2685 {
2686         struct shell_surface *shsurf = wl_resource_get_user_data(resource);
2687         struct weston_output *output;
2688
2689         surface_clear_next_states(shsurf);
2690         shsurf->next_state.maximized = true;
2691         shsurf->state_changed = true;
2692
2693         set_type(shsurf, SHELL_SURFACE_TOPLEVEL);
2694         shell_surface_set_parent(shsurf, NULL);
2695
2696         if (output_resource)
2697                 output = wl_resource_get_user_data(output_resource);
2698         else
2699                 output = NULL;
2700
2701         shell_surface_set_output(shsurf, output);
2702
2703         send_configure_for_surface(shsurf);
2704 }
2705
2706 /* This is only ever called from set_surface_type(), so there’s no need to
2707  * update layer_links here, since they’ll be updated when we return. */
2708 static int
2709 reset_surface_type(struct shell_surface *surface)
2710 {
2711         if (surface->state.fullscreen)
2712                 unset_fullscreen(surface);
2713         if (surface->state.maximized)
2714                 unset_maximized(surface);
2715
2716         return 0;
2717 }
2718
2719 static void
2720 set_full_output(struct shell_surface *shsurf)
2721 {
2722         shsurf->saved_x = shsurf->view->geometry.x;
2723         shsurf->saved_y = shsurf->view->geometry.y;
2724         shsurf->saved_position_valid = true;
2725
2726         if (!wl_list_empty(&shsurf->rotation.transform.link)) {
2727                 wl_list_remove(&shsurf->rotation.transform.link);
2728                 wl_list_init(&shsurf->rotation.transform.link);
2729                 weston_view_geometry_dirty(shsurf->view);
2730                 shsurf->saved_rotation_valid = true;
2731         }
2732 }
2733
2734 static void
2735 set_surface_type(struct shell_surface *shsurf)
2736 {
2737         struct weston_surface *pes = shsurf->parent;
2738         struct weston_view *pev = get_default_view(pes);
2739
2740         reset_surface_type(shsurf);
2741
2742         shsurf->state = shsurf->next_state;
2743         shsurf->state_changed = false;
2744
2745         switch (shsurf->type) {
2746         case SHELL_SURFACE_TOPLEVEL:
2747                 if (shsurf->state.maximized || shsurf->state.fullscreen) {
2748                         set_full_output(shsurf);
2749                 } else if (shsurf->state.relative && pev) {
2750                         weston_view_set_position(shsurf->view,
2751                                                  pev->geometry.x + shsurf->transient.x,
2752                                                  pev->geometry.y + shsurf->transient.y);
2753                 }
2754                 break;
2755
2756         case SHELL_SURFACE_XWAYLAND:
2757                 weston_view_set_position(shsurf->view, shsurf->transient.x,
2758                                          shsurf->transient.y);
2759                 break;
2760
2761         case SHELL_SURFACE_POPUP:
2762         case SHELL_SURFACE_NONE:
2763         default:
2764                 break;
2765         }
2766
2767         /* Update the surface’s layer. */
2768         shell_surface_update_layer(shsurf);
2769 }
2770
2771 static struct desktop_shell *
2772 shell_surface_get_shell(struct shell_surface *shsurf)
2773 {
2774         return shsurf->shell;
2775 }
2776
2777 static int
2778 black_surface_get_label(struct weston_surface *surface, char *buf, size_t len)
2779 {
2780         struct weston_view *fs_view = surface->committed_private;
2781         struct weston_surface *fs_surface = fs_view->surface;
2782         int n;
2783         int rem;
2784         int ret;
2785
2786         n = snprintf(buf, len, "black background surface for ");
2787         if (n < 0)
2788                 return n;
2789
2790         rem = (int)len - n;
2791         if (rem < 0)
2792                 rem = 0;
2793
2794         if (fs_surface->get_label)
2795                 ret = fs_surface->get_label(fs_surface, buf + n, rem);
2796         else
2797                 ret = snprintf(buf + n, rem, "<unknown>");
2798
2799         if (ret < 0)
2800                 return n;
2801
2802         return n + ret;
2803 }
2804
2805 static void
2806 black_surface_committed(struct weston_surface *es, int32_t sx, int32_t sy);
2807
2808 static struct weston_view *
2809 create_black_surface(struct weston_compositor *ec,
2810                      struct weston_view *fs_view,
2811                      float x, float y, int w, int h)
2812 {
2813         struct weston_surface *surface = NULL;
2814         struct weston_view *view;
2815
2816         surface = weston_surface_create(ec);
2817         if (surface == NULL) {
2818                 weston_log("no memory\n");
2819                 return NULL;
2820         }
2821         view = weston_view_create(surface);
2822         if (surface == NULL) {
2823                 weston_log("no memory\n");
2824                 weston_surface_destroy(surface);
2825                 return NULL;
2826         }
2827
2828         surface->committed = black_surface_committed;
2829         surface->committed_private = fs_view;
2830         weston_surface_set_label_func(surface, black_surface_get_label);
2831         weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1);
2832         pixman_region32_fini(&surface->opaque);
2833         pixman_region32_init_rect(&surface->opaque, 0, 0, w, h);
2834         pixman_region32_fini(&surface->input);
2835         pixman_region32_init_rect(&surface->input, 0, 0, w, h);
2836
2837         weston_surface_set_size(surface, w, h);
2838         weston_view_set_position(view, x, y);
2839
2840         return view;
2841 }
2842
2843 static void
2844 shell_ensure_fullscreen_black_view(struct shell_surface *shsurf)
2845 {
2846         struct weston_output *output = shsurf->fullscreen_output;
2847
2848         assert(shsurf->state.fullscreen);
2849
2850         if (!shsurf->fullscreen.black_view)
2851                 shsurf->fullscreen.black_view =
2852                         create_black_surface(shsurf->surface->compositor,
2853                                              shsurf->view,
2854                                              output->x, output->y,
2855                                              output->width,
2856                                              output->height);
2857
2858         weston_view_geometry_dirty(shsurf->fullscreen.black_view);
2859         weston_layer_entry_remove(&shsurf->fullscreen.black_view->layer_link);
2860         weston_layer_entry_insert(&shsurf->view->layer_link,
2861                                   &shsurf->fullscreen.black_view->layer_link);
2862         weston_view_geometry_dirty(shsurf->fullscreen.black_view);
2863         weston_surface_damage(shsurf->surface);
2864
2865         shsurf->fullscreen.black_view->is_mapped = true;
2866         shsurf->state.lowered = false;
2867 }
2868
2869 /* Create black surface and append it to the associated fullscreen surface.
2870  * Handle size dismatch and positioning according to the method. */
2871 static void
2872 shell_configure_fullscreen(struct shell_surface *shsurf)
2873 {
2874         struct weston_output *output = shsurf->fullscreen_output;
2875         struct weston_surface *surface = shsurf->surface;
2876         struct weston_matrix *matrix;
2877         float scale, output_aspect, surface_aspect, x, y;
2878         int32_t surf_x, surf_y, surf_width, surf_height;
2879
2880         if (shsurf->fullscreen.type != WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER)
2881                 restore_output_mode(output);
2882
2883         /* Reverse the effect of lower_fullscreen_layer() */
2884         weston_layer_entry_remove(&shsurf->view->layer_link);
2885         weston_layer_entry_insert(&shsurf->shell->fullscreen_layer.view_list, &shsurf->view->layer_link);
2886
2887         shell_ensure_fullscreen_black_view(shsurf);
2888
2889         surface_subsurfaces_boundingbox(shsurf->surface, &surf_x, &surf_y,
2890                                         &surf_width, &surf_height);
2891
2892         switch (shsurf->fullscreen.type) {
2893         case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT:
2894                 if (surface->buffer_ref.buffer)
2895                         center_on_output(shsurf->view, shsurf->fullscreen_output);
2896                 break;
2897         case WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE:
2898                 /* 1:1 mapping between surface and output dimensions */
2899                 if (output->width == surf_width &&
2900                         output->height == surf_height) {
2901                         weston_view_set_position(shsurf->view,
2902                                                  output->x - surf_x,
2903                                                  output->y - surf_y);
2904                         break;
2905                 }
2906
2907                 matrix = &shsurf->fullscreen.transform.matrix;
2908                 weston_matrix_init(matrix);
2909
2910                 output_aspect = (float) output->width /
2911                         (float) output->height;
2912                 /* XXX: Use surf_width and surf_height here? */
2913                 surface_aspect = (float) surface->width /
2914                         (float) surface->height;
2915                 if (output_aspect < surface_aspect)
2916                         scale = (float) output->width /
2917                                 (float) surf_width;
2918                 else
2919                         scale = (float) output->height /
2920                                 (float) surf_height;
2921
2922                 weston_matrix_scale(matrix, scale, scale, 1);
2923                 wl_list_remove(&shsurf->fullscreen.transform.link);
2924                 wl_list_insert(&shsurf->view->geometry.transformation_list,
2925                                &shsurf->fullscreen.transform.link);
2926                 x = output->x + (output->width - surf_width * scale) / 2 - surf_x;
2927                 y = output->y + (output->height - surf_height * scale) / 2 - surf_y;
2928                 weston_view_set_position(shsurf->view, x, y);
2929
2930                 break;
2931         case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER:
2932                 if (shell_surface_is_top_fullscreen(shsurf)) {
2933                         struct weston_mode mode = {0,
2934                                 surf_width * surface->buffer_viewport.buffer.scale,
2935                                 surf_height * surface->buffer_viewport.buffer.scale,
2936                                 shsurf->fullscreen.framerate};
2937
2938                         if (weston_output_mode_switch_to_temporary(output, &mode,
2939                                         surface->buffer_viewport.buffer.scale) == 0) {
2940                                 weston_view_set_position(shsurf->view,
2941                                                          output->x - surf_x,
2942                                                          output->y - surf_y);
2943                                 shsurf->fullscreen.black_view->surface->width = output->width;
2944                                 shsurf->fullscreen.black_view->surface->height = output->height;
2945                                 weston_view_set_position(shsurf->fullscreen.black_view,
2946                                                          output->x - surf_x,
2947                                                          output->y - surf_y);
2948                                 break;
2949                         } else {
2950                                 weston_log("shell: Can't switch to temporary mode.\n");
2951                                 restore_output_mode(output);
2952                                 center_on_output(shsurf->view, output);
2953                         }
2954                 }
2955                 break;
2956         case WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL:
2957                 center_on_output(shsurf->view, output);
2958                 break;
2959         default:
2960                 break;
2961         }
2962 }
2963
2964 static void
2965 shell_map_fullscreen(struct shell_surface *shsurf)
2966 {
2967         shell_configure_fullscreen(shsurf);
2968 }
2969
2970 static void
2971 set_xwayland(struct shell_surface *shsurf, int x, int y, uint32_t flags)
2972 {
2973         /* XXX: using the same fields for transient type */
2974         surface_clear_next_states(shsurf);
2975         shsurf->transient.x = x;
2976         shsurf->transient.y = y;
2977         shsurf->transient.flags = flags;
2978
2979         shell_surface_set_parent(shsurf, NULL);
2980
2981         set_type(shsurf, SHELL_SURFACE_XWAYLAND);
2982         shsurf->state_changed = true;
2983 }
2984
2985 static void
2986 shell_interface_set_fullscreen(struct shell_surface *shsurf,
2987                                uint32_t method,
2988                                uint32_t framerate,
2989                                struct weston_output *output)
2990 {
2991         surface_clear_next_states(shsurf);
2992         shsurf->next_state.fullscreen = true;
2993         shsurf->state_changed = true;
2994
2995         set_fullscreen(shsurf, method, framerate, output);
2996 }
2997
2998 static struct weston_output *
2999 get_focused_output(struct weston_compositor *compositor)
3000 {
3001         struct weston_seat *seat;
3002         struct weston_output *output = NULL;
3003
3004         wl_list_for_each(seat, &compositor->seat_list, link) {
3005                 struct weston_touch *touch = weston_seat_get_touch(seat);
3006                 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
3007                 struct weston_keyboard *keyboard =
3008                         weston_seat_get_keyboard(seat);
3009
3010                 /* Priority has touch focus, then pointer and
3011                  * then keyboard focus. We should probably have
3012                  * three for loops and check frist for touch,
3013                  * then for pointer, etc. but unless somebody has some
3014                  * objections, I think this is sufficient. */
3015                 if (touch && touch->focus)
3016                         output = touch->focus->output;
3017                 else if (pointer && pointer->focus)
3018                         output = pointer->focus->output;
3019                 else if (keyboard && keyboard->focus)
3020                         output = keyboard->focus->output;
3021
3022                 if (output)
3023                         break;
3024         }
3025
3026         return output;
3027 }
3028
3029 static void
3030 shell_interface_set_maximized(struct shell_surface *shsurf)
3031 {
3032         struct weston_output *output;
3033
3034         surface_clear_next_states(shsurf);
3035         shsurf->next_state.maximized = true;
3036         shsurf->state_changed = true;
3037         shsurf->type = SHELL_SURFACE_TOPLEVEL;
3038
3039         if (!weston_surface_is_mapped(shsurf->surface))
3040                 output = get_focused_output(shsurf->surface->compositor);
3041         else
3042                 output = shsurf->surface->output;
3043
3044         shell_surface_set_output(shsurf, output);
3045         send_configure_for_surface(shsurf);
3046 }
3047
3048 static int
3049 shell_interface_move(struct shell_surface *shsurf, struct weston_pointer *pointer)
3050 {
3051         return surface_move(shsurf, pointer, true);
3052 }
3053
3054 static int
3055 shell_interface_resize(struct shell_surface *shsurf,
3056                        struct weston_pointer *pointer,
3057                        uint32_t edges)
3058 {
3059         return surface_resize(shsurf, pointer, edges);
3060 }
3061
3062 static const struct weston_pointer_grab_interface popup_grab_interface;
3063
3064 static void
3065 destroy_shell_seat(struct wl_listener *listener, void *data)
3066 {
3067         struct shell_seat *shseat =
3068                 container_of(listener,
3069                              struct shell_seat, seat_destroy_listener);
3070         struct shell_surface *shsurf, *next;
3071
3072         if (shseat->popup_grab.grab.interface == &popup_grab_interface) {
3073                 weston_pointer_end_grab(shseat->popup_grab.grab.pointer);
3074                 shseat->popup_grab.client = NULL;
3075
3076                 wl_list_for_each_safe(shsurf, next,
3077                                       &shseat->popup_grab.surfaces_list,
3078                                       popup.grab_link) {
3079                         shsurf->popup.shseat = NULL;
3080                         wl_list_init(&shsurf->popup.grab_link);
3081                 }
3082         }
3083
3084         wl_list_remove(&shseat->seat_destroy_listener.link);
3085         free(shseat);
3086 }
3087
3088 static void
3089 shell_seat_caps_changed(struct wl_listener *listener, void *data)
3090 {
3091         struct weston_keyboard *keyboard;
3092         struct weston_pointer *pointer;
3093         struct shell_seat *seat;
3094
3095         seat = container_of(listener, struct shell_seat, caps_changed_listener);
3096         keyboard = weston_seat_get_keyboard(seat->seat);
3097         pointer = weston_seat_get_pointer(seat->seat);
3098
3099         if (keyboard &&
3100             wl_list_empty(&seat->keyboard_focus_listener.link)) {
3101                 wl_signal_add(&keyboard->focus_signal,
3102                               &seat->keyboard_focus_listener);
3103         } else if (!keyboard) {
3104                 wl_list_remove(&seat->keyboard_focus_listener.link);
3105                 wl_list_init(&seat->keyboard_focus_listener.link);
3106         }
3107
3108         if (pointer &&
3109             wl_list_empty(&seat->pointer_focus_listener.link)) {
3110                 wl_signal_add(&pointer->focus_signal,
3111                               &seat->pointer_focus_listener);
3112         } else if (!pointer) {
3113                 wl_list_remove(&seat->pointer_focus_listener.link);
3114                 wl_list_init(&seat->pointer_focus_listener.link);
3115         }
3116 }
3117
3118 static struct shell_seat *
3119 create_shell_seat(struct weston_seat *seat)
3120 {
3121         struct shell_seat *shseat;
3122
3123         shseat = calloc(1, sizeof *shseat);
3124         if (!shseat) {
3125                 weston_log("no memory to allocate shell seat\n");
3126                 return NULL;
3127         }
3128
3129         shseat->seat = seat;
3130         wl_list_init(&shseat->popup_grab.surfaces_list);
3131
3132         shseat->seat_destroy_listener.notify = destroy_shell_seat;
3133         wl_signal_add(&seat->destroy_signal,
3134                       &shseat->seat_destroy_listener);
3135
3136         shseat->keyboard_focus_listener.notify = handle_keyboard_focus;
3137         wl_list_init(&shseat->keyboard_focus_listener.link);
3138
3139         shseat->pointer_focus_listener.notify = handle_pointer_focus;
3140         wl_list_init(&shseat->pointer_focus_listener.link);
3141
3142         shseat->caps_changed_listener.notify = shell_seat_caps_changed;
3143         wl_signal_add(&seat->updated_caps_signal,
3144                       &shseat->caps_changed_listener);
3145         shell_seat_caps_changed(&shseat->caps_changed_listener, NULL);
3146
3147         return shseat;
3148 }
3149
3150 static struct shell_seat *
3151 get_shell_seat(struct weston_seat *seat)
3152 {
3153         struct wl_listener *listener;
3154
3155         listener = wl_signal_get(&seat->destroy_signal, destroy_shell_seat);
3156         assert(listener != NULL);
3157
3158         return container_of(listener,
3159                             struct shell_seat, seat_destroy_listener);
3160 }
3161
3162 static void
3163 popup_grab_focus(struct weston_pointer_grab *grab)
3164 {
3165         struct weston_pointer *pointer = grab->pointer;
3166         struct weston_view *view;
3167         struct shell_seat *shseat =
3168             container_of(grab, struct shell_seat, popup_grab.grab);
3169         struct wl_client *client = shseat->popup_grab.client;
3170         wl_fixed_t sx, sy;
3171
3172         view = weston_compositor_pick_view(pointer->seat->compositor,
3173                                            pointer->x, pointer->y,
3174                                            &sx, &sy);
3175
3176         if (view && view->surface->resource &&
3177             wl_resource_get_client(view->surface->resource) == client) {
3178                 weston_pointer_set_focus(pointer, view, sx, sy);
3179         } else {
3180                 weston_pointer_clear_focus(pointer);
3181         }
3182 }
3183
3184 static void
3185 popup_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
3186                   struct weston_pointer_motion_event *event)
3187 {
3188         struct weston_pointer *pointer = grab->pointer;
3189         struct wl_resource *resource;
3190         struct wl_list *resource_list;
3191         wl_fixed_t x, y;
3192         wl_fixed_t sx, sy;
3193
3194         if (pointer->focus) {
3195                 weston_pointer_motion_to_abs(pointer, event, &x, &y);
3196                 weston_view_from_global_fixed(pointer->focus, x, y,
3197                                               &pointer->sx, &pointer->sy);
3198         }
3199
3200         weston_pointer_move(pointer, event);
3201
3202         if (!pointer->focus_client)
3203                 return;
3204
3205         resource_list = &pointer->focus_client->pointer_resources;
3206         wl_resource_for_each(resource, resource_list) {
3207                 weston_view_from_global_fixed(pointer->focus,
3208                                               pointer->x, pointer->y,
3209                                               &sx, &sy);
3210                 wl_pointer_send_motion(resource, time, sx, sy);
3211         }
3212 }
3213
3214 static void
3215 popup_grab_button(struct weston_pointer_grab *grab,
3216                   uint32_t time, uint32_t button, uint32_t state_w)
3217 {
3218         struct wl_resource *resource;
3219         struct shell_seat *shseat =
3220             container_of(grab, struct shell_seat, popup_grab.grab);
3221         struct wl_display *display = shseat->seat->compositor->wl_display;
3222         enum wl_pointer_button_state state = state_w;
3223         uint32_t serial;
3224         struct wl_list *resource_list = NULL;
3225
3226         if (grab->pointer->focus_client)
3227                 resource_list = &grab->pointer->focus_client->pointer_resources;
3228         if (resource_list && !wl_list_empty(resource_list)) {
3229                 serial = wl_display_get_serial(display);
3230                 wl_resource_for_each(resource, resource_list) {
3231                         wl_pointer_send_button(resource, serial,
3232                                                time, button, state);
3233                 }
3234         } else if (state == WL_POINTER_BUTTON_STATE_RELEASED &&
3235                    (shseat->popup_grab.initial_up ||
3236                     time - grab->pointer->grab_time > 500)) {
3237                 popup_grab_end(grab->pointer);
3238         }
3239
3240         if (state == WL_POINTER_BUTTON_STATE_RELEASED)
3241                 shseat->popup_grab.initial_up = 1;
3242 }
3243
3244 static void
3245 popup_grab_axis(struct weston_pointer_grab *grab,
3246                 uint32_t time,
3247                 struct weston_pointer_axis_event *event)
3248 {
3249         weston_pointer_send_axis(grab->pointer, time, event);
3250 }
3251
3252 static void
3253 popup_grab_axis_source(struct weston_pointer_grab *grab, uint32_t source)
3254 {
3255         weston_pointer_send_axis_source(grab->pointer, source);
3256 }
3257
3258 static void
3259 popup_grab_frame(struct weston_pointer_grab *grab)
3260 {
3261         weston_pointer_send_frame(grab->pointer);
3262 }
3263
3264 static void
3265 popup_grab_cancel(struct weston_pointer_grab *grab)
3266 {
3267         popup_grab_end(grab->pointer);
3268 }
3269
3270 static const struct weston_pointer_grab_interface popup_grab_interface = {
3271         popup_grab_focus,
3272         popup_grab_motion,
3273         popup_grab_button,
3274         popup_grab_axis,
3275         popup_grab_axis_source,
3276         popup_grab_frame,
3277         popup_grab_cancel,
3278 };
3279
3280 static void
3281 touch_popup_grab_down(struct weston_touch_grab *grab, uint32_t time,
3282                       int touch_id, wl_fixed_t x, wl_fixed_t y)
3283 {
3284         struct wl_resource *resource;
3285         struct shell_seat *shseat =
3286             container_of(grab, struct shell_seat, popup_grab.touch_grab);
3287         struct wl_display *display = shseat->seat->compositor->wl_display;
3288         uint32_t serial;
3289         struct wl_list *resource_list;
3290         wl_fixed_t sx, sy;
3291
3292         weston_view_from_global_fixed(grab->touch->focus, x, y, &sx, &sy);
3293
3294         resource_list = &grab->touch->focus_resource_list;
3295         if (!wl_list_empty(resource_list)) {
3296                 serial = wl_display_get_serial(display);
3297                 wl_resource_for_each(resource, resource_list) {
3298                         wl_touch_send_down(resource, serial, time,
3299                                 grab->touch->focus->surface->resource,
3300                                 touch_id, sx, sy);
3301                 }
3302         }
3303 }
3304
3305 static void
3306 touch_popup_grab_up(struct weston_touch_grab *grab, uint32_t time, int touch_id)
3307 {
3308         struct wl_resource *resource;
3309         struct shell_seat *shseat =
3310             container_of(grab, struct shell_seat, popup_grab.touch_grab);
3311         struct wl_display *display = shseat->seat->compositor->wl_display;
3312         uint32_t serial;
3313         struct wl_list *resource_list;
3314
3315         resource_list = &grab->touch->focus_resource_list;
3316         if (!wl_list_empty(resource_list)) {
3317                 serial = wl_display_get_serial(display);
3318                 wl_resource_for_each(resource, resource_list) {
3319                         wl_touch_send_up(resource, serial, time, touch_id);
3320                 }
3321         }
3322 }
3323
3324 static void
3325 touch_popup_grab_motion(struct weston_touch_grab *grab, uint32_t time,
3326                         int touch_id, wl_fixed_t x, wl_fixed_t y)
3327 {
3328         struct wl_resource *resource;
3329         struct wl_list *resource_list;
3330         wl_fixed_t sx, sy;
3331
3332         weston_view_from_global_fixed(grab->touch->focus, x, y, &sx, &sy);
3333
3334         resource_list = &grab->touch->focus_resource_list;
3335         if (!wl_list_empty(resource_list)) {
3336                 wl_resource_for_each(resource, resource_list) {
3337                         wl_touch_send_motion(resource, time, touch_id, sx, sy);
3338                 }
3339         }
3340 }
3341
3342 static void
3343 touch_popup_grab_frame(struct weston_touch_grab *grab)
3344 {
3345 }
3346
3347 static void
3348 touch_popup_grab_cancel(struct weston_touch_grab *grab)
3349 {
3350         touch_popup_grab_end(grab->touch);
3351 }
3352
3353 static const struct weston_touch_grab_interface touch_popup_grab_interface = {
3354         touch_popup_grab_down,
3355         touch_popup_grab_up,
3356         touch_popup_grab_motion,
3357         touch_popup_grab_frame,
3358         touch_popup_grab_cancel,
3359 };
3360
3361 static void
3362 shell_surface_send_popup_done(struct shell_surface *shsurf)
3363 {
3364         if (shsurf->resource == NULL)
3365                 return;
3366         else if (shell_surface_is_wl_shell_surface(shsurf))
3367                 wl_shell_surface_send_popup_done(shsurf->resource);
3368         else if (shell_surface_is_xdg_popup(shsurf))
3369                 xdg_popup_send_popup_done(shsurf->resource);
3370 }
3371
3372 static void
3373 popup_grab_end(struct weston_pointer *pointer)
3374 {
3375         struct weston_pointer_grab *grab = pointer->grab;
3376         struct shell_seat *shseat =
3377             container_of(grab, struct shell_seat, popup_grab.grab);
3378         struct shell_surface *shsurf;
3379         struct shell_surface *next;
3380
3381         if (pointer->grab->interface == &popup_grab_interface) {
3382                 weston_pointer_end_grab(grab->pointer);
3383                 shseat->popup_grab.client = NULL;
3384                 shseat->popup_grab.grab.interface = NULL;
3385                 assert(!wl_list_empty(&shseat->popup_grab.surfaces_list));
3386                 /* Send the popup_done event to all the popups open */
3387                 wl_list_for_each_safe(shsurf, next,
3388                                       &shseat->popup_grab.surfaces_list,
3389                                       popup.grab_link) {
3390                         shell_surface_send_popup_done(shsurf);
3391                         shsurf->popup.shseat = NULL;
3392                         wl_list_init(&shsurf->popup.grab_link);
3393                 }
3394                 wl_list_init(&shseat->popup_grab.surfaces_list);
3395         }
3396 }
3397
3398 static void
3399 touch_popup_grab_end(struct weston_touch *touch)
3400 {
3401         struct weston_touch_grab *grab = touch->grab;
3402         struct shell_seat *shseat =
3403             container_of(grab, struct shell_seat, popup_grab.touch_grab);
3404         struct shell_surface *shsurf;
3405         struct shell_surface *next;
3406
3407         if (touch->grab->interface == &touch_popup_grab_interface) {
3408                 weston_touch_end_grab(grab->touch);
3409                 shseat->popup_grab.client = NULL;
3410                 shseat->popup_grab.touch_grab.interface = NULL;
3411                 assert(!wl_list_empty(&shseat->popup_grab.surfaces_list));
3412                 /* Send the popup_done event to all the popups open */
3413                 wl_list_for_each_safe(shsurf, next,
3414                                       &shseat->popup_grab.surfaces_list,
3415                                       popup.grab_link) {
3416                         shell_surface_send_popup_done(shsurf);
3417                         shsurf->popup.shseat = NULL;
3418                         wl_list_init(&shsurf->popup.grab_link);
3419                 }
3420                 wl_list_init(&shseat->popup_grab.surfaces_list);
3421         }
3422 }
3423
3424 static struct shell_surface *
3425 get_top_popup(struct shell_seat *shseat)
3426 {
3427         struct shell_surface *shsurf;
3428
3429         if (wl_list_empty(&shseat->popup_grab.surfaces_list)) {
3430                 return NULL;
3431         } else {
3432                 shsurf = container_of(shseat->popup_grab.surfaces_list.next,
3433                                       struct shell_surface,
3434                                       popup.grab_link);
3435                 return shsurf;
3436         }
3437 }
3438
3439 static int
3440 add_popup_grab(struct shell_surface *shsurf,
3441                struct shell_seat *shseat,
3442                int32_t type)
3443 {
3444         struct weston_seat *seat = shseat->seat;
3445         struct shell_surface *parent, *top_surface;
3446         struct weston_pointer *pointer = weston_seat_get_pointer(seat);
3447         struct weston_touch *touch = weston_seat_get_touch(seat);
3448
3449         parent = get_shell_surface(shsurf->parent);
3450         top_surface = get_top_popup(shseat);
3451         if (shell_surface_is_xdg_popup(shsurf) &&
3452             (!parent ||
3453              (top_surface == NULL && !shell_surface_is_xdg_surface(parent)) ||
3454              (top_surface != NULL && parent != top_surface))) {
3455                 wl_resource_post_error(shsurf->owner_resource,
3456                                        XDG_SHELL_ERROR_NOT_THE_TOPMOST_POPUP,
3457                                        "xdg_popup was not created on the "
3458                                        "topmost popup");
3459                 return -1;
3460         }
3461
3462         if (wl_list_empty(&shseat->popup_grab.surfaces_list)) {
3463                 shseat->popup_grab.type = type;
3464                 shseat->popup_grab.client =
3465                         wl_resource_get_client(shsurf->resource);
3466
3467                 if (type == POINTER) {
3468                         shseat->popup_grab.grab.interface =
3469                                 &popup_grab_interface;
3470
3471                         /* We must make sure here that this popup was opened
3472                          * after a mouse press, and not just by moving around
3473                          * with other popups already open. */
3474                         if (pointer->button_count > 0)
3475                                 shseat->popup_grab.initial_up = 0;
3476                 } else if (type == TOUCH) {
3477                         shseat->popup_grab.touch_grab.interface =
3478                                 &touch_popup_grab_interface;
3479                 }
3480
3481                 wl_list_insert(&shseat->popup_grab.surfaces_list,
3482                                &shsurf->popup.grab_link);
3483
3484                 if (type == POINTER) {
3485                         weston_pointer_start_grab(pointer,
3486                                                   &shseat->popup_grab.grab);
3487                 } else if (type == TOUCH) {
3488                         weston_touch_start_grab(touch,
3489                                                 &shseat->popup_grab.touch_grab);
3490                 }
3491         } else {
3492                 wl_list_insert(&shseat->popup_grab.surfaces_list,
3493                                &shsurf->popup.grab_link);
3494         }
3495
3496         return 0;
3497 }
3498
3499 static void
3500 remove_popup_grab(struct shell_surface *shsurf)
3501 {
3502         struct shell_seat *shseat = shsurf->popup.shseat;
3503
3504         if (shell_surface_is_xdg_popup(shsurf) &&
3505             get_top_popup(shseat) != shsurf) {
3506                 wl_resource_post_error(shsurf->owner_resource,
3507                                        XDG_SHELL_ERROR_NOT_THE_TOPMOST_POPUP,
3508                                        "xdg_popup was destroyed while it was "
3509                                        "not the topmost popup.");
3510                 return;
3511         }
3512
3513         wl_list_remove(&shsurf->popup.grab_link);
3514         wl_list_init(&shsurf->popup.grab_link);
3515         if (wl_list_empty(&shseat->popup_grab.surfaces_list)) {
3516                 if (shseat->popup_grab.type == POINTER) {
3517                         weston_pointer_end_grab(shseat->popup_grab.grab.pointer);
3518                         shseat->popup_grab.grab.interface = NULL;
3519                 } else if (shseat->popup_grab.type == TOUCH) {
3520                         weston_touch_end_grab(shseat->popup_grab.touch_grab.touch);
3521                         shseat->popup_grab.touch_grab.interface = NULL;
3522                 }
3523         }
3524 }
3525
3526 static int
3527 shell_map_popup(struct shell_surface *shsurf)
3528 {
3529         struct shell_seat *shseat = shsurf->popup.shseat;
3530         struct weston_view *parent_view = get_default_view(shsurf->parent);
3531         struct weston_pointer *pointer = weston_seat_get_pointer(shseat->seat);
3532         struct weston_touch *touch = weston_seat_get_touch(shseat->seat);
3533
3534         shsurf->surface->output = parent_view->output;
3535         shsurf->surface->is_mapped = true;
3536         shsurf->view->output = parent_view->output;
3537
3538         weston_view_set_transform_parent(shsurf->view, parent_view);
3539         weston_view_set_position(shsurf->view, shsurf->popup.x, shsurf->popup.y);
3540         weston_view_update_transform(shsurf->view);
3541         shsurf->view->is_mapped = true;
3542
3543         if (pointer &&
3544             pointer->grab_serial == shsurf->popup.serial) {
3545                 if (add_popup_grab(shsurf, shseat, POINTER) != 0)
3546                         return -1;
3547         } else if (touch &&
3548                    touch->grab_serial == shsurf->popup.serial) {
3549                 if (add_popup_grab(shsurf, shseat, TOUCH) != 0)
3550                         return -1;
3551         } else {
3552                 shell_surface_send_popup_done(shsurf);
3553                 shseat->popup_grab.client = NULL;
3554         }
3555
3556         return 0;
3557 }
3558
3559 static const struct wl_shell_surface_interface shell_surface_implementation = {
3560         shell_surface_pong,
3561         shell_surface_move,
3562         shell_surface_resize,
3563         shell_surface_set_toplevel,
3564         shell_surface_set_transient,
3565         shell_surface_set_fullscreen,
3566         shell_surface_set_popup,
3567         shell_surface_set_maximized,
3568         shell_surface_set_title,
3569         shell_surface_set_class
3570 };
3571
3572 static void
3573 destroy_shell_surface(struct shell_surface *shsurf)
3574 {
3575         struct shell_surface *child, *next;
3576
3577         wl_signal_emit(&shsurf->destroy_signal, shsurf);
3578
3579         if (!wl_list_empty(&shsurf->popup.grab_link)) {
3580                 remove_popup_grab(shsurf);
3581         }
3582
3583         if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
3584             shell_surface_is_top_fullscreen(shsurf))
3585                 restore_output_mode (shsurf->fullscreen_output);
3586
3587         if (shsurf->fullscreen.black_view)
3588                 weston_surface_destroy(shsurf->fullscreen.black_view->surface);
3589
3590         /* As destroy_resource() use wl_list_for_each_safe(),
3591          * we can always remove the listener.
3592          */
3593         wl_list_remove(&shsurf->surface_destroy_listener.link);
3594         shsurf->surface->committed = NULL;
3595         weston_surface_set_label_func(shsurf->surface, NULL);
3596         free(shsurf->title);
3597
3598         weston_view_destroy(shsurf->view);
3599
3600         wl_list_remove(&shsurf->children_link);
3601         wl_list_for_each_safe(child, next, &shsurf->children_list, children_link)
3602                 shell_surface_set_parent(child, NULL);
3603
3604         wl_list_remove(&shsurf->link);
3605         free(shsurf);
3606 }
3607
3608 static void
3609 shell_destroy_shell_surface(struct wl_resource *resource)
3610 {
3611         struct shell_surface *shsurf = wl_resource_get_user_data(resource);
3612
3613         if (!wl_list_empty(&shsurf->popup.grab_link))
3614                 remove_popup_grab(shsurf);
3615         if (shsurf->resource)
3616                 wl_list_remove(wl_resource_get_link(shsurf->resource));
3617         shsurf->resource = NULL;
3618 }
3619
3620 static void
3621 shell_handle_surface_destroy(struct wl_listener *listener, void *data)
3622 {
3623         struct shell_surface *shsurf = container_of(listener,
3624                                                     struct shell_surface,
3625                                                     surface_destroy_listener);
3626
3627         if (shsurf->resource)
3628                 wl_resource_destroy(shsurf->resource);
3629
3630         destroy_shell_surface(shsurf);
3631 }
3632
3633 static void
3634 fade_out_done_idle_cb(void *data)
3635 {
3636         struct shell_surface *shsurf = data;
3637
3638         weston_surface_destroy(shsurf->surface);
3639 }
3640
3641 static void
3642 fade_out_done(struct weston_view_animation *animation, void *data)
3643 {
3644         struct shell_surface *shsurf = data;
3645         struct wl_event_loop *loop;
3646
3647         loop = wl_display_get_event_loop(
3648                                 shsurf->surface->compositor->wl_display);
3649
3650         if (!shsurf->destroying) {
3651                 wl_event_loop_add_idle(loop, fade_out_done_idle_cb, shsurf);
3652                 shsurf->destroying = true;
3653         }
3654 }
3655
3656 static void
3657 handle_resource_destroy(struct wl_listener *listener, void *data)
3658 {
3659         struct shell_surface *shsurf =
3660                 container_of(listener, struct shell_surface,
3661                              resource_destroy_listener);
3662
3663         if (!weston_surface_is_mapped(shsurf->surface))
3664                 return;
3665
3666         shsurf->surface->ref_count++;
3667
3668         pixman_region32_fini(&shsurf->surface->pending.input);
3669         pixman_region32_init(&shsurf->surface->pending.input);
3670         pixman_region32_fini(&shsurf->surface->input);
3671         pixman_region32_init(&shsurf->surface->input);
3672         if (shsurf->shell->win_close_animation_type == ANIMATION_FADE) {
3673                 weston_fade_run(shsurf->view, 1.0, 0.0, 300.0,
3674                                 fade_out_done, shsurf);
3675         } else {
3676                 weston_surface_destroy(shsurf->surface);
3677         }
3678 }
3679
3680 static void
3681 shell_surface_committed(struct weston_surface *, int32_t, int32_t);
3682
3683 struct shell_surface *
3684 get_shell_surface(struct weston_surface *surface)
3685 {
3686         if (surface->committed == shell_surface_committed)
3687                 return surface->committed_private;
3688         else
3689                 return NULL;
3690 }
3691
3692 static struct shell_surface *
3693 create_common_surface(struct shell_client *owner, void *shell,
3694                       struct weston_surface *surface,
3695                       const struct weston_shell_client *client)
3696 {
3697         struct shell_surface *shsurf;
3698
3699         assert(surface->committed == NULL);
3700
3701         shsurf = calloc(1, sizeof *shsurf);
3702         if (!shsurf) {
3703                 weston_log("no memory to allocate shell surface\n");
3704                 return NULL;
3705         }
3706
3707         shsurf->view = weston_view_create(surface);
3708         if (!shsurf->view) {
3709                 weston_log("no memory to allocate shell surface\n");
3710                 free(shsurf);
3711                 return NULL;
3712         }
3713
3714         surface->committed = shell_surface_committed;
3715         surface->committed_private = shsurf;
3716         weston_surface_set_label_func(surface, shell_surface_get_label);
3717
3718         shsurf->resource_destroy_listener.notify = handle_resource_destroy;
3719         wl_resource_add_destroy_listener(surface->resource,
3720                                          &shsurf->resource_destroy_listener);
3721         shsurf->owner = owner;
3722
3723         shsurf->shell = (struct desktop_shell *) shell;
3724         shsurf->unresponsive = 0;
3725         shsurf->saved_position_valid = false;
3726         shsurf->saved_rotation_valid = false;
3727         shsurf->surface = surface;
3728         shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
3729         shsurf->fullscreen.framerate = 0;
3730         shsurf->fullscreen.black_view = NULL;
3731         wl_list_init(&shsurf->fullscreen.transform.link);
3732
3733         shsurf->output = get_default_output(shsurf->shell->compositor);
3734
3735         wl_signal_init(&shsurf->destroy_signal);
3736         shsurf->surface_destroy_listener.notify = shell_handle_surface_destroy;
3737         wl_signal_add(&surface->destroy_signal,
3738                       &shsurf->surface_destroy_listener);
3739
3740         /* init link so its safe to always remove it in destroy_shell_surface */
3741         wl_list_init(&shsurf->link);
3742         wl_list_init(&shsurf->popup.grab_link);
3743
3744         /* empty when not in use */
3745         wl_list_init(&shsurf->rotation.transform.link);
3746         weston_matrix_init(&shsurf->rotation.rotation);
3747
3748         wl_list_init(&shsurf->workspace_transform.link);
3749
3750         wl_list_init(&shsurf->children_link);
3751         wl_list_init(&shsurf->children_list);
3752         shsurf->parent = NULL;
3753
3754         set_type(shsurf, SHELL_SURFACE_NONE);
3755
3756         shsurf->client = client;
3757
3758         return shsurf;
3759 }
3760
3761 static struct shell_surface *
3762 create_shell_surface(void *shell, struct weston_surface *surface,
3763                      const struct weston_shell_client *client)
3764 {
3765         return create_common_surface(NULL, shell, surface, client);
3766 }
3767
3768 static void
3769 shell_get_shell_surface(struct wl_client *client,
3770                         struct wl_resource *resource,
3771                         uint32_t id,
3772                         struct wl_resource *surface_resource)
3773 {
3774         struct weston_surface *surface =
3775                 wl_resource_get_user_data(surface_resource);
3776         struct shell_client *sc = wl_resource_get_user_data(resource);
3777         struct desktop_shell *shell = sc->shell;
3778         struct shell_surface *shsurf;
3779
3780         if (weston_surface_set_role(surface, "wl_shell_surface",
3781                                     resource, WL_SHELL_ERROR_ROLE) < 0)
3782                 return;
3783
3784         shsurf = create_common_surface(sc, shell, surface, &shell_client);
3785         if (!shsurf) {
3786                 wl_resource_post_no_memory(surface_resource);
3787                 return;
3788         }
3789
3790         shsurf->resource =
3791                 wl_resource_create(client,
3792                                    &wl_shell_surface_interface, 1, id);
3793         if (!shsurf->resource) {
3794                 wl_resource_post_no_memory(surface_resource);
3795                 return;
3796         }
3797         wl_resource_set_implementation(shsurf->resource,
3798                                        &shell_surface_implementation,
3799                                        shsurf, shell_destroy_shell_surface);
3800         wl_list_insert(&sc->surface_list,
3801                        wl_resource_get_link(shsurf->resource));
3802 }
3803
3804 static bool
3805 shell_surface_is_wl_shell_surface(struct shell_surface *shsurf)
3806 {
3807         /* A shell surface without a resource is created from xwayland
3808          * and is considered a wl_shell surface for now. */
3809
3810         return shsurf->resource == NULL ||
3811                 wl_resource_instance_of(shsurf->resource,
3812                                         &wl_shell_surface_interface,
3813                                         &shell_surface_implementation);
3814 }
3815
3816 static const struct wl_shell_interface shell_implementation = {
3817         shell_get_shell_surface
3818 };
3819
3820 /****************************
3821  * xdg-shell implementation */
3822
3823 static void
3824 xdg_surface_destroy(struct wl_client *client,
3825                     struct wl_resource *resource)
3826 {
3827         wl_resource_destroy(resource);
3828 }
3829
3830 static void
3831 xdg_surface_set_parent(struct wl_client *client,
3832                        struct wl_resource *resource,
3833                        struct wl_resource *parent_resource)
3834 {
3835         struct shell_surface *shsurf = wl_resource_get_user_data(resource);
3836         struct shell_surface *parent;
3837
3838         if (parent_resource) {
3839                 parent = wl_resource_get_user_data(parent_resource);
3840                 shell_surface_set_parent(shsurf, parent->surface);
3841         } else {
3842                 shell_surface_set_parent(shsurf, NULL);
3843         }
3844 }
3845
3846 static void
3847 xdg_surface_set_app_id(struct wl_client *client,
3848                        struct wl_resource *resource,
3849                        const char *app_id)
3850 {
3851         struct shell_surface *shsurf = wl_resource_get_user_data(resource);
3852
3853         free(shsurf->class);
3854         shsurf->class = strdup(app_id);
3855         shsurf->surface->timeline.force_refresh = 1;
3856 }
3857
3858 static void
3859 xdg_surface_show_window_menu(struct wl_client *client,
3860                              struct wl_resource *surface_resource,
3861                              struct wl_resource *seat_resource,
3862                              uint32_t serial,
3863                              int32_t x,
3864                              int32_t y)
3865 {
3866         /* TODO */
3867 }
3868
3869 static void
3870 xdg_surface_set_title(struct wl_client *client,
3871                         struct wl_resource *resource, const char *title)
3872 {
3873         struct shell_surface *shsurf = wl_resource_get_user_data(resource);
3874
3875         set_title(shsurf, title);
3876 }
3877
3878 static void
3879 xdg_surface_move(struct wl_client *client, struct wl_resource *resource,
3880                  struct wl_resource *seat_resource, uint32_t serial)
3881 {
3882         common_surface_move(resource, seat_resource, serial);
3883 }
3884
3885 static void
3886 xdg_surface_resize(struct wl_client *client, struct wl_resource *resource,
3887                    struct wl_resource *seat_resource, uint32_t serial,
3888                    uint32_t edges)
3889 {
3890         common_surface_resize(resource, seat_resource, serial, edges);
3891 }
3892
3893 static void
3894 xdg_surface_ack_configure(struct wl_client *client,
3895                           struct wl_resource *resource,
3896                           uint32_t serial)
3897 {
3898         struct shell_surface *shsurf = wl_resource_get_user_data(resource);
3899
3900         if (shsurf->state_requested) {
3901                 shsurf->next_state = shsurf->requested_state;
3902                 shsurf->state_changed = true;
3903                 shsurf->state_requested = false;
3904         }
3905 }
3906
3907 static void
3908 xdg_surface_set_window_geometry(struct wl_client *client,
3909                                 struct wl_resource *resource,
3910                                 int32_t x,
3911                                 int32_t y,
3912                                 int32_t width,
3913                                 int32_t height)
3914 {
3915         struct shell_surface *shsurf = wl_resource_get_user_data(resource);
3916
3917         set_window_geometry(shsurf, x, y, width, height);
3918 }
3919
3920 static void
3921 xdg_surface_set_maximized(struct wl_client *client,
3922                           struct wl_resource *resource)
3923 {
3924         struct shell_surface *shsurf = wl_resource_get_user_data(resource);
3925         struct weston_output *output;
3926
3927         shsurf->state_requested = true;
3928         shsurf->requested_state.maximized = true;
3929
3930         if (!weston_surface_is_mapped(shsurf->surface))
3931                 output = get_focused_output(shsurf->surface->compositor);
3932         else
3933                 output = shsurf->surface->output;
3934
3935         shell_surface_set_output(shsurf, output);
3936         send_configure_for_surface(shsurf);
3937 }
3938
3939 static void
3940 xdg_surface_unset_maximized(struct wl_client *client,
3941                             struct wl_resource *resource)
3942 {
3943         struct shell_surface *shsurf = wl_resource_get_user_data(resource);
3944
3945         shsurf->state_requested = true;
3946         shsurf->requested_state.maximized = false;
3947         send_configure_for_surface(shsurf);
3948 }
3949
3950 static void
3951 xdg_surface_set_fullscreen(struct wl_client *client,
3952                            struct wl_resource *resource,
3953                            struct wl_resource *output_resource)
3954 {
3955         struct shell_surface *shsurf = wl_resource_get_user_data(resource);
3956         struct weston_output *output;
3957
3958         shsurf->state_requested = true;
3959         shsurf->requested_state.fullscreen = true;
3960
3961         if (output_resource)
3962                 output = wl_resource_get_user_data(output_resource);
3963         else
3964                 output = NULL;
3965
3966         /* handle clients launching in fullscreen */
3967         if (output == NULL && !weston_surface_is_mapped(shsurf->surface)) {
3968                 /* Set the output to the one that has focus currently. */
3969                 assert(shsurf->surface);
3970                 output = get_focused_output(shsurf->surface->compositor);
3971         }
3972
3973         shell_surface_set_output(shsurf, output);
3974         shsurf->fullscreen_output = shsurf->output;
3975
3976         send_configure_for_surface(shsurf);
3977 }
3978
3979 static void
3980 xdg_surface_unset_fullscreen(struct wl_client *client,
3981                              struct wl_resource *resource)
3982 {
3983         struct shell_surface *shsurf = wl_resource_get_user_data(resource);
3984
3985         shsurf->state_requested = true;
3986         shsurf->requested_state.fullscreen = false;
3987         send_configure_for_surface(shsurf);
3988 }
3989
3990 static void
3991 xdg_surface_set_minimized(struct wl_client *client,
3992                             struct wl_resource *resource)
3993 {
3994         struct shell_surface *shsurf = wl_resource_get_user_data(resource);
3995
3996         if (shsurf->type != SHELL_SURFACE_TOPLEVEL)
3997                 return;
3998
3999          /* apply compositor's own minimization logic (hide) */
4000         set_minimized(shsurf->surface);
4001 }
4002
4003 static const struct xdg_surface_interface xdg_surface_implementation = {
4004         xdg_surface_destroy,
4005         xdg_surface_set_parent,
4006         xdg_surface_set_title,
4007         xdg_surface_set_app_id,
4008         xdg_surface_show_window_menu,
4009         xdg_surface_move,
4010         xdg_surface_resize,
4011         xdg_surface_ack_configure,
4012         xdg_surface_set_window_geometry,
4013         xdg_surface_set_maximized,
4014         xdg_surface_unset_maximized,
4015         xdg_surface_set_fullscreen,
4016         xdg_surface_unset_fullscreen,
4017         xdg_surface_set_minimized,
4018 };
4019
4020 static void
4021 xdg_send_configure(struct weston_surface *surface,
4022                    int32_t width, int32_t height)
4023 {
4024         struct shell_surface *shsurf = get_shell_surface(surface);
4025         uint32_t *s;
4026         struct wl_array states;
4027         uint32_t serial;
4028
4029         assert(shsurf);
4030
4031         if (!shsurf->resource)
4032                 return;
4033
4034         wl_array_init(&states);
4035         if (shsurf->requested_state.fullscreen) {
4036                 s = wl_array_add(&states, sizeof *s);
4037                 *s = XDG_SURFACE_STATE_FULLSCREEN;
4038         } else if (shsurf->requested_state.maximized) {
4039                 s = wl_array_add(&states, sizeof *s);
4040                 *s = XDG_SURFACE_STATE_MAXIMIZED;
4041         }
4042         if (shsurf->resize_edges != 0) {
4043                 s = wl_array_add(&states, sizeof *s);
4044                 *s = XDG_SURFACE_STATE_RESIZING;
4045         }
4046         if (shsurf->focus_count > 0) {
4047                 s = wl_array_add(&states, sizeof *s);
4048                 *s = XDG_SURFACE_STATE_ACTIVATED;
4049         }
4050
4051         serial = wl_display_next_serial(shsurf->surface->compositor->wl_display);
4052         xdg_surface_send_configure(shsurf->resource, width, height, &states, serial);
4053
4054         wl_array_release(&states);
4055 }
4056
4057 static const struct weston_shell_client xdg_client = {
4058         xdg_send_configure,
4059         NULL
4060 };
4061
4062 static void
4063 xdg_shell_destroy(struct wl_client *client,
4064                   struct wl_resource *resource)
4065 {
4066         struct shell_client *sc = wl_resource_get_user_data(resource);
4067         struct wl_resource *shsurf_resource;
4068         struct shell_surface *shsurf;
4069
4070         wl_resource_for_each(shsurf_resource, &sc->surface_list) {
4071                 shsurf = wl_resource_get_user_data(shsurf_resource);
4072                 if (shsurf->owner_resource == resource) {
4073                         wl_resource_post_error(
4074                                 resource,
4075                                 XDG_SHELL_ERROR_DEFUNCT_SURFACES,
4076                                 "not all child surface objects destroyed");
4077                         return;
4078                 }
4079         }
4080
4081         wl_resource_destroy(resource);
4082 }
4083
4084 static void
4085 xdg_use_unstable_version(struct wl_client *client,
4086                          struct wl_resource *resource,
4087                          int32_t version)
4088 {
4089         if (version > 1) {
4090                 wl_resource_post_error(resource,
4091                                        1,
4092                                        "xdg-shell:: version not implemented yet.");
4093                 return;
4094         }
4095 }
4096
4097 static struct shell_surface *
4098 create_xdg_surface(struct shell_client *owner, void *shell,
4099                    struct weston_surface *surface,
4100                    const struct weston_shell_client *client)
4101 {
4102         struct shell_surface *shsurf;
4103
4104         shsurf = create_common_surface(owner, shell, surface, client);
4105         if (!shsurf)
4106                 return NULL;
4107
4108         set_type(shsurf, SHELL_SURFACE_TOPLEVEL);
4109
4110         return shsurf;
4111 }
4112
4113 static void
4114 xdg_get_xdg_surface(struct wl_client *client,
4115                     struct wl_resource *resource,
4116                     uint32_t id,
4117                     struct wl_resource *surface_resource)
4118 {
4119         struct weston_surface *surface =
4120                 wl_resource_get_user_data(surface_resource);
4121         struct shell_client *sc = wl_resource_get_user_data(resource);
4122         struct desktop_shell *shell = sc->shell;
4123         struct shell_surface *shsurf;
4124
4125         shsurf = get_shell_surface(surface);
4126         if (shsurf && shell_surface_is_xdg_surface(shsurf)) {
4127                 wl_resource_post_error(resource, XDG_SHELL_ERROR_ROLE,
4128                                        "This wl_surface is already an "
4129                                        "xdg_surface");
4130                 return;
4131         }
4132
4133         if (weston_surface_set_role(surface, "xdg_surface",
4134                                     resource, XDG_SHELL_ERROR_ROLE) < 0)
4135                 return;
4136
4137         shsurf = create_xdg_surface(sc, shell, surface, &xdg_client);
4138         if (!shsurf) {
4139                 wl_resource_post_no_memory(surface_resource);
4140                 return;
4141         }
4142
4143         shsurf->resource =
4144                 wl_resource_create(client,
4145                                    &xdg_surface_interface, 1, id);
4146         if (!shsurf->resource) {
4147                 wl_resource_post_no_memory(surface_resource);
4148                 return;
4149         }
4150         wl_resource_set_implementation(shsurf->resource,
4151                                        &xdg_surface_implementation,
4152                                        shsurf, shell_destroy_shell_surface);
4153         shsurf->owner_resource = resource;
4154         wl_list_insert(&sc->surface_list,
4155                        wl_resource_get_link(shsurf->resource));
4156 }
4157
4158 static bool
4159 shell_surface_is_xdg_surface(struct shell_surface *shsurf)
4160 {
4161         return shsurf->resource &&
4162                 wl_resource_instance_of(shsurf->resource,
4163                                         &xdg_surface_interface,
4164                                         &xdg_surface_implementation);
4165 }
4166
4167 /* xdg-popup implementation */
4168
4169 static void
4170 xdg_popup_destroy(struct wl_client *client,
4171                   struct wl_resource *resource)
4172 {
4173         wl_resource_destroy(resource);
4174 }
4175
4176 static const struct xdg_popup_interface xdg_popup_implementation = {
4177         xdg_popup_destroy,
4178 };
4179
4180 static void
4181 xdg_popup_send_configure(struct weston_surface *surface,
4182                          int32_t width, int32_t height)
4183 {
4184 }
4185
4186 static const struct weston_shell_client xdg_popup_client = {
4187         xdg_popup_send_configure,
4188         NULL
4189 };
4190
4191 static struct shell_surface *
4192 create_xdg_popup(struct shell_client *owner, void *shell,
4193                  struct weston_surface *surface,
4194                  const struct weston_shell_client *client,
4195                  struct weston_surface *parent,
4196                  struct shell_seat *seat,
4197                  uint32_t serial,
4198                  int32_t x, int32_t y)
4199 {
4200         struct shell_surface *shsurf;
4201
4202         shsurf = create_common_surface(owner, shell, surface, client);
4203         if (!shsurf)
4204                 return NULL;
4205
4206         set_type(shsurf, SHELL_SURFACE_POPUP);
4207         shsurf->popup.shseat = seat;
4208         shsurf->popup.serial = serial;
4209         shsurf->popup.x = x;
4210         shsurf->popup.y = y;
4211         shell_surface_set_parent(shsurf, parent);
4212
4213         return shsurf;
4214 }
4215
4216 static void
4217 xdg_get_xdg_popup(struct wl_client *client,
4218                   struct wl_resource *resource,
4219                   uint32_t id,
4220                   struct wl_resource *surface_resource,
4221                   struct wl_resource *parent_resource,
4222                   struct wl_resource *seat_resource,
4223                   uint32_t serial,
4224                   int32_t x, int32_t y)
4225 {
4226         struct weston_surface *surface =
4227                 wl_resource_get_user_data(surface_resource);
4228         struct shell_client *sc = wl_resource_get_user_data(resource);
4229         struct desktop_shell *shell = sc->shell;
4230         struct shell_surface *shsurf;
4231         struct shell_surface *parent_shsurf;
4232         struct weston_surface *parent;
4233         struct shell_seat *seat;
4234
4235         shsurf = get_shell_surface(surface);
4236         if (shsurf && shell_surface_is_xdg_popup(shsurf)) {
4237                 wl_resource_post_error(resource, XDG_SHELL_ERROR_ROLE,
4238                                        "This wl_surface is already an "
4239                                        "xdg_popup");
4240                 return;
4241         }
4242
4243         if (weston_surface_set_role(surface, "xdg_popup",
4244                                     resource, XDG_SHELL_ERROR_ROLE) < 0)
4245                 return;
4246
4247         if (!parent_resource) {
4248                 wl_resource_post_error(surface_resource,
4249                                        WL_DISPLAY_ERROR_INVALID_OBJECT,
4250                                        "xdg_shell::get_xdg_popup requires a parent shell surface");
4251                 return;
4252         }
4253
4254         parent = wl_resource_get_user_data(parent_resource);
4255         seat = get_shell_seat(wl_resource_get_user_data(seat_resource));
4256
4257         /* Verify that we are creating the top most popup when mapping,
4258          * as it's not until then we know whether it was mapped as most
4259          * top level or not. */
4260
4261         parent_shsurf = get_shell_surface(parent);
4262         if (!parent_shsurf ||
4263             (!shell_surface_is_xdg_popup(parent_shsurf) &&
4264              !shell_surface_is_xdg_surface(parent_shsurf))) {
4265                 wl_resource_post_error(resource,
4266                                        XDG_SHELL_ERROR_INVALID_POPUP_PARENT,
4267                                        "xdg_popup parent was invalid");
4268                 return;
4269         }
4270
4271         shsurf = create_xdg_popup(sc, shell, surface, &xdg_popup_client,
4272                                   parent, seat, serial, x, y);
4273         if (!shsurf) {
4274                 wl_resource_post_no_memory(surface_resource);
4275                 return;
4276         }
4277
4278         shsurf->resource =
4279                 wl_resource_create(client,
4280                                    &xdg_popup_interface, 1, id);
4281         if (!shsurf->resource) {
4282                 wl_resource_post_no_memory(surface_resource);
4283                 return;
4284         }
4285         wl_resource_set_implementation(shsurf->resource,
4286                                        &xdg_popup_implementation,
4287                                        shsurf, shell_destroy_shell_surface);
4288         shsurf->owner_resource = resource;
4289         wl_list_insert(&sc->surface_list,
4290                        wl_resource_get_link(shsurf->resource));
4291 }
4292
4293 static void
4294 xdg_pong(struct wl_client *client,
4295          struct wl_resource *resource, uint32_t serial)
4296 {
4297         struct shell_client *sc = wl_resource_get_user_data(resource);
4298
4299         shell_client_pong(sc, serial);
4300 }
4301
4302 static bool
4303 shell_surface_is_xdg_popup(struct shell_surface *shsurf)
4304 {
4305         return (shsurf->resource &&
4306                 wl_resource_instance_of(shsurf->resource,
4307                                         &xdg_popup_interface,
4308                                         &xdg_popup_implementation));
4309 }
4310
4311 static const struct xdg_shell_interface xdg_implementation = {
4312         xdg_shell_destroy,
4313         xdg_use_unstable_version,
4314         xdg_get_xdg_surface,
4315         xdg_get_xdg_popup,
4316         xdg_pong
4317 };
4318
4319 static int
4320 xdg_shell_unversioned_dispatch(const void *implementation,
4321                                void *_target, uint32_t opcode,
4322                                const struct wl_message *message,
4323                                union wl_argument *args)
4324 {
4325         struct wl_resource *resource = _target;
4326         struct shell_client *sc = wl_resource_get_user_data(resource);
4327
4328         if (opcode != 1 /* XDG_SHELL_USE_UNSTABLE_VERSION */) {
4329                 wl_resource_post_error(resource,
4330                                        WL_DISPLAY_ERROR_INVALID_OBJECT,
4331                                        "must call use_unstable_version first");
4332                 return 0;
4333         }
4334
4335 #define XDG_SERVER_VERSION 5
4336
4337         static_assert(XDG_SERVER_VERSION == XDG_SHELL_VERSION_CURRENT,
4338                       "shell implementation doesn't match protocol version");
4339
4340         if (args[0].i != XDG_SERVER_VERSION) {
4341                 wl_resource_post_error(resource,
4342                                        WL_DISPLAY_ERROR_INVALID_OBJECT,
4343                                        "incompatible version, server is %d "
4344                                        "client wants %d",
4345                                        XDG_SERVER_VERSION, args[0].i);
4346                 return 0;
4347         }
4348
4349         wl_resource_set_implementation(resource, &xdg_implementation,
4350                                        sc, NULL);
4351
4352         return 1;
4353 }
4354
4355 /* end of xdg-shell implementation */
4356 /***********************************/
4357
4358 static void
4359 shell_fade(struct desktop_shell *shell, enum fade_type type);
4360
4361 static void
4362 configure_static_view(struct weston_view *ev, struct weston_layer *layer)
4363 {
4364         struct weston_view *v, *next;
4365
4366         wl_list_for_each_safe(v, next, &layer->view_list.link, layer_link.link) {
4367                 if (v->output == ev->output && v != ev) {
4368                         weston_view_unmap(v);
4369                         v->surface->committed = NULL;
4370                         weston_surface_set_label_func(v->surface, NULL);
4371                 }
4372         }
4373
4374         weston_view_set_position(ev, ev->output->x, ev->output->y);
4375         ev->surface->is_mapped = true;
4376         ev->is_mapped = true;
4377
4378         if (wl_list_empty(&ev->layer_link.link)) {
4379                 weston_layer_entry_insert(&layer->view_list, &ev->layer_link);
4380                 weston_compositor_schedule_repaint(ev->surface->compositor);
4381         }
4382 }
4383
4384
4385 static struct shell_output *
4386 find_shell_output_from_weston_output(struct desktop_shell *shell, struct weston_output *output)
4387 {
4388         struct shell_output *shell_output;
4389
4390         wl_list_for_each(shell_output, &shell->output_list, link) {
4391                 if (shell_output->output == output)
4392                         return shell_output;
4393         }
4394
4395         return NULL;
4396 }
4397
4398 static int
4399 background_get_label(struct weston_surface *surface, char *buf, size_t len)
4400 {
4401         return snprintf(buf, len, "background for output %s",
4402                         surface->output->name);
4403 }
4404
4405 static void
4406 background_committed(struct weston_surface *es, int32_t sx, int32_t sy)
4407 {
4408         struct desktop_shell *shell = es->committed_private;
4409         struct weston_view *view;
4410
4411         view = container_of(es->views.next, struct weston_view, surface_link);
4412
4413         configure_static_view(view, &shell->background_layer);
4414 }
4415
4416 static void
4417 handle_background_surface_destroy(struct wl_listener *listener, void *data)
4418 {
4419         struct shell_output *output =
4420             container_of(listener, struct shell_output, background_surface_listener);
4421
4422         weston_log("background surface gone\n");
4423         output->background_surface = NULL;
4424 }
4425
4426 static void
4427 desktop_shell_set_background(struct wl_client *client,
4428                              struct wl_resource *resource,
4429                              struct wl_resource *output_resource,
4430                              struct wl_resource *surface_resource)
4431 {
4432         struct desktop_shell *shell = wl_resource_get_user_data(resource);
4433         struct weston_surface *surface =
4434                 wl_resource_get_user_data(surface_resource);
4435         struct shell_output *sh_output;
4436         struct weston_view *view, *next;
4437
4438         if (surface->committed) {
4439                 wl_resource_post_error(surface_resource,
4440                                        WL_DISPLAY_ERROR_INVALID_OBJECT,
4441                                        "surface role already assigned");
4442                 return;
4443         }
4444
4445         wl_list_for_each_safe(view, next, &surface->views, surface_link)
4446                 weston_view_destroy(view);
4447         view = weston_view_create(surface);
4448
4449         surface->committed = background_committed;
4450         surface->committed_private = shell;
4451         weston_surface_set_label_func(surface, background_get_label);
4452         surface->output = wl_resource_get_user_data(output_resource);
4453         view->output = surface->output;
4454         weston_desktop_shell_send_configure(resource, 0,
4455                                             surface_resource,
4456                                             surface->output->width,
4457                                             surface->output->height);
4458
4459         sh_output = find_shell_output_from_weston_output(shell, surface->output);
4460         sh_output->background_surface = surface;
4461
4462         sh_output->background_surface_listener.notify = handle_background_surface_destroy;
4463         wl_signal_add(&surface->destroy_signal, &sh_output->background_surface_listener);
4464 }
4465
4466 static int
4467 panel_get_label(struct weston_surface *surface, char *buf, size_t len)
4468 {
4469         return snprintf(buf, len, "panel for output %s",
4470                         surface->output->name);
4471 }
4472
4473 static void
4474 panel_committed(struct weston_surface *es, int32_t sx, int32_t sy)
4475 {
4476         struct desktop_shell *shell = es->committed_private;
4477         struct weston_view *view;
4478
4479         view = container_of(es->views.next, struct weston_view, surface_link);
4480
4481         configure_static_view(view, &shell->panel_layer);
4482 }
4483
4484 static void
4485 handle_panel_surface_destroy(struct wl_listener *listener, void *data)
4486 {
4487         struct shell_output *output =
4488             container_of(listener, struct shell_output, panel_surface_listener);
4489
4490         weston_log("panel surface gone\n");
4491         output->panel_surface = NULL;
4492 }
4493
4494
4495 static void
4496 desktop_shell_set_panel(struct wl_client *client,
4497                         struct wl_resource *resource,
4498                         struct wl_resource *output_resource,
4499                         struct wl_resource *surface_resource)
4500 {
4501         struct desktop_shell *shell = wl_resource_get_user_data(resource);
4502         struct weston_surface *surface =
4503                 wl_resource_get_user_data(surface_resource);
4504         struct weston_view *view, *next;
4505         struct shell_output *sh_output;
4506
4507         if (surface->committed) {
4508                 wl_resource_post_error(surface_resource,
4509                                        WL_DISPLAY_ERROR_INVALID_OBJECT,
4510                                        "surface role already assigned");
4511                 return;
4512         }
4513
4514         wl_list_for_each_safe(view, next, &surface->views, surface_link)
4515                 weston_view_destroy(view);
4516         view = weston_view_create(surface);
4517
4518         surface->committed = panel_committed;
4519         surface->committed_private = shell;
4520         weston_surface_set_label_func(surface, panel_get_label);
4521         surface->output = wl_resource_get_user_data(output_resource);
4522         view->output = surface->output;
4523         weston_desktop_shell_send_configure(resource, 0,
4524                                             surface_resource,
4525                                             surface->output->width,
4526                                             surface->output->height);
4527
4528         sh_output = find_shell_output_from_weston_output(shell, surface->output);
4529         sh_output->panel_surface = surface;
4530
4531         sh_output->panel_surface_listener.notify = handle_panel_surface_destroy;
4532         wl_signal_add(&surface->destroy_signal, &sh_output->panel_surface_listener);
4533 }
4534
4535 static int
4536 lock_surface_get_label(struct weston_surface *surface, char *buf, size_t len)
4537 {
4538         return snprintf(buf, len, "lock window");
4539 }
4540
4541 static void
4542 lock_surface_committed(struct weston_surface *surface, int32_t sx, int32_t sy)
4543 {
4544         struct desktop_shell *shell = surface->committed_private;
4545         struct weston_view *view;
4546
4547         view = container_of(surface->views.next, struct weston_view, surface_link);
4548
4549         if (surface->width == 0)
4550                 return;
4551
4552         center_on_output(view, get_default_output(shell->compositor));
4553
4554         if (!weston_surface_is_mapped(surface)) {
4555                 weston_layer_entry_insert(&shell->lock_layer.view_list,
4556                                           &view->layer_link);
4557                 weston_view_update_transform(view);
4558                 surface->is_mapped = true;
4559                 view->is_mapped = true;
4560                 shell_fade(shell, FADE_IN);
4561         }
4562 }
4563
4564 static void
4565 handle_lock_surface_destroy(struct wl_listener *listener, void *data)
4566 {
4567         struct desktop_shell *shell =
4568             container_of(listener, struct desktop_shell, lock_surface_listener);
4569
4570         weston_log("lock surface gone\n");
4571         shell->lock_surface = NULL;
4572 }
4573
4574 static void
4575 desktop_shell_set_lock_surface(struct wl_client *client,
4576                                struct wl_resource *resource,
4577                                struct wl_resource *surface_resource)
4578 {
4579         struct desktop_shell *shell = wl_resource_get_user_data(resource);
4580         struct weston_surface *surface =
4581                 wl_resource_get_user_data(surface_resource);
4582
4583         shell->prepare_event_sent = false;
4584
4585         if (!shell->locked)
4586                 return;
4587
4588         shell->lock_surface = surface;
4589
4590         shell->lock_surface_listener.notify = handle_lock_surface_destroy;
4591         wl_signal_add(&surface->destroy_signal,
4592                       &shell->lock_surface_listener);
4593
4594         weston_view_create(surface);
4595         surface->committed = lock_surface_committed;
4596         surface->committed_private = shell;
4597         weston_surface_set_label_func(surface, lock_surface_get_label);
4598 }
4599
4600 static void
4601 resume_desktop(struct desktop_shell *shell)
4602 {
4603         struct workspace *ws = get_current_workspace(shell);
4604
4605         wl_list_remove(&shell->lock_layer.link);
4606         if (shell->showing_input_panels) {
4607                 wl_list_insert(&shell->compositor->cursor_layer.link,
4608                                &shell->input_panel_layer.link);
4609                 wl_list_insert(&shell->input_panel_layer.link,
4610                                &shell->fullscreen_layer.link);
4611         } else {
4612                 wl_list_insert(&shell->compositor->cursor_layer.link,
4613                                &shell->fullscreen_layer.link);
4614         }
4615         wl_list_insert(&shell->fullscreen_layer.link,
4616                        &shell->panel_layer.link);
4617         wl_list_insert(&shell->panel_layer.link,
4618                        &ws->layer.link),
4619
4620         restore_focus_state(shell, get_current_workspace(shell));
4621
4622         shell->locked = false;
4623         shell_fade(shell, FADE_IN);
4624         weston_compositor_damage_all(shell->compositor);
4625 }
4626
4627 static void
4628 desktop_shell_unlock(struct wl_client *client,
4629                      struct wl_resource *resource)
4630 {
4631         struct desktop_shell *shell = wl_resource_get_user_data(resource);
4632
4633         shell->prepare_event_sent = false;
4634
4635         if (shell->locked)
4636                 resume_desktop(shell);
4637 }
4638
4639 static void
4640 desktop_shell_set_grab_surface(struct wl_client *client,
4641                                struct wl_resource *resource,
4642                                struct wl_resource *surface_resource)
4643 {
4644         struct desktop_shell *shell = wl_resource_get_user_data(resource);
4645
4646         shell->grab_surface = wl_resource_get_user_data(surface_resource);
4647         weston_view_create(shell->grab_surface);
4648 }
4649
4650 static void
4651 desktop_shell_desktop_ready(struct wl_client *client,
4652                             struct wl_resource *resource)
4653 {
4654         struct desktop_shell *shell = wl_resource_get_user_data(resource);
4655
4656         shell_fade_startup(shell);
4657 }
4658
4659 static void
4660 desktop_shell_set_panel_position(struct wl_client *client,
4661                                  struct wl_resource *resource,
4662                                  uint32_t position)
4663 {
4664         struct desktop_shell *shell = wl_resource_get_user_data(resource);
4665
4666         if (position != WESTON_DESKTOP_SHELL_PANEL_POSITION_TOP &&
4667             position != WESTON_DESKTOP_SHELL_PANEL_POSITION_BOTTOM &&
4668             position != WESTON_DESKTOP_SHELL_PANEL_POSITION_LEFT &&
4669             position != WESTON_DESKTOP_SHELL_PANEL_POSITION_RIGHT) {
4670                 wl_resource_post_error(resource,
4671                                        WESTON_DESKTOP_SHELL_ERROR_INVALID_ARGUMENT,
4672                                        "bad position argument");
4673                 return;
4674         }
4675
4676         shell->panel_position = position;
4677 }
4678
4679 static const struct weston_desktop_shell_interface desktop_shell_implementation = {
4680         desktop_shell_set_background,
4681         desktop_shell_set_panel,
4682         desktop_shell_set_lock_surface,
4683         desktop_shell_unlock,
4684         desktop_shell_set_grab_surface,
4685         desktop_shell_desktop_ready,
4686         desktop_shell_set_panel_position
4687 };
4688
4689 static enum shell_surface_type
4690 get_shell_surface_type(struct weston_surface *surface)
4691 {
4692         struct shell_surface *shsurf;
4693
4694         shsurf = get_shell_surface(surface);
4695         if (!shsurf)
4696                 return SHELL_SURFACE_NONE;
4697         return shsurf->type;
4698 }
4699
4700 static void
4701 move_binding(struct weston_pointer *pointer, uint32_t time,
4702              uint32_t button, void *data)
4703 {
4704         struct weston_surface *focus;
4705         struct weston_surface *surface;
4706         struct shell_surface *shsurf;
4707
4708         if (pointer->focus == NULL)
4709                 return;
4710
4711         focus = pointer->focus->surface;
4712
4713         surface = weston_surface_get_main_surface(focus);
4714         if (surface == NULL)
4715                 return;
4716
4717         shsurf = get_shell_surface(surface);
4718         if (shsurf == NULL || shsurf->state.fullscreen ||
4719             shsurf->state.maximized)
4720                 return;
4721
4722         surface_move(shsurf, pointer, false);
4723 }
4724
4725 static void
4726 maximize_binding(struct weston_keyboard *keyboard, uint32_t time,
4727                  uint32_t button, void *data)
4728 {
4729         struct weston_surface *focus = keyboard->focus;
4730         struct weston_surface *surface;
4731         struct shell_surface *shsurf;
4732
4733         surface = weston_surface_get_main_surface(focus);
4734         if (surface == NULL)
4735                 return;
4736
4737         shsurf = get_shell_surface(surface);
4738         if (shsurf == NULL)
4739                 return;
4740
4741         if (!shell_surface_is_xdg_surface(shsurf))
4742                 return;
4743
4744         shsurf->state_requested = true;
4745         shsurf->requested_state.maximized = !shsurf->state.maximized;
4746         send_configure_for_surface(shsurf);
4747 }
4748
4749 static void
4750 fullscreen_binding(struct weston_keyboard *keyboard, uint32_t time,
4751                    uint32_t button, void *data)
4752 {
4753         struct weston_surface *focus = keyboard->focus;
4754         struct weston_surface *surface;
4755         struct shell_surface *shsurf;
4756
4757         surface = weston_surface_get_main_surface(focus);
4758         if (surface == NULL)
4759                 return;
4760
4761         shsurf = get_shell_surface(surface);
4762         if (shsurf == NULL)
4763                 return;
4764
4765         if (!shell_surface_is_xdg_surface(shsurf))
4766                 return;
4767
4768         shsurf->state_requested = true;
4769         shsurf->requested_state.fullscreen = !shsurf->state.fullscreen;
4770         shsurf->fullscreen_output = shsurf->output;
4771         send_configure_for_surface(shsurf);
4772 }
4773
4774 static void
4775 touch_move_binding(struct weston_touch *touch, uint32_t time, void *data)
4776 {
4777         struct weston_surface *focus;
4778         struct weston_surface *surface;
4779         struct shell_surface *shsurf;
4780
4781         if (touch->focus == NULL)
4782                 return;
4783
4784         focus = touch->focus->surface;
4785         surface = weston_surface_get_main_surface(focus);
4786         if (surface == NULL)
4787                 return;
4788
4789         shsurf = get_shell_surface(surface);
4790         if (shsurf == NULL || shsurf->state.fullscreen ||
4791             shsurf->state.maximized)
4792                 return;
4793
4794         surface_touch_move(shsurf, touch);
4795 }
4796
4797 static void
4798 resize_binding(struct weston_pointer *pointer, uint32_t time,
4799                uint32_t button, void *data)
4800 {
4801         struct weston_surface *focus;
4802         struct weston_surface *surface;
4803         uint32_t edges = 0;
4804         int32_t x, y;
4805         struct shell_surface *shsurf;
4806
4807         if (pointer->focus == NULL)
4808                 return;
4809
4810         focus = pointer->focus->surface;
4811
4812         surface = weston_surface_get_main_surface(focus);
4813         if (surface == NULL)
4814                 return;
4815
4816         shsurf = get_shell_surface(surface);
4817         if (shsurf == NULL || shsurf->state.fullscreen ||
4818             shsurf->state.maximized)
4819                 return;
4820
4821         weston_view_from_global(shsurf->view,
4822                                 wl_fixed_to_int(pointer->grab_x),
4823                                 wl_fixed_to_int(pointer->grab_y),
4824                                 &x, &y);
4825
4826         if (x < shsurf->surface->width / 3)
4827                 edges |= WL_SHELL_SURFACE_RESIZE_LEFT;
4828         else if (x < 2 * shsurf->surface->width / 3)
4829                 edges |= 0;
4830         else
4831                 edges |= WL_SHELL_SURFACE_RESIZE_RIGHT;
4832
4833         if (y < shsurf->surface->height / 3)
4834                 edges |= WL_SHELL_SURFACE_RESIZE_TOP;
4835         else if (y < 2 * shsurf->surface->height / 3)
4836                 edges |= 0;
4837         else
4838                 edges |= WL_SHELL_SURFACE_RESIZE_BOTTOM;
4839
4840         surface_resize(shsurf, pointer, edges);
4841 }
4842
4843 static void
4844 surface_opacity_binding(struct weston_pointer *pointer, uint32_t time,
4845                         struct weston_pointer_axis_event *event,
4846                         void *data)
4847 {
4848         float step = 0.005;
4849         struct shell_surface *shsurf;
4850         struct weston_surface *focus = pointer->focus->surface;
4851         struct weston_surface *surface;
4852
4853         /* XXX: broken for windows containing sub-surfaces */
4854         surface = weston_surface_get_main_surface(focus);
4855         if (surface == NULL)
4856                 return;
4857
4858         shsurf = get_shell_surface(surface);
4859         if (!shsurf)
4860                 return;
4861
4862         shsurf->view->alpha -= event->value * step;
4863
4864         if (shsurf->view->alpha > 1.0)
4865                 shsurf->view->alpha = 1.0;
4866         if (shsurf->view->alpha < step)
4867                 shsurf->view->alpha = step;
4868
4869         weston_view_geometry_dirty(shsurf->view);
4870         weston_surface_damage(surface);
4871 }
4872
4873 static void
4874 do_zoom(struct weston_seat *seat, uint32_t time, uint32_t key, uint32_t axis,
4875         double value)
4876 {
4877         struct weston_compositor *compositor = seat->compositor;
4878         struct weston_pointer *pointer = weston_seat_get_pointer(seat);
4879         struct weston_output *output;
4880         float increment;
4881
4882         if (!pointer) {
4883                 weston_log("Zoom hotkey pressed but seat '%s' contains no pointer.\n", seat->seat_name);
4884                 return;
4885         }
4886
4887         wl_list_for_each(output, &compositor->output_list, link) {
4888                 if (pixman_region32_contains_point(&output->region,
4889                                                    wl_fixed_to_double(pointer->x),
4890                                                    wl_fixed_to_double(pointer->y),
4891                                                    NULL)) {
4892                         if (key == KEY_PAGEUP)
4893                                 increment = output->zoom.increment;
4894                         else if (key == KEY_PAGEDOWN)
4895                                 increment = -output->zoom.increment;
4896                         else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
4897                                 /* For every pixel zoom 20th of a step */
4898                                 increment = output->zoom.increment *
4899                                             -value / 20.0;
4900                         else
4901                                 increment = 0;
4902
4903                         output->zoom.level += increment;
4904
4905                         if (output->zoom.level < 0.0)
4906                                 output->zoom.level = 0.0;
4907                         else if (output->zoom.level > output->zoom.max_level)
4908                                 output->zoom.level = output->zoom.max_level;
4909
4910                         if (!output->zoom.active) {
4911                                 if (output->zoom.level <= 0.0)
4912                                         continue;
4913                                 weston_output_activate_zoom(output, seat);
4914                         }
4915
4916                         output->zoom.spring_z.target = output->zoom.level;
4917
4918                         weston_output_update_zoom(output);
4919                 }
4920         }
4921 }
4922
4923 static void
4924 zoom_axis_binding(struct weston_pointer *pointer, uint32_t time,
4925                   struct weston_pointer_axis_event *event,
4926                   void *data)
4927 {
4928         do_zoom(pointer->seat, time, 0, event->axis, event->value);
4929 }
4930
4931 static void
4932 zoom_key_binding(struct weston_keyboard *keyboard, uint32_t time,
4933                  uint32_t key, void *data)
4934 {
4935         do_zoom(keyboard->seat, time, key, 0, 0);
4936 }
4937
4938 static void
4939 terminate_binding(struct weston_keyboard *keyboard, uint32_t time,
4940                   uint32_t key, void *data)
4941 {
4942         struct weston_compositor *compositor = data;
4943
4944         wl_display_terminate(compositor->wl_display);
4945 }
4946
4947 static void
4948 rotate_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
4949                    struct weston_pointer_motion_event *event)
4950 {
4951         struct rotate_grab *rotate =
4952                 container_of(grab, struct rotate_grab, base.grab);
4953         struct weston_pointer *pointer = grab->pointer;
4954         struct shell_surface *shsurf = rotate->base.shsurf;
4955         float cx, cy, dx, dy, cposx, cposy, dposx, dposy, r;
4956
4957         weston_pointer_move(pointer, event);
4958
4959         if (!shsurf)
4960                 return;
4961
4962         cx = 0.5f * shsurf->surface->width;
4963         cy = 0.5f * shsurf->surface->height;
4964
4965         dx = wl_fixed_to_double(pointer->x) - rotate->center.x;
4966         dy = wl_fixed_to_double(pointer->y) - rotate->center.y;
4967         r = sqrtf(dx * dx + dy * dy);
4968
4969         wl_list_remove(&shsurf->rotation.transform.link);
4970         weston_view_geometry_dirty(shsurf->view);
4971
4972         if (r > 20.0f) {
4973                 struct weston_matrix *matrix =
4974                         &shsurf->rotation.transform.matrix;
4975
4976                 weston_matrix_init(&rotate->rotation);
4977                 weston_matrix_rotate_xy(&rotate->rotation, dx / r, dy / r);
4978
4979                 weston_matrix_init(matrix);
4980                 weston_matrix_translate(matrix, -cx, -cy, 0.0f);
4981                 weston_matrix_multiply(matrix, &shsurf->rotation.rotation);
4982                 weston_matrix_multiply(matrix, &rotate->rotation);
4983                 weston_matrix_translate(matrix, cx, cy, 0.0f);
4984
4985                 wl_list_insert(
4986                         &shsurf->view->geometry.transformation_list,
4987                         &shsurf->rotation.transform.link);
4988         } else {
4989                 wl_list_init(&shsurf->rotation.transform.link);
4990                 weston_matrix_init(&shsurf->rotation.rotation);
4991                 weston_matrix_init(&rotate->rotation);
4992         }
4993
4994         /* We need to adjust the position of the surface
4995          * in case it was resized in a rotated state before */
4996         cposx = shsurf->view->geometry.x + cx;
4997         cposy = shsurf->view->geometry.y + cy;
4998         dposx = rotate->center.x - cposx;
4999         dposy = rotate->center.y - cposy;
5000         if (dposx != 0.0f || dposy != 0.0f) {
5001                 weston_view_set_position(shsurf->view,
5002                                          shsurf->view->geometry.x + dposx,
5003                                          shsurf->view->geometry.y + dposy);
5004         }
5005
5006         /* Repaint implies weston_view_update_transform(), which
5007          * lazily applies the damage due to rotation update.
5008          */
5009         weston_compositor_schedule_repaint(shsurf->surface->compositor);
5010 }
5011
5012 static void
5013 rotate_grab_button(struct weston_pointer_grab *grab,
5014                    uint32_t time, uint32_t button, uint32_t state_w)
5015 {
5016         struct rotate_grab *rotate =
5017                 container_of(grab, struct rotate_grab, base.grab);
5018         struct weston_pointer *pointer = grab->pointer;
5019         struct shell_surface *shsurf = rotate->base.shsurf;
5020         enum wl_pointer_button_state state = state_w;
5021
5022         if (pointer->button_count == 0 &&
5023             state == WL_POINTER_BUTTON_STATE_RELEASED) {
5024                 if (shsurf)
5025                         weston_matrix_multiply(&shsurf->rotation.rotation,
5026                                                &rotate->rotation);
5027                 shell_grab_end(&rotate->base);
5028                 free(rotate);
5029         }
5030 }
5031
5032 static void
5033 rotate_grab_cancel(struct weston_pointer_grab *grab)
5034 {
5035         struct rotate_grab *rotate =
5036                 container_of(grab, struct rotate_grab, base.grab);
5037
5038         shell_grab_end(&rotate->base);
5039         free(rotate);
5040 }
5041
5042 static const struct weston_pointer_grab_interface rotate_grab_interface = {
5043         noop_grab_focus,
5044         rotate_grab_motion,
5045         rotate_grab_button,
5046         noop_grab_axis,
5047         noop_grab_axis_source,
5048         noop_grab_frame,
5049         rotate_grab_cancel,
5050 };
5051
5052 static void
5053 surface_rotate(struct shell_surface *surface, struct weston_pointer *pointer)
5054 {
5055         struct rotate_grab *rotate;
5056         float dx, dy;
5057         float r;
5058
5059         surface = find_toplevel_surface(surface);
5060
5061         rotate = malloc(sizeof *rotate);
5062         if (!rotate)
5063                 return;
5064
5065         weston_view_to_global_float(surface->view,
5066                                     surface->surface->width * 0.5f,
5067                                     surface->surface->height * 0.5f,
5068                                     &rotate->center.x, &rotate->center.y);
5069
5070         dx = wl_fixed_to_double(pointer->x) - rotate->center.x;
5071         dy = wl_fixed_to_double(pointer->y) - rotate->center.y;
5072         r = sqrtf(dx * dx + dy * dy);
5073         if (r > 20.0f) {
5074                 struct weston_matrix inverse;
5075
5076                 weston_matrix_init(&inverse);
5077                 weston_matrix_rotate_xy(&inverse, dx / r, -dy / r);
5078                 weston_matrix_multiply(&surface->rotation.rotation, &inverse);
5079
5080                 weston_matrix_init(&rotate->rotation);
5081                 weston_matrix_rotate_xy(&rotate->rotation, dx / r, dy / r);
5082         } else {
5083                 weston_matrix_init(&surface->rotation.rotation);
5084                 weston_matrix_init(&rotate->rotation);
5085         }
5086
5087         shell_grab_start(&rotate->base, &rotate_grab_interface, surface,
5088                          pointer, WESTON_DESKTOP_SHELL_CURSOR_ARROW);
5089 }
5090
5091 static void
5092 rotate_binding(struct weston_pointer *pointer, uint32_t time, uint32_t button,
5093                void *data)
5094 {
5095         struct weston_surface *focus;
5096         struct weston_surface *base_surface;
5097         struct shell_surface *surface;
5098
5099         if (pointer->focus == NULL)
5100                 return;
5101
5102         focus = pointer->focus->surface;
5103
5104         base_surface = weston_surface_get_main_surface(focus);
5105         if (base_surface == NULL)
5106                 return;
5107
5108         surface = get_shell_surface(base_surface);
5109         if (surface == NULL || surface->state.fullscreen ||
5110             surface->state.maximized)
5111                 return;
5112
5113         surface_rotate(surface, pointer);
5114 }
5115
5116 /* Move all fullscreen layers down to the current workspace and hide their
5117  * black views. The surfaces' state is set to both fullscreen and lowered,
5118  * and this is reversed when such a surface is re-configured, see
5119  * shell_configure_fullscreen() and shell_ensure_fullscreen_black_view().
5120  *
5121  * lowering_output = NULL - Lower on all outputs, else only lower on the
5122  *                   specified output.
5123  *
5124  * This should be used when implementing shell-wide overlays, such as
5125  * the alt-tab switcher, which need to de-promote fullscreen layers. */
5126 void
5127 lower_fullscreen_layer(struct desktop_shell *shell,
5128                                            struct weston_output *lowering_output)
5129 {
5130         struct workspace *ws;
5131         struct weston_view *view, *prev;
5132
5133         ws = get_current_workspace(shell);
5134         wl_list_for_each_reverse_safe(view, prev,
5135                                       &shell->fullscreen_layer.view_list.link,
5136                                       layer_link.link) {
5137                 struct shell_surface *shsurf = get_shell_surface(view->surface);
5138
5139                 if (!shsurf)
5140                         continue;
5141
5142                 /* Only lower surfaces which have lowering_output as their fullscreen
5143                  * output, unless a NULL output asks for lowering on all outputs.
5144                  */
5145                 if (lowering_output && (shsurf->fullscreen_output != lowering_output))
5146                         continue;
5147
5148                 /* We can have a non-fullscreen popup for a fullscreen surface
5149                  * in the fullscreen layer. */
5150                 if (shsurf->state.fullscreen) {
5151                         /* Hide the black view */
5152                         weston_layer_entry_remove(&shsurf->fullscreen.black_view->layer_link);
5153                         wl_list_init(&shsurf->fullscreen.black_view->layer_link.link);
5154                         weston_view_damage_below(shsurf->fullscreen.black_view);
5155
5156                 }
5157
5158                 /* Lower the view to the workspace layer */
5159                 weston_layer_entry_remove(&view->layer_link);
5160                 weston_layer_entry_insert(&ws->layer.view_list, &view->layer_link);
5161                 weston_view_damage_below(view);
5162                 weston_surface_damage(view->surface);
5163
5164                 shsurf->state.lowered = true;
5165         }
5166 }
5167
5168 void
5169 activate(struct desktop_shell *shell, struct weston_view *view,
5170          struct weston_seat *seat, uint32_t flags)
5171 {
5172         struct weston_surface *es = view->surface;
5173         struct weston_surface *main_surface;
5174         struct focus_state *state;
5175         struct workspace *ws;
5176         struct weston_surface *old_es;
5177         struct shell_surface *shsurf;
5178
5179         main_surface = weston_surface_get_main_surface(es);
5180         shsurf = get_shell_surface(main_surface);
5181         assert(shsurf);
5182
5183         /* Only demote fullscreen surfaces on the output of activated shsurf.
5184          * Leave fullscreen surfaces on unrelated outputs alone. */
5185         lower_fullscreen_layer(shell, shsurf->output);
5186
5187         weston_view_activate(view, seat, flags);
5188
5189         state = ensure_focus_state(shell, seat);
5190         if (state == NULL)
5191                 return;
5192
5193         old_es = state->keyboard_focus;
5194         focus_state_set_focus(state, es);
5195
5196         if (shsurf->state.fullscreen && flags & WESTON_ACTIVATE_FLAG_CONFIGURE)
5197                 shell_configure_fullscreen(shsurf);
5198         else
5199                 restore_output_mode(shsurf->output);
5200
5201         /* Update the surface’s layer. This brings it to the top of the stacking
5202          * order as appropriate. */
5203         shell_surface_update_layer(shsurf);
5204
5205         if (shell->focus_animation_type != ANIMATION_NONE) {
5206                 ws = get_current_workspace(shell);
5207                 animate_focus_change(shell, ws, get_default_view(old_es), get_default_view(es));
5208         }
5209 }
5210
5211 /* no-op func for checking black surface */
5212 static void
5213 black_surface_committed(struct weston_surface *es, int32_t sx, int32_t sy)
5214 {
5215 }
5216
5217 static bool
5218 is_black_surface_view(struct weston_view *view, struct weston_view **fs_view)
5219 {
5220         struct weston_surface *surface = view->surface;
5221
5222         if (surface->committed == black_surface_committed) {
5223                 if (fs_view)
5224                         *fs_view = surface->committed_private;
5225                 return true;
5226         }
5227         return false;
5228 }
5229
5230 static void
5231 activate_binding(struct weston_seat *seat,
5232                  struct desktop_shell *shell,
5233                  struct weston_view *focus_view,
5234                  uint32_t flags)
5235 {
5236         struct weston_view *main_view;
5237         struct weston_surface *main_surface;
5238
5239         if (!focus_view)
5240                 return;
5241
5242         if (is_black_surface_view(focus_view, &main_view))
5243                 focus_view = main_view;
5244
5245         main_surface = weston_surface_get_main_surface(focus_view->surface);
5246         if (get_shell_surface_type(main_surface) == SHELL_SURFACE_NONE)
5247                 return;
5248
5249         activate(shell, focus_view, seat, flags);
5250 }
5251
5252 static void
5253 click_to_activate_binding(struct weston_pointer *pointer, uint32_t time,
5254                           uint32_t button, void *data)
5255 {
5256         if (pointer->grab != &pointer->default_grab)
5257                 return;
5258         if (pointer->focus == NULL)
5259                 return;
5260
5261         activate_binding(pointer->seat, data, pointer->focus,
5262                          WESTON_ACTIVATE_FLAG_CLICKED |
5263                          WESTON_ACTIVATE_FLAG_CONFIGURE);
5264 }
5265
5266 static void
5267 touch_to_activate_binding(struct weston_touch *touch, uint32_t time,
5268                           void *data)
5269 {
5270         if (touch->grab != &touch->default_grab)
5271                 return;
5272         if (touch->focus == NULL)
5273                 return;
5274
5275         activate_binding(touch->seat, data, touch->focus,
5276                          WESTON_ACTIVATE_FLAG_CONFIGURE);
5277 }
5278
5279 static void
5280 unfocus_all_seats(struct desktop_shell *shell)
5281 {
5282         struct weston_seat *seat, *next;
5283
5284         wl_list_for_each_safe(seat, next, &shell->compositor->seat_list, link) {
5285                 struct weston_keyboard *keyboard =
5286                         weston_seat_get_keyboard(seat);
5287
5288                 if (!keyboard)
5289                         continue;
5290
5291                 weston_keyboard_set_focus(keyboard, NULL);
5292         }
5293 }
5294
5295 static void
5296 lock(struct desktop_shell *shell)
5297 {
5298         struct workspace *ws = get_current_workspace(shell);
5299
5300         if (shell->locked) {
5301                 weston_compositor_sleep(shell->compositor);
5302                 return;
5303         }
5304
5305         shell->locked = true;
5306
5307         /* Hide all surfaces by removing the fullscreen, panel and
5308          * toplevel layers.  This way nothing else can show or receive
5309          * input events while we are locked. */
5310
5311         wl_list_remove(&shell->panel_layer.link);
5312         wl_list_remove(&shell->fullscreen_layer.link);
5313         if (shell->showing_input_panels)
5314                 wl_list_remove(&shell->input_panel_layer.link);
5315         wl_list_remove(&ws->layer.link);
5316         wl_list_insert(&shell->compositor->cursor_layer.link,
5317                        &shell->lock_layer.link);
5318
5319         weston_compositor_sleep(shell->compositor);
5320
5321         /* Remove the keyboard focus on all seats. This will be
5322          * restored to the workspace's saved state via
5323          * restore_focus_state when the compositor is unlocked */
5324         unfocus_all_seats(shell);
5325
5326         /* TODO: disable bindings that should not work while locked. */
5327
5328         /* All this must be undone in resume_desktop(). */
5329 }
5330
5331 static void
5332 unlock(struct desktop_shell *shell)
5333 {
5334         struct wl_resource *shell_resource;
5335
5336         if (!shell->locked || shell->lock_surface) {
5337                 shell_fade(shell, FADE_IN);
5338                 return;
5339         }
5340
5341         /* If desktop-shell client has gone away, unlock immediately. */
5342         if (!shell->child.desktop_shell) {
5343                 resume_desktop(shell);
5344                 return;
5345         }
5346
5347         if (shell->prepare_event_sent)
5348                 return;
5349
5350         shell_resource = shell->child.desktop_shell;
5351         weston_desktop_shell_send_prepare_lock_surface(shell_resource);
5352         shell->prepare_event_sent = true;
5353 }
5354
5355 static void
5356 shell_fade_done(struct weston_view_animation *animation, void *data)
5357 {
5358         struct desktop_shell *shell = data;
5359
5360         shell->fade.animation = NULL;
5361
5362         switch (shell->fade.type) {
5363         case FADE_IN:
5364                 weston_surface_destroy(shell->fade.view->surface);
5365                 shell->fade.view = NULL;
5366                 break;
5367         case FADE_OUT:
5368                 lock(shell);
5369                 break;
5370         default:
5371                 break;
5372         }
5373 }
5374
5375 static struct weston_view *
5376 shell_fade_create_surface(struct desktop_shell *shell)
5377 {
5378         struct weston_compositor *compositor = shell->compositor;
5379         struct weston_surface *surface;
5380         struct weston_view *view;
5381
5382         surface = weston_surface_create(compositor);
5383         if (!surface)
5384                 return NULL;
5385
5386         view = weston_view_create(surface);
5387         if (!view) {
5388                 weston_surface_destroy(surface);
5389                 return NULL;
5390         }
5391
5392         weston_surface_set_size(surface, 8192, 8192);
5393         weston_view_set_position(view, 0, 0);
5394         weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1.0);
5395         weston_layer_entry_insert(&compositor->fade_layer.view_list,
5396                                   &view->layer_link);
5397         pixman_region32_init(&surface->input);
5398         surface->is_mapped = true;
5399         view->is_mapped = true;
5400
5401         return view;
5402 }
5403
5404 static void
5405 shell_fade(struct desktop_shell *shell, enum fade_type type)
5406 {
5407         float tint;
5408
5409         switch (type) {
5410         case FADE_IN:
5411                 tint = 0.0;
5412                 break;
5413         case FADE_OUT:
5414                 tint = 1.0;
5415                 break;
5416         default:
5417                 weston_log("shell: invalid fade type\n");
5418                 return;
5419         }
5420
5421         shell->fade.type = type;
5422
5423         if (shell->fade.view == NULL) {
5424                 shell->fade.view = shell_fade_create_surface(shell);
5425                 if (!shell->fade.view)
5426                         return;
5427
5428                 shell->fade.view->alpha = 1.0 - tint;
5429                 weston_view_update_transform(shell->fade.view);
5430         }
5431
5432         if (shell->fade.view->output == NULL) {
5433                 /* If the black view gets a NULL output, we lost the
5434                  * last output and we'll just cancel the fade.  This
5435                  * happens when you close the last window under the
5436                  * X11 or Wayland backends. */
5437                 shell->locked = false;
5438                 weston_surface_destroy(shell->fade.view->surface);
5439                 shell->fade.view = NULL;
5440         } else if (shell->fade.animation) {
5441                 weston_fade_update(shell->fade.animation, tint);
5442         } else {
5443                 shell->fade.animation =
5444                         weston_fade_run(shell->fade.view,
5445                                         1.0 - tint, tint, 300.0,
5446                                         shell_fade_done, shell);
5447         }
5448 }
5449
5450 static void
5451 do_shell_fade_startup(void *data)
5452 {
5453         struct desktop_shell *shell = data;
5454
5455         if (shell->startup_animation_type == ANIMATION_FADE) {
5456                 shell_fade(shell, FADE_IN);
5457         } else {
5458                 weston_log("desktop shell: "
5459                            "unexpected fade-in animation type %d\n",
5460                            shell->startup_animation_type);
5461                 weston_surface_destroy(shell->fade.view->surface);
5462                 shell->fade.view = NULL;
5463         }
5464 }
5465
5466 static void
5467 shell_fade_startup(struct desktop_shell *shell)
5468 {
5469         struct wl_event_loop *loop;
5470
5471         if (!shell->fade.startup_timer)
5472                 return;
5473
5474         wl_event_source_remove(shell->fade.startup_timer);
5475         shell->fade.startup_timer = NULL;
5476
5477         loop = wl_display_get_event_loop(shell->compositor->wl_display);
5478         wl_event_loop_add_idle(loop, do_shell_fade_startup, shell);
5479 }
5480
5481 static int
5482 fade_startup_timeout(void *data)
5483 {
5484         struct desktop_shell *shell = data;
5485
5486         shell_fade_startup(shell);
5487         return 0;
5488 }
5489
5490 static void
5491 shell_fade_init(struct desktop_shell *shell)
5492 {
5493         /* Make compositor output all black, and wait for the desktop-shell
5494          * client to signal it is ready, then fade in. The timer triggers a
5495          * fade-in, in case the desktop-shell client takes too long.
5496          */
5497
5498         struct wl_event_loop *loop;
5499
5500         if (shell->fade.view != NULL) {
5501                 weston_log("%s: warning: fade surface already exists\n",
5502                            __func__);
5503                 return;
5504         }
5505
5506         if (shell->startup_animation_type == ANIMATION_NONE)
5507                 return;
5508
5509         shell->fade.view = shell_fade_create_surface(shell);
5510         if (!shell->fade.view)
5511                 return;
5512
5513         weston_view_update_transform(shell->fade.view);
5514         weston_surface_damage(shell->fade.view->surface);
5515
5516         loop = wl_display_get_event_loop(shell->compositor->wl_display);
5517         shell->fade.startup_timer =
5518                 wl_event_loop_add_timer(loop, fade_startup_timeout, shell);
5519         wl_event_source_timer_update(shell->fade.startup_timer, 15000);
5520 }
5521
5522 static void
5523 idle_handler(struct wl_listener *listener, void *data)
5524 {
5525         struct desktop_shell *shell =
5526                 container_of(listener, struct desktop_shell, idle_listener);
5527         struct weston_seat *seat;
5528
5529         wl_list_for_each(seat, &shell->compositor->seat_list, link) {
5530                 struct weston_touch *touch = weston_seat_get_touch(seat);
5531                 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
5532
5533                 if (pointer)
5534                         popup_grab_end(pointer);
5535                 if (touch)
5536                         touch_popup_grab_end(touch);
5537         }
5538
5539         shell_fade(shell, FADE_OUT);
5540         /* lock() is called from shell_fade_done() */
5541 }
5542
5543 static void
5544 wake_handler(struct wl_listener *listener, void *data)
5545 {
5546         struct desktop_shell *shell =
5547                 container_of(listener, struct desktop_shell, wake_listener);
5548
5549         unlock(shell);
5550 }
5551
5552 static void
5553 transform_handler(struct wl_listener *listener, void *data)
5554 {
5555         struct weston_surface *surface = data;
5556         struct shell_surface *shsurf = get_shell_surface(surface);
5557         struct weston_view *view;;
5558         int x, y;
5559
5560         if (!shsurf || !shsurf->client->send_position)
5561                 return;
5562
5563         view = shsurf->view;
5564         if (!view || !weston_view_is_mapped(view))
5565                 return;
5566
5567         x = view->geometry.x;
5568         y = view->geometry.y;
5569
5570         shsurf->client->send_position(surface, x, y);
5571 }
5572
5573 static void
5574 center_on_output(struct weston_view *view, struct weston_output *output)
5575 {
5576         int32_t surf_x, surf_y, width, height;
5577         float x, y;
5578
5579         surface_subsurfaces_boundingbox(view->surface, &surf_x, &surf_y, &width, &height);
5580
5581         x = output->x + (output->width - width) / 2 - surf_x / 2;
5582         y = output->y + (output->height - height) / 2 - surf_y / 2;
5583
5584         weston_view_set_position(view, x, y);
5585 }
5586
5587 static void
5588 weston_view_set_initial_position(struct weston_view *view,
5589                                  struct desktop_shell *shell)
5590 {
5591         struct weston_compositor *compositor = shell->compositor;
5592         int ix = 0, iy = 0;
5593         int32_t range_x, range_y;
5594         int32_t x, y;
5595         struct weston_output *output, *target_output = NULL;
5596         struct weston_seat *seat;
5597         pixman_rectangle32_t area;
5598
5599         /* As a heuristic place the new window on the same output as the
5600          * pointer. Falling back to the output containing 0, 0.
5601          *
5602          * TODO: Do something clever for touch too?
5603          */
5604         wl_list_for_each(seat, &compositor->seat_list, link) {
5605                 struct weston_pointer *pointer = weston_seat_get_pointer(seat);
5606
5607                 if (pointer) {
5608                         ix = wl_fixed_to_int(pointer->x);
5609                         iy = wl_fixed_to_int(pointer->y);
5610                         break;
5611                 }
5612         }
5613
5614         wl_list_for_each(output, &compositor->output_list, link) {
5615                 if (pixman_region32_contains_point(&output->region, ix, iy, NULL)) {
5616                         target_output = output;
5617                         break;
5618                 }
5619         }
5620
5621         if (!target_output) {
5622                 weston_view_set_position(view, 10 + random() % 400,
5623                                          10 + random() % 400);
5624                 return;
5625         }
5626
5627         /* Valid range within output where the surface will still be onscreen.
5628          * If this is negative it means that the surface is bigger than
5629          * output.
5630          */
5631         get_output_work_area(shell, target_output, &area);
5632
5633         x = area.x;
5634         y = area.y;
5635         range_x = area.width - view->surface->width;
5636         range_y = area.height - view->surface->height;
5637
5638         if (range_x > 0)
5639                 x += random() % range_x;
5640
5641         if (range_y > 0)
5642                 y += random() % range_y;
5643
5644         weston_view_set_position(view, x, y);
5645 }
5646
5647 static void
5648 set_maximized_position(struct desktop_shell *shell,
5649                        struct shell_surface *shsurf)
5650 {
5651         int32_t surf_x, surf_y;
5652         pixman_rectangle32_t area;
5653
5654         get_output_work_area(shell, shsurf->output, &area);
5655         if (shsurf->has_set_geometry) {
5656                 surf_x = shsurf->geometry.x;
5657                 surf_y = shsurf->geometry.y;
5658         } else {
5659                 surface_subsurfaces_boundingbox(shsurf->surface,
5660                                                 &surf_x, &surf_y, NULL, NULL);
5661         }
5662
5663         weston_view_set_position(shsurf->view,
5664                                  area.x - surf_x,
5665                                  area.y - surf_y);
5666 }
5667
5668 static void
5669 map(struct desktop_shell *shell, struct shell_surface *shsurf,
5670     int32_t sx, int32_t sy)
5671 {
5672         struct weston_compositor *compositor = shell->compositor;
5673         struct weston_seat *seat;
5674
5675         /* initial positioning, see also configure() */
5676         switch (shsurf->type) {
5677         case SHELL_SURFACE_TOPLEVEL:
5678                 if (shsurf->state.fullscreen) {
5679                         center_on_output(shsurf->view, shsurf->fullscreen_output);
5680                         shell_map_fullscreen(shsurf);
5681                 } else if (shsurf->state.maximized) {
5682                         set_maximized_position(shell, shsurf);
5683                 } else if (!shsurf->state.relative) {
5684                         weston_view_set_initial_position(shsurf->view, shell);
5685                 }
5686                 break;
5687         case SHELL_SURFACE_POPUP:
5688                 if (shell_map_popup(shsurf) != 0)
5689                         return;
5690                 break;
5691         case SHELL_SURFACE_NONE:
5692                 weston_view_set_position(shsurf->view,
5693                                          shsurf->view->geometry.x + sx,
5694                                          shsurf->view->geometry.y + sy);
5695                 break;
5696         case SHELL_SURFACE_XWAYLAND:
5697         default:
5698                 ;
5699         }
5700
5701         /* Surface stacking order, see also activate(). */
5702         shell_surface_update_layer(shsurf);
5703
5704         if (shsurf->type != SHELL_SURFACE_NONE) {
5705                 weston_view_update_transform(shsurf->view);
5706                 shsurf->view->is_mapped = true;
5707                 if (shsurf->state.maximized) {
5708                         shsurf->surface->output = shsurf->output;
5709                         shsurf->view->output = shsurf->output;
5710                 }
5711         }
5712
5713         switch (shsurf->type) {
5714         /* XXX: xwayland's using the same fields for transient type */
5715         case SHELL_SURFACE_XWAYLAND:
5716                 if (shsurf->transient.flags ==
5717                                 WL_SHELL_SURFACE_TRANSIENT_INACTIVE)
5718                         break;
5719         case SHELL_SURFACE_TOPLEVEL:
5720                 if (shsurf->state.relative &&
5721                     shsurf->transient.flags == WL_SHELL_SURFACE_TRANSIENT_INACTIVE)
5722                         break;
5723                 if (shell->locked)
5724                         break;
5725                 wl_list_for_each(seat, &compositor->seat_list, link)
5726                         activate(shell, shsurf->view, seat,
5727                                  WESTON_ACTIVATE_FLAG_CONFIGURE);
5728                 break;
5729         case SHELL_SURFACE_POPUP:
5730         case SHELL_SURFACE_NONE:
5731         default:
5732                 break;
5733         }
5734
5735         if (shsurf->type == SHELL_SURFACE_TOPLEVEL &&
5736             !shsurf->state.maximized && !shsurf->state.fullscreen)
5737         {
5738                 switch (shell->win_animation_type) {
5739                 case ANIMATION_FADE:
5740                         weston_fade_run(shsurf->view, 0.0, 1.0, 300.0, NULL, NULL);
5741                         break;
5742                 case ANIMATION_ZOOM:
5743                         weston_zoom_run(shsurf->view, 0.5, 1.0, NULL, NULL);
5744                         break;
5745                 case ANIMATION_NONE:
5746                 default:
5747                         break;
5748                 }
5749         }
5750 }
5751
5752 static void
5753 configure(struct desktop_shell *shell, struct weston_surface *surface,
5754           float x, float y)
5755 {
5756         struct shell_surface *shsurf;
5757         struct weston_view *view;
5758
5759         shsurf = get_shell_surface(surface);
5760
5761         assert(shsurf);
5762
5763         if (shsurf->state.fullscreen)
5764                 shell_configure_fullscreen(shsurf);
5765         else if (shsurf->state.maximized) {
5766                 set_maximized_position(shell, shsurf);
5767         } else {
5768                 weston_view_set_position(shsurf->view, x, y);
5769         }
5770
5771         /* XXX: would a fullscreen surface need the same handling? */
5772         if (surface->output) {
5773                 wl_list_for_each(view, &surface->views, surface_link)
5774                         weston_view_update_transform(view);
5775
5776                 if (shsurf->state.maximized)
5777                         surface->output = shsurf->output;
5778         }
5779 }
5780
5781 static void
5782 shell_surface_committed(struct weston_surface *es, int32_t sx, int32_t sy)
5783 {
5784         struct shell_surface *shsurf = get_shell_surface(es);
5785         struct desktop_shell *shell;
5786         int type_changed = 0;
5787
5788         assert(shsurf);
5789
5790         shell = shsurf->shell;
5791
5792         if (!weston_surface_is_mapped(es) &&
5793             !wl_list_empty(&shsurf->popup.grab_link)) {
5794                 remove_popup_grab(shsurf);
5795         }
5796
5797         if (es->width == 0)
5798                 return;
5799
5800         if (shsurf->has_next_geometry) {
5801                 shsurf->geometry = shsurf->next_geometry;
5802                 shsurf->has_next_geometry = false;
5803                 shsurf->has_set_geometry = true;
5804         } else if (!shsurf->has_set_geometry) {
5805                 surface_subsurfaces_boundingbox(shsurf->surface,
5806                                                 &shsurf->geometry.x,
5807                                                 &shsurf->geometry.y,
5808                                                 &shsurf->geometry.width,
5809                                                 &shsurf->geometry.height);
5810         }
5811
5812         if (shsurf->state_changed) {
5813                 set_surface_type(shsurf);
5814                 type_changed = 1;
5815         }
5816
5817         if (!weston_surface_is_mapped(es)) {
5818                 map(shell, shsurf, sx, sy);
5819                 es->is_mapped = true;
5820         } else if (type_changed || sx != 0 || sy != 0 ||
5821                    shsurf->last_width != es->width ||
5822                    shsurf->last_height != es->height) {
5823                 float from_x, from_y;
5824                 float to_x, to_y;
5825
5826                 if (shsurf->resize_edges) {
5827                         sx = 0;
5828                         sy = 0;
5829                 }
5830
5831                 if (shsurf->resize_edges & WL_SHELL_SURFACE_RESIZE_LEFT)
5832                         sx = shsurf->last_width - es->width;
5833                 if (shsurf->resize_edges & WL_SHELL_SURFACE_RESIZE_TOP)
5834                         sy = shsurf->last_height - es->height;
5835
5836                 shsurf->last_width = es->width;
5837                 shsurf->last_height = es->height;
5838
5839                 weston_view_to_global_float(shsurf->view, 0, 0, &from_x, &from_y);
5840                 weston_view_to_global_float(shsurf->view, sx, sy, &to_x, &to_y);
5841                 configure(shell, es,
5842                           shsurf->view->geometry.x + to_x - from_x,
5843                           shsurf->view->geometry.y + to_y - from_y);
5844         }
5845 }
5846
5847 static bool
5848 check_desktop_shell_crash_too_early(struct desktop_shell *shell)
5849 {
5850         struct timespec now;
5851
5852         if (clock_gettime(CLOCK_MONOTONIC, &now) < 0)
5853                 return false;
5854
5855         /*
5856          * If the shell helper client dies before the session has been
5857          * up for roughly 30 seconds, better just make Weston shut down,
5858          * because the user likely has no way to interact with the desktop
5859          * anyway.
5860          */
5861         if (now.tv_sec - shell->startup_time.tv_sec < 30) {
5862                 weston_log("Error: %s apparently cannot run at all.\n",
5863                            shell->client);
5864                 weston_log_continue(STAMP_SPACE "Quitting...");
5865                 wl_display_terminate(shell->compositor->wl_display);
5866
5867                 return true;
5868         }
5869
5870         return false;
5871 }
5872
5873 static void launch_desktop_shell_process(void *data);
5874
5875 static void
5876 respawn_desktop_shell_process(struct desktop_shell *shell)
5877 {
5878         uint32_t time;
5879
5880         /* if desktop-shell dies more than 5 times in 30 seconds, give up */
5881         time = weston_compositor_get_time();
5882         if (time - shell->child.deathstamp > 30000) {
5883                 shell->child.deathstamp = time;
5884                 shell->child.deathcount = 0;
5885         }
5886
5887         shell->child.deathcount++;
5888         if (shell->child.deathcount > 5) {
5889                 weston_log("%s disconnected, giving up.\n", shell->client);
5890                 return;
5891         }
5892
5893         weston_log("%s disconnected, respawning...\n", shell->client);
5894         launch_desktop_shell_process(shell);
5895 }
5896
5897 static void
5898 desktop_shell_client_destroy(struct wl_listener *listener, void *data)
5899 {
5900         struct desktop_shell *shell;
5901
5902         shell = container_of(listener, struct desktop_shell,
5903                              child.client_destroy_listener);
5904
5905         wl_list_remove(&shell->child.client_destroy_listener.link);
5906         shell->child.client = NULL;
5907         /*
5908          * unbind_desktop_shell() will reset shell->child.desktop_shell
5909          * before the respawned process has a chance to create a new
5910          * desktop_shell object, because we are being called from the
5911          * wl_client destructor which destroys all wl_resources before
5912          * returning.
5913          */
5914
5915         if (!check_desktop_shell_crash_too_early(shell))
5916                 respawn_desktop_shell_process(shell);
5917
5918         shell_fade_startup(shell);
5919 }
5920
5921 static void
5922 launch_desktop_shell_process(void *data)
5923 {
5924         struct desktop_shell *shell = data;
5925
5926         shell->child.client = weston_client_start(shell->compositor,
5927                                                   shell->client);
5928
5929         if (!shell->child.client) {
5930                 weston_log("not able to start %s\n", shell->client);
5931                 return;
5932         }
5933
5934         shell->child.client_destroy_listener.notify =
5935                 desktop_shell_client_destroy;
5936         wl_client_add_destroy_listener(shell->child.client,
5937                                        &shell->child.client_destroy_listener);
5938 }
5939
5940 static void
5941 handle_shell_client_destroy(struct wl_listener *listener, void *data)
5942 {
5943         struct shell_client *sc =
5944                 container_of(listener, struct shell_client, destroy_listener);
5945         struct wl_resource *shsurf_resource;
5946         struct shell_surface *shsurf;
5947
5948         if (sc->ping_timer)
5949                 wl_event_source_remove(sc->ping_timer);
5950
5951         /* Since we're about to free shell_client, we remove it from the
5952          * head of the surface list so we don't use that freed list node
5953          * during surface clean up later on.
5954          */
5955         wl_resource_for_each(shsurf_resource, &sc->surface_list) {
5956                 shsurf = wl_resource_get_user_data(shsurf_resource);
5957                 shsurf->owner = NULL;
5958         }
5959         wl_list_remove(&sc->surface_list);
5960
5961         free(sc);
5962 }
5963
5964 static struct shell_client *
5965 shell_client_create(struct wl_client *client, struct desktop_shell *shell,
5966                     const struct wl_interface *interface, uint32_t id)
5967 {
5968         struct shell_client *sc;
5969
5970         sc = zalloc(sizeof *sc);
5971         if (sc == NULL) {
5972                 wl_client_post_no_memory(client);
5973                 return NULL;
5974         }
5975
5976         sc->resource = wl_resource_create(client, interface, 1, id);
5977         if (sc->resource == NULL) {
5978                 free(sc);
5979                 wl_client_post_no_memory(client);
5980                 return NULL;
5981         }
5982
5983         sc->client = client;
5984         sc->shell = shell;
5985         sc->destroy_listener.notify = handle_shell_client_destroy;
5986         wl_client_add_destroy_listener(client, &sc->destroy_listener);
5987         wl_list_init(&sc->surface_list);
5988
5989         return sc;
5990 }
5991
5992 static void
5993 bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
5994 {
5995         struct desktop_shell *shell = data;
5996         struct shell_client *sc;
5997
5998         sc = shell_client_create(client, shell, &wl_shell_interface, id);
5999         if (sc)
6000                 wl_resource_set_implementation(sc->resource,
6001                                                &shell_implementation,
6002                                                sc, NULL);
6003 }
6004
6005 static void
6006 bind_xdg_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
6007 {
6008         struct desktop_shell *shell = data;
6009         struct shell_client *sc;
6010
6011         sc = shell_client_create(client, shell, &xdg_shell_interface, id);
6012         if (sc)
6013                 wl_resource_set_dispatcher(sc->resource,
6014                                            xdg_shell_unversioned_dispatch,
6015                                            NULL, sc, NULL);
6016 }
6017
6018 static void
6019 unbind_desktop_shell(struct wl_resource *resource)
6020 {
6021         struct desktop_shell *shell = wl_resource_get_user_data(resource);
6022
6023         if (shell->locked)
6024                 resume_desktop(shell);
6025
6026         shell->child.desktop_shell = NULL;
6027         shell->prepare_event_sent = false;
6028 }
6029
6030 static void
6031 bind_desktop_shell(struct wl_client *client,
6032                    void *data, uint32_t version, uint32_t id)
6033 {
6034         struct desktop_shell *shell = data;
6035         struct wl_resource *resource;
6036
6037         resource = wl_resource_create(client, &weston_desktop_shell_interface,
6038                                       1, id);
6039
6040         if (client == shell->child.client) {
6041                 wl_resource_set_implementation(resource,
6042                                                &desktop_shell_implementation,
6043                                                shell, unbind_desktop_shell);
6044                 shell->child.desktop_shell = resource;
6045                 return;
6046         }
6047
6048         wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
6049                                "permission to bind desktop_shell denied");
6050 }
6051
6052 struct switcher {
6053         struct desktop_shell *shell;
6054         struct weston_view *current;
6055         struct wl_listener listener;
6056         struct weston_keyboard_grab grab;
6057         struct wl_array minimized_array;
6058 };
6059
6060 static void
6061 switcher_next(struct switcher *switcher)
6062 {
6063         struct weston_view *view;
6064         struct weston_view *first = NULL, *prev = NULL, *next = NULL;
6065         struct shell_surface *shsurf;
6066         struct workspace *ws = get_current_workspace(switcher->shell);
6067
6068          /* temporary re-display minimized surfaces */
6069         struct weston_view *tmp;
6070         struct weston_view **minimized;
6071         wl_list_for_each_safe(view, tmp, &switcher->shell->minimized_layer.view_list.link, layer_link.link) {
6072                 weston_layer_entry_remove(&view->layer_link);
6073                 weston_layer_entry_insert(&ws->layer.view_list, &view->layer_link);
6074                 minimized = wl_array_add(&switcher->minimized_array, sizeof *minimized);
6075                 *minimized = view;
6076         }
6077
6078         wl_list_for_each(view, &ws->layer.view_list.link, layer_link.link) {
6079                 shsurf = get_shell_surface(view->surface);
6080                 if (shsurf &&
6081                     shsurf->type == SHELL_SURFACE_TOPLEVEL &&
6082                     shsurf->parent == NULL) {
6083                         if (first == NULL)
6084                                 first = view;
6085                         if (prev == switcher->current)
6086                                 next = view;
6087                         prev = view;
6088                         view->alpha = 0.25;
6089                         weston_view_geometry_dirty(view);
6090                         weston_surface_damage(view->surface);
6091                 }
6092
6093                 if (is_black_surface_view(view, NULL)) {
6094                         view->alpha = 0.25;
6095                         weston_view_geometry_dirty(view);
6096                         weston_surface_damage(view->surface);
6097                 }
6098         }
6099
6100         if (next == NULL)
6101                 next = first;
6102
6103         if (next == NULL)
6104                 return;
6105
6106         wl_list_remove(&switcher->listener.link);
6107         wl_signal_add(&next->destroy_signal, &switcher->listener);
6108
6109         switcher->current = next;
6110         wl_list_for_each(view, &next->surface->views, surface_link)
6111                 view->alpha = 1.0;
6112
6113         shsurf = get_shell_surface(switcher->current->surface);
6114         if (shsurf && shsurf->state.fullscreen)
6115                 shsurf->fullscreen.black_view->alpha = 1.0;
6116 }
6117
6118 static void
6119 switcher_handle_view_destroy(struct wl_listener *listener, void *data)
6120 {
6121         struct switcher *switcher =
6122                 container_of(listener, struct switcher, listener);
6123
6124         switcher_next(switcher);
6125 }
6126
6127 static void
6128 switcher_destroy(struct switcher *switcher)
6129 {
6130         struct weston_view *view;
6131         struct weston_keyboard *keyboard = switcher->grab.keyboard;
6132         struct workspace *ws = get_current_workspace(switcher->shell);
6133
6134         wl_list_for_each(view, &ws->layer.view_list.link, layer_link.link) {
6135                 if (is_focus_view(view))
6136                         continue;
6137
6138                 view->alpha = 1.0;
6139                 weston_surface_damage(view->surface);
6140         }
6141
6142         if (switcher->current) {
6143                 activate(switcher->shell, switcher->current,
6144                          keyboard->seat,
6145                          WESTON_ACTIVATE_FLAG_CONFIGURE);
6146         }
6147
6148         wl_list_remove(&switcher->listener.link);
6149         weston_keyboard_end_grab(keyboard);
6150         if (keyboard->input_method_resource)
6151                 keyboard->grab = &keyboard->input_method_grab;
6152
6153          /* re-hide surfaces that were temporary shown during the switch */
6154         struct weston_view **minimized;
6155         wl_array_for_each(minimized, &switcher->minimized_array) {
6156                 /* with the exception of the current selected */
6157                 if ((*minimized)->surface != switcher->current->surface) {
6158                         weston_layer_entry_remove(&(*minimized)->layer_link);
6159                         weston_layer_entry_insert(&switcher->shell->minimized_layer.view_list, &(*minimized)->layer_link);
6160                         weston_view_damage_below(*minimized);
6161                 }
6162         }
6163         wl_array_release(&switcher->minimized_array);
6164
6165         free(switcher);
6166 }
6167
6168 static void
6169 switcher_key(struct weston_keyboard_grab *grab,
6170              uint32_t time, uint32_t key, uint32_t state_w)
6171 {
6172         struct switcher *switcher = container_of(grab, struct switcher, grab);
6173         enum wl_keyboard_key_state state = state_w;
6174
6175         if (key == KEY_TAB && state == WL_KEYBOARD_KEY_STATE_PRESSED)
6176                 switcher_next(switcher);
6177 }
6178
6179 static void
6180 switcher_modifier(struct weston_keyboard_grab *grab, uint32_t serial,
6181                   uint32_t mods_depressed, uint32_t mods_latched,
6182                   uint32_t mods_locked, uint32_t group)
6183 {
6184         struct switcher *switcher = container_of(grab, struct switcher, grab);
6185         struct weston_seat *seat = grab->keyboard->seat;
6186
6187         if ((seat->modifier_state & switcher->shell->binding_modifier) == 0)
6188                 switcher_destroy(switcher);
6189 }
6190
6191 static void
6192 switcher_cancel(struct weston_keyboard_grab *grab)
6193 {
6194         struct switcher *switcher = container_of(grab, struct switcher, grab);
6195
6196         switcher_destroy(switcher);
6197 }
6198
6199 static const struct weston_keyboard_grab_interface switcher_grab = {
6200         switcher_key,
6201         switcher_modifier,
6202         switcher_cancel,
6203 };
6204
6205 static void
6206 switcher_binding(struct weston_keyboard *keyboard, uint32_t time,
6207                  uint32_t key, void *data)
6208 {
6209         struct desktop_shell *shell = data;
6210         struct switcher *switcher;
6211
6212         switcher = malloc(sizeof *switcher);
6213         switcher->shell = shell;
6214         switcher->current = NULL;
6215         switcher->listener.notify = switcher_handle_view_destroy;
6216         wl_list_init(&switcher->listener.link);
6217         wl_array_init(&switcher->minimized_array);
6218
6219         restore_all_output_modes(shell->compositor);
6220         lower_fullscreen_layer(switcher->shell, NULL);
6221         switcher->grab.interface = &switcher_grab;
6222         weston_keyboard_start_grab(keyboard, &switcher->grab);
6223         weston_keyboard_set_focus(keyboard, NULL);
6224         switcher_next(switcher);
6225 }
6226
6227 static void
6228 backlight_binding(struct weston_keyboard *keyboard, uint32_t time,
6229                   uint32_t key, void *data)
6230 {
6231         struct weston_compositor *compositor = data;
6232         struct weston_output *output;
6233         long backlight_new = 0;
6234
6235         /* TODO: we're limiting to simple use cases, where we assume just
6236          * control on the primary display. We'd have to extend later if we
6237          * ever get support for setting backlights on random desktop LCD
6238          * panels though */
6239         output = get_default_output(compositor);
6240         if (!output)
6241                 return;
6242
6243         if (!output->set_backlight)
6244                 return;
6245
6246         if (key == KEY_F9 || key == KEY_BRIGHTNESSDOWN)
6247                 backlight_new = output->backlight_current - 25;
6248         else if (key == KEY_F10 || key == KEY_BRIGHTNESSUP)
6249                 backlight_new = output->backlight_current + 25;
6250
6251         if (backlight_new < 5)
6252                 backlight_new = 5;
6253         if (backlight_new > 255)
6254                 backlight_new = 255;
6255
6256         output->backlight_current = backlight_new;
6257         output->set_backlight(output, output->backlight_current);
6258 }
6259
6260 static void
6261 force_kill_binding(struct weston_keyboard *keyboard, uint32_t time,
6262                    uint32_t key, void *data)
6263 {
6264         struct weston_surface *focus_surface;
6265         struct wl_client *client;
6266         struct desktop_shell *shell = data;
6267         struct weston_compositor *compositor = shell->compositor;
6268         pid_t pid;
6269
6270         focus_surface = keyboard->focus;
6271         if (!focus_surface)
6272                 return;
6273
6274         wl_signal_emit(&compositor->kill_signal, focus_surface);
6275
6276         client = wl_resource_get_client(focus_surface->resource);
6277         wl_client_get_credentials(client, &pid, NULL, NULL);
6278
6279         /* Skip clients that we launched ourselves (the credentials of
6280          * the socketpair is ours) */
6281         if (pid == getpid())
6282                 return;
6283
6284         kill(pid, SIGKILL);
6285 }
6286
6287 static void
6288 workspace_up_binding(struct weston_keyboard *keyboard, uint32_t time,
6289                      uint32_t key, void *data)
6290 {
6291         struct desktop_shell *shell = data;
6292         unsigned int new_index = shell->workspaces.current;
6293
6294         if (shell->locked)
6295                 return;
6296         if (new_index != 0)
6297                 new_index--;
6298
6299         change_workspace(shell, new_index);
6300 }
6301
6302 static void
6303 workspace_down_binding(struct weston_keyboard *keyboard, uint32_t time,
6304                        uint32_t key, void *data)
6305 {
6306         struct desktop_shell *shell = data;
6307         unsigned int new_index = shell->workspaces.current;
6308
6309         if (shell->locked)
6310                 return;
6311         if (new_index < shell->workspaces.num - 1)
6312                 new_index++;
6313
6314         change_workspace(shell, new_index);
6315 }
6316
6317 static void
6318 workspace_f_binding(struct weston_keyboard *keyboard, uint32_t time,
6319                     uint32_t key, void *data)
6320 {
6321         struct desktop_shell *shell = data;
6322         unsigned int new_index;
6323
6324         if (shell->locked)
6325                 return;
6326         new_index = key - KEY_F1;
6327         if (new_index >= shell->workspaces.num)
6328                 new_index = shell->workspaces.num - 1;
6329
6330         change_workspace(shell, new_index);
6331 }
6332
6333 static void
6334 workspace_move_surface_up_binding(struct weston_keyboard *keyboard,
6335                                   uint32_t time, uint32_t key, void *data)
6336 {
6337         struct desktop_shell *shell = data;
6338         unsigned int new_index = shell->workspaces.current;
6339
6340         if (shell->locked)
6341                 return;
6342
6343         if (new_index != 0)
6344                 new_index--;
6345
6346         take_surface_to_workspace_by_seat(shell, keyboard->seat, new_index);
6347 }
6348
6349 static void
6350 workspace_move_surface_down_binding(struct weston_keyboard *keyboard,
6351                                     uint32_t time, uint32_t key, void *data)
6352 {
6353         struct desktop_shell *shell = data;
6354         unsigned int new_index = shell->workspaces.current;
6355
6356         if (shell->locked)
6357                 return;
6358
6359         if (new_index < shell->workspaces.num - 1)
6360                 new_index++;
6361
6362         take_surface_to_workspace_by_seat(shell, keyboard->seat, new_index);
6363 }
6364
6365 static void
6366 shell_reposition_view_on_output_destroy(struct weston_view *view)
6367 {
6368         struct weston_output *output, *first_output;
6369         struct weston_compositor *ec = view->surface->compositor;
6370         struct shell_surface *shsurf;
6371         float x, y;
6372         int visible;
6373
6374         x = view->geometry.x;
6375         y = view->geometry.y;
6376
6377         /* At this point the destroyed output is not in the list anymore.
6378          * If the view is still visible somewhere, we leave where it is,
6379          * otherwise, move it to the first output. */
6380         visible = 0;
6381         wl_list_for_each(output, &ec->output_list, link) {
6382                 if (pixman_region32_contains_point(&output->region,
6383                                                    x, y, NULL)) {
6384                         visible = 1;
6385                         break;
6386                 }
6387         }
6388
6389         if (!visible) {
6390                 first_output = container_of(ec->output_list.next,
6391                                             struct weston_output, link);
6392
6393                 x = first_output->x + first_output->width / 4;
6394                 y = first_output->y + first_output->height / 4;
6395
6396                 weston_view_set_position(view, x, y);
6397         } else {
6398                 weston_view_geometry_dirty(view);
6399         }
6400
6401
6402         shsurf = get_shell_surface(view->surface);
6403
6404         if (shsurf) {
6405                 shsurf->saved_position_valid = false;
6406                 shsurf->next_state.maximized = false;
6407                 shsurf->next_state.fullscreen = false;
6408                 shsurf->state_changed = true;
6409         }
6410 }
6411
6412 void
6413 shell_for_each_layer(struct desktop_shell *shell,
6414                      shell_for_each_layer_func_t func, void *data)
6415 {
6416         struct workspace **ws;
6417
6418         func(shell, &shell->fullscreen_layer, data);
6419         func(shell, &shell->panel_layer, data);
6420         func(shell, &shell->background_layer, data);
6421         func(shell, &shell->lock_layer, data);
6422         func(shell, &shell->input_panel_layer, data);
6423
6424         wl_array_for_each(ws, &shell->workspaces.array)
6425                 func(shell, &(*ws)->layer, data);
6426 }
6427
6428 static void
6429 shell_output_destroy_move_layer(struct desktop_shell *shell,
6430                                 struct weston_layer *layer,
6431                                 void *data)
6432 {
6433         struct weston_output *output = data;
6434         struct weston_view *view;
6435
6436         wl_list_for_each(view, &layer->view_list.link, layer_link.link) {
6437                 if (view->output != output)
6438                         continue;
6439
6440                 shell_reposition_view_on_output_destroy(view);
6441         }
6442 }
6443
6444 static void
6445 handle_output_destroy(struct wl_listener *listener, void *data)
6446 {
6447         struct shell_output *output_listener =
6448                 container_of(listener, struct shell_output, destroy_listener);
6449         struct weston_output *output = output_listener->output;
6450         struct desktop_shell *shell = output_listener->shell;
6451
6452         shell_for_each_layer(shell, shell_output_destroy_move_layer, output);
6453
6454         wl_list_remove(&output_listener->destroy_listener.link);
6455         wl_list_remove(&output_listener->link);
6456         free(output_listener);
6457 }
6458
6459 static void
6460 shell_resize_surface_to_output(struct desktop_shell *shell,
6461                                 struct weston_surface *surface,
6462                                 const struct weston_output *output)
6463 {
6464         if (!surface)
6465                 return;
6466
6467         weston_desktop_shell_send_configure(shell->child.desktop_shell, 0,
6468                                         surface->resource,
6469                                         output->width,
6470                                         output->height);
6471 }
6472
6473
6474 static void
6475 handle_output_resized(struct wl_listener *listener, void *data)
6476 {
6477         struct desktop_shell *shell =
6478                 container_of(listener, struct desktop_shell, resized_listener);
6479         struct weston_output *output = (struct weston_output *)data;
6480         struct shell_output *sh_output = find_shell_output_from_weston_output(shell, output);
6481
6482         shell_resize_surface_to_output(shell, sh_output->background_surface, output);
6483         shell_resize_surface_to_output(shell, sh_output->panel_surface, output);
6484 }
6485
6486 static void
6487 create_shell_output(struct desktop_shell *shell,
6488                                         struct weston_output *output)
6489 {
6490         struct shell_output *shell_output;
6491
6492         shell_output = zalloc(sizeof *shell_output);
6493         if (shell_output == NULL)
6494                 return;
6495
6496         shell_output->output = output;
6497         shell_output->shell = shell;
6498         shell_output->destroy_listener.notify = handle_output_destroy;
6499         wl_signal_add(&output->destroy_signal,
6500                       &shell_output->destroy_listener);
6501         wl_list_insert(shell->output_list.prev, &shell_output->link);
6502 }
6503
6504 static void
6505 handle_output_create(struct wl_listener *listener, void *data)
6506 {
6507         struct desktop_shell *shell =
6508                 container_of(listener, struct desktop_shell, output_create_listener);
6509         struct weston_output *output = (struct weston_output *)data;
6510
6511         create_shell_output(shell, output);
6512 }
6513
6514 static void
6515 handle_output_move_layer(struct desktop_shell *shell,
6516                          struct weston_layer *layer, void *data)
6517 {
6518         struct weston_output *output = data;
6519         struct weston_view *view;
6520         float x, y;
6521
6522         wl_list_for_each(view, &layer->view_list.link, layer_link.link) {
6523                 if (view->output != output)
6524                         continue;
6525
6526                 x = view->geometry.x + output->move_x;
6527                 y = view->geometry.y + output->move_y;
6528                 weston_view_set_position(view, x, y);
6529         }
6530 }
6531
6532 static void
6533 handle_output_move(struct wl_listener *listener, void *data)
6534 {
6535         struct desktop_shell *shell;
6536
6537         shell = container_of(listener, struct desktop_shell,
6538                              output_move_listener);
6539
6540         shell_for_each_layer(shell, handle_output_move_layer, data);
6541 }
6542
6543 static void
6544 setup_output_destroy_handler(struct weston_compositor *ec,
6545                                                         struct desktop_shell *shell)
6546 {
6547         struct weston_output *output;
6548
6549         wl_list_init(&shell->output_list);
6550         wl_list_for_each(output, &ec->output_list, link)
6551                 create_shell_output(shell, output);
6552
6553         shell->output_create_listener.notify = handle_output_create;
6554         wl_signal_add(&ec->output_created_signal,
6555                                 &shell->output_create_listener);
6556
6557         shell->output_move_listener.notify = handle_output_move;
6558         wl_signal_add(&ec->output_moved_signal, &shell->output_move_listener);
6559 }
6560
6561 static void
6562 shell_destroy(struct wl_listener *listener, void *data)
6563 {
6564         struct desktop_shell *shell =
6565                 container_of(listener, struct desktop_shell, destroy_listener);
6566         struct workspace **ws;
6567         struct shell_output *shell_output, *tmp;
6568
6569         /* Force state to unlocked so we don't try to fade */
6570         shell->locked = false;
6571
6572         if (shell->child.client) {
6573                 /* disable respawn */
6574                 wl_list_remove(&shell->child.client_destroy_listener.link);
6575                 wl_client_destroy(shell->child.client);
6576         }
6577
6578         wl_list_remove(&shell->idle_listener.link);
6579         wl_list_remove(&shell->wake_listener.link);
6580         wl_list_remove(&shell->transform_listener.link);
6581
6582         text_backend_destroy(shell->text_backend);
6583         input_panel_destroy(shell);
6584
6585         wl_list_for_each_safe(shell_output, tmp, &shell->output_list, link) {
6586                 wl_list_remove(&shell_output->destroy_listener.link);
6587                 wl_list_remove(&shell_output->link);
6588                 free(shell_output);
6589         }
6590
6591         wl_list_remove(&shell->output_create_listener.link);
6592         wl_list_remove(&shell->output_move_listener.link);
6593         wl_list_remove(&shell->resized_listener.link);
6594
6595         wl_array_for_each(ws, &shell->workspaces.array)
6596                 workspace_destroy(*ws);
6597         wl_array_release(&shell->workspaces.array);
6598
6599         free(shell->client);
6600         free(shell);
6601 }
6602
6603 static void
6604 shell_add_bindings(struct weston_compositor *ec, struct desktop_shell *shell)
6605 {
6606         uint32_t mod;
6607         int i, num_workspace_bindings;
6608
6609         if (shell->allow_zap)
6610                 weston_compositor_add_key_binding(ec, KEY_BACKSPACE,
6611                                                   MODIFIER_CTRL | MODIFIER_ALT,
6612                                                   terminate_binding, ec);
6613
6614         /* fixed bindings */
6615         weston_compositor_add_button_binding(ec, BTN_LEFT, 0,
6616                                              click_to_activate_binding,
6617                                              shell);
6618         weston_compositor_add_button_binding(ec, BTN_RIGHT, 0,
6619                                              click_to_activate_binding,
6620                                              shell);
6621         weston_compositor_add_touch_binding(ec, 0,
6622                                             touch_to_activate_binding,
6623                                             shell);
6624         weston_compositor_add_axis_binding(ec, WL_POINTER_AXIS_VERTICAL_SCROLL,
6625                                            MODIFIER_SUPER | MODIFIER_ALT,
6626                                            surface_opacity_binding, NULL);
6627         weston_compositor_add_axis_binding(ec, WL_POINTER_AXIS_VERTICAL_SCROLL,
6628                                            MODIFIER_SUPER, zoom_axis_binding,
6629                                            NULL);
6630         weston_compositor_add_key_binding(ec, KEY_BRIGHTNESSDOWN, 0,
6631                                           backlight_binding, ec);
6632         weston_compositor_add_key_binding(ec, KEY_BRIGHTNESSUP, 0,
6633                                           backlight_binding, ec);
6634
6635         /* configurable bindings */
6636         if (shell->exposay_modifier)
6637                 weston_compositor_add_modifier_binding(ec, shell->exposay_modifier,
6638                                                        exposay_binding, shell);
6639
6640         mod = shell->binding_modifier;
6641         if (!mod)
6642                 return;
6643
6644         weston_compositor_add_key_binding(ec, KEY_PAGEUP, mod,
6645                                           zoom_key_binding, NULL);
6646         weston_compositor_add_key_binding(ec, KEY_PAGEDOWN, mod,
6647                                           zoom_key_binding, NULL);
6648         weston_compositor_add_key_binding(ec, KEY_M, mod | MODIFIER_SHIFT,
6649                                           maximize_binding, NULL);
6650         weston_compositor_add_key_binding(ec, KEY_F, mod | MODIFIER_SHIFT,
6651                                           fullscreen_binding, NULL);
6652         weston_compositor_add_button_binding(ec, BTN_LEFT, mod, move_binding,
6653                                              shell);
6654         weston_compositor_add_touch_binding(ec, mod, touch_move_binding, shell);
6655         weston_compositor_add_button_binding(ec, BTN_RIGHT, mod,
6656                                              resize_binding, shell);
6657         weston_compositor_add_button_binding(ec, BTN_LEFT,
6658                                              mod | MODIFIER_SHIFT,
6659                                              resize_binding, shell);
6660
6661         if (ec->capabilities & WESTON_CAP_ROTATION_ANY)
6662                 weston_compositor_add_button_binding(ec, BTN_MIDDLE, mod,
6663                                                      rotate_binding, NULL);
6664
6665         weston_compositor_add_key_binding(ec, KEY_TAB, mod, switcher_binding,
6666                                           shell);
6667         weston_compositor_add_key_binding(ec, KEY_F9, mod, backlight_binding,
6668                                           ec);
6669         weston_compositor_add_key_binding(ec, KEY_F10, mod, backlight_binding,
6670                                           ec);
6671         weston_compositor_add_key_binding(ec, KEY_K, mod,
6672                                           force_kill_binding, shell);
6673         weston_compositor_add_key_binding(ec, KEY_UP, mod,
6674                                           workspace_up_binding, shell);
6675         weston_compositor_add_key_binding(ec, KEY_DOWN, mod,
6676                                           workspace_down_binding, shell);
6677         weston_compositor_add_key_binding(ec, KEY_UP, mod | MODIFIER_SHIFT,
6678                                           workspace_move_surface_up_binding,
6679                                           shell);
6680         weston_compositor_add_key_binding(ec, KEY_DOWN, mod | MODIFIER_SHIFT,
6681                                           workspace_move_surface_down_binding,
6682                                           shell);
6683
6684         /* Add bindings for mod+F[1-6] for workspace 1 to 6. */
6685         if (shell->workspaces.num > 1) {
6686                 num_workspace_bindings = shell->workspaces.num;
6687                 if (num_workspace_bindings > 6)
6688                         num_workspace_bindings = 6;
6689                 for (i = 0; i < num_workspace_bindings; i++)
6690                         weston_compositor_add_key_binding(ec, KEY_F1 + i, mod,
6691                                                           workspace_f_binding,
6692                                                           shell);
6693         }
6694
6695         weston_install_debug_key_binding(ec, mod);
6696 }
6697
6698 static void
6699 handle_seat_created(struct wl_listener *listener, void *data)
6700 {
6701         struct weston_seat *seat = data;
6702
6703         create_shell_seat(seat);
6704 }
6705
6706 WL_EXPORT int
6707 module_init(struct weston_compositor *ec,
6708             int *argc, char *argv[])
6709 {
6710         struct weston_seat *seat;
6711         struct desktop_shell *shell;
6712         struct workspace **pws;
6713         unsigned int i;
6714         struct wl_event_loop *loop;
6715
6716         shell = zalloc(sizeof *shell);
6717         if (shell == NULL)
6718                 return -1;
6719
6720         shell->compositor = ec;
6721
6722         shell->destroy_listener.notify = shell_destroy;
6723         wl_signal_add(&ec->destroy_signal, &shell->destroy_listener);
6724         shell->idle_listener.notify = idle_handler;
6725         wl_signal_add(&ec->idle_signal, &shell->idle_listener);
6726         shell->wake_listener.notify = wake_handler;
6727         wl_signal_add(&ec->wake_signal, &shell->wake_listener);
6728         shell->transform_listener.notify = transform_handler;
6729         wl_signal_add(&ec->transform_signal, &shell->transform_listener);
6730
6731         ec->shell_interface.shell = shell;
6732         ec->shell_interface.create_shell_surface = create_shell_surface;
6733         ec->shell_interface.set_toplevel = set_toplevel;
6734         ec->shell_interface.set_transient = set_transient;
6735         ec->shell_interface.set_fullscreen = shell_interface_set_fullscreen;
6736         ec->shell_interface.set_xwayland = set_xwayland;
6737         ec->shell_interface.move = shell_interface_move;
6738         ec->shell_interface.resize = shell_interface_resize;
6739         ec->shell_interface.set_title = set_title;
6740         ec->shell_interface.set_window_geometry = set_window_geometry;
6741         ec->shell_interface.set_maximized = shell_interface_set_maximized;
6742         ec->shell_interface.set_pid = set_pid;
6743         ec->shell_interface.get_output_work_area = get_output_work_area;
6744
6745         weston_layer_init(&shell->fullscreen_layer, &ec->cursor_layer.link);
6746         weston_layer_init(&shell->panel_layer, &shell->fullscreen_layer.link);
6747         weston_layer_init(&shell->background_layer, &shell->panel_layer.link);
6748         weston_layer_init(&shell->lock_layer, NULL);
6749         weston_layer_init(&shell->input_panel_layer, NULL);
6750
6751         wl_array_init(&shell->workspaces.array);
6752         wl_list_init(&shell->workspaces.client_list);
6753
6754         if (input_panel_setup(shell) < 0)
6755                 return -1;
6756
6757         shell->text_backend = text_backend_init(ec);
6758         if (!shell->text_backend)
6759                 return -1;
6760
6761         shell_configuration(shell);
6762
6763         shell->exposay.state_cur = EXPOSAY_LAYOUT_INACTIVE;
6764         shell->exposay.state_target = EXPOSAY_TARGET_CANCEL;
6765
6766         for (i = 0; i < shell->workspaces.num; i++) {
6767                 pws = wl_array_add(&shell->workspaces.array, sizeof *pws);
6768                 if (pws == NULL)
6769                         return -1;
6770
6771                 *pws = workspace_create();
6772                 if (*pws == NULL)
6773                         return -1;
6774         }
6775         activate_workspace(shell, 0);
6776
6777         weston_layer_init(&shell->minimized_layer, NULL);
6778
6779         wl_list_init(&shell->workspaces.anim_sticky_list);
6780         wl_list_init(&shell->workspaces.animation.link);
6781         shell->workspaces.animation.frame = animate_workspace_change_frame;
6782
6783         if (wl_global_create(ec->wl_display, &wl_shell_interface, 1,
6784                                   shell, bind_shell) == NULL)
6785                 return -1;
6786
6787         if (wl_global_create(ec->wl_display, &xdg_shell_interface, 1,
6788                                   shell, bind_xdg_shell) == NULL)
6789                 return -1;
6790
6791         if (wl_global_create(ec->wl_display,
6792                              &weston_desktop_shell_interface, 1,
6793                              shell, bind_desktop_shell) == NULL)
6794                 return -1;
6795
6796         shell->child.deathstamp = weston_compositor_get_time();
6797
6798         shell->panel_position = WESTON_DESKTOP_SHELL_PANEL_POSITION_TOP;
6799
6800         setup_output_destroy_handler(ec, shell);
6801
6802         loop = wl_display_get_event_loop(ec->wl_display);
6803         wl_event_loop_add_idle(loop, launch_desktop_shell_process, shell);
6804
6805         wl_list_for_each(seat, &ec->seat_list, link)
6806                 handle_seat_created(NULL, seat);
6807         shell->seat_create_listener.notify = handle_seat_created;
6808         wl_signal_add(&ec->seat_created_signal, &shell->seat_create_listener);
6809
6810         shell->resized_listener.notify = handle_output_resized;
6811         wl_signal_add(&ec->output_resized_signal, &shell->resized_listener);
6812
6813         screenshooter_create(ec);
6814
6815         shell_add_bindings(ec, shell);
6816
6817         shell_fade_init(shell);
6818
6819         clock_gettime(CLOCK_MONOTONIC, &shell->startup_time);
6820
6821         return 0;
6822 }