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