switcher: Don't use compositor->surface_list
[profile/ivi/weston.git] / src / shell.c
1 /*
2  * Copyright © 2010-2012 Intel Corporation
3  * Copyright © 2011-2012 Collabora, Ltd.
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and
6  * its documentation for any purpose is hereby granted without fee, provided
7  * that the above copyright notice appear in all copies and that both that
8  * copyright notice and this permission notice appear in supporting
9  * documentation, and that the name of the copyright holders not be used in
10  * advertising or publicity pertaining to distribution of the software
11  * without specific, written prior permission.  The copyright holders make
12  * no representations about the suitability of this software for any
13  * purpose.  It is provided "as is" without express or implied warranty.
14  *
15  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
16  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
20  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  */
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <stdbool.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <linux/input.h>
30 #include <assert.h>
31 #include <signal.h>
32 #include <math.h>
33 #include <sys/types.h>
34
35 #include <wayland-server.h>
36 #include "compositor.h"
37 #include "desktop-shell-server-protocol.h"
38 #include "../shared/config-parser.h"
39 #include "log.h"
40
41 #define DEFAULT_NUM_WORKSPACES 1
42 #define DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH 200
43
44 enum animation_type {
45         ANIMATION_NONE,
46
47         ANIMATION_ZOOM,
48         ANIMATION_FADE
49 };
50
51 struct focus_state {
52         struct weston_seat *seat;
53         struct weston_surface *keyboard_focus;
54         struct wl_list link;
55         struct wl_listener seat_destroy_listener;
56         struct wl_listener surface_destroy_listener;
57 };
58
59 struct workspace {
60         struct weston_layer layer;
61
62         struct wl_list focus_list;
63         struct wl_listener seat_destroyed_listener;
64 };
65
66 struct desktop_shell {
67         struct weston_compositor *compositor;
68
69         struct wl_listener lock_listener;
70         struct wl_listener unlock_listener;
71         struct wl_listener destroy_listener;
72
73         struct weston_layer fullscreen_layer;
74         struct weston_layer panel_layer;
75         struct weston_layer background_layer;
76         struct weston_layer lock_layer;
77
78         struct wl_listener pointer_focus_listener;
79         struct weston_surface *busy_surface;
80
81         struct {
82                 struct weston_process process;
83                 struct wl_client *client;
84                 struct wl_resource *desktop_shell;
85
86                 unsigned deathcount;
87                 uint32_t deathstamp;
88         } child;
89
90         bool locked;
91         bool prepare_event_sent;
92
93         struct shell_surface *lock_surface;
94         struct wl_listener lock_surface_listener;
95
96         struct wl_list backgrounds;
97         struct wl_list panels;
98
99         struct {
100                 struct wl_array array;
101                 unsigned int current;
102                 unsigned int num;
103
104                 struct weston_animation animation;
105                 int anim_dir;
106                 uint32_t anim_timestamp;
107                 double anim_current;
108                 struct workspace *anim_from;
109                 struct workspace *anim_to;
110         } workspaces;
111
112         struct {
113                 char *path;
114                 int duration;
115                 struct wl_resource *binding;
116                 struct wl_list surfaces;
117                 struct weston_process process;
118         } screensaver;
119
120         uint32_t binding_modifier;
121         enum animation_type win_animation_type;
122         struct weston_surface *debug_repaint_surface;
123 };
124
125 enum shell_surface_type {
126         SHELL_SURFACE_NONE,
127
128         SHELL_SURFACE_PANEL,
129         SHELL_SURFACE_BACKGROUND,
130         SHELL_SURFACE_LOCK,
131         SHELL_SURFACE_SCREENSAVER,
132
133         SHELL_SURFACE_TOPLEVEL,
134         SHELL_SURFACE_TRANSIENT,
135         SHELL_SURFACE_FULLSCREEN,
136         SHELL_SURFACE_MAXIMIZED,
137         SHELL_SURFACE_POPUP
138 };
139
140 struct ping_timer {
141         struct wl_event_source *source;
142         uint32_t serial;
143 };
144
145 struct shell_surface {
146         struct wl_resource resource;
147
148         struct weston_surface *surface;
149         struct wl_listener surface_destroy_listener;
150         struct shell_surface *parent;
151         struct desktop_shell *shell;
152
153         enum shell_surface_type type, next_type;
154         char *title, *class;
155         int32_t saved_x, saved_y;
156         bool saved_position_valid;
157         bool saved_rotation_valid;
158         int unresponsive;
159
160         struct {
161                 struct weston_transform transform;
162                 struct weston_matrix rotation;
163         } rotation;
164
165         struct {
166                 struct wl_pointer_grab grab;
167                 int32_t x, y;
168                 struct weston_transform parent_transform;
169                 int32_t initial_up;
170                 struct wl_seat *seat;
171                 uint32_t serial;
172         } popup;
173
174         struct {
175                 int32_t x, y;
176                 uint32_t flags;
177         } transient;
178
179         struct {
180                 enum wl_shell_surface_fullscreen_method type;
181                 struct weston_transform transform; /* matrix from x, y */
182                 uint32_t framerate;
183                 struct weston_surface *black_surface;
184         } fullscreen;
185
186         struct ping_timer *ping_timer;
187
188         struct weston_transform workspace_transform;
189
190         struct focus_state *focus_state;
191
192         struct weston_output *fullscreen_output;
193         struct weston_output *output;
194         struct wl_list link;
195
196         const struct weston_shell_client *client;
197 };
198
199 struct shell_grab {
200         struct wl_pointer_grab grab;
201         struct shell_surface *shsurf;
202         struct wl_listener shsurf_destroy_listener;
203 };
204
205 struct weston_move_grab {
206         struct shell_grab base;
207         wl_fixed_t dx, dy;
208 };
209
210 struct rotate_grab {
211         struct shell_grab base;
212         struct weston_matrix rotation;
213         struct {
214                 GLfloat x;
215                 GLfloat y;
216         } center;
217 };
218
219 static struct shell_surface *
220 get_shell_surface(struct weston_surface *surface);
221
222 static struct desktop_shell *
223 shell_surface_get_shell(struct shell_surface *shsurf);
224
225 static bool
226 shell_surface_is_top_fullscreen(struct shell_surface *shsurf)
227 {
228         struct desktop_shell *shell;
229         struct weston_surface *top_fs_es;
230
231         shell = shell_surface_get_shell(shsurf);
232         
233         if (wl_list_empty(&shell->fullscreen_layer.surface_list))
234                 return false;
235
236         top_fs_es = container_of(shell->fullscreen_layer.surface_list.next,
237                                  struct weston_surface, 
238                                  layer_link);
239         return (shsurf == get_shell_surface(top_fs_es));
240 }
241
242 static void
243 destroy_shell_grab_shsurf(struct wl_listener *listener, void *data)
244 {
245         struct shell_grab *grab;
246
247         grab = container_of(listener, struct shell_grab,
248                             shsurf_destroy_listener);
249
250         grab->shsurf = NULL;
251 }
252
253 static void
254 shell_grab_init(struct shell_grab *grab,
255                 const struct wl_pointer_grab_interface *interface,
256                 struct shell_surface *shsurf)
257 {
258         grab->grab.interface = interface;
259         grab->shsurf = shsurf;
260         grab->shsurf_destroy_listener.notify = destroy_shell_grab_shsurf;
261         wl_signal_add(&shsurf->resource.destroy_signal,
262                       &grab->shsurf_destroy_listener);
263
264 }
265
266 static void
267 shell_grab_finish(struct shell_grab *grab)
268 {
269         if (grab->shsurf)
270                 wl_list_remove(&grab->shsurf_destroy_listener.link);
271 }
272
273 static void
274 center_on_output(struct weston_surface *surface,
275                  struct weston_output *output);
276
277 static enum weston_keyboard_modifier
278 get_modifier(char *modifier)
279 {
280         if (!modifier)
281                 return MODIFIER_SUPER;
282
283         if (!strcmp("ctrl", modifier))
284                 return MODIFIER_CTRL;
285         else if (!strcmp("alt", modifier))
286                 return MODIFIER_ALT;
287         else if (!strcmp("super", modifier))
288                 return MODIFIER_SUPER;
289         else
290                 return MODIFIER_SUPER;
291 }
292
293 static enum animation_type
294 get_animation_type(char *animation)
295 {
296         if (!animation)
297                 return ANIMATION_NONE;
298
299         if (!strcmp("zoom", animation))
300                 return ANIMATION_ZOOM;
301         else if (!strcmp("fade", animation))
302                 return ANIMATION_FADE;
303         else
304                 return ANIMATION_NONE;
305 }
306
307 static void
308 shell_configuration(struct desktop_shell *shell)
309 {
310         char *config_file;
311         char *path = NULL;
312         int duration = 60;
313         unsigned int num_workspaces = DEFAULT_NUM_WORKSPACES;
314         char *modifier = NULL;
315         char *win_animation = NULL;
316
317         struct config_key shell_keys[] = {
318                 { "binding-modifier",   CONFIG_KEY_STRING, &modifier },
319                 { "animation",          CONFIG_KEY_STRING, &win_animation},
320                 { "num-workspaces",
321                         CONFIG_KEY_UNSIGNED_INTEGER, &num_workspaces },
322         };
323
324         struct config_key saver_keys[] = {
325                 { "path",       CONFIG_KEY_STRING,  &path },
326                 { "duration",   CONFIG_KEY_INTEGER, &duration },
327         };
328
329         struct config_section cs[] = {
330                 { "shell", shell_keys, ARRAY_LENGTH(shell_keys), NULL },
331                 { "screensaver", saver_keys, ARRAY_LENGTH(saver_keys), NULL },
332         };
333
334         config_file = config_file_path("weston.ini");
335         parse_config_file(config_file, cs, ARRAY_LENGTH(cs), shell);
336         free(config_file);
337
338         shell->screensaver.path = path;
339         shell->screensaver.duration = duration;
340         shell->binding_modifier = get_modifier(modifier);
341         shell->win_animation_type = get_animation_type(win_animation);
342         shell->workspaces.num = num_workspaces > 0 ? num_workspaces : 1;
343 }
344
345 static void
346 focus_state_destroy(struct focus_state *state)
347 {
348         wl_list_remove(&state->seat_destroy_listener.link);
349         wl_list_remove(&state->surface_destroy_listener.link);
350         free(state);
351 }
352
353 static void
354 focus_state_seat_destroy(struct wl_listener *listener, void *data)
355 {
356         struct focus_state *state = container_of(listener,
357                                                  struct focus_state,
358                                                  seat_destroy_listener);
359
360         wl_list_remove(&state->link);
361         focus_state_destroy(state);
362 }
363
364 static void
365 focus_state_surface_destroy(struct wl_listener *listener, void *data)
366 {
367         struct focus_state *state = container_of(listener,
368                                                  struct focus_state,
369                                                  seat_destroy_listener);
370
371         wl_list_remove(&state->link);
372         focus_state_destroy(state);
373 }
374
375 static struct focus_state *
376 focus_state_create(struct weston_seat *seat)
377 {
378         struct wl_keyboard *keyboard = seat->seat.keyboard;
379         struct focus_state *state;
380         struct wl_surface *surface;
381         struct shell_surface *shsurf;
382
383         state = malloc(sizeof *state);
384         if (state == NULL)
385                 return NULL;
386
387         surface = keyboard->focus;
388         shsurf = get_shell_surface((struct weston_surface *)keyboard->focus);
389         shsurf->focus_state = state;
390
391         state->seat = seat;
392         state->keyboard_focus = shsurf->surface;
393         wl_list_init(&state->link);
394
395         state->seat_destroy_listener.notify = focus_state_seat_destroy;
396         state->surface_destroy_listener.notify = focus_state_surface_destroy;
397         wl_signal_add(&seat->seat.destroy_signal,
398                       &state->seat_destroy_listener);
399         wl_signal_add(&surface->resource.destroy_signal,
400                       &state->surface_destroy_listener);
401
402         return state;
403 }
404
405 static void
406 pop_focus_state(struct desktop_shell *shell, struct workspace *ws)
407 {
408         struct focus_state *state, *next;
409
410         wl_list_for_each_safe(state, next, &ws->focus_list, link) {
411                 if (state->keyboard_focus)
412                         wl_keyboard_set_focus(state->seat->seat.keyboard,
413                                               &state->keyboard_focus->surface);
414
415                 focus_state_destroy(state);
416         }
417         wl_list_init(&ws->focus_list);
418 }
419
420 static void
421 push_focus_state(struct desktop_shell *shell, struct workspace *ws)
422 {
423         struct weston_seat *seat;
424         struct focus_state *state;
425         struct wl_keyboard *keyboard;
426
427         wl_list_for_each(seat, &shell->compositor->seat_list, link) {
428                 keyboard = seat->seat.keyboard;
429                 if (keyboard && keyboard->focus) {
430                         state = focus_state_create(seat);
431                         if (state == NULL)
432                                 return;
433
434                         wl_list_insert(&ws->focus_list, &state->link);
435
436                         wl_keyboard_set_focus(seat->seat.keyboard, NULL);
437                 }
438         }
439 }
440
441 static void
442 workspace_destroy(struct workspace *ws)
443 {
444         struct focus_state *state, *next;
445
446         wl_list_for_each_safe(state, next, &ws->focus_list, link)
447                 focus_state_destroy(state);
448
449         free(ws);
450 }
451
452 static void
453 seat_destroyed(struct wl_listener *listener, void *data)
454 {
455         struct weston_seat *seat = data;
456         struct focus_state *state, *next;
457         struct workspace *ws = container_of(listener,
458                                             struct workspace,
459                                             seat_destroyed_listener);
460
461         wl_list_for_each_safe(state, next, &ws->focus_list, link)
462                 if (state->seat == seat)
463                         wl_list_remove(&state->link);
464 }
465
466 static struct workspace *
467 workspace_create(void)
468 {
469         struct workspace *ws = malloc(sizeof *ws);
470         if (ws == NULL)
471                 return NULL;
472
473         weston_layer_init(&ws->layer, NULL);
474
475         wl_list_init(&ws->focus_list);
476         wl_list_init(&ws->seat_destroyed_listener.link);
477         ws->seat_destroyed_listener.notify = seat_destroyed;
478
479         return ws;
480 }
481
482 static int
483 workspace_is_empty(struct workspace *ws)
484 {
485         return wl_list_empty(&ws->layer.surface_list);
486 }
487
488 static struct workspace *
489 get_workspace(struct desktop_shell *shell, unsigned int index)
490 {
491         struct workspace **pws = shell->workspaces.array.data;
492         pws += index;
493         return *pws;
494 }
495
496 static struct workspace *
497 get_current_workspace(struct desktop_shell *shell)
498 {
499         return get_workspace(shell, shell->workspaces.current);
500 }
501
502 static void
503 activate_workspace(struct desktop_shell *shell, unsigned int index)
504 {
505         struct workspace *ws;
506
507         ws = get_workspace(shell, index);
508         wl_list_insert(&shell->panel_layer.link, &ws->layer.link);
509
510         shell->workspaces.current = index;
511 }
512
513 static unsigned int
514 get_output_height(struct weston_output *output)
515 {
516         return abs(output->region.extents.y1 - output->region.extents.y2);
517 }
518
519 static void
520 surface_translate(struct weston_surface *surface, double d)
521 {
522         struct shell_surface *shsurf = get_shell_surface(surface);
523         struct weston_transform *transform;
524
525         transform = &shsurf->workspace_transform;
526         if (wl_list_empty(&transform->link))
527                 wl_list_insert(surface->geometry.transformation_list.prev,
528                                &shsurf->workspace_transform.link);
529
530         weston_matrix_init(&shsurf->workspace_transform.matrix);
531         weston_matrix_translate(&shsurf->workspace_transform.matrix,
532                                 0.0, d, 0.0);
533         surface->geometry.dirty = 1;
534 }
535
536 static void
537 workspace_translate_out(struct workspace *ws, double fraction)
538 {
539         struct weston_surface *surface;
540         unsigned int height;
541         double d;
542
543         wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
544                 height = get_output_height(surface->output);
545                 d = height * fraction;
546
547                 surface_translate(surface, d);
548         }
549 }
550
551 static void
552 workspace_translate_in(struct workspace *ws, double fraction)
553 {
554         struct weston_surface *surface;
555         unsigned int height;
556         double d;
557
558         wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
559                 height = get_output_height(surface->output);
560
561                 if (fraction > 0)
562                         d = -(height - height * fraction);
563                 else
564                         d = height + height * fraction;
565
566                 surface_translate(surface, d);
567         }
568 }
569
570 static void
571 workspace_damage_all_surfaces(struct workspace *ws)
572 {
573         struct weston_surface *surface;
574
575         wl_list_for_each(surface, &ws->layer.surface_list, layer_link)
576                 weston_surface_damage(surface);
577 }
578
579 static void
580 reverse_workspace_change_animation(struct desktop_shell *shell,
581                                    unsigned int index,
582                                    struct workspace *from,
583                                    struct workspace *to)
584 {
585         shell->workspaces.current = index;
586
587         shell->workspaces.anim_to = to;
588         shell->workspaces.anim_from = from;
589         shell->workspaces.anim_dir = -1 * shell->workspaces.anim_dir;
590         shell->workspaces.anim_timestamp = 0;
591
592         push_focus_state(shell, from);
593         pop_focus_state(shell, to);
594
595         workspace_damage_all_surfaces(from);
596         workspace_damage_all_surfaces(to);
597 }
598
599 static void
600 workspace_deactivate_transforms(struct workspace *ws)
601 {
602         struct weston_surface *surface;
603         struct shell_surface *shsurf;
604
605         wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
606                 shsurf = get_shell_surface(surface);
607                 wl_list_remove(&shsurf->workspace_transform.link);
608                 wl_list_init(&shsurf->workspace_transform.link);
609                 shsurf->surface->geometry.dirty = 1;
610         }
611 }
612
613 static void
614 finish_workspace_change_animation(struct desktop_shell *shell,
615                                   struct workspace *from,
616                                   struct workspace *to)
617 {
618         workspace_damage_all_surfaces(from);
619         workspace_damage_all_surfaces(to);
620
621         wl_list_remove(&shell->workspaces.animation.link);
622         workspace_deactivate_transforms(from);
623         workspace_deactivate_transforms(to);
624         shell->workspaces.anim_to = NULL;
625
626         wl_list_remove(&shell->workspaces.anim_from->layer.link);
627 }
628
629 static void
630 animate_workspace_change_frame(struct weston_animation *animation,
631                                struct weston_output *output, uint32_t msecs)
632 {
633         struct desktop_shell *shell =
634                 container_of(animation, struct desktop_shell,
635                              workspaces.animation);
636         struct workspace *from = shell->workspaces.anim_from;
637         struct workspace *to = shell->workspaces.anim_to;
638         uint32_t t;
639         double x, y;
640
641         if (workspace_is_empty(from) && workspace_is_empty(to)) {
642                 finish_workspace_change_animation(shell, from, to);
643                 return;
644         }
645
646         if (shell->workspaces.anim_timestamp == 0) {
647                 if (shell->workspaces.anim_current == 0.0)
648                         shell->workspaces.anim_timestamp = msecs;
649                 else
650                         shell->workspaces.anim_timestamp =
651                                 msecs -
652                                 /* Invers of movement function 'y' below. */
653                                 (asin(1.0 - shell->workspaces.anim_current) *
654                                  DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH *
655                                  M_2_PI);
656         }
657
658         t = msecs - shell->workspaces.anim_timestamp;
659
660         /*
661          * x = [0, π/2]
662          * y(x) = sin(x)
663          */
664         x = t * (1.0/DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH) * M_PI_2;
665         y = sin(x);
666
667         if (t < DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH) {
668                 workspace_damage_all_surfaces(from);
669                 workspace_damage_all_surfaces(to);
670
671                 workspace_translate_out(from, shell->workspaces.anim_dir * y);
672                 workspace_translate_in(to, shell->workspaces.anim_dir * y);
673                 shell->workspaces.anim_current = y;
674
675                 workspace_damage_all_surfaces(from);
676                 workspace_damage_all_surfaces(to);
677         }
678         else
679                 finish_workspace_change_animation(shell, from, to);
680 }
681
682 static void
683 animate_workspace_change(struct desktop_shell *shell,
684                          unsigned int index,
685                          struct workspace *from,
686                          struct workspace *to)
687 {
688         struct weston_output *output;
689
690         int dir;
691
692         if (index > shell->workspaces.current)
693                 dir = -1;
694         else
695                 dir = 1;
696
697         shell->workspaces.current = index;
698
699         shell->workspaces.anim_dir = dir;
700         shell->workspaces.anim_from = from;
701         shell->workspaces.anim_to = to;
702         shell->workspaces.anim_current = 0.0;
703         shell->workspaces.anim_timestamp = 0;
704
705         output = container_of(shell->compositor->output_list.next,
706                               struct weston_output, link);
707         wl_list_insert(&output->animation_list,
708                        &shell->workspaces.animation.link);
709
710         wl_list_insert(&from->layer.link, &to->layer.link);
711
712         workspace_translate_in(to, 0);
713
714         push_focus_state(shell, from);
715         pop_focus_state(shell, to);
716
717         workspace_damage_all_surfaces(from);
718         workspace_damage_all_surfaces(to);
719 }
720
721 static void
722 change_workspace(struct desktop_shell *shell, unsigned int index)
723 {
724         struct workspace *from;
725         struct workspace *to;
726
727         if (index == shell->workspaces.current)
728                 return;
729
730         /* Don't change workspace when there is any fullscreen surfaces. */
731         if (!wl_list_empty(&shell->fullscreen_layer.surface_list))
732                 return;
733
734         from = get_current_workspace(shell);
735         to = get_workspace(shell, index);
736
737         if (shell->workspaces.anim_from == to &&
738             shell->workspaces.anim_to == from) {
739                 reverse_workspace_change_animation(shell, index, from, to);
740                 return;
741         }
742
743         if (shell->workspaces.anim_to != NULL)
744                 finish_workspace_change_animation(shell,
745                                                   shell->workspaces.anim_from,
746                                                   shell->workspaces.anim_to);
747
748         if (workspace_is_empty(to) && workspace_is_empty(from)) {
749                 shell->workspaces.current = index;
750                 wl_list_insert(&from->layer.link, &to->layer.link);
751                 wl_list_remove(&from->layer.link);
752
753                 push_focus_state(shell, from);
754                 pop_focus_state(shell, to);
755         }
756         else
757                 animate_workspace_change(shell, index, from, to);
758 }
759
760 static void
761 noop_grab_focus(struct wl_pointer_grab *grab,
762                 struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y)
763 {
764         grab->focus = NULL;
765 }
766
767 static void
768 move_grab_motion(struct wl_pointer_grab *grab,
769                  uint32_t time, wl_fixed_t x, wl_fixed_t y)
770 {
771         struct weston_move_grab *move = (struct weston_move_grab *) grab;
772         struct wl_pointer *pointer = grab->pointer;
773         struct shell_surface *shsurf = move->base.shsurf;
774         struct weston_surface *es;
775         int dx = wl_fixed_to_int(pointer->x + move->dx);
776         int dy = wl_fixed_to_int(pointer->y + move->dy);
777
778         if (!shsurf)
779                 return;
780
781         es = shsurf->surface;
782
783         weston_surface_configure(es, dx, dy,
784                                  es->geometry.width, es->geometry.height);
785 }
786
787 static void
788 move_grab_button(struct wl_pointer_grab *grab,
789                  uint32_t time, uint32_t button, uint32_t state_w)
790 {
791         struct shell_grab *shell_grab = container_of(grab, struct shell_grab,
792                                                     grab);
793         struct wl_pointer *pointer = grab->pointer;
794         enum wl_pointer_button_state state = state_w;
795
796         if (pointer->button_count == 0 &&
797             state == WL_POINTER_BUTTON_STATE_RELEASED) {
798                 shell_grab_finish(shell_grab);
799                 wl_pointer_end_grab(pointer);
800                 free(grab);
801         }
802 }
803
804 static const struct wl_pointer_grab_interface move_grab_interface = {
805         noop_grab_focus,
806         move_grab_motion,
807         move_grab_button,
808 };
809
810 static void
811 busy_cursor_grab_focus(struct wl_pointer_grab *base,
812                        struct wl_surface *surface, int32_t x, int32_t y)
813 {
814         struct shell_grab *grab = (struct shell_grab *) base;
815         struct wl_pointer *pointer = base->pointer;
816
817         if (grab->grab.focus != surface) {
818                 shell_grab_finish(grab);
819                 wl_pointer_end_grab(pointer);
820                 free(grab);
821         }
822 }
823
824 static void
825 busy_cursor_grab_motion(struct wl_pointer_grab *grab,
826                         uint32_t time, int32_t x, int32_t y)
827 {
828 }
829
830 static void
831 busy_cursor_grab_button(struct wl_pointer_grab *grab,
832                         uint32_t time, uint32_t button, uint32_t state)
833 {
834 }
835
836 static const struct wl_pointer_grab_interface busy_cursor_grab_interface = {
837         busy_cursor_grab_focus,
838         busy_cursor_grab_motion,
839         busy_cursor_grab_button,
840 };
841
842 static void
843 set_busy_cursor(struct shell_surface *shsurf, struct wl_pointer *pointer)
844 {
845         struct shell_grab *grab;
846         struct desktop_shell *shell = shsurf->shell;
847
848         grab = malloc(sizeof *grab);
849         if (!grab)
850                 return;
851
852         shell_grab_init(grab, &busy_cursor_grab_interface, shsurf);
853         grab->grab.focus = &shsurf->surface->surface;
854         wl_pointer_start_grab(pointer, &grab->grab);
855         wl_pointer_set_focus(pointer, &shell->busy_surface->surface, 0, 0);
856 }
857
858 static void
859 end_busy_cursor(struct shell_surface *shsurf, struct wl_pointer *pointer)
860 {
861         struct shell_grab *grab = (struct shell_grab *) pointer->grab;
862
863         if (grab->grab.interface == &busy_cursor_grab_interface) {
864                 shell_grab_finish(grab);
865                 wl_pointer_end_grab(pointer);
866                 free(grab);
867         }
868 }
869
870 static void
871 ping_timer_destroy(struct shell_surface *shsurf)
872 {
873         if (!shsurf || !shsurf->ping_timer)
874                 return;
875
876         if (shsurf->ping_timer->source)
877                 wl_event_source_remove(shsurf->ping_timer->source);
878
879         free(shsurf->ping_timer);
880         shsurf->ping_timer = NULL;
881 }
882
883 static int
884 ping_timeout_handler(void *data)
885 {
886         struct shell_surface *shsurf = data;
887         struct weston_seat *seat;
888
889         /* Client is not responding */
890         shsurf->unresponsive = 1;
891
892         wl_list_for_each(seat, &shsurf->surface->compositor->seat_list, link)
893                 if (seat->seat.pointer->focus == &shsurf->surface->surface)
894                         set_busy_cursor(shsurf, seat->seat.pointer);
895
896         return 1;
897 }
898
899 static void
900 ping_handler(struct weston_surface *surface, uint32_t serial)
901 {
902         struct shell_surface *shsurf = get_shell_surface(surface);
903         struct wl_event_loop *loop;
904         int ping_timeout = 200;
905
906         if (!shsurf)
907                 return;
908         if (!shsurf->resource.client)
909                 return;
910
911         if (!shsurf->ping_timer) {
912                 shsurf->ping_timer = malloc(sizeof *shsurf->ping_timer);
913                 if (!shsurf->ping_timer)
914                         return;
915
916                 shsurf->ping_timer->serial = serial;
917                 loop = wl_display_get_event_loop(surface->compositor->wl_display);
918                 shsurf->ping_timer->source =
919                         wl_event_loop_add_timer(loop, ping_timeout_handler, shsurf);
920                 wl_event_source_timer_update(shsurf->ping_timer->source, ping_timeout);
921
922                 wl_shell_surface_send_ping(&shsurf->resource, serial);
923         }
924 }
925
926 static void
927 handle_pointer_focus(struct wl_listener *listener, void *data)
928 {
929         struct wl_pointer *pointer = data;
930         struct weston_surface *surface =
931                 (struct weston_surface *) pointer->focus;
932         struct weston_compositor *compositor;
933         struct shell_surface *shsurf;
934         uint32_t serial;
935
936         if (!surface)
937                 return;
938
939         compositor = surface->compositor;
940         shsurf = get_shell_surface(surface);
941
942         if (shsurf && shsurf->unresponsive) {
943                 set_busy_cursor(shsurf, pointer);
944         } else {
945                 serial = wl_display_next_serial(compositor->wl_display);
946                 ping_handler(surface, serial);
947         }
948 }
949
950 static void
951 shell_surface_pong(struct wl_client *client, struct wl_resource *resource,
952                                                         uint32_t serial)
953 {
954         struct shell_surface *shsurf = resource->data;
955         struct desktop_shell *shell = shsurf->shell;
956         struct weston_seat *seat;
957         struct weston_compositor *ec = shsurf->surface->compositor;
958         struct wl_pointer *pointer;
959         int was_unresponsive;
960
961         if (shsurf->ping_timer->serial == serial) {
962                 was_unresponsive = shsurf->unresponsive;
963                 shsurf->unresponsive = 0;
964                 if (was_unresponsive) {
965                         /* Received pong from previously unresponsive client */
966                         wl_list_for_each(seat, &ec->seat_list, link) {
967                                 pointer = seat->seat.pointer;
968                                 if (pointer->focus ==
969                                     &shell->busy_surface->surface &&
970                                     pointer->current ==
971                                     &shsurf->surface->surface)
972                                         end_busy_cursor(shsurf, pointer);
973                         }
974                 }
975                 ping_timer_destroy(shsurf);
976         }
977 }
978
979 static void
980 shell_surface_set_title(struct wl_client *client,
981                         struct wl_resource *resource, const char *title)
982 {
983         struct shell_surface *shsurf = resource->data;
984
985         free(shsurf->title);
986         shsurf->title = strdup(title);
987 }
988
989 static void
990 shell_surface_set_class(struct wl_client *client,
991                         struct wl_resource *resource, const char *class)
992 {
993         struct shell_surface *shsurf = resource->data;
994
995         free(shsurf->class);
996         shsurf->class = strdup(class);
997 }
998
999 static int
1000 surface_move(struct shell_surface *shsurf, struct weston_seat *ws)
1001 {
1002         struct weston_move_grab *move;
1003
1004         if (!shsurf)
1005                 return -1;
1006
1007         move = malloc(sizeof *move);
1008         if (!move)
1009                 return -1;
1010
1011         shell_grab_init(&move->base, &move_grab_interface, shsurf);
1012
1013         move->dx = wl_fixed_from_double(shsurf->surface->geometry.x) -
1014                         ws->seat.pointer->grab_x;
1015         move->dy = wl_fixed_from_double(shsurf->surface->geometry.y) -
1016                         ws->seat.pointer->grab_y;
1017
1018         wl_pointer_start_grab(ws->seat.pointer, &move->base.grab);
1019
1020         wl_pointer_set_focus(ws->seat.pointer, NULL,
1021                              wl_fixed_from_int(0),
1022                              wl_fixed_from_int(0));
1023
1024         return 0;
1025 }
1026
1027 static void
1028 shell_surface_move(struct wl_client *client, struct wl_resource *resource,
1029                    struct wl_resource *seat_resource, uint32_t serial)
1030 {
1031         struct weston_seat *ws = seat_resource->data;
1032         struct shell_surface *shsurf = resource->data;
1033
1034         if (ws->seat.pointer->button_count == 0 ||
1035             ws->seat.pointer->grab_serial != serial ||
1036             ws->seat.pointer->focus != &shsurf->surface->surface)
1037                 return;
1038
1039         if (surface_move(shsurf, ws) < 0)
1040                 wl_resource_post_no_memory(resource);
1041 }
1042
1043 struct weston_resize_grab {
1044         struct shell_grab base;
1045         uint32_t edges;
1046         int32_t width, height;
1047 };
1048
1049 static void
1050 resize_grab_motion(struct wl_pointer_grab *grab,
1051                    uint32_t time, wl_fixed_t x, wl_fixed_t y)
1052 {
1053         struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
1054         struct wl_pointer *pointer = grab->pointer;
1055         struct shell_surface *shsurf = resize->base.shsurf;
1056         int32_t width, height;
1057         wl_fixed_t from_x, from_y;
1058         wl_fixed_t to_x, to_y;
1059
1060         if (!shsurf)
1061                 return;
1062
1063         weston_surface_from_global_fixed(shsurf->surface,
1064                                          pointer->grab_x, pointer->grab_y,
1065                                          &from_x, &from_y);
1066         weston_surface_from_global_fixed(shsurf->surface,
1067                                          pointer->x, pointer->y, &to_x, &to_y);
1068
1069         width = resize->width;
1070         if (resize->edges & WL_SHELL_SURFACE_RESIZE_LEFT) {
1071                 width += wl_fixed_to_int(from_x - to_x);
1072         } else if (resize->edges & WL_SHELL_SURFACE_RESIZE_RIGHT) {
1073                 width += wl_fixed_to_int(to_x - from_x);
1074         }
1075
1076         height = resize->height;
1077         if (resize->edges & WL_SHELL_SURFACE_RESIZE_TOP) {
1078                 height += wl_fixed_to_int(from_y - to_y);
1079         } else if (resize->edges & WL_SHELL_SURFACE_RESIZE_BOTTOM) {
1080                 height += wl_fixed_to_int(to_y - from_y);
1081         }
1082
1083         shsurf->client->send_configure(shsurf->surface,
1084                                        resize->edges, width, height);
1085 }
1086
1087 static void
1088 send_configure(struct weston_surface *surface,
1089                uint32_t edges, int32_t width, int32_t height)
1090 {
1091         struct shell_surface *shsurf = get_shell_surface(surface);
1092
1093         wl_shell_surface_send_configure(&shsurf->resource,
1094                                         edges, width, height);
1095 }
1096
1097 static const struct weston_shell_client shell_client = {
1098         send_configure
1099 };
1100
1101 static void
1102 resize_grab_button(struct wl_pointer_grab *grab,
1103                    uint32_t time, uint32_t button, uint32_t state_w)
1104 {
1105         struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
1106         struct wl_pointer *pointer = grab->pointer;
1107         enum wl_pointer_button_state state = state_w;
1108
1109         if (pointer->button_count == 0 &&
1110             state == WL_POINTER_BUTTON_STATE_RELEASED) {
1111                 shell_grab_finish(&resize->base);
1112                 wl_pointer_end_grab(pointer);
1113                 free(grab);
1114         }
1115 }
1116
1117 static const struct wl_pointer_grab_interface resize_grab_interface = {
1118         noop_grab_focus,
1119         resize_grab_motion,
1120         resize_grab_button,
1121 };
1122
1123 static int
1124 surface_resize(struct shell_surface *shsurf,
1125                struct weston_seat *ws, uint32_t edges)
1126 {
1127         struct weston_resize_grab *resize;
1128
1129         if (shsurf->type == SHELL_SURFACE_FULLSCREEN)
1130                 return 0;
1131
1132         if (edges == 0 || edges > 15 ||
1133             (edges & 3) == 3 || (edges & 12) == 12)
1134                 return 0;
1135
1136         resize = malloc(sizeof *resize);
1137         if (!resize)
1138                 return -1;
1139
1140         shell_grab_init(&resize->base, &resize_grab_interface, shsurf);
1141
1142         resize->edges = edges;
1143         resize->width = shsurf->surface->geometry.width;
1144         resize->height = shsurf->surface->geometry.height;
1145
1146         wl_pointer_start_grab(ws->seat.pointer, &resize->base.grab);
1147
1148         wl_pointer_set_focus(ws->seat.pointer, NULL,
1149                              wl_fixed_from_int(0),
1150                              wl_fixed_from_int(0));
1151
1152         return 0;
1153 }
1154
1155 static void
1156 shell_surface_resize(struct wl_client *client, struct wl_resource *resource,
1157                      struct wl_resource *seat_resource, uint32_t serial,
1158                      uint32_t edges)
1159 {
1160         struct weston_seat *ws = seat_resource->data;
1161         struct shell_surface *shsurf = resource->data;
1162
1163         if (shsurf->type == SHELL_SURFACE_FULLSCREEN)
1164                 return;
1165
1166         if (ws->seat.pointer->button_count == 0 ||
1167             ws->seat.pointer->grab_serial != serial ||
1168             ws->seat.pointer->focus != &shsurf->surface->surface)
1169                 return;
1170
1171         if (surface_resize(shsurf, ws, edges) < 0)
1172                 wl_resource_post_no_memory(resource);
1173 }
1174
1175 static struct weston_output *
1176 get_default_output(struct weston_compositor *compositor)
1177 {
1178         return container_of(compositor->output_list.next,
1179                             struct weston_output, link);
1180 }
1181
1182 static void
1183 shell_unset_fullscreen(struct shell_surface *shsurf)
1184 {
1185         /* undo all fullscreen things here */
1186         if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
1187             shell_surface_is_top_fullscreen(shsurf)) {
1188                 weston_output_switch_mode(shsurf->fullscreen_output,
1189                                           shsurf->fullscreen_output->origin);
1190         }
1191         shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
1192         shsurf->fullscreen.framerate = 0;
1193         wl_list_remove(&shsurf->fullscreen.transform.link);
1194         wl_list_init(&shsurf->fullscreen.transform.link);
1195         if (shsurf->fullscreen.black_surface)
1196                 weston_surface_destroy(shsurf->fullscreen.black_surface);
1197         shsurf->fullscreen.black_surface = NULL;
1198         shsurf->fullscreen_output = NULL;
1199         weston_surface_set_position(shsurf->surface,
1200                                     shsurf->saved_x, shsurf->saved_y);
1201         if (shsurf->saved_rotation_valid) {
1202                 wl_list_insert(&shsurf->surface->geometry.transformation_list,
1203                                &shsurf->rotation.transform.link);
1204                 shsurf->saved_rotation_valid = false;
1205         }
1206 }
1207
1208 static int
1209 reset_shell_surface_type(struct shell_surface *surface)
1210 {
1211         switch (surface->type) {
1212         case SHELL_SURFACE_FULLSCREEN:
1213                 shell_unset_fullscreen(surface);
1214                 break;
1215         case SHELL_SURFACE_MAXIMIZED:
1216                 surface->output = get_default_output(surface->surface->compositor);
1217                 weston_surface_set_position(surface->surface,
1218                                             surface->saved_x,
1219                                             surface->saved_y);
1220                 break;
1221         case SHELL_SURFACE_PANEL:
1222         case SHELL_SURFACE_BACKGROUND:
1223                 wl_list_remove(&surface->link);
1224                 wl_list_init(&surface->link);
1225                 break;
1226         case SHELL_SURFACE_SCREENSAVER:
1227         case SHELL_SURFACE_LOCK:
1228                 wl_resource_post_error(&surface->resource,
1229                                        WL_DISPLAY_ERROR_INVALID_METHOD,
1230                                        "cannot reassign surface type");
1231                 return -1;
1232         case SHELL_SURFACE_NONE:
1233         case SHELL_SURFACE_TOPLEVEL:
1234         case SHELL_SURFACE_TRANSIENT:
1235         case SHELL_SURFACE_POPUP:
1236                 break;
1237         }
1238
1239         surface->type = SHELL_SURFACE_NONE;
1240         return 0;
1241 }
1242
1243 static void
1244 set_surface_type(struct shell_surface *shsurf)
1245 {
1246         struct weston_surface *surface = shsurf->surface;
1247         struct shell_surface *pshsurf = shsurf->parent;
1248         struct weston_surface *pes;
1249         struct shell_surface *priv;
1250         struct desktop_shell *shell = shsurf->shell;
1251
1252         reset_shell_surface_type(shsurf);
1253
1254         shsurf->type = shsurf->next_type;
1255         shsurf->next_type = SHELL_SURFACE_NONE;
1256
1257         switch (shsurf->type) {
1258         case SHELL_SURFACE_TOPLEVEL:
1259                 break;
1260         case SHELL_SURFACE_TRANSIENT:
1261                 pes = pshsurf->surface;
1262                 weston_surface_set_position(surface,
1263                                 pes->geometry.x + shsurf->transient.x,
1264                                 pes->geometry.y + shsurf->transient.y);
1265                 break;
1266
1267         case SHELL_SURFACE_MAXIMIZED:
1268                 shsurf->saved_x = surface->geometry.x;
1269                 shsurf->saved_y = surface->geometry.y;
1270                 shsurf->saved_position_valid = true;
1271                 break;
1272
1273         case SHELL_SURFACE_FULLSCREEN:
1274                 shsurf->saved_x = surface->geometry.x;
1275                 shsurf->saved_y = surface->geometry.y;
1276                 shsurf->saved_position_valid = true;
1277
1278                 if (!wl_list_empty(&shsurf->rotation.transform.link)) {
1279                         wl_list_remove(&shsurf->rotation.transform.link);
1280                         wl_list_init(&shsurf->rotation.transform.link);
1281                         shsurf->surface->geometry.dirty = 1;
1282                         shsurf->saved_rotation_valid = true;
1283                 }
1284                 break;
1285
1286         case SHELL_SURFACE_BACKGROUND:
1287                 wl_list_for_each(priv, &shell->backgrounds, link) {
1288                         if (priv->output == shsurf->output) {
1289                                 priv->surface->output = NULL;
1290                                 wl_list_remove(&priv->surface->layer_link);
1291                                 wl_list_remove(&priv->link);
1292                                 break;
1293                         }
1294                 }
1295
1296                 wl_list_insert(&shell->backgrounds, &shsurf->link);
1297
1298                 weston_surface_set_position(surface, shsurf->output->x,
1299                                             shsurf->output->y);
1300                 break;
1301
1302         case SHELL_SURFACE_PANEL:
1303                 wl_list_for_each(priv, &shell->panels, link) {
1304                         if (priv->output == shsurf->output) {
1305                                 priv->surface->output = NULL;
1306                                 wl_list_remove(&priv->surface->layer_link);
1307                                 wl_list_remove(&priv->link);
1308                                 break;
1309                         }
1310                 }
1311
1312                 wl_list_insert(&shell->panels, &shsurf->link);
1313
1314                 weston_surface_set_position(surface, shsurf->output->x,
1315                                             shsurf->output->y);
1316                 break;
1317
1318         default:
1319                 break;
1320         }
1321 }
1322
1323 static void
1324 set_toplevel(struct shell_surface *shsurf)
1325 {
1326        shsurf->next_type = SHELL_SURFACE_TOPLEVEL;
1327 }
1328
1329 static void
1330 shell_surface_set_toplevel(struct wl_client *client,
1331                            struct wl_resource *resource)
1332 {
1333         struct shell_surface *surface = resource->data;
1334
1335         set_toplevel(surface);
1336 }
1337
1338 static void
1339 set_transient(struct shell_surface *shsurf,
1340               struct shell_surface *pshsurf, int x, int y, uint32_t flags)
1341 {
1342         /* assign to parents output */
1343         shsurf->parent = pshsurf;
1344         shsurf->transient.x = x;
1345         shsurf->transient.y = y;
1346         shsurf->transient.flags = flags;
1347         shsurf->next_type = SHELL_SURFACE_TRANSIENT;
1348 }
1349
1350 static void
1351 shell_surface_set_transient(struct wl_client *client,
1352                             struct wl_resource *resource,
1353                             struct wl_resource *parent_resource,
1354                             int x, int y, uint32_t flags)
1355 {
1356         struct shell_surface *shsurf = resource->data;
1357         struct shell_surface *pshsurf = parent_resource->data;
1358
1359         set_transient(shsurf, pshsurf, x, y, flags);
1360 }
1361
1362 static struct desktop_shell *
1363 shell_surface_get_shell(struct shell_surface *shsurf)
1364 {
1365         return shsurf->shell;
1366 }
1367
1368 static int
1369 get_output_panel_height(struct desktop_shell *shell,
1370                         struct weston_output *output)
1371 {
1372         struct shell_surface *priv;
1373         int panel_height = 0;
1374
1375         if (!output)
1376                 return 0;
1377
1378         wl_list_for_each(priv, &shell->panels, link) {
1379                 if (priv->output == output) {
1380                         panel_height = priv->surface->geometry.height;
1381                         break;
1382                 }
1383         }
1384         return panel_height;
1385 }
1386
1387 static void
1388 shell_surface_set_maximized(struct wl_client *client,
1389                             struct wl_resource *resource,
1390                             struct wl_resource *output_resource )
1391 {
1392         struct shell_surface *shsurf = resource->data;
1393         struct weston_surface *es = shsurf->surface;
1394         struct desktop_shell *shell = NULL;
1395         uint32_t edges = 0, panel_height = 0;
1396
1397         /* get the default output, if the client set it as NULL
1398            check whether the ouput is available */
1399         if (output_resource)
1400                 shsurf->output = output_resource->data;
1401         else
1402                 shsurf->output = get_default_output(es->compositor);
1403
1404         shell = shell_surface_get_shell(shsurf);
1405         panel_height = get_output_panel_height(shell, es->output);
1406         edges = WL_SHELL_SURFACE_RESIZE_TOP|WL_SHELL_SURFACE_RESIZE_LEFT;
1407
1408         shsurf->client->send_configure(shsurf->surface, edges,
1409                                        es->output->current->width,
1410                                        es->output->current->height - panel_height);
1411
1412         shsurf->next_type = SHELL_SURFACE_MAXIMIZED;
1413 }
1414
1415 static void
1416 black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy);
1417
1418 static struct weston_surface *
1419 create_black_surface(struct weston_compositor *ec,
1420                      struct weston_surface *fs_surface,
1421                      GLfloat x, GLfloat y, int w, int h)
1422 {
1423         struct weston_surface *surface = NULL;
1424
1425         surface = weston_surface_create(ec);
1426         if (surface == NULL) {
1427                 weston_log("no memory\n");
1428                 return NULL;
1429         }
1430
1431         surface->configure = black_surface_configure;
1432         surface->private = fs_surface;
1433         weston_surface_configure(surface, x, y, w, h);
1434         weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1);
1435         return surface;
1436 }
1437
1438 /* Create black surface and append it to the associated fullscreen surface.
1439  * Handle size dismatch and positioning according to the method. */
1440 static void
1441 shell_configure_fullscreen(struct shell_surface *shsurf)
1442 {
1443         struct weston_output *output = shsurf->fullscreen_output;
1444         struct weston_surface *surface = shsurf->surface;
1445         struct weston_matrix *matrix;
1446         float scale;
1447
1448         center_on_output(surface, output);
1449
1450         if (!shsurf->fullscreen.black_surface)
1451                 shsurf->fullscreen.black_surface =
1452                         create_black_surface(surface->compositor,
1453                                              surface,
1454                                              output->x, output->y,
1455                                              output->current->width,
1456                                              output->current->height);
1457
1458         wl_list_remove(&shsurf->fullscreen.black_surface->layer_link);
1459         wl_list_insert(&surface->layer_link,
1460                        &shsurf->fullscreen.black_surface->layer_link);
1461         shsurf->fullscreen.black_surface->output = output;
1462
1463         switch (shsurf->fullscreen.type) {
1464         case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT:
1465                 break;
1466         case WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE:
1467                 matrix = &shsurf->fullscreen.transform.matrix;
1468                 weston_matrix_init(matrix);
1469                 scale = (float)output->current->width/(float)surface->geometry.width;
1470                 weston_matrix_scale(matrix, scale, scale, 1);
1471                 wl_list_remove(&shsurf->fullscreen.transform.link);
1472                 wl_list_insert(surface->geometry.transformation_list.prev,
1473                                &shsurf->fullscreen.transform.link);
1474                 weston_surface_set_position(surface, output->x, output->y);
1475                 break;
1476         case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER:
1477                 if (shell_surface_is_top_fullscreen(shsurf)) {
1478                         struct weston_mode mode = {0, 
1479                                 surface->geometry.width,
1480                                 surface->geometry.height,
1481                                 shsurf->fullscreen.framerate};
1482
1483                         if (weston_output_switch_mode(output, &mode) == 0) {
1484                                 weston_surface_configure(shsurf->fullscreen.black_surface, 
1485                                                          output->x, output->y,
1486                                                          output->current->width,
1487                                                          output->current->height);
1488                                 weston_surface_set_position(surface, output->x, output->y);
1489                                 break;
1490                         }
1491                 }
1492                 break;
1493         case WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL:
1494                 break;
1495         default:
1496                 break;
1497         }
1498 }
1499
1500 /* make the fullscreen and black surface at the top */
1501 static void
1502 shell_stack_fullscreen(struct shell_surface *shsurf)
1503 {
1504         struct weston_output *output = shsurf->fullscreen_output;
1505         struct weston_surface *surface = shsurf->surface;
1506         struct desktop_shell *shell = shell_surface_get_shell(shsurf);
1507
1508         wl_list_remove(&surface->layer_link);
1509         wl_list_insert(&shell->fullscreen_layer.surface_list,
1510                        &surface->layer_link);
1511         weston_surface_damage(surface);
1512
1513         if (!shsurf->fullscreen.black_surface)
1514                 shsurf->fullscreen.black_surface =
1515                         create_black_surface(surface->compositor,
1516                                              surface,
1517                                              output->x, output->y,
1518                                              output->current->width,
1519                                              output->current->height);
1520
1521         wl_list_remove(&shsurf->fullscreen.black_surface->layer_link);
1522         wl_list_insert(&surface->layer_link,
1523                        &shsurf->fullscreen.black_surface->layer_link);
1524         weston_surface_damage(shsurf->fullscreen.black_surface);
1525 }
1526
1527 static void
1528 shell_map_fullscreen(struct shell_surface *shsurf)
1529 {
1530         shell_stack_fullscreen(shsurf);
1531         shell_configure_fullscreen(shsurf);
1532 }
1533
1534 static void
1535 shell_surface_set_fullscreen(struct wl_client *client,
1536                              struct wl_resource *resource,
1537                              uint32_t method,
1538                              uint32_t framerate,
1539                              struct wl_resource *output_resource)
1540 {
1541         struct shell_surface *shsurf = resource->data;
1542         struct weston_surface *es = shsurf->surface;
1543
1544         if (output_resource)
1545                 shsurf->output = output_resource->data;
1546         else
1547                 shsurf->output = get_default_output(es->compositor);
1548
1549         shsurf->fullscreen_output = shsurf->output;
1550         shsurf->fullscreen.type = method;
1551         shsurf->fullscreen.framerate = framerate;
1552         shsurf->next_type = SHELL_SURFACE_FULLSCREEN;
1553
1554         shsurf->client->send_configure(shsurf->surface, 0,
1555                                        shsurf->output->current->width,
1556                                        shsurf->output->current->height);
1557 }
1558
1559 static void
1560 popup_grab_focus(struct wl_pointer_grab *grab,
1561                  struct wl_surface *surface,
1562                  wl_fixed_t x,
1563                  wl_fixed_t y)
1564 {
1565         struct wl_pointer *pointer = grab->pointer;
1566         struct shell_surface *priv =
1567                 container_of(grab, struct shell_surface, popup.grab);
1568         struct wl_client *client = priv->surface->surface.resource.client;
1569
1570         if (surface && surface->resource.client == client) {
1571                 wl_pointer_set_focus(pointer, surface, x, y);
1572                 grab->focus = surface;
1573         } else {
1574                 wl_pointer_set_focus(pointer, NULL,
1575                                      wl_fixed_from_int(0),
1576                                      wl_fixed_from_int(0));
1577                 grab->focus = NULL;
1578         }
1579 }
1580
1581 static void
1582 popup_grab_motion(struct wl_pointer_grab *grab,
1583                   uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
1584 {
1585         struct wl_resource *resource;
1586
1587         resource = grab->pointer->focus_resource;
1588         if (resource)
1589                 wl_pointer_send_motion(resource, time, sx, sy);
1590 }
1591
1592 static void
1593 popup_grab_button(struct wl_pointer_grab *grab,
1594                   uint32_t time, uint32_t button, uint32_t state_w)
1595 {
1596         struct wl_resource *resource;
1597         struct shell_surface *shsurf =
1598                 container_of(grab, struct shell_surface, popup.grab);
1599         struct wl_display *display;
1600         enum wl_pointer_button_state state = state_w;
1601         uint32_t serial;
1602
1603         resource = grab->pointer->focus_resource;
1604         if (resource) {
1605                 display = wl_client_get_display(resource->client);
1606                 serial = wl_display_get_serial(display);
1607                 wl_pointer_send_button(resource, serial, time, button, state);
1608         } else if (state == WL_POINTER_BUTTON_STATE_RELEASED &&
1609                    (shsurf->popup.initial_up ||
1610                     time - shsurf->popup.seat->pointer->grab_time > 500)) {
1611                 wl_shell_surface_send_popup_done(&shsurf->resource);
1612                 wl_pointer_end_grab(grab->pointer);
1613                 shsurf->popup.grab.pointer = NULL;
1614         }
1615
1616         if (state == WL_POINTER_BUTTON_STATE_RELEASED)
1617                 shsurf->popup.initial_up = 1;
1618 }
1619
1620 static const struct wl_pointer_grab_interface popup_grab_interface = {
1621         popup_grab_focus,
1622         popup_grab_motion,
1623         popup_grab_button,
1624 };
1625
1626 static void
1627 shell_map_popup(struct shell_surface *shsurf)
1628 {
1629         struct wl_seat *seat = shsurf->popup.seat;
1630         struct weston_surface *es = shsurf->surface;
1631         struct weston_surface *parent = shsurf->parent->surface;
1632
1633         es->output = parent->output;
1634         shsurf->popup.grab.interface = &popup_grab_interface;
1635
1636         weston_surface_update_transform(parent);
1637         if (parent->transform.enabled) {
1638                 shsurf->popup.parent_transform.matrix =
1639                         parent->transform.matrix;
1640         } else {
1641                 /* construct x, y translation matrix */
1642                 weston_matrix_init(&shsurf->popup.parent_transform.matrix);
1643                 shsurf->popup.parent_transform.matrix.d[12] =
1644                         parent->geometry.x;
1645                 shsurf->popup.parent_transform.matrix.d[13] =
1646                         parent->geometry.y;
1647         }
1648         wl_list_insert(es->geometry.transformation_list.prev,
1649                        &shsurf->popup.parent_transform.link);
1650         weston_surface_set_position(es, shsurf->popup.x, shsurf->popup.y);
1651
1652         shsurf->popup.initial_up = 0;
1653
1654         /* We don't require the grab to still be active, but if another
1655          * grab has started in the meantime, we end the popup now. */
1656         if (seat->pointer->grab_serial == shsurf->popup.serial) {
1657                 wl_pointer_start_grab(seat->pointer, &shsurf->popup.grab);
1658         } else {
1659                 wl_shell_surface_send_popup_done(&shsurf->resource);
1660         }
1661 }
1662
1663 static void
1664 shell_surface_set_popup(struct wl_client *client,
1665                         struct wl_resource *resource,
1666                         struct wl_resource *seat_resource,
1667                         uint32_t serial,
1668                         struct wl_resource *parent_resource,
1669                         int32_t x, int32_t y, uint32_t flags)
1670 {
1671         struct shell_surface *shsurf = resource->data;
1672
1673         shsurf->type = SHELL_SURFACE_POPUP;
1674         shsurf->parent = parent_resource->data;
1675         shsurf->popup.seat = seat_resource->data;
1676         shsurf->popup.serial = serial;
1677         shsurf->popup.x = x;
1678         shsurf->popup.y = y;
1679 }
1680
1681 static const struct wl_shell_surface_interface shell_surface_implementation = {
1682         shell_surface_pong,
1683         shell_surface_move,
1684         shell_surface_resize,
1685         shell_surface_set_toplevel,
1686         shell_surface_set_transient,
1687         shell_surface_set_fullscreen,
1688         shell_surface_set_popup,
1689         shell_surface_set_maximized,
1690         shell_surface_set_title,
1691         shell_surface_set_class
1692 };
1693
1694 static void
1695 destroy_shell_surface(struct shell_surface *shsurf)
1696 {
1697         if (shsurf->popup.grab.pointer)
1698                 wl_pointer_end_grab(shsurf->popup.grab.pointer);
1699
1700         if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
1701             shell_surface_is_top_fullscreen(shsurf)) {
1702                 weston_output_switch_mode(shsurf->fullscreen_output,
1703                                           shsurf->fullscreen_output->origin);
1704         }
1705
1706         if (shsurf->fullscreen.black_surface)
1707                 weston_surface_destroy(shsurf->fullscreen.black_surface);
1708
1709         /* As destroy_resource() use wl_list_for_each_safe(),
1710          * we can always remove the listener.
1711          */
1712         wl_list_remove(&shsurf->surface_destroy_listener.link);
1713         shsurf->surface->configure = NULL;
1714         ping_timer_destroy(shsurf);
1715
1716         wl_list_remove(&shsurf->link);
1717         free(shsurf);
1718 }
1719
1720 static void
1721 shell_destroy_shell_surface(struct wl_resource *resource)
1722 {
1723         struct shell_surface *shsurf = resource->data;
1724
1725         destroy_shell_surface(shsurf);
1726 }
1727
1728 static void
1729 shell_handle_surface_destroy(struct wl_listener *listener, void *data)
1730 {
1731         struct shell_surface *shsurf = container_of(listener,
1732                                                     struct shell_surface,
1733                                                     surface_destroy_listener);
1734
1735         if (shsurf->resource.client) {
1736                 wl_resource_destroy(&shsurf->resource);
1737         } else {
1738                 wl_signal_emit(&shsurf->resource.destroy_signal,
1739                                &shsurf->resource);
1740                 destroy_shell_surface(shsurf);
1741         }
1742 }
1743
1744 static struct shell_surface *
1745 get_shell_surface(struct weston_surface *surface)
1746 {
1747         struct wl_listener *listener;
1748
1749         listener = wl_signal_get(&surface->surface.resource.destroy_signal,
1750                                  shell_handle_surface_destroy);
1751         if (listener)
1752                 return container_of(listener, struct shell_surface,
1753                                     surface_destroy_listener);
1754
1755         return NULL;
1756 }
1757
1758 static void
1759 shell_surface_configure(struct weston_surface *, int32_t, int32_t);
1760
1761 static  struct shell_surface *
1762 create_shell_surface(void *shell, struct weston_surface *surface,
1763                      const struct weston_shell_client *client)
1764 {
1765         struct shell_surface *shsurf;
1766
1767         if (surface->configure) {
1768                 weston_log("surface->configure already set\n");
1769                 return NULL;
1770         }
1771
1772         shsurf = calloc(1, sizeof *shsurf);
1773         if (!shsurf) {
1774                 weston_log("no memory to allocate shell surface\n");
1775                 return NULL;
1776         }
1777
1778         surface->configure = shell_surface_configure;
1779         surface->compositor->shell_interface.shell = shell;
1780
1781         shsurf->shell = (struct desktop_shell *) shell;
1782         shsurf->unresponsive = 0;
1783         shsurf->saved_position_valid = false;
1784         shsurf->saved_rotation_valid = false;
1785         shsurf->surface = surface;
1786         shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
1787         shsurf->fullscreen.framerate = 0;
1788         shsurf->fullscreen.black_surface = NULL;
1789         shsurf->ping_timer = NULL;
1790         wl_list_init(&shsurf->fullscreen.transform.link);
1791
1792         wl_signal_init(&shsurf->resource.destroy_signal);
1793         shsurf->surface_destroy_listener.notify = shell_handle_surface_destroy;
1794         wl_signal_add(&surface->surface.resource.destroy_signal,
1795                       &shsurf->surface_destroy_listener);
1796
1797         /* init link so its safe to always remove it in destroy_shell_surface */
1798         wl_list_init(&shsurf->link);
1799
1800         /* empty when not in use */
1801         wl_list_init(&shsurf->rotation.transform.link);
1802         weston_matrix_init(&shsurf->rotation.rotation);
1803
1804         wl_list_init(&shsurf->workspace_transform.link);
1805
1806         shsurf->type = SHELL_SURFACE_NONE;
1807         shsurf->next_type = SHELL_SURFACE_NONE;
1808
1809         shsurf->client = client;
1810
1811         return shsurf;
1812 }
1813
1814 static void
1815 shell_get_shell_surface(struct wl_client *client,
1816                         struct wl_resource *resource,
1817                         uint32_t id,
1818                         struct wl_resource *surface_resource)
1819 {
1820         struct weston_surface *surface = surface_resource->data;
1821         struct desktop_shell *shell = resource->data;
1822         struct shell_surface *shsurf;
1823
1824         if (get_shell_surface(surface)) {
1825                 wl_resource_post_error(surface_resource,
1826                                        WL_DISPLAY_ERROR_INVALID_OBJECT,
1827                                        "desktop_shell::get_shell_surface already requested");
1828                 return;
1829         }
1830
1831         shsurf = create_shell_surface(shell, surface, &shell_client);
1832         if (!shsurf) {
1833                 wl_resource_post_error(surface_resource,
1834                                        WL_DISPLAY_ERROR_INVALID_OBJECT,
1835                                        "surface->configure already set");
1836                 return;
1837         }
1838
1839         shsurf->resource.destroy = shell_destroy_shell_surface;
1840         shsurf->resource.object.id = id;
1841         shsurf->resource.object.interface = &wl_shell_surface_interface;
1842         shsurf->resource.object.implementation =
1843                 (void (**)(void)) &shell_surface_implementation;
1844         shsurf->resource.data = shsurf;
1845
1846         wl_client_add_resource(client, &shsurf->resource);
1847 }
1848
1849 static const struct wl_shell_interface shell_implementation = {
1850         shell_get_shell_surface
1851 };
1852
1853 static void
1854 handle_screensaver_sigchld(struct weston_process *proc, int status)
1855 {
1856         proc->pid = 0;
1857 }
1858
1859 static void
1860 launch_screensaver(struct desktop_shell *shell)
1861 {
1862         if (shell->screensaver.binding)
1863                 return;
1864
1865         if (!shell->screensaver.path)
1866                 return;
1867
1868         if (shell->screensaver.process.pid != 0) {
1869                 weston_log("old screensaver still running\n");
1870                 return;
1871         }
1872
1873         weston_client_launch(shell->compositor,
1874                            &shell->screensaver.process,
1875                            shell->screensaver.path,
1876                            handle_screensaver_sigchld);
1877 }
1878
1879 static void
1880 terminate_screensaver(struct desktop_shell *shell)
1881 {
1882         if (shell->screensaver.process.pid == 0)
1883                 return;
1884
1885         kill(shell->screensaver.process.pid, SIGTERM);
1886 }
1887
1888 static void
1889 show_screensaver(struct desktop_shell *shell, struct shell_surface *surface)
1890 {
1891         struct wl_list *list;
1892
1893         if (shell->lock_surface)
1894                 list = &shell->lock_surface->surface->layer_link;
1895         else
1896                 list = &shell->lock_layer.surface_list;
1897
1898         wl_list_remove(&surface->surface->layer_link);
1899         wl_list_insert(list, &surface->surface->layer_link);
1900         surface->surface->output = surface->output;
1901         weston_surface_damage(surface->surface);
1902 }
1903
1904 static void
1905 hide_screensaver(struct desktop_shell *shell, struct shell_surface *surface)
1906 {
1907         wl_list_remove(&surface->surface->layer_link);
1908         wl_list_init(&surface->surface->layer_link);
1909         surface->surface->output = NULL;
1910 }
1911
1912 static void
1913 desktop_shell_set_background(struct wl_client *client,
1914                              struct wl_resource *resource,
1915                              struct wl_resource *output_resource,
1916                              struct wl_resource *surface_resource)
1917 {
1918         struct shell_surface *shsurf = surface_resource->data;
1919
1920         shsurf->next_type = SHELL_SURFACE_BACKGROUND;
1921         shsurf->output = output_resource->data;
1922
1923         desktop_shell_send_configure(resource, 0,
1924                                      surface_resource,
1925                                      shsurf->output->current->width,
1926                                      shsurf->output->current->height);
1927 }
1928
1929 static void
1930 desktop_shell_set_panel(struct wl_client *client,
1931                         struct wl_resource *resource,
1932                         struct wl_resource *output_resource,
1933                         struct wl_resource *surface_resource)
1934 {
1935         struct shell_surface *shsurf = surface_resource->data;
1936
1937         shsurf->next_type = SHELL_SURFACE_PANEL;
1938         shsurf->output = output_resource->data;
1939
1940         desktop_shell_send_configure(resource, 0,
1941                                      surface_resource,
1942                                      shsurf->output->current->width,
1943                                      shsurf->output->current->height);
1944 }
1945
1946 static void
1947 handle_lock_surface_destroy(struct wl_listener *listener, void *data)
1948 {
1949         struct desktop_shell *shell =
1950             container_of(listener, struct desktop_shell, lock_surface_listener);
1951
1952         weston_log("lock surface gone\n");
1953         shell->lock_surface = NULL;
1954 }
1955
1956 static void
1957 desktop_shell_set_lock_surface(struct wl_client *client,
1958                                struct wl_resource *resource,
1959                                struct wl_resource *surface_resource)
1960 {
1961         struct desktop_shell *shell = resource->data;
1962         struct shell_surface *surface = surface_resource->data;
1963
1964         shell->prepare_event_sent = false;
1965
1966         if (!shell->locked)
1967                 return;
1968
1969         shell->lock_surface = surface;
1970
1971         shell->lock_surface_listener.notify = handle_lock_surface_destroy;
1972         wl_signal_add(&surface_resource->destroy_signal,
1973                       &shell->lock_surface_listener);
1974
1975         shell->lock_surface->next_type = SHELL_SURFACE_LOCK;
1976 }
1977
1978 static void
1979 resume_desktop(struct desktop_shell *shell)
1980 {
1981         struct shell_surface *tmp;
1982
1983         wl_list_for_each(tmp, &shell->screensaver.surfaces, link)
1984                 hide_screensaver(shell, tmp);
1985
1986         terminate_screensaver(shell);
1987
1988         wl_list_remove(&shell->lock_layer.link);
1989         wl_list_insert(&shell->compositor->cursor_layer.link,
1990                        &shell->fullscreen_layer.link);
1991         wl_list_insert(&shell->fullscreen_layer.link,
1992                        &shell->panel_layer.link);
1993
1994         pop_focus_state(shell, get_current_workspace(shell));
1995
1996         shell->locked = false;
1997         shell->compositor->idle_time = shell->compositor->option_idle_time;
1998         weston_compositor_wake(shell->compositor);
1999         weston_compositor_damage_all(shell->compositor);
2000 }
2001
2002 static void
2003 desktop_shell_unlock(struct wl_client *client,
2004                      struct wl_resource *resource)
2005 {
2006         struct desktop_shell *shell = resource->data;
2007
2008         shell->prepare_event_sent = false;
2009
2010         if (shell->locked)
2011                 resume_desktop(shell);
2012 }
2013
2014 static void
2015 desktop_shell_set_busy_surface(struct wl_client *client,
2016                                struct wl_resource *resource,
2017                                struct wl_resource *surface_resource)
2018 {
2019         struct desktop_shell *shell = resource->data;
2020
2021         shell->busy_surface = surface_resource->data;
2022 }
2023
2024 static const struct desktop_shell_interface desktop_shell_implementation = {
2025         desktop_shell_set_background,
2026         desktop_shell_set_panel,
2027         desktop_shell_set_lock_surface,
2028         desktop_shell_unlock,
2029         desktop_shell_set_busy_surface
2030 };
2031
2032 static enum shell_surface_type
2033 get_shell_surface_type(struct weston_surface *surface)
2034 {
2035         struct shell_surface *shsurf;
2036
2037         shsurf = get_shell_surface(surface);
2038         if (!shsurf)
2039                 return SHELL_SURFACE_NONE;
2040         return shsurf->type;
2041 }
2042
2043 static void
2044 move_binding(struct wl_seat *seat, uint32_t time, uint32_t button, void *data)
2045 {
2046         struct weston_surface *surface =
2047                 (struct weston_surface *) seat->pointer->focus;
2048         struct shell_surface *shsurf;
2049
2050         if (surface == NULL)
2051                 return;
2052
2053         shsurf = get_shell_surface(surface);
2054         if (shsurf == NULL)
2055                 return;
2056
2057         switch (shsurf->type) {
2058                 case SHELL_SURFACE_PANEL:
2059                 case SHELL_SURFACE_BACKGROUND:
2060                 case SHELL_SURFACE_FULLSCREEN:
2061                 case SHELL_SURFACE_SCREENSAVER:
2062                         return;
2063                 default:
2064                         break;
2065         }
2066
2067         surface_move(shsurf, (struct weston_seat *) seat);
2068 }
2069
2070 static void
2071 resize_binding(struct wl_seat *seat, uint32_t time, uint32_t button, void *data)
2072 {
2073         struct weston_surface *surface =
2074                 (struct weston_surface *) seat->pointer->focus;
2075         uint32_t edges = 0;
2076         int32_t x, y;
2077         struct shell_surface *shsurf;
2078
2079         if (surface == NULL)
2080                 return;
2081
2082         shsurf = get_shell_surface(surface);
2083         if (!shsurf)
2084                 return;
2085
2086         switch (shsurf->type) {
2087                 case SHELL_SURFACE_PANEL:
2088                 case SHELL_SURFACE_BACKGROUND:
2089                 case SHELL_SURFACE_FULLSCREEN:
2090                 case SHELL_SURFACE_SCREENSAVER:
2091                         return;
2092                 default:
2093                         break;
2094         }
2095
2096         weston_surface_from_global(surface,
2097                                    wl_fixed_to_int(seat->pointer->grab_x),
2098                                    wl_fixed_to_int(seat->pointer->grab_y),
2099                                    &x, &y);
2100
2101         if (x < surface->geometry.width / 3)
2102                 edges |= WL_SHELL_SURFACE_RESIZE_LEFT;
2103         else if (x < 2 * surface->geometry.width / 3)
2104                 edges |= 0;
2105         else
2106                 edges |= WL_SHELL_SURFACE_RESIZE_RIGHT;
2107
2108         if (y < surface->geometry.height / 3)
2109                 edges |= WL_SHELL_SURFACE_RESIZE_TOP;
2110         else if (y < 2 * surface->geometry.height / 3)
2111                 edges |= 0;
2112         else
2113                 edges |= WL_SHELL_SURFACE_RESIZE_BOTTOM;
2114
2115         surface_resize(shsurf, (struct weston_seat *) seat, edges);
2116 }
2117
2118 static void
2119 surface_opacity_binding(struct wl_seat *seat, uint32_t time, uint32_t axis,
2120                         wl_fixed_t value, void *data)
2121 {
2122         float step = 0.05;
2123         struct shell_surface *shsurf;
2124         struct weston_surface *surface =
2125                 (struct weston_surface *) seat->pointer->focus;
2126
2127         if (surface == NULL)
2128                 return;
2129
2130         shsurf = get_shell_surface(surface);
2131         if (!shsurf)
2132                 return;
2133
2134         switch (shsurf->type) {
2135                 case SHELL_SURFACE_BACKGROUND:
2136                 case SHELL_SURFACE_SCREENSAVER:
2137                         return;
2138                 default:
2139                         break;
2140         }
2141
2142         surface->alpha += wl_fixed_to_double(value) * step;
2143
2144         if (surface->alpha > 1.0)
2145                 surface->alpha = 1.0;
2146         if (surface->alpha < step)
2147                 surface->alpha = step;
2148
2149         surface->geometry.dirty = 1;
2150         weston_surface_damage(surface);
2151 }
2152
2153 static void
2154 do_zoom(struct wl_seat *seat, uint32_t time, uint32_t key, uint32_t axis,
2155         wl_fixed_t value)
2156 {
2157         struct weston_seat *ws = (struct weston_seat *) seat;
2158         struct weston_compositor *compositor = ws->compositor;
2159         struct weston_output *output;
2160         float increment;
2161
2162         wl_list_for_each(output, &compositor->output_list, link) {
2163                 if (pixman_region32_contains_point(&output->region,
2164                                                    wl_fixed_to_double(seat->pointer->x),
2165                                                    wl_fixed_to_double(seat->pointer->y),
2166                                                    NULL)) {
2167                         if (key == KEY_PAGEUP)
2168                                 increment = output->zoom.increment;
2169                         else if (key == KEY_PAGEDOWN)
2170                                 increment = -output->zoom.increment;
2171                         else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
2172                                 increment = output->zoom.increment *
2173                                             wl_fixed_to_double(value);
2174                         else
2175                                 increment = 0;
2176
2177                         output->zoom.level += increment;
2178
2179                         if (output->zoom.level < 0.0)
2180                                 output->zoom.level = 0.0;
2181                         else if (output->zoom.level > output->zoom.max_level)
2182                                 output->zoom.level = output->zoom.max_level;
2183                         else
2184                                 output->zoom.active = 1;
2185
2186                         output->zoom.spring_z.target = output->zoom.level;
2187
2188                         weston_output_update_zoom(output, output->zoom.type);
2189                 }
2190         }
2191 }
2192
2193 static void
2194 zoom_axis_binding(struct wl_seat *seat, uint32_t time, uint32_t axis,
2195                   wl_fixed_t value, void *data)
2196 {
2197         do_zoom(seat, time, 0, axis, value);
2198 }
2199
2200 static void
2201 zoom_key_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
2202                  void *data)
2203 {
2204         do_zoom(seat, time, key, 0, 0);
2205 }
2206
2207 static void
2208 terminate_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
2209                   void *data)
2210 {
2211         struct weston_compositor *compositor = data;
2212
2213         wl_display_terminate(compositor->wl_display);
2214 }
2215
2216 static void
2217 rotate_grab_motion(struct wl_pointer_grab *grab,
2218                    uint32_t time, wl_fixed_t x, wl_fixed_t y)
2219 {
2220         struct rotate_grab *rotate =
2221                 container_of(grab, struct rotate_grab, base.grab);
2222         struct wl_pointer *pointer = grab->pointer;
2223         struct shell_surface *shsurf = rotate->base.shsurf;
2224         struct weston_surface *surface;
2225         GLfloat cx, cy, dx, dy, cposx, cposy, dposx, dposy, r;
2226
2227         if (!shsurf)
2228                 return;
2229
2230         surface = shsurf->surface;
2231
2232         cx = 0.5f * surface->geometry.width;
2233         cy = 0.5f * surface->geometry.height;
2234
2235         dx = wl_fixed_to_double(pointer->x) - rotate->center.x;
2236         dy = wl_fixed_to_double(pointer->y) - rotate->center.y;
2237         r = sqrtf(dx * dx + dy * dy);
2238
2239         wl_list_remove(&shsurf->rotation.transform.link);
2240         shsurf->surface->geometry.dirty = 1;
2241
2242         if (r > 20.0f) {
2243                 struct weston_matrix *matrix =
2244                         &shsurf->rotation.transform.matrix;
2245
2246                 weston_matrix_init(&rotate->rotation);
2247                 rotate->rotation.d[0] = dx / r;
2248                 rotate->rotation.d[4] = -dy / r;
2249                 rotate->rotation.d[1] = -rotate->rotation.d[4];
2250                 rotate->rotation.d[5] = rotate->rotation.d[0];
2251
2252                 weston_matrix_init(matrix);
2253                 weston_matrix_translate(matrix, -cx, -cy, 0.0f);
2254                 weston_matrix_multiply(matrix, &shsurf->rotation.rotation);
2255                 weston_matrix_multiply(matrix, &rotate->rotation);
2256                 weston_matrix_translate(matrix, cx, cy, 0.0f);
2257
2258                 wl_list_insert(
2259                         &shsurf->surface->geometry.transformation_list,
2260                         &shsurf->rotation.transform.link);
2261         } else {
2262                 wl_list_init(&shsurf->rotation.transform.link);
2263                 weston_matrix_init(&shsurf->rotation.rotation);
2264                 weston_matrix_init(&rotate->rotation);
2265         }
2266
2267         /* We need to adjust the position of the surface
2268          * in case it was resized in a rotated state before */
2269         cposx = surface->geometry.x + cx;
2270         cposy = surface->geometry.y + cy;
2271         dposx = rotate->center.x - cposx;
2272         dposy = rotate->center.y - cposy;
2273         if (dposx != 0.0f || dposy != 0.0f) {
2274                 weston_surface_set_position(surface,
2275                                             surface->geometry.x + dposx,
2276                                             surface->geometry.y + dposy);
2277         }
2278
2279         /* Repaint implies weston_surface_update_transform(), which
2280          * lazily applies the damage due to rotation update.
2281          */
2282         weston_compositor_schedule_repaint(shsurf->surface->compositor);
2283 }
2284
2285 static void
2286 rotate_grab_button(struct wl_pointer_grab *grab,
2287                  uint32_t time, uint32_t button, uint32_t state_w)
2288 {
2289         struct rotate_grab *rotate =
2290                 container_of(grab, struct rotate_grab, base.grab);
2291         struct wl_pointer *pointer = grab->pointer;
2292         struct shell_surface *shsurf = rotate->base.shsurf;
2293         enum wl_pointer_button_state state = state_w;
2294
2295         if (pointer->button_count == 0 &&
2296             state == WL_POINTER_BUTTON_STATE_RELEASED) {
2297                 if (shsurf)
2298                         weston_matrix_multiply(&shsurf->rotation.rotation,
2299                                                &rotate->rotation);
2300                 shell_grab_finish(&rotate->base);
2301                 wl_pointer_end_grab(pointer);
2302                 free(rotate);
2303         }
2304 }
2305
2306 static const struct wl_pointer_grab_interface rotate_grab_interface = {
2307         noop_grab_focus,
2308         rotate_grab_motion,
2309         rotate_grab_button,
2310 };
2311
2312 static void
2313 rotate_binding(struct wl_seat *seat, uint32_t time, uint32_t button,
2314                void *data)
2315 {
2316         struct weston_surface *base_surface =
2317                 (struct weston_surface *) seat->pointer->focus;
2318         struct shell_surface *surface;
2319         struct rotate_grab *rotate;
2320         GLfloat dx, dy;
2321         GLfloat r;
2322
2323         if (base_surface == NULL)
2324                 return;
2325
2326         surface = get_shell_surface(base_surface);
2327         if (!surface)
2328                 return;
2329
2330         switch (surface->type) {
2331                 case SHELL_SURFACE_PANEL:
2332                 case SHELL_SURFACE_BACKGROUND:
2333                 case SHELL_SURFACE_FULLSCREEN:
2334                 case SHELL_SURFACE_SCREENSAVER:
2335                         return;
2336                 default:
2337                         break;
2338         }
2339
2340         rotate = malloc(sizeof *rotate);
2341         if (!rotate)
2342                 return;
2343
2344         shell_grab_init(&rotate->base, &rotate_grab_interface, surface);
2345
2346         weston_surface_to_global_float(surface->surface,
2347                                        surface->surface->geometry.width / 2,
2348                                        surface->surface->geometry.height / 2,
2349                                        &rotate->center.x, &rotate->center.y);
2350
2351         wl_pointer_start_grab(seat->pointer, &rotate->base.grab);
2352
2353         dx = wl_fixed_to_double(seat->pointer->x) - rotate->center.x;
2354         dy = wl_fixed_to_double(seat->pointer->y) - rotate->center.y;
2355         r = sqrtf(dx * dx + dy * dy);
2356         if (r > 20.0f) {
2357                 struct weston_matrix inverse;
2358
2359                 weston_matrix_init(&inverse);
2360                 inverse.d[0] = dx / r;
2361                 inverse.d[4] = dy / r;
2362                 inverse.d[1] = -inverse.d[4];
2363                 inverse.d[5] = inverse.d[0];
2364                 weston_matrix_multiply(&surface->rotation.rotation, &inverse);
2365
2366                 weston_matrix_init(&rotate->rotation);
2367                 rotate->rotation.d[0] = dx / r;
2368                 rotate->rotation.d[4] = -dy / r;
2369                 rotate->rotation.d[1] = -rotate->rotation.d[4];
2370                 rotate->rotation.d[5] = rotate->rotation.d[0];
2371         } else {
2372                 weston_matrix_init(&surface->rotation.rotation);
2373                 weston_matrix_init(&rotate->rotation);
2374         }
2375
2376         wl_pointer_set_focus(seat->pointer, NULL,
2377                              wl_fixed_from_int(0),
2378                              wl_fixed_from_int(0));
2379 }
2380
2381 static void
2382 lower_fullscreen_layer(struct desktop_shell *shell)
2383 {
2384         struct workspace *ws;
2385         struct weston_surface *surface, *prev;
2386
2387         ws = get_current_workspace(shell);
2388         wl_list_for_each_reverse_safe(surface, prev,
2389                                       &shell->fullscreen_layer.surface_list,
2390                                       layer_link)
2391                 weston_surface_restack(surface, &ws->layer.surface_list);
2392 }
2393
2394 static void
2395 activate(struct desktop_shell *shell, struct weston_surface *es,
2396          struct weston_seat *seat)
2397 {
2398         struct workspace *ws;
2399
2400         weston_surface_activate(es, seat);
2401
2402         switch (get_shell_surface_type(es)) {
2403         case SHELL_SURFACE_BACKGROUND:
2404         case SHELL_SURFACE_PANEL:
2405         case SHELL_SURFACE_LOCK:
2406                 break;
2407
2408         case SHELL_SURFACE_SCREENSAVER:
2409                 /* always below lock surface */
2410                 if (shell->lock_surface)
2411                         weston_surface_restack(es,
2412                                                &shell->lock_surface->surface->layer_link);
2413                 break;
2414         case SHELL_SURFACE_FULLSCREEN:
2415                 /* should on top of panels */
2416                 shell_stack_fullscreen(get_shell_surface(es));
2417                 shell_configure_fullscreen(get_shell_surface(es));
2418                 break;
2419         default:
2420                 ws = get_current_workspace(shell);
2421                 lower_fullscreen_layer(shell);
2422                 weston_surface_restack(es, &ws->layer.surface_list);
2423                 break;
2424         }
2425 }
2426
2427 /* no-op func for checking black surface */
2428 static void
2429 black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy)
2430 {
2431 }
2432
2433 static bool 
2434 is_black_surface (struct weston_surface *es, struct weston_surface **fs_surface)
2435 {
2436         if (es->configure == black_surface_configure) {
2437                 if (fs_surface)
2438                         *fs_surface = (struct weston_surface *)es->private;
2439                 return true;
2440         }
2441         return false;
2442 }
2443
2444 static void
2445 click_to_activate_binding(struct wl_seat *seat, uint32_t time, uint32_t button,
2446                           void *data)
2447 {
2448         struct weston_seat *ws = (struct weston_seat *) seat;
2449         struct desktop_shell *shell = data;
2450         struct weston_surface *focus;
2451         struct weston_surface *upper;
2452
2453         focus = (struct weston_surface *) seat->pointer->focus;
2454         if (!focus)
2455                 return;
2456
2457         if (is_black_surface(focus, &upper))
2458                 focus = upper;
2459
2460         if (seat->pointer->grab == &seat->pointer->default_grab)
2461                 activate(shell, focus, ws);
2462 }
2463
2464 static void
2465 lock(struct wl_listener *listener, void *data)
2466 {
2467         struct desktop_shell *shell =
2468                 container_of(listener, struct desktop_shell, lock_listener);
2469         struct shell_surface *shsurf;
2470         struct weston_output *output;
2471
2472         if (shell->locked) {
2473                 wl_list_for_each(output, &shell->compositor->output_list, link)
2474                         /* TODO: find a way to jump to other DPMS levels */
2475                         if (output->set_dpms)
2476                                 output->set_dpms(output, WESTON_DPMS_STANDBY);
2477                 return;
2478         }
2479
2480         shell->locked = true;
2481
2482         /* Hide all surfaces by removing the fullscreen, panel and
2483          * toplevel layers.  This way nothing else can show or receive
2484          * input events while we are locked. */
2485
2486         wl_list_remove(&shell->panel_layer.link);
2487         wl_list_remove(&shell->fullscreen_layer.link);
2488         wl_list_insert(&shell->compositor->cursor_layer.link,
2489                        &shell->lock_layer.link);
2490
2491         launch_screensaver(shell);
2492
2493         wl_list_for_each(shsurf, &shell->screensaver.surfaces, link)
2494                 show_screensaver(shell, shsurf);
2495
2496         if (!wl_list_empty(&shell->screensaver.surfaces)) {
2497                 shell->compositor->idle_time = shell->screensaver.duration;
2498                 weston_compositor_wake(shell->compositor);
2499                 shell->compositor->state = WESTON_COMPOSITOR_IDLE;
2500         }
2501
2502         /* reset pointer foci */
2503         weston_compositor_schedule_repaint(shell->compositor);
2504
2505         /* stash keyboard foci in current workspace */
2506         push_focus_state(shell, get_current_workspace(shell));
2507
2508         /* TODO: disable bindings that should not work while locked. */
2509
2510         /* All this must be undone in resume_desktop(). */
2511 }
2512
2513 static void
2514 unlock(struct wl_listener *listener, void *data)
2515 {
2516         struct desktop_shell *shell =
2517                 container_of(listener, struct desktop_shell, unlock_listener);
2518
2519         if (!shell->locked || shell->lock_surface) {
2520                 weston_compositor_wake(shell->compositor);
2521                 return;
2522         }
2523
2524         /* If desktop-shell client has gone away, unlock immediately. */
2525         if (!shell->child.desktop_shell) {
2526                 resume_desktop(shell);
2527                 return;
2528         }
2529
2530         if (shell->prepare_event_sent)
2531                 return;
2532
2533         desktop_shell_send_prepare_lock_surface(shell->child.desktop_shell);
2534         shell->prepare_event_sent = true;
2535 }
2536
2537 static void
2538 center_on_output(struct weston_surface *surface, struct weston_output *output)
2539 {
2540         struct weston_mode *mode = output->current;
2541         GLfloat x = (mode->width - surface->geometry.width) / 2;
2542         GLfloat y = (mode->height - surface->geometry.height) / 2;
2543
2544         weston_surface_set_position(surface, output->x + x, output->y + y);
2545 }
2546
2547 static void
2548 map(struct desktop_shell *shell, struct weston_surface *surface,
2549     int32_t width, int32_t height, int32_t sx, int32_t sy)
2550 {
2551         struct weston_compositor *compositor = shell->compositor;
2552         struct shell_surface *shsurf = get_shell_surface(surface);
2553         enum shell_surface_type surface_type = shsurf->type;
2554         struct weston_surface *parent;
2555         struct weston_seat *seat;
2556         struct workspace *ws;
2557         int panel_height = 0;
2558
2559         surface->geometry.width = width;
2560         surface->geometry.height = height;
2561         surface->geometry.dirty = 1;
2562
2563         /* initial positioning, see also configure() */
2564         switch (surface_type) {
2565         case SHELL_SURFACE_TOPLEVEL:
2566                 weston_surface_set_position(surface, 10 + random() % 400,
2567                                             10 + random() % 400);
2568                 break;
2569         case SHELL_SURFACE_SCREENSAVER:
2570                 center_on_output(surface, shsurf->fullscreen_output);
2571                 break;
2572         case SHELL_SURFACE_FULLSCREEN:
2573                 shell_map_fullscreen(shsurf);
2574                 break;
2575         case SHELL_SURFACE_MAXIMIZED:
2576                 /* use surface configure to set the geometry */
2577                 panel_height = get_output_panel_height(shell,surface->output);
2578                 weston_surface_set_position(surface, surface->output->x,
2579                                             surface->output->y + panel_height);
2580                 break;
2581         case SHELL_SURFACE_LOCK:
2582                 center_on_output(surface, get_default_output(compositor));
2583                 break;
2584         case SHELL_SURFACE_POPUP:
2585                 shell_map_popup(shsurf);
2586         case SHELL_SURFACE_NONE:
2587                 weston_surface_set_position(surface,
2588                                             surface->geometry.x + sx,
2589                                             surface->geometry.y + sy);
2590                 break;
2591         default:
2592                 ;
2593         }
2594
2595         /* surface stacking order, see also activate() */
2596         switch (surface_type) {
2597         case SHELL_SURFACE_BACKGROUND:
2598                 /* background always visible, at the bottom */
2599                 wl_list_insert(&shell->background_layer.surface_list,
2600                                &surface->layer_link);
2601                 break;
2602         case SHELL_SURFACE_PANEL:
2603                 /* panel always on top, hidden while locked */
2604                 wl_list_insert(&shell->panel_layer.surface_list,
2605                                &surface->layer_link);
2606                 break;
2607         case SHELL_SURFACE_LOCK:
2608                 /* lock surface always visible, on top */
2609                 wl_list_insert(&shell->lock_layer.surface_list,
2610                                &surface->layer_link);
2611                 weston_compositor_wake(compositor);
2612                 break;
2613         case SHELL_SURFACE_SCREENSAVER:
2614                 /* If locked, show it. */
2615                 if (shell->locked) {
2616                         show_screensaver(shell, shsurf);
2617                         compositor->idle_time = shell->screensaver.duration;
2618                         weston_compositor_wake(compositor);
2619                         if (!shell->lock_surface)
2620                                 compositor->state = WESTON_COMPOSITOR_IDLE;
2621                 }
2622                 break;
2623         case SHELL_SURFACE_POPUP:
2624         case SHELL_SURFACE_TRANSIENT:
2625                 parent = shsurf->parent->surface;
2626                 wl_list_insert(parent->layer_link.prev, &surface->layer_link);
2627                 break;
2628         case SHELL_SURFACE_FULLSCREEN:
2629         case SHELL_SURFACE_NONE:
2630                 break;
2631         default:
2632                 ws = get_current_workspace(shell);
2633                 wl_list_insert(&ws->layer.surface_list, &surface->layer_link);
2634                 break;
2635         }
2636
2637         if (surface_type != SHELL_SURFACE_NONE) {
2638                 weston_surface_assign_output(surface);
2639                 if (surface_type == SHELL_SURFACE_MAXIMIZED)
2640                         surface->output = shsurf->output;
2641         }
2642
2643         switch (surface_type) {
2644         case SHELL_SURFACE_TRANSIENT:
2645                 if (shsurf->transient.flags ==
2646                                 WL_SHELL_SURFACE_TRANSIENT_INACTIVE)
2647                         break;
2648         case SHELL_SURFACE_TOPLEVEL:
2649         case SHELL_SURFACE_FULLSCREEN:
2650         case SHELL_SURFACE_MAXIMIZED:
2651                 if (!shell->locked) {
2652                         wl_list_for_each(seat, &compositor->seat_list, link)
2653                                 activate(shell, surface, seat);
2654                 }
2655                 break;
2656         default:
2657                 break;
2658         }
2659
2660         if (surface_type == SHELL_SURFACE_TOPLEVEL)
2661         {
2662                 switch (shell->win_animation_type) {
2663                 case ANIMATION_FADE:
2664                         weston_fade_run(surface, NULL, NULL);
2665                         break;
2666                 case ANIMATION_ZOOM:
2667                         weston_zoom_run(surface, 0.8, 1.0, NULL, NULL);
2668                         break;
2669                 default:
2670                         break;
2671                 }
2672         }
2673 }
2674
2675 static void
2676 configure(struct desktop_shell *shell, struct weston_surface *surface,
2677           GLfloat x, GLfloat y, int32_t width, int32_t height)
2678 {
2679         enum shell_surface_type surface_type = SHELL_SURFACE_NONE;
2680         struct shell_surface *shsurf;
2681
2682         shsurf = get_shell_surface(surface);
2683         if (shsurf)
2684                 surface_type = shsurf->type;
2685
2686         surface->geometry.x = x;
2687         surface->geometry.y = y;
2688         surface->geometry.width = width;
2689         surface->geometry.height = height;
2690         surface->geometry.dirty = 1;
2691
2692         switch (surface_type) {
2693         case SHELL_SURFACE_SCREENSAVER:
2694                 center_on_output(surface, shsurf->fullscreen_output);
2695                 break;
2696         case SHELL_SURFACE_FULLSCREEN:
2697                 shell_stack_fullscreen(shsurf);
2698                 shell_configure_fullscreen(shsurf);
2699                 break;
2700         case SHELL_SURFACE_MAXIMIZED:
2701                 /* setting x, y and using configure to change that geometry */
2702                 surface->geometry.x = surface->output->x;
2703                 surface->geometry.y = surface->output->y +
2704                         get_output_panel_height(shell,surface->output);
2705                 break;
2706         case SHELL_SURFACE_TOPLEVEL:
2707                 break;
2708         default:
2709                 break;
2710         }
2711
2712         /* XXX: would a fullscreen surface need the same handling? */
2713         if (surface->output) {
2714                 weston_surface_assign_output(surface);
2715
2716                 if (surface_type == SHELL_SURFACE_SCREENSAVER)
2717                         surface->output = shsurf->output;
2718                 else if (surface_type == SHELL_SURFACE_MAXIMIZED)
2719                         surface->output = shsurf->output;
2720         }
2721 }
2722
2723 static void
2724 shell_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy)
2725 {
2726         struct shell_surface *shsurf = get_shell_surface(es);
2727         struct desktop_shell *shell = shsurf->shell;
2728         int type_changed = 0;
2729
2730         if (shsurf->next_type != SHELL_SURFACE_NONE &&
2731             shsurf->type != shsurf->next_type) {
2732                 set_surface_type(shsurf);
2733                 type_changed = 1;
2734         }
2735
2736         if (!weston_surface_is_mapped(es)) {
2737                 map(shell, es, es->buffer->width, es->buffer->height, sx, sy);
2738         } else if (type_changed || sx != 0 || sy != 0 ||
2739                    es->geometry.width != es->buffer->width ||
2740                    es->geometry.height != es->buffer->height) {
2741                 GLfloat from_x, from_y;
2742                 GLfloat to_x, to_y;
2743
2744                 weston_surface_to_global_float(es, 0, 0, &from_x, &from_y);
2745                 weston_surface_to_global_float(es, sx, sy, &to_x, &to_y);
2746                 configure(shell, es,
2747                           es->geometry.x + to_x - from_x,
2748                           es->geometry.y + to_y - from_y,
2749                           es->buffer->width, es->buffer->height);
2750         }
2751 }
2752
2753 static int launch_desktop_shell_process(struct desktop_shell *shell);
2754
2755 static void
2756 desktop_shell_sigchld(struct weston_process *process, int status)
2757 {
2758         uint32_t time;
2759         struct desktop_shell *shell =
2760                 container_of(process, struct desktop_shell, child.process);
2761
2762         shell->child.process.pid = 0;
2763         shell->child.client = NULL; /* already destroyed by wayland */
2764
2765         /* if desktop-shell dies more than 5 times in 30 seconds, give up */
2766         time = weston_compositor_get_time();
2767         if (time - shell->child.deathstamp > 30000) {
2768                 shell->child.deathstamp = time;
2769                 shell->child.deathcount = 0;
2770         }
2771
2772         shell->child.deathcount++;
2773         if (shell->child.deathcount > 5) {
2774                 weston_log("weston-desktop-shell died, giving up.\n");
2775                 return;
2776         }
2777
2778         weston_log("weston-desktop-shell died, respawning...\n");
2779         launch_desktop_shell_process(shell);
2780 }
2781
2782 static int
2783 launch_desktop_shell_process(struct desktop_shell *shell)
2784 {
2785         const char *shell_exe = LIBEXECDIR "/weston-desktop-shell";
2786
2787         shell->child.client = weston_client_launch(shell->compositor,
2788                                                  &shell->child.process,
2789                                                  shell_exe,
2790                                                  desktop_shell_sigchld);
2791
2792         if (!shell->child.client)
2793                 return -1;
2794         return 0;
2795 }
2796
2797 static void
2798 bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
2799 {
2800         struct desktop_shell *shell = data;
2801
2802         wl_client_add_object(client, &wl_shell_interface,
2803                              &shell_implementation, id, shell);
2804 }
2805
2806 static void
2807 unbind_desktop_shell(struct wl_resource *resource)
2808 {
2809         struct desktop_shell *shell = resource->data;
2810
2811         if (shell->locked)
2812                 resume_desktop(shell);
2813
2814         shell->child.desktop_shell = NULL;
2815         shell->prepare_event_sent = false;
2816         free(resource);
2817 }
2818
2819 static void
2820 bind_desktop_shell(struct wl_client *client,
2821                    void *data, uint32_t version, uint32_t id)
2822 {
2823         struct desktop_shell *shell = data;
2824         struct wl_resource *resource;
2825
2826         resource = wl_client_add_object(client, &desktop_shell_interface,
2827                                         &desktop_shell_implementation,
2828                                         id, shell);
2829
2830         if (client == shell->child.client) {
2831                 resource->destroy = unbind_desktop_shell;
2832                 shell->child.desktop_shell = resource;
2833                 return;
2834         }
2835
2836         wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
2837                                "permission to bind desktop_shell denied");
2838         wl_resource_destroy(resource);
2839 }
2840
2841 static void
2842 screensaver_set_surface(struct wl_client *client,
2843                         struct wl_resource *resource,
2844                         struct wl_resource *shell_surface_resource,
2845                         struct wl_resource *output_resource)
2846 {
2847         struct desktop_shell *shell = resource->data;
2848         struct shell_surface *surface = shell_surface_resource->data;
2849         struct weston_output *output = output_resource->data;
2850
2851         surface->next_type = SHELL_SURFACE_SCREENSAVER;
2852
2853         surface->fullscreen_output = output;
2854         surface->output = output;
2855         wl_list_insert(shell->screensaver.surfaces.prev, &surface->link);
2856 }
2857
2858 static const struct screensaver_interface screensaver_implementation = {
2859         screensaver_set_surface
2860 };
2861
2862 static void
2863 unbind_screensaver(struct wl_resource *resource)
2864 {
2865         struct desktop_shell *shell = resource->data;
2866
2867         shell->screensaver.binding = NULL;
2868         free(resource);
2869 }
2870
2871 static void
2872 bind_screensaver(struct wl_client *client,
2873                  void *data, uint32_t version, uint32_t id)
2874 {
2875         struct desktop_shell *shell = data;
2876         struct wl_resource *resource;
2877
2878         resource = wl_client_add_object(client, &screensaver_interface,
2879                                         &screensaver_implementation,
2880                                         id, shell);
2881
2882         if (shell->screensaver.binding == NULL) {
2883                 resource->destroy = unbind_screensaver;
2884                 shell->screensaver.binding = resource;
2885                 return;
2886         }
2887
2888         wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
2889                                "interface object already bound");
2890         wl_resource_destroy(resource);
2891 }
2892
2893 struct switcher {
2894         struct desktop_shell *shell;
2895         struct weston_surface *current;
2896         struct wl_listener listener;
2897         struct wl_keyboard_grab grab;
2898 };
2899
2900 static void
2901 switcher_next(struct switcher *switcher)
2902 {
2903         struct weston_surface *surface;
2904         struct weston_surface *first = NULL, *prev = NULL, *next = NULL;
2905         struct shell_surface *shsurf;
2906         struct workspace *ws = get_current_workspace(switcher->shell);
2907
2908         wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
2909                 switch (get_shell_surface_type(surface)) {
2910                 case SHELL_SURFACE_TOPLEVEL:
2911                 case SHELL_SURFACE_FULLSCREEN:
2912                 case SHELL_SURFACE_MAXIMIZED:
2913                         if (first == NULL)
2914                                 first = surface;
2915                         if (prev == switcher->current)
2916                                 next = surface;
2917                         prev = surface;
2918                         surface->alpha = 0.25;
2919                         surface->geometry.dirty = 1;
2920                         weston_surface_damage(surface);
2921                         break;
2922                 default:
2923                         break;
2924                 }
2925
2926                 if (is_black_surface(surface, NULL)) {
2927                         surface->alpha = 0.25;
2928                         surface->geometry.dirty = 1;
2929                         weston_surface_damage(surface);
2930                 }
2931         }
2932
2933         if (next == NULL)
2934                 next = first;
2935
2936         if (next == NULL)
2937                 return;
2938
2939         wl_list_remove(&switcher->listener.link);
2940         wl_signal_add(&next->surface.resource.destroy_signal,
2941                       &switcher->listener);
2942
2943         switcher->current = next;
2944         next->alpha = 1.0;
2945
2946         shsurf = get_shell_surface(switcher->current);
2947         if (shsurf && shsurf->type ==SHELL_SURFACE_FULLSCREEN)
2948                 shsurf->fullscreen.black_surface->alpha = 1.0;
2949 }
2950
2951 static void
2952 switcher_handle_surface_destroy(struct wl_listener *listener, void *data)
2953 {
2954         struct switcher *switcher =
2955                 container_of(listener, struct switcher, listener);
2956
2957         switcher_next(switcher);
2958 }
2959
2960 static void
2961 switcher_destroy(struct switcher *switcher)
2962 {
2963         struct weston_surface *surface;
2964         struct wl_keyboard *keyboard = switcher->grab.keyboard;
2965         struct workspace *ws = get_current_workspace(switcher->shell);
2966
2967         wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
2968                 surface->alpha = 1.0;
2969                 weston_surface_damage(surface);
2970         }
2971
2972         if (switcher->current)
2973                 activate(switcher->shell, switcher->current,
2974                          (struct weston_seat *) keyboard->seat);
2975         wl_list_remove(&switcher->listener.link);
2976         wl_keyboard_end_grab(keyboard);
2977         free(switcher);
2978 }
2979
2980 static void
2981 switcher_key(struct wl_keyboard_grab *grab,
2982              uint32_t time, uint32_t key, uint32_t state_w)
2983 {
2984         struct switcher *switcher = container_of(grab, struct switcher, grab);
2985         enum wl_keyboard_key_state state = state_w;
2986
2987         if (key == KEY_TAB && state == WL_KEYBOARD_KEY_STATE_PRESSED)
2988                 switcher_next(switcher);
2989 }
2990
2991 static void
2992 switcher_modifier(struct wl_keyboard_grab *grab, uint32_t serial,
2993                   uint32_t mods_depressed, uint32_t mods_latched,
2994                   uint32_t mods_locked, uint32_t group)
2995 {
2996         struct switcher *switcher = container_of(grab, struct switcher, grab);
2997         struct weston_seat *seat = (struct weston_seat *) grab->keyboard->seat;
2998
2999         if ((seat->modifier_state & switcher->shell->binding_modifier) == 0)
3000                 switcher_destroy(switcher);
3001 }
3002
3003 static const struct wl_keyboard_grab_interface switcher_grab = {
3004         switcher_key,
3005         switcher_modifier,
3006 };
3007
3008 static void
3009 switcher_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
3010                  void *data)
3011 {
3012         struct desktop_shell *shell = data;
3013         struct switcher *switcher;
3014
3015         switcher = malloc(sizeof *switcher);
3016         switcher->shell = shell;
3017         switcher->current = NULL;
3018         switcher->listener.notify = switcher_handle_surface_destroy;
3019         wl_list_init(&switcher->listener.link);
3020
3021         lower_fullscreen_layer(switcher->shell);
3022         switcher->grab.interface = &switcher_grab;
3023         wl_keyboard_start_grab(seat->keyboard, &switcher->grab);
3024         wl_keyboard_set_focus(seat->keyboard, NULL);
3025         switcher_next(switcher);
3026 }
3027
3028 static void
3029 backlight_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
3030                   void *data)
3031 {
3032         struct weston_compositor *compositor = data;
3033         struct weston_output *output;
3034         long backlight_new = 0;
3035
3036         /* TODO: we're limiting to simple use cases, where we assume just
3037          * control on the primary display. We'd have to extend later if we
3038          * ever get support for setting backlights on random desktop LCD
3039          * panels though */
3040         output = get_default_output(compositor);
3041         if (!output)
3042                 return;
3043
3044         if (!output->set_backlight)
3045                 return;
3046
3047         if (key == KEY_F9 || key == KEY_BRIGHTNESSDOWN)
3048                 backlight_new = output->backlight_current - 25;
3049         else if (key == KEY_F10 || key == KEY_BRIGHTNESSUP)
3050                 backlight_new = output->backlight_current + 25;
3051
3052         if (backlight_new < 5)
3053                 backlight_new = 5;
3054         if (backlight_new > 255)
3055                 backlight_new = 255;
3056
3057         output->backlight_current = backlight_new;
3058         output->set_backlight(output, output->backlight_current);
3059 }
3060
3061 static void
3062 debug_repaint_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
3063                       void *data)
3064 {
3065         struct desktop_shell *shell = data;
3066         struct weston_compositor *compositor = shell->compositor;
3067         struct weston_surface *surface;
3068
3069         if (shell->debug_repaint_surface) {
3070                 weston_surface_destroy(shell->debug_repaint_surface);
3071                 shell->debug_repaint_surface = NULL;
3072         } else {
3073                 surface = weston_surface_create(compositor);
3074                 weston_surface_set_color(surface, 1.0, 0.0, 0.0, 0.2);
3075                 weston_surface_configure(surface, 0, 0, 8192, 8192);
3076                 wl_list_insert(&compositor->fade_layer.surface_list,
3077                                &surface->layer_link);
3078                 weston_surface_assign_output(surface);
3079                 pixman_region32_init(&surface->input);
3080
3081                 /* Here's the dirty little trick that makes the
3082                  * repaint debugging work: we force an
3083                  * update_transform first to update dependent state
3084                  * and clear the geometry.dirty bit.  Then we clear
3085                  * the surface damage so it only gets repainted
3086                  * piecewise as we repaint other things.  */
3087
3088                 weston_surface_update_transform(surface);
3089                 pixman_region32_fini(&surface->damage);
3090                 pixman_region32_init(&surface->damage);
3091                 shell->debug_repaint_surface = surface;
3092         }
3093 }
3094
3095 static void
3096 force_kill_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
3097                    void *data)
3098 {
3099         struct wl_client *client;
3100         pid_t pid;
3101         uid_t uid;
3102         gid_t gid;
3103
3104         client = seat->keyboard->focus->resource.client;
3105         wl_client_get_credentials(client, &pid, &uid, &gid);
3106
3107         kill(pid, SIGKILL);
3108 }
3109
3110 static void
3111 workspace_up_binding(struct wl_seat *seat, uint32_t time,
3112                      uint32_t key, void *data)
3113 {
3114         struct desktop_shell *shell = data;
3115         unsigned int new_index = shell->workspaces.current;
3116
3117         if (new_index != 0)
3118                 new_index--;
3119
3120         change_workspace(shell, new_index);
3121 }
3122
3123 static void
3124 workspace_down_binding(struct wl_seat *seat, uint32_t time,
3125                        uint32_t key, void *data)
3126 {
3127         struct desktop_shell *shell = data;
3128         unsigned int new_index = shell->workspaces.current;
3129
3130         if (new_index < shell->workspaces.num - 1)
3131                 new_index++;
3132
3133         change_workspace(shell, new_index);
3134 }
3135
3136 static void
3137 workspace_f_binding(struct wl_seat *seat, uint32_t time,
3138                     uint32_t key, void *data)
3139 {
3140         struct desktop_shell *shell = data;
3141         unsigned int new_index;
3142
3143         new_index = key - KEY_F1;
3144         if (new_index >= shell->workspaces.num)
3145                 new_index = shell->workspaces.num - 1;
3146
3147         change_workspace(shell, new_index);
3148 }
3149
3150
3151 static void
3152 shell_destroy(struct wl_listener *listener, void *data)
3153 {
3154         struct desktop_shell *shell =
3155                 container_of(listener, struct desktop_shell, destroy_listener);
3156         struct workspace **ws;
3157
3158         if (shell->child.client)
3159                 wl_client_destroy(shell->child.client);
3160
3161         wl_list_remove(&shell->lock_listener.link);
3162         wl_list_remove(&shell->unlock_listener.link);
3163
3164         wl_array_for_each(ws, &shell->workspaces.array)
3165                 workspace_destroy(*ws);
3166         wl_array_release(&shell->workspaces.array);
3167
3168         free(shell->screensaver.path);
3169         free(shell);
3170 }
3171
3172 static void
3173 shell_add_bindings(struct weston_compositor *ec, struct desktop_shell *shell)
3174 {
3175         uint32_t mod;
3176         int i, num_workspace_bindings;
3177
3178         /* fixed bindings */
3179         weston_compositor_add_key_binding(ec, KEY_BACKSPACE,
3180                                           MODIFIER_CTRL | MODIFIER_ALT,
3181                                           terminate_binding, ec);
3182         weston_compositor_add_button_binding(ec, BTN_LEFT, 0,
3183                                              click_to_activate_binding,
3184                                              shell);
3185         weston_compositor_add_axis_binding(ec, WL_POINTER_AXIS_VERTICAL_SCROLL,
3186                                            MODIFIER_SUPER | MODIFIER_ALT,
3187                                            surface_opacity_binding, NULL);
3188         weston_compositor_add_axis_binding(ec, WL_POINTER_AXIS_VERTICAL_SCROLL,
3189                                            MODIFIER_SUPER, zoom_axis_binding,
3190                                            NULL);
3191
3192         /* configurable bindings */
3193         mod = shell->binding_modifier;
3194         weston_compositor_add_key_binding(ec, KEY_PAGEUP, mod,
3195                                           zoom_key_binding, NULL);
3196         weston_compositor_add_key_binding(ec, KEY_PAGEDOWN, mod,
3197                                           zoom_key_binding, NULL);
3198         weston_compositor_add_button_binding(ec, BTN_LEFT, mod, move_binding,
3199                                              shell);
3200         weston_compositor_add_button_binding(ec, BTN_MIDDLE, mod,
3201                                              resize_binding, shell);
3202         weston_compositor_add_button_binding(ec, BTN_RIGHT, mod,
3203                                              rotate_binding, NULL);
3204         weston_compositor_add_key_binding(ec, KEY_TAB, mod, switcher_binding,
3205                                           shell);
3206         weston_compositor_add_key_binding(ec, KEY_F9, mod, backlight_binding,
3207                                           ec);
3208         weston_compositor_add_key_binding(ec, KEY_BRIGHTNESSDOWN, 0,
3209                                           backlight_binding, ec);
3210         weston_compositor_add_key_binding(ec, KEY_F10, mod, backlight_binding,
3211                                           ec);
3212         weston_compositor_add_key_binding(ec, KEY_BRIGHTNESSUP, 0,
3213                                           backlight_binding, ec);
3214         weston_compositor_add_key_binding(ec, KEY_SPACE, mod,
3215                                           debug_repaint_binding, shell);
3216         weston_compositor_add_key_binding(ec, KEY_K, mod,
3217                                           force_kill_binding, shell);
3218         weston_compositor_add_key_binding(ec, KEY_UP, mod,
3219                                           workspace_up_binding, shell);
3220         weston_compositor_add_key_binding(ec, KEY_DOWN, mod,
3221                                           workspace_down_binding, shell);
3222
3223         /* Add bindings for mod+F[1-6] for workspace 1 to 6. */
3224         if (shell->workspaces.num > 1) {
3225                 num_workspace_bindings = shell->workspaces.num;
3226                 if (num_workspace_bindings > 6)
3227                         num_workspace_bindings = 6;
3228                 for (i = 0; i < num_workspace_bindings; i++)
3229                         weston_compositor_add_key_binding(ec, KEY_F1 + i, mod,
3230                                                           workspace_f_binding,
3231                                                           shell);
3232         }
3233 }
3234
3235 int
3236 shell_init(struct weston_compositor *ec);
3237
3238 WL_EXPORT int
3239 shell_init(struct weston_compositor *ec)
3240 {
3241         struct desktop_shell *shell;
3242         struct workspace **pws;
3243         unsigned int i;
3244
3245         shell = malloc(sizeof *shell);
3246         if (shell == NULL)
3247                 return -1;
3248
3249         memset(shell, 0, sizeof *shell);
3250         shell->compositor = ec;
3251
3252         shell->destroy_listener.notify = shell_destroy;
3253         wl_signal_add(&ec->destroy_signal, &shell->destroy_listener);
3254         shell->lock_listener.notify = lock;
3255         wl_signal_add(&ec->lock_signal, &shell->lock_listener);
3256         shell->unlock_listener.notify = unlock;
3257         wl_signal_add(&ec->unlock_signal, &shell->unlock_listener);
3258         ec->ping_handler = ping_handler;
3259         ec->shell_interface.create_shell_surface = create_shell_surface;
3260         ec->shell_interface.set_toplevel = set_toplevel;
3261         ec->shell_interface.set_transient = set_transient;
3262         ec->shell_interface.move = surface_move;
3263         ec->shell_interface.resize = surface_resize;
3264
3265         wl_list_init(&shell->backgrounds);
3266         wl_list_init(&shell->panels);
3267         wl_list_init(&shell->screensaver.surfaces);
3268
3269         weston_layer_init(&shell->fullscreen_layer, &ec->cursor_layer.link);
3270         weston_layer_init(&shell->panel_layer, &shell->fullscreen_layer.link);
3271         weston_layer_init(&shell->background_layer, &shell->panel_layer.link);
3272         weston_layer_init(&shell->lock_layer, NULL);
3273
3274         wl_array_init(&shell->workspaces.array);
3275
3276         shell_configuration(shell);
3277
3278         for (i = 0; i < shell->workspaces.num; i++) {
3279                 pws = wl_array_add(&shell->workspaces.array, sizeof *pws);
3280                 if (pws == NULL)
3281                         return -1;
3282
3283                 *pws = workspace_create();
3284                 if (*pws == NULL)
3285                         return -1;
3286         }
3287         activate_workspace(shell, 0);
3288
3289         wl_list_init(&shell->workspaces.animation.link);
3290         shell->workspaces.animation.frame = animate_workspace_change_frame;
3291
3292         if (wl_display_add_global(ec->wl_display, &wl_shell_interface,
3293                                   shell, bind_shell) == NULL)
3294                 return -1;
3295
3296         if (wl_display_add_global(ec->wl_display,
3297                                   &desktop_shell_interface,
3298                                   shell, bind_desktop_shell) == NULL)
3299                 return -1;
3300
3301         if (wl_display_add_global(ec->wl_display, &screensaver_interface,
3302                                   shell, bind_screensaver) == NULL)
3303                 return -1;
3304
3305         shell->child.deathstamp = weston_compositor_get_time();
3306         if (launch_desktop_shell_process(shell) != 0)
3307                 return -1;
3308
3309         shell->pointer_focus_listener.notify = handle_pointer_focus;
3310         if (ec->seat->seat.pointer)
3311                 wl_signal_add(&ec->seat->seat.pointer->focus_signal,
3312                               &shell->pointer_focus_listener);
3313
3314         shell_add_bindings(ec, shell);
3315
3316         return 0;
3317 }