2 * Copyright © 2010-2012 Intel Corporation
3 * Copyright © 2011-2012 Collabora, Ltd.
4 * Copyright © 2013 TOYOTA MOTOR CORPORATION.
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.
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.
30 #include <linux/input.h>
34 #include <sys/types.h>
36 #include <wayland-server.h>
37 #include <weston/compositor.h>
38 #include "desktop-shell-server-protocol.h"
39 #include "input-method-server-protocol.h"
40 #include "workspaces-server-protocol.h"
41 #include <weston/config-parser.h>
42 #include "ico_ivi_shell.h"
44 #define DEFAULT_NUM_WORKSPACES 1
45 #define DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH 200
60 struct weston_seat *seat;
62 struct weston_surface *keyboard_focus;
64 struct wl_listener seat_destroy_listener;
65 struct wl_listener surface_destroy_listener;
69 struct weston_layer layer;
71 struct wl_list focus_list;
72 struct wl_listener seat_destroyed_listener;
75 struct input_panel_surface {
76 struct wl_resource *resource;
77 struct wl_signal destroy_signal;
79 struct desktop_shell *shell;
82 struct weston_surface *surface;
83 struct wl_listener surface_destroy_listener;
85 struct weston_output *output;
89 struct desktop_shell {
90 struct weston_compositor *compositor;
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;
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;
105 struct wl_listener pointer_focus_listener;
106 struct weston_surface *grab_surface;
109 struct weston_process process;
110 struct wl_client *client;
111 struct wl_resource *desktop_shell;
118 bool showing_input_panels;
119 bool prepare_event_sent;
122 struct weston_surface *surface;
123 pixman_box32_t cursor_rectangle;
126 struct weston_surface *lock_surface;
127 struct wl_listener lock_surface_listener;
130 struct wl_array array;
131 unsigned int current;
134 struct wl_list client_list;
136 struct weston_animation animation;
137 struct wl_list anim_sticky_list;
139 uint32_t anim_timestamp;
141 struct workspace *anim_from;
142 struct workspace *anim_to;
148 struct wl_resource *binding;
149 struct weston_process process;
150 struct wl_event_source *timer;
154 struct wl_resource *binding;
155 struct wl_list surfaces;
159 struct weston_surface *surface;
160 struct weston_surface_animation *animation;
162 struct wl_event_source *startup_timer;
165 uint32_t binding_modifier;
166 enum animation_type win_animation_type;
169 enum shell_surface_type {
171 SHELL_SURFACE_TOPLEVEL,
172 SHELL_SURFACE_TRANSIENT,
173 SHELL_SURFACE_FULLSCREEN,
174 SHELL_SURFACE_MAXIMIZED,
176 SHELL_SURFACE_XWAYLAND
180 struct wl_event_source *source;
184 struct shell_surface {
185 struct wl_resource *resource;
186 struct wl_signal destroy_signal;
188 struct weston_surface *surface;
189 struct wl_listener surface_destroy_listener;
190 struct weston_surface *parent;
191 struct desktop_shell *shell;
193 enum shell_surface_type type, next_type;
195 int32_t saved_x, saved_y;
196 bool saved_position_valid;
197 bool saved_rotation_valid;
201 struct weston_transform transform;
202 struct weston_matrix rotation;
206 struct wl_list grab_link;
208 struct shell_seat *shseat;
218 enum wl_shell_surface_fullscreen_method type;
219 struct weston_transform transform; /* matrix from x, y */
221 struct weston_surface *black_surface;
224 struct ping_timer *ping_timer;
226 struct weston_transform workspace_transform;
228 struct weston_output *fullscreen_output;
229 struct weston_output *output;
232 const struct weston_shell_client *client;
236 struct weston_pointer_grab grab;
237 struct shell_surface *shsurf;
238 struct wl_listener shsurf_destroy_listener;
239 struct weston_pointer *pointer;
242 struct weston_move_grab {
243 struct shell_grab base;
248 struct shell_grab base;
249 struct weston_matrix rotation;
257 struct weston_seat *seat;
258 struct wl_listener seat_destroy_listener;
261 struct weston_pointer_grab grab;
262 struct wl_list surfaces_list;
263 struct wl_client *client;
269 activate(struct desktop_shell *shell, struct weston_surface *es,
270 struct weston_seat *seat);
272 static struct workspace *
273 get_current_workspace(struct desktop_shell *shell);
275 static struct shell_surface *
276 get_shell_surface(struct weston_surface *surface);
278 static struct desktop_shell *
279 shell_surface_get_shell(struct shell_surface *shsurf);
282 surface_rotate(struct shell_surface *surface, struct weston_seat *seat);
285 shell_fade_startup(struct desktop_shell *shell);
287 /* shell management table */
288 static struct desktop_shell *_ico_ivi_shell = NULL;
289 /* shell program path for ico-ivi */
290 static char *shell_exe = NULL;
291 static int ico_debug_level = 3; /* Debug Level */
293 /* debug log macros */
294 #define uifw_trace(fmt,...) \
295 { if (ico_debug_level >= 4) {weston_log("DBG>"fmt" (%s:%d)\n",##__VA_ARGS__,__FILE__,__LINE__);} }
296 #define uifw_info(fmt,...) \
297 { if (ico_debug_level >= 3) {weston_log("INF>"fmt" (%s:%d)\n",##__VA_ARGS__,__FILE__,__LINE__);} }
298 #define uifw_warn(fmt,...) \
299 { if (ico_debug_level >= 2) {weston_log("WRN>"fmt" (%s:%d)\n",##__VA_ARGS__,__FILE__,__LINE__);} }
300 #define uifw_error(fmt,...) \
301 { if (ico_debug_level >= 1) {weston_log("ERR>"fmt" (%s:%d)\n",##__VA_ARGS__,__FILE__,__LINE__);} }
304 static void (*shell_hook_bind)(struct wl_client *client, void *shell) = NULL;
305 static void (*shell_hook_unbind)(struct wl_client *client) = NULL;
306 static void (*shell_hook_create)(struct wl_client *client, struct wl_resource *resource,
307 struct weston_surface *surface,
308 struct shell_surface *shsurf) = NULL;
309 static void (*shell_hook_destroy)(struct weston_surface *surface) = NULL;
310 static void (*shell_hook_map)(struct weston_surface *surface, int32_t *width,
311 int32_t *height, int32_t *sx, int32_t *sy) = NULL;
312 static void (*shell_hook_change)(struct weston_surface *surface, const int to,
313 const int manager) = NULL;
314 static void (*shell_hook_select)(struct weston_surface *surface) = NULL;
315 static void (*shell_hook_title)(struct weston_surface *surface, const char *title) = NULL;
316 static void (*shell_hook_move)(struct weston_surface *surface, int *dx, int *dy) = NULL;
319 shell_surface_is_top_fullscreen(struct shell_surface *shsurf)
321 struct desktop_shell *shell;
322 struct weston_surface *top_fs_es;
324 shell = shell_surface_get_shell(shsurf);
326 if (wl_list_empty(&shell->fullscreen_layer.surface_list))
329 top_fs_es = container_of(shell->fullscreen_layer.surface_list.next,
330 struct weston_surface,
332 return (shsurf == get_shell_surface(top_fs_es));
336 destroy_shell_grab_shsurf(struct wl_listener *listener, void *data)
338 struct shell_grab *grab;
340 grab = container_of(listener, struct shell_grab,
341 shsurf_destroy_listener);
347 popup_grab_end(struct weston_pointer *pointer);
350 shell_grab_start(struct shell_grab *grab,
351 const struct weston_pointer_grab_interface *interface,
352 struct shell_surface *shsurf,
353 struct weston_pointer *pointer,
354 enum desktop_shell_cursor cursor)
356 struct desktop_shell *shell = shsurf->shell;
358 popup_grab_end(pointer);
360 grab->grab.interface = interface;
361 grab->shsurf = shsurf;
362 grab->shsurf_destroy_listener.notify = destroy_shell_grab_shsurf;
363 wl_signal_add(&shsurf->destroy_signal,
364 &grab->shsurf_destroy_listener);
366 grab->pointer = pointer;
368 weston_pointer_start_grab(pointer, &grab->grab);
369 if (shell->child.desktop_shell) {
370 desktop_shell_send_grab_cursor(shell->child.desktop_shell,
372 weston_pointer_set_focus(pointer, shell->grab_surface,
373 wl_fixed_from_int(0),
374 wl_fixed_from_int(0));
379 shell_grab_end(struct shell_grab *grab)
382 wl_list_remove(&grab->shsurf_destroy_listener.link);
384 weston_pointer_end_grab(grab->pointer);
388 center_on_output(struct weston_surface *surface,
389 struct weston_output *output);
391 static enum weston_keyboard_modifier
392 get_modifier(char *modifier)
395 return MODIFIER_SUPER;
397 if (!strcmp("ctrl", modifier))
398 return MODIFIER_CTRL;
399 else if (!strcmp("alt", modifier))
401 else if (!strcmp("super", modifier))
402 return MODIFIER_SUPER;
404 return MODIFIER_SUPER;
407 static enum animation_type
408 get_animation_type(char *animation)
411 return ANIMATION_NONE;
413 if (!strcmp("zoom", animation))
414 return ANIMATION_ZOOM;
415 else if (!strcmp("fade", animation))
416 return ANIMATION_FADE;
418 return ANIMATION_NONE;
422 shell_configuration(struct desktop_shell *shell)
424 struct weston_config_section *section;
428 section = weston_config_get_section(shell->compositor->config,
429 "screensaver", NULL, NULL);
430 weston_config_section_get_string(section,
431 "path", &shell->screensaver.path, NULL);
432 weston_config_section_get_int(section, "duration", &duration, 60);
433 shell->screensaver.duration = duration * 1000;
435 section = weston_config_get_section(shell->compositor->config,
436 "shell", NULL, NULL);
437 weston_config_section_get_string(section,
438 "binding-modifier", &s, "super");
439 shell->binding_modifier = get_modifier(s);
441 weston_config_section_get_string(section, "animation", &s, "none");
442 shell->win_animation_type = get_animation_type(s);
444 weston_config_section_get_uint(section, "num-workspaces",
445 &shell->workspaces.num,
446 DEFAULT_NUM_WORKSPACES);
447 /* shell program path for ico-ivi */
448 weston_config_section_get_string(section, "shell-exe", &shell_exe,
449 LIBEXECDIR "/weston-desktop-shell");
450 weston_log("ws=%d exe=%s\n", shell->workspaces.num, shell_exe);
452 /* get debug level for ivi debug */
453 section = weston_config_get_section(shell->compositor->config, "ivi-debug", NULL, NULL);
455 weston_config_section_get_int(section, "log", &ico_debug_level, 3);
460 focus_state_destroy(struct focus_state *state)
462 wl_list_remove(&state->seat_destroy_listener.link);
463 wl_list_remove(&state->surface_destroy_listener.link);
468 focus_state_seat_destroy(struct wl_listener *listener, void *data)
470 struct focus_state *state = container_of(listener,
472 seat_destroy_listener);
474 wl_list_remove(&state->link);
475 focus_state_destroy(state);
479 focus_state_surface_destroy(struct wl_listener *listener, void *data)
481 struct focus_state *state = container_of(listener,
483 surface_destroy_listener);
484 struct desktop_shell *shell;
485 struct weston_surface *main_surface;
486 struct weston_surface *surface, *next;
488 main_surface = weston_surface_get_main_surface(state->keyboard_focus);
491 wl_list_for_each(surface, &state->ws->layer.surface_list, layer_link) {
492 if (surface == main_surface)
499 /* if the focus was a sub-surface, activate its main surface */
500 if (main_surface != state->keyboard_focus)
504 shell = state->seat->compositor->shell_interface.shell;
505 activate(shell, next, state->seat);
507 wl_list_remove(&state->link);
508 focus_state_destroy(state);
512 static struct focus_state *
513 focus_state_create(struct weston_seat *seat, struct workspace *ws)
515 struct focus_state *state;
517 state = malloc(sizeof *state);
523 wl_list_insert(&ws->focus_list, &state->link);
525 state->seat_destroy_listener.notify = focus_state_seat_destroy;
526 state->surface_destroy_listener.notify = focus_state_surface_destroy;
527 wl_signal_add(&seat->destroy_signal,
528 &state->seat_destroy_listener);
529 wl_list_init(&state->surface_destroy_listener.link);
534 static struct focus_state *
535 ensure_focus_state(struct desktop_shell *shell, struct weston_seat *seat)
537 struct workspace *ws = get_current_workspace(shell);
538 struct focus_state *state;
540 wl_list_for_each(state, &ws->focus_list, link)
541 if (state->seat == seat)
544 if (&state->link == &ws->focus_list)
545 state = focus_state_create(seat, ws);
551 restore_focus_state(struct desktop_shell *shell, struct workspace *ws)
553 struct focus_state *state, *next;
554 struct weston_surface *surface;
556 wl_list_for_each_safe(state, next, &ws->focus_list, link) {
557 surface = state->keyboard_focus;
559 weston_keyboard_set_focus(state->seat->keyboard, surface);
564 replace_focus_state(struct desktop_shell *shell, struct workspace *ws,
565 struct weston_seat *seat)
567 struct focus_state *state;
568 struct weston_surface *surface;
570 wl_list_for_each(state, &ws->focus_list, link) {
571 if (state->seat == seat) {
572 surface = seat->keyboard->focus;
573 state->keyboard_focus = surface;
580 drop_focus_state(struct desktop_shell *shell, struct workspace *ws,
581 struct weston_surface *surface)
583 struct focus_state *state;
585 wl_list_for_each(state, &ws->focus_list, link)
586 if (state->keyboard_focus == surface)
587 state->keyboard_focus = NULL;
591 workspace_destroy(struct workspace *ws)
593 struct focus_state *state, *next;
595 wl_list_for_each_safe(state, next, &ws->focus_list, link)
596 focus_state_destroy(state);
602 seat_destroyed(struct wl_listener *listener, void *data)
604 struct weston_seat *seat = data;
605 struct focus_state *state, *next;
606 struct workspace *ws = container_of(listener,
608 seat_destroyed_listener);
610 wl_list_for_each_safe(state, next, &ws->focus_list, link)
611 if (state->seat == seat)
612 wl_list_remove(&state->link);
615 static struct workspace *
616 workspace_create(void)
618 struct workspace *ws = malloc(sizeof *ws);
622 weston_layer_init(&ws->layer, NULL);
624 wl_list_init(&ws->focus_list);
625 wl_list_init(&ws->seat_destroyed_listener.link);
626 ws->seat_destroyed_listener.notify = seat_destroyed;
632 workspace_is_empty(struct workspace *ws)
634 return wl_list_empty(&ws->layer.surface_list);
637 static struct workspace *
638 get_workspace(struct desktop_shell *shell, unsigned int index)
640 struct workspace **pws = shell->workspaces.array.data;
641 assert(index < shell->workspaces.num);
646 static struct workspace *
647 get_current_workspace(struct desktop_shell *shell)
649 return get_workspace(shell, shell->workspaces.current);
653 activate_workspace(struct desktop_shell *shell, unsigned int index)
655 struct workspace *ws;
657 ws = get_workspace(shell, index);
658 wl_list_insert(&shell->panel_layer.link, &ws->layer.link);
660 shell->workspaces.current = index;
664 get_output_height(struct weston_output *output)
666 return abs(output->region.extents.y1 - output->region.extents.y2);
670 surface_translate(struct weston_surface *surface, double d)
672 struct shell_surface *shsurf = get_shell_surface(surface);
673 struct weston_transform *transform;
675 transform = &shsurf->workspace_transform;
676 if (wl_list_empty(&transform->link))
677 wl_list_insert(surface->geometry.transformation_list.prev,
678 &shsurf->workspace_transform.link);
680 weston_matrix_init(&shsurf->workspace_transform.matrix);
681 weston_matrix_translate(&shsurf->workspace_transform.matrix,
683 weston_surface_geometry_dirty(surface);
687 workspace_translate_out(struct workspace *ws, double fraction)
689 struct weston_surface *surface;
693 wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
694 height = get_output_height(surface->output);
695 d = height * fraction;
697 surface_translate(surface, d);
702 workspace_translate_in(struct workspace *ws, double fraction)
704 struct weston_surface *surface;
708 wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
709 height = get_output_height(surface->output);
712 d = -(height - height * fraction);
714 d = height + height * fraction;
716 surface_translate(surface, d);
721 broadcast_current_workspace_state(struct desktop_shell *shell)
723 struct wl_list *link;
725 for (link = shell->workspaces.client_list.next;
726 link != &shell->workspaces.client_list;
728 workspace_manager_send_state(wl_resource_from_link(link),
729 shell->workspaces.current,
730 shell->workspaces.num);
735 reverse_workspace_change_animation(struct desktop_shell *shell,
737 struct workspace *from,
738 struct workspace *to)
740 shell->workspaces.current = index;
742 shell->workspaces.anim_to = to;
743 shell->workspaces.anim_from = from;
744 shell->workspaces.anim_dir = -1 * shell->workspaces.anim_dir;
745 shell->workspaces.anim_timestamp = 0;
747 weston_compositor_schedule_repaint(shell->compositor);
751 workspace_deactivate_transforms(struct workspace *ws)
753 struct weston_surface *surface;
754 struct shell_surface *shsurf;
756 wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
757 shsurf = get_shell_surface(surface);
758 if (!wl_list_empty(&shsurf->workspace_transform.link)) {
759 wl_list_remove(&shsurf->workspace_transform.link);
760 wl_list_init(&shsurf->workspace_transform.link);
762 weston_surface_geometry_dirty(surface);
767 finish_workspace_change_animation(struct desktop_shell *shell,
768 struct workspace *from,
769 struct workspace *to)
771 weston_compositor_schedule_repaint(shell->compositor);
773 wl_list_remove(&shell->workspaces.animation.link);
774 workspace_deactivate_transforms(from);
775 workspace_deactivate_transforms(to);
776 shell->workspaces.anim_to = NULL;
778 wl_list_remove(&shell->workspaces.anim_from->layer.link);
782 animate_workspace_change_frame(struct weston_animation *animation,
783 struct weston_output *output, uint32_t msecs)
785 struct desktop_shell *shell =
786 container_of(animation, struct desktop_shell,
787 workspaces.animation);
788 struct workspace *from = shell->workspaces.anim_from;
789 struct workspace *to = shell->workspaces.anim_to;
793 if (workspace_is_empty(from) && workspace_is_empty(to)) {
794 finish_workspace_change_animation(shell, from, to);
798 if (shell->workspaces.anim_timestamp == 0) {
799 if (shell->workspaces.anim_current == 0.0)
800 shell->workspaces.anim_timestamp = msecs;
802 shell->workspaces.anim_timestamp =
804 /* Invers of movement function 'y' below. */
805 (asin(1.0 - shell->workspaces.anim_current) *
806 DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH *
810 t = msecs - shell->workspaces.anim_timestamp;
816 x = t * (1.0/DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH) * M_PI_2;
819 if (t < DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH) {
820 weston_compositor_schedule_repaint(shell->compositor);
822 workspace_translate_out(from, shell->workspaces.anim_dir * y);
823 workspace_translate_in(to, shell->workspaces.anim_dir * y);
824 shell->workspaces.anim_current = y;
826 weston_compositor_schedule_repaint(shell->compositor);
829 finish_workspace_change_animation(shell, from, to);
833 animate_workspace_change(struct desktop_shell *shell,
835 struct workspace *from,
836 struct workspace *to)
838 struct weston_output *output;
842 if (index > shell->workspaces.current)
847 shell->workspaces.current = index;
849 shell->workspaces.anim_dir = dir;
850 shell->workspaces.anim_from = from;
851 shell->workspaces.anim_to = to;
852 shell->workspaces.anim_current = 0.0;
853 shell->workspaces.anim_timestamp = 0;
855 output = container_of(shell->compositor->output_list.next,
856 struct weston_output, link);
857 wl_list_insert(&output->animation_list,
858 &shell->workspaces.animation.link);
860 wl_list_insert(from->layer.link.prev, &to->layer.link);
862 workspace_translate_in(to, 0);
864 restore_focus_state(shell, to);
866 weston_compositor_schedule_repaint(shell->compositor);
870 update_workspace(struct desktop_shell *shell, unsigned int index,
871 struct workspace *from, struct workspace *to)
873 shell->workspaces.current = index;
874 wl_list_insert(&from->layer.link, &to->layer.link);
875 wl_list_remove(&from->layer.link);
879 change_workspace(struct desktop_shell *shell, unsigned int index)
881 struct workspace *from;
882 struct workspace *to;
884 if (index == shell->workspaces.current)
887 /* Don't change workspace when there is any fullscreen surfaces. */
888 if (!wl_list_empty(&shell->fullscreen_layer.surface_list))
891 from = get_current_workspace(shell);
892 to = get_workspace(shell, index);
894 if (shell->workspaces.anim_from == to &&
895 shell->workspaces.anim_to == from) {
896 restore_focus_state(shell, to);
897 reverse_workspace_change_animation(shell, index, from, to);
898 broadcast_current_workspace_state(shell);
902 if (shell->workspaces.anim_to != NULL)
903 finish_workspace_change_animation(shell,
904 shell->workspaces.anim_from,
905 shell->workspaces.anim_to);
907 restore_focus_state(shell, to);
909 if (workspace_is_empty(to) && workspace_is_empty(from))
910 update_workspace(shell, index, from, to);
912 animate_workspace_change(shell, index, from, to);
914 broadcast_current_workspace_state(shell);
918 workspace_has_only(struct workspace *ws, struct weston_surface *surface)
920 struct wl_list *list = &ws->layer.surface_list;
923 if (wl_list_empty(list))
931 return container_of(e, struct weston_surface, layer_link) == surface;
935 move_surface_to_workspace(struct desktop_shell *shell,
936 struct weston_surface *surface,
939 struct workspace *from;
940 struct workspace *to;
941 struct weston_seat *seat;
942 struct weston_surface *focus;
944 assert(weston_surface_get_main_surface(surface) == surface);
946 if (workspace == shell->workspaces.current)
949 if (workspace >= shell->workspaces.num)
950 workspace = shell->workspaces.num - 1;
952 from = get_current_workspace(shell);
953 to = get_workspace(shell, workspace);
955 wl_list_remove(&surface->layer_link);
956 wl_list_insert(&to->layer.surface_list, &surface->layer_link);
958 drop_focus_state(shell, from, surface);
959 wl_list_for_each(seat, &shell->compositor->seat_list, link) {
963 focus = weston_surface_get_main_surface(seat->keyboard->focus);
964 if (focus == surface)
965 weston_keyboard_set_focus(seat->keyboard, NULL);
968 weston_surface_damage_below(surface);
972 take_surface_to_workspace_by_seat(struct desktop_shell *shell,
973 struct weston_seat *seat,
976 struct weston_surface *surface;
977 struct shell_surface *shsurf;
978 struct workspace *from;
979 struct workspace *to;
980 struct focus_state *state;
982 surface = weston_surface_get_main_surface(seat->keyboard->focus);
983 if (surface == NULL ||
984 index == shell->workspaces.current)
987 from = get_current_workspace(shell);
988 to = get_workspace(shell, index);
990 wl_list_remove(&surface->layer_link);
991 wl_list_insert(&to->layer.surface_list, &surface->layer_link);
993 replace_focus_state(shell, to, seat);
994 drop_focus_state(shell, from, surface);
996 if (shell->workspaces.anim_from == to &&
997 shell->workspaces.anim_to == from) {
998 wl_list_remove(&to->layer.link);
999 wl_list_insert(from->layer.link.prev, &to->layer.link);
1001 reverse_workspace_change_animation(shell, index, from, to);
1002 broadcast_current_workspace_state(shell);
1007 if (shell->workspaces.anim_to != NULL)
1008 finish_workspace_change_animation(shell,
1009 shell->workspaces.anim_from,
1010 shell->workspaces.anim_to);
1012 if (workspace_is_empty(from) &&
1013 workspace_has_only(to, surface))
1014 update_workspace(shell, index, from, to);
1016 shsurf = get_shell_surface(surface);
1017 if (wl_list_empty(&shsurf->workspace_transform.link))
1018 wl_list_insert(&shell->workspaces.anim_sticky_list,
1019 &shsurf->workspace_transform.link);
1021 animate_workspace_change(shell, index, from, to);
1024 broadcast_current_workspace_state(shell);
1026 state = ensure_focus_state(shell, seat);
1028 state->keyboard_focus = surface;
1032 workspace_manager_move_surface(struct wl_client *client,
1033 struct wl_resource *resource,
1034 struct wl_resource *surface_resource,
1037 struct desktop_shell *shell = wl_resource_get_user_data(resource);
1038 struct weston_surface *surface =
1039 wl_resource_get_user_data(surface_resource);
1040 struct weston_surface *main_surface;
1042 main_surface = weston_surface_get_main_surface(surface);
1043 move_surface_to_workspace(shell, main_surface, workspace);
1046 static const struct workspace_manager_interface workspace_manager_implementation = {
1047 workspace_manager_move_surface,
1051 unbind_resource(struct wl_resource *resource)
1053 wl_list_remove(wl_resource_get_link(resource));
1057 bind_workspace_manager(struct wl_client *client,
1058 void *data, uint32_t version, uint32_t id)
1060 struct desktop_shell *shell = data;
1061 struct wl_resource *resource;
1063 resource = wl_resource_create(client,
1064 &workspace_manager_interface, 1, id);
1066 if (resource == NULL) {
1067 weston_log("couldn't add workspace manager object");
1071 wl_resource_set_implementation(resource,
1072 &workspace_manager_implementation,
1073 shell, unbind_resource);
1074 wl_list_insert(&shell->workspaces.client_list,
1075 wl_resource_get_link(resource));
1077 workspace_manager_send_state(resource,
1078 shell->workspaces.current,
1079 shell->workspaces.num);
1083 noop_grab_focus(struct weston_pointer_grab *grab)
1088 move_grab_motion(struct weston_pointer_grab *grab, uint32_t time)
1090 struct weston_move_grab *move = (struct weston_move_grab *) grab;
1091 struct weston_pointer *pointer = grab->pointer;
1092 struct shell_surface *shsurf = move->base.shsurf;
1093 struct weston_surface *es;
1094 int dx = wl_fixed_to_int(pointer->x + move->dx);
1095 int dy = wl_fixed_to_int(pointer->y + move->dy);
1100 es = shsurf->surface;
1102 uifw_trace("move_grab_motion: configure %08x x/y=%d/%d w/h=%d/%d",
1103 (int)es, (int)dx, (int)dy, es->geometry.width, es->geometry.height);
1105 /* ico-ivi-shell hook move */
1106 if (shell_hook_move) {
1107 (*shell_hook_move)(shsurf->surface, &dx, &dy);
1109 weston_surface_configure(es, dx, dy,
1110 es->geometry.width, es->geometry.height);
1112 weston_compositor_schedule_repaint(es->compositor);
1116 move_grab_button(struct weston_pointer_grab *grab,
1117 uint32_t time, uint32_t button, uint32_t state_w)
1119 struct shell_grab *shell_grab = container_of(grab, struct shell_grab,
1121 struct weston_pointer *pointer = grab->pointer;
1122 enum wl_pointer_button_state state = state_w;
1124 if (pointer->button_count == 0 &&
1125 state == WL_POINTER_BUTTON_STATE_RELEASED) {
1126 shell_grab_end(shell_grab);
1131 static const struct weston_pointer_grab_interface move_grab_interface = {
1138 surface_move(struct shell_surface *shsurf, struct weston_seat *seat)
1140 struct weston_move_grab *move;
1145 if (shsurf->type == SHELL_SURFACE_FULLSCREEN)
1148 move = malloc(sizeof *move);
1152 move->dx = wl_fixed_from_double(shsurf->surface->geometry.x) -
1153 seat->pointer->grab_x;
1154 move->dy = wl_fixed_from_double(shsurf->surface->geometry.y) -
1155 seat->pointer->grab_y;
1157 shell_grab_start(&move->base, &move_grab_interface, shsurf,
1158 seat->pointer, DESKTOP_SHELL_CURSOR_MOVE);
1164 shell_surface_move(struct wl_client *client, struct wl_resource *resource,
1165 struct wl_resource *seat_resource, uint32_t serial)
1167 struct weston_seat *seat = wl_resource_get_user_data(seat_resource);
1168 struct shell_surface *shsurf = wl_resource_get_user_data(resource);
1169 struct weston_surface *surface;
1171 surface = weston_surface_get_main_surface(seat->pointer->focus);
1172 if (seat->pointer->button_count == 0 ||
1173 seat->pointer->grab_serial != serial ||
1174 surface != shsurf->surface)
1177 if (surface_move(shsurf, seat) < 0)
1178 wl_resource_post_no_memory(resource);
1181 struct weston_resize_grab {
1182 struct shell_grab base;
1184 int32_t width, height;
1188 resize_grab_motion(struct weston_pointer_grab *grab, uint32_t time)
1190 struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
1191 struct weston_pointer *pointer = grab->pointer;
1192 struct shell_surface *shsurf = resize->base.shsurf;
1193 int32_t width, height;
1194 wl_fixed_t from_x, from_y;
1195 wl_fixed_t to_x, to_y;
1200 weston_surface_from_global_fixed(shsurf->surface,
1201 pointer->grab_x, pointer->grab_y,
1203 weston_surface_from_global_fixed(shsurf->surface,
1204 pointer->x, pointer->y, &to_x, &to_y);
1206 width = resize->width;
1207 if (resize->edges & WL_SHELL_SURFACE_RESIZE_LEFT) {
1208 width += wl_fixed_to_int(from_x - to_x);
1209 } else if (resize->edges & WL_SHELL_SURFACE_RESIZE_RIGHT) {
1210 width += wl_fixed_to_int(to_x - from_x);
1213 height = resize->height;
1214 if (resize->edges & WL_SHELL_SURFACE_RESIZE_TOP) {
1215 height += wl_fixed_to_int(from_y - to_y);
1216 } else if (resize->edges & WL_SHELL_SURFACE_RESIZE_BOTTOM) {
1217 height += wl_fixed_to_int(to_y - from_y);
1220 uifw_trace("resize_grab_motion: send configure %08x %x w/h=%d/%d",
1221 (int)shsurf->surface, resize->edges, width, height);
1222 shsurf->client->send_configure(shsurf->surface,
1223 resize->edges, width, height);
1227 send_configure(struct weston_surface *surface,
1228 uint32_t edges, int32_t width, int32_t height)
1230 struct shell_surface *shsurf = get_shell_surface(surface);
1232 uifw_trace("send_configure: send %08x %x w/h=%d/%d",
1233 (int)shsurf->surface, edges, width, height);
1234 wl_shell_surface_send_configure(shsurf->resource,
1235 edges, width, height);
1238 static const struct weston_shell_client shell_client = {
1243 resize_grab_button(struct weston_pointer_grab *grab,
1244 uint32_t time, uint32_t button, uint32_t state_w)
1246 struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
1247 struct weston_pointer *pointer = grab->pointer;
1248 enum wl_pointer_button_state state = state_w;
1250 if (pointer->button_count == 0 &&
1251 state == WL_POINTER_BUTTON_STATE_RELEASED) {
1252 shell_grab_end(&resize->base);
1257 static const struct weston_pointer_grab_interface resize_grab_interface = {
1264 * Returns the bounding box of a surface and all its sub-surfaces,
1265 * in the surface coordinates system. */
1267 surface_subsurfaces_boundingbox(struct weston_surface *surface, int32_t *x,
1268 int32_t *y, int32_t *w, int32_t *h) {
1269 pixman_region32_t region;
1270 pixman_box32_t *box;
1271 struct weston_subsurface *subsurface;
1273 pixman_region32_init_rect(®ion, 0, 0,
1274 surface->geometry.width,
1275 surface->geometry.height);
1277 wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) {
1278 pixman_region32_union_rect(®ion, ®ion,
1279 subsurface->position.x,
1280 subsurface->position.y,
1281 subsurface->surface->geometry.width,
1282 subsurface->surface->geometry.height);
1285 box = pixman_region32_extents(®ion);
1291 *w = box->x2 - box->x1;
1293 *h = box->y2 - box->y1;
1295 pixman_region32_fini(®ion);
1299 surface_resize(struct shell_surface *shsurf,
1300 struct weston_seat *seat, uint32_t edges)
1302 struct weston_resize_grab *resize;
1304 if (shsurf->type == SHELL_SURFACE_FULLSCREEN ||
1305 shsurf->type == SHELL_SURFACE_MAXIMIZED)
1308 if (edges == 0 || edges > 15 ||
1309 (edges & 3) == 3 || (edges & 12) == 12)
1312 resize = malloc(sizeof *resize);
1316 resize->edges = edges;
1317 surface_subsurfaces_boundingbox(shsurf->surface, NULL, NULL,
1318 &resize->width, &resize->height);
1320 shell_grab_start(&resize->base, &resize_grab_interface, shsurf,
1321 seat->pointer, edges);
1327 shell_surface_resize(struct wl_client *client, struct wl_resource *resource,
1328 struct wl_resource *seat_resource, uint32_t serial,
1331 struct weston_seat *seat = wl_resource_get_user_data(seat_resource);
1332 struct shell_surface *shsurf = wl_resource_get_user_data(resource);
1333 struct weston_surface *surface;
1335 if (shsurf->type == SHELL_SURFACE_FULLSCREEN)
1338 surface = weston_surface_get_main_surface(seat->pointer->focus);
1339 if (seat->pointer->button_count == 0 ||
1340 seat->pointer->grab_serial != serial ||
1341 surface != shsurf->surface)
1344 if (surface_resize(shsurf, seat, edges) < 0)
1345 wl_resource_post_no_memory(resource);
1349 end_busy_cursor(struct shell_surface *shsurf, struct weston_pointer *pointer);
1352 busy_cursor_grab_focus(struct weston_pointer_grab *base)
1354 struct shell_grab *grab = (struct shell_grab *) base;
1355 struct weston_pointer *pointer = base->pointer;
1356 struct weston_surface *surface;
1359 surface = weston_compositor_pick_surface(pointer->seat->compositor,
1360 pointer->x, pointer->y,
1363 if (!grab->shsurf || grab->shsurf->surface != surface)
1364 end_busy_cursor(grab->shsurf, pointer);
1368 busy_cursor_grab_motion(struct weston_pointer_grab *grab, uint32_t time)
1373 busy_cursor_grab_button(struct weston_pointer_grab *base,
1374 uint32_t time, uint32_t button, uint32_t state)
1376 struct shell_grab *grab = (struct shell_grab *) base;
1377 struct shell_surface *shsurf = grab->shsurf;
1378 struct weston_seat *seat = grab->grab.pointer->seat;
1380 if (shsurf && button == BTN_LEFT && state) {
1381 activate(shsurf->shell, shsurf->surface, seat);
1382 surface_move(shsurf, seat);
1383 } else if (shsurf && button == BTN_RIGHT && state) {
1384 activate(shsurf->shell, shsurf->surface, seat);
1385 surface_rotate(shsurf, seat);
1389 static const struct weston_pointer_grab_interface busy_cursor_grab_interface = {
1390 busy_cursor_grab_focus,
1391 busy_cursor_grab_motion,
1392 busy_cursor_grab_button,
1396 set_busy_cursor(struct shell_surface *shsurf, struct weston_pointer *pointer)
1398 struct shell_grab *grab;
1400 grab = malloc(sizeof *grab);
1404 shell_grab_start(grab, &busy_cursor_grab_interface, shsurf, pointer,
1405 DESKTOP_SHELL_CURSOR_BUSY);
1409 end_busy_cursor(struct shell_surface *shsurf, struct weston_pointer *pointer)
1411 struct shell_grab *grab = (struct shell_grab *) pointer->grab;
1413 if (grab->grab.interface == &busy_cursor_grab_interface &&
1414 grab->shsurf == shsurf) {
1415 shell_grab_end(grab);
1421 ping_timer_destroy(struct shell_surface *shsurf)
1423 if (!shsurf || !shsurf->ping_timer)
1426 if (shsurf->ping_timer->source)
1427 wl_event_source_remove(shsurf->ping_timer->source);
1429 free(shsurf->ping_timer);
1430 shsurf->ping_timer = NULL;
1434 ping_timeout_handler(void *data)
1436 struct shell_surface *shsurf = data;
1437 struct weston_seat *seat;
1439 /* Client is not responding */
1440 shsurf->unresponsive = 1;
1442 wl_list_for_each(seat, &shsurf->surface->compositor->seat_list, link)
1443 if (seat->pointer->focus == shsurf->surface)
1444 set_busy_cursor(shsurf, seat->pointer);
1450 ping_handler(struct weston_surface *surface, uint32_t serial)
1452 struct shell_surface *shsurf = get_shell_surface(surface);
1453 struct wl_event_loop *loop;
1454 int ping_timeout = 200;
1458 if (!shsurf->resource)
1461 if (shsurf->surface == shsurf->shell->grab_surface)
1464 if (!shsurf->ping_timer) {
1465 shsurf->ping_timer = malloc(sizeof *shsurf->ping_timer);
1466 if (!shsurf->ping_timer)
1469 shsurf->ping_timer->serial = serial;
1470 loop = wl_display_get_event_loop(surface->compositor->wl_display);
1471 shsurf->ping_timer->source =
1472 wl_event_loop_add_timer(loop, ping_timeout_handler, shsurf);
1473 wl_event_source_timer_update(shsurf->ping_timer->source, ping_timeout);
1475 wl_shell_surface_send_ping(shsurf->resource, serial);
1480 handle_pointer_focus(struct wl_listener *listener, void *data)
1482 struct weston_pointer *pointer = data;
1483 struct weston_surface *surface = pointer->focus;
1484 struct weston_compositor *compositor;
1485 struct shell_surface *shsurf;
1491 compositor = surface->compositor;
1492 shsurf = get_shell_surface(surface);
1494 if (shsurf && shsurf->unresponsive) {
1495 set_busy_cursor(shsurf, pointer);
1497 serial = wl_display_next_serial(compositor->wl_display);
1498 ping_handler(surface, serial);
1503 create_pointer_focus_listener(struct weston_seat *seat)
1505 struct wl_listener *listener;
1510 listener = malloc(sizeof *listener);
1511 listener->notify = handle_pointer_focus;
1512 wl_signal_add(&seat->pointer->focus_signal, listener);
1516 shell_surface_pong(struct wl_client *client, struct wl_resource *resource,
1519 struct shell_surface *shsurf = wl_resource_get_user_data(resource);
1520 struct weston_seat *seat;
1521 struct weston_compositor *ec = shsurf->surface->compositor;
1523 if (shsurf->ping_timer == NULL)
1524 /* Just ignore unsolicited pong. */
1527 if (shsurf->ping_timer->serial == serial) {
1528 shsurf->unresponsive = 0;
1529 wl_list_for_each(seat, &ec->seat_list, link) {
1531 end_busy_cursor(shsurf, seat->pointer);
1533 ping_timer_destroy(shsurf);
1538 shell_surface_set_title(struct wl_client *client,
1539 struct wl_resource *resource, const char *title)
1541 struct shell_surface *shsurf = wl_resource_get_user_data(resource);
1543 free(shsurf->title);
1544 shsurf->title = strdup(title);
1546 /* if ico_window_mgr hook, call hook routine */
1547 if (shell_hook_title) {
1548 (*shell_hook_title)(shsurf->surface, shsurf->title);
1553 shell_surface_set_class(struct wl_client *client,
1554 struct wl_resource *resource, const char *class)
1556 struct shell_surface *shsurf = wl_resource_get_user_data(resource);
1558 free(shsurf->class);
1559 shsurf->class = strdup(class);
1562 static struct weston_output *
1563 get_default_output(struct weston_compositor *compositor)
1565 return container_of(compositor->output_list.next,
1566 struct weston_output, link);
1570 restore_output_mode(struct weston_output *output)
1572 if (output->current != output->origin ||
1573 (int32_t)output->scale != output->origin_scale)
1574 weston_output_switch_mode(output,
1576 output->origin_scale);
1580 restore_all_output_modes(struct weston_compositor *compositor)
1582 struct weston_output *output;
1584 wl_list_for_each(output, &compositor->output_list, link)
1585 restore_output_mode(output);
1589 shell_unset_fullscreen(struct shell_surface *shsurf)
1591 struct workspace *ws;
1592 /* undo all fullscreen things here */
1593 if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
1594 shell_surface_is_top_fullscreen(shsurf)) {
1595 restore_output_mode(shsurf->fullscreen_output);
1597 shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
1598 shsurf->fullscreen.framerate = 0;
1599 wl_list_remove(&shsurf->fullscreen.transform.link);
1600 wl_list_init(&shsurf->fullscreen.transform.link);
1601 if (shsurf->fullscreen.black_surface)
1602 weston_surface_destroy(shsurf->fullscreen.black_surface);
1603 shsurf->fullscreen.black_surface = NULL;
1604 shsurf->fullscreen_output = NULL;
1605 weston_surface_set_position(shsurf->surface,
1606 shsurf->saved_x, shsurf->saved_y);
1607 if (shsurf->saved_rotation_valid) {
1608 wl_list_insert(&shsurf->surface->geometry.transformation_list,
1609 &shsurf->rotation.transform.link);
1610 shsurf->saved_rotation_valid = false;
1613 ws = get_current_workspace(shsurf->shell);
1614 wl_list_remove(&shsurf->surface->layer_link);
1615 wl_list_insert(&ws->layer.surface_list, &shsurf->surface->layer_link);
1619 shell_unset_maximized(struct shell_surface *shsurf)
1621 struct workspace *ws;
1622 /* undo all maximized things here */
1623 shsurf->output = get_default_output(shsurf->surface->compositor);
1624 weston_surface_set_position(shsurf->surface,
1628 if (shsurf->saved_rotation_valid) {
1629 wl_list_insert(&shsurf->surface->geometry.transformation_list,
1630 &shsurf->rotation.transform.link);
1631 shsurf->saved_rotation_valid = false;
1634 ws = get_current_workspace(shsurf->shell);
1635 wl_list_remove(&shsurf->surface->layer_link);
1636 wl_list_insert(&ws->layer.surface_list, &shsurf->surface->layer_link);
1640 reset_shell_surface_type(struct shell_surface *surface)
1642 switch (surface->type) {
1643 case SHELL_SURFACE_FULLSCREEN:
1644 shell_unset_fullscreen(surface);
1646 case SHELL_SURFACE_MAXIMIZED:
1647 shell_unset_maximized(surface);
1649 case SHELL_SURFACE_NONE:
1650 case SHELL_SURFACE_TOPLEVEL:
1651 case SHELL_SURFACE_TRANSIENT:
1652 case SHELL_SURFACE_POPUP:
1653 case SHELL_SURFACE_XWAYLAND:
1657 surface->type = SHELL_SURFACE_NONE;
1662 set_surface_type(struct shell_surface *shsurf)
1664 struct weston_surface *surface = shsurf->surface;
1665 struct weston_surface *pes = shsurf->parent;
1667 reset_shell_surface_type(shsurf);
1669 shsurf->type = shsurf->next_type;
1670 shsurf->next_type = SHELL_SURFACE_NONE;
1672 switch (shsurf->type) {
1673 case SHELL_SURFACE_TOPLEVEL:
1675 case SHELL_SURFACE_TRANSIENT:
1676 weston_surface_set_position(surface,
1677 pes->geometry.x + shsurf->transient.x,
1678 pes->geometry.y + shsurf->transient.y);
1681 case SHELL_SURFACE_MAXIMIZED:
1682 case SHELL_SURFACE_FULLSCREEN:
1683 shsurf->saved_x = surface->geometry.x;
1684 shsurf->saved_y = surface->geometry.y;
1685 shsurf->saved_position_valid = true;
1687 if (!wl_list_empty(&shsurf->rotation.transform.link)) {
1688 wl_list_remove(&shsurf->rotation.transform.link);
1689 wl_list_init(&shsurf->rotation.transform.link);
1690 weston_surface_geometry_dirty(shsurf->surface);
1691 shsurf->saved_rotation_valid = true;
1695 case SHELL_SURFACE_XWAYLAND:
1696 weston_surface_set_position(surface, shsurf->transient.x,
1697 shsurf->transient.y);
1706 set_toplevel(struct shell_surface *shsurf)
1708 shsurf->next_type = SHELL_SURFACE_TOPLEVEL;
1712 shell_surface_set_toplevel(struct wl_client *client,
1713 struct wl_resource *resource)
1715 struct shell_surface *surface = wl_resource_get_user_data(resource);
1717 set_toplevel(surface);
1721 set_transient(struct shell_surface *shsurf,
1722 struct weston_surface *parent, int x, int y, uint32_t flags)
1724 /* assign to parents output */
1725 shsurf->parent = parent;
1726 shsurf->transient.x = x;
1727 shsurf->transient.y = y;
1728 shsurf->transient.flags = flags;
1729 shsurf->next_type = SHELL_SURFACE_TRANSIENT;
1733 shell_surface_set_transient(struct wl_client *client,
1734 struct wl_resource *resource,
1735 struct wl_resource *parent_resource,
1736 int x, int y, uint32_t flags)
1738 struct shell_surface *shsurf = wl_resource_get_user_data(resource);
1739 struct weston_surface *parent =
1740 wl_resource_get_user_data(parent_resource);
1742 set_transient(shsurf, parent, x, y, flags);
1745 static struct desktop_shell *
1746 shell_surface_get_shell(struct shell_surface *shsurf)
1748 return shsurf->shell;
1752 get_output_panel_height(struct desktop_shell *shell,
1753 struct weston_output *output)
1755 struct weston_surface *surface;
1756 int panel_height = 0;
1761 wl_list_for_each(surface, &shell->panel_layer.surface_list, layer_link) {
1762 if (surface->output == output) {
1763 panel_height = surface->geometry.height;
1768 return panel_height;
1772 shell_surface_set_maximized(struct wl_client *client,
1773 struct wl_resource *resource,
1774 struct wl_resource *output_resource )
1776 struct shell_surface *shsurf = wl_resource_get_user_data(resource);
1777 struct weston_surface *es = shsurf->surface;
1778 struct desktop_shell *shell = NULL;
1779 uint32_t edges = 0, panel_height = 0;
1781 /* get the default output, if the client set it as NULL
1782 check whether the ouput is available */
1783 if (output_resource)
1784 shsurf->output = wl_resource_get_user_data(output_resource);
1785 else if (es->output)
1786 shsurf->output = es->output;
1788 shsurf->output = get_default_output(es->compositor);
1790 shell = shell_surface_get_shell(shsurf);
1791 panel_height = get_output_panel_height(shell, shsurf->output);
1792 edges = WL_SHELL_SURFACE_RESIZE_TOP|WL_SHELL_SURFACE_RESIZE_LEFT;
1794 uifw_trace("shell_surface_set_maximized: send %08x %x w/h=%d/%d",
1795 (int)shsurf->surface, edges, shsurf->output->width,
1796 shsurf->output->height - panel_height);
1797 shsurf->client->send_configure(shsurf->surface, edges,
1798 shsurf->output->width,
1799 shsurf->output->height - panel_height);
1801 shsurf->next_type = SHELL_SURFACE_MAXIMIZED;
1805 black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height);
1807 static struct weston_surface *
1808 create_black_surface(struct weston_compositor *ec,
1809 struct weston_surface *fs_surface,
1810 float x, float y, int w, int h)
1812 struct weston_surface *surface = NULL;
1814 surface = weston_surface_create(ec);
1815 if (surface == NULL) {
1816 weston_log("no memory\n");
1820 surface->configure = black_surface_configure;
1821 surface->configure_private = fs_surface;
1822 uifw_trace("create_black_surface: configure %08x x/y=%d/%d w/h=%d/%d",
1823 (int)surface, (int)x, (int)y, w, h);
1824 weston_surface_configure(surface, x, y, w, h);
1825 weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1);
1826 pixman_region32_fini(&surface->opaque);
1827 pixman_region32_init_rect(&surface->opaque, 0, 0, w, h);
1828 pixman_region32_fini(&surface->input);
1829 pixman_region32_init_rect(&surface->input, 0, 0, w, h);
1834 /* Create black surface and append it to the associated fullscreen surface.
1835 * Handle size dismatch and positioning according to the method. */
1837 shell_configure_fullscreen(struct shell_surface *shsurf)
1839 struct weston_output *output = shsurf->fullscreen_output;
1840 struct weston_surface *surface = shsurf->surface;
1841 struct weston_matrix *matrix;
1842 float scale, output_aspect, surface_aspect, x, y;
1843 int32_t surf_x, surf_y, surf_width, surf_height;
1845 if (shsurf->fullscreen.type != WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER)
1846 restore_output_mode(output);
1848 if (!shsurf->fullscreen.black_surface)
1849 shsurf->fullscreen.black_surface =
1850 create_black_surface(surface->compositor,
1852 output->x, output->y,
1856 wl_list_remove(&shsurf->fullscreen.black_surface->layer_link);
1857 wl_list_insert(&surface->layer_link,
1858 &shsurf->fullscreen.black_surface->layer_link);
1859 shsurf->fullscreen.black_surface->output = output;
1861 surface_subsurfaces_boundingbox(surface, &surf_x, &surf_y,
1862 &surf_width, &surf_height);
1864 switch (shsurf->fullscreen.type) {
1865 case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT:
1866 if (surface->buffer_ref.buffer)
1867 center_on_output(surface, shsurf->fullscreen_output);
1869 case WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE:
1870 /* 1:1 mapping between surface and output dimensions */
1871 if (output->width == surf_width &&
1872 output->height == surf_height) {
1873 weston_surface_set_position(surface, output->x - surf_x,
1874 output->y - surf_y);
1878 matrix = &shsurf->fullscreen.transform.matrix;
1879 weston_matrix_init(matrix);
1881 output_aspect = (float) output->width /
1882 (float) output->height;
1883 surface_aspect = (float) surface->geometry.width /
1884 (float) surface->geometry.height;
1885 if (output_aspect < surface_aspect)
1886 scale = (float) output->width /
1889 scale = (float) output->height /
1890 (float) surf_height;
1892 weston_matrix_scale(matrix, scale, scale, 1);
1893 wl_list_remove(&shsurf->fullscreen.transform.link);
1894 wl_list_insert(&surface->geometry.transformation_list,
1895 &shsurf->fullscreen.transform.link);
1896 x = output->x + (output->width - surf_width * scale) / 2 - surf_x;
1897 y = output->y + (output->height - surf_height * scale) / 2 - surf_y;
1898 weston_surface_set_position(surface, x, y);
1901 case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER:
1902 if (shell_surface_is_top_fullscreen(shsurf)) {
1903 struct weston_mode mode = {0,
1904 surf_width * surface->buffer_scale,
1905 surf_height * surface->buffer_scale,
1906 shsurf->fullscreen.framerate};
1908 if (weston_output_switch_mode(output, &mode, surface->buffer_scale) == 0) {
1909 weston_surface_set_position(surface,
1911 output->y - surf_y);
1912 uifw_trace("shell_configure_fullscreen: configure %08x x/y=%d/%d w/h=%d/%d",
1913 (int)shsurf->fullscreen.black_surface, (int)(output->x - surf_x),
1914 (int)(output->y - surf_y), output->width, output->height);
1915 weston_surface_configure(shsurf->fullscreen.black_surface,
1922 restore_output_mode(output);
1923 center_on_output(surface, output);
1927 case WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL:
1928 center_on_output(surface, output);
1935 /* make the fullscreen and black surface at the top */
1937 shell_stack_fullscreen(struct shell_surface *shsurf)
1939 struct weston_output *output = shsurf->fullscreen_output;
1940 struct weston_surface *surface = shsurf->surface;
1941 struct desktop_shell *shell = shell_surface_get_shell(shsurf);
1943 wl_list_remove(&surface->layer_link);
1944 wl_list_insert(&shell->fullscreen_layer.surface_list,
1945 &surface->layer_link);
1946 weston_surface_damage(surface);
1948 if (!shsurf->fullscreen.black_surface)
1949 shsurf->fullscreen.black_surface =
1950 create_black_surface(surface->compositor,
1952 output->x, output->y,
1956 wl_list_remove(&shsurf->fullscreen.black_surface->layer_link);
1957 wl_list_insert(&surface->layer_link,
1958 &shsurf->fullscreen.black_surface->layer_link);
1959 weston_surface_damage(shsurf->fullscreen.black_surface);
1963 shell_map_fullscreen(struct shell_surface *shsurf)
1965 shell_stack_fullscreen(shsurf);
1966 shell_configure_fullscreen(shsurf);
1970 set_fullscreen(struct shell_surface *shsurf,
1973 struct weston_output *output)
1975 struct weston_surface *es = shsurf->surface;
1978 shsurf->output = output;
1979 else if (es->output)
1980 shsurf->output = es->output;
1982 shsurf->output = get_default_output(es->compositor);
1984 shsurf->fullscreen_output = shsurf->output;
1985 shsurf->fullscreen.type = method;
1986 shsurf->fullscreen.framerate = framerate;
1987 shsurf->next_type = SHELL_SURFACE_FULLSCREEN;
1989 uifw_trace("set_fullscreen: send %08x 0 w/h=%d/%d",
1990 (int)shsurf->surface, shsurf->output->width, shsurf->output->height);
1991 shsurf->client->send_configure(shsurf->surface, 0,
1992 shsurf->output->width,
1993 shsurf->output->height);
1997 shell_surface_set_fullscreen(struct wl_client *client,
1998 struct wl_resource *resource,
2001 struct wl_resource *output_resource)
2003 struct shell_surface *shsurf = wl_resource_get_user_data(resource);
2004 struct weston_output *output;
2006 if (output_resource)
2007 output = wl_resource_get_user_data(output_resource);
2011 set_fullscreen(shsurf, method, framerate, output);
2015 set_xwayland(struct shell_surface *shsurf, int x, int y, uint32_t flags)
2017 /* XXX: using the same fields for transient type */
2018 shsurf->transient.x = x;
2019 shsurf->transient.y = y;
2020 shsurf->transient.flags = flags;
2021 shsurf->next_type = SHELL_SURFACE_XWAYLAND;
2024 static const struct weston_pointer_grab_interface popup_grab_interface;
2027 destroy_shell_seat(struct wl_listener *listener, void *data)
2029 struct shell_seat *shseat =
2030 container_of(listener,
2031 struct shell_seat, seat_destroy_listener);
2032 struct shell_surface *shsurf, *prev = NULL;
2034 if (shseat->popup_grab.grab.interface == &popup_grab_interface) {
2035 weston_pointer_end_grab(shseat->popup_grab.grab.pointer);
2036 shseat->popup_grab.client = NULL;
2038 wl_list_for_each(shsurf, &shseat->popup_grab.surfaces_list, popup.grab_link) {
2039 shsurf->popup.shseat = NULL;
2041 wl_list_init(&prev->popup.grab_link);
2045 wl_list_init(&prev->popup.grab_link);
2048 wl_list_remove(&shseat->seat_destroy_listener.link);
2052 static struct shell_seat *
2053 create_shell_seat(struct weston_seat *seat)
2055 struct shell_seat *shseat;
2057 shseat = calloc(1, sizeof *shseat);
2059 weston_log("no memory to allocate shell seat\n");
2063 shseat->seat = seat;
2064 wl_list_init(&shseat->popup_grab.surfaces_list);
2066 shseat->seat_destroy_listener.notify = destroy_shell_seat;
2067 wl_signal_add(&seat->destroy_signal,
2068 &shseat->seat_destroy_listener);
2073 static struct shell_seat *
2074 get_shell_seat(struct weston_seat *seat)
2076 struct wl_listener *listener;
2078 listener = wl_signal_get(&seat->destroy_signal, destroy_shell_seat);
2079 if (listener == NULL)
2080 return create_shell_seat(seat);
2082 return container_of(listener,
2083 struct shell_seat, seat_destroy_listener);
2087 popup_grab_focus(struct weston_pointer_grab *grab)
2089 struct weston_pointer *pointer = grab->pointer;
2090 struct weston_surface *surface;
2091 struct shell_seat *shseat =
2092 container_of(grab, struct shell_seat, popup_grab.grab);
2093 struct wl_client *client = shseat->popup_grab.client;
2096 surface = weston_compositor_pick_surface(pointer->seat->compositor,
2097 pointer->x, pointer->y,
2100 if (surface && wl_resource_get_client(surface->resource) == client) {
2101 weston_pointer_set_focus(pointer, surface, sx, sy);
2103 weston_pointer_set_focus(pointer, NULL,
2104 wl_fixed_from_int(0),
2105 wl_fixed_from_int(0));
2110 popup_grab_motion(struct weston_pointer_grab *grab, uint32_t time)
2112 struct weston_pointer *pointer = grab->pointer;
2115 if (pointer->focus_resource) {
2116 weston_surface_from_global_fixed(pointer->focus,
2117 pointer->x, pointer->y,
2119 wl_pointer_send_motion(pointer->focus_resource, time, sx, sy);
2124 popup_grab_button(struct weston_pointer_grab *grab,
2125 uint32_t time, uint32_t button, uint32_t state_w)
2127 struct wl_resource *resource;
2128 struct shell_seat *shseat =
2129 container_of(grab, struct shell_seat, popup_grab.grab);
2130 struct wl_display *display;
2131 enum wl_pointer_button_state state = state_w;
2134 resource = grab->pointer->focus_resource;
2136 display = wl_client_get_display(wl_resource_get_client(resource));
2137 serial = wl_display_get_serial(display);
2138 wl_pointer_send_button(resource, serial, time, button, state);
2139 } else if (state == WL_POINTER_BUTTON_STATE_RELEASED &&
2140 (shseat->popup_grab.initial_up ||
2141 time - shseat->seat->pointer->grab_time > 500)) {
2142 popup_grab_end(grab->pointer);
2145 if (state == WL_POINTER_BUTTON_STATE_RELEASED)
2146 shseat->popup_grab.initial_up = 1;
2149 static const struct weston_pointer_grab_interface popup_grab_interface = {
2156 popup_grab_end(struct weston_pointer *pointer)
2158 struct weston_pointer_grab *grab = pointer->grab;
2159 struct shell_seat *shseat =
2160 container_of(grab, struct shell_seat, popup_grab.grab);
2161 struct shell_surface *shsurf;
2162 struct shell_surface *prev = NULL;
2164 if (pointer->grab->interface == &popup_grab_interface) {
2165 weston_pointer_end_grab(grab->pointer);
2166 shseat->popup_grab.client = NULL;
2167 shseat->popup_grab.grab.interface = NULL;
2168 assert(!wl_list_empty(&shseat->popup_grab.surfaces_list));
2169 /* Send the popup_done event to all the popups open */
2170 wl_list_for_each(shsurf, &shseat->popup_grab.surfaces_list, popup.grab_link) {
2171 wl_shell_surface_send_popup_done(shsurf->resource);
2172 shsurf->popup.shseat = NULL;
2174 wl_list_init(&prev->popup.grab_link);
2178 wl_list_init(&prev->popup.grab_link);
2179 wl_list_init(&shseat->popup_grab.surfaces_list);
2184 add_popup_grab(struct shell_surface *shsurf, struct shell_seat *shseat)
2186 struct weston_seat *seat = shseat->seat;
2188 if (wl_list_empty(&shseat->popup_grab.surfaces_list)) {
2189 shseat->popup_grab.client = wl_resource_get_client(shsurf->resource);
2190 shseat->popup_grab.grab.interface = &popup_grab_interface;
2191 /* We must make sure here that this popup was opened after
2192 * a mouse press, and not just by moving around with other
2193 * popups already open. */
2194 if (shseat->seat->pointer->button_count > 0)
2195 shseat->popup_grab.initial_up = 0;
2197 wl_list_insert(&shseat->popup_grab.surfaces_list, &shsurf->popup.grab_link);
2198 weston_pointer_start_grab(seat->pointer, &shseat->popup_grab.grab);
2200 wl_list_insert(&shseat->popup_grab.surfaces_list, &shsurf->popup.grab_link);
2205 remove_popup_grab(struct shell_surface *shsurf)
2207 struct shell_seat *shseat = shsurf->popup.shseat;
2209 wl_list_remove(&shsurf->popup.grab_link);
2210 wl_list_init(&shsurf->popup.grab_link);
2211 if (wl_list_empty(&shseat->popup_grab.surfaces_list)) {
2212 weston_pointer_end_grab(shseat->popup_grab.grab.pointer);
2213 shseat->popup_grab.grab.interface = NULL;
2218 shell_map_popup(struct shell_surface *shsurf)
2220 struct shell_seat *shseat = shsurf->popup.shseat;
2221 struct weston_surface *es = shsurf->surface;
2222 struct weston_surface *parent = shsurf->parent;
2224 es->output = parent->output;
2226 weston_surface_set_transform_parent(es, parent);
2227 weston_surface_set_position(es, shsurf->popup.x, shsurf->popup.y);
2228 weston_surface_update_transform(es);
2230 if (shseat->seat->pointer->grab_serial == shsurf->popup.serial) {
2231 add_popup_grab(shsurf, shseat);
2233 wl_shell_surface_send_popup_done(shsurf->resource);
2234 shseat->popup_grab.client = NULL;
2239 shell_surface_set_popup(struct wl_client *client,
2240 struct wl_resource *resource,
2241 struct wl_resource *seat_resource,
2243 struct wl_resource *parent_resource,
2244 int32_t x, int32_t y, uint32_t flags)
2246 struct shell_surface *shsurf = wl_resource_get_user_data(resource);
2248 shsurf->type = SHELL_SURFACE_POPUP;
2249 shsurf->parent = wl_resource_get_user_data(parent_resource);
2250 shsurf->popup.shseat = get_shell_seat(wl_resource_get_user_data(seat_resource));
2251 shsurf->popup.serial = serial;
2252 shsurf->popup.x = x;
2253 shsurf->popup.y = y;
2256 static const struct wl_shell_surface_interface shell_surface_implementation = {
2259 shell_surface_resize,
2260 shell_surface_set_toplevel,
2261 shell_surface_set_transient,
2262 shell_surface_set_fullscreen,
2263 shell_surface_set_popup,
2264 shell_surface_set_maximized,
2265 shell_surface_set_title,
2266 shell_surface_set_class
2270 destroy_shell_surface(struct shell_surface *shsurf)
2272 wl_signal_emit(&shsurf->destroy_signal, shsurf);
2274 /* if ico_window_mgr hook, call hook routine */
2275 if (shell_hook_destroy) {
2276 (*shell_hook_destroy)(shsurf->surface);
2279 if (!wl_list_empty(&shsurf->popup.grab_link)) {
2280 remove_popup_grab(shsurf);
2283 if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
2284 shell_surface_is_top_fullscreen(shsurf))
2285 restore_output_mode (shsurf->fullscreen_output);
2287 if (shsurf->fullscreen.black_surface)
2288 weston_surface_destroy(shsurf->fullscreen.black_surface);
2290 /* As destroy_resource() use wl_list_for_each_safe(),
2291 * we can always remove the listener.
2293 wl_list_remove(&shsurf->surface_destroy_listener.link);
2294 shsurf->surface->configure = NULL;
2295 ping_timer_destroy(shsurf);
2296 free(shsurf->title);
2298 wl_list_remove(&shsurf->link);
2303 shell_destroy_shell_surface(struct wl_resource *resource)
2305 struct shell_surface *shsurf = wl_resource_get_user_data(resource);
2307 destroy_shell_surface(shsurf);
2311 shell_handle_surface_destroy(struct wl_listener *listener, void *data)
2313 struct shell_surface *shsurf = container_of(listener,
2314 struct shell_surface,
2315 surface_destroy_listener);
2317 if (shsurf->resource)
2318 wl_resource_destroy(shsurf->resource);
2320 destroy_shell_surface(shsurf);
2324 shell_surface_configure(struct weston_surface *, int32_t, int32_t, int32_t, int32_t);
2326 static struct shell_surface *
2327 get_shell_surface(struct weston_surface *surface)
2329 if (surface->configure == shell_surface_configure)
2330 return surface->configure_private;
2335 static struct shell_surface *
2336 create_shell_surface(void *shell, struct weston_surface *surface,
2337 const struct weston_shell_client *client)
2339 struct shell_surface *shsurf;
2341 if (surface->configure) {
2342 weston_log("surface->configure already set\n");
2346 shsurf = calloc(1, sizeof *shsurf);
2348 weston_log("no memory to allocate shell surface\n");
2352 surface->configure = shell_surface_configure;
2353 surface->configure_private = shsurf;
2355 shsurf->shell = (struct desktop_shell *) shell;
2356 shsurf->unresponsive = 0;
2357 shsurf->saved_position_valid = false;
2358 shsurf->saved_rotation_valid = false;
2359 shsurf->surface = surface;
2360 shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
2361 shsurf->fullscreen.framerate = 0;
2362 shsurf->fullscreen.black_surface = NULL;
2363 shsurf->ping_timer = NULL;
2364 wl_list_init(&shsurf->fullscreen.transform.link);
2366 wl_signal_init(&shsurf->destroy_signal);
2367 shsurf->surface_destroy_listener.notify = shell_handle_surface_destroy;
2368 wl_signal_add(&surface->destroy_signal,
2369 &shsurf->surface_destroy_listener);
2371 /* init link so its safe to always remove it in destroy_shell_surface */
2372 wl_list_init(&shsurf->link);
2373 wl_list_init(&shsurf->popup.grab_link);
2375 /* empty when not in use */
2376 wl_list_init(&shsurf->rotation.transform.link);
2377 weston_matrix_init(&shsurf->rotation.rotation);
2379 wl_list_init(&shsurf->workspace_transform.link);
2381 shsurf->type = SHELL_SURFACE_NONE;
2382 shsurf->next_type = SHELL_SURFACE_NONE;
2384 shsurf->client = client;
2390 shell_get_shell_surface(struct wl_client *client,
2391 struct wl_resource *resource,
2393 struct wl_resource *surface_resource)
2395 struct weston_surface *surface =
2396 wl_resource_get_user_data(surface_resource);
2397 struct desktop_shell *shell = wl_resource_get_user_data(resource);
2398 struct shell_surface *shsurf;
2400 if (get_shell_surface(surface)) {
2401 wl_resource_post_error(surface_resource,
2402 WL_DISPLAY_ERROR_INVALID_OBJECT,
2403 "desktop_shell::get_shell_surface already requested");
2407 shsurf = create_shell_surface(shell, surface, &shell_client);
2409 wl_resource_post_error(surface_resource,
2410 WL_DISPLAY_ERROR_INVALID_OBJECT,
2411 "surface->configure already set");
2416 wl_resource_create(client,
2417 &wl_shell_surface_interface, 1, id);
2418 wl_resource_set_implementation(shsurf->resource,
2419 &shell_surface_implementation,
2420 shsurf, shell_destroy_shell_surface);
2422 /* if ico_window_mgr hook, call hook routine */
2423 if (shell_hook_create) {
2424 (*shell_hook_create)(client, resource, surface, shsurf);
2428 static const struct wl_shell_interface shell_implementation = {
2429 shell_get_shell_surface
2433 shell_fade(struct desktop_shell *shell, enum fade_type type);
2436 screensaver_timeout(void *data)
2438 struct desktop_shell *shell = data;
2440 shell_fade(shell, FADE_OUT);
2446 handle_screensaver_sigchld(struct weston_process *proc, int status)
2448 struct desktop_shell *shell =
2449 container_of(proc, struct desktop_shell, screensaver.process);
2454 weston_compositor_sleep(shell->compositor);
2458 launch_screensaver(struct desktop_shell *shell)
2460 if (shell->screensaver.binding)
2463 if (!shell->screensaver.path) {
2464 weston_compositor_sleep(shell->compositor);
2468 if (shell->screensaver.process.pid != 0) {
2469 weston_log("old screensaver still running\n");
2473 weston_client_launch(shell->compositor,
2474 &shell->screensaver.process,
2475 shell->screensaver.path,
2476 handle_screensaver_sigchld);
2480 terminate_screensaver(struct desktop_shell *shell)
2482 if (shell->screensaver.process.pid == 0)
2485 kill(shell->screensaver.process.pid, SIGTERM);
2489 configure_static_surface(struct weston_surface *es, struct weston_layer *layer, int32_t width, int32_t height)
2491 struct weston_surface *s, *next;
2496 wl_list_for_each_safe(s, next, &layer->surface_list, layer_link) {
2497 if (s->output == es->output && s != es) {
2498 weston_surface_unmap(s);
2499 s->configure = NULL;
2503 uifw_trace("configure_static_surface: configure %08x x/y=%d/%d w/h=%d/%d",
2504 (int)es, (int)es->output->x, (int)es->output->y, width, height);
2505 weston_surface_configure(es, es->output->x, es->output->y, width, height);
2507 if (wl_list_empty(&es->layer_link)) {
2508 wl_list_insert(&layer->surface_list, &es->layer_link);
2509 weston_compositor_schedule_repaint(es->compositor);
2514 background_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height)
2516 struct desktop_shell *shell = es->configure_private;
2518 configure_static_surface(es, &shell->background_layer, width, height);
2522 desktop_shell_set_background(struct wl_client *client,
2523 struct wl_resource *resource,
2524 struct wl_resource *output_resource,
2525 struct wl_resource *surface_resource)
2527 struct desktop_shell *shell = wl_resource_get_user_data(resource);
2528 struct weston_surface *surface =
2529 wl_resource_get_user_data(surface_resource);
2531 if (surface->configure) {
2532 wl_resource_post_error(surface_resource,
2533 WL_DISPLAY_ERROR_INVALID_OBJECT,
2534 "surface role already assigned");
2538 surface->configure = background_configure;
2539 surface->configure_private = shell;
2540 surface->output = wl_resource_get_user_data(output_resource);
2541 uifw_trace("desktop_shell_set_background: send %08x 0 w/h=%d/%d",
2542 (int)surface, surface->output->width, surface->output->height);
2543 desktop_shell_send_configure(resource, 0,
2545 surface->output->width,
2546 surface->output->height);
2550 panel_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height)
2552 struct desktop_shell *shell = es->configure_private;
2554 configure_static_surface(es, &shell->panel_layer, width, height);
2558 desktop_shell_set_panel(struct wl_client *client,
2559 struct wl_resource *resource,
2560 struct wl_resource *output_resource,
2561 struct wl_resource *surface_resource)
2563 struct desktop_shell *shell = wl_resource_get_user_data(resource);
2564 struct weston_surface *surface =
2565 wl_resource_get_user_data(surface_resource);
2567 if (surface->configure) {
2568 wl_resource_post_error(surface_resource,
2569 WL_DISPLAY_ERROR_INVALID_OBJECT,
2570 "surface role already assigned");
2574 surface->configure = panel_configure;
2575 surface->configure_private = shell;
2576 surface->output = wl_resource_get_user_data(output_resource);
2577 uifw_trace("desktop_shell_set_panel: send %08x 0 w/h=%d/%d",
2578 (int)surface, surface->output->width, surface->output->height);
2579 desktop_shell_send_configure(resource, 0,
2581 surface->output->width,
2582 surface->output->height);
2586 lock_surface_configure(struct weston_surface *surface, int32_t sx, int32_t sy, int32_t width, int32_t height)
2588 struct desktop_shell *shell = surface->configure_private;
2593 uifw_trace("lock_surface_configure: change %08x w/h=%d/%d", (int)surface, width, height);
2594 surface->geometry.width = width;
2595 surface->geometry.height = height;
2596 center_on_output(surface, get_default_output(shell->compositor));
2598 if (!weston_surface_is_mapped(surface)) {
2599 wl_list_insert(&shell->lock_layer.surface_list,
2600 &surface->layer_link);
2601 weston_surface_update_transform(surface);
2602 shell_fade(shell, FADE_IN);
2607 handle_lock_surface_destroy(struct wl_listener *listener, void *data)
2609 struct desktop_shell *shell =
2610 container_of(listener, struct desktop_shell, lock_surface_listener);
2612 weston_log("lock surface gone\n");
2613 shell->lock_surface = NULL;
2617 desktop_shell_set_lock_surface(struct wl_client *client,
2618 struct wl_resource *resource,
2619 struct wl_resource *surface_resource)
2621 struct desktop_shell *shell = wl_resource_get_user_data(resource);
2622 struct weston_surface *surface =
2623 wl_resource_get_user_data(surface_resource);
2625 shell->prepare_event_sent = false;
2630 shell->lock_surface = surface;
2632 shell->lock_surface_listener.notify = handle_lock_surface_destroy;
2633 wl_signal_add(&surface->destroy_signal,
2634 &shell->lock_surface_listener);
2636 surface->configure = lock_surface_configure;
2637 surface->configure_private = shell;
2641 resume_desktop(struct desktop_shell *shell)
2643 struct workspace *ws = get_current_workspace(shell);
2645 terminate_screensaver(shell);
2647 wl_list_remove(&shell->lock_layer.link);
2648 wl_list_insert(&shell->compositor->cursor_layer.link,
2649 &shell->fullscreen_layer.link);
2650 wl_list_insert(&shell->fullscreen_layer.link,
2651 &shell->panel_layer.link);
2652 if (shell->showing_input_panels) {
2653 wl_list_insert(&shell->panel_layer.link,
2654 &shell->input_panel_layer.link);
2655 wl_list_insert(&shell->input_panel_layer.link,
2658 wl_list_insert(&shell->panel_layer.link, &ws->layer.link);
2661 restore_focus_state(shell, get_current_workspace(shell));
2663 shell->locked = false;
2664 shell_fade(shell, FADE_IN);
2665 weston_compositor_damage_all(shell->compositor);
2669 desktop_shell_unlock(struct wl_client *client,
2670 struct wl_resource *resource)
2672 struct desktop_shell *shell = wl_resource_get_user_data(resource);
2674 shell->prepare_event_sent = false;
2677 resume_desktop(shell);
2681 desktop_shell_set_grab_surface(struct wl_client *client,
2682 struct wl_resource *resource,
2683 struct wl_resource *surface_resource)
2685 struct desktop_shell *shell = wl_resource_get_user_data(resource);
2687 shell->grab_surface = wl_resource_get_user_data(surface_resource);
2691 desktop_shell_desktop_ready(struct wl_client *client,
2692 struct wl_resource *resource)
2694 struct desktop_shell *shell = wl_resource_get_user_data(resource);
2696 shell_fade_startup(shell);
2699 static const struct desktop_shell_interface desktop_shell_implementation = {
2700 desktop_shell_set_background,
2701 desktop_shell_set_panel,
2702 desktop_shell_set_lock_surface,
2703 desktop_shell_unlock,
2704 desktop_shell_set_grab_surface,
2705 desktop_shell_desktop_ready
2708 static enum shell_surface_type
2709 get_shell_surface_type(struct weston_surface *surface)
2711 struct shell_surface *shsurf;
2713 shsurf = get_shell_surface(surface);
2715 return SHELL_SURFACE_NONE;
2716 return shsurf->type;
2720 move_binding(struct weston_seat *seat, uint32_t time, uint32_t button, void *data)
2722 struct weston_surface *focus =
2723 (struct weston_surface *) seat->pointer->focus;
2724 struct weston_surface *surface;
2725 struct shell_surface *shsurf;
2727 surface = weston_surface_get_main_surface(focus);
2728 if (surface == NULL)
2731 shsurf = get_shell_surface(surface);
2732 if (shsurf == NULL || shsurf->type == SHELL_SURFACE_FULLSCREEN ||
2733 shsurf->type == SHELL_SURFACE_MAXIMIZED)
2736 surface_move(shsurf, (struct weston_seat *) seat);
2740 resize_binding(struct weston_seat *seat, uint32_t time, uint32_t button, void *data)
2742 struct weston_surface *focus =
2743 (struct weston_surface *) seat->pointer->focus;
2744 struct weston_surface *surface;
2747 struct shell_surface *shsurf;
2749 surface = weston_surface_get_main_surface(focus);
2750 if (surface == NULL)
2753 shsurf = get_shell_surface(surface);
2754 if (!shsurf || shsurf->type == SHELL_SURFACE_FULLSCREEN ||
2755 shsurf->type == SHELL_SURFACE_MAXIMIZED)
2758 weston_surface_from_global(surface,
2759 wl_fixed_to_int(seat->pointer->grab_x),
2760 wl_fixed_to_int(seat->pointer->grab_y),
2763 if (x < surface->geometry.width / 3)
2764 edges |= WL_SHELL_SURFACE_RESIZE_LEFT;
2765 else if (x < 2 * surface->geometry.width / 3)
2768 edges |= WL_SHELL_SURFACE_RESIZE_RIGHT;
2770 if (y < surface->geometry.height / 3)
2771 edges |= WL_SHELL_SURFACE_RESIZE_TOP;
2772 else if (y < 2 * surface->geometry.height / 3)
2775 edges |= WL_SHELL_SURFACE_RESIZE_BOTTOM;
2777 surface_resize(shsurf, (struct weston_seat *) seat, edges);
2781 surface_opacity_binding(struct weston_seat *seat, uint32_t time, uint32_t axis,
2782 wl_fixed_t value, void *data)
2785 struct shell_surface *shsurf;
2786 struct weston_surface *focus =
2787 (struct weston_surface *) seat->pointer->focus;
2788 struct weston_surface *surface;
2790 /* XXX: broken for windows containing sub-surfaces */
2791 surface = weston_surface_get_main_surface(focus);
2792 if (surface == NULL)
2795 shsurf = get_shell_surface(surface);
2799 surface->alpha -= wl_fixed_to_double(value) * step;
2801 if (surface->alpha > 1.0)
2802 surface->alpha = 1.0;
2803 if (surface->alpha < step)
2804 surface->alpha = step;
2806 weston_surface_geometry_dirty(surface);
2807 weston_surface_damage(surface);
2811 do_zoom(struct weston_seat *seat, uint32_t time, uint32_t key, uint32_t axis,
2814 struct weston_seat *ws = (struct weston_seat *) seat;
2815 struct weston_compositor *compositor = ws->compositor;
2816 struct weston_output *output;
2819 wl_list_for_each(output, &compositor->output_list, link) {
2820 if (pixman_region32_contains_point(&output->region,
2821 wl_fixed_to_double(seat->pointer->x),
2822 wl_fixed_to_double(seat->pointer->y),
2824 if (key == KEY_PAGEUP)
2825 increment = output->zoom.increment;
2826 else if (key == KEY_PAGEDOWN)
2827 increment = -output->zoom.increment;
2828 else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
2829 /* For every pixel zoom 20th of a step */
2830 increment = output->zoom.increment *
2831 -wl_fixed_to_double(value) / 20.0;
2835 output->zoom.level += increment;
2837 if (output->zoom.level < 0.0)
2838 output->zoom.level = 0.0;
2839 else if (output->zoom.level > output->zoom.max_level)
2840 output->zoom.level = output->zoom.max_level;
2841 else if (!output->zoom.active) {
2842 output->zoom.active = 1;
2843 output->disable_planes++;
2846 output->zoom.spring_z.target = output->zoom.level;
2848 weston_output_update_zoom(output, output->zoom.type);
2854 zoom_axis_binding(struct weston_seat *seat, uint32_t time, uint32_t axis,
2855 wl_fixed_t value, void *data)
2857 do_zoom(seat, time, 0, axis, value);
2861 zoom_key_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
2864 do_zoom(seat, time, key, 0, 0);
2868 terminate_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
2871 struct weston_compositor *compositor = data;
2873 wl_display_terminate(compositor->wl_display);
2877 rotate_grab_motion(struct weston_pointer_grab *grab, uint32_t time)
2879 struct rotate_grab *rotate =
2880 container_of(grab, struct rotate_grab, base.grab);
2881 struct weston_pointer *pointer = grab->pointer;
2882 struct shell_surface *shsurf = rotate->base.shsurf;
2883 struct weston_surface *surface;
2884 float cx, cy, dx, dy, cposx, cposy, dposx, dposy, r;
2889 surface = shsurf->surface;
2891 cx = 0.5f * surface->geometry.width;
2892 cy = 0.5f * surface->geometry.height;
2894 dx = wl_fixed_to_double(pointer->x) - rotate->center.x;
2895 dy = wl_fixed_to_double(pointer->y) - rotate->center.y;
2896 r = sqrtf(dx * dx + dy * dy);
2898 wl_list_remove(&shsurf->rotation.transform.link);
2899 weston_surface_geometry_dirty(shsurf->surface);
2902 struct weston_matrix *matrix =
2903 &shsurf->rotation.transform.matrix;
2905 weston_matrix_init(&rotate->rotation);
2906 weston_matrix_rotate_xy(&rotate->rotation, dx / r, dy / r);
2908 weston_matrix_init(matrix);
2909 weston_matrix_translate(matrix, -cx, -cy, 0.0f);
2910 weston_matrix_multiply(matrix, &shsurf->rotation.rotation);
2911 weston_matrix_multiply(matrix, &rotate->rotation);
2912 weston_matrix_translate(matrix, cx, cy, 0.0f);
2915 &shsurf->surface->geometry.transformation_list,
2916 &shsurf->rotation.transform.link);
2918 wl_list_init(&shsurf->rotation.transform.link);
2919 weston_matrix_init(&shsurf->rotation.rotation);
2920 weston_matrix_init(&rotate->rotation);
2923 /* We need to adjust the position of the surface
2924 * in case it was resized in a rotated state before */
2925 cposx = surface->geometry.x + cx;
2926 cposy = surface->geometry.y + cy;
2927 dposx = rotate->center.x - cposx;
2928 dposy = rotate->center.y - cposy;
2929 if (dposx != 0.0f || dposy != 0.0f) {
2930 weston_surface_set_position(surface,
2931 surface->geometry.x + dposx,
2932 surface->geometry.y + dposy);
2935 /* Repaint implies weston_surface_update_transform(), which
2936 * lazily applies the damage due to rotation update.
2938 weston_compositor_schedule_repaint(shsurf->surface->compositor);
2942 rotate_grab_button(struct weston_pointer_grab *grab,
2943 uint32_t time, uint32_t button, uint32_t state_w)
2945 struct rotate_grab *rotate =
2946 container_of(grab, struct rotate_grab, base.grab);
2947 struct weston_pointer *pointer = grab->pointer;
2948 struct shell_surface *shsurf = rotate->base.shsurf;
2949 enum wl_pointer_button_state state = state_w;
2951 if (pointer->button_count == 0 &&
2952 state == WL_POINTER_BUTTON_STATE_RELEASED) {
2954 weston_matrix_multiply(&shsurf->rotation.rotation,
2956 shell_grab_end(&rotate->base);
2961 static const struct weston_pointer_grab_interface rotate_grab_interface = {
2968 surface_rotate(struct shell_surface *surface, struct weston_seat *seat)
2970 struct rotate_grab *rotate;
2974 rotate = malloc(sizeof *rotate);
2978 weston_surface_to_global_float(surface->surface,
2979 surface->surface->geometry.width * 0.5f,
2980 surface->surface->geometry.height * 0.5f,
2981 &rotate->center.x, &rotate->center.y);
2983 dx = wl_fixed_to_double(seat->pointer->x) - rotate->center.x;
2984 dy = wl_fixed_to_double(seat->pointer->y) - rotate->center.y;
2985 r = sqrtf(dx * dx + dy * dy);
2987 struct weston_matrix inverse;
2989 weston_matrix_init(&inverse);
2990 weston_matrix_rotate_xy(&inverse, dx / r, -dy / r);
2991 weston_matrix_multiply(&surface->rotation.rotation, &inverse);
2993 weston_matrix_init(&rotate->rotation);
2994 weston_matrix_rotate_xy(&rotate->rotation, dx / r, dy / r);
2996 weston_matrix_init(&surface->rotation.rotation);
2997 weston_matrix_init(&rotate->rotation);
3000 shell_grab_start(&rotate->base, &rotate_grab_interface, surface,
3001 seat->pointer, DESKTOP_SHELL_CURSOR_ARROW);
3005 rotate_binding(struct weston_seat *seat, uint32_t time, uint32_t button,
3008 struct weston_surface *focus =
3009 (struct weston_surface *) seat->pointer->focus;
3010 struct weston_surface *base_surface;
3011 struct shell_surface *surface;
3013 base_surface = weston_surface_get_main_surface(focus);
3014 if (base_surface == NULL)
3017 surface = get_shell_surface(base_surface);
3018 if (!surface || surface->type == SHELL_SURFACE_FULLSCREEN ||
3019 surface->type == SHELL_SURFACE_MAXIMIZED)
3022 surface_rotate(surface, seat);
3026 lower_fullscreen_layer(struct desktop_shell *shell)
3028 struct workspace *ws;
3029 struct weston_surface *surface, *prev;
3031 ws = get_current_workspace(shell);
3032 wl_list_for_each_reverse_safe(surface, prev,
3033 &shell->fullscreen_layer.surface_list,
3035 weston_surface_restack(surface, &ws->layer.surface_list);
3039 activate(struct desktop_shell *shell, struct weston_surface *es,
3040 struct weston_seat *seat)
3042 struct weston_surface *main_surface;
3043 struct focus_state *state;
3044 struct workspace *ws;
3046 main_surface = weston_surface_get_main_surface(es);
3048 weston_surface_activate(es, seat);
3050 state = ensure_focus_state(shell, seat);
3054 state->keyboard_focus = es;
3055 wl_list_remove(&state->surface_destroy_listener.link);
3056 wl_signal_add(&es->destroy_signal, &state->surface_destroy_listener);
3058 switch (get_shell_surface_type(main_surface)) {
3059 case SHELL_SURFACE_FULLSCREEN:
3060 /* should on top of panels */
3061 shell_stack_fullscreen(get_shell_surface(main_surface));
3062 shell_configure_fullscreen(get_shell_surface(main_surface));
3065 restore_all_output_modes(shell->compositor);
3066 ws = get_current_workspace(shell);
3067 weston_surface_restack(main_surface, &ws->layer.surface_list);
3072 /* no-op func for checking black surface */
3074 black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height)
3079 is_black_surface (struct weston_surface *es, struct weston_surface **fs_surface)
3081 if (es->configure == black_surface_configure) {
3083 *fs_surface = (struct weston_surface *)es->configure_private;
3090 click_to_activate_binding(struct weston_seat *seat, uint32_t time, uint32_t button,
3093 struct weston_seat *ws = (struct weston_seat *) seat;
3094 struct desktop_shell *shell = data;
3095 struct weston_surface *focus;
3096 struct weston_surface *main_surface;
3098 focus = (struct weston_surface *) seat->pointer->focus;
3102 if (is_black_surface(focus, &main_surface))
3103 focus = main_surface;
3105 main_surface = weston_surface_get_main_surface(focus);
3106 if (get_shell_surface_type(main_surface) == SHELL_SURFACE_NONE)
3109 if (seat->pointer->grab == &seat->pointer->default_grab)
3110 activate(shell, focus, ws);
3112 /* if ico_window_mgr hook, call hook routine */
3113 if (shell_hook_select) {
3114 (*shell_hook_select)(focus);
3119 lock(struct desktop_shell *shell)
3121 struct workspace *ws = get_current_workspace(shell);
3123 if (shell->locked) {
3124 weston_compositor_sleep(shell->compositor);
3128 shell->locked = true;
3130 /* Hide all surfaces by removing the fullscreen, panel and
3131 * toplevel layers. This way nothing else can show or receive
3132 * input events while we are locked. */
3134 wl_list_remove(&shell->panel_layer.link);
3135 wl_list_remove(&shell->fullscreen_layer.link);
3136 if (shell->showing_input_panels)
3137 wl_list_remove(&shell->input_panel_layer.link);
3138 wl_list_remove(&ws->layer.link);
3139 wl_list_insert(&shell->compositor->cursor_layer.link,
3140 &shell->lock_layer.link);
3142 launch_screensaver(shell);
3144 /* TODO: disable bindings that should not work while locked. */
3146 /* All this must be undone in resume_desktop(). */
3150 unlock(struct desktop_shell *shell)
3152 if (!shell->locked || shell->lock_surface) {
3153 shell_fade(shell, FADE_IN);
3157 /* If desktop-shell client has gone away, unlock immediately. */
3158 if (!shell->child.desktop_shell) {
3159 resume_desktop(shell);
3163 if (shell->prepare_event_sent)
3166 desktop_shell_send_prepare_lock_surface(shell->child.desktop_shell);
3167 shell->prepare_event_sent = true;
3171 shell_fade_done(struct weston_surface_animation *animation, void *data)
3173 struct desktop_shell *shell = data;
3175 shell->fade.animation = NULL;
3177 switch (shell->fade.type) {
3179 weston_surface_destroy(shell->fade.surface);
3180 shell->fade.surface = NULL;
3188 static struct weston_surface *
3189 shell_fade_create_surface(struct desktop_shell *shell)
3191 struct weston_compositor *compositor = shell->compositor;
3192 struct weston_surface *surface;
3194 surface = weston_surface_create(compositor);
3198 uifw_trace("shell_fade_create_surface: configure %08x x/y=%d/%d w/h=%d/%d",
3199 (int)surface, 0, 0, 8192, 8192);
3200 weston_surface_configure(surface, 0, 0, 8192, 8192);
3201 weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1.0);
3202 wl_list_insert(&compositor->fade_layer.surface_list,
3203 &surface->layer_link);
3204 pixman_region32_init(&surface->input);
3210 shell_fade(struct desktop_shell *shell, enum fade_type type)
3222 weston_log("shell: invalid fade type\n");
3226 shell->fade.type = type;
3228 if (shell->fade.surface == NULL) {
3229 shell->fade.surface = shell_fade_create_surface(shell);
3230 if (!shell->fade.surface)
3233 shell->fade.surface->alpha = 1.0 - tint;
3234 weston_surface_update_transform(shell->fade.surface);
3237 if (shell->fade.animation)
3238 weston_fade_update(shell->fade.animation, tint);
3240 shell->fade.animation =
3241 weston_fade_run(shell->fade.surface,
3242 1.0 - tint, tint, 300.0,
3243 shell_fade_done, shell);
3247 do_shell_fade_startup(void *data)
3249 struct desktop_shell *shell = data;
3251 shell_fade(shell, FADE_IN);
3255 shell_fade_startup(struct desktop_shell *shell)
3257 struct wl_event_loop *loop;
3259 if (!shell->fade.startup_timer)
3262 wl_event_source_remove(shell->fade.startup_timer);
3263 shell->fade.startup_timer = NULL;
3265 loop = wl_display_get_event_loop(shell->compositor->wl_display);
3266 wl_event_loop_add_idle(loop, do_shell_fade_startup, shell);
3270 fade_startup_timeout(void *data)
3272 struct desktop_shell *shell = data;
3274 shell_fade_startup(shell);
3279 shell_fade_init(struct desktop_shell *shell)
3281 /* Make compositor output all black, and wait for the desktop-shell
3282 * client to signal it is ready, then fade in. The timer triggers a
3283 * fade-in, in case the desktop-shell client takes too long.
3286 struct wl_event_loop *loop;
3288 if (shell->fade.surface != NULL) {
3289 weston_log("%s: warning: fade surface already exists\n",
3294 shell->fade.surface = shell_fade_create_surface(shell);
3295 if (!shell->fade.surface)
3298 weston_surface_update_transform(shell->fade.surface);
3299 weston_surface_damage(shell->fade.surface);
3301 loop = wl_display_get_event_loop(shell->compositor->wl_display);
3302 shell->fade.startup_timer =
3303 wl_event_loop_add_timer(loop, fade_startup_timeout, shell);
3304 wl_event_source_timer_update(shell->fade.startup_timer, 15000);
3308 idle_handler(struct wl_listener *listener, void *data)
3310 struct desktop_shell *shell =
3311 container_of(listener, struct desktop_shell, idle_listener);
3313 shell_fade(shell, FADE_OUT);
3314 /* lock() is called from shell_fade_done() */
3318 wake_handler(struct wl_listener *listener, void *data)
3320 struct desktop_shell *shell =
3321 container_of(listener, struct desktop_shell, wake_listener);
3327 show_input_panels(struct wl_listener *listener, void *data)
3329 struct desktop_shell *shell =
3330 container_of(listener, struct desktop_shell,
3331 show_input_panel_listener);
3332 struct input_panel_surface *surface, *next;
3333 struct weston_surface *ws;
3335 shell->text_input.surface = (struct weston_surface*)data;
3337 if (shell->showing_input_panels)
3340 shell->showing_input_panels = true;
3343 wl_list_insert(&shell->panel_layer.link,
3344 &shell->input_panel_layer.link);
3346 wl_list_for_each_safe(surface, next,
3347 &shell->input_panel.surfaces, link) {
3348 ws = surface->surface;
3349 if (!ws->buffer_ref.buffer)
3351 wl_list_insert(&shell->input_panel_layer.surface_list,
3353 weston_surface_geometry_dirty(ws);
3354 weston_surface_update_transform(ws);
3355 weston_surface_damage(ws);
3356 weston_slide_run(ws, ws->geometry.height, 0, NULL, NULL);
3361 hide_input_panels(struct wl_listener *listener, void *data)
3363 struct desktop_shell *shell =
3364 container_of(listener, struct desktop_shell,
3365 hide_input_panel_listener);
3366 struct weston_surface *surface, *next;
3368 if (!shell->showing_input_panels)
3371 shell->showing_input_panels = false;
3374 wl_list_remove(&shell->input_panel_layer.link);
3376 wl_list_for_each_safe(surface, next,
3377 &shell->input_panel_layer.surface_list, layer_link)
3378 weston_surface_unmap(surface);
3382 update_input_panels(struct wl_listener *listener, void *data)
3384 struct desktop_shell *shell =
3385 container_of(listener, struct desktop_shell,
3386 update_input_panel_listener);
3388 memcpy(&shell->text_input.cursor_rectangle, data, sizeof(pixman_box32_t));
3392 center_on_output(struct weston_surface *surface, struct weston_output *output)
3394 int32_t surf_x, surf_y, width, height;
3397 surface_subsurfaces_boundingbox(surface, &surf_x, &surf_y, &width, &height);
3399 x = output->x + (output->width - width) / 2 - surf_x / 2;
3400 y = output->y + (output->height - height) / 2 - surf_y / 2;
3402 uifw_trace("center_on_output: %08x x/y=%d/%d w/h=%d/%d",
3403 (int)output, (int)x, (int)y, width, height);
3404 weston_surface_configure(surface, x, y, width, height);
3408 weston_surface_set_initial_position (struct weston_surface *surface,
3409 struct desktop_shell *shell)
3411 struct weston_compositor *compositor = shell->compositor;
3413 int range_x, range_y;
3414 int dx, dy, x, y, panel_height;
3415 struct weston_output *output, *target_output = NULL;
3416 struct weston_seat *seat;
3418 /* As a heuristic place the new window on the same output as the
3419 * pointer. Falling back to the output containing 0, 0.
3421 * TODO: Do something clever for touch too?
3423 wl_list_for_each(seat, &compositor->seat_list, link) {
3424 if (seat->pointer) {
3425 ix = wl_fixed_to_int(seat->pointer->x);
3426 iy = wl_fixed_to_int(seat->pointer->y);
3431 wl_list_for_each(output, &compositor->output_list, link) {
3432 if (pixman_region32_contains_point(&output->region, ix, iy, NULL)) {
3433 target_output = output;
3438 if (!target_output) {
3439 weston_surface_set_position(surface, 10 + random() % 400,
3440 10 + random() % 400);
3444 /* Valid range within output where the surface will still be onscreen.
3445 * If this is negative it means that the surface is bigger than
3448 panel_height = get_output_panel_height(shell, target_output);
3449 range_x = target_output->width - surface->geometry.width;
3450 range_y = (target_output->height - panel_height) -
3451 surface->geometry.height;
3454 dx = random() % range_x;
3459 dy = panel_height + random() % range_y;
3463 x = target_output->x + dx;
3464 y = target_output->y + dy;
3466 weston_surface_set_position (surface, x, y);
3470 map(struct desktop_shell *shell, struct weston_surface *surface,
3471 int32_t width, int32_t height, int32_t sx, int32_t sy)
3473 struct weston_compositor *compositor = shell->compositor;
3474 struct shell_surface *shsurf = get_shell_surface(surface);
3475 enum shell_surface_type surface_type = shsurf->type;
3476 struct weston_surface *parent;
3477 struct weston_seat *seat;
3478 struct workspace *ws;
3479 int panel_height = 0;
3480 int32_t surf_x, surf_y;
3482 uifw_trace("map: %08x sx/sy=%d/%d w/h=%d/%d", (int)surface, sx, sy, width, height);
3483 surface->geometry.width = width;
3484 surface->geometry.height = height;
3485 weston_surface_geometry_dirty(surface);
3487 /* initial positioning, see also configure() */
3488 switch (surface_type) {
3489 case SHELL_SURFACE_TOPLEVEL:
3490 weston_surface_set_initial_position(surface, shell);
3492 case SHELL_SURFACE_FULLSCREEN:
3493 center_on_output(surface, shsurf->fullscreen_output);
3494 shell_map_fullscreen(shsurf);
3496 case SHELL_SURFACE_MAXIMIZED:
3497 /* use surface configure to set the geometry */
3498 panel_height = get_output_panel_height(shell,surface->output);
3499 surface_subsurfaces_boundingbox(shsurf->surface, &surf_x, &surf_y,
3501 weston_surface_set_position(surface, shsurf->output->x - surf_x,
3502 shsurf->output->y + panel_height - surf_y);
3504 case SHELL_SURFACE_POPUP:
3505 shell_map_popup(shsurf);
3507 case SHELL_SURFACE_NONE:
3508 weston_surface_set_position(surface,
3509 surface->geometry.x + sx,
3510 surface->geometry.y + sy);
3516 /* surface stacking order, see also activate() */
3517 switch (surface_type) {
3518 case SHELL_SURFACE_POPUP:
3519 case SHELL_SURFACE_TRANSIENT:
3520 parent = shsurf->parent;
3521 wl_list_insert(parent->layer_link.prev, &surface->layer_link);
3523 case SHELL_SURFACE_FULLSCREEN:
3524 case SHELL_SURFACE_NONE:
3526 case SHELL_SURFACE_XWAYLAND:
3528 ws = get_current_workspace(shell);
3529 wl_list_insert(&ws->layer.surface_list, &surface->layer_link);
3533 if (surface_type != SHELL_SURFACE_NONE) {
3534 weston_surface_update_transform(surface);
3535 if (surface_type == SHELL_SURFACE_MAXIMIZED)
3536 surface->output = shsurf->output;
3539 switch (surface_type) {
3540 /* XXX: xwayland's using the same fields for transient type */
3541 case SHELL_SURFACE_XWAYLAND:
3542 case SHELL_SURFACE_TRANSIENT:
3543 if (shsurf->transient.flags ==
3544 WL_SHELL_SURFACE_TRANSIENT_INACTIVE)
3546 case SHELL_SURFACE_TOPLEVEL:
3547 case SHELL_SURFACE_FULLSCREEN:
3548 case SHELL_SURFACE_MAXIMIZED:
3549 if (!shell->locked) {
3550 wl_list_for_each(seat, &compositor->seat_list, link)
3551 activate(shell, surface, seat);
3558 if (surface_type == SHELL_SURFACE_TOPLEVEL)
3560 switch (shell->win_animation_type) {
3561 case ANIMATION_FADE:
3562 weston_fade_run(surface, 0.0, 1.0, 300.0, NULL, NULL);
3564 case ANIMATION_ZOOM:
3565 weston_zoom_run(surface, 0.5, 1.0, NULL, NULL);
3572 /* if ico_window_mgr hook, call hook routine */
3573 if (shell_hook_map) {
3574 (*shell_hook_map)(surface, &width, &height, &sx, &sy);
3576 if (shell_hook_change) {
3577 (*shell_hook_change)(surface, -1, 0); /* send event to manager */
3582 configure(struct desktop_shell *shell, struct weston_surface *surface,
3583 float x, float y, int32_t width, int32_t height)
3585 enum shell_surface_type surface_type = SHELL_SURFACE_NONE;
3586 struct shell_surface *shsurf;
3587 int32_t surf_x, surf_y;
3589 shsurf = get_shell_surface(surface);
3591 surface_type = shsurf->type;
3593 uifw_trace("configure: %08x x/y=%d/%d w/h=%d/%d",
3594 (int)surface, (int)x, (int)y, width, height);
3595 weston_surface_configure(surface, x, y, width, height);
3597 switch (surface_type) {
3598 case SHELL_SURFACE_FULLSCREEN:
3599 shell_stack_fullscreen(shsurf);
3600 shell_configure_fullscreen(shsurf);
3602 case SHELL_SURFACE_MAXIMIZED:
3603 /* setting x, y and using configure to change that geometry */
3604 surface_subsurfaces_boundingbox(shsurf->surface, &surf_x, &surf_y,
3606 surface->geometry.x = surface->output->x - surf_x;
3607 surface->geometry.y = surface->output->y +
3608 get_output_panel_height(shell,surface->output) - surf_y;
3610 case SHELL_SURFACE_TOPLEVEL:
3616 /* XXX: would a fullscreen surface need the same handling? */
3617 if (surface->output) {
3618 weston_surface_update_transform(surface);
3620 if (surface_type == SHELL_SURFACE_MAXIMIZED)
3621 surface->output = shsurf->output;
3624 /* if ico_window_mgr hook, call hook routine */
3625 if (shell_hook_change) {
3626 (*shell_hook_change)(surface, -1, 0);
3631 shell_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height)
3633 struct shell_surface *shsurf = get_shell_surface(es);
3634 struct desktop_shell *shell = shsurf->shell;
3636 int type_changed = 0;
3638 if (!weston_surface_is_mapped(es) &&
3639 !wl_list_empty(&shsurf->popup.grab_link)) {
3640 remove_popup_grab(shsurf);
3646 if (shsurf->next_type != SHELL_SURFACE_NONE &&
3647 shsurf->type != shsurf->next_type) {
3648 set_surface_type(shsurf);
3652 if (!weston_surface_is_mapped(es)) {
3653 map(shell, es, width, height, sx, sy);
3654 } else if (type_changed || sx != 0 || sy != 0 ||
3655 es->geometry.width != width ||
3656 es->geometry.height != height) {
3657 float from_x, from_y;
3660 weston_surface_to_global_float(es, 0, 0, &from_x, &from_y);
3661 weston_surface_to_global_float(es, sx, sy, &to_x, &to_y);
3662 uifw_trace("shell_surface_configure: configure %08x x/y=%d/%d w/h=%d/%d",
3663 (int)es, (int)(es->geometry.x + to_x - from_x),
3664 (int)(es->geometry.y + to_y - from_y), width, height);
3665 configure(shell, es,
3666 es->geometry.x + to_x - from_x,
3667 es->geometry.y + to_y - from_y,
3672 static void launch_desktop_shell_process(void *data);
3675 desktop_shell_sigchld(struct weston_process *process, int status)
3678 struct desktop_shell *shell =
3679 container_of(process, struct desktop_shell, child.process);
3681 shell->child.process.pid = 0;
3682 shell->child.client = NULL; /* already destroyed by wayland */
3684 /* if desktop-shell dies more than 5 times in 30 seconds, give up */
3685 time = weston_compositor_get_time();
3686 if (time - shell->child.deathstamp > 30000) {
3687 shell->child.deathstamp = time;
3688 shell->child.deathcount = 0;
3691 shell->child.deathcount++;
3692 if (shell->child.deathcount > 5) {
3693 weston_log("%s, giving up.\n", shell_exe);
3697 weston_log("%s died, respawning...\n", shell_exe);
3698 launch_desktop_shell_process(shell);
3699 shell_fade_startup(shell);
3703 launch_desktop_shell_process(void *data)
3705 struct desktop_shell *shell = data;
3706 /* shell program path configurable for ico-ivi */
3707 /* const char *shell_exe = LIBEXECDIR "/weston-desktop-shell"; */
3709 if ((shell_exe[0] == 0) || (shell_exe[0] == ' ')) {
3710 weston_log("no shell program\n");
3713 shell->child.client = weston_client_launch(shell->compositor,
3714 &shell->child.process,
3716 desktop_shell_sigchld);
3718 if (!shell->child.client)
3719 weston_log("not able to start %s\n", shell_exe);
3721 weston_log("shell %s started\n", shell_exe);
3726 bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
3728 struct desktop_shell *shell = data;
3729 struct wl_resource *resource;
3731 resource = wl_resource_create(client, &wl_shell_interface, 1, id);
3733 wl_resource_set_implementation(resource, &shell_implementation,
3736 /* if ico_window_mgr hook, call hook routine */
3737 if (shell_hook_bind) {
3738 (*shell_hook_bind)(client, data);
3743 unbind_desktop_shell(struct wl_resource *resource)
3745 struct desktop_shell *shell = wl_resource_get_user_data(resource);
3747 /* if ico_window_mgr hook, call hook routine */
3748 if (shell_hook_unbind) {
3749 (*shell_hook_unbind)(resource->client);
3753 resume_desktop(shell);
3755 shell->child.desktop_shell = NULL;
3756 shell->prepare_event_sent = false;
3760 bind_desktop_shell(struct wl_client *client,
3761 void *data, uint32_t version, uint32_t id)
3763 struct desktop_shell *shell = data;
3764 struct wl_resource *resource;
3766 resource = wl_resource_create(client, &desktop_shell_interface,
3767 MIN(version, 2), id);
3769 if (client == shell->child.client) {
3770 wl_resource_set_implementation(resource,
3771 &desktop_shell_implementation,
3772 shell, unbind_desktop_shell);
3773 shell->child.desktop_shell = resource;
3776 shell_fade_startup(shell);
3781 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
3782 "permission to bind desktop_shell denied");
3783 wl_resource_destroy(resource);
3787 screensaver_configure(struct weston_surface *surface, int32_t sx, int32_t sy, int32_t width, int32_t height)
3789 struct desktop_shell *shell = surface->configure_private;
3794 /* XXX: starting weston-screensaver beforehand does not work */
3798 center_on_output(surface, surface->output);
3800 if (wl_list_empty(&surface->layer_link)) {
3801 wl_list_insert(shell->lock_layer.surface_list.prev,
3802 &surface->layer_link);
3803 weston_surface_update_transform(surface);
3804 wl_event_source_timer_update(shell->screensaver.timer,
3805 shell->screensaver.duration);
3806 shell_fade(shell, FADE_IN);
3811 screensaver_set_surface(struct wl_client *client,
3812 struct wl_resource *resource,
3813 struct wl_resource *surface_resource,
3814 struct wl_resource *output_resource)
3816 struct desktop_shell *shell = wl_resource_get_user_data(resource);
3817 struct weston_surface *surface =
3818 wl_resource_get_user_data(surface_resource);
3819 struct weston_output *output = wl_resource_get_user_data(output_resource);
3821 surface->configure = screensaver_configure;
3822 surface->configure_private = shell;
3823 surface->output = output;
3826 static const struct screensaver_interface screensaver_implementation = {
3827 screensaver_set_surface
3831 unbind_screensaver(struct wl_resource *resource)
3833 struct desktop_shell *shell = wl_resource_get_user_data(resource);
3835 shell->screensaver.binding = NULL;
3839 bind_screensaver(struct wl_client *client,
3840 void *data, uint32_t version, uint32_t id)
3842 struct desktop_shell *shell = data;
3843 struct wl_resource *resource;
3845 resource = wl_resource_create(client, &screensaver_interface, 1, id);
3847 if (shell->screensaver.binding == NULL) {
3848 wl_resource_set_implementation(resource,
3849 &screensaver_implementation,
3850 shell, unbind_screensaver);
3851 shell->screensaver.binding = resource;
3855 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
3856 "interface object already bound");
3857 wl_resource_destroy(resource);
3861 input_panel_configure(struct weston_surface *surface, int32_t sx, int32_t sy, int32_t width, int32_t height)
3863 struct input_panel_surface *ip_surface = surface->configure_private;
3864 struct desktop_shell *shell = ip_surface->shell;
3866 uint32_t show_surface = 0;
3871 if (!weston_surface_is_mapped(surface)) {
3872 if (!shell->showing_input_panels)
3878 fprintf(stderr, "%s panel: %d, output: %p\n", __FUNCTION__, ip_surface->panel, ip_surface->output);
3880 if (ip_surface->panel) {
3881 x = shell->text_input.surface->geometry.x + shell->text_input.cursor_rectangle.x2;
3882 y = shell->text_input.surface->geometry.y + shell->text_input.cursor_rectangle.y2;
3884 x = ip_surface->output->x + (ip_surface->output->width - width) / 2;
3885 y = ip_surface->output->y + ip_surface->output->height - height;
3888 uifw_trace("input_panel_configure: configure %08x x/y=%d/%d w/h=%d/%d",
3889 (int)surface, (int)x, (int)y, width, height);
3890 weston_surface_configure(surface,
3895 wl_list_insert(&shell->input_panel_layer.surface_list,
3896 &surface->layer_link);
3897 weston_surface_update_transform(surface);
3898 weston_surface_damage(surface);
3899 weston_slide_run(surface, surface->geometry.height, 0, NULL, NULL);
3904 destroy_input_panel_surface(struct input_panel_surface *input_panel_surface)
3906 wl_signal_emit(&input_panel_surface->destroy_signal, input_panel_surface);
3908 wl_list_remove(&input_panel_surface->surface_destroy_listener.link);
3909 wl_list_remove(&input_panel_surface->link);
3911 input_panel_surface->surface->configure = NULL;
3913 free(input_panel_surface);
3916 static struct input_panel_surface *
3917 get_input_panel_surface(struct weston_surface *surface)
3919 if (surface->configure == input_panel_configure) {
3920 return surface->configure_private;
3927 input_panel_handle_surface_destroy(struct wl_listener *listener, void *data)
3929 struct input_panel_surface *ipsurface = container_of(listener,
3930 struct input_panel_surface,
3931 surface_destroy_listener);
3933 if (ipsurface->resource) {
3934 wl_resource_destroy(ipsurface->resource);
3936 destroy_input_panel_surface(ipsurface);
3940 static struct input_panel_surface *
3941 create_input_panel_surface(struct desktop_shell *shell,
3942 struct weston_surface *surface)
3944 struct input_panel_surface *input_panel_surface;
3946 input_panel_surface = calloc(1, sizeof *input_panel_surface);
3947 if (!input_panel_surface)
3950 surface->configure = input_panel_configure;
3951 surface->configure_private = input_panel_surface;
3953 input_panel_surface->shell = shell;
3955 input_panel_surface->surface = surface;
3957 wl_signal_init(&input_panel_surface->destroy_signal);
3958 input_panel_surface->surface_destroy_listener.notify = input_panel_handle_surface_destroy;
3959 wl_signal_add(&surface->destroy_signal,
3960 &input_panel_surface->surface_destroy_listener);
3962 wl_list_init(&input_panel_surface->link);
3964 return input_panel_surface;
3968 input_panel_surface_set_toplevel(struct wl_client *client,
3969 struct wl_resource *resource,
3970 struct wl_resource *output_resource,
3973 struct input_panel_surface *input_panel_surface =
3974 wl_resource_get_user_data(resource);
3975 struct desktop_shell *shell = input_panel_surface->shell;
3977 wl_list_insert(&shell->input_panel.surfaces,
3978 &input_panel_surface->link);
3980 input_panel_surface->output = wl_resource_get_user_data(output_resource);
3981 input_panel_surface->panel = 0;
3985 input_panel_surface_set_overlay_panel(struct wl_client *client,
3986 struct wl_resource *resource)
3988 struct input_panel_surface *input_panel_surface =
3989 wl_resource_get_user_data(resource);
3990 struct desktop_shell *shell = input_panel_surface->shell;
3992 wl_list_insert(&shell->input_panel.surfaces,
3993 &input_panel_surface->link);
3995 input_panel_surface->panel = 1;
3998 static const struct wl_input_panel_surface_interface input_panel_surface_implementation = {
3999 input_panel_surface_set_toplevel,
4000 input_panel_surface_set_overlay_panel
4004 destroy_input_panel_surface_resource(struct wl_resource *resource)
4006 struct input_panel_surface *ipsurf =
4007 wl_resource_get_user_data(resource);
4009 destroy_input_panel_surface(ipsurf);
4013 input_panel_get_input_panel_surface(struct wl_client *client,
4014 struct wl_resource *resource,
4016 struct wl_resource *surface_resource)
4018 struct weston_surface *surface =
4019 wl_resource_get_user_data(surface_resource);
4020 struct desktop_shell *shell = wl_resource_get_user_data(resource);
4021 struct input_panel_surface *ipsurf;
4023 if (get_input_panel_surface(surface)) {
4024 wl_resource_post_error(surface_resource,
4025 WL_DISPLAY_ERROR_INVALID_OBJECT,
4026 "wl_input_panel::get_input_panel_surface already requested");
4030 ipsurf = create_input_panel_surface(shell, surface);
4032 wl_resource_post_error(surface_resource,
4033 WL_DISPLAY_ERROR_INVALID_OBJECT,
4034 "surface->configure already set");
4039 wl_resource_create(client,
4040 &wl_input_panel_surface_interface, 1, id);
4041 wl_resource_set_implementation(ipsurf->resource,
4042 &input_panel_surface_implementation,
4044 destroy_input_panel_surface_resource);
4047 static const struct wl_input_panel_interface input_panel_implementation = {
4048 input_panel_get_input_panel_surface
4052 unbind_input_panel(struct wl_resource *resource)
4054 struct desktop_shell *shell = wl_resource_get_user_data(resource);
4056 shell->input_panel.binding = NULL;
4060 bind_input_panel(struct wl_client *client,
4061 void *data, uint32_t version, uint32_t id)
4063 struct desktop_shell *shell = data;
4064 struct wl_resource *resource;
4066 resource = wl_resource_create(client,
4067 &wl_input_panel_interface, 1, id);
4069 if (shell->input_panel.binding == NULL) {
4070 wl_resource_set_implementation(resource,
4071 &input_panel_implementation,
4072 shell, unbind_input_panel);
4073 shell->input_panel.binding = resource;
4077 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
4078 "interface object already bound");
4079 wl_resource_destroy(resource);
4083 struct desktop_shell *shell;
4084 struct weston_surface *current;
4085 struct wl_listener listener;
4086 struct weston_keyboard_grab grab;
4090 switcher_next(struct switcher *switcher)
4092 struct weston_surface *surface;
4093 struct weston_surface *first = NULL, *prev = NULL, *next = NULL;
4094 struct shell_surface *shsurf;
4095 struct workspace *ws = get_current_workspace(switcher->shell);
4097 wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
4098 switch (get_shell_surface_type(surface)) {
4099 case SHELL_SURFACE_TOPLEVEL:
4100 case SHELL_SURFACE_FULLSCREEN:
4101 case SHELL_SURFACE_MAXIMIZED:
4104 if (prev == switcher->current)
4107 surface->alpha = 0.25;
4108 weston_surface_geometry_dirty(surface);
4109 weston_surface_damage(surface);
4115 if (is_black_surface(surface, NULL)) {
4116 surface->alpha = 0.25;
4117 weston_surface_geometry_dirty(surface);
4118 weston_surface_damage(surface);
4128 wl_list_remove(&switcher->listener.link);
4129 wl_signal_add(&next->destroy_signal, &switcher->listener);
4131 switcher->current = next;
4134 shsurf = get_shell_surface(switcher->current);
4135 if (shsurf && shsurf->type ==SHELL_SURFACE_FULLSCREEN)
4136 shsurf->fullscreen.black_surface->alpha = 1.0;
4140 switcher_handle_surface_destroy(struct wl_listener *listener, void *data)
4142 struct switcher *switcher =
4143 container_of(listener, struct switcher, listener);
4145 switcher_next(switcher);
4149 switcher_destroy(struct switcher *switcher)
4151 struct weston_surface *surface;
4152 struct weston_keyboard *keyboard = switcher->grab.keyboard;
4153 struct workspace *ws = get_current_workspace(switcher->shell);
4155 wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
4156 surface->alpha = 1.0;
4157 weston_surface_damage(surface);
4160 if (switcher->current)
4161 activate(switcher->shell, switcher->current,
4162 (struct weston_seat *) keyboard->seat);
4163 wl_list_remove(&switcher->listener.link);
4164 weston_keyboard_end_grab(keyboard);
4165 if (keyboard->input_method_resource)
4166 keyboard->grab = &keyboard->input_method_grab;
4171 switcher_key(struct weston_keyboard_grab *grab,
4172 uint32_t time, uint32_t key, uint32_t state_w)
4174 struct switcher *switcher = container_of(grab, struct switcher, grab);
4175 enum wl_keyboard_key_state state = state_w;
4177 if (key == KEY_TAB && state == WL_KEYBOARD_KEY_STATE_PRESSED)
4178 switcher_next(switcher);
4182 switcher_modifier(struct weston_keyboard_grab *grab, uint32_t serial,
4183 uint32_t mods_depressed, uint32_t mods_latched,
4184 uint32_t mods_locked, uint32_t group)
4186 struct switcher *switcher = container_of(grab, struct switcher, grab);
4187 struct weston_seat *seat = (struct weston_seat *) grab->keyboard->seat;
4189 if ((seat->modifier_state & switcher->shell->binding_modifier) == 0)
4190 switcher_destroy(switcher);
4193 static const struct weston_keyboard_grab_interface switcher_grab = {
4199 switcher_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
4202 struct desktop_shell *shell = data;
4203 struct switcher *switcher;
4205 switcher = malloc(sizeof *switcher);
4206 switcher->shell = shell;
4207 switcher->current = NULL;
4208 switcher->listener.notify = switcher_handle_surface_destroy;
4209 wl_list_init(&switcher->listener.link);
4211 restore_all_output_modes(shell->compositor);
4212 lower_fullscreen_layer(switcher->shell);
4213 switcher->grab.interface = &switcher_grab;
4214 weston_keyboard_start_grab(seat->keyboard, &switcher->grab);
4215 weston_keyboard_set_focus(seat->keyboard, NULL);
4216 switcher_next(switcher);
4220 backlight_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
4223 struct weston_compositor *compositor = data;
4224 struct weston_output *output;
4225 long backlight_new = 0;
4227 /* TODO: we're limiting to simple use cases, where we assume just
4228 * control on the primary display. We'd have to extend later if we
4229 * ever get support for setting backlights on random desktop LCD
4231 output = get_default_output(compositor);
4235 if (!output->set_backlight)
4238 if (key == KEY_F9 || key == KEY_BRIGHTNESSDOWN)
4239 backlight_new = output->backlight_current - 25;
4240 else if (key == KEY_F10 || key == KEY_BRIGHTNESSUP)
4241 backlight_new = output->backlight_current + 25;
4243 if (backlight_new < 5)
4245 if (backlight_new > 255)
4246 backlight_new = 255;
4248 output->backlight_current = backlight_new;
4249 output->set_backlight(output, output->backlight_current);
4252 struct debug_binding_grab {
4253 struct weston_keyboard_grab grab;
4254 struct weston_seat *seat;
4256 int key_released[2];
4260 debug_binding_key(struct weston_keyboard_grab *grab, uint32_t time,
4261 uint32_t key, uint32_t state)
4263 struct debug_binding_grab *db = (struct debug_binding_grab *) grab;
4264 struct wl_resource *resource;
4265 struct wl_display *display;
4267 int send = 0, terminate = 0;
4268 int check_binding = 1;
4271 if (state == WL_KEYBOARD_KEY_STATE_RELEASED) {
4272 /* Do not run bindings on key releases */
4275 for (i = 0; i < 2; i++)
4276 if (key == db->key[i])
4277 db->key_released[i] = 1;
4279 if (db->key_released[0] && db->key_released[1]) {
4280 /* All key releases been swalled so end the grab */
4282 } else if (key != db->key[0] && key != db->key[1]) {
4283 /* Should not swallow release of other keys */
4286 } else if (key == db->key[0] && !db->key_released[0]) {
4287 /* Do not check bindings for the first press of the binding
4288 * key. This allows it to be used as a debug shortcut.
4289 * We still need to swallow this event. */
4291 } else if (db->key[1]) {
4292 /* If we already ran a binding don't process another one since
4293 * we can't keep track of all the binding keys that were
4294 * pressed in order to swallow the release events. */
4299 if (check_binding) {
4300 struct weston_compositor *ec = db->seat->compositor;
4302 if (weston_compositor_run_debug_binding(ec, db->seat, time,
4304 /* We ran a binding so swallow the press and keep the
4305 * grab to swallow the released too. */
4310 /* Terminate the grab since the key pressed is not a
4311 * debug binding key. */
4318 resource = grab->keyboard->focus_resource;
4321 display = wl_client_get_display(wl_resource_get_client(resource));
4322 serial = wl_display_next_serial(display);
4323 wl_keyboard_send_key(resource, serial, time, key, state);
4328 weston_keyboard_end_grab(grab->keyboard);
4329 if (grab->keyboard->input_method_resource)
4330 grab->keyboard->grab = &grab->keyboard->input_method_grab;
4336 debug_binding_modifiers(struct weston_keyboard_grab *grab, uint32_t serial,
4337 uint32_t mods_depressed, uint32_t mods_latched,
4338 uint32_t mods_locked, uint32_t group)
4340 struct wl_resource *resource;
4342 resource = grab->keyboard->focus_resource;
4346 wl_keyboard_send_modifiers(resource, serial, mods_depressed,
4347 mods_latched, mods_locked, group);
4350 struct weston_keyboard_grab_interface debug_binding_keyboard_grab = {
4352 debug_binding_modifiers
4356 debug_binding(struct weston_seat *seat, uint32_t time, uint32_t key, void *data)
4358 struct debug_binding_grab *grab;
4360 grab = calloc(1, sizeof *grab);
4364 grab->seat = (struct weston_seat *) seat;
4366 grab->grab.interface = &debug_binding_keyboard_grab;
4367 weston_keyboard_start_grab(seat->keyboard, &grab->grab);
4371 force_kill_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
4374 struct weston_surface *focus_surface;
4375 struct wl_client *client;
4376 struct desktop_shell *shell = data;
4377 struct weston_compositor *compositor = shell->compositor;
4380 focus_surface = seat->keyboard->focus;
4384 wl_signal_emit(&compositor->kill_signal, focus_surface);
4386 client = wl_resource_get_client(focus_surface->resource);
4387 wl_client_get_credentials(client, &pid, NULL, NULL);
4389 /* Skip clients that we launched ourselves (the credentials of
4390 * the socketpair is ours) */
4391 if (pid == getpid())
4398 workspace_up_binding(struct weston_seat *seat, uint32_t time,
4399 uint32_t key, void *data)
4401 struct desktop_shell *shell = data;
4402 unsigned int new_index = shell->workspaces.current;
4409 change_workspace(shell, new_index);
4413 workspace_down_binding(struct weston_seat *seat, uint32_t time,
4414 uint32_t key, void *data)
4416 struct desktop_shell *shell = data;
4417 unsigned int new_index = shell->workspaces.current;
4421 if (new_index < shell->workspaces.num - 1)
4424 change_workspace(shell, new_index);
4428 workspace_f_binding(struct weston_seat *seat, uint32_t time,
4429 uint32_t key, void *data)
4431 struct desktop_shell *shell = data;
4432 unsigned int new_index;
4436 new_index = key - KEY_F1;
4437 if (new_index >= shell->workspaces.num)
4438 new_index = shell->workspaces.num - 1;
4440 change_workspace(shell, new_index);
4444 workspace_move_surface_up_binding(struct weston_seat *seat, uint32_t time,
4445 uint32_t key, void *data)
4447 struct desktop_shell *shell = data;
4448 unsigned int new_index = shell->workspaces.current;
4456 take_surface_to_workspace_by_seat(shell, seat, new_index);
4460 workspace_move_surface_down_binding(struct weston_seat *seat, uint32_t time,
4461 uint32_t key, void *data)
4463 struct desktop_shell *shell = data;
4464 unsigned int new_index = shell->workspaces.current;
4469 if (new_index < shell->workspaces.num - 1)
4472 take_surface_to_workspace_by_seat(shell, seat, new_index);
4476 shell_destroy(struct wl_listener *listener, void *data)
4478 struct desktop_shell *shell =
4479 container_of(listener, struct desktop_shell, destroy_listener);
4480 struct workspace **ws;
4482 if (shell->child.client)
4483 wl_client_destroy(shell->child.client);
4485 wl_list_remove(&shell->idle_listener.link);
4486 wl_list_remove(&shell->wake_listener.link);
4487 wl_list_remove(&shell->show_input_panel_listener.link);
4488 wl_list_remove(&shell->hide_input_panel_listener.link);
4490 wl_array_for_each(ws, &shell->workspaces.array)
4491 workspace_destroy(*ws);
4492 wl_array_release(&shell->workspaces.array);
4494 free(shell->screensaver.path);
4499 shell_add_bindings(struct weston_compositor *ec, struct desktop_shell *shell)
4502 int i, num_workspace_bindings;
4504 /* fixed bindings */
4505 weston_compositor_add_key_binding(ec, KEY_BACKSPACE,
4506 MODIFIER_CTRL | MODIFIER_ALT,
4507 terminate_binding, ec);
4508 weston_compositor_add_button_binding(ec, BTN_LEFT, 0,
4509 click_to_activate_binding,
4511 weston_compositor_add_axis_binding(ec, WL_POINTER_AXIS_VERTICAL_SCROLL,
4512 MODIFIER_SUPER | MODIFIER_ALT,
4513 surface_opacity_binding, NULL);
4514 weston_compositor_add_axis_binding(ec, WL_POINTER_AXIS_VERTICAL_SCROLL,
4515 MODIFIER_SUPER, zoom_axis_binding,
4518 /* configurable bindings */
4519 mod = shell->binding_modifier;
4520 weston_compositor_add_key_binding(ec, KEY_PAGEUP, mod,
4521 zoom_key_binding, NULL);
4522 weston_compositor_add_key_binding(ec, KEY_PAGEDOWN, mod,
4523 zoom_key_binding, NULL);
4524 weston_compositor_add_button_binding(ec, BTN_LEFT, mod, move_binding,
4526 weston_compositor_add_button_binding(ec, BTN_MIDDLE, mod,
4527 resize_binding, shell);
4529 if (ec->capabilities & WESTON_CAP_ROTATION_ANY)
4530 weston_compositor_add_button_binding(ec, BTN_RIGHT, mod,
4531 rotate_binding, NULL);
4533 weston_compositor_add_key_binding(ec, KEY_TAB, mod, switcher_binding,
4535 weston_compositor_add_key_binding(ec, KEY_F9, mod, backlight_binding,
4537 weston_compositor_add_key_binding(ec, KEY_BRIGHTNESSDOWN, 0,
4538 backlight_binding, ec);
4539 weston_compositor_add_key_binding(ec, KEY_F10, mod, backlight_binding,
4541 weston_compositor_add_key_binding(ec, KEY_BRIGHTNESSUP, 0,
4542 backlight_binding, ec);
4543 weston_compositor_add_key_binding(ec, KEY_K, mod,
4544 force_kill_binding, shell);
4545 weston_compositor_add_key_binding(ec, KEY_UP, mod,
4546 workspace_up_binding, shell);
4547 weston_compositor_add_key_binding(ec, KEY_DOWN, mod,
4548 workspace_down_binding, shell);
4549 weston_compositor_add_key_binding(ec, KEY_UP, mod | MODIFIER_SHIFT,
4550 workspace_move_surface_up_binding,
4552 weston_compositor_add_key_binding(ec, KEY_DOWN, mod | MODIFIER_SHIFT,
4553 workspace_move_surface_down_binding,
4556 /* Add bindings for mod+F[1-6] for workspace 1 to 6. */
4557 if (shell->workspaces.num > 1) {
4558 num_workspace_bindings = shell->workspaces.num;
4559 if (num_workspace_bindings > 6)
4560 num_workspace_bindings = 6;
4561 for (i = 0; i < num_workspace_bindings; i++)
4562 weston_compositor_add_key_binding(ec, KEY_F1 + i, mod,
4563 workspace_f_binding,
4567 /* Debug bindings */
4568 weston_compositor_add_key_binding(ec, KEY_SPACE, mod | MODIFIER_SHIFT,
4569 debug_binding, shell);
4573 module_init(struct weston_compositor *ec,
4574 int *argc, char *argv[])
4576 struct weston_seat *seat;
4577 struct desktop_shell *shell;
4578 struct workspace **pws;
4580 struct wl_event_loop *loop;
4582 shell = malloc(sizeof *shell);
4586 /* save shell management table for other plugin */
4587 _ico_ivi_shell = shell;
4589 memset(shell, 0, sizeof *shell);
4590 shell->compositor = ec;
4592 shell->destroy_listener.notify = shell_destroy;
4593 wl_signal_add(&ec->destroy_signal, &shell->destroy_listener);
4594 shell->idle_listener.notify = idle_handler;
4595 wl_signal_add(&ec->idle_signal, &shell->idle_listener);
4596 shell->wake_listener.notify = wake_handler;
4597 wl_signal_add(&ec->wake_signal, &shell->wake_listener);
4598 shell->show_input_panel_listener.notify = show_input_panels;
4599 wl_signal_add(&ec->show_input_panel_signal, &shell->show_input_panel_listener);
4600 shell->hide_input_panel_listener.notify = hide_input_panels;
4601 wl_signal_add(&ec->hide_input_panel_signal, &shell->hide_input_panel_listener);
4602 shell->update_input_panel_listener.notify = update_input_panels;
4603 wl_signal_add(&ec->update_input_panel_signal, &shell->update_input_panel_listener);
4604 ec->ping_handler = ping_handler;
4605 ec->shell_interface.shell = shell;
4606 ec->shell_interface.create_shell_surface = create_shell_surface;
4607 ec->shell_interface.set_toplevel = set_toplevel;
4608 ec->shell_interface.set_transient = set_transient;
4609 ec->shell_interface.set_fullscreen = set_fullscreen;
4610 ec->shell_interface.set_xwayland = set_xwayland;
4611 ec->shell_interface.move = surface_move;
4612 ec->shell_interface.resize = surface_resize;
4614 wl_list_init(&shell->input_panel.surfaces);
4616 weston_layer_init(&shell->fullscreen_layer, &ec->cursor_layer.link);
4617 weston_layer_init(&shell->panel_layer, &shell->fullscreen_layer.link);
4618 weston_layer_init(&shell->background_layer, &shell->panel_layer.link);
4619 weston_layer_init(&shell->lock_layer, NULL);
4620 weston_layer_init(&shell->input_panel_layer, NULL);
4622 wl_array_init(&shell->workspaces.array);
4623 wl_list_init(&shell->workspaces.client_list);
4625 shell_configuration(shell);
4627 for (i = 0; i < shell->workspaces.num; i++) {
4628 pws = wl_array_add(&shell->workspaces.array, sizeof *pws);
4632 *pws = workspace_create();
4636 activate_workspace(shell, 0);
4638 wl_list_init(&shell->workspaces.anim_sticky_list);
4639 wl_list_init(&shell->workspaces.animation.link);
4640 shell->workspaces.animation.frame = animate_workspace_change_frame;
4642 if (wl_global_create(ec->wl_display, &wl_shell_interface, 1,
4643 shell, bind_shell) == NULL)
4646 if (wl_global_create(ec->wl_display,
4647 &desktop_shell_interface, 2,
4648 shell, bind_desktop_shell) == NULL)
4651 if (wl_global_create(ec->wl_display, &screensaver_interface, 1,
4652 shell, bind_screensaver) == NULL)
4655 if (wl_global_create(ec->wl_display, &wl_input_panel_interface, 1,
4656 shell, bind_input_panel) == NULL)
4659 if (wl_global_create(ec->wl_display, &workspace_manager_interface, 1,
4660 shell, bind_workspace_manager) == NULL)
4663 shell->child.deathstamp = weston_compositor_get_time();
4665 loop = wl_display_get_event_loop(ec->wl_display);
4666 wl_event_loop_add_idle(loop, launch_desktop_shell_process, shell);
4668 shell->screensaver.timer =
4669 wl_event_loop_add_timer(loop, screensaver_timeout, shell);
4671 wl_list_for_each(seat, &ec->seat_list, link)
4672 create_pointer_focus_listener(seat);
4674 shell_add_bindings(ec, shell);
4676 shell_fade_init(shell);
4681 /*--------------------------------------------------------------------------*/
4683 * @brief ico_ivi_shell_current_layer: get current weston layer
4686 * @return current weston layer
4687 * @retval !=NULL success(current weston layer)
4688 * @retval ==NULL error(no layer)
4690 /*--------------------------------------------------------------------------*/
4691 /* API for other plugin */
4692 WL_EXPORT struct weston_layer *
4693 ico_ivi_shell_current_layer(void)
4695 struct workspace *ws = get_current_workspace(_ico_ivi_shell);
4697 return (ws != NULL) ? &ws->layer : NULL;
4700 /*--------------------------------------------------------------------------*/
4702 * @brief ico_ivi_shell_set_toplevel: set surface to TopLevel
4704 * @param[in] shsurf shell surface
4707 /*--------------------------------------------------------------------------*/
4709 ico_ivi_shell_set_toplevel(struct shell_surface *shsurf)
4711 set_toplevel(shsurf);
4714 /*--------------------------------------------------------------------------*/
4716 * @brief ico_ivi_shell_set_surface_type: set surface type
4718 * @param[in] shsurf shell surface
4721 /*--------------------------------------------------------------------------*/
4723 ico_ivi_shell_set_surface_type(struct shell_surface *shsurf)
4725 set_surface_type(shsurf);
4728 /*--------------------------------------------------------------------------*/
4730 * @brief ico_ivi_shell_send_configure: send configure event to client application
4732 * @param[in] surface weston surface
4733 * @param[in] edges surface resize position
4734 * @param[in] width surface width
4735 * @param[in] height surface height
4738 /*--------------------------------------------------------------------------*/
4740 ico_ivi_shell_send_configure(struct weston_surface *surface,
4741 const uint32_t edges, const int width, const int height)
4743 send_configure(surface, edges, width, height);
4746 /*--------------------------------------------------------------------------*/
4748 * @brief ico_ivi_shell_startup: start shell surface fade
4750 * @param[in] shell shell table address
4753 /*--------------------------------------------------------------------------*/
4755 ico_ivi_shell_startup(void *shell)
4757 shell_fade_startup((struct desktop_shell *)shell);
4760 /*--------------------------------------------------------------------------*/
4762 * @brief ico_ivi_shell_hook_bind: regist hook function for shell bind
4764 * @param[in] hook_bind hook function(if NULL, reset hook function)
4767 /*--------------------------------------------------------------------------*/
4769 ico_ivi_shell_hook_bind(void (*hook_bind)(struct wl_client *client, void *shell))
4771 shell_hook_bind = hook_bind;
4774 /*--------------------------------------------------------------------------*/
4776 * @brief ico_ivi_shell_hook_unbind: regist hook function for shell unbind
4778 * @param[in] hook_unbind hook function(if NULL, reset hook function)
4781 /*--------------------------------------------------------------------------*/
4783 ico_ivi_shell_hook_unbind(void (*hook_unbind)(struct wl_client *client))
4785 shell_hook_unbind = hook_unbind;
4788 /*--------------------------------------------------------------------------*/
4790 * @brief ico_ivi_shell_hook_create: regist hook function for create shell surface
4792 * @param[in] hook_create hook function(if NULL, reset hook function)
4795 /*--------------------------------------------------------------------------*/
4797 ico_ivi_shell_hook_create(void (*hook_create)(struct wl_client *client,
4798 struct wl_resource *resource,
4799 struct weston_surface *surface,
4800 struct shell_surface *shsurf))
4802 shell_hook_create = hook_create;
4805 /*--------------------------------------------------------------------------*/
4807 * @brief ico_ivi_shell_hook_destroy: regist hook function for destroy shell surface
4809 * @param[in] hook_destroy hook function(if NULL, reset hook function)
4812 /*--------------------------------------------------------------------------*/
4814 ico_ivi_shell_hook_destroy(void (*hook_destroy)(struct weston_surface *surface))
4816 shell_hook_destroy = hook_destroy;
4819 /*--------------------------------------------------------------------------*/
4821 * @brief ico_ivi_shell_hook_map: regist hook function for map shell surface
4823 * @param[in] hook_map hook function(if NULL, reset hook function)
4826 /*--------------------------------------------------------------------------*/
4828 ico_ivi_shell_hook_map(void (*hook_map)(struct weston_surface *surface,
4829 int32_t *width, int32_t *height,
4830 int32_t *sx, int32_t *sy))
4832 shell_hook_map = hook_map;
4835 /*--------------------------------------------------------------------------*/
4837 * @brief ico_ivi_shell_hook_change: regist hook function for change shell surface
4839 * @param[in] hook_change hook function(if NULL, reset hook function)
4842 /*--------------------------------------------------------------------------*/
4844 ico_ivi_shell_hook_change(void (*hook_change)(struct weston_surface *surface,
4845 const int to, const int manager))
4847 shell_hook_change = hook_change;
4850 /*--------------------------------------------------------------------------*/
4852 * @brief ico_ivi_shell_hook_select: regist hook function for select(active) shell surface
4854 * @param[in] hook_select hook function(if NULL, reset hook function)
4857 /*--------------------------------------------------------------------------*/
4859 ico_ivi_shell_hook_select(void (*hook_select)(struct weston_surface *surface))
4861 shell_hook_select = hook_select;
4864 /*--------------------------------------------------------------------------*/
4866 * @brief ico_ivi_shell_hook_title: regist hook function for select(active) shell surface
4868 * @param[in] hook_title hook function(if NULL, reset hook function)
4871 /*--------------------------------------------------------------------------*/
4873 ico_ivi_shell_hook_title(void (*hook_title)(struct weston_surface *surface,
4876 shell_hook_title = hook_title;
4879 /*--------------------------------------------------------------------------*/
4881 * @brief ico_ivi_shell_hook_move: regist hook function for move grab
4883 * @param[in] hook_move hook function(if NULL, reset hook function)
4884 * @param[in/out] dx new X coordinate
4885 * @param[in/out] dy new Y coordinate
4888 /*--------------------------------------------------------------------------*/
4890 ico_ivi_shell_hook_move(void (*hook_move)(struct weston_surface *surface, int *dx, int *dy))
4892 shell_hook_move = hook_move;