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