eb8d802d99f825f50120f02c49b89439f186d461
[platform/upstream/weston.git] / src / shell.c
1 /*
2  * Copyright © 2010-2012 Intel Corporation
3  * Copyright © 2011-2012 Collabora, Ltd.
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and
6  * its documentation for any purpose is hereby granted without fee, provided
7  * that the above copyright notice appear in all copies and that both that
8  * copyright notice and this permission notice appear in supporting
9  * documentation, and that the name of the copyright holders not be used in
10  * advertising or publicity pertaining to distribution of the software
11  * without specific, written prior permission.  The copyright holders make
12  * no representations about the suitability of this software for any
13  * purpose.  It is provided "as is" without express or implied warranty.
14  *
15  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
16  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
20  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  */
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <stdbool.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <linux/input.h>
30 #include <assert.h>
31 #include <signal.h>
32 #include <math.h>
33 #include <sys/types.h>
34
35 #include <wayland-server.h>
36 #include "compositor.h"
37 #include "desktop-shell-server-protocol.h"
38 #include "input-method-server-protocol.h"
39 #include "workspaces-server-protocol.h"
40 #include "../shared/config-parser.h"
41
42 #define DEFAULT_NUM_WORKSPACES 1
43 #define DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH 200
44
45 enum animation_type {
46         ANIMATION_NONE,
47
48         ANIMATION_ZOOM,
49         ANIMATION_FADE
50 };
51
52 enum fade_type {
53         FADE_IN,
54         FADE_OUT
55 };
56
57 struct focus_state {
58         struct weston_seat *seat;
59         struct workspace *ws;
60         struct weston_surface *keyboard_focus;
61         struct wl_list link;
62         struct wl_listener seat_destroy_listener;
63         struct wl_listener surface_destroy_listener;
64 };
65
66 struct workspace {
67         struct weston_layer layer;
68
69         struct wl_list focus_list;
70         struct wl_listener seat_destroyed_listener;
71 };
72
73 struct input_panel_surface {
74         struct wl_resource resource;
75
76         struct desktop_shell *shell;
77
78         struct wl_list link;
79         struct weston_surface *surface;
80         struct wl_listener surface_destroy_listener;
81
82         struct weston_output *output;
83         uint32_t panel;
84 };
85
86 struct desktop_shell {
87         struct weston_compositor *compositor;
88
89         struct wl_listener idle_listener;
90         struct wl_listener wake_listener;
91         struct wl_listener destroy_listener;
92         struct wl_listener show_input_panel_listener;
93         struct wl_listener hide_input_panel_listener;
94         struct wl_listener update_input_panel_listener;
95
96         struct weston_layer fullscreen_layer;
97         struct weston_layer panel_layer;
98         struct weston_layer background_layer;
99         struct weston_layer lock_layer;
100         struct weston_layer input_panel_layer;
101
102         struct wl_listener pointer_focus_listener;
103         struct weston_surface *grab_surface;
104
105         struct {
106                 struct weston_process process;
107                 struct wl_client *client;
108                 struct wl_resource *desktop_shell;
109
110                 unsigned deathcount;
111                 uint32_t deathstamp;
112         } child;
113
114         bool locked;
115         bool showing_input_panels;
116         bool prepare_event_sent;
117
118         struct {
119                 struct weston_surface *surface;
120                 pixman_box32_t cursor_rectangle;
121         } text_input;
122
123         struct weston_surface *lock_surface;
124         struct wl_listener lock_surface_listener;
125
126         struct {
127                 struct wl_array array;
128                 unsigned int current;
129                 unsigned int num;
130
131                 struct wl_list client_list;
132
133                 struct weston_animation animation;
134                 struct wl_list anim_sticky_list;
135                 int anim_dir;
136                 uint32_t anim_timestamp;
137                 double anim_current;
138                 struct workspace *anim_from;
139                 struct workspace *anim_to;
140         } workspaces;
141
142         struct {
143                 char *path;
144                 int duration;
145                 struct wl_resource *binding;
146                 struct weston_process process;
147                 struct wl_event_source *timer;
148         } screensaver;
149
150         struct {
151                 struct wl_resource *binding;
152                 struct wl_list surfaces;
153         } input_panel;
154
155         struct {
156                 struct weston_surface *surface;
157                 struct weston_surface_animation *animation;
158                 enum fade_type type;
159                 struct wl_event_source *startup_timer;
160         } fade;
161
162         uint32_t binding_modifier;
163         enum animation_type win_animation_type;
164 };
165
166 enum shell_surface_type {
167         SHELL_SURFACE_NONE,
168         SHELL_SURFACE_TOPLEVEL,
169         SHELL_SURFACE_TRANSIENT,
170         SHELL_SURFACE_FULLSCREEN,
171         SHELL_SURFACE_MAXIMIZED,
172         SHELL_SURFACE_POPUP
173 };
174
175 struct ping_timer {
176         struct wl_event_source *source;
177         uint32_t serial;
178 };
179
180 struct shell_surface {
181         struct wl_resource resource;
182
183         struct weston_surface *surface;
184         struct wl_listener surface_destroy_listener;
185         struct weston_surface *parent;
186         struct desktop_shell *shell;
187
188         enum shell_surface_type type, next_type;
189         char *title, *class;
190         int32_t saved_x, saved_y;
191         bool saved_position_valid;
192         bool saved_rotation_valid;
193         int unresponsive;
194
195         struct {
196                 struct weston_transform transform;
197                 struct weston_matrix rotation;
198         } rotation;
199
200         struct {
201                 struct wl_list grab_link;
202                 int32_t x, y;
203                 struct shell_seat *shseat;
204                 uint32_t serial;
205         } popup;
206
207         struct {
208                 int32_t x, y;
209                 uint32_t flags;
210         } transient;
211
212         struct {
213                 enum wl_shell_surface_fullscreen_method type;
214                 struct weston_transform transform; /* matrix from x, y */
215                 uint32_t framerate;
216                 struct weston_surface *black_surface;
217         } fullscreen;
218
219         struct ping_timer *ping_timer;
220
221         struct weston_transform workspace_transform;
222
223         struct weston_output *fullscreen_output;
224         struct weston_output *output;
225         struct wl_list link;
226
227         const struct weston_shell_client *client;
228 };
229
230 struct shell_grab {
231         struct weston_pointer_grab grab;
232         struct shell_surface *shsurf;
233         struct wl_listener shsurf_destroy_listener;
234         struct weston_pointer *pointer;
235 };
236
237 struct weston_move_grab {
238         struct shell_grab base;
239         wl_fixed_t dx, dy;
240 };
241
242 struct rotate_grab {
243         struct shell_grab base;
244         struct weston_matrix rotation;
245         struct {
246                 float x;
247                 float y;
248         } center;
249 };
250
251 struct shell_seat {
252         struct weston_seat *seat;
253         struct wl_listener seat_destroy_listener;
254
255         struct {
256                 struct weston_pointer_grab grab;
257                 struct wl_list surfaces_list;
258                 struct wl_client *client;
259                 int32_t initial_up;
260         } popup_grab;
261 };
262
263 static void
264 activate(struct desktop_shell *shell, struct weston_surface *es,
265          struct weston_seat *seat);
266
267 static struct workspace *
268 get_current_workspace(struct desktop_shell *shell);
269
270 static struct shell_surface *
271 get_shell_surface(struct weston_surface *surface);
272
273 static struct desktop_shell *
274 shell_surface_get_shell(struct shell_surface *shsurf);
275
276 static void
277 surface_rotate(struct shell_surface *surface, struct weston_seat *seat);
278
279 static void
280 shell_fade_startup(struct desktop_shell *shell);
281
282 static bool
283 shell_surface_is_top_fullscreen(struct shell_surface *shsurf)
284 {
285         struct desktop_shell *shell;
286         struct weston_surface *top_fs_es;
287
288         shell = shell_surface_get_shell(shsurf);
289
290         if (wl_list_empty(&shell->fullscreen_layer.surface_list))
291                 return false;
292
293         top_fs_es = container_of(shell->fullscreen_layer.surface_list.next,
294                                  struct weston_surface,
295                                  layer_link);
296         return (shsurf == get_shell_surface(top_fs_es));
297 }
298
299 static void
300 destroy_shell_grab_shsurf(struct wl_listener *listener, void *data)
301 {
302         struct shell_grab *grab;
303
304         grab = container_of(listener, struct shell_grab,
305                             shsurf_destroy_listener);
306
307         grab->shsurf = NULL;
308 }
309
310 static void
311 popup_grab_end(struct weston_pointer *pointer);
312
313 static void
314 shell_grab_start(struct shell_grab *grab,
315                  const struct weston_pointer_grab_interface *interface,
316                  struct shell_surface *shsurf,
317                  struct weston_pointer *pointer,
318                  enum desktop_shell_cursor cursor)
319 {
320         struct desktop_shell *shell = shsurf->shell;
321
322         popup_grab_end(pointer);
323
324         grab->grab.interface = interface;
325         grab->shsurf = shsurf;
326         grab->shsurf_destroy_listener.notify = destroy_shell_grab_shsurf;
327         wl_signal_add(&shsurf->resource.destroy_signal,
328                       &grab->shsurf_destroy_listener);
329
330         grab->pointer = pointer;
331
332         weston_pointer_start_grab(pointer, &grab->grab);
333         desktop_shell_send_grab_cursor(shell->child.desktop_shell, cursor);
334         weston_pointer_set_focus(pointer, shell->grab_surface,
335                                  wl_fixed_from_int(0), wl_fixed_from_int(0));
336 }
337
338 static void
339 shell_grab_end(struct shell_grab *grab)
340 {
341         if (grab->shsurf)
342                 wl_list_remove(&grab->shsurf_destroy_listener.link);
343
344         weston_pointer_end_grab(grab->pointer);
345 }
346
347 static void
348 center_on_output(struct weston_surface *surface,
349                  struct weston_output *output);
350
351 static enum weston_keyboard_modifier
352 get_modifier(char *modifier)
353 {
354         if (!modifier)
355                 return MODIFIER_SUPER;
356
357         if (!strcmp("ctrl", modifier))
358                 return MODIFIER_CTRL;
359         else if (!strcmp("alt", modifier))
360                 return MODIFIER_ALT;
361         else if (!strcmp("super", modifier))
362                 return MODIFIER_SUPER;
363         else
364                 return MODIFIER_SUPER;
365 }
366
367 static enum animation_type
368 get_animation_type(char *animation)
369 {
370         if (!animation)
371                 return ANIMATION_NONE;
372
373         if (!strcmp("zoom", animation))
374                 return ANIMATION_ZOOM;
375         else if (!strcmp("fade", animation))
376                 return ANIMATION_FADE;
377         else
378                 return ANIMATION_NONE;
379 }
380
381 static void
382 shell_configuration(struct desktop_shell *shell, int config_fd)
383 {
384         char *path = NULL;
385         int duration = 60;
386         unsigned int num_workspaces = DEFAULT_NUM_WORKSPACES;
387         char *modifier = NULL;
388         char *win_animation = NULL;
389
390         struct config_key shell_keys[] = {
391                 { "binding-modifier",   CONFIG_KEY_STRING, &modifier },
392                 { "animation",          CONFIG_KEY_STRING, &win_animation},
393                 { "num-workspaces",
394                         CONFIG_KEY_UNSIGNED_INTEGER, &num_workspaces },
395         };
396
397         struct config_key saver_keys[] = {
398                 { "path",       CONFIG_KEY_STRING,  &path },
399                 { "duration",   CONFIG_KEY_INTEGER, &duration },
400         };
401
402         struct config_section cs[] = {
403                 { "shell", shell_keys, ARRAY_LENGTH(shell_keys), NULL },
404                 { "screensaver", saver_keys, ARRAY_LENGTH(saver_keys), NULL },
405         };
406
407         parse_config_file(config_fd, cs, ARRAY_LENGTH(cs), shell);
408
409         shell->screensaver.path = path;
410         shell->screensaver.duration = duration * 1000;
411         shell->binding_modifier = get_modifier(modifier);
412         shell->win_animation_type = get_animation_type(win_animation);
413         shell->workspaces.num = num_workspaces > 0 ? num_workspaces : 1;
414 }
415
416 static void
417 focus_state_destroy(struct focus_state *state)
418 {
419         wl_list_remove(&state->seat_destroy_listener.link);
420         wl_list_remove(&state->surface_destroy_listener.link);
421         free(state);
422 }
423
424 static void
425 focus_state_seat_destroy(struct wl_listener *listener, void *data)
426 {
427         struct focus_state *state = container_of(listener,
428                                                  struct focus_state,
429                                                  seat_destroy_listener);
430
431         wl_list_remove(&state->link);
432         focus_state_destroy(state);
433 }
434
435 static void
436 focus_state_surface_destroy(struct wl_listener *listener, void *data)
437 {
438         struct focus_state *state = container_of(listener,
439                                                  struct focus_state,
440                                                  surface_destroy_listener);
441         struct desktop_shell *shell;
442         struct weston_surface *main_surface;
443         struct weston_surface *surface, *next;
444
445         main_surface = weston_surface_get_main_surface(state->keyboard_focus);
446
447         next = NULL;
448         wl_list_for_each(surface, &state->ws->layer.surface_list, layer_link) {
449                 if (surface == main_surface)
450                         continue;
451
452                 next = surface;
453                 break;
454         }
455
456         /* if the focus was a sub-surface, activate its main surface */
457         if (main_surface != state->keyboard_focus)
458                 next = main_surface;
459
460         if (next) {
461                 shell = state->seat->compositor->shell_interface.shell;
462                 activate(shell, next, state->seat);
463         } else {
464                 wl_list_remove(&state->link);
465                 focus_state_destroy(state);
466         }
467 }
468
469 static struct focus_state *
470 focus_state_create(struct weston_seat *seat, struct workspace *ws)
471 {
472         struct focus_state *state;
473
474         state = malloc(sizeof *state);
475         if (state == NULL)
476                 return NULL;
477
478         state->ws = ws;
479         state->seat = seat;
480         wl_list_insert(&ws->focus_list, &state->link);
481
482         state->seat_destroy_listener.notify = focus_state_seat_destroy;
483         state->surface_destroy_listener.notify = focus_state_surface_destroy;
484         wl_signal_add(&seat->destroy_signal,
485                       &state->seat_destroy_listener);
486         wl_list_init(&state->surface_destroy_listener.link);
487
488         return state;
489 }
490
491 static struct focus_state *
492 ensure_focus_state(struct desktop_shell *shell, struct weston_seat *seat)
493 {
494         struct workspace *ws = get_current_workspace(shell);
495         struct focus_state *state;
496
497         wl_list_for_each(state, &ws->focus_list, link)
498                 if (state->seat == seat)
499                         break;
500
501         if (&state->link == &ws->focus_list)
502                 state = focus_state_create(seat, ws);
503
504         return state;
505 }
506
507 static void
508 restore_focus_state(struct desktop_shell *shell, struct workspace *ws)
509 {
510         struct focus_state *state, *next;
511         struct weston_surface *surface;
512
513         wl_list_for_each_safe(state, next, &ws->focus_list, link) {
514                 surface = state->keyboard_focus;
515
516                 weston_keyboard_set_focus(state->seat->keyboard, surface);
517         }
518 }
519
520 static void
521 replace_focus_state(struct desktop_shell *shell, struct workspace *ws,
522                     struct weston_seat *seat)
523 {
524         struct focus_state *state;
525         struct weston_surface *surface;
526
527         wl_list_for_each(state, &ws->focus_list, link) {
528                 if (state->seat == seat) {
529                         surface = seat->keyboard->focus;
530                         state->keyboard_focus =
531                                 (struct weston_surface *) surface;
532                         return;
533                 }
534         }
535 }
536
537 static void
538 drop_focus_state(struct desktop_shell *shell, struct workspace *ws,
539                  struct weston_surface *surface)
540 {
541         struct focus_state *state;
542
543         wl_list_for_each(state, &ws->focus_list, link)
544                 if (state->keyboard_focus == surface)
545                         state->keyboard_focus = NULL;
546 }
547
548 static void
549 workspace_destroy(struct workspace *ws)
550 {
551         struct focus_state *state, *next;
552
553         wl_list_for_each_safe(state, next, &ws->focus_list, link)
554                 focus_state_destroy(state);
555
556         free(ws);
557 }
558
559 static void
560 seat_destroyed(struct wl_listener *listener, void *data)
561 {
562         struct weston_seat *seat = data;
563         struct focus_state *state, *next;
564         struct workspace *ws = container_of(listener,
565                                             struct workspace,
566                                             seat_destroyed_listener);
567
568         wl_list_for_each_safe(state, next, &ws->focus_list, link)
569                 if (state->seat == seat)
570                         wl_list_remove(&state->link);
571 }
572
573 static struct workspace *
574 workspace_create(void)
575 {
576         struct workspace *ws = malloc(sizeof *ws);
577         if (ws == NULL)
578                 return NULL;
579
580         weston_layer_init(&ws->layer, NULL);
581
582         wl_list_init(&ws->focus_list);
583         wl_list_init(&ws->seat_destroyed_listener.link);
584         ws->seat_destroyed_listener.notify = seat_destroyed;
585
586         return ws;
587 }
588
589 static int
590 workspace_is_empty(struct workspace *ws)
591 {
592         return wl_list_empty(&ws->layer.surface_list);
593 }
594
595 static struct workspace *
596 get_workspace(struct desktop_shell *shell, unsigned int index)
597 {
598         struct workspace **pws = shell->workspaces.array.data;
599         assert(index < shell->workspaces.num);
600         pws += index;
601         return *pws;
602 }
603
604 static struct workspace *
605 get_current_workspace(struct desktop_shell *shell)
606 {
607         return get_workspace(shell, shell->workspaces.current);
608 }
609
610 static void
611 activate_workspace(struct desktop_shell *shell, unsigned int index)
612 {
613         struct workspace *ws;
614
615         ws = get_workspace(shell, index);
616         wl_list_insert(&shell->panel_layer.link, &ws->layer.link);
617
618         shell->workspaces.current = index;
619 }
620
621 static unsigned int
622 get_output_height(struct weston_output *output)
623 {
624         return abs(output->region.extents.y1 - output->region.extents.y2);
625 }
626
627 static void
628 surface_translate(struct weston_surface *surface, double d)
629 {
630         struct shell_surface *shsurf = get_shell_surface(surface);
631         struct weston_transform *transform;
632
633         transform = &shsurf->workspace_transform;
634         if (wl_list_empty(&transform->link))
635                 wl_list_insert(surface->geometry.transformation_list.prev,
636                                &shsurf->workspace_transform.link);
637
638         weston_matrix_init(&shsurf->workspace_transform.matrix);
639         weston_matrix_translate(&shsurf->workspace_transform.matrix,
640                                 0.0, d, 0.0);
641         weston_surface_geometry_dirty(surface);
642 }
643
644 static void
645 workspace_translate_out(struct workspace *ws, double fraction)
646 {
647         struct weston_surface *surface;
648         unsigned int height;
649         double d;
650
651         wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
652                 height = get_output_height(surface->output);
653                 d = height * fraction;
654
655                 surface_translate(surface, d);
656         }
657 }
658
659 static void
660 workspace_translate_in(struct workspace *ws, double fraction)
661 {
662         struct weston_surface *surface;
663         unsigned int height;
664         double d;
665
666         wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
667                 height = get_output_height(surface->output);
668
669                 if (fraction > 0)
670                         d = -(height - height * fraction);
671                 else
672                         d = height + height * fraction;
673
674                 surface_translate(surface, d);
675         }
676 }
677
678 static void
679 broadcast_current_workspace_state(struct desktop_shell *shell)
680 {
681         struct wl_resource *resource;
682
683         wl_list_for_each(resource, &shell->workspaces.client_list, link)
684                 workspace_manager_send_state(resource,
685                                              shell->workspaces.current,
686                                              shell->workspaces.num);
687 }
688
689 static void
690 reverse_workspace_change_animation(struct desktop_shell *shell,
691                                    unsigned int index,
692                                    struct workspace *from,
693                                    struct workspace *to)
694 {
695         shell->workspaces.current = index;
696
697         shell->workspaces.anim_to = to;
698         shell->workspaces.anim_from = from;
699         shell->workspaces.anim_dir = -1 * shell->workspaces.anim_dir;
700         shell->workspaces.anim_timestamp = 0;
701
702         weston_compositor_schedule_repaint(shell->compositor);
703 }
704
705 static void
706 workspace_deactivate_transforms(struct workspace *ws)
707 {
708         struct weston_surface *surface;
709         struct shell_surface *shsurf;
710
711         wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
712                 shsurf = get_shell_surface(surface);
713                 if (!wl_list_empty(&shsurf->workspace_transform.link)) {
714                         wl_list_remove(&shsurf->workspace_transform.link);
715                         wl_list_init(&shsurf->workspace_transform.link);
716                 }
717                 weston_surface_geometry_dirty(surface);
718         }
719 }
720
721 static void
722 finish_workspace_change_animation(struct desktop_shell *shell,
723                                   struct workspace *from,
724                                   struct workspace *to)
725 {
726         weston_compositor_schedule_repaint(shell->compositor);
727
728         wl_list_remove(&shell->workspaces.animation.link);
729         workspace_deactivate_transforms(from);
730         workspace_deactivate_transforms(to);
731         shell->workspaces.anim_to = NULL;
732
733         wl_list_remove(&shell->workspaces.anim_from->layer.link);
734 }
735
736 static void
737 animate_workspace_change_frame(struct weston_animation *animation,
738                                struct weston_output *output, uint32_t msecs)
739 {
740         struct desktop_shell *shell =
741                 container_of(animation, struct desktop_shell,
742                              workspaces.animation);
743         struct workspace *from = shell->workspaces.anim_from;
744         struct workspace *to = shell->workspaces.anim_to;
745         uint32_t t;
746         double x, y;
747
748         if (workspace_is_empty(from) && workspace_is_empty(to)) {
749                 finish_workspace_change_animation(shell, from, to);
750                 return;
751         }
752
753         if (shell->workspaces.anim_timestamp == 0) {
754                 if (shell->workspaces.anim_current == 0.0)
755                         shell->workspaces.anim_timestamp = msecs;
756                 else
757                         shell->workspaces.anim_timestamp =
758                                 msecs -
759                                 /* Invers of movement function 'y' below. */
760                                 (asin(1.0 - shell->workspaces.anim_current) *
761                                  DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH *
762                                  M_2_PI);
763         }
764
765         t = msecs - shell->workspaces.anim_timestamp;
766
767         /*
768          * x = [0, π/2]
769          * y(x) = sin(x)
770          */
771         x = t * (1.0/DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH) * M_PI_2;
772         y = sin(x);
773
774         if (t < DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH) {
775                 weston_compositor_schedule_repaint(shell->compositor);
776
777                 workspace_translate_out(from, shell->workspaces.anim_dir * y);
778                 workspace_translate_in(to, shell->workspaces.anim_dir * y);
779                 shell->workspaces.anim_current = y;
780
781                 weston_compositor_schedule_repaint(shell->compositor);
782         }
783         else
784                 finish_workspace_change_animation(shell, from, to);
785 }
786
787 static void
788 animate_workspace_change(struct desktop_shell *shell,
789                          unsigned int index,
790                          struct workspace *from,
791                          struct workspace *to)
792 {
793         struct weston_output *output;
794
795         int dir;
796
797         if (index > shell->workspaces.current)
798                 dir = -1;
799         else
800                 dir = 1;
801
802         shell->workspaces.current = index;
803
804         shell->workspaces.anim_dir = dir;
805         shell->workspaces.anim_from = from;
806         shell->workspaces.anim_to = to;
807         shell->workspaces.anim_current = 0.0;
808         shell->workspaces.anim_timestamp = 0;
809
810         output = container_of(shell->compositor->output_list.next,
811                               struct weston_output, link);
812         wl_list_insert(&output->animation_list,
813                        &shell->workspaces.animation.link);
814
815         wl_list_insert(from->layer.link.prev, &to->layer.link);
816
817         workspace_translate_in(to, 0);
818
819         restore_focus_state(shell, to);
820
821         weston_compositor_schedule_repaint(shell->compositor);
822 }
823
824 static void
825 update_workspace(struct desktop_shell *shell, unsigned int index,
826                  struct workspace *from, struct workspace *to)
827 {
828         shell->workspaces.current = index;
829         wl_list_insert(&from->layer.link, &to->layer.link);
830         wl_list_remove(&from->layer.link);
831 }
832
833 static void
834 change_workspace(struct desktop_shell *shell, unsigned int index)
835 {
836         struct workspace *from;
837         struct workspace *to;
838
839         if (index == shell->workspaces.current)
840                 return;
841
842         /* Don't change workspace when there is any fullscreen surfaces. */
843         if (!wl_list_empty(&shell->fullscreen_layer.surface_list))
844                 return;
845
846         from = get_current_workspace(shell);
847         to = get_workspace(shell, index);
848
849         if (shell->workspaces.anim_from == to &&
850             shell->workspaces.anim_to == from) {
851                 restore_focus_state(shell, to);
852                 reverse_workspace_change_animation(shell, index, from, to);
853                 broadcast_current_workspace_state(shell);
854                 return;
855         }
856
857         if (shell->workspaces.anim_to != NULL)
858                 finish_workspace_change_animation(shell,
859                                                   shell->workspaces.anim_from,
860                                                   shell->workspaces.anim_to);
861
862         restore_focus_state(shell, to);
863
864         if (workspace_is_empty(to) && workspace_is_empty(from))
865                 update_workspace(shell, index, from, to);
866         else
867                 animate_workspace_change(shell, index, from, to);
868
869         broadcast_current_workspace_state(shell);
870 }
871
872 static bool
873 workspace_has_only(struct workspace *ws, struct weston_surface *surface)
874 {
875         struct wl_list *list = &ws->layer.surface_list;
876         struct wl_list *e;
877
878         if (wl_list_empty(list))
879                 return false;
880
881         e = list->next;
882
883         if (e->next != list)
884                 return false;
885
886         return container_of(e, struct weston_surface, layer_link) == surface;
887 }
888
889 static void
890 move_surface_to_workspace(struct desktop_shell *shell,
891                           struct weston_surface *surface,
892                           uint32_t workspace)
893 {
894         struct workspace *from;
895         struct workspace *to;
896         struct weston_seat *seat;
897         struct weston_surface *focus;
898
899         assert(weston_surface_get_main_surface(surface) == surface);
900
901         if (workspace == shell->workspaces.current)
902                 return;
903
904         if (workspace >= shell->workspaces.num)
905                 workspace = shell->workspaces.num - 1;
906
907         from = get_current_workspace(shell);
908         to = get_workspace(shell, workspace);
909
910         wl_list_remove(&surface->layer_link);
911         wl_list_insert(&to->layer.surface_list, &surface->layer_link);
912
913         drop_focus_state(shell, from, surface);
914         wl_list_for_each(seat, &shell->compositor->seat_list, link) {
915                 if (!seat->keyboard)
916                         continue;
917
918                 focus = weston_surface_get_main_surface(seat->keyboard->focus);
919                 if (focus == surface)
920                         weston_keyboard_set_focus(seat->keyboard, NULL);
921         }
922
923         weston_surface_damage_below(surface);
924 }
925
926 static void
927 take_surface_to_workspace_by_seat(struct desktop_shell *shell,
928                                   struct weston_seat *seat,
929                                   unsigned int index)
930 {
931         struct weston_surface *surface;
932         struct shell_surface *shsurf;
933         struct workspace *from;
934         struct workspace *to;
935         struct focus_state *state;
936
937         surface = weston_surface_get_main_surface(seat->keyboard->focus);
938         if (surface == NULL ||
939             index == shell->workspaces.current)
940                 return;
941
942         from = get_current_workspace(shell);
943         to = get_workspace(shell, index);
944
945         wl_list_remove(&surface->layer_link);
946         wl_list_insert(&to->layer.surface_list, &surface->layer_link);
947
948         replace_focus_state(shell, to, seat);
949         drop_focus_state(shell, from, surface);
950
951         if (shell->workspaces.anim_from == to &&
952             shell->workspaces.anim_to == from) {
953                 wl_list_remove(&to->layer.link);
954                 wl_list_insert(from->layer.link.prev, &to->layer.link);
955
956                 reverse_workspace_change_animation(shell, index, from, to);
957                 broadcast_current_workspace_state(shell);
958
959                 return;
960         }
961
962         if (shell->workspaces.anim_to != NULL)
963                 finish_workspace_change_animation(shell,
964                                                   shell->workspaces.anim_from,
965                                                   shell->workspaces.anim_to);
966
967         if (workspace_is_empty(from) &&
968             workspace_has_only(to, surface))
969                 update_workspace(shell, index, from, to);
970         else {
971                 shsurf = get_shell_surface(surface);
972                 if (wl_list_empty(&shsurf->workspace_transform.link))
973                         wl_list_insert(&shell->workspaces.anim_sticky_list,
974                                        &shsurf->workspace_transform.link);
975
976                 animate_workspace_change(shell, index, from, to);
977         }
978
979         broadcast_current_workspace_state(shell);
980
981         state = ensure_focus_state(shell, seat);
982         if (state != NULL)
983                 state->keyboard_focus = surface;
984 }
985
986 static void
987 workspace_manager_move_surface(struct wl_client *client,
988                                struct wl_resource *resource,
989                                struct wl_resource *surface_resource,
990                                uint32_t workspace)
991 {
992         struct desktop_shell *shell = resource->data;
993         struct weston_surface *surface =
994                 (struct weston_surface *) surface_resource;
995         struct weston_surface *main_surface;
996
997         main_surface = weston_surface_get_main_surface(surface);
998         move_surface_to_workspace(shell, main_surface, workspace);
999 }
1000
1001 static const struct workspace_manager_interface workspace_manager_implementation = {
1002         workspace_manager_move_surface,
1003 };
1004
1005 static void
1006 unbind_resource(struct wl_resource *resource)
1007 {
1008         wl_list_remove(&resource->link);
1009         free(resource);
1010 }
1011
1012 static void
1013 bind_workspace_manager(struct wl_client *client,
1014                        void *data, uint32_t version, uint32_t id)
1015 {
1016         struct desktop_shell *shell = data;
1017         struct wl_resource *resource;
1018
1019         resource = wl_client_add_object(client, &workspace_manager_interface,
1020                                         &workspace_manager_implementation,
1021                                         id, shell);
1022
1023         if (resource == NULL) {
1024                 weston_log("couldn't add workspace manager object");
1025                 return;
1026         }
1027
1028         resource->destroy = unbind_resource;
1029         wl_list_insert(&shell->workspaces.client_list, &resource->link);
1030
1031         workspace_manager_send_state(resource,
1032                                      shell->workspaces.current,
1033                                      shell->workspaces.num);
1034 }
1035
1036 static void
1037 noop_grab_focus(struct weston_pointer_grab *grab)
1038 {
1039 }
1040
1041 static void
1042 move_grab_motion(struct weston_pointer_grab *grab, uint32_t time)
1043 {
1044         struct weston_move_grab *move = (struct weston_move_grab *) grab;
1045         struct weston_pointer *pointer = grab->pointer;
1046         struct shell_surface *shsurf = move->base.shsurf;
1047         struct weston_surface *es;
1048         int dx = wl_fixed_to_int(pointer->x + move->dx);
1049         int dy = wl_fixed_to_int(pointer->y + move->dy);
1050
1051         if (!shsurf)
1052                 return;
1053
1054         es = shsurf->surface;
1055
1056         weston_surface_configure(es, dx, dy,
1057                                  es->geometry.width, es->geometry.height);
1058
1059         weston_compositor_schedule_repaint(es->compositor);
1060 }
1061
1062 static void
1063 move_grab_button(struct weston_pointer_grab *grab,
1064                  uint32_t time, uint32_t button, uint32_t state_w)
1065 {
1066         struct shell_grab *shell_grab = container_of(grab, struct shell_grab,
1067                                                     grab);
1068         struct weston_pointer *pointer = grab->pointer;
1069         enum wl_pointer_button_state state = state_w;
1070
1071         if (pointer->button_count == 0 &&
1072             state == WL_POINTER_BUTTON_STATE_RELEASED) {
1073                 shell_grab_end(shell_grab);
1074                 free(grab);
1075         }
1076 }
1077
1078 static const struct weston_pointer_grab_interface move_grab_interface = {
1079         noop_grab_focus,
1080         move_grab_motion,
1081         move_grab_button,
1082 };
1083
1084 static int
1085 surface_move(struct shell_surface *shsurf, struct weston_seat *seat)
1086 {
1087         struct weston_move_grab *move;
1088
1089         if (!shsurf)
1090                 return -1;
1091
1092         if (shsurf->type == SHELL_SURFACE_FULLSCREEN)
1093                 return 0;
1094
1095         move = malloc(sizeof *move);
1096         if (!move)
1097                 return -1;
1098
1099         move->dx = wl_fixed_from_double(shsurf->surface->geometry.x) -
1100                         seat->pointer->grab_x;
1101         move->dy = wl_fixed_from_double(shsurf->surface->geometry.y) -
1102                         seat->pointer->grab_y;
1103
1104         shell_grab_start(&move->base, &move_grab_interface, shsurf,
1105                          seat->pointer, DESKTOP_SHELL_CURSOR_MOVE);
1106
1107         return 0;
1108 }
1109
1110 static void
1111 shell_surface_move(struct wl_client *client, struct wl_resource *resource,
1112                    struct wl_resource *seat_resource, uint32_t serial)
1113 {
1114         struct weston_seat *seat = seat_resource->data;
1115         struct shell_surface *shsurf = resource->data;
1116         struct weston_surface *surface;
1117
1118         surface = weston_surface_get_main_surface(seat->pointer->focus);
1119         if (seat->pointer->button_count == 0 ||
1120             seat->pointer->grab_serial != serial ||
1121             surface != shsurf->surface)
1122                 return;
1123
1124         if (surface_move(shsurf, seat) < 0)
1125                 wl_resource_post_no_memory(resource);
1126 }
1127
1128 struct weston_resize_grab {
1129         struct shell_grab base;
1130         uint32_t edges;
1131         int32_t width, height;
1132 };
1133
1134 static void
1135 resize_grab_motion(struct weston_pointer_grab *grab, uint32_t time)
1136 {
1137         struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
1138         struct weston_pointer *pointer = grab->pointer;
1139         struct shell_surface *shsurf = resize->base.shsurf;
1140         int32_t width, height;
1141         wl_fixed_t from_x, from_y;
1142         wl_fixed_t to_x, to_y;
1143
1144         if (!shsurf)
1145                 return;
1146
1147         weston_surface_from_global_fixed(shsurf->surface,
1148                                          pointer->grab_x, pointer->grab_y,
1149                                          &from_x, &from_y);
1150         weston_surface_from_global_fixed(shsurf->surface,
1151                                          pointer->x, pointer->y, &to_x, &to_y);
1152
1153         width = resize->width;
1154         if (resize->edges & WL_SHELL_SURFACE_RESIZE_LEFT) {
1155                 width += wl_fixed_to_int(from_x - to_x);
1156         } else if (resize->edges & WL_SHELL_SURFACE_RESIZE_RIGHT) {
1157                 width += wl_fixed_to_int(to_x - from_x);
1158         }
1159
1160         height = resize->height;
1161         if (resize->edges & WL_SHELL_SURFACE_RESIZE_TOP) {
1162                 height += wl_fixed_to_int(from_y - to_y);
1163         } else if (resize->edges & WL_SHELL_SURFACE_RESIZE_BOTTOM) {
1164                 height += wl_fixed_to_int(to_y - from_y);
1165         }
1166
1167         shsurf->client->send_configure(shsurf->surface,
1168                                        resize->edges, width, height);
1169 }
1170
1171 static void
1172 send_configure(struct weston_surface *surface,
1173                uint32_t edges, int32_t width, int32_t height)
1174 {
1175         struct shell_surface *shsurf = get_shell_surface(surface);
1176
1177         wl_shell_surface_send_configure(&shsurf->resource,
1178                                         edges, width, height);
1179 }
1180
1181 static const struct weston_shell_client shell_client = {
1182         send_configure
1183 };
1184
1185 static void
1186 resize_grab_button(struct weston_pointer_grab *grab,
1187                    uint32_t time, uint32_t button, uint32_t state_w)
1188 {
1189         struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
1190         struct weston_pointer *pointer = grab->pointer;
1191         enum wl_pointer_button_state state = state_w;
1192
1193         if (pointer->button_count == 0 &&
1194             state == WL_POINTER_BUTTON_STATE_RELEASED) {
1195                 shell_grab_end(&resize->base);
1196                 free(grab);
1197         }
1198 }
1199
1200 static const struct weston_pointer_grab_interface resize_grab_interface = {
1201         noop_grab_focus,
1202         resize_grab_motion,
1203         resize_grab_button,
1204 };
1205
1206 /*
1207  * Returns the bounding box of a surface and all its sub-surfaces,
1208  * in the surface coordinates system. */
1209 static void
1210 surface_subsurfaces_boundingbox(struct weston_surface *surface, int32_t *x,
1211                                 int32_t *y, int32_t *w, int32_t *h) {
1212         pixman_region32_t region;
1213         pixman_box32_t *box;
1214         struct weston_subsurface *subsurface;
1215
1216         pixman_region32_init_rect(&region, 0, 0,
1217                                   surface->geometry.width,
1218                                   surface->geometry.height);
1219
1220         wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) {
1221                 pixman_region32_union_rect(&region, &region,
1222                                            subsurface->position.x,
1223                                            subsurface->position.y,
1224                                            subsurface->surface->geometry.width,
1225                                            subsurface->surface->geometry.height);
1226         }
1227
1228         box = pixman_region32_extents(&region);
1229         if (x)
1230                 *x = box->x1;
1231         if (y)
1232                 *y = box->y1;
1233         if (w)
1234                 *w = box->x2 - box->x1;
1235         if (h)
1236                 *h = box->y2 - box->y1;
1237
1238         pixman_region32_fini(&region);
1239 }
1240
1241 static int
1242 surface_resize(struct shell_surface *shsurf,
1243                struct weston_seat *seat, uint32_t edges)
1244 {
1245         struct weston_resize_grab *resize;
1246
1247         if (shsurf->type == SHELL_SURFACE_FULLSCREEN ||
1248             shsurf->type == SHELL_SURFACE_MAXIMIZED)
1249                 return 0;
1250
1251         if (edges == 0 || edges > 15 ||
1252             (edges & 3) == 3 || (edges & 12) == 12)
1253                 return 0;
1254
1255         resize = malloc(sizeof *resize);
1256         if (!resize)
1257                 return -1;
1258
1259         resize->edges = edges;
1260         surface_subsurfaces_boundingbox(shsurf->surface, NULL, NULL,
1261                                         &resize->width, &resize->height);
1262
1263         shell_grab_start(&resize->base, &resize_grab_interface, shsurf,
1264                          seat->pointer, edges);
1265
1266         return 0;
1267 }
1268
1269 static void
1270 shell_surface_resize(struct wl_client *client, struct wl_resource *resource,
1271                      struct wl_resource *seat_resource, uint32_t serial,
1272                      uint32_t edges)
1273 {
1274         struct weston_seat *seat = seat_resource->data;
1275         struct shell_surface *shsurf = resource->data;
1276         struct weston_surface *surface;
1277
1278         if (shsurf->type == SHELL_SURFACE_FULLSCREEN)
1279                 return;
1280
1281         surface = weston_surface_get_main_surface(seat->pointer->focus);
1282         if (seat->pointer->button_count == 0 ||
1283             seat->pointer->grab_serial != serial ||
1284             surface != shsurf->surface)
1285                 return;
1286
1287         if (surface_resize(shsurf, seat, edges) < 0)
1288                 wl_resource_post_no_memory(resource);
1289 }
1290
1291 static void
1292 busy_cursor_grab_focus(struct weston_pointer_grab *base)
1293 {
1294         struct shell_grab *grab = (struct shell_grab *) base;
1295         struct weston_pointer *pointer = base->pointer;
1296         struct weston_surface *surface;
1297         wl_fixed_t sx, sy;
1298
1299         surface = weston_compositor_pick_surface(pointer->seat->compositor,
1300                                                  pointer->x, pointer->y,
1301                                                  &sx, &sy);
1302
1303         if (!grab->shsurf || grab->shsurf->surface != surface) {
1304                 shell_grab_end(grab);
1305                 free(grab);
1306         }
1307 }
1308
1309 static void
1310 busy_cursor_grab_motion(struct weston_pointer_grab *grab, uint32_t time)
1311 {
1312 }
1313
1314 static void
1315 busy_cursor_grab_button(struct weston_pointer_grab *base,
1316                         uint32_t time, uint32_t button, uint32_t state)
1317 {
1318         struct shell_grab *grab = (struct shell_grab *) base;
1319         struct shell_surface *shsurf = grab->shsurf;
1320         struct weston_seat *seat = grab->grab.pointer->seat;
1321
1322         if (shsurf && button == BTN_LEFT && state) {
1323                 activate(shsurf->shell, shsurf->surface, seat);
1324                 surface_move(shsurf, seat);
1325         } else if (shsurf && button == BTN_RIGHT && state) {
1326                 activate(shsurf->shell, shsurf->surface, seat);
1327                 surface_rotate(shsurf, seat);
1328         }
1329 }
1330
1331 static const struct weston_pointer_grab_interface busy_cursor_grab_interface = {
1332         busy_cursor_grab_focus,
1333         busy_cursor_grab_motion,
1334         busy_cursor_grab_button,
1335 };
1336
1337 static void
1338 set_busy_cursor(struct shell_surface *shsurf, struct weston_pointer *pointer)
1339 {
1340         struct shell_grab *grab;
1341
1342         grab = malloc(sizeof *grab);
1343         if (!grab)
1344                 return;
1345
1346         shell_grab_start(grab, &busy_cursor_grab_interface, shsurf, pointer,
1347                          DESKTOP_SHELL_CURSOR_BUSY);
1348 }
1349
1350 static void
1351 end_busy_cursor(struct shell_surface *shsurf, struct weston_pointer *pointer)
1352 {
1353         struct shell_grab *grab = (struct shell_grab *) pointer->grab;
1354
1355         if (grab->grab.interface == &busy_cursor_grab_interface &&
1356             grab->shsurf == shsurf) {
1357                 shell_grab_end(grab);
1358                 free(grab);
1359         }
1360 }
1361
1362 static void
1363 ping_timer_destroy(struct shell_surface *shsurf)
1364 {
1365         if (!shsurf || !shsurf->ping_timer)
1366                 return;
1367
1368         if (shsurf->ping_timer->source)
1369                 wl_event_source_remove(shsurf->ping_timer->source);
1370
1371         free(shsurf->ping_timer);
1372         shsurf->ping_timer = NULL;
1373 }
1374
1375 static int
1376 ping_timeout_handler(void *data)
1377 {
1378         struct shell_surface *shsurf = data;
1379         struct weston_seat *seat;
1380
1381         /* Client is not responding */
1382         shsurf->unresponsive = 1;
1383
1384         wl_list_for_each(seat, &shsurf->surface->compositor->seat_list, link)
1385                 if (seat->pointer->focus == shsurf->surface)
1386                         set_busy_cursor(shsurf, seat->pointer);
1387
1388         return 1;
1389 }
1390
1391 static void
1392 ping_handler(struct weston_surface *surface, uint32_t serial)
1393 {
1394         struct shell_surface *shsurf = get_shell_surface(surface);
1395         struct wl_event_loop *loop;
1396         int ping_timeout = 200;
1397
1398         if (!shsurf)
1399                 return;
1400         if (!shsurf->resource.client)
1401                 return;
1402
1403         if (shsurf->surface == shsurf->shell->grab_surface)
1404                 return;
1405
1406         if (!shsurf->ping_timer) {
1407                 shsurf->ping_timer = malloc(sizeof *shsurf->ping_timer);
1408                 if (!shsurf->ping_timer)
1409                         return;
1410
1411                 shsurf->ping_timer->serial = serial;
1412                 loop = wl_display_get_event_loop(surface->compositor->wl_display);
1413                 shsurf->ping_timer->source =
1414                         wl_event_loop_add_timer(loop, ping_timeout_handler, shsurf);
1415                 wl_event_source_timer_update(shsurf->ping_timer->source, ping_timeout);
1416
1417                 wl_shell_surface_send_ping(&shsurf->resource, serial);
1418         }
1419 }
1420
1421 static void
1422 handle_pointer_focus(struct wl_listener *listener, void *data)
1423 {
1424         struct weston_pointer *pointer = data;
1425         struct weston_surface *surface =
1426                 (struct weston_surface *) pointer->focus;
1427         struct weston_compositor *compositor;
1428         struct shell_surface *shsurf;
1429         uint32_t serial;
1430
1431         if (!surface)
1432                 return;
1433
1434         compositor = surface->compositor;
1435         shsurf = get_shell_surface(surface);
1436
1437         if (shsurf && shsurf->unresponsive) {
1438                 set_busy_cursor(shsurf, pointer);
1439         } else {
1440                 serial = wl_display_next_serial(compositor->wl_display);
1441                 ping_handler(surface, serial);
1442         }
1443 }
1444
1445 static void
1446 create_pointer_focus_listener(struct weston_seat *seat)
1447 {
1448         struct wl_listener *listener;
1449
1450         if (!seat->pointer)
1451                 return;
1452
1453         listener = malloc(sizeof *listener);
1454         listener->notify = handle_pointer_focus;
1455         wl_signal_add(&seat->pointer->focus_signal, listener);
1456 }
1457
1458 static void
1459 shell_surface_pong(struct wl_client *client, struct wl_resource *resource,
1460                                                         uint32_t serial)
1461 {
1462         struct shell_surface *shsurf = resource->data;
1463         struct weston_seat *seat;
1464         struct weston_compositor *ec = shsurf->surface->compositor;
1465
1466         if (shsurf->ping_timer == NULL)
1467                 /* Just ignore unsolicited pong. */
1468                 return;
1469
1470         if (shsurf->ping_timer->serial == serial) {
1471                 shsurf->unresponsive = 0;
1472                 wl_list_for_each(seat, &ec->seat_list, link) {
1473                         if(seat->pointer)
1474                                 end_busy_cursor(shsurf, seat->pointer);
1475                 }
1476                 ping_timer_destroy(shsurf);
1477         }
1478 }
1479
1480 static void
1481 shell_surface_set_title(struct wl_client *client,
1482                         struct wl_resource *resource, const char *title)
1483 {
1484         struct shell_surface *shsurf = resource->data;
1485
1486         free(shsurf->title);
1487         shsurf->title = strdup(title);
1488 }
1489
1490 static void
1491 shell_surface_set_class(struct wl_client *client,
1492                         struct wl_resource *resource, const char *class)
1493 {
1494         struct shell_surface *shsurf = resource->data;
1495
1496         free(shsurf->class);
1497         shsurf->class = strdup(class);
1498 }
1499
1500 static struct weston_output *
1501 get_default_output(struct weston_compositor *compositor)
1502 {
1503         return container_of(compositor->output_list.next,
1504                             struct weston_output, link);
1505 }
1506
1507 static void
1508 shell_unset_fullscreen(struct shell_surface *shsurf)
1509 {
1510         struct workspace *ws;
1511         /* undo all fullscreen things here */
1512         if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
1513             shell_surface_is_top_fullscreen(shsurf)) {
1514                 weston_output_switch_mode(shsurf->fullscreen_output,
1515                                           shsurf->fullscreen_output->origin);
1516         }
1517         shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
1518         shsurf->fullscreen.framerate = 0;
1519         wl_list_remove(&shsurf->fullscreen.transform.link);
1520         wl_list_init(&shsurf->fullscreen.transform.link);
1521         if (shsurf->fullscreen.black_surface)
1522                 weston_surface_destroy(shsurf->fullscreen.black_surface);
1523         shsurf->fullscreen.black_surface = NULL;
1524         shsurf->fullscreen_output = NULL;
1525         weston_surface_set_position(shsurf->surface,
1526                                     shsurf->saved_x, shsurf->saved_y);
1527         if (shsurf->saved_rotation_valid) {
1528                 wl_list_insert(&shsurf->surface->geometry.transformation_list,
1529                                &shsurf->rotation.transform.link);
1530                 shsurf->saved_rotation_valid = false;
1531         }
1532
1533         ws = get_current_workspace(shsurf->shell);
1534         wl_list_remove(&shsurf->surface->layer_link);
1535         wl_list_insert(&ws->layer.surface_list, &shsurf->surface->layer_link);
1536 }
1537
1538 static void
1539 shell_unset_maximized(struct shell_surface *shsurf)
1540 {
1541         struct workspace *ws;
1542         /* undo all maximized things here */
1543         shsurf->output = get_default_output(shsurf->surface->compositor);
1544         weston_surface_set_position(shsurf->surface,
1545                                     shsurf->saved_x,
1546                                     shsurf->saved_y);
1547
1548         if (shsurf->saved_rotation_valid) {
1549                 wl_list_insert(&shsurf->surface->geometry.transformation_list,
1550                                                    &shsurf->rotation.transform.link);
1551                 shsurf->saved_rotation_valid = false;
1552         }
1553
1554         ws = get_current_workspace(shsurf->shell);
1555         wl_list_remove(&shsurf->surface->layer_link);
1556         wl_list_insert(&ws->layer.surface_list, &shsurf->surface->layer_link);
1557 }
1558
1559 static int
1560 reset_shell_surface_type(struct shell_surface *surface)
1561 {
1562         switch (surface->type) {
1563         case SHELL_SURFACE_FULLSCREEN:
1564                 shell_unset_fullscreen(surface);
1565                 break;
1566         case SHELL_SURFACE_MAXIMIZED:
1567                 shell_unset_maximized(surface);
1568                 break;
1569         case SHELL_SURFACE_NONE:
1570         case SHELL_SURFACE_TOPLEVEL:
1571         case SHELL_SURFACE_TRANSIENT:
1572         case SHELL_SURFACE_POPUP:
1573                 break;
1574         }
1575
1576         surface->type = SHELL_SURFACE_NONE;
1577         return 0;
1578 }
1579
1580 static void
1581 set_surface_type(struct shell_surface *shsurf)
1582 {
1583         struct weston_surface *surface = shsurf->surface;
1584         struct weston_surface *pes = shsurf->parent;
1585
1586         reset_shell_surface_type(shsurf);
1587
1588         shsurf->type = shsurf->next_type;
1589         shsurf->next_type = SHELL_SURFACE_NONE;
1590
1591         switch (shsurf->type) {
1592         case SHELL_SURFACE_TOPLEVEL:
1593                 break;
1594         case SHELL_SURFACE_TRANSIENT:
1595                 weston_surface_set_position(surface,
1596                                 pes->geometry.x + shsurf->transient.x,
1597                                 pes->geometry.y + shsurf->transient.y);
1598                 break;
1599
1600         case SHELL_SURFACE_MAXIMIZED:
1601         case SHELL_SURFACE_FULLSCREEN:
1602                 shsurf->saved_x = surface->geometry.x;
1603                 shsurf->saved_y = surface->geometry.y;
1604                 shsurf->saved_position_valid = true;
1605
1606                 if (!wl_list_empty(&shsurf->rotation.transform.link)) {
1607                         wl_list_remove(&shsurf->rotation.transform.link);
1608                         wl_list_init(&shsurf->rotation.transform.link);
1609                         weston_surface_geometry_dirty(shsurf->surface);
1610                         shsurf->saved_rotation_valid = true;
1611                 }
1612                 break;
1613
1614         default:
1615                 break;
1616         }
1617 }
1618
1619 static void
1620 set_toplevel(struct shell_surface *shsurf)
1621 {
1622        shsurf->next_type = SHELL_SURFACE_TOPLEVEL;
1623 }
1624
1625 static void
1626 shell_surface_set_toplevel(struct wl_client *client,
1627                            struct wl_resource *resource)
1628 {
1629         struct shell_surface *surface = resource->data;
1630
1631         set_toplevel(surface);
1632 }
1633
1634 static void
1635 set_transient(struct shell_surface *shsurf,
1636               struct weston_surface *parent, int x, int y, uint32_t flags)
1637 {
1638         /* assign to parents output */
1639         shsurf->parent = parent;
1640         shsurf->transient.x = x;
1641         shsurf->transient.y = y;
1642         shsurf->transient.flags = flags;
1643         shsurf->next_type = SHELL_SURFACE_TRANSIENT;
1644 }
1645
1646 static void
1647 shell_surface_set_transient(struct wl_client *client,
1648                             struct wl_resource *resource,
1649                             struct wl_resource *parent_resource,
1650                             int x, int y, uint32_t flags)
1651 {
1652         struct shell_surface *shsurf = resource->data;
1653         struct weston_surface *parent = parent_resource->data;
1654
1655         set_transient(shsurf, parent, x, y, flags);
1656 }
1657
1658 static struct desktop_shell *
1659 shell_surface_get_shell(struct shell_surface *shsurf)
1660 {
1661         return shsurf->shell;
1662 }
1663
1664 static int
1665 get_output_panel_height(struct desktop_shell *shell,
1666                         struct weston_output *output)
1667 {
1668         struct weston_surface *surface;
1669         int panel_height = 0;
1670
1671         if (!output)
1672                 return 0;
1673
1674         wl_list_for_each(surface, &shell->panel_layer.surface_list, layer_link) {
1675                 if (surface->output == output) {
1676                         panel_height = surface->geometry.height;
1677                         break;
1678                 }
1679         }
1680
1681         return panel_height;
1682 }
1683
1684 static void
1685 shell_surface_set_maximized(struct wl_client *client,
1686                             struct wl_resource *resource,
1687                             struct wl_resource *output_resource )
1688 {
1689         struct shell_surface *shsurf = resource->data;
1690         struct weston_surface *es = shsurf->surface;
1691         struct desktop_shell *shell = NULL;
1692         uint32_t edges = 0, panel_height = 0;
1693
1694         /* get the default output, if the client set it as NULL
1695            check whether the ouput is available */
1696         if (output_resource)
1697                 shsurf->output = output_resource->data;
1698         else if (es->output)
1699                 shsurf->output = es->output;
1700         else
1701                 shsurf->output = get_default_output(es->compositor);
1702
1703         shell = shell_surface_get_shell(shsurf);
1704         panel_height = get_output_panel_height(shell, shsurf->output);
1705         edges = WL_SHELL_SURFACE_RESIZE_TOP|WL_SHELL_SURFACE_RESIZE_LEFT;
1706
1707         shsurf->client->send_configure(shsurf->surface, edges,
1708                                        shsurf->output->width,
1709                                        shsurf->output->height - panel_height);
1710
1711         shsurf->next_type = SHELL_SURFACE_MAXIMIZED;
1712 }
1713
1714 static void
1715 black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height);
1716
1717 static struct weston_surface *
1718 create_black_surface(struct weston_compositor *ec,
1719                      struct weston_surface *fs_surface,
1720                      float x, float y, int w, int h)
1721 {
1722         struct weston_surface *surface = NULL;
1723
1724         surface = weston_surface_create(ec);
1725         if (surface == NULL) {
1726                 weston_log("no memory\n");
1727                 return NULL;
1728         }
1729
1730         surface->configure = black_surface_configure;
1731         surface->configure_private = fs_surface;
1732         weston_surface_configure(surface, x, y, w, h);
1733         weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1);
1734         pixman_region32_fini(&surface->opaque);
1735         pixman_region32_init_rect(&surface->opaque, 0, 0, w, h);
1736         pixman_region32_fini(&surface->input);
1737         pixman_region32_init_rect(&surface->input, 0, 0, w, h);
1738
1739         return surface;
1740 }
1741
1742 /* Create black surface and append it to the associated fullscreen surface.
1743  * Handle size dismatch and positioning according to the method. */
1744 static void
1745 shell_configure_fullscreen(struct shell_surface *shsurf)
1746 {
1747         struct weston_output *output = shsurf->fullscreen_output;
1748         struct weston_surface *surface = shsurf->surface;
1749         struct weston_matrix *matrix;
1750         float scale, output_aspect, surface_aspect, x, y;
1751         int32_t surf_x, surf_y, surf_width, surf_height;
1752
1753         if (!shsurf->fullscreen.black_surface)
1754                 shsurf->fullscreen.black_surface =
1755                         create_black_surface(surface->compositor,
1756                                              surface,
1757                                              output->x, output->y,
1758                                              output->width,
1759                                              output->height);
1760
1761         wl_list_remove(&shsurf->fullscreen.black_surface->layer_link);
1762         wl_list_insert(&surface->layer_link,
1763                        &shsurf->fullscreen.black_surface->layer_link);
1764         shsurf->fullscreen.black_surface->output = output;
1765
1766         surface_subsurfaces_boundingbox(surface, &surf_x, &surf_y,
1767                                         &surf_width, &surf_height);
1768
1769         switch (shsurf->fullscreen.type) {
1770         case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT:
1771                 if (surface->buffer_ref.buffer)
1772                         center_on_output(surface, shsurf->fullscreen_output);
1773                 break;
1774         case WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE:
1775                 /* 1:1 mapping between surface and output dimensions */
1776                 if (output->width == surf_width &&
1777                         output->height == surf_height) {
1778                         weston_surface_set_position(surface, output->x - surf_x,
1779                                                              output->y - surf_y);
1780                         break;
1781                 }
1782
1783                 matrix = &shsurf->fullscreen.transform.matrix;
1784                 weston_matrix_init(matrix);
1785
1786                 output_aspect = (float) output->width /
1787                         (float) output->height;
1788                 surface_aspect = (float) surface->geometry.width /
1789                         (float) surface->geometry.height;
1790                 if (output_aspect < surface_aspect)
1791                         scale = (float) output->width /
1792                                 (float) surf_width;
1793                 else
1794                         scale = (float) output->height /
1795                                 (float) surf_height;
1796
1797                 weston_matrix_scale(matrix, scale, scale, 1);
1798                 wl_list_remove(&shsurf->fullscreen.transform.link);
1799                 wl_list_insert(&surface->geometry.transformation_list,
1800                                &shsurf->fullscreen.transform.link);
1801                 x = output->x + (output->width - surf_width * scale) / 2 - surf_x;
1802                 y = output->y + (output->height - surf_height * scale) / 2 - surf_y;
1803                 weston_surface_set_position(surface, x, y);
1804
1805                 break;
1806         case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER:
1807                 if (shell_surface_is_top_fullscreen(shsurf)) {
1808                         struct weston_mode mode = {0,
1809                                 surf_width,
1810                                 surf_height,
1811                                 shsurf->fullscreen.framerate};
1812
1813                         if (weston_output_switch_mode(output, &mode) == 0) {
1814                                 weston_surface_configure(shsurf->fullscreen.black_surface,
1815                                                          output->x - surf_x,
1816                                                          output->y - surf_y,
1817                                                          output->width,
1818                                                          output->height);
1819                                 break;
1820                         }
1821                 }
1822                 break;
1823         case WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL:
1824                 break;
1825         default:
1826                 break;
1827         }
1828 }
1829
1830 /* make the fullscreen and black surface at the top */
1831 static void
1832 shell_stack_fullscreen(struct shell_surface *shsurf)
1833 {
1834         struct weston_output *output = shsurf->fullscreen_output;
1835         struct weston_surface *surface = shsurf->surface;
1836         struct desktop_shell *shell = shell_surface_get_shell(shsurf);
1837
1838         wl_list_remove(&surface->layer_link);
1839         wl_list_insert(&shell->fullscreen_layer.surface_list,
1840                        &surface->layer_link);
1841         weston_surface_damage(surface);
1842
1843         if (!shsurf->fullscreen.black_surface)
1844                 shsurf->fullscreen.black_surface =
1845                         create_black_surface(surface->compositor,
1846                                              surface,
1847                                              output->x, output->y,
1848                                              output->width,
1849                                              output->height);
1850
1851         wl_list_remove(&shsurf->fullscreen.black_surface->layer_link);
1852         wl_list_insert(&surface->layer_link,
1853                        &shsurf->fullscreen.black_surface->layer_link);
1854         weston_surface_damage(shsurf->fullscreen.black_surface);
1855 }
1856
1857 static void
1858 shell_map_fullscreen(struct shell_surface *shsurf)
1859 {
1860         shell_stack_fullscreen(shsurf);
1861         shell_configure_fullscreen(shsurf);
1862 }
1863
1864 static void
1865 set_fullscreen(struct shell_surface *shsurf,
1866                uint32_t method,
1867                uint32_t framerate,
1868                struct weston_output *output)
1869 {
1870         struct weston_surface *es = shsurf->surface;
1871
1872         if (output)
1873                 shsurf->output = output;
1874         else if (es->output)
1875                 shsurf->output = es->output;
1876         else
1877                 shsurf->output = get_default_output(es->compositor);
1878
1879         shsurf->fullscreen_output = shsurf->output;
1880         shsurf->fullscreen.type = method;
1881         shsurf->fullscreen.framerate = framerate;
1882         shsurf->next_type = SHELL_SURFACE_FULLSCREEN;
1883
1884         shsurf->client->send_configure(shsurf->surface, 0,
1885                                        shsurf->output->width,
1886                                        shsurf->output->height);
1887 }
1888
1889 static void
1890 shell_surface_set_fullscreen(struct wl_client *client,
1891                              struct wl_resource *resource,
1892                              uint32_t method,
1893                              uint32_t framerate,
1894                              struct wl_resource *output_resource)
1895 {
1896         struct shell_surface *shsurf = resource->data;
1897         struct weston_output *output;
1898
1899         if (output_resource)
1900                 output = output_resource->data;
1901         else
1902                 output = NULL;
1903
1904         set_fullscreen(shsurf, method, framerate, output);
1905 }
1906
1907 static const struct weston_pointer_grab_interface popup_grab_interface;
1908
1909 static void
1910 destroy_shell_seat(struct wl_listener *listener, void *data)
1911 {
1912         struct shell_seat *shseat =
1913                 container_of(listener,
1914                              struct shell_seat, seat_destroy_listener);
1915         struct shell_surface *shsurf, *prev = NULL;
1916
1917         if (shseat->popup_grab.grab.interface == &popup_grab_interface) {
1918                 weston_pointer_end_grab(shseat->popup_grab.grab.pointer);
1919                 shseat->popup_grab.client = NULL;
1920
1921                 wl_list_for_each(shsurf, &shseat->popup_grab.surfaces_list, popup.grab_link) {
1922                         shsurf->popup.shseat = NULL;
1923                         if (prev) {
1924                                 wl_list_init(&prev->popup.grab_link);
1925                         }
1926                         prev = shsurf;
1927                 }
1928                 wl_list_init(&prev->popup.grab_link);
1929         }
1930
1931         wl_list_remove(&shseat->seat_destroy_listener.link);
1932         free(shseat);
1933 }
1934
1935 static struct shell_seat *
1936 create_shell_seat(struct weston_seat *seat)
1937 {
1938         struct shell_seat *shseat;
1939
1940         shseat = calloc(1, sizeof *shseat);
1941         if (!shseat) {
1942                 weston_log("no memory to allocate shell seat\n");
1943                 return NULL;
1944         }
1945
1946         shseat->seat = seat;
1947         wl_list_init(&shseat->popup_grab.surfaces_list);
1948
1949         shseat->seat_destroy_listener.notify = destroy_shell_seat;
1950         wl_signal_add(&seat->destroy_signal,
1951                       &shseat->seat_destroy_listener);
1952
1953         return shseat;
1954 }
1955
1956 static struct shell_seat *
1957 get_shell_seat(struct weston_seat *seat)
1958 {
1959         struct wl_listener *listener;
1960
1961         listener = wl_signal_get(&seat->destroy_signal, destroy_shell_seat);
1962         if (listener == NULL)
1963                 return create_shell_seat(seat);
1964
1965         return container_of(listener,
1966                             struct shell_seat, seat_destroy_listener);
1967 }
1968
1969 static void
1970 popup_grab_focus(struct weston_pointer_grab *grab)
1971 {
1972         struct weston_pointer *pointer = grab->pointer;
1973         struct weston_surface *surface;
1974         struct shell_seat *shseat =
1975             container_of(grab, struct shell_seat, popup_grab.grab);
1976         struct wl_client *client = shseat->popup_grab.client;
1977         wl_fixed_t sx, sy;
1978
1979         surface = weston_compositor_pick_surface(pointer->seat->compositor,
1980                                                  pointer->x, pointer->y,
1981                                                  &sx, &sy);
1982
1983         if (surface && surface->resource.client == client) {
1984                 weston_pointer_set_focus(pointer, surface, sx, sy);
1985         } else {
1986                 weston_pointer_set_focus(pointer, NULL,
1987                                          wl_fixed_from_int(0),
1988                                          wl_fixed_from_int(0));
1989         }
1990 }
1991
1992 static void
1993 popup_grab_motion(struct weston_pointer_grab *grab, uint32_t time)
1994 {
1995         struct weston_pointer *pointer = grab->pointer;
1996         wl_fixed_t sx, sy;
1997
1998         if (pointer->focus_resource) {
1999                 weston_surface_from_global_fixed(pointer->focus,
2000                                                  pointer->x, pointer->y,
2001                                                  &sx, &sy);
2002                 wl_pointer_send_motion(pointer->focus_resource, time, sx, sy);
2003         }
2004 }
2005
2006 static void
2007 popup_grab_button(struct weston_pointer_grab *grab,
2008                   uint32_t time, uint32_t button, uint32_t state_w)
2009 {
2010         struct wl_resource *resource;
2011         struct shell_seat *shseat =
2012             container_of(grab, struct shell_seat, popup_grab.grab);
2013         struct wl_display *display;
2014         enum wl_pointer_button_state state = state_w;
2015         uint32_t serial;
2016
2017         resource = grab->pointer->focus_resource;
2018         if (resource) {
2019                 display = wl_client_get_display(resource->client);
2020                 serial = wl_display_get_serial(display);
2021                 wl_pointer_send_button(resource, serial, time, button, state);
2022         } else if (state == WL_POINTER_BUTTON_STATE_RELEASED &&
2023                    (shseat->popup_grab.initial_up ||
2024                     time - shseat->seat->pointer->grab_time > 500)) {
2025                 popup_grab_end(grab->pointer);
2026         }
2027
2028         if (state == WL_POINTER_BUTTON_STATE_RELEASED)
2029                 shseat->popup_grab.initial_up = 1;
2030 }
2031
2032 static const struct weston_pointer_grab_interface popup_grab_interface = {
2033         popup_grab_focus,
2034         popup_grab_motion,
2035         popup_grab_button,
2036 };
2037
2038 static void
2039 popup_grab_end(struct weston_pointer *pointer)
2040 {
2041         struct weston_pointer_grab *grab = pointer->grab;
2042         struct shell_seat *shseat =
2043             container_of(grab, struct shell_seat, popup_grab.grab);
2044         struct shell_surface *shsurf;
2045         struct shell_surface *prev = NULL;
2046
2047         if (pointer->grab->interface == &popup_grab_interface) {
2048                 weston_pointer_end_grab(grab->pointer);
2049                 shseat->popup_grab.client = NULL;
2050                 shseat->popup_grab.grab.interface = NULL;
2051                 assert(!wl_list_empty(&shseat->popup_grab.surfaces_list));
2052                 /* Send the popup_done event to all the popups open */
2053                 wl_list_for_each(shsurf, &shseat->popup_grab.surfaces_list, popup.grab_link) {
2054                         wl_shell_surface_send_popup_done(&shsurf->resource);
2055                         shsurf->popup.shseat = NULL;
2056                         if (prev) {
2057                                 wl_list_init(&prev->popup.grab_link);
2058                         }
2059                         prev = shsurf;
2060                 }
2061                 wl_list_init(&prev->popup.grab_link);
2062                 wl_list_init(&shseat->popup_grab.surfaces_list);
2063         }
2064 }
2065
2066 static void
2067 add_popup_grab(struct shell_surface *shsurf, struct shell_seat *shseat)
2068 {
2069         struct weston_seat *seat = shseat->seat;
2070
2071         if (wl_list_empty(&shseat->popup_grab.surfaces_list)) {
2072                 shseat->popup_grab.client = shsurf->resource.client;
2073                 shseat->popup_grab.grab.interface = &popup_grab_interface;
2074                 /* We must make sure here that this popup was opened after
2075                  * a mouse press, and not just by moving around with other
2076                  * popups already open. */
2077                 if (shseat->seat->pointer->button_count > 0)
2078                         shseat->popup_grab.initial_up = 0;
2079
2080                 weston_pointer_start_grab(seat->pointer, &shseat->popup_grab.grab);
2081         }
2082         wl_list_insert(&shseat->popup_grab.surfaces_list, &shsurf->popup.grab_link);
2083 }
2084
2085 static void
2086 remove_popup_grab(struct shell_surface *shsurf)
2087 {
2088         struct shell_seat *shseat = shsurf->popup.shseat;
2089
2090         wl_list_remove(&shsurf->popup.grab_link);
2091         wl_list_init(&shsurf->popup.grab_link);
2092         if (wl_list_empty(&shseat->popup_grab.surfaces_list)) {
2093                 weston_pointer_end_grab(shseat->popup_grab.grab.pointer);
2094                 shseat->popup_grab.grab.interface = NULL;
2095         }
2096 }
2097
2098 static void
2099 shell_map_popup(struct shell_surface *shsurf)
2100 {
2101         struct shell_seat *shseat = shsurf->popup.shseat;
2102         struct weston_surface *es = shsurf->surface;
2103         struct weston_surface *parent = shsurf->parent;
2104
2105         es->output = parent->output;
2106
2107         weston_surface_set_transform_parent(es, parent);
2108         weston_surface_set_position(es, shsurf->popup.x, shsurf->popup.y);
2109         weston_surface_update_transform(es);
2110
2111         if (shseat->seat->pointer->grab_serial == shsurf->popup.serial) {
2112                 add_popup_grab(shsurf, shseat);
2113         } else {
2114                 wl_shell_surface_send_popup_done(&shsurf->resource);
2115                 shseat->popup_grab.client = NULL;
2116         }
2117 }
2118
2119 static void
2120 shell_surface_set_popup(struct wl_client *client,
2121                         struct wl_resource *resource,
2122                         struct wl_resource *seat_resource,
2123                         uint32_t serial,
2124                         struct wl_resource *parent_resource,
2125                         int32_t x, int32_t y, uint32_t flags)
2126 {
2127         struct shell_surface *shsurf = resource->data;
2128
2129         shsurf->type = SHELL_SURFACE_POPUP;
2130         shsurf->parent = parent_resource->data;
2131         shsurf->popup.shseat = get_shell_seat(seat_resource->data);
2132         shsurf->popup.serial = serial;
2133         shsurf->popup.x = x;
2134         shsurf->popup.y = y;
2135 }
2136
2137 static const struct wl_shell_surface_interface shell_surface_implementation = {
2138         shell_surface_pong,
2139         shell_surface_move,
2140         shell_surface_resize,
2141         shell_surface_set_toplevel,
2142         shell_surface_set_transient,
2143         shell_surface_set_fullscreen,
2144         shell_surface_set_popup,
2145         shell_surface_set_maximized,
2146         shell_surface_set_title,
2147         shell_surface_set_class
2148 };
2149
2150 static void
2151 destroy_shell_surface(struct shell_surface *shsurf)
2152 {
2153         if (!wl_list_empty(&shsurf->popup.grab_link)) {
2154                 remove_popup_grab(shsurf);
2155         }
2156
2157         if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
2158             shell_surface_is_top_fullscreen(shsurf)) {
2159                 weston_output_switch_mode(shsurf->fullscreen_output,
2160                                           shsurf->fullscreen_output->origin);
2161         }
2162
2163         if (shsurf->fullscreen.black_surface)
2164                 weston_surface_destroy(shsurf->fullscreen.black_surface);
2165
2166         /* As destroy_resource() use wl_list_for_each_safe(),
2167          * we can always remove the listener.
2168          */
2169         wl_list_remove(&shsurf->surface_destroy_listener.link);
2170         shsurf->surface->configure = NULL;
2171         ping_timer_destroy(shsurf);
2172         free(shsurf->title);
2173
2174         wl_list_remove(&shsurf->link);
2175         free(shsurf);
2176 }
2177
2178 static void
2179 shell_destroy_shell_surface(struct wl_resource *resource)
2180 {
2181         struct shell_surface *shsurf = resource->data;
2182
2183         destroy_shell_surface(shsurf);
2184 }
2185
2186 static void
2187 shell_handle_surface_destroy(struct wl_listener *listener, void *data)
2188 {
2189         struct shell_surface *shsurf = container_of(listener,
2190                                                     struct shell_surface,
2191                                                     surface_destroy_listener);
2192
2193         if (shsurf->resource.client) {
2194                 wl_resource_destroy(&shsurf->resource);
2195         } else {
2196                 wl_signal_emit(&shsurf->resource.destroy_signal,
2197                                &shsurf->resource);
2198                 destroy_shell_surface(shsurf);
2199         }
2200 }
2201
2202 static void
2203 shell_surface_configure(struct weston_surface *, int32_t, int32_t, int32_t, int32_t);
2204
2205 static struct shell_surface *
2206 get_shell_surface(struct weston_surface *surface)
2207 {
2208         if (surface->configure == shell_surface_configure)
2209                 return surface->configure_private;
2210         else
2211                 return NULL;
2212 }
2213
2214 static  struct shell_surface *
2215 create_shell_surface(void *shell, struct weston_surface *surface,
2216                      const struct weston_shell_client *client)
2217 {
2218         struct shell_surface *shsurf;
2219
2220         if (surface->configure) {
2221                 weston_log("surface->configure already set\n");
2222                 return NULL;
2223         }
2224
2225         shsurf = calloc(1, sizeof *shsurf);
2226         if (!shsurf) {
2227                 weston_log("no memory to allocate shell surface\n");
2228                 return NULL;
2229         }
2230
2231         surface->configure = shell_surface_configure;
2232         surface->configure_private = shsurf;
2233
2234         shsurf->shell = (struct desktop_shell *) shell;
2235         shsurf->unresponsive = 0;
2236         shsurf->saved_position_valid = false;
2237         shsurf->saved_rotation_valid = false;
2238         shsurf->surface = surface;
2239         shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
2240         shsurf->fullscreen.framerate = 0;
2241         shsurf->fullscreen.black_surface = NULL;
2242         shsurf->ping_timer = NULL;
2243         wl_list_init(&shsurf->fullscreen.transform.link);
2244
2245         wl_signal_init(&shsurf->resource.destroy_signal);
2246         shsurf->surface_destroy_listener.notify = shell_handle_surface_destroy;
2247         wl_signal_add(&surface->resource.destroy_signal,
2248                       &shsurf->surface_destroy_listener);
2249
2250         /* init link so its safe to always remove it in destroy_shell_surface */
2251         wl_list_init(&shsurf->link);
2252         wl_list_init(&shsurf->popup.grab_link);
2253
2254         /* empty when not in use */
2255         wl_list_init(&shsurf->rotation.transform.link);
2256         weston_matrix_init(&shsurf->rotation.rotation);
2257
2258         wl_list_init(&shsurf->workspace_transform.link);
2259
2260         shsurf->type = SHELL_SURFACE_NONE;
2261         shsurf->next_type = SHELL_SURFACE_NONE;
2262
2263         shsurf->client = client;
2264
2265         return shsurf;
2266 }
2267
2268 static void
2269 shell_get_shell_surface(struct wl_client *client,
2270                         struct wl_resource *resource,
2271                         uint32_t id,
2272                         struct wl_resource *surface_resource)
2273 {
2274         struct weston_surface *surface = surface_resource->data;
2275         struct desktop_shell *shell = resource->data;
2276         struct shell_surface *shsurf;
2277
2278         if (get_shell_surface(surface)) {
2279                 wl_resource_post_error(surface_resource,
2280                                        WL_DISPLAY_ERROR_INVALID_OBJECT,
2281                                        "desktop_shell::get_shell_surface already requested");
2282                 return;
2283         }
2284
2285         shsurf = create_shell_surface(shell, surface, &shell_client);
2286         if (!shsurf) {
2287                 wl_resource_post_error(surface_resource,
2288                                        WL_DISPLAY_ERROR_INVALID_OBJECT,
2289                                        "surface->configure already set");
2290                 return;
2291         }
2292
2293         shsurf->resource.destroy = shell_destroy_shell_surface;
2294         shsurf->resource.object.id = id;
2295         shsurf->resource.object.interface = &wl_shell_surface_interface;
2296         shsurf->resource.object.implementation =
2297                 (void (**)(void)) &shell_surface_implementation;
2298         shsurf->resource.data = shsurf;
2299
2300         wl_client_add_resource(client, &shsurf->resource);
2301 }
2302
2303 static const struct wl_shell_interface shell_implementation = {
2304         shell_get_shell_surface
2305 };
2306
2307 static void
2308 shell_fade(struct desktop_shell *shell, enum fade_type type);
2309
2310 static int
2311 screensaver_timeout(void *data)
2312 {
2313         struct desktop_shell *shell = data;
2314
2315         shell_fade(shell, FADE_OUT);
2316
2317         return 1;
2318 }
2319
2320 static void
2321 handle_screensaver_sigchld(struct weston_process *proc, int status)
2322 {
2323         struct desktop_shell *shell =
2324                 container_of(proc, struct desktop_shell, screensaver.process);
2325
2326         proc->pid = 0;
2327
2328         if (shell->locked)
2329                 weston_compositor_sleep(shell->compositor);
2330 }
2331
2332 static void
2333 launch_screensaver(struct desktop_shell *shell)
2334 {
2335         if (shell->screensaver.binding)
2336                 return;
2337
2338         if (!shell->screensaver.path) {
2339                 weston_compositor_sleep(shell->compositor);
2340                 return;
2341         }
2342
2343         if (shell->screensaver.process.pid != 0) {
2344                 weston_log("old screensaver still running\n");
2345                 return;
2346         }
2347
2348         weston_client_launch(shell->compositor,
2349                            &shell->screensaver.process,
2350                            shell->screensaver.path,
2351                            handle_screensaver_sigchld);
2352 }
2353
2354 static void
2355 terminate_screensaver(struct desktop_shell *shell)
2356 {
2357         if (shell->screensaver.process.pid == 0)
2358                 return;
2359
2360         kill(shell->screensaver.process.pid, SIGTERM);
2361 }
2362
2363 static void
2364 configure_static_surface(struct weston_surface *es, struct weston_layer *layer, int32_t width, int32_t height)
2365 {
2366         struct weston_surface *s, *next;
2367
2368         if (width == 0)
2369                 return;
2370
2371         wl_list_for_each_safe(s, next, &layer->surface_list, layer_link) {
2372                 if (s->output == es->output && s != es) {
2373                         weston_surface_unmap(s);
2374                         s->configure = NULL;
2375                 }
2376         }
2377
2378         weston_surface_configure(es, es->output->x, es->output->y, width, height);
2379
2380         if (wl_list_empty(&es->layer_link)) {
2381                 wl_list_insert(&layer->surface_list, &es->layer_link);
2382                 weston_compositor_schedule_repaint(es->compositor);
2383         }
2384 }
2385
2386 static void
2387 background_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height)
2388 {
2389         struct desktop_shell *shell = es->configure_private;
2390
2391         configure_static_surface(es, &shell->background_layer, width, height);
2392 }
2393
2394 static void
2395 desktop_shell_set_background(struct wl_client *client,
2396                              struct wl_resource *resource,
2397                              struct wl_resource *output_resource,
2398                              struct wl_resource *surface_resource)
2399 {
2400         struct desktop_shell *shell = resource->data;
2401         struct weston_surface *surface = surface_resource->data;
2402
2403         if (surface->configure) {
2404                 wl_resource_post_error(surface_resource,
2405                                        WL_DISPLAY_ERROR_INVALID_OBJECT,
2406                                        "surface role already assigned");
2407                 return;
2408         }
2409
2410         surface->configure = background_configure;
2411         surface->configure_private = shell;
2412         surface->output = output_resource->data;
2413         desktop_shell_send_configure(resource, 0,
2414                                      surface_resource,
2415                                      surface->output->width,
2416                                      surface->output->height);
2417 }
2418
2419 static void
2420 panel_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height)
2421 {
2422         struct desktop_shell *shell = es->configure_private;
2423
2424         configure_static_surface(es, &shell->panel_layer, width, height);
2425 }
2426
2427 static void
2428 desktop_shell_set_panel(struct wl_client *client,
2429                         struct wl_resource *resource,
2430                         struct wl_resource *output_resource,
2431                         struct wl_resource *surface_resource)
2432 {
2433         struct desktop_shell *shell = resource->data;
2434         struct weston_surface *surface = surface_resource->data;
2435
2436         if (surface->configure) {
2437                 wl_resource_post_error(surface_resource,
2438                                        WL_DISPLAY_ERROR_INVALID_OBJECT,
2439                                        "surface role already assigned");
2440                 return;
2441         }
2442
2443         surface->configure = panel_configure;
2444         surface->configure_private = shell;
2445         surface->output = output_resource->data;
2446         desktop_shell_send_configure(resource, 0,
2447                                      surface_resource,
2448                                      surface->output->width,
2449                                      surface->output->height);
2450 }
2451
2452 static void
2453 lock_surface_configure(struct weston_surface *surface, int32_t sx, int32_t sy, int32_t width, int32_t height)
2454 {
2455         struct desktop_shell *shell = surface->configure_private;
2456
2457         if (width == 0)
2458                 return;
2459
2460         surface->geometry.width = width;
2461         surface->geometry.height = height;
2462         center_on_output(surface, get_default_output(shell->compositor));
2463
2464         if (!weston_surface_is_mapped(surface)) {
2465                 wl_list_insert(&shell->lock_layer.surface_list,
2466                                &surface->layer_link);
2467                 weston_surface_update_transform(surface);
2468                 shell_fade(shell, FADE_IN);
2469         }
2470 }
2471
2472 static void
2473 handle_lock_surface_destroy(struct wl_listener *listener, void *data)
2474 {
2475         struct desktop_shell *shell =
2476             container_of(listener, struct desktop_shell, lock_surface_listener);
2477
2478         weston_log("lock surface gone\n");
2479         shell->lock_surface = NULL;
2480 }
2481
2482 static void
2483 desktop_shell_set_lock_surface(struct wl_client *client,
2484                                struct wl_resource *resource,
2485                                struct wl_resource *surface_resource)
2486 {
2487         struct desktop_shell *shell = resource->data;
2488         struct weston_surface *surface = surface_resource->data;
2489
2490         shell->prepare_event_sent = false;
2491
2492         if (!shell->locked)
2493                 return;
2494
2495         shell->lock_surface = surface;
2496
2497         shell->lock_surface_listener.notify = handle_lock_surface_destroy;
2498         wl_signal_add(&surface_resource->destroy_signal,
2499                       &shell->lock_surface_listener);
2500
2501         surface->configure = lock_surface_configure;
2502         surface->configure_private = shell;
2503 }
2504
2505 static void
2506 resume_desktop(struct desktop_shell *shell)
2507 {
2508         struct workspace *ws = get_current_workspace(shell);
2509
2510         terminate_screensaver(shell);
2511
2512         wl_list_remove(&shell->lock_layer.link);
2513         wl_list_insert(&shell->compositor->cursor_layer.link,
2514                        &shell->fullscreen_layer.link);
2515         wl_list_insert(&shell->fullscreen_layer.link,
2516                        &shell->panel_layer.link);
2517         if (shell->showing_input_panels) {
2518                 wl_list_insert(&shell->panel_layer.link,
2519                                &shell->input_panel_layer.link);
2520                 wl_list_insert(&shell->input_panel_layer.link,
2521                                &ws->layer.link);
2522         } else {
2523                 wl_list_insert(&shell->panel_layer.link, &ws->layer.link);
2524         }
2525
2526         restore_focus_state(shell, get_current_workspace(shell));
2527
2528         shell->locked = false;
2529         shell_fade(shell, FADE_IN);
2530         weston_compositor_damage_all(shell->compositor);
2531 }
2532
2533 static void
2534 desktop_shell_unlock(struct wl_client *client,
2535                      struct wl_resource *resource)
2536 {
2537         struct desktop_shell *shell = resource->data;
2538
2539         shell->prepare_event_sent = false;
2540
2541         if (shell->locked)
2542                 resume_desktop(shell);
2543 }
2544
2545 static void
2546 desktop_shell_set_grab_surface(struct wl_client *client,
2547                                struct wl_resource *resource,
2548                                struct wl_resource *surface_resource)
2549 {
2550         struct desktop_shell *shell = resource->data;
2551
2552         shell->grab_surface = surface_resource->data;
2553 }
2554
2555 static void
2556 desktop_shell_desktop_ready(struct wl_client *client,
2557                             struct wl_resource *resource)
2558 {
2559         struct desktop_shell *shell = resource->data;
2560
2561         shell_fade_startup(shell);
2562 }
2563
2564 static const struct desktop_shell_interface desktop_shell_implementation = {
2565         desktop_shell_set_background,
2566         desktop_shell_set_panel,
2567         desktop_shell_set_lock_surface,
2568         desktop_shell_unlock,
2569         desktop_shell_set_grab_surface,
2570         desktop_shell_desktop_ready
2571 };
2572
2573 static enum shell_surface_type
2574 get_shell_surface_type(struct weston_surface *surface)
2575 {
2576         struct shell_surface *shsurf;
2577
2578         shsurf = get_shell_surface(surface);
2579         if (!shsurf)
2580                 return SHELL_SURFACE_NONE;
2581         return shsurf->type;
2582 }
2583
2584 static void
2585 move_binding(struct weston_seat *seat, uint32_t time, uint32_t button, void *data)
2586 {
2587         struct weston_surface *focus =
2588                 (struct weston_surface *) seat->pointer->focus;
2589         struct weston_surface *surface;
2590         struct shell_surface *shsurf;
2591
2592         surface = weston_surface_get_main_surface(focus);
2593         if (surface == NULL)
2594                 return;
2595
2596         shsurf = get_shell_surface(surface);
2597         if (shsurf == NULL || shsurf->type == SHELL_SURFACE_FULLSCREEN ||
2598             shsurf->type == SHELL_SURFACE_MAXIMIZED)
2599                 return;
2600
2601         surface_move(shsurf, (struct weston_seat *) seat);
2602 }
2603
2604 static void
2605 resize_binding(struct weston_seat *seat, uint32_t time, uint32_t button, void *data)
2606 {
2607         struct weston_surface *focus =
2608                 (struct weston_surface *) seat->pointer->focus;
2609         struct weston_surface *surface;
2610         uint32_t edges = 0;
2611         int32_t x, y;
2612         struct shell_surface *shsurf;
2613
2614         surface = weston_surface_get_main_surface(focus);
2615         if (surface == NULL)
2616                 return;
2617
2618         shsurf = get_shell_surface(surface);
2619         if (!shsurf || shsurf->type == SHELL_SURFACE_FULLSCREEN ||
2620             shsurf->type == SHELL_SURFACE_MAXIMIZED)
2621                 return;
2622
2623         weston_surface_from_global(surface,
2624                                    wl_fixed_to_int(seat->pointer->grab_x),
2625                                    wl_fixed_to_int(seat->pointer->grab_y),
2626                                    &x, &y);
2627
2628         if (x < surface->geometry.width / 3)
2629                 edges |= WL_SHELL_SURFACE_RESIZE_LEFT;
2630         else if (x < 2 * surface->geometry.width / 3)
2631                 edges |= 0;
2632         else
2633                 edges |= WL_SHELL_SURFACE_RESIZE_RIGHT;
2634
2635         if (y < surface->geometry.height / 3)
2636                 edges |= WL_SHELL_SURFACE_RESIZE_TOP;
2637         else if (y < 2 * surface->geometry.height / 3)
2638                 edges |= 0;
2639         else
2640                 edges |= WL_SHELL_SURFACE_RESIZE_BOTTOM;
2641
2642         surface_resize(shsurf, (struct weston_seat *) seat, edges);
2643 }
2644
2645 static void
2646 surface_opacity_binding(struct weston_seat *seat, uint32_t time, uint32_t axis,
2647                         wl_fixed_t value, void *data)
2648 {
2649         float step = 0.005;
2650         struct shell_surface *shsurf;
2651         struct weston_surface *focus =
2652                 (struct weston_surface *) seat->pointer->focus;
2653         struct weston_surface *surface;
2654
2655         /* XXX: broken for windows containing sub-surfaces */
2656         surface = weston_surface_get_main_surface(focus);
2657         if (surface == NULL)
2658                 return;
2659
2660         shsurf = get_shell_surface(surface);
2661         if (!shsurf)
2662                 return;
2663
2664         surface->alpha -= wl_fixed_to_double(value) * step;
2665
2666         if (surface->alpha > 1.0)
2667                 surface->alpha = 1.0;
2668         if (surface->alpha < step)
2669                 surface->alpha = step;
2670
2671         weston_surface_geometry_dirty(surface);
2672         weston_surface_damage(surface);
2673 }
2674
2675 static void
2676 do_zoom(struct weston_seat *seat, uint32_t time, uint32_t key, uint32_t axis,
2677         wl_fixed_t value)
2678 {
2679         struct weston_seat *ws = (struct weston_seat *) seat;
2680         struct weston_compositor *compositor = ws->compositor;
2681         struct weston_output *output;
2682         float increment;
2683
2684         wl_list_for_each(output, &compositor->output_list, link) {
2685                 if (pixman_region32_contains_point(&output->region,
2686                                                    wl_fixed_to_double(seat->pointer->x),
2687                                                    wl_fixed_to_double(seat->pointer->y),
2688                                                    NULL)) {
2689                         if (key == KEY_PAGEUP)
2690                                 increment = output->zoom.increment;
2691                         else if (key == KEY_PAGEDOWN)
2692                                 increment = -output->zoom.increment;
2693                         else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
2694                                 /* For every pixel zoom 20th of a step */
2695                                 increment = output->zoom.increment *
2696                                             -wl_fixed_to_double(value) / 20.0;
2697                         else
2698                                 increment = 0;
2699
2700                         output->zoom.level += increment;
2701
2702                         if (output->zoom.level < 0.0)
2703                                 output->zoom.level = 0.0;
2704                         else if (output->zoom.level > output->zoom.max_level)
2705                                 output->zoom.level = output->zoom.max_level;
2706                         else if (!output->zoom.active) {
2707                                 output->zoom.active = 1;
2708                                 output->disable_planes++;
2709                         }
2710
2711                         output->zoom.spring_z.target = output->zoom.level;
2712
2713                         weston_output_update_zoom(output, output->zoom.type);
2714                 }
2715         }
2716 }
2717
2718 static void
2719 zoom_axis_binding(struct weston_seat *seat, uint32_t time, uint32_t axis,
2720                   wl_fixed_t value, void *data)
2721 {
2722         do_zoom(seat, time, 0, axis, value);
2723 }
2724
2725 static void
2726 zoom_key_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
2727                  void *data)
2728 {
2729         do_zoom(seat, time, key, 0, 0);
2730 }
2731
2732 static void
2733 terminate_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
2734                   void *data)
2735 {
2736         struct weston_compositor *compositor = data;
2737
2738         wl_display_terminate(compositor->wl_display);
2739 }
2740
2741 static void
2742 rotate_grab_motion(struct weston_pointer_grab *grab, uint32_t time)
2743 {
2744         struct rotate_grab *rotate =
2745                 container_of(grab, struct rotate_grab, base.grab);
2746         struct weston_pointer *pointer = grab->pointer;
2747         struct shell_surface *shsurf = rotate->base.shsurf;
2748         struct weston_surface *surface;
2749         float cx, cy, dx, dy, cposx, cposy, dposx, dposy, r;
2750
2751         if (!shsurf)
2752                 return;
2753
2754         surface = shsurf->surface;
2755
2756         cx = 0.5f * surface->geometry.width;
2757         cy = 0.5f * surface->geometry.height;
2758
2759         dx = wl_fixed_to_double(pointer->x) - rotate->center.x;
2760         dy = wl_fixed_to_double(pointer->y) - rotate->center.y;
2761         r = sqrtf(dx * dx + dy * dy);
2762
2763         wl_list_remove(&shsurf->rotation.transform.link);
2764         weston_surface_geometry_dirty(shsurf->surface);
2765
2766         if (r > 20.0f) {
2767                 struct weston_matrix *matrix =
2768                         &shsurf->rotation.transform.matrix;
2769
2770                 weston_matrix_init(&rotate->rotation);
2771                 weston_matrix_rotate_xy(&rotate->rotation, dx / r, dy / r);
2772
2773                 weston_matrix_init(matrix);
2774                 weston_matrix_translate(matrix, -cx, -cy, 0.0f);
2775                 weston_matrix_multiply(matrix, &shsurf->rotation.rotation);
2776                 weston_matrix_multiply(matrix, &rotate->rotation);
2777                 weston_matrix_translate(matrix, cx, cy, 0.0f);
2778
2779                 wl_list_insert(
2780                         &shsurf->surface->geometry.transformation_list,
2781                         &shsurf->rotation.transform.link);
2782         } else {
2783                 wl_list_init(&shsurf->rotation.transform.link);
2784                 weston_matrix_init(&shsurf->rotation.rotation);
2785                 weston_matrix_init(&rotate->rotation);
2786         }
2787
2788         /* We need to adjust the position of the surface
2789          * in case it was resized in a rotated state before */
2790         cposx = surface->geometry.x + cx;
2791         cposy = surface->geometry.y + cy;
2792         dposx = rotate->center.x - cposx;
2793         dposy = rotate->center.y - cposy;
2794         if (dposx != 0.0f || dposy != 0.0f) {
2795                 weston_surface_set_position(surface,
2796                                             surface->geometry.x + dposx,
2797                                             surface->geometry.y + dposy);
2798         }
2799
2800         /* Repaint implies weston_surface_update_transform(), which
2801          * lazily applies the damage due to rotation update.
2802          */
2803         weston_compositor_schedule_repaint(shsurf->surface->compositor);
2804 }
2805
2806 static void
2807 rotate_grab_button(struct weston_pointer_grab *grab,
2808                    uint32_t time, uint32_t button, uint32_t state_w)
2809 {
2810         struct rotate_grab *rotate =
2811                 container_of(grab, struct rotate_grab, base.grab);
2812         struct weston_pointer *pointer = grab->pointer;
2813         struct shell_surface *shsurf = rotate->base.shsurf;
2814         enum wl_pointer_button_state state = state_w;
2815
2816         if (pointer->button_count == 0 &&
2817             state == WL_POINTER_BUTTON_STATE_RELEASED) {
2818                 if (shsurf)
2819                         weston_matrix_multiply(&shsurf->rotation.rotation,
2820                                                &rotate->rotation);
2821                 shell_grab_end(&rotate->base);
2822                 free(rotate);
2823         }
2824 }
2825
2826 static const struct weston_pointer_grab_interface rotate_grab_interface = {
2827         noop_grab_focus,
2828         rotate_grab_motion,
2829         rotate_grab_button,
2830 };
2831
2832 static void
2833 surface_rotate(struct shell_surface *surface, struct weston_seat *seat)
2834 {
2835         struct rotate_grab *rotate;
2836         float dx, dy;
2837         float r;
2838
2839         rotate = malloc(sizeof *rotate);
2840         if (!rotate)
2841                 return;
2842
2843         weston_surface_to_global_float(surface->surface,
2844                                        surface->surface->geometry.width / 2,
2845                                        surface->surface->geometry.height / 2,
2846                                        &rotate->center.x, &rotate->center.y);
2847
2848         dx = wl_fixed_to_double(seat->pointer->x) - rotate->center.x;
2849         dy = wl_fixed_to_double(seat->pointer->y) - rotate->center.y;
2850         r = sqrtf(dx * dx + dy * dy);
2851         if (r > 20.0f) {
2852                 struct weston_matrix inverse;
2853
2854                 weston_matrix_init(&inverse);
2855                 weston_matrix_rotate_xy(&inverse, dx / r, -dy / r);
2856                 weston_matrix_multiply(&surface->rotation.rotation, &inverse);
2857
2858                 weston_matrix_init(&rotate->rotation);
2859                 weston_matrix_rotate_xy(&rotate->rotation, dx / r, dy / r);
2860         } else {
2861                 weston_matrix_init(&surface->rotation.rotation);
2862                 weston_matrix_init(&rotate->rotation);
2863         }
2864
2865         shell_grab_start(&rotate->base, &rotate_grab_interface, surface,
2866                          seat->pointer, DESKTOP_SHELL_CURSOR_ARROW);
2867 }
2868
2869 static void
2870 rotate_binding(struct weston_seat *seat, uint32_t time, uint32_t button,
2871                void *data)
2872 {
2873         struct weston_surface *focus =
2874                 (struct weston_surface *) seat->pointer->focus;
2875         struct weston_surface *base_surface;
2876         struct shell_surface *surface;
2877
2878         base_surface = weston_surface_get_main_surface(focus);
2879         if (base_surface == NULL)
2880                 return;
2881
2882         surface = get_shell_surface(base_surface);
2883         if (!surface || surface->type == SHELL_SURFACE_FULLSCREEN ||
2884             surface->type == SHELL_SURFACE_MAXIMIZED)
2885                 return;
2886
2887         surface_rotate(surface, seat);
2888 }
2889
2890 static void
2891 lower_fullscreen_layer(struct desktop_shell *shell)
2892 {
2893         struct workspace *ws;
2894         struct weston_surface *surface, *prev;
2895
2896         ws = get_current_workspace(shell);
2897         wl_list_for_each_reverse_safe(surface, prev,
2898                                       &shell->fullscreen_layer.surface_list,
2899                                       layer_link)
2900                 weston_surface_restack(surface, &ws->layer.surface_list);
2901 }
2902
2903 static void
2904 activate(struct desktop_shell *shell, struct weston_surface *es,
2905          struct weston_seat *seat)
2906 {
2907         struct weston_surface *main_surface;
2908         struct focus_state *state;
2909         struct workspace *ws;
2910
2911         main_surface = weston_surface_get_main_surface(es);
2912
2913         weston_surface_activate(es, seat);
2914
2915         state = ensure_focus_state(shell, seat);
2916         if (state == NULL)
2917                 return;
2918
2919         state->keyboard_focus = es;
2920         wl_list_remove(&state->surface_destroy_listener.link);
2921         wl_signal_add(&es->resource.destroy_signal,
2922                       &state->surface_destroy_listener);
2923
2924         switch (get_shell_surface_type(main_surface)) {
2925         case SHELL_SURFACE_FULLSCREEN:
2926                 /* should on top of panels */
2927                 shell_stack_fullscreen(get_shell_surface(main_surface));
2928                 shell_configure_fullscreen(get_shell_surface(main_surface));
2929                 break;
2930         default:
2931                 ws = get_current_workspace(shell);
2932                 weston_surface_restack(main_surface, &ws->layer.surface_list);
2933                 break;
2934         }
2935 }
2936
2937 /* no-op func for checking black surface */
2938 static void
2939 black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height)
2940 {
2941 }
2942
2943 static bool
2944 is_black_surface (struct weston_surface *es, struct weston_surface **fs_surface)
2945 {
2946         if (es->configure == black_surface_configure) {
2947                 if (fs_surface)
2948                         *fs_surface = (struct weston_surface *)es->configure_private;
2949                 return true;
2950         }
2951         return false;
2952 }
2953
2954 static void
2955 click_to_activate_binding(struct weston_seat *seat, uint32_t time, uint32_t button,
2956                           void *data)
2957 {
2958         struct weston_seat *ws = (struct weston_seat *) seat;
2959         struct desktop_shell *shell = data;
2960         struct weston_surface *focus;
2961         struct weston_surface *main_surface;
2962
2963         focus = (struct weston_surface *) seat->pointer->focus;
2964         if (!focus)
2965                 return;
2966
2967         if (is_black_surface(focus, &main_surface))
2968                 focus = main_surface;
2969
2970         main_surface = weston_surface_get_main_surface(focus);
2971         if (get_shell_surface_type(main_surface) == SHELL_SURFACE_NONE)
2972                 return;
2973
2974         if (seat->pointer->grab == &seat->pointer->default_grab)
2975                 activate(shell, focus, ws);
2976 }
2977
2978 static void
2979 lock(struct desktop_shell *shell)
2980 {
2981         struct workspace *ws = get_current_workspace(shell);
2982
2983         if (shell->locked) {
2984                 weston_compositor_sleep(shell->compositor);
2985                 return;
2986         }
2987
2988         shell->locked = true;
2989
2990         /* Hide all surfaces by removing the fullscreen, panel and
2991          * toplevel layers.  This way nothing else can show or receive
2992          * input events while we are locked. */
2993
2994         wl_list_remove(&shell->panel_layer.link);
2995         wl_list_remove(&shell->fullscreen_layer.link);
2996         if (shell->showing_input_panels)
2997                 wl_list_remove(&shell->input_panel_layer.link);
2998         wl_list_remove(&ws->layer.link);
2999         wl_list_insert(&shell->compositor->cursor_layer.link,
3000                        &shell->lock_layer.link);
3001
3002         launch_screensaver(shell);
3003
3004         /* TODO: disable bindings that should not work while locked. */
3005
3006         /* All this must be undone in resume_desktop(). */
3007 }
3008
3009 static void
3010 unlock(struct desktop_shell *shell)
3011 {
3012         if (!shell->locked || shell->lock_surface) {
3013                 shell_fade(shell, FADE_IN);
3014                 return;
3015         }
3016
3017         /* If desktop-shell client has gone away, unlock immediately. */
3018         if (!shell->child.desktop_shell) {
3019                 resume_desktop(shell);
3020                 return;
3021         }
3022
3023         if (shell->prepare_event_sent)
3024                 return;
3025
3026         desktop_shell_send_prepare_lock_surface(shell->child.desktop_shell);
3027         shell->prepare_event_sent = true;
3028 }
3029
3030 static void
3031 shell_fade_done(struct weston_surface_animation *animation, void *data)
3032 {
3033         struct desktop_shell *shell = data;
3034
3035         shell->fade.animation = NULL;
3036
3037         switch (shell->fade.type) {
3038         case FADE_IN:
3039                 weston_surface_destroy(shell->fade.surface);
3040                 shell->fade.surface = NULL;
3041                 break;
3042         case FADE_OUT:
3043                 lock(shell);
3044                 break;
3045         }
3046 }
3047
3048 static struct weston_surface *
3049 shell_fade_create_surface(struct desktop_shell *shell)
3050 {
3051         struct weston_compositor *compositor = shell->compositor;
3052         struct weston_surface *surface;
3053
3054         surface = weston_surface_create(compositor);
3055         if (!surface)
3056                 return NULL;
3057
3058         weston_surface_configure(surface, 0, 0, 8192, 8192);
3059         weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1.0);
3060         wl_list_insert(&compositor->fade_layer.surface_list,
3061                        &surface->layer_link);
3062         pixman_region32_init(&surface->input);
3063
3064         return surface;
3065 }
3066
3067 static void
3068 shell_fade(struct desktop_shell *shell, enum fade_type type)
3069 {
3070         float tint;
3071
3072         switch (type) {
3073         case FADE_IN:
3074                 tint = 0.0;
3075                 break;
3076         case FADE_OUT:
3077                 tint = 1.0;
3078                 break;
3079         default:
3080                 weston_log("shell: invalid fade type\n");
3081                 return;
3082         }
3083
3084         shell->fade.type = type;
3085
3086         if (shell->fade.surface == NULL) {
3087                 shell->fade.surface = shell_fade_create_surface(shell);
3088                 if (!shell->fade.surface)
3089                         return;
3090
3091                 shell->fade.surface->alpha = 1.0 - tint;
3092                 weston_surface_update_transform(shell->fade.surface);
3093         }
3094
3095         if (shell->fade.animation)
3096                 weston_fade_update(shell->fade.animation,
3097                                    shell->fade.surface->alpha, tint, 30.0);
3098         else
3099                 shell->fade.animation =
3100                         weston_fade_run(shell->fade.surface,
3101                                         1.0 - tint, tint, 30.0,
3102                                         shell_fade_done, shell);
3103 }
3104
3105 static void
3106 do_shell_fade_startup(void *data)
3107 {
3108         struct desktop_shell *shell = data;
3109
3110         shell_fade(shell, FADE_IN);
3111 }
3112
3113 static void
3114 shell_fade_startup(struct desktop_shell *shell)
3115 {
3116         struct wl_event_loop *loop;
3117
3118         if (!shell->fade.startup_timer)
3119                 return;
3120
3121         wl_event_source_remove(shell->fade.startup_timer);
3122         shell->fade.startup_timer = NULL;
3123
3124         loop = wl_display_get_event_loop(shell->compositor->wl_display);
3125         wl_event_loop_add_idle(loop, do_shell_fade_startup, shell);
3126 }
3127
3128 static int
3129 fade_startup_timeout(void *data)
3130 {
3131         struct desktop_shell *shell = data;
3132
3133         shell_fade_startup(shell);
3134         return 0;
3135 }
3136
3137 static void
3138 shell_fade_init(struct desktop_shell *shell)
3139 {
3140         /* Make compositor output all black, and wait for the desktop-shell
3141          * client to signal it is ready, then fade in. The timer triggers a
3142          * fade-in, in case the desktop-shell client takes too long.
3143          */
3144
3145         struct wl_event_loop *loop;
3146
3147         if (shell->fade.surface != NULL) {
3148                 weston_log("%s: warning: fade surface already exists\n",
3149                            __func__);
3150                 return;
3151         }
3152
3153         shell->fade.surface = shell_fade_create_surface(shell);
3154         if (!shell->fade.surface)
3155                 return;
3156
3157         weston_surface_update_transform(shell->fade.surface);
3158         weston_surface_damage(shell->fade.surface);
3159
3160         loop = wl_display_get_event_loop(shell->compositor->wl_display);
3161         shell->fade.startup_timer =
3162                 wl_event_loop_add_timer(loop, fade_startup_timeout, shell);
3163         wl_event_source_timer_update(shell->fade.startup_timer, 15000);
3164 }
3165
3166 static void
3167 idle_handler(struct wl_listener *listener, void *data)
3168 {
3169         struct desktop_shell *shell =
3170                 container_of(listener, struct desktop_shell, idle_listener);
3171
3172         shell_fade(shell, FADE_OUT);
3173         /* lock() is called from shell_fade_done() */
3174 }
3175
3176 static void
3177 wake_handler(struct wl_listener *listener, void *data)
3178 {
3179         struct desktop_shell *shell =
3180                 container_of(listener, struct desktop_shell, wake_listener);
3181
3182         unlock(shell);
3183 }
3184
3185 static void
3186 show_input_panels(struct wl_listener *listener, void *data)
3187 {
3188         struct desktop_shell *shell =
3189                 container_of(listener, struct desktop_shell,
3190                              show_input_panel_listener);
3191         struct input_panel_surface *surface, *next;
3192         struct weston_surface *ws;
3193
3194         shell->text_input.surface = (struct weston_surface*)data;
3195
3196         if (shell->showing_input_panels)
3197                 return;
3198
3199         shell->showing_input_panels = true;
3200
3201         if (!shell->locked)
3202                 wl_list_insert(&shell->panel_layer.link,
3203                                &shell->input_panel_layer.link);
3204
3205         wl_list_for_each_safe(surface, next,
3206                               &shell->input_panel.surfaces, link) {
3207                 ws = surface->surface;
3208                 if (!ws->buffer_ref.buffer)
3209                         continue;
3210                 wl_list_insert(&shell->input_panel_layer.surface_list,
3211                                &ws->layer_link);
3212                 weston_surface_geometry_dirty(ws);
3213                 weston_surface_update_transform(ws);
3214                 weston_surface_damage(ws);
3215                 weston_slide_run(ws, ws->geometry.height, 0, NULL, NULL);
3216         }
3217 }
3218
3219 static void
3220 hide_input_panels(struct wl_listener *listener, void *data)
3221 {
3222         struct desktop_shell *shell =
3223                 container_of(listener, struct desktop_shell,
3224                              hide_input_panel_listener);
3225         struct weston_surface *surface, *next;
3226
3227         if (!shell->showing_input_panels)
3228                 return;
3229
3230         shell->showing_input_panels = false;
3231
3232         if (!shell->locked)
3233                 wl_list_remove(&shell->input_panel_layer.link);
3234
3235         wl_list_for_each_safe(surface, next,
3236                               &shell->input_panel_layer.surface_list, layer_link)
3237                 weston_surface_unmap(surface);
3238 }
3239
3240 static void
3241 update_input_panels(struct wl_listener *listener, void *data)
3242 {
3243         struct desktop_shell *shell =
3244                 container_of(listener, struct desktop_shell,
3245                              update_input_panel_listener);
3246
3247         memcpy(&shell->text_input.cursor_rectangle, data, sizeof(pixman_box32_t));
3248 }
3249
3250 static void
3251 center_on_output(struct weston_surface *surface, struct weston_output *output)
3252 {
3253         int32_t surf_x, surf_y, width, height;
3254         float x, y;
3255
3256         surface_subsurfaces_boundingbox(surface, &surf_x, &surf_y, &width, &height);
3257
3258         x = output->x + (output->width - width) / 2 - surf_x / 2;
3259         y = output->y + (output->height - height) / 2 - surf_y / 2;
3260
3261         weston_surface_configure(surface, x, y, width, height);
3262 }
3263
3264 static void
3265 weston_surface_set_initial_position (struct weston_surface *surface,
3266                                      struct desktop_shell *shell)
3267 {
3268         struct weston_compositor *compositor = shell->compositor;
3269         int ix = 0, iy = 0;
3270         int range_x, range_y;
3271         int dx, dy, x, y, panel_height;
3272         struct weston_output *output, *target_output = NULL;
3273         struct weston_seat *seat;
3274
3275         /* As a heuristic place the new window on the same output as the
3276          * pointer. Falling back to the output containing 0, 0.
3277          *
3278          * TODO: Do something clever for touch too?
3279          */
3280         wl_list_for_each(seat, &compositor->seat_list, link) {
3281                 if (seat->pointer) {
3282                         ix = wl_fixed_to_int(seat->pointer->x);
3283                         iy = wl_fixed_to_int(seat->pointer->y);
3284                         break;
3285                 }
3286         }
3287
3288         wl_list_for_each(output, &compositor->output_list, link) {
3289                 if (pixman_region32_contains_point(&output->region, ix, iy, NULL)) {
3290                         target_output = output;
3291                         break;
3292                 }
3293         }
3294
3295         if (!target_output) {
3296                 weston_surface_set_position(surface, 10 + random() % 400,
3297                                            10 + random() % 400);
3298                 return;
3299         }
3300
3301         /* Valid range within output where the surface will still be onscreen.
3302          * If this is negative it means that the surface is bigger than
3303          * output.
3304          */
3305         panel_height = get_output_panel_height(shell, target_output);
3306         range_x = target_output->width - surface->geometry.width;
3307         range_y = (target_output->height - panel_height) -
3308                   surface->geometry.height;
3309
3310         if (range_x > 0)
3311                 dx = random() % range_x;
3312         else
3313                 dx = 0;
3314
3315         if (range_y > 0)
3316                 dy = panel_height + random() % range_y;
3317         else
3318                 dy = panel_height;
3319
3320         x = target_output->x + dx;
3321         y = target_output->y + dy;
3322
3323         weston_surface_set_position (surface, x, y);
3324 }
3325
3326 static void
3327 map(struct desktop_shell *shell, struct weston_surface *surface,
3328     int32_t width, int32_t height, int32_t sx, int32_t sy)
3329 {
3330         struct weston_compositor *compositor = shell->compositor;
3331         struct shell_surface *shsurf = get_shell_surface(surface);
3332         enum shell_surface_type surface_type = shsurf->type;
3333         struct weston_surface *parent;
3334         struct weston_seat *seat;
3335         struct workspace *ws;
3336         int panel_height = 0;
3337         int32_t surf_x, surf_y;
3338
3339         surface->geometry.width = width;
3340         surface->geometry.height = height;
3341         weston_surface_geometry_dirty(surface);
3342
3343         /* initial positioning, see also configure() */
3344         switch (surface_type) {
3345         case SHELL_SURFACE_TOPLEVEL:
3346                 weston_surface_set_initial_position(surface, shell);
3347                 break;
3348         case SHELL_SURFACE_FULLSCREEN:
3349                 center_on_output(surface, shsurf->fullscreen_output);
3350                 shell_map_fullscreen(shsurf);
3351                 break;
3352         case SHELL_SURFACE_MAXIMIZED:
3353                 /* use surface configure to set the geometry */
3354                 panel_height = get_output_panel_height(shell,surface->output);
3355                 surface_subsurfaces_boundingbox(shsurf->surface, &surf_x, &surf_y,
3356                                                                  NULL, NULL);
3357                 weston_surface_set_position(surface, shsurf->output->x - surf_x,
3358                                             shsurf->output->y + panel_height - surf_y);
3359                 break;
3360         case SHELL_SURFACE_POPUP:
3361                 shell_map_popup(shsurf);
3362                 break;
3363         case SHELL_SURFACE_NONE:
3364                 weston_surface_set_position(surface,
3365                                             surface->geometry.x + sx,
3366                                             surface->geometry.y + sy);
3367                 break;
3368         default:
3369                 ;
3370         }
3371
3372         /* surface stacking order, see also activate() */
3373         switch (surface_type) {
3374         case SHELL_SURFACE_POPUP:
3375         case SHELL_SURFACE_TRANSIENT:
3376                 parent = shsurf->parent;
3377                 wl_list_insert(parent->layer_link.prev, &surface->layer_link);
3378                 break;
3379         case SHELL_SURFACE_FULLSCREEN:
3380         case SHELL_SURFACE_NONE:
3381                 break;
3382         default:
3383                 ws = get_current_workspace(shell);
3384                 wl_list_insert(&ws->layer.surface_list, &surface->layer_link);
3385                 break;
3386         }
3387
3388         if (surface_type != SHELL_SURFACE_NONE) {
3389                 weston_surface_update_transform(surface);
3390                 if (surface_type == SHELL_SURFACE_MAXIMIZED)
3391                         surface->output = shsurf->output;
3392         }
3393
3394         switch (surface_type) {
3395         case SHELL_SURFACE_TRANSIENT:
3396                 if (shsurf->transient.flags ==
3397                                 WL_SHELL_SURFACE_TRANSIENT_INACTIVE)
3398                         break;
3399         case SHELL_SURFACE_TOPLEVEL:
3400         case SHELL_SURFACE_FULLSCREEN:
3401         case SHELL_SURFACE_MAXIMIZED:
3402                 if (!shell->locked) {
3403                         wl_list_for_each(seat, &compositor->seat_list, link)
3404                                 activate(shell, surface, seat);
3405                 }
3406                 break;
3407         default:
3408                 break;
3409         }
3410
3411         if (surface_type == SHELL_SURFACE_TOPLEVEL)
3412         {
3413                 switch (shell->win_animation_type) {
3414                 case ANIMATION_FADE:
3415                         weston_fade_run(surface, 0.0, 1.0, 200.0, NULL, NULL);
3416                         break;
3417                 case ANIMATION_ZOOM:
3418                         weston_zoom_run(surface, 0.8, 1.0, NULL, NULL);
3419                         break;
3420                 default:
3421                         break;
3422                 }
3423         }
3424 }
3425
3426 static void
3427 configure(struct desktop_shell *shell, struct weston_surface *surface,
3428           float x, float y, int32_t width, int32_t height)
3429 {
3430         enum shell_surface_type surface_type = SHELL_SURFACE_NONE;
3431         struct shell_surface *shsurf;
3432         int32_t surf_x, surf_y;
3433
3434         shsurf = get_shell_surface(surface);
3435         if (shsurf)
3436                 surface_type = shsurf->type;
3437
3438         weston_surface_configure(surface, x, y, width, height);
3439
3440         switch (surface_type) {
3441         case SHELL_SURFACE_FULLSCREEN:
3442                 shell_stack_fullscreen(shsurf);
3443                 shell_configure_fullscreen(shsurf);
3444                 break;
3445         case SHELL_SURFACE_MAXIMIZED:
3446                 /* setting x, y and using configure to change that geometry */
3447                 surface_subsurfaces_boundingbox(shsurf->surface, &surf_x, &surf_y,
3448                                                                  NULL, NULL);
3449                 surface->geometry.x = surface->output->x - surf_x;
3450                 surface->geometry.y = surface->output->y +
3451                 get_output_panel_height(shell,surface->output) - surf_y;
3452                 break;
3453         case SHELL_SURFACE_TOPLEVEL:
3454                 break;
3455         default:
3456                 break;
3457         }
3458
3459         /* XXX: would a fullscreen surface need the same handling? */
3460         if (surface->output) {
3461                 weston_surface_update_transform(surface);
3462
3463                 if (surface_type == SHELL_SURFACE_MAXIMIZED)
3464                         surface->output = shsurf->output;
3465         }
3466 }
3467
3468 static void
3469 shell_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height)
3470 {
3471         struct shell_surface *shsurf = get_shell_surface(es);
3472         struct desktop_shell *shell = shsurf->shell;
3473
3474         int type_changed = 0;
3475
3476         if (!weston_surface_is_mapped(es) && !wl_list_empty(&shsurf->popup.grab_link)) {
3477                 remove_popup_grab(shsurf);
3478         }
3479
3480         if (width == 0)
3481                 return;
3482
3483         if (shsurf->next_type != SHELL_SURFACE_NONE &&
3484             shsurf->type != shsurf->next_type) {
3485                 set_surface_type(shsurf);
3486                 type_changed = 1;
3487         }
3488
3489         if (!weston_surface_is_mapped(es)) {
3490                 map(shell, es, width, height, sx, sy);
3491         } else if (type_changed || sx != 0 || sy != 0 ||
3492                    es->geometry.width != width ||
3493                    es->geometry.height != height) {
3494                 float from_x, from_y;
3495                 float to_x, to_y;
3496
3497                 weston_surface_to_global_float(es, 0, 0, &from_x, &from_y);
3498                 weston_surface_to_global_float(es, sx, sy, &to_x, &to_y);
3499                 configure(shell, es,
3500                           es->geometry.x + to_x - from_x,
3501                           es->geometry.y + to_y - from_y,
3502                           width, height);
3503         }
3504 }
3505
3506 static void launch_desktop_shell_process(void *data);
3507
3508 static void
3509 desktop_shell_sigchld(struct weston_process *process, int status)
3510 {
3511         uint32_t time;
3512         struct desktop_shell *shell =
3513                 container_of(process, struct desktop_shell, child.process);
3514
3515         shell->child.process.pid = 0;
3516         shell->child.client = NULL; /* already destroyed by wayland */
3517
3518         /* if desktop-shell dies more than 5 times in 30 seconds, give up */
3519         time = weston_compositor_get_time();
3520         if (time - shell->child.deathstamp > 30000) {
3521                 shell->child.deathstamp = time;
3522                 shell->child.deathcount = 0;
3523         }
3524
3525         shell->child.deathcount++;
3526         if (shell->child.deathcount > 5) {
3527                 weston_log("weston-desktop-shell died, giving up.\n");
3528                 return;
3529         }
3530
3531         weston_log("weston-desktop-shell died, respawning...\n");
3532         launch_desktop_shell_process(shell);
3533         shell_fade_startup(shell);
3534 }
3535
3536 static void
3537 launch_desktop_shell_process(void *data)
3538 {
3539         struct desktop_shell *shell = data;
3540         const char *shell_exe = LIBEXECDIR "/weston-desktop-shell";
3541
3542         shell->child.client = weston_client_launch(shell->compositor,
3543                                                  &shell->child.process,
3544                                                  shell_exe,
3545                                                  desktop_shell_sigchld);
3546
3547         if (!shell->child.client)
3548                 weston_log("not able to start %s\n", shell_exe);
3549 }
3550
3551 static void
3552 bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
3553 {
3554         struct desktop_shell *shell = data;
3555
3556         wl_client_add_object(client, &wl_shell_interface,
3557                              &shell_implementation, id, shell);
3558 }
3559
3560 static void
3561 unbind_desktop_shell(struct wl_resource *resource)
3562 {
3563         struct desktop_shell *shell = resource->data;
3564
3565         if (shell->locked)
3566                 resume_desktop(shell);
3567
3568         shell->child.desktop_shell = NULL;
3569         shell->prepare_event_sent = false;
3570         free(resource);
3571 }
3572
3573 static void
3574 bind_desktop_shell(struct wl_client *client,
3575                    void *data, uint32_t version, uint32_t id)
3576 {
3577         struct desktop_shell *shell = data;
3578         struct wl_resource *resource;
3579
3580         resource = wl_client_add_object(client, &desktop_shell_interface,
3581                                         &desktop_shell_implementation,
3582                                         id, shell);
3583
3584         if (client == shell->child.client) {
3585                 resource->destroy = unbind_desktop_shell;
3586                 shell->child.desktop_shell = resource;
3587
3588                 if (version < 2)
3589                         shell_fade_startup(shell);
3590
3591                 return;
3592         }
3593
3594         wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
3595                                "permission to bind desktop_shell denied");
3596         wl_resource_destroy(resource);
3597 }
3598
3599 static void
3600 screensaver_configure(struct weston_surface *surface, int32_t sx, int32_t sy, int32_t width, int32_t height)
3601 {
3602         struct desktop_shell *shell = surface->configure_private;
3603
3604         if (width == 0)
3605                 return;
3606
3607         /* XXX: starting weston-screensaver beforehand does not work */
3608         if (!shell->locked)
3609                 return;
3610
3611         center_on_output(surface, surface->output);
3612
3613         if (wl_list_empty(&surface->layer_link)) {
3614                 wl_list_insert(shell->lock_layer.surface_list.prev,
3615                                &surface->layer_link);
3616                 weston_surface_update_transform(surface);
3617                 wl_event_source_timer_update(shell->screensaver.timer,
3618                                              shell->screensaver.duration);
3619                 shell_fade(shell, FADE_IN);
3620         }
3621 }
3622
3623 static void
3624 screensaver_set_surface(struct wl_client *client,
3625                         struct wl_resource *resource,
3626                         struct wl_resource *surface_resource,
3627                         struct wl_resource *output_resource)
3628 {
3629         struct desktop_shell *shell = resource->data;
3630         struct weston_surface *surface = surface_resource->data;
3631         struct weston_output *output = output_resource->data;
3632
3633         surface->configure = screensaver_configure;
3634         surface->configure_private = shell;
3635         surface->output = output;
3636 }
3637
3638 static const struct screensaver_interface screensaver_implementation = {
3639         screensaver_set_surface
3640 };
3641
3642 static void
3643 unbind_screensaver(struct wl_resource *resource)
3644 {
3645         struct desktop_shell *shell = resource->data;
3646
3647         shell->screensaver.binding = NULL;
3648         free(resource);
3649 }
3650
3651 static void
3652 bind_screensaver(struct wl_client *client,
3653                  void *data, uint32_t version, uint32_t id)
3654 {
3655         struct desktop_shell *shell = data;
3656         struct wl_resource *resource;
3657
3658         resource = wl_client_add_object(client, &screensaver_interface,
3659                                         &screensaver_implementation,
3660                                         id, shell);
3661
3662         if (shell->screensaver.binding == NULL) {
3663                 resource->destroy = unbind_screensaver;
3664                 shell->screensaver.binding = resource;
3665                 return;
3666         }
3667
3668         wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
3669                                "interface object already bound");
3670         wl_resource_destroy(resource);
3671 }
3672
3673 static void
3674 input_panel_configure(struct weston_surface *surface, int32_t sx, int32_t sy, int32_t width, int32_t height)
3675 {
3676         struct input_panel_surface *ip_surface = surface->configure_private;
3677         struct desktop_shell *shell = ip_surface->shell;
3678         struct weston_mode *mode;
3679         float x, y;
3680         uint32_t show_surface = 0;
3681
3682         if (width == 0)
3683                 return;
3684
3685         if (!weston_surface_is_mapped(surface)) {
3686                 if (!shell->showing_input_panels)
3687                         return;
3688
3689                 show_surface = 1;
3690         }
3691
3692         fprintf(stderr, "%s panel: %d, output: %p\n", __FUNCTION__, ip_surface->panel, ip_surface->output);
3693
3694         if (ip_surface->panel) {
3695                 x = shell->text_input.surface->geometry.x + shell->text_input.cursor_rectangle.x2;
3696                 y = shell->text_input.surface->geometry.y + shell->text_input.cursor_rectangle.y2;
3697         } else {
3698                 mode = ip_surface->output->current;
3699
3700                 x = ip_surface->output->x + (mode->width - width) / 2;
3701                 y = ip_surface->output->y + mode->height - height;
3702         }
3703
3704         weston_surface_configure(surface,
3705                                  x, y,
3706                                  width, height);
3707
3708         if (show_surface) {
3709                 wl_list_insert(&shell->input_panel_layer.surface_list,
3710                                &surface->layer_link);
3711                 weston_surface_update_transform(surface);
3712                 weston_surface_damage(surface);
3713                 weston_slide_run(surface, surface->geometry.height, 0, NULL, NULL);
3714         }
3715 }
3716
3717 static void
3718 destroy_input_panel_surface(struct input_panel_surface *input_panel_surface)
3719 {
3720         wl_list_remove(&input_panel_surface->surface_destroy_listener.link);
3721         wl_list_remove(&input_panel_surface->link);
3722
3723         input_panel_surface->surface->configure = NULL;
3724
3725         free(input_panel_surface);
3726 }
3727
3728 static struct input_panel_surface *
3729 get_input_panel_surface(struct weston_surface *surface)
3730 {
3731         if (surface->configure == input_panel_configure) {
3732                 return surface->configure_private;
3733         } else {
3734                 return NULL;
3735         }
3736 }
3737
3738 static void
3739 input_panel_handle_surface_destroy(struct wl_listener *listener, void *data)
3740 {
3741         struct input_panel_surface *ipsurface = container_of(listener,
3742                                                              struct input_panel_surface,
3743                                                              surface_destroy_listener);
3744
3745         if (ipsurface->resource.client) {
3746                 wl_resource_destroy(&ipsurface->resource);
3747         } else {
3748                 wl_signal_emit(&ipsurface->resource.destroy_signal,
3749                                &ipsurface->resource);
3750                 destroy_input_panel_surface(ipsurface);
3751         }
3752 }
3753 static struct input_panel_surface *
3754 create_input_panel_surface(struct desktop_shell *shell,
3755                            struct weston_surface *surface)
3756 {
3757         struct input_panel_surface *input_panel_surface;
3758
3759         input_panel_surface = calloc(1, sizeof *input_panel_surface);
3760         if (!input_panel_surface)
3761                 return NULL;
3762
3763         surface->configure = input_panel_configure;
3764         surface->configure_private = input_panel_surface;
3765
3766         input_panel_surface->shell = shell;
3767
3768         input_panel_surface->surface = surface;
3769
3770         wl_signal_init(&input_panel_surface->resource.destroy_signal);
3771         input_panel_surface->surface_destroy_listener.notify = input_panel_handle_surface_destroy;
3772         wl_signal_add(&surface->resource.destroy_signal,
3773                       &input_panel_surface->surface_destroy_listener);
3774
3775         wl_list_init(&input_panel_surface->link);
3776
3777         return input_panel_surface;
3778 }
3779
3780 static void
3781 input_panel_surface_set_toplevel(struct wl_client *client,
3782                                  struct wl_resource *resource,
3783                                  struct wl_resource *output_resource,
3784                                  uint32_t position)
3785 {
3786         struct input_panel_surface *input_panel_surface = resource->data;
3787         struct desktop_shell *shell = input_panel_surface->shell;
3788
3789         wl_list_insert(&shell->input_panel.surfaces,
3790                        &input_panel_surface->link);
3791
3792         input_panel_surface->output = output_resource->data;
3793         input_panel_surface->panel = 0;
3794
3795         fprintf(stderr, "%s panel: %d, output: %p\n", __FUNCTION__,
3796                 input_panel_surface->panel,
3797                 input_panel_surface->output);
3798 }
3799
3800 static void
3801 input_panel_surface_set_overlay_panel(struct wl_client *client,
3802                                       struct wl_resource *resource)
3803 {
3804         struct input_panel_surface *input_panel_surface = resource->data;
3805         struct desktop_shell *shell = input_panel_surface->shell;
3806
3807         wl_list_insert(&shell->input_panel.surfaces,
3808                        &input_panel_surface->link);
3809
3810         input_panel_surface->panel = 1;
3811 }
3812
3813 static const struct wl_input_panel_surface_interface input_panel_surface_implementation = {
3814         input_panel_surface_set_toplevel,
3815         input_panel_surface_set_overlay_panel
3816 };
3817
3818 static void
3819 destroy_input_panel_surface_resource(struct wl_resource *resource)
3820 {
3821         struct input_panel_surface *ipsurf = resource->data;
3822
3823         destroy_input_panel_surface(ipsurf);
3824 }
3825
3826 static void
3827 input_panel_get_input_panel_surface(struct wl_client *client,
3828                                     struct wl_resource *resource,
3829                                     uint32_t id,
3830                                     struct wl_resource *surface_resource)
3831 {
3832         struct weston_surface *surface = surface_resource->data;
3833         struct desktop_shell *shell = resource->data;
3834         struct input_panel_surface *ipsurf;
3835
3836         if (get_input_panel_surface(surface)) {
3837                 wl_resource_post_error(surface_resource,
3838                                        WL_DISPLAY_ERROR_INVALID_OBJECT,
3839                                        "wl_input_panel::get_input_panel_surface already requested");
3840                 return;
3841         }
3842
3843         ipsurf = create_input_panel_surface(shell, surface);
3844         if (!ipsurf) {
3845                 wl_resource_post_error(surface_resource,
3846                                        WL_DISPLAY_ERROR_INVALID_OBJECT,
3847                                        "surface->configure already set");
3848                 return;
3849         }
3850
3851         ipsurf->resource.destroy = destroy_input_panel_surface_resource;
3852         ipsurf->resource.object.id = id;
3853         ipsurf->resource.object.interface = &wl_input_panel_surface_interface;
3854         ipsurf->resource.object.implementation =
3855                 (void (**)(void)) &input_panel_surface_implementation;
3856         ipsurf->resource.data = ipsurf;
3857
3858         wl_client_add_resource(client, &ipsurf->resource);
3859 }
3860
3861 static const struct wl_input_panel_interface input_panel_implementation = {
3862         input_panel_get_input_panel_surface
3863 };
3864
3865 static void
3866 unbind_input_panel(struct wl_resource *resource)
3867 {
3868         struct desktop_shell *shell = resource->data;
3869
3870         shell->input_panel.binding = NULL;
3871         free(resource);
3872 }
3873
3874 static void
3875 bind_input_panel(struct wl_client *client,
3876               void *data, uint32_t version, uint32_t id)
3877 {
3878         struct desktop_shell *shell = data;
3879         struct wl_resource *resource;
3880
3881         resource = wl_client_add_object(client, &wl_input_panel_interface,
3882                                         &input_panel_implementation,
3883                                         id, shell);
3884
3885         if (shell->input_panel.binding == NULL) {
3886                 resource->destroy = unbind_input_panel;
3887                 shell->input_panel.binding = resource;
3888                 return;
3889         }
3890
3891         wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
3892                                "interface object already bound");
3893         wl_resource_destroy(resource);
3894 }
3895
3896 struct switcher {
3897         struct desktop_shell *shell;
3898         struct weston_surface *current;
3899         struct wl_listener listener;
3900         struct weston_keyboard_grab grab;
3901 };
3902
3903 static void
3904 switcher_next(struct switcher *switcher)
3905 {
3906         struct weston_surface *surface;
3907         struct weston_surface *first = NULL, *prev = NULL, *next = NULL;
3908         struct shell_surface *shsurf;
3909         struct workspace *ws = get_current_workspace(switcher->shell);
3910
3911         wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
3912                 switch (get_shell_surface_type(surface)) {
3913                 case SHELL_SURFACE_TOPLEVEL:
3914                 case SHELL_SURFACE_FULLSCREEN:
3915                 case SHELL_SURFACE_MAXIMIZED:
3916                         if (first == NULL)
3917                                 first = surface;
3918                         if (prev == switcher->current)
3919                                 next = surface;
3920                         prev = surface;
3921                         surface->alpha = 0.25;
3922                         weston_surface_geometry_dirty(surface);
3923                         weston_surface_damage(surface);
3924                         break;
3925                 default:
3926                         break;
3927                 }
3928
3929                 if (is_black_surface(surface, NULL)) {
3930                         surface->alpha = 0.25;
3931                         weston_surface_geometry_dirty(surface);
3932                         weston_surface_damage(surface);
3933                 }
3934         }
3935
3936         if (next == NULL)
3937                 next = first;
3938
3939         if (next == NULL)
3940                 return;
3941
3942         wl_list_remove(&switcher->listener.link);
3943         wl_signal_add(&next->resource.destroy_signal, &switcher->listener);
3944
3945         switcher->current = next;
3946         next->alpha = 1.0;
3947
3948         shsurf = get_shell_surface(switcher->current);
3949         if (shsurf && shsurf->type ==SHELL_SURFACE_FULLSCREEN)
3950                 shsurf->fullscreen.black_surface->alpha = 1.0;
3951 }
3952
3953 static void
3954 switcher_handle_surface_destroy(struct wl_listener *listener, void *data)
3955 {
3956         struct switcher *switcher =
3957                 container_of(listener, struct switcher, listener);
3958
3959         switcher_next(switcher);
3960 }
3961
3962 static void
3963 switcher_destroy(struct switcher *switcher)
3964 {
3965         struct weston_surface *surface;
3966         struct weston_keyboard *keyboard = switcher->grab.keyboard;
3967         struct workspace *ws = get_current_workspace(switcher->shell);
3968
3969         wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
3970                 surface->alpha = 1.0;
3971                 weston_surface_damage(surface);
3972         }
3973
3974         if (switcher->current)
3975                 activate(switcher->shell, switcher->current,
3976                          (struct weston_seat *) keyboard->seat);
3977         wl_list_remove(&switcher->listener.link);
3978         weston_keyboard_end_grab(keyboard);
3979         if (keyboard->input_method_resource)
3980                 keyboard->grab = &keyboard->input_method_grab;
3981         free(switcher);
3982 }
3983
3984 static void
3985 switcher_key(struct weston_keyboard_grab *grab,
3986              uint32_t time, uint32_t key, uint32_t state_w)
3987 {
3988         struct switcher *switcher = container_of(grab, struct switcher, grab);
3989         enum wl_keyboard_key_state state = state_w;
3990
3991         if (key == KEY_TAB && state == WL_KEYBOARD_KEY_STATE_PRESSED)
3992                 switcher_next(switcher);
3993 }
3994
3995 static void
3996 switcher_modifier(struct weston_keyboard_grab *grab, uint32_t serial,
3997                   uint32_t mods_depressed, uint32_t mods_latched,
3998                   uint32_t mods_locked, uint32_t group)
3999 {
4000         struct switcher *switcher = container_of(grab, struct switcher, grab);
4001         struct weston_seat *seat = (struct weston_seat *) grab->keyboard->seat;
4002
4003         if ((seat->modifier_state & switcher->shell->binding_modifier) == 0)
4004                 switcher_destroy(switcher);
4005 }
4006
4007 static const struct weston_keyboard_grab_interface switcher_grab = {
4008         switcher_key,
4009         switcher_modifier,
4010 };
4011
4012 static void
4013 switcher_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
4014                  void *data)
4015 {
4016         struct desktop_shell *shell = data;
4017         struct switcher *switcher;
4018
4019         switcher = malloc(sizeof *switcher);
4020         switcher->shell = shell;
4021         switcher->current = NULL;
4022         switcher->listener.notify = switcher_handle_surface_destroy;
4023         wl_list_init(&switcher->listener.link);
4024
4025         lower_fullscreen_layer(switcher->shell);
4026         switcher->grab.interface = &switcher_grab;
4027         weston_keyboard_start_grab(seat->keyboard, &switcher->grab);
4028         weston_keyboard_set_focus(seat->keyboard, NULL);
4029         switcher_next(switcher);
4030 }
4031
4032 static void
4033 backlight_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
4034                   void *data)
4035 {
4036         struct weston_compositor *compositor = data;
4037         struct weston_output *output;
4038         long backlight_new = 0;
4039
4040         /* TODO: we're limiting to simple use cases, where we assume just
4041          * control on the primary display. We'd have to extend later if we
4042          * ever get support for setting backlights on random desktop LCD
4043          * panels though */
4044         output = get_default_output(compositor);
4045         if (!output)
4046                 return;
4047
4048         if (!output->set_backlight)
4049                 return;
4050
4051         if (key == KEY_F9 || key == KEY_BRIGHTNESSDOWN)
4052                 backlight_new = output->backlight_current - 25;
4053         else if (key == KEY_F10 || key == KEY_BRIGHTNESSUP)
4054                 backlight_new = output->backlight_current + 25;
4055
4056         if (backlight_new < 5)
4057                 backlight_new = 5;
4058         if (backlight_new > 255)
4059                 backlight_new = 255;
4060
4061         output->backlight_current = backlight_new;
4062         output->set_backlight(output, output->backlight_current);
4063 }
4064
4065 struct debug_binding_grab {
4066         struct weston_keyboard_grab grab;
4067         struct weston_seat *seat;
4068         uint32_t key[2];
4069         int key_released[2];
4070 };
4071
4072 static void
4073 debug_binding_key(struct weston_keyboard_grab *grab, uint32_t time,
4074                   uint32_t key, uint32_t state)
4075 {
4076         struct debug_binding_grab *db = (struct debug_binding_grab *) grab;
4077         struct wl_resource *resource;
4078         struct wl_display *display;
4079         uint32_t serial;
4080         int send = 0, terminate = 0;
4081         int check_binding = 1;
4082         int i;
4083
4084         if (state == WL_KEYBOARD_KEY_STATE_RELEASED) {
4085                 /* Do not run bindings on key releases */
4086                 check_binding = 0;
4087
4088                 for (i = 0; i < 2; i++)
4089                         if (key == db->key[i])
4090                                 db->key_released[i] = 1;
4091
4092                 if (db->key_released[0] && db->key_released[1]) {
4093                         /* All key releases been swalled so end the grab */
4094                         terminate = 1;
4095                 } else if (key != db->key[0] && key != db->key[1]) {
4096                         /* Should not swallow release of other keys */
4097                         send = 1;
4098                 }
4099         } else if (key == db->key[0] && !db->key_released[0]) {
4100                 /* Do not check bindings for the first press of the binding
4101                  * key. This allows it to be used as a debug shortcut.
4102                  * We still need to swallow this event. */
4103                 check_binding = 0;
4104         } else if (db->key[1]) {
4105                 /* If we already ran a binding don't process another one since
4106                  * we can't keep track of all the binding keys that were
4107                  * pressed in order to swallow the release events. */
4108                 send = 1;
4109                 check_binding = 0;
4110         }
4111
4112         if (check_binding) {
4113                 struct weston_compositor *ec = db->seat->compositor;
4114
4115                 if (weston_compositor_run_debug_binding(ec, db->seat, time,
4116                                                         key, state)) {
4117                         /* We ran a binding so swallow the press and keep the
4118                          * grab to swallow the released too. */
4119                         send = 0;
4120                         terminate = 0;
4121                         db->key[1] = key;
4122                 } else {
4123                         /* Terminate the grab since the key pressed is not a
4124                          * debug binding key. */
4125                         send = 1;
4126                         terminate = 1;
4127                 }
4128         }
4129
4130         if (send) {
4131                 resource = grab->keyboard->focus_resource;
4132
4133                 if (resource) {
4134                         display = wl_client_get_display(resource->client);
4135                         serial = wl_display_next_serial(display);
4136                         wl_keyboard_send_key(resource, serial, time, key, state);
4137                 }
4138         }
4139
4140         if (terminate) {
4141                 weston_keyboard_end_grab(grab->keyboard);
4142                 if (grab->keyboard->input_method_resource)
4143                         grab->keyboard->grab = &grab->keyboard->input_method_grab;
4144                 free(db);
4145         }
4146 }
4147
4148 static void
4149 debug_binding_modifiers(struct weston_keyboard_grab *grab, uint32_t serial,
4150                         uint32_t mods_depressed, uint32_t mods_latched,
4151                         uint32_t mods_locked, uint32_t group)
4152 {
4153         struct wl_resource *resource;
4154
4155         resource = grab->keyboard->focus_resource;
4156         if (!resource)
4157                 return;
4158
4159         wl_keyboard_send_modifiers(resource, serial, mods_depressed,
4160                                    mods_latched, mods_locked, group);
4161 }
4162
4163 struct weston_keyboard_grab_interface debug_binding_keyboard_grab = {
4164         debug_binding_key,
4165         debug_binding_modifiers
4166 };
4167
4168 static void
4169 debug_binding(struct weston_seat *seat, uint32_t time, uint32_t key, void *data)
4170 {
4171         struct debug_binding_grab *grab;
4172
4173         grab = calloc(1, sizeof *grab);
4174         if (!grab)
4175                 return;
4176
4177         grab->seat = (struct weston_seat *) seat;
4178         grab->key[0] = key;
4179         grab->grab.interface = &debug_binding_keyboard_grab;
4180         weston_keyboard_start_grab(seat->keyboard, &grab->grab);
4181 }
4182
4183 static void
4184 force_kill_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
4185                    void *data)
4186 {
4187         struct weston_surface *focus_surface;
4188         struct wl_client *client;
4189         struct desktop_shell *shell = data;
4190         struct weston_compositor *compositor = shell->compositor;
4191         pid_t pid;
4192
4193         focus_surface = seat->keyboard->focus;
4194         if (!focus_surface)
4195                 return;
4196
4197         wl_signal_emit(&compositor->kill_signal, focus_surface);
4198
4199         client = focus_surface->resource.client;
4200         wl_client_get_credentials(client, &pid, NULL, NULL);
4201
4202         /* Skip clients that we launched ourselves (the credentials of
4203          * the socketpair is ours) */
4204         if (pid == getpid())
4205                 return;
4206
4207         kill(pid, SIGKILL);
4208 }
4209
4210 static void
4211 workspace_up_binding(struct weston_seat *seat, uint32_t time,
4212                      uint32_t key, void *data)
4213 {
4214         struct desktop_shell *shell = data;
4215         unsigned int new_index = shell->workspaces.current;
4216
4217         if (shell->locked)
4218                 return;
4219         if (new_index != 0)
4220                 new_index--;
4221
4222         change_workspace(shell, new_index);
4223 }
4224
4225 static void
4226 workspace_down_binding(struct weston_seat *seat, uint32_t time,
4227                        uint32_t key, void *data)
4228 {
4229         struct desktop_shell *shell = data;
4230         unsigned int new_index = shell->workspaces.current;
4231
4232         if (shell->locked)
4233                 return;
4234         if (new_index < shell->workspaces.num - 1)
4235                 new_index++;
4236
4237         change_workspace(shell, new_index);
4238 }
4239
4240 static void
4241 workspace_f_binding(struct weston_seat *seat, uint32_t time,
4242                     uint32_t key, void *data)
4243 {
4244         struct desktop_shell *shell = data;
4245         unsigned int new_index;
4246
4247         if (shell->locked)
4248                 return;
4249         new_index = key - KEY_F1;
4250         if (new_index >= shell->workspaces.num)
4251                 new_index = shell->workspaces.num - 1;
4252
4253         change_workspace(shell, new_index);
4254 }
4255
4256 static void
4257 workspace_move_surface_up_binding(struct weston_seat *seat, uint32_t time,
4258                                   uint32_t key, void *data)
4259 {
4260         struct desktop_shell *shell = data;
4261         unsigned int new_index = shell->workspaces.current;
4262
4263         if (shell->locked)
4264                 return;
4265
4266         if (new_index != 0)
4267                 new_index--;
4268
4269         take_surface_to_workspace_by_seat(shell, seat, new_index);
4270 }
4271
4272 static void
4273 workspace_move_surface_down_binding(struct weston_seat *seat, uint32_t time,
4274                                     uint32_t key, void *data)
4275 {
4276         struct desktop_shell *shell = data;
4277         unsigned int new_index = shell->workspaces.current;
4278
4279         if (shell->locked)
4280                 return;
4281
4282         if (new_index < shell->workspaces.num - 1)
4283                 new_index++;
4284
4285         take_surface_to_workspace_by_seat(shell, seat, new_index);
4286 }
4287
4288 static void
4289 shell_destroy(struct wl_listener *listener, void *data)
4290 {
4291         struct desktop_shell *shell =
4292                 container_of(listener, struct desktop_shell, destroy_listener);
4293         struct workspace **ws;
4294
4295         if (shell->child.client)
4296                 wl_client_destroy(shell->child.client);
4297
4298         wl_list_remove(&shell->idle_listener.link);
4299         wl_list_remove(&shell->wake_listener.link);
4300         wl_list_remove(&shell->show_input_panel_listener.link);
4301         wl_list_remove(&shell->hide_input_panel_listener.link);
4302
4303         wl_array_for_each(ws, &shell->workspaces.array)
4304                 workspace_destroy(*ws);
4305         wl_array_release(&shell->workspaces.array);
4306
4307         free(shell->screensaver.path);
4308         free(shell);
4309 }
4310
4311 static void
4312 shell_add_bindings(struct weston_compositor *ec, struct desktop_shell *shell)
4313 {
4314         uint32_t mod;
4315         int i, num_workspace_bindings;
4316
4317         /* fixed bindings */
4318         weston_compositor_add_key_binding(ec, KEY_BACKSPACE,
4319                                           MODIFIER_CTRL | MODIFIER_ALT,
4320                                           terminate_binding, ec);
4321         weston_compositor_add_button_binding(ec, BTN_LEFT, 0,
4322                                              click_to_activate_binding,
4323                                              shell);
4324         weston_compositor_add_axis_binding(ec, WL_POINTER_AXIS_VERTICAL_SCROLL,
4325                                            MODIFIER_SUPER | MODIFIER_ALT,
4326                                            surface_opacity_binding, NULL);
4327         weston_compositor_add_axis_binding(ec, WL_POINTER_AXIS_VERTICAL_SCROLL,
4328                                            MODIFIER_SUPER, zoom_axis_binding,
4329                                            NULL);
4330
4331         /* configurable bindings */
4332         mod = shell->binding_modifier;
4333         weston_compositor_add_key_binding(ec, KEY_PAGEUP, mod,
4334                                           zoom_key_binding, NULL);
4335         weston_compositor_add_key_binding(ec, KEY_PAGEDOWN, mod,
4336                                           zoom_key_binding, NULL);
4337         weston_compositor_add_button_binding(ec, BTN_LEFT, mod, move_binding,
4338                                              shell);
4339         weston_compositor_add_button_binding(ec, BTN_MIDDLE, mod,
4340                                              resize_binding, shell);
4341
4342         if (ec->capabilities & WESTON_CAP_ROTATION_ANY)
4343                 weston_compositor_add_button_binding(ec, BTN_RIGHT, mod,
4344                                                      rotate_binding, NULL);
4345
4346         weston_compositor_add_key_binding(ec, KEY_TAB, mod, switcher_binding,
4347                                           shell);
4348         weston_compositor_add_key_binding(ec, KEY_F9, mod, backlight_binding,
4349                                           ec);
4350         weston_compositor_add_key_binding(ec, KEY_BRIGHTNESSDOWN, 0,
4351                                           backlight_binding, ec);
4352         weston_compositor_add_key_binding(ec, KEY_F10, mod, backlight_binding,
4353                                           ec);
4354         weston_compositor_add_key_binding(ec, KEY_BRIGHTNESSUP, 0,
4355                                           backlight_binding, ec);
4356         weston_compositor_add_key_binding(ec, KEY_K, mod,
4357                                           force_kill_binding, shell);
4358         weston_compositor_add_key_binding(ec, KEY_UP, mod,
4359                                           workspace_up_binding, shell);
4360         weston_compositor_add_key_binding(ec, KEY_DOWN, mod,
4361                                           workspace_down_binding, shell);
4362         weston_compositor_add_key_binding(ec, KEY_UP, mod | MODIFIER_SHIFT,
4363                                           workspace_move_surface_up_binding,
4364                                           shell);
4365         weston_compositor_add_key_binding(ec, KEY_DOWN, mod | MODIFIER_SHIFT,
4366                                           workspace_move_surface_down_binding,
4367                                           shell);
4368
4369         /* Add bindings for mod+F[1-6] for workspace 1 to 6. */
4370         if (shell->workspaces.num > 1) {
4371                 num_workspace_bindings = shell->workspaces.num;
4372                 if (num_workspace_bindings > 6)
4373                         num_workspace_bindings = 6;
4374                 for (i = 0; i < num_workspace_bindings; i++)
4375                         weston_compositor_add_key_binding(ec, KEY_F1 + i, mod,
4376                                                           workspace_f_binding,
4377                                                           shell);
4378         }
4379
4380         /* Debug bindings */
4381         weston_compositor_add_key_binding(ec, KEY_SPACE, mod | MODIFIER_SHIFT,
4382                                           debug_binding, shell);
4383 }
4384
4385 WL_EXPORT int
4386 module_init(struct weston_compositor *ec,
4387             int *argc, char *argv[])
4388 {
4389         struct weston_seat *seat;
4390         struct desktop_shell *shell;
4391         struct workspace **pws;
4392         unsigned int i;
4393         struct wl_event_loop *loop;
4394
4395         shell = malloc(sizeof *shell);
4396         if (shell == NULL)
4397                 return -1;
4398
4399         memset(shell, 0, sizeof *shell);
4400         shell->compositor = ec;
4401
4402         shell->destroy_listener.notify = shell_destroy;
4403         wl_signal_add(&ec->destroy_signal, &shell->destroy_listener);
4404         shell->idle_listener.notify = idle_handler;
4405         wl_signal_add(&ec->idle_signal, &shell->idle_listener);
4406         shell->wake_listener.notify = wake_handler;
4407         wl_signal_add(&ec->wake_signal, &shell->wake_listener);
4408         shell->show_input_panel_listener.notify = show_input_panels;
4409         wl_signal_add(&ec->show_input_panel_signal, &shell->show_input_panel_listener);
4410         shell->hide_input_panel_listener.notify = hide_input_panels;
4411         wl_signal_add(&ec->hide_input_panel_signal, &shell->hide_input_panel_listener);
4412         shell->update_input_panel_listener.notify = update_input_panels;
4413         wl_signal_add(&ec->update_input_panel_signal, &shell->update_input_panel_listener);
4414         ec->ping_handler = ping_handler;
4415         ec->shell_interface.shell = shell;
4416         ec->shell_interface.create_shell_surface = create_shell_surface;
4417         ec->shell_interface.set_toplevel = set_toplevel;
4418         ec->shell_interface.set_transient = set_transient;
4419         ec->shell_interface.set_fullscreen = set_fullscreen;
4420         ec->shell_interface.move = surface_move;
4421         ec->shell_interface.resize = surface_resize;
4422
4423         wl_list_init(&shell->input_panel.surfaces);
4424
4425         weston_layer_init(&shell->fullscreen_layer, &ec->cursor_layer.link);
4426         weston_layer_init(&shell->panel_layer, &shell->fullscreen_layer.link);
4427         weston_layer_init(&shell->background_layer, &shell->panel_layer.link);
4428         weston_layer_init(&shell->lock_layer, NULL);
4429         weston_layer_init(&shell->input_panel_layer, NULL);
4430
4431         wl_array_init(&shell->workspaces.array);
4432         wl_list_init(&shell->workspaces.client_list);
4433
4434         shell_configuration(shell, ec->config_fd);
4435
4436         for (i = 0; i < shell->workspaces.num; i++) {
4437                 pws = wl_array_add(&shell->workspaces.array, sizeof *pws);
4438                 if (pws == NULL)
4439                         return -1;
4440
4441                 *pws = workspace_create();
4442                 if (*pws == NULL)
4443                         return -1;
4444         }
4445         activate_workspace(shell, 0);
4446
4447         wl_list_init(&shell->workspaces.anim_sticky_list);
4448         wl_list_init(&shell->workspaces.animation.link);
4449         shell->workspaces.animation.frame = animate_workspace_change_frame;
4450
4451         if (wl_display_add_global(ec->wl_display, &wl_shell_interface,
4452                                   shell, bind_shell) == NULL)
4453                 return -1;
4454
4455         if (wl_display_add_global(ec->wl_display,
4456                                   &desktop_shell_interface,
4457                                   shell, bind_desktop_shell) == NULL)
4458                 return -1;
4459
4460         if (wl_display_add_global(ec->wl_display, &screensaver_interface,
4461                                   shell, bind_screensaver) == NULL)
4462                 return -1;
4463
4464         if (wl_display_add_global(ec->wl_display, &wl_input_panel_interface,
4465                                   shell, bind_input_panel) == NULL)
4466                 return -1;
4467
4468         if (wl_display_add_global(ec->wl_display, &workspace_manager_interface,
4469                                   shell, bind_workspace_manager) == NULL)
4470                 return -1;
4471
4472         shell->child.deathstamp = weston_compositor_get_time();
4473
4474         loop = wl_display_get_event_loop(ec->wl_display);
4475         wl_event_loop_add_idle(loop, launch_desktop_shell_process, shell);
4476
4477         shell->screensaver.timer =
4478                 wl_event_loop_add_timer(loop, screensaver_timeout, shell);
4479
4480         wl_list_for_each(seat, &ec->seat_list, link)
4481                 create_pointer_focus_listener(seat);
4482
4483         shell_add_bindings(ec, shell);
4484
4485         shell_fade_init(shell);
4486
4487         return 0;
4488 }