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