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