blob: 20bc355fa9e94a04526f948f8ad3289c8c1b40fa [file] [log] [blame]
Kristian Høgsberg4cca3492011-01-18 07:53:49 -05001/*
Kristian Høgsberg07045392012-02-19 18:52:44 -05002 * Copyright © 2010-2012 Intel Corporation
Pekka Paalanend581a8f2012-01-27 16:25:16 +02003 * Copyright © 2011-2012 Collabora, Ltd.
Kristian Høgsberg4cca3492011-01-18 07:53:49 -05004 *
5 * Permission to use, copy, modify, distribute, and sell this software and
6 * its documentation for any purpose is hereby granted without fee, provided
7 * that the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of the copyright holders not be used in
10 * advertising or publicity pertaining to distribution of the software
11 * without specific, written prior permission. The copyright holders make
12 * no representations about the suitability of this software for any
13 * purpose. It is provided "as is" without express or implied warranty.
14 *
15 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
16 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
20 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 */
23
24#include <stdlib.h>
Kristian Høgsberg75840622011-09-06 13:48:16 -040025#include <stdio.h>
Pekka Paalanen9ef3e012011-11-15 13:34:48 +020026#include <stdbool.h>
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050027#include <string.h>
28#include <unistd.h>
Kristian Høgsberg07937562011-04-12 17:25:42 -040029#include <linux/input.h>
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +020030#include <assert.h>
Pekka Paalanen18027e52011-12-02 16:31:49 +020031#include <signal.h>
Pekka Paalanen460099f2012-01-20 16:48:25 +020032#include <math.h>
Kristian Høgsberg92a57db2012-05-26 13:41:06 -040033#include <sys/types.h>
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050034
Pekka Paalanen50719bc2011-11-22 14:18:50 +020035#include <wayland-server.h>
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050036#include "compositor.h"
Kristian Høgsberg75840622011-09-06 13:48:16 -040037#include "desktop-shell-server-protocol.h"
Jonas Ådahle9d22502012-08-29 22:13:01 +020038#include "workspaces-server-protocol.h"
Pekka Paalanene955f1e2011-12-07 11:49:52 +020039#include "../shared/config-parser.h"
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050040
Jonas Ådahle3cddce2012-06-13 00:01:22 +020041#define DEFAULT_NUM_WORKSPACES 1
Jonas Ådahl62fcd042012-06-13 00:01:23 +020042#define DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH 200
Jonas Ådahle3cddce2012-06-13 00:01:22 +020043
Juan Zhaoe10d2792012-04-25 19:09:52 +080044enum animation_type {
45 ANIMATION_NONE,
46
47 ANIMATION_ZOOM,
48 ANIMATION_FADE
49};
50
Jonas Ådahl04769742012-06-13 00:01:24 +020051struct focus_state {
52 struct weston_seat *seat;
Kristian Høgsberg2f5faff2012-07-31 16:36:34 -040053 struct workspace *ws;
Jonas Ådahl04769742012-06-13 00:01:24 +020054 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
Jonas Ådahle3cddce2012-06-13 00:01:22 +020060struct workspace {
61 struct weston_layer layer;
Jonas Ådahl04769742012-06-13 00:01:24 +020062
63 struct wl_list focus_list;
64 struct wl_listener seat_destroyed_listener;
Jonas Ådahle3cddce2012-06-13 00:01:22 +020065};
66
Philipp Brüschweiler88013572012-08-06 13:44:42 +020067struct input_panel_surface {
68 struct wl_list link;
69 struct weston_surface *surface;
70 struct wl_listener listener;
71};
72
Tiago Vignattibe143262012-04-16 17:31:41 +030073struct desktop_shell {
Kristian Høgsberg8334bc12012-01-03 10:29:47 -050074 struct weston_compositor *compositor;
Kristian Høgsberg02e79dc2012-04-12 09:55:26 -040075
76 struct wl_listener lock_listener;
77 struct wl_listener unlock_listener;
78 struct wl_listener destroy_listener;
Jan Arne Petersen42feced2012-06-21 21:52:17 +020079 struct wl_listener show_input_panel_listener;
80 struct wl_listener hide_input_panel_listener;
Pekka Paalanen6cd281a2011-11-03 14:11:32 +020081
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -050082 struct weston_layer fullscreen_layer;
83 struct weston_layer panel_layer;
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -050084 struct weston_layer background_layer;
85 struct weston_layer lock_layer;
Philipp Brüschweiler711fda82012-08-09 18:50:43 +020086 struct weston_layer input_panel_layer;
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -050087
Kristian Høgsbergd56bd902012-06-05 09:58:51 -040088 struct wl_listener pointer_focus_listener;
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +030089 struct weston_surface *grab_surface;
Kristian Høgsbergd56bd902012-06-05 09:58:51 -040090
Pekka Paalanen6cd281a2011-11-03 14:11:32 +020091 struct {
Kristian Høgsberg8334bc12012-01-03 10:29:47 -050092 struct weston_process process;
Pekka Paalanen6cd281a2011-11-03 14:11:32 +020093 struct wl_client *client;
Pekka Paalanen9ef3e012011-11-15 13:34:48 +020094 struct wl_resource *desktop_shell;
Pekka Paalanen4d733ee2012-01-17 14:36:27 +020095
96 unsigned deathcount;
97 uint32_t deathstamp;
Pekka Paalanen6cd281a2011-11-03 14:11:32 +020098 } child;
Pekka Paalanen9ef3e012011-11-15 13:34:48 +020099
100 bool locked;
Philipp Brüschweiler711fda82012-08-09 18:50:43 +0200101 bool showing_input_panels;
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200102 bool prepare_event_sent;
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +0200103
Kristian Høgsberg730c94d2012-06-26 21:44:35 -0400104 struct weston_surface *lock_surface;
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500105 struct wl_listener lock_surface_listener;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100106
Pekka Paalanen77346a62011-11-30 16:26:35 +0200107 struct {
Jonas Ådahle3cddce2012-06-13 00:01:22 +0200108 struct wl_array array;
109 unsigned int current;
110 unsigned int num;
Jonas Ådahl62fcd042012-06-13 00:01:23 +0200111
Jonas Ådahle9d22502012-08-29 22:13:01 +0200112 struct wl_list client_list;
113
Jonas Ådahl62fcd042012-06-13 00:01:23 +0200114 struct weston_animation animation;
Jonas Ådahl8de6a1d2012-08-29 22:13:00 +0200115 struct wl_list anim_sticky_list;
Jonas Ådahl62fcd042012-06-13 00:01:23 +0200116 int anim_dir;
117 uint32_t anim_timestamp;
118 double anim_current;
119 struct workspace *anim_from;
120 struct workspace *anim_to;
Jonas Ådahle3cddce2012-06-13 00:01:22 +0200121 } workspaces;
122
123 struct {
Pekka Paalanen3c647232011-12-22 13:43:43 +0200124 char *path;
Pekka Paalanen7296e792011-12-07 16:22:00 +0200125 int duration;
Pekka Paalanen77346a62011-11-30 16:26:35 +0200126 struct wl_resource *binding;
127 struct wl_list surfaces;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500128 struct weston_process process;
Pekka Paalanen77346a62011-11-30 16:26:35 +0200129 } screensaver;
Kristian Høgsbergb41c0812012-03-04 14:53:40 -0500130
Jan Arne Petersen42feced2012-06-21 21:52:17 +0200131 struct {
132 struct wl_resource *binding;
133 struct wl_list surfaces;
134 } input_panel;
135
Tiago Vignatti0b52d482012-04-20 18:54:25 +0300136 uint32_t binding_modifier;
Juan Zhaoe10d2792012-04-25 19:09:52 +0800137 enum animation_type win_animation_type;
Kristian Høgsbergb41c0812012-03-04 14:53:40 -0500138 struct weston_surface *debug_repaint_surface;
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400139};
140
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500141enum shell_surface_type {
Pekka Paalanen98262232011-12-01 10:42:22 +0200142 SHELL_SURFACE_NONE,
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500143 SHELL_SURFACE_TOPLEVEL,
144 SHELL_SURFACE_TRANSIENT,
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500145 SHELL_SURFACE_FULLSCREEN,
Juan Zhao96879df2012-02-07 08:45:41 +0800146 SHELL_SURFACE_MAXIMIZED,
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500147 SHELL_SURFACE_POPUP
Pekka Paalanen57da4a82011-11-23 16:42:16 +0200148};
149
Scott Moreauff1db4a2012-04-17 19:06:18 -0600150struct ping_timer {
151 struct wl_event_source *source;
Scott Moreauff1db4a2012-04-17 19:06:18 -0600152 uint32_t serial;
153};
154
Pekka Paalanen56cdea92011-11-23 16:14:12 +0200155struct shell_surface {
Pekka Paalanen9d1613e2011-11-25 12:09:16 +0200156 struct wl_resource resource;
157
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500158 struct weston_surface *surface;
Pekka Paalanen9d1613e2011-11-25 12:09:16 +0200159 struct wl_listener surface_destroy_listener;
Kristian Høgsberg8150b192012-06-27 10:22:58 -0400160 struct weston_surface *parent;
Tiago Vignattibe143262012-04-16 17:31:41 +0300161 struct desktop_shell *shell;
Pekka Paalanen57da4a82011-11-23 16:42:16 +0200162
Kristian Høgsberg7f366e72012-04-27 17:20:01 -0400163 enum shell_surface_type type, next_type;
Kristian Høgsberge7afd912012-05-02 09:47:44 -0400164 char *title, *class;
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500165 int32_t saved_x, saved_y;
Alex Wu4539b082012-03-01 12:57:46 +0800166 bool saved_position_valid;
Alex Wu7bcb8bd2012-04-27 09:07:24 +0800167 bool saved_rotation_valid;
Scott Moreauff1db4a2012-04-17 19:06:18 -0600168 int unresponsive;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100169
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500170 struct {
Pekka Paalanen460099f2012-01-20 16:48:25 +0200171 struct weston_transform transform;
Kristian Høgsberg765e27b2012-01-27 13:36:13 -0500172 struct weston_matrix rotation;
Pekka Paalanen460099f2012-01-20 16:48:25 +0200173 } rotation;
174
175 struct {
Scott Moreau447013d2012-02-18 05:05:29 -0700176 struct wl_pointer_grab grab;
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500177 int32_t x, y;
Pekka Paalanen938269a2012-02-07 14:19:01 +0200178 struct weston_transform parent_transform;
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500179 int32_t initial_up;
Daniel Stone37816df2012-05-16 18:45:18 +0100180 struct wl_seat *seat;
Kristian Høgsberg3730f362012-04-13 12:40:07 -0400181 uint32_t serial;
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -0500182 } popup;
183
Alex Wu4539b082012-03-01 12:57:46 +0800184 struct {
Tiago Vignatti52e598c2012-05-07 15:23:08 +0300185 int32_t x, y;
Tiago Vignatti491bac12012-05-18 16:37:43 -0400186 uint32_t flags;
Tiago Vignatti52e598c2012-05-07 15:23:08 +0300187 } transient;
188
189 struct {
Alex Wu4539b082012-03-01 12:57:46 +0800190 enum wl_shell_surface_fullscreen_method type;
191 struct weston_transform transform; /* matrix from x, y */
192 uint32_t framerate;
193 struct weston_surface *black_surface;
194 } fullscreen;
195
Scott Moreauff1db4a2012-04-17 19:06:18 -0600196 struct ping_timer *ping_timer;
197
Jonas Ådahl62fcd042012-06-13 00:01:23 +0200198 struct weston_transform workspace_transform;
199
Kristian Høgsberg1cbf3262012-02-17 23:49:07 -0500200 struct weston_output *fullscreen_output;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500201 struct weston_output *output;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100202 struct wl_list link;
Kristian Høgsberga61ca062012-05-22 16:05:52 -0400203
204 const struct weston_shell_client *client;
Pekka Paalanen56cdea92011-11-23 16:14:12 +0200205};
206
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +0300207struct shell_grab {
Scott Moreau447013d2012-02-18 05:05:29 -0700208 struct wl_pointer_grab grab;
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +0300209 struct shell_surface *shsurf;
210 struct wl_listener shsurf_destroy_listener;
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300211 struct wl_pointer *pointer;
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +0300212};
213
214struct weston_move_grab {
215 struct shell_grab base;
Daniel Stone103db7f2012-05-08 17:17:55 +0100216 wl_fixed_t dx, dy;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500217};
218
Pekka Paalanen460099f2012-01-20 16:48:25 +0200219struct rotate_grab {
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +0300220 struct shell_grab base;
Kristian Høgsberg765e27b2012-01-27 13:36:13 -0500221 struct weston_matrix rotation;
Pekka Paalanen460099f2012-01-20 16:48:25 +0200222 struct {
Kristian Høgsbergb2af93e2012-06-07 20:10:23 -0400223 GLfloat x;
224 GLfloat y;
Pekka Paalanen460099f2012-01-20 16:48:25 +0200225 } center;
226};
227
Kristian Høgsberg2f5faff2012-07-31 16:36:34 -0400228static void
229activate(struct desktop_shell *shell, struct weston_surface *es,
230 struct weston_seat *seat);
231
232static struct workspace *
233get_current_workspace(struct desktop_shell *shell);
234
Alex Wubd3354b2012-04-17 17:20:49 +0800235static struct shell_surface *
236get_shell_surface(struct weston_surface *surface);
237
238static struct desktop_shell *
239shell_surface_get_shell(struct shell_surface *shsurf);
240
241static bool
242shell_surface_is_top_fullscreen(struct shell_surface *shsurf)
243{
244 struct desktop_shell *shell;
245 struct weston_surface *top_fs_es;
246
247 shell = shell_surface_get_shell(shsurf);
248
249 if (wl_list_empty(&shell->fullscreen_layer.surface_list))
250 return false;
251
252 top_fs_es = container_of(shell->fullscreen_layer.surface_list.next,
253 struct weston_surface,
254 layer_link);
255 return (shsurf == get_shell_surface(top_fs_es));
256}
257
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500258static void
Kristian Høgsberg27e30522012-04-11 23:18:23 -0400259destroy_shell_grab_shsurf(struct wl_listener *listener, void *data)
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +0300260{
261 struct shell_grab *grab;
262
263 grab = container_of(listener, struct shell_grab,
264 shsurf_destroy_listener);
265
266 grab->shsurf = NULL;
267}
268
269static void
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300270shell_grab_start(struct shell_grab *grab,
271 const struct wl_pointer_grab_interface *interface,
272 struct shell_surface *shsurf,
273 struct wl_pointer *pointer,
274 enum desktop_shell_cursor cursor)
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +0300275{
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300276 struct desktop_shell *shell = shsurf->shell;
277
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +0300278 grab->grab.interface = interface;
279 grab->shsurf = shsurf;
Kristian Høgsberg27e30522012-04-11 23:18:23 -0400280 grab->shsurf_destroy_listener.notify = destroy_shell_grab_shsurf;
281 wl_signal_add(&shsurf->resource.destroy_signal,
282 &grab->shsurf_destroy_listener);
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +0300283
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300284 grab->pointer = pointer;
285 grab->grab.focus = &shsurf->surface->surface;
286
287 wl_pointer_start_grab(pointer, &grab->grab);
288 desktop_shell_send_grab_cursor(shell->child.desktop_shell, cursor);
289 wl_pointer_set_focus(pointer, &shell->grab_surface->surface,
290 wl_fixed_from_int(0), wl_fixed_from_int(0));
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +0300291}
292
293static void
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300294shell_grab_end(struct shell_grab *grab)
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +0300295{
Kristian Høgsberg47b5dca2012-06-07 18:08:04 -0400296 if (grab->shsurf)
297 wl_list_remove(&grab->shsurf_destroy_listener.link);
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300298
299 wl_pointer_end_grab(grab->pointer);
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +0300300}
301
302static void
Alex Wu4539b082012-03-01 12:57:46 +0800303center_on_output(struct weston_surface *surface,
304 struct weston_output *output);
305
Daniel Stone496ca172012-05-30 16:31:42 +0100306static enum weston_keyboard_modifier
Tiago Vignatti0b52d482012-04-20 18:54:25 +0300307get_modifier(char *modifier)
308{
309 if (!modifier)
310 return MODIFIER_SUPER;
311
312 if (!strcmp("ctrl", modifier))
313 return MODIFIER_CTRL;
314 else if (!strcmp("alt", modifier))
315 return MODIFIER_ALT;
316 else if (!strcmp("super", modifier))
317 return MODIFIER_SUPER;
318 else
319 return MODIFIER_SUPER;
320}
321
Juan Zhaoe10d2792012-04-25 19:09:52 +0800322static enum animation_type
323get_animation_type(char *animation)
324{
325 if (!animation)
326 return ANIMATION_NONE;
327
328 if (!strcmp("zoom", animation))
329 return ANIMATION_ZOOM;
330 else if (!strcmp("fade", animation))
331 return ANIMATION_FADE;
332 else
333 return ANIMATION_NONE;
334}
335
Alex Wu4539b082012-03-01 12:57:46 +0800336static void
Tiago Vignattibe143262012-04-16 17:31:41 +0300337shell_configuration(struct desktop_shell *shell)
Pekka Paalanene955f1e2011-12-07 11:49:52 +0200338{
Pekka Paalanene955f1e2011-12-07 11:49:52 +0200339 char *config_file;
Pekka Paalanen7296e792011-12-07 16:22:00 +0200340 char *path = NULL;
341 int duration = 60;
Jonas Ådahle3cddce2012-06-13 00:01:22 +0200342 unsigned int num_workspaces = DEFAULT_NUM_WORKSPACES;
Tiago Vignatti0b52d482012-04-20 18:54:25 +0300343 char *modifier = NULL;
Juan Zhaoe10d2792012-04-25 19:09:52 +0800344 char *win_animation = NULL;
Pekka Paalanene955f1e2011-12-07 11:49:52 +0200345
Kristian Høgsberga4e8b332012-04-20 16:48:21 -0400346 struct config_key shell_keys[] = {
Tiago Vignatti0b52d482012-04-20 18:54:25 +0300347 { "binding-modifier", CONFIG_KEY_STRING, &modifier },
Juan Zhaoe10d2792012-04-25 19:09:52 +0800348 { "animation", CONFIG_KEY_STRING, &win_animation},
Jonas Ådahle3cddce2012-06-13 00:01:22 +0200349 { "num-workspaces",
350 CONFIG_KEY_UNSIGNED_INTEGER, &num_workspaces },
Pekka Paalanene955f1e2011-12-07 11:49:52 +0200351 };
352
Kristian Høgsberga4e8b332012-04-20 16:48:21 -0400353 struct config_key saver_keys[] = {
354 { "path", CONFIG_KEY_STRING, &path },
355 { "duration", CONFIG_KEY_INTEGER, &duration },
356 };
357
Pekka Paalanene955f1e2011-12-07 11:49:52 +0200358 struct config_section cs[] = {
Kristian Høgsberga4e8b332012-04-20 16:48:21 -0400359 { "shell", shell_keys, ARRAY_LENGTH(shell_keys), NULL },
Pekka Paalanene955f1e2011-12-07 11:49:52 +0200360 { "screensaver", saver_keys, ARRAY_LENGTH(saver_keys), NULL },
361 };
362
Tiago Vignatti9a206c42012-03-21 19:49:18 +0200363 config_file = config_file_path("weston.ini");
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -0500364 parse_config_file(config_file, cs, ARRAY_LENGTH(cs), shell);
Pekka Paalanene955f1e2011-12-07 11:49:52 +0200365 free(config_file);
366
Pekka Paalanen7296e792011-12-07 16:22:00 +0200367 shell->screensaver.path = path;
368 shell->screensaver.duration = duration;
Tiago Vignatti0b52d482012-04-20 18:54:25 +0300369 shell->binding_modifier = get_modifier(modifier);
Juan Zhaoe10d2792012-04-25 19:09:52 +0800370 shell->win_animation_type = get_animation_type(win_animation);
Jonas Ådahle3cddce2012-06-13 00:01:22 +0200371 shell->workspaces.num = num_workspaces > 0 ? num_workspaces : 1;
372}
373
374static void
Jonas Ådahl04769742012-06-13 00:01:24 +0200375focus_state_destroy(struct focus_state *state)
376{
377 wl_list_remove(&state->seat_destroy_listener.link);
378 wl_list_remove(&state->surface_destroy_listener.link);
379 free(state);
380}
381
382static void
383focus_state_seat_destroy(struct wl_listener *listener, void *data)
384{
385 struct focus_state *state = container_of(listener,
386 struct focus_state,
387 seat_destroy_listener);
388
389 wl_list_remove(&state->link);
390 focus_state_destroy(state);
391}
392
393static void
394focus_state_surface_destroy(struct wl_listener *listener, void *data)
395{
396 struct focus_state *state = container_of(listener,
397 struct focus_state,
Kristian Høgsbergb8e0d0f2012-07-31 10:30:26 -0400398 surface_destroy_listener);
Kristian Høgsberge3778222012-07-31 17:29:30 -0400399 struct desktop_shell *shell;
400 struct weston_surface *surface, *next;
Jonas Ådahl04769742012-06-13 00:01:24 +0200401
Kristian Høgsberge3778222012-07-31 17:29:30 -0400402 next = NULL;
403 wl_list_for_each(surface, &state->ws->layer.surface_list, layer_link) {
404 if (surface == state->keyboard_focus)
405 continue;
406
407 next = surface;
408 break;
409 }
410
411 if (next) {
412 shell = state->seat->compositor->shell_interface.shell;
413 activate(shell, next, state->seat);
414 } else {
415 wl_list_remove(&state->link);
416 focus_state_destroy(state);
417 }
Jonas Ådahl04769742012-06-13 00:01:24 +0200418}
419
420static struct focus_state *
Kristian Høgsberg2f5faff2012-07-31 16:36:34 -0400421focus_state_create(struct weston_seat *seat, struct workspace *ws)
Jonas Ådahl04769742012-06-13 00:01:24 +0200422{
Jonas Ådahl04769742012-06-13 00:01:24 +0200423 struct focus_state *state;
Jonas Ådahl04769742012-06-13 00:01:24 +0200424
425 state = malloc(sizeof *state);
426 if (state == NULL)
427 return NULL;
428
Kristian Høgsberg2f5faff2012-07-31 16:36:34 -0400429 state->ws = ws;
Jonas Ådahl04769742012-06-13 00:01:24 +0200430 state->seat = seat;
Kristian Høgsberg2f5faff2012-07-31 16:36:34 -0400431 wl_list_insert(&ws->focus_list, &state->link);
Jonas Ådahl04769742012-06-13 00:01:24 +0200432
433 state->seat_destroy_listener.notify = focus_state_seat_destroy;
434 state->surface_destroy_listener.notify = focus_state_surface_destroy;
435 wl_signal_add(&seat->seat.destroy_signal,
436 &state->seat_destroy_listener);
Kristian Høgsberg2f5faff2012-07-31 16:36:34 -0400437 wl_list_init(&state->surface_destroy_listener.link);
Jonas Ådahl04769742012-06-13 00:01:24 +0200438
439 return state;
440}
441
442static void
Kristian Høgsberg2f5faff2012-07-31 16:36:34 -0400443restore_focus_state(struct desktop_shell *shell, struct workspace *ws)
Jonas Ådahl04769742012-06-13 00:01:24 +0200444{
445 struct focus_state *state, *next;
Jonas Ådahl56899442012-08-29 22:12:59 +0200446 struct wl_surface *surface;
Jonas Ådahl04769742012-06-13 00:01:24 +0200447
448 wl_list_for_each_safe(state, next, &ws->focus_list, link) {
Jonas Ådahl56899442012-08-29 22:12:59 +0200449 surface = state->keyboard_focus ?
450 &state->keyboard_focus->surface : NULL;
451
452 wl_keyboard_set_focus(state->seat->seat.keyboard, surface);
Jonas Ådahl04769742012-06-13 00:01:24 +0200453 }
454}
455
456static void
Jonas Ådahl8de6a1d2012-08-29 22:13:00 +0200457replace_focus_state(struct desktop_shell *shell, struct workspace *ws,
458 struct weston_seat *seat)
459{
460 struct focus_state *state;
461 struct wl_surface *surface;
462
463 wl_list_for_each(state, &ws->focus_list, link) {
464 if (state->seat == seat) {
465 surface = seat->seat.keyboard->focus;
466 state->keyboard_focus =
467 (struct weston_surface *) surface;
468 return;
469 }
470 }
471}
472
473static void
474drop_focus_state(struct desktop_shell *shell, struct workspace *ws,
475 struct weston_surface *surface)
476{
477 struct focus_state *state;
478
479 wl_list_for_each(state, &ws->focus_list, link)
480 if (state->keyboard_focus == surface)
481 state->keyboard_focus = NULL;
482}
483
484static void
Jonas Ådahle3cddce2012-06-13 00:01:22 +0200485workspace_destroy(struct workspace *ws)
486{
Jonas Ådahl04769742012-06-13 00:01:24 +0200487 struct focus_state *state, *next;
488
489 wl_list_for_each_safe(state, next, &ws->focus_list, link)
490 focus_state_destroy(state);
491
Jonas Ådahle3cddce2012-06-13 00:01:22 +0200492 free(ws);
493}
494
Jonas Ådahl04769742012-06-13 00:01:24 +0200495static void
496seat_destroyed(struct wl_listener *listener, void *data)
497{
498 struct weston_seat *seat = data;
499 struct focus_state *state, *next;
500 struct workspace *ws = container_of(listener,
501 struct workspace,
502 seat_destroyed_listener);
503
504 wl_list_for_each_safe(state, next, &ws->focus_list, link)
505 if (state->seat == seat)
506 wl_list_remove(&state->link);
507}
508
Jonas Ådahle3cddce2012-06-13 00:01:22 +0200509static struct workspace *
510workspace_create(void)
511{
512 struct workspace *ws = malloc(sizeof *ws);
513 if (ws == NULL)
514 return NULL;
515
516 weston_layer_init(&ws->layer, NULL);
517
Jonas Ådahl04769742012-06-13 00:01:24 +0200518 wl_list_init(&ws->focus_list);
519 wl_list_init(&ws->seat_destroyed_listener.link);
520 ws->seat_destroyed_listener.notify = seat_destroyed;
521
Jonas Ådahle3cddce2012-06-13 00:01:22 +0200522 return ws;
523}
524
Jonas Ådahl62fcd042012-06-13 00:01:23 +0200525static int
526workspace_is_empty(struct workspace *ws)
527{
528 return wl_list_empty(&ws->layer.surface_list);
529}
530
Jonas Ådahle3cddce2012-06-13 00:01:22 +0200531static struct workspace *
532get_workspace(struct desktop_shell *shell, unsigned int index)
533{
534 struct workspace **pws = shell->workspaces.array.data;
535 pws += index;
536 return *pws;
537}
538
539static struct workspace *
540get_current_workspace(struct desktop_shell *shell)
541{
542 return get_workspace(shell, shell->workspaces.current);
543}
544
545static void
546activate_workspace(struct desktop_shell *shell, unsigned int index)
547{
548 struct workspace *ws;
549
550 ws = get_workspace(shell, index);
551 wl_list_insert(&shell->panel_layer.link, &ws->layer.link);
552
553 shell->workspaces.current = index;
554}
555
Jonas Ådahl62fcd042012-06-13 00:01:23 +0200556static unsigned int
557get_output_height(struct weston_output *output)
558{
559 return abs(output->region.extents.y1 - output->region.extents.y2);
560}
561
562static void
563surface_translate(struct weston_surface *surface, double d)
564{
565 struct shell_surface *shsurf = get_shell_surface(surface);
566 struct weston_transform *transform;
567
568 transform = &shsurf->workspace_transform;
569 if (wl_list_empty(&transform->link))
570 wl_list_insert(surface->geometry.transformation_list.prev,
571 &shsurf->workspace_transform.link);
572
573 weston_matrix_init(&shsurf->workspace_transform.matrix);
574 weston_matrix_translate(&shsurf->workspace_transform.matrix,
575 0.0, d, 0.0);
576 surface->geometry.dirty = 1;
577}
578
579static void
580workspace_translate_out(struct workspace *ws, double fraction)
581{
582 struct weston_surface *surface;
583 unsigned int height;
584 double d;
585
586 wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
587 height = get_output_height(surface->output);
588 d = height * fraction;
589
590 surface_translate(surface, d);
591 }
592}
593
594static void
595workspace_translate_in(struct workspace *ws, double fraction)
596{
597 struct weston_surface *surface;
598 unsigned int height;
599 double d;
600
601 wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
602 height = get_output_height(surface->output);
603
604 if (fraction > 0)
605 d = -(height - height * fraction);
606 else
607 d = height + height * fraction;
608
609 surface_translate(surface, d);
610 }
611}
612
613static void
Jonas Ådahle9d22502012-08-29 22:13:01 +0200614broadcast_current_workspace_state(struct desktop_shell *shell)
615{
616 struct wl_resource *resource;
617
618 wl_list_for_each(resource, &shell->workspaces.client_list, link)
619 workspace_manager_send_state(resource,
620 shell->workspaces.current,
621 shell->workspaces.num);
622}
623
624static void
Jonas Ådahl62fcd042012-06-13 00:01:23 +0200625reverse_workspace_change_animation(struct desktop_shell *shell,
626 unsigned int index,
627 struct workspace *from,
628 struct workspace *to)
629{
630 shell->workspaces.current = index;
631
632 shell->workspaces.anim_to = to;
633 shell->workspaces.anim_from = from;
634 shell->workspaces.anim_dir = -1 * shell->workspaces.anim_dir;
635 shell->workspaces.anim_timestamp = 0;
636
Scott Moreau4272e632012-08-13 09:58:41 -0600637 weston_compositor_schedule_repaint(shell->compositor);
Jonas Ådahl62fcd042012-06-13 00:01:23 +0200638}
639
640static void
641workspace_deactivate_transforms(struct workspace *ws)
642{
643 struct weston_surface *surface;
644 struct shell_surface *shsurf;
645
646 wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
647 shsurf = get_shell_surface(surface);
Jonas Ådahl8de6a1d2012-08-29 22:13:00 +0200648 if (!wl_list_empty(&shsurf->workspace_transform.link)) {
649 wl_list_remove(&shsurf->workspace_transform.link);
650 wl_list_init(&shsurf->workspace_transform.link);
651 }
Jonas Ådahl62fcd042012-06-13 00:01:23 +0200652 shsurf->surface->geometry.dirty = 1;
653 }
654}
655
656static void
657finish_workspace_change_animation(struct desktop_shell *shell,
658 struct workspace *from,
659 struct workspace *to)
660{
Scott Moreau4272e632012-08-13 09:58:41 -0600661 weston_compositor_schedule_repaint(shell->compositor);
Jonas Ådahl62fcd042012-06-13 00:01:23 +0200662
663 wl_list_remove(&shell->workspaces.animation.link);
664 workspace_deactivate_transforms(from);
665 workspace_deactivate_transforms(to);
666 shell->workspaces.anim_to = NULL;
667
668 wl_list_remove(&shell->workspaces.anim_from->layer.link);
669}
670
671static void
672animate_workspace_change_frame(struct weston_animation *animation,
673 struct weston_output *output, uint32_t msecs)
674{
675 struct desktop_shell *shell =
676 container_of(animation, struct desktop_shell,
677 workspaces.animation);
678 struct workspace *from = shell->workspaces.anim_from;
679 struct workspace *to = shell->workspaces.anim_to;
680 uint32_t t;
681 double x, y;
682
683 if (workspace_is_empty(from) && workspace_is_empty(to)) {
684 finish_workspace_change_animation(shell, from, to);
685 return;
686 }
687
688 if (shell->workspaces.anim_timestamp == 0) {
689 if (shell->workspaces.anim_current == 0.0)
690 shell->workspaces.anim_timestamp = msecs;
691 else
692 shell->workspaces.anim_timestamp =
693 msecs -
694 /* Invers of movement function 'y' below. */
695 (asin(1.0 - shell->workspaces.anim_current) *
696 DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH *
697 M_2_PI);
698 }
699
700 t = msecs - shell->workspaces.anim_timestamp;
701
702 /*
703 * x = [0, π/2]
704 * y(x) = sin(x)
705 */
706 x = t * (1.0/DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH) * M_PI_2;
707 y = sin(x);
708
709 if (t < DEFAULT_WORKSPACE_CHANGE_ANIMATION_LENGTH) {
Scott Moreau4272e632012-08-13 09:58:41 -0600710 weston_compositor_schedule_repaint(shell->compositor);
Jonas Ådahl62fcd042012-06-13 00:01:23 +0200711
712 workspace_translate_out(from, shell->workspaces.anim_dir * y);
713 workspace_translate_in(to, shell->workspaces.anim_dir * y);
714 shell->workspaces.anim_current = y;
715
Scott Moreau4272e632012-08-13 09:58:41 -0600716 weston_compositor_schedule_repaint(shell->compositor);
Jonas Ådahl62fcd042012-06-13 00:01:23 +0200717 }
Jonas Ådahl04769742012-06-13 00:01:24 +0200718 else
Jonas Ådahl62fcd042012-06-13 00:01:23 +0200719 finish_workspace_change_animation(shell, from, to);
Jonas Ådahl62fcd042012-06-13 00:01:23 +0200720}
721
722static void
723animate_workspace_change(struct desktop_shell *shell,
724 unsigned int index,
725 struct workspace *from,
726 struct workspace *to)
727{
728 struct weston_output *output;
729
730 int dir;
731
732 if (index > shell->workspaces.current)
733 dir = -1;
734 else
735 dir = 1;
736
737 shell->workspaces.current = index;
738
739 shell->workspaces.anim_dir = dir;
740 shell->workspaces.anim_from = from;
741 shell->workspaces.anim_to = to;
742 shell->workspaces.anim_current = 0.0;
743 shell->workspaces.anim_timestamp = 0;
744
745 output = container_of(shell->compositor->output_list.next,
746 struct weston_output, link);
747 wl_list_insert(&output->animation_list,
748 &shell->workspaces.animation.link);
749
Jonas Ådahl8de6a1d2012-08-29 22:13:00 +0200750 wl_list_insert(from->layer.link.prev, &to->layer.link);
Jonas Ådahl62fcd042012-06-13 00:01:23 +0200751
752 workspace_translate_in(to, 0);
753
Kristian Høgsberg2f5faff2012-07-31 16:36:34 -0400754 restore_focus_state(shell, to);
Jonas Ådahl04769742012-06-13 00:01:24 +0200755
Scott Moreau4272e632012-08-13 09:58:41 -0600756 weston_compositor_schedule_repaint(shell->compositor);
Jonas Ådahl62fcd042012-06-13 00:01:23 +0200757}
758
Jonas Ådahle3cddce2012-06-13 00:01:22 +0200759static void
Jonas Ådahl8de6a1d2012-08-29 22:13:00 +0200760update_workspace(struct desktop_shell *shell, unsigned int index,
761 struct workspace *from, struct workspace *to)
762{
763 shell->workspaces.current = index;
764 wl_list_insert(&from->layer.link, &to->layer.link);
765 wl_list_remove(&from->layer.link);
766}
767
768static void
Jonas Ådahle3cddce2012-06-13 00:01:22 +0200769change_workspace(struct desktop_shell *shell, unsigned int index)
770{
771 struct workspace *from;
772 struct workspace *to;
Jonas Ådahle3cddce2012-06-13 00:01:22 +0200773
774 if (index == shell->workspaces.current)
775 return;
776
777 /* Don't change workspace when there is any fullscreen surfaces. */
778 if (!wl_list_empty(&shell->fullscreen_layer.surface_list))
779 return;
780
Jonas Ådahle3cddce2012-06-13 00:01:22 +0200781 from = get_current_workspace(shell);
782 to = get_workspace(shell, index);
783
Jonas Ådahl62fcd042012-06-13 00:01:23 +0200784 if (shell->workspaces.anim_from == to &&
785 shell->workspaces.anim_to == from) {
Jonas Ådahl8de6a1d2012-08-29 22:13:00 +0200786 restore_focus_state(shell, to);
Jonas Ådahl62fcd042012-06-13 00:01:23 +0200787 reverse_workspace_change_animation(shell, index, from, to);
Jonas Ådahle9d22502012-08-29 22:13:01 +0200788 broadcast_current_workspace_state(shell);
Jonas Ådahl62fcd042012-06-13 00:01:23 +0200789 return;
790 }
Jonas Ådahle3cddce2012-06-13 00:01:22 +0200791
Jonas Ådahl62fcd042012-06-13 00:01:23 +0200792 if (shell->workspaces.anim_to != NULL)
793 finish_workspace_change_animation(shell,
794 shell->workspaces.anim_from,
795 shell->workspaces.anim_to);
796
Jonas Ådahl8de6a1d2012-08-29 22:13:00 +0200797 restore_focus_state(shell, to);
Jonas Ådahl04769742012-06-13 00:01:24 +0200798
Jonas Ådahl8de6a1d2012-08-29 22:13:00 +0200799 if (workspace_is_empty(to) && workspace_is_empty(from))
800 update_workspace(shell, index, from, to);
Jonas Ådahl62fcd042012-06-13 00:01:23 +0200801 else
802 animate_workspace_change(shell, index, from, to);
Jonas Ådahle9d22502012-08-29 22:13:01 +0200803
804 broadcast_current_workspace_state(shell);
Pekka Paalanene955f1e2011-12-07 11:49:52 +0200805}
806
Jonas Ådahl8de6a1d2012-08-29 22:13:00 +0200807static bool
808workspace_has_only(struct workspace *ws, struct weston_surface *surface)
809{
810 struct wl_list *list = &ws->layer.surface_list;
811 struct wl_list *e;
812
813 if (wl_list_empty(list))
814 return false;
815
816 e = list->next;
817
818 if (e->next != list)
819 return false;
820
821 return container_of(e, struct weston_surface, layer_link) == surface;
822}
823
824static void
Jonas Ådahle9d22502012-08-29 22:13:01 +0200825move_surface_to_workspace(struct desktop_shell *shell,
826 struct weston_surface *surface,
827 uint32_t workspace)
828{
829 struct workspace *from;
830 struct workspace *to;
831 struct weston_seat *seat;
832
833 if (workspace == shell->workspaces.current)
834 return;
835
836 from = get_current_workspace(shell);
837 to = get_workspace(shell, workspace);
838
839 wl_list_remove(&surface->layer_link);
840 wl_list_insert(&to->layer.surface_list, &surface->layer_link);
841
842 drop_focus_state(shell, from, surface);
843 wl_list_for_each(seat, &shell->compositor->seat_list, link)
844 if (seat->has_keyboard &&
845 seat->keyboard.focus == &surface->surface)
846 wl_keyboard_set_focus(&seat->keyboard, NULL);
847
848 weston_surface_damage_below(surface);
849}
850
851static void
Jonas Ådahl8de6a1d2012-08-29 22:13:00 +0200852take_surface_to_workspace_by_seat(struct desktop_shell *shell,
Jonas Ådahle9d22502012-08-29 22:13:01 +0200853 struct wl_seat *wl_seat,
Jonas Ådahl8de6a1d2012-08-29 22:13:00 +0200854 unsigned int index)
855{
Jonas Ådahle9d22502012-08-29 22:13:01 +0200856 struct weston_seat *seat = (struct weston_seat *) wl_seat;
Jonas Ådahl8de6a1d2012-08-29 22:13:00 +0200857 struct weston_surface *surface =
Jonas Ådahle9d22502012-08-29 22:13:01 +0200858 (struct weston_surface *) wl_seat->keyboard->focus;
Jonas Ådahl8de6a1d2012-08-29 22:13:00 +0200859 struct shell_surface *shsurf;
860 struct workspace *from;
861 struct workspace *to;
862
863 if (surface == NULL ||
864 index == shell->workspaces.current)
865 return;
866
867 from = get_current_workspace(shell);
868 to = get_workspace(shell, index);
869
870 wl_list_remove(&surface->layer_link);
871 wl_list_insert(&to->layer.surface_list, &surface->layer_link);
872
Jonas Ådahle9d22502012-08-29 22:13:01 +0200873 replace_focus_state(shell, to, seat);
Jonas Ådahl8de6a1d2012-08-29 22:13:00 +0200874 drop_focus_state(shell, from, surface);
875
876 if (shell->workspaces.anim_from == to &&
877 shell->workspaces.anim_to == from) {
Jonas Ådahle9d22502012-08-29 22:13:01 +0200878 wl_list_remove(&to->layer.link);
879 wl_list_insert(from->layer.link.prev, &to->layer.link);
880
Jonas Ådahl8de6a1d2012-08-29 22:13:00 +0200881 reverse_workspace_change_animation(shell, index, from, to);
Jonas Ådahle9d22502012-08-29 22:13:01 +0200882 broadcast_current_workspace_state(shell);
883
Jonas Ådahl8de6a1d2012-08-29 22:13:00 +0200884 return;
885 }
886
887 if (shell->workspaces.anim_to != NULL)
888 finish_workspace_change_animation(shell,
889 shell->workspaces.anim_from,
890 shell->workspaces.anim_to);
891
892 if (workspace_is_empty(from) &&
893 workspace_has_only(to, surface))
894 update_workspace(shell, index, from, to);
895 else {
896 shsurf = get_shell_surface(surface);
897 if (wl_list_empty(&shsurf->workspace_transform.link))
898 wl_list_insert(&shell->workspaces.anim_sticky_list,
899 &shsurf->workspace_transform.link);
900
901 animate_workspace_change(shell, index, from, to);
902 }
Jonas Ådahle9d22502012-08-29 22:13:01 +0200903
904 broadcast_current_workspace_state(shell);
905}
906
907static void
908workspace_manager_move_surface(struct wl_client *client,
909 struct wl_resource *resource,
910 struct wl_resource *surface_resource,
911 uint32_t workspace)
912{
913 struct desktop_shell *shell = resource->data;
914 struct weston_surface *surface =
915 (struct weston_surface *) surface_resource;
916
917 move_surface_to_workspace(shell, surface, workspace);
918}
919
920static const struct workspace_manager_interface workspace_manager_implementation = {
921 workspace_manager_move_surface,
922};
923
924static void
925unbind_resource(struct wl_resource *resource)
926{
927 wl_list_remove(&resource->link);
928 free(resource);
929}
930
931static void
932bind_workspace_manager(struct wl_client *client,
933 void *data, uint32_t version, uint32_t id)
934{
935 struct desktop_shell *shell = data;
936 struct wl_resource *resource;
937
938 resource = wl_client_add_object(client, &workspace_manager_interface,
939 &workspace_manager_implementation,
940 id, shell);
941
942 if (resource == NULL) {
943 weston_log("couldn't add workspace manager object");
944 return;
945 }
946
947 resource->destroy = unbind_resource;
948 wl_list_insert(&shell->workspaces.client_list, &resource->link);
949
950 workspace_manager_send_state(resource,
951 shell->workspaces.current,
952 shell->workspaces.num);
Jonas Ådahl8de6a1d2012-08-29 22:13:00 +0200953}
954
Pekka Paalanen56cdea92011-11-23 16:14:12 +0200955static void
Kristian Høgsbergeae5de72012-04-11 22:42:15 -0400956noop_grab_focus(struct wl_pointer_grab *grab,
Daniel Stone103db7f2012-05-08 17:17:55 +0100957 struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y)
Kristian Høgsberg9ddb8262012-01-04 21:30:29 -0500958{
959 grab->focus = NULL;
960}
961
962static void
Scott Moreau447013d2012-02-18 05:05:29 -0700963move_grab_motion(struct wl_pointer_grab *grab,
Daniel Stone103db7f2012-05-08 17:17:55 +0100964 uint32_t time, wl_fixed_t x, wl_fixed_t y)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500965{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -0500966 struct weston_move_grab *move = (struct weston_move_grab *) grab;
Daniel Stone37816df2012-05-16 18:45:18 +0100967 struct wl_pointer *pointer = grab->pointer;
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +0300968 struct shell_surface *shsurf = move->base.shsurf;
969 struct weston_surface *es;
Daniel Stone37816df2012-05-16 18:45:18 +0100970 int dx = wl_fixed_to_int(pointer->x + move->dx);
971 int dy = wl_fixed_to_int(pointer->y + move->dy);
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +0300972
973 if (!shsurf)
974 return;
975
976 es = shsurf->surface;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500977
Daniel Stone103db7f2012-05-08 17:17:55 +0100978 weston_surface_configure(es, dx, dy,
Pekka Paalanen60921e52012-01-25 15:55:43 +0200979 es->geometry.width, es->geometry.height);
Kristian Høgsberg6c6fb992012-06-21 12:06:22 -0400980
981 weston_compositor_schedule_repaint(es->compositor);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500982}
983
984static void
Scott Moreau447013d2012-02-18 05:05:29 -0700985move_grab_button(struct wl_pointer_grab *grab,
Daniel Stone4dbadb12012-05-30 16:31:51 +0100986 uint32_t time, uint32_t button, uint32_t state_w)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500987{
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +0300988 struct shell_grab *shell_grab = container_of(grab, struct shell_grab,
989 grab);
Daniel Stone37816df2012-05-16 18:45:18 +0100990 struct wl_pointer *pointer = grab->pointer;
Daniel Stone4dbadb12012-05-30 16:31:51 +0100991 enum wl_pointer_button_state state = state_w;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500992
Daniel Stone4dbadb12012-05-30 16:31:51 +0100993 if (pointer->button_count == 0 &&
994 state == WL_POINTER_BUTTON_STATE_RELEASED) {
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +0300995 shell_grab_end(shell_grab);
Kristian Høgsberg9ddb8262012-01-04 21:30:29 -0500996 free(grab);
997 }
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500998}
999
Scott Moreau447013d2012-02-18 05:05:29 -07001000static const struct wl_pointer_grab_interface move_grab_interface = {
Kristian Høgsberg9ddb8262012-01-04 21:30:29 -05001001 noop_grab_focus,
Kristian Høgsberg4cca3492011-01-18 07:53:49 -05001002 move_grab_motion,
1003 move_grab_button,
Kristian Høgsberg4cca3492011-01-18 07:53:49 -05001004};
1005
Kristian Høgsberg9e31bff2012-08-01 00:08:07 -04001006static int
1007surface_move(struct shell_surface *shsurf, struct weston_seat *ws)
1008{
1009 struct weston_move_grab *move;
1010
1011 if (!shsurf)
1012 return -1;
1013
1014 if (shsurf->type == SHELL_SURFACE_FULLSCREEN)
1015 return 0;
1016
1017 move = malloc(sizeof *move);
1018 if (!move)
1019 return -1;
1020
1021 move->dx = wl_fixed_from_double(shsurf->surface->geometry.x) -
1022 ws->seat.pointer->grab_x;
1023 move->dy = wl_fixed_from_double(shsurf->surface->geometry.y) -
1024 ws->seat.pointer->grab_y;
1025
1026 shell_grab_start(&move->base, &move_grab_interface, shsurf,
1027 ws->seat.pointer, DESKTOP_SHELL_CURSOR_MOVE);
1028
1029 return 0;
1030}
1031
1032static void
1033shell_surface_move(struct wl_client *client, struct wl_resource *resource,
1034 struct wl_resource *seat_resource, uint32_t serial)
1035{
1036 struct weston_seat *ws = seat_resource->data;
1037 struct shell_surface *shsurf = resource->data;
1038
1039 if (ws->seat.pointer->button_count == 0 ||
1040 ws->seat.pointer->grab_serial != serial ||
1041 ws->seat.pointer->focus != &shsurf->surface->surface)
1042 return;
1043
1044 if (surface_move(shsurf, ws) < 0)
1045 wl_resource_post_no_memory(resource);
1046}
1047
1048struct weston_resize_grab {
1049 struct shell_grab base;
1050 uint32_t edges;
1051 int32_t width, height;
1052};
1053
1054static void
1055resize_grab_motion(struct wl_pointer_grab *grab,
1056 uint32_t time, wl_fixed_t x, wl_fixed_t y)
1057{
1058 struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
1059 struct wl_pointer *pointer = grab->pointer;
1060 struct shell_surface *shsurf = resize->base.shsurf;
1061 int32_t width, height;
1062 wl_fixed_t from_x, from_y;
1063 wl_fixed_t to_x, to_y;
1064
1065 if (!shsurf)
1066 return;
1067
1068 weston_surface_from_global_fixed(shsurf->surface,
1069 pointer->grab_x, pointer->grab_y,
1070 &from_x, &from_y);
1071 weston_surface_from_global_fixed(shsurf->surface,
1072 pointer->x, pointer->y, &to_x, &to_y);
1073
1074 width = resize->width;
1075 if (resize->edges & WL_SHELL_SURFACE_RESIZE_LEFT) {
1076 width += wl_fixed_to_int(from_x - to_x);
1077 } else if (resize->edges & WL_SHELL_SURFACE_RESIZE_RIGHT) {
1078 width += wl_fixed_to_int(to_x - from_x);
1079 }
1080
1081 height = resize->height;
1082 if (resize->edges & WL_SHELL_SURFACE_RESIZE_TOP) {
1083 height += wl_fixed_to_int(from_y - to_y);
1084 } else if (resize->edges & WL_SHELL_SURFACE_RESIZE_BOTTOM) {
1085 height += wl_fixed_to_int(to_y - from_y);
1086 }
1087
1088 shsurf->client->send_configure(shsurf->surface,
1089 resize->edges, width, height);
1090}
1091
1092static void
1093send_configure(struct weston_surface *surface,
1094 uint32_t edges, int32_t width, int32_t height)
1095{
1096 struct shell_surface *shsurf = get_shell_surface(surface);
1097
1098 wl_shell_surface_send_configure(&shsurf->resource,
1099 edges, width, height);
1100}
1101
1102static const struct weston_shell_client shell_client = {
1103 send_configure
1104};
1105
1106static void
1107resize_grab_button(struct wl_pointer_grab *grab,
1108 uint32_t time, uint32_t button, uint32_t state_w)
1109{
1110 struct weston_resize_grab *resize = (struct weston_resize_grab *) grab;
1111 struct wl_pointer *pointer = grab->pointer;
1112 enum wl_pointer_button_state state = state_w;
1113
1114 if (pointer->button_count == 0 &&
1115 state == WL_POINTER_BUTTON_STATE_RELEASED) {
1116 shell_grab_end(&resize->base);
1117 free(grab);
1118 }
1119}
1120
1121static const struct wl_pointer_grab_interface resize_grab_interface = {
1122 noop_grab_focus,
1123 resize_grab_motion,
1124 resize_grab_button,
1125};
1126
1127static int
1128surface_resize(struct shell_surface *shsurf,
1129 struct weston_seat *ws, uint32_t edges)
1130{
1131 struct weston_resize_grab *resize;
1132
1133 if (shsurf->type == SHELL_SURFACE_FULLSCREEN)
1134 return 0;
1135
1136 if (edges == 0 || edges > 15 ||
1137 (edges & 3) == 3 || (edges & 12) == 12)
1138 return 0;
1139
1140 resize = malloc(sizeof *resize);
1141 if (!resize)
1142 return -1;
1143
1144 resize->edges = edges;
1145 resize->width = shsurf->surface->geometry.width;
1146 resize->height = shsurf->surface->geometry.height;
1147
1148 shell_grab_start(&resize->base, &resize_grab_interface, shsurf,
1149 ws->seat.pointer, edges);
1150
1151 return 0;
1152}
1153
1154static void
1155shell_surface_resize(struct wl_client *client, struct wl_resource *resource,
1156 struct wl_resource *seat_resource, uint32_t serial,
1157 uint32_t edges)
1158{
1159 struct weston_seat *ws = seat_resource->data;
1160 struct shell_surface *shsurf = resource->data;
1161
1162 if (shsurf->type == SHELL_SURFACE_FULLSCREEN)
1163 return;
1164
1165 if (ws->seat.pointer->button_count == 0 ||
1166 ws->seat.pointer->grab_serial != serial ||
1167 ws->seat.pointer->focus != &shsurf->surface->surface)
1168 return;
1169
1170 if (surface_resize(shsurf, ws, edges) < 0)
1171 wl_resource_post_no_memory(resource);
1172}
1173
Scott Moreauc3e54eb2012-04-17 19:06:20 -06001174static void
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001175busy_cursor_grab_focus(struct wl_pointer_grab *base,
1176 struct wl_surface *surface, int32_t x, int32_t y)
Scott Moreauc3e54eb2012-04-17 19:06:20 -06001177{
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001178 struct shell_grab *grab = (struct shell_grab *) base;
Scott Moreauc3e54eb2012-04-17 19:06:20 -06001179
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001180 if (grab->grab.focus != surface) {
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03001181 shell_grab_end(grab);
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001182 free(grab);
Scott Moreauc3e54eb2012-04-17 19:06:20 -06001183 }
1184}
1185
1186static void
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001187busy_cursor_grab_motion(struct wl_pointer_grab *grab,
1188 uint32_t time, int32_t x, int32_t y)
Scott Moreauc3e54eb2012-04-17 19:06:20 -06001189{
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001190}
Scott Moreauc3e54eb2012-04-17 19:06:20 -06001191
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001192static void
Kristian Høgsbergbbe98392012-08-01 00:20:21 -04001193busy_cursor_grab_button(struct wl_pointer_grab *base,
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001194 uint32_t time, uint32_t button, uint32_t state)
1195{
Kristian Høgsbergbbe98392012-08-01 00:20:21 -04001196 struct shell_grab *grab = (struct shell_grab *) base;
1197 struct shell_surface *shsurf;
1198 struct weston_surface *surface =
1199 (struct weston_surface *) grab->grab.pointer->current;
1200 struct weston_seat *seat =
1201 (struct weston_seat *) grab->grab.pointer->seat;
1202
1203 shsurf = get_shell_surface(surface);
1204 if (shsurf && button == BTN_LEFT && state) {
1205 activate(shsurf->shell, shsurf->surface, seat);
1206 surface_move(shsurf, seat);
1207 }
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001208}
1209
1210static const struct wl_pointer_grab_interface busy_cursor_grab_interface = {
1211 busy_cursor_grab_focus,
1212 busy_cursor_grab_motion,
1213 busy_cursor_grab_button,
1214};
1215
1216static void
1217set_busy_cursor(struct shell_surface *shsurf, struct wl_pointer *pointer)
1218{
1219 struct shell_grab *grab;
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001220
1221 grab = malloc(sizeof *grab);
1222 if (!grab)
Scott Moreauc3e54eb2012-04-17 19:06:20 -06001223 return;
1224
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03001225 shell_grab_start(grab, &busy_cursor_grab_interface, shsurf, pointer,
1226 DESKTOP_SHELL_CURSOR_BUSY);
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001227}
Scott Moreauc3e54eb2012-04-17 19:06:20 -06001228
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001229static void
1230end_busy_cursor(struct shell_surface *shsurf, struct wl_pointer *pointer)
1231{
1232 struct shell_grab *grab = (struct shell_grab *) pointer->grab;
1233
1234 if (grab->grab.interface == &busy_cursor_grab_interface) {
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03001235 shell_grab_end(grab);
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001236 free(grab);
Scott Moreauc3e54eb2012-04-17 19:06:20 -06001237 }
Scott Moreauc3e54eb2012-04-17 19:06:20 -06001238}
1239
Scott Moreau9521d5e2012-04-19 13:06:17 -06001240static void
1241ping_timer_destroy(struct shell_surface *shsurf)
1242{
1243 if (!shsurf || !shsurf->ping_timer)
1244 return;
1245
1246 if (shsurf->ping_timer->source)
1247 wl_event_source_remove(shsurf->ping_timer->source);
1248
1249 free(shsurf->ping_timer);
1250 shsurf->ping_timer = NULL;
1251}
1252
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -04001253static int
Scott Moreauff1db4a2012-04-17 19:06:18 -06001254ping_timeout_handler(void *data)
1255{
1256 struct shell_surface *shsurf = data;
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001257 struct weston_seat *seat;
Scott Moreauff1db4a2012-04-17 19:06:18 -06001258
Scott Moreau9521d5e2012-04-19 13:06:17 -06001259 /* Client is not responding */
1260 shsurf->unresponsive = 1;
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001261
1262 wl_list_for_each(seat, &shsurf->surface->compositor->seat_list, link)
1263 if (seat->seat.pointer->focus == &shsurf->surface->surface)
1264 set_busy_cursor(shsurf, seat->seat.pointer);
Scott Moreauff1db4a2012-04-17 19:06:18 -06001265
1266 return 1;
1267}
1268
1269static void
1270ping_handler(struct weston_surface *surface, uint32_t serial)
1271{
Kristian Høgsbergb71302e2012-05-10 12:28:35 -04001272 struct shell_surface *shsurf = get_shell_surface(surface);
Scott Moreauff1db4a2012-04-17 19:06:18 -06001273 struct wl_event_loop *loop;
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001274 int ping_timeout = 200;
Scott Moreauff1db4a2012-04-17 19:06:18 -06001275
1276 if (!shsurf)
1277 return;
Kristian Høgsbergca535c12012-04-21 23:20:07 -04001278 if (!shsurf->resource.client)
1279 return;
Scott Moreauff1db4a2012-04-17 19:06:18 -06001280
Ander Conselvan de Oliveiraeac9a462012-07-16 14:15:48 +03001281 if (shsurf->surface == shsurf->shell->grab_surface)
1282 return;
1283
Scott Moreauff1db4a2012-04-17 19:06:18 -06001284 if (!shsurf->ping_timer) {
Ander Conselvan de Oliveirafb980892012-04-27 13:55:55 +03001285 shsurf->ping_timer = malloc(sizeof *shsurf->ping_timer);
Scott Moreauff1db4a2012-04-17 19:06:18 -06001286 if (!shsurf->ping_timer)
1287 return;
1288
1289 shsurf->ping_timer->serial = serial;
Scott Moreauff1db4a2012-04-17 19:06:18 -06001290 loop = wl_display_get_event_loop(surface->compositor->wl_display);
1291 shsurf->ping_timer->source =
1292 wl_event_loop_add_timer(loop, ping_timeout_handler, shsurf);
1293 wl_event_source_timer_update(shsurf->ping_timer->source, ping_timeout);
1294
1295 wl_shell_surface_send_ping(&shsurf->resource, serial);
1296 }
1297}
1298
1299static void
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001300handle_pointer_focus(struct wl_listener *listener, void *data)
1301{
1302 struct wl_pointer *pointer = data;
1303 struct weston_surface *surface =
1304 (struct weston_surface *) pointer->focus;
1305 struct weston_compositor *compositor;
1306 struct shell_surface *shsurf;
1307 uint32_t serial;
1308
1309 if (!surface)
1310 return;
1311
1312 compositor = surface->compositor;
1313 shsurf = get_shell_surface(surface);
1314
Pekka Paalanen4e1f2ff2012-06-06 16:59:45 +03001315 if (shsurf && shsurf->unresponsive) {
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001316 set_busy_cursor(shsurf, pointer);
1317 } else {
1318 serial = wl_display_next_serial(compositor->wl_display);
1319 ping_handler(surface, serial);
1320 }
1321}
1322
1323static void
Kristian Høgsbergf4d2f232012-08-10 10:05:39 -04001324create_pointer_focus_listener(struct weston_seat *seat)
1325{
1326 struct wl_listener *listener;
1327
1328 if (!seat->seat.pointer)
1329 return;
1330
1331 listener = malloc(sizeof *listener);
1332 listener->notify = handle_pointer_focus;
1333 wl_signal_add(&seat->seat.pointer->focus_signal, listener);
1334}
1335
1336static void
Scott Moreauff1db4a2012-04-17 19:06:18 -06001337shell_surface_pong(struct wl_client *client, struct wl_resource *resource,
1338 uint32_t serial)
1339{
1340 struct shell_surface *shsurf = resource->data;
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001341 struct desktop_shell *shell = shsurf->shell;
1342 struct weston_seat *seat;
1343 struct weston_compositor *ec = shsurf->surface->compositor;
1344 struct wl_pointer *pointer;
1345 int was_unresponsive;
Scott Moreauff1db4a2012-04-17 19:06:18 -06001346
Kristian Høgsberg92374e12012-08-11 22:39:12 -04001347 if (shsurf->ping_timer == NULL)
1348 /* Just ignore unsolicited pong. */
1349 return;
1350
Scott Moreauff1db4a2012-04-17 19:06:18 -06001351 if (shsurf->ping_timer->serial == serial) {
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001352 was_unresponsive = shsurf->unresponsive;
Scott Moreauff1db4a2012-04-17 19:06:18 -06001353 shsurf->unresponsive = 0;
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001354 if (was_unresponsive) {
1355 /* Received pong from previously unresponsive client */
1356 wl_list_for_each(seat, &ec->seat_list, link) {
1357 pointer = seat->seat.pointer;
1358 if (pointer->focus ==
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03001359 &shell->grab_surface->surface &&
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04001360 pointer->current ==
1361 &shsurf->surface->surface)
1362 end_busy_cursor(shsurf, pointer);
1363 }
1364 }
Scott Moreau9521d5e2012-04-19 13:06:17 -06001365 ping_timer_destroy(shsurf);
Scott Moreauff1db4a2012-04-17 19:06:18 -06001366 }
1367}
1368
Kristian Høgsberge7afd912012-05-02 09:47:44 -04001369static void
1370shell_surface_set_title(struct wl_client *client,
1371 struct wl_resource *resource, const char *title)
1372{
1373 struct shell_surface *shsurf = resource->data;
1374
1375 free(shsurf->title);
1376 shsurf->title = strdup(title);
1377}
1378
1379static void
1380shell_surface_set_class(struct wl_client *client,
1381 struct wl_resource *resource, const char *class)
1382{
1383 struct shell_surface *shsurf = resource->data;
1384
1385 free(shsurf->class);
1386 shsurf->class = strdup(class);
1387}
1388
Juan Zhao96879df2012-02-07 08:45:41 +08001389static struct weston_output *
1390get_default_output(struct weston_compositor *compositor)
1391{
1392 return container_of(compositor->output_list.next,
1393 struct weston_output, link);
1394}
1395
Alex Wu4539b082012-03-01 12:57:46 +08001396static void
1397shell_unset_fullscreen(struct shell_surface *shsurf)
1398{
1399 /* undo all fullscreen things here */
Alex Wubd3354b2012-04-17 17:20:49 +08001400 if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
1401 shell_surface_is_top_fullscreen(shsurf)) {
1402 weston_output_switch_mode(shsurf->fullscreen_output,
1403 shsurf->fullscreen_output->origin);
1404 }
Alex Wu4539b082012-03-01 12:57:46 +08001405 shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
1406 shsurf->fullscreen.framerate = 0;
1407 wl_list_remove(&shsurf->fullscreen.transform.link);
1408 wl_list_init(&shsurf->fullscreen.transform.link);
Alex Wubd3354b2012-04-17 17:20:49 +08001409 if (shsurf->fullscreen.black_surface)
1410 weston_surface_destroy(shsurf->fullscreen.black_surface);
Alex Wu4539b082012-03-01 12:57:46 +08001411 shsurf->fullscreen.black_surface = NULL;
1412 shsurf->fullscreen_output = NULL;
Alex Wu4539b082012-03-01 12:57:46 +08001413 weston_surface_set_position(shsurf->surface,
1414 shsurf->saved_x, shsurf->saved_y);
Alex Wu7bcb8bd2012-04-27 09:07:24 +08001415 if (shsurf->saved_rotation_valid) {
1416 wl_list_insert(&shsurf->surface->geometry.transformation_list,
1417 &shsurf->rotation.transform.link);
1418 shsurf->saved_rotation_valid = false;
1419 }
Alex Wu4539b082012-03-01 12:57:46 +08001420}
1421
Pekka Paalanen98262232011-12-01 10:42:22 +02001422static int
1423reset_shell_surface_type(struct shell_surface *surface)
1424{
1425 switch (surface->type) {
1426 case SHELL_SURFACE_FULLSCREEN:
Alex Wu4539b082012-03-01 12:57:46 +08001427 shell_unset_fullscreen(surface);
Pekka Paalanen98262232011-12-01 10:42:22 +02001428 break;
Juan Zhao96879df2012-02-07 08:45:41 +08001429 case SHELL_SURFACE_MAXIMIZED:
1430 surface->output = get_default_output(surface->surface->compositor);
1431 weston_surface_set_position(surface->surface,
1432 surface->saved_x,
1433 surface->saved_y);
1434 break;
Pekka Paalanen98262232011-12-01 10:42:22 +02001435 case SHELL_SURFACE_NONE:
1436 case SHELL_SURFACE_TOPLEVEL:
1437 case SHELL_SURFACE_TRANSIENT:
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001438 case SHELL_SURFACE_POPUP:
Pekka Paalanen98262232011-12-01 10:42:22 +02001439 break;
1440 }
1441
1442 surface->type = SHELL_SURFACE_NONE;
1443 return 0;
1444}
1445
Kristian Høgsberg4cca3492011-01-18 07:53:49 -05001446static void
Kristian Høgsberg7f366e72012-04-27 17:20:01 -04001447set_surface_type(struct shell_surface *shsurf)
1448{
1449 struct weston_surface *surface = shsurf->surface;
Kristian Høgsberg8150b192012-06-27 10:22:58 -04001450 struct weston_surface *pes = shsurf->parent;
Kristian Høgsberg7f366e72012-04-27 17:20:01 -04001451
1452 reset_shell_surface_type(shsurf);
1453
1454 shsurf->type = shsurf->next_type;
1455 shsurf->next_type = SHELL_SURFACE_NONE;
1456
1457 switch (shsurf->type) {
1458 case SHELL_SURFACE_TOPLEVEL:
1459 break;
1460 case SHELL_SURFACE_TRANSIENT:
Kristian Høgsberg7f366e72012-04-27 17:20:01 -04001461 weston_surface_set_position(surface,
Tiago Vignatti52e598c2012-05-07 15:23:08 +03001462 pes->geometry.x + shsurf->transient.x,
1463 pes->geometry.y + shsurf->transient.y);
Kristian Høgsberg7f366e72012-04-27 17:20:01 -04001464 break;
1465
1466 case SHELL_SURFACE_MAXIMIZED:
1467 shsurf->saved_x = surface->geometry.x;
1468 shsurf->saved_y = surface->geometry.y;
1469 shsurf->saved_position_valid = true;
1470 break;
1471
1472 case SHELL_SURFACE_FULLSCREEN:
1473 shsurf->saved_x = surface->geometry.x;
1474 shsurf->saved_y = surface->geometry.y;
1475 shsurf->saved_position_valid = true;
1476
1477 if (!wl_list_empty(&shsurf->rotation.transform.link)) {
1478 wl_list_remove(&shsurf->rotation.transform.link);
1479 wl_list_init(&shsurf->rotation.transform.link);
1480 shsurf->surface->geometry.dirty = 1;
1481 shsurf->saved_rotation_valid = true;
1482 }
1483 break;
1484
Kristian Høgsberg7f366e72012-04-27 17:20:01 -04001485 default:
1486 break;
1487 }
1488}
1489
1490static void
Tiago Vignattibc052c92012-04-19 16:18:18 +03001491set_toplevel(struct shell_surface *shsurf)
1492{
Kristian Høgsberg7f366e72012-04-27 17:20:01 -04001493 shsurf->next_type = SHELL_SURFACE_TOPLEVEL;
Tiago Vignattibc052c92012-04-19 16:18:18 +03001494}
1495
1496static void
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02001497shell_surface_set_toplevel(struct wl_client *client,
1498 struct wl_resource *resource)
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -04001499{
Pekka Paalanen98262232011-12-01 10:42:22 +02001500 struct shell_surface *surface = resource->data;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -04001501
Tiago Vignattibc052c92012-04-19 16:18:18 +03001502 set_toplevel(surface);
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -04001503}
1504
1505static void
Tiago Vignatti491bac12012-05-18 16:37:43 -04001506set_transient(struct shell_surface *shsurf,
Kristian Høgsberg8150b192012-06-27 10:22:58 -04001507 struct weston_surface *parent, int x, int y, uint32_t flags)
Tiago Vignatti491bac12012-05-18 16:37:43 -04001508{
1509 /* assign to parents output */
Kristian Høgsberg8150b192012-06-27 10:22:58 -04001510 shsurf->parent = parent;
Tiago Vignatti491bac12012-05-18 16:37:43 -04001511 shsurf->transient.x = x;
1512 shsurf->transient.y = y;
1513 shsurf->transient.flags = flags;
1514 shsurf->next_type = SHELL_SURFACE_TRANSIENT;
1515}
1516
1517static void
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02001518shell_surface_set_transient(struct wl_client *client,
1519 struct wl_resource *resource,
1520 struct wl_resource *parent_resource,
1521 int x, int y, uint32_t flags)
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -04001522{
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02001523 struct shell_surface *shsurf = resource->data;
Kristian Høgsberg8150b192012-06-27 10:22:58 -04001524 struct weston_surface *parent = parent_resource->data;
Pekka Paalanen98262232011-12-01 10:42:22 +02001525
Kristian Høgsberg8150b192012-06-27 10:22:58 -04001526 set_transient(shsurf, parent, x, y, flags);
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -04001527}
1528
Tiago Vignattibe143262012-04-16 17:31:41 +03001529static struct desktop_shell *
Juan Zhao96879df2012-02-07 08:45:41 +08001530shell_surface_get_shell(struct shell_surface *shsurf)
Pekka Paalanenaf0e34c2011-12-02 10:59:17 +02001531{
Kristian Høgsberg02e79dc2012-04-12 09:55:26 -04001532 return shsurf->shell;
Juan Zhao96879df2012-02-07 08:45:41 +08001533}
1534
1535static int
Tiago Vignattibe143262012-04-16 17:31:41 +03001536get_output_panel_height(struct desktop_shell *shell,
1537 struct weston_output *output)
Juan Zhao96879df2012-02-07 08:45:41 +08001538{
Kristian Høgsbergaf7b1ff2012-06-26 21:19:23 -04001539 struct weston_surface *surface;
Juan Zhao96879df2012-02-07 08:45:41 +08001540 int panel_height = 0;
1541
1542 if (!output)
1543 return 0;
1544
Juan Zhao4ab94682012-07-09 22:24:09 -07001545 wl_list_for_each(surface, &shell->panel_layer.surface_list, layer_link) {
Kristian Høgsbergaf7b1ff2012-06-26 21:19:23 -04001546 if (surface->output == output) {
1547 panel_height = surface->geometry.height;
Juan Zhao96879df2012-02-07 08:45:41 +08001548 break;
1549 }
1550 }
Kristian Høgsbergaf7b1ff2012-06-26 21:19:23 -04001551
Juan Zhao96879df2012-02-07 08:45:41 +08001552 return panel_height;
1553}
1554
1555static void
1556shell_surface_set_maximized(struct wl_client *client,
1557 struct wl_resource *resource,
1558 struct wl_resource *output_resource )
1559{
1560 struct shell_surface *shsurf = resource->data;
1561 struct weston_surface *es = shsurf->surface;
Tiago Vignattibe143262012-04-16 17:31:41 +03001562 struct desktop_shell *shell = NULL;
Juan Zhao96879df2012-02-07 08:45:41 +08001563 uint32_t edges = 0, panel_height = 0;
1564
1565 /* get the default output, if the client set it as NULL
1566 check whether the ouput is available */
1567 if (output_resource)
1568 shsurf->output = output_resource->data;
Kristian Høgsberg94de6802012-07-18 09:54:04 -04001569 else if (es->output)
1570 shsurf->output = es->output;
Juan Zhao96879df2012-02-07 08:45:41 +08001571 else
1572 shsurf->output = get_default_output(es->compositor);
1573
Tiago Vignattibe143262012-04-16 17:31:41 +03001574 shell = shell_surface_get_shell(shsurf);
Rob Bradford31b68622012-07-02 19:00:19 +01001575 panel_height = get_output_panel_height(shell, shsurf->output);
Juan Zhao96879df2012-02-07 08:45:41 +08001576 edges = WL_SHELL_SURFACE_RESIZE_TOP|WL_SHELL_SURFACE_RESIZE_LEFT;
Kristian Høgsberg0b5cd0c2012-03-04 21:57:37 -05001577
Kristian Høgsberga61ca062012-05-22 16:05:52 -04001578 shsurf->client->send_configure(shsurf->surface, edges,
Scott Moreau1bad5db2012-08-18 01:04:05 -06001579 shsurf->output->width,
1580 shsurf->output->height - panel_height);
Juan Zhao96879df2012-02-07 08:45:41 +08001581
Kristian Høgsberg7f366e72012-04-27 17:20:01 -04001582 shsurf->next_type = SHELL_SURFACE_MAXIMIZED;
Pekka Paalanenaf0e34c2011-12-02 10:59:17 +02001583}
1584
Alex Wu21858432012-04-01 20:13:08 +08001585static void
1586black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy);
1587
Alex Wu4539b082012-03-01 12:57:46 +08001588static struct weston_surface *
1589create_black_surface(struct weston_compositor *ec,
Alex Wu21858432012-04-01 20:13:08 +08001590 struct weston_surface *fs_surface,
Alex Wu4539b082012-03-01 12:57:46 +08001591 GLfloat x, GLfloat y, int w, int h)
1592{
1593 struct weston_surface *surface = NULL;
1594
1595 surface = weston_surface_create(ec);
1596 if (surface == NULL) {
Martin Minarik6d118362012-06-07 18:01:59 +02001597 weston_log("no memory\n");
Alex Wu4539b082012-03-01 12:57:46 +08001598 return NULL;
1599 }
1600
Alex Wu21858432012-04-01 20:13:08 +08001601 surface->configure = black_surface_configure;
1602 surface->private = fs_surface;
Alex Wu4539b082012-03-01 12:57:46 +08001603 weston_surface_configure(surface, x, y, w, h);
1604 weston_surface_set_color(surface, 0.0, 0.0, 0.0, 1);
Kristian Høgsberg61f00f52012-08-03 16:31:36 -04001605 pixman_region32_init_rect(&surface->opaque, 0, 0, w, h);
1606
Alex Wu4539b082012-03-01 12:57:46 +08001607 return surface;
1608}
1609
1610/* Create black surface and append it to the associated fullscreen surface.
1611 * Handle size dismatch and positioning according to the method. */
1612static void
1613shell_configure_fullscreen(struct shell_surface *shsurf)
1614{
1615 struct weston_output *output = shsurf->fullscreen_output;
1616 struct weston_surface *surface = shsurf->surface;
1617 struct weston_matrix *matrix;
Kristian Høgsberg240dfeb2012-07-12 12:32:31 -04001618 float scale, output_aspect, surface_aspect, x, y;
Alex Wu4539b082012-03-01 12:57:46 +08001619
Alex Wu4539b082012-03-01 12:57:46 +08001620 if (!shsurf->fullscreen.black_surface)
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -05001621 shsurf->fullscreen.black_surface =
1622 create_black_surface(surface->compositor,
Alex Wu21858432012-04-01 20:13:08 +08001623 surface,
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -05001624 output->x, output->y,
Scott Moreau1bad5db2012-08-18 01:04:05 -06001625 output->width,
1626 output->height);
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -05001627
1628 wl_list_remove(&shsurf->fullscreen.black_surface->layer_link);
1629 wl_list_insert(&surface->layer_link,
1630 &shsurf->fullscreen.black_surface->layer_link);
Alex Wu4539b082012-03-01 12:57:46 +08001631 shsurf->fullscreen.black_surface->output = output;
1632
1633 switch (shsurf->fullscreen.type) {
1634 case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT:
Kristian Høgsberga08b5282012-07-20 15:30:36 -04001635 if (surface->buffer)
1636 center_on_output(surface, shsurf->fullscreen_output);
Alex Wu4539b082012-03-01 12:57:46 +08001637 break;
1638 case WL_SHELL_SURFACE_FULLSCREEN_METHOD_SCALE:
1639 matrix = &shsurf->fullscreen.transform.matrix;
1640 weston_matrix_init(matrix);
Kristian Høgsberg240dfeb2012-07-12 12:32:31 -04001641
Scott Moreau1bad5db2012-08-18 01:04:05 -06001642 output_aspect = (float) output->width /
1643 (float) output->height;
Kristian Høgsberg240dfeb2012-07-12 12:32:31 -04001644 surface_aspect = (float) surface->geometry.width /
1645 (float) surface->geometry.height;
1646 if (output_aspect < surface_aspect)
Scott Moreau1bad5db2012-08-18 01:04:05 -06001647 scale = (float) output->width /
Kristian Høgsberg240dfeb2012-07-12 12:32:31 -04001648 (float) surface->geometry.width;
1649 else
Scott Moreau1bad5db2012-08-18 01:04:05 -06001650 scale = (float) output->height /
Kristian Høgsberg240dfeb2012-07-12 12:32:31 -04001651 (float) surface->geometry.height;
1652
Alex Wu4539b082012-03-01 12:57:46 +08001653 weston_matrix_scale(matrix, scale, scale, 1);
1654 wl_list_remove(&shsurf->fullscreen.transform.link);
Kristian Høgsberg240dfeb2012-07-12 12:32:31 -04001655 wl_list_insert(&surface->geometry.transformation_list,
Alex Wu4539b082012-03-01 12:57:46 +08001656 &shsurf->fullscreen.transform.link);
Scott Moreau1bad5db2012-08-18 01:04:05 -06001657 x = output->x + (output->width - surface->geometry.width * scale) / 2;
1658 y = output->y + (output->height - surface->geometry.height * scale) / 2;
Kristian Høgsberg240dfeb2012-07-12 12:32:31 -04001659 weston_surface_set_position(surface, x, y);
1660
Alex Wu4539b082012-03-01 12:57:46 +08001661 break;
1662 case WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER:
Alex Wubd3354b2012-04-17 17:20:49 +08001663 if (shell_surface_is_top_fullscreen(shsurf)) {
1664 struct weston_mode mode = {0,
1665 surface->geometry.width,
1666 surface->geometry.height,
1667 shsurf->fullscreen.framerate};
1668
1669 if (weston_output_switch_mode(output, &mode) == 0) {
1670 weston_surface_configure(shsurf->fullscreen.black_surface,
1671 output->x, output->y,
Scott Moreau1bad5db2012-08-18 01:04:05 -06001672 output->width,
1673 output->height);
Alex Wubd3354b2012-04-17 17:20:49 +08001674 weston_surface_set_position(surface, output->x, output->y);
1675 break;
1676 }
1677 }
Alex Wu4539b082012-03-01 12:57:46 +08001678 break;
1679 case WL_SHELL_SURFACE_FULLSCREEN_METHOD_FILL:
1680 break;
1681 default:
1682 break;
1683 }
1684}
1685
1686/* make the fullscreen and black surface at the top */
1687static void
1688shell_stack_fullscreen(struct shell_surface *shsurf)
1689{
Alex Wubd3354b2012-04-17 17:20:49 +08001690 struct weston_output *output = shsurf->fullscreen_output;
Alex Wu4539b082012-03-01 12:57:46 +08001691 struct weston_surface *surface = shsurf->surface;
Tiago Vignattibe143262012-04-16 17:31:41 +03001692 struct desktop_shell *shell = shell_surface_get_shell(shsurf);
Alex Wu4539b082012-03-01 12:57:46 +08001693
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -05001694 wl_list_remove(&surface->layer_link);
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -05001695 wl_list_insert(&shell->fullscreen_layer.surface_list,
1696 &surface->layer_link);
Alex Wubd3354b2012-04-17 17:20:49 +08001697 weston_surface_damage(surface);
1698
1699 if (!shsurf->fullscreen.black_surface)
1700 shsurf->fullscreen.black_surface =
1701 create_black_surface(surface->compositor,
1702 surface,
1703 output->x, output->y,
Scott Moreau1bad5db2012-08-18 01:04:05 -06001704 output->width,
1705 output->height);
Alex Wubd3354b2012-04-17 17:20:49 +08001706
1707 wl_list_remove(&shsurf->fullscreen.black_surface->layer_link);
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -05001708 wl_list_insert(&surface->layer_link,
1709 &shsurf->fullscreen.black_surface->layer_link);
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -05001710 weston_surface_damage(shsurf->fullscreen.black_surface);
Alex Wu4539b082012-03-01 12:57:46 +08001711}
1712
1713static void
1714shell_map_fullscreen(struct shell_surface *shsurf)
1715{
Alex Wu4539b082012-03-01 12:57:46 +08001716 shell_stack_fullscreen(shsurf);
Alex Wubd3354b2012-04-17 17:20:49 +08001717 shell_configure_fullscreen(shsurf);
Alex Wu4539b082012-03-01 12:57:46 +08001718}
1719
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -04001720static void
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02001721shell_surface_set_fullscreen(struct wl_client *client,
Kristian Høgsbergf856fd22012-02-16 15:58:14 -05001722 struct wl_resource *resource,
1723 uint32_t method,
1724 uint32_t framerate,
1725 struct wl_resource *output_resource)
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -04001726{
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02001727 struct shell_surface *shsurf = resource->data;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05001728 struct weston_surface *es = shsurf->surface;
Alex Wu4539b082012-03-01 12:57:46 +08001729
1730 if (output_resource)
1731 shsurf->output = output_resource->data;
Kristian Høgsberg94de6802012-07-18 09:54:04 -04001732 else if (es->output)
1733 shsurf->output = es->output;
Alex Wu4539b082012-03-01 12:57:46 +08001734 else
1735 shsurf->output = get_default_output(es->compositor);
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -04001736
Alex Wu4539b082012-03-01 12:57:46 +08001737 shsurf->fullscreen_output = shsurf->output;
1738 shsurf->fullscreen.type = method;
1739 shsurf->fullscreen.framerate = framerate;
Kristian Høgsberg7f366e72012-04-27 17:20:01 -04001740 shsurf->next_type = SHELL_SURFACE_FULLSCREEN;
Alex Wu4539b082012-03-01 12:57:46 +08001741
Kristian Høgsberga61ca062012-05-22 16:05:52 -04001742 shsurf->client->send_configure(shsurf->surface, 0,
Scott Moreau1bad5db2012-08-18 01:04:05 -06001743 shsurf->output->width,
1744 shsurf->output->height);
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -04001745}
1746
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001747static void
Kristian Høgsbergeae5de72012-04-11 22:42:15 -04001748popup_grab_focus(struct wl_pointer_grab *grab,
Daniel Stone103db7f2012-05-08 17:17:55 +01001749 struct wl_surface *surface,
1750 wl_fixed_t x,
1751 wl_fixed_t y)
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001752{
Daniel Stone37816df2012-05-16 18:45:18 +01001753 struct wl_pointer *pointer = grab->pointer;
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001754 struct shell_surface *priv =
1755 container_of(grab, struct shell_surface, popup.grab);
1756 struct wl_client *client = priv->surface->surface.resource.client;
1757
Pekka Paalanencb108432012-01-19 16:25:40 +02001758 if (surface && surface->resource.client == client) {
Daniel Stone37816df2012-05-16 18:45:18 +01001759 wl_pointer_set_focus(pointer, surface, x, y);
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001760 grab->focus = surface;
1761 } else {
Daniel Stone37816df2012-05-16 18:45:18 +01001762 wl_pointer_set_focus(pointer, NULL,
1763 wl_fixed_from_int(0),
1764 wl_fixed_from_int(0));
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001765 grab->focus = NULL;
1766 }
1767}
1768
1769static void
Scott Moreau447013d2012-02-18 05:05:29 -07001770popup_grab_motion(struct wl_pointer_grab *grab,
Daniel Stone103db7f2012-05-08 17:17:55 +01001771 uint32_t time, wl_fixed_t sx, wl_fixed_t sy)
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001772{
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001773 struct wl_resource *resource;
1774
Daniel Stone37816df2012-05-16 18:45:18 +01001775 resource = grab->pointer->focus_resource;
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001776 if (resource)
Daniel Stone37816df2012-05-16 18:45:18 +01001777 wl_pointer_send_motion(resource, time, sx, sy);
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001778}
1779
1780static void
Scott Moreau447013d2012-02-18 05:05:29 -07001781popup_grab_button(struct wl_pointer_grab *grab,
Daniel Stone4dbadb12012-05-30 16:31:51 +01001782 uint32_t time, uint32_t button, uint32_t state_w)
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001783{
1784 struct wl_resource *resource;
1785 struct shell_surface *shsurf =
1786 container_of(grab, struct shell_surface, popup.grab);
Kristian Høgsbergeae5de72012-04-11 22:42:15 -04001787 struct wl_display *display;
Daniel Stone4dbadb12012-05-30 16:31:51 +01001788 enum wl_pointer_button_state state = state_w;
Kristian Høgsbergeae5de72012-04-11 22:42:15 -04001789 uint32_t serial;
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001790
Daniel Stone37816df2012-05-16 18:45:18 +01001791 resource = grab->pointer->focus_resource;
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001792 if (resource) {
Kristian Høgsbergeae5de72012-04-11 22:42:15 -04001793 display = wl_client_get_display(resource->client);
1794 serial = wl_display_get_serial(display);
Daniel Stone37816df2012-05-16 18:45:18 +01001795 wl_pointer_send_button(resource, serial, time, button, state);
Daniel Stone4dbadb12012-05-30 16:31:51 +01001796 } else if (state == WL_POINTER_BUTTON_STATE_RELEASED &&
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001797 (shsurf->popup.initial_up ||
Daniel Stone37816df2012-05-16 18:45:18 +01001798 time - shsurf->popup.seat->pointer->grab_time > 500)) {
Kristian Høgsberg0b5cd0c2012-03-04 21:57:37 -05001799 wl_shell_surface_send_popup_done(&shsurf->resource);
Daniel Stone37816df2012-05-16 18:45:18 +01001800 wl_pointer_end_grab(grab->pointer);
1801 shsurf->popup.grab.pointer = NULL;
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001802 }
1803
Daniel Stone4dbadb12012-05-30 16:31:51 +01001804 if (state == WL_POINTER_BUTTON_STATE_RELEASED)
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001805 shsurf->popup.initial_up = 1;
1806}
1807
Scott Moreau447013d2012-02-18 05:05:29 -07001808static const struct wl_pointer_grab_interface popup_grab_interface = {
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001809 popup_grab_focus,
1810 popup_grab_motion,
1811 popup_grab_button,
1812};
1813
1814static void
Kristian Høgsberg3730f362012-04-13 12:40:07 -04001815shell_map_popup(struct shell_surface *shsurf)
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001816{
Daniel Stone37816df2012-05-16 18:45:18 +01001817 struct wl_seat *seat = shsurf->popup.seat;
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001818 struct weston_surface *es = shsurf->surface;
Kristian Høgsberg8150b192012-06-27 10:22:58 -04001819 struct weston_surface *parent = shsurf->parent;
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001820
1821 es->output = parent->output;
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001822 shsurf->popup.grab.interface = &popup_grab_interface;
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001823
Pekka Paalanen938269a2012-02-07 14:19:01 +02001824 weston_surface_update_transform(parent);
1825 if (parent->transform.enabled) {
1826 shsurf->popup.parent_transform.matrix =
1827 parent->transform.matrix;
1828 } else {
1829 /* construct x, y translation matrix */
1830 weston_matrix_init(&shsurf->popup.parent_transform.matrix);
1831 shsurf->popup.parent_transform.matrix.d[12] =
1832 parent->geometry.x;
1833 shsurf->popup.parent_transform.matrix.d[13] =
1834 parent->geometry.y;
1835 }
1836 wl_list_insert(es->geometry.transformation_list.prev,
1837 &shsurf->popup.parent_transform.link);
Pekka Paalanen8fb8d3b2012-02-13 13:03:59 +02001838 weston_surface_set_position(es, shsurf->popup.x, shsurf->popup.y);
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001839
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001840 shsurf->popup.initial_up = 0;
1841
Kristian Høgsberg3730f362012-04-13 12:40:07 -04001842 /* We don't require the grab to still be active, but if another
1843 * grab has started in the meantime, we end the popup now. */
Daniel Stone37816df2012-05-16 18:45:18 +01001844 if (seat->pointer->grab_serial == shsurf->popup.serial) {
1845 wl_pointer_start_grab(seat->pointer, &shsurf->popup.grab);
Kristian Høgsberg3730f362012-04-13 12:40:07 -04001846 } else {
1847 wl_shell_surface_send_popup_done(&shsurf->resource);
1848 }
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001849}
1850
1851static void
1852shell_surface_set_popup(struct wl_client *client,
1853 struct wl_resource *resource,
Daniel Stone37816df2012-05-16 18:45:18 +01001854 struct wl_resource *seat_resource,
Kristian Høgsberg3730f362012-04-13 12:40:07 -04001855 uint32_t serial,
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001856 struct wl_resource *parent_resource,
1857 int32_t x, int32_t y, uint32_t flags)
1858{
1859 struct shell_surface *shsurf = resource->data;
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001860
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001861 shsurf->type = SHELL_SURFACE_POPUP;
1862 shsurf->parent = parent_resource->data;
Daniel Stone37816df2012-05-16 18:45:18 +01001863 shsurf->popup.seat = seat_resource->data;
Kristian Høgsberg3730f362012-04-13 12:40:07 -04001864 shsurf->popup.serial = serial;
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001865 shsurf->popup.x = x;
1866 shsurf->popup.y = y;
1867}
1868
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02001869static const struct wl_shell_surface_interface shell_surface_implementation = {
Scott Moreauff1db4a2012-04-17 19:06:18 -06001870 shell_surface_pong,
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02001871 shell_surface_move,
1872 shell_surface_resize,
1873 shell_surface_set_toplevel,
1874 shell_surface_set_transient,
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001875 shell_surface_set_fullscreen,
Juan Zhao96879df2012-02-07 08:45:41 +08001876 shell_surface_set_popup,
Kristian Høgsberge7afd912012-05-02 09:47:44 -04001877 shell_surface_set_maximized,
1878 shell_surface_set_title,
1879 shell_surface_set_class
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02001880};
1881
1882static void
Tiago Vignattibc052c92012-04-19 16:18:18 +03001883destroy_shell_surface(struct shell_surface *shsurf)
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02001884{
Daniel Stone37816df2012-05-16 18:45:18 +01001885 if (shsurf->popup.grab.pointer)
1886 wl_pointer_end_grab(shsurf->popup.grab.pointer);
Kristian Høgsbergb3cca0a2012-01-04 22:19:14 -05001887
Alex Wubd3354b2012-04-17 17:20:49 +08001888 if (shsurf->fullscreen.type == WL_SHELL_SURFACE_FULLSCREEN_METHOD_DRIVER &&
1889 shell_surface_is_top_fullscreen(shsurf)) {
1890 weston_output_switch_mode(shsurf->fullscreen_output,
1891 shsurf->fullscreen_output->origin);
Ander Conselvan de Oliveira093bfa32012-03-27 17:36:41 +03001892 }
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02001893
Alex Wuaa08e2d2012-03-05 11:01:40 +08001894 if (shsurf->fullscreen.black_surface)
1895 weston_surface_destroy(shsurf->fullscreen.black_surface);
1896
Alex Wubd3354b2012-04-17 17:20:49 +08001897 /* As destroy_resource() use wl_list_for_each_safe(),
1898 * we can always remove the listener.
1899 */
1900 wl_list_remove(&shsurf->surface_destroy_listener.link);
1901 shsurf->surface->configure = NULL;
Scott Moreau9521d5e2012-04-19 13:06:17 -06001902 ping_timer_destroy(shsurf);
Alex Wubd3354b2012-04-17 17:20:49 +08001903
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02001904 wl_list_remove(&shsurf->link);
1905 free(shsurf);
1906}
1907
1908static void
Tiago Vignattibc052c92012-04-19 16:18:18 +03001909shell_destroy_shell_surface(struct wl_resource *resource)
1910{
1911 struct shell_surface *shsurf = resource->data;
1912
1913 destroy_shell_surface(shsurf);
1914}
1915
1916static void
Kristian Høgsberg27e30522012-04-11 23:18:23 -04001917shell_handle_surface_destroy(struct wl_listener *listener, void *data)
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02001918{
1919 struct shell_surface *shsurf = container_of(listener,
1920 struct shell_surface,
1921 surface_destroy_listener);
1922
Kristian Høgsberg633b1452012-06-07 18:08:47 -04001923 if (shsurf->resource.client) {
Tiago Vignattibc052c92012-04-19 16:18:18 +03001924 wl_resource_destroy(&shsurf->resource);
Kristian Høgsberg633b1452012-06-07 18:08:47 -04001925 } else {
1926 wl_signal_emit(&shsurf->resource.destroy_signal,
1927 &shsurf->resource);
Tiago Vignattibc052c92012-04-19 16:18:18 +03001928 destroy_shell_surface(shsurf);
Kristian Høgsberg633b1452012-06-07 18:08:47 -04001929 }
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02001930}
1931
Kristian Høgsbergd8134452012-06-21 12:49:02 -04001932static void
1933shell_surface_configure(struct weston_surface *, int32_t, int32_t);
1934
Pekka Paalanenec2b32f2011-11-28 15:12:34 +02001935static struct shell_surface *
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05001936get_shell_surface(struct weston_surface *surface)
Pekka Paalanenec2b32f2011-11-28 15:12:34 +02001937{
Kristian Høgsbergd8134452012-06-21 12:49:02 -04001938 if (surface->configure == shell_surface_configure)
1939 return surface->private;
1940 else
1941 return NULL;
Pekka Paalanenec2b32f2011-11-28 15:12:34 +02001942}
1943
Kristian Høgsberg45ba8692012-05-21 14:27:33 -04001944static struct shell_surface *
Kristian Høgsberga61ca062012-05-22 16:05:52 -04001945create_shell_surface(void *shell, struct weston_surface *surface,
1946 const struct weston_shell_client *client)
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02001947{
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02001948 struct shell_surface *shsurf;
1949
Ander Conselvan de Oliveira093bfa32012-03-27 17:36:41 +03001950 if (surface->configure) {
Martin Minarik6d118362012-06-07 18:01:59 +02001951 weston_log("surface->configure already set\n");
Kristian Høgsberg45ba8692012-05-21 14:27:33 -04001952 return NULL;
Ander Conselvan de Oliveira093bfa32012-03-27 17:36:41 +03001953 }
1954
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02001955 shsurf = calloc(1, sizeof *shsurf);
1956 if (!shsurf) {
Martin Minarik6d118362012-06-07 18:01:59 +02001957 weston_log("no memory to allocate shell surface\n");
Kristian Høgsberg45ba8692012-05-21 14:27:33 -04001958 return NULL;
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02001959 }
1960
Ander Conselvan de Oliveira093bfa32012-03-27 17:36:41 +03001961 surface->configure = shell_surface_configure;
Kristian Høgsbergd8134452012-06-21 12:49:02 -04001962 surface->private = shsurf;
Ander Conselvan de Oliveira093bfa32012-03-27 17:36:41 +03001963
Tiago Vignattibc052c92012-04-19 16:18:18 +03001964 shsurf->shell = (struct desktop_shell *) shell;
Scott Moreauff1db4a2012-04-17 19:06:18 -06001965 shsurf->unresponsive = 0;
Alex Wu4539b082012-03-01 12:57:46 +08001966 shsurf->saved_position_valid = false;
Alex Wu7bcb8bd2012-04-27 09:07:24 +08001967 shsurf->saved_rotation_valid = false;
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02001968 shsurf->surface = surface;
Alex Wu4539b082012-03-01 12:57:46 +08001969 shsurf->fullscreen.type = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT;
1970 shsurf->fullscreen.framerate = 0;
1971 shsurf->fullscreen.black_surface = NULL;
Scott Moreauff1db4a2012-04-17 19:06:18 -06001972 shsurf->ping_timer = NULL;
Alex Wu4539b082012-03-01 12:57:46 +08001973 wl_list_init(&shsurf->fullscreen.transform.link);
1974
Tiago Vignattibc052c92012-04-19 16:18:18 +03001975 wl_signal_init(&shsurf->resource.destroy_signal);
Kristian Høgsberg27e30522012-04-11 23:18:23 -04001976 shsurf->surface_destroy_listener.notify = shell_handle_surface_destroy;
1977 wl_signal_add(&surface->surface.resource.destroy_signal,
1978 &shsurf->surface_destroy_listener);
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02001979
1980 /* init link so its safe to always remove it in destroy_shell_surface */
1981 wl_list_init(&shsurf->link);
1982
Pekka Paalanen460099f2012-01-20 16:48:25 +02001983 /* empty when not in use */
1984 wl_list_init(&shsurf->rotation.transform.link);
Kristian Høgsberg765e27b2012-01-27 13:36:13 -05001985 weston_matrix_init(&shsurf->rotation.rotation);
Pekka Paalanen460099f2012-01-20 16:48:25 +02001986
Jonas Ådahl62fcd042012-06-13 00:01:23 +02001987 wl_list_init(&shsurf->workspace_transform.link);
1988
Pekka Paalanen98262232011-12-01 10:42:22 +02001989 shsurf->type = SHELL_SURFACE_NONE;
Kristian Høgsberg7f366e72012-04-27 17:20:01 -04001990 shsurf->next_type = SHELL_SURFACE_NONE;
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02001991
Kristian Høgsberga61ca062012-05-22 16:05:52 -04001992 shsurf->client = client;
1993
Kristian Høgsberg45ba8692012-05-21 14:27:33 -04001994 return shsurf;
Tiago Vignattibc052c92012-04-19 16:18:18 +03001995}
1996
1997static void
1998shell_get_shell_surface(struct wl_client *client,
1999 struct wl_resource *resource,
2000 uint32_t id,
2001 struct wl_resource *surface_resource)
2002{
2003 struct weston_surface *surface = surface_resource->data;
2004 struct desktop_shell *shell = resource->data;
2005 struct shell_surface *shsurf;
2006
2007 if (get_shell_surface(surface)) {
2008 wl_resource_post_error(surface_resource,
Kristian Høgsberg9540ea62012-05-21 14:28:57 -04002009 WL_DISPLAY_ERROR_INVALID_OBJECT,
2010 "desktop_shell::get_shell_surface already requested");
Tiago Vignattibc052c92012-04-19 16:18:18 +03002011 return;
2012 }
2013
Kristian Høgsberga61ca062012-05-22 16:05:52 -04002014 shsurf = create_shell_surface(shell, surface, &shell_client);
Kristian Høgsberg9540ea62012-05-21 14:28:57 -04002015 if (!shsurf) {
2016 wl_resource_post_error(surface_resource,
2017 WL_DISPLAY_ERROR_INVALID_OBJECT,
2018 "surface->configure already set");
2019 return;
2020 }
Tiago Vignattibc052c92012-04-19 16:18:18 +03002021
Kristian Høgsberg9540ea62012-05-21 14:28:57 -04002022 shsurf->resource.destroy = shell_destroy_shell_surface;
2023 shsurf->resource.object.id = id;
2024 shsurf->resource.object.interface = &wl_shell_surface_interface;
2025 shsurf->resource.object.implementation =
2026 (void (**)(void)) &shell_surface_implementation;
2027 shsurf->resource.data = shsurf;
Tiago Vignattibc052c92012-04-19 16:18:18 +03002028
Kristian Høgsberg9540ea62012-05-21 14:28:57 -04002029 wl_client_add_resource(client, &shsurf->resource);
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02002030}
2031
2032static const struct wl_shell_interface shell_implementation = {
Pekka Paalanen46229672011-11-29 15:49:31 +02002033 shell_get_shell_surface
Kristian Høgsberg4cca3492011-01-18 07:53:49 -05002034};
2035
Kristian Høgsberg07937562011-04-12 17:25:42 -04002036static void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002037handle_screensaver_sigchld(struct weston_process *proc, int status)
Pekka Paalanen18027e52011-12-02 16:31:49 +02002038{
2039 proc->pid = 0;
2040}
2041
2042static void
Tiago Vignattibe143262012-04-16 17:31:41 +03002043launch_screensaver(struct desktop_shell *shell)
Pekka Paalanen77346a62011-11-30 16:26:35 +02002044{
2045 if (shell->screensaver.binding)
2046 return;
2047
Pekka Paalanene955f1e2011-12-07 11:49:52 +02002048 if (!shell->screensaver.path)
2049 return;
2050
Kristian Høgsberg32bed572012-03-01 17:11:36 -05002051 if (shell->screensaver.process.pid != 0) {
Martin Minarik6d118362012-06-07 18:01:59 +02002052 weston_log("old screensaver still running\n");
Kristian Høgsberg32bed572012-03-01 17:11:36 -05002053 return;
2054 }
2055
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002056 weston_client_launch(shell->compositor,
Pekka Paalanen18027e52011-12-02 16:31:49 +02002057 &shell->screensaver.process,
Pekka Paalanene955f1e2011-12-07 11:49:52 +02002058 shell->screensaver.path,
Pekka Paalanen18027e52011-12-02 16:31:49 +02002059 handle_screensaver_sigchld);
Pekka Paalanen77346a62011-11-30 16:26:35 +02002060}
2061
2062static void
Tiago Vignattibe143262012-04-16 17:31:41 +03002063terminate_screensaver(struct desktop_shell *shell)
Pekka Paalanen77346a62011-11-30 16:26:35 +02002064{
Pekka Paalanen18027e52011-12-02 16:31:49 +02002065 if (shell->screensaver.process.pid == 0)
2066 return;
2067
2068 kill(shell->screensaver.process.pid, SIGTERM);
Pekka Paalanen77346a62011-11-30 16:26:35 +02002069}
2070
2071static void
Kristian Høgsbergaf7b1ff2012-06-26 21:19:23 -04002072configure_static_surface(struct weston_surface *es, struct weston_layer *layer)
Kristian Høgsberg962342c2012-06-26 16:29:50 -04002073{
Kristian Høgsbergaf7b1ff2012-06-26 21:19:23 -04002074 struct weston_surface *s, *next;
Kristian Høgsberg962342c2012-06-26 16:29:50 -04002075
Kristian Høgsbergaf7b1ff2012-06-26 21:19:23 -04002076 wl_list_for_each_safe(s, next, &layer->surface_list, layer_link) {
2077 if (s->output == es->output && s != es) {
2078 weston_surface_unmap(s);
Kristian Høgsberg962342c2012-06-26 16:29:50 -04002079 s->configure = NULL;
Kristian Høgsberg962342c2012-06-26 16:29:50 -04002080 }
2081 }
2082
2083 weston_surface_configure(es, es->output->x, es->output->y,
2084 es->buffer->width, es->buffer->height);
2085
2086 if (wl_list_empty(&es->layer_link)) {
Kristian Høgsbergaf7b1ff2012-06-26 21:19:23 -04002087 wl_list_insert(&layer->surface_list, &es->layer_link);
Kristian Høgsbergc7cd6262012-06-28 13:46:09 -04002088 weston_compositor_schedule_repaint(es->compositor);
Kristian Høgsberg962342c2012-06-26 16:29:50 -04002089 }
2090}
2091
2092static void
Kristian Høgsbergaf7b1ff2012-06-26 21:19:23 -04002093background_configure(struct weston_surface *es, int32_t sx, int32_t sy)
2094{
2095 struct desktop_shell *shell = es->private;
2096
2097 configure_static_surface(es, &shell->background_layer);
2098}
2099
2100static void
Kristian Høgsberg75840622011-09-06 13:48:16 -04002101desktop_shell_set_background(struct wl_client *client,
2102 struct wl_resource *resource,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +01002103 struct wl_resource *output_resource,
Kristian Høgsberg75840622011-09-06 13:48:16 -04002104 struct wl_resource *surface_resource)
2105{
Kristian Høgsberg962342c2012-06-26 16:29:50 -04002106 struct desktop_shell *shell = resource->data;
2107 struct weston_surface *surface = surface_resource->data;
Kristian Høgsberg75840622011-09-06 13:48:16 -04002108
Kristian Høgsberg962342c2012-06-26 16:29:50 -04002109 if (surface->configure) {
2110 wl_resource_post_error(surface_resource,
2111 WL_DISPLAY_ERROR_INVALID_OBJECT,
2112 "surface role already assigned");
2113 return;
2114 }
Benjamin Franzked0f79ab2011-11-22 12:43:52 +01002115
Kristian Høgsberg962342c2012-06-26 16:29:50 -04002116 surface->configure = background_configure;
2117 surface->private = shell;
2118 surface->output = output_resource->data;
Kristian Høgsbergeae5de72012-04-11 22:42:15 -04002119 desktop_shell_send_configure(resource, 0,
Kristian Høgsberg0b5cd0c2012-03-04 21:57:37 -05002120 surface_resource,
Scott Moreau1bad5db2012-08-18 01:04:05 -06002121 surface->output->width,
2122 surface->output->height);
Kristian Høgsberg75840622011-09-06 13:48:16 -04002123}
2124
2125static void
Kristian Høgsbergaf7b1ff2012-06-26 21:19:23 -04002126panel_configure(struct weston_surface *es, int32_t sx, int32_t sy)
2127{
2128 struct desktop_shell *shell = es->private;
2129
2130 configure_static_surface(es, &shell->panel_layer);
2131}
2132
2133static void
Kristian Høgsberg75840622011-09-06 13:48:16 -04002134desktop_shell_set_panel(struct wl_client *client,
2135 struct wl_resource *resource,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +01002136 struct wl_resource *output_resource,
Kristian Høgsberg75840622011-09-06 13:48:16 -04002137 struct wl_resource *surface_resource)
2138{
Kristian Høgsbergaf7b1ff2012-06-26 21:19:23 -04002139 struct desktop_shell *shell = resource->data;
2140 struct weston_surface *surface = surface_resource->data;
Kristian Høgsberg75840622011-09-06 13:48:16 -04002141
Kristian Høgsbergaf7b1ff2012-06-26 21:19:23 -04002142 if (surface->configure) {
2143 wl_resource_post_error(surface_resource,
2144 WL_DISPLAY_ERROR_INVALID_OBJECT,
2145 "surface role already assigned");
2146 return;
2147 }
Benjamin Franzked0f79ab2011-11-22 12:43:52 +01002148
Kristian Høgsbergaf7b1ff2012-06-26 21:19:23 -04002149 surface->configure = panel_configure;
2150 surface->private = shell;
2151 surface->output = output_resource->data;
Kristian Høgsbergeae5de72012-04-11 22:42:15 -04002152 desktop_shell_send_configure(resource, 0,
Kristian Høgsbergaf7b1ff2012-06-26 21:19:23 -04002153 surface_resource,
Scott Moreau1bad5db2012-08-18 01:04:05 -06002154 surface->output->width,
2155 surface->output->height);
Kristian Høgsberg75840622011-09-06 13:48:16 -04002156}
2157
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02002158static void
Kristian Høgsberg730c94d2012-06-26 21:44:35 -04002159lock_surface_configure(struct weston_surface *surface, int32_t sx, int32_t sy)
2160{
2161 struct desktop_shell *shell = surface->private;
2162
2163 center_on_output(surface, get_default_output(shell->compositor));
2164
2165 if (!weston_surface_is_mapped(surface)) {
2166 wl_list_insert(&shell->lock_layer.surface_list,
2167 &surface->layer_link);
2168 weston_surface_assign_output(surface);
2169 weston_compositor_wake(shell->compositor);
2170 }
2171}
2172
2173static void
Kristian Høgsberg27e30522012-04-11 23:18:23 -04002174handle_lock_surface_destroy(struct wl_listener *listener, void *data)
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -05002175{
Tiago Vignattibe143262012-04-16 17:31:41 +03002176 struct desktop_shell *shell =
2177 container_of(listener, struct desktop_shell, lock_surface_listener);
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -05002178
Martin Minarik6d118362012-06-07 18:01:59 +02002179 weston_log("lock surface gone\n");
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -05002180 shell->lock_surface = NULL;
2181}
2182
2183static void
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02002184desktop_shell_set_lock_surface(struct wl_client *client,
2185 struct wl_resource *resource,
2186 struct wl_resource *surface_resource)
2187{
Tiago Vignattibe143262012-04-16 17:31:41 +03002188 struct desktop_shell *shell = resource->data;
Kristian Høgsberg730c94d2012-06-26 21:44:35 -04002189 struct weston_surface *surface = surface_resource->data;
Pekka Paalanen98262232011-12-01 10:42:22 +02002190
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02002191 shell->prepare_event_sent = false;
Kristian Høgsbergaf867cc2011-11-15 13:34:49 +02002192
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02002193 if (!shell->locked)
2194 return;
2195
Pekka Paalanen98262232011-12-01 10:42:22 +02002196 shell->lock_surface = surface;
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02002197
Kristian Høgsberg27e30522012-04-11 23:18:23 -04002198 shell->lock_surface_listener.notify = handle_lock_surface_destroy;
2199 wl_signal_add(&surface_resource->destroy_signal,
2200 &shell->lock_surface_listener);
Pekka Paalanen57da4a82011-11-23 16:42:16 +02002201
Kristian Høgsberg730c94d2012-06-26 21:44:35 -04002202 surface->configure = lock_surface_configure;
2203 surface->private = shell;
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02002204}
2205
2206static void
Tiago Vignattibe143262012-04-16 17:31:41 +03002207resume_desktop(struct desktop_shell *shell)
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02002208{
Kristian Høgsberg1a73a632012-06-26 22:15:53 -04002209 struct weston_surface *surface;
Kristian Høgsberg4476aaf2012-06-25 14:03:13 -04002210 struct workspace *ws = get_current_workspace(shell);
Pekka Paalanen77346a62011-11-30 16:26:35 +02002211
Kristian Høgsberg1a73a632012-06-26 22:15:53 -04002212 wl_list_for_each(surface, &shell->screensaver.surfaces, link)
2213 weston_surface_unmap(surface);
Pekka Paalanen77346a62011-11-30 16:26:35 +02002214
2215 terminate_screensaver(shell);
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02002216
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -05002217 wl_list_remove(&shell->lock_layer.link);
2218 wl_list_insert(&shell->compositor->cursor_layer.link,
2219 &shell->fullscreen_layer.link);
2220 wl_list_insert(&shell->fullscreen_layer.link,
2221 &shell->panel_layer.link);
Philipp Brüschweiler711fda82012-08-09 18:50:43 +02002222 if (shell->showing_input_panels) {
2223 wl_list_insert(&shell->panel_layer.link,
2224 &shell->input_panel_layer.link);
2225 wl_list_insert(&shell->input_panel_layer.link,
2226 &ws->layer.link);
2227 } else {
2228 wl_list_insert(&shell->panel_layer.link, &ws->layer.link);
2229 }
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02002230
Kristian Høgsberg2f5faff2012-07-31 16:36:34 -04002231 restore_focus_state(shell, get_current_workspace(shell));
Jonas Ådahl04769742012-06-13 00:01:24 +02002232
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02002233 shell->locked = false;
Pekka Paalanen7296e792011-12-07 16:22:00 +02002234 shell->compositor->idle_time = shell->compositor->option_idle_time;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002235 weston_compositor_wake(shell->compositor);
Pekka Paalanenfc6d91a2012-02-10 15:33:10 +02002236 weston_compositor_damage_all(shell->compositor);
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02002237}
2238
2239static void
2240desktop_shell_unlock(struct wl_client *client,
2241 struct wl_resource *resource)
2242{
Tiago Vignattibe143262012-04-16 17:31:41 +03002243 struct desktop_shell *shell = resource->data;
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02002244
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02002245 shell->prepare_event_sent = false;
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02002246
2247 if (shell->locked)
2248 resume_desktop(shell);
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02002249}
2250
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04002251static void
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03002252desktop_shell_set_grab_surface(struct wl_client *client,
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04002253 struct wl_resource *resource,
2254 struct wl_resource *surface_resource)
2255{
2256 struct desktop_shell *shell = resource->data;
2257
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03002258 shell->grab_surface = surface_resource->data;
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04002259}
2260
Kristian Høgsberg75840622011-09-06 13:48:16 -04002261static const struct desktop_shell_interface desktop_shell_implementation = {
2262 desktop_shell_set_background,
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02002263 desktop_shell_set_panel,
2264 desktop_shell_set_lock_surface,
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04002265 desktop_shell_unlock,
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03002266 desktop_shell_set_grab_surface
Kristian Høgsberg75840622011-09-06 13:48:16 -04002267};
2268
Pekka Paalanen92a0dc42011-11-28 15:34:13 +02002269static enum shell_surface_type
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002270get_shell_surface_type(struct weston_surface *surface)
Pekka Paalanen92a0dc42011-11-28 15:34:13 +02002271{
2272 struct shell_surface *shsurf;
2273
2274 shsurf = get_shell_surface(surface);
2275 if (!shsurf)
Pekka Paalanen98262232011-12-01 10:42:22 +02002276 return SHELL_SURFACE_NONE;
Pekka Paalanen92a0dc42011-11-28 15:34:13 +02002277 return shsurf->type;
2278}
2279
Kristian Høgsberg75840622011-09-06 13:48:16 -04002280static void
Daniel Stone325fc2d2012-05-30 16:31:58 +01002281move_binding(struct wl_seat *seat, uint32_t time, uint32_t button, void *data)
Kristian Høgsberg07937562011-04-12 17:25:42 -04002282{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002283 struct weston_surface *surface =
Daniel Stone37816df2012-05-16 18:45:18 +01002284 (struct weston_surface *) seat->pointer->focus;
Kristian Høgsberg938b8fa2012-05-18 13:46:27 -04002285 struct shell_surface *shsurf;
Kristian Høgsbergd2abb832011-11-23 10:52:40 -05002286
Benjamin Franzked0f79ab2011-11-22 12:43:52 +01002287 if (surface == NULL)
2288 return;
Kristian Høgsberg07937562011-04-12 17:25:42 -04002289
Kristian Høgsberg938b8fa2012-05-18 13:46:27 -04002290 shsurf = get_shell_surface(surface);
Kristian Høgsberg0636ac32012-06-27 10:22:15 -04002291 if (shsurf == NULL || shsurf->type == SHELL_SURFACE_FULLSCREEN)
Kristian Høgsberg938b8fa2012-05-18 13:46:27 -04002292 return;
2293
Kristian Høgsberg938b8fa2012-05-18 13:46:27 -04002294 surface_move(shsurf, (struct weston_seat *) seat);
Kristian Høgsberg07937562011-04-12 17:25:42 -04002295}
2296
2297static void
Daniel Stone325fc2d2012-05-30 16:31:58 +01002298resize_binding(struct wl_seat *seat, uint32_t time, uint32_t button, void *data)
Kristian Høgsberg07937562011-04-12 17:25:42 -04002299{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002300 struct weston_surface *surface =
Daniel Stone37816df2012-05-16 18:45:18 +01002301 (struct weston_surface *) seat->pointer->focus;
Kristian Høgsberg07937562011-04-12 17:25:42 -04002302 uint32_t edges = 0;
2303 int32_t x, y;
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02002304 struct shell_surface *shsurf;
Kristian Høgsbergd2abb832011-11-23 10:52:40 -05002305
Benjamin Franzked0f79ab2011-11-22 12:43:52 +01002306 if (surface == NULL)
2307 return;
Pekka Paalanen92a0dc42011-11-28 15:34:13 +02002308
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02002309 shsurf = get_shell_surface(surface);
Kristian Høgsberg0636ac32012-06-27 10:22:15 -04002310 if (!shsurf || shsurf->type == SHELL_SURFACE_FULLSCREEN)
Pekka Paalanen92a0dc42011-11-28 15:34:13 +02002311 return;
2312
Pekka Paalanen5c97ae72012-01-30 16:19:47 +02002313 weston_surface_from_global(surface,
Daniel Stone37816df2012-05-16 18:45:18 +01002314 wl_fixed_to_int(seat->pointer->grab_x),
2315 wl_fixed_to_int(seat->pointer->grab_y),
Daniel Stone103db7f2012-05-08 17:17:55 +01002316 &x, &y);
Kristian Høgsberg07937562011-04-12 17:25:42 -04002317
Pekka Paalanen60921e52012-01-25 15:55:43 +02002318 if (x < surface->geometry.width / 3)
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02002319 edges |= WL_SHELL_SURFACE_RESIZE_LEFT;
Pekka Paalanen60921e52012-01-25 15:55:43 +02002320 else if (x < 2 * surface->geometry.width / 3)
Kristian Høgsberg07937562011-04-12 17:25:42 -04002321 edges |= 0;
2322 else
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02002323 edges |= WL_SHELL_SURFACE_RESIZE_RIGHT;
Kristian Høgsberg07937562011-04-12 17:25:42 -04002324
Pekka Paalanen60921e52012-01-25 15:55:43 +02002325 if (y < surface->geometry.height / 3)
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02002326 edges |= WL_SHELL_SURFACE_RESIZE_TOP;
Pekka Paalanen60921e52012-01-25 15:55:43 +02002327 else if (y < 2 * surface->geometry.height / 3)
Kristian Høgsberg07937562011-04-12 17:25:42 -04002328 edges |= 0;
2329 else
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02002330 edges |= WL_SHELL_SURFACE_RESIZE_BOTTOM;
Kristian Høgsberg07937562011-04-12 17:25:42 -04002331
Kristian Høgsbergc1693f22012-05-22 16:56:23 -04002332 surface_resize(shsurf, (struct weston_seat *) seat, edges);
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04002333}
2334
2335static void
Daniel Stone325fc2d2012-05-30 16:31:58 +01002336surface_opacity_binding(struct wl_seat *seat, uint32_t time, uint32_t axis,
Daniel Stone0c1e46e2012-05-30 16:31:59 +01002337 wl_fixed_t value, void *data)
Scott Moreaua3aa9c92012-03-22 11:01:03 -06002338{
Scott Moreau02709af2012-05-22 01:54:10 -06002339 float step = 0.05;
Scott Moreaua3aa9c92012-03-22 11:01:03 -06002340 struct shell_surface *shsurf;
2341 struct weston_surface *surface =
Daniel Stone37816df2012-05-16 18:45:18 +01002342 (struct weston_surface *) seat->pointer->focus;
Scott Moreaua3aa9c92012-03-22 11:01:03 -06002343
2344 if (surface == NULL)
2345 return;
2346
2347 shsurf = get_shell_surface(surface);
2348 if (!shsurf)
2349 return;
2350
Daniel Stone0c1e46e2012-05-30 16:31:59 +01002351 surface->alpha += wl_fixed_to_double(value) * step;
Scott Moreaua3aa9c92012-03-22 11:01:03 -06002352
Scott Moreau02709af2012-05-22 01:54:10 -06002353 if (surface->alpha > 1.0)
2354 surface->alpha = 1.0;
Scott Moreaua3aa9c92012-03-22 11:01:03 -06002355 if (surface->alpha < step)
2356 surface->alpha = step;
2357
2358 surface->geometry.dirty = 1;
2359 weston_surface_damage(surface);
2360}
2361
2362static void
Daniel Stone325fc2d2012-05-30 16:31:58 +01002363do_zoom(struct wl_seat *seat, uint32_t time, uint32_t key, uint32_t axis,
Daniel Stone0c1e46e2012-05-30 16:31:59 +01002364 wl_fixed_t value)
Scott Moreauccbf29d2012-02-22 14:21:41 -07002365{
Daniel Stone37816df2012-05-16 18:45:18 +01002366 struct weston_seat *ws = (struct weston_seat *) seat;
2367 struct weston_compositor *compositor = ws->compositor;
Scott Moreauccbf29d2012-02-22 14:21:41 -07002368 struct weston_output *output;
Scott Moreaue6603982012-06-11 13:07:51 -06002369 float increment;
Scott Moreauccbf29d2012-02-22 14:21:41 -07002370
2371 wl_list_for_each(output, &compositor->output_list, link) {
2372 if (pixman_region32_contains_point(&output->region,
Daniel Stone37816df2012-05-16 18:45:18 +01002373 wl_fixed_to_double(seat->pointer->x),
2374 wl_fixed_to_double(seat->pointer->y),
Daniel Stone103db7f2012-05-08 17:17:55 +01002375 NULL)) {
Daniel Stone325fc2d2012-05-30 16:31:58 +01002376 if (key == KEY_PAGEUP)
Kristian Høgsberg9b68af02012-05-22 12:55:18 -04002377 increment = output->zoom.increment;
Daniel Stone325fc2d2012-05-30 16:31:58 +01002378 else if (key == KEY_PAGEDOWN)
Kristian Høgsberg9b68af02012-05-22 12:55:18 -04002379 increment = -output->zoom.increment;
2380 else if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
Daniel Stone0c1e46e2012-05-30 16:31:59 +01002381 increment = output->zoom.increment *
2382 wl_fixed_to_double(value);
Kristian Høgsberg9b68af02012-05-22 12:55:18 -04002383 else
2384 increment = 0;
2385
Kristian Høgsberg9b68af02012-05-22 12:55:18 -04002386 output->zoom.level += increment;
Scott Moreauc6d7f602012-02-23 22:28:37 -07002387
Scott Moreaue6603982012-06-11 13:07:51 -06002388 if (output->zoom.level < 0.0)
Scott Moreau850ca422012-05-21 15:21:25 -06002389 output->zoom.level = 0.0;
Scott Moreaue6603982012-06-11 13:07:51 -06002390 else if (output->zoom.level > output->zoom.max_level)
2391 output->zoom.level = output->zoom.max_level;
Kristian Høgsberg79af73e2012-08-03 15:45:23 -04002392 else {
Scott Moreaue6603982012-06-11 13:07:51 -06002393 output->zoom.active = 1;
Kristian Høgsberg79af73e2012-08-03 15:45:23 -04002394 output->disable_planes++;
2395 }
Scott Moreauccbf29d2012-02-22 14:21:41 -07002396
Scott Moreaue6603982012-06-11 13:07:51 -06002397 output->zoom.spring_z.target = output->zoom.level;
Scott Moreauccbf29d2012-02-22 14:21:41 -07002398
Scott Moreau8dacaab2012-06-17 18:10:58 -06002399 weston_output_update_zoom(output, output->zoom.type);
Scott Moreauccbf29d2012-02-22 14:21:41 -07002400 }
2401 }
2402}
2403
Scott Moreauccbf29d2012-02-22 14:21:41 -07002404static void
Daniel Stone325fc2d2012-05-30 16:31:58 +01002405zoom_axis_binding(struct wl_seat *seat, uint32_t time, uint32_t axis,
Daniel Stone0c1e46e2012-05-30 16:31:59 +01002406 wl_fixed_t value, void *data)
Daniel Stone325fc2d2012-05-30 16:31:58 +01002407{
2408 do_zoom(seat, time, 0, axis, value);
2409}
2410
2411static void
2412zoom_key_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
2413 void *data)
2414{
2415 do_zoom(seat, time, key, 0, 0);
2416}
2417
2418static void
2419terminate_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
2420 void *data)
Kristian Høgsberge1a850e2011-12-19 15:18:05 -05002421{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002422 struct weston_compositor *compositor = data;
Kristian Høgsberge1a850e2011-12-19 15:18:05 -05002423
Daniel Stone325fc2d2012-05-30 16:31:58 +01002424 wl_display_terminate(compositor->wl_display);
Kristian Høgsberge1a850e2011-12-19 15:18:05 -05002425}
2426
2427static void
Scott Moreau447013d2012-02-18 05:05:29 -07002428rotate_grab_motion(struct wl_pointer_grab *grab,
Daniel Stone103db7f2012-05-08 17:17:55 +01002429 uint32_t time, wl_fixed_t x, wl_fixed_t y)
Pekka Paalanen460099f2012-01-20 16:48:25 +02002430{
2431 struct rotate_grab *rotate =
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +03002432 container_of(grab, struct rotate_grab, base.grab);
Daniel Stone37816df2012-05-16 18:45:18 +01002433 struct wl_pointer *pointer = grab->pointer;
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +03002434 struct shell_surface *shsurf = rotate->base.shsurf;
2435 struct weston_surface *surface;
2436 GLfloat cx, cy, dx, dy, cposx, cposy, dposx, dposy, r;
2437
2438 if (!shsurf)
2439 return;
2440
2441 surface = shsurf->surface;
2442
2443 cx = 0.5f * surface->geometry.width;
2444 cy = 0.5f * surface->geometry.height;
Pekka Paalanen460099f2012-01-20 16:48:25 +02002445
Daniel Stone37816df2012-05-16 18:45:18 +01002446 dx = wl_fixed_to_double(pointer->x) - rotate->center.x;
2447 dy = wl_fixed_to_double(pointer->y) - rotate->center.y;
Pekka Paalanen460099f2012-01-20 16:48:25 +02002448 r = sqrtf(dx * dx + dy * dy);
2449
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +03002450 wl_list_remove(&shsurf->rotation.transform.link);
2451 shsurf->surface->geometry.dirty = 1;
Pekka Paalanen460099f2012-01-20 16:48:25 +02002452
2453 if (r > 20.0f) {
Pekka Paalanen460099f2012-01-20 16:48:25 +02002454 struct weston_matrix *matrix =
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +03002455 &shsurf->rotation.transform.matrix;
Pekka Paalanen460099f2012-01-20 16:48:25 +02002456
Kristian Høgsberg765e27b2012-01-27 13:36:13 -05002457 weston_matrix_init(&rotate->rotation);
2458 rotate->rotation.d[0] = dx / r;
2459 rotate->rotation.d[4] = -dy / r;
2460 rotate->rotation.d[1] = -rotate->rotation.d[4];
2461 rotate->rotation.d[5] = rotate->rotation.d[0];
Pekka Paalanen460099f2012-01-20 16:48:25 +02002462
2463 weston_matrix_init(matrix);
Pekka Paalanen7b3bd3d2012-01-30 14:16:34 +02002464 weston_matrix_translate(matrix, -cx, -cy, 0.0f);
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +03002465 weston_matrix_multiply(matrix, &shsurf->rotation.rotation);
Kristian Høgsberg765e27b2012-01-27 13:36:13 -05002466 weston_matrix_multiply(matrix, &rotate->rotation);
Pekka Paalanen7b3bd3d2012-01-30 14:16:34 +02002467 weston_matrix_translate(matrix, cx, cy, 0.0f);
Pekka Paalanen460099f2012-01-20 16:48:25 +02002468
Pekka Paalanenbc0b7e72012-01-24 09:53:37 +02002469 wl_list_insert(
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +03002470 &shsurf->surface->geometry.transformation_list,
2471 &shsurf->rotation.transform.link);
Pekka Paalanen460099f2012-01-20 16:48:25 +02002472 } else {
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +03002473 wl_list_init(&shsurf->rotation.transform.link);
2474 weston_matrix_init(&shsurf->rotation.rotation);
Kristian Høgsberg765e27b2012-01-27 13:36:13 -05002475 weston_matrix_init(&rotate->rotation);
Pekka Paalanen460099f2012-01-20 16:48:25 +02002476 }
Pekka Paalanenb45ac5e2012-02-09 15:58:44 +02002477
Rafal Mielniczuk2d7ab822012-03-22 22:22:04 +01002478 /* We need to adjust the position of the surface
2479 * in case it was resized in a rotated state before */
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +03002480 cposx = surface->geometry.x + cx;
2481 cposy = surface->geometry.y + cy;
Rafal Mielniczuk2d7ab822012-03-22 22:22:04 +01002482 dposx = rotate->center.x - cposx;
2483 dposy = rotate->center.y - cposy;
2484 if (dposx != 0.0f || dposy != 0.0f) {
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +03002485 weston_surface_set_position(surface,
2486 surface->geometry.x + dposx,
2487 surface->geometry.y + dposy);
Rafal Mielniczuk2d7ab822012-03-22 22:22:04 +01002488 }
2489
Pekka Paalanenb45ac5e2012-02-09 15:58:44 +02002490 /* Repaint implies weston_surface_update_transform(), which
2491 * lazily applies the damage due to rotation update.
2492 */
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +03002493 weston_compositor_schedule_repaint(shsurf->surface->compositor);
Pekka Paalanen460099f2012-01-20 16:48:25 +02002494}
2495
2496static void
Scott Moreau447013d2012-02-18 05:05:29 -07002497rotate_grab_button(struct wl_pointer_grab *grab,
Daniel Stone4dbadb12012-05-30 16:31:51 +01002498 uint32_t time, uint32_t button, uint32_t state_w)
Pekka Paalanen460099f2012-01-20 16:48:25 +02002499{
2500 struct rotate_grab *rotate =
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +03002501 container_of(grab, struct rotate_grab, base.grab);
Daniel Stone37816df2012-05-16 18:45:18 +01002502 struct wl_pointer *pointer = grab->pointer;
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +03002503 struct shell_surface *shsurf = rotate->base.shsurf;
Daniel Stone4dbadb12012-05-30 16:31:51 +01002504 enum wl_pointer_button_state state = state_w;
Pekka Paalanen460099f2012-01-20 16:48:25 +02002505
Daniel Stone4dbadb12012-05-30 16:31:51 +01002506 if (pointer->button_count == 0 &&
2507 state == WL_POINTER_BUTTON_STATE_RELEASED) {
Ander Conselvan de Oliveirafe0444a2012-04-04 17:48:05 +03002508 if (shsurf)
2509 weston_matrix_multiply(&shsurf->rotation.rotation,
2510 &rotate->rotation);
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03002511 shell_grab_end(&rotate->base);
Pekka Paalanen460099f2012-01-20 16:48:25 +02002512 free(rotate);
2513 }
2514}
2515
Scott Moreau447013d2012-02-18 05:05:29 -07002516static const struct wl_pointer_grab_interface rotate_grab_interface = {
Pekka Paalanen460099f2012-01-20 16:48:25 +02002517 noop_grab_focus,
2518 rotate_grab_motion,
2519 rotate_grab_button,
2520};
2521
2522static void
Daniel Stone325fc2d2012-05-30 16:31:58 +01002523rotate_binding(struct wl_seat *seat, uint32_t time, uint32_t button,
Daniel Stonee5a01202012-05-04 11:21:57 +01002524 void *data)
Pekka Paalanen460099f2012-01-20 16:48:25 +02002525{
2526 struct weston_surface *base_surface =
Daniel Stone37816df2012-05-16 18:45:18 +01002527 (struct weston_surface *) seat->pointer->focus;
Pekka Paalanen460099f2012-01-20 16:48:25 +02002528 struct shell_surface *surface;
2529 struct rotate_grab *rotate;
Rafal Mielniczuk2d7ab822012-03-22 22:22:04 +01002530 GLfloat dx, dy;
Kristian Høgsberg765e27b2012-01-27 13:36:13 -05002531 GLfloat r;
Pekka Paalanen460099f2012-01-20 16:48:25 +02002532
2533 if (base_surface == NULL)
2534 return;
2535
2536 surface = get_shell_surface(base_surface);
Kristian Høgsberg0636ac32012-06-27 10:22:15 -04002537 if (!surface || surface->type == SHELL_SURFACE_FULLSCREEN)
Pekka Paalanen460099f2012-01-20 16:48:25 +02002538 return;
2539
Pekka Paalanen460099f2012-01-20 16:48:25 +02002540 rotate = malloc(sizeof *rotate);
2541 if (!rotate)
2542 return;
2543
Kristian Høgsbergb2af93e2012-06-07 20:10:23 -04002544 weston_surface_to_global_float(surface->surface,
2545 surface->surface->geometry.width / 2,
2546 surface->surface->geometry.height / 2,
2547 &rotate->center.x, &rotate->center.y);
Pekka Paalanen460099f2012-01-20 16:48:25 +02002548
Daniel Stone37816df2012-05-16 18:45:18 +01002549 dx = wl_fixed_to_double(seat->pointer->x) - rotate->center.x;
2550 dy = wl_fixed_to_double(seat->pointer->y) - rotate->center.y;
Kristian Høgsberg765e27b2012-01-27 13:36:13 -05002551 r = sqrtf(dx * dx + dy * dy);
2552 if (r > 20.0f) {
2553 struct weston_matrix inverse;
2554
2555 weston_matrix_init(&inverse);
2556 inverse.d[0] = dx / r;
2557 inverse.d[4] = dy / r;
2558 inverse.d[1] = -inverse.d[4];
2559 inverse.d[5] = inverse.d[0];
2560 weston_matrix_multiply(&surface->rotation.rotation, &inverse);
Rafal Mielniczuk2d7ab822012-03-22 22:22:04 +01002561
2562 weston_matrix_init(&rotate->rotation);
2563 rotate->rotation.d[0] = dx / r;
2564 rotate->rotation.d[4] = -dy / r;
2565 rotate->rotation.d[1] = -rotate->rotation.d[4];
2566 rotate->rotation.d[5] = rotate->rotation.d[0];
Kristian Høgsberg765e27b2012-01-27 13:36:13 -05002567 } else {
2568 weston_matrix_init(&surface->rotation.rotation);
2569 weston_matrix_init(&rotate->rotation);
2570 }
2571
Ander Conselvan de Oliveirab9d2a0f2012-06-28 18:08:05 +03002572 shell_grab_start(&rotate->base, &rotate_grab_interface, surface,
2573 seat->pointer, DESKTOP_SHELL_CURSOR_ARROW);
Pekka Paalanen460099f2012-01-20 16:48:25 +02002574}
2575
2576static void
Kristian Høgsbergb0d8e772012-06-18 16:34:58 -04002577lower_fullscreen_layer(struct desktop_shell *shell)
2578{
2579 struct workspace *ws;
2580 struct weston_surface *surface, *prev;
2581
2582 ws = get_current_workspace(shell);
2583 wl_list_for_each_reverse_safe(surface, prev,
2584 &shell->fullscreen_layer.surface_list,
2585 layer_link)
2586 weston_surface_restack(surface, &ws->layer.surface_list);
2587}
2588
2589static void
Tiago Vignattibe143262012-04-16 17:31:41 +03002590activate(struct desktop_shell *shell, struct weston_surface *es,
Daniel Stone37816df2012-05-16 18:45:18 +01002591 struct weston_seat *seat)
Kristian Høgsberg75840622011-09-06 13:48:16 -04002592{
Kristian Høgsberg2f5faff2012-07-31 16:36:34 -04002593 struct workspace *ws = get_current_workspace(shell);
2594 struct focus_state *state;
Kristian Høgsberg75840622011-09-06 13:48:16 -04002595
Daniel Stone37816df2012-05-16 18:45:18 +01002596 weston_surface_activate(es, seat);
Kristian Høgsberg75840622011-09-06 13:48:16 -04002597
Kristian Høgsberg2f5faff2012-07-31 16:36:34 -04002598 wl_list_for_each(state, &ws->focus_list, link)
2599 if (state->seat == seat)
2600 break;
2601
2602 if (&state->link == &ws->focus_list) {
2603 state = focus_state_create(seat, ws);
2604 if (state == NULL)
2605 return;
2606 }
2607
2608 state->keyboard_focus = es;
2609 wl_list_remove(&state->surface_destroy_listener.link);
2610 wl_signal_add(&es->surface.resource.destroy_signal,
2611 &state->surface_destroy_listener);
2612
Pekka Paalanen92a0dc42011-11-28 15:34:13 +02002613 switch (get_shell_surface_type(es)) {
Alex Wu4539b082012-03-01 12:57:46 +08002614 case SHELL_SURFACE_FULLSCREEN:
2615 /* should on top of panels */
Alex Wu21858432012-04-01 20:13:08 +08002616 shell_stack_fullscreen(get_shell_surface(es));
Alex Wubd3354b2012-04-17 17:20:49 +08002617 shell_configure_fullscreen(get_shell_surface(es));
Alex Wu4539b082012-03-01 12:57:46 +08002618 break;
Pekka Paalanen57da4a82011-11-23 16:42:16 +02002619 default:
Jonas Ådahle3cddce2012-06-13 00:01:22 +02002620 ws = get_current_workspace(shell);
Kristian Høgsbergb0d8e772012-06-18 16:34:58 -04002621 lower_fullscreen_layer(shell);
2622 weston_surface_restack(es, &ws->layer.surface_list);
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -05002623 break;
Kristian Høgsberg75840622011-09-06 13:48:16 -04002624 }
2625}
2626
Alex Wu21858432012-04-01 20:13:08 +08002627/* no-op func for checking black surface */
2628static void
2629black_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy)
2630{
2631}
2632
2633static bool
2634is_black_surface (struct weston_surface *es, struct weston_surface **fs_surface)
2635{
2636 if (es->configure == black_surface_configure) {
2637 if (fs_surface)
2638 *fs_surface = (struct weston_surface *)es->private;
2639 return true;
2640 }
2641 return false;
2642}
2643
Kristian Høgsberg75840622011-09-06 13:48:16 -04002644static void
Daniel Stone325fc2d2012-05-30 16:31:58 +01002645click_to_activate_binding(struct wl_seat *seat, uint32_t time, uint32_t button,
Daniel Stone4dbadb12012-05-30 16:31:51 +01002646 void *data)
Kristian Høgsberge1a850e2011-12-19 15:18:05 -05002647{
Daniel Stone37816df2012-05-16 18:45:18 +01002648 struct weston_seat *ws = (struct weston_seat *) seat;
Tiago Vignattibe143262012-04-16 17:31:41 +03002649 struct desktop_shell *shell = data;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002650 struct weston_surface *focus;
Alex Wu4539b082012-03-01 12:57:46 +08002651 struct weston_surface *upper;
Kristian Høgsberge1a850e2011-12-19 15:18:05 -05002652
Daniel Stone37816df2012-05-16 18:45:18 +01002653 focus = (struct weston_surface *) seat->pointer->focus;
Alex Wu9c35e6b2012-03-05 14:13:13 +08002654 if (!focus)
2655 return;
2656
Alex Wu21858432012-04-01 20:13:08 +08002657 if (is_black_surface(focus, &upper))
Alex Wu4539b082012-03-01 12:57:46 +08002658 focus = upper;
Alex Wu4539b082012-03-01 12:57:46 +08002659
Kristian Høgsberg0636ac32012-06-27 10:22:15 -04002660 if (get_shell_surface_type(focus) == SHELL_SURFACE_NONE)
2661 return;
Kristian Høgsberg85b2e4b2012-06-21 16:49:42 -04002662
Daniel Stone325fc2d2012-05-30 16:31:58 +01002663 if (seat->pointer->grab == &seat->pointer->default_grab)
Daniel Stone37816df2012-05-16 18:45:18 +01002664 activate(shell, focus, ws);
Kristian Høgsberge1a850e2011-12-19 15:18:05 -05002665}
2666
2667static void
Kristian Høgsberg02e79dc2012-04-12 09:55:26 -04002668lock(struct wl_listener *listener, void *data)
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04002669{
Tiago Vignattibe143262012-04-16 17:31:41 +03002670 struct desktop_shell *shell =
2671 container_of(listener, struct desktop_shell, lock_listener);
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02002672 struct weston_output *output;
Kristian Høgsberg4476aaf2012-06-25 14:03:13 -04002673 struct workspace *ws = get_current_workspace(shell);
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02002674
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02002675 if (shell->locked) {
2676 wl_list_for_each(output, &shell->compositor->output_list, link)
2677 /* TODO: find a way to jump to other DPMS levels */
2678 if (output->set_dpms)
2679 output->set_dpms(output, WESTON_DPMS_STANDBY);
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02002680 return;
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02002681 }
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02002682
2683 shell->locked = true;
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02002684
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -05002685 /* Hide all surfaces by removing the fullscreen, panel and
2686 * toplevel layers. This way nothing else can show or receive
2687 * input events while we are locked. */
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02002688
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -05002689 wl_list_remove(&shell->panel_layer.link);
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -05002690 wl_list_remove(&shell->fullscreen_layer.link);
Philipp Brüschweiler711fda82012-08-09 18:50:43 +02002691 if (shell->showing_input_panels)
2692 wl_list_remove(&shell->input_panel_layer.link);
Kristian Høgsberg4476aaf2012-06-25 14:03:13 -04002693 wl_list_remove(&ws->layer.link);
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -05002694 wl_list_insert(&shell->compositor->cursor_layer.link,
2695 &shell->lock_layer.link);
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02002696
Pekka Paalanen77346a62011-11-30 16:26:35 +02002697 launch_screensaver(shell);
2698
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02002699 /* TODO: disable bindings that should not work while locked. */
2700
2701 /* All this must be undone in resume_desktop(). */
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02002702}
2703
2704static void
Kristian Høgsberg02e79dc2012-04-12 09:55:26 -04002705unlock(struct wl_listener *listener, void *data)
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02002706{
Tiago Vignattibe143262012-04-16 17:31:41 +03002707 struct desktop_shell *shell =
2708 container_of(listener, struct desktop_shell, unlock_listener);
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02002709
Pekka Paalanend81c2162011-11-16 13:47:34 +02002710 if (!shell->locked || shell->lock_surface) {
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002711 weston_compositor_wake(shell->compositor);
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02002712 return;
2713 }
2714
2715 /* If desktop-shell client has gone away, unlock immediately. */
2716 if (!shell->child.desktop_shell) {
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02002717 resume_desktop(shell);
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02002718 return;
2719 }
2720
2721 if (shell->prepare_event_sent)
2722 return;
2723
Kristian Høgsberg0b5cd0c2012-03-04 21:57:37 -05002724 desktop_shell_send_prepare_lock_surface(shell->child.desktop_shell);
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02002725 shell->prepare_event_sent = true;
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04002726}
2727
2728static void
Jan Arne Petersen42feced2012-06-21 21:52:17 +02002729show_input_panels(struct wl_listener *listener, void *data)
2730{
2731 struct desktop_shell *shell =
Philipp Brüschweiler711fda82012-08-09 18:50:43 +02002732 container_of(listener, struct desktop_shell,
2733 show_input_panel_listener);
Philipp Brüschweiler88013572012-08-06 13:44:42 +02002734 struct input_panel_surface *surface, *next;
2735 struct weston_surface *ws;
Jan Arne Petersen42feced2012-06-21 21:52:17 +02002736
Philipp Brüschweiler711fda82012-08-09 18:50:43 +02002737 shell->showing_input_panels = true;
2738
2739 wl_list_insert(&shell->panel_layer.link,
2740 &shell->input_panel_layer.link);
2741
Kristian Høgsberg0636ac32012-06-27 10:22:15 -04002742 wl_list_for_each_safe(surface, next,
Philipp Brüschweiler88013572012-08-06 13:44:42 +02002743 &shell->input_panel.surfaces, link) {
2744 ws = surface->surface;
Philipp Brüschweiler711fda82012-08-09 18:50:43 +02002745 wl_list_insert(&shell->input_panel_layer.surface_list,
Philipp Brüschweiler88013572012-08-06 13:44:42 +02002746 &ws->layer_link);
2747 weston_surface_assign_output(ws);
2748 weston_surface_damage(ws);
2749 weston_slide_run(ws, ws->geometry.height, 0, NULL, NULL);
Jan Arne Petersen42feced2012-06-21 21:52:17 +02002750 }
2751}
2752
2753static void
2754hide_input_panels(struct wl_listener *listener, void *data)
2755{
2756 struct desktop_shell *shell =
Philipp Brüschweiler711fda82012-08-09 18:50:43 +02002757 container_of(listener, struct desktop_shell,
2758 hide_input_panel_listener);
Kristian Høgsberg0636ac32012-06-27 10:22:15 -04002759 struct weston_surface *surface, *next;
Jan Arne Petersen42feced2012-06-21 21:52:17 +02002760
Philipp Brüschweiler711fda82012-08-09 18:50:43 +02002761 shell->showing_input_panels = false;
2762
2763 wl_list_remove(&shell->input_panel_layer.link);
2764
Kristian Høgsberg0636ac32012-06-27 10:22:15 -04002765 wl_list_for_each_safe(surface, next,
Philipp Brüschweiler711fda82012-08-09 18:50:43 +02002766 &shell->input_panel_layer.surface_list, layer_link)
2767 weston_surface_unmap(surface);
Jan Arne Petersen42feced2012-06-21 21:52:17 +02002768}
2769
2770static void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002771center_on_output(struct weston_surface *surface, struct weston_output *output)
Pekka Paalanen77346a62011-11-30 16:26:35 +02002772{
Scott Moreau1bad5db2012-08-18 01:04:05 -06002773 GLfloat x = (output->width - surface->buffer->width) / 2;
2774 GLfloat y = (output->height - surface->buffer->height) / 2;
Pekka Paalanen77346a62011-11-30 16:26:35 +02002775
Kristian Høgsberg730c94d2012-06-26 21:44:35 -04002776 weston_surface_configure(surface, output->x + x, output->y + y,
2777 surface->buffer->width,
2778 surface->buffer->height);
Pekka Paalanen77346a62011-11-30 16:26:35 +02002779}
2780
2781static void
Rob Bradfordac63e5b2012-08-13 14:07:52 +01002782weston_surface_set_initial_position (struct weston_surface *surface,
2783 struct desktop_shell *shell)
2784{
2785 struct weston_compositor *compositor = shell->compositor;
2786 int ix = 0, iy = 0;
2787 int range_x, range_y;
2788 int dx, dy, x, y, panel_height;
2789 struct weston_output *output, *target_output = NULL;
2790 struct weston_seat *seat;
2791
2792 /* As a heuristic place the new window on the same output as the
2793 * pointer. Falling back to the output containing 0, 0.
2794 *
2795 * TODO: Do something clever for touch too?
2796 */
2797 wl_list_for_each(seat, &compositor->seat_list, link) {
2798 if (seat->has_pointer) {
2799 ix = wl_fixed_to_int(seat->pointer.x);
2800 iy = wl_fixed_to_int(seat->pointer.y);
2801 break;
2802 }
2803 }
2804
2805 wl_list_for_each(output, &compositor->output_list, link) {
2806 if (pixman_region32_contains_point(&output->region, ix, iy, NULL)) {
2807 target_output = output;
2808 break;
2809 }
2810 }
2811
2812 if (!target_output) {
2813 weston_surface_set_position(surface, 10 + random() % 400,
2814 10 + random() % 400);
2815 return;
2816 }
2817
2818 /* Valid range within output where the surface will still be onscreen.
2819 * If this is negative it means that the surface is bigger than
2820 * output.
2821 */
2822 panel_height = get_output_panel_height(shell, target_output);
Scott Moreau1bad5db2012-08-18 01:04:05 -06002823 range_x = target_output->width - surface->geometry.width;
2824 range_y = (target_output->height - panel_height) -
Rob Bradfordac63e5b2012-08-13 14:07:52 +01002825 surface->geometry.height;
2826
Rob Bradford4cb88c72012-08-13 15:18:44 +01002827 if (range_x > 0)
Rob Bradfordac63e5b2012-08-13 14:07:52 +01002828 dx = random() % range_x;
Rob Bradfordac63e5b2012-08-13 14:07:52 +01002829 else
Rob Bradford4cb88c72012-08-13 15:18:44 +01002830 dx = 0;
2831
2832 if (range_y > 0)
Rob Bradfordac63e5b2012-08-13 14:07:52 +01002833 dy = panel_height + random() % range_y;
Rob Bradford4cb88c72012-08-13 15:18:44 +01002834 else
2835 dy = panel_height;
Rob Bradfordac63e5b2012-08-13 14:07:52 +01002836
2837 x = target_output->x + dx;
2838 y = target_output->y + dy;
2839
2840 weston_surface_set_position (surface, x, y);
2841}
2842
2843static void
Tiago Vignattibe143262012-04-16 17:31:41 +03002844map(struct desktop_shell *shell, struct weston_surface *surface,
Ander Conselvan de Oliveirae9e05152012-02-15 17:02:56 +02002845 int32_t width, int32_t height, int32_t sx, int32_t sy)
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04002846{
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05002847 struct weston_compositor *compositor = shell->compositor;
Jonas Ådahle3cddce2012-06-13 00:01:22 +02002848 struct shell_surface *shsurf = get_shell_surface(surface);
2849 enum shell_surface_type surface_type = shsurf->type;
Kristian Høgsberg60c49542012-03-05 20:51:34 -05002850 struct weston_surface *parent;
Daniel Stoneb2104682012-05-30 16:31:56 +01002851 struct weston_seat *seat;
Jonas Ådahle3cddce2012-06-13 00:01:22 +02002852 struct workspace *ws;
Juan Zhao96879df2012-02-07 08:45:41 +08002853 int panel_height = 0;
Pekka Paalanen57da4a82011-11-23 16:42:16 +02002854
Pekka Paalanen60921e52012-01-25 15:55:43 +02002855 surface->geometry.width = width;
2856 surface->geometry.height = height;
2857 surface->geometry.dirty = 1;
Pekka Paalanen77346a62011-11-30 16:26:35 +02002858
2859 /* initial positioning, see also configure() */
2860 switch (surface_type) {
2861 case SHELL_SURFACE_TOPLEVEL:
Rob Bradfordac63e5b2012-08-13 14:07:52 +01002862 weston_surface_set_initial_position(surface, shell);
Pekka Paalanen77346a62011-11-30 16:26:35 +02002863 break;
Alex Wu4539b082012-03-01 12:57:46 +08002864 case SHELL_SURFACE_FULLSCREEN:
Kristian Høgsberge4d3a2b2012-07-09 21:43:22 -04002865 center_on_output(surface, shsurf->fullscreen_output);
Alex Wu4539b082012-03-01 12:57:46 +08002866 shell_map_fullscreen(shsurf);
2867 break;
Juan Zhao96879df2012-02-07 08:45:41 +08002868 case SHELL_SURFACE_MAXIMIZED:
Alex Wu4539b082012-03-01 12:57:46 +08002869 /* use surface configure to set the geometry */
Juan Zhao96879df2012-02-07 08:45:41 +08002870 panel_height = get_output_panel_height(shell,surface->output);
Rob Bradford31b68622012-07-02 19:00:19 +01002871 weston_surface_set_position(surface, shsurf->output->x,
2872 shsurf->output->y + panel_height);
Juan Zhao96879df2012-02-07 08:45:41 +08002873 break;
Tiago Vignatti0f997012012-02-10 16:17:23 +02002874 case SHELL_SURFACE_POPUP:
Kristian Høgsberg3730f362012-04-13 12:40:07 -04002875 shell_map_popup(shsurf);
Ander Conselvan de Oliveirae9e05152012-02-15 17:02:56 +02002876 case SHELL_SURFACE_NONE:
2877 weston_surface_set_position(surface,
2878 surface->geometry.x + sx,
2879 surface->geometry.y + sy);
Tiago Vignatti0f997012012-02-10 16:17:23 +02002880 break;
Pekka Paalanen77346a62011-11-30 16:26:35 +02002881 default:
2882 ;
2883 }
Kristian Høgsberg75840622011-09-06 13:48:16 -04002884
Pekka Paalanend3dd6e12011-11-16 13:47:33 +02002885 /* surface stacking order, see also activate() */
Pekka Paalanen92a0dc42011-11-28 15:34:13 +02002886 switch (surface_type) {
Kristian Høgsberg60c49542012-03-05 20:51:34 -05002887 case SHELL_SURFACE_POPUP:
2888 case SHELL_SURFACE_TRANSIENT:
Kristian Høgsberg8150b192012-06-27 10:22:58 -04002889 parent = shsurf->parent;
Kristian Høgsberg60c49542012-03-05 20:51:34 -05002890 wl_list_insert(parent->layer_link.prev, &surface->layer_link);
2891 break;
Alex Wu4539b082012-03-01 12:57:46 +08002892 case SHELL_SURFACE_FULLSCREEN:
Ander Conselvan de Oliveiraa1ff53b2012-02-15 17:02:54 +02002893 case SHELL_SURFACE_NONE:
2894 break;
Pekka Paalanen57da4a82011-11-23 16:42:16 +02002895 default:
Jonas Ådahle3cddce2012-06-13 00:01:22 +02002896 ws = get_current_workspace(shell);
2897 wl_list_insert(&ws->layer.surface_list, &surface->layer_link);
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -05002898 break;
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02002899 }
2900
Ander Conselvan de Oliveirade56c312012-03-05 15:39:23 +02002901 if (surface_type != SHELL_SURFACE_NONE) {
2902 weston_surface_assign_output(surface);
Ander Conselvan de Oliveirade56c312012-03-05 15:39:23 +02002903 if (surface_type == SHELL_SURFACE_MAXIMIZED)
2904 surface->output = shsurf->output;
2905 }
Kristian Høgsberg2f88a402011-12-04 15:32:59 -05002906
Juan Zhao7bb92f02011-12-15 11:31:51 -05002907 switch (surface_type) {
Juan Zhao7bb92f02011-12-15 11:31:51 -05002908 case SHELL_SURFACE_TRANSIENT:
Tiago Vignatti99aeb1e2012-05-23 22:06:26 +03002909 if (shsurf->transient.flags ==
2910 WL_SHELL_SURFACE_TRANSIENT_INACTIVE)
2911 break;
2912 case SHELL_SURFACE_TOPLEVEL:
Juan Zhao7bb92f02011-12-15 11:31:51 -05002913 case SHELL_SURFACE_FULLSCREEN:
Juan Zhao96879df2012-02-07 08:45:41 +08002914 case SHELL_SURFACE_MAXIMIZED:
Daniel Stoneb2104682012-05-30 16:31:56 +01002915 if (!shell->locked) {
2916 wl_list_for_each(seat, &compositor->seat_list, link)
2917 activate(shell, surface, seat);
2918 }
Juan Zhao7bb92f02011-12-15 11:31:51 -05002919 break;
2920 default:
2921 break;
2922 }
2923
Kristian Høgsberg2f88a402011-12-04 15:32:59 -05002924 if (surface_type == SHELL_SURFACE_TOPLEVEL)
Juan Zhaoe10d2792012-04-25 19:09:52 +08002925 {
2926 switch (shell->win_animation_type) {
2927 case ANIMATION_FADE:
2928 weston_fade_run(surface, NULL, NULL);
2929 break;
2930 case ANIMATION_ZOOM:
2931 weston_zoom_run(surface, 0.8, 1.0, NULL, NULL);
2932 break;
2933 default:
2934 break;
2935 }
2936 }
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -05002937}
2938
2939static void
Tiago Vignattibe143262012-04-16 17:31:41 +03002940configure(struct desktop_shell *shell, struct weston_surface *surface,
Pekka Paalanenddae03c2012-02-06 14:54:20 +02002941 GLfloat x, GLfloat y, int32_t width, int32_t height)
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -05002942{
Pekka Paalanen77346a62011-11-30 16:26:35 +02002943 enum shell_surface_type surface_type = SHELL_SURFACE_NONE;
2944 struct shell_surface *shsurf;
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -05002945
Pekka Paalanen77346a62011-11-30 16:26:35 +02002946 shsurf = get_shell_surface(surface);
2947 if (shsurf)
2948 surface_type = shsurf->type;
2949
Kristian Høgsberg6a8b5532012-02-16 23:43:59 -05002950 surface->geometry.x = x;
2951 surface->geometry.y = y;
Pekka Paalanen60921e52012-01-25 15:55:43 +02002952 surface->geometry.width = width;
2953 surface->geometry.height = height;
2954 surface->geometry.dirty = 1;
Pekka Paalanen77346a62011-11-30 16:26:35 +02002955
2956 switch (surface_type) {
Alex Wu4539b082012-03-01 12:57:46 +08002957 case SHELL_SURFACE_FULLSCREEN:
Alex Wubd3354b2012-04-17 17:20:49 +08002958 shell_stack_fullscreen(shsurf);
Alex Wu4539b082012-03-01 12:57:46 +08002959 shell_configure_fullscreen(shsurf);
Alex Wu4539b082012-03-01 12:57:46 +08002960 break;
Juan Zhao96879df2012-02-07 08:45:41 +08002961 case SHELL_SURFACE_MAXIMIZED:
Alex Wu4539b082012-03-01 12:57:46 +08002962 /* setting x, y and using configure to change that geometry */
Kristian Høgsberg6a8b5532012-02-16 23:43:59 -05002963 surface->geometry.x = surface->output->x;
2964 surface->geometry.y = surface->output->y +
2965 get_output_panel_height(shell,surface->output);
Juan Zhao96879df2012-02-07 08:45:41 +08002966 break;
Alex Wu4539b082012-03-01 12:57:46 +08002967 case SHELL_SURFACE_TOPLEVEL:
2968 break;
Kristian Høgsbergd2abb832011-11-23 10:52:40 -05002969 default:
2970 break;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -04002971 }
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -05002972
Alex Wu4539b082012-03-01 12:57:46 +08002973 /* XXX: would a fullscreen surface need the same handling? */
Kristian Høgsberg6a8b5532012-02-16 23:43:59 -05002974 if (surface->output) {
Pekka Paalanenf07cb5d2012-02-10 13:34:36 +02002975 weston_surface_assign_output(surface);
Pekka Paalanen77346a62011-11-30 16:26:35 +02002976
Kristian Høgsberg1a73a632012-06-26 22:15:53 -04002977 if (surface_type == SHELL_SURFACE_MAXIMIZED)
Juan Zhao96879df2012-02-07 08:45:41 +08002978 surface->output = shsurf->output;
Pekka Paalanen77346a62011-11-30 16:26:35 +02002979 }
Kristian Høgsberg07937562011-04-12 17:25:42 -04002980}
2981
Ander Conselvan de Oliveira093bfa32012-03-27 17:36:41 +03002982static void
2983shell_surface_configure(struct weston_surface *es, int32_t sx, int32_t sy)
2984{
Ander Conselvan de Oliveira7fb9f952012-03-27 17:36:42 +03002985 struct shell_surface *shsurf = get_shell_surface(es);
Tiago Vignattibe143262012-04-16 17:31:41 +03002986 struct desktop_shell *shell = shsurf->shell;
Tiago Vignatti70e5c9c2012-05-07 15:23:07 +03002987 int type_changed = 0;
Ander Conselvan de Oliveira093bfa32012-03-27 17:36:41 +03002988
Kristian Høgsberg7f366e72012-04-27 17:20:01 -04002989 if (shsurf->next_type != SHELL_SURFACE_NONE &&
Kristian Høgsbergf7e23d52012-04-27 17:51:59 -04002990 shsurf->type != shsurf->next_type) {
Kristian Høgsberg7f366e72012-04-27 17:20:01 -04002991 set_surface_type(shsurf);
Kristian Høgsbergf7e23d52012-04-27 17:51:59 -04002992 type_changed = 1;
2993 }
Kristian Høgsberg7f366e72012-04-27 17:20:01 -04002994
Ander Conselvan de Oliveira093bfa32012-03-27 17:36:41 +03002995 if (!weston_surface_is_mapped(es)) {
2996 map(shell, es, es->buffer->width, es->buffer->height, sx, sy);
Kristian Høgsbergf7e23d52012-04-27 17:51:59 -04002997 } else if (type_changed || sx != 0 || sy != 0 ||
Ander Conselvan de Oliveira093bfa32012-03-27 17:36:41 +03002998 es->geometry.width != es->buffer->width ||
2999 es->geometry.height != es->buffer->height) {
3000 GLfloat from_x, from_y;
3001 GLfloat to_x, to_y;
3002
3003 weston_surface_to_global_float(es, 0, 0, &from_x, &from_y);
3004 weston_surface_to_global_float(es, sx, sy, &to_x, &to_y);
3005 configure(shell, es,
3006 es->geometry.x + to_x - from_x,
3007 es->geometry.y + to_y - from_y,
3008 es->buffer->width, es->buffer->height);
Ander Conselvan de Oliveira093bfa32012-03-27 17:36:41 +03003009 }
3010}
3011
Tiago Vignattibe143262012-04-16 17:31:41 +03003012static int launch_desktop_shell_process(struct desktop_shell *shell);
Pekka Paalanen4d733ee2012-01-17 14:36:27 +02003013
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -04003014static void
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05003015desktop_shell_sigchld(struct weston_process *process, int status)
Pekka Paalanen6cd281a2011-11-03 14:11:32 +02003016{
Pekka Paalanen4d733ee2012-01-17 14:36:27 +02003017 uint32_t time;
Tiago Vignattibe143262012-04-16 17:31:41 +03003018 struct desktop_shell *shell =
3019 container_of(process, struct desktop_shell, child.process);
Pekka Paalanen6cd281a2011-11-03 14:11:32 +02003020
3021 shell->child.process.pid = 0;
3022 shell->child.client = NULL; /* already destroyed by wayland */
Pekka Paalanen4d733ee2012-01-17 14:36:27 +02003023
3024 /* if desktop-shell dies more than 5 times in 30 seconds, give up */
3025 time = weston_compositor_get_time();
Kristian Høgsbergf03a6162012-01-17 11:07:42 -05003026 if (time - shell->child.deathstamp > 30000) {
Pekka Paalanen4d733ee2012-01-17 14:36:27 +02003027 shell->child.deathstamp = time;
3028 shell->child.deathcount = 0;
3029 }
3030
3031 shell->child.deathcount++;
3032 if (shell->child.deathcount > 5) {
Martin Minarik6d118362012-06-07 18:01:59 +02003033 weston_log("weston-desktop-shell died, giving up.\n");
Pekka Paalanen4d733ee2012-01-17 14:36:27 +02003034 return;
3035 }
3036
Martin Minarik6d118362012-06-07 18:01:59 +02003037 weston_log("weston-desktop-shell died, respawning...\n");
Pekka Paalanen4d733ee2012-01-17 14:36:27 +02003038 launch_desktop_shell_process(shell);
Pekka Paalanen6cd281a2011-11-03 14:11:32 +02003039}
3040
3041static int
Tiago Vignattibe143262012-04-16 17:31:41 +03003042launch_desktop_shell_process(struct desktop_shell *shell)
Pekka Paalanen6cd281a2011-11-03 14:11:32 +02003043{
Kristian Høgsberg9724b512012-01-03 14:35:49 -05003044 const char *shell_exe = LIBEXECDIR "/weston-desktop-shell";
Pekka Paalanen6cd281a2011-11-03 14:11:32 +02003045
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05003046 shell->child.client = weston_client_launch(shell->compositor,
Pekka Paalanen409ef0a2011-12-02 15:30:21 +02003047 &shell->child.process,
3048 shell_exe,
3049 desktop_shell_sigchld);
3050
3051 if (!shell->child.client)
Pekka Paalanen6cd281a2011-11-03 14:11:32 +02003052 return -1;
Pekka Paalanen6cd281a2011-11-03 14:11:32 +02003053 return 0;
3054}
3055
3056static void
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -04003057bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
3058{
Tiago Vignattibe143262012-04-16 17:31:41 +03003059 struct desktop_shell *shell = data;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -04003060
3061 wl_client_add_object(client, &wl_shell_interface,
Pekka Paalanen9d1613e2011-11-25 12:09:16 +02003062 &shell_implementation, id, shell);
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -04003063}
3064
Kristian Høgsberg75840622011-09-06 13:48:16 -04003065static void
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02003066unbind_desktop_shell(struct wl_resource *resource)
3067{
Tiago Vignattibe143262012-04-16 17:31:41 +03003068 struct desktop_shell *shell = resource->data;
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -05003069
3070 if (shell->locked)
3071 resume_desktop(shell);
3072
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02003073 shell->child.desktop_shell = NULL;
3074 shell->prepare_event_sent = false;
3075 free(resource);
3076}
3077
3078static void
Kristian Høgsberg75840622011-09-06 13:48:16 -04003079bind_desktop_shell(struct wl_client *client,
3080 void *data, uint32_t version, uint32_t id)
3081{
Tiago Vignattibe143262012-04-16 17:31:41 +03003082 struct desktop_shell *shell = data;
Pekka Paalanenbbe60522011-11-03 14:11:33 +02003083 struct wl_resource *resource;
Kristian Høgsberg75840622011-09-06 13:48:16 -04003084
Pekka Paalanenbbe60522011-11-03 14:11:33 +02003085 resource = wl_client_add_object(client, &desktop_shell_interface,
3086 &desktop_shell_implementation,
3087 id, shell);
3088
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02003089 if (client == shell->child.client) {
3090 resource->destroy = unbind_desktop_shell;
3091 shell->child.desktop_shell = resource;
Pekka Paalanenbbe60522011-11-03 14:11:33 +02003092 return;
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02003093 }
Pekka Paalanenbbe60522011-11-03 14:11:33 +02003094
3095 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
3096 "permission to bind desktop_shell denied");
Kristian Høgsbergeae5de72012-04-11 22:42:15 -04003097 wl_resource_destroy(resource);
Kristian Høgsberg75840622011-09-06 13:48:16 -04003098}
3099
Pekka Paalanen6e168112011-11-24 11:34:05 +02003100static void
Kristian Høgsberg1a73a632012-06-26 22:15:53 -04003101screensaver_configure(struct weston_surface *surface, int32_t sx, int32_t sy)
3102{
3103 struct desktop_shell *shell = surface->private;
3104
3105 if (!shell->locked)
3106 return;
3107
3108 center_on_output(surface, surface->output);
3109
3110 if (wl_list_empty(&surface->layer_link)) {
3111 wl_list_insert(shell->lock_layer.surface_list.prev,
3112 &surface->layer_link);
3113 weston_surface_assign_output(surface);
3114 shell->compositor->idle_time = shell->screensaver.duration;
3115 weston_compositor_wake(shell->compositor);
3116 shell->compositor->state = WESTON_COMPOSITOR_IDLE;
3117 }
3118}
3119
3120static void
Pekka Paalanen6e168112011-11-24 11:34:05 +02003121screensaver_set_surface(struct wl_client *client,
3122 struct wl_resource *resource,
Kristian Høgsberg1a73a632012-06-26 22:15:53 -04003123 struct wl_resource *surface_resource,
Pekka Paalanen6e168112011-11-24 11:34:05 +02003124 struct wl_resource *output_resource)
3125{
Tiago Vignattibe143262012-04-16 17:31:41 +03003126 struct desktop_shell *shell = resource->data;
Kristian Høgsberg1a73a632012-06-26 22:15:53 -04003127 struct weston_surface *surface = surface_resource->data;
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05003128 struct weston_output *output = output_resource->data;
Pekka Paalanen6e168112011-11-24 11:34:05 +02003129
Kristian Høgsberg1a73a632012-06-26 22:15:53 -04003130 surface->configure = screensaver_configure;
3131 surface->private = shell;
Pekka Paalanen77346a62011-11-30 16:26:35 +02003132 surface->output = output;
Pekka Paalanen6e168112011-11-24 11:34:05 +02003133}
3134
3135static const struct screensaver_interface screensaver_implementation = {
3136 screensaver_set_surface
3137};
3138
3139static void
3140unbind_screensaver(struct wl_resource *resource)
3141{
Tiago Vignattibe143262012-04-16 17:31:41 +03003142 struct desktop_shell *shell = resource->data;
Pekka Paalanen6e168112011-11-24 11:34:05 +02003143
Pekka Paalanen77346a62011-11-30 16:26:35 +02003144 shell->screensaver.binding = NULL;
Pekka Paalanen6e168112011-11-24 11:34:05 +02003145 free(resource);
3146}
3147
3148static void
3149bind_screensaver(struct wl_client *client,
3150 void *data, uint32_t version, uint32_t id)
3151{
Tiago Vignattibe143262012-04-16 17:31:41 +03003152 struct desktop_shell *shell = data;
Pekka Paalanen6e168112011-11-24 11:34:05 +02003153 struct wl_resource *resource;
3154
3155 resource = wl_client_add_object(client, &screensaver_interface,
3156 &screensaver_implementation,
3157 id, shell);
3158
Pekka Paalanen77346a62011-11-30 16:26:35 +02003159 if (shell->screensaver.binding == NULL) {
Pekka Paalanen6e168112011-11-24 11:34:05 +02003160 resource->destroy = unbind_screensaver;
Pekka Paalanen77346a62011-11-30 16:26:35 +02003161 shell->screensaver.binding = resource;
Pekka Paalanen6e168112011-11-24 11:34:05 +02003162 return;
3163 }
3164
3165 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
3166 "interface object already bound");
Kristian Høgsbergeae5de72012-04-11 22:42:15 -04003167 wl_resource_destroy(resource);
Pekka Paalanen6e168112011-11-24 11:34:05 +02003168}
3169
Jan Arne Petersen42feced2012-06-21 21:52:17 +02003170static void
Kristian Høgsberg0636ac32012-06-27 10:22:15 -04003171input_panel_configure(struct weston_surface *surface, int32_t sx, int32_t sy)
3172{
3173 struct weston_mode *mode = surface->output->current;
3174 GLfloat x = (mode->width - surface->buffer->width) / 2;
3175 GLfloat y = mode->height - surface->buffer->height;
3176
3177 /* Don't map the input panel here, wait for
3178 * show_input_panels signal. */
3179
3180 weston_surface_configure(surface,
3181 surface->output->x + x,
3182 surface->output->y + y,
3183 surface->buffer->width,
3184 surface->buffer->height);
3185}
3186
3187static void
Philipp Brüschweiler88013572012-08-06 13:44:42 +02003188destroy_input_panel_surface(struct wl_listener *listener,
3189 void *data)
3190{
3191 struct input_panel_surface *input_panel_surface =
3192 container_of(listener, struct input_panel_surface, listener);
3193
3194 wl_list_remove(&listener->link);
3195 wl_list_remove(&input_panel_surface->link);
3196
3197 free(input_panel_surface);
3198}
3199
3200static void
Jan Arne Petersen42feced2012-06-21 21:52:17 +02003201input_panel_set_surface(struct wl_client *client,
3202 struct wl_resource *resource,
Kristian Høgsberg0636ac32012-06-27 10:22:15 -04003203 struct wl_resource *surface_resource,
Jan Arne Petersen42feced2012-06-21 21:52:17 +02003204 struct wl_resource *output_resource)
3205{
3206 struct desktop_shell *shell = resource->data;
Kristian Høgsberg0636ac32012-06-27 10:22:15 -04003207 struct weston_surface *surface = surface_resource->data;
Jan Arne Petersen42feced2012-06-21 21:52:17 +02003208 struct weston_output *output = output_resource->data;
Philipp Brüschweiler88013572012-08-06 13:44:42 +02003209 struct input_panel_surface *input_panel_surface;
Jan Arne Petersen42feced2012-06-21 21:52:17 +02003210
Kristian Høgsberg0636ac32012-06-27 10:22:15 -04003211 surface->configure = input_panel_configure;
3212 surface->private = shell;
Jan Arne Petersen42feced2012-06-21 21:52:17 +02003213 surface->output = output;
Philipp Brüschweiler88013572012-08-06 13:44:42 +02003214
3215 input_panel_surface = malloc(sizeof *input_panel_surface);
3216 if (!input_panel_surface) {
3217 wl_resource_post_no_memory(resource);
3218 return;
3219 }
3220
3221 input_panel_surface->surface = surface;
3222 input_panel_surface->listener.notify = destroy_input_panel_surface;
3223
3224 wl_signal_add(&surface_resource->destroy_signal,
3225 &input_panel_surface->listener);
3226
3227 wl_list_insert(&shell->input_panel.surfaces,
3228 &input_panel_surface->link);
Jan Arne Petersen42feced2012-06-21 21:52:17 +02003229}
3230
3231static const struct input_panel_interface input_panel_implementation = {
3232 input_panel_set_surface
3233};
3234
3235static void
3236unbind_input_panel(struct wl_resource *resource)
3237{
3238 struct desktop_shell *shell = resource->data;
3239
3240 shell->input_panel.binding = NULL;
3241 free(resource);
3242}
3243
3244static void
3245bind_input_panel(struct wl_client *client,
3246 void *data, uint32_t version, uint32_t id)
3247{
3248 struct desktop_shell *shell = data;
3249 struct wl_resource *resource;
3250
3251 resource = wl_client_add_object(client, &input_panel_interface,
3252 &input_panel_implementation,
3253 id, shell);
3254
3255 if (shell->input_panel.binding == NULL) {
3256 resource->destroy = unbind_input_panel;
3257 shell->input_panel.binding = resource;
3258 return;
3259 }
3260
3261 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
3262 "interface object already bound");
3263 wl_resource_destroy(resource);
3264}
3265
Kristian Høgsberg07045392012-02-19 18:52:44 -05003266struct switcher {
Tiago Vignattibe143262012-04-16 17:31:41 +03003267 struct desktop_shell *shell;
Kristian Høgsberg07045392012-02-19 18:52:44 -05003268 struct weston_surface *current;
3269 struct wl_listener listener;
3270 struct wl_keyboard_grab grab;
3271};
3272
3273static void
3274switcher_next(struct switcher *switcher)
3275{
Kristian Høgsberg07045392012-02-19 18:52:44 -05003276 struct weston_surface *surface;
3277 struct weston_surface *first = NULL, *prev = NULL, *next = NULL;
Kristian Høgsberg32e56862012-04-02 22:18:58 -04003278 struct shell_surface *shsurf;
Kristian Høgsbergb0d8e772012-06-18 16:34:58 -04003279 struct workspace *ws = get_current_workspace(switcher->shell);
Kristian Høgsberg07045392012-02-19 18:52:44 -05003280
Kristian Høgsbergb0d8e772012-06-18 16:34:58 -04003281 wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
Kristian Høgsberg07045392012-02-19 18:52:44 -05003282 switch (get_shell_surface_type(surface)) {
3283 case SHELL_SURFACE_TOPLEVEL:
3284 case SHELL_SURFACE_FULLSCREEN:
3285 case SHELL_SURFACE_MAXIMIZED:
3286 if (first == NULL)
3287 first = surface;
3288 if (prev == switcher->current)
3289 next = surface;
3290 prev = surface;
Scott Moreau02709af2012-05-22 01:54:10 -06003291 surface->alpha = 0.25;
Kristian Høgsbergcacb7cd2012-02-28 09:20:21 -05003292 surface->geometry.dirty = 1;
Kristian Høgsberg07045392012-02-19 18:52:44 -05003293 weston_surface_damage(surface);
3294 break;
3295 default:
3296 break;
3297 }
Alex Wu1659daa2012-04-01 20:13:09 +08003298
3299 if (is_black_surface(surface, NULL)) {
Scott Moreau02709af2012-05-22 01:54:10 -06003300 surface->alpha = 0.25;
Alex Wu1659daa2012-04-01 20:13:09 +08003301 surface->geometry.dirty = 1;
3302 weston_surface_damage(surface);
3303 }
Kristian Høgsberg07045392012-02-19 18:52:44 -05003304 }
3305
3306 if (next == NULL)
3307 next = first;
3308
Alex Wu07b26062012-03-12 16:06:01 +08003309 if (next == NULL)
3310 return;
3311
Kristian Høgsberg07045392012-02-19 18:52:44 -05003312 wl_list_remove(&switcher->listener.link);
Kristian Høgsberg27e30522012-04-11 23:18:23 -04003313 wl_signal_add(&next->surface.resource.destroy_signal,
3314 &switcher->listener);
Kristian Høgsberg07045392012-02-19 18:52:44 -05003315
3316 switcher->current = next;
Kristian Høgsberga416fa12012-05-21 14:06:52 -04003317 next->alpha = 1.0;
Alex Wu1659daa2012-04-01 20:13:09 +08003318
Kristian Høgsberg32e56862012-04-02 22:18:58 -04003319 shsurf = get_shell_surface(switcher->current);
3320 if (shsurf && shsurf->type ==SHELL_SURFACE_FULLSCREEN)
Kristian Høgsberga416fa12012-05-21 14:06:52 -04003321 shsurf->fullscreen.black_surface->alpha = 1.0;
Kristian Høgsberg07045392012-02-19 18:52:44 -05003322}
3323
3324static void
Kristian Høgsberg27e30522012-04-11 23:18:23 -04003325switcher_handle_surface_destroy(struct wl_listener *listener, void *data)
Kristian Høgsberg07045392012-02-19 18:52:44 -05003326{
3327 struct switcher *switcher =
3328 container_of(listener, struct switcher, listener);
3329
3330 switcher_next(switcher);
3331}
3332
3333static void
Daniel Stone351eb612012-05-31 15:27:47 -04003334switcher_destroy(struct switcher *switcher)
Kristian Høgsberg07045392012-02-19 18:52:44 -05003335{
Kristian Høgsberg07045392012-02-19 18:52:44 -05003336 struct weston_surface *surface;
Daniel Stone37816df2012-05-16 18:45:18 +01003337 struct wl_keyboard *keyboard = switcher->grab.keyboard;
Kristian Høgsbergb0d8e772012-06-18 16:34:58 -04003338 struct workspace *ws = get_current_workspace(switcher->shell);
Kristian Høgsberg07045392012-02-19 18:52:44 -05003339
Kristian Høgsbergb0d8e772012-06-18 16:34:58 -04003340 wl_list_for_each(surface, &ws->layer.surface_list, layer_link) {
Kristian Høgsberga416fa12012-05-21 14:06:52 -04003341 surface->alpha = 1.0;
Kristian Høgsberg07045392012-02-19 18:52:44 -05003342 weston_surface_damage(surface);
3343 }
3344
Alex Wu07b26062012-03-12 16:06:01 +08003345 if (switcher->current)
Daniel Stone37816df2012-05-16 18:45:18 +01003346 activate(switcher->shell, switcher->current,
3347 (struct weston_seat *) keyboard->seat);
Kristian Høgsberg07045392012-02-19 18:52:44 -05003348 wl_list_remove(&switcher->listener.link);
Daniel Stone37816df2012-05-16 18:45:18 +01003349 wl_keyboard_end_grab(keyboard);
Kristian Høgsberg07045392012-02-19 18:52:44 -05003350 free(switcher);
3351}
3352
3353static void
3354switcher_key(struct wl_keyboard_grab *grab,
Daniel Stonec9785ea2012-05-30 16:31:52 +01003355 uint32_t time, uint32_t key, uint32_t state_w)
Kristian Høgsberg07045392012-02-19 18:52:44 -05003356{
3357 struct switcher *switcher = container_of(grab, struct switcher, grab);
Daniel Stonec9785ea2012-05-30 16:31:52 +01003358 enum wl_keyboard_key_state state = state_w;
Daniel Stone351eb612012-05-31 15:27:47 -04003359
Daniel Stonec9785ea2012-05-30 16:31:52 +01003360 if (key == KEY_TAB && state == WL_KEYBOARD_KEY_STATE_PRESSED)
Daniel Stone351eb612012-05-31 15:27:47 -04003361 switcher_next(switcher);
3362}
3363
3364static void
3365switcher_modifier(struct wl_keyboard_grab *grab, uint32_t serial,
3366 uint32_t mods_depressed, uint32_t mods_latched,
3367 uint32_t mods_locked, uint32_t group)
3368{
3369 struct switcher *switcher = container_of(grab, struct switcher, grab);
Daniel Stone37816df2012-05-16 18:45:18 +01003370 struct weston_seat *seat = (struct weston_seat *) grab->keyboard->seat;
Kristian Høgsberg07045392012-02-19 18:52:44 -05003371
Daniel Stone351eb612012-05-31 15:27:47 -04003372 if ((seat->modifier_state & switcher->shell->binding_modifier) == 0)
3373 switcher_destroy(switcher);
Kristian Høgsbergb71302e2012-05-10 12:28:35 -04003374}
Kristian Høgsberg07045392012-02-19 18:52:44 -05003375
3376static const struct wl_keyboard_grab_interface switcher_grab = {
Daniel Stone351eb612012-05-31 15:27:47 -04003377 switcher_key,
3378 switcher_modifier,
Kristian Høgsberg07045392012-02-19 18:52:44 -05003379};
3380
3381static void
Daniel Stone325fc2d2012-05-30 16:31:58 +01003382switcher_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
3383 void *data)
Kristian Høgsberg07045392012-02-19 18:52:44 -05003384{
Tiago Vignattibe143262012-04-16 17:31:41 +03003385 struct desktop_shell *shell = data;
Kristian Høgsberg07045392012-02-19 18:52:44 -05003386 struct switcher *switcher;
3387
3388 switcher = malloc(sizeof *switcher);
Kristian Høgsberg02e79dc2012-04-12 09:55:26 -04003389 switcher->shell = shell;
Kristian Høgsberg07045392012-02-19 18:52:44 -05003390 switcher->current = NULL;
Kristian Høgsberg27e30522012-04-11 23:18:23 -04003391 switcher->listener.notify = switcher_handle_surface_destroy;
Kristian Høgsberg07045392012-02-19 18:52:44 -05003392 wl_list_init(&switcher->listener.link);
3393
Kristian Høgsbergb0d8e772012-06-18 16:34:58 -04003394 lower_fullscreen_layer(switcher->shell);
Kristian Høgsberg07045392012-02-19 18:52:44 -05003395 switcher->grab.interface = &switcher_grab;
Daniel Stone37816df2012-05-16 18:45:18 +01003396 wl_keyboard_start_grab(seat->keyboard, &switcher->grab);
3397 wl_keyboard_set_focus(seat->keyboard, NULL);
Kristian Høgsberg07045392012-02-19 18:52:44 -05003398 switcher_next(switcher);
3399}
3400
Pekka Paalanen3c647232011-12-22 13:43:43 +02003401static void
Daniel Stone325fc2d2012-05-30 16:31:58 +01003402backlight_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
3403 void *data)
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02003404{
3405 struct weston_compositor *compositor = data;
3406 struct weston_output *output;
Tiago Vignatti5ab91ad2012-03-12 19:40:09 -03003407 long backlight_new = 0;
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02003408
3409 /* TODO: we're limiting to simple use cases, where we assume just
3410 * control on the primary display. We'd have to extend later if we
3411 * ever get support for setting backlights on random desktop LCD
3412 * panels though */
3413 output = get_default_output(compositor);
3414 if (!output)
3415 return;
3416
3417 if (!output->set_backlight)
3418 return;
3419
Tiago Vignatti5ab91ad2012-03-12 19:40:09 -03003420 if (key == KEY_F9 || key == KEY_BRIGHTNESSDOWN)
3421 backlight_new = output->backlight_current - 25;
3422 else if (key == KEY_F10 || key == KEY_BRIGHTNESSUP)
3423 backlight_new = output->backlight_current + 25;
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02003424
Tiago Vignatti5ab91ad2012-03-12 19:40:09 -03003425 if (backlight_new < 5)
3426 backlight_new = 5;
3427 if (backlight_new > 255)
3428 backlight_new = 255;
3429
3430 output->backlight_current = backlight_new;
Tiago Vignatti8e53c7f2012-02-29 19:53:50 +02003431 output->set_backlight(output, output->backlight_current);
3432}
3433
3434static void
Daniel Stone325fc2d2012-05-30 16:31:58 +01003435debug_repaint_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
3436 void *data)
Kristian Høgsbergb41c0812012-03-04 14:53:40 -05003437{
Tiago Vignattibe143262012-04-16 17:31:41 +03003438 struct desktop_shell *shell = data;
Kristian Høgsberg02e79dc2012-04-12 09:55:26 -04003439 struct weston_compositor *compositor = shell->compositor;
Kristian Høgsbergb41c0812012-03-04 14:53:40 -05003440 struct weston_surface *surface;
Ander Conselvan de Oliveira383b6712012-08-09 16:44:59 +03003441 struct weston_plane plane;
Kristian Høgsbergb41c0812012-03-04 14:53:40 -05003442
3443 if (shell->debug_repaint_surface) {
3444 weston_surface_destroy(shell->debug_repaint_surface);
3445 shell->debug_repaint_surface = NULL;
3446 } else {
3447 surface = weston_surface_create(compositor);
3448 weston_surface_set_color(surface, 1.0, 0.0, 0.0, 0.2);
3449 weston_surface_configure(surface, 0, 0, 8192, 8192);
3450 wl_list_insert(&compositor->fade_layer.surface_list,
3451 &surface->layer_link);
3452 weston_surface_assign_output(surface);
3453 pixman_region32_init(&surface->input);
3454
3455 /* Here's the dirty little trick that makes the
Ander Conselvan de Oliveira383b6712012-08-09 16:44:59 +03003456 * repaint debugging work: we move the surface to a
3457 * different plane and force an update_transform to
3458 * update dependent state and clear the
3459 * geometry.dirty bit. This way the call to
3460 * damage_below() in update_transform() does not
3461 * add damage to the primary plane. */
Kristian Høgsbergb41c0812012-03-04 14:53:40 -05003462
Ander Conselvan de Oliveira383b6712012-08-09 16:44:59 +03003463 weston_plane_init(&plane, 0, 0);
3464 surface->plane = &plane;
Kristian Høgsbergb41c0812012-03-04 14:53:40 -05003465 weston_surface_update_transform(surface);
Kristian Høgsbergb41c0812012-03-04 14:53:40 -05003466 shell->debug_repaint_surface = surface;
Ander Conselvan de Oliveira383b6712012-08-09 16:44:59 +03003467 surface->plane = &compositor->primary_plane;
3468 weston_plane_release(&plane);
Kristian Høgsbergb41c0812012-03-04 14:53:40 -05003469 }
3470}
3471
Pekka Paalanen07c91f82012-08-30 16:47:21 -05003472
3473static void
3474fan_debug_repaint_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
3475 void *data)
3476{
3477 struct desktop_shell *shell = data;
3478 struct weston_compositor *compositor = shell->compositor;
3479 compositor->fan_debug = !compositor->fan_debug;
3480 weston_compositor_damage_all(compositor);
3481}
3482
Kristian Høgsbergb41c0812012-03-04 14:53:40 -05003483static void
Daniel Stone325fc2d2012-05-30 16:31:58 +01003484force_kill_binding(struct wl_seat *seat, uint32_t time, uint32_t key,
3485 void *data)
Kristian Høgsberg92a57db2012-05-26 13:41:06 -04003486{
Philipp Brüschweiler6cef0092012-08-13 21:27:27 +02003487 struct wl_surface *focus_surface;
Kristian Høgsberg92a57db2012-05-26 13:41:06 -04003488 struct wl_client *client;
3489 pid_t pid;
3490 uid_t uid;
3491 gid_t gid;
3492
Philipp Brüschweiler6cef0092012-08-13 21:27:27 +02003493 focus_surface = seat->keyboard->focus;
3494 if (!focus_surface)
3495 return;
3496
3497 client = focus_surface->resource.client;
Daniel Stone325fc2d2012-05-30 16:31:58 +01003498 wl_client_get_credentials(client, &pid, &uid, &gid);
Kristian Høgsberg92a57db2012-05-26 13:41:06 -04003499
Daniel Stone325fc2d2012-05-30 16:31:58 +01003500 kill(pid, SIGKILL);
Kristian Høgsberg92a57db2012-05-26 13:41:06 -04003501}
3502
3503static void
Jonas Ådahle3cddce2012-06-13 00:01:22 +02003504workspace_up_binding(struct wl_seat *seat, uint32_t time,
3505 uint32_t key, void *data)
3506{
3507 struct desktop_shell *shell = data;
3508 unsigned int new_index = shell->workspaces.current;
3509
Kristian Høgsbergce345b02012-06-25 21:35:29 -04003510 if (shell->locked)
Kristian Høgsberg4476aaf2012-06-25 14:03:13 -04003511 return;
Jonas Ådahle3cddce2012-06-13 00:01:22 +02003512 if (new_index != 0)
3513 new_index--;
3514
3515 change_workspace(shell, new_index);
3516}
3517
3518static void
3519workspace_down_binding(struct wl_seat *seat, uint32_t time,
3520 uint32_t key, void *data)
3521{
3522 struct desktop_shell *shell = data;
3523 unsigned int new_index = shell->workspaces.current;
3524
Kristian Høgsbergce345b02012-06-25 21:35:29 -04003525 if (shell->locked)
Kristian Høgsberg4476aaf2012-06-25 14:03:13 -04003526 return;
Jonas Ådahle3cddce2012-06-13 00:01:22 +02003527 if (new_index < shell->workspaces.num - 1)
3528 new_index++;
3529
3530 change_workspace(shell, new_index);
3531}
3532
3533static void
3534workspace_f_binding(struct wl_seat *seat, uint32_t time,
3535 uint32_t key, void *data)
3536{
3537 struct desktop_shell *shell = data;
3538 unsigned int new_index;
3539
Kristian Høgsbergce345b02012-06-25 21:35:29 -04003540 if (shell->locked)
Kristian Høgsberg4476aaf2012-06-25 14:03:13 -04003541 return;
Jonas Ådahle3cddce2012-06-13 00:01:22 +02003542 new_index = key - KEY_F1;
3543 if (new_index >= shell->workspaces.num)
3544 new_index = shell->workspaces.num - 1;
3545
3546 change_workspace(shell, new_index);
3547}
3548
Jonas Ådahl8de6a1d2012-08-29 22:13:00 +02003549static void
3550workspace_move_surface_up_binding(struct wl_seat *seat, uint32_t time,
3551 uint32_t key, void *data)
3552{
3553 struct desktop_shell *shell = data;
3554 unsigned int new_index = shell->workspaces.current;
3555
3556 if (shell->locked)
3557 return;
3558
3559 if (new_index != 0)
3560 new_index--;
3561
3562 take_surface_to_workspace_by_seat(shell, seat, new_index);
3563}
3564
3565static void
3566workspace_move_surface_down_binding(struct wl_seat *seat, uint32_t time,
3567 uint32_t key, void *data)
3568{
3569 struct desktop_shell *shell = data;
3570 unsigned int new_index = shell->workspaces.current;
3571
3572 if (shell->locked)
3573 return;
3574
3575 if (new_index < shell->workspaces.num - 1)
3576 new_index++;
3577
3578 take_surface_to_workspace_by_seat(shell, seat, new_index);
3579}
Jonas Ådahle3cddce2012-06-13 00:01:22 +02003580
3581static void
Kristian Høgsberg02e79dc2012-04-12 09:55:26 -04003582shell_destroy(struct wl_listener *listener, void *data)
Pekka Paalanen3c647232011-12-22 13:43:43 +02003583{
Tiago Vignattibe143262012-04-16 17:31:41 +03003584 struct desktop_shell *shell =
3585 container_of(listener, struct desktop_shell, destroy_listener);
Jonas Ådahle3cddce2012-06-13 00:01:22 +02003586 struct workspace **ws;
Pekka Paalanen3c647232011-12-22 13:43:43 +02003587
Pekka Paalanen9cf5cc82012-01-02 16:00:24 +02003588 if (shell->child.client)
3589 wl_client_destroy(shell->child.client);
3590
Kristian Høgsberg88c16072012-05-16 08:04:19 -04003591 wl_list_remove(&shell->lock_listener.link);
3592 wl_list_remove(&shell->unlock_listener.link);
Jan Arne Petersen42feced2012-06-21 21:52:17 +02003593 wl_list_remove(&shell->show_input_panel_listener.link);
3594 wl_list_remove(&shell->hide_input_panel_listener.link);
Kristian Høgsberg88c16072012-05-16 08:04:19 -04003595
Jonas Ådahle3cddce2012-06-13 00:01:22 +02003596 wl_array_for_each(ws, &shell->workspaces.array)
3597 workspace_destroy(*ws);
3598 wl_array_release(&shell->workspaces.array);
3599
Pekka Paalanen3c647232011-12-22 13:43:43 +02003600 free(shell->screensaver.path);
3601 free(shell);
3602}
3603
Tiago Vignatti0b52d482012-04-20 18:54:25 +03003604static void
3605shell_add_bindings(struct weston_compositor *ec, struct desktop_shell *shell)
3606{
3607 uint32_t mod;
Jonas Ådahle3cddce2012-06-13 00:01:22 +02003608 int i, num_workspace_bindings;
Tiago Vignatti0b52d482012-04-20 18:54:25 +03003609
3610 /* fixed bindings */
Daniel Stone325fc2d2012-05-30 16:31:58 +01003611 weston_compositor_add_key_binding(ec, KEY_BACKSPACE,
3612 MODIFIER_CTRL | MODIFIER_ALT,
3613 terminate_binding, ec);
3614 weston_compositor_add_button_binding(ec, BTN_LEFT, 0,
3615 click_to_activate_binding,
3616 shell);
3617 weston_compositor_add_axis_binding(ec, WL_POINTER_AXIS_VERTICAL_SCROLL,
3618 MODIFIER_SUPER | MODIFIER_ALT,
3619 surface_opacity_binding, NULL);
3620 weston_compositor_add_axis_binding(ec, WL_POINTER_AXIS_VERTICAL_SCROLL,
3621 MODIFIER_SUPER, zoom_axis_binding,
3622 NULL);
Tiago Vignatti0b52d482012-04-20 18:54:25 +03003623
3624 /* configurable bindings */
3625 mod = shell->binding_modifier;
Daniel Stone325fc2d2012-05-30 16:31:58 +01003626 weston_compositor_add_key_binding(ec, KEY_PAGEUP, mod,
3627 zoom_key_binding, NULL);
3628 weston_compositor_add_key_binding(ec, KEY_PAGEDOWN, mod,
3629 zoom_key_binding, NULL);
3630 weston_compositor_add_button_binding(ec, BTN_LEFT, mod, move_binding,
3631 shell);
3632 weston_compositor_add_button_binding(ec, BTN_MIDDLE, mod,
3633 resize_binding, shell);
3634 weston_compositor_add_button_binding(ec, BTN_RIGHT, mod,
3635 rotate_binding, NULL);
3636 weston_compositor_add_key_binding(ec, KEY_TAB, mod, switcher_binding,
3637 shell);
3638 weston_compositor_add_key_binding(ec, KEY_F9, mod, backlight_binding,
3639 ec);
3640 weston_compositor_add_key_binding(ec, KEY_BRIGHTNESSDOWN, 0,
3641 backlight_binding, ec);
3642 weston_compositor_add_key_binding(ec, KEY_F10, mod, backlight_binding,
3643 ec);
3644 weston_compositor_add_key_binding(ec, KEY_BRIGHTNESSUP, 0,
3645 backlight_binding, ec);
Kristian Høgsberg73694c82012-06-28 14:13:10 -04003646 weston_compositor_add_key_binding(ec, KEY_SPACE, mod | MODIFIER_SHIFT,
Daniel Stone325fc2d2012-05-30 16:31:58 +01003647 debug_repaint_binding, shell);
Pekka Paalanen07c91f82012-08-30 16:47:21 -05003648 weston_compositor_add_key_binding(ec, KEY_SPACE, mod | MODIFIER_ALT,
3649 fan_debug_repaint_binding, shell);
Daniel Stone325fc2d2012-05-30 16:31:58 +01003650 weston_compositor_add_key_binding(ec, KEY_K, mod,
3651 force_kill_binding, shell);
Jonas Ådahle3cddce2012-06-13 00:01:22 +02003652 weston_compositor_add_key_binding(ec, KEY_UP, mod,
3653 workspace_up_binding, shell);
3654 weston_compositor_add_key_binding(ec, KEY_DOWN, mod,
3655 workspace_down_binding, shell);
Jonas Ådahl8de6a1d2012-08-29 22:13:00 +02003656 weston_compositor_add_key_binding(ec, KEY_UP, mod | MODIFIER_SHIFT,
3657 workspace_move_surface_up_binding,
3658 shell);
3659 weston_compositor_add_key_binding(ec, KEY_DOWN, mod | MODIFIER_SHIFT,
3660 workspace_move_surface_down_binding,
3661 shell);
Jonas Ådahle3cddce2012-06-13 00:01:22 +02003662
3663 /* Add bindings for mod+F[1-6] for workspace 1 to 6. */
3664 if (shell->workspaces.num > 1) {
3665 num_workspace_bindings = shell->workspaces.num;
3666 if (num_workspace_bindings > 6)
3667 num_workspace_bindings = 6;
3668 for (i = 0; i < num_workspace_bindings; i++)
3669 weston_compositor_add_key_binding(ec, KEY_F1 + i, mod,
3670 workspace_f_binding,
3671 shell);
3672 }
Tiago Vignatti0b52d482012-04-20 18:54:25 +03003673}
3674
Kristian Høgsberg6c709a32011-05-06 14:52:41 -04003675int
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05003676shell_init(struct weston_compositor *ec);
Kristian Høgsberg6c709a32011-05-06 14:52:41 -04003677
Kristian Høgsberg1c562182011-05-02 22:09:20 -04003678WL_EXPORT int
Kristian Høgsberg8334bc12012-01-03 10:29:47 -05003679shell_init(struct weston_compositor *ec)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -05003680{
Kristian Høgsbergf4d2f232012-08-10 10:05:39 -04003681 struct weston_seat *seat;
Tiago Vignattibe143262012-04-16 17:31:41 +03003682 struct desktop_shell *shell;
Jonas Ådahle3cddce2012-06-13 00:01:22 +02003683 struct workspace **pws;
3684 unsigned int i;
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04003685
3686 shell = malloc(sizeof *shell);
3687 if (shell == NULL)
3688 return -1;
3689
Kristian Høgsbergf0d91162011-10-11 22:44:23 -04003690 memset(shell, 0, sizeof *shell);
Kristian Høgsberg75840622011-09-06 13:48:16 -04003691 shell->compositor = ec;
Kristian Høgsberg02e79dc2012-04-12 09:55:26 -04003692
3693 shell->destroy_listener.notify = shell_destroy;
3694 wl_signal_add(&ec->destroy_signal, &shell->destroy_listener);
3695 shell->lock_listener.notify = lock;
3696 wl_signal_add(&ec->lock_signal, &shell->lock_listener);
3697 shell->unlock_listener.notify = unlock;
3698 wl_signal_add(&ec->unlock_signal, &shell->unlock_listener);
Jan Arne Petersen42feced2012-06-21 21:52:17 +02003699 shell->show_input_panel_listener.notify = show_input_panels;
3700 wl_signal_add(&ec->show_input_panel_signal, &shell->show_input_panel_listener);
3701 shell->hide_input_panel_listener.notify = hide_input_panels;
3702 wl_signal_add(&ec->hide_input_panel_signal, &shell->hide_input_panel_listener);
Scott Moreauff1db4a2012-04-17 19:06:18 -06003703 ec->ping_handler = ping_handler;
Kristian Høgsberg82a1d112012-07-19 14:02:00 -04003704 ec->shell_interface.shell = shell;
Tiago Vignattibc052c92012-04-19 16:18:18 +03003705 ec->shell_interface.create_shell_surface = create_shell_surface;
3706 ec->shell_interface.set_toplevel = set_toplevel;
Tiago Vignatti491bac12012-05-18 16:37:43 -04003707 ec->shell_interface.set_transient = set_transient;
Kristian Høgsberg938b8fa2012-05-18 13:46:27 -04003708 ec->shell_interface.move = surface_move;
Kristian Høgsbergc1693f22012-05-22 16:56:23 -04003709 ec->shell_interface.resize = surface_resize;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -05003710
Pekka Paalanen77346a62011-11-30 16:26:35 +02003711 wl_list_init(&shell->screensaver.surfaces);
Jan Arne Petersen42feced2012-06-21 21:52:17 +02003712 wl_list_init(&shell->input_panel.surfaces);
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02003713
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -05003714 weston_layer_init(&shell->fullscreen_layer, &ec->cursor_layer.link);
3715 weston_layer_init(&shell->panel_layer, &shell->fullscreen_layer.link);
Jonas Ådahle3cddce2012-06-13 00:01:22 +02003716 weston_layer_init(&shell->background_layer, &shell->panel_layer.link);
3717 weston_layer_init(&shell->lock_layer, NULL);
Philipp Brüschweiler711fda82012-08-09 18:50:43 +02003718 weston_layer_init(&shell->input_panel_layer, NULL);
Jonas Ådahle3cddce2012-06-13 00:01:22 +02003719
3720 wl_array_init(&shell->workspaces.array);
Jonas Ådahle9d22502012-08-29 22:13:01 +02003721 wl_list_init(&shell->workspaces.client_list);
Kristian Høgsberg3be2ce92012-02-29 12:42:35 -05003722
Kristian Høgsberg6af8eb92012-01-25 16:57:11 -05003723 shell_configuration(shell);
Pekka Paalanene955f1e2011-12-07 11:49:52 +02003724
Jonas Ådahle3cddce2012-06-13 00:01:22 +02003725 for (i = 0; i < shell->workspaces.num; i++) {
3726 pws = wl_array_add(&shell->workspaces.array, sizeof *pws);
3727 if (pws == NULL)
3728 return -1;
3729
3730 *pws = workspace_create();
3731 if (*pws == NULL)
3732 return -1;
3733 }
3734 activate_workspace(shell, 0);
3735
Jonas Ådahl8de6a1d2012-08-29 22:13:00 +02003736 wl_list_init(&shell->workspaces.anim_sticky_list);
Jonas Ådahl62fcd042012-06-13 00:01:23 +02003737 wl_list_init(&shell->workspaces.animation.link);
3738 shell->workspaces.animation.frame = animate_workspace_change_frame;
3739
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -04003740 if (wl_display_add_global(ec->wl_display, &wl_shell_interface,
3741 shell, bind_shell) == NULL)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -05003742 return -1;
3743
Kristian Høgsberg75840622011-09-06 13:48:16 -04003744 if (wl_display_add_global(ec->wl_display,
3745 &desktop_shell_interface,
3746 shell, bind_desktop_shell) == NULL)
3747 return -1;
3748
Pekka Paalanen6e168112011-11-24 11:34:05 +02003749 if (wl_display_add_global(ec->wl_display, &screensaver_interface,
3750 shell, bind_screensaver) == NULL)
3751 return -1;
3752
Jan Arne Petersen42feced2012-06-21 21:52:17 +02003753 if (wl_display_add_global(ec->wl_display, &input_panel_interface,
3754 shell, bind_input_panel) == NULL)
3755 return -1;
3756
Jonas Ådahle9d22502012-08-29 22:13:01 +02003757 if (wl_display_add_global(ec->wl_display, &workspace_manager_interface,
3758 shell, bind_workspace_manager) == NULL)
3759 return -1;
3760
Kristian Høgsbergf03a6162012-01-17 11:07:42 -05003761 shell->child.deathstamp = weston_compositor_get_time();
Pekka Paalanen6cd281a2011-11-03 14:11:32 +02003762 if (launch_desktop_shell_process(shell) != 0)
3763 return -1;
3764
Kristian Høgsbergf4d2f232012-08-10 10:05:39 -04003765 wl_list_for_each(seat, &ec->seat_list, link)
3766 create_pointer_focus_listener(seat);
Kristian Høgsbergd56bd902012-06-05 09:58:51 -04003767
Tiago Vignatti0b52d482012-04-20 18:54:25 +03003768 shell_add_bindings(ec, shell);
Kristian Høgsberg07937562011-04-12 17:25:42 -04003769
Kristian Høgsberg4cca3492011-01-18 07:53:49 -05003770 return 0;
3771}