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