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