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