2 * Copyright © 2010-2012 Intel Corporation
3 * Copyright © 2011-2012 Collabora, Ltd.
5 * Permission to use, copy, modify, distribute, and sell this software and
6 * its documentation for any purpose is hereby granted without fee, provided
7 * that the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of the copyright holders not be used in
10 * advertising or publicity pertaining to distribution of the software
11 * without specific, written prior permission. The copyright holders make
12 * no representations about the suitability of this software for any
13 * purpose. It is provided "as is" without express or implied warranty.
15 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
16 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
20 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
29 #include <linux/input.h>
34 #include <wayland-server.h>
35 #include "compositor.h"
36 #include "desktop-shell-server-protocol.h"
37 #include "../shared/config-parser.h"
46 struct desktop_shell {
47 struct weston_compositor *compositor;
49 struct wl_listener lock_listener;
50 struct wl_listener unlock_listener;
51 struct wl_listener destroy_listener;
53 struct weston_layer fullscreen_layer;
54 struct weston_layer panel_layer;
55 struct weston_layer toplevel_layer;
56 struct weston_layer background_layer;
57 struct weston_layer lock_layer;
60 struct weston_process process;
61 struct wl_client *client;
62 struct wl_resource *desktop_shell;
69 bool prepare_event_sent;
71 struct shell_surface *lock_surface;
72 struct wl_listener lock_surface_listener;
74 struct wl_list backgrounds;
75 struct wl_list panels;
80 struct wl_resource *binding;
81 struct wl_list surfaces;
82 struct weston_process process;
85 uint32_t binding_modifier;
86 enum animation_type win_animation_type;
87 struct weston_surface *debug_repaint_surface;
90 enum shell_surface_type {
94 SHELL_SURFACE_BACKGROUND,
96 SHELL_SURFACE_SCREENSAVER,
98 SHELL_SURFACE_TOPLEVEL,
99 SHELL_SURFACE_TRANSIENT,
100 SHELL_SURFACE_FULLSCREEN,
101 SHELL_SURFACE_MAXIMIZED,
106 struct wl_event_source *source;
110 struct shell_surface {
111 struct wl_resource resource;
113 struct weston_surface *surface;
114 struct wl_listener surface_destroy_listener;
115 struct shell_surface *parent;
116 struct desktop_shell *shell;
118 enum shell_surface_type type;
119 int32_t saved_x, saved_y;
120 bool saved_position_valid;
124 struct weston_transform transform;
125 struct weston_matrix rotation;
129 struct wl_pointer_grab grab;
131 struct weston_transform parent_transform;
133 struct wl_input_device *device;
138 enum wl_shell_surface_fullscreen_method type;
139 struct weston_transform transform; /* matrix from x, y */
141 struct weston_surface *black_surface;
144 struct ping_timer *ping_timer;
147 struct weston_animation current;
151 } unresponsive_animation;
153 struct weston_output *fullscreen_output;
154 struct weston_output *output;
161 struct wl_pointer_grab grab;
162 struct shell_surface *shsurf;
163 struct wl_listener shsurf_destroy_listener;
166 struct weston_move_grab {
167 struct shell_grab base;
172 struct shell_grab base;
173 struct weston_matrix rotation;
180 static struct shell_surface *
181 get_shell_surface(struct weston_surface *surface);
183 static struct desktop_shell *
184 shell_surface_get_shell(struct shell_surface *shsurf);
187 shell_surface_is_top_fullscreen(struct shell_surface *shsurf)
189 struct desktop_shell *shell;
190 struct weston_surface *top_fs_es;
192 shell = shell_surface_get_shell(shsurf);
194 if (wl_list_empty(&shell->fullscreen_layer.surface_list))
197 top_fs_es = container_of(shell->fullscreen_layer.surface_list.next,
198 struct weston_surface,
200 return (shsurf == get_shell_surface(top_fs_es));
204 destroy_shell_grab_shsurf(struct wl_listener *listener, void *data)
206 struct shell_grab *grab;
208 grab = container_of(listener, struct shell_grab,
209 shsurf_destroy_listener);
215 shell_grab_init(struct shell_grab *grab,
216 const struct wl_pointer_grab_interface *interface,
217 struct shell_surface *shsurf)
219 grab->grab.interface = interface;
220 grab->shsurf = shsurf;
221 grab->shsurf_destroy_listener.notify = destroy_shell_grab_shsurf;
222 wl_signal_add(&shsurf->resource.destroy_signal,
223 &grab->shsurf_destroy_listener);
228 shell_grab_finish(struct shell_grab *grab)
230 wl_list_remove(&grab->shsurf_destroy_listener.link);
234 center_on_output(struct weston_surface *surface,
235 struct weston_output *output);
238 get_modifier(char *modifier)
241 return MODIFIER_SUPER;
243 if (!strcmp("ctrl", modifier))
244 return MODIFIER_CTRL;
245 else if (!strcmp("alt", modifier))
247 else if (!strcmp("super", modifier))
248 return MODIFIER_SUPER;
250 return MODIFIER_SUPER;
253 static enum animation_type
254 get_animation_type(char *animation)
257 return ANIMATION_NONE;
259 if (!strcmp("zoom", animation))
260 return ANIMATION_ZOOM;
261 else if (!strcmp("fade", animation))
262 return ANIMATION_FADE;
264 return ANIMATION_NONE;
268 shell_configuration(struct desktop_shell *shell)
273 char *modifier = NULL;
274 char *win_animation = NULL;
276 struct config_key shell_keys[] = {
277 { "binding-modifier", CONFIG_KEY_STRING, &modifier },
278 { "animation", CONFIG_KEY_STRING, &win_animation},
281 struct config_key saver_keys[] = {
282 { "path", CONFIG_KEY_STRING, &path },
283 { "duration", CONFIG_KEY_INTEGER, &duration },
286 struct config_section cs[] = {
287 { "shell", shell_keys, ARRAY_LENGTH(shell_keys), NULL },
288 { "screensaver", saver_keys, ARRAY_LENGTH(saver_keys), NULL },
291 config_file = config_file_path("weston.ini");
292 parse_config_file(config_file, cs, ARRAY_LENGTH(cs), shell);
295 shell->screensaver.path = path;
296 shell->screensaver.duration = duration;
297 shell->binding_modifier = get_modifier(modifier);
298 shell->win_animation_type = get_animation_type(win_animation);
302 noop_grab_focus(struct wl_pointer_grab *grab,
303 struct wl_surface *surface, int32_t x, int32_t y)
309 move_grab_motion(struct wl_pointer_grab *grab,
310 uint32_t time, int32_t x, int32_t y)
312 struct weston_move_grab *move = (struct weston_move_grab *) grab;
313 struct wl_input_device *device = grab->input_device;
314 struct shell_surface *shsurf = move->base.shsurf;
315 struct weston_surface *es;
320 es = shsurf->surface;
322 weston_surface_configure(es,
323 device->x + move->dx,
324 device->y + move->dy,
325 es->geometry.width, es->geometry.height);
329 move_grab_button(struct wl_pointer_grab *grab,
330 uint32_t time, uint32_t button, int32_t state)
332 struct shell_grab *shell_grab = container_of(grab, struct shell_grab,
334 struct wl_input_device *device = grab->input_device;
336 if (device->button_count == 0 && state == 0) {
337 shell_grab_finish(shell_grab);
338 wl_input_device_end_pointer_grab(device);
343 static const struct wl_pointer_grab_interface move_grab_interface = {
350 unresponsive_surface_fade(struct shell_surface *shsurf, bool reverse)
352 shsurf->unresponsive_animation.fading_in = reverse ? 0 : 1;
354 if(!shsurf->unresponsive_animation.exists) {
355 wl_list_insert(&shsurf->surface->compositor->animation_list,
356 &shsurf->unresponsive_animation.current.link);
357 shsurf->unresponsive_animation.exists = 1;
358 shsurf->unresponsive_animation.timestamp = weston_compositor_get_time();
359 weston_surface_damage(shsurf->surface);
364 unresponsive_fade_frame(struct weston_animation *animation,
365 struct weston_output *output, uint32_t msecs)
367 struct shell_surface *shsurf =
368 container_of(animation, struct shell_surface, unresponsive_animation.current);
369 struct weston_surface *surface = shsurf->surface;
370 unsigned int step = 8;
372 if (!surface || !shsurf)
375 if (shsurf->unresponsive_animation.fading_in) {
376 while (step < msecs - shsurf->unresponsive_animation.timestamp) {
377 if (surface->saturation > 1)
378 surface->saturation -= 5;
379 if (surface->brightness > 200)
380 surface->brightness--;
382 shsurf->unresponsive_animation.timestamp += step;
385 if (surface->saturation <= 1 && surface->brightness <= 200) {
386 wl_list_remove(&shsurf->unresponsive_animation.current.link);
387 shsurf->unresponsive_animation.exists = 0;
391 while (step < msecs - shsurf->unresponsive_animation.timestamp) {
392 if (surface->saturation < 255)
393 surface->saturation += 5;
394 if (surface->brightness < 255)
395 surface->brightness++;
397 shsurf->unresponsive_animation.timestamp += step;
400 if (surface->saturation >= 255 && surface->brightness >= 255) {
401 surface->saturation = surface->brightness = 255;
402 wl_list_remove(&shsurf->unresponsive_animation.current.link);
403 shsurf->unresponsive_animation.exists = 0;
407 surface->geometry.dirty = 1;
408 weston_surface_damage(surface);
412 ping_timer_destroy(struct shell_surface *shsurf)
414 if (!shsurf || !shsurf->ping_timer)
417 if (shsurf->ping_timer->source)
418 wl_event_source_remove(shsurf->ping_timer->source);
420 free(shsurf->ping_timer);
421 shsurf->ping_timer = NULL;
425 ping_timeout_handler(void *data)
427 struct shell_surface *shsurf = data;
429 /* Client is not responding */
430 shsurf->unresponsive = 1;
431 unresponsive_surface_fade(shsurf, false);
437 ping_handler(struct weston_surface *surface, uint32_t serial)
439 struct shell_surface *shsurf;
440 shsurf = get_shell_surface(surface);
441 struct wl_event_loop *loop;
442 int ping_timeout = 2500;
446 if (!shsurf->resource.client)
449 if (!shsurf->ping_timer) {
450 shsurf->ping_timer = malloc(sizeof *shsurf->ping_timer);
451 if (!shsurf->ping_timer)
454 shsurf->ping_timer->serial = serial;
455 loop = wl_display_get_event_loop(surface->compositor->wl_display);
456 shsurf->ping_timer->source =
457 wl_event_loop_add_timer(loop, ping_timeout_handler, shsurf);
458 wl_event_source_timer_update(shsurf->ping_timer->source, ping_timeout);
460 wl_shell_surface_send_ping(&shsurf->resource, serial);
465 shell_surface_pong(struct wl_client *client, struct wl_resource *resource,
468 struct shell_surface *shsurf = resource->data;
470 if (shsurf->ping_timer->serial == serial) {
471 if (shsurf->unresponsive) {
472 /* Received pong from previously unresponsive client */
473 unresponsive_surface_fade(shsurf, true);
475 shsurf->unresponsive = 0;
476 ping_timer_destroy(shsurf);
481 weston_surface_move(struct weston_surface *es,
482 struct weston_input_device *wd)
484 struct weston_move_grab *move;
485 struct shell_surface *shsurf = get_shell_surface(es);
490 move = malloc(sizeof *move);
494 shell_grab_init(&move->base, &move_grab_interface, shsurf);
496 move->dx = es->geometry.x - wd->input_device.grab_x;
497 move->dy = es->geometry.y - wd->input_device.grab_y;
499 wl_input_device_start_pointer_grab(&wd->input_device,
502 wl_input_device_set_pointer_focus(&wd->input_device, NULL, 0, 0);
508 shell_surface_move(struct wl_client *client, struct wl_resource *resource,
509 struct wl_resource *input_resource, uint32_t serial)
511 struct weston_input_device *wd = input_resource->data;
512 struct shell_surface *shsurf = resource->data;
514 if (wd->input_device.button_count == 0 ||
515 wd->input_device.grab_serial != serial ||
516 wd->input_device.pointer_focus != &shsurf->surface->surface)
519 if (weston_surface_move(shsurf->surface, wd) < 0)
520 wl_resource_post_no_memory(resource);
523 struct weston_resize_grab {
524 struct shell_grab base;
526 int32_t width, height;
530 resize_grab_motion(struct wl_pointer_grab *grab,
531 uint32_t time, int32_t x, int32_t y)
533 struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
534 struct wl_input_device *device = grab->input_device;
535 int32_t width, height;
536 int32_t from_x, from_y;
539 if (!resize->base.shsurf)
542 weston_surface_from_global(resize->base.shsurf->surface,
543 device->grab_x, device->grab_y,
545 weston_surface_from_global(resize->base.shsurf->surface,
546 device->x, device->y, &to_x, &to_y);
548 if (resize->edges & WL_SHELL_SURFACE_RESIZE_LEFT) {
549 width = resize->width + from_x - to_x;
550 } else if (resize->edges & WL_SHELL_SURFACE_RESIZE_RIGHT) {
551 width = resize->width + to_x - from_x;
553 width = resize->width;
556 if (resize->edges & WL_SHELL_SURFACE_RESIZE_TOP) {
557 height = resize->height + from_y - to_y;
558 } else if (resize->edges & WL_SHELL_SURFACE_RESIZE_BOTTOM) {
559 height = resize->height + to_y - from_y;
561 height = resize->height;
564 wl_shell_surface_send_configure(&resize->base.shsurf->resource,
565 resize->edges, width, height);
569 resize_grab_button(struct wl_pointer_grab *grab,
570 uint32_t time, uint32_t button, int32_t state)
572 struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
573 struct wl_input_device *device = grab->input_device;
575 if (device->button_count == 0 && state == 0) {
576 shell_grab_finish(&resize->base);
577 wl_input_device_end_pointer_grab(device);
582 static const struct wl_pointer_grab_interface resize_grab_interface = {
589 weston_surface_resize(struct shell_surface *shsurf,
590 struct weston_input_device *wd, uint32_t edges)
592 struct weston_resize_grab *resize;
594 if (shsurf->type == SHELL_SURFACE_FULLSCREEN)
597 if (edges == 0 || edges > 15 ||
598 (edges & 3) == 3 || (edges & 12) == 12)
601 resize = malloc(sizeof *resize);
605 shell_grab_init(&resize->base, &resize_grab_interface, shsurf);
607 resize->edges = edges;
608 resize->width = shsurf->surface->geometry.width;
609 resize->height = shsurf->surface->geometry.height;
611 wl_input_device_start_pointer_grab(&wd->input_device,
614 wl_input_device_set_pointer_focus(&wd->input_device, NULL, 0, 0);
620 shell_surface_resize(struct wl_client *client, struct wl_resource *resource,
621 struct wl_resource *input_resource, uint32_t serial,
624 struct weston_input_device *wd = input_resource->data;
625 struct shell_surface *shsurf = resource->data;
627 if (shsurf->type == SHELL_SURFACE_FULLSCREEN)
630 if (wd->input_device.button_count == 0 ||
631 wd->input_device.grab_serial != serial ||
632 wd->input_device.pointer_focus != &shsurf->surface->surface)
635 if (weston_surface_resize(shsurf, wd, edges) < 0)
636 wl_resource_post_no_memory(resource);
639 static struct weston_output *
640 get_default_output(struct weston_compositor *compositor)
642 return container_of(compositor->output_list.next,
643 struct weston_output, link);
647 shell_unset_fullscreen(struct shell_surface *shsurf)
649 /* undo all fullscreen things here */
650 if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
651 shell_surface_is_top_fullscreen(shsurf)) {
652 weston_output_switch_mode(shsurf->fullscreen_output,
653 shsurf->fullscreen_output->origin);
655 shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
656 shsurf->fullscreen.framerate = 0;
657 wl_list_remove(&shsurf->fullscreen.transform.link);
658 wl_list_init(&shsurf->fullscreen.transform.link);
659 if (shsurf->fullscreen.black_surface)
660 weston_surface_destroy(shsurf->fullscreen.black_surface);
661 shsurf->fullscreen.black_surface = NULL;
662 shsurf->fullscreen_output = NULL;
663 shsurf->force_configure = 1;
664 weston_surface_set_position(shsurf->surface,
665 shsurf->saved_x, shsurf->saved_y);
669 reset_shell_surface_type(struct shell_surface *surface)
671 switch (surface->type) {
672 case SHELL_SURFACE_FULLSCREEN:
673 shell_unset_fullscreen(surface);
675 case SHELL_SURFACE_MAXIMIZED:
676 surface->output = get_default_output(surface->surface->compositor);
677 weston_surface_set_position(surface->surface,
681 case SHELL_SURFACE_PANEL:
682 case SHELL_SURFACE_BACKGROUND:
683 wl_list_remove(&surface->link);
684 wl_list_init(&surface->link);
686 case SHELL_SURFACE_SCREENSAVER:
687 case SHELL_SURFACE_LOCK:
688 wl_resource_post_error(&surface->resource,
689 WL_DISPLAY_ERROR_INVALID_METHOD,
690 "cannot reassign surface type");
692 case SHELL_SURFACE_NONE:
693 case SHELL_SURFACE_TOPLEVEL:
694 case SHELL_SURFACE_TRANSIENT:
695 case SHELL_SURFACE_POPUP:
699 surface->type = SHELL_SURFACE_NONE;
704 set_toplevel(struct shell_surface *shsurf)
706 if (reset_shell_surface_type(shsurf))
709 shsurf->type = SHELL_SURFACE_TOPLEVEL;
713 shell_surface_set_toplevel(struct wl_client *client,
714 struct wl_resource *resource)
717 struct shell_surface *surface = resource->data;
719 set_toplevel(surface);
723 shell_surface_set_transient(struct wl_client *client,
724 struct wl_resource *resource,
725 struct wl_resource *parent_resource,
726 int x, int y, uint32_t flags)
728 struct shell_surface *shsurf = resource->data;
729 struct weston_surface *es = shsurf->surface;
730 struct shell_surface *pshsurf = parent_resource->data;
731 struct weston_surface *pes = pshsurf->surface;
733 if (reset_shell_surface_type(shsurf))
736 /* assign to parents output */
737 shsurf->output = pes->output;
738 weston_surface_set_position(es, pes->geometry.x + x,
739 pes->geometry.y + y);
741 shsurf->type = SHELL_SURFACE_TRANSIENT;
744 static struct desktop_shell *
745 shell_surface_get_shell(struct shell_surface *shsurf)
747 return shsurf->shell;
751 get_output_panel_height(struct desktop_shell *shell,
752 struct weston_output *output)
754 struct shell_surface *priv;
755 int panel_height = 0;
760 wl_list_for_each(priv, &shell->panels, link) {
761 if (priv->output == output) {
762 panel_height = priv->surface->geometry.height;
770 shell_surface_set_maximized(struct wl_client *client,
771 struct wl_resource *resource,
772 struct wl_resource *output_resource )
774 struct shell_surface *shsurf = resource->data;
775 struct weston_surface *es = shsurf->surface;
776 struct desktop_shell *shell = NULL;
777 uint32_t edges = 0, panel_height = 0;
779 /* get the default output, if the client set it as NULL
780 check whether the ouput is available */
782 shsurf->output = output_resource->data;
784 shsurf->output = get_default_output(es->compositor);
786 if (reset_shell_surface_type(shsurf))
789 shsurf->saved_x = es->geometry.x;
790 shsurf->saved_y = es->geometry.y;
791 shsurf->saved_position_valid = true;
793 shell = shell_surface_get_shell(shsurf);
794 panel_height = get_output_panel_height(shell, es->output);
795 edges = WL_SHELL_SURFACE_RESIZE_TOP|WL_SHELL_SURFACE_RESIZE_LEFT;
797 wl_shell_surface_send_configure(&shsurf->resource, edges,
798 es->output->current->width,
799 es->output->current->height - panel_height);
801 shsurf->type = SHELL_SURFACE_MAXIMIZED;
805 black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy);
807 static struct weston_surface *
808 create_black_surface(struct weston_compositor *ec,
809 struct weston_surface *fs_surface,
810 GLfloat x, GLfloat y, int w, int h)
812 struct weston_surface *surface = NULL;
814 surface = weston_surface_create(ec);
815 if (surface == NULL) {
816 fprintf(stderr, "no memory\n");
820 surface->configure = black_surface_configure;
821 surface->private = fs_surface;
822 weston_surface_configure(surface, x, y, w, h);
823 weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1);
827 /* Create black surface and append it to the associated fullscreen surface.
828 * Handle size dismatch and positioning according to the method. */
830 shell_configure_fullscreen(struct shell_surface *shsurf)
832 struct weston_output *output = shsurf->fullscreen_output;
833 struct weston_surface *surface = shsurf->surface;
834 struct weston_matrix *matrix;
837 center_on_output(surface, output);
839 if (!shsurf->fullscreen.black_surface)
840 shsurf->fullscreen.black_surface =
841 create_black_surface(surface->compositor,
843 output->x, output->y,
844 output->current->width,
845 output->current->height);
847 wl_list_remove(&shsurf->fullscreen.black_surface->layer_link);
848 wl_list_insert(&surface->layer_link,
849 &shsurf->fullscreen.black_surface->layer_link);
850 shsurf->fullscreen.black_surface->output = output;
852 switch (shsurf->fullscreen.type) {
853 case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT:
855 case WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE:
856 matrix = &shsurf->fullscreen.transform.matrix;
857 weston_matrix_init(matrix);
858 scale = (float)output->current->width/(float)surface->geometry.width;
859 weston_matrix_scale(matrix, scale, scale, 1);
860 wl_list_remove(&shsurf->fullscreen.transform.link);
861 wl_list_insert(surface->geometry.transformation_list.prev,
862 &shsurf->fullscreen.transform.link);
863 weston_surface_set_position(surface, output->x, output->y);
865 case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER:
866 if (shell_surface_is_top_fullscreen(shsurf)) {
867 struct weston_mode mode = {0,
868 surface->geometry.width,
869 surface->geometry.height,
870 shsurf->fullscreen.framerate};
872 if (weston_output_switch_mode(output, &mode) == 0) {
873 weston_surface_configure(shsurf->fullscreen.black_surface,
874 output->x, output->y,
875 output->current->width,
876 output->current->height);
877 weston_surface_set_position(surface, output->x, output->y);
882 case WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL:
889 /* make the fullscreen and black surface at the top */
891 shell_stack_fullscreen(struct shell_surface *shsurf)
893 struct weston_output *output = shsurf->fullscreen_output;
894 struct weston_surface *surface = shsurf->surface;
895 struct desktop_shell *shell = shell_surface_get_shell(shsurf);
897 wl_list_remove(&surface->layer_link);
898 wl_list_insert(&shell->fullscreen_layer.surface_list,
899 &surface->layer_link);
900 weston_surface_damage(surface);
902 if (!shsurf->fullscreen.black_surface)
903 shsurf->fullscreen.black_surface =
904 create_black_surface(surface->compositor,
906 output->x, output->y,
907 output->current->width,
908 output->current->height);
910 wl_list_remove(&shsurf->fullscreen.black_surface->layer_link);
911 wl_list_insert(&surface->layer_link,
912 &shsurf->fullscreen.black_surface->layer_link);
913 weston_surface_damage(shsurf->fullscreen.black_surface);
917 shell_map_fullscreen(struct shell_surface *shsurf)
919 shell_stack_fullscreen(shsurf);
920 shell_configure_fullscreen(shsurf);
924 shell_surface_set_fullscreen(struct wl_client *client,
925 struct wl_resource *resource,
928 struct wl_resource *output_resource)
930 struct shell_surface *shsurf = resource->data;
931 struct weston_surface *es = shsurf->surface;
934 shsurf->output = output_resource->data;
936 shsurf->output = get_default_output(es->compositor);
938 if (reset_shell_surface_type(shsurf))
941 shsurf->fullscreen_output = shsurf->output;
942 shsurf->fullscreen.type = method;
943 shsurf->fullscreen.framerate = framerate;
944 shsurf->type = SHELL_SURFACE_FULLSCREEN;
946 shsurf->saved_x = es->geometry.x;
947 shsurf->saved_y = es->geometry.y;
948 shsurf->saved_position_valid = true;
950 if (weston_surface_is_mapped(es))
951 shsurf->force_configure = 1;
953 wl_shell_surface_send_configure(&shsurf->resource, 0,
954 shsurf->output->current->width,
955 shsurf->output->current->height);
959 popup_grab_focus(struct wl_pointer_grab *grab,
960 struct wl_surface *surface, int32_t x, int32_t y)
962 struct wl_input_device *device = grab->input_device;
963 struct shell_surface *priv =
964 container_of(grab, struct shell_surface, popup.grab);
965 struct wl_client *client = priv->surface->surface.resource.client;
967 if (surface && surface->resource.client == client) {
968 wl_input_device_set_pointer_focus(device, surface, x, y);
969 grab->focus = surface;
971 wl_input_device_set_pointer_focus(device, NULL, 0, 0);
977 popup_grab_motion(struct wl_pointer_grab *grab,
978 uint32_t time, int32_t sx, int32_t sy)
980 struct wl_resource *resource;
982 resource = grab->input_device->pointer_focus_resource;
984 wl_input_device_send_motion(resource, time, sx, sy);
988 popup_grab_button(struct wl_pointer_grab *grab,
989 uint32_t time, uint32_t button, int32_t state)
991 struct wl_resource *resource;
992 struct shell_surface *shsurf =
993 container_of(grab, struct shell_surface, popup.grab);
994 struct wl_display *display;
997 resource = grab->input_device->pointer_focus_resource;
999 display = wl_client_get_display(resource->client);
1000 serial = wl_display_get_serial(display);
1001 wl_input_device_send_button(resource, serial,
1002 time, button, state);
1003 } else if (state == 0 &&
1004 (shsurf->popup.initial_up ||
1005 time - shsurf->popup.device->grab_time > 500)) {
1006 wl_shell_surface_send_popup_done(&shsurf->resource);
1007 wl_input_device_end_pointer_grab(grab->input_device);
1008 shsurf->popup.grab.input_device = NULL;
1012 shsurf->popup.initial_up = 1;
1015 static const struct wl_pointer_grab_interface popup_grab_interface = {
1022 shell_map_popup(struct shell_surface *shsurf)
1024 struct wl_input_device *device = shsurf->popup.device;
1025 struct weston_surface *es = shsurf->surface;
1026 struct weston_surface *parent = shsurf->parent->surface;
1028 es->output = parent->output;
1029 shsurf->popup.grab.interface = &popup_grab_interface;
1031 weston_surface_update_transform(parent);
1032 if (parent->transform.enabled) {
1033 shsurf->popup.parent_transform.matrix =
1034 parent->transform.matrix;
1036 /* construct x, y translation matrix */
1037 weston_matrix_init(&shsurf->popup.parent_transform.matrix);
1038 shsurf->popup.parent_transform.matrix.d[12] =
1040 shsurf->popup.parent_transform.matrix.d[13] =
1043 wl_list_insert(es->geometry.transformation_list.prev,
1044 &shsurf->popup.parent_transform.link);
1045 weston_surface_set_position(es, shsurf->popup.x, shsurf->popup.y);
1047 shsurf->popup.initial_up = 0;
1049 /* We don't require the grab to still be active, but if another
1050 * grab has started in the meantime, we end the popup now. */
1051 if (device->grab_serial == shsurf->popup.serial) {
1052 wl_input_device_start_pointer_grab(device,
1053 &shsurf->popup.grab);
1055 wl_shell_surface_send_popup_done(&shsurf->resource);
1060 shell_surface_set_popup(struct wl_client *client,
1061 struct wl_resource *resource,
1062 struct wl_resource *input_device_resource,
1064 struct wl_resource *parent_resource,
1065 int32_t x, int32_t y, uint32_t flags)
1067 struct shell_surface *shsurf = resource->data;
1069 shsurf->type = SHELL_SURFACE_POPUP;
1070 shsurf->parent = parent_resource->data;
1071 shsurf->popup.device = input_device_resource->data;
1072 shsurf->popup.serial = serial;
1073 shsurf->popup.x = x;
1074 shsurf->popup.y = y;
1077 static const struct wl_shell_surface_interface shell_surface_implementation = {
1080 shell_surface_resize,
1081 shell_surface_set_toplevel,
1082 shell_surface_set_transient,
1083 shell_surface_set_fullscreen,
1084 shell_surface_set_popup,
1085 shell_surface_set_maximized
1089 destroy_shell_surface(struct shell_surface *shsurf)
1091 if (shsurf->popup.grab.input_device)
1092 wl_input_device_end_pointer_grab(shsurf->popup.grab.input_device);
1094 if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
1095 shell_surface_is_top_fullscreen(shsurf)) {
1096 weston_output_switch_mode(shsurf->fullscreen_output,
1097 shsurf->fullscreen_output->origin);
1100 if (shsurf->fullscreen.black_surface)
1101 weston_surface_destroy(shsurf->fullscreen.black_surface);
1103 /* As destroy_resource() use wl_list_for_each_safe(),
1104 * we can always remove the listener.
1106 wl_list_remove(&shsurf->surface_destroy_listener.link);
1107 shsurf->surface->configure = NULL;
1108 ping_timer_destroy(shsurf);
1110 wl_list_remove(&shsurf->link);
1115 shell_destroy_shell_surface(struct wl_resource *resource)
1117 struct shell_surface *shsurf = resource->data;
1119 destroy_shell_surface(shsurf);
1123 shell_handle_surface_destroy(struct wl_listener *listener, void *data)
1125 struct shell_surface *shsurf = container_of(listener,
1126 struct shell_surface,
1127 surface_destroy_listener);
1129 /* tricky way to check if resource was in fact created */
1130 if (shsurf->resource.object.implementation != 0)
1131 wl_resource_destroy(&shsurf->resource);
1133 destroy_shell_surface(shsurf);
1136 static struct shell_surface *
1137 get_shell_surface(struct weston_surface *surface)
1139 struct wl_listener *listener;
1141 listener = wl_signal_get(&surface->surface.resource.destroy_signal,
1142 shell_handle_surface_destroy);
1144 return container_of(listener, struct shell_surface,
1145 surface_destroy_listener);
1151 shell_surface_configure(struct weston_surface *, int32_t, int32_t);
1154 create_shell_surface(void *shell, struct weston_surface *surface,
1155 struct shell_surface **ret)
1157 struct shell_surface *shsurf;
1159 if (surface->configure) {
1160 fprintf(stderr, "surface->configure already set\n");
1164 shsurf = calloc(1, sizeof *shsurf);
1166 fprintf(stderr, "no memory to allocate shell surface\n");
1170 surface->configure = shell_surface_configure;
1171 surface->compositor->shell_interface.shell = shell;
1173 shsurf->shell = (struct desktop_shell *) shell;
1174 shsurf->unresponsive = 0;
1175 shsurf->unresponsive_animation.exists = 0;
1176 shsurf->unresponsive_animation.fading_in = 0;
1177 shsurf->unresponsive_animation.current.frame = unresponsive_fade_frame;
1178 shsurf->saved_position_valid = false;
1179 shsurf->surface = surface;
1180 shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
1181 shsurf->fullscreen.framerate = 0;
1182 shsurf->fullscreen.black_surface = NULL;
1183 shsurf->ping_timer = NULL;
1184 wl_list_init(&shsurf->fullscreen.transform.link);
1186 wl_signal_init(&shsurf->resource.destroy_signal);
1187 shsurf->surface_destroy_listener.notify = shell_handle_surface_destroy;
1188 wl_signal_add(&surface->surface.resource.destroy_signal,
1189 &shsurf->surface_destroy_listener);
1191 /* init link so its safe to always remove it in destroy_shell_surface */
1192 wl_list_init(&shsurf->link);
1194 /* empty when not in use */
1195 wl_list_init(&shsurf->rotation.transform.link);
1196 weston_matrix_init(&shsurf->rotation.rotation);
1198 shsurf->type = SHELL_SURFACE_NONE;
1204 shell_get_shell_surface(struct wl_client *client,
1205 struct wl_resource *resource,
1207 struct wl_resource *surface_resource)
1209 struct weston_surface *surface = surface_resource->data;
1210 struct desktop_shell *shell = resource->data;
1211 struct shell_surface *shsurf;
1213 if (get_shell_surface(surface)) {
1214 wl_resource_post_error(surface_resource,
1215 WL_DISPLAY_ERROR_INVALID_OBJECT,
1216 "desktop_shell::get_shell_surface already requested");
1220 create_shell_surface(shell, surface, &shsurf);
1222 wl_resource_post_error(surface_resource,
1223 WL_DISPLAY_ERROR_INVALID_OBJECT,
1224 "surface->configure already set");
1228 shsurf->resource.destroy = shell_destroy_shell_surface;
1229 shsurf->resource.object.id = id;
1230 shsurf->resource.object.interface = &wl_shell_surface_interface;
1231 shsurf->resource.object.implementation =
1232 (void (**)(void)) &shell_surface_implementation;
1233 shsurf->resource.data = shsurf;
1235 wl_client_add_resource(client, &shsurf->resource);
1238 static const struct wl_shell_interface shell_implementation = {
1239 shell_get_shell_surface
1243 handle_screensaver_sigchld(struct weston_process *proc, int status)
1249 launch_screensaver(struct desktop_shell *shell)
1251 if (shell->screensaver.binding)
1254 if (!shell->screensaver.path)
1257 if (shell->screensaver.process.pid != 0) {
1258 fprintf(stderr, "old screensaver still running\n");
1262 weston_client_launch(shell->compositor,
1263 &shell->screensaver.process,
1264 shell->screensaver.path,
1265 handle_screensaver_sigchld);
1269 terminate_screensaver(struct desktop_shell *shell)
1271 if (shell->screensaver.process.pid == 0)
1274 kill(shell->screensaver.process.pid, SIGTERM);
1278 show_screensaver(struct desktop_shell *shell, struct shell_surface *surface)
1280 struct wl_list *list;
1282 if (shell->lock_surface)
1283 list = &shell->lock_surface->surface->layer_link;
1285 list = &shell->lock_layer.surface_list;
1287 wl_list_remove(&surface->surface->layer_link);
1288 wl_list_insert(list, &surface->surface->layer_link);
1289 surface->surface->output = surface->output;
1290 weston_surface_damage(surface->surface);
1294 hide_screensaver(struct desktop_shell *shell, struct shell_surface *surface)
1296 wl_list_remove(&surface->surface->layer_link);
1297 wl_list_init(&surface->surface->layer_link);
1298 surface->surface->output = NULL;
1302 desktop_shell_set_background(struct wl_client *client,
1303 struct wl_resource *resource,
1304 struct wl_resource *output_resource,
1305 struct wl_resource *surface_resource)
1307 struct desktop_shell *shell = resource->data;
1308 struct shell_surface *shsurf = surface_resource->data;
1309 struct weston_surface *surface = shsurf->surface;
1310 struct shell_surface *priv;
1312 if (reset_shell_surface_type(shsurf))
1315 wl_list_for_each(priv, &shell->backgrounds, link) {
1316 if (priv->output == output_resource->data) {
1317 priv->surface->output = NULL;
1318 wl_list_remove(&priv->surface->layer_link);
1319 wl_list_remove(&priv->link);
1324 shsurf->type = SHELL_SURFACE_BACKGROUND;
1325 shsurf->output = output_resource->data;
1327 wl_list_insert(&shell->backgrounds, &shsurf->link);
1329 weston_surface_set_position(surface, shsurf->output->x,
1332 desktop_shell_send_configure(resource, 0,
1334 shsurf->output->current->width,
1335 shsurf->output->current->height);
1339 desktop_shell_set_panel(struct wl_client *client,
1340 struct wl_resource *resource,
1341 struct wl_resource *output_resource,
1342 struct wl_resource *surface_resource)
1344 struct desktop_shell *shell = resource->data;
1345 struct shell_surface *shsurf = surface_resource->data;
1346 struct weston_surface *surface = shsurf->surface;
1347 struct shell_surface *priv;
1349 if (reset_shell_surface_type(shsurf))
1352 wl_list_for_each(priv, &shell->panels, link) {
1353 if (priv->output == output_resource->data) {
1354 priv->surface->output = NULL;
1355 wl_list_remove(&priv->surface->layer_link);
1356 wl_list_remove(&priv->link);
1361 shsurf->type = SHELL_SURFACE_PANEL;
1362 shsurf->output = output_resource->data;
1364 wl_list_insert(&shell->panels, &shsurf->link);
1366 weston_surface_set_position(surface, shsurf->output->x,
1369 desktop_shell_send_configure(resource, 0,
1371 shsurf->output->current->width,
1372 shsurf->output->current->height);
1376 handle_lock_surface_destroy(struct wl_listener *listener, void *data)
1378 struct desktop_shell *shell =
1379 container_of(listener, struct desktop_shell, lock_surface_listener);
1381 fprintf(stderr, "lock surface gone\n");
1382 shell->lock_surface = NULL;
1386 desktop_shell_set_lock_surface(struct wl_client *client,
1387 struct wl_resource *resource,
1388 struct wl_resource *surface_resource)
1390 struct desktop_shell *shell = resource->data;
1391 struct shell_surface *surface = surface_resource->data;
1393 if (reset_shell_surface_type(surface))
1396 shell->prepare_event_sent = false;
1401 shell->lock_surface = surface;
1403 shell->lock_surface_listener.notify = handle_lock_surface_destroy;
1404 wl_signal_add(&surface_resource->destroy_signal,
1405 &shell->lock_surface_listener);
1407 shell->lock_surface->type = SHELL_SURFACE_LOCK;
1411 resume_desktop(struct desktop_shell *shell)
1413 struct shell_surface *tmp;
1415 wl_list_for_each(tmp, &shell->screensaver.surfaces, link)
1416 hide_screensaver(shell, tmp);
1418 terminate_screensaver(shell);
1420 wl_list_remove(&shell->lock_layer.link);
1421 wl_list_insert(&shell->compositor->cursor_layer.link,
1422 &shell->fullscreen_layer.link);
1423 wl_list_insert(&shell->fullscreen_layer.link,
1424 &shell->panel_layer.link);
1425 wl_list_insert(&shell->panel_layer.link, &shell->toplevel_layer.link);
1427 shell->locked = false;
1428 shell->compositor->idle_time = shell->compositor->option_idle_time;
1429 weston_compositor_wake(shell->compositor);
1430 weston_compositor_damage_all(shell->compositor);
1434 desktop_shell_unlock(struct wl_client *client,
1435 struct wl_resource *resource)
1437 struct desktop_shell *shell = resource->data;
1439 shell->prepare_event_sent = false;
1442 resume_desktop(shell);
1445 static const struct desktop_shell_interface desktop_shell_implementation = {
1446 desktop_shell_set_background,
1447 desktop_shell_set_panel,
1448 desktop_shell_set_lock_surface,
1449 desktop_shell_unlock
1452 static enum shell_surface_type
1453 get_shell_surface_type(struct weston_surface *surface)
1455 struct shell_surface *shsurf;
1457 shsurf = get_shell_surface(surface);
1459 return SHELL_SURFACE_NONE;
1460 return shsurf->type;
1464 move_binding(struct wl_input_device *device, uint32_t time,
1465 uint32_t key, uint32_t button, uint32_t axis, int32_t state, void *data)
1467 struct weston_surface *surface =
1468 (struct weston_surface *) device->pointer_focus;
1470 if (surface == NULL)
1473 switch (get_shell_surface_type(surface)) {
1474 case SHELL_SURFACE_PANEL:
1475 case SHELL_SURFACE_BACKGROUND:
1476 case SHELL_SURFACE_FULLSCREEN:
1477 case SHELL_SURFACE_SCREENSAVER:
1483 weston_surface_move(surface, (struct weston_input_device *) device);
1487 resize_binding(struct wl_input_device *device, uint32_t time,
1488 uint32_t key, uint32_t button, uint32_t axis, int32_t state, void *data)
1490 struct weston_surface *surface =
1491 (struct weston_surface *) device->pointer_focus;
1494 struct shell_surface *shsurf;
1496 if (surface == NULL)
1499 shsurf = get_shell_surface(surface);
1503 switch (shsurf->type) {
1504 case SHELL_SURFACE_PANEL:
1505 case SHELL_SURFACE_BACKGROUND:
1506 case SHELL_SURFACE_FULLSCREEN:
1507 case SHELL_SURFACE_SCREENSAVER:
1513 weston_surface_from_global(surface,
1514 device->grab_x, device->grab_y, &x, &y);
1516 if (x < surface->geometry.width / 3)
1517 edges |= WL_SHELL_SURFACE_RESIZE_LEFT;
1518 else if (x < 2 * surface->geometry.width / 3)
1521 edges |= WL_SHELL_SURFACE_RESIZE_RIGHT;
1523 if (y < surface->geometry.height / 3)
1524 edges |= WL_SHELL_SURFACE_RESIZE_TOP;
1525 else if (y < 2 * surface->geometry.height / 3)
1528 edges |= WL_SHELL_SURFACE_RESIZE_BOTTOM;
1530 weston_surface_resize(shsurf, (struct weston_input_device *) device,
1535 surface_opacity_binding(struct wl_input_device *device, uint32_t time,
1536 uint32_t key, uint32_t button, uint32_t axis, int32_t value, void *data)
1539 struct shell_surface *shsurf;
1540 struct weston_surface *surface =
1541 (struct weston_surface *) device->pointer_focus;
1543 if (surface == NULL)
1546 shsurf = get_shell_surface(surface);
1550 switch (shsurf->type) {
1551 case SHELL_SURFACE_BACKGROUND:
1552 case SHELL_SURFACE_SCREENSAVER:
1558 surface->alpha += value * step;
1560 if (surface->alpha > 255)
1561 surface->alpha = 255;
1562 if (surface->alpha < step)
1563 surface->alpha = step;
1565 surface->geometry.dirty = 1;
1566 weston_surface_damage(surface);
1570 zoom_binding(struct wl_input_device *device, uint32_t time,
1571 uint32_t key, uint32_t button, uint32_t axis, int32_t value, void *data)
1573 struct weston_input_device *wd = (struct weston_input_device *) device;
1574 struct weston_compositor *compositor = wd->compositor;
1575 struct weston_output *output;
1577 wl_list_for_each(output, &compositor->output_list, link) {
1578 if (pixman_region32_contains_point(&output->region,
1579 device->x, device->y, NULL)) {
1580 output->zoom.active = 1;
1581 output->zoom.level += output->zoom.increment * -value;
1583 if (output->zoom.level >= 1.0) {
1584 output->zoom.active = 0;
1585 output->zoom.level = 1.0;
1588 if (output->zoom.level < output->zoom.increment)
1589 output->zoom.level = output->zoom.increment;
1591 weston_output_update_zoom(output, device->x, device->y);
1597 terminate_binding(struct wl_input_device *device, uint32_t time,
1598 uint32_t key, uint32_t button, uint32_t axis, int32_t state, void *data)
1600 struct weston_compositor *compositor = data;
1603 wl_display_terminate(compositor->wl_display);
1607 rotate_grab_motion(struct wl_pointer_grab *grab,
1608 uint32_t time, int32_t x, int32_t y)
1610 struct rotate_grab *rotate =
1611 container_of(grab, struct rotate_grab, base.grab);
1612 struct wl_input_device *device = grab->input_device;
1613 struct shell_surface *shsurf = rotate->base.shsurf;
1614 struct weston_surface *surface;
1615 GLfloat cx, cy, dx, dy, cposx, cposy, dposx, dposy, r;
1620 surface = shsurf->surface;
1622 cx = 0.5f * surface->geometry.width;
1623 cy = 0.5f * surface->geometry.height;
1625 dx = device->x - rotate->center.x;
1626 dy = device->y - rotate->center.y;
1627 r = sqrtf(dx * dx + dy * dy);
1629 wl_list_remove(&shsurf->rotation.transform.link);
1630 shsurf->surface->geometry.dirty = 1;
1633 struct weston_matrix *matrix =
1634 &shsurf->rotation.transform.matrix;
1636 weston_matrix_init(&rotate->rotation);
1637 rotate->rotation.d[0] = dx / r;
1638 rotate->rotation.d[4] = -dy / r;
1639 rotate->rotation.d[1] = -rotate->rotation.d[4];
1640 rotate->rotation.d[5] = rotate->rotation.d[0];
1642 weston_matrix_init(matrix);
1643 weston_matrix_translate(matrix, -cx, -cy, 0.0f);
1644 weston_matrix_multiply(matrix, &shsurf->rotation.rotation);
1645 weston_matrix_multiply(matrix, &rotate->rotation);
1646 weston_matrix_translate(matrix, cx, cy, 0.0f);
1649 &shsurf->surface->geometry.transformation_list,
1650 &shsurf->rotation.transform.link);
1652 wl_list_init(&shsurf->rotation.transform.link);
1653 weston_matrix_init(&shsurf->rotation.rotation);
1654 weston_matrix_init(&rotate->rotation);
1657 /* We need to adjust the position of the surface
1658 * in case it was resized in a rotated state before */
1659 cposx = surface->geometry.x + cx;
1660 cposy = surface->geometry.y + cy;
1661 dposx = rotate->center.x - cposx;
1662 dposy = rotate->center.y - cposy;
1663 if (dposx != 0.0f || dposy != 0.0f) {
1664 weston_surface_set_position(surface,
1665 surface->geometry.x + dposx,
1666 surface->geometry.y + dposy);
1669 /* Repaint implies weston_surface_update_transform(), which
1670 * lazily applies the damage due to rotation update.
1672 weston_compositor_schedule_repaint(shsurf->surface->compositor);
1676 rotate_grab_button(struct wl_pointer_grab *grab,
1677 uint32_t time, uint32_t button, int32_t state)
1679 struct rotate_grab *rotate =
1680 container_of(grab, struct rotate_grab, base.grab);
1681 struct wl_input_device *device = grab->input_device;
1682 struct shell_surface *shsurf = rotate->base.shsurf;
1684 if (device->button_count == 0 && state == 0) {
1686 weston_matrix_multiply(&shsurf->rotation.rotation,
1688 shell_grab_finish(&rotate->base);
1689 wl_input_device_end_pointer_grab(device);
1694 static const struct wl_pointer_grab_interface rotate_grab_interface = {
1701 rotate_binding(struct wl_input_device *device, uint32_t time,
1702 uint32_t key, uint32_t button, uint32_t axis, int32_t state, void *data)
1704 struct weston_surface *base_surface =
1705 (struct weston_surface *) device->pointer_focus;
1706 struct shell_surface *surface;
1707 struct rotate_grab *rotate;
1711 if (base_surface == NULL)
1714 surface = get_shell_surface(base_surface);
1718 switch (surface->type) {
1719 case SHELL_SURFACE_PANEL:
1720 case SHELL_SURFACE_BACKGROUND:
1721 case SHELL_SURFACE_FULLSCREEN:
1722 case SHELL_SURFACE_SCREENSAVER:
1728 rotate = malloc(sizeof *rotate);
1732 shell_grab_init(&rotate->base, &rotate_grab_interface, surface);
1734 weston_surface_to_global(surface->surface,
1735 surface->surface->geometry.width / 2,
1736 surface->surface->geometry.height / 2,
1737 &rotate->center.x, &rotate->center.y);
1739 wl_input_device_start_pointer_grab(device, &rotate->base.grab);
1741 dx = device->x - rotate->center.x;
1742 dy = device->y - rotate->center.y;
1743 r = sqrtf(dx * dx + dy * dy);
1745 struct weston_matrix inverse;
1747 weston_matrix_init(&inverse);
1748 inverse.d[0] = dx / r;
1749 inverse.d[4] = dy / r;
1750 inverse.d[1] = -inverse.d[4];
1751 inverse.d[5] = inverse.d[0];
1752 weston_matrix_multiply(&surface->rotation.rotation, &inverse);
1754 weston_matrix_init(&rotate->rotation);
1755 rotate->rotation.d[0] = dx / r;
1756 rotate->rotation.d[4] = -dy / r;
1757 rotate->rotation.d[1] = -rotate->rotation.d[4];
1758 rotate->rotation.d[5] = rotate->rotation.d[0];
1760 weston_matrix_init(&surface->rotation.rotation);
1761 weston_matrix_init(&rotate->rotation);
1764 wl_input_device_set_pointer_focus(device, NULL, 0, 0);
1768 activate(struct desktop_shell *shell, struct weston_surface *es,
1769 struct weston_input_device *device)
1771 struct weston_surface *surf, *prev;
1773 weston_surface_activate(es, device);
1775 switch (get_shell_surface_type(es)) {
1776 case SHELL_SURFACE_BACKGROUND:
1777 case SHELL_SURFACE_PANEL:
1778 case SHELL_SURFACE_LOCK:
1781 case SHELL_SURFACE_SCREENSAVER:
1782 /* always below lock surface */
1783 if (shell->lock_surface)
1784 weston_surface_restack(es,
1785 &shell->lock_surface->surface->layer_link);
1787 case SHELL_SURFACE_FULLSCREEN:
1788 /* should on top of panels */
1789 shell_stack_fullscreen(get_shell_surface(es));
1790 shell_configure_fullscreen(get_shell_surface(es));
1793 /* move the fullscreen surfaces down into the toplevel layer */
1794 if (!wl_list_empty(&shell->fullscreen_layer.surface_list)) {
1795 wl_list_for_each_reverse_safe(surf,
1797 &shell->fullscreen_layer.surface_list,
1799 weston_surface_restack(surf,
1800 &shell->toplevel_layer.surface_list);
1803 weston_surface_restack(es,
1804 &shell->toplevel_layer.surface_list);
1809 /* no-op func for checking black surface */
1811 black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy)
1816 is_black_surface (struct weston_surface *es, struct weston_surface **fs_surface)
1818 if (es->configure == black_surface_configure) {
1820 *fs_surface = (struct weston_surface *)es->private;
1827 click_to_activate_binding(struct wl_input_device *device,
1828 uint32_t time, uint32_t key,
1829 uint32_t button, uint32_t axis, int32_t state, void *data)
1831 struct weston_input_device *wd = (struct weston_input_device *) device;
1832 struct desktop_shell *shell = data;
1833 struct weston_surface *focus;
1834 struct weston_surface *upper;
1836 focus = (struct weston_surface *) device->pointer_focus;
1840 if (is_black_surface(focus, &upper))
1843 if (state && device->pointer_grab == &device->default_pointer_grab)
1844 activate(shell, focus, wd);
1848 lock(struct wl_listener *listener, void *data)
1850 struct desktop_shell *shell =
1851 container_of(listener, struct desktop_shell, lock_listener);
1852 struct weston_input_device *device;
1853 struct shell_surface *shsurf;
1854 struct weston_output *output;
1856 if (shell->locked) {
1857 wl_list_for_each(output, &shell->compositor->output_list, link)
1858 /* TODO: find a way to jump to other DPMS levels */
1859 if (output->set_dpms)
1860 output->set_dpms(output, WESTON_DPMS_STANDBY);
1864 shell->locked = true;
1866 /* Hide all surfaces by removing the fullscreen, panel and
1867 * toplevel layers. This way nothing else can show or receive
1868 * input events while we are locked. */
1870 wl_list_remove(&shell->panel_layer.link);
1871 wl_list_remove(&shell->toplevel_layer.link);
1872 wl_list_remove(&shell->fullscreen_layer.link);
1873 wl_list_insert(&shell->compositor->cursor_layer.link,
1874 &shell->lock_layer.link);
1876 launch_screensaver(shell);
1878 wl_list_for_each(shsurf, &shell->screensaver.surfaces, link)
1879 show_screensaver(shell, shsurf);
1881 if (!wl_list_empty(&shell->screensaver.surfaces)) {
1882 shell->compositor->idle_time = shell->screensaver.duration;
1883 weston_compositor_wake(shell->compositor);
1884 shell->compositor->state = WESTON_COMPOSITOR_IDLE;
1887 /* reset pointer foci */
1888 weston_compositor_schedule_repaint(shell->compositor);
1890 /* reset keyboard foci */
1891 wl_list_for_each(device, &shell->compositor->input_device_list, link) {
1892 wl_input_device_set_keyboard_focus(&device->input_device,
1896 /* TODO: disable bindings that should not work while locked. */
1898 /* All this must be undone in resume_desktop(). */
1902 unlock(struct wl_listener *listener, void *data)
1904 struct desktop_shell *shell =
1905 container_of(listener, struct desktop_shell, unlock_listener);
1907 if (!shell->locked || shell->lock_surface) {
1908 weston_compositor_wake(shell->compositor);
1912 /* If desktop-shell client has gone away, unlock immediately. */
1913 if (!shell->child.desktop_shell) {
1914 resume_desktop(shell);
1918 if (shell->prepare_event_sent)
1921 desktop_shell_send_prepare_lock_surface(shell->child.desktop_shell);
1922 shell->prepare_event_sent = true;
1926 center_on_output(struct weston_surface *surface, struct weston_output *output)
1928 struct weston_mode *mode = output->current;
1929 GLfloat x = (mode->width - surface->geometry.width) / 2;
1930 GLfloat y = (mode->height - surface->geometry.height) / 2;
1932 weston_surface_set_position(surface, output->x + x, output->y + y);
1936 map(struct desktop_shell *shell, struct weston_surface *surface,
1937 int32_t width, int32_t height, int32_t sx, int32_t sy)
1939 struct weston_compositor *compositor = shell->compositor;
1940 struct shell_surface *shsurf;
1941 enum shell_surface_type surface_type = SHELL_SURFACE_NONE;
1942 struct weston_surface *parent;
1943 int panel_height = 0;
1945 shsurf = get_shell_surface(surface);
1947 surface_type = shsurf->type;
1949 surface->geometry.width = width;
1950 surface->geometry.height = height;
1951 surface->geometry.dirty = 1;
1953 /* initial positioning, see also configure() */
1954 switch (surface_type) {
1955 case SHELL_SURFACE_TOPLEVEL:
1956 weston_surface_set_position(surface, 10 + random() % 400,
1957 10 + random() % 400);
1959 case SHELL_SURFACE_SCREENSAVER:
1960 center_on_output(surface, shsurf->fullscreen_output);
1962 case SHELL_SURFACE_FULLSCREEN:
1963 shell_map_fullscreen(shsurf);
1965 case SHELL_SURFACE_MAXIMIZED:
1966 /* use surface configure to set the geometry */
1967 panel_height = get_output_panel_height(shell,surface->output);
1968 weston_surface_set_position(surface, surface->output->x,
1969 surface->output->y + panel_height);
1971 case SHELL_SURFACE_LOCK:
1972 center_on_output(surface, get_default_output(compositor));
1974 case SHELL_SURFACE_POPUP:
1975 shell_map_popup(shsurf);
1976 case SHELL_SURFACE_NONE:
1977 weston_surface_set_position(surface,
1978 surface->geometry.x + sx,
1979 surface->geometry.y + sy);
1985 /* surface stacking order, see also activate() */
1986 switch (surface_type) {
1987 case SHELL_SURFACE_BACKGROUND:
1988 /* background always visible, at the bottom */
1989 wl_list_insert(&shell->background_layer.surface_list,
1990 &surface->layer_link);
1992 case SHELL_SURFACE_PANEL:
1993 /* panel always on top, hidden while locked */
1994 wl_list_insert(&shell->panel_layer.surface_list,
1995 &surface->layer_link);
1997 case SHELL_SURFACE_LOCK:
1998 /* lock surface always visible, on top */
1999 wl_list_insert(&shell->lock_layer.surface_list,
2000 &surface->layer_link);
2001 weston_compositor_wake(compositor);
2003 case SHELL_SURFACE_SCREENSAVER:
2004 /* If locked, show it. */
2005 if (shell->locked) {
2006 show_screensaver(shell, shsurf);
2007 compositor->idle_time = shell->screensaver.duration;
2008 weston_compositor_wake(compositor);
2009 if (!shell->lock_surface)
2010 compositor->state = WESTON_COMPOSITOR_IDLE;
2013 case SHELL_SURFACE_POPUP:
2014 case SHELL_SURFACE_TRANSIENT:
2015 parent = shsurf->parent->surface;
2016 wl_list_insert(parent->layer_link.prev, &surface->layer_link);
2018 case SHELL_SURFACE_FULLSCREEN:
2019 case SHELL_SURFACE_NONE:
2022 wl_list_insert(&shell->toplevel_layer.surface_list,
2023 &surface->layer_link);
2027 if (surface_type != SHELL_SURFACE_NONE) {
2028 weston_surface_assign_output(surface);
2029 if (surface_type == SHELL_SURFACE_MAXIMIZED)
2030 surface->output = shsurf->output;
2033 switch (surface_type) {
2034 case SHELL_SURFACE_TOPLEVEL:
2035 case SHELL_SURFACE_TRANSIENT:
2036 case SHELL_SURFACE_FULLSCREEN:
2037 case SHELL_SURFACE_MAXIMIZED:
2039 activate(shell, surface,
2040 (struct weston_input_device *)
2041 compositor->input_device);
2047 if (surface_type == SHELL_SURFACE_TOPLEVEL)
2049 switch (shell->win_animation_type) {
2050 case ANIMATION_FADE:
2051 weston_fade_run(surface, NULL, NULL);
2053 case ANIMATION_ZOOM:
2054 weston_zoom_run(surface, 0.8, 1.0, NULL, NULL);
2063 configure(struct desktop_shell *shell, struct weston_surface *surface,
2064 GLfloat x, GLfloat y, int32_t width, int32_t height)
2066 enum shell_surface_type surface_type = SHELL_SURFACE_NONE;
2067 struct shell_surface *shsurf;
2069 shsurf = get_shell_surface(surface);
2071 surface_type = shsurf->type;
2073 surface->geometry.x = x;
2074 surface->geometry.y = y;
2075 surface->geometry.width = width;
2076 surface->geometry.height = height;
2077 surface->geometry.dirty = 1;
2079 switch (surface_type) {
2080 case SHELL_SURFACE_SCREENSAVER:
2081 center_on_output(surface, shsurf->fullscreen_output);
2083 case SHELL_SURFACE_FULLSCREEN:
2084 shell_stack_fullscreen(shsurf);
2085 shell_configure_fullscreen(shsurf);
2087 case SHELL_SURFACE_MAXIMIZED:
2088 /* setting x, y and using configure to change that geometry */
2089 surface->geometry.x = surface->output->x;
2090 surface->geometry.y = surface->output->y +
2091 get_output_panel_height(shell,surface->output);
2093 case SHELL_SURFACE_TOPLEVEL:
2099 /* XXX: would a fullscreen surface need the same handling? */
2100 if (surface->output) {
2101 weston_surface_assign_output(surface);
2103 if (surface_type == SHELL_SURFACE_SCREENSAVER)
2104 surface->output = shsurf->output;
2105 else if (surface_type == SHELL_SURFACE_MAXIMIZED)
2106 surface->output = shsurf->output;
2111 shell_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy)
2113 struct shell_surface *shsurf = get_shell_surface(es);
2114 struct desktop_shell *shell = shsurf->shell;
2116 if (!weston_surface_is_mapped(es)) {
2117 map(shell, es, es->buffer->width, es->buffer->height, sx, sy);
2118 } else if (shsurf->force_configure || sx != 0 || sy != 0 ||
2119 es->geometry.width != es->buffer->width ||
2120 es->geometry.height != es->buffer->height) {
2121 GLfloat from_x, from_y;
2124 weston_surface_to_global_float(es, 0, 0, &from_x, &from_y);
2125 weston_surface_to_global_float(es, sx, sy, &to_x, &to_y);
2126 configure(shell, es,
2127 es->geometry.x + to_x - from_x,
2128 es->geometry.y + to_y - from_y,
2129 es->buffer->width, es->buffer->height);
2130 shsurf->force_configure = 0;
2134 static int launch_desktop_shell_process(struct desktop_shell *shell);
2137 desktop_shell_sigchld(struct weston_process *process, int status)
2140 struct desktop_shell *shell =
2141 container_of(process, struct desktop_shell, child.process);
2143 shell->child.process.pid = 0;
2144 shell->child.client = NULL; /* already destroyed by wayland */
2146 /* if desktop-shell dies more than 5 times in 30 seconds, give up */
2147 time = weston_compositor_get_time();
2148 if (time - shell->child.deathstamp > 30000) {
2149 shell->child.deathstamp = time;
2150 shell->child.deathcount = 0;
2153 shell->child.deathcount++;
2154 if (shell->child.deathcount > 5) {
2155 fprintf(stderr, "weston-desktop-shell died, giving up.\n");
2159 fprintf(stderr, "weston-desktop-shell died, respawning...\n");
2160 launch_desktop_shell_process(shell);
2164 launch_desktop_shell_process(struct desktop_shell *shell)
2166 const char *shell_exe = LIBEXECDIR "/weston-desktop-shell";
2168 shell->child.client = weston_client_launch(shell->compositor,
2169 &shell->child.process,
2171 desktop_shell_sigchld);
2173 if (!shell->child.client)
2179 bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
2181 struct desktop_shell *shell = data;
2183 wl_client_add_object(client, &wl_shell_interface,
2184 &shell_implementation, id, shell);
2188 unbind_desktop_shell(struct wl_resource *resource)
2190 struct desktop_shell *shell = resource->data;
2193 resume_desktop(shell);
2195 shell->child.desktop_shell = NULL;
2196 shell->prepare_event_sent = false;
2201 bind_desktop_shell(struct wl_client *client,
2202 void *data, uint32_t version, uint32_t id)
2204 struct desktop_shell *shell = data;
2205 struct wl_resource *resource;
2207 resource = wl_client_add_object(client, &desktop_shell_interface,
2208 &desktop_shell_implementation,
2211 if (client == shell->child.client) {
2212 resource->destroy = unbind_desktop_shell;
2213 shell->child.desktop_shell = resource;
2217 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
2218 "permission to bind desktop_shell denied");
2219 wl_resource_destroy(resource);
2223 screensaver_set_surface(struct wl_client *client,
2224 struct wl_resource *resource,
2225 struct wl_resource *shell_surface_resource,
2226 struct wl_resource *output_resource)
2228 struct desktop_shell *shell = resource->data;
2229 struct shell_surface *surface = shell_surface_resource->data;
2230 struct weston_output *output = output_resource->data;
2232 if (reset_shell_surface_type(surface))
2235 surface->type = SHELL_SURFACE_SCREENSAVER;
2237 surface->fullscreen_output = output;
2238 surface->output = output;
2239 wl_list_insert(shell->screensaver.surfaces.prev, &surface->link);
2242 static const struct screensaver_interface screensaver_implementation = {
2243 screensaver_set_surface
2247 unbind_screensaver(struct wl_resource *resource)
2249 struct desktop_shell *shell = resource->data;
2251 shell->screensaver.binding = NULL;
2256 bind_screensaver(struct wl_client *client,
2257 void *data, uint32_t version, uint32_t id)
2259 struct desktop_shell *shell = data;
2260 struct wl_resource *resource;
2262 resource = wl_client_add_object(client, &screensaver_interface,
2263 &screensaver_implementation,
2266 if (shell->screensaver.binding == NULL) {
2267 resource->destroy = unbind_screensaver;
2268 shell->screensaver.binding = resource;
2272 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
2273 "interface object already bound");
2274 wl_resource_destroy(resource);
2278 struct desktop_shell *shell;
2279 struct weston_surface *current;
2280 struct wl_listener listener;
2281 struct wl_keyboard_grab grab;
2285 switcher_next(struct switcher *switcher)
2287 struct weston_compositor *compositor = switcher->shell->compositor;
2288 struct weston_surface *surface;
2289 struct weston_surface *first = NULL, *prev = NULL, *next = NULL;
2290 struct shell_surface *shsurf;
2292 wl_list_for_each(surface, &compositor->surface_list, link) {
2293 switch (get_shell_surface_type(surface)) {
2294 case SHELL_SURFACE_TOPLEVEL:
2295 case SHELL_SURFACE_FULLSCREEN:
2296 case SHELL_SURFACE_MAXIMIZED:
2299 if (prev == switcher->current)
2302 surface->alpha = 64;
2303 surface->geometry.dirty = 1;
2304 weston_surface_damage(surface);
2310 if (is_black_surface(surface, NULL)) {
2311 surface->alpha = 64;
2312 surface->geometry.dirty = 1;
2313 weston_surface_damage(surface);
2323 wl_list_remove(&switcher->listener.link);
2324 wl_signal_add(&next->surface.resource.destroy_signal,
2325 &switcher->listener);
2327 switcher->current = next;
2330 shsurf = get_shell_surface(switcher->current);
2331 if (shsurf && shsurf->type ==SHELL_SURFACE_FULLSCREEN)
2332 shsurf->fullscreen.black_surface->alpha = 255;
2336 switcher_handle_surface_destroy(struct wl_listener *listener, void *data)
2338 struct switcher *switcher =
2339 container_of(listener, struct switcher, listener);
2341 switcher_next(switcher);
2345 switcher_destroy(struct switcher *switcher, uint32_t time)
2347 struct weston_compositor *compositor = switcher->shell->compositor;
2348 struct weston_surface *surface;
2349 struct weston_input_device *device =
2350 (struct weston_input_device *) switcher->grab.input_device;
2352 wl_list_for_each(surface, &compositor->surface_list, link) {
2353 surface->alpha = 255;
2354 weston_surface_damage(surface);
2357 if (switcher->current)
2358 activate(switcher->shell, switcher->current, device);
2359 wl_list_remove(&switcher->listener.link);
2360 wl_input_device_end_keyboard_grab(&device->input_device);
2365 switcher_key(struct wl_keyboard_grab *grab,
2366 uint32_t time, uint32_t key, int32_t state)
2368 struct switcher *switcher = container_of(grab, struct switcher, grab);
2369 struct weston_input_device *device =
2370 (struct weston_input_device *) grab->input_device;
2372 if ((device->modifier_state & switcher->shell->binding_modifier) == 0) {
2373 switcher_destroy(switcher, time);
2374 } else if (key == KEY_TAB && state) {
2375 switcher_next(switcher);
2379 static const struct wl_keyboard_grab_interface switcher_grab = {
2384 switcher_binding(struct wl_input_device *device, uint32_t time,
2385 uint32_t key, uint32_t button, uint32_t axis,
2386 int32_t state, void *data)
2388 struct desktop_shell *shell = data;
2389 struct switcher *switcher;
2391 switcher = malloc(sizeof *switcher);
2392 switcher->shell = shell;
2393 switcher->current = NULL;
2394 switcher->listener.notify = switcher_handle_surface_destroy;
2395 wl_list_init(&switcher->listener.link);
2397 switcher->grab.interface = &switcher_grab;
2398 wl_input_device_start_keyboard_grab(device, &switcher->grab);
2399 wl_input_device_set_keyboard_focus(device, NULL);
2400 switcher_next(switcher);
2404 backlight_binding(struct wl_input_device *device, uint32_t time,
2405 uint32_t key, uint32_t button, uint32_t axis, int32_t state, void *data)
2407 struct weston_compositor *compositor = data;
2408 struct weston_output *output;
2409 long backlight_new = 0;
2411 /* TODO: we're limiting to simple use cases, where we assume just
2412 * control on the primary display. We'd have to extend later if we
2413 * ever get support for setting backlights on random desktop LCD
2415 output = get_default_output(compositor);
2419 if (!output->set_backlight)
2422 if (key == KEY_F9 || key == KEY_BRIGHTNESSDOWN)
2423 backlight_new = output->backlight_current - 25;
2424 else if (key == KEY_F10 || key == KEY_BRIGHTNESSUP)
2425 backlight_new = output->backlight_current + 25;
2427 if (backlight_new < 5)
2429 if (backlight_new > 255)
2430 backlight_new = 255;
2432 output->backlight_current = backlight_new;
2433 output->set_backlight(output, output->backlight_current);
2437 debug_repaint_binding(struct wl_input_device *device, uint32_t time,
2438 uint32_t key, uint32_t button, uint32_t axis, int32_t state, void *data)
2440 struct desktop_shell *shell = data;
2441 struct weston_compositor *compositor = shell->compositor;
2442 struct weston_surface *surface;
2444 if (shell->debug_repaint_surface) {
2445 weston_surface_destroy(shell->debug_repaint_surface);
2446 shell->debug_repaint_surface = NULL;
2448 surface = weston_surface_create(compositor);
2449 weston_surface_set_color(surface, 1.0, 0.0, 0.0, 0.2);
2450 weston_surface_configure(surface, 0, 0, 8192, 8192);
2451 wl_list_insert(&compositor->fade_layer.surface_list,
2452 &surface->layer_link);
2453 weston_surface_assign_output(surface);
2454 pixman_region32_init(&surface->input);
2456 /* Here's the dirty little trick that makes the
2457 * repaint debugging work: we force an
2458 * update_transform first to update dependent state
2459 * and clear the geometry.dirty bit. Then we clear
2460 * the surface damage so it only gets repainted
2461 * piecewise as we repaint other things. */
2463 weston_surface_update_transform(surface);
2464 pixman_region32_fini(&surface->damage);
2465 pixman_region32_init(&surface->damage);
2466 shell->debug_repaint_surface = surface;
2471 shell_destroy(struct wl_listener *listener, void *data)
2473 struct desktop_shell *shell =
2474 container_of(listener, struct desktop_shell, destroy_listener);
2476 if (shell->child.client)
2477 wl_client_destroy(shell->child.client);
2479 free(shell->screensaver.path);
2484 shell_add_bindings(struct weston_compositor *ec, struct desktop_shell *shell)
2488 /* fixed bindings */
2489 weston_compositor_add_binding(ec, KEY_BACKSPACE, 0, 0,
2490 MODIFIER_CTRL | MODIFIER_ALT,
2491 terminate_binding, ec);
2492 weston_compositor_add_binding(ec, 0, BTN_LEFT, 0, 0,
2493 click_to_activate_binding, shell);
2494 weston_compositor_add_binding(ec, 0, 0,
2495 WL_INPUT_DEVICE_AXIS_VERTICAL_SCROLL,
2496 MODIFIER_SUPER | MODIFIER_ALT,
2497 surface_opacity_binding, NULL);
2498 weston_compositor_add_binding(ec, 0, 0,
2499 WL_INPUT_DEVICE_AXIS_VERTICAL_SCROLL,
2500 MODIFIER_SUPER, zoom_binding, NULL);
2502 /* configurable bindings */
2503 mod = shell->binding_modifier;
2504 weston_compositor_add_binding(ec, 0, BTN_LEFT, 0, mod,
2505 move_binding, shell);
2506 weston_compositor_add_binding(ec, 0, BTN_MIDDLE, 0, mod,
2507 resize_binding, shell);
2508 weston_compositor_add_binding(ec, 0, BTN_RIGHT, 0, mod,
2509 rotate_binding, NULL);
2510 weston_compositor_add_binding(ec, KEY_TAB, 0, 0, mod,
2511 switcher_binding, shell);
2512 weston_compositor_add_binding(ec, KEY_F9, 0, 0, mod,
2513 backlight_binding, ec);
2514 weston_compositor_add_binding(ec, KEY_BRIGHTNESSDOWN, 0, 0, 0,
2515 backlight_binding, ec);
2516 weston_compositor_add_binding(ec, KEY_F10, 0, 0, mod,
2517 backlight_binding, ec);
2518 weston_compositor_add_binding(ec, KEY_BRIGHTNESSUP, 0, 0, 0,
2519 backlight_binding, ec);
2520 weston_compositor_add_binding(ec, KEY_SPACE, 0, 0, mod,
2521 debug_repaint_binding, shell);
2525 shell_init(struct weston_compositor *ec);
2528 shell_init(struct weston_compositor *ec)
2530 struct desktop_shell *shell;
2532 shell = malloc(sizeof *shell);
2536 memset(shell, 0, sizeof *shell);
2537 shell->compositor = ec;
2539 shell->destroy_listener.notify = shell_destroy;
2540 wl_signal_add(&ec->destroy_signal, &shell->destroy_listener);
2541 shell->lock_listener.notify = lock;
2542 wl_signal_add(&ec->lock_signal, &shell->lock_listener);
2543 shell->unlock_listener.notify = unlock;
2544 wl_signal_add(&ec->unlock_signal, &shell->unlock_listener);
2545 ec->ping_handler = ping_handler;
2546 ec->shell_interface.create_shell_surface = create_shell_surface;
2547 ec->shell_interface.set_toplevel = set_toplevel;
2549 wl_list_init(&shell->backgrounds);
2550 wl_list_init(&shell->panels);
2551 wl_list_init(&shell->screensaver.surfaces);
2553 weston_layer_init(&shell->fullscreen_layer, &ec->cursor_layer.link);
2554 weston_layer_init(&shell->panel_layer, &shell->fullscreen_layer.link);
2555 weston_layer_init(&shell->toplevel_layer, &shell->panel_layer.link);
2556 weston_layer_init(&shell->background_layer,
2557 &shell->toplevel_layer.link);
2558 wl_list_init(&shell->lock_layer.surface_list);
2560 shell_configuration(shell);
2562 if (wl_display_add_global(ec->wl_display, &wl_shell_interface,
2563 shell, bind_shell) == NULL)
2566 if (wl_display_add_global(ec->wl_display,
2567 &desktop_shell_interface,
2568 shell, bind_desktop_shell) == NULL)
2571 if (wl_display_add_global(ec->wl_display, &screensaver_interface,
2572 shell, bind_screensaver) == NULL)
2575 shell->child.deathstamp = weston_compositor_get_time();
2576 if (launch_desktop_shell_process(shell) != 0)
2579 shell_add_bindings(ec, shell);