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