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