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