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