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