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