shell: Emit destroy signal for when we manually destroy shell surface
[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         if (shsurf->resource.client) {
1287                 wl_resource_destroy(&shsurf->resource);
1288         } else {
1289                 wl_signal_emit(&shsurf->resource.destroy_signal,
1290                                &shsurf->resource);
1291                 destroy_shell_surface(shsurf);
1292         }
1293 }
1294
1295 static struct shell_surface *
1296 get_shell_surface(struct weston_surface *surface)
1297 {
1298         struct wl_listener *listener;
1299
1300         listener = wl_signal_get(&surface->surface.resource.destroy_signal,
1301                                  shell_handle_surface_destroy);
1302         if (listener)
1303                 return container_of(listener, struct shell_surface,
1304                                     surface_destroy_listener);
1305
1306         return NULL;
1307 }
1308
1309 static void
1310 shell_surface_configure(struct weston_surface *, int32_t, int32_t);
1311
1312 static  struct shell_surface *
1313 create_shell_surface(void *shell, struct weston_surface *surface,
1314                      const struct weston_shell_client *client)
1315 {
1316         struct shell_surface *shsurf;
1317
1318         if (surface->configure) {
1319                 fprintf(stderr, "surface->configure already set\n");
1320                 return NULL;
1321         }
1322
1323         shsurf = calloc(1, sizeof *shsurf);
1324         if (!shsurf) {
1325                 fprintf(stderr, "no memory to allocate shell surface\n");
1326                 return NULL;
1327         }
1328
1329         surface->configure = shell_surface_configure;
1330         surface->compositor->shell_interface.shell = shell;
1331
1332         shsurf->shell = (struct desktop_shell *) shell;
1333         shsurf->unresponsive = 0;
1334         shsurf->saved_position_valid = false;
1335         shsurf->saved_rotation_valid = false;
1336         shsurf->surface = surface;
1337         shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
1338         shsurf->fullscreen.framerate = 0;
1339         shsurf->fullscreen.black_surface = NULL;
1340         shsurf->ping_timer = NULL;
1341         wl_list_init(&shsurf->fullscreen.transform.link);
1342
1343         wl_signal_init(&shsurf->resource.destroy_signal);
1344         shsurf->surface_destroy_listener.notify = shell_handle_surface_destroy;
1345         wl_signal_add(&surface->surface.resource.destroy_signal,
1346                       &shsurf->surface_destroy_listener);
1347
1348         /* init link so its safe to always remove it in destroy_shell_surface */
1349         wl_list_init(&shsurf->link);
1350
1351         /* empty when not in use */
1352         wl_list_init(&shsurf->rotation.transform.link);
1353         weston_matrix_init(&shsurf->rotation.rotation);
1354
1355         shsurf->type = SHELL_SURFACE_NONE;
1356         shsurf->next_type = SHELL_SURFACE_NONE;
1357
1358         shsurf->client = client;
1359
1360         return shsurf;
1361 }
1362
1363 static void
1364 shell_get_shell_surface(struct wl_client *client,
1365                         struct wl_resource *resource,
1366                         uint32_t id,
1367                         struct wl_resource *surface_resource)
1368 {
1369         struct weston_surface *surface = surface_resource->data;
1370         struct desktop_shell *shell = resource->data;
1371         struct shell_surface *shsurf;
1372
1373         if (get_shell_surface(surface)) {
1374                 wl_resource_post_error(surface_resource,
1375                                        WL_DISPLAY_ERROR_INVALID_OBJECT,
1376                                        "desktop_shell::get_shell_surface already requested");
1377                 return;
1378         }
1379
1380         shsurf = create_shell_surface(shell, surface, &shell_client);
1381         if (!shsurf) {
1382                 wl_resource_post_error(surface_resource,
1383                                        WL_DISPLAY_ERROR_INVALID_OBJECT,
1384                                        "surface->configure already set");
1385                 return;
1386         }
1387
1388         shsurf->resource.destroy = shell_destroy_shell_surface;
1389         shsurf->resource.object.id = id;
1390         shsurf->resource.object.interface = &wl_shell_surface_interface;
1391         shsurf->resource.object.implementation =
1392                 (void (**)(void)) &shell_surface_implementation;
1393         shsurf->resource.data = shsurf;
1394
1395         wl_client_add_resource(client, &shsurf->resource);
1396 }
1397
1398 static const struct wl_shell_interface shell_implementation = {
1399         shell_get_shell_surface
1400 };
1401
1402 static void
1403 handle_screensaver_sigchld(struct weston_process *proc, int status)
1404 {
1405         proc->pid = 0;
1406 }
1407
1408 static void
1409 launch_screensaver(struct desktop_shell *shell)
1410 {
1411         if (shell->screensaver.binding)
1412                 return;
1413
1414         if (!shell->screensaver.path)
1415                 return;
1416
1417         if (shell->screensaver.process.pid != 0) {
1418                 fprintf(stderr, "old screensaver still running\n");
1419                 return;
1420         }
1421
1422         weston_client_launch(shell->compositor,
1423                            &shell->screensaver.process,
1424                            shell->screensaver.path,
1425                            handle_screensaver_sigchld);
1426 }
1427
1428 static void
1429 terminate_screensaver(struct desktop_shell *shell)
1430 {
1431         if (shell->screensaver.process.pid == 0)
1432                 return;
1433
1434         kill(shell->screensaver.process.pid, SIGTERM);
1435 }
1436
1437 static void
1438 show_screensaver(struct desktop_shell *shell, struct shell_surface *surface)
1439 {
1440         struct wl_list *list;
1441
1442         if (shell->lock_surface)
1443                 list = &shell->lock_surface->surface->layer_link;
1444         else
1445                 list = &shell->lock_layer.surface_list;
1446
1447         wl_list_remove(&surface->surface->layer_link);
1448         wl_list_insert(list, &surface->surface->layer_link);
1449         surface->surface->output = surface->output;
1450         weston_surface_damage(surface->surface);
1451 }
1452
1453 static void
1454 hide_screensaver(struct desktop_shell *shell, struct shell_surface *surface)
1455 {
1456         wl_list_remove(&surface->surface->layer_link);
1457         wl_list_init(&surface->surface->layer_link);
1458         surface->surface->output = NULL;
1459 }
1460
1461 static void
1462 desktop_shell_set_background(struct wl_client *client,
1463                              struct wl_resource *resource,
1464                              struct wl_resource *output_resource,
1465                              struct wl_resource *surface_resource)
1466 {
1467         struct shell_surface *shsurf = surface_resource->data;
1468
1469         shsurf->next_type = SHELL_SURFACE_BACKGROUND;
1470         shsurf->output = output_resource->data;
1471
1472         desktop_shell_send_configure(resource, 0,
1473                                      surface_resource,
1474                                      shsurf->output->current->width,
1475                                      shsurf->output->current->height);
1476 }
1477
1478 static void
1479 desktop_shell_set_panel(struct wl_client *client,
1480                         struct wl_resource *resource,
1481                         struct wl_resource *output_resource,
1482                         struct wl_resource *surface_resource)
1483 {
1484         struct shell_surface *shsurf = surface_resource->data;
1485
1486         shsurf->next_type = SHELL_SURFACE_PANEL;
1487         shsurf->output = output_resource->data;
1488
1489         desktop_shell_send_configure(resource, 0,
1490                                      surface_resource,
1491                                      shsurf->output->current->width,
1492                                      shsurf->output->current->height);
1493 }
1494
1495 static void
1496 handle_lock_surface_destroy(struct wl_listener *listener, void *data)
1497 {
1498         struct desktop_shell *shell =
1499             container_of(listener, struct desktop_shell, lock_surface_listener);
1500
1501         fprintf(stderr, "lock surface gone\n");
1502         shell->lock_surface = NULL;
1503 }
1504
1505 static void
1506 desktop_shell_set_lock_surface(struct wl_client *client,
1507                                struct wl_resource *resource,
1508                                struct wl_resource *surface_resource)
1509 {
1510         struct desktop_shell *shell = resource->data;
1511         struct shell_surface *surface = surface_resource->data;
1512
1513         shell->prepare_event_sent = false;
1514
1515         if (!shell->locked)
1516                 return;
1517
1518         shell->lock_surface = surface;
1519
1520         shell->lock_surface_listener.notify = handle_lock_surface_destroy;
1521         wl_signal_add(&surface_resource->destroy_signal,
1522                       &shell->lock_surface_listener);
1523
1524         shell->lock_surface->next_type = SHELL_SURFACE_LOCK;
1525 }
1526
1527 static void
1528 resume_desktop(struct desktop_shell *shell)
1529 {
1530         struct shell_surface *tmp;
1531
1532         wl_list_for_each(tmp, &shell->screensaver.surfaces, link)
1533                 hide_screensaver(shell, tmp);
1534
1535         terminate_screensaver(shell);
1536
1537         wl_list_remove(&shell->lock_layer.link);
1538         wl_list_insert(&shell->compositor->cursor_layer.link,
1539                        &shell->fullscreen_layer.link);
1540         wl_list_insert(&shell->fullscreen_layer.link,
1541                        &shell->panel_layer.link);
1542         wl_list_insert(&shell->panel_layer.link, &shell->toplevel_layer.link);
1543
1544         shell->locked = false;
1545         shell->compositor->idle_time = shell->compositor->option_idle_time;
1546         weston_compositor_wake(shell->compositor);
1547         weston_compositor_damage_all(shell->compositor);
1548 }
1549
1550 static void
1551 desktop_shell_unlock(struct wl_client *client,
1552                      struct wl_resource *resource)
1553 {
1554         struct desktop_shell *shell = resource->data;
1555
1556         shell->prepare_event_sent = false;
1557
1558         if (shell->locked)
1559                 resume_desktop(shell);
1560 }
1561
1562 static void
1563 desktop_shell_set_busy_surface(struct wl_client *client,
1564                                struct wl_resource *resource,
1565                                struct wl_resource *surface_resource)
1566 {
1567         struct desktop_shell *shell = resource->data;
1568
1569         shell->busy_surface = surface_resource->data;
1570 }
1571
1572 static const struct desktop_shell_interface desktop_shell_implementation = {
1573         desktop_shell_set_background,
1574         desktop_shell_set_panel,
1575         desktop_shell_set_lock_surface,
1576         desktop_shell_unlock,
1577         desktop_shell_set_busy_surface
1578 };
1579
1580 static enum shell_surface_type
1581 get_shell_surface_type(struct weston_surface *surface)
1582 {
1583         struct shell_surface *shsurf;
1584
1585         shsurf = get_shell_surface(surface);
1586         if (!shsurf)
1587                 return SHELL_SURFACE_NONE;
1588         return shsurf->type;
1589 }
1590
1591 static void
1592 move_binding(struct wl_seat *seat, uint32_t time, uint32_t button, void *data)
1593 {
1594         struct weston_surface *surface =
1595                 (struct weston_surface *) seat->pointer->focus;
1596         struct shell_surface *shsurf;
1597
1598         if (surface == NULL)
1599                 return;
1600
1601         shsurf = get_shell_surface(surface);
1602         if (shsurf == NULL)
1603                 return;
1604
1605         switch (shsurf->type) {
1606                 case SHELL_SURFACE_PANEL:
1607                 case SHELL_SURFACE_BACKGROUND:
1608                 case SHELL_SURFACE_FULLSCREEN:
1609                 case SHELL_SURFACE_SCREENSAVER:
1610                         return;
1611                 default:
1612                         break;
1613         }
1614
1615         surface_move(shsurf, (struct weston_seat *) seat);
1616 }
1617
1618 static void
1619 resize_binding(struct wl_seat *seat, uint32_t time, uint32_t button, void *data)
1620 {
1621         struct weston_surface *surface =
1622                 (struct weston_surface *) seat->pointer->focus;
1623         uint32_t edges = 0;
1624         int32_t x, y;
1625         struct shell_surface *shsurf;
1626
1627         if (surface == NULL)
1628                 return;
1629
1630         shsurf = get_shell_surface(surface);
1631         if (!shsurf)
1632                 return;
1633
1634         switch (shsurf->type) {
1635                 case SHELL_SURFACE_PANEL:
1636                 case SHELL_SURFACE_BACKGROUND:
1637                 case SHELL_SURFACE_FULLSCREEN:
1638                 case SHELL_SURFACE_SCREENSAVER:
1639                         return;
1640                 default:
1641                         break;
1642         }
1643
1644         weston_surface_from_global(surface,
1645                                    wl_fixed_to_int(seat->pointer->grab_x),
1646                                    wl_fixed_to_int(seat->pointer->grab_y),
1647                                    &x, &y);
1648
1649         if (x < surface->geometry.width / 3)
1650                 edges |= WL_SHELL_SURFACE_RESIZE_LEFT;
1651         else if (x < 2 * surface->geometry.width / 3)
1652                 edges |= 0;
1653         else
1654                 edges |= WL_SHELL_SURFACE_RESIZE_RIGHT;
1655
1656         if (y < surface->geometry.height / 3)
1657                 edges |= WL_SHELL_SURFACE_RESIZE_TOP;
1658         else if (y < 2 * surface->geometry.height / 3)
1659                 edges |= 0;
1660         else
1661                 edges |= WL_SHELL_SURFACE_RESIZE_BOTTOM;
1662
1663         surface_resize(shsurf, (struct weston_seat *) seat, edges);
1664 }
1665
1666 static void
1667 surface_opacity_binding(struct wl_seat *seat, uint32_t time, uint32_t axis,
1668                         wl_fixed_t value, void *data)
1669 {
1670         float step = 0.05;
1671         struct shell_surface *shsurf;
1672         struct weston_surface *surface =
1673                 (struct weston_surface *) seat->pointer->focus;
1674
1675         if (surface == NULL)
1676                 return;
1677
1678         shsurf = get_shell_surface(surface);
1679         if (!shsurf)
1680                 return;
1681
1682         switch (shsurf->type) {
1683                 case SHELL_SURFACE_BACKGROUND:
1684                 case SHELL_SURFACE_SCREENSAVER:
1685                         return;
1686                 default:
1687                         break;
1688         }
1689
1690         surface->alpha += wl_fixed_to_double(value) * step;
1691
1692         if (surface->alpha > 1.0)
1693                 surface->alpha = 1.0;
1694         if (surface->alpha < step)
1695                 surface->alpha = step;
1696
1697         surface->geometry.dirty = 1;
1698         weston_surface_damage(surface);
1699 }
1700
1701 static void
1702 do_zoom(struct wl_seat *seat, uint32_t time, uint32_t key, uint32_t axis,
1703         wl_fixed_t value)
1704 {
1705         struct weston_seat *ws = (struct weston_seat *) seat;
1706         struct weston_compositor *compositor = ws->compositor;
1707         struct weston_output *output;
1708         float maximum_level, increment;
1709
1710         wl_list_for_each(output, &compositor->output_list, link) {
1711                 if (pixman_region32_contains_point(&output->region,
1712                                                    wl_fixed_to_double(seat->pointer->x),
1713                                                    wl_fixed_to_double(seat->pointer->y),
1714                                                    NULL)) {
1715                         if (key == KEY_PAGEUP)
1716                                 increment = output->zoom.increment;
1717                         else if (key == KEY_PAGEDOWN)
1718                                 increment = -output->zoom.increment;
1719                         else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
1720                                 increment = output->zoom.increment *
1721                                             wl_fixed_to_double(value);
1722                         else
1723                                 increment = 0;
1724
1725                         output->zoom.active = 1;
1726                         output->zoom.level += increment;
1727
1728                         if (output->zoom.level <= 0.0) {
1729                                 output->zoom.active = 0;
1730                                 output->zoom.level = 0.0;
1731                         }
1732
1733                         maximum_level = 1 - output->zoom.increment;
1734
1735                         if (output->zoom.level > maximum_level)
1736                                 output->zoom.level = maximum_level;
1737
1738                         weston_output_update_zoom(output,
1739                                                   seat->pointer->x,
1740                                                   seat->pointer->y,
1741                                                   ZOOM_POINTER);
1742                 }
1743         }
1744 }
1745
1746 static void
1747 zoom_axis_binding(struct wl_seat *seat, uint32_t time, uint32_t axis,
1748                   wl_fixed_t value, void *data)
1749 {
1750         do_zoom(seat, time, 0, axis, value);
1751 }
1752
1753 static void
1754 zoom_key_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
1755                  void *data)
1756 {
1757         do_zoom(seat, time, key, 0, 0);
1758 }
1759
1760 static void
1761 terminate_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
1762                   void *data)
1763 {
1764         struct weston_compositor *compositor = data;
1765
1766         wl_display_terminate(compositor->wl_display);
1767 }
1768
1769 static void
1770 rotate_grab_motion(struct wl_pointer_grab *grab,
1771                    uint32_t time, wl_fixed_t x, wl_fixed_t y)
1772 {
1773         struct rotate_grab *rotate =
1774                 container_of(grab, struct rotate_grab, base.grab);
1775         struct wl_pointer *pointer = grab->pointer;
1776         struct shell_surface *shsurf = rotate->base.shsurf;
1777         struct weston_surface *surface;
1778         GLfloat cx, cy, dx, dy, cposx, cposy, dposx, dposy, r;
1779
1780         if (!shsurf)
1781                 return;
1782
1783         surface = shsurf->surface;
1784
1785         cx = 0.5f * surface->geometry.width;
1786         cy = 0.5f * surface->geometry.height;
1787
1788         dx = wl_fixed_to_double(pointer->x) - rotate->center.x;
1789         dy = wl_fixed_to_double(pointer->y) - rotate->center.y;
1790         r = sqrtf(dx * dx + dy * dy);
1791
1792         wl_list_remove(&shsurf->rotation.transform.link);
1793         shsurf->surface->geometry.dirty = 1;
1794
1795         if (r > 20.0f) {
1796                 struct weston_matrix *matrix =
1797                         &shsurf->rotation.transform.matrix;
1798
1799                 weston_matrix_init(&rotate->rotation);
1800                 rotate->rotation.d[0] = dx / r;
1801                 rotate->rotation.d[4] = -dy / r;
1802                 rotate->rotation.d[1] = -rotate->rotation.d[4];
1803                 rotate->rotation.d[5] = rotate->rotation.d[0];
1804
1805                 weston_matrix_init(matrix);
1806                 weston_matrix_translate(matrix, -cx, -cy, 0.0f);
1807                 weston_matrix_multiply(matrix, &shsurf->rotation.rotation);
1808                 weston_matrix_multiply(matrix, &rotate->rotation);
1809                 weston_matrix_translate(matrix, cx, cy, 0.0f);
1810
1811                 wl_list_insert(
1812                         &shsurf->surface->geometry.transformation_list,
1813                         &shsurf->rotation.transform.link);
1814         } else {
1815                 wl_list_init(&shsurf->rotation.transform.link);
1816                 weston_matrix_init(&shsurf->rotation.rotation);
1817                 weston_matrix_init(&rotate->rotation);
1818         }
1819
1820         /* We need to adjust the position of the surface
1821          * in case it was resized in a rotated state before */
1822         cposx = surface->geometry.x + cx;
1823         cposy = surface->geometry.y + cy;
1824         dposx = rotate->center.x - cposx;
1825         dposy = rotate->center.y - cposy;
1826         if (dposx != 0.0f || dposy != 0.0f) {
1827                 weston_surface_set_position(surface,
1828                                             surface->geometry.x + dposx,
1829                                             surface->geometry.y + dposy);
1830         }
1831
1832         /* Repaint implies weston_surface_update_transform(), which
1833          * lazily applies the damage due to rotation update.
1834          */
1835         weston_compositor_schedule_repaint(shsurf->surface->compositor);
1836 }
1837
1838 static void
1839 rotate_grab_button(struct wl_pointer_grab *grab,
1840                  uint32_t time, uint32_t button, uint32_t state_w)
1841 {
1842         struct rotate_grab *rotate =
1843                 container_of(grab, struct rotate_grab, base.grab);
1844         struct wl_pointer *pointer = grab->pointer;
1845         struct shell_surface *shsurf = rotate->base.shsurf;
1846         enum wl_pointer_button_state state = state_w;
1847
1848         if (pointer->button_count == 0 &&
1849             state == WL_POINTER_BUTTON_STATE_RELEASED) {
1850                 if (shsurf)
1851                         weston_matrix_multiply(&shsurf->rotation.rotation,
1852                                                &rotate->rotation);
1853                 shell_grab_finish(&rotate->base);
1854                 wl_pointer_end_grab(pointer);
1855                 free(rotate);
1856         }
1857 }
1858
1859 static const struct wl_pointer_grab_interface rotate_grab_interface = {
1860         noop_grab_focus,
1861         rotate_grab_motion,
1862         rotate_grab_button,
1863 };
1864
1865 static void
1866 rotate_binding(struct wl_seat *seat, uint32_t time, uint32_t button,
1867                void *data)
1868 {
1869         struct weston_surface *base_surface =
1870                 (struct weston_surface *) seat->pointer->focus;
1871         struct shell_surface *surface;
1872         struct rotate_grab *rotate;
1873         GLfloat dx, dy;
1874         GLfloat r;
1875
1876         if (base_surface == NULL)
1877                 return;
1878
1879         surface = get_shell_surface(base_surface);
1880         if (!surface)
1881                 return;
1882
1883         switch (surface->type) {
1884                 case SHELL_SURFACE_PANEL:
1885                 case SHELL_SURFACE_BACKGROUND:
1886                 case SHELL_SURFACE_FULLSCREEN:
1887                 case SHELL_SURFACE_SCREENSAVER:
1888                         return;
1889                 default:
1890                         break;
1891         }
1892
1893         rotate = malloc(sizeof *rotate);
1894         if (!rotate)
1895                 return;
1896
1897         shell_grab_init(&rotate->base, &rotate_grab_interface, surface);
1898
1899         weston_surface_to_global(surface->surface,
1900                                  surface->surface->geometry.width / 2,
1901                                  surface->surface->geometry.height / 2,
1902                                  &rotate->center.x, &rotate->center.y);
1903
1904         wl_pointer_start_grab(seat->pointer, &rotate->base.grab);
1905
1906         dx = wl_fixed_to_double(seat->pointer->x) - rotate->center.x;
1907         dy = wl_fixed_to_double(seat->pointer->y) - rotate->center.y;
1908         r = sqrtf(dx * dx + dy * dy);
1909         if (r > 20.0f) {
1910                 struct weston_matrix inverse;
1911
1912                 weston_matrix_init(&inverse);
1913                 inverse.d[0] = dx / r;
1914                 inverse.d[4] = dy / r;
1915                 inverse.d[1] = -inverse.d[4];
1916                 inverse.d[5] = inverse.d[0];
1917                 weston_matrix_multiply(&surface->rotation.rotation, &inverse);
1918
1919                 weston_matrix_init(&rotate->rotation);
1920                 rotate->rotation.d[0] = dx / r;
1921                 rotate->rotation.d[4] = -dy / r;
1922                 rotate->rotation.d[1] = -rotate->rotation.d[4];
1923                 rotate->rotation.d[5] = rotate->rotation.d[0];
1924         } else {
1925                 weston_matrix_init(&surface->rotation.rotation);
1926                 weston_matrix_init(&rotate->rotation);
1927         }
1928
1929         wl_pointer_set_focus(seat->pointer, NULL,
1930                              wl_fixed_from_int(0),
1931                              wl_fixed_from_int(0));
1932 }
1933
1934 static void
1935 activate(struct desktop_shell *shell, struct weston_surface *es,
1936          struct weston_seat *seat)
1937 {
1938         struct weston_surface *surf, *prev;
1939
1940         weston_surface_activate(es, seat);
1941
1942         switch (get_shell_surface_type(es)) {
1943         case SHELL_SURFACE_BACKGROUND:
1944         case SHELL_SURFACE_PANEL:
1945         case SHELL_SURFACE_LOCK:
1946                 break;
1947
1948         case SHELL_SURFACE_SCREENSAVER:
1949                 /* always below lock surface */
1950                 if (shell->lock_surface)
1951                         weston_surface_restack(es,
1952                                                &shell->lock_surface->surface->layer_link);
1953                 break;
1954         case SHELL_SURFACE_FULLSCREEN:
1955                 /* should on top of panels */
1956                 shell_stack_fullscreen(get_shell_surface(es));
1957                 shell_configure_fullscreen(get_shell_surface(es));
1958                 break;
1959         default:
1960                 /* move the fullscreen surfaces down into the toplevel layer */
1961                 if (!wl_list_empty(&shell->fullscreen_layer.surface_list)) {
1962                         wl_list_for_each_reverse_safe(surf,
1963                                                       prev, 
1964                                                       &shell->fullscreen_layer.surface_list, 
1965                                                       layer_link)
1966                                 weston_surface_restack(surf,
1967                                                        &shell->toplevel_layer.surface_list); 
1968                 }
1969
1970                 weston_surface_restack(es,
1971                                        &shell->toplevel_layer.surface_list);
1972                 break;
1973         }
1974 }
1975
1976 /* no-op func for checking black surface */
1977 static void
1978 black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy)
1979 {
1980 }
1981
1982 static bool 
1983 is_black_surface (struct weston_surface *es, struct weston_surface **fs_surface)
1984 {
1985         if (es->configure == black_surface_configure) {
1986                 if (fs_surface)
1987                         *fs_surface = (struct weston_surface *)es->private;
1988                 return true;
1989         }
1990         return false;
1991 }
1992
1993 static void
1994 click_to_activate_binding(struct wl_seat *seat, uint32_t time, uint32_t button,
1995                           void *data)
1996 {
1997         struct weston_seat *ws = (struct weston_seat *) seat;
1998         struct desktop_shell *shell = data;
1999         struct weston_surface *focus;
2000         struct weston_surface *upper;
2001
2002         focus = (struct weston_surface *) seat->pointer->focus;
2003         if (!focus)
2004                 return;
2005
2006         if (is_black_surface(focus, &upper))
2007                 focus = upper;
2008
2009         if (seat->pointer->grab == &seat->pointer->default_grab)
2010                 activate(shell, focus, ws);
2011 }
2012
2013 static void
2014 lock(struct wl_listener *listener, void *data)
2015 {
2016         struct desktop_shell *shell =
2017                 container_of(listener, struct desktop_shell, lock_listener);
2018         struct weston_seat *seat;
2019         struct shell_surface *shsurf;
2020         struct weston_output *output;
2021
2022         if (shell->locked) {
2023                 wl_list_for_each(output, &shell->compositor->output_list, link)
2024                         /* TODO: find a way to jump to other DPMS levels */
2025                         if (output->set_dpms)
2026                                 output->set_dpms(output, WESTON_DPMS_STANDBY);
2027                 return;
2028         }
2029
2030         shell->locked = true;
2031
2032         /* Hide all surfaces by removing the fullscreen, panel and
2033          * toplevel layers.  This way nothing else can show or receive
2034          * input events while we are locked. */
2035
2036         wl_list_remove(&shell->panel_layer.link);
2037         wl_list_remove(&shell->toplevel_layer.link);
2038         wl_list_remove(&shell->fullscreen_layer.link);
2039         wl_list_insert(&shell->compositor->cursor_layer.link,
2040                        &shell->lock_layer.link);
2041
2042         launch_screensaver(shell);
2043
2044         wl_list_for_each(shsurf, &shell->screensaver.surfaces, link)
2045                 show_screensaver(shell, shsurf);
2046
2047         if (!wl_list_empty(&shell->screensaver.surfaces)) {
2048                 shell->compositor->idle_time = shell->screensaver.duration;
2049                 weston_compositor_wake(shell->compositor);
2050                 shell->compositor->state = WESTON_COMPOSITOR_IDLE;
2051         }
2052
2053         /* reset pointer foci */
2054         weston_compositor_schedule_repaint(shell->compositor);
2055
2056         /* reset keyboard foci */
2057         wl_list_for_each(seat, &shell->compositor->seat_list, link) {
2058                 wl_keyboard_set_focus(seat->seat.keyboard, NULL);
2059         }
2060
2061         /* TODO: disable bindings that should not work while locked. */
2062
2063         /* All this must be undone in resume_desktop(). */
2064 }
2065
2066 static void
2067 unlock(struct wl_listener *listener, void *data)
2068 {
2069         struct desktop_shell *shell =
2070                 container_of(listener, struct desktop_shell, unlock_listener);
2071
2072         if (!shell->locked || shell->lock_surface) {
2073                 weston_compositor_wake(shell->compositor);
2074                 return;
2075         }
2076
2077         /* If desktop-shell client has gone away, unlock immediately. */
2078         if (!shell->child.desktop_shell) {
2079                 resume_desktop(shell);
2080                 return;
2081         }
2082
2083         if (shell->prepare_event_sent)
2084                 return;
2085
2086         desktop_shell_send_prepare_lock_surface(shell->child.desktop_shell);
2087         shell->prepare_event_sent = true;
2088 }
2089
2090 static void
2091 center_on_output(struct weston_surface *surface, struct weston_output *output)
2092 {
2093         struct weston_mode *mode = output->current;
2094         GLfloat x = (mode->width - surface->geometry.width) / 2;
2095         GLfloat y = (mode->height - surface->geometry.height) / 2;
2096
2097         weston_surface_set_position(surface, output->x + x, output->y + y);
2098 }
2099
2100 static void
2101 map(struct desktop_shell *shell, struct weston_surface *surface,
2102     int32_t width, int32_t height, int32_t sx, int32_t sy)
2103 {
2104         struct weston_compositor *compositor = shell->compositor;
2105         struct shell_surface *shsurf;
2106         enum shell_surface_type surface_type = SHELL_SURFACE_NONE;
2107         struct weston_surface *parent;
2108         struct weston_seat *seat;
2109         int panel_height = 0;
2110
2111         shsurf = get_shell_surface(surface);
2112         if (shsurf)
2113                 surface_type = shsurf->type;
2114
2115         surface->geometry.width = width;
2116         surface->geometry.height = height;
2117         surface->geometry.dirty = 1;
2118
2119         /* initial positioning, see also configure() */
2120         switch (surface_type) {
2121         case SHELL_SURFACE_TOPLEVEL:
2122                 weston_surface_set_position(surface, 10 + random() % 400,
2123                                             10 + random() % 400);
2124                 break;
2125         case SHELL_SURFACE_SCREENSAVER:
2126                 center_on_output(surface, shsurf->fullscreen_output);
2127                 break;
2128         case SHELL_SURFACE_FULLSCREEN:
2129                 shell_map_fullscreen(shsurf);
2130                 break;
2131         case SHELL_SURFACE_MAXIMIZED:
2132                 /* use surface configure to set the geometry */
2133                 panel_height = get_output_panel_height(shell,surface->output);
2134                 weston_surface_set_position(surface, surface->output->x,
2135                                             surface->output->y + panel_height);
2136                 break;
2137         case SHELL_SURFACE_LOCK:
2138                 center_on_output(surface, get_default_output(compositor));
2139                 break;
2140         case SHELL_SURFACE_POPUP:
2141                 shell_map_popup(shsurf);
2142         case SHELL_SURFACE_NONE:
2143                 weston_surface_set_position(surface,
2144                                             surface->geometry.x + sx,
2145                                             surface->geometry.y + sy);
2146                 break;
2147         default:
2148                 ;
2149         }
2150
2151         /* surface stacking order, see also activate() */
2152         switch (surface_type) {
2153         case SHELL_SURFACE_BACKGROUND:
2154                 /* background always visible, at the bottom */
2155                 wl_list_insert(&shell->background_layer.surface_list,
2156                                &surface->layer_link);
2157                 break;
2158         case SHELL_SURFACE_PANEL:
2159                 /* panel always on top, hidden while locked */
2160                 wl_list_insert(&shell->panel_layer.surface_list,
2161                                &surface->layer_link);
2162                 break;
2163         case SHELL_SURFACE_LOCK:
2164                 /* lock surface always visible, on top */
2165                 wl_list_insert(&shell->lock_layer.surface_list,
2166                                &surface->layer_link);
2167                 weston_compositor_wake(compositor);
2168                 break;
2169         case SHELL_SURFACE_SCREENSAVER:
2170                 /* If locked, show it. */
2171                 if (shell->locked) {
2172                         show_screensaver(shell, shsurf);
2173                         compositor->idle_time = shell->screensaver.duration;
2174                         weston_compositor_wake(compositor);
2175                         if (!shell->lock_surface)
2176                                 compositor->state = WESTON_COMPOSITOR_IDLE;
2177                 }
2178                 break;
2179         case SHELL_SURFACE_POPUP:
2180         case SHELL_SURFACE_TRANSIENT:
2181                 parent = shsurf->parent->surface;
2182                 wl_list_insert(parent->layer_link.prev, &surface->layer_link);
2183                 break;
2184         case SHELL_SURFACE_FULLSCREEN:
2185         case SHELL_SURFACE_NONE:
2186                 break;
2187         default:
2188                 wl_list_insert(&shell->toplevel_layer.surface_list,
2189                                &surface->layer_link); 
2190                 break;
2191         }
2192
2193         if (surface_type != SHELL_SURFACE_NONE) {
2194                 weston_surface_assign_output(surface);
2195                 if (surface_type == SHELL_SURFACE_MAXIMIZED)
2196                         surface->output = shsurf->output;
2197         }
2198
2199         switch (surface_type) {
2200         case SHELL_SURFACE_TRANSIENT:
2201                 if (shsurf->transient.flags ==
2202                                 WL_SHELL_SURFACE_TRANSIENT_INACTIVE)
2203                         break;
2204         case SHELL_SURFACE_TOPLEVEL:
2205         case SHELL_SURFACE_FULLSCREEN:
2206         case SHELL_SURFACE_MAXIMIZED:
2207                 if (!shell->locked) {
2208                         wl_list_for_each(seat, &compositor->seat_list, link)
2209                                 activate(shell, surface, seat);
2210                 }
2211                 break;
2212         default:
2213                 break;
2214         }
2215
2216         if (surface_type == SHELL_SURFACE_TOPLEVEL)
2217         {
2218                 switch (shell->win_animation_type) {
2219                 case ANIMATION_FADE:
2220                         weston_fade_run(surface, NULL, NULL);
2221                         break;
2222                 case ANIMATION_ZOOM:
2223                         weston_zoom_run(surface, 0.8, 1.0, NULL, NULL);
2224                         break;
2225                 default:
2226                         break;
2227                 }
2228         }
2229 }
2230
2231 static void
2232 configure(struct desktop_shell *shell, struct weston_surface *surface,
2233           GLfloat x, GLfloat y, int32_t width, int32_t height)
2234 {
2235         enum shell_surface_type surface_type = SHELL_SURFACE_NONE;
2236         struct shell_surface *shsurf;
2237
2238         shsurf = get_shell_surface(surface);
2239         if (shsurf)
2240                 surface_type = shsurf->type;
2241
2242         surface->geometry.x = x;
2243         surface->geometry.y = y;
2244         surface->geometry.width = width;
2245         surface->geometry.height = height;
2246         surface->geometry.dirty = 1;
2247
2248         switch (surface_type) {
2249         case SHELL_SURFACE_SCREENSAVER:
2250                 center_on_output(surface, shsurf->fullscreen_output);
2251                 break;
2252         case SHELL_SURFACE_FULLSCREEN:
2253                 shell_stack_fullscreen(shsurf);
2254                 shell_configure_fullscreen(shsurf);
2255                 break;
2256         case SHELL_SURFACE_MAXIMIZED:
2257                 /* setting x, y and using configure to change that geometry */
2258                 surface->geometry.x = surface->output->x;
2259                 surface->geometry.y = surface->output->y +
2260                         get_output_panel_height(shell,surface->output);
2261                 break;
2262         case SHELL_SURFACE_TOPLEVEL:
2263                 break;
2264         default:
2265                 break;
2266         }
2267
2268         /* XXX: would a fullscreen surface need the same handling? */
2269         if (surface->output) {
2270                 weston_surface_assign_output(surface);
2271
2272                 if (surface_type == SHELL_SURFACE_SCREENSAVER)
2273                         surface->output = shsurf->output;
2274                 else if (surface_type == SHELL_SURFACE_MAXIMIZED)
2275                         surface->output = shsurf->output;
2276         }
2277 }
2278
2279 static void
2280 shell_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy)
2281 {
2282         struct shell_surface *shsurf = get_shell_surface(es);
2283         struct desktop_shell *shell = shsurf->shell;
2284         int type_changed = 0;
2285
2286         if (shsurf->next_type != SHELL_SURFACE_NONE &&
2287             shsurf->type != shsurf->next_type) {
2288                 set_surface_type(shsurf);
2289                 type_changed = 1;
2290         }
2291
2292         if (!weston_surface_is_mapped(es)) {
2293                 map(shell, es, es->buffer->width, es->buffer->height, sx, sy);
2294         } else if (type_changed || sx != 0 || sy != 0 ||
2295                    es->geometry.width != es->buffer->width ||
2296                    es->geometry.height != es->buffer->height) {
2297                 GLfloat from_x, from_y;
2298                 GLfloat to_x, to_y;
2299
2300                 weston_surface_to_global_float(es, 0, 0, &from_x, &from_y);
2301                 weston_surface_to_global_float(es, sx, sy, &to_x, &to_y);
2302                 configure(shell, es,
2303                           es->geometry.x + to_x - from_x,
2304                           es->geometry.y + to_y - from_y,
2305                           es->buffer->width, es->buffer->height);
2306         }
2307 }
2308
2309 static int launch_desktop_shell_process(struct desktop_shell *shell);
2310
2311 static void
2312 desktop_shell_sigchld(struct weston_process *process, int status)
2313 {
2314         uint32_t time;
2315         struct desktop_shell *shell =
2316                 container_of(process, struct desktop_shell, child.process);
2317
2318         shell->child.process.pid = 0;
2319         shell->child.client = NULL; /* already destroyed by wayland */
2320
2321         /* if desktop-shell dies more than 5 times in 30 seconds, give up */
2322         time = weston_compositor_get_time();
2323         if (time - shell->child.deathstamp > 30000) {
2324                 shell->child.deathstamp = time;
2325                 shell->child.deathcount = 0;
2326         }
2327
2328         shell->child.deathcount++;
2329         if (shell->child.deathcount > 5) {
2330                 fprintf(stderr, "weston-desktop-shell died, giving up.\n");
2331                 return;
2332         }
2333
2334         fprintf(stderr, "weston-desktop-shell died, respawning...\n");
2335         launch_desktop_shell_process(shell);
2336 }
2337
2338 static int
2339 launch_desktop_shell_process(struct desktop_shell *shell)
2340 {
2341         const char *shell_exe = LIBEXECDIR "/weston-desktop-shell";
2342
2343         shell->child.client = weston_client_launch(shell->compositor,
2344                                                  &shell->child.process,
2345                                                  shell_exe,
2346                                                  desktop_shell_sigchld);
2347
2348         if (!shell->child.client)
2349                 return -1;
2350         return 0;
2351 }
2352
2353 static void
2354 bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
2355 {
2356         struct desktop_shell *shell = data;
2357
2358         wl_client_add_object(client, &wl_shell_interface,
2359                              &shell_implementation, id, shell);
2360 }
2361
2362 static void
2363 unbind_desktop_shell(struct wl_resource *resource)
2364 {
2365         struct desktop_shell *shell = resource->data;
2366
2367         if (shell->locked)
2368                 resume_desktop(shell);
2369
2370         shell->child.desktop_shell = NULL;
2371         shell->prepare_event_sent = false;
2372         free(resource);
2373 }
2374
2375 static void
2376 bind_desktop_shell(struct wl_client *client,
2377                    void *data, uint32_t version, uint32_t id)
2378 {
2379         struct desktop_shell *shell = data;
2380         struct wl_resource *resource;
2381
2382         resource = wl_client_add_object(client, &desktop_shell_interface,
2383                                         &desktop_shell_implementation,
2384                                         id, shell);
2385
2386         if (client == shell->child.client) {
2387                 resource->destroy = unbind_desktop_shell;
2388                 shell->child.desktop_shell = resource;
2389                 return;
2390         }
2391
2392         wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
2393                                "permission to bind desktop_shell denied");
2394         wl_resource_destroy(resource);
2395 }
2396
2397 static void
2398 screensaver_set_surface(struct wl_client *client,
2399                         struct wl_resource *resource,
2400                         struct wl_resource *shell_surface_resource,
2401                         struct wl_resource *output_resource)
2402 {
2403         struct desktop_shell *shell = resource->data;
2404         struct shell_surface *surface = shell_surface_resource->data;
2405         struct weston_output *output = output_resource->data;
2406
2407         surface->next_type = SHELL_SURFACE_SCREENSAVER;
2408
2409         surface->fullscreen_output = output;
2410         surface->output = output;
2411         wl_list_insert(shell->screensaver.surfaces.prev, &surface->link);
2412 }
2413
2414 static const struct screensaver_interface screensaver_implementation = {
2415         screensaver_set_surface
2416 };
2417
2418 static void
2419 unbind_screensaver(struct wl_resource *resource)
2420 {
2421         struct desktop_shell *shell = resource->data;
2422
2423         shell->screensaver.binding = NULL;
2424         free(resource);
2425 }
2426
2427 static void
2428 bind_screensaver(struct wl_client *client,
2429                  void *data, uint32_t version, uint32_t id)
2430 {
2431         struct desktop_shell *shell = data;
2432         struct wl_resource *resource;
2433
2434         resource = wl_client_add_object(client, &screensaver_interface,
2435                                         &screensaver_implementation,
2436                                         id, shell);
2437
2438         if (shell->screensaver.binding == NULL) {
2439                 resource->destroy = unbind_screensaver;
2440                 shell->screensaver.binding = resource;
2441                 return;
2442         }
2443
2444         wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
2445                                "interface object already bound");
2446         wl_resource_destroy(resource);
2447 }
2448
2449 struct switcher {
2450         struct desktop_shell *shell;
2451         struct weston_surface *current;
2452         struct wl_listener listener;
2453         struct wl_keyboard_grab grab;
2454 };
2455
2456 static void
2457 switcher_next(struct switcher *switcher)
2458 {
2459         struct weston_compositor *compositor = switcher->shell->compositor;
2460         struct weston_surface *surface;
2461         struct weston_surface *first = NULL, *prev = NULL, *next = NULL;
2462         struct shell_surface *shsurf;
2463
2464         wl_list_for_each(surface, &compositor->surface_list, link) {
2465                 switch (get_shell_surface_type(surface)) {
2466                 case SHELL_SURFACE_TOPLEVEL:
2467                 case SHELL_SURFACE_FULLSCREEN:
2468                 case SHELL_SURFACE_MAXIMIZED:
2469                         if (first == NULL)
2470                                 first = surface;
2471                         if (prev == switcher->current)
2472                                 next = surface;
2473                         prev = surface;
2474                         surface->alpha = 0.25;
2475                         surface->geometry.dirty = 1;
2476                         weston_surface_damage(surface);
2477                         break;
2478                 default:
2479                         break;
2480                 }
2481
2482                 if (is_black_surface(surface, NULL)) {
2483                         surface->alpha = 0.25;
2484                         surface->geometry.dirty = 1;
2485                         weston_surface_damage(surface);
2486                 }
2487         }
2488
2489         if (next == NULL)
2490                 next = first;
2491
2492         if (next == NULL)
2493                 return;
2494
2495         wl_list_remove(&switcher->listener.link);
2496         wl_signal_add(&next->surface.resource.destroy_signal,
2497                       &switcher->listener);
2498
2499         switcher->current = next;
2500         next->alpha = 1.0;
2501
2502         shsurf = get_shell_surface(switcher->current);
2503         if (shsurf && shsurf->type ==SHELL_SURFACE_FULLSCREEN)
2504                 shsurf->fullscreen.black_surface->alpha = 1.0;
2505 }
2506
2507 static void
2508 switcher_handle_surface_destroy(struct wl_listener *listener, void *data)
2509 {
2510         struct switcher *switcher =
2511                 container_of(listener, struct switcher, listener);
2512
2513         switcher_next(switcher);
2514 }
2515
2516 static void
2517 switcher_destroy(struct switcher *switcher)
2518 {
2519         struct weston_compositor *compositor = switcher->shell->compositor;
2520         struct weston_surface *surface;
2521         struct wl_keyboard *keyboard = switcher->grab.keyboard;
2522
2523         wl_list_for_each(surface, &compositor->surface_list, link) {
2524                 surface->alpha = 1.0;
2525                 weston_surface_damage(surface);
2526         }
2527
2528         if (switcher->current)
2529                 activate(switcher->shell, switcher->current,
2530                          (struct weston_seat *) keyboard->seat);
2531         wl_list_remove(&switcher->listener.link);
2532         wl_keyboard_end_grab(keyboard);
2533         free(switcher);
2534 }
2535
2536 static void
2537 switcher_key(struct wl_keyboard_grab *grab,
2538              uint32_t time, uint32_t key, uint32_t state_w)
2539 {
2540         struct switcher *switcher = container_of(grab, struct switcher, grab);
2541         enum wl_keyboard_key_state state = state_w;
2542
2543         if (key == KEY_TAB && state == WL_KEYBOARD_KEY_STATE_PRESSED)
2544                 switcher_next(switcher);
2545 }
2546
2547 static void
2548 switcher_modifier(struct wl_keyboard_grab *grab, uint32_t serial,
2549                   uint32_t mods_depressed, uint32_t mods_latched,
2550                   uint32_t mods_locked, uint32_t group)
2551 {
2552         struct switcher *switcher = container_of(grab, struct switcher, grab);
2553         struct weston_seat *seat = (struct weston_seat *) grab->keyboard->seat;
2554
2555         if ((seat->modifier_state & switcher->shell->binding_modifier) == 0)
2556                 switcher_destroy(switcher);
2557 }
2558
2559 static const struct wl_keyboard_grab_interface switcher_grab = {
2560         switcher_key,
2561         switcher_modifier,
2562 };
2563
2564 static void
2565 switcher_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
2566                  void *data)
2567 {
2568         struct desktop_shell *shell = data;
2569         struct switcher *switcher;
2570
2571         switcher = malloc(sizeof *switcher);
2572         switcher->shell = shell;
2573         switcher->current = NULL;
2574         switcher->listener.notify = switcher_handle_surface_destroy;
2575         wl_list_init(&switcher->listener.link);
2576
2577         switcher->grab.interface = &switcher_grab;
2578         wl_keyboard_start_grab(seat->keyboard, &switcher->grab);
2579         wl_keyboard_set_focus(seat->keyboard, NULL);
2580         switcher_next(switcher);
2581 }
2582
2583 static void
2584 backlight_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
2585                   void *data)
2586 {
2587         struct weston_compositor *compositor = data;
2588         struct weston_output *output;
2589         long backlight_new = 0;
2590
2591         /* TODO: we're limiting to simple use cases, where we assume just
2592          * control on the primary display. We'd have to extend later if we
2593          * ever get support for setting backlights on random desktop LCD
2594          * panels though */
2595         output = get_default_output(compositor);
2596         if (!output)
2597                 return;
2598
2599         if (!output->set_backlight)
2600                 return;
2601
2602         if (key == KEY_F9 || key == KEY_BRIGHTNESSDOWN)
2603                 backlight_new = output->backlight_current - 25;
2604         else if (key == KEY_F10 || key == KEY_BRIGHTNESSUP)
2605                 backlight_new = output->backlight_current + 25;
2606
2607         if (backlight_new < 5)
2608                 backlight_new = 5;
2609         if (backlight_new > 255)
2610                 backlight_new = 255;
2611
2612         output->backlight_current = backlight_new;
2613         output->set_backlight(output, output->backlight_current);
2614 }
2615
2616 static void
2617 debug_repaint_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
2618                       void *data)
2619 {
2620         struct desktop_shell *shell = data;
2621         struct weston_compositor *compositor = shell->compositor;
2622         struct weston_surface *surface;
2623
2624         if (shell->debug_repaint_surface) {
2625                 weston_surface_destroy(shell->debug_repaint_surface);
2626                 shell->debug_repaint_surface = NULL;
2627         } else {
2628                 surface = weston_surface_create(compositor);
2629                 weston_surface_set_color(surface, 1.0, 0.0, 0.0, 0.2);
2630                 weston_surface_configure(surface, 0, 0, 8192, 8192);
2631                 wl_list_insert(&compositor->fade_layer.surface_list,
2632                                &surface->layer_link);
2633                 weston_surface_assign_output(surface);
2634                 pixman_region32_init(&surface->input);
2635
2636                 /* Here's the dirty little trick that makes the
2637                  * repaint debugging work: we force an
2638                  * update_transform first to update dependent state
2639                  * and clear the geometry.dirty bit.  Then we clear
2640                  * the surface damage so it only gets repainted
2641                  * piecewise as we repaint other things.  */
2642
2643                 weston_surface_update_transform(surface);
2644                 pixman_region32_fini(&surface->damage);
2645                 pixman_region32_init(&surface->damage);
2646                 shell->debug_repaint_surface = surface;
2647         }
2648 }
2649
2650 static void
2651 force_kill_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
2652                    void *data)
2653 {
2654         struct wl_client *client;
2655         pid_t pid;
2656         uid_t uid;
2657         gid_t gid;
2658
2659         client = seat->keyboard->focus->resource.client;
2660         wl_client_get_credentials(client, &pid, &uid, &gid);
2661
2662         kill(pid, SIGKILL);
2663 }
2664
2665 static void
2666 shell_destroy(struct wl_listener *listener, void *data)
2667 {
2668         struct desktop_shell *shell =
2669                 container_of(listener, struct desktop_shell, destroy_listener);
2670
2671         if (shell->child.client)
2672                 wl_client_destroy(shell->child.client);
2673
2674         wl_list_remove(&shell->lock_listener.link);
2675         wl_list_remove(&shell->unlock_listener.link);
2676
2677         free(shell->screensaver.path);
2678         free(shell);
2679 }
2680
2681 static void
2682 shell_add_bindings(struct weston_compositor *ec, struct desktop_shell *shell)
2683 {
2684         uint32_t mod;
2685
2686         /* fixed bindings */
2687         weston_compositor_add_key_binding(ec, KEY_BACKSPACE,
2688                                           MODIFIER_CTRL | MODIFIER_ALT,
2689                                           terminate_binding, ec);
2690         weston_compositor_add_button_binding(ec, BTN_LEFT, 0,
2691                                              click_to_activate_binding,
2692                                              shell);
2693         weston_compositor_add_axis_binding(ec, WL_POINTER_AXIS_VERTICAL_SCROLL,
2694                                            MODIFIER_SUPER | MODIFIER_ALT,
2695                                            surface_opacity_binding, NULL);
2696         weston_compositor_add_axis_binding(ec, WL_POINTER_AXIS_VERTICAL_SCROLL,
2697                                            MODIFIER_SUPER, zoom_axis_binding,
2698                                            NULL);
2699
2700         /* configurable bindings */
2701         mod = shell->binding_modifier;
2702         weston_compositor_add_key_binding(ec, KEY_PAGEUP, mod,
2703                                           zoom_key_binding, NULL);
2704         weston_compositor_add_key_binding(ec, KEY_PAGEDOWN, mod,
2705                                           zoom_key_binding, NULL);
2706         weston_compositor_add_button_binding(ec, BTN_LEFT, mod, move_binding,
2707                                              shell);
2708         weston_compositor_add_button_binding(ec, BTN_MIDDLE, mod,
2709                                              resize_binding, shell);
2710         weston_compositor_add_button_binding(ec, BTN_RIGHT, mod,
2711                                              rotate_binding, NULL);
2712         weston_compositor_add_key_binding(ec, KEY_TAB, mod, switcher_binding,
2713                                           shell);
2714         weston_compositor_add_key_binding(ec, KEY_F9, mod, backlight_binding,
2715                                           ec);
2716         weston_compositor_add_key_binding(ec, KEY_BRIGHTNESSDOWN, 0,
2717                                           backlight_binding, ec);
2718         weston_compositor_add_key_binding(ec, KEY_F10, mod, backlight_binding,
2719                                           ec);
2720         weston_compositor_add_key_binding(ec, KEY_BRIGHTNESSUP, 0,
2721                                           backlight_binding, ec);
2722         weston_compositor_add_key_binding(ec, KEY_SPACE, mod,
2723                                           debug_repaint_binding, shell);
2724         weston_compositor_add_key_binding(ec, KEY_K, mod,
2725                                           force_kill_binding, shell);
2726 }
2727
2728 int
2729 shell_init(struct weston_compositor *ec);
2730
2731 WL_EXPORT int
2732 shell_init(struct weston_compositor *ec)
2733 {
2734         struct desktop_shell *shell;
2735
2736         shell = malloc(sizeof *shell);
2737         if (shell == NULL)
2738                 return -1;
2739
2740         memset(shell, 0, sizeof *shell);
2741         shell->compositor = ec;
2742
2743         shell->destroy_listener.notify = shell_destroy;
2744         wl_signal_add(&ec->destroy_signal, &shell->destroy_listener);
2745         shell->lock_listener.notify = lock;
2746         wl_signal_add(&ec->lock_signal, &shell->lock_listener);
2747         shell->unlock_listener.notify = unlock;
2748         wl_signal_add(&ec->unlock_signal, &shell->unlock_listener);
2749         ec->ping_handler = ping_handler;
2750         ec->shell_interface.create_shell_surface = create_shell_surface;
2751         ec->shell_interface.set_toplevel = set_toplevel;
2752         ec->shell_interface.set_transient = set_transient;
2753         ec->shell_interface.move = surface_move;
2754         ec->shell_interface.resize = surface_resize;
2755
2756         wl_list_init(&shell->backgrounds);
2757         wl_list_init(&shell->panels);
2758         wl_list_init(&shell->screensaver.surfaces);
2759
2760         weston_layer_init(&shell->fullscreen_layer, &ec->cursor_layer.link);
2761         weston_layer_init(&shell->panel_layer, &shell->fullscreen_layer.link);
2762         weston_layer_init(&shell->toplevel_layer, &shell->panel_layer.link);
2763         weston_layer_init(&shell->background_layer,
2764                           &shell->toplevel_layer.link);
2765         wl_list_init(&shell->lock_layer.surface_list);
2766
2767         shell_configuration(shell);
2768
2769         if (wl_display_add_global(ec->wl_display, &wl_shell_interface,
2770                                   shell, bind_shell) == NULL)
2771                 return -1;
2772
2773         if (wl_display_add_global(ec->wl_display,
2774                                   &desktop_shell_interface,
2775                                   shell, bind_desktop_shell) == NULL)
2776                 return -1;
2777
2778         if (wl_display_add_global(ec->wl_display, &screensaver_interface,
2779                                   shell, bind_screensaver) == NULL)
2780                 return -1;
2781
2782         shell->child.deathstamp = weston_compositor_get_time();
2783         if (launch_desktop_shell_process(shell) != 0)
2784                 return -1;
2785
2786         shell->pointer_focus_listener.notify = handle_pointer_focus;
2787         if (ec->seat->seat.pointer)
2788                 wl_signal_add(&ec->seat->seat.pointer->focus_signal,
2789                               &shell->pointer_focus_listener);
2790
2791         shell_add_bindings(ec, shell);
2792
2793         return 0;
2794 }