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