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