2 * Copyright © 2010-2012 Intel Corporation
3 * Copyright © 2011-2012 Collabora, Ltd.
4 * Copyright © 2013 Raspberry Pi Foundation
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.
32 #include <linux/input.h>
36 #include <sys/types.h>
38 #include "compositor.h"
39 #include "desktop-shell-server-protocol.h"
40 #include "input-method-server-protocol.h"
41 #include "workspaces-server-protocol.h"
42 #include "../shared/config-parser.h"
44 #define DEFAULT_NUM_WORKSPACES 1
45 #define DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH 200
60 enum exposay_target_state {
61 EXPOSAY_TARGET_OVERVIEW, /* show all windows */
62 EXPOSAY_TARGET_CANCEL, /* return to normal, same focus */
63 EXPOSAY_TARGET_SWITCH, /* return to normal, switch focus */
66 enum exposay_layout_state {
67 EXPOSAY_LAYOUT_INACTIVE = 0, /* normal desktop */
68 EXPOSAY_LAYOUT_ANIMATE_TO_INACTIVE, /* in transition to normal */
69 EXPOSAY_LAYOUT_OVERVIEW, /* show all windows */
70 EXPOSAY_LAYOUT_ANIMATE_TO_OVERVIEW, /* in transition to all windows */
74 struct weston_seat *seat;
76 struct weston_surface *keyboard_focus;
78 struct wl_listener seat_destroy_listener;
79 struct wl_listener surface_destroy_listener;
82 struct focus_surface {
83 struct weston_surface *surface;
84 struct weston_view *view;
85 struct weston_transform workspace_transform;
89 struct weston_layer layer;
91 struct wl_list focus_list;
92 struct wl_listener seat_destroyed_listener;
94 struct focus_surface *fsurf_front;
95 struct focus_surface *fsurf_back;
96 struct weston_view_animation *focus_animation;
99 struct input_panel_surface {
100 struct wl_resource *resource;
101 struct wl_signal destroy_signal;
103 struct desktop_shell *shell;
106 struct weston_surface *surface;
107 struct weston_view *view;
108 struct wl_listener surface_destroy_listener;
110 struct weston_output *output;
114 struct shell_output {
115 struct desktop_shell *shell;
116 struct weston_output *output;
117 struct wl_listener destroy_listener;
121 struct desktop_shell {
122 struct weston_compositor *compositor;
124 struct wl_listener idle_listener;
125 struct wl_listener wake_listener;
126 struct wl_listener destroy_listener;
127 struct wl_listener show_input_panel_listener;
128 struct wl_listener hide_input_panel_listener;
129 struct wl_listener update_input_panel_listener;
131 struct weston_layer fullscreen_layer;
132 struct weston_layer panel_layer;
133 struct weston_layer background_layer;
134 struct weston_layer lock_layer;
135 struct weston_layer input_panel_layer;
137 struct wl_listener pointer_focus_listener;
138 struct weston_surface *grab_surface;
141 struct weston_process process;
142 struct wl_client *client;
143 struct wl_resource *desktop_shell;
150 bool showing_input_panels;
151 bool prepare_event_sent;
154 struct weston_surface *surface;
155 pixman_box32_t cursor_rectangle;
158 struct weston_surface *lock_surface;
159 struct wl_listener lock_surface_listener;
162 struct wl_array array;
163 unsigned int current;
166 struct wl_list client_list;
168 struct weston_animation animation;
169 struct wl_list anim_sticky_list;
171 uint32_t anim_timestamp;
173 struct workspace *anim_from;
174 struct workspace *anim_to;
180 struct wl_resource *binding;
181 struct weston_process process;
182 struct wl_event_source *timer;
186 struct wl_resource *binding;
187 struct wl_list surfaces;
191 struct weston_view *view;
192 struct weston_view_animation *animation;
194 struct wl_event_source *startup_timer;
198 /* XXX: Make these exposay_surfaces. */
199 struct weston_view *focus_prev;
200 struct weston_view *focus_current;
201 struct weston_view *clicked;
202 struct workspace *workspace;
203 struct weston_seat *seat;
204 struct wl_list surface_list;
206 struct weston_keyboard_grab grab_kbd;
207 struct weston_pointer_grab grab_ptr;
209 enum exposay_target_state state_target;
210 enum exposay_layout_state state_cur;
211 int in_flight; /* number of animations still running */
225 uint32_t binding_modifier;
226 enum animation_type win_animation_type;
227 enum animation_type startup_animation_type;
228 enum animation_type focus_animation_type;
230 struct wl_listener output_create_listener;
231 struct wl_list output_list;
236 enum shell_surface_type {
238 SHELL_SURFACE_TOPLEVEL,
239 SHELL_SURFACE_TRANSIENT,
240 SHELL_SURFACE_FULLSCREEN,
241 SHELL_SURFACE_MAXIMIZED,
243 SHELL_SURFACE_XWAYLAND
247 struct wl_event_source *source;
251 struct shell_surface {
252 struct wl_resource *resource;
253 struct wl_signal destroy_signal;
255 struct weston_surface *surface;
256 struct weston_view *view;
257 struct wl_listener surface_destroy_listener;
258 struct weston_surface *parent;
259 struct desktop_shell *shell;
261 enum shell_surface_type type, next_type;
263 int32_t saved_x, saved_y;
264 bool saved_position_valid;
265 bool saved_rotation_valid;
266 int unresponsive, grabbed;
269 struct weston_transform transform;
270 struct weston_matrix rotation;
274 struct wl_list grab_link;
276 struct shell_seat *shseat;
286 enum wl_shell_surface_fullscreen_method type;
287 struct weston_transform transform; /* matrix from x, y */
289 struct weston_view *black_view;
292 struct ping_timer *ping_timer;
294 struct weston_transform workspace_transform;
296 struct weston_output *fullscreen_output;
297 struct weston_output *output;
300 const struct weston_shell_client *client;
304 struct weston_pointer_grab grab;
305 struct shell_surface *shsurf;
306 struct wl_listener shsurf_destroy_listener;
309 struct shell_touch_grab {
310 struct weston_touch_grab grab;
311 struct shell_surface *shsurf;
312 struct wl_listener shsurf_destroy_listener;
313 struct weston_touch *touch;
316 struct weston_move_grab {
317 struct shell_grab base;
321 struct weston_touch_move_grab {
322 struct shell_touch_grab base;
327 struct shell_grab base;
328 struct weston_matrix rotation;
336 struct weston_seat *seat;
337 struct wl_listener seat_destroy_listener;
340 struct weston_pointer_grab grab;
341 struct wl_list surfaces_list;
342 struct wl_client *client;
348 activate(struct desktop_shell *shell, struct weston_surface *es,
349 struct weston_seat *seat);
351 static struct workspace *
352 get_current_workspace(struct desktop_shell *shell);
354 static struct shell_surface *
355 get_shell_surface(struct weston_surface *surface);
357 static struct desktop_shell *
358 shell_surface_get_shell(struct shell_surface *shsurf);
361 surface_rotate(struct shell_surface *surface, struct weston_seat *seat);
364 shell_fade_startup(struct desktop_shell *shell);
367 shell_surface_is_top_fullscreen(struct shell_surface *shsurf)
369 struct desktop_shell *shell;
370 struct weston_view *top_fs_ev;
372 shell = shell_surface_get_shell(shsurf);
374 if (wl_list_empty(&shell->fullscreen_layer.view_list))
377 top_fs_ev = container_of(shell->fullscreen_layer.view_list.next,
380 return (shsurf == get_shell_surface(top_fs_ev->surface));
384 destroy_shell_grab_shsurf(struct wl_listener *listener, void *data)
386 struct shell_grab *grab;
388 grab = container_of(listener, struct shell_grab,
389 shsurf_destroy_listener);
394 static struct weston_view *
395 get_default_view(struct weston_surface *surface)
397 struct shell_surface *shsurf;
398 struct weston_view *view;
400 if (!surface || wl_list_empty(&surface->views))
403 shsurf = get_shell_surface(surface);
407 wl_list_for_each(view, &surface->views, surface_link)
408 if (weston_view_is_mapped(view))
411 return container_of(surface->views.next, struct weston_view, surface_link);
415 popup_grab_end(struct weston_pointer *pointer);
418 shell_grab_start(struct shell_grab *grab,
419 const struct weston_pointer_grab_interface *interface,
420 struct shell_surface *shsurf,
421 struct weston_pointer *pointer,
422 enum desktop_shell_cursor cursor)
424 struct desktop_shell *shell = shsurf->shell;
426 popup_grab_end(pointer);
428 grab->grab.interface = interface;
429 grab->shsurf = shsurf;
430 grab->shsurf_destroy_listener.notify = destroy_shell_grab_shsurf;
431 wl_signal_add(&shsurf->destroy_signal,
432 &grab->shsurf_destroy_listener);
435 weston_pointer_start_grab(pointer, &grab->grab);
436 if (shell->child.desktop_shell) {
437 desktop_shell_send_grab_cursor(shell->child.desktop_shell,
439 weston_pointer_set_focus(pointer,
440 get_default_view(shell->grab_surface),
441 wl_fixed_from_int(0),
442 wl_fixed_from_int(0));
447 shell_grab_end(struct shell_grab *grab)
450 wl_list_remove(&grab->shsurf_destroy_listener.link);
451 grab->shsurf->grabbed = 0;
454 weston_pointer_end_grab(grab->grab.pointer);
458 shell_touch_grab_start(struct shell_touch_grab *grab,
459 const struct weston_touch_grab_interface *interface,
460 struct shell_surface *shsurf,
461 struct weston_touch *touch)
463 struct desktop_shell *shell = shsurf->shell;
465 grab->grab.interface = interface;
466 grab->shsurf = shsurf;
467 grab->shsurf_destroy_listener.notify = destroy_shell_grab_shsurf;
468 wl_signal_add(&shsurf->destroy_signal,
469 &grab->shsurf_destroy_listener);
474 weston_touch_start_grab(touch, &grab->grab);
475 if (shell->child.desktop_shell)
476 weston_touch_set_focus(touch->seat,
477 get_default_view(shell->grab_surface));
481 shell_touch_grab_end(struct shell_touch_grab *grab)
484 wl_list_remove(&grab->shsurf_destroy_listener.link);
485 grab->shsurf->grabbed = 0;
488 weston_touch_end_grab(grab->touch);
492 center_on_output(struct weston_view *view,
493 struct weston_output *output);
495 static enum weston_keyboard_modifier
496 get_modifier(char *modifier)
499 return MODIFIER_SUPER;
501 if (!strcmp("ctrl", modifier))
502 return MODIFIER_CTRL;
503 else if (!strcmp("alt", modifier))
505 else if (!strcmp("super", modifier))
506 return MODIFIER_SUPER;
508 return MODIFIER_SUPER;
511 static enum animation_type
512 get_animation_type(char *animation)
514 if (!strcmp("zoom", animation))
515 return ANIMATION_ZOOM;
516 else if (!strcmp("fade", animation))
517 return ANIMATION_FADE;
518 else if (!strcmp("dim-layer", animation))
519 return ANIMATION_DIM_LAYER;
521 return ANIMATION_NONE;
525 shell_configuration(struct desktop_shell *shell)
527 struct weston_config_section *section;
531 section = weston_config_get_section(shell->compositor->config,
532 "screensaver", NULL, NULL);
533 weston_config_section_get_string(section,
534 "path", &shell->screensaver.path, NULL);
535 weston_config_section_get_int(section, "duration", &duration, 60);
536 shell->screensaver.duration = duration * 1000;
538 section = weston_config_get_section(shell->compositor->config,
539 "shell", NULL, NULL);
540 weston_config_section_get_string(section,
541 "client", &s, LIBEXECDIR "/weston-desktop-shell");
543 weston_config_section_get_string(section,
544 "binding-modifier", &s, "super");
545 shell->binding_modifier = get_modifier(s);
547 weston_config_section_get_string(section, "animation", &s, "none");
548 shell->win_animation_type = get_animation_type(s);
550 weston_config_section_get_string(section,
551 "startup-animation", &s, "fade");
552 shell->startup_animation_type = get_animation_type(s);
554 if (shell->startup_animation_type == ANIMATION_ZOOM)
555 shell->startup_animation_type = ANIMATION_NONE;
556 weston_config_section_get_string(section, "focus-animation", &s, "none");
557 shell->focus_animation_type = get_animation_type(s);
559 weston_config_section_get_uint(section, "num-workspaces",
560 &shell->workspaces.num,
561 DEFAULT_NUM_WORKSPACES);
564 static struct weston_output *
565 get_default_output(struct weston_compositor *compositor)
567 return container_of(compositor->output_list.next,
568 struct weston_output, link);
572 /* no-op func for checking focus surface */
574 focus_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy,
575 int32_t width, int32_t height)
579 static struct focus_surface *
580 get_focus_surface(struct weston_surface *surface)
582 if (surface->configure == focus_surface_configure)
583 return surface->configure_private;
589 is_focus_surface (struct weston_surface *es)
591 return (es->configure == focus_surface_configure);
595 is_focus_view (struct weston_view *view)
597 return is_focus_surface (view->surface);
600 static struct focus_surface *
601 create_focus_surface(struct weston_compositor *ec,
602 struct weston_output *output)
604 struct focus_surface *fsurf = NULL;
605 struct weston_surface *surface = NULL;
607 fsurf = malloc(sizeof *fsurf);
611 fsurf->surface = weston_surface_create(ec);
612 surface = fsurf->surface;
613 if (surface == NULL) {
618 surface->configure = focus_surface_configure;
619 surface->output = output;
620 surface->configure_private = fsurf;
622 fsurf->view = weston_view_create (surface);
623 fsurf->view->output = output;
625 weston_view_configure(fsurf->view, output->x, output->y,
626 output->width, output->height);
627 weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1.0);
628 pixman_region32_fini(&surface->opaque);
629 pixman_region32_init_rect(&surface->opaque, output->x, output->y,
630 output->width, output->height);
631 pixman_region32_fini(&surface->input);
632 pixman_region32_init(&surface->input);
634 wl_list_init(&fsurf->workspace_transform.link);
640 focus_surface_destroy(struct focus_surface *fsurf)
642 weston_surface_destroy(fsurf->surface);
647 focus_animation_done(struct weston_view_animation *animation, void *data)
649 struct workspace *ws = data;
651 ws->focus_animation = NULL;
655 focus_state_destroy(struct focus_state *state)
657 wl_list_remove(&state->seat_destroy_listener.link);
658 wl_list_remove(&state->surface_destroy_listener.link);
663 focus_state_seat_destroy(struct wl_listener *listener, void *data)
665 struct focus_state *state = container_of(listener,
667 seat_destroy_listener);
669 wl_list_remove(&state->link);
670 focus_state_destroy(state);
674 focus_state_surface_destroy(struct wl_listener *listener, void *data)
676 struct focus_state *state = container_of(listener,
678 surface_destroy_listener);
679 struct desktop_shell *shell;
680 struct weston_surface *main_surface, *next;
681 struct weston_view *view;
683 main_surface = weston_surface_get_main_surface(state->keyboard_focus);
686 wl_list_for_each(view, &state->ws->layer.view_list, layer_link) {
687 if (view->surface == main_surface)
689 if (is_focus_view(view))
692 next = view->surface;
696 /* if the focus was a sub-surface, activate its main surface */
697 if (main_surface != state->keyboard_focus)
700 shell = state->seat->compositor->shell_interface.shell;
702 state->keyboard_focus = NULL;
703 activate(shell, next, state->seat);
705 if (shell->focus_animation_type == ANIMATION_DIM_LAYER) {
706 if (state->ws->focus_animation)
707 weston_view_animation_destroy(state->ws->focus_animation);
709 state->ws->focus_animation = weston_fade_run(
710 state->ws->fsurf_front->view,
711 state->ws->fsurf_front->view->alpha, 0.0, 300,
712 focus_animation_done, state->ws);
715 wl_list_remove(&state->link);
716 focus_state_destroy(state);
720 static struct focus_state *
721 focus_state_create(struct weston_seat *seat, struct workspace *ws)
723 struct focus_state *state;
725 state = malloc(sizeof *state);
729 state->keyboard_focus = NULL;
732 wl_list_insert(&ws->focus_list, &state->link);
734 state->seat_destroy_listener.notify = focus_state_seat_destroy;
735 state->surface_destroy_listener.notify = focus_state_surface_destroy;
736 wl_signal_add(&seat->destroy_signal,
737 &state->seat_destroy_listener);
738 wl_list_init(&state->surface_destroy_listener.link);
743 static struct focus_state *
744 ensure_focus_state(struct desktop_shell *shell, struct weston_seat *seat)
746 struct workspace *ws = get_current_workspace(shell);
747 struct focus_state *state;
749 wl_list_for_each(state, &ws->focus_list, link)
750 if (state->seat == seat)
753 if (&state->link == &ws->focus_list)
754 state = focus_state_create(seat, ws);
760 restore_focus_state(struct desktop_shell *shell, struct workspace *ws)
762 struct focus_state *state, *next;
763 struct weston_surface *surface;
765 wl_list_for_each_safe(state, next, &ws->focus_list, link) {
766 surface = state->keyboard_focus;
768 weston_keyboard_set_focus(state->seat->keyboard, surface);
773 replace_focus_state(struct desktop_shell *shell, struct workspace *ws,
774 struct weston_seat *seat)
776 struct focus_state *state;
777 struct weston_surface *surface;
779 wl_list_for_each(state, &ws->focus_list, link) {
780 if (state->seat == seat) {
781 surface = seat->keyboard->focus;
782 state->keyboard_focus = surface;
789 drop_focus_state(struct desktop_shell *shell, struct workspace *ws,
790 struct weston_surface *surface)
792 struct focus_state *state;
794 wl_list_for_each(state, &ws->focus_list, link)
795 if (state->keyboard_focus == surface)
796 state->keyboard_focus = NULL;
800 animate_focus_change(struct desktop_shell *shell, struct workspace *ws,
801 struct weston_view *from, struct weston_view *to)
803 struct weston_output *output;
804 bool focus_surface_created = false;
806 /* FIXME: Only support dim animation using two layers */
807 if (from == to || shell->focus_animation_type != ANIMATION_DIM_LAYER)
810 output = get_default_output(shell->compositor);
811 if (ws->fsurf_front == NULL && (from || to)) {
812 ws->fsurf_front = create_focus_surface(shell->compositor, output);
813 ws->fsurf_back = create_focus_surface(shell->compositor, output);
814 ws->fsurf_front->view->alpha = 0.0;
815 ws->fsurf_back->view->alpha = 0.0;
816 focus_surface_created = true;
818 wl_list_remove(&ws->fsurf_front->view->layer_link);
819 wl_list_remove(&ws->fsurf_back->view->layer_link);
822 if (ws->focus_animation) {
823 weston_view_animation_destroy(ws->focus_animation);
824 ws->focus_animation = NULL;
828 wl_list_insert(&to->layer_link,
829 &ws->fsurf_front->view->layer_link);
831 wl_list_insert(&ws->layer.view_list,
832 &ws->fsurf_front->view->layer_link);
834 if (focus_surface_created) {
835 ws->focus_animation = weston_fade_run(
836 ws->fsurf_front->view,
837 ws->fsurf_front->view->alpha, 0.6, 300,
838 focus_animation_done, ws);
840 wl_list_insert(&from->layer_link,
841 &ws->fsurf_back->view->layer_link);
842 ws->focus_animation = weston_stable_fade_run(
843 ws->fsurf_front->view, 0.0,
844 ws->fsurf_back->view, 0.6,
845 focus_animation_done, ws);
847 wl_list_insert(&ws->layer.view_list,
848 &ws->fsurf_back->view->layer_link);
849 ws->focus_animation = weston_stable_fade_run(
850 ws->fsurf_front->view, 0.0,
851 ws->fsurf_back->view, 0.6,
852 focus_animation_done, ws);
857 workspace_destroy(struct workspace *ws)
859 struct focus_state *state, *next;
861 wl_list_for_each_safe(state, next, &ws->focus_list, link)
862 focus_state_destroy(state);
865 focus_surface_destroy(ws->fsurf_front);
867 focus_surface_destroy(ws->fsurf_back);
873 seat_destroyed(struct wl_listener *listener, void *data)
875 struct weston_seat *seat = data;
876 struct focus_state *state, *next;
877 struct workspace *ws = container_of(listener,
879 seat_destroyed_listener);
881 wl_list_for_each_safe(state, next, &ws->focus_list, link)
882 if (state->seat == seat)
883 wl_list_remove(&state->link);
886 static struct workspace *
887 workspace_create(void)
889 struct workspace *ws = malloc(sizeof *ws);
893 weston_layer_init(&ws->layer, NULL);
895 wl_list_init(&ws->focus_list);
896 wl_list_init(&ws->seat_destroyed_listener.link);
897 ws->seat_destroyed_listener.notify = seat_destroyed;
898 ws->fsurf_front = NULL;
899 ws->fsurf_back = NULL;
900 ws->focus_animation = NULL;
906 workspace_is_empty(struct workspace *ws)
908 return wl_list_empty(&ws->layer.view_list);
911 static struct workspace *
912 get_workspace(struct desktop_shell *shell, unsigned int index)
914 struct workspace **pws = shell->workspaces.array.data;
915 assert(index < shell->workspaces.num);
920 static struct workspace *
921 get_current_workspace(struct desktop_shell *shell)
923 return get_workspace(shell, shell->workspaces.current);
927 activate_workspace(struct desktop_shell *shell, unsigned int index)
929 struct workspace *ws;
931 ws = get_workspace(shell, index);
932 wl_list_insert(&shell->panel_layer.link, &ws->layer.link);
934 shell->workspaces.current = index;
938 get_output_height(struct weston_output *output)
940 return abs(output->region.extents.y1 - output->region.extents.y2);
944 view_translate(struct workspace *ws, struct weston_view *view, double d)
946 struct weston_transform *transform;
948 if (is_focus_view(view)) {
949 struct focus_surface *fsurf = get_focus_surface(view->surface);
950 transform = &fsurf->workspace_transform;
952 struct shell_surface *shsurf = get_shell_surface(view->surface);
953 transform = &shsurf->workspace_transform;
956 if (wl_list_empty(&transform->link))
957 wl_list_insert(view->geometry.transformation_list.prev,
960 weston_matrix_init(&transform->matrix);
961 weston_matrix_translate(&transform->matrix,
963 weston_view_geometry_dirty(view);
967 workspace_translate_out(struct workspace *ws, double fraction)
969 struct weston_view *view;
973 wl_list_for_each(view, &ws->layer.view_list, layer_link) {
974 height = get_output_height(view->surface->output);
975 d = height * fraction;
977 view_translate(ws, view, d);
982 workspace_translate_in(struct workspace *ws, double fraction)
984 struct weston_view *view;
988 wl_list_for_each(view, &ws->layer.view_list, layer_link) {
989 height = get_output_height(view->surface->output);
992 d = -(height - height * fraction);
994 d = height + height * fraction;
996 view_translate(ws, view, d);
1001 broadcast_current_workspace_state(struct desktop_shell *shell)
1003 struct wl_resource *resource;
1005 wl_resource_for_each(resource, &shell->workspaces.client_list)
1006 workspace_manager_send_state(resource,
1007 shell->workspaces.current,
1008 shell->workspaces.num);
1012 reverse_workspace_change_animation(struct desktop_shell *shell,
1014 struct workspace *from,
1015 struct workspace *to)
1017 shell->workspaces.current = index;
1019 shell->workspaces.anim_to = to;
1020 shell->workspaces.anim_from = from;
1021 shell->workspaces.anim_dir = -1 * shell->workspaces.anim_dir;
1022 shell->workspaces.anim_timestamp = 0;
1024 weston_compositor_schedule_repaint(shell->compositor);
1028 workspace_deactivate_transforms(struct workspace *ws)
1030 struct weston_view *view;
1031 struct weston_transform *transform;
1033 wl_list_for_each(view, &ws->layer.view_list, layer_link) {
1034 if (is_focus_view(view)) {
1035 struct focus_surface *fsurf = get_focus_surface(view->surface);
1036 transform = &fsurf->workspace_transform;
1038 struct shell_surface *shsurf = get_shell_surface(view->surface);
1039 transform = &shsurf->workspace_transform;
1042 if (!wl_list_empty(&transform->link)) {
1043 wl_list_remove(&transform->link);
1044 wl_list_init(&transform->link);
1046 weston_view_geometry_dirty(view);
1051 finish_workspace_change_animation(struct desktop_shell *shell,
1052 struct workspace *from,
1053 struct workspace *to)
1055 weston_compositor_schedule_repaint(shell->compositor);
1057 wl_list_remove(&shell->workspaces.animation.link);
1058 workspace_deactivate_transforms(from);
1059 workspace_deactivate_transforms(to);
1060 shell->workspaces.anim_to = NULL;
1062 wl_list_remove(&shell->workspaces.anim_from->layer.link);
1066 animate_workspace_change_frame(struct weston_animation *animation,
1067 struct weston_output *output, uint32_t msecs)
1069 struct desktop_shell *shell =
1070 container_of(animation, struct desktop_shell,
1071 workspaces.animation);
1072 struct workspace *from = shell->workspaces.anim_from;
1073 struct workspace *to = shell->workspaces.anim_to;
1077 if (workspace_is_empty(from) && workspace_is_empty(to)) {
1078 finish_workspace_change_animation(shell, from, to);
1082 if (shell->workspaces.anim_timestamp == 0) {
1083 if (shell->workspaces.anim_current == 0.0)
1084 shell->workspaces.anim_timestamp = msecs;
1086 shell->workspaces.anim_timestamp =
1088 /* Invers of movement function 'y' below. */
1089 (asin(1.0 - shell->workspaces.anim_current) *
1090 DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH *
1094 t = msecs - shell->workspaces.anim_timestamp;
1100 x = t * (1.0/DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH) * M_PI_2;
1103 if (t < DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH) {
1104 weston_compositor_schedule_repaint(shell->compositor);
1106 workspace_translate_out(from, shell->workspaces.anim_dir * y);
1107 workspace_translate_in(to, shell->workspaces.anim_dir * y);
1108 shell->workspaces.anim_current = y;
1110 weston_compositor_schedule_repaint(shell->compositor);
1113 finish_workspace_change_animation(shell, from, to);
1117 animate_workspace_change(struct desktop_shell *shell,
1119 struct workspace *from,
1120 struct workspace *to)
1122 struct weston_output *output;
1126 if (index > shell->workspaces.current)
1131 shell->workspaces.current = index;
1133 shell->workspaces.anim_dir = dir;
1134 shell->workspaces.anim_from = from;
1135 shell->workspaces.anim_to = to;
1136 shell->workspaces.anim_current = 0.0;
1137 shell->workspaces.anim_timestamp = 0;
1139 output = container_of(shell->compositor->output_list.next,
1140 struct weston_output, link);
1141 wl_list_insert(&output->animation_list,
1142 &shell->workspaces.animation.link);
1144 wl_list_insert(from->layer.link.prev, &to->layer.link);
1146 workspace_translate_in(to, 0);
1148 restore_focus_state(shell, to);
1150 weston_compositor_schedule_repaint(shell->compositor);
1154 update_workspace(struct desktop_shell *shell, unsigned int index,
1155 struct workspace *from, struct workspace *to)
1157 shell->workspaces.current = index;
1158 wl_list_insert(&from->layer.link, &to->layer.link);
1159 wl_list_remove(&from->layer.link);
1163 change_workspace(struct desktop_shell *shell, unsigned int index)
1165 struct workspace *from;
1166 struct workspace *to;
1167 struct focus_state *state;
1169 if (index == shell->workspaces.current)
1172 /* Don't change workspace when there is any fullscreen surfaces. */
1173 if (!wl_list_empty(&shell->fullscreen_layer.view_list))
1176 from = get_current_workspace(shell);
1177 to = get_workspace(shell, index);
1179 if (shell->workspaces.anim_from == to &&
1180 shell->workspaces.anim_to == from) {
1181 restore_focus_state(shell, to);
1182 reverse_workspace_change_animation(shell, index, from, to);
1183 broadcast_current_workspace_state(shell);
1187 if (shell->workspaces.anim_to != NULL)
1188 finish_workspace_change_animation(shell,
1189 shell->workspaces.anim_from,
1190 shell->workspaces.anim_to);
1192 restore_focus_state(shell, to);
1194 if (shell->focus_animation_type != ANIMATION_NONE) {
1195 wl_list_for_each(state, &from->focus_list, link)
1196 if (state->keyboard_focus)
1197 animate_focus_change(shell, from,
1198 get_default_view(state->keyboard_focus), NULL);
1200 wl_list_for_each(state, &to->focus_list, link)
1201 if (state->keyboard_focus)
1202 animate_focus_change(shell, to,
1203 NULL, get_default_view(state->keyboard_focus));
1206 if (workspace_is_empty(to) && workspace_is_empty(from))
1207 update_workspace(shell, index, from, to);
1209 animate_workspace_change(shell, index, from, to);
1211 broadcast_current_workspace_state(shell);
1215 workspace_has_only(struct workspace *ws, struct weston_surface *surface)
1217 struct wl_list *list = &ws->layer.view_list;
1220 if (wl_list_empty(list))
1225 if (e->next != list)
1228 return container_of(e, struct weston_view, layer_link)->surface == surface;
1232 move_view_to_workspace(struct desktop_shell *shell,
1233 struct weston_view *view,
1236 struct workspace *from;
1237 struct workspace *to;
1238 struct weston_seat *seat;
1239 struct weston_surface *focus;
1241 assert(weston_surface_get_main_surface(view->surface) == view->surface);
1243 if (workspace == shell->workspaces.current)
1246 if (workspace >= shell->workspaces.num)
1247 workspace = shell->workspaces.num - 1;
1249 from = get_current_workspace(shell);
1250 to = get_workspace(shell, workspace);
1252 wl_list_remove(&view->layer_link);
1253 wl_list_insert(&to->layer.view_list, &view->layer_link);
1255 drop_focus_state(shell, from, view->surface);
1256 wl_list_for_each(seat, &shell->compositor->seat_list, link) {
1257 if (!seat->keyboard)
1260 focus = weston_surface_get_main_surface(seat->keyboard->focus);
1261 if (focus == view->surface)
1262 weston_keyboard_set_focus(seat->keyboard, NULL);
1265 weston_view_damage_below(view);
1269 take_surface_to_workspace_by_seat(struct desktop_shell *shell,
1270 struct weston_seat *seat,
1273 struct weston_surface *surface;
1274 struct weston_view *view;
1275 struct shell_surface *shsurf;
1276 struct workspace *from;
1277 struct workspace *to;
1278 struct focus_state *state;
1280 surface = weston_surface_get_main_surface(seat->keyboard->focus);
1281 view = get_default_view(surface);
1283 index == shell->workspaces.current ||
1284 is_focus_view(view))
1287 from = get_current_workspace(shell);
1288 to = get_workspace(shell, index);
1290 wl_list_remove(&view->layer_link);
1291 wl_list_insert(&to->layer.view_list, &view->layer_link);
1293 replace_focus_state(shell, to, seat);
1294 drop_focus_state(shell, from, surface);
1296 if (shell->workspaces.anim_from == to &&
1297 shell->workspaces.anim_to == from) {
1298 wl_list_remove(&to->layer.link);
1299 wl_list_insert(from->layer.link.prev, &to->layer.link);
1301 reverse_workspace_change_animation(shell, index, from, to);
1302 broadcast_current_workspace_state(shell);
1307 if (shell->workspaces.anim_to != NULL)
1308 finish_workspace_change_animation(shell,
1309 shell->workspaces.anim_from,
1310 shell->workspaces.anim_to);
1312 if (workspace_is_empty(from) &&
1313 workspace_has_only(to, surface))
1314 update_workspace(shell, index, from, to);
1316 shsurf = get_shell_surface(surface);
1317 if (wl_list_empty(&shsurf->workspace_transform.link))
1318 wl_list_insert(&shell->workspaces.anim_sticky_list,
1319 &shsurf->workspace_transform.link);
1321 animate_workspace_change(shell, index, from, to);
1324 broadcast_current_workspace_state(shell);
1326 state = ensure_focus_state(shell, seat);
1328 state->keyboard_focus = surface;
1332 workspace_manager_move_surface(struct wl_client *client,
1333 struct wl_resource *resource,
1334 struct wl_resource *surface_resource,
1337 struct desktop_shell *shell = wl_resource_get_user_data(resource);
1338 struct weston_surface *surface =
1339 wl_resource_get_user_data(surface_resource);
1340 struct weston_surface *main_surface;
1341 struct weston_view *view;
1343 main_surface = weston_surface_get_main_surface(surface);
1344 view = get_default_view(main_surface);
1347 move_view_to_workspace(shell, view, workspace);
1350 static const struct workspace_manager_interface workspace_manager_implementation = {
1351 workspace_manager_move_surface,
1355 unbind_resource(struct wl_resource *resource)
1357 wl_list_remove(wl_resource_get_link(resource));
1361 bind_workspace_manager(struct wl_client *client,
1362 void *data, uint32_t version, uint32_t id)
1364 struct desktop_shell *shell = data;
1365 struct wl_resource *resource;
1367 resource = wl_resource_create(client,
1368 &workspace_manager_interface, 1, id);
1370 if (resource == NULL) {
1371 weston_log("couldn't add workspace manager object");
1375 wl_resource_set_implementation(resource,
1376 &workspace_manager_implementation,
1377 shell, unbind_resource);
1378 wl_list_insert(&shell->workspaces.client_list,
1379 wl_resource_get_link(resource));
1381 workspace_manager_send_state(resource,
1382 shell->workspaces.current,
1383 shell->workspaces.num);
1387 touch_move_grab_down(struct weston_touch_grab *grab, uint32_t time,
1388 int touch_id, wl_fixed_t sx, wl_fixed_t sy)
1393 touch_move_grab_up(struct weston_touch_grab *grab, uint32_t time, int touch_id)
1395 struct weston_touch_move_grab *move =
1396 (struct weston_touch_move_grab *) container_of(
1397 grab, struct shell_touch_grab, grab);
1399 if (grab->touch->seat->num_tp == 0) {
1400 shell_touch_grab_end(&move->base);
1406 touch_move_grab_motion(struct weston_touch_grab *grab, uint32_t time,
1407 int touch_id, wl_fixed_t sx, wl_fixed_t sy)
1409 struct weston_touch_move_grab *move = (struct weston_touch_move_grab *) grab;
1410 struct shell_surface *shsurf = move->base.shsurf;
1411 struct weston_surface *es;
1412 int dx = wl_fixed_to_int(grab->touch->grab_x + move->dx);
1413 int dy = wl_fixed_to_int(grab->touch->grab_y + move->dy);
1418 es = shsurf->surface;
1420 weston_view_configure(shsurf->view, dx, dy,
1421 shsurf->view->geometry.width,
1422 shsurf->view->geometry.height);
1424 weston_compositor_schedule_repaint(es->compositor);
1428 touch_move_grab_cancel(struct weston_touch_grab *grab)
1430 struct weston_touch_move_grab *move =
1431 (struct weston_touch_move_grab *) container_of(
1432 grab, struct shell_touch_grab, grab);
1434 shell_touch_grab_end(&move->base);
1438 static const struct weston_touch_grab_interface touch_move_grab_interface = {
1439 touch_move_grab_down,
1441 touch_move_grab_motion,
1442 touch_move_grab_cancel,
1446 surface_touch_move(struct shell_surface *shsurf, struct weston_seat *seat)
1448 struct weston_touch_move_grab *move;
1453 if (shsurf->type == SHELL_SURFACE_FULLSCREEN)
1455 if (shsurf->grabbed)
1458 move = malloc(sizeof *move);
1462 move->dx = wl_fixed_from_double(shsurf->view->geometry.x) -
1463 seat->touch->grab_x;
1464 move->dy = wl_fixed_from_double(shsurf->view->geometry.y) -
1465 seat->touch->grab_y;
1467 shell_touch_grab_start(&move->base, &touch_move_grab_interface, shsurf,
1474 noop_grab_focus(struct weston_pointer_grab *grab)
1479 move_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
1480 wl_fixed_t x, wl_fixed_t y)
1482 struct weston_move_grab *move = (struct weston_move_grab *) grab;
1483 struct weston_pointer *pointer = grab->pointer;
1484 struct shell_surface *shsurf = move->base.shsurf;
1487 weston_pointer_move(pointer, x, y);
1488 dx = wl_fixed_to_int(pointer->x + move->dx);
1489 dy = wl_fixed_to_int(pointer->y + move->dy);
1494 weston_view_configure(shsurf->view, dx, dy,
1495 shsurf->view->geometry.width,
1496 shsurf->view->geometry.height);
1498 weston_compositor_schedule_repaint(shsurf->surface->compositor);
1502 move_grab_button(struct weston_pointer_grab *grab,
1503 uint32_t time, uint32_t button, uint32_t state_w)
1505 struct shell_grab *shell_grab = container_of(grab, struct shell_grab,
1507 struct weston_pointer *pointer = grab->pointer;
1508 enum wl_pointer_button_state state = state_w;
1510 if (pointer->button_count == 0 &&
1511 state == WL_POINTER_BUTTON_STATE_RELEASED) {
1512 shell_grab_end(shell_grab);
1518 move_grab_cancel(struct weston_pointer_grab *grab)
1520 struct shell_grab *shell_grab =
1521 container_of(grab, struct shell_grab, grab);
1523 shell_grab_end(shell_grab);
1527 static const struct weston_pointer_grab_interface move_grab_interface = {
1535 surface_move(struct shell_surface *shsurf, struct weston_seat *seat)
1537 struct weston_move_grab *move;
1542 if (shsurf->grabbed)
1544 if (shsurf->type == SHELL_SURFACE_FULLSCREEN)
1547 move = malloc(sizeof *move);
1551 move->dx = wl_fixed_from_double(shsurf->view->geometry.x) -
1552 seat->pointer->grab_x;
1553 move->dy = wl_fixed_from_double(shsurf->view->geometry.y) -
1554 seat->pointer->grab_y;
1556 shell_grab_start(&move->base, &move_grab_interface, shsurf,
1557 seat->pointer, DESKTOP_SHELL_CURSOR_MOVE);
1563 shell_surface_move(struct wl_client *client, struct wl_resource *resource,
1564 struct wl_resource *seat_resource, uint32_t serial)
1566 struct weston_seat *seat = wl_resource_get_user_data(seat_resource);
1567 struct shell_surface *shsurf = wl_resource_get_user_data(resource);
1568 struct weston_surface *surface;
1570 if (seat->pointer &&
1571 seat->pointer->button_count > 0 &&
1572 seat->pointer->grab_serial == serial) {
1573 surface = weston_surface_get_main_surface(seat->pointer->focus->surface);
1574 if ((surface == shsurf->surface) &&
1575 (surface_move(shsurf, seat) < 0))
1576 wl_resource_post_no_memory(resource);
1577 } else if (seat->touch &&
1578 seat->touch->grab_serial == serial) {
1579 surface = weston_surface_get_main_surface(seat->touch->focus->surface);
1580 if ((surface == shsurf->surface) &&
1581 (surface_touch_move(shsurf, seat) < 0))
1582 wl_resource_post_no_memory(resource);
1586 struct weston_resize_grab {
1587 struct shell_grab base;
1589 int32_t width, height;
1593 resize_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
1594 wl_fixed_t x, wl_fixed_t y)
1596 struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
1597 struct weston_pointer *pointer = grab->pointer;
1598 struct shell_surface *shsurf = resize->base.shsurf;
1599 int32_t width, height;
1600 wl_fixed_t from_x, from_y;
1601 wl_fixed_t to_x, to_y;
1603 weston_pointer_move(pointer, x, y);
1608 weston_view_from_global_fixed(shsurf->view,
1609 pointer->grab_x, pointer->grab_y,
1611 weston_view_from_global_fixed(shsurf->view,
1612 pointer->x, pointer->y, &to_x, &to_y);
1614 width = resize->width;
1615 if (resize->edges & WL_SHELL_SURFACE_RESIZE_LEFT) {
1616 width += wl_fixed_to_int(from_x - to_x);
1617 } else if (resize->edges & WL_SHELL_SURFACE_RESIZE_RIGHT) {
1618 width += wl_fixed_to_int(to_x - from_x);
1621 height = resize->height;
1622 if (resize->edges & WL_SHELL_SURFACE_RESIZE_TOP) {
1623 height += wl_fixed_to_int(from_y - to_y);
1624 } else if (resize->edges & WL_SHELL_SURFACE_RESIZE_BOTTOM) {
1625 height += wl_fixed_to_int(to_y - from_y);
1628 shsurf->client->send_configure(shsurf->surface,
1629 resize->edges, width, height);
1633 send_configure(struct weston_surface *surface,
1634 uint32_t edges, int32_t width, int32_t height)
1636 struct shell_surface *shsurf = get_shell_surface(surface);
1638 wl_shell_surface_send_configure(shsurf->resource,
1639 edges, width, height);
1642 static const struct weston_shell_client shell_client = {
1647 resize_grab_button(struct weston_pointer_grab *grab,
1648 uint32_t time, uint32_t button, uint32_t state_w)
1650 struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
1651 struct weston_pointer *pointer = grab->pointer;
1652 enum wl_pointer_button_state state = state_w;
1654 if (pointer->button_count == 0 &&
1655 state == WL_POINTER_BUTTON_STATE_RELEASED) {
1656 shell_grab_end(&resize->base);
1662 resize_grab_cancel(struct weston_pointer_grab *grab)
1664 struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
1666 shell_grab_end(&resize->base);
1670 static const struct weston_pointer_grab_interface resize_grab_interface = {
1678 * Returns the bounding box of a surface and all its sub-surfaces,
1679 * in the surface coordinates system. */
1681 surface_subsurfaces_boundingbox(struct weston_surface *surface, int32_t *x,
1682 int32_t *y, int32_t *w, int32_t *h) {
1683 pixman_region32_t region;
1684 pixman_box32_t *box;
1685 struct weston_subsurface *subsurface;
1687 pixman_region32_init_rect(®ion, 0, 0,
1691 wl_list_for_each(subsurface, &surface->subsurface_list, parent_link) {
1692 pixman_region32_union_rect(®ion, ®ion,
1693 subsurface->position.x,
1694 subsurface->position.y,
1695 subsurface->surface->width,
1696 subsurface->surface->height);
1699 box = pixman_region32_extents(®ion);
1705 *w = box->x2 - box->x1;
1707 *h = box->y2 - box->y1;
1709 pixman_region32_fini(®ion);
1713 surface_resize(struct shell_surface *shsurf,
1714 struct weston_seat *seat, uint32_t edges)
1716 struct weston_resize_grab *resize;
1718 if (shsurf->type == SHELL_SURFACE_FULLSCREEN ||
1719 shsurf->type == SHELL_SURFACE_MAXIMIZED)
1722 if (edges == 0 || edges > 15 ||
1723 (edges & 3) == 3 || (edges & 12) == 12)
1726 resize = malloc(sizeof *resize);
1730 resize->edges = edges;
1731 surface_subsurfaces_boundingbox(shsurf->surface, NULL, NULL,
1732 &resize->width, &resize->height);
1734 shell_grab_start(&resize->base, &resize_grab_interface, shsurf,
1735 seat->pointer, edges);
1741 shell_surface_resize(struct wl_client *client, struct wl_resource *resource,
1742 struct wl_resource *seat_resource, uint32_t serial,
1745 struct weston_seat *seat = wl_resource_get_user_data(seat_resource);
1746 struct shell_surface *shsurf = wl_resource_get_user_data(resource);
1747 struct weston_surface *surface;
1749 if (shsurf->type == SHELL_SURFACE_FULLSCREEN)
1752 surface = weston_surface_get_main_surface(seat->pointer->focus->surface);
1753 if (seat->pointer->button_count == 0 ||
1754 seat->pointer->grab_serial != serial ||
1755 surface != shsurf->surface)
1758 if (surface_resize(shsurf, seat, edges) < 0)
1759 wl_resource_post_no_memory(resource);
1763 end_busy_cursor(struct shell_surface *shsurf, struct weston_pointer *pointer);
1766 busy_cursor_grab_focus(struct weston_pointer_grab *base)
1768 struct shell_grab *grab = (struct shell_grab *) base;
1769 struct weston_pointer *pointer = base->pointer;
1770 struct weston_view *view;
1773 view = weston_compositor_pick_view(pointer->seat->compositor,
1774 pointer->x, pointer->y,
1777 if (!grab->shsurf || grab->shsurf->surface != view->surface)
1778 end_busy_cursor(grab->shsurf, pointer);
1782 busy_cursor_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
1783 wl_fixed_t x, wl_fixed_t y)
1785 weston_pointer_move(grab->pointer, x, y);
1789 busy_cursor_grab_button(struct weston_pointer_grab *base,
1790 uint32_t time, uint32_t button, uint32_t state)
1792 struct shell_grab *grab = (struct shell_grab *) base;
1793 struct shell_surface *shsurf = grab->shsurf;
1794 struct weston_seat *seat = grab->grab.pointer->seat;
1796 if (shsurf && button == BTN_LEFT && state) {
1797 activate(shsurf->shell, shsurf->surface, seat);
1798 surface_move(shsurf, seat);
1799 } else if (shsurf && button == BTN_RIGHT && state) {
1800 activate(shsurf->shell, shsurf->surface, seat);
1801 surface_rotate(shsurf, seat);
1806 busy_cursor_grab_cancel(struct weston_pointer_grab *base)
1808 struct shell_grab *grab = (struct shell_grab *) base;
1810 shell_grab_end(grab);
1814 static const struct weston_pointer_grab_interface busy_cursor_grab_interface = {
1815 busy_cursor_grab_focus,
1816 busy_cursor_grab_motion,
1817 busy_cursor_grab_button,
1818 busy_cursor_grab_cancel,
1822 set_busy_cursor(struct shell_surface *shsurf, struct weston_pointer *pointer)
1824 struct shell_grab *grab;
1826 grab = malloc(sizeof *grab);
1830 shell_grab_start(grab, &busy_cursor_grab_interface, shsurf, pointer,
1831 DESKTOP_SHELL_CURSOR_BUSY);
1835 end_busy_cursor(struct shell_surface *shsurf, struct weston_pointer *pointer)
1837 struct shell_grab *grab = (struct shell_grab *) pointer->grab;
1839 if (grab->grab.interface == &busy_cursor_grab_interface &&
1840 grab->shsurf == shsurf) {
1841 shell_grab_end(grab);
1847 ping_timer_destroy(struct shell_surface *shsurf)
1849 if (!shsurf || !shsurf->ping_timer)
1852 if (shsurf->ping_timer->source)
1853 wl_event_source_remove(shsurf->ping_timer->source);
1855 free(shsurf->ping_timer);
1856 shsurf->ping_timer = NULL;
1860 ping_timeout_handler(void *data)
1862 struct shell_surface *shsurf = data;
1863 struct weston_seat *seat;
1865 /* Client is not responding */
1866 shsurf->unresponsive = 1;
1868 wl_list_for_each(seat, &shsurf->surface->compositor->seat_list, link)
1869 if (seat->pointer->focus &&
1870 seat->pointer->focus->surface == shsurf->surface)
1871 set_busy_cursor(shsurf, seat->pointer);
1877 ping_handler(struct weston_surface *surface, uint32_t serial)
1879 struct shell_surface *shsurf = get_shell_surface(surface);
1880 struct wl_event_loop *loop;
1881 int ping_timeout = 200;
1885 if (!shsurf->resource)
1888 if (shsurf->surface == shsurf->shell->grab_surface)
1891 if (!shsurf->ping_timer) {
1892 shsurf->ping_timer = malloc(sizeof *shsurf->ping_timer);
1893 if (!shsurf->ping_timer)
1896 shsurf->ping_timer->serial = serial;
1897 loop = wl_display_get_event_loop(surface->compositor->wl_display);
1898 shsurf->ping_timer->source =
1899 wl_event_loop_add_timer(loop, ping_timeout_handler, shsurf);
1900 wl_event_source_timer_update(shsurf->ping_timer->source, ping_timeout);
1902 wl_shell_surface_send_ping(shsurf->resource, serial);
1907 handle_pointer_focus(struct wl_listener *listener, void *data)
1909 struct weston_pointer *pointer = data;
1910 struct weston_view *view = pointer->focus;
1911 struct weston_compositor *compositor;
1912 struct shell_surface *shsurf;
1918 compositor = view->surface->compositor;
1919 shsurf = get_shell_surface(view->surface);
1921 if (shsurf && shsurf->unresponsive) {
1922 set_busy_cursor(shsurf, pointer);
1924 serial = wl_display_next_serial(compositor->wl_display);
1925 ping_handler(view->surface, serial);
1930 create_pointer_focus_listener(struct weston_seat *seat)
1932 struct wl_listener *listener;
1937 listener = malloc(sizeof *listener);
1938 listener->notify = handle_pointer_focus;
1939 wl_signal_add(&seat->pointer->focus_signal, listener);
1943 shell_surface_pong(struct wl_client *client, struct wl_resource *resource,
1946 struct shell_surface *shsurf = wl_resource_get_user_data(resource);
1947 struct weston_seat *seat;
1948 struct weston_compositor *ec = shsurf->surface->compositor;
1950 if (shsurf->ping_timer == NULL)
1951 /* Just ignore unsolicited pong. */
1954 if (shsurf->ping_timer->serial == serial) {
1955 shsurf->unresponsive = 0;
1956 wl_list_for_each(seat, &ec->seat_list, link) {
1958 end_busy_cursor(shsurf, seat->pointer);
1960 ping_timer_destroy(shsurf);
1965 set_title(struct shell_surface *shsurf, const char *title)
1967 free(shsurf->title);
1968 shsurf->title = strdup(title);
1972 shell_surface_set_title(struct wl_client *client,
1973 struct wl_resource *resource, const char *title)
1975 struct shell_surface *shsurf = wl_resource_get_user_data(resource);
1977 set_title(shsurf, title);
1981 shell_surface_set_class(struct wl_client *client,
1982 struct wl_resource *resource, const char *class)
1984 struct shell_surface *shsurf = wl_resource_get_user_data(resource);
1986 free(shsurf->class);
1987 shsurf->class = strdup(class);
1991 restore_output_mode(struct weston_output *output)
1993 if (output->current_mode != output->original_mode ||
1994 (int32_t)output->current_scale != output->original_scale)
1995 weston_output_switch_mode(output,
1996 output->original_mode,
1997 output->original_scale,
1998 WESTON_MODE_SWITCH_RESTORE_NATIVE);
2002 restore_all_output_modes(struct weston_compositor *compositor)
2004 struct weston_output *output;
2006 wl_list_for_each(output, &compositor->output_list, link)
2007 restore_output_mode(output);
2011 shell_unset_fullscreen(struct shell_surface *shsurf)
2013 struct workspace *ws;
2014 /* undo all fullscreen things here */
2015 if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
2016 shell_surface_is_top_fullscreen(shsurf)) {
2017 restore_output_mode(shsurf->fullscreen_output);
2019 shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
2020 shsurf->fullscreen.framerate = 0;
2021 wl_list_remove(&shsurf->fullscreen.transform.link);
2022 wl_list_init(&shsurf->fullscreen.transform.link);
2023 if (shsurf->fullscreen.black_view)
2024 weston_surface_destroy(shsurf->fullscreen.black_view->surface);
2025 shsurf->fullscreen.black_view = NULL;
2026 shsurf->fullscreen_output = NULL;
2027 weston_view_set_position(shsurf->view,
2028 shsurf->saved_x, shsurf->saved_y);
2029 if (shsurf->saved_rotation_valid) {
2030 wl_list_insert(&shsurf->view->geometry.transformation_list,
2031 &shsurf->rotation.transform.link);
2032 shsurf->saved_rotation_valid = false;
2035 ws = get_current_workspace(shsurf->shell);
2036 wl_list_remove(&shsurf->view->layer_link);
2037 wl_list_insert(&ws->layer.view_list, &shsurf->view->layer_link);
2041 shell_unset_maximized(struct shell_surface *shsurf)
2043 struct workspace *ws;
2044 /* undo all maximized things here */
2045 shsurf->output = get_default_output(shsurf->surface->compositor);
2046 weston_view_set_position(shsurf->view,
2050 if (shsurf->saved_rotation_valid) {
2051 wl_list_insert(&shsurf->view->geometry.transformation_list,
2052 &shsurf->rotation.transform.link);
2053 shsurf->saved_rotation_valid = false;
2056 ws = get_current_workspace(shsurf->shell);
2057 wl_list_remove(&shsurf->view->layer_link);
2058 wl_list_insert(&ws->layer.view_list, &shsurf->view->layer_link);
2062 reset_shell_surface_type(struct shell_surface *surface)
2064 switch (surface->type) {
2065 case SHELL_SURFACE_FULLSCREEN:
2066 shell_unset_fullscreen(surface);
2068 case SHELL_SURFACE_MAXIMIZED:
2069 shell_unset_maximized(surface);
2071 case SHELL_SURFACE_NONE:
2072 case SHELL_SURFACE_TOPLEVEL:
2073 case SHELL_SURFACE_TRANSIENT:
2074 case SHELL_SURFACE_POPUP:
2075 case SHELL_SURFACE_XWAYLAND:
2079 surface->type = SHELL_SURFACE_NONE;
2084 set_surface_type(struct shell_surface *shsurf)
2086 struct weston_surface *pes = shsurf->parent;
2087 struct weston_view *pev = get_default_view(pes);
2089 reset_shell_surface_type(shsurf);
2091 shsurf->type = shsurf->next_type;
2092 shsurf->next_type = SHELL_SURFACE_NONE;
2094 switch (shsurf->type) {
2095 case SHELL_SURFACE_TOPLEVEL:
2097 case SHELL_SURFACE_TRANSIENT:
2099 weston_view_set_position(shsurf->view,
2100 pev->geometry.x + shsurf->transient.x,
2101 pev->geometry.y + shsurf->transient.y);
2104 case SHELL_SURFACE_MAXIMIZED:
2105 case SHELL_SURFACE_FULLSCREEN:
2106 shsurf->saved_x = shsurf->view->geometry.x;
2107 shsurf->saved_y = shsurf->view->geometry.y;
2108 shsurf->saved_position_valid = true;
2110 if (!wl_list_empty(&shsurf->rotation.transform.link)) {
2111 wl_list_remove(&shsurf->rotation.transform.link);
2112 wl_list_init(&shsurf->rotation.transform.link);
2113 weston_view_geometry_dirty(shsurf->view);
2114 shsurf->saved_rotation_valid = true;
2118 case SHELL_SURFACE_XWAYLAND:
2119 weston_view_set_position(shsurf->view, shsurf->transient.x,
2120 shsurf->transient.y);
2129 set_toplevel(struct shell_surface *shsurf)
2131 shsurf->next_type = SHELL_SURFACE_TOPLEVEL;
2135 shell_surface_set_toplevel(struct wl_client *client,
2136 struct wl_resource *resource)
2138 struct shell_surface *surface = wl_resource_get_user_data(resource);
2140 set_toplevel(surface);
2144 set_transient(struct shell_surface *shsurf,
2145 struct weston_surface *parent, int x, int y, uint32_t flags)
2147 /* assign to parents output */
2148 shsurf->parent = parent;
2149 shsurf->transient.x = x;
2150 shsurf->transient.y = y;
2151 shsurf->transient.flags = flags;
2152 shsurf->next_type = SHELL_SURFACE_TRANSIENT;
2156 shell_surface_set_transient(struct wl_client *client,
2157 struct wl_resource *resource,
2158 struct wl_resource *parent_resource,
2159 int x, int y, uint32_t flags)
2161 struct shell_surface *shsurf = wl_resource_get_user_data(resource);
2162 struct weston_surface *parent =
2163 wl_resource_get_user_data(parent_resource);
2165 set_transient(shsurf, parent, x, y, flags);
2168 static struct desktop_shell *
2169 shell_surface_get_shell(struct shell_surface *shsurf)
2171 return shsurf->shell;
2175 get_output_panel_height(struct desktop_shell *shell,
2176 struct weston_output *output)
2178 struct weston_view *view;
2179 int panel_height = 0;
2184 wl_list_for_each(view, &shell->panel_layer.view_list, layer_link) {
2185 if (view->surface->output == output) {
2186 panel_height = view->geometry.height;
2191 return panel_height;
2195 shell_surface_set_maximized(struct wl_client *client,
2196 struct wl_resource *resource,
2197 struct wl_resource *output_resource )
2199 struct shell_surface *shsurf = wl_resource_get_user_data(resource);
2200 struct weston_surface *es = shsurf->surface;
2201 struct desktop_shell *shell = NULL;
2202 uint32_t edges = 0, panel_height = 0;
2204 /* get the default output, if the client set it as NULL
2205 check whether the ouput is available */
2206 if (output_resource)
2207 shsurf->output = wl_resource_get_user_data(output_resource);
2208 else if (es->output)
2209 shsurf->output = es->output;
2211 shsurf->output = get_default_output(es->compositor);
2213 shell = shell_surface_get_shell(shsurf);
2214 panel_height = get_output_panel_height(shell, shsurf->output);
2215 edges = WL_SHELL_SURFACE_RESIZE_TOP|WL_SHELL_SURFACE_RESIZE_LEFT;
2217 shsurf->client->send_configure(shsurf->surface, edges,
2218 shsurf->output->width,
2219 shsurf->output->height - panel_height);
2221 shsurf->next_type = SHELL_SURFACE_MAXIMIZED;
2225 black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height);
2227 static struct weston_view *
2228 create_black_surface(struct weston_compositor *ec,
2229 struct weston_surface *fs_surface,
2230 float x, float y, int w, int h)
2232 struct weston_surface *surface = NULL;
2233 struct weston_view *view;
2235 surface = weston_surface_create(ec);
2236 if (surface == NULL) {
2237 weston_log("no memory\n");
2240 view = weston_view_create(surface);
2241 if (surface == NULL) {
2242 weston_log("no memory\n");
2243 weston_surface_destroy(surface);
2247 surface->configure = black_surface_configure;
2248 surface->configure_private = fs_surface;
2249 weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1);
2250 pixman_region32_fini(&surface->opaque);
2251 pixman_region32_init_rect(&surface->opaque, 0, 0, w, h);
2252 pixman_region32_fini(&surface->input);
2253 pixman_region32_init_rect(&surface->input, 0, 0, w, h);
2255 weston_view_configure(view, x, y, w, h);
2260 /* Create black surface and append it to the associated fullscreen surface.
2261 * Handle size dismatch and positioning according to the method. */
2263 shell_configure_fullscreen(struct shell_surface *shsurf)
2265 struct weston_output *output = shsurf->fullscreen_output;
2266 struct weston_surface *surface = shsurf->surface;
2267 struct weston_matrix *matrix;
2268 float scale, output_aspect, surface_aspect, x, y;
2269 int32_t surf_x, surf_y, surf_width, surf_height;
2271 if (shsurf->fullscreen.type != WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER)
2272 restore_output_mode(output);
2274 if (!shsurf->fullscreen.black_view)
2275 shsurf->fullscreen.black_view =
2276 create_black_surface(surface->compositor,
2278 output->x, output->y,
2282 wl_list_remove(&shsurf->fullscreen.black_view->layer_link);
2283 wl_list_insert(&shsurf->view->layer_link,
2284 &shsurf->fullscreen.black_view->layer_link);
2285 shsurf->fullscreen.black_view->surface->output = output;
2286 shsurf->fullscreen.black_view->output = output;
2288 surface_subsurfaces_boundingbox(shsurf->surface, &surf_x, &surf_y,
2289 &surf_width, &surf_height);
2291 switch (shsurf->fullscreen.type) {
2292 case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT:
2293 if (surface->buffer_ref.buffer)
2294 center_on_output(shsurf->view, shsurf->fullscreen_output);
2296 case WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE:
2297 /* 1:1 mapping between surface and output dimensions */
2298 if (output->width == surf_width &&
2299 output->height == surf_height) {
2300 weston_view_set_position(shsurf->view,
2302 output->y - surf_y);
2306 matrix = &shsurf->fullscreen.transform.matrix;
2307 weston_matrix_init(matrix);
2309 output_aspect = (float) output->width /
2310 (float) output->height;
2311 /* XXX: Use surf_width and surf_height here? */
2312 surface_aspect = (float) surface->width /
2313 (float) surface->height;
2314 if (output_aspect < surface_aspect)
2315 scale = (float) output->width /
2318 scale = (float) output->height /
2319 (float) surf_height;
2321 weston_matrix_scale(matrix, scale, scale, 1);
2322 wl_list_remove(&shsurf->fullscreen.transform.link);
2323 wl_list_insert(&shsurf->view->geometry.transformation_list,
2324 &shsurf->fullscreen.transform.link);
2325 x = output->x + (output->width - surf_width * scale) / 2 - surf_x;
2326 y = output->y + (output->height - surf_height * scale) / 2 - surf_y;
2327 weston_view_set_position(shsurf->view, x, y);
2330 case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER:
2331 if (shell_surface_is_top_fullscreen(shsurf)) {
2332 struct weston_mode mode = {0,
2333 surf_width * surface->buffer_scale,
2334 surf_height * surface->buffer_scale,
2335 shsurf->fullscreen.framerate};
2337 if (weston_output_switch_mode(output, &mode, surface->buffer_scale,
2338 WESTON_MODE_SWITCH_SET_TEMPORARY) == 0) {
2339 weston_view_set_position(shsurf->view,
2341 output->y - surf_y);
2342 weston_view_configure(shsurf->fullscreen.black_view,
2349 restore_output_mode(output);
2350 center_on_output(shsurf->view, output);
2354 case WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL:
2355 center_on_output(shsurf->view, output);
2362 /* make the fullscreen and black surface at the top */
2364 shell_stack_fullscreen(struct shell_surface *shsurf)
2366 struct weston_output *output = shsurf->fullscreen_output;
2367 struct desktop_shell *shell = shell_surface_get_shell(shsurf);
2369 wl_list_remove(&shsurf->view->layer_link);
2370 wl_list_insert(&shell->fullscreen_layer.view_list,
2371 &shsurf->view->layer_link);
2372 weston_surface_damage(shsurf->surface);
2374 if (!shsurf->fullscreen.black_view)
2375 shsurf->fullscreen.black_view =
2376 create_black_surface(shsurf->surface->compositor,
2378 output->x, output->y,
2382 wl_list_remove(&shsurf->fullscreen.black_view->layer_link);
2383 wl_list_insert(&shsurf->view->layer_link,
2384 &shsurf->fullscreen.black_view->layer_link);
2385 weston_surface_damage(shsurf->fullscreen.black_view->surface);
2389 shell_map_fullscreen(struct shell_surface *shsurf)
2391 shell_stack_fullscreen(shsurf);
2392 shell_configure_fullscreen(shsurf);
2396 set_fullscreen(struct shell_surface *shsurf,
2399 struct weston_output *output)
2401 struct weston_surface *es = shsurf->surface;
2404 shsurf->output = output;
2405 else if (es->output)
2406 shsurf->output = es->output;
2408 shsurf->output = get_default_output(es->compositor);
2410 shsurf->fullscreen_output = shsurf->output;
2411 shsurf->fullscreen.type = method;
2412 shsurf->fullscreen.framerate = framerate;
2413 shsurf->next_type = SHELL_SURFACE_FULLSCREEN;
2415 shsurf->client->send_configure(shsurf->surface, 0,
2416 shsurf->output->width,
2417 shsurf->output->height);
2421 shell_surface_set_fullscreen(struct wl_client *client,
2422 struct wl_resource *resource,
2425 struct wl_resource *output_resource)
2427 struct shell_surface *shsurf = wl_resource_get_user_data(resource);
2428 struct weston_output *output;
2430 if (output_resource)
2431 output = wl_resource_get_user_data(output_resource);
2435 set_fullscreen(shsurf, method, framerate, output);
2439 set_xwayland(struct shell_surface *shsurf, int x, int y, uint32_t flags)
2441 /* XXX: using the same fields for transient type */
2442 shsurf->transient.x = x;
2443 shsurf->transient.y = y;
2444 shsurf->transient.flags = flags;
2445 shsurf->next_type = SHELL_SURFACE_XWAYLAND;
2448 static const struct weston_pointer_grab_interface popup_grab_interface;
2451 destroy_shell_seat(struct wl_listener *listener, void *data)
2453 struct shell_seat *shseat =
2454 container_of(listener,
2455 struct shell_seat, seat_destroy_listener);
2456 struct shell_surface *shsurf, *prev = NULL;
2458 if (shseat->popup_grab.grab.interface == &popup_grab_interface) {
2459 weston_pointer_end_grab(shseat->popup_grab.grab.pointer);
2460 shseat->popup_grab.client = NULL;
2462 wl_list_for_each(shsurf, &shseat->popup_grab.surfaces_list, popup.grab_link) {
2463 shsurf->popup.shseat = NULL;
2465 wl_list_init(&prev->popup.grab_link);
2469 wl_list_init(&prev->popup.grab_link);
2472 wl_list_remove(&shseat->seat_destroy_listener.link);
2476 static struct shell_seat *
2477 create_shell_seat(struct weston_seat *seat)
2479 struct shell_seat *shseat;
2481 shseat = calloc(1, sizeof *shseat);
2483 weston_log("no memory to allocate shell seat\n");
2487 shseat->seat = seat;
2488 wl_list_init(&shseat->popup_grab.surfaces_list);
2490 shseat->seat_destroy_listener.notify = destroy_shell_seat;
2491 wl_signal_add(&seat->destroy_signal,
2492 &shseat->seat_destroy_listener);
2497 static struct shell_seat *
2498 get_shell_seat(struct weston_seat *seat)
2500 struct wl_listener *listener;
2502 listener = wl_signal_get(&seat->destroy_signal, destroy_shell_seat);
2503 if (listener == NULL)
2504 return create_shell_seat(seat);
2506 return container_of(listener,
2507 struct shell_seat, seat_destroy_listener);
2511 popup_grab_focus(struct weston_pointer_grab *grab)
2513 struct weston_pointer *pointer = grab->pointer;
2514 struct weston_view *view;
2515 struct shell_seat *shseat =
2516 container_of(grab, struct shell_seat, popup_grab.grab);
2517 struct wl_client *client = shseat->popup_grab.client;
2520 view = weston_compositor_pick_view(pointer->seat->compositor,
2521 pointer->x, pointer->y,
2524 if (view && view->surface->resource &&
2525 wl_resource_get_client(view->surface->resource) == client) {
2526 weston_pointer_set_focus(pointer, view, sx, sy);
2528 weston_pointer_set_focus(pointer, NULL,
2529 wl_fixed_from_int(0),
2530 wl_fixed_from_int(0));
2535 popup_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
2536 wl_fixed_t x, wl_fixed_t y)
2538 struct weston_pointer *pointer = grab->pointer;
2539 struct wl_resource *resource;
2542 weston_pointer_move(pointer, x, y);
2544 wl_resource_for_each(resource, &pointer->focus_resource_list) {
2545 weston_view_from_global_fixed(pointer->focus,
2546 pointer->x, pointer->y,
2548 wl_pointer_send_motion(resource, time, sx, sy);
2553 popup_grab_button(struct weston_pointer_grab *grab,
2554 uint32_t time, uint32_t button, uint32_t state_w)
2556 struct wl_resource *resource;
2557 struct shell_seat *shseat =
2558 container_of(grab, struct shell_seat, popup_grab.grab);
2559 struct wl_display *display = shseat->seat->compositor->wl_display;
2560 enum wl_pointer_button_state state = state_w;
2562 struct wl_list *resource_list;
2564 resource_list = &grab->pointer->focus_resource_list;
2565 if (!wl_list_empty(resource_list)) {
2566 serial = wl_display_get_serial(display);
2567 wl_resource_for_each(resource, resource_list) {
2568 wl_pointer_send_button(resource, serial,
2569 time, button, state);
2571 } else if (state == WL_POINTER_BUTTON_STATE_RELEASED &&
2572 (shseat->popup_grab.initial_up ||
2573 time - shseat->seat->pointer->grab_time > 500)) {
2574 popup_grab_end(grab->pointer);
2577 if (state == WL_POINTER_BUTTON_STATE_RELEASED)
2578 shseat->popup_grab.initial_up = 1;
2582 popup_grab_cancel(struct weston_pointer_grab *grab)
2584 popup_grab_end(grab->pointer);
2587 static const struct weston_pointer_grab_interface popup_grab_interface = {
2595 popup_grab_end(struct weston_pointer *pointer)
2597 struct weston_pointer_grab *grab = pointer->grab;
2598 struct shell_seat *shseat =
2599 container_of(grab, struct shell_seat, popup_grab.grab);
2600 struct shell_surface *shsurf;
2601 struct shell_surface *prev = NULL;
2603 if (pointer->grab->interface == &popup_grab_interface) {
2604 weston_pointer_end_grab(grab->pointer);
2605 shseat->popup_grab.client = NULL;
2606 shseat->popup_grab.grab.interface = NULL;
2607 assert(!wl_list_empty(&shseat->popup_grab.surfaces_list));
2608 /* Send the popup_done event to all the popups open */
2609 wl_list_for_each(shsurf, &shseat->popup_grab.surfaces_list, popup.grab_link) {
2610 wl_shell_surface_send_popup_done(shsurf->resource);
2611 shsurf->popup.shseat = NULL;
2613 wl_list_init(&prev->popup.grab_link);
2617 wl_list_init(&prev->popup.grab_link);
2618 wl_list_init(&shseat->popup_grab.surfaces_list);
2623 add_popup_grab(struct shell_surface *shsurf, struct shell_seat *shseat)
2625 struct weston_seat *seat = shseat->seat;
2627 if (wl_list_empty(&shseat->popup_grab.surfaces_list)) {
2628 shseat->popup_grab.client = wl_resource_get_client(shsurf->resource);
2629 shseat->popup_grab.grab.interface = &popup_grab_interface;
2630 /* We must make sure here that this popup was opened after
2631 * a mouse press, and not just by moving around with other
2632 * popups already open. */
2633 if (shseat->seat->pointer->button_count > 0)
2634 shseat->popup_grab.initial_up = 0;
2636 wl_list_insert(&shseat->popup_grab.surfaces_list, &shsurf->popup.grab_link);
2637 weston_pointer_start_grab(seat->pointer, &shseat->popup_grab.grab);
2639 wl_list_insert(&shseat->popup_grab.surfaces_list, &shsurf->popup.grab_link);
2644 remove_popup_grab(struct shell_surface *shsurf)
2646 struct shell_seat *shseat = shsurf->popup.shseat;
2648 wl_list_remove(&shsurf->popup.grab_link);
2649 wl_list_init(&shsurf->popup.grab_link);
2650 if (wl_list_empty(&shseat->popup_grab.surfaces_list)) {
2651 weston_pointer_end_grab(shseat->popup_grab.grab.pointer);
2652 shseat->popup_grab.grab.interface = NULL;
2657 shell_map_popup(struct shell_surface *shsurf)
2659 struct shell_seat *shseat = shsurf->popup.shseat;
2660 struct weston_view *parent_view = get_default_view(shsurf->parent);
2662 shsurf->surface->output = parent_view->output;
2663 shsurf->view->output = parent_view->output;
2665 weston_view_set_transform_parent(shsurf->view, parent_view);
2666 weston_view_set_position(shsurf->view, shsurf->popup.x, shsurf->popup.y);
2667 weston_view_update_transform(shsurf->view);
2669 if (shseat->seat->pointer->grab_serial == shsurf->popup.serial) {
2670 add_popup_grab(shsurf, shseat);
2672 wl_shell_surface_send_popup_done(shsurf->resource);
2673 shseat->popup_grab.client = NULL;
2678 shell_surface_set_popup(struct wl_client *client,
2679 struct wl_resource *resource,
2680 struct wl_resource *seat_resource,
2682 struct wl_resource *parent_resource,
2683 int32_t x, int32_t y, uint32_t flags)
2685 struct shell_surface *shsurf = wl_resource_get_user_data(resource);
2687 shsurf->type = SHELL_SURFACE_POPUP;
2688 shsurf->parent = wl_resource_get_user_data(parent_resource);
2689 shsurf->popup.shseat = get_shell_seat(wl_resource_get_user_data(seat_resource));
2690 shsurf->popup.serial = serial;
2691 shsurf->popup.x = x;
2692 shsurf->popup.y = y;
2695 static const struct wl_shell_surface_interface shell_surface_implementation = {
2698 shell_surface_resize,
2699 shell_surface_set_toplevel,
2700 shell_surface_set_transient,
2701 shell_surface_set_fullscreen,
2702 shell_surface_set_popup,
2703 shell_surface_set_maximized,
2704 shell_surface_set_title,
2705 shell_surface_set_class
2709 destroy_shell_surface(struct shell_surface *shsurf)
2711 wl_signal_emit(&shsurf->destroy_signal, shsurf);
2713 if (!wl_list_empty(&shsurf->popup.grab_link)) {
2714 remove_popup_grab(shsurf);
2717 if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
2718 shell_surface_is_top_fullscreen(shsurf))
2719 restore_output_mode (shsurf->fullscreen_output);
2721 if (shsurf->fullscreen.black_view)
2722 weston_surface_destroy(shsurf->fullscreen.black_view->surface);
2724 /* As destroy_resource() use wl_list_for_each_safe(),
2725 * we can always remove the listener.
2727 wl_list_remove(&shsurf->surface_destroy_listener.link);
2728 shsurf->surface->configure = NULL;
2729 ping_timer_destroy(shsurf);
2730 free(shsurf->title);
2732 weston_view_destroy(shsurf->view);
2734 wl_list_remove(&shsurf->link);
2739 shell_destroy_shell_surface(struct wl_resource *resource)
2741 struct shell_surface *shsurf = wl_resource_get_user_data(resource);
2743 destroy_shell_surface(shsurf);
2747 shell_handle_surface_destroy(struct wl_listener *listener, void *data)
2749 struct shell_surface *shsurf = container_of(listener,
2750 struct shell_surface,
2751 surface_destroy_listener);
2753 if (shsurf->resource)
2754 wl_resource_destroy(shsurf->resource);
2756 destroy_shell_surface(shsurf);
2760 shell_surface_configure(struct weston_surface *, int32_t, int32_t, int32_t, int32_t);
2762 static struct shell_surface *
2763 get_shell_surface(struct weston_surface *surface)
2765 if (surface->configure == shell_surface_configure)
2766 return surface->configure_private;
2771 static struct shell_surface *
2772 create_shell_surface(void *shell, struct weston_surface *surface,
2773 const struct weston_shell_client *client)
2775 struct shell_surface *shsurf;
2777 if (surface->configure) {
2778 weston_log("surface->configure already set\n");
2782 shsurf = calloc(1, sizeof *shsurf);
2784 weston_log("no memory to allocate shell surface\n");
2788 shsurf->view = weston_view_create(surface);
2789 if (!shsurf->view) {
2790 weston_log("no memory to allocate shell surface\n");
2795 surface->configure = shell_surface_configure;
2796 surface->configure_private = shsurf;
2798 shsurf->shell = (struct desktop_shell *) shell;
2799 shsurf->unresponsive = 0;
2800 shsurf->saved_position_valid = false;
2801 shsurf->saved_rotation_valid = false;
2802 shsurf->surface = surface;
2803 shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
2804 shsurf->fullscreen.framerate = 0;
2805 shsurf->fullscreen.black_view = NULL;
2806 shsurf->ping_timer = NULL;
2807 wl_list_init(&shsurf->fullscreen.transform.link);
2809 wl_signal_init(&shsurf->destroy_signal);
2810 shsurf->surface_destroy_listener.notify = shell_handle_surface_destroy;
2811 wl_signal_add(&surface->destroy_signal,
2812 &shsurf->surface_destroy_listener);
2814 /* init link so its safe to always remove it in destroy_shell_surface */
2815 wl_list_init(&shsurf->link);
2816 wl_list_init(&shsurf->popup.grab_link);
2818 /* empty when not in use */
2819 wl_list_init(&shsurf->rotation.transform.link);
2820 weston_matrix_init(&shsurf->rotation.rotation);
2822 wl_list_init(&shsurf->workspace_transform.link);
2824 shsurf->type = SHELL_SURFACE_NONE;
2825 shsurf->next_type = SHELL_SURFACE_NONE;
2827 shsurf->client = client;
2832 static struct weston_view *
2833 get_primary_view(void *shell, struct shell_surface *shsurf)
2835 return shsurf->view;
2839 shell_get_shell_surface(struct wl_client *client,
2840 struct wl_resource *resource,
2842 struct wl_resource *surface_resource)
2844 struct weston_surface *surface =
2845 wl_resource_get_user_data(surface_resource);
2846 struct desktop_shell *shell = wl_resource_get_user_data(resource);
2847 struct shell_surface *shsurf;
2849 if (get_shell_surface(surface)) {
2850 wl_resource_post_error(surface_resource,
2851 WL_DISPLAY_ERROR_INVALID_OBJECT,
2852 "desktop_shell::get_shell_surface already requested");
2856 shsurf = create_shell_surface(shell, surface, &shell_client);
2858 wl_resource_post_error(surface_resource,
2859 WL_DISPLAY_ERROR_INVALID_OBJECT,
2860 "surface->configure already set");
2865 wl_resource_create(client,
2866 &wl_shell_surface_interface, 1, id);
2867 wl_resource_set_implementation(shsurf->resource,
2868 &shell_surface_implementation,
2869 shsurf, shell_destroy_shell_surface);
2872 static const struct wl_shell_interface shell_implementation = {
2873 shell_get_shell_surface
2877 shell_fade(struct desktop_shell *shell, enum fade_type type);
2880 screensaver_timeout(void *data)
2882 struct desktop_shell *shell = data;
2884 shell_fade(shell, FADE_OUT);
2890 handle_screensaver_sigchld(struct weston_process *proc, int status)
2892 struct desktop_shell *shell =
2893 container_of(proc, struct desktop_shell, screensaver.process);
2898 weston_compositor_sleep(shell->compositor);
2902 launch_screensaver(struct desktop_shell *shell)
2904 if (shell->screensaver.binding)
2907 if (!shell->screensaver.path) {
2908 weston_compositor_sleep(shell->compositor);
2912 if (shell->screensaver.process.pid != 0) {
2913 weston_log("old screensaver still running\n");
2917 weston_client_launch(shell->compositor,
2918 &shell->screensaver.process,
2919 shell->screensaver.path,
2920 handle_screensaver_sigchld);
2924 terminate_screensaver(struct desktop_shell *shell)
2926 if (shell->screensaver.process.pid == 0)
2929 kill(shell->screensaver.process.pid, SIGTERM);
2933 configure_static_view(struct weston_view *ev, struct weston_layer *layer, int32_t width, int32_t height)
2935 struct weston_view *v, *next;
2940 wl_list_for_each_safe(v, next, &layer->view_list, layer_link) {
2941 if (v->output == ev->output && v != ev) {
2942 weston_view_unmap(v);
2943 v->surface->configure = NULL;
2947 weston_view_configure(ev, ev->output->x, ev->output->y, width, height);
2949 if (wl_list_empty(&ev->layer_link)) {
2950 wl_list_insert(&layer->view_list, &ev->layer_link);
2951 weston_compositor_schedule_repaint(ev->surface->compositor);
2956 background_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height)
2958 struct desktop_shell *shell = es->configure_private;
2959 struct weston_view *view;
2961 view = container_of(es->views.next, struct weston_view, surface_link);
2963 configure_static_view(view, &shell->background_layer, width, height);
2967 desktop_shell_set_background(struct wl_client *client,
2968 struct wl_resource *resource,
2969 struct wl_resource *output_resource,
2970 struct wl_resource *surface_resource)
2972 struct desktop_shell *shell = wl_resource_get_user_data(resource);
2973 struct weston_surface *surface =
2974 wl_resource_get_user_data(surface_resource);
2975 struct weston_view *view, *next;
2977 if (surface->configure) {
2978 wl_resource_post_error(surface_resource,
2979 WL_DISPLAY_ERROR_INVALID_OBJECT,
2980 "surface role already assigned");
2984 wl_list_for_each_safe(view, next, &surface->views, surface_link)
2985 weston_view_destroy(view);
2986 view = weston_view_create(surface);
2988 surface->configure = background_configure;
2989 surface->configure_private = shell;
2990 surface->output = wl_resource_get_user_data(output_resource);
2991 view->output = surface->output;
2992 desktop_shell_send_configure(resource, 0,
2994 surface->output->width,
2995 surface->output->height);
2999 panel_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height)
3001 struct desktop_shell *shell = es->configure_private;
3002 struct weston_view *view;
3004 view = container_of(es->views.next, struct weston_view, surface_link);
3006 configure_static_view(view, &shell->panel_layer, width, height);
3010 desktop_shell_set_panel(struct wl_client *client,
3011 struct wl_resource *resource,
3012 struct wl_resource *output_resource,
3013 struct wl_resource *surface_resource)
3015 struct desktop_shell *shell = wl_resource_get_user_data(resource);
3016 struct weston_surface *surface =
3017 wl_resource_get_user_data(surface_resource);
3018 struct weston_view *view, *next;
3020 if (surface->configure) {
3021 wl_resource_post_error(surface_resource,
3022 WL_DISPLAY_ERROR_INVALID_OBJECT,
3023 "surface role already assigned");
3027 wl_list_for_each_safe(view, next, &surface->views, surface_link)
3028 weston_view_destroy(view);
3029 view = weston_view_create(surface);
3031 surface->configure = panel_configure;
3032 surface->configure_private = shell;
3033 surface->output = wl_resource_get_user_data(output_resource);
3034 view->output = surface->output;
3035 desktop_shell_send_configure(resource, 0,
3037 surface->output->width,
3038 surface->output->height);
3042 lock_surface_configure(struct weston_surface *surface, int32_t sx, int32_t sy, int32_t width, int32_t height)
3044 struct desktop_shell *shell = surface->configure_private;
3045 struct weston_view *view;
3047 view = container_of(surface->views.next, struct weston_view, surface_link);
3052 surface->width = width;
3053 surface->height = height;
3054 view->geometry.width = width;
3055 view->geometry.height = height;
3056 center_on_output(view, get_default_output(shell->compositor));
3058 if (!weston_surface_is_mapped(surface)) {
3059 wl_list_insert(&shell->lock_layer.view_list,
3061 weston_view_update_transform(view);
3062 shell_fade(shell, FADE_IN);
3067 handle_lock_surface_destroy(struct wl_listener *listener, void *data)
3069 struct desktop_shell *shell =
3070 container_of(listener, struct desktop_shell, lock_surface_listener);
3072 weston_log("lock surface gone\n");
3073 shell->lock_surface = NULL;
3077 desktop_shell_set_lock_surface(struct wl_client *client,
3078 struct wl_resource *resource,
3079 struct wl_resource *surface_resource)
3081 struct desktop_shell *shell = wl_resource_get_user_data(resource);
3082 struct weston_surface *surface =
3083 wl_resource_get_user_data(surface_resource);
3085 shell->prepare_event_sent = false;
3090 shell->lock_surface = surface;
3092 shell->lock_surface_listener.notify = handle_lock_surface_destroy;
3093 wl_signal_add(&surface->destroy_signal,
3094 &shell->lock_surface_listener);
3096 weston_view_create(surface);
3097 surface->configure = lock_surface_configure;
3098 surface->configure_private = shell;
3102 resume_desktop(struct desktop_shell *shell)
3104 struct workspace *ws = get_current_workspace(shell);
3106 terminate_screensaver(shell);
3108 wl_list_remove(&shell->lock_layer.link);
3109 wl_list_insert(&shell->compositor->cursor_layer.link,
3110 &shell->fullscreen_layer.link);
3111 wl_list_insert(&shell->fullscreen_layer.link,
3112 &shell->panel_layer.link);
3113 if (shell->showing_input_panels) {
3114 wl_list_insert(&shell->panel_layer.link,
3115 &shell->input_panel_layer.link);
3116 wl_list_insert(&shell->input_panel_layer.link,
3119 wl_list_insert(&shell->panel_layer.link, &ws->layer.link);
3122 restore_focus_state(shell, get_current_workspace(shell));
3124 shell->locked = false;
3125 shell_fade(shell, FADE_IN);
3126 weston_compositor_damage_all(shell->compositor);
3130 desktop_shell_unlock(struct wl_client *client,
3131 struct wl_resource *resource)
3133 struct desktop_shell *shell = wl_resource_get_user_data(resource);
3135 shell->prepare_event_sent = false;
3138 resume_desktop(shell);
3142 desktop_shell_set_grab_surface(struct wl_client *client,
3143 struct wl_resource *resource,
3144 struct wl_resource *surface_resource)
3146 struct desktop_shell *shell = wl_resource_get_user_data(resource);
3148 shell->grab_surface = wl_resource_get_user_data(surface_resource);
3149 weston_view_create(shell->grab_surface);
3153 desktop_shell_desktop_ready(struct wl_client *client,
3154 struct wl_resource *resource)
3156 struct desktop_shell *shell = wl_resource_get_user_data(resource);
3158 shell_fade_startup(shell);
3161 static const struct desktop_shell_interface desktop_shell_implementation = {
3162 desktop_shell_set_background,
3163 desktop_shell_set_panel,
3164 desktop_shell_set_lock_surface,
3165 desktop_shell_unlock,
3166 desktop_shell_set_grab_surface,
3167 desktop_shell_desktop_ready
3170 static enum shell_surface_type
3171 get_shell_surface_type(struct weston_surface *surface)
3173 struct shell_surface *shsurf;
3175 shsurf = get_shell_surface(surface);
3177 return SHELL_SURFACE_NONE;
3178 return shsurf->type;
3182 move_binding(struct weston_seat *seat, uint32_t time, uint32_t button, void *data)
3184 struct weston_surface *focus = seat->pointer->focus->surface;
3185 struct weston_surface *surface;
3186 struct shell_surface *shsurf;
3188 surface = weston_surface_get_main_surface(focus);
3189 if (surface == NULL)
3192 shsurf = get_shell_surface(surface);
3193 if (shsurf == NULL || shsurf->type == SHELL_SURFACE_FULLSCREEN ||
3194 shsurf->type == SHELL_SURFACE_MAXIMIZED)
3197 surface_move(shsurf, (struct weston_seat *) seat);
3201 touch_move_binding(struct weston_seat *seat, uint32_t time, void *data)
3203 struct weston_surface *focus = seat->touch->focus->surface;
3204 struct weston_surface *surface;
3205 struct shell_surface *shsurf;
3207 surface = weston_surface_get_main_surface(focus);
3208 if (surface == NULL)
3211 shsurf = get_shell_surface(surface);
3212 if (shsurf == NULL || shsurf->type == SHELL_SURFACE_FULLSCREEN ||
3213 shsurf->type == SHELL_SURFACE_MAXIMIZED)
3216 surface_touch_move(shsurf, (struct weston_seat *) seat);
3220 resize_binding(struct weston_seat *seat, uint32_t time, uint32_t button, void *data)
3222 struct weston_surface *focus = seat->pointer->focus->surface;
3223 struct weston_surface *surface;
3226 struct shell_surface *shsurf;
3228 surface = weston_surface_get_main_surface(focus);
3229 if (surface == NULL)
3232 shsurf = get_shell_surface(surface);
3233 if (!shsurf || shsurf->type == SHELL_SURFACE_FULLSCREEN ||
3234 shsurf->type == SHELL_SURFACE_MAXIMIZED)
3237 weston_view_from_global(shsurf->view,
3238 wl_fixed_to_int(seat->pointer->grab_x),
3239 wl_fixed_to_int(seat->pointer->grab_y),
3242 if (x < shsurf->view->geometry.width / 3)
3243 edges |= WL_SHELL_SURFACE_RESIZE_LEFT;
3244 else if (x < 2 * shsurf->view->geometry.width / 3)
3247 edges |= WL_SHELL_SURFACE_RESIZE_RIGHT;
3249 if (y < shsurf->view->geometry.height / 3)
3250 edges |= WL_SHELL_SURFACE_RESIZE_TOP;
3251 else if (y < 2 * shsurf->view->geometry.height / 3)
3254 edges |= WL_SHELL_SURFACE_RESIZE_BOTTOM;
3256 surface_resize(shsurf, (struct weston_seat *) seat, edges);
3260 surface_opacity_binding(struct weston_seat *seat, uint32_t time, uint32_t axis,
3261 wl_fixed_t value, void *data)
3264 struct shell_surface *shsurf;
3265 struct weston_surface *focus = seat->pointer->focus->surface;
3266 struct weston_surface *surface;
3268 /* XXX: broken for windows containing sub-surfaces */
3269 surface = weston_surface_get_main_surface(focus);
3270 if (surface == NULL)
3273 shsurf = get_shell_surface(surface);
3277 shsurf->view->alpha -= wl_fixed_to_double(value) * step;
3279 if (shsurf->view->alpha > 1.0)
3280 shsurf->view->alpha = 1.0;
3281 if (shsurf->view->alpha < step)
3282 shsurf->view->alpha = step;
3284 weston_view_geometry_dirty(shsurf->view);
3285 weston_surface_damage(surface);
3289 do_zoom(struct weston_seat *seat, uint32_t time, uint32_t key, uint32_t axis,
3292 struct weston_seat *ws = (struct weston_seat *) seat;
3293 struct weston_compositor *compositor = ws->compositor;
3294 struct weston_output *output;
3297 wl_list_for_each(output, &compositor->output_list, link) {
3298 if (pixman_region32_contains_point(&output->region,
3299 wl_fixed_to_double(seat->pointer->x),
3300 wl_fixed_to_double(seat->pointer->y),
3302 if (key == KEY_PAGEUP)
3303 increment = output->zoom.increment;
3304 else if (key == KEY_PAGEDOWN)
3305 increment = -output->zoom.increment;
3306 else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
3307 /* For every pixel zoom 20th of a step */
3308 increment = output->zoom.increment *
3309 -wl_fixed_to_double(value) / 20.0;
3313 output->zoom.level += increment;
3315 if (output->zoom.level < 0.0)
3316 output->zoom.level = 0.0;
3317 else if (output->zoom.level > output->zoom.max_level)
3318 output->zoom.level = output->zoom.max_level;
3319 else if (!output->zoom.active) {
3320 weston_output_activate_zoom(output);
3323 output->zoom.spring_z.target = output->zoom.level;
3325 weston_output_update_zoom(output);
3331 zoom_axis_binding(struct weston_seat *seat, uint32_t time, uint32_t axis,
3332 wl_fixed_t value, void *data)
3334 do_zoom(seat, time, 0, axis, value);
3338 zoom_key_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
3341 do_zoom(seat, time, key, 0, 0);
3345 terminate_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
3348 struct weston_compositor *compositor = data;
3350 wl_display_terminate(compositor->wl_display);
3354 lower_fullscreen_layer(struct desktop_shell *shell);
3357 struct desktop_shell *shell;
3358 struct weston_keyboard_grab grab;
3360 struct wl_list *current;
3362 struct wl_list preview_list;
3365 struct alt_tab_preview {
3366 struct alt_tab *alt_tab;
3368 struct weston_view *view;
3369 struct weston_transform transform;
3371 struct wl_listener listener;
3373 struct wl_list link;
3377 alt_tab_next(struct alt_tab *alt_tab)
3379 alt_tab->current = alt_tab->current->next;
3381 /* Make sure we're not pointing to the list header e.g. after
3382 * cycling through the whole list. */
3383 if (alt_tab->current->next == alt_tab->preview_list.next)
3384 alt_tab->current = alt_tab->current->next;
3388 alt_tab_destroy(struct alt_tab *alt_tab)
3390 struct alt_tab_preview *preview, *next;
3391 struct weston_keyboard *keyboard = alt_tab->grab.keyboard;
3393 if (alt_tab->current && alt_tab->current != &alt_tab->preview_list) {
3394 preview = wl_container_of(alt_tab->current, preview, link);
3396 activate(alt_tab->shell, preview->view->surface,
3397 (struct weston_seat *) keyboard->seat);
3400 wl_list_for_each_safe(preview, next, &alt_tab->preview_list, link) {
3401 wl_list_remove(&preview->link);
3402 wl_list_remove(&preview->listener.link);
3403 weston_view_destroy(preview->view);
3407 weston_keyboard_end_grab(keyboard);
3408 if (keyboard->input_method_resource)
3409 keyboard->grab = &keyboard->input_method_grab;
3415 alt_tab_handle_surface_destroy(struct wl_listener *listener, void *data)
3417 struct alt_tab_preview *preview =
3418 container_of(listener, struct alt_tab_preview, listener);
3419 struct alt_tab *alt_tab = preview->alt_tab;
3422 /* If the preview that we're removing is the currently selected one,
3423 * we want to move to the next one. So we move to ->prev and then
3424 * call _next() after removing the preview. */
3425 if (alt_tab->current == &preview->link) {
3426 alt_tab->current = alt_tab->current->prev;
3430 wl_list_remove(&preview->listener.link);
3431 wl_list_remove(&preview->link);
3436 alt_tab_next(alt_tab);
3438 /* If the last preview goes away, stop the alt-tab */
3439 if (wl_list_empty(alt_tab->current))
3440 alt_tab_destroy(alt_tab);
3444 alt_tab_key(struct weston_keyboard_grab *grab,
3445 uint32_t time, uint32_t key, uint32_t state_w)
3447 struct alt_tab *alt_tab = container_of(grab, struct alt_tab, grab);
3448 enum wl_keyboard_key_state state = state_w;
3450 if (key == KEY_TAB && state == WL_KEYBOARD_KEY_STATE_PRESSED)
3451 alt_tab_next(alt_tab);
3455 alt_tab_modifier(struct weston_keyboard_grab *grab, uint32_t serial,
3456 uint32_t mods_depressed, uint32_t mods_latched,
3457 uint32_t mods_locked, uint32_t group)
3459 struct alt_tab *alt_tab = container_of(grab, struct alt_tab, grab);
3460 struct weston_seat *seat = (struct weston_seat *) grab->keyboard->seat;
3462 if ((seat->modifier_state & MODIFIER_ALT) == 0)
3463 alt_tab_destroy(alt_tab);
3467 alt_tab_cancel(struct weston_keyboard_grab *grab)
3469 struct alt_tab *alt_tab = container_of(grab, struct alt_tab, grab);
3471 alt_tab_destroy(alt_tab);
3474 static const struct weston_keyboard_grab_interface alt_tab_grab = {
3481 view_for_alt_tab(struct weston_view *view)
3483 if (!get_shell_surface(view->surface))
3486 if (get_shell_surface_type(view->surface) == SHELL_SURFACE_TRANSIENT)
3489 if (view != get_default_view(view->surface))
3496 alt_tab_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
3499 struct alt_tab *alt_tab;
3500 struct desktop_shell *shell = data;
3501 struct weston_output *output = get_default_output(shell->compositor);
3502 struct workspace *ws;
3503 struct weston_view *view;
3504 int num_surfaces = 0;
3505 int x, y, side, margin;
3507 wl_list_for_each(view, &shell->compositor->view_list, link) {
3509 if (view_for_alt_tab(view))
3516 alt_tab = malloc(sizeof *alt_tab);
3520 alt_tab->shell = shell;
3521 wl_list_init(&alt_tab->preview_list);
3522 alt_tab->current = &alt_tab->preview_list;
3524 restore_all_output_modes(shell->compositor);
3525 lower_fullscreen_layer(alt_tab->shell);
3527 alt_tab->grab.interface = &alt_tab_grab;
3528 weston_keyboard_start_grab(seat->keyboard, &alt_tab->grab);
3529 weston_keyboard_set_focus(seat->keyboard, NULL);
3531 ws = get_current_workspace(shell);
3533 /* FIXME: add some visual candy e.g. prelight the selected view
3534 * and/or add a black surrounding background à la gnome-shell */
3536 /* Determine the size for each preview */
3537 side = output->width / num_surfaces;
3544 y = (output->height - side) / 2;
3546 /* Create a view for each surface */
3547 wl_list_for_each(view, &shell->compositor->view_list, link) {
3548 struct alt_tab_preview *preview;
3549 struct weston_view *v;
3552 if (!view_for_alt_tab(view))
3555 preview = malloc(sizeof *preview);
3557 alt_tab_destroy(alt_tab);
3561 preview->alt_tab = alt_tab;
3563 preview->view = v = weston_view_create(view->surface);
3564 v->output = view->output;
3565 weston_view_restack(v, &ws->layer.view_list);
3566 weston_view_configure(v, x, y, view->geometry.width, view->geometry.height);
3568 preview->listener.notify = alt_tab_handle_surface_destroy;
3569 wl_signal_add(&v->destroy_signal, &preview->listener);
3571 if (view->geometry.width > view->geometry.height)
3572 scale = side / (float) view->geometry.width;
3574 scale = side / (float) view->geometry.height;
3576 wl_list_insert(&v->geometry.transformation_list,
3577 &preview->transform.link);
3578 weston_matrix_init(&preview->transform.matrix);
3579 weston_matrix_scale(&preview->transform.matrix,
3580 scale, scale, 1.0f);
3582 weston_view_geometry_dirty(v);
3583 weston_compositor_schedule_repaint(v->surface->compositor);
3585 /* Insert at the end of the list */
3586 wl_list_insert(alt_tab->preview_list.prev, &preview->link);
3591 /* Start at the second preview so a simple <alt>tab changes window.
3592 * We set `current' to the first preview and not the second because
3593 * we're going to receive a key press callback for the initial
3594 * <alt>tab which will make `current' point to the second element. */
3595 alt_tab_next(alt_tab);
3599 rotate_grab_motion(struct weston_pointer_grab *grab, uint32_t time,
3600 wl_fixed_t x, wl_fixed_t y)
3602 struct rotate_grab *rotate =
3603 container_of(grab, struct rotate_grab, base.grab);
3604 struct weston_pointer *pointer = grab->pointer;
3605 struct shell_surface *shsurf = rotate->base.shsurf;
3606 float cx, cy, dx, dy, cposx, cposy, dposx, dposy, r;
3608 weston_pointer_move(pointer, x, y);
3613 cx = 0.5f * shsurf->view->geometry.width;
3614 cy = 0.5f * shsurf->view->geometry.height;
3616 dx = wl_fixed_to_double(pointer->x) - rotate->center.x;
3617 dy = wl_fixed_to_double(pointer->y) - rotate->center.y;
3618 r = sqrtf(dx * dx + dy * dy);
3620 wl_list_remove(&shsurf->rotation.transform.link);
3621 weston_view_geometry_dirty(shsurf->view);
3624 struct weston_matrix *matrix =
3625 &shsurf->rotation.transform.matrix;
3627 weston_matrix_init(&rotate->rotation);
3628 weston_matrix_rotate_xy(&rotate->rotation, dx / r, dy / r);
3630 weston_matrix_init(matrix);
3631 weston_matrix_translate(matrix, -cx, -cy, 0.0f);
3632 weston_matrix_multiply(matrix, &shsurf->rotation.rotation);
3633 weston_matrix_multiply(matrix, &rotate->rotation);
3634 weston_matrix_translate(matrix, cx, cy, 0.0f);
3637 &shsurf->view->geometry.transformation_list,
3638 &shsurf->rotation.transform.link);
3640 wl_list_init(&shsurf->rotation.transform.link);
3641 weston_matrix_init(&shsurf->rotation.rotation);
3642 weston_matrix_init(&rotate->rotation);
3645 /* We need to adjust the position of the surface
3646 * in case it was resized in a rotated state before */
3647 cposx = shsurf->view->geometry.x + cx;
3648 cposy = shsurf->view->geometry.y + cy;
3649 dposx = rotate->center.x - cposx;
3650 dposy = rotate->center.y - cposy;
3651 if (dposx != 0.0f || dposy != 0.0f) {
3652 weston_view_set_position(shsurf->view,
3653 shsurf->view->geometry.x + dposx,
3654 shsurf->view->geometry.y + dposy);
3657 /* Repaint implies weston_surface_update_transform(), which
3658 * lazily applies the damage due to rotation update.
3660 weston_compositor_schedule_repaint(shsurf->surface->compositor);
3664 rotate_grab_button(struct weston_pointer_grab *grab,
3665 uint32_t time, uint32_t button, uint32_t state_w)
3667 struct rotate_grab *rotate =
3668 container_of(grab, struct rotate_grab, base.grab);
3669 struct weston_pointer *pointer = grab->pointer;
3670 struct shell_surface *shsurf = rotate->base.shsurf;
3671 enum wl_pointer_button_state state = state_w;
3673 if (pointer->button_count == 0 &&
3674 state == WL_POINTER_BUTTON_STATE_RELEASED) {
3676 weston_matrix_multiply(&shsurf->rotation.rotation,
3678 shell_grab_end(&rotate->base);
3684 rotate_grab_cancel(struct weston_pointer_grab *grab)
3686 struct rotate_grab *rotate =
3687 container_of(grab, struct rotate_grab, base.grab);
3689 shell_grab_end(&rotate->base);
3693 static const struct weston_pointer_grab_interface rotate_grab_interface = {
3701 surface_rotate(struct shell_surface *surface, struct weston_seat *seat)
3703 struct rotate_grab *rotate;
3707 rotate = malloc(sizeof *rotate);
3711 weston_view_to_global_float(surface->view,
3712 surface->view->geometry.width * 0.5f,
3713 surface->view->geometry.height * 0.5f,
3714 &rotate->center.x, &rotate->center.y);
3716 dx = wl_fixed_to_double(seat->pointer->x) - rotate->center.x;
3717 dy = wl_fixed_to_double(seat->pointer->y) - rotate->center.y;
3718 r = sqrtf(dx * dx + dy * dy);
3720 struct weston_matrix inverse;
3722 weston_matrix_init(&inverse);
3723 weston_matrix_rotate_xy(&inverse, dx / r, -dy / r);
3724 weston_matrix_multiply(&surface->rotation.rotation, &inverse);
3726 weston_matrix_init(&rotate->rotation);
3727 weston_matrix_rotate_xy(&rotate->rotation, dx / r, dy / r);
3729 weston_matrix_init(&surface->rotation.rotation);
3730 weston_matrix_init(&rotate->rotation);
3733 shell_grab_start(&rotate->base, &rotate_grab_interface, surface,
3734 seat->pointer, DESKTOP_SHELL_CURSOR_ARROW);
3738 rotate_binding(struct weston_seat *seat, uint32_t time, uint32_t button,
3741 struct weston_surface *focus = seat->pointer->focus->surface;
3742 struct weston_surface *base_surface;
3743 struct shell_surface *surface;
3745 base_surface = weston_surface_get_main_surface(focus);
3746 if (base_surface == NULL)
3749 surface = get_shell_surface(base_surface);
3750 if (!surface || surface->type == SHELL_SURFACE_FULLSCREEN ||
3751 surface->type == SHELL_SURFACE_MAXIMIZED)
3754 surface_rotate(surface, seat);
3758 lower_fullscreen_layer(struct desktop_shell *shell)
3760 struct workspace *ws;
3761 struct weston_view *view, *prev;
3763 ws = get_current_workspace(shell);
3764 wl_list_for_each_reverse_safe(view, prev,
3765 &shell->fullscreen_layer.view_list,
3767 weston_view_restack(view, &ws->layer.view_list);
3771 activate(struct desktop_shell *shell, struct weston_surface *es,
3772 struct weston_seat *seat)
3774 struct weston_surface *main_surface;
3775 struct weston_view *main_view;
3776 struct focus_state *state;
3777 struct workspace *ws;
3778 struct weston_surface *old_es;
3780 main_surface = weston_surface_get_main_surface(es);
3782 weston_surface_activate(es, seat);
3784 state = ensure_focus_state(shell, seat);
3788 old_es = state->keyboard_focus;
3789 state->keyboard_focus = es;
3790 wl_list_remove(&state->surface_destroy_listener.link);
3791 wl_signal_add(&es->destroy_signal, &state->surface_destroy_listener);
3793 switch (get_shell_surface_type(main_surface)) {
3794 case SHELL_SURFACE_FULLSCREEN:
3795 /* should on top of panels */
3796 shell_stack_fullscreen(get_shell_surface(main_surface));
3797 shell_configure_fullscreen(get_shell_surface(main_surface));
3800 restore_all_output_modes(shell->compositor);
3801 ws = get_current_workspace(shell);
3802 main_view = get_default_view(main_surface);
3804 weston_view_restack(main_view, &ws->layer.view_list);
3808 if (shell->focus_animation_type != ANIMATION_NONE)
3809 animate_focus_change(shell, ws, get_default_view(old_es), get_default_view(es));
3812 /* no-op func for checking black surface */
3814 black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height)
3819 is_black_surface (struct weston_surface *es, struct weston_surface **fs_surface)
3821 if (es->configure == black_surface_configure) {
3823 *fs_surface = (struct weston_surface *)es->configure_private;
3830 activate_binding(struct weston_seat *seat,
3831 struct desktop_shell *shell,
3832 struct weston_surface *focus)
3834 struct weston_surface *main_surface;
3839 if (is_black_surface(focus, &main_surface))
3840 focus = main_surface;
3842 main_surface = weston_surface_get_main_surface(focus);
3843 if (get_shell_surface_type(main_surface) == SHELL_SURFACE_NONE)
3846 activate(shell, focus, seat);
3850 click_to_activate_binding(struct weston_seat *seat, uint32_t time, uint32_t button,
3853 if (seat->pointer->grab != &seat->pointer->default_grab)
3856 activate_binding(seat, data, seat->pointer->focus->surface);
3860 touch_to_activate_binding(struct weston_seat *seat, uint32_t time, void *data)
3862 if (seat->touch->grab != &seat->touch->default_grab)
3865 activate_binding(seat, data, seat->touch->focus->surface);
3869 lock(struct desktop_shell *shell)
3871 struct workspace *ws = get_current_workspace(shell);
3873 if (shell->locked) {
3874 weston_compositor_sleep(shell->compositor);
3878 shell->locked = true;
3880 /* Hide all surfaces by removing the fullscreen, panel and
3881 * toplevel layers. This way nothing else can show or receive
3882 * input events while we are locked. */
3884 wl_list_remove(&shell->panel_layer.link);
3885 wl_list_remove(&shell->fullscreen_layer.link);
3886 if (shell->showing_input_panels)
3887 wl_list_remove(&shell->input_panel_layer.link);
3888 wl_list_remove(&ws->layer.link);
3889 wl_list_insert(&shell->compositor->cursor_layer.link,
3890 &shell->lock_layer.link);
3892 launch_screensaver(shell);
3894 /* TODO: disable bindings that should not work while locked. */
3896 /* All this must be undone in resume_desktop(). */
3900 unlock(struct desktop_shell *shell)
3902 if (!shell->locked || shell->lock_surface) {
3903 shell_fade(shell, FADE_IN);
3907 /* If desktop-shell client has gone away, unlock immediately. */
3908 if (!shell->child.desktop_shell) {
3909 resume_desktop(shell);
3913 if (shell->prepare_event_sent)
3916 desktop_shell_send_prepare_lock_surface(shell->child.desktop_shell);
3917 shell->prepare_event_sent = true;
3921 shell_fade_done(struct weston_view_animation *animation, void *data)
3923 struct desktop_shell *shell = data;
3925 shell->fade.animation = NULL;
3927 switch (shell->fade.type) {
3929 weston_surface_destroy(shell->fade.view->surface);
3930 shell->fade.view = NULL;
3938 static struct weston_view *
3939 shell_fade_create_surface(struct desktop_shell *shell)
3941 struct weston_compositor *compositor = shell->compositor;
3942 struct weston_surface *surface;
3943 struct weston_view *view;
3945 surface = weston_surface_create(compositor);
3949 view = weston_view_create(surface);
3951 weston_surface_destroy(surface);
3955 weston_view_configure(view, 0, 0, 8192, 8192);
3956 weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1.0);
3957 wl_list_insert(&compositor->fade_layer.view_list,
3959 pixman_region32_init(&surface->input);
3965 shell_fade(struct desktop_shell *shell, enum fade_type type)
3977 weston_log("shell: invalid fade type\n");
3981 shell->fade.type = type;
3983 if (shell->fade.view == NULL) {
3984 shell->fade.view = shell_fade_create_surface(shell);
3985 if (!shell->fade.view)
3988 shell->fade.view->alpha = 1.0 - tint;
3989 weston_view_update_transform(shell->fade.view);
3992 if (shell->fade.animation)
3993 weston_fade_update(shell->fade.animation, tint);
3995 shell->fade.animation =
3996 weston_fade_run(shell->fade.view,
3997 1.0 - tint, tint, 300.0,
3998 shell_fade_done, shell);
4002 do_shell_fade_startup(void *data)
4004 struct desktop_shell *shell = data;
4006 if (shell->startup_animation_type == ANIMATION_FADE)
4007 shell_fade(shell, FADE_IN);
4008 else if (shell->startup_animation_type == ANIMATION_NONE) {
4009 weston_surface_destroy(shell->fade.view->surface);
4010 shell->fade.view = NULL;
4015 shell_fade_startup(struct desktop_shell *shell)
4017 struct wl_event_loop *loop;
4019 if (!shell->fade.startup_timer)
4022 wl_event_source_remove(shell->fade.startup_timer);
4023 shell->fade.startup_timer = NULL;
4025 loop = wl_display_get_event_loop(shell->compositor->wl_display);
4026 wl_event_loop_add_idle(loop, do_shell_fade_startup, shell);
4030 fade_startup_timeout(void *data)
4032 struct desktop_shell *shell = data;
4034 shell_fade_startup(shell);
4039 shell_fade_init(struct desktop_shell *shell)
4041 /* Make compositor output all black, and wait for the desktop-shell
4042 * client to signal it is ready, then fade in. The timer triggers a
4043 * fade-in, in case the desktop-shell client takes too long.
4046 struct wl_event_loop *loop;
4048 if (shell->fade.view != NULL) {
4049 weston_log("%s: warning: fade surface already exists\n",
4054 shell->fade.view = shell_fade_create_surface(shell);
4055 if (!shell->fade.view)
4058 weston_view_update_transform(shell->fade.view);
4059 weston_surface_damage(shell->fade.view->surface);
4061 loop = wl_display_get_event_loop(shell->compositor->wl_display);
4062 shell->fade.startup_timer =
4063 wl_event_loop_add_timer(loop, fade_startup_timeout, shell);
4064 wl_event_source_timer_update(shell->fade.startup_timer, 15000);
4068 idle_handler(struct wl_listener *listener, void *data)
4070 struct desktop_shell *shell =
4071 container_of(listener, struct desktop_shell, idle_listener);
4073 shell_fade(shell, FADE_OUT);
4074 /* lock() is called from shell_fade_done() */
4078 wake_handler(struct wl_listener *listener, void *data)
4080 struct desktop_shell *shell =
4081 container_of(listener, struct desktop_shell, wake_listener);
4087 show_input_panels(struct wl_listener *listener, void *data)
4089 struct desktop_shell *shell =
4090 container_of(listener, struct desktop_shell,
4091 show_input_panel_listener);
4092 struct input_panel_surface *ipsurf, *next;
4094 shell->text_input.surface = (struct weston_surface*)data;
4096 if (shell->showing_input_panels)
4099 shell->showing_input_panels = true;
4102 wl_list_insert(&shell->panel_layer.link,
4103 &shell->input_panel_layer.link);
4105 wl_list_for_each_safe(ipsurf, next,
4106 &shell->input_panel.surfaces, link) {
4107 if (!ipsurf->surface->buffer_ref.buffer)
4109 wl_list_insert(&shell->input_panel_layer.view_list,
4110 &ipsurf->view->layer_link);
4111 weston_view_geometry_dirty(ipsurf->view);
4112 weston_view_update_transform(ipsurf->view);
4113 weston_surface_damage(ipsurf->surface);
4114 weston_slide_run(ipsurf->view, ipsurf->view->geometry.height,
4120 hide_input_panels(struct wl_listener *listener, void *data)
4122 struct desktop_shell *shell =
4123 container_of(listener, struct desktop_shell,
4124 hide_input_panel_listener);
4125 struct weston_view *view, *next;
4127 if (!shell->showing_input_panels)
4130 shell->showing_input_panels = false;
4133 wl_list_remove(&shell->input_panel_layer.link);
4135 wl_list_for_each_safe(view, next,
4136 &shell->input_panel_layer.view_list, layer_link)
4137 weston_view_unmap(view);
4141 update_input_panels(struct wl_listener *listener, void *data)
4143 struct desktop_shell *shell =
4144 container_of(listener, struct desktop_shell,
4145 update_input_panel_listener);
4147 memcpy(&shell->text_input.cursor_rectangle, data, sizeof(pixman_box32_t));
4151 center_on_output(struct weston_view *view, struct weston_output *output)
4153 int32_t surf_x, surf_y, width, height;
4156 surface_subsurfaces_boundingbox(view->surface, &surf_x, &surf_y, &width, &height);
4158 x = output->x + (output->width - width) / 2 - surf_x / 2;
4159 y = output->y + (output->height - height) / 2 - surf_y / 2;
4161 weston_view_configure(view, x, y, width, height);
4165 weston_view_set_initial_position(struct weston_view *view,
4166 struct desktop_shell *shell)
4168 struct weston_compositor *compositor = shell->compositor;
4170 int range_x, range_y;
4171 int dx, dy, x, y, panel_height;
4172 struct weston_output *output, *target_output = NULL;
4173 struct weston_seat *seat;
4175 /* As a heuristic place the new window on the same output as the
4176 * pointer. Falling back to the output containing 0, 0.
4178 * TODO: Do something clever for touch too?
4180 wl_list_for_each(seat, &compositor->seat_list, link) {
4181 if (seat->pointer) {
4182 ix = wl_fixed_to_int(seat->pointer->x);
4183 iy = wl_fixed_to_int(seat->pointer->y);
4188 wl_list_for_each(output, &compositor->output_list, link) {
4189 if (pixman_region32_contains_point(&output->region, ix, iy, NULL)) {
4190 target_output = output;
4195 if (!target_output) {
4196 weston_view_set_position(view, 10 + random() % 400,
4197 10 + random() % 400);
4201 /* Valid range within output where the surface will still be onscreen.
4202 * If this is negative it means that the surface is bigger than
4205 panel_height = get_output_panel_height(shell, target_output);
4206 range_x = target_output->width - view->geometry.width;
4207 range_y = (target_output->height - panel_height) -
4208 view->geometry.height;
4211 dx = random() % range_x;
4216 dy = panel_height + random() % range_y;
4220 x = target_output->x + dx;
4221 y = target_output->y + dy;
4223 weston_view_set_position(view, x, y);
4227 map(struct desktop_shell *shell, struct shell_surface *shsurf,
4228 int32_t width, int32_t height, int32_t sx, int32_t sy)
4230 struct weston_compositor *compositor = shell->compositor;
4231 struct weston_view *parent;
4232 struct weston_seat *seat;
4233 struct workspace *ws;
4234 int panel_height = 0;
4235 int32_t surf_x, surf_y;
4237 shsurf->view->geometry.width = width;
4238 shsurf->view->geometry.height = height;
4239 weston_view_geometry_dirty(shsurf->view);
4241 /* initial positioning, see also configure() */
4242 switch (shsurf->type) {
4243 case SHELL_SURFACE_TOPLEVEL:
4244 weston_view_set_initial_position(shsurf->view, shell);
4246 case SHELL_SURFACE_FULLSCREEN:
4247 center_on_output(shsurf->view, shsurf->fullscreen_output);
4248 shell_map_fullscreen(shsurf);
4250 case SHELL_SURFACE_MAXIMIZED:
4251 /* use surface configure to set the geometry */
4252 panel_height = get_output_panel_height(shell, shsurf->output);
4253 surface_subsurfaces_boundingbox(shsurf->surface,
4254 &surf_x, &surf_y, NULL, NULL);
4255 weston_view_set_position(shsurf->view,
4256 shsurf->output->x - surf_x,
4257 shsurf->output->y + panel_height - surf_y);
4259 case SHELL_SURFACE_POPUP:
4260 shell_map_popup(shsurf);
4262 case SHELL_SURFACE_NONE:
4263 weston_view_set_position(shsurf->view,
4264 shsurf->view->geometry.x + sx,
4265 shsurf->view->geometry.y + sy);
4271 /* surface stacking order, see also activate() */
4272 switch (shsurf->type) {
4273 case SHELL_SURFACE_POPUP:
4274 case SHELL_SURFACE_TRANSIENT:
4275 /* TODO: Handle a parent with multiple views */
4276 parent = get_default_view(shsurf->parent);
4278 wl_list_remove(&shsurf->view->layer_link);
4279 wl_list_insert(parent->layer_link.prev,
4280 &shsurf->view->layer_link);
4283 case SHELL_SURFACE_FULLSCREEN:
4284 case SHELL_SURFACE_NONE:
4286 case SHELL_SURFACE_XWAYLAND:
4288 ws = get_current_workspace(shell);
4289 wl_list_remove(&shsurf->view->layer_link);
4290 wl_list_insert(&ws->layer.view_list, &shsurf->view->layer_link);
4294 if (shsurf->type != SHELL_SURFACE_NONE) {
4295 weston_view_update_transform(shsurf->view);
4296 if (shsurf->type == SHELL_SURFACE_MAXIMIZED) {
4297 shsurf->surface->output = shsurf->output;
4298 shsurf->view->output = shsurf->output;
4302 switch (shsurf->type) {
4303 /* XXX: xwayland's using the same fields for transient type */
4304 case SHELL_SURFACE_XWAYLAND:
4305 case SHELL_SURFACE_TRANSIENT:
4306 if (shsurf->transient.flags ==
4307 WL_SHELL_SURFACE_TRANSIENT_INACTIVE)
4309 case SHELL_SURFACE_TOPLEVEL:
4310 case SHELL_SURFACE_FULLSCREEN:
4311 case SHELL_SURFACE_MAXIMIZED:
4312 if (!shell->locked) {
4313 wl_list_for_each(seat, &compositor->seat_list, link)
4314 activate(shell, shsurf->surface, seat);
4321 if (shsurf->type == SHELL_SURFACE_TOPLEVEL)
4323 switch (shell->win_animation_type) {
4324 case ANIMATION_FADE:
4325 weston_fade_run(shsurf->view, 0.0, 1.0, 300.0, NULL, NULL);
4327 case ANIMATION_ZOOM:
4328 weston_zoom_run(shsurf->view, 0.5, 1.0, NULL, NULL);
4337 configure(struct desktop_shell *shell, struct weston_surface *surface,
4338 float x, float y, int32_t width, int32_t height)
4340 enum shell_surface_type surface_type = SHELL_SURFACE_NONE;
4341 struct shell_surface *shsurf;
4342 struct weston_view *view;
4343 int32_t surf_x, surf_y;
4345 shsurf = get_shell_surface(surface);
4347 surface_type = shsurf->type;
4350 * This should probably be changed to be more shell_surface
4353 wl_list_for_each(view, &surface->views, surface_link)
4354 weston_view_configure(view, x, y, width, height);
4356 switch (surface_type) {
4357 case SHELL_SURFACE_FULLSCREEN:
4358 shell_stack_fullscreen(shsurf);
4359 shell_configure_fullscreen(shsurf);
4361 case SHELL_SURFACE_MAXIMIZED:
4362 /* setting x, y and using configure to change that geometry */
4363 surface_subsurfaces_boundingbox(shsurf->surface, &surf_x, &surf_y,
4365 shsurf->view->geometry.x = shsurf->output->x - surf_x;
4366 shsurf->view->geometry.y = shsurf->output->y +
4367 get_output_panel_height(shell,shsurf->output) - surf_y;
4369 case SHELL_SURFACE_TOPLEVEL:
4375 /* XXX: would a fullscreen surface need the same handling? */
4376 if (surface->output) {
4377 wl_list_for_each(view, &surface->views, surface_link)
4378 weston_view_update_transform(view);
4380 if (surface_type == SHELL_SURFACE_MAXIMIZED)
4381 surface->output = shsurf->output;
4386 shell_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy, int32_t width, int32_t height)
4388 struct shell_surface *shsurf = get_shell_surface(es);
4389 struct desktop_shell *shell = shsurf->shell;
4391 int type_changed = 0;
4393 if (!weston_surface_is_mapped(es) &&
4394 !wl_list_empty(&shsurf->popup.grab_link)) {
4395 remove_popup_grab(shsurf);
4401 if (shsurf->next_type != SHELL_SURFACE_NONE &&
4402 shsurf->type != shsurf->next_type) {
4403 set_surface_type(shsurf);
4407 if (!weston_surface_is_mapped(es)) {
4408 map(shell, shsurf, width, height, sx, sy);
4409 } else if (type_changed || sx != 0 || sy != 0 ||
4410 shsurf->view->geometry.width != width ||
4411 shsurf->view->geometry.height != height) {
4412 float from_x, from_y;
4415 weston_view_to_global_float(shsurf->view, 0, 0, &from_x, &from_y);
4416 weston_view_to_global_float(shsurf->view, sx, sy, &to_x, &to_y);
4417 configure(shell, es,
4418 shsurf->view->geometry.x + to_x - from_x,
4419 shsurf->view->geometry.y + to_y - from_y,
4424 static void launch_desktop_shell_process(void *data);
4427 desktop_shell_sigchld(struct weston_process *process, int status)
4430 struct desktop_shell *shell =
4431 container_of(process, struct desktop_shell, child.process);
4433 shell->child.process.pid = 0;
4434 shell->child.client = NULL; /* already destroyed by wayland */
4436 /* if desktop-shell dies more than 5 times in 30 seconds, give up */
4437 time = weston_compositor_get_time();
4438 if (time - shell->child.deathstamp > 30000) {
4439 shell->child.deathstamp = time;
4440 shell->child.deathcount = 0;
4443 shell->child.deathcount++;
4444 if (shell->child.deathcount > 5) {
4445 weston_log("%s died, giving up.\n", shell->client);
4449 weston_log("%s died, respawning...\n", shell->client);
4450 launch_desktop_shell_process(shell);
4451 shell_fade_startup(shell);
4455 launch_desktop_shell_process(void *data)
4457 struct desktop_shell *shell = data;
4459 shell->child.client = weston_client_launch(shell->compositor,
4460 &shell->child.process,
4462 desktop_shell_sigchld);
4464 if (!shell->child.client)
4465 weston_log("not able to start %s\n", shell->client);
4469 bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
4471 struct desktop_shell *shell = data;
4472 struct wl_resource *resource;
4474 resource = wl_resource_create(client, &wl_shell_interface, 1, id);
4476 wl_resource_set_implementation(resource, &shell_implementation,
4481 unbind_desktop_shell(struct wl_resource *resource)
4483 struct desktop_shell *shell = wl_resource_get_user_data(resource);
4486 resume_desktop(shell);
4488 shell->child.desktop_shell = NULL;
4489 shell->prepare_event_sent = false;
4493 bind_desktop_shell(struct wl_client *client,
4494 void *data, uint32_t version, uint32_t id)
4496 struct desktop_shell *shell = data;
4497 struct wl_resource *resource;
4499 resource = wl_resource_create(client, &desktop_shell_interface,
4500 MIN(version, 2), id);
4502 if (client == shell->child.client) {
4503 wl_resource_set_implementation(resource,
4504 &desktop_shell_implementation,
4505 shell, unbind_desktop_shell);
4506 shell->child.desktop_shell = resource;
4509 shell_fade_startup(shell);
4514 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
4515 "permission to bind desktop_shell denied");
4516 wl_resource_destroy(resource);
4520 screensaver_configure(struct weston_surface *surface, int32_t sx, int32_t sy, int32_t width, int32_t height)
4522 struct desktop_shell *shell = surface->configure_private;
4523 struct weston_view *view;
4528 /* XXX: starting weston-screensaver beforehand does not work */
4532 view = container_of(surface->views.next, struct weston_view, surface_link);
4533 center_on_output(view, surface->output);
4535 if (wl_list_empty(&view->layer_link)) {
4536 wl_list_insert(shell->lock_layer.view_list.prev,
4538 weston_view_update_transform(view);
4539 wl_event_source_timer_update(shell->screensaver.timer,
4540 shell->screensaver.duration);
4541 shell_fade(shell, FADE_IN);
4546 screensaver_set_surface(struct wl_client *client,
4547 struct wl_resource *resource,
4548 struct wl_resource *surface_resource,
4549 struct wl_resource *output_resource)
4551 struct desktop_shell *shell = wl_resource_get_user_data(resource);
4552 struct weston_surface *surface =
4553 wl_resource_get_user_data(surface_resource);
4554 struct weston_output *output = wl_resource_get_user_data(output_resource);
4555 struct weston_view *view, *next;
4557 /* Make sure we only have one view */
4558 wl_list_for_each_safe(view, next, &surface->views, surface_link)
4559 weston_view_destroy(view);
4560 weston_view_create(surface);
4562 surface->configure = screensaver_configure;
4563 surface->configure_private = shell;
4564 surface->output = output;
4567 static const struct screensaver_interface screensaver_implementation = {
4568 screensaver_set_surface
4572 unbind_screensaver(struct wl_resource *resource)
4574 struct desktop_shell *shell = wl_resource_get_user_data(resource);
4576 shell->screensaver.binding = NULL;
4580 bind_screensaver(struct wl_client *client,
4581 void *data, uint32_t version, uint32_t id)
4583 struct desktop_shell *shell = data;
4584 struct wl_resource *resource;
4586 resource = wl_resource_create(client, &screensaver_interface, 1, id);
4588 if (shell->screensaver.binding == NULL) {
4589 wl_resource_set_implementation(resource,
4590 &screensaver_implementation,
4591 shell, unbind_screensaver);
4592 shell->screensaver.binding = resource;
4596 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
4597 "interface object already bound");
4598 wl_resource_destroy(resource);
4602 input_panel_configure(struct weston_surface *surface, int32_t sx, int32_t sy, int32_t width, int32_t height)
4604 struct input_panel_surface *ip_surface = surface->configure_private;
4605 struct desktop_shell *shell = ip_surface->shell;
4607 uint32_t show_surface = 0;
4612 if (!weston_surface_is_mapped(surface)) {
4613 if (!shell->showing_input_panels)
4619 fprintf(stderr, "%s panel: %d, output: %p\n", __FUNCTION__, ip_surface->panel, ip_surface->output);
4621 if (ip_surface->panel) {
4622 x = get_default_view(shell->text_input.surface)->geometry.x + shell->text_input.cursor_rectangle.x2;
4623 y = get_default_view(shell->text_input.surface)->geometry.y + shell->text_input.cursor_rectangle.y2;
4625 x = ip_surface->output->x + (ip_surface->output->width - width) / 2;
4626 y = ip_surface->output->y + ip_surface->output->height - height;
4629 weston_view_configure(ip_surface->view, x, y, width, height);
4632 wl_list_insert(&shell->input_panel_layer.view_list,
4633 &ip_surface->view->layer_link);
4634 weston_view_update_transform(ip_surface->view);
4635 weston_surface_damage(surface);
4636 weston_slide_run(ip_surface->view, ip_surface->view->geometry.height, 0, NULL, NULL);
4641 destroy_input_panel_surface(struct input_panel_surface *input_panel_surface)
4643 wl_signal_emit(&input_panel_surface->destroy_signal, input_panel_surface);
4645 wl_list_remove(&input_panel_surface->surface_destroy_listener.link);
4646 wl_list_remove(&input_panel_surface->link);
4648 input_panel_surface->surface->configure = NULL;
4649 weston_view_destroy(input_panel_surface->view);
4651 free(input_panel_surface);
4654 static struct input_panel_surface *
4655 get_input_panel_surface(struct weston_surface *surface)
4657 if (surface->configure == input_panel_configure) {
4658 return surface->configure_private;
4665 input_panel_handle_surface_destroy(struct wl_listener *listener, void *data)
4667 struct input_panel_surface *ipsurface = container_of(listener,
4668 struct input_panel_surface,
4669 surface_destroy_listener);
4671 if (ipsurface->resource) {
4672 wl_resource_destroy(ipsurface->resource);
4674 destroy_input_panel_surface(ipsurface);
4678 static struct input_panel_surface *
4679 create_input_panel_surface(struct desktop_shell *shell,
4680 struct weston_surface *surface)
4682 struct input_panel_surface *input_panel_surface;
4684 input_panel_surface = calloc(1, sizeof *input_panel_surface);
4685 if (!input_panel_surface)
4688 surface->configure = input_panel_configure;
4689 surface->configure_private = input_panel_surface;
4691 input_panel_surface->shell = shell;
4693 input_panel_surface->surface = surface;
4694 input_panel_surface->view = weston_view_create(surface);
4696 wl_signal_init(&input_panel_surface->destroy_signal);
4697 input_panel_surface->surface_destroy_listener.notify = input_panel_handle_surface_destroy;
4698 wl_signal_add(&surface->destroy_signal,
4699 &input_panel_surface->surface_destroy_listener);
4701 wl_list_init(&input_panel_surface->link);
4703 return input_panel_surface;
4707 input_panel_surface_set_toplevel(struct wl_client *client,
4708 struct wl_resource *resource,
4709 struct wl_resource *output_resource,
4712 struct input_panel_surface *input_panel_surface =
4713 wl_resource_get_user_data(resource);
4714 struct desktop_shell *shell = input_panel_surface->shell;
4716 wl_list_insert(&shell->input_panel.surfaces,
4717 &input_panel_surface->link);
4719 input_panel_surface->output = wl_resource_get_user_data(output_resource);
4720 input_panel_surface->panel = 0;
4724 input_panel_surface_set_overlay_panel(struct wl_client *client,
4725 struct wl_resource *resource)
4727 struct input_panel_surface *input_panel_surface =
4728 wl_resource_get_user_data(resource);
4729 struct desktop_shell *shell = input_panel_surface->shell;
4731 wl_list_insert(&shell->input_panel.surfaces,
4732 &input_panel_surface->link);
4734 input_panel_surface->panel = 1;
4737 static const struct wl_input_panel_surface_interface input_panel_surface_implementation = {
4738 input_panel_surface_set_toplevel,
4739 input_panel_surface_set_overlay_panel
4743 destroy_input_panel_surface_resource(struct wl_resource *resource)
4745 struct input_panel_surface *ipsurf =
4746 wl_resource_get_user_data(resource);
4748 destroy_input_panel_surface(ipsurf);
4752 input_panel_get_input_panel_surface(struct wl_client *client,
4753 struct wl_resource *resource,
4755 struct wl_resource *surface_resource)
4757 struct weston_surface *surface =
4758 wl_resource_get_user_data(surface_resource);
4759 struct desktop_shell *shell = wl_resource_get_user_data(resource);
4760 struct input_panel_surface *ipsurf;
4762 if (get_input_panel_surface(surface)) {
4763 wl_resource_post_error(surface_resource,
4764 WL_DISPLAY_ERROR_INVALID_OBJECT,
4765 "wl_input_panel::get_input_panel_surface already requested");
4769 ipsurf = create_input_panel_surface(shell, surface);
4771 wl_resource_post_error(surface_resource,
4772 WL_DISPLAY_ERROR_INVALID_OBJECT,
4773 "surface->configure already set");
4778 wl_resource_create(client,
4779 &wl_input_panel_surface_interface, 1, id);
4780 wl_resource_set_implementation(ipsurf->resource,
4781 &input_panel_surface_implementation,
4783 destroy_input_panel_surface_resource);
4786 static const struct wl_input_panel_interface input_panel_implementation = {
4787 input_panel_get_input_panel_surface
4791 unbind_input_panel(struct wl_resource *resource)
4793 struct desktop_shell *shell = wl_resource_get_user_data(resource);
4795 shell->input_panel.binding = NULL;
4799 bind_input_panel(struct wl_client *client,
4800 void *data, uint32_t version, uint32_t id)
4802 struct desktop_shell *shell = data;
4803 struct wl_resource *resource;
4805 resource = wl_resource_create(client,
4806 &wl_input_panel_interface, 1, id);
4808 if (shell->input_panel.binding == NULL) {
4809 wl_resource_set_implementation(resource,
4810 &input_panel_implementation,
4811 shell, unbind_input_panel);
4812 shell->input_panel.binding = resource;
4816 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
4817 "interface object already bound");
4818 wl_resource_destroy(resource);
4822 struct desktop_shell *shell;
4823 struct weston_surface *current;
4824 struct wl_listener listener;
4825 struct weston_keyboard_grab grab;
4829 switcher_next(struct switcher *switcher)
4831 struct weston_view *view;
4832 struct weston_surface *first = NULL, *prev = NULL, *next = NULL;
4833 struct shell_surface *shsurf;
4834 struct workspace *ws = get_current_workspace(switcher->shell);
4836 wl_list_for_each(view, &ws->layer.view_list, layer_link) {
4837 switch (get_shell_surface_type(view->surface)) {
4838 case SHELL_SURFACE_TOPLEVEL:
4839 case SHELL_SURFACE_FULLSCREEN:
4840 case SHELL_SURFACE_MAXIMIZED:
4842 first = view->surface;
4843 if (prev == switcher->current)
4844 next = view->surface;
4845 prev = view->surface;
4847 weston_view_geometry_dirty(view);
4848 weston_surface_damage(view->surface);
4854 if (is_black_surface(view->surface, NULL)) {
4856 weston_view_geometry_dirty(view);
4857 weston_surface_damage(view->surface);
4867 wl_list_remove(&switcher->listener.link);
4868 wl_signal_add(&next->destroy_signal, &switcher->listener);
4870 switcher->current = next;
4871 wl_list_for_each(view, &next->views, surface_link)
4874 shsurf = get_shell_surface(switcher->current);
4875 if (shsurf && shsurf->type ==SHELL_SURFACE_FULLSCREEN)
4876 shsurf->fullscreen.black_view->alpha = 1.0;
4880 switcher_handle_surface_destroy(struct wl_listener *listener, void *data)
4882 struct switcher *switcher =
4883 container_of(listener, struct switcher, listener);
4885 switcher_next(switcher);
4889 switcher_destroy(struct switcher *switcher)
4891 struct weston_view *view;
4892 struct weston_keyboard *keyboard = switcher->grab.keyboard;
4893 struct workspace *ws = get_current_workspace(switcher->shell);
4895 wl_list_for_each(view, &ws->layer.view_list, layer_link) {
4896 if (is_focus_view(view))
4900 weston_surface_damage(view->surface);
4903 if (switcher->current)
4904 activate(switcher->shell, switcher->current,
4905 (struct weston_seat *) keyboard->seat);
4906 wl_list_remove(&switcher->listener.link);
4907 weston_keyboard_end_grab(keyboard);
4908 if (keyboard->input_method_resource)
4909 keyboard->grab = &keyboard->input_method_grab;
4914 switcher_key(struct weston_keyboard_grab *grab,
4915 uint32_t time, uint32_t key, uint32_t state_w)
4917 struct switcher *switcher = container_of(grab, struct switcher, grab);
4918 enum wl_keyboard_key_state state = state_w;
4920 if (key == KEY_TAB && state == WL_KEYBOARD_KEY_STATE_PRESSED)
4921 switcher_next(switcher);
4925 switcher_modifier(struct weston_keyboard_grab *grab, uint32_t serial,
4926 uint32_t mods_depressed, uint32_t mods_latched,
4927 uint32_t mods_locked, uint32_t group)
4929 struct switcher *switcher = container_of(grab, struct switcher, grab);
4930 struct weston_seat *seat = (struct weston_seat *) grab->keyboard->seat;
4932 if ((seat->modifier_state & switcher->shell->binding_modifier) == 0)
4933 switcher_destroy(switcher);
4937 switcher_cancel(struct weston_keyboard_grab *grab)
4939 struct switcher *switcher = container_of(grab, struct switcher, grab);
4941 switcher_destroy(switcher);
4944 static const struct weston_keyboard_grab_interface switcher_grab = {
4951 switcher_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
4954 struct desktop_shell *shell = data;
4955 struct switcher *switcher;
4957 switcher = malloc(sizeof *switcher);
4958 switcher->shell = shell;
4959 switcher->current = NULL;
4960 switcher->listener.notify = switcher_handle_surface_destroy;
4961 wl_list_init(&switcher->listener.link);
4963 restore_all_output_modes(shell->compositor);
4964 lower_fullscreen_layer(switcher->shell);
4965 switcher->grab.interface = &switcher_grab;
4966 weston_keyboard_start_grab(seat->keyboard, &switcher->grab);
4967 weston_keyboard_set_focus(seat->keyboard, NULL);
4968 switcher_next(switcher);
4971 struct exposay_surface {
4972 struct desktop_shell *shell;
4973 struct weston_surface *surface;
4974 struct weston_view *view;
4975 struct wl_list link;
4986 /* The animations only apply a transformation for their own lifetime,
4987 * and don't have an option to indefinitely maintain the
4988 * transformation in a steady state - so, we apply our own once the
4989 * animation has finished. */
4990 struct weston_transform transform;
4993 static void exposay_set_state(struct desktop_shell *shell,
4994 enum exposay_target_state state,
4995 struct weston_seat *seat);
4996 static void exposay_check_state(struct desktop_shell *shell);
4999 exposay_in_flight_inc(struct desktop_shell *shell)
5001 shell->exposay.in_flight++;
5005 exposay_in_flight_dec(struct desktop_shell *shell)
5007 if (--shell->exposay.in_flight > 0)
5010 exposay_check_state(shell);
5014 exposay_animate_in_done(struct weston_view_animation *animation, void *data)
5016 struct exposay_surface *esurface = data;
5018 wl_list_insert(&esurface->view->geometry.transformation_list,
5019 &esurface->transform.link);
5020 weston_matrix_init(&esurface->transform.matrix);
5021 weston_matrix_scale(&esurface->transform.matrix,
5022 esurface->scale, esurface->scale, 1.0f);
5023 weston_matrix_translate(&esurface->transform.matrix,
5024 esurface->x - esurface->view->geometry.x,
5025 esurface->y - esurface->view->geometry.y,
5028 weston_view_geometry_dirty(esurface->view);
5029 weston_compositor_schedule_repaint(esurface->view->surface->compositor);
5031 exposay_in_flight_dec(esurface->shell);
5035 exposay_animate_in(struct exposay_surface *esurface)
5037 exposay_in_flight_inc(esurface->shell);
5039 weston_move_scale_run(esurface->view,
5040 esurface->x - esurface->view->geometry.x,
5041 esurface->y - esurface->view->geometry.y,
5042 1.0, esurface->scale, 0,
5043 exposay_animate_in_done, esurface);
5047 exposay_animate_out_done(struct weston_view_animation *animation, void *data)
5049 struct exposay_surface *esurface = data;
5050 struct desktop_shell *shell = esurface->shell;
5052 wl_list_remove(&esurface->link);
5055 exposay_in_flight_dec(shell);
5059 exposay_animate_out(struct exposay_surface *esurface)
5061 exposay_in_flight_inc(esurface->shell);
5063 /* Remove the static transformation set up by
5064 * exposay_transform_in_done(). */
5065 wl_list_remove(&esurface->transform.link);
5066 weston_view_geometry_dirty(esurface->view);
5068 weston_move_scale_run(esurface->view,
5069 esurface->x - esurface->view->geometry.x,
5070 esurface->y - esurface->view->geometry.y,
5071 1.0, esurface->scale, 1,
5072 exposay_animate_out_done, esurface);
5076 exposay_highlight_surface(struct desktop_shell *shell,
5077 struct exposay_surface *esurface)
5079 struct weston_view *view = NULL;
5082 shell->exposay.row_current = esurface->row;
5083 shell->exposay.column_current = esurface->column;
5084 view = esurface->view;
5087 activate(shell, view->surface, shell->exposay.seat);
5088 shell->exposay.focus_current = view;
5092 exposay_is_animating(struct desktop_shell *shell)
5094 if (shell->exposay.state_cur == EXPOSAY_LAYOUT_INACTIVE ||
5095 shell->exposay.state_cur == EXPOSAY_LAYOUT_OVERVIEW)
5098 return (shell->exposay.in_flight > 0);
5102 exposay_pick(struct desktop_shell *shell, int x, int y)
5104 struct exposay_surface *esurface;
5106 if (exposay_is_animating(shell))
5109 wl_list_for_each(esurface, &shell->exposay.surface_list, link) {
5110 if (x < esurface->x || x > esurface->x + esurface->width)
5112 if (y < esurface->y || y > esurface->y + esurface->height)
5115 exposay_highlight_surface(shell, esurface);
5120 /* Pretty lame layout for now; just tries to make a square. Should take
5121 * aspect ratio into account really. Also needs to be notified of surface
5122 * addition and removal and adjust layout/animate accordingly. */
5123 static enum exposay_layout_state
5124 exposay_layout(struct desktop_shell *shell)
5126 struct workspace *workspace = shell->exposay.workspace;
5127 struct weston_compositor *compositor = shell->compositor;
5128 struct weston_output *output = get_default_output(compositor);
5129 struct weston_view *view;
5130 struct exposay_surface *esurface;
5133 int last_row_removed = 0;
5135 wl_list_init(&shell->exposay.surface_list);
5137 shell->exposay.num_surfaces = 0;
5138 wl_list_for_each(view, &workspace->layer.view_list, layer_link) {
5139 if (!get_shell_surface(view->surface))
5141 shell->exposay.num_surfaces++;
5144 if (shell->exposay.num_surfaces == 0) {
5145 shell->exposay.grid_size = 0;
5146 shell->exposay.hpadding_outer = 0;
5147 shell->exposay.vpadding_outer = 0;
5148 shell->exposay.padding_inner = 0;
5149 shell->exposay.surface_size = 0;
5150 return EXPOSAY_LAYOUT_OVERVIEW;
5153 /* Lay the grid out as square as possible, losing surfaces from the
5154 * bottom row if required. Start with fixed padding of a 10% margin
5155 * around the outside and 80px internal padding between surfaces, and
5156 * maximise the area made available to surfaces after this, but only
5157 * to a maximum of 1/3rd the total output size.
5159 * If we can't make a square grid, add one extra row at the bottom
5160 * which will have a smaller number of columns.
5162 * XXX: Surely there has to be a better way to express this maths,
5165 shell->exposay.grid_size = floor(sqrtf(shell->exposay.num_surfaces));
5166 if (pow(shell->exposay.grid_size, 2) != shell->exposay.num_surfaces)
5167 shell->exposay.grid_size++;
5168 last_row_removed = pow(shell->exposay.grid_size, 2) - shell->exposay.num_surfaces;
5170 shell->exposay.hpadding_outer = (output->width / 10);
5171 shell->exposay.vpadding_outer = (output->height / 10);
5172 shell->exposay.padding_inner = 80;
5174 w = output->width - (shell->exposay.hpadding_outer * 2);
5175 w -= shell->exposay.padding_inner * (shell->exposay.grid_size - 1);
5176 w /= shell->exposay.grid_size;
5178 h = output->height - (shell->exposay.vpadding_outer * 2);
5179 h -= shell->exposay.padding_inner * (shell->exposay.grid_size - 1);
5180 h /= shell->exposay.grid_size;
5182 shell->exposay.surface_size = (w < h) ? w : h;
5183 if (shell->exposay.surface_size > (output->width / 2))
5184 shell->exposay.surface_size = output->width / 2;
5185 if (shell->exposay.surface_size > (output->height / 2))
5186 shell->exposay.surface_size = output->height / 2;
5189 wl_list_for_each(view, &workspace->layer.view_list, layer_link) {
5192 pad = shell->exposay.surface_size + shell->exposay.padding_inner;
5194 if (!get_shell_surface(view->surface))
5197 esurface = malloc(sizeof(*esurface));
5199 exposay_set_state(shell, EXPOSAY_TARGET_CANCEL,
5200 shell->exposay.seat);
5204 wl_list_insert(&shell->exposay.surface_list, &esurface->link);
5205 esurface->shell = shell;
5206 esurface->view = view;
5208 esurface->row = i / shell->exposay.grid_size;
5209 esurface->column = i % shell->exposay.grid_size;
5211 esurface->x = shell->exposay.hpadding_outer;
5212 esurface->x += pad * esurface->column;
5213 esurface->y = shell->exposay.vpadding_outer;
5214 esurface->y += pad * esurface->row;
5216 if (esurface->row == shell->exposay.grid_size - 1)
5217 esurface->x += (shell->exposay.surface_size + shell->exposay.padding_inner) * last_row_removed / 2;
5219 if (view->geometry.width > view->geometry.height)
5220 esurface->scale = shell->exposay.surface_size / (float) view->geometry.width;
5222 esurface->scale = shell->exposay.surface_size / (float) view->geometry.height;
5223 esurface->width = view->geometry.width * esurface->scale;
5224 esurface->height = view->geometry.height * esurface->scale;
5226 if (shell->exposay.focus_current == esurface->view)
5227 exposay_highlight_surface(shell, esurface);
5229 exposay_animate_in(esurface);
5234 weston_compositor_schedule_repaint(shell->compositor);
5236 return EXPOSAY_LAYOUT_ANIMATE_TO_OVERVIEW;
5240 exposay_motion(struct weston_pointer_grab *grab, uint32_t time,
5241 wl_fixed_t x, wl_fixed_t y)
5243 struct desktop_shell *shell =
5244 container_of(grab, struct desktop_shell, exposay.grab_ptr);
5246 weston_pointer_move(grab->pointer, x, y);
5249 wl_fixed_to_int(grab->pointer->x),
5250 wl_fixed_to_int(grab->pointer->y));
5254 exposay_button(struct weston_pointer_grab *grab, uint32_t time, uint32_t button,
5257 struct desktop_shell *shell =
5258 container_of(grab, struct desktop_shell, exposay.grab_ptr);
5259 struct weston_seat *seat = grab->pointer->seat;
5260 enum wl_pointer_button_state state = state_w;
5262 if (button != BTN_LEFT)
5265 /* Store the surface we clicked on, and don't do anything if we end up
5266 * releasing on a different surface. */
5267 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
5268 shell->exposay.clicked = shell->exposay.focus_current;
5272 if (shell->exposay.focus_current == shell->exposay.clicked)
5273 exposay_set_state(shell, EXPOSAY_TARGET_SWITCH, seat);
5275 shell->exposay.clicked = NULL;
5278 static const struct weston_pointer_grab_interface exposay_ptr_grab = {
5285 exposay_maybe_move(struct desktop_shell *shell, int row, int column)
5287 struct exposay_surface *esurface;
5289 wl_list_for_each(esurface, &shell->exposay.surface_list, link) {
5290 if (esurface->row != row || esurface->column != column)
5293 exposay_highlight_surface(shell, esurface);
5301 exposay_key(struct weston_keyboard_grab *grab, uint32_t time, uint32_t key,
5304 struct weston_seat *seat = grab->keyboard->seat;
5305 struct desktop_shell *shell =
5306 container_of(grab, struct desktop_shell, exposay.grab_kbd);
5307 enum wl_keyboard_key_state state = state_w;
5309 if (state != WL_KEYBOARD_KEY_STATE_RELEASED)
5314 exposay_set_state(shell, EXPOSAY_TARGET_CANCEL, seat);
5317 exposay_set_state(shell, EXPOSAY_TARGET_SWITCH, seat);
5320 exposay_maybe_move(shell, shell->exposay.row_current - 1,
5321 shell->exposay.column_current);
5324 /* Special case for trying to move to the bottom row when it
5325 * has fewer items than all the others. */
5326 if (!exposay_maybe_move(shell, shell->exposay.row_current + 1,
5327 shell->exposay.column_current) &&
5328 shell->exposay.row_current < (shell->exposay.grid_size - 1)) {
5329 exposay_maybe_move(shell, shell->exposay.row_current + 1,
5330 (shell->exposay.num_surfaces %
5331 shell->exposay.grid_size) - 1);
5335 exposay_maybe_move(shell, shell->exposay.row_current,
5336 shell->exposay.column_current - 1);
5339 exposay_maybe_move(shell, shell->exposay.row_current,
5340 shell->exposay.column_current + 1);
5343 /* Try to move right, then down (and to the leftmost column),
5344 * then if all else fails, to the top left. */
5345 if (!exposay_maybe_move(shell, shell->exposay.row_current,
5346 shell->exposay.column_current + 1) &&
5347 !exposay_maybe_move(shell, shell->exposay.row_current + 1, 0))
5348 exposay_maybe_move(shell, 0, 0);
5356 exposay_modifier(struct weston_keyboard_grab *grab, uint32_t serial,
5357 uint32_t mods_depressed, uint32_t mods_latched,
5358 uint32_t mods_locked, uint32_t group)
5363 exposay_cancel(struct weston_keyboard_grab *grab)
5365 struct desktop_shell *shell =
5366 container_of(grab, struct desktop_shell, exposay.grab_kbd);
5368 exposay_set_state(shell, EXPOSAY_TARGET_CANCEL, shell->exposay.seat);
5371 static const struct weston_keyboard_grab_interface exposay_kbd_grab = {
5378 * Called when the transition from overview -> inactive has completed.
5380 static enum exposay_layout_state
5381 exposay_set_inactive(struct desktop_shell *shell)
5383 struct weston_seat *seat = shell->exposay.seat;
5385 weston_keyboard_end_grab(seat->keyboard);
5386 weston_pointer_end_grab(seat->pointer);
5387 if (seat->keyboard->input_method_resource)
5388 seat->keyboard->grab = &seat->keyboard->input_method_grab;
5390 return EXPOSAY_LAYOUT_INACTIVE;
5394 * Begins the transition from overview to inactive. */
5395 static enum exposay_layout_state
5396 exposay_transition_inactive(struct desktop_shell *shell, int switch_focus)
5398 struct exposay_surface *esurface;
5400 /* Call activate() before we start the animations to avoid
5401 * animating back the old state and then immediately transitioning
5403 if (switch_focus && shell->exposay.focus_current)
5404 activate(shell, shell->exposay.focus_current->surface,
5405 shell->exposay.seat);
5406 else if (shell->exposay.focus_prev)
5407 activate(shell, shell->exposay.focus_prev->surface,
5408 shell->exposay.seat);
5410 wl_list_for_each(esurface, &shell->exposay.surface_list, link)
5411 exposay_animate_out(esurface);
5412 weston_compositor_schedule_repaint(shell->compositor);
5414 return EXPOSAY_LAYOUT_ANIMATE_TO_INACTIVE;
5417 static enum exposay_layout_state
5418 exposay_transition_active(struct desktop_shell *shell)
5420 struct weston_seat *seat = shell->exposay.seat;
5422 shell->exposay.workspace = get_current_workspace(shell);
5423 shell->exposay.focus_prev = get_default_view (seat->keyboard->focus);
5424 shell->exposay.focus_current = get_default_view (seat->keyboard->focus);
5425 shell->exposay.clicked = NULL;
5426 wl_list_init(&shell->exposay.surface_list);
5428 lower_fullscreen_layer(shell);
5429 shell->exposay.grab_kbd.interface = &exposay_kbd_grab;
5430 weston_keyboard_start_grab(seat->keyboard,
5431 &shell->exposay.grab_kbd);
5432 weston_keyboard_set_focus(seat->keyboard, NULL);
5434 shell->exposay.grab_ptr.interface = &exposay_ptr_grab;
5435 weston_pointer_start_grab(seat->pointer,
5436 &shell->exposay.grab_ptr);
5437 weston_pointer_set_focus(seat->pointer, NULL,
5438 seat->pointer->x, seat->pointer->y);
5440 return exposay_layout(shell);
5444 exposay_check_state(struct desktop_shell *shell)
5446 enum exposay_layout_state state_new = shell->exposay.state_cur;
5449 /* Don't do anything whilst animations are running, just store up
5450 * target state changes and only act on them when the animations have
5452 if (exposay_is_animating(shell))
5455 switch (shell->exposay.state_target) {
5456 case EXPOSAY_TARGET_OVERVIEW:
5457 switch (shell->exposay.state_cur) {
5458 case EXPOSAY_LAYOUT_OVERVIEW:
5460 case EXPOSAY_LAYOUT_ANIMATE_TO_OVERVIEW:
5461 state_new = EXPOSAY_LAYOUT_OVERVIEW;
5464 state_new = exposay_transition_active(shell);
5469 case EXPOSAY_TARGET_SWITCH:
5470 do_switch = 1; /* fallthrough */
5471 case EXPOSAY_TARGET_CANCEL:
5472 switch (shell->exposay.state_cur) {
5473 case EXPOSAY_LAYOUT_INACTIVE:
5475 case EXPOSAY_LAYOUT_ANIMATE_TO_INACTIVE:
5476 state_new = exposay_set_inactive(shell);
5479 state_new = exposay_transition_inactive(shell, do_switch);
5487 shell->exposay.state_cur = state_new;
5491 exposay_set_state(struct desktop_shell *shell, enum exposay_target_state state,
5492 struct weston_seat *seat)
5494 shell->exposay.state_target = state;
5495 shell->exposay.seat = seat;
5496 exposay_check_state(shell);
5500 exposay_binding(struct weston_seat *seat, enum weston_keyboard_modifier modifier,
5503 struct desktop_shell *shell = data;
5505 if (shell->exposay.state_target == EXPOSAY_TARGET_OVERVIEW)
5506 exposay_set_state(shell, EXPOSAY_TARGET_CANCEL, seat);
5508 exposay_set_state(shell, EXPOSAY_TARGET_OVERVIEW, seat);
5512 backlight_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
5515 struct weston_compositor *compositor = data;
5516 struct weston_output *output;
5517 long backlight_new = 0;
5519 /* TODO: we're limiting to simple use cases, where we assume just
5520 * control on the primary display. We'd have to extend later if we
5521 * ever get support for setting backlights on random desktop LCD
5523 output = get_default_output(compositor);
5527 if (!output->set_backlight)
5530 if (key == KEY_F9 || key == KEY_BRIGHTNESSDOWN)
5531 backlight_new = output->backlight_current - 25;
5532 else if (key == KEY_F10 || key == KEY_BRIGHTNESSUP)
5533 backlight_new = output->backlight_current + 25;
5535 if (backlight_new < 5)
5537 if (backlight_new > 255)
5538 backlight_new = 255;
5540 output->backlight_current = backlight_new;
5541 output->set_backlight(output, output->backlight_current);
5544 struct debug_binding_grab {
5545 struct weston_keyboard_grab grab;
5546 struct weston_seat *seat;
5548 int key_released[2];
5552 debug_binding_key(struct weston_keyboard_grab *grab, uint32_t time,
5553 uint32_t key, uint32_t state)
5555 struct debug_binding_grab *db = (struct debug_binding_grab *) grab;
5556 struct weston_compositor *ec = db->seat->compositor;
5557 struct wl_display *display = ec->wl_display;
5558 struct wl_resource *resource;
5560 int send = 0, terminate = 0;
5561 int check_binding = 1;
5563 struct wl_list *resource_list;
5565 if (state == WL_KEYBOARD_KEY_STATE_RELEASED) {
5566 /* Do not run bindings on key releases */
5569 for (i = 0; i < 2; i++)
5570 if (key == db->key[i])
5571 db->key_released[i] = 1;
5573 if (db->key_released[0] && db->key_released[1]) {
5574 /* All key releases been swalled so end the grab */
5576 } else if (key != db->key[0] && key != db->key[1]) {
5577 /* Should not swallow release of other keys */
5580 } else if (key == db->key[0] && !db->key_released[0]) {
5581 /* Do not check bindings for the first press of the binding
5582 * key. This allows it to be used as a debug shortcut.
5583 * We still need to swallow this event. */
5585 } else if (db->key[1]) {
5586 /* If we already ran a binding don't process another one since
5587 * we can't keep track of all the binding keys that were
5588 * pressed in order to swallow the release events. */
5593 if (check_binding) {
5594 if (weston_compositor_run_debug_binding(ec, db->seat, time,
5596 /* We ran a binding so swallow the press and keep the
5597 * grab to swallow the released too. */
5602 /* Terminate the grab since the key pressed is not a
5603 * debug binding key. */
5610 serial = wl_display_next_serial(display);
5611 resource_list = &grab->keyboard->focus_resource_list;
5612 wl_resource_for_each(resource, resource_list) {
5613 wl_keyboard_send_key(resource, serial, time, key, state);
5618 weston_keyboard_end_grab(grab->keyboard);
5619 if (grab->keyboard->input_method_resource)
5620 grab->keyboard->grab = &grab->keyboard->input_method_grab;
5626 debug_binding_modifiers(struct weston_keyboard_grab *grab, uint32_t serial,
5627 uint32_t mods_depressed, uint32_t mods_latched,
5628 uint32_t mods_locked, uint32_t group)
5630 struct wl_resource *resource;
5631 struct wl_list *resource_list;
5633 resource_list = &grab->keyboard->focus_resource_list;
5635 wl_resource_for_each(resource, resource_list) {
5636 wl_keyboard_send_modifiers(resource, serial, mods_depressed,
5637 mods_latched, mods_locked, group);
5642 debug_binding_cancel(struct weston_keyboard_grab *grab)
5644 struct debug_binding_grab *db = (struct debug_binding_grab *) grab;
5646 weston_keyboard_end_grab(grab->keyboard);
5650 struct weston_keyboard_grab_interface debug_binding_keyboard_grab = {
5652 debug_binding_modifiers,
5653 debug_binding_cancel,
5657 debug_binding(struct weston_seat *seat, uint32_t time, uint32_t key, void *data)
5659 struct debug_binding_grab *grab;
5661 grab = calloc(1, sizeof *grab);
5665 grab->seat = (struct weston_seat *) seat;
5667 grab->grab.interface = &debug_binding_keyboard_grab;
5668 weston_keyboard_start_grab(seat->keyboard, &grab->grab);
5672 force_kill_binding(struct weston_seat *seat, uint32_t time, uint32_t key,
5675 struct weston_surface *focus_surface;
5676 struct wl_client *client;
5677 struct desktop_shell *shell = data;
5678 struct weston_compositor *compositor = shell->compositor;
5681 focus_surface = seat->keyboard->focus;
5685 wl_signal_emit(&compositor->kill_signal, focus_surface);
5687 client = wl_resource_get_client(focus_surface->resource);
5688 wl_client_get_credentials(client, &pid, NULL, NULL);
5690 /* Skip clients that we launched ourselves (the credentials of
5691 * the socketpair is ours) */
5692 if (pid == getpid())
5699 workspace_up_binding(struct weston_seat *seat, uint32_t time,
5700 uint32_t key, void *data)
5702 struct desktop_shell *shell = data;
5703 unsigned int new_index = shell->workspaces.current;
5710 change_workspace(shell, new_index);
5714 workspace_down_binding(struct weston_seat *seat, uint32_t time,
5715 uint32_t key, void *data)
5717 struct desktop_shell *shell = data;
5718 unsigned int new_index = shell->workspaces.current;
5722 if (new_index < shell->workspaces.num - 1)
5725 change_workspace(shell, new_index);
5729 workspace_f_binding(struct weston_seat *seat, uint32_t time,
5730 uint32_t key, void *data)
5732 struct desktop_shell *shell = data;
5733 unsigned int new_index;
5737 new_index = key - KEY_F1;
5738 if (new_index >= shell->workspaces.num)
5739 new_index = shell->workspaces.num - 1;
5741 change_workspace(shell, new_index);
5745 workspace_move_surface_up_binding(struct weston_seat *seat, uint32_t time,
5746 uint32_t key, void *data)
5748 struct desktop_shell *shell = data;
5749 unsigned int new_index = shell->workspaces.current;
5757 take_surface_to_workspace_by_seat(shell, seat, new_index);
5761 workspace_move_surface_down_binding(struct weston_seat *seat, uint32_t time,
5762 uint32_t key, void *data)
5764 struct desktop_shell *shell = data;
5765 unsigned int new_index = shell->workspaces.current;
5770 if (new_index < shell->workspaces.num - 1)
5773 take_surface_to_workspace_by_seat(shell, seat, new_index);
5777 handle_output_destroy(struct wl_listener *listener, void *data)
5779 struct shell_output *output_listener =
5780 container_of(listener, struct shell_output, destroy_listener);
5782 wl_list_remove(&output_listener->destroy_listener.link);
5783 wl_list_remove(&output_listener->link);
5784 free(output_listener);
5788 create_shell_output(struct desktop_shell *shell,
5789 struct weston_output *output)
5791 struct shell_output *shell_output;
5793 shell_output = zalloc(sizeof *shell_output);
5794 if (shell_output == NULL)
5797 shell_output->output = output;
5798 shell_output->shell = shell;
5799 shell_output->destroy_listener.notify = handle_output_destroy;
5800 wl_signal_add(&output->destroy_signal,
5801 &shell_output->destroy_listener);
5802 wl_list_insert(shell->output_list.prev, &shell_output->link);
5806 handle_output_create(struct wl_listener *listener, void *data)
5808 struct desktop_shell *shell =
5809 container_of(listener, struct desktop_shell, output_create_listener);
5810 struct weston_output *output = (struct weston_output *)data;
5812 create_shell_output(shell, output);
5816 setup_output_destroy_handler(struct weston_compositor *ec,
5817 struct desktop_shell *shell)
5819 struct weston_output *output;
5821 wl_list_init(&shell->output_list);
5822 wl_list_for_each(output, &ec->output_list, link)
5823 create_shell_output(shell, output);
5825 shell->output_create_listener.notify = handle_output_create;
5826 wl_signal_add(&ec->output_created_signal,
5827 &shell->output_create_listener);
5831 shell_destroy(struct wl_listener *listener, void *data)
5833 struct desktop_shell *shell =
5834 container_of(listener, struct desktop_shell, destroy_listener);
5835 struct workspace **ws;
5836 struct shell_output *shell_output, *tmp;
5838 if (shell->child.client)
5839 wl_client_destroy(shell->child.client);
5841 wl_list_remove(&shell->idle_listener.link);
5842 wl_list_remove(&shell->wake_listener.link);
5843 wl_list_remove(&shell->show_input_panel_listener.link);
5844 wl_list_remove(&shell->hide_input_panel_listener.link);
5846 wl_list_for_each_safe(shell_output, tmp, &shell->output_list, link) {
5847 wl_list_remove(&shell_output->destroy_listener.link);
5848 wl_list_remove(&shell_output->link);
5852 wl_list_remove(&shell->output_create_listener.link);
5854 wl_array_for_each(ws, &shell->workspaces.array)
5855 workspace_destroy(*ws);
5856 wl_array_release(&shell->workspaces.array);
5858 free(shell->screensaver.path);
5859 free(shell->client);
5864 shell_add_bindings(struct weston_compositor *ec, struct desktop_shell *shell)
5867 int i, num_workspace_bindings;
5869 /* fixed bindings */
5870 weston_compositor_add_key_binding(ec, KEY_BACKSPACE,
5871 MODIFIER_CTRL | MODIFIER_ALT,
5872 terminate_binding, ec);
5873 weston_compositor_add_key_binding(ec, KEY_TAB,
5875 alt_tab_binding, shell);
5876 weston_compositor_add_button_binding(ec, BTN_LEFT, 0,
5877 click_to_activate_binding,
5879 weston_compositor_add_touch_binding(ec, 0,
5880 touch_to_activate_binding,
5882 weston_compositor_add_axis_binding(ec, WL_POINTER_AXIS_VERTICAL_SCROLL,
5883 MODIFIER_SUPER | MODIFIER_ALT,
5884 surface_opacity_binding, NULL);
5885 weston_compositor_add_axis_binding(ec, WL_POINTER_AXIS_VERTICAL_SCROLL,
5886 MODIFIER_SUPER, zoom_axis_binding,
5889 /* configurable bindings */
5890 mod = shell->binding_modifier;
5891 weston_compositor_add_key_binding(ec, KEY_PAGEUP, mod,
5892 zoom_key_binding, NULL);
5893 weston_compositor_add_key_binding(ec, KEY_PAGEDOWN, mod,
5894 zoom_key_binding, NULL);
5895 weston_compositor_add_button_binding(ec, BTN_LEFT, mod, move_binding,
5897 weston_compositor_add_touch_binding(ec, mod, touch_move_binding, shell);
5898 weston_compositor_add_button_binding(ec, BTN_MIDDLE, mod,
5899 resize_binding, shell);
5901 if (ec->capabilities & WESTON_CAP_ROTATION_ANY)
5902 weston_compositor_add_button_binding(ec, BTN_RIGHT, mod,
5903 rotate_binding, NULL);
5905 weston_compositor_add_key_binding(ec, KEY_TAB, mod, switcher_binding,
5907 weston_compositor_add_key_binding(ec, KEY_F9, mod, backlight_binding,
5909 weston_compositor_add_key_binding(ec, KEY_BRIGHTNESSDOWN, 0,
5910 backlight_binding, ec);
5911 weston_compositor_add_key_binding(ec, KEY_F10, mod, backlight_binding,
5913 weston_compositor_add_key_binding(ec, KEY_BRIGHTNESSUP, 0,
5914 backlight_binding, ec);
5915 weston_compositor_add_key_binding(ec, KEY_K, mod,
5916 force_kill_binding, shell);
5917 weston_compositor_add_key_binding(ec, KEY_UP, mod,
5918 workspace_up_binding, shell);
5919 weston_compositor_add_key_binding(ec, KEY_DOWN, mod,
5920 workspace_down_binding, shell);
5921 weston_compositor_add_key_binding(ec, KEY_UP, mod | MODIFIER_SHIFT,
5922 workspace_move_surface_up_binding,
5924 weston_compositor_add_key_binding(ec, KEY_DOWN, mod | MODIFIER_SHIFT,
5925 workspace_move_surface_down_binding,
5928 weston_compositor_add_modifier_binding(ec, mod, exposay_binding, shell);
5930 /* Add bindings for mod+F[1-6] for workspace 1 to 6. */
5931 if (shell->workspaces.num > 1) {
5932 num_workspace_bindings = shell->workspaces.num;
5933 if (num_workspace_bindings > 6)
5934 num_workspace_bindings = 6;
5935 for (i = 0; i < num_workspace_bindings; i++)
5936 weston_compositor_add_key_binding(ec, KEY_F1 + i, mod,
5937 workspace_f_binding,
5941 /* Debug bindings */
5942 weston_compositor_add_key_binding(ec, KEY_SPACE, mod | MODIFIER_SHIFT,
5943 debug_binding, shell);
5947 module_init(struct weston_compositor *ec,
5948 int *argc, char *argv[])
5950 struct weston_seat *seat;
5951 struct desktop_shell *shell;
5952 struct workspace **pws;
5954 struct wl_event_loop *loop;
5956 shell = zalloc(sizeof *shell);
5960 shell->compositor = ec;
5962 shell->destroy_listener.notify = shell_destroy;
5963 wl_signal_add(&ec->destroy_signal, &shell->destroy_listener);
5964 shell->idle_listener.notify = idle_handler;
5965 wl_signal_add(&ec->idle_signal, &shell->idle_listener);
5966 shell->wake_listener.notify = wake_handler;
5967 wl_signal_add(&ec->wake_signal, &shell->wake_listener);
5968 shell->show_input_panel_listener.notify = show_input_panels;
5969 wl_signal_add(&ec->show_input_panel_signal, &shell->show_input_panel_listener);
5970 shell->hide_input_panel_listener.notify = hide_input_panels;
5971 wl_signal_add(&ec->hide_input_panel_signal, &shell->hide_input_panel_listener);
5972 shell->update_input_panel_listener.notify = update_input_panels;
5973 wl_signal_add(&ec->update_input_panel_signal, &shell->update_input_panel_listener);
5974 ec->ping_handler = ping_handler;
5975 ec->shell_interface.shell = shell;
5976 ec->shell_interface.create_shell_surface = create_shell_surface;
5977 ec->shell_interface.get_primary_view = get_primary_view;
5978 ec->shell_interface.set_toplevel = set_toplevel;
5979 ec->shell_interface.set_transient = set_transient;
5980 ec->shell_interface.set_fullscreen = set_fullscreen;
5981 ec->shell_interface.set_xwayland = set_xwayland;
5982 ec->shell_interface.move = surface_move;
5983 ec->shell_interface.resize = surface_resize;
5984 ec->shell_interface.set_title = set_title;
5986 wl_list_init(&shell->input_panel.surfaces);
5988 weston_layer_init(&shell->fullscreen_layer, &ec->cursor_layer.link);
5989 weston_layer_init(&shell->panel_layer, &shell->fullscreen_layer.link);
5990 weston_layer_init(&shell->background_layer, &shell->panel_layer.link);
5991 weston_layer_init(&shell->lock_layer, NULL);
5992 weston_layer_init(&shell->input_panel_layer, NULL);
5994 wl_array_init(&shell->workspaces.array);
5995 wl_list_init(&shell->workspaces.client_list);
5997 shell_configuration(shell);
5999 shell->exposay.state_cur = EXPOSAY_LAYOUT_INACTIVE;
6000 shell->exposay.state_target = EXPOSAY_TARGET_CANCEL;
6002 for (i = 0; i < shell->workspaces.num; i++) {
6003 pws = wl_array_add(&shell->workspaces.array, sizeof *pws);
6007 *pws = workspace_create();
6011 activate_workspace(shell, 0);
6013 wl_list_init(&shell->workspaces.anim_sticky_list);
6014 wl_list_init(&shell->workspaces.animation.link);
6015 shell->workspaces.animation.frame = animate_workspace_change_frame;
6017 if (wl_global_create(ec->wl_display, &wl_shell_interface, 1,
6018 shell, bind_shell) == NULL)
6021 if (wl_global_create(ec->wl_display,
6022 &desktop_shell_interface, 2,
6023 shell, bind_desktop_shell) == NULL)
6026 if (wl_global_create(ec->wl_display, &screensaver_interface, 1,
6027 shell, bind_screensaver) == NULL)
6030 if (wl_global_create(ec->wl_display, &wl_input_panel_interface, 1,
6031 shell, bind_input_panel) == NULL)
6034 if (wl_global_create(ec->wl_display, &workspace_manager_interface, 1,
6035 shell, bind_workspace_manager) == NULL)
6038 shell->child.deathstamp = weston_compositor_get_time();
6040 setup_output_destroy_handler(ec, shell);
6042 loop = wl_display_get_event_loop(ec->wl_display);
6043 wl_event_loop_add_idle(loop, launch_desktop_shell_process, shell);
6045 shell->screensaver.timer =
6046 wl_event_loop_add_timer(loop, screensaver_timeout, shell);
6048 wl_list_for_each(seat, &ec->seat_list, link)
6049 create_pointer_focus_listener(seat);
6051 shell_add_bindings(ec, shell);
6053 shell_fade_init(shell);