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