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