Track server changes.
[profile/ivi/weston.git] / src / shell.c
1 /*
2  * Copyright © 2010 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 struct shell_surface;
40
41 struct wl_shell {
42         struct weston_compositor *compositor;
43         struct weston_shell shell;
44
45         struct {
46                 struct weston_process process;
47                 struct wl_client *client;
48                 struct wl_resource *desktop_shell;
49
50                 unsigned deathcount;
51                 uint32_t deathstamp;
52         } child;
53
54         bool locked;
55         bool prepare_event_sent;
56
57         struct shell_surface *lock_surface;
58         struct wl_listener lock_surface_listener;
59         struct wl_list hidden_surface_list;
60
61         struct wl_list backgrounds;
62         struct wl_list panels;
63
64         struct {
65                 char *path;
66                 int duration;
67                 struct wl_resource *binding;
68                 struct wl_list surfaces;
69                 struct weston_process process;
70         } screensaver;
71 };
72
73 enum shell_surface_type {
74         SHELL_SURFACE_NONE,
75
76         SHELL_SURFACE_PANEL,
77         SHELL_SURFACE_BACKGROUND,
78         SHELL_SURFACE_LOCK,
79         SHELL_SURFACE_SCREENSAVER,
80
81         SHELL_SURFACE_TOPLEVEL,
82         SHELL_SURFACE_TRANSIENT,
83         SHELL_SURFACE_FULLSCREEN,
84         SHELL_SURFACE_MAXIMIZED,
85         SHELL_SURFACE_POPUP
86 };
87
88 struct shell_surface {
89         struct wl_resource resource;
90
91         struct weston_surface *surface;
92         struct wl_listener surface_destroy_listener;
93         struct shell_surface *parent;
94
95         enum shell_surface_type type;
96         int32_t saved_x, saved_y;
97
98         struct {
99                 struct weston_transform transform;
100                 struct weston_matrix rotation;
101         } rotation;
102
103         struct {
104                 struct wl_pointer_grab grab;
105                 uint32_t time;
106                 int32_t x, y;
107                 struct weston_transform parent_transform;
108                 int32_t initial_up;
109         } popup;
110
111         struct weston_output *fullscreen_output;
112         struct weston_output *output;
113         struct wl_list link;
114 };
115
116 struct weston_move_grab {
117         struct wl_pointer_grab grab;
118         struct weston_surface *surface;
119         int32_t dx, dy;
120 };
121
122 struct rotate_grab {
123         struct wl_pointer_grab grab;
124         struct shell_surface *surface;
125         struct weston_matrix rotation;
126         struct {
127                 int32_t x;
128                 int32_t y;
129         } center;
130 };
131
132 static void
133 shell_configuration(struct wl_shell *shell)
134 {
135         char *config_file;
136         char *path = NULL;
137         int duration = 60;
138
139         struct config_key saver_keys[] = {
140                 { "path",       CONFIG_KEY_STRING,  &path },
141                 { "duration",   CONFIG_KEY_INTEGER, &duration },
142         };
143
144         struct config_section cs[] = {
145                 { "screensaver", saver_keys, ARRAY_LENGTH(saver_keys), NULL },
146         };
147
148         config_file = config_file_path("weston-desktop-shell.ini");
149         parse_config_file(config_file, cs, ARRAY_LENGTH(cs), shell);
150         free(config_file);
151
152         shell->screensaver.path = path;
153         shell->screensaver.duration = duration;
154 }
155
156 static void
157 noop_grab_focus(struct wl_pointer_grab *grab, uint32_t time,
158                 struct wl_surface *surface, int32_t x, int32_t y)
159 {
160         grab->focus = NULL;
161 }
162
163 static void
164 move_grab_motion(struct wl_pointer_grab *grab,
165                  uint32_t time, int32_t x, int32_t y)
166 {
167         struct weston_move_grab *move = (struct weston_move_grab *) grab;
168         struct wl_input_device *device = grab->input_device;
169         struct weston_surface *es = move->surface;
170
171         weston_surface_configure(es,
172                                  device->x + move->dx,
173                                  device->y + move->dy,
174                                  es->geometry.width, es->geometry.height);
175 }
176
177 static void
178 move_grab_button(struct wl_pointer_grab *grab,
179                  uint32_t time, int32_t button, int32_t state)
180 {
181         struct wl_input_device *device = grab->input_device;
182
183         if (device->button_count == 0 && state == 0) {
184                 wl_input_device_end_pointer_grab(device, time);
185                 free(grab);
186         }
187 }
188
189 static const struct wl_pointer_grab_interface move_grab_interface = {
190         noop_grab_focus,
191         move_grab_motion,
192         move_grab_button,
193 };
194
195 static int
196 weston_surface_move(struct weston_surface *es,
197                     struct weston_input_device *wd, uint32_t time)
198 {
199         struct weston_move_grab *move;
200
201         move = malloc(sizeof *move);
202         if (!move)
203                 return -1;
204
205         move->grab.interface = &move_grab_interface;
206         move->dx = es->geometry.x - wd->input_device.grab_x;
207         move->dy = es->geometry.y - wd->input_device.grab_y;
208         move->surface = es;
209
210         wl_input_device_start_pointer_grab(&wd->input_device, &move->grab, time);
211
212         wl_input_device_set_pointer_focus(&wd->input_device, NULL, time, 0, 0);
213
214         return 0;
215 }
216
217 static void
218 shell_surface_move(struct wl_client *client, struct wl_resource *resource,
219                    struct wl_resource *input_resource, uint32_t time)
220 {
221         struct weston_input_device *wd = input_resource->data;
222         struct shell_surface *shsurf = resource->data;
223
224         if (wd->input_device.button_count == 0 ||
225             wd->input_device.grab_time != time ||
226             wd->input_device.pointer_focus != &shsurf->surface->surface)
227                 return;
228
229         if (weston_surface_move(shsurf->surface, wd, time) < 0)
230                 wl_resource_post_no_memory(resource);
231 }
232
233 struct weston_resize_grab {
234         struct wl_pointer_grab grab;
235         uint32_t edges;
236         int32_t width, height;
237         struct shell_surface *shsurf;
238 };
239
240 static void
241 resize_grab_motion(struct wl_pointer_grab *grab,
242                    uint32_t time, int32_t x, int32_t y)
243 {
244         struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
245         struct wl_input_device *device = grab->input_device;
246         int32_t width, height;
247         int32_t from_x, from_y;
248         int32_t to_x, to_y;
249
250         weston_surface_from_global(resize->shsurf->surface,
251                                    device->grab_x, device->grab_y,
252                                    &from_x, &from_y);
253         weston_surface_from_global(resize->shsurf->surface,
254                                    device->x, device->y, &to_x, &to_y);
255
256         if (resize->edges & WL_SHELL_SURFACE_RESIZE_LEFT) {
257                 width = resize->width + from_x - to_x;
258         } else if (resize->edges & WL_SHELL_SURFACE_RESIZE_RIGHT) {
259                 width = resize->width + to_x - from_x;
260         } else {
261                 width = resize->width;
262         }
263
264         if (resize->edges & WL_SHELL_SURFACE_RESIZE_TOP) {
265                 height = resize->height + from_y - to_y;
266         } else if (resize->edges & WL_SHELL_SURFACE_RESIZE_BOTTOM) {
267                 height = resize->height + to_y - from_y;
268         } else {
269                 height = resize->height;
270         }
271
272         wl_resource_post_event(&resize->shsurf->resource,
273                                WL_SHELL_SURFACE_CONFIGURE, time, resize->edges,
274                                width, height);
275 }
276
277 static void
278 resize_grab_button(struct wl_pointer_grab *grab,
279                    uint32_t time, int32_t button, int32_t state)
280 {
281         struct wl_input_device *device = grab->input_device;
282
283         if (device->button_count == 0 && state == 0) {
284                 wl_input_device_end_pointer_grab(device, time);
285                 free(grab);
286         }
287 }
288
289 static const struct wl_pointer_grab_interface resize_grab_interface = {
290         noop_grab_focus,
291         resize_grab_motion,
292         resize_grab_button,
293 };
294
295 static int
296 weston_surface_resize(struct shell_surface *shsurf,
297                     struct weston_input_device *wd,
298                     uint32_t time, uint32_t edges)
299 {
300         struct weston_resize_grab *resize;
301
302         /* FIXME: Reject if fullscreen */
303
304         if (edges == 0 || edges > 15 ||
305             (edges & 3) == 3 || (edges & 12) == 12)
306                 return 0;
307
308         resize = malloc(sizeof *resize);
309         if (!resize)
310                 return -1;
311
312         resize->grab.interface = &resize_grab_interface;
313         resize->edges = edges;
314         resize->width = shsurf->surface->geometry.width;
315         resize->height = shsurf->surface->geometry.height;
316         resize->shsurf = shsurf;
317
318         wl_input_device_start_pointer_grab(&wd->input_device, &resize->grab, time);
319
320         wl_input_device_set_pointer_focus(&wd->input_device, NULL, time, 0, 0);
321
322         return 0;
323 }
324
325 static void
326 shell_surface_resize(struct wl_client *client, struct wl_resource *resource,
327                      struct wl_resource *input_resource, uint32_t time,
328                      uint32_t edges)
329 {
330         struct weston_input_device *wd = input_resource->data;
331         struct shell_surface *shsurf = resource->data;
332
333         /* FIXME: Reject if fullscreen */
334
335         if (wd->input_device.button_count == 0 ||
336             wd->input_device.grab_time != time ||
337             wd->input_device.pointer_focus != &shsurf->surface->surface)
338                 return;
339
340         if (weston_surface_resize(shsurf, wd, time, edges) < 0)
341                 wl_resource_post_no_memory(resource);
342 }
343
344 static struct weston_output *
345 get_default_output(struct weston_compositor *compositor)
346 {
347         return container_of(compositor->output_list.next,
348                             struct weston_output, link);
349 }
350
351 static int
352 reset_shell_surface_type(struct shell_surface *surface)
353 {
354         switch (surface->type) {
355         case SHELL_SURFACE_FULLSCREEN:
356                 weston_surface_set_position(surface->surface,
357                                             surface->saved_x,
358                                             surface->saved_y);
359                 surface->fullscreen_output = NULL;
360                 break;
361         case SHELL_SURFACE_MAXIMIZED:
362                 surface->output = get_default_output(surface->surface->compositor);
363                 weston_surface_set_position(surface->surface,
364                                             surface->saved_x,
365                                             surface->saved_y);
366                 break;
367         case SHELL_SURFACE_PANEL:
368         case SHELL_SURFACE_BACKGROUND:
369                 wl_list_remove(&surface->link);
370                 wl_list_init(&surface->link);
371                 break;
372         case SHELL_SURFACE_SCREENSAVER:
373         case SHELL_SURFACE_LOCK:
374                 wl_resource_post_error(&surface->resource,
375                                        WL_DISPLAY_ERROR_INVALID_METHOD,
376                                        "cannot reassign surface type");
377                 return -1;
378         case SHELL_SURFACE_NONE:
379         case SHELL_SURFACE_TOPLEVEL:
380         case SHELL_SURFACE_TRANSIENT:
381         case SHELL_SURFACE_POPUP:
382                 break;
383         }
384
385         surface->type = SHELL_SURFACE_NONE;
386         return 0;
387 }
388
389 static void
390 shell_surface_set_toplevel(struct wl_client *client,
391                            struct wl_resource *resource)
392
393 {
394         struct shell_surface *surface = resource->data;
395
396         if (reset_shell_surface_type(surface))
397                 return;
398
399         surface->type = SHELL_SURFACE_TOPLEVEL;
400 }
401
402 static void
403 shell_surface_set_transient(struct wl_client *client,
404                             struct wl_resource *resource,
405                             struct wl_resource *parent_resource,
406                             int x, int y, uint32_t flags)
407 {
408         struct shell_surface *shsurf = resource->data;
409         struct weston_surface *es = shsurf->surface;
410         struct shell_surface *pshsurf = parent_resource->data;
411         struct weston_surface *pes = pshsurf->surface;
412
413         if (reset_shell_surface_type(shsurf))
414                 return;
415
416         /* assign to parents output  */
417         es->output = pes->output;
418         weston_surface_set_position(es, pes->geometry.x + x,
419                                         pes->geometry.y + y);
420
421         shsurf->type = SHELL_SURFACE_TRANSIENT;
422 }
423
424 static struct wl_shell *
425 shell_surface_get_shell(struct shell_surface *shsurf)
426 {
427         struct weston_surface *es = shsurf->surface;
428         struct weston_shell *shell = es->compositor->shell;
429
430         return (struct wl_shell *)container_of(shell, struct wl_shell, shell);
431 }
432
433 static int
434 get_output_panel_height(struct wl_shell *wlshell,struct weston_output *output)
435 {
436         struct shell_surface *priv;
437         int panel_height = 0;
438
439         if (!output)
440                 return 0;
441
442         wl_list_for_each(priv, &wlshell->panels, link) {
443                 if (priv->output == output) {
444                         panel_height = priv->surface->geometry.height;
445                         break;
446                 }
447         }
448         return panel_height;
449 }
450
451 static void
452 shell_surface_set_maximized(struct wl_client *client,
453                             struct wl_resource *resource,
454                             struct wl_resource *output_resource )
455 {
456         struct shell_surface *shsurf = resource->data;
457         struct weston_surface *es = shsurf->surface;
458         struct wl_shell *wlshell = NULL;
459         uint32_t edges = 0, panel_height = 0;
460
461         /* get the default output, if the client set it as NULL
462            check whether the ouput is available */
463         if (output_resource)
464                 shsurf->output = output_resource->data;
465         else
466                 shsurf->output = get_default_output(es->compositor);
467
468         if (reset_shell_surface_type(shsurf))
469                 return;
470
471         shsurf->saved_x = es->geometry.x;
472         shsurf->saved_y = es->geometry.y;
473
474         wlshell = shell_surface_get_shell(shsurf);
475         panel_height = get_output_panel_height(wlshell, es->output);
476         edges = WL_SHELL_SURFACE_RESIZE_TOP|WL_SHELL_SURFACE_RESIZE_LEFT;
477         wl_resource_post_event(&shsurf->resource,
478                                WL_SHELL_SURFACE_CONFIGURE,
479                                weston_compositor_get_time(), edges,
480                                es->output->current->width,
481                                es->output->current->height - panel_height);
482
483         shsurf->type = SHELL_SURFACE_MAXIMIZED;
484 }
485
486 static void
487 shell_surface_set_fullscreen(struct wl_client *client,
488                              struct wl_resource *resource,
489                              uint32_t method,
490                              uint32_t framerate,
491                              struct wl_resource *output_resource)
492 {
493         struct shell_surface *shsurf = resource->data;
494         struct weston_surface *es = shsurf->surface;
495         struct weston_output *output;
496
497         if (reset_shell_surface_type(shsurf))
498                 return;
499
500         /* FIXME: Fullscreen on first output */
501         /* FIXME: Handle output going away */
502         output = get_default_output(es->compositor);
503         es->output = output;
504
505         shsurf->saved_x = es->geometry.x;
506         shsurf->saved_y = es->geometry.y;
507         shsurf->fullscreen_output = output;
508         shsurf->type = SHELL_SURFACE_FULLSCREEN;
509
510         wl_resource_post_event(resource,
511                                WL_SHELL_SURFACE_CONFIGURE,
512                                weston_compositor_get_time(), 0,
513                                es->output->current->width,
514                                es->output->current->height);
515 }
516
517 static void
518 popup_grab_focus(struct wl_pointer_grab *grab, uint32_t time,
519                  struct wl_surface *surface, int32_t x, int32_t y)
520 {
521         struct wl_input_device *device = grab->input_device;
522         struct shell_surface *priv =
523                 container_of(grab, struct shell_surface, popup.grab);
524         struct wl_client *client = priv->surface->surface.resource.client;
525
526         if (surface && surface->resource.client == client) {
527                 wl_input_device_set_pointer_focus(device, surface, time, x, y);
528                 grab->focus = surface;
529         } else {
530                 wl_input_device_set_pointer_focus(device, NULL, time, 0, 0);
531                 grab->focus = NULL;
532         }
533 }
534
535 static void
536 popup_grab_motion(struct wl_pointer_grab *grab,
537                   uint32_t time, int32_t sx, int32_t sy)
538 {
539         struct wl_resource *resource;
540
541         resource = grab->input_device->pointer_focus_resource;
542         if (resource)
543                 wl_resource_post_event(resource, WL_INPUT_DEVICE_MOTION,
544                                        time, sx, sy);
545 }
546
547 static void
548 popup_grab_button(struct wl_pointer_grab *grab,
549                   uint32_t time, int32_t button, int32_t state)
550 {
551         struct wl_resource *resource;
552         struct shell_surface *shsurf =
553                 container_of(grab, struct shell_surface, popup.grab);
554
555         resource = grab->input_device->pointer_focus_resource;
556         if (resource) {
557                 wl_resource_post_event(resource, WL_INPUT_DEVICE_BUTTON,
558                                        time, button, state);
559         } else if (state == 0 &&
560                    (shsurf->popup.initial_up ||
561                     time - shsurf->popup.time > 500)) {
562                 wl_resource_post_event(&shsurf->resource,
563                                        WL_SHELL_SURFACE_POPUP_DONE);
564                 wl_input_device_end_pointer_grab(grab->input_device, time);
565                 shsurf->popup.grab.input_device = NULL;
566         }
567
568         if (state == 0)
569                 shsurf->popup.initial_up = 1;
570 }
571
572 static const struct wl_pointer_grab_interface popup_grab_interface = {
573         popup_grab_focus,
574         popup_grab_motion,
575         popup_grab_button,
576 };
577
578 static void
579 shell_map_popup(struct shell_surface *shsurf, uint32_t time)
580 {
581         struct wl_input_device *device;
582         struct weston_surface *es = shsurf->surface;
583         struct weston_surface *parent = shsurf->parent->surface;
584
585         es->output = parent->output;
586
587         shsurf->popup.grab.interface = &popup_grab_interface;
588         device = es->compositor->input_device;
589
590         weston_surface_update_transform(parent);
591         if (parent->transform.enabled) {
592                 shsurf->popup.parent_transform.matrix =
593                         parent->transform.matrix;
594         } else {
595                 /* construct x, y translation matrix */
596                 weston_matrix_init(&shsurf->popup.parent_transform.matrix);
597                 shsurf->popup.parent_transform.matrix.d[12] =
598                         parent->geometry.x;
599                 shsurf->popup.parent_transform.matrix.d[13] =
600                         parent->geometry.y;
601         }
602         wl_list_insert(es->geometry.transformation_list.prev,
603                        &shsurf->popup.parent_transform.link);
604         weston_surface_set_position(es, shsurf->popup.x, shsurf->popup.y);
605
606         shsurf->popup.grab.input_device = device;
607         shsurf->popup.time = device->grab_time;
608         shsurf->popup.initial_up = 0;
609
610         wl_input_device_start_pointer_grab(shsurf->popup.grab.input_device,
611                                    &shsurf->popup.grab, shsurf->popup.time);
612 }
613
614 static void
615 shell_surface_set_popup(struct wl_client *client,
616                         struct wl_resource *resource,
617                         struct wl_resource *input_device_resource,
618                         uint32_t time,
619                         struct wl_resource *parent_resource,
620                         int32_t x, int32_t y, uint32_t flags)
621 {
622         struct shell_surface *shsurf = resource->data;
623
624         shsurf->type = SHELL_SURFACE_POPUP;
625         shsurf->parent = parent_resource->data;
626         shsurf->popup.x = x;
627         shsurf->popup.y = y;
628 }
629
630 static const struct wl_shell_surface_interface shell_surface_implementation = {
631         shell_surface_move,
632         shell_surface_resize,
633         shell_surface_set_toplevel,
634         shell_surface_set_transient,
635         shell_surface_set_fullscreen,
636         shell_surface_set_popup,
637         shell_surface_set_maximized
638 };
639
640 static void
641 destroy_shell_surface(struct wl_resource *resource)
642 {
643         struct shell_surface *shsurf = resource->data;
644
645         if (shsurf->popup.grab.input_device)
646                 wl_input_device_end_pointer_grab(shsurf->popup.grab.input_device, 0);
647
648         /* in case cleaning up a dead client destroys shell_surface first */
649         if (shsurf->surface)
650                 wl_list_remove(&shsurf->surface_destroy_listener.link);
651
652         wl_list_remove(&shsurf->link);
653         free(shsurf);
654 }
655
656 static void
657 shell_handle_surface_destroy(struct wl_listener *listener,
658                              struct wl_resource *resource, uint32_t time)
659 {
660         struct shell_surface *shsurf = container_of(listener,
661                                                     struct shell_surface,
662                                                     surface_destroy_listener);
663
664         shsurf->surface = NULL;
665         wl_resource_destroy(&shsurf->resource, time);
666 }
667
668 static struct shell_surface *
669 get_shell_surface(struct weston_surface *surface)
670 {
671         struct wl_list *lst = &surface->surface.resource.destroy_listener_list;
672         struct wl_listener *listener;
673
674         /* search the destroy listener list for our callback */
675         wl_list_for_each(listener, lst, link) {
676                 if (listener->func == shell_handle_surface_destroy) {
677                         return container_of(listener, struct shell_surface,
678                                             surface_destroy_listener);
679                 }
680         }
681
682         return NULL;
683 }
684
685 static void
686 shell_get_shell_surface(struct wl_client *client,
687                         struct wl_resource *resource,
688                         uint32_t id,
689                         struct wl_resource *surface_resource)
690 {
691         struct weston_surface *surface = surface_resource->data;
692         struct shell_surface *shsurf;
693
694         if (get_shell_surface(surface)) {
695                 wl_resource_post_error(surface_resource,
696                         WL_DISPLAY_ERROR_INVALID_OBJECT,
697                         "wl_shell::get_shell_surface already requested");
698                 return;
699         }
700
701         shsurf = calloc(1, sizeof *shsurf);
702         if (!shsurf) {
703                 wl_resource_post_no_memory(resource);
704                 return;
705         }
706
707         shsurf->resource.destroy = destroy_shell_surface;
708         shsurf->resource.object.id = id;
709         shsurf->resource.object.interface = &wl_shell_surface_interface;
710         shsurf->resource.object.implementation =
711                 (void (**)(void)) &shell_surface_implementation;
712         shsurf->resource.data = shsurf;
713
714         shsurf->surface = surface;
715         shsurf->surface_destroy_listener.func = shell_handle_surface_destroy;
716         wl_list_insert(surface->surface.resource.destroy_listener_list.prev,
717                        &shsurf->surface_destroy_listener.link);
718
719         /* init link so its safe to always remove it in destroy_shell_surface */
720         wl_list_init(&shsurf->link);
721
722         /* empty when not in use */
723         wl_list_init(&shsurf->rotation.transform.link);
724         weston_matrix_init(&shsurf->rotation.rotation);
725
726         shsurf->type = SHELL_SURFACE_NONE;
727
728         wl_client_add_resource(client, &shsurf->resource);
729 }
730
731 static const struct wl_shell_interface shell_implementation = {
732         shell_get_shell_surface
733 };
734
735 static void
736 handle_screensaver_sigchld(struct weston_process *proc, int status)
737 {
738         proc->pid = 0;
739 }
740
741 static void
742 launch_screensaver(struct wl_shell *shell)
743 {
744         if (shell->screensaver.binding)
745                 return;
746
747         if (!shell->screensaver.path)
748                 return;
749
750         weston_client_launch(shell->compositor,
751                            &shell->screensaver.process,
752                            shell->screensaver.path,
753                            handle_screensaver_sigchld);
754 }
755
756 static void
757 terminate_screensaver(struct wl_shell *shell)
758 {
759         if (shell->screensaver.process.pid == 0)
760                 return;
761
762         kill(shell->screensaver.process.pid, SIGTERM);
763 }
764
765 static void
766 show_screensaver(struct wl_shell *shell, struct shell_surface *surface)
767 {
768         struct wl_list *list;
769
770         if (shell->lock_surface)
771                 list = &shell->lock_surface->surface->link;
772         else
773                 list = &shell->compositor->surface_list;
774
775         wl_list_remove(&surface->surface->link);
776         wl_list_insert(list, &surface->surface->link);
777         surface->surface->output = surface->output;
778         weston_surface_damage(surface->surface);
779 }
780
781 static void
782 hide_screensaver(struct wl_shell *shell, struct shell_surface *surface)
783 {
784         wl_list_remove(&surface->surface->link);
785         wl_list_init(&surface->surface->link);
786         surface->surface->output = NULL;
787 }
788
789 static void
790 desktop_shell_set_background(struct wl_client *client,
791                              struct wl_resource *resource,
792                              struct wl_resource *output_resource,
793                              struct wl_resource *surface_resource)
794 {
795         struct wl_shell *shell = resource->data;
796         struct shell_surface *shsurf = surface_resource->data;
797         struct weston_surface *surface = shsurf->surface;
798         struct shell_surface *priv;
799
800         if (reset_shell_surface_type(shsurf))
801                 return;
802
803         wl_list_for_each(priv, &shell->backgrounds, link) {
804                 if (priv->output == output_resource->data) {
805                         priv->surface->output = NULL;
806                         wl_list_remove(&priv->surface->link);
807                         wl_list_remove(&priv->link);
808                         break;
809                 }
810         }
811
812         shsurf->type = SHELL_SURFACE_BACKGROUND;
813         shsurf->output = output_resource->data;
814
815         wl_list_insert(&shell->backgrounds, &shsurf->link);
816
817         weston_surface_set_position(surface, shsurf->output->x,
818                                     shsurf->output->y);
819
820         wl_resource_post_event(resource,
821                                DESKTOP_SHELL_CONFIGURE,
822                                weston_compositor_get_time(), 0, surface_resource,
823                                shsurf->output->current->width,
824                                shsurf->output->current->height);
825 }
826
827 static void
828 desktop_shell_set_panel(struct wl_client *client,
829                         struct wl_resource *resource,
830                         struct wl_resource *output_resource,
831                         struct wl_resource *surface_resource)
832 {
833         struct wl_shell *shell = resource->data;
834         struct shell_surface *shsurf = surface_resource->data;
835         struct weston_surface *surface = shsurf->surface;
836         struct shell_surface *priv;
837
838         if (reset_shell_surface_type(shsurf))
839                 return;
840
841         wl_list_for_each(priv, &shell->panels, link) {
842                 if (priv->output == output_resource->data) {
843                         priv->surface->output = NULL;
844                         wl_list_remove(&priv->surface->link);
845                         wl_list_remove(&priv->link);
846                         break;
847                 }
848         }
849
850         shsurf->type = SHELL_SURFACE_PANEL;
851         shsurf->output = output_resource->data;
852
853         wl_list_insert(&shell->panels, &shsurf->link);
854
855         weston_surface_set_position(surface, shsurf->output->x,
856                                     shsurf->output->y);
857
858         wl_resource_post_event(resource,
859                                DESKTOP_SHELL_CONFIGURE,
860                                weston_compositor_get_time(), 0, surface_resource,
861                                shsurf->output->current->width,
862                                shsurf->output->current->height);
863 }
864
865 static void
866 handle_lock_surface_destroy(struct wl_listener *listener,
867                             struct wl_resource *resource, uint32_t time)
868 {
869         struct wl_shell *shell =
870                 container_of(listener, struct wl_shell, lock_surface_listener);
871
872         fprintf(stderr, "lock surface gone\n");
873         shell->lock_surface = NULL;
874 }
875
876 static void
877 desktop_shell_set_lock_surface(struct wl_client *client,
878                                struct wl_resource *resource,
879                                struct wl_resource *surface_resource)
880 {
881         struct wl_shell *shell = resource->data;
882         struct shell_surface *surface = surface_resource->data;
883
884         if (reset_shell_surface_type(surface))
885                 return;
886
887         shell->prepare_event_sent = false;
888
889         if (!shell->locked)
890                 return;
891
892         shell->lock_surface = surface;
893
894         shell->lock_surface_listener.func = handle_lock_surface_destroy;
895         wl_list_insert(&surface_resource->destroy_listener_list,
896                        &shell->lock_surface_listener.link);
897
898         shell->lock_surface->type = SHELL_SURFACE_LOCK;
899 }
900
901 static void
902 resume_desktop(struct wl_shell *shell)
903 {
904         struct weston_surface *surface;
905         struct wl_list *list;
906         struct shell_surface *tmp;
907
908         wl_list_for_each(tmp, &shell->screensaver.surfaces, link)
909                 hide_screensaver(shell, tmp);
910
911         terminate_screensaver(shell);
912
913         wl_list_for_each(surface, &shell->hidden_surface_list, link)
914                 weston_surface_assign_output(surface);
915
916         if (wl_list_empty(&shell->backgrounds)) {
917                 list = &shell->compositor->surface_list;
918         } else {
919                 struct shell_surface *background;
920                 background = container_of(shell->backgrounds.prev,
921                                           struct shell_surface, link);
922                 list = background->surface->link.prev;
923         }
924
925         if (!wl_list_empty(&shell->hidden_surface_list))
926                 wl_list_insert_list(list, &shell->hidden_surface_list);
927         wl_list_init(&shell->hidden_surface_list);
928
929         shell->locked = false;
930         weston_compositor_repick(shell->compositor);
931         shell->compositor->idle_time = shell->compositor->option_idle_time;
932         weston_compositor_wake(shell->compositor);
933         weston_compositor_damage_all(shell->compositor);
934 }
935
936 static void
937 desktop_shell_unlock(struct wl_client *client,
938                      struct wl_resource *resource)
939 {
940         struct wl_shell *shell = resource->data;
941
942         shell->prepare_event_sent = false;
943
944         if (shell->locked)
945                 resume_desktop(shell);
946 }
947
948 static const struct desktop_shell_interface desktop_shell_implementation = {
949         desktop_shell_set_background,
950         desktop_shell_set_panel,
951         desktop_shell_set_lock_surface,
952         desktop_shell_unlock
953 };
954
955 static enum shell_surface_type
956 get_shell_surface_type(struct weston_surface *surface)
957 {
958         struct shell_surface *shsurf;
959
960         shsurf = get_shell_surface(surface);
961         if (!shsurf)
962                 return SHELL_SURFACE_NONE;
963         return shsurf->type;
964 }
965
966 static void
967 move_binding(struct wl_input_device *device, uint32_t time,
968              uint32_t key, uint32_t button, uint32_t state, void *data)
969 {
970         struct weston_surface *surface =
971                 (struct weston_surface *) device->pointer_focus;
972
973         if (surface == NULL)
974                 return;
975
976         switch (get_shell_surface_type(surface)) {
977                 case SHELL_SURFACE_PANEL:
978                 case SHELL_SURFACE_BACKGROUND:
979                 case SHELL_SURFACE_FULLSCREEN:
980                 case SHELL_SURFACE_SCREENSAVER:
981                         return;
982                 default:
983                         break;
984         }
985
986         weston_surface_move(surface, (struct weston_input_device *) device, time);
987 }
988
989 static void
990 resize_binding(struct wl_input_device *device, uint32_t time,
991                uint32_t key, uint32_t button, uint32_t state, void *data)
992 {
993         struct weston_surface *surface =
994                 (struct weston_surface *) device->pointer_focus;
995         uint32_t edges = 0;
996         int32_t x, y;
997         struct shell_surface *shsurf;
998
999         if (surface == NULL)
1000                 return;
1001
1002         shsurf = get_shell_surface(surface);
1003         if (!shsurf)
1004                 return;
1005
1006         switch (shsurf->type) {
1007                 case SHELL_SURFACE_PANEL:
1008                 case SHELL_SURFACE_BACKGROUND:
1009                 case SHELL_SURFACE_FULLSCREEN:
1010                 case SHELL_SURFACE_SCREENSAVER:
1011                         return;
1012                 default:
1013                         break;
1014         }
1015
1016         weston_surface_from_global(surface,
1017                                    device->grab_x, device->grab_y, &x, &y);
1018
1019         if (x < surface->geometry.width / 3)
1020                 edges |= WL_SHELL_SURFACE_RESIZE_LEFT;
1021         else if (x < 2 * surface->geometry.width / 3)
1022                 edges |= 0;
1023         else
1024                 edges |= WL_SHELL_SURFACE_RESIZE_RIGHT;
1025
1026         if (y < surface->geometry.height / 3)
1027                 edges |= WL_SHELL_SURFACE_RESIZE_TOP;
1028         else if (y < 2 * surface->geometry.height / 3)
1029                 edges |= 0;
1030         else
1031                 edges |= WL_SHELL_SURFACE_RESIZE_BOTTOM;
1032
1033         weston_surface_resize(shsurf, (struct weston_input_device *) device,
1034                             time, edges);
1035 }
1036
1037 static void
1038 terminate_binding(struct wl_input_device *device, uint32_t time,
1039                   uint32_t key, uint32_t button, uint32_t state, void *data)
1040 {
1041         struct weston_compositor *compositor = data;
1042
1043         if (state)
1044                 wl_display_terminate(compositor->wl_display);
1045 }
1046
1047 static void
1048 rotate_grab_motion(struct wl_pointer_grab *grab,
1049                  uint32_t time, int32_t x, int32_t y)
1050 {
1051         struct rotate_grab *rotate =
1052                 container_of(grab, struct rotate_grab, grab);
1053         struct wl_input_device *device = grab->input_device;
1054         struct shell_surface *surface = rotate->surface;
1055         GLfloat cx = 0.5f * surface->surface->geometry.width;
1056         GLfloat cy = 0.5f * surface->surface->geometry.height;
1057         GLfloat dx, dy;
1058         GLfloat r;
1059
1060         dx = device->x - rotate->center.x;
1061         dy = device->y - rotate->center.y;
1062         r = sqrtf(dx * dx + dy * dy);
1063
1064         wl_list_remove(&surface->rotation.transform.link);
1065         surface->surface->geometry.dirty = 1;
1066
1067         if (r > 20.0f) {
1068                 struct weston_matrix *matrix =
1069                         &surface->rotation.transform.matrix;
1070
1071                 weston_matrix_init(&rotate->rotation);
1072                 rotate->rotation.d[0] = dx / r;
1073                 rotate->rotation.d[4] = -dy / r;
1074                 rotate->rotation.d[1] = -rotate->rotation.d[4];
1075                 rotate->rotation.d[5] = rotate->rotation.d[0];
1076
1077                 weston_matrix_init(matrix);
1078                 weston_matrix_translate(matrix, -cx, -cy, 0.0f);
1079                 weston_matrix_multiply(matrix, &surface->rotation.rotation);
1080                 weston_matrix_multiply(matrix, &rotate->rotation);
1081                 weston_matrix_translate(matrix, cx, cy, 0.0f);
1082
1083                 wl_list_insert(
1084                         &surface->surface->geometry.transformation_list,
1085                         &surface->rotation.transform.link);
1086         } else {
1087                 wl_list_init(&surface->rotation.transform.link);
1088                 weston_matrix_init(&surface->rotation.rotation);
1089                 weston_matrix_init(&rotate->rotation);
1090         }
1091
1092         /* Repaint implies weston_surface_update_transform(), which
1093          * lazily applies the damage due to rotation update.
1094          */
1095         weston_compositor_schedule_repaint(surface->surface->compositor);
1096 }
1097
1098 static void
1099 rotate_grab_button(struct wl_pointer_grab *grab,
1100                  uint32_t time, int32_t button, int32_t state)
1101 {
1102         struct rotate_grab *rotate =
1103                 container_of(grab, struct rotate_grab, grab);
1104         struct wl_input_device *device = grab->input_device;
1105         struct shell_surface *surface = rotate->surface;
1106
1107         if (device->button_count == 0 && state == 0) {
1108                 weston_matrix_multiply(&surface->rotation.rotation,
1109                                        &rotate->rotation);
1110                 wl_input_device_end_pointer_grab(device, time);
1111                 free(rotate);
1112         }
1113 }
1114
1115 static const struct wl_pointer_grab_interface rotate_grab_interface = {
1116         noop_grab_focus,
1117         rotate_grab_motion,
1118         rotate_grab_button,
1119 };
1120
1121 static void
1122 rotate_binding(struct wl_input_device *device, uint32_t time,
1123                uint32_t key, uint32_t button, uint32_t state, void *data)
1124 {
1125         struct weston_surface *base_surface =
1126                 (struct weston_surface *) device->pointer_focus;
1127         struct shell_surface *surface;
1128         struct rotate_grab *rotate;
1129         GLfloat dx, dy;
1130         GLfloat r;
1131
1132         if (base_surface == NULL)
1133                 return;
1134
1135         surface = get_shell_surface(base_surface);
1136         if (!surface)
1137                 return;
1138
1139         switch (surface->type) {
1140                 case SHELL_SURFACE_PANEL:
1141                 case SHELL_SURFACE_BACKGROUND:
1142                 case SHELL_SURFACE_FULLSCREEN:
1143                 case SHELL_SURFACE_SCREENSAVER:
1144                         return;
1145                 default:
1146                         break;
1147         }
1148
1149         rotate = malloc(sizeof *rotate);
1150         if (!rotate)
1151                 return;
1152
1153         rotate->grab.interface = &rotate_grab_interface;
1154         rotate->surface = surface;
1155
1156         weston_surface_to_global(surface->surface,
1157                                  surface->surface->geometry.width / 2,
1158                                  surface->surface->geometry.height / 2,
1159                                  &rotate->center.x, &rotate->center.y);
1160
1161         wl_input_device_start_pointer_grab(device, &rotate->grab, time);
1162
1163         dx = device->x - rotate->center.x;
1164         dy = device->y - rotate->center.y;
1165         r = sqrtf(dx * dx + dy * dy);
1166         if (r > 20.0f) {
1167                 struct weston_matrix inverse;
1168
1169                 weston_matrix_init(&inverse);
1170                 inverse.d[0] = dx / r;
1171                 inverse.d[4] = dy / r;
1172                 inverse.d[1] = -inverse.d[4];
1173                 inverse.d[5] = inverse.d[0];
1174                 weston_matrix_multiply(&surface->rotation.rotation, &inverse);
1175         } else {
1176                 weston_matrix_init(&surface->rotation.rotation);
1177                 weston_matrix_init(&rotate->rotation);
1178         }
1179
1180         wl_input_device_set_pointer_focus(device, NULL, time, 0, 0);
1181 }
1182
1183 static void
1184 activate(struct weston_shell *base, struct weston_surface *es,
1185          struct weston_input_device *device, uint32_t time)
1186 {
1187         struct wl_shell *shell = container_of(base, struct wl_shell, shell);
1188         struct weston_compositor *compositor = shell->compositor;
1189         struct wl_list *list;
1190
1191         weston_surface_activate(es, device, time);
1192
1193         if (compositor->wxs)
1194                 weston_xserver_surface_activate(es);
1195
1196         switch (get_shell_surface_type(es)) {
1197         case SHELL_SURFACE_BACKGROUND:
1198                 /* put background back to bottom */
1199                 wl_list_remove(&es->link);
1200                 wl_list_insert(compositor->surface_list.prev, &es->link);
1201                 break;
1202         case SHELL_SURFACE_PANEL:
1203                 /* already put on top */
1204                 break;
1205         case SHELL_SURFACE_SCREENSAVER:
1206                 /* always below lock surface */
1207                 if (shell->lock_surface) {
1208                         wl_list_remove(&es->link);
1209                         wl_list_insert(&shell->lock_surface->surface->link,
1210                                        &es->link);
1211                 }
1212                 break;
1213         default:
1214                 if (!shell->locked) {
1215                         list = weston_compositor_top(compositor);
1216
1217                         /* bring panel back to top */
1218                         struct shell_surface *panel;
1219                         wl_list_for_each(panel, &shell->panels, link) {
1220                                 wl_list_remove(&panel->surface->link);
1221                                 wl_list_insert(list, &panel->surface->link);
1222                         }
1223                 }
1224         }
1225 }
1226
1227 static void
1228 click_to_activate_binding(struct wl_input_device *device,
1229                          uint32_t time, uint32_t key,
1230                           uint32_t button, uint32_t state, void *data)
1231 {
1232         struct weston_input_device *wd = (struct weston_input_device *) device;
1233         struct weston_compositor *compositor = data;
1234         struct weston_surface *focus;
1235
1236         focus = (struct weston_surface *) device->pointer_focus;
1237         if (state && focus && device->pointer_grab == &device->default_pointer_grab)
1238                 activate(compositor->shell, focus, wd, time);
1239 }
1240
1241 static void
1242 lock(struct weston_shell *base)
1243 {
1244         struct wl_shell *shell = container_of(base, struct wl_shell, shell);
1245         struct wl_list *surface_list = &shell->compositor->surface_list;
1246         struct weston_surface *cur;
1247         struct weston_surface *tmp;
1248         struct weston_input_device *device;
1249         struct shell_surface *shsurf;
1250         uint32_t time;
1251
1252         if (shell->locked)
1253                 return;
1254
1255         shell->locked = true;
1256
1257         /* Move all surfaces from compositor's list to our hidden list,
1258          * except the background. This way nothing else can show or
1259          * receive input events while we are locked. */
1260
1261         if (!wl_list_empty(&shell->hidden_surface_list)) {
1262                 fprintf(stderr,
1263                 "%s: Assertion failed: hidden_surface_list is not empty.\n",
1264                                                                 __func__);
1265         }
1266
1267         wl_list_for_each_safe(cur, tmp, surface_list, link) {
1268                 /* skip input device sprites, cur->surface is uninitialised */
1269                 if (cur->surface.resource.client == NULL)
1270                         continue;
1271
1272                 if (get_shell_surface_type(cur) == SHELL_SURFACE_BACKGROUND)
1273                         continue;
1274
1275                 cur->output = NULL;
1276                 wl_list_remove(&cur->link);
1277                 wl_list_insert(shell->hidden_surface_list.prev, &cur->link);
1278         }
1279
1280         launch_screensaver(shell);
1281
1282         wl_list_for_each(shsurf, &shell->screensaver.surfaces, link)
1283                 show_screensaver(shell, shsurf);
1284
1285         if (!wl_list_empty(&shell->screensaver.surfaces)) {
1286                 shell->compositor->idle_time = shell->screensaver.duration;
1287                 weston_compositor_wake(shell->compositor);
1288                 shell->compositor->state = WESTON_COMPOSITOR_IDLE;
1289         }
1290
1291         /* reset pointer foci */
1292         weston_compositor_repick(shell->compositor);
1293
1294         /* reset keyboard foci */
1295         time = weston_compositor_get_time();
1296         wl_list_for_each(device, &shell->compositor->input_device_list, link) {
1297                 wl_input_device_set_keyboard_focus(&device->input_device,
1298                                                    NULL, time);
1299         }
1300
1301         /* TODO: disable bindings that should not work while locked. */
1302
1303         /* All this must be undone in resume_desktop(). */
1304 }
1305
1306 static void
1307 unlock(struct weston_shell *base)
1308 {
1309         struct wl_shell *shell = container_of(base, struct wl_shell, shell);
1310
1311         if (!shell->locked || shell->lock_surface) {
1312                 weston_compositor_wake(shell->compositor);
1313                 return;
1314         }
1315
1316         /* If desktop-shell client has gone away, unlock immediately. */
1317         if (!shell->child.desktop_shell) {
1318                 resume_desktop(shell);
1319                 return;
1320         }
1321
1322         if (shell->prepare_event_sent)
1323                 return;
1324
1325         wl_resource_post_event(shell->child.desktop_shell,
1326                                DESKTOP_SHELL_PREPARE_LOCK_SURFACE);
1327         shell->prepare_event_sent = true;
1328 }
1329
1330 static void
1331 center_on_output(struct weston_surface *surface, struct weston_output *output)
1332 {
1333         struct weston_mode *mode = output->current;
1334         GLfloat x = (mode->width - surface->geometry.width) / 2;
1335         GLfloat y = (mode->height - surface->geometry.height) / 2;
1336
1337         weston_surface_set_position(surface, output->x + x, output->y + y);
1338 }
1339
1340 static void
1341 map(struct weston_shell *base, struct weston_surface *surface,
1342     int32_t width, int32_t height, int32_t sx, int32_t sy)
1343 {
1344         struct wl_shell *shell = container_of(base, struct wl_shell, shell);
1345         struct weston_compositor *compositor = shell->compositor;
1346         struct wl_list *list;
1347         struct shell_surface *shsurf;
1348         enum shell_surface_type surface_type = SHELL_SURFACE_NONE;
1349         int do_configure;
1350         int panel_height = 0;
1351
1352         shsurf = get_shell_surface(surface);
1353         if (shsurf)
1354                 surface_type = shsurf->type;
1355
1356         if (shell->locked) {
1357                 list = &shell->hidden_surface_list;
1358                 do_configure = 0;
1359         } else {
1360                 list = weston_compositor_top(compositor);
1361                 do_configure = 1;
1362         }
1363
1364         surface->geometry.width = width;
1365         surface->geometry.height = height;
1366         surface->geometry.dirty = 1;
1367
1368         weston_compositor_update_drag_surfaces(compositor);
1369
1370         /* initial positioning, see also configure() */
1371         switch (surface_type) {
1372         case SHELL_SURFACE_TOPLEVEL:
1373                 weston_surface_set_position(surface, 10 + random() % 400,
1374                                             10 + random() % 400);
1375                 break;
1376         case SHELL_SURFACE_SCREENSAVER:
1377         case SHELL_SURFACE_FULLSCREEN:
1378                 center_on_output(surface, shsurf->fullscreen_output);
1379                 break;
1380         case SHELL_SURFACE_MAXIMIZED:
1381                 /*use surface configure to set the geometry*/
1382                 panel_height = get_output_panel_height(shell,surface->output);
1383                 weston_surface_set_position(surface, surface->output->x,
1384                                             surface->output->y + panel_height);
1385                 break;
1386         case SHELL_SURFACE_LOCK:
1387                 center_on_output(surface, get_default_output(compositor));
1388                 break;
1389         case SHELL_SURFACE_POPUP:
1390                 shell_map_popup(shsurf, shsurf->popup.time);
1391         case SHELL_SURFACE_NONE:
1392                 weston_surface_set_position(surface,
1393                                             surface->geometry.x + sx,
1394                                             surface->geometry.y + sy);
1395                 break;
1396         default:
1397                 ;
1398         }
1399
1400         /* surface stacking order, see also activate() */
1401         switch (surface_type) {
1402         case SHELL_SURFACE_BACKGROUND:
1403                 /* background always visible, at the bottom */
1404                 wl_list_insert(compositor->surface_list.prev, &surface->link);
1405                 do_configure = 1;
1406                 break;
1407         case SHELL_SURFACE_PANEL:
1408                 /* panel always on top, hidden while locked */
1409                 wl_list_insert(list, &surface->link);
1410                 break;
1411         case SHELL_SURFACE_LOCK:
1412                 /* lock surface always visible, on top */
1413                 wl_list_insert(&compositor->surface_list, &surface->link);
1414
1415                 weston_compositor_wake(compositor);
1416                 do_configure = 1;
1417                 break;
1418         case SHELL_SURFACE_SCREENSAVER:
1419                 /* If locked, show it. */
1420                 if (shell->locked) {
1421                         show_screensaver(shell, shsurf);
1422                         compositor->idle_time = shell->screensaver.duration;
1423                         weston_compositor_wake(compositor);
1424                         if (!shell->lock_surface)
1425                                 compositor->state = WESTON_COMPOSITOR_IDLE;
1426                 }
1427                 do_configure = 0;
1428                 break;
1429         case SHELL_SURFACE_NONE:
1430                 break;
1431         default:
1432                 /* everything else just below the panel */
1433                 if (!wl_list_empty(&shell->panels)) {
1434                         struct shell_surface *panel =
1435                                 container_of(shell->panels.prev,
1436                                              struct shell_surface, link);
1437                         wl_list_insert(&panel->surface->link, &surface->link);
1438                 } else {
1439                         wl_list_insert(list, &surface->link);
1440                 }
1441         }
1442
1443         if (do_configure) {
1444                 weston_surface_assign_output(surface);
1445                 weston_compositor_repick(compositor);
1446                 if (surface_type == SHELL_SURFACE_MAXIMIZED)
1447                         surface->output = shsurf->output;
1448         }
1449
1450         switch (surface_type) {
1451         case SHELL_SURFACE_TOPLEVEL:
1452         case SHELL_SURFACE_TRANSIENT:
1453         case SHELL_SURFACE_FULLSCREEN:
1454         case SHELL_SURFACE_MAXIMIZED:
1455                 if (!shell->locked)
1456                         activate(base, surface,
1457                                  (struct weston_input_device *)
1458                                         compositor->input_device,
1459                                  weston_compositor_get_time());
1460                 break;
1461         default:
1462                 break;
1463         }
1464
1465         if (surface_type == SHELL_SURFACE_TOPLEVEL)
1466                 weston_zoom_run(surface, 0.8, 1.0, NULL, NULL);
1467 }
1468
1469 static void
1470 configure(struct weston_shell *base, struct weston_surface *surface,
1471           GLfloat x, GLfloat y, int32_t width, int32_t height)
1472 {
1473         struct wl_shell *shell = container_of(base, struct wl_shell, shell);
1474         enum shell_surface_type surface_type = SHELL_SURFACE_NONE;
1475         struct shell_surface *shsurf;
1476
1477         shsurf = get_shell_surface(surface);
1478         if (shsurf)
1479                 surface_type = shsurf->type;
1480
1481         surface->geometry.x = x;
1482         surface->geometry.y = y;
1483         surface->geometry.width = width;
1484         surface->geometry.height = height;
1485         surface->geometry.dirty = 1;
1486
1487         switch (surface_type) {
1488         case SHELL_SURFACE_SCREENSAVER:
1489         case SHELL_SURFACE_FULLSCREEN:
1490                 center_on_output(surface, shsurf->fullscreen_output);
1491                 break;
1492         case SHELL_SURFACE_MAXIMIZED:
1493                 /*setting x, y and using configure to change that geometry*/
1494                 surface->geometry.x = surface->output->x;
1495                 surface->geometry.y = surface->output->y +
1496                         get_output_panel_height(shell,surface->output);
1497                 break;
1498         default:
1499                 break;
1500         }
1501
1502         /*  XXX: would a fullscreen surface need the same handling? */
1503         if (surface->output) {
1504                 weston_surface_assign_output(surface);
1505
1506                 if (surface_type == SHELL_SURFACE_SCREENSAVER)
1507                         surface->output = shsurf->output;
1508                 else if (surface_type == SHELL_SURFACE_MAXIMIZED)
1509                         surface->output = shsurf->output;
1510         }
1511 }
1512
1513 static int launch_desktop_shell_process(struct wl_shell *shell);
1514
1515 static void
1516 desktop_shell_sigchld(struct weston_process *process, int status)
1517 {
1518         uint32_t time;
1519         struct wl_shell *shell =
1520                 container_of(process, struct wl_shell, child.process);
1521
1522         shell->child.process.pid = 0;
1523         shell->child.client = NULL; /* already destroyed by wayland */
1524
1525         /* if desktop-shell dies more than 5 times in 30 seconds, give up */
1526         time = weston_compositor_get_time();
1527         if (time - shell->child.deathstamp > 30000) {
1528                 shell->child.deathstamp = time;
1529                 shell->child.deathcount = 0;
1530         }
1531
1532         shell->child.deathcount++;
1533         if (shell->child.deathcount > 5) {
1534                 fprintf(stderr, "weston-desktop-shell died, giving up.\n");
1535                 return;
1536         }
1537
1538         fprintf(stderr, "weston-desktop-shell died, respawning...\n");
1539         launch_desktop_shell_process(shell);
1540 }
1541
1542 static int
1543 launch_desktop_shell_process(struct wl_shell *shell)
1544 {
1545         const char *shell_exe = LIBEXECDIR "/weston-desktop-shell";
1546
1547         shell->child.client = weston_client_launch(shell->compositor,
1548                                                  &shell->child.process,
1549                                                  shell_exe,
1550                                                  desktop_shell_sigchld);
1551
1552         if (!shell->child.client)
1553                 return -1;
1554         return 0;
1555 }
1556
1557 static void
1558 bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
1559 {
1560         struct wl_shell *shell = data;
1561
1562         wl_client_add_object(client, &wl_shell_interface,
1563                              &shell_implementation, id, shell);
1564 }
1565
1566 static void
1567 unbind_desktop_shell(struct wl_resource *resource)
1568 {
1569         struct wl_shell *shell = resource->data;
1570
1571         if (shell->locked)
1572                 resume_desktop(shell);
1573
1574         shell->child.desktop_shell = NULL;
1575         shell->prepare_event_sent = false;
1576         free(resource);
1577 }
1578
1579 static void
1580 bind_desktop_shell(struct wl_client *client,
1581                    void *data, uint32_t version, uint32_t id)
1582 {
1583         struct wl_shell *shell = data;
1584         struct wl_resource *resource;
1585
1586         resource = wl_client_add_object(client, &desktop_shell_interface,
1587                                         &desktop_shell_implementation,
1588                                         id, shell);
1589
1590         if (client == shell->child.client) {
1591                 resource->destroy = unbind_desktop_shell;
1592                 shell->child.desktop_shell = resource;
1593                 return;
1594         }
1595
1596         wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
1597                                "permission to bind desktop_shell denied");
1598         wl_resource_destroy(resource, 0);
1599 }
1600
1601 static void
1602 screensaver_set_surface(struct wl_client *client,
1603                         struct wl_resource *resource,
1604                         struct wl_resource *shell_surface_resource,
1605                         struct wl_resource *output_resource)
1606 {
1607         struct wl_shell *shell = resource->data;
1608         struct shell_surface *surface = shell_surface_resource->data;
1609         struct weston_output *output = output_resource->data;
1610
1611         if (reset_shell_surface_type(surface))
1612                 return;
1613
1614         surface->type = SHELL_SURFACE_SCREENSAVER;
1615
1616         surface->fullscreen_output = output;
1617         surface->output = output;
1618         wl_list_insert(shell->screensaver.surfaces.prev, &surface->link);
1619 }
1620
1621 static const struct screensaver_interface screensaver_implementation = {
1622         screensaver_set_surface
1623 };
1624
1625 static void
1626 unbind_screensaver(struct wl_resource *resource)
1627 {
1628         struct wl_shell *shell = resource->data;
1629
1630         shell->screensaver.binding = NULL;
1631         free(resource);
1632 }
1633
1634 static void
1635 bind_screensaver(struct wl_client *client,
1636                  void *data, uint32_t version, uint32_t id)
1637 {
1638         struct wl_shell *shell = data;
1639         struct wl_resource *resource;
1640
1641         resource = wl_client_add_object(client, &screensaver_interface,
1642                                         &screensaver_implementation,
1643                                         id, shell);
1644
1645         if (shell->screensaver.binding == NULL) {
1646                 resource->destroy = unbind_screensaver;
1647                 shell->screensaver.binding = resource;
1648                 return;
1649         }
1650
1651         wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
1652                                "interface object already bound");
1653         wl_resource_destroy(resource, 0);
1654 }
1655
1656 static void
1657 shell_destroy(struct weston_shell *base)
1658 {
1659         struct wl_shell *shell = container_of(base, struct wl_shell, shell);
1660
1661         if (shell->child.client)
1662                 wl_client_destroy(shell->child.client);
1663
1664         free(shell->screensaver.path);
1665         free(shell);
1666 }
1667
1668 int
1669 shell_init(struct weston_compositor *ec);
1670
1671 WL_EXPORT int
1672 shell_init(struct weston_compositor *ec)
1673 {
1674         struct wl_shell *shell;
1675
1676         shell = malloc(sizeof *shell);
1677         if (shell == NULL)
1678                 return -1;
1679
1680         memset(shell, 0, sizeof *shell);
1681         shell->compositor = ec;
1682         shell->shell.lock = lock;
1683         shell->shell.unlock = unlock;
1684         shell->shell.map = map;
1685         shell->shell.configure = configure;
1686         shell->shell.destroy = shell_destroy;
1687
1688         wl_list_init(&shell->hidden_surface_list);
1689         wl_list_init(&shell->backgrounds);
1690         wl_list_init(&shell->panels);
1691         wl_list_init(&shell->screensaver.surfaces);
1692
1693         shell_configuration(shell);
1694
1695         if (wl_display_add_global(ec->wl_display, &wl_shell_interface,
1696                                   shell, bind_shell) == NULL)
1697                 return -1;
1698
1699         if (wl_display_add_global(ec->wl_display,
1700                                   &desktop_shell_interface,
1701                                   shell, bind_desktop_shell) == NULL)
1702                 return -1;
1703
1704         if (wl_display_add_global(ec->wl_display, &screensaver_interface,
1705                                   shell, bind_screensaver) == NULL)
1706                 return -1;
1707
1708         shell->child.deathstamp = weston_compositor_get_time();
1709         if (launch_desktop_shell_process(shell) != 0)
1710                 return -1;
1711
1712         weston_compositor_add_binding(ec, 0, BTN_LEFT, MODIFIER_SUPER,
1713                                     move_binding, shell);
1714         weston_compositor_add_binding(ec, 0, BTN_MIDDLE, MODIFIER_SUPER,
1715                                     resize_binding, shell);
1716         weston_compositor_add_binding(ec, KEY_BACKSPACE, 0,
1717                                     MODIFIER_CTRL | MODIFIER_ALT,
1718                                     terminate_binding, ec);
1719         weston_compositor_add_binding(ec, 0, BTN_LEFT, 0,
1720                                     click_to_activate_binding, ec);
1721         weston_compositor_add_binding(ec, 0, BTN_LEFT,
1722                                       MODIFIER_SUPER | MODIFIER_ALT,
1723                                       rotate_binding, NULL);
1724
1725         ec->shell = &shell->shell;
1726
1727         return 0;
1728 }