f8cee0ec3592c889c675c741f310f828c1808d10
[profile/ivi/weston.git] / src / shell.c
1 /*
2  * Copyright © 2010-2012 Intel Corporation
3  * Copyright © 2011-2012 Collabora, Ltd.
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and
6  * its documentation for any purpose is hereby granted without fee, provided
7  * that the above copyright notice appear in all copies and that both that
8  * copyright notice and this permission notice appear in supporting
9  * documentation, and that the name of the copyright holders not be used in
10  * advertising or publicity pertaining to distribution of the software
11  * without specific, written prior permission.  The copyright holders make
12  * no representations about the suitability of this software for any
13  * purpose.  It is provided "as is" without express or implied warranty.
14  *
15  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
16  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17  * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
20  * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  */
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <stdbool.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <linux/input.h>
30 #include <assert.h>
31 #include <signal.h>
32 #include <math.h>
33 #include <sys/types.h>
34
35 #include <wayland-server.h>
36 #include "compositor.h"
37 #include "desktop-shell-server-protocol.h"
38 #include "workspaces-server-protocol.h"
39 #include "../shared/config-parser.h"
40
41 #define DEFAULT_NUM_WORKSPACES 1
42 #define DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH 200
43
44 enum animation_type {
45         ANIMATION_NONE,
46
47         ANIMATION_ZOOM,
48         ANIMATION_FADE
49 };
50
51 struct focus_state {
52         struct weston_seat *seat;
53         struct workspace *ws;
54         struct weston_surface *keyboard_focus;
55         struct wl_list link;
56         struct wl_listener seat_destroy_listener;
57         struct wl_listener surface_destroy_listener;
58 };
59
60 struct workspace {
61         struct weston_layer layer;
62
63         struct wl_list focus_list;
64         struct wl_listener seat_destroyed_listener;
65 };
66
67 struct input_panel_surface {
68         struct wl_list link;
69         struct weston_surface *surface;
70         struct wl_listener listener;
71 };
72
73 struct desktop_shell {
74         struct weston_compositor *compositor;
75
76         struct wl_listener lock_listener;
77         struct wl_listener unlock_listener;
78         struct wl_listener destroy_listener;
79         struct wl_listener show_input_panel_listener;
80         struct wl_listener hide_input_panel_listener;
81
82         struct weston_layer fullscreen_layer;
83         struct weston_layer panel_layer;
84         struct weston_layer background_layer;
85         struct weston_layer lock_layer;
86         struct weston_layer input_panel_layer;
87
88         struct wl_listener pointer_focus_listener;
89         struct weston_surface *grab_surface;
90
91         struct {
92                 struct weston_process process;
93                 struct wl_client *client;
94                 struct wl_resource *desktop_shell;
95
96                 unsigned deathcount;
97                 uint32_t deathstamp;
98         } child;
99
100         bool locked;
101         bool showing_input_panels;
102         bool prepare_event_sent;
103
104         struct weston_surface *lock_surface;
105         struct wl_listener lock_surface_listener;
106
107         struct {
108                 struct wl_array array;
109                 unsigned int current;
110                 unsigned int num;
111
112                 struct wl_list client_list;
113
114                 struct weston_animation animation;
115                 struct wl_list anim_sticky_list;
116                 int anim_dir;
117                 uint32_t anim_timestamp;
118                 double anim_current;
119                 struct workspace *anim_from;
120                 struct workspace *anim_to;
121         } workspaces;
122
123         struct {
124                 char *path;
125                 int duration;
126                 struct wl_resource *binding;
127                 struct wl_list surfaces;
128                 struct weston_process process;
129         } screensaver;
130
131         struct {
132                 struct wl_resource *binding;
133                 struct wl_list surfaces;
134         } input_panel;
135
136         uint32_t binding_modifier;
137         enum animation_type win_animation_type;
138         struct weston_surface *debug_repaint_surface;
139 };
140
141 enum shell_surface_type {
142         SHELL_SURFACE_NONE,
143         SHELL_SURFACE_TOPLEVEL,
144         SHELL_SURFACE_TRANSIENT,
145         SHELL_SURFACE_FULLSCREEN,
146         SHELL_SURFACE_MAXIMIZED,
147         SHELL_SURFACE_POPUP
148 };
149
150 struct ping_timer {
151         struct wl_event_source *source;
152         uint32_t serial;
153 };
154
155 struct shell_surface {
156         struct wl_resource resource;
157
158         struct weston_surface *surface;
159         struct wl_listener surface_destroy_listener;
160         struct weston_surface *parent;
161         struct desktop_shell *shell;
162
163         enum shell_surface_type type, next_type;
164         char *title, *class;
165         int32_t saved_x, saved_y;
166         bool saved_position_valid;
167         bool saved_rotation_valid;
168         int unresponsive;
169
170         struct {
171                 struct weston_transform transform;
172                 struct weston_matrix rotation;
173         } rotation;
174
175         struct {
176                 struct wl_pointer_grab grab;
177                 int32_t x, y;
178                 struct weston_transform parent_transform;
179                 int32_t initial_up;
180                 struct wl_seat *seat;
181                 uint32_t serial;
182         } popup;
183
184         struct {
185                 int32_t x, y;
186                 uint32_t flags;
187         } transient;
188
189         struct {
190                 enum wl_shell_surface_fullscreen_method type;
191                 struct weston_transform transform; /* matrix from x, y */
192                 uint32_t framerate;
193                 struct weston_surface *black_surface;
194         } fullscreen;
195
196         struct ping_timer *ping_timer;
197
198         struct weston_transform workspace_transform;
199
200         struct weston_output *fullscreen_output;
201         struct weston_output *output;
202         struct wl_list link;
203
204         const struct weston_shell_client *client;
205 };
206
207 struct shell_grab {
208         struct wl_pointer_grab grab;
209         struct shell_surface *shsurf;
210         struct wl_listener shsurf_destroy_listener;
211         struct wl_pointer *pointer;
212 };
213
214 struct weston_move_grab {
215         struct shell_grab base;
216         wl_fixed_t dx, dy;
217 };
218
219 struct rotate_grab {
220         struct shell_grab base;
221         struct weston_matrix rotation;
222         struct {
223                 float x;
224                 float y;
225         } center;
226 };
227
228 static void
229 activate(struct desktop_shell *shell, struct weston_surface *es,
230          struct weston_seat *seat);
231
232 static struct workspace *
233 get_current_workspace(struct desktop_shell *shell);
234
235 static struct shell_surface *
236 get_shell_surface(struct weston_surface *surface);
237
238 static struct desktop_shell *
239 shell_surface_get_shell(struct shell_surface *shsurf);
240
241 static bool
242 shell_surface_is_top_fullscreen(struct shell_surface *shsurf)
243 {
244         struct desktop_shell *shell;
245         struct weston_surface *top_fs_es;
246
247         shell = shell_surface_get_shell(shsurf);
248         
249         if (wl_list_empty(&shell->fullscreen_layer.surface_list))
250                 return false;
251
252         top_fs_es = container_of(shell->fullscreen_layer.surface_list.next,
253                                  struct weston_surface, 
254                                  layer_link);
255         return (shsurf == get_shell_surface(top_fs_es));
256 }
257
258 static void
259 destroy_shell_grab_shsurf(struct wl_listener *listener, void *data)
260 {
261         struct shell_grab *grab;
262
263         grab = container_of(listener, struct shell_grab,
264                             shsurf_destroy_listener);
265
266         grab->shsurf = NULL;
267 }
268
269 static void
270 popup_grab_end(struct wl_pointer *pointer);
271
272 static void
273 shell_grab_start(struct shell_grab *grab,
274                  const struct wl_pointer_grab_interface *interface,
275                  struct shell_surface *shsurf,
276                  struct wl_pointer *pointer,
277                  enum desktop_shell_cursor cursor)
278 {
279         struct desktop_shell *shell = shsurf->shell;
280
281         popup_grab_end(pointer);
282
283         grab->grab.interface = interface;
284         grab->shsurf = shsurf;
285         grab->shsurf_destroy_listener.notify = destroy_shell_grab_shsurf;
286         wl_signal_add(&shsurf->resource.destroy_signal,
287                       &grab->shsurf_destroy_listener);
288
289         grab->pointer = pointer;
290         grab->grab.focus = &shsurf->surface->surface;
291
292         wl_pointer_start_grab(pointer, &grab->grab);
293         desktop_shell_send_grab_cursor(shell->child.desktop_shell, cursor);
294         wl_pointer_set_focus(pointer, &shell->grab_surface->surface,
295                              wl_fixed_from_int(0), wl_fixed_from_int(0));
296 }
297
298 static void
299 shell_grab_end(struct shell_grab *grab)
300 {
301         if (grab->shsurf)
302                 wl_list_remove(&grab->shsurf_destroy_listener.link);
303
304         wl_pointer_end_grab(grab->pointer);
305 }
306
307 static void
308 center_on_output(struct weston_surface *surface,
309                  struct weston_output *output);
310
311 static enum weston_keyboard_modifier
312 get_modifier(char *modifier)
313 {
314         if (!modifier)
315                 return MODIFIER_SUPER;
316
317         if (!strcmp("ctrl", modifier))
318                 return MODIFIER_CTRL;
319         else if (!strcmp("alt", modifier))
320                 return MODIFIER_ALT;
321         else if (!strcmp("super", modifier))
322                 return MODIFIER_SUPER;
323         else
324                 return MODIFIER_SUPER;
325 }
326
327 static enum animation_type
328 get_animation_type(char *animation)
329 {
330         if (!animation)
331                 return ANIMATION_NONE;
332
333         if (!strcmp("zoom", animation))
334                 return ANIMATION_ZOOM;
335         else if (!strcmp("fade", animation))
336                 return ANIMATION_FADE;
337         else
338                 return ANIMATION_NONE;
339 }
340
341 static void
342 shell_configuration(struct desktop_shell *shell)
343 {
344         char *config_file;
345         char *path = NULL;
346         int duration = 60;
347         unsigned int num_workspaces = DEFAULT_NUM_WORKSPACES;
348         char *modifier = NULL;
349         char *win_animation = NULL;
350
351         struct config_key shell_keys[] = {
352                 { "binding-modifier",   CONFIG_KEY_STRING, &modifier },
353                 { "animation",          CONFIG_KEY_STRING, &win_animation},
354                 { "num-workspaces",
355                         CONFIG_KEY_UNSIGNED_INTEGER, &num_workspaces },
356         };
357
358         struct config_key saver_keys[] = {
359                 { "path",       CONFIG_KEY_STRING,  &path },
360                 { "duration",   CONFIG_KEY_INTEGER, &duration },
361         };
362
363         struct config_section cs[] = {
364                 { "shell", shell_keys, ARRAY_LENGTH(shell_keys), NULL },
365                 { "screensaver", saver_keys, ARRAY_LENGTH(saver_keys), NULL },
366         };
367
368         config_file = config_file_path("weston.ini");
369         parse_config_file(config_file, cs, ARRAY_LENGTH(cs), shell);
370         free(config_file);
371
372         shell->screensaver.path = path;
373         shell->screensaver.duration = duration;
374         shell->binding_modifier = get_modifier(modifier);
375         shell->win_animation_type = get_animation_type(win_animation);
376         shell->workspaces.num = num_workspaces > 0 ? num_workspaces : 1;
377 }
378
379 static void
380 focus_state_destroy(struct focus_state *state)
381 {
382         wl_list_remove(&state->seat_destroy_listener.link);
383         wl_list_remove(&state->surface_destroy_listener.link);
384         free(state);
385 }
386
387 static void
388 focus_state_seat_destroy(struct wl_listener *listener, void *data)
389 {
390         struct focus_state *state = container_of(listener,
391                                                  struct focus_state,
392                                                  seat_destroy_listener);
393
394         wl_list_remove(&state->link);
395         focus_state_destroy(state);
396 }
397
398 static void
399 focus_state_surface_destroy(struct wl_listener *listener, void *data)
400 {
401         struct focus_state *state = container_of(listener,
402                                                  struct focus_state,
403                                                  surface_destroy_listener);
404         struct desktop_shell *shell;
405         struct weston_surface *surface, *next;
406
407         next = NULL;
408         wl_list_for_each(surface, &state->ws->layer.surface_list, layer_link) {
409                 if (surface == state->keyboard_focus)
410                         continue;
411
412                 next = surface;
413                 break;
414         }
415
416         if (next) {
417                 shell = state->seat->compositor->shell_interface.shell;
418                 activate(shell, next, state->seat);
419         } else {
420                 wl_list_remove(&state->link);
421                 focus_state_destroy(state);
422         }
423 }
424
425 static struct focus_state *
426 focus_state_create(struct weston_seat *seat, struct workspace *ws)
427 {
428         struct focus_state *state;
429
430         state = malloc(sizeof *state);
431         if (state == NULL)
432                 return NULL;
433
434         state->ws = ws;
435         state->seat = seat;
436         wl_list_insert(&ws->focus_list, &state->link);
437
438         state->seat_destroy_listener.notify = focus_state_seat_destroy;
439         state->surface_destroy_listener.notify = focus_state_surface_destroy;
440         wl_signal_add(&seat->seat.destroy_signal,
441                       &state->seat_destroy_listener);
442         wl_list_init(&state->surface_destroy_listener.link);
443
444         return state;
445 }
446
447 static struct focus_state *
448 ensure_focus_state(struct desktop_shell *shell, struct weston_seat *seat)
449 {
450         struct workspace *ws = get_current_workspace(shell);
451         struct focus_state *state;
452
453         wl_list_for_each(state, &ws->focus_list, link)
454                 if (state->seat == seat)
455                         break;
456
457         if (&state->link == &ws->focus_list)
458                 state = focus_state_create(seat, ws);
459
460         return state;
461 }
462
463 static void
464 restore_focus_state(struct desktop_shell *shell, struct workspace *ws)
465 {
466         struct focus_state *state, *next;
467         struct wl_surface *surface;
468
469         wl_list_for_each_safe(state, next, &ws->focus_list, link) {
470                 surface = state->keyboard_focus ?
471                         &state->keyboard_focus->surface : NULL;
472
473                 wl_keyboard_set_focus(state->seat->seat.keyboard, surface);
474         }
475 }
476
477 static void
478 replace_focus_state(struct desktop_shell *shell, struct workspace *ws,
479                     struct weston_seat *seat)
480 {
481         struct focus_state *state;
482         struct wl_surface *surface;
483
484         wl_list_for_each(state, &ws->focus_list, link) {
485                 if (state->seat == seat) {
486                         surface = seat->seat.keyboard->focus;
487                         state->keyboard_focus =
488                                 (struct weston_surface *) surface;
489                         return;
490                 }
491         }
492 }
493
494 static void
495 drop_focus_state(struct desktop_shell *shell, struct workspace *ws,
496                  struct weston_surface *surface)
497 {
498         struct focus_state *state;
499
500         wl_list_for_each(state, &ws->focus_list, link)
501                 if (state->keyboard_focus == surface)
502                         state->keyboard_focus = NULL;
503 }
504
505 static void
506 workspace_destroy(struct workspace *ws)
507 {
508         struct focus_state *state, *next;
509
510         wl_list_for_each_safe(state, next, &ws->focus_list, link)
511                 focus_state_destroy(state);
512
513         free(ws);
514 }
515
516 static void
517 seat_destroyed(struct wl_listener *listener, void *data)
518 {
519         struct weston_seat *seat = data;
520         struct focus_state *state, *next;
521         struct workspace *ws = container_of(listener,
522                                             struct workspace,
523                                             seat_destroyed_listener);
524
525         wl_list_for_each_safe(state, next, &ws->focus_list, link)
526                 if (state->seat == seat)
527                         wl_list_remove(&state->link);
528 }
529
530 static struct workspace *
531 workspace_create(void)
532 {
533         struct workspace *ws = malloc(sizeof *ws);
534         if (ws == NULL)
535                 return NULL;
536
537         weston_layer_init(&ws->layer, NULL);
538
539         wl_list_init(&ws->focus_list);
540         wl_list_init(&ws->seat_destroyed_listener.link);
541         ws->seat_destroyed_listener.notify = seat_destroyed;
542
543         return ws;
544 }
545
546 static int
547 workspace_is_empty(struct workspace *ws)
548 {
549         return wl_list_empty(&ws->layer.surface_list);
550 }
551
552 static struct workspace *
553 get_workspace(struct desktop_shell *shell, unsigned int index)
554 {
555         struct workspace **pws = shell->workspaces.array.data;
556         assert(index < shell->workspaces.num);
557         pws += index;
558         return *pws;
559 }
560
561 static struct workspace *
562 get_current_workspace(struct desktop_shell *shell)
563 {
564         return get_workspace(shell, shell->workspaces.current);
565 }
566
567 static void
568 activate_workspace(struct desktop_shell *shell, unsigned int index)
569 {
570         struct workspace *ws;
571
572         ws = get_workspace(shell, index);
573         wl_list_insert(&shell->panel_layer.link, &ws->layer.link);
574
575         shell->workspaces.current = index;
576 }
577
578 static unsigned int
579 get_output_height(struct weston_output *output)
580 {
581         return abs(output->region.extents.y1 - output->region.extents.y2);
582 }
583
584 static void
585 surface_translate(struct weston_surface *surface, double d)
586 {
587         struct shell_surface *shsurf = get_shell_surface(surface);
588         struct weston_transform *transform;
589
590         transform = &shsurf->workspace_transform;
591         if (wl_list_empty(&transform->link))
592                 wl_list_insert(surface->geometry.transformation_list.prev,
593                                &shsurf->workspace_transform.link);
594
595         weston_matrix_init(&shsurf->workspace_transform.matrix);
596         weston_matrix_translate(&shsurf->workspace_transform.matrix,
597                                 0.0, d, 0.0);
598         surface->geometry.dirty = 1;
599 }
600
601 static void
602 workspace_translate_out(struct workspace *ws, double fraction)
603 {
604         struct weston_surface *surface;
605         unsigned int height;
606         double d;
607
608         wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
609                 height = get_output_height(surface->output);
610                 d = height * fraction;
611
612                 surface_translate(surface, d);
613         }
614 }
615
616 static void
617 workspace_translate_in(struct workspace *ws, double fraction)
618 {
619         struct weston_surface *surface;
620         unsigned int height;
621         double d;
622
623         wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
624                 height = get_output_height(surface->output);
625
626                 if (fraction > 0)
627                         d = -(height - height * fraction);
628                 else
629                         d = height + height * fraction;
630
631                 surface_translate(surface, d);
632         }
633 }
634
635 static void
636 broadcast_current_workspace_state(struct desktop_shell *shell)
637 {
638         struct wl_resource *resource;
639
640         wl_list_for_each(resource, &shell->workspaces.client_list, link)
641                 workspace_manager_send_state(resource,
642                                              shell->workspaces.current,
643                                              shell->workspaces.num);
644 }
645
646 static void
647 reverse_workspace_change_animation(struct desktop_shell *shell,
648                                    unsigned int index,
649                                    struct workspace *from,
650                                    struct workspace *to)
651 {
652         shell->workspaces.current = index;
653
654         shell->workspaces.anim_to = to;
655         shell->workspaces.anim_from = from;
656         shell->workspaces.anim_dir = -1 * shell->workspaces.anim_dir;
657         shell->workspaces.anim_timestamp = 0;
658
659         weston_compositor_schedule_repaint(shell->compositor);
660 }
661
662 static void
663 workspace_deactivate_transforms(struct workspace *ws)
664 {
665         struct weston_surface *surface;
666         struct shell_surface *shsurf;
667
668         wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
669                 shsurf = get_shell_surface(surface);
670                 if (!wl_list_empty(&shsurf->workspace_transform.link)) {
671                         wl_list_remove(&shsurf->workspace_transform.link);
672                         wl_list_init(&shsurf->workspace_transform.link);
673                 }
674                 shsurf->surface->geometry.dirty = 1;
675         }
676 }
677
678 static void
679 finish_workspace_change_animation(struct desktop_shell *shell,
680                                   struct workspace *from,
681                                   struct workspace *to)
682 {
683         weston_compositor_schedule_repaint(shell->compositor);
684
685         wl_list_remove(&shell->workspaces.animation.link);
686         workspace_deactivate_transforms(from);
687         workspace_deactivate_transforms(to);
688         shell->workspaces.anim_to = NULL;
689
690         wl_list_remove(&shell->workspaces.anim_from->layer.link);
691 }
692
693 static void
694 animate_workspace_change_frame(struct weston_animation *animation,
695                                struct weston_output *output, uint32_t msecs)
696 {
697         struct desktop_shell *shell =
698                 container_of(animation, struct desktop_shell,
699                              workspaces.animation);
700         struct workspace *from = shell->workspaces.anim_from;
701         struct workspace *to = shell->workspaces.anim_to;
702         uint32_t t;
703         double x, y;
704
705         if (workspace_is_empty(from) && workspace_is_empty(to)) {
706                 finish_workspace_change_animation(shell, from, to);
707                 return;
708         }
709
710         if (shell->workspaces.anim_timestamp == 0) {
711                 if (shell->workspaces.anim_current == 0.0)
712                         shell->workspaces.anim_timestamp = msecs;
713                 else
714                         shell->workspaces.anim_timestamp =
715                                 msecs -
716                                 /* Invers of movement function 'y' below. */
717                                 (asin(1.0 - shell->workspaces.anim_current) *
718                                  DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH *
719                                  M_2_PI);
720         }
721
722         t = msecs - shell->workspaces.anim_timestamp;
723
724         /*
725          * x = [0, π/2]
726          * y(x) = sin(x)
727          */
728         x = t * (1.0/DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH) * M_PI_2;
729         y = sin(x);
730
731         if (t < DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH) {
732                 weston_compositor_schedule_repaint(shell->compositor);
733
734                 workspace_translate_out(from, shell->workspaces.anim_dir * y);
735                 workspace_translate_in(to, shell->workspaces.anim_dir * y);
736                 shell->workspaces.anim_current = y;
737
738                 weston_compositor_schedule_repaint(shell->compositor);
739         }
740         else
741                 finish_workspace_change_animation(shell, from, to);
742 }
743
744 static void
745 animate_workspace_change(struct desktop_shell *shell,
746                          unsigned int index,
747                          struct workspace *from,
748                          struct workspace *to)
749 {
750         struct weston_output *output;
751
752         int dir;
753
754         if (index > shell->workspaces.current)
755                 dir = -1;
756         else
757                 dir = 1;
758
759         shell->workspaces.current = index;
760
761         shell->workspaces.anim_dir = dir;
762         shell->workspaces.anim_from = from;
763         shell->workspaces.anim_to = to;
764         shell->workspaces.anim_current = 0.0;
765         shell->workspaces.anim_timestamp = 0;
766
767         output = container_of(shell->compositor->output_list.next,
768                               struct weston_output, link);
769         wl_list_insert(&output->animation_list,
770                        &shell->workspaces.animation.link);
771
772         wl_list_insert(from->layer.link.prev, &to->layer.link);
773
774         workspace_translate_in(to, 0);
775
776         restore_focus_state(shell, to);
777
778         weston_compositor_schedule_repaint(shell->compositor);
779 }
780
781 static void
782 update_workspace(struct desktop_shell *shell, unsigned int index,
783                  struct workspace *from, struct workspace *to)
784 {
785         shell->workspaces.current = index;
786         wl_list_insert(&from->layer.link, &to->layer.link);
787         wl_list_remove(&from->layer.link);
788 }
789
790 static void
791 change_workspace(struct desktop_shell *shell, unsigned int index)
792 {
793         struct workspace *from;
794         struct workspace *to;
795
796         if (index == shell->workspaces.current)
797                 return;
798
799         /* Don't change workspace when there is any fullscreen surfaces. */
800         if (!wl_list_empty(&shell->fullscreen_layer.surface_list))
801                 return;
802
803         from = get_current_workspace(shell);
804         to = get_workspace(shell, index);
805
806         if (shell->workspaces.anim_from == to &&
807             shell->workspaces.anim_to == from) {
808                 restore_focus_state(shell, to);
809                 reverse_workspace_change_animation(shell, index, from, to);
810                 broadcast_current_workspace_state(shell);
811                 return;
812         }
813
814         if (shell->workspaces.anim_to != NULL)
815                 finish_workspace_change_animation(shell,
816                                                   shell->workspaces.anim_from,
817                                                   shell->workspaces.anim_to);
818
819         restore_focus_state(shell, to);
820
821         if (workspace_is_empty(to) && workspace_is_empty(from))
822                 update_workspace(shell, index, from, to);
823         else
824                 animate_workspace_change(shell, index, from, to);
825
826         broadcast_current_workspace_state(shell);
827 }
828
829 static bool
830 workspace_has_only(struct workspace *ws, struct weston_surface *surface)
831 {
832         struct wl_list *list = &ws->layer.surface_list;
833         struct wl_list *e;
834
835         if (wl_list_empty(list))
836                 return false;
837
838         e = list->next;
839
840         if (e->next != list)
841                 return false;
842
843         return container_of(e, struct weston_surface, layer_link) == surface;
844 }
845
846 static void
847 move_surface_to_workspace(struct desktop_shell *shell,
848                           struct weston_surface *surface,
849                           uint32_t workspace)
850 {
851         struct workspace *from;
852         struct workspace *to;
853         struct weston_seat *seat;
854
855         if (workspace == shell->workspaces.current)
856                 return;
857
858         if (workspace >= shell->workspaces.num)
859                 workspace = shell->workspaces.num - 1;
860
861         from = get_current_workspace(shell);
862         to = get_workspace(shell, workspace);
863
864         wl_list_remove(&surface->layer_link);
865         wl_list_insert(&to->layer.surface_list, &surface->layer_link);
866
867         drop_focus_state(shell, from, surface);
868         wl_list_for_each(seat, &shell->compositor->seat_list, link)
869                 if (seat->has_keyboard &&
870                     seat->keyboard.focus == &surface->surface)
871                         wl_keyboard_set_focus(&seat->keyboard, NULL);
872
873         weston_surface_damage_below(surface);
874 }
875
876 static void
877 take_surface_to_workspace_by_seat(struct desktop_shell *shell,
878                                   struct wl_seat *wl_seat,
879                                   unsigned int index)
880 {
881         struct weston_seat *seat = (struct weston_seat *) wl_seat;
882         struct weston_surface *surface =
883                 (struct weston_surface *) wl_seat->keyboard->focus;
884         struct shell_surface *shsurf;
885         struct workspace *from;
886         struct workspace *to;
887         struct focus_state *state;
888
889         if (surface == NULL ||
890             index == shell->workspaces.current)
891                 return;
892
893         from = get_current_workspace(shell);
894         to = get_workspace(shell, index);
895
896         wl_list_remove(&surface->layer_link);
897         wl_list_insert(&to->layer.surface_list, &surface->layer_link);
898
899         replace_focus_state(shell, to, seat);
900         drop_focus_state(shell, from, surface);
901
902         if (shell->workspaces.anim_from == to &&
903             shell->workspaces.anim_to == from) {
904                 wl_list_remove(&to->layer.link);
905                 wl_list_insert(from->layer.link.prev, &to->layer.link);
906
907                 reverse_workspace_change_animation(shell, index, from, to);
908                 broadcast_current_workspace_state(shell);
909
910                 return;
911         }
912
913         if (shell->workspaces.anim_to != NULL)
914                 finish_workspace_change_animation(shell,
915                                                   shell->workspaces.anim_from,
916                                                   shell->workspaces.anim_to);
917
918         if (workspace_is_empty(from) &&
919             workspace_has_only(to, surface))
920                 update_workspace(shell, index, from, to);
921         else {
922                 shsurf = get_shell_surface(surface);
923                 if (wl_list_empty(&shsurf->workspace_transform.link))
924                         wl_list_insert(&shell->workspaces.anim_sticky_list,
925                                        &shsurf->workspace_transform.link);
926
927                 animate_workspace_change(shell, index, from, to);
928         }
929
930         broadcast_current_workspace_state(shell);
931
932         state = ensure_focus_state(shell, seat);
933         if (state != NULL)
934                 state->keyboard_focus = surface;
935 }
936
937 static void
938 workspace_manager_move_surface(struct wl_client *client,
939                                struct wl_resource *resource,
940                                struct wl_resource *surface_resource,
941                                uint32_t workspace)
942 {
943         struct desktop_shell *shell = resource->data;
944         struct weston_surface *surface =
945                 (struct weston_surface *) surface_resource;
946
947         move_surface_to_workspace(shell, surface, workspace);
948 }
949
950 static const struct workspace_manager_interface workspace_manager_implementation = {
951         workspace_manager_move_surface,
952 };
953
954 static void
955 unbind_resource(struct wl_resource *resource)
956 {
957         wl_list_remove(&resource->link);
958         free(resource);
959 }
960
961 static void
962 bind_workspace_manager(struct wl_client *client,
963                        void *data, uint32_t version, uint32_t id)
964 {
965         struct desktop_shell *shell = data;
966         struct wl_resource *resource;
967
968         resource = wl_client_add_object(client, &workspace_manager_interface,
969                                         &workspace_manager_implementation,
970                                         id, shell);
971
972         if (resource == NULL) {
973                 weston_log("couldn't add workspace manager object");
974                 return;
975         }
976
977         resource->destroy = unbind_resource;
978         wl_list_insert(&shell->workspaces.client_list, &resource->link);
979
980         workspace_manager_send_state(resource,
981                                      shell->workspaces.current,
982                                      shell->workspaces.num);
983 }
984
985 static void
986 noop_grab_focus(struct wl_pointer_grab *grab,
987                 struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y)
988 {
989         grab->focus = NULL;
990 }
991
992 static void
993 move_grab_motion(struct wl_pointer_grab *grab,
994                  uint32_t time, wl_fixed_t x, wl_fixed_t y)
995 {
996         struct weston_move_grab *move = (struct weston_move_grab *) grab;
997         struct wl_pointer *pointer = grab->pointer;
998         struct shell_surface *shsurf = move->base.shsurf;
999         struct weston_surface *es;
1000         int dx = wl_fixed_to_int(pointer->x + move->dx);
1001         int dy = wl_fixed_to_int(pointer->y + move->dy);
1002
1003         if (!shsurf)
1004                 return;
1005
1006         es = shsurf->surface;
1007
1008         weston_surface_configure(es, dx, dy,
1009                                  es->geometry.width, es->geometry.height);
1010
1011         weston_compositor_schedule_repaint(es->compositor);
1012 }
1013
1014 static void
1015 move_grab_button(struct wl_pointer_grab *grab,
1016                  uint32_t time, uint32_t button, uint32_t state_w)
1017 {
1018         struct shell_grab *shell_grab = container_of(grab, struct shell_grab,
1019                                                     grab);
1020         struct wl_pointer *pointer = grab->pointer;
1021         enum wl_pointer_button_state state = state_w;
1022
1023         if (pointer->button_count == 0 &&
1024             state == WL_POINTER_BUTTON_STATE_RELEASED) {
1025                 shell_grab_end(shell_grab);
1026                 free(grab);
1027         }
1028 }
1029
1030 static const struct wl_pointer_grab_interface move_grab_interface = {
1031         noop_grab_focus,
1032         move_grab_motion,
1033         move_grab_button,
1034 };
1035
1036 static int
1037 surface_move(struct shell_surface *shsurf, struct weston_seat *ws)
1038 {
1039         struct weston_move_grab *move;
1040
1041         if (!shsurf)
1042                 return -1;
1043
1044         if (shsurf->type == SHELL_SURFACE_FULLSCREEN)
1045                 return 0;
1046
1047         move = malloc(sizeof *move);
1048         if (!move)
1049                 return -1;
1050
1051         move->dx = wl_fixed_from_double(shsurf->surface->geometry.x) -
1052                         ws->seat.pointer->grab_x;
1053         move->dy = wl_fixed_from_double(shsurf->surface->geometry.y) -
1054                         ws->seat.pointer->grab_y;
1055
1056         shell_grab_start(&move->base, &move_grab_interface, shsurf,
1057                          ws->seat.pointer, DESKTOP_SHELL_CURSOR_MOVE);
1058
1059         return 0;
1060 }
1061
1062 static void
1063 shell_surface_move(struct wl_client *client, struct wl_resource *resource,
1064                    struct wl_resource *seat_resource, uint32_t serial)
1065 {
1066         struct weston_seat *ws = seat_resource->data;
1067         struct shell_surface *shsurf = resource->data;
1068
1069         if (ws->seat.pointer->button_count == 0 ||
1070             ws->seat.pointer->grab_serial != serial ||
1071             ws->seat.pointer->focus != &shsurf->surface->surface)
1072                 return;
1073
1074         if (surface_move(shsurf, ws) < 0)
1075                 wl_resource_post_no_memory(resource);
1076 }
1077
1078 struct weston_resize_grab {
1079         struct shell_grab base;
1080         uint32_t edges;
1081         int32_t width, height;
1082 };
1083
1084 static void
1085 resize_grab_motion(struct wl_pointer_grab *grab,
1086                    uint32_t time, wl_fixed_t x, wl_fixed_t y)
1087 {
1088         struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
1089         struct wl_pointer *pointer = grab->pointer;
1090         struct shell_surface *shsurf = resize->base.shsurf;
1091         int32_t width, height;
1092         wl_fixed_t from_x, from_y;
1093         wl_fixed_t to_x, to_y;
1094
1095         if (!shsurf)
1096                 return;
1097
1098         weston_surface_from_global_fixed(shsurf->surface,
1099                                          pointer->grab_x, pointer->grab_y,
1100                                          &from_x, &from_y);
1101         weston_surface_from_global_fixed(shsurf->surface,
1102                                          pointer->x, pointer->y, &to_x, &to_y);
1103
1104         width = resize->width;
1105         if (resize->edges & WL_SHELL_SURFACE_RESIZE_LEFT) {
1106                 width += wl_fixed_to_int(from_x - to_x);
1107         } else if (resize->edges & WL_SHELL_SURFACE_RESIZE_RIGHT) {
1108                 width += wl_fixed_to_int(to_x - from_x);
1109         }
1110
1111         height = resize->height;
1112         if (resize->edges & WL_SHELL_SURFACE_RESIZE_TOP) {
1113                 height += wl_fixed_to_int(from_y - to_y);
1114         } else if (resize->edges & WL_SHELL_SURFACE_RESIZE_BOTTOM) {
1115                 height += wl_fixed_to_int(to_y - from_y);
1116         }
1117
1118         shsurf->client->send_configure(shsurf->surface,
1119                                        resize->edges, width, height);
1120 }
1121
1122 static void
1123 send_configure(struct weston_surface *surface,
1124                uint32_t edges, int32_t width, int32_t height)
1125 {
1126         struct shell_surface *shsurf = get_shell_surface(surface);
1127
1128         wl_shell_surface_send_configure(&shsurf->resource,
1129                                         edges, width, height);
1130 }
1131
1132 static const struct weston_shell_client shell_client = {
1133         send_configure
1134 };
1135
1136 static void
1137 resize_grab_button(struct wl_pointer_grab *grab,
1138                    uint32_t time, uint32_t button, uint32_t state_w)
1139 {
1140         struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
1141         struct wl_pointer *pointer = grab->pointer;
1142         enum wl_pointer_button_state state = state_w;
1143
1144         if (pointer->button_count == 0 &&
1145             state == WL_POINTER_BUTTON_STATE_RELEASED) {
1146                 shell_grab_end(&resize->base);
1147                 free(grab);
1148         }
1149 }
1150
1151 static const struct wl_pointer_grab_interface resize_grab_interface = {
1152         noop_grab_focus,
1153         resize_grab_motion,
1154         resize_grab_button,
1155 };
1156
1157 static int
1158 surface_resize(struct shell_surface *shsurf,
1159                struct weston_seat *ws, uint32_t edges)
1160 {
1161         struct weston_resize_grab *resize;
1162
1163         if (shsurf->type == SHELL_SURFACE_FULLSCREEN)
1164                 return 0;
1165
1166         if (edges == 0 || edges > 15 ||
1167             (edges & 3) == 3 || (edges & 12) == 12)
1168                 return 0;
1169
1170         resize = malloc(sizeof *resize);
1171         if (!resize)
1172                 return -1;
1173
1174         resize->edges = edges;
1175         resize->width = shsurf->surface->geometry.width;
1176         resize->height = shsurf->surface->geometry.height;
1177
1178         shell_grab_start(&resize->base, &resize_grab_interface, shsurf,
1179                          ws->seat.pointer, edges);
1180
1181         return 0;
1182 }
1183
1184 static void
1185 shell_surface_resize(struct wl_client *client, struct wl_resource *resource,
1186                      struct wl_resource *seat_resource, uint32_t serial,
1187                      uint32_t edges)
1188 {
1189         struct weston_seat *ws = seat_resource->data;
1190         struct shell_surface *shsurf = resource->data;
1191
1192         if (shsurf->type == SHELL_SURFACE_FULLSCREEN)
1193                 return;
1194
1195         if (ws->seat.pointer->button_count == 0 ||
1196             ws->seat.pointer->grab_serial != serial ||
1197             ws->seat.pointer->focus != &shsurf->surface->surface)
1198                 return;
1199
1200         if (surface_resize(shsurf, ws, edges) < 0)
1201                 wl_resource_post_no_memory(resource);
1202 }
1203
1204 static void
1205 busy_cursor_grab_focus(struct wl_pointer_grab *base,
1206                        struct wl_surface *surface, int32_t x, int32_t y)
1207 {
1208         struct shell_grab *grab = (struct shell_grab *) base;
1209
1210         if (grab->grab.focus != surface) {
1211                 shell_grab_end(grab);
1212                 free(grab);
1213         }
1214 }
1215
1216 static void
1217 busy_cursor_grab_motion(struct wl_pointer_grab *grab,
1218                         uint32_t time, int32_t x, int32_t y)
1219 {
1220 }
1221
1222 static void
1223 busy_cursor_grab_button(struct wl_pointer_grab *base,
1224                         uint32_t time, uint32_t button, uint32_t state)
1225 {
1226         struct shell_grab *grab = (struct shell_grab *) base;
1227         struct shell_surface *shsurf;
1228         struct weston_surface *surface = 
1229                 (struct weston_surface *) grab->grab.pointer->current;
1230         struct weston_seat *seat =
1231                 (struct weston_seat *) grab->grab.pointer->seat;
1232
1233         shsurf = get_shell_surface(surface);
1234         if (shsurf && button == BTN_LEFT && state) {
1235                 activate(shsurf->shell, shsurf->surface, seat);
1236                 surface_move(shsurf, seat);
1237         }
1238 }
1239
1240 static const struct wl_pointer_grab_interface busy_cursor_grab_interface = {
1241         busy_cursor_grab_focus,
1242         busy_cursor_grab_motion,
1243         busy_cursor_grab_button,
1244 };
1245
1246 static void
1247 set_busy_cursor(struct shell_surface *shsurf, struct wl_pointer *pointer)
1248 {
1249         struct shell_grab *grab;
1250
1251         grab = malloc(sizeof *grab);
1252         if (!grab)
1253                 return;
1254
1255         shell_grab_start(grab, &busy_cursor_grab_interface, shsurf, pointer,
1256                          DESKTOP_SHELL_CURSOR_BUSY);
1257 }
1258
1259 static void
1260 end_busy_cursor(struct shell_surface *shsurf, struct wl_pointer *pointer)
1261 {
1262         struct shell_grab *grab = (struct shell_grab *) pointer->grab;
1263
1264         if (grab->grab.interface == &busy_cursor_grab_interface) {
1265                 shell_grab_end(grab);
1266                 free(grab);
1267         }
1268 }
1269
1270 static void
1271 ping_timer_destroy(struct shell_surface *shsurf)
1272 {
1273         if (!shsurf || !shsurf->ping_timer)
1274                 return;
1275
1276         if (shsurf->ping_timer->source)
1277                 wl_event_source_remove(shsurf->ping_timer->source);
1278
1279         free(shsurf->ping_timer);
1280         shsurf->ping_timer = NULL;
1281 }
1282
1283 static int
1284 ping_timeout_handler(void *data)
1285 {
1286         struct shell_surface *shsurf = data;
1287         struct weston_seat *seat;
1288
1289         /* Client is not responding */
1290         shsurf->unresponsive = 1;
1291
1292         wl_list_for_each(seat, &shsurf->surface->compositor->seat_list, link)
1293                 if (seat->seat.pointer->focus == &shsurf->surface->surface)
1294                         set_busy_cursor(shsurf, seat->seat.pointer);
1295
1296         return 1;
1297 }
1298
1299 static void
1300 ping_handler(struct weston_surface *surface, uint32_t serial)
1301 {
1302         struct shell_surface *shsurf = get_shell_surface(surface);
1303         struct wl_event_loop *loop;
1304         int ping_timeout = 200;
1305
1306         if (!shsurf)
1307                 return;
1308         if (!shsurf->resource.client)
1309                 return;
1310
1311         if (shsurf->surface == shsurf->shell->grab_surface)
1312                 return;
1313
1314         if (!shsurf->ping_timer) {
1315                 shsurf->ping_timer = malloc(sizeof *shsurf->ping_timer);
1316                 if (!shsurf->ping_timer)
1317                         return;
1318
1319                 shsurf->ping_timer->serial = serial;
1320                 loop = wl_display_get_event_loop(surface->compositor->wl_display);
1321                 shsurf->ping_timer->source =
1322                         wl_event_loop_add_timer(loop, ping_timeout_handler, shsurf);
1323                 wl_event_source_timer_update(shsurf->ping_timer->source, ping_timeout);
1324
1325                 wl_shell_surface_send_ping(&shsurf->resource, serial);
1326         }
1327 }
1328
1329 static void
1330 handle_pointer_focus(struct wl_listener *listener, void *data)
1331 {
1332         struct wl_pointer *pointer = data;
1333         struct weston_surface *surface =
1334                 (struct weston_surface *) pointer->focus;
1335         struct weston_compositor *compositor;
1336         struct shell_surface *shsurf;
1337         uint32_t serial;
1338
1339         if (!surface)
1340                 return;
1341
1342         compositor = surface->compositor;
1343         shsurf = get_shell_surface(surface);
1344
1345         if (shsurf && shsurf->unresponsive) {
1346                 set_busy_cursor(shsurf, pointer);
1347         } else {
1348                 serial = wl_display_next_serial(compositor->wl_display);
1349                 ping_handler(surface, serial);
1350         }
1351 }
1352
1353 static void
1354 create_pointer_focus_listener(struct weston_seat *seat)
1355 {
1356         struct wl_listener *listener;
1357
1358         if (!seat->seat.pointer)
1359                 return;
1360
1361         listener = malloc(sizeof *listener);
1362         listener->notify = handle_pointer_focus;
1363         wl_signal_add(&seat->seat.pointer->focus_signal, listener);
1364 }
1365
1366 static void
1367 shell_surface_pong(struct wl_client *client, struct wl_resource *resource,
1368                                                         uint32_t serial)
1369 {
1370         struct shell_surface *shsurf = resource->data;
1371         struct desktop_shell *shell = shsurf->shell;
1372         struct weston_seat *seat;
1373         struct weston_compositor *ec = shsurf->surface->compositor;
1374         struct wl_pointer *pointer;
1375         int was_unresponsive;
1376
1377         if (shsurf->ping_timer == NULL)
1378                 /* Just ignore unsolicited pong. */
1379                 return;
1380
1381         if (shsurf->ping_timer->serial == serial) {
1382                 was_unresponsive = shsurf->unresponsive;
1383                 shsurf->unresponsive = 0;
1384                 if (was_unresponsive) {
1385                         /* Received pong from previously unresponsive client */
1386                         wl_list_for_each(seat, &ec->seat_list, link) {
1387                                 pointer = seat->seat.pointer;
1388                                 if (pointer->focus ==
1389                                     &shell->grab_surface->surface &&
1390                                     pointer->current ==
1391                                     &shsurf->surface->surface)
1392                                         end_busy_cursor(shsurf, pointer);
1393                         }
1394                 }
1395                 ping_timer_destroy(shsurf);
1396         }
1397 }
1398
1399 static void
1400 shell_surface_set_title(struct wl_client *client,
1401                         struct wl_resource *resource, const char *title)
1402 {
1403         struct shell_surface *shsurf = resource->data;
1404
1405         free(shsurf->title);
1406         shsurf->title = strdup(title);
1407 }
1408
1409 static void
1410 shell_surface_set_class(struct wl_client *client,
1411                         struct wl_resource *resource, const char *class)
1412 {
1413         struct shell_surface *shsurf = resource->data;
1414
1415         free(shsurf->class);
1416         shsurf->class = strdup(class);
1417 }
1418
1419 static struct weston_output *
1420 get_default_output(struct weston_compositor *compositor)
1421 {
1422         return container_of(compositor->output_list.next,
1423                             struct weston_output, link);
1424 }
1425
1426 static void
1427 shell_unset_fullscreen(struct shell_surface *shsurf)
1428 {
1429         struct workspace *ws;
1430         /* undo all fullscreen things here */
1431         if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
1432             shell_surface_is_top_fullscreen(shsurf)) {
1433                 weston_output_switch_mode(shsurf->fullscreen_output,
1434                                           shsurf->fullscreen_output->origin);
1435         }
1436         shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
1437         shsurf->fullscreen.framerate = 0;
1438         wl_list_remove(&shsurf->fullscreen.transform.link);
1439         wl_list_init(&shsurf->fullscreen.transform.link);
1440         if (shsurf->fullscreen.black_surface)
1441                 weston_surface_destroy(shsurf->fullscreen.black_surface);
1442         shsurf->fullscreen.black_surface = NULL;
1443         shsurf->fullscreen_output = NULL;
1444         weston_surface_set_position(shsurf->surface,
1445                                     shsurf->saved_x, shsurf->saved_y);
1446         if (shsurf->saved_rotation_valid) {
1447                 wl_list_insert(&shsurf->surface->geometry.transformation_list,
1448                                &shsurf->rotation.transform.link);
1449                 shsurf->saved_rotation_valid = false;
1450         }
1451
1452         ws = get_current_workspace(shsurf->shell);
1453         wl_list_remove(&shsurf->surface->layer_link);
1454         wl_list_insert(&ws->layer.surface_list, &shsurf->surface->layer_link);
1455 }
1456
1457 static int
1458 reset_shell_surface_type(struct shell_surface *surface)
1459 {
1460         switch (surface->type) {
1461         case SHELL_SURFACE_FULLSCREEN:
1462                 shell_unset_fullscreen(surface);
1463                 break;
1464         case SHELL_SURFACE_MAXIMIZED:
1465                 surface->output = get_default_output(surface->surface->compositor);
1466                 weston_surface_set_position(surface->surface,
1467                                             surface->saved_x,
1468                                             surface->saved_y);
1469                 break;
1470         case SHELL_SURFACE_NONE:
1471         case SHELL_SURFACE_TOPLEVEL:
1472         case SHELL_SURFACE_TRANSIENT:
1473         case SHELL_SURFACE_POPUP:
1474                 break;
1475         }
1476
1477         surface->type = SHELL_SURFACE_NONE;
1478         return 0;
1479 }
1480
1481 static void
1482 set_surface_type(struct shell_surface *shsurf)
1483 {
1484         struct weston_surface *surface = shsurf->surface;
1485         struct weston_surface *pes = shsurf->parent;
1486
1487         reset_shell_surface_type(shsurf);
1488
1489         shsurf->type = shsurf->next_type;
1490         shsurf->next_type = SHELL_SURFACE_NONE;
1491
1492         switch (shsurf->type) {
1493         case SHELL_SURFACE_TOPLEVEL:
1494                 break;
1495         case SHELL_SURFACE_TRANSIENT:
1496                 weston_surface_set_position(surface,
1497                                 pes->geometry.x + shsurf->transient.x,
1498                                 pes->geometry.y + shsurf->transient.y);
1499                 break;
1500
1501         case SHELL_SURFACE_MAXIMIZED:
1502                 shsurf->saved_x = surface->geometry.x;
1503                 shsurf->saved_y = surface->geometry.y;
1504                 shsurf->saved_position_valid = true;
1505                 break;
1506
1507         case SHELL_SURFACE_FULLSCREEN:
1508                 shsurf->saved_x = surface->geometry.x;
1509                 shsurf->saved_y = surface->geometry.y;
1510                 shsurf->saved_position_valid = true;
1511
1512                 if (!wl_list_empty(&shsurf->rotation.transform.link)) {
1513                         wl_list_remove(&shsurf->rotation.transform.link);
1514                         wl_list_init(&shsurf->rotation.transform.link);
1515                         shsurf->surface->geometry.dirty = 1;
1516                         shsurf->saved_rotation_valid = true;
1517                 }
1518                 break;
1519
1520         default:
1521                 break;
1522         }
1523 }
1524
1525 static void
1526 set_toplevel(struct shell_surface *shsurf)
1527 {
1528        shsurf->next_type = SHELL_SURFACE_TOPLEVEL;
1529 }
1530
1531 static void
1532 shell_surface_set_toplevel(struct wl_client *client,
1533                            struct wl_resource *resource)
1534 {
1535         struct shell_surface *surface = resource->data;
1536
1537         set_toplevel(surface);
1538 }
1539
1540 static void
1541 set_transient(struct shell_surface *shsurf,
1542               struct weston_surface *parent, int x, int y, uint32_t flags)
1543 {
1544         /* assign to parents output */
1545         shsurf->parent = parent;
1546         shsurf->transient.x = x;
1547         shsurf->transient.y = y;
1548         shsurf->transient.flags = flags;
1549         shsurf->next_type = SHELL_SURFACE_TRANSIENT;
1550 }
1551
1552 static void
1553 shell_surface_set_transient(struct wl_client *client,
1554                             struct wl_resource *resource,
1555                             struct wl_resource *parent_resource,
1556                             int x, int y, uint32_t flags)
1557 {
1558         struct shell_surface *shsurf = resource->data;
1559         struct weston_surface *parent = parent_resource->data;
1560
1561         set_transient(shsurf, parent, x, y, flags);
1562 }
1563
1564 static struct desktop_shell *
1565 shell_surface_get_shell(struct shell_surface *shsurf)
1566 {
1567         return shsurf->shell;
1568 }
1569
1570 static int
1571 get_output_panel_height(struct desktop_shell *shell,
1572                         struct weston_output *output)
1573 {
1574         struct weston_surface *surface;
1575         int panel_height = 0;
1576
1577         if (!output)
1578                 return 0;
1579
1580         wl_list_for_each(surface, &shell->panel_layer.surface_list, layer_link) {
1581                 if (surface->output == output) {
1582                         panel_height = surface->geometry.height;
1583                         break;
1584                 }
1585         }
1586
1587         return panel_height;
1588 }
1589
1590 static void
1591 shell_surface_set_maximized(struct wl_client *client,
1592                             struct wl_resource *resource,
1593                             struct wl_resource *output_resource )
1594 {
1595         struct shell_surface *shsurf = resource->data;
1596         struct weston_surface *es = shsurf->surface;
1597         struct desktop_shell *shell = NULL;
1598         uint32_t edges = 0, panel_height = 0;
1599
1600         /* get the default output, if the client set it as NULL
1601            check whether the ouput is available */
1602         if (output_resource)
1603                 shsurf->output = output_resource->data;
1604         else if (es->output)
1605                 shsurf->output = es->output;
1606         else
1607                 shsurf->output = get_default_output(es->compositor);
1608
1609         shell = shell_surface_get_shell(shsurf);
1610         panel_height = get_output_panel_height(shell, shsurf->output);
1611         edges = WL_SHELL_SURFACE_RESIZE_TOP|WL_SHELL_SURFACE_RESIZE_LEFT;
1612
1613         shsurf->client->send_configure(shsurf->surface, edges,
1614                                        shsurf->output->width,
1615                                        shsurf->output->height - panel_height);
1616
1617         shsurf->next_type = SHELL_SURFACE_MAXIMIZED;
1618 }
1619
1620 static void
1621 black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy);
1622
1623 static struct weston_surface *
1624 create_black_surface(struct weston_compositor *ec,
1625                      struct weston_surface *fs_surface,
1626                      float x, float y, int w, int h)
1627 {
1628         struct weston_surface *surface = NULL;
1629
1630         surface = weston_surface_create(ec);
1631         if (surface == NULL) {
1632                 weston_log("no memory\n");
1633                 return NULL;
1634         }
1635
1636         surface->configure = black_surface_configure;
1637         surface->private = fs_surface;
1638         weston_surface_configure(surface, x, y, w, h);
1639         weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1);
1640         pixman_region32_fini(&surface->opaque);
1641         pixman_region32_init_rect(&surface->opaque, 0, 0, w, h);
1642
1643         return surface;
1644 }
1645
1646 /* Create black surface and append it to the associated fullscreen surface.
1647  * Handle size dismatch and positioning according to the method. */
1648 static void
1649 shell_configure_fullscreen(struct shell_surface *shsurf)
1650 {
1651         struct weston_output *output = shsurf->fullscreen_output;
1652         struct weston_surface *surface = shsurf->surface;
1653         struct weston_matrix *matrix;
1654         float scale, output_aspect, surface_aspect, x, y;
1655
1656         if (!shsurf->fullscreen.black_surface)
1657                 shsurf->fullscreen.black_surface =
1658                         create_black_surface(surface->compositor,
1659                                              surface,
1660                                              output->x, output->y,
1661                                              output->width,
1662                                              output->height);
1663
1664         wl_list_remove(&shsurf->fullscreen.black_surface->layer_link);
1665         wl_list_insert(&surface->layer_link,
1666                        &shsurf->fullscreen.black_surface->layer_link);
1667         shsurf->fullscreen.black_surface->output = output;
1668
1669         switch (shsurf->fullscreen.type) {
1670         case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT:
1671                 if (surface->buffer)
1672                         center_on_output(surface, shsurf->fullscreen_output);
1673                 break;
1674         case WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE:
1675                 matrix = &shsurf->fullscreen.transform.matrix;
1676                 weston_matrix_init(matrix);
1677
1678                 output_aspect = (float) output->width /
1679                         (float) output->height;
1680                 surface_aspect = (float) surface->geometry.width /
1681                         (float) surface->geometry.height;
1682                 if (output_aspect < surface_aspect)
1683                         scale = (float) output->width /
1684                                 (float) surface->geometry.width;
1685                 else
1686                         scale = (float) output->height /
1687                                 (float) surface->geometry.height;
1688
1689                 weston_matrix_scale(matrix, scale, scale, 1);
1690                 wl_list_remove(&shsurf->fullscreen.transform.link);
1691                 wl_list_insert(&surface->geometry.transformation_list,
1692                                &shsurf->fullscreen.transform.link);
1693                 x = output->x + (output->width - surface->geometry.width * scale) / 2;
1694                 y = output->y + (output->height - surface->geometry.height * scale) / 2;
1695                 weston_surface_set_position(surface, x, y);
1696
1697                 break;
1698         case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER:
1699                 if (shell_surface_is_top_fullscreen(shsurf)) {
1700                         struct weston_mode mode = {0, 
1701                                 surface->geometry.width,
1702                                 surface->geometry.height,
1703                                 shsurf->fullscreen.framerate};
1704
1705                         if (weston_output_switch_mode(output, &mode) == 0) {
1706                                 weston_surface_configure(shsurf->fullscreen.black_surface, 
1707                                                          output->x, output->y,
1708                                                          output->width,
1709                                                          output->height);
1710                                 weston_surface_set_position(surface, output->x, output->y);
1711                                 break;
1712                         }
1713                 }
1714                 break;
1715         case WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL:
1716                 break;
1717         default:
1718                 break;
1719         }
1720 }
1721
1722 /* make the fullscreen and black surface at the top */
1723 static void
1724 shell_stack_fullscreen(struct shell_surface *shsurf)
1725 {
1726         struct weston_output *output = shsurf->fullscreen_output;
1727         struct weston_surface *surface = shsurf->surface;
1728         struct desktop_shell *shell = shell_surface_get_shell(shsurf);
1729
1730         wl_list_remove(&surface->layer_link);
1731         wl_list_insert(&shell->fullscreen_layer.surface_list,
1732                        &surface->layer_link);
1733         weston_surface_damage(surface);
1734
1735         if (!shsurf->fullscreen.black_surface)
1736                 shsurf->fullscreen.black_surface =
1737                         create_black_surface(surface->compositor,
1738                                              surface,
1739                                              output->x, output->y,
1740                                              output->width,
1741                                              output->height);
1742
1743         wl_list_remove(&shsurf->fullscreen.black_surface->layer_link);
1744         wl_list_insert(&surface->layer_link,
1745                        &shsurf->fullscreen.black_surface->layer_link);
1746         weston_surface_damage(shsurf->fullscreen.black_surface);
1747 }
1748
1749 static void
1750 shell_map_fullscreen(struct shell_surface *shsurf)
1751 {
1752         shell_stack_fullscreen(shsurf);
1753         shell_configure_fullscreen(shsurf);
1754 }
1755
1756 static void
1757 shell_surface_set_fullscreen(struct wl_client *client,
1758                              struct wl_resource *resource,
1759                              uint32_t method,
1760                              uint32_t framerate,
1761                              struct wl_resource *output_resource)
1762 {
1763         struct shell_surface *shsurf = resource->data;
1764         struct weston_surface *es = shsurf->surface;
1765
1766         if (output_resource)
1767                 shsurf->output = output_resource->data;
1768         else if (es->output)
1769                 shsurf->output = es->output;
1770         else
1771                 shsurf->output = get_default_output(es->compositor);
1772
1773         shsurf->fullscreen_output = shsurf->output;
1774         shsurf->fullscreen.type = method;
1775         shsurf->fullscreen.framerate = framerate;
1776         shsurf->next_type = SHELL_SURFACE_FULLSCREEN;
1777
1778         shsurf->client->send_configure(shsurf->surface, 0,
1779                                        shsurf->output->width,
1780                                        shsurf->output->height);
1781 }
1782
1783 static void
1784 popup_grab_focus(struct wl_pointer_grab *grab,
1785                  struct wl_surface *surface,
1786                  wl_fixed_t x,
1787                  wl_fixed_t y)
1788 {
1789         struct wl_pointer *pointer = grab->pointer;
1790         struct shell_surface *priv =
1791                 container_of(grab, struct shell_surface, popup.grab);
1792         struct wl_client *client = priv->surface->surface.resource.client;
1793
1794         if (surface && surface->resource.client == client) {
1795                 wl_pointer_set_focus(pointer, surface, x, y);
1796                 grab->focus = surface;
1797         } else {
1798                 wl_pointer_set_focus(pointer, NULL,
1799                                      wl_fixed_from_int(0),
1800                                      wl_fixed_from_int(0));
1801                 grab->focus = NULL;
1802         }
1803 }
1804
1805 static void
1806 popup_grab_motion(struct wl_pointer_grab *grab,
1807                   uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
1808 {
1809         struct wl_resource *resource;
1810
1811         resource = grab->pointer->focus_resource;
1812         if (resource)
1813                 wl_pointer_send_motion(resource, time, sx, sy);
1814 }
1815
1816 static void
1817 popup_grab_button(struct wl_pointer_grab *grab,
1818                   uint32_t time, uint32_t button, uint32_t state_w)
1819 {
1820         struct wl_resource *resource;
1821         struct shell_surface *shsurf =
1822                 container_of(grab, struct shell_surface, popup.grab);
1823         struct wl_display *display;
1824         enum wl_pointer_button_state state = state_w;
1825         uint32_t serial;
1826
1827         resource = grab->pointer->focus_resource;
1828         if (resource) {
1829                 display = wl_client_get_display(resource->client);
1830                 serial = wl_display_get_serial(display);
1831                 wl_pointer_send_button(resource, serial, time, button, state);
1832         } else if (state == WL_POINTER_BUTTON_STATE_RELEASED &&
1833                    (shsurf->popup.initial_up ||
1834                     time - shsurf->popup.seat->pointer->grab_time > 500)) {
1835                 popup_grab_end(grab->pointer);
1836         }
1837
1838         if (state == WL_POINTER_BUTTON_STATE_RELEASED)
1839                 shsurf->popup.initial_up = 1;
1840 }
1841
1842 static const struct wl_pointer_grab_interface popup_grab_interface = {
1843         popup_grab_focus,
1844         popup_grab_motion,
1845         popup_grab_button,
1846 };
1847
1848 static void
1849 popup_grab_end(struct wl_pointer *pointer)
1850 {
1851         struct wl_pointer_grab *grab = pointer->grab;
1852         struct shell_surface *shsurf =
1853                 container_of(grab, struct shell_surface, popup.grab);
1854
1855         if (pointer->grab->interface == &popup_grab_interface) {
1856                 wl_shell_surface_send_popup_done(&shsurf->resource);
1857                 wl_pointer_end_grab(grab->pointer);
1858                 shsurf->popup.grab.pointer = NULL;
1859         }
1860 }
1861
1862 static void
1863 shell_map_popup(struct shell_surface *shsurf)
1864 {
1865         struct wl_seat *seat = shsurf->popup.seat;
1866         struct weston_surface *es = shsurf->surface;
1867         struct weston_surface *parent = shsurf->parent;
1868
1869         es->output = parent->output;
1870         shsurf->popup.grab.interface = &popup_grab_interface;
1871
1872         weston_surface_update_transform(parent);
1873         if (parent->transform.enabled) {
1874                 shsurf->popup.parent_transform.matrix =
1875                         parent->transform.matrix;
1876         } else {
1877                 /* construct x, y translation matrix */
1878                 weston_matrix_init(&shsurf->popup.parent_transform.matrix);
1879                 shsurf->popup.parent_transform.matrix.d[12] =
1880                         parent->geometry.x;
1881                 shsurf->popup.parent_transform.matrix.d[13] =
1882                         parent->geometry.y;
1883         }
1884         wl_list_insert(es->geometry.transformation_list.prev,
1885                        &shsurf->popup.parent_transform.link);
1886
1887         shsurf->popup.initial_up = 0;
1888         weston_surface_set_position(es, shsurf->popup.x, shsurf->popup.y);
1889         weston_surface_update_transform(es);
1890
1891         /* We don't require the grab to still be active, but if another
1892          * grab has started in the meantime, we end the popup now. */
1893         if (seat->pointer->grab_serial == shsurf->popup.serial) {
1894                 wl_pointer_start_grab(seat->pointer, &shsurf->popup.grab);
1895         } else {
1896                 wl_shell_surface_send_popup_done(&shsurf->resource);
1897         }
1898 }
1899
1900 static void
1901 shell_surface_set_popup(struct wl_client *client,
1902                         struct wl_resource *resource,
1903                         struct wl_resource *seat_resource,
1904                         uint32_t serial,
1905                         struct wl_resource *parent_resource,
1906                         int32_t x, int32_t y, uint32_t flags)
1907 {
1908         struct shell_surface *shsurf = resource->data;
1909
1910         shsurf->type = SHELL_SURFACE_POPUP;
1911         shsurf->parent = parent_resource->data;
1912         shsurf->popup.seat = seat_resource->data;
1913         shsurf->popup.serial = serial;
1914         shsurf->popup.x = x;
1915         shsurf->popup.y = y;
1916 }
1917
1918 static const struct wl_shell_surface_interface shell_surface_implementation = {
1919         shell_surface_pong,
1920         shell_surface_move,
1921         shell_surface_resize,
1922         shell_surface_set_toplevel,
1923         shell_surface_set_transient,
1924         shell_surface_set_fullscreen,
1925         shell_surface_set_popup,
1926         shell_surface_set_maximized,
1927         shell_surface_set_title,
1928         shell_surface_set_class
1929 };
1930
1931 static void
1932 destroy_shell_surface(struct shell_surface *shsurf)
1933 {
1934         if (shsurf->popup.grab.pointer)
1935                 wl_pointer_end_grab(shsurf->popup.grab.pointer);
1936
1937         if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
1938             shell_surface_is_top_fullscreen(shsurf)) {
1939                 weston_output_switch_mode(shsurf->fullscreen_output,
1940                                           shsurf->fullscreen_output->origin);
1941         }
1942
1943         if (shsurf->fullscreen.black_surface)
1944                 weston_surface_destroy(shsurf->fullscreen.black_surface);
1945
1946         /* As destroy_resource() use wl_list_for_each_safe(),
1947          * we can always remove the listener.
1948          */
1949         wl_list_remove(&shsurf->surface_destroy_listener.link);
1950         shsurf->surface->configure = NULL;
1951         ping_timer_destroy(shsurf);
1952
1953         wl_list_remove(&shsurf->link);
1954         free(shsurf);
1955 }
1956
1957 static void
1958 shell_destroy_shell_surface(struct wl_resource *resource)
1959 {
1960         struct shell_surface *shsurf = resource->data;
1961
1962         destroy_shell_surface(shsurf);
1963 }
1964
1965 static void
1966 shell_handle_surface_destroy(struct wl_listener *listener, void *data)
1967 {
1968         struct shell_surface *shsurf = container_of(listener,
1969                                                     struct shell_surface,
1970                                                     surface_destroy_listener);
1971
1972         if (shsurf->resource.client) {
1973                 wl_resource_destroy(&shsurf->resource);
1974         } else {
1975                 wl_signal_emit(&shsurf->resource.destroy_signal,
1976                                &shsurf->resource);
1977                 destroy_shell_surface(shsurf);
1978         }
1979 }
1980
1981 static void
1982 shell_surface_configure(struct weston_surface *, int32_t, int32_t);
1983
1984 static struct shell_surface *
1985 get_shell_surface(struct weston_surface *surface)
1986 {
1987         if (surface->configure == shell_surface_configure)
1988                 return surface->private;
1989         else
1990                 return NULL;
1991 }
1992
1993 static  struct shell_surface *
1994 create_shell_surface(void *shell, struct weston_surface *surface,
1995                      const struct weston_shell_client *client)
1996 {
1997         struct shell_surface *shsurf;
1998
1999         if (surface->configure) {
2000                 weston_log("surface->configure already set\n");
2001                 return NULL;
2002         }
2003
2004         shsurf = calloc(1, sizeof *shsurf);
2005         if (!shsurf) {
2006                 weston_log("no memory to allocate shell surface\n");
2007                 return NULL;
2008         }
2009
2010         surface->configure = shell_surface_configure;
2011         surface->private = shsurf;
2012
2013         shsurf->shell = (struct desktop_shell *) shell;
2014         shsurf->unresponsive = 0;
2015         shsurf->saved_position_valid = false;
2016         shsurf->saved_rotation_valid = false;
2017         shsurf->surface = surface;
2018         shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
2019         shsurf->fullscreen.framerate = 0;
2020         shsurf->fullscreen.black_surface = NULL;
2021         shsurf->ping_timer = NULL;
2022         wl_list_init(&shsurf->fullscreen.transform.link);
2023
2024         wl_signal_init(&shsurf->resource.destroy_signal);
2025         shsurf->surface_destroy_listener.notify = shell_handle_surface_destroy;
2026         wl_signal_add(&surface->surface.resource.destroy_signal,
2027                       &shsurf->surface_destroy_listener);
2028
2029         /* init link so its safe to always remove it in destroy_shell_surface */
2030         wl_list_init(&shsurf->link);
2031
2032         /* empty when not in use */
2033         wl_list_init(&shsurf->rotation.transform.link);
2034         weston_matrix_init(&shsurf->rotation.rotation);
2035
2036         wl_list_init(&shsurf->workspace_transform.link);
2037
2038         shsurf->type = SHELL_SURFACE_NONE;
2039         shsurf->next_type = SHELL_SURFACE_NONE;
2040
2041         shsurf->client = client;
2042
2043         return shsurf;
2044 }
2045
2046 static void
2047 shell_get_shell_surface(struct wl_client *client,
2048                         struct wl_resource *resource,
2049                         uint32_t id,
2050                         struct wl_resource *surface_resource)
2051 {
2052         struct weston_surface *surface = surface_resource->data;
2053         struct desktop_shell *shell = resource->data;
2054         struct shell_surface *shsurf;
2055
2056         if (get_shell_surface(surface)) {
2057                 wl_resource_post_error(surface_resource,
2058                                        WL_DISPLAY_ERROR_INVALID_OBJECT,
2059                                        "desktop_shell::get_shell_surface already requested");
2060                 return;
2061         }
2062
2063         shsurf = create_shell_surface(shell, surface, &shell_client);
2064         if (!shsurf) {
2065                 wl_resource_post_error(surface_resource,
2066                                        WL_DISPLAY_ERROR_INVALID_OBJECT,
2067                                        "surface->configure already set");
2068                 return;
2069         }
2070
2071         shsurf->resource.destroy = shell_destroy_shell_surface;
2072         shsurf->resource.object.id = id;
2073         shsurf->resource.object.interface = &wl_shell_surface_interface;
2074         shsurf->resource.object.implementation =
2075                 (void (**)(void)) &shell_surface_implementation;
2076         shsurf->resource.data = shsurf;
2077
2078         wl_client_add_resource(client, &shsurf->resource);
2079 }
2080
2081 static const struct wl_shell_interface shell_implementation = {
2082         shell_get_shell_surface
2083 };
2084
2085 static void
2086 handle_screensaver_sigchld(struct weston_process *proc, int status)
2087 {
2088         proc->pid = 0;
2089 }
2090
2091 static void
2092 launch_screensaver(struct desktop_shell *shell)
2093 {
2094         if (shell->screensaver.binding)
2095                 return;
2096
2097         if (!shell->screensaver.path)
2098                 return;
2099
2100         if (shell->screensaver.process.pid != 0) {
2101                 weston_log("old screensaver still running\n");
2102                 return;
2103         }
2104
2105         weston_client_launch(shell->compositor,
2106                            &shell->screensaver.process,
2107                            shell->screensaver.path,
2108                            handle_screensaver_sigchld);
2109 }
2110
2111 static void
2112 terminate_screensaver(struct desktop_shell *shell)
2113 {
2114         if (shell->screensaver.process.pid == 0)
2115                 return;
2116
2117         kill(shell->screensaver.process.pid, SIGTERM);
2118 }
2119
2120 static void
2121 configure_static_surface(struct weston_surface *es, struct weston_layer *layer)
2122 {
2123         struct weston_surface *s, *next;
2124
2125         wl_list_for_each_safe(s, next, &layer->surface_list, layer_link) {
2126                 if (s->output == es->output && s != es) {
2127                         weston_surface_unmap(s);
2128                         s->configure = NULL;
2129                 }
2130         }
2131
2132         weston_surface_configure(es, es->output->x, es->output->y,
2133                                  es->buffer->width, es->buffer->height);
2134
2135         if (wl_list_empty(&es->layer_link)) {
2136                 wl_list_insert(&layer->surface_list, &es->layer_link);
2137                 weston_compositor_schedule_repaint(es->compositor);
2138         }
2139 }
2140
2141 static void
2142 background_configure(struct weston_surface *es, int32_t sx, int32_t sy)
2143 {
2144         struct desktop_shell *shell = es->private;
2145
2146         configure_static_surface(es, &shell->background_layer);
2147 }
2148
2149 static void
2150 desktop_shell_set_background(struct wl_client *client,
2151                              struct wl_resource *resource,
2152                              struct wl_resource *output_resource,
2153                              struct wl_resource *surface_resource)
2154 {
2155         struct desktop_shell *shell = resource->data;
2156         struct weston_surface *surface = surface_resource->data;
2157
2158         if (surface->configure) {
2159                 wl_resource_post_error(surface_resource,
2160                                        WL_DISPLAY_ERROR_INVALID_OBJECT,
2161                                        "surface role already assigned");
2162                 return;
2163         }
2164
2165         surface->configure = background_configure;
2166         surface->private = shell;
2167         surface->output = output_resource->data;
2168         desktop_shell_send_configure(resource, 0,
2169                                      surface_resource,
2170                                      surface->output->width,
2171                                      surface->output->height);
2172 }
2173
2174 static void
2175 panel_configure(struct weston_surface *es, int32_t sx, int32_t sy)
2176 {
2177         struct desktop_shell *shell = es->private;
2178
2179         configure_static_surface(es, &shell->panel_layer);
2180 }
2181
2182 static void
2183 desktop_shell_set_panel(struct wl_client *client,
2184                         struct wl_resource *resource,
2185                         struct wl_resource *output_resource,
2186                         struct wl_resource *surface_resource)
2187 {
2188         struct desktop_shell *shell = resource->data;
2189         struct weston_surface *surface = surface_resource->data;
2190
2191         if (surface->configure) {
2192                 wl_resource_post_error(surface_resource,
2193                                        WL_DISPLAY_ERROR_INVALID_OBJECT,
2194                                        "surface role already assigned");
2195                 return;
2196         }
2197
2198         surface->configure = panel_configure;
2199         surface->private = shell;
2200         surface->output = output_resource->data;
2201         desktop_shell_send_configure(resource, 0,
2202                                      surface_resource,
2203                                      surface->output->width,
2204                                      surface->output->height);
2205 }
2206
2207 static void
2208 lock_surface_configure(struct weston_surface *surface, int32_t sx, int32_t sy)
2209 {
2210         struct desktop_shell *shell = surface->private;
2211
2212         center_on_output(surface, get_default_output(shell->compositor));
2213
2214         if (!weston_surface_is_mapped(surface)) {
2215                 wl_list_insert(&shell->lock_layer.surface_list,
2216                                &surface->layer_link);
2217                 weston_surface_update_transform(surface);
2218                 weston_compositor_wake(shell->compositor);
2219         }
2220 }
2221
2222 static void
2223 handle_lock_surface_destroy(struct wl_listener *listener, void *data)
2224 {
2225         struct desktop_shell *shell =
2226             container_of(listener, struct desktop_shell, lock_surface_listener);
2227
2228         weston_log("lock surface gone\n");
2229         shell->lock_surface = NULL;
2230 }
2231
2232 static void
2233 desktop_shell_set_lock_surface(struct wl_client *client,
2234                                struct wl_resource *resource,
2235                                struct wl_resource *surface_resource)
2236 {
2237         struct desktop_shell *shell = resource->data;
2238         struct weston_surface *surface = surface_resource->data;
2239
2240         shell->prepare_event_sent = false;
2241
2242         if (!shell->locked)
2243                 return;
2244
2245         shell->lock_surface = surface;
2246
2247         shell->lock_surface_listener.notify = handle_lock_surface_destroy;
2248         wl_signal_add(&surface_resource->destroy_signal,
2249                       &shell->lock_surface_listener);
2250
2251         surface->configure = lock_surface_configure;
2252         surface->private = shell;
2253 }
2254
2255 static void
2256 resume_desktop(struct desktop_shell *shell)
2257 {
2258         struct weston_surface *surface;
2259         struct workspace *ws = get_current_workspace(shell);
2260
2261         wl_list_for_each(surface, &shell->screensaver.surfaces, link)
2262                 weston_surface_unmap(surface);
2263
2264         terminate_screensaver(shell);
2265
2266         wl_list_remove(&shell->lock_layer.link);
2267         wl_list_insert(&shell->compositor->cursor_layer.link,
2268                        &shell->fullscreen_layer.link);
2269         wl_list_insert(&shell->fullscreen_layer.link,
2270                        &shell->panel_layer.link);
2271         if (shell->showing_input_panels) {
2272                 wl_list_insert(&shell->panel_layer.link,
2273                                &shell->input_panel_layer.link);
2274                 wl_list_insert(&shell->input_panel_layer.link,
2275                                &ws->layer.link);
2276         } else {
2277                 wl_list_insert(&shell->panel_layer.link, &ws->layer.link);
2278         }
2279
2280         restore_focus_state(shell, get_current_workspace(shell));
2281
2282         shell->locked = false;
2283         shell->compositor->idle_time = shell->compositor->option_idle_time;
2284         weston_compositor_wake(shell->compositor);
2285         weston_compositor_damage_all(shell->compositor);
2286 }
2287
2288 static void
2289 desktop_shell_unlock(struct wl_client *client,
2290                      struct wl_resource *resource)
2291 {
2292         struct desktop_shell *shell = resource->data;
2293
2294         shell->prepare_event_sent = false;
2295
2296         if (shell->locked)
2297                 resume_desktop(shell);
2298 }
2299
2300 static void
2301 desktop_shell_set_grab_surface(struct wl_client *client,
2302                                struct wl_resource *resource,
2303                                struct wl_resource *surface_resource)
2304 {
2305         struct desktop_shell *shell = resource->data;
2306
2307         shell->grab_surface = surface_resource->data;
2308 }
2309
2310 static const struct desktop_shell_interface desktop_shell_implementation = {
2311         desktop_shell_set_background,
2312         desktop_shell_set_panel,
2313         desktop_shell_set_lock_surface,
2314         desktop_shell_unlock,
2315         desktop_shell_set_grab_surface
2316 };
2317
2318 static enum shell_surface_type
2319 get_shell_surface_type(struct weston_surface *surface)
2320 {
2321         struct shell_surface *shsurf;
2322
2323         shsurf = get_shell_surface(surface);
2324         if (!shsurf)
2325                 return SHELL_SURFACE_NONE;
2326         return shsurf->type;
2327 }
2328
2329 static void
2330 move_binding(struct wl_seat *seat, uint32_t time, uint32_t button, void *data)
2331 {
2332         struct weston_surface *surface =
2333                 (struct weston_surface *) seat->pointer->focus;
2334         struct shell_surface *shsurf;
2335
2336         if (surface == NULL)
2337                 return;
2338
2339         shsurf = get_shell_surface(surface);
2340         if (shsurf == NULL || shsurf->type == SHELL_SURFACE_FULLSCREEN)
2341                 return;
2342
2343         surface_move(shsurf, (struct weston_seat *) seat);
2344 }
2345
2346 static void
2347 resize_binding(struct wl_seat *seat, uint32_t time, uint32_t button, void *data)
2348 {
2349         struct weston_surface *surface =
2350                 (struct weston_surface *) seat->pointer->focus;
2351         uint32_t edges = 0;
2352         int32_t x, y;
2353         struct shell_surface *shsurf;
2354
2355         if (surface == NULL)
2356                 return;
2357
2358         shsurf = get_shell_surface(surface);
2359         if (!shsurf || shsurf->type == SHELL_SURFACE_FULLSCREEN)
2360                 return;
2361
2362         weston_surface_from_global(surface,
2363                                    wl_fixed_to_int(seat->pointer->grab_x),
2364                                    wl_fixed_to_int(seat->pointer->grab_y),
2365                                    &x, &y);
2366
2367         if (x < surface->geometry.width / 3)
2368                 edges |= WL_SHELL_SURFACE_RESIZE_LEFT;
2369         else if (x < 2 * surface->geometry.width / 3)
2370                 edges |= 0;
2371         else
2372                 edges |= WL_SHELL_SURFACE_RESIZE_RIGHT;
2373
2374         if (y < surface->geometry.height / 3)
2375                 edges |= WL_SHELL_SURFACE_RESIZE_TOP;
2376         else if (y < 2 * surface->geometry.height / 3)
2377                 edges |= 0;
2378         else
2379                 edges |= WL_SHELL_SURFACE_RESIZE_BOTTOM;
2380
2381         surface_resize(shsurf, (struct weston_seat *) seat, edges);
2382 }
2383
2384 static void
2385 surface_opacity_binding(struct wl_seat *seat, uint32_t time, uint32_t axis,
2386                         wl_fixed_t value, void *data)
2387 {
2388         float step = 0.005;
2389         struct shell_surface *shsurf;
2390         struct weston_surface *surface =
2391                 (struct weston_surface *) seat->pointer->focus;
2392
2393         if (surface == NULL)
2394                 return;
2395
2396         shsurf = get_shell_surface(surface);
2397         if (!shsurf)
2398                 return;
2399
2400         surface->alpha -= wl_fixed_to_double(value) * step;
2401
2402         if (surface->alpha > 1.0)
2403                 surface->alpha = 1.0;
2404         if (surface->alpha < step)
2405                 surface->alpha = step;
2406
2407         surface->geometry.dirty = 1;
2408         weston_surface_damage(surface);
2409 }
2410
2411 static void
2412 do_zoom(struct wl_seat *seat, uint32_t time, uint32_t key, uint32_t axis,
2413         wl_fixed_t value)
2414 {
2415         struct weston_seat *ws = (struct weston_seat *) seat;
2416         struct weston_compositor *compositor = ws->compositor;
2417         struct weston_output *output;
2418         float increment;
2419
2420         wl_list_for_each(output, &compositor->output_list, link) {
2421                 if (pixman_region32_contains_point(&output->region,
2422                                                    wl_fixed_to_double(seat->pointer->x),
2423                                                    wl_fixed_to_double(seat->pointer->y),
2424                                                    NULL)) {
2425                         if (key == KEY_PAGEUP)
2426                                 increment = output->zoom.increment;
2427                         else if (key == KEY_PAGEDOWN)
2428                                 increment = -output->zoom.increment;
2429                         else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
2430                                 /* For every pixel zoom 20th of a step */
2431                                 increment = output->zoom.increment *
2432                                             -wl_fixed_to_double(value) / 20.0;
2433                         else
2434                                 increment = 0;
2435
2436                         output->zoom.level += increment;
2437
2438                         if (output->zoom.level < 0.0)
2439                                 output->zoom.level = 0.0;
2440                         else if (output->zoom.level > output->zoom.max_level)
2441                                 output->zoom.level = output->zoom.max_level;
2442                         else if (!output->zoom.active) {
2443                                 output->zoom.active = 1;
2444                                 output->disable_planes++;
2445                         }
2446
2447                         output->zoom.spring_z.target = output->zoom.level;
2448
2449                         weston_output_update_zoom(output, output->zoom.type);
2450                 }
2451         }
2452 }
2453
2454 static void
2455 zoom_axis_binding(struct wl_seat *seat, uint32_t time, uint32_t axis,
2456                   wl_fixed_t value, void *data)
2457 {
2458         do_zoom(seat, time, 0, axis, value);
2459 }
2460
2461 static void
2462 zoom_key_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
2463                  void *data)
2464 {
2465         do_zoom(seat, time, key, 0, 0);
2466 }
2467
2468 static void
2469 terminate_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
2470                   void *data)
2471 {
2472         struct weston_compositor *compositor = data;
2473
2474         wl_display_terminate(compositor->wl_display);
2475 }
2476
2477 static void
2478 rotate_grab_motion(struct wl_pointer_grab *grab,
2479                    uint32_t time, wl_fixed_t x, wl_fixed_t y)
2480 {
2481         struct rotate_grab *rotate =
2482                 container_of(grab, struct rotate_grab, base.grab);
2483         struct wl_pointer *pointer = grab->pointer;
2484         struct shell_surface *shsurf = rotate->base.shsurf;
2485         struct weston_surface *surface;
2486         float cx, cy, dx, dy, cposx, cposy, dposx, dposy, r;
2487
2488         if (!shsurf)
2489                 return;
2490
2491         surface = shsurf->surface;
2492
2493         cx = 0.5f * surface->geometry.width;
2494         cy = 0.5f * surface->geometry.height;
2495
2496         dx = wl_fixed_to_double(pointer->x) - rotate->center.x;
2497         dy = wl_fixed_to_double(pointer->y) - rotate->center.y;
2498         r = sqrtf(dx * dx + dy * dy);
2499
2500         wl_list_remove(&shsurf->rotation.transform.link);
2501         shsurf->surface->geometry.dirty = 1;
2502
2503         if (r > 20.0f) {
2504                 struct weston_matrix *matrix =
2505                         &shsurf->rotation.transform.matrix;
2506
2507                 weston_matrix_init(&rotate->rotation);
2508                 rotate->rotation.d[0] = dx / r;
2509                 rotate->rotation.d[4] = -dy / r;
2510                 rotate->rotation.d[1] = -rotate->rotation.d[4];
2511                 rotate->rotation.d[5] = rotate->rotation.d[0];
2512
2513                 weston_matrix_init(matrix);
2514                 weston_matrix_translate(matrix, -cx, -cy, 0.0f);
2515                 weston_matrix_multiply(matrix, &shsurf->rotation.rotation);
2516                 weston_matrix_multiply(matrix, &rotate->rotation);
2517                 weston_matrix_translate(matrix, cx, cy, 0.0f);
2518
2519                 wl_list_insert(
2520                         &shsurf->surface->geometry.transformation_list,
2521                         &shsurf->rotation.transform.link);
2522         } else {
2523                 wl_list_init(&shsurf->rotation.transform.link);
2524                 weston_matrix_init(&shsurf->rotation.rotation);
2525                 weston_matrix_init(&rotate->rotation);
2526         }
2527
2528         /* We need to adjust the position of the surface
2529          * in case it was resized in a rotated state before */
2530         cposx = surface->geometry.x + cx;
2531         cposy = surface->geometry.y + cy;
2532         dposx = rotate->center.x - cposx;
2533         dposy = rotate->center.y - cposy;
2534         if (dposx != 0.0f || dposy != 0.0f) {
2535                 weston_surface_set_position(surface,
2536                                             surface->geometry.x + dposx,
2537                                             surface->geometry.y + dposy);
2538         }
2539
2540         /* Repaint implies weston_surface_update_transform(), which
2541          * lazily applies the damage due to rotation update.
2542          */
2543         weston_compositor_schedule_repaint(shsurf->surface->compositor);
2544 }
2545
2546 static void
2547 rotate_grab_button(struct wl_pointer_grab *grab,
2548                  uint32_t time, uint32_t button, uint32_t state_w)
2549 {
2550         struct rotate_grab *rotate =
2551                 container_of(grab, struct rotate_grab, base.grab);
2552         struct wl_pointer *pointer = grab->pointer;
2553         struct shell_surface *shsurf = rotate->base.shsurf;
2554         enum wl_pointer_button_state state = state_w;
2555
2556         if (pointer->button_count == 0 &&
2557             state == WL_POINTER_BUTTON_STATE_RELEASED) {
2558                 if (shsurf)
2559                         weston_matrix_multiply(&shsurf->rotation.rotation,
2560                                                &rotate->rotation);
2561                 shell_grab_end(&rotate->base);
2562                 free(rotate);
2563         }
2564 }
2565
2566 static const struct wl_pointer_grab_interface rotate_grab_interface = {
2567         noop_grab_focus,
2568         rotate_grab_motion,
2569         rotate_grab_button,
2570 };
2571
2572 static void
2573 rotate_binding(struct wl_seat *seat, uint32_t time, uint32_t button,
2574                void *data)
2575 {
2576         struct weston_surface *base_surface =
2577                 (struct weston_surface *) seat->pointer->focus;
2578         struct shell_surface *surface;
2579         struct rotate_grab *rotate;
2580         float dx, dy;
2581         float r;
2582
2583         if (base_surface == NULL)
2584                 return;
2585
2586         surface = get_shell_surface(base_surface);
2587         if (!surface || surface->type == SHELL_SURFACE_FULLSCREEN)
2588                 return;
2589
2590         rotate = malloc(sizeof *rotate);
2591         if (!rotate)
2592                 return;
2593
2594         weston_surface_to_global_float(surface->surface,
2595                                        surface->surface->geometry.width / 2,
2596                                        surface->surface->geometry.height / 2,
2597                                        &rotate->center.x, &rotate->center.y);
2598
2599         dx = wl_fixed_to_double(seat->pointer->x) - rotate->center.x;
2600         dy = wl_fixed_to_double(seat->pointer->y) - rotate->center.y;
2601         r = sqrtf(dx * dx + dy * dy);
2602         if (r > 20.0f) {
2603                 struct weston_matrix inverse;
2604
2605                 weston_matrix_init(&inverse);
2606                 inverse.d[0] = dx / r;
2607                 inverse.d[4] = dy / r;
2608                 inverse.d[1] = -inverse.d[4];
2609                 inverse.d[5] = inverse.d[0];
2610                 weston_matrix_multiply(&surface->rotation.rotation, &inverse);
2611
2612                 weston_matrix_init(&rotate->rotation);
2613                 rotate->rotation.d[0] = dx / r;
2614                 rotate->rotation.d[4] = -dy / r;
2615                 rotate->rotation.d[1] = -rotate->rotation.d[4];
2616                 rotate->rotation.d[5] = rotate->rotation.d[0];
2617         } else {
2618                 weston_matrix_init(&surface->rotation.rotation);
2619                 weston_matrix_init(&rotate->rotation);
2620         }
2621
2622         shell_grab_start(&rotate->base, &rotate_grab_interface, surface,
2623                          seat->pointer, DESKTOP_SHELL_CURSOR_ARROW);
2624 }
2625
2626 static void
2627 lower_fullscreen_layer(struct desktop_shell *shell)
2628 {
2629         struct workspace *ws;
2630         struct weston_surface *surface, *prev;
2631
2632         ws = get_current_workspace(shell);
2633         wl_list_for_each_reverse_safe(surface, prev,
2634                                       &shell->fullscreen_layer.surface_list,
2635                                       layer_link)
2636                 weston_surface_restack(surface, &ws->layer.surface_list);
2637 }
2638
2639 static void
2640 activate(struct desktop_shell *shell, struct weston_surface *es,
2641          struct weston_seat *seat)
2642 {
2643         struct focus_state *state;
2644         struct workspace *ws;
2645
2646         weston_surface_activate(es, seat);
2647
2648         state = ensure_focus_state(shell, seat);
2649         if (state == NULL)
2650                 return;
2651
2652         state->keyboard_focus = es;
2653         wl_list_remove(&state->surface_destroy_listener.link);
2654         wl_signal_add(&es->surface.resource.destroy_signal,
2655                       &state->surface_destroy_listener);
2656
2657         switch (get_shell_surface_type(es)) {
2658         case SHELL_SURFACE_FULLSCREEN:
2659                 /* should on top of panels */
2660                 shell_stack_fullscreen(get_shell_surface(es));
2661                 shell_configure_fullscreen(get_shell_surface(es));
2662                 break;
2663         default:
2664                 ws = get_current_workspace(shell);
2665                 lower_fullscreen_layer(shell);
2666                 weston_surface_restack(es, &ws->layer.surface_list);
2667                 break;
2668         }
2669 }
2670
2671 /* no-op func for checking black surface */
2672 static void
2673 black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy)
2674 {
2675 }
2676
2677 static bool 
2678 is_black_surface (struct weston_surface *es, struct weston_surface **fs_surface)
2679 {
2680         if (es->configure == black_surface_configure) {
2681                 if (fs_surface)
2682                         *fs_surface = (struct weston_surface *)es->private;
2683                 return true;
2684         }
2685         return false;
2686 }
2687
2688 static void
2689 click_to_activate_binding(struct wl_seat *seat, uint32_t time, uint32_t button,
2690                           void *data)
2691 {
2692         struct weston_seat *ws = (struct weston_seat *) seat;
2693         struct desktop_shell *shell = data;
2694         struct weston_surface *focus;
2695         struct weston_surface *upper;
2696
2697         focus = (struct weston_surface *) seat->pointer->focus;
2698         if (!focus)
2699                 return;
2700
2701         if (is_black_surface(focus, &upper))
2702                 focus = upper;
2703
2704         if (get_shell_surface_type(focus) == SHELL_SURFACE_NONE)
2705                 return;
2706
2707         if (seat->pointer->grab == &seat->pointer->default_grab)
2708                 activate(shell, focus, ws);
2709 }
2710
2711 static void
2712 lock(struct wl_listener *listener, void *data)
2713 {
2714         struct desktop_shell *shell =
2715                 container_of(listener, struct desktop_shell, lock_listener);
2716         struct weston_output *output;
2717         struct workspace *ws = get_current_workspace(shell);
2718
2719         if (shell->locked) {
2720                 wl_list_for_each(output, &shell->compositor->output_list, link)
2721                         /* TODO: find a way to jump to other DPMS levels */
2722                         if (output->set_dpms)
2723                                 output->set_dpms(output, WESTON_DPMS_STANDBY);
2724                 return;
2725         }
2726
2727         shell->locked = true;
2728
2729         /* Hide all surfaces by removing the fullscreen, panel and
2730          * toplevel layers.  This way nothing else can show or receive
2731          * input events while we are locked. */
2732
2733         wl_list_remove(&shell->panel_layer.link);
2734         wl_list_remove(&shell->fullscreen_layer.link);
2735         if (shell->showing_input_panels)
2736                 wl_list_remove(&shell->input_panel_layer.link);
2737         wl_list_remove(&ws->layer.link);
2738         wl_list_insert(&shell->compositor->cursor_layer.link,
2739                        &shell->lock_layer.link);
2740
2741         launch_screensaver(shell);
2742
2743         /* TODO: disable bindings that should not work while locked. */
2744
2745         /* All this must be undone in resume_desktop(). */
2746 }
2747
2748 static void
2749 unlock(struct wl_listener *listener, void *data)
2750 {
2751         struct desktop_shell *shell =
2752                 container_of(listener, struct desktop_shell, unlock_listener);
2753
2754         if (!shell->locked || shell->lock_surface) {
2755                 weston_compositor_wake(shell->compositor);
2756                 return;
2757         }
2758
2759         /* If desktop-shell client has gone away, unlock immediately. */
2760         if (!shell->child.desktop_shell) {
2761                 resume_desktop(shell);
2762                 return;
2763         }
2764
2765         if (shell->prepare_event_sent)
2766                 return;
2767
2768         desktop_shell_send_prepare_lock_surface(shell->child.desktop_shell);
2769         shell->prepare_event_sent = true;
2770 }
2771
2772 static void
2773 show_input_panels(struct wl_listener *listener, void *data)
2774 {
2775         struct desktop_shell *shell =
2776                 container_of(listener, struct desktop_shell,
2777                              show_input_panel_listener);
2778         struct input_panel_surface *surface, *next;
2779         struct weston_surface *ws;
2780
2781         shell->showing_input_panels = true;
2782
2783         if (!shell->locked)
2784                 wl_list_insert(&shell->panel_layer.link,
2785                                &shell->input_panel_layer.link);
2786
2787         wl_list_for_each_safe(surface, next,
2788                               &shell->input_panel.surfaces, link) {
2789                 ws = surface->surface;
2790                 wl_list_insert(&shell->input_panel_layer.surface_list,
2791                                &ws->layer_link);
2792                 ws->geometry.dirty = 1;
2793                 weston_surface_update_transform(ws);
2794                 weston_surface_damage(ws);
2795                 weston_slide_run(ws, ws->geometry.height, 0, NULL, NULL);
2796         }
2797 }
2798
2799 static void
2800 hide_input_panels(struct wl_listener *listener, void *data)
2801 {
2802         struct desktop_shell *shell =
2803                 container_of(listener, struct desktop_shell,
2804                              hide_input_panel_listener);
2805         struct weston_surface *surface, *next;
2806
2807         shell->showing_input_panels = false;
2808
2809         if (!shell->locked)
2810                 wl_list_remove(&shell->input_panel_layer.link);
2811
2812         wl_list_for_each_safe(surface, next,
2813                               &shell->input_panel_layer.surface_list, layer_link)
2814                 weston_surface_unmap(surface);
2815 }
2816
2817 static void
2818 center_on_output(struct weston_surface *surface, struct weston_output *output)
2819 {
2820         float x = (output->width - surface->buffer->width) / 2;
2821         float y = (output->height - surface->buffer->height) / 2;
2822
2823         weston_surface_configure(surface, output->x + x, output->y + y,
2824                                  surface->buffer->width,
2825                                  surface->buffer->height);
2826 }
2827
2828 static void
2829 weston_surface_set_initial_position (struct weston_surface *surface,
2830                                      struct desktop_shell *shell)
2831 {
2832         struct weston_compositor *compositor = shell->compositor;
2833         int ix = 0, iy = 0;
2834         int range_x, range_y;
2835         int dx, dy, x, y, panel_height;
2836         struct weston_output *output, *target_output = NULL;
2837         struct weston_seat *seat;
2838
2839         /* As a heuristic place the new window on the same output as the
2840          * pointer. Falling back to the output containing 0, 0.
2841          *
2842          * TODO: Do something clever for touch too?
2843          */
2844         wl_list_for_each(seat, &compositor->seat_list, link) {
2845                 if (seat->has_pointer) {
2846                         ix = wl_fixed_to_int(seat->pointer.x);
2847                         iy = wl_fixed_to_int(seat->pointer.y);
2848                         break;
2849                 }
2850         }
2851
2852         wl_list_for_each(output, &compositor->output_list, link) {
2853                 if (pixman_region32_contains_point(&output->region, ix, iy, NULL)) {
2854                         target_output = output;
2855                         break;
2856                 }
2857         }
2858
2859         if (!target_output) {
2860                 weston_surface_set_position(surface, 10 + random() % 400,
2861                                            10 + random() % 400);
2862                 return;
2863         }
2864
2865         /* Valid range within output where the surface will still be onscreen.
2866          * If this is negative it means that the surface is bigger than
2867          * output.
2868          */
2869         panel_height = get_output_panel_height(shell, target_output);
2870         range_x = target_output->width - surface->geometry.width;
2871         range_y = (target_output->height - panel_height) -
2872                   surface->geometry.height;
2873
2874         if (range_x > 0)
2875                 dx = random() % range_x;
2876         else
2877                 dx = 0;
2878
2879         if (range_y > 0)
2880                 dy = panel_height + random() % range_y;
2881         else
2882                 dy = panel_height;
2883
2884         x = target_output->x + dx;
2885         y = target_output->y + dy;
2886
2887         weston_surface_set_position (surface, x, y);
2888 }
2889
2890 static void
2891 map(struct desktop_shell *shell, struct weston_surface *surface,
2892     int32_t width, int32_t height, int32_t sx, int32_t sy)
2893 {
2894         struct weston_compositor *compositor = shell->compositor;
2895         struct shell_surface *shsurf = get_shell_surface(surface);
2896         enum shell_surface_type surface_type = shsurf->type;
2897         struct weston_surface *parent;
2898         struct weston_seat *seat;
2899         struct workspace *ws;
2900         int panel_height = 0;
2901
2902         surface->geometry.width = width;
2903         surface->geometry.height = height;
2904         surface->geometry.dirty = 1;
2905
2906         /* initial positioning, see also configure() */
2907         switch (surface_type) {
2908         case SHELL_SURFACE_TOPLEVEL:
2909                 weston_surface_set_initial_position(surface, shell);
2910                 break;
2911         case SHELL_SURFACE_FULLSCREEN:
2912                 center_on_output(surface, shsurf->fullscreen_output);
2913                 shell_map_fullscreen(shsurf);
2914                 break;
2915         case SHELL_SURFACE_MAXIMIZED:
2916                 /* use surface configure to set the geometry */
2917                 panel_height = get_output_panel_height(shell,surface->output);
2918                 weston_surface_set_position(surface, shsurf->output->x,
2919                                             shsurf->output->y + panel_height);
2920                 break;
2921         case SHELL_SURFACE_POPUP:
2922                 shell_map_popup(shsurf);
2923                 break;
2924         case SHELL_SURFACE_NONE:
2925                 weston_surface_set_position(surface,
2926                                             surface->geometry.x + sx,
2927                                             surface->geometry.y + sy);
2928                 break;
2929         default:
2930                 ;
2931         }
2932
2933         /* surface stacking order, see also activate() */
2934         switch (surface_type) {
2935         case SHELL_SURFACE_POPUP:
2936         case SHELL_SURFACE_TRANSIENT:
2937                 parent = shsurf->parent;
2938                 wl_list_insert(parent->layer_link.prev, &surface->layer_link);
2939                 break;
2940         case SHELL_SURFACE_FULLSCREEN:
2941         case SHELL_SURFACE_NONE:
2942                 break;
2943         default:
2944                 ws = get_current_workspace(shell);
2945                 wl_list_insert(&ws->layer.surface_list, &surface->layer_link);
2946                 break;
2947         }
2948
2949         if (surface_type != SHELL_SURFACE_NONE) {
2950                 weston_surface_update_transform(surface);
2951                 if (surface_type == SHELL_SURFACE_MAXIMIZED)
2952                         surface->output = shsurf->output;
2953         }
2954
2955         switch (surface_type) {
2956         case SHELL_SURFACE_TRANSIENT:
2957                 if (shsurf->transient.flags ==
2958                                 WL_SHELL_SURFACE_TRANSIENT_INACTIVE)
2959                         break;
2960         case SHELL_SURFACE_TOPLEVEL:
2961         case SHELL_SURFACE_FULLSCREEN:
2962         case SHELL_SURFACE_MAXIMIZED:
2963                 if (!shell->locked) {
2964                         wl_list_for_each(seat, &compositor->seat_list, link)
2965                                 activate(shell, surface, seat);
2966                 }
2967                 break;
2968         default:
2969                 break;
2970         }
2971
2972         if (surface_type == SHELL_SURFACE_TOPLEVEL)
2973         {
2974                 switch (shell->win_animation_type) {
2975                 case ANIMATION_FADE:
2976                         weston_fade_run(surface, NULL, NULL);
2977                         break;
2978                 case ANIMATION_ZOOM:
2979                         weston_zoom_run(surface, 0.8, 1.0, NULL, NULL);
2980                         break;
2981                 default:
2982                         break;
2983                 }
2984         }
2985 }
2986
2987 static void
2988 configure(struct desktop_shell *shell, struct weston_surface *surface,
2989           float x, float y, int32_t width, int32_t height)
2990 {
2991         enum shell_surface_type surface_type = SHELL_SURFACE_NONE;
2992         struct shell_surface *shsurf;
2993
2994         shsurf = get_shell_surface(surface);
2995         if (shsurf)
2996                 surface_type = shsurf->type;
2997
2998         surface->geometry.x = x;
2999         surface->geometry.y = y;
3000         surface->geometry.width = width;
3001         surface->geometry.height = height;
3002         surface->geometry.dirty = 1;
3003
3004         switch (surface_type) {
3005         case SHELL_SURFACE_FULLSCREEN:
3006                 shell_stack_fullscreen(shsurf);
3007                 shell_configure_fullscreen(shsurf);
3008                 break;
3009         case SHELL_SURFACE_MAXIMIZED:
3010                 /* setting x, y and using configure to change that geometry */
3011                 surface->geometry.x = surface->output->x;
3012                 surface->geometry.y = surface->output->y +
3013                         get_output_panel_height(shell,surface->output);
3014                 break;
3015         case SHELL_SURFACE_TOPLEVEL:
3016                 break;
3017         default:
3018                 break;
3019         }
3020
3021         /* XXX: would a fullscreen surface need the same handling? */
3022         if (surface->output) {
3023                 weston_surface_update_transform(surface);
3024
3025                 if (surface_type == SHELL_SURFACE_MAXIMIZED)
3026                         surface->output = shsurf->output;
3027         }
3028 }
3029
3030 static void
3031 shell_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy)
3032 {
3033         struct shell_surface *shsurf = get_shell_surface(es);
3034         struct desktop_shell *shell = shsurf->shell;
3035         int type_changed = 0;
3036
3037         if (shsurf->next_type != SHELL_SURFACE_NONE &&
3038             shsurf->type != shsurf->next_type) {
3039                 set_surface_type(shsurf);
3040                 type_changed = 1;
3041         }
3042
3043         if (!weston_surface_is_mapped(es)) {
3044                 map(shell, es, es->buffer->width, es->buffer->height, sx, sy);
3045         } else if (type_changed || sx != 0 || sy != 0 ||
3046                    es->geometry.width != es->buffer->width ||
3047                    es->geometry.height != es->buffer->height) {
3048                 float from_x, from_y;
3049                 float to_x, to_y;
3050
3051                 weston_surface_to_global_float(es, 0, 0, &from_x, &from_y);
3052                 weston_surface_to_global_float(es, sx, sy, &to_x, &to_y);
3053                 configure(shell, es,
3054                           es->geometry.x + to_x - from_x,
3055                           es->geometry.y + to_y - from_y,
3056                           es->buffer->width, es->buffer->height);
3057         }
3058 }
3059
3060 static void launch_desktop_shell_process(void *data);
3061
3062 static void
3063 desktop_shell_sigchld(struct weston_process *process, int status)
3064 {
3065         uint32_t time;
3066         struct desktop_shell *shell =
3067                 container_of(process, struct desktop_shell, child.process);
3068
3069         shell->child.process.pid = 0;
3070         shell->child.client = NULL; /* already destroyed by wayland */
3071
3072         /* if desktop-shell dies more than 5 times in 30 seconds, give up */
3073         time = weston_compositor_get_time();
3074         if (time - shell->child.deathstamp > 30000) {
3075                 shell->child.deathstamp = time;
3076                 shell->child.deathcount = 0;
3077         }
3078
3079         shell->child.deathcount++;
3080         if (shell->child.deathcount > 5) {
3081                 weston_log("weston-desktop-shell died, giving up.\n");
3082                 return;
3083         }
3084
3085         weston_log("weston-desktop-shell died, respawning...\n");
3086         launch_desktop_shell_process(shell);
3087 }
3088
3089 static void
3090 launch_desktop_shell_process(void *data)
3091 {
3092         struct desktop_shell *shell = data;
3093         const char *shell_exe = LIBEXECDIR "/weston-desktop-shell";
3094
3095         shell->child.client = weston_client_launch(shell->compositor,
3096                                                  &shell->child.process,
3097                                                  shell_exe,
3098                                                  desktop_shell_sigchld);
3099
3100         if (!shell->child.client)
3101                 weston_log("not able to start %s\n", shell_exe);
3102 }
3103
3104 static void
3105 bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
3106 {
3107         struct desktop_shell *shell = data;
3108
3109         wl_client_add_object(client, &wl_shell_interface,
3110                              &shell_implementation, id, shell);
3111 }
3112
3113 static void
3114 unbind_desktop_shell(struct wl_resource *resource)
3115 {
3116         struct desktop_shell *shell = resource->data;
3117
3118         if (shell->locked)
3119                 resume_desktop(shell);
3120
3121         shell->child.desktop_shell = NULL;
3122         shell->prepare_event_sent = false;
3123         free(resource);
3124 }
3125
3126 static void
3127 bind_desktop_shell(struct wl_client *client,
3128                    void *data, uint32_t version, uint32_t id)
3129 {
3130         struct desktop_shell *shell = data;
3131         struct wl_resource *resource;
3132
3133         resource = wl_client_add_object(client, &desktop_shell_interface,
3134                                         &desktop_shell_implementation,
3135                                         id, shell);
3136
3137         if (client == shell->child.client) {
3138                 resource->destroy = unbind_desktop_shell;
3139                 shell->child.desktop_shell = resource;
3140                 return;
3141         }
3142
3143         wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
3144                                "permission to bind desktop_shell denied");
3145         wl_resource_destroy(resource);
3146 }
3147
3148 static void
3149 screensaver_configure(struct weston_surface *surface, int32_t sx, int32_t sy)
3150 {
3151         struct desktop_shell *shell = surface->private;
3152
3153         if (!shell->locked)
3154                 return;
3155
3156         center_on_output(surface, surface->output);
3157
3158         if (wl_list_empty(&surface->layer_link)) {
3159                 wl_list_insert(shell->lock_layer.surface_list.prev,
3160                                &surface->layer_link);
3161                 weston_surface_update_transform(surface);
3162                 shell->compositor->idle_time = shell->screensaver.duration;
3163                 weston_compositor_wake(shell->compositor);
3164                 shell->compositor->state = WESTON_COMPOSITOR_IDLE;
3165         }
3166 }
3167
3168 static void
3169 screensaver_set_surface(struct wl_client *client,
3170                         struct wl_resource *resource,
3171                         struct wl_resource *surface_resource,
3172                         struct wl_resource *output_resource)
3173 {
3174         struct desktop_shell *shell = resource->data;
3175         struct weston_surface *surface = surface_resource->data;
3176         struct weston_output *output = output_resource->data;
3177
3178         surface->configure = screensaver_configure;
3179         surface->private = shell;
3180         surface->output = output;
3181 }
3182
3183 static const struct screensaver_interface screensaver_implementation = {
3184         screensaver_set_surface
3185 };
3186
3187 static void
3188 unbind_screensaver(struct wl_resource *resource)
3189 {
3190         struct desktop_shell *shell = resource->data;
3191
3192         shell->screensaver.binding = NULL;
3193         free(resource);
3194 }
3195
3196 static void
3197 bind_screensaver(struct wl_client *client,
3198                  void *data, uint32_t version, uint32_t id)
3199 {
3200         struct desktop_shell *shell = data;
3201         struct wl_resource *resource;
3202
3203         resource = wl_client_add_object(client, &screensaver_interface,
3204                                         &screensaver_implementation,
3205                                         id, shell);
3206
3207         if (shell->screensaver.binding == NULL) {
3208                 resource->destroy = unbind_screensaver;
3209                 shell->screensaver.binding = resource;
3210                 return;
3211         }
3212
3213         wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
3214                                "interface object already bound");
3215         wl_resource_destroy(resource);
3216 }
3217
3218 static void
3219 input_panel_configure(struct weston_surface *surface, int32_t sx, int32_t sy)
3220 {
3221         struct weston_mode *mode = surface->output->current;
3222         float x = (mode->width - surface->buffer->width) / 2;
3223         float y = mode->height - surface->buffer->height;
3224
3225         /* Don't map the input panel here, wait for
3226          * show_input_panels signal. */
3227
3228         weston_surface_configure(surface,
3229                                  surface->output->x + x,
3230                                  surface->output->y + y,
3231                                  surface->buffer->width,
3232                                  surface->buffer->height);
3233 }
3234
3235 static void
3236 destroy_input_panel_surface(struct wl_listener *listener,
3237                             void *data)
3238 {
3239         struct input_panel_surface *input_panel_surface =
3240                 container_of(listener, struct input_panel_surface, listener);
3241
3242         wl_list_remove(&listener->link);
3243         wl_list_remove(&input_panel_surface->link);
3244
3245         free(input_panel_surface);
3246 }
3247
3248 static void
3249 input_panel_set_surface(struct wl_client *client,
3250                         struct wl_resource *resource,
3251                         struct wl_resource *surface_resource,
3252                         struct wl_resource *output_resource)
3253 {
3254         struct desktop_shell *shell = resource->data;
3255         struct weston_surface *surface = surface_resource->data;
3256         struct weston_output *output = output_resource->data;
3257         struct input_panel_surface *input_panel_surface;
3258
3259         surface->configure = input_panel_configure;
3260         surface->private = shell;
3261         surface->output = output;
3262
3263         input_panel_surface = malloc(sizeof *input_panel_surface);
3264         if (!input_panel_surface) {
3265                 wl_resource_post_no_memory(resource);
3266                 return;
3267         }
3268
3269         input_panel_surface->surface = surface;
3270         input_panel_surface->listener.notify = destroy_input_panel_surface;
3271
3272         wl_signal_add(&surface_resource->destroy_signal,
3273                       &input_panel_surface->listener);
3274
3275         wl_list_insert(&shell->input_panel.surfaces,
3276                        &input_panel_surface->link);
3277 }
3278
3279 static const struct input_panel_interface input_panel_implementation = {
3280         input_panel_set_surface
3281 };
3282
3283 static void
3284 unbind_input_panel(struct wl_resource *resource)
3285 {
3286         struct desktop_shell *shell = resource->data;
3287
3288         shell->input_panel.binding = NULL;
3289         free(resource);
3290 }
3291
3292 static void
3293 bind_input_panel(struct wl_client *client,
3294               void *data, uint32_t version, uint32_t id)
3295 {
3296         struct desktop_shell *shell = data;
3297         struct wl_resource *resource;
3298
3299         resource = wl_client_add_object(client, &input_panel_interface,
3300                                         &input_panel_implementation,
3301                                         id, shell);
3302
3303         if (shell->input_panel.binding == NULL) {
3304                 resource->destroy = unbind_input_panel;
3305                 shell->input_panel.binding = resource;
3306                 return;
3307         }
3308
3309         wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
3310                                "interface object already bound");
3311         wl_resource_destroy(resource);
3312 }
3313
3314 struct switcher {
3315         struct desktop_shell *shell;
3316         struct weston_surface *current;
3317         struct wl_listener listener;
3318         struct wl_keyboard_grab grab;
3319 };
3320
3321 static void
3322 switcher_next(struct switcher *switcher)
3323 {
3324         struct weston_surface *surface;
3325         struct weston_surface *first = NULL, *prev = NULL, *next = NULL;
3326         struct shell_surface *shsurf;
3327         struct workspace *ws = get_current_workspace(switcher->shell);
3328
3329         wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
3330                 switch (get_shell_surface_type(surface)) {
3331                 case SHELL_SURFACE_TOPLEVEL:
3332                 case SHELL_SURFACE_FULLSCREEN:
3333                 case SHELL_SURFACE_MAXIMIZED:
3334                         if (first == NULL)
3335                                 first = surface;
3336                         if (prev == switcher->current)
3337                                 next = surface;
3338                         prev = surface;
3339                         surface->alpha = 0.25;
3340                         surface->geometry.dirty = 1;
3341                         weston_surface_damage(surface);
3342                         break;
3343                 default:
3344                         break;
3345                 }
3346
3347                 if (is_black_surface(surface, NULL)) {
3348                         surface->alpha = 0.25;
3349                         surface->geometry.dirty = 1;
3350                         weston_surface_damage(surface);
3351                 }
3352         }
3353
3354         if (next == NULL)
3355                 next = first;
3356
3357         if (next == NULL)
3358                 return;
3359
3360         wl_list_remove(&switcher->listener.link);
3361         wl_signal_add(&next->surface.resource.destroy_signal,
3362                       &switcher->listener);
3363
3364         switcher->current = next;
3365         next->alpha = 1.0;
3366
3367         shsurf = get_shell_surface(switcher->current);
3368         if (shsurf && shsurf->type ==SHELL_SURFACE_FULLSCREEN)
3369                 shsurf->fullscreen.black_surface->alpha = 1.0;
3370 }
3371
3372 static void
3373 switcher_handle_surface_destroy(struct wl_listener *listener, void *data)
3374 {
3375         struct switcher *switcher =
3376                 container_of(listener, struct switcher, listener);
3377
3378         switcher_next(switcher);
3379 }
3380
3381 static void
3382 switcher_destroy(struct switcher *switcher)
3383 {
3384         struct weston_surface *surface;
3385         struct wl_keyboard *keyboard = switcher->grab.keyboard;
3386         struct workspace *ws = get_current_workspace(switcher->shell);
3387
3388         wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
3389                 surface->alpha = 1.0;
3390                 weston_surface_damage(surface);
3391         }
3392
3393         if (switcher->current)
3394                 activate(switcher->shell, switcher->current,
3395                          (struct weston_seat *) keyboard->seat);
3396         wl_list_remove(&switcher->listener.link);
3397         wl_keyboard_end_grab(keyboard);
3398         free(switcher);
3399 }
3400
3401 static void
3402 switcher_key(struct wl_keyboard_grab *grab,
3403              uint32_t time, uint32_t key, uint32_t state_w)
3404 {
3405         struct switcher *switcher = container_of(grab, struct switcher, grab);
3406         enum wl_keyboard_key_state state = state_w;
3407
3408         if (key == KEY_TAB && state == WL_KEYBOARD_KEY_STATE_PRESSED)
3409                 switcher_next(switcher);
3410 }
3411
3412 static void
3413 switcher_modifier(struct wl_keyboard_grab *grab, uint32_t serial,
3414                   uint32_t mods_depressed, uint32_t mods_latched,
3415                   uint32_t mods_locked, uint32_t group)
3416 {
3417         struct switcher *switcher = container_of(grab, struct switcher, grab);
3418         struct weston_seat *seat = (struct weston_seat *) grab->keyboard->seat;
3419
3420         if ((seat->modifier_state & switcher->shell->binding_modifier) == 0)
3421                 switcher_destroy(switcher);
3422 }
3423
3424 static const struct wl_keyboard_grab_interface switcher_grab = {
3425         switcher_key,
3426         switcher_modifier,
3427 };
3428
3429 static void
3430 switcher_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
3431                  void *data)
3432 {
3433         struct desktop_shell *shell = data;
3434         struct switcher *switcher;
3435
3436         switcher = malloc(sizeof *switcher);
3437         switcher->shell = shell;
3438         switcher->current = NULL;
3439         switcher->listener.notify = switcher_handle_surface_destroy;
3440         wl_list_init(&switcher->listener.link);
3441
3442         lower_fullscreen_layer(switcher->shell);
3443         switcher->grab.interface = &switcher_grab;
3444         wl_keyboard_start_grab(seat->keyboard, &switcher->grab);
3445         wl_keyboard_set_focus(seat->keyboard, NULL);
3446         switcher_next(switcher);
3447 }
3448
3449 static void
3450 backlight_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
3451                   void *data)
3452 {
3453         struct weston_compositor *compositor = data;
3454         struct weston_output *output;
3455         long backlight_new = 0;
3456
3457         /* TODO: we're limiting to simple use cases, where we assume just
3458          * control on the primary display. We'd have to extend later if we
3459          * ever get support for setting backlights on random desktop LCD
3460          * panels though */
3461         output = get_default_output(compositor);
3462         if (!output)
3463                 return;
3464
3465         if (!output->set_backlight)
3466                 return;
3467
3468         if (key == KEY_F9 || key == KEY_BRIGHTNESSDOWN)
3469                 backlight_new = output->backlight_current - 25;
3470         else if (key == KEY_F10 || key == KEY_BRIGHTNESSUP)
3471                 backlight_new = output->backlight_current + 25;
3472
3473         if (backlight_new < 5)
3474                 backlight_new = 5;
3475         if (backlight_new > 255)
3476                 backlight_new = 255;
3477
3478         output->backlight_current = backlight_new;
3479         output->set_backlight(output, output->backlight_current);
3480 }
3481
3482 static void
3483 debug_repaint_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
3484                       void *data)
3485 {
3486         struct desktop_shell *shell = data;
3487         struct weston_compositor *compositor = shell->compositor;
3488         struct weston_surface *surface;
3489         struct weston_plane plane;
3490
3491         if (shell->debug_repaint_surface) {
3492                 weston_surface_destroy(shell->debug_repaint_surface);
3493                 shell->debug_repaint_surface = NULL;
3494         } else {
3495                 surface = weston_surface_create(compositor);
3496                 weston_surface_set_color(surface, 1.0, 0.0, 0.0, 0.2);
3497                 weston_surface_configure(surface, 0, 0, 8192, 8192);
3498                 wl_list_insert(&compositor->fade_layer.surface_list,
3499                                &surface->layer_link);
3500                 pixman_region32_fini(&surface->input);
3501                 pixman_region32_init(&surface->input);
3502
3503                 /* Here's the dirty little trick that makes the
3504                  * repaint debugging work: we move the surface to a
3505                  * different plane and force an update_transform to
3506                  * update dependent state and clear the
3507                  * geometry.dirty bit.  This way the call to
3508                  * damage_below() in update_transform() does not
3509                  * add damage to the primary plane.  */
3510
3511                 weston_plane_init(&plane, 0, 0);
3512                 surface->plane = &plane;
3513                 weston_surface_update_transform(surface);
3514                 shell->debug_repaint_surface = surface;
3515                 surface->plane = &compositor->primary_plane;
3516                 weston_plane_release(&plane);
3517         }
3518 }
3519
3520
3521 static void
3522 fan_debug_repaint_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
3523                       void *data)
3524 {
3525         struct desktop_shell *shell = data;
3526         struct weston_compositor *compositor = shell->compositor;
3527         compositor->fan_debug = !compositor->fan_debug;
3528         weston_compositor_damage_all(compositor);
3529 }
3530
3531 static void
3532 force_kill_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
3533                    void *data)
3534 {
3535         struct wl_surface *focus_surface;
3536         struct wl_client *client;
3537         struct desktop_shell *shell = data;
3538         struct weston_compositor *compositor = shell->compositor;
3539         pid_t pid;
3540
3541         focus_surface = seat->keyboard->focus;
3542         if (!focus_surface)
3543                 return;
3544
3545         wl_signal_emit(&compositor->kill_signal, focus_surface);
3546
3547         client = focus_surface->resource.client;
3548         wl_client_get_credentials(client, &pid, NULL, NULL);
3549
3550         /* Skip clients that we launched ourselves (the credentials of
3551          * the socketpair is ours) */
3552         if (pid == getpid())
3553                 return;
3554
3555         kill(pid, SIGKILL);
3556 }
3557
3558 static void
3559 workspace_up_binding(struct wl_seat *seat, uint32_t time,
3560                      uint32_t key, void *data)
3561 {
3562         struct desktop_shell *shell = data;
3563         unsigned int new_index = shell->workspaces.current;
3564
3565         if (shell->locked)
3566                 return;
3567         if (new_index != 0)
3568                 new_index--;
3569
3570         change_workspace(shell, new_index);
3571 }
3572
3573 static void
3574 workspace_down_binding(struct wl_seat *seat, uint32_t time,
3575                        uint32_t key, void *data)
3576 {
3577         struct desktop_shell *shell = data;
3578         unsigned int new_index = shell->workspaces.current;
3579
3580         if (shell->locked)
3581                 return;
3582         if (new_index < shell->workspaces.num - 1)
3583                 new_index++;
3584
3585         change_workspace(shell, new_index);
3586 }
3587
3588 static void
3589 workspace_f_binding(struct wl_seat *seat, uint32_t time,
3590                     uint32_t key, void *data)
3591 {
3592         struct desktop_shell *shell = data;
3593         unsigned int new_index;
3594
3595         if (shell->locked)
3596                 return;
3597         new_index = key - KEY_F1;
3598         if (new_index >= shell->workspaces.num)
3599                 new_index = shell->workspaces.num - 1;
3600
3601         change_workspace(shell, new_index);
3602 }
3603
3604 static void
3605 workspace_move_surface_up_binding(struct wl_seat *seat, uint32_t time,
3606                                   uint32_t key, void *data)
3607 {
3608         struct desktop_shell *shell = data;
3609         unsigned int new_index = shell->workspaces.current;
3610
3611         if (shell->locked)
3612                 return;
3613
3614         if (new_index != 0)
3615                 new_index--;
3616
3617         take_surface_to_workspace_by_seat(shell, seat, new_index);
3618 }
3619
3620 static void
3621 workspace_move_surface_down_binding(struct wl_seat *seat, uint32_t time,
3622                                     uint32_t key, void *data)
3623 {
3624         struct desktop_shell *shell = data;
3625         unsigned int new_index = shell->workspaces.current;
3626
3627         if (shell->locked)
3628                 return;
3629
3630         if (new_index < shell->workspaces.num - 1)
3631                 new_index++;
3632
3633         take_surface_to_workspace_by_seat(shell, seat, new_index);
3634 }
3635
3636 static void
3637 shell_destroy(struct wl_listener *listener, void *data)
3638 {
3639         struct desktop_shell *shell =
3640                 container_of(listener, struct desktop_shell, destroy_listener);
3641         struct workspace **ws;
3642
3643         if (shell->child.client)
3644                 wl_client_destroy(shell->child.client);
3645
3646         wl_list_remove(&shell->lock_listener.link);
3647         wl_list_remove(&shell->unlock_listener.link);
3648         wl_list_remove(&shell->show_input_panel_listener.link);
3649         wl_list_remove(&shell->hide_input_panel_listener.link);
3650
3651         wl_array_for_each(ws, &shell->workspaces.array)
3652                 workspace_destroy(*ws);
3653         wl_array_release(&shell->workspaces.array);
3654
3655         free(shell->screensaver.path);
3656         free(shell);
3657 }
3658
3659 static void
3660 shell_add_bindings(struct weston_compositor *ec, struct desktop_shell *shell)
3661 {
3662         uint32_t mod;
3663         int i, num_workspace_bindings;
3664
3665         /* fixed bindings */
3666         weston_compositor_add_key_binding(ec, KEY_BACKSPACE,
3667                                           MODIFIER_CTRL | MODIFIER_ALT,
3668                                           terminate_binding, ec);
3669         weston_compositor_add_button_binding(ec, BTN_LEFT, 0,
3670                                              click_to_activate_binding,
3671                                              shell);
3672         weston_compositor_add_axis_binding(ec, WL_POINTER_AXIS_VERTICAL_SCROLL,
3673                                            MODIFIER_SUPER | MODIFIER_ALT,
3674                                            surface_opacity_binding, NULL);
3675         weston_compositor_add_axis_binding(ec, WL_POINTER_AXIS_VERTICAL_SCROLL,
3676                                            MODIFIER_SUPER, zoom_axis_binding,
3677                                            NULL);
3678
3679         /* configurable bindings */
3680         mod = shell->binding_modifier;
3681         weston_compositor_add_key_binding(ec, KEY_PAGEUP, mod,
3682                                           zoom_key_binding, NULL);
3683         weston_compositor_add_key_binding(ec, KEY_PAGEDOWN, mod,
3684                                           zoom_key_binding, NULL);
3685         weston_compositor_add_button_binding(ec, BTN_LEFT, mod, move_binding,
3686                                              shell);
3687         weston_compositor_add_button_binding(ec, BTN_MIDDLE, mod,
3688                                              resize_binding, shell);
3689         weston_compositor_add_button_binding(ec, BTN_RIGHT, mod,
3690                                              rotate_binding, NULL);
3691         weston_compositor_add_key_binding(ec, KEY_TAB, mod, switcher_binding,
3692                                           shell);
3693         weston_compositor_add_key_binding(ec, KEY_F9, mod, backlight_binding,
3694                                           ec);
3695         weston_compositor_add_key_binding(ec, KEY_BRIGHTNESSDOWN, 0,
3696                                           backlight_binding, ec);
3697         weston_compositor_add_key_binding(ec, KEY_F10, mod, backlight_binding,
3698                                           ec);
3699         weston_compositor_add_key_binding(ec, KEY_BRIGHTNESSUP, 0,
3700                                           backlight_binding, ec);
3701         weston_compositor_add_key_binding(ec, KEY_SPACE, mod | MODIFIER_SHIFT,
3702                                           debug_repaint_binding, shell);
3703         weston_compositor_add_key_binding(ec, KEY_SPACE, mod | MODIFIER_ALT,
3704                                           fan_debug_repaint_binding, shell);
3705         weston_compositor_add_key_binding(ec, KEY_K, mod,
3706                                           force_kill_binding, shell);
3707         weston_compositor_add_key_binding(ec, KEY_UP, mod,
3708                                           workspace_up_binding, shell);
3709         weston_compositor_add_key_binding(ec, KEY_DOWN, mod,
3710                                           workspace_down_binding, shell);
3711         weston_compositor_add_key_binding(ec, KEY_UP, mod | MODIFIER_SHIFT,
3712                                           workspace_move_surface_up_binding,
3713                                           shell);
3714         weston_compositor_add_key_binding(ec, KEY_DOWN, mod | MODIFIER_SHIFT,
3715                                           workspace_move_surface_down_binding,
3716                                           shell);
3717
3718         /* Add bindings for mod+F[1-6] for workspace 1 to 6. */
3719         if (shell->workspaces.num > 1) {
3720                 num_workspace_bindings = shell->workspaces.num;
3721                 if (num_workspace_bindings > 6)
3722                         num_workspace_bindings = 6;
3723                 for (i = 0; i < num_workspace_bindings; i++)
3724                         weston_compositor_add_key_binding(ec, KEY_F1 + i, mod,
3725                                                           workspace_f_binding,
3726                                                           shell);
3727         }
3728 }
3729
3730 WL_EXPORT int
3731 module_init(struct weston_compositor *ec)
3732 {
3733         struct weston_seat *seat;
3734         struct desktop_shell *shell;
3735         struct workspace **pws;
3736         unsigned int i;
3737         struct wl_event_loop *loop;
3738
3739         shell = malloc(sizeof *shell);
3740         if (shell == NULL)
3741                 return -1;
3742
3743         memset(shell, 0, sizeof *shell);
3744         shell->compositor = ec;
3745
3746         shell->destroy_listener.notify = shell_destroy;
3747         wl_signal_add(&ec->destroy_signal, &shell->destroy_listener);
3748         shell->lock_listener.notify = lock;
3749         wl_signal_add(&ec->lock_signal, &shell->lock_listener);
3750         shell->unlock_listener.notify = unlock;
3751         wl_signal_add(&ec->unlock_signal, &shell->unlock_listener);
3752         shell->show_input_panel_listener.notify = show_input_panels;
3753         wl_signal_add(&ec->show_input_panel_signal, &shell->show_input_panel_listener);
3754         shell->hide_input_panel_listener.notify = hide_input_panels;
3755         wl_signal_add(&ec->hide_input_panel_signal, &shell->hide_input_panel_listener);
3756         ec->ping_handler = ping_handler;
3757         ec->shell_interface.shell = shell;
3758         ec->shell_interface.create_shell_surface = create_shell_surface;
3759         ec->shell_interface.set_toplevel = set_toplevel;
3760         ec->shell_interface.set_transient = set_transient;
3761         ec->shell_interface.move = surface_move;
3762         ec->shell_interface.resize = surface_resize;
3763
3764         wl_list_init(&shell->screensaver.surfaces);
3765         wl_list_init(&shell->input_panel.surfaces);
3766
3767         weston_layer_init(&shell->fullscreen_layer, &ec->cursor_layer.link);
3768         weston_layer_init(&shell->panel_layer, &shell->fullscreen_layer.link);
3769         weston_layer_init(&shell->background_layer, &shell->panel_layer.link);
3770         weston_layer_init(&shell->lock_layer, NULL);
3771         weston_layer_init(&shell->input_panel_layer, NULL);
3772
3773         wl_array_init(&shell->workspaces.array);
3774         wl_list_init(&shell->workspaces.client_list);
3775
3776         shell_configuration(shell);
3777
3778         for (i = 0; i < shell->workspaces.num; i++) {
3779                 pws = wl_array_add(&shell->workspaces.array, sizeof *pws);
3780                 if (pws == NULL)
3781                         return -1;
3782
3783                 *pws = workspace_create();
3784                 if (*pws == NULL)
3785                         return -1;
3786         }
3787         activate_workspace(shell, 0);
3788
3789         wl_list_init(&shell->workspaces.anim_sticky_list);
3790         wl_list_init(&shell->workspaces.animation.link);
3791         shell->workspaces.animation.frame = animate_workspace_change_frame;
3792
3793         if (wl_display_add_global(ec->wl_display, &wl_shell_interface,
3794                                   shell, bind_shell) == NULL)
3795                 return -1;
3796
3797         if (wl_display_add_global(ec->wl_display,
3798                                   &desktop_shell_interface,
3799                                   shell, bind_desktop_shell) == NULL)
3800                 return -1;
3801
3802         if (wl_display_add_global(ec->wl_display, &screensaver_interface,
3803                                   shell, bind_screensaver) == NULL)
3804                 return -1;
3805
3806         if (wl_display_add_global(ec->wl_display, &input_panel_interface,
3807                                   shell, bind_input_panel) == NULL)
3808                 return -1;
3809
3810         if (wl_display_add_global(ec->wl_display, &workspace_manager_interface,
3811                                   shell, bind_workspace_manager) == NULL)
3812                 return -1;
3813
3814         shell->child.deathstamp = weston_compositor_get_time();
3815
3816         loop = wl_display_get_event_loop(ec->wl_display);
3817         wl_event_loop_add_idle(loop, launch_desktop_shell_process, shell);
3818
3819         wl_list_for_each(seat, &ec->seat_list, link)
3820                 create_pointer_focus_listener(seat);
3821
3822         shell_add_bindings(ec, shell);
3823
3824         return 0;
3825 }