blob: a2ffc0df8bff49ce64fb8c43d133e67f40942a05 [file] [log] [blame]
Kristian Høgsberg4cca3492011-01-18 07:53:49 -05001/*
2 * Copyright © 2010 Intel Corporation
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02003 * Copyright © 2011 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 Paalanen6cd281a2011-11-03 14:11:32 +020030#include <sys/types.h>
31#include <sys/socket.h>
32#include <fcntl.h>
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +020033#include <assert.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"
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050038
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -040039struct wl_shell {
Kristian Høgsberg75840622011-09-06 13:48:16 -040040 struct wlsc_compositor *compositor;
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -040041 struct wlsc_shell shell;
Pekka Paalanen6cd281a2011-11-03 14:11:32 +020042
43 struct {
44 struct wlsc_process process;
45 struct wl_client *client;
Pekka Paalanen9ef3e012011-11-15 13:34:48 +020046 struct wl_resource *desktop_shell;
Pekka Paalanen6cd281a2011-11-03 14:11:32 +020047 } child;
Pekka Paalanen9ef3e012011-11-15 13:34:48 +020048
49 bool locked;
50 bool prepare_event_sent;
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +020051
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -050052 struct wlsc_surface *lock_surface;
53 struct wl_listener lock_surface_listener;
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +020054 struct wl_list hidden_surface_list;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010055
56 struct wl_list backgrounds;
57 struct wl_list panels;
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -040058};
59
Kristian Høgsbergd2abb832011-11-23 10:52:40 -050060enum shell_surface_type {
Pekka Paalanen57da4a82011-11-23 16:42:16 +020061 SHELL_SURFACE_NORMAL,
Kristian Høgsbergd2abb832011-11-23 10:52:40 -050062
Pekka Paalanen57da4a82011-11-23 16:42:16 +020063 SHELL_SURFACE_PANEL,
64 SHELL_SURFACE_BACKGROUND,
65 SHELL_SURFACE_LOCK,
Kristian Høgsbergd2abb832011-11-23 10:52:40 -050066
67 SHELL_SURFACE_TOPLEVEL,
68 SHELL_SURFACE_TRANSIENT,
69 SHELL_SURFACE_FULLSCREEN
Pekka Paalanen57da4a82011-11-23 16:42:16 +020070};
71
Pekka Paalanen56cdea92011-11-23 16:14:12 +020072struct shell_surface {
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010073 struct wlsc_surface *surface;
Pekka Paalanen56cdea92011-11-23 16:14:12 +020074 struct wl_listener destroy_listener;
Pekka Paalanen57da4a82011-11-23 16:42:16 +020075
Kristian Høgsbergd2abb832011-11-23 10:52:40 -050076 enum shell_surface_type type;
77 int32_t saved_x, saved_y;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010078
79 struct wlsc_output *output;
80 struct wl_list link;
Pekka Paalanen56cdea92011-11-23 16:14:12 +020081};
82
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050083struct wlsc_move_grab {
84 struct wl_grab grab;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -050085 struct wlsc_surface *surface;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050086 int32_t dx, dy;
87};
88
89static void
Pekka Paalanen56cdea92011-11-23 16:14:12 +020090destroy_shell_surface(struct shell_surface *priv)
91{
92 wl_list_remove(&priv->destroy_listener.link);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +010093 wl_list_remove(&priv->link);
Pekka Paalanen56cdea92011-11-23 16:14:12 +020094 free(priv);
95}
96
97static void
98handle_shell_surface_destroy(struct wl_listener *listener,
99 struct wl_resource *resource, uint32_t time)
100{
101 struct shell_surface *priv =
102 container_of(listener, struct shell_surface, destroy_listener);
103 destroy_shell_surface(priv);
104}
105
106static struct shell_surface *
107get_shell_surface(struct wlsc_surface *surface)
108{
109 struct shell_surface *priv;
110
111 if (surface->shell_priv)
112 return surface->shell_priv;
113
114 priv = calloc(1, sizeof *priv);
115 if (!priv)
116 return NULL;
117
118 priv->destroy_listener.func = handle_shell_surface_destroy;
119 wl_list_insert(surface->surface.resource.destroy_listener_list.prev,
120 &priv->destroy_listener.link);
121
122 surface->shell_priv = priv;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100123 priv->surface = surface;
124 /* init link so its safe to always remove it in destroy_shell_surface */
125 wl_list_init(&priv->link);
Pekka Paalanen56cdea92011-11-23 16:14:12 +0200126
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500127 priv->type = SHELL_SURFACE_NORMAL;
Pekka Paalanen57da4a82011-11-23 16:42:16 +0200128
Pekka Paalanen56cdea92011-11-23 16:14:12 +0200129 return priv;
130}
131
132static void
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500133move_grab_motion(struct wl_grab *grab,
134 uint32_t time, int32_t x, int32_t y)
135{
136 struct wlsc_move_grab *move = (struct wlsc_move_grab *) grab;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500137 struct wlsc_surface *es = move->surface;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500138
Kristian Høgsberga691aee2011-06-23 21:43:50 -0400139 wlsc_surface_configure(es, x + move->dx, y + move->dy,
140 es->width, es->height);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500141}
142
143static void
144move_grab_button(struct wl_grab *grab,
145 uint32_t time, int32_t button, int32_t state)
146{
147}
148
149static void
150move_grab_end(struct wl_grab *grab, uint32_t time)
151{
152 free(grab);
153}
154
155static const struct wl_grab_interface move_grab_interface = {
156 move_grab_motion,
157 move_grab_button,
158 move_grab_end
159};
160
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400161static int
162wlsc_surface_move(struct wlsc_surface *es,
163 struct wlsc_input_device *wd, uint32_t time)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500164{
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500165 struct wlsc_move_grab *move;
166
167 move = malloc(sizeof *move);
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400168 if (!move)
169 return -1;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500170
171 move->grab.interface = &move_grab_interface;
172 move->dx = es->x - wd->input_device.grab_x;
173 move->dy = es->y - wd->input_device.grab_y;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500174 move->surface = es;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500175
176 if (wl_input_device_update_grab(&wd->input_device,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400177 &move->grab, &es->surface, time) < 0)
178 return 0;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500179
180 wlsc_input_device_set_pointer_image(wd, WLSC_POINTER_DRAGGING);
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400181 wl_input_device_set_pointer_focus(&wd->input_device,
182 NULL, time, 0, 0, 0, 0);
183
184 return 0;
185}
186
187static void
188shell_move(struct wl_client *client, struct wl_resource *resource,
189 struct wl_resource *surface_resource,
190 struct wl_resource *input_resource, uint32_t time)
191{
192 struct wlsc_input_device *wd = input_resource->data;
193 struct wlsc_surface *es = surface_resource->data;
194
195 if (wlsc_surface_move(es, wd, time) < 0)
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400196 wl_resource_post_no_memory(resource);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500197}
198
199struct wlsc_resize_grab {
200 struct wl_grab grab;
201 uint32_t edges;
202 int32_t dx, dy, width, height;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500203 struct wlsc_surface *surface;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400204 struct wl_resource *resource;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500205};
206
207static void
208resize_grab_motion(struct wl_grab *grab,
209 uint32_t time, int32_t x, int32_t y)
210{
211 struct wlsc_resize_grab *resize = (struct wlsc_resize_grab *) grab;
212 struct wl_input_device *device = grab->input_device;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500213 struct wl_surface *surface = &resize->surface->surface;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500214 int32_t width, height;
215
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500216 if (resize->edges & WL_SHELL_RESIZE_LEFT) {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500217 width = device->grab_x - x + resize->width;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500218 } else if (resize->edges & WL_SHELL_RESIZE_RIGHT) {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500219 width = x - device->grab_x + resize->width;
220 } else {
221 width = resize->width;
222 }
223
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500224 if (resize->edges & WL_SHELL_RESIZE_TOP) {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500225 height = device->grab_y - y + resize->height;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500226 } else if (resize->edges & WL_SHELL_RESIZE_BOTTOM) {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500227 height = y - device->grab_y + resize->height;
228 } else {
229 height = resize->height;
230 }
231
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400232 wl_resource_post_event(resize->resource,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400233 WL_SHELL_CONFIGURE, time, resize->edges,
234 surface, width, height);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500235}
236
237static void
238resize_grab_button(struct wl_grab *grab,
239 uint32_t time, int32_t button, int32_t state)
240{
241}
242
243static void
244resize_grab_end(struct wl_grab *grab, uint32_t time)
245{
246 free(grab);
247}
248
249static const struct wl_grab_interface resize_grab_interface = {
250 resize_grab_motion,
251 resize_grab_button,
252 resize_grab_end
253};
254
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400255static int
256wlsc_surface_resize(struct wlsc_surface *es,
257 struct wlsc_input_device *wd,
258 uint32_t time, uint32_t edges,
259 struct wl_resource *resource)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500260{
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500261 struct wlsc_resize_grab *resize;
262 enum wlsc_pointer_type pointer = WLSC_POINTER_LEFT_PTR;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500263
Kristian Høgsberg0ce24572011-01-28 15:18:33 -0500264 /* FIXME: Reject if fullscreen */
265
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500266 resize = malloc(sizeof *resize);
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400267 if (!resize)
268 return -1;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500269
270 resize->grab.interface = &resize_grab_interface;
271 resize->edges = edges;
272 resize->dx = es->x - wd->input_device.grab_x;
273 resize->dy = es->y - wd->input_device.grab_y;
274 resize->width = es->width;
275 resize->height = es->height;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500276 resize->surface = es;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400277 resize->resource = resource;
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400278
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500279 if (edges == 0 || edges > 15 ||
280 (edges & 3) == 3 || (edges & 12) == 12)
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400281 return 0;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500282
283 switch (edges) {
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500284 case WL_SHELL_RESIZE_TOP:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500285 pointer = WLSC_POINTER_TOP;
286 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500287 case WL_SHELL_RESIZE_BOTTOM:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500288 pointer = WLSC_POINTER_BOTTOM;
289 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500290 case WL_SHELL_RESIZE_LEFT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500291 pointer = WLSC_POINTER_LEFT;
292 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500293 case WL_SHELL_RESIZE_TOP_LEFT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500294 pointer = WLSC_POINTER_TOP_LEFT;
295 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500296 case WL_SHELL_RESIZE_BOTTOM_LEFT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500297 pointer = WLSC_POINTER_BOTTOM_LEFT;
298 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500299 case WL_SHELL_RESIZE_RIGHT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500300 pointer = WLSC_POINTER_RIGHT;
301 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500302 case WL_SHELL_RESIZE_TOP_RIGHT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500303 pointer = WLSC_POINTER_TOP_RIGHT;
304 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500305 case WL_SHELL_RESIZE_BOTTOM_RIGHT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500306 pointer = WLSC_POINTER_BOTTOM_RIGHT;
307 break;
308 }
309
310 if (wl_input_device_update_grab(&wd->input_device,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400311 &resize->grab, &es->surface, time) < 0)
312 return 0;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500313
314 wlsc_input_device_set_pointer_image(wd, pointer);
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400315 wl_input_device_set_pointer_focus(&wd->input_device,
316 NULL, time, 0, 0, 0, 0);
317
318 return 0;
319}
320
321static void
322shell_resize(struct wl_client *client, struct wl_resource *resource,
323 struct wl_resource *surface_resource,
324 struct wl_resource *input_resource, uint32_t time, uint32_t edges)
325{
326 struct wlsc_input_device *wd = input_resource->data;
327 struct wlsc_surface *es = surface_resource->data;
328
329 /* FIXME: Reject if fullscreen */
330
331 if (wlsc_surface_resize(es, wd, time, edges, resource) < 0)
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400332 wl_resource_post_no_memory(resource);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500333}
334
335static void
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400336shell_set_toplevel(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400337 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400338 struct wl_resource *surface_resource)
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400339
340{
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400341 struct wlsc_surface *es = surface_resource->data;
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500342 struct shell_surface *priv;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400343
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500344 priv = get_shell_surface(es);
345 if (priv->type == SHELL_SURFACE_FULLSCREEN) {
346 es->x = priv->saved_x;
347 es->y = priv->saved_y;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400348 }
349
350 wlsc_surface_damage(es);
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500351 priv->type = SHELL_SURFACE_TOPLEVEL;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400352 es->fullscreen_output = NULL;
353}
354
355static void
356shell_set_transient(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400357 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400358 struct wl_resource *surface_resource,
359 struct wl_resource *parent_resource,
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400360 int x, int y, uint32_t flags)
361{
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400362 struct wlsc_surface *es = surface_resource->data;
363 struct wlsc_surface *pes = parent_resource->data;
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500364 struct shell_surface *priv;
365
366 priv = get_shell_surface(es);
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400367
368 /* assign to parents output */
369 es->output = pes->output;
370
371 es->x = pes->x + x;
372 es->y = pes->y + y;
373
374 wlsc_surface_damage(es);
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500375 priv->type = SHELL_SURFACE_TRANSIENT;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400376}
377
378static void
379shell_set_fullscreen(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400380 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400381 struct wl_resource *surface_resource)
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400382
383{
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400384 struct wlsc_surface *es = surface_resource->data;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400385 struct wlsc_output *output;
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500386 struct shell_surface *priv;
387
388 priv = get_shell_surface(es);
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400389
390 /* FIXME: Fullscreen on first output */
391 /* FIXME: Handle output going away */
392 output = container_of(es->compositor->output_list.next,
393 struct wlsc_output, link);
394 es->output = output;
395
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500396 priv->saved_x = es->x;
397 priv->saved_y = es->y;
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400398 es->x = (output->current->width - es->width) / 2;
399 es->y = (output->current->height - es->height) / 2;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400400 es->fullscreen_output = output;
401 wlsc_surface_damage(es);
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500402 priv->type = SHELL_SURFACE_FULLSCREEN;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400403}
404
405static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400406destroy_drag(struct wl_resource *resource)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500407{
408 struct wl_drag *drag =
409 container_of(resource, struct wl_drag, resource);
410
411 wl_list_remove(&drag->drag_focus_listener.link);
412 if (drag->grab.input_device)
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400413 wl_input_device_end_grab(drag->grab.input_device,
414 wlsc_compositor_get_time());
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500415
416 free(drag);
417}
418
419
420static void
421wl_drag_set_pointer_focus(struct wl_drag *drag,
422 struct wl_surface *surface, uint32_t time,
423 int32_t x, int32_t y, int32_t sx, int32_t sy)
424{
425 char **p, **end;
426
427 if (drag->drag_focus == surface)
428 return;
429
430 if (drag->drag_focus &&
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400431 (!surface ||
432 drag->drag_focus->resource.client != surface->resource.client))
433 wl_resource_post_event(&drag->drag_offer.resource,
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500434 WL_DRAG_OFFER_POINTER_FOCUS,
435 time, NULL, 0, 0, 0, 0);
436
437 if (surface &&
438 (!drag->drag_focus ||
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400439 drag->drag_focus->resource.client != surface->resource.client)) {
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400440
441 drag->drag_offer.resource.client = surface->resource.client;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500442 end = drag->types.data + drag->types.size;
443 for (p = drag->types.data; p < end; p++)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400444 wl_resource_post_event(&drag->drag_offer.resource,
445 WL_DRAG_OFFER_OFFER, *p);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500446 }
447
448 if (surface) {
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400449 wl_resource_post_event(&drag->drag_offer.resource,
450 WL_DRAG_OFFER_POINTER_FOCUS,
451 time, surface,
452 x, y, sx, sy);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500453
454 }
455
456 drag->drag_focus = surface;
457 drag->pointer_focus_time = time;
458 drag->target = NULL;
459
460 wl_list_remove(&drag->drag_focus_listener.link);
461 if (surface)
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200462 wl_list_insert(surface->resource.destroy_listener_list.prev,
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500463 &drag->drag_focus_listener.link);
464}
465
466static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400467drag_offer_accept(struct wl_client *client, struct wl_resource *resource,
468 uint32_t time, const char *type)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500469{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400470 struct wl_drag_offer *offer = resource->data;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500471 struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer);
472 char **p, **end;
473
474 /* If the client responds to drag pointer_focus or motion
475 * events after the pointer has left the surface, we just
476 * discard the accept requests. The drag source just won't
477 * get the corresponding 'target' events and eventually the
478 * next surface/root will start sending events. */
479 if (time < drag->pointer_focus_time)
480 return;
481
482 drag->target = client;
483 drag->type = NULL;
484 end = drag->types.data + drag->types.size;
485 for (p = drag->types.data; p < end; p++)
486 if (type && strcmp(*p, type) == 0)
487 drag->type = *p;
488
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400489 wl_resource_post_event(&drag->resource, WL_DRAG_TARGET, drag->type);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500490}
491
492static void
493drag_offer_receive(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400494 struct wl_resource *resource, int fd)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500495{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400496 struct wl_drag_offer *offer = resource->data;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500497 struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer);
498
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400499 wl_resource_post_event(&drag->resource, WL_DRAG_FINISH, fd);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500500 close(fd);
501}
502
503static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400504drag_offer_reject(struct wl_client *client, struct wl_resource *resource)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500505{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400506 struct wl_drag_offer *offer = resource->data;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500507 struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer);
508
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400509 wl_resource_post_event(&drag->resource, WL_DRAG_REJECT);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500510}
511
512static const struct wl_drag_offer_interface drag_offer_interface = {
513 drag_offer_accept,
514 drag_offer_receive,
515 drag_offer_reject
516};
517
518static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400519drag_offer(struct wl_client *client,
520 struct wl_resource *resource, const char *type)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500521{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400522 struct wl_drag *drag = resource->data;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500523 char **p;
524
525 p = wl_array_add(&drag->types, sizeof *p);
526 if (p)
527 *p = strdup(type);
528 if (!p || !*p)
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400529 wl_resource_post_no_memory(resource);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500530}
531
532static void
533drag_grab_motion(struct wl_grab *grab,
534 uint32_t time, int32_t x, int32_t y)
535{
536 struct wl_drag *drag = container_of(grab, struct wl_drag, grab);
537 struct wlsc_surface *es;
538 int32_t sx, sy;
539
540 es = pick_surface(grab->input_device, &sx, &sy);
541 wl_drag_set_pointer_focus(drag, &es->surface, time, x, y, sx, sy);
542 if (es)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400543 wl_resource_post_event(&drag->drag_offer.resource,
544 WL_DRAG_OFFER_MOTION,
545 time, x, y, sx, sy);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500546}
547
548static void
549drag_grab_button(struct wl_grab *grab,
550 uint32_t time, int32_t button, int32_t state)
551{
552}
553
554static void
555drag_grab_end(struct wl_grab *grab, uint32_t time)
556{
557 struct wl_drag *drag = container_of(grab, struct wl_drag, grab);
558
559 if (drag->target)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400560 wl_resource_post_event(&drag->drag_offer.resource,
561 WL_DRAG_OFFER_DROP);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500562
563 wl_drag_set_pointer_focus(drag, NULL, time, 0, 0, 0, 0);
564}
565
566static const struct wl_grab_interface drag_grab_interface = {
567 drag_grab_motion,
568 drag_grab_button,
569 drag_grab_end
570};
571
572static void
573drag_activate(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400574 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400575 struct wl_resource *surface_resource,
576 struct wl_resource *device_resource, uint32_t time)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500577{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400578 struct wl_drag *drag = resource->data;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400579 struct wl_surface *surface = surface_resource->data;
580 struct wl_input_device *device = device_resource->data;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500581 struct wl_display *display = wl_client_get_display (client);
582 struct wlsc_surface *target;
583 int32_t sx, sy;
584
585 if (wl_input_device_update_grab(device,
586 &drag->grab, surface, time) < 0)
587 return;
588
589 drag->grab.interface = &drag_grab_interface;
590
591 drag->source = surface;
592
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400593 drag->drag_offer.resource.object.interface = &wl_drag_offer_interface;
594 drag->drag_offer.resource.object.implementation =
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500595 (void (**)(void)) &drag_offer_interface;
596
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400597 wl_display_add_global(display, &wl_drag_offer_interface, drag, NULL);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500598
599 target = pick_surface(device, &sx, &sy);
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500600 wl_input_device_set_pointer_focus(device, NULL, time, 0, 0, 0, 0);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500601 wl_drag_set_pointer_focus(drag, &target->surface, time,
602 device->x, device->y, sx, sy);
603}
604
605static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400606drag_destroy(struct wl_client *client, struct wl_resource *resource)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500607{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400608 wl_resource_destroy(resource, wlsc_compositor_get_time());
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500609}
610
611static const struct wl_drag_interface drag_interface = {
612 drag_offer,
613 drag_activate,
614 drag_destroy,
615};
616
617static void
618drag_handle_surface_destroy(struct wl_listener *listener,
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200619 struct wl_resource *resource, uint32_t time)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500620{
621 struct wl_drag *drag =
622 container_of(listener, struct wl_drag, drag_focus_listener);
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200623 struct wl_surface *surface = (struct wl_surface *) resource;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500624
625 if (drag->drag_focus == surface)
626 wl_drag_set_pointer_focus(drag, NULL, time, 0, 0, 0, 0);
627}
628
629static void
630shell_create_drag(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400631 struct wl_resource *resource, uint32_t id)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500632{
633 struct wl_drag *drag;
634
635 drag = malloc(sizeof *drag);
636 if (drag == NULL) {
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400637 wl_resource_post_no_memory(resource);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500638 return;
639 }
640
641 memset(drag, 0, sizeof *drag);
642 drag->resource.object.id = id;
643 drag->resource.object.interface = &wl_drag_interface;
644 drag->resource.object.implementation =
645 (void (**)(void)) &drag_interface;
646
Pekka Paalanen02ebfb12011-10-24 17:34:53 +0300647 drag->resource.data = drag;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500648 drag->resource.destroy = destroy_drag;
649
650 drag->drag_focus_listener.func = drag_handle_surface_destroy;
651 wl_list_init(&drag->drag_focus_listener.link);
652
653 wl_client_add_resource(client, &drag->resource);
654}
655
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400656static void
657wlsc_selection_set_focus(struct wlsc_shell *shell,
658 struct wl_selection *selection,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500659 struct wl_surface *surface, uint32_t time)
660{
661 char **p, **end;
662
663 if (selection->selection_focus == surface)
664 return;
665
666 if (selection->selection_focus != NULL)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400667 wl_resource_post_event(&selection->selection_offer.resource,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500668 WL_SELECTION_OFFER_KEYBOARD_FOCUS,
669 NULL);
670
671 if (surface) {
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500672
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400673 selection->selection_offer.resource.client = surface->resource.client;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500674 end = selection->types.data + selection->types.size;
675 for (p = selection->types.data; p < end; p++)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400676 wl_resource_post_event(&selection->selection_offer.resource,
677 WL_SELECTION_OFFER_OFFER, *p);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500678
679 wl_list_remove(&selection->selection_focus_listener.link);
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200680 wl_list_insert(surface->resource.destroy_listener_list.prev,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500681 &selection->selection_focus_listener.link);
682
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400683 wl_resource_post_event(&selection->selection_offer.resource,
684 WL_SELECTION_OFFER_KEYBOARD_FOCUS,
685 selection->input_device);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500686 }
687
688 selection->selection_focus = surface;
689
690 wl_list_remove(&selection->selection_focus_listener.link);
691 if (surface)
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200692 wl_list_insert(surface->resource.destroy_listener_list.prev,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500693 &selection->selection_focus_listener.link);
694}
695
696static void
697selection_offer_receive(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400698 struct wl_resource *resource,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500699 const char *mime_type, int fd)
700{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400701 struct wl_selection_offer *offer = resource->data;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500702 struct wl_selection *selection =
703 container_of(offer, struct wl_selection, selection_offer);
704
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400705 wl_resource_post_event(&selection->resource,
706 WL_SELECTION_SEND, mime_type, fd);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500707 close(fd);
708}
709
710static const struct wl_selection_offer_interface selection_offer_interface = {
711 selection_offer_receive
712};
713
714static void
715selection_offer(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400716 struct wl_resource *resource, const char *type)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500717{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400718 struct wl_selection *selection = resource->data;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500719 char **p;
720
721 p = wl_array_add(&selection->types, sizeof *p);
722 if (p)
723 *p = strdup(type);
724 if (!p || !*p)
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400725 wl_resource_post_no_memory(resource);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500726}
727
728static void
729selection_activate(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400730 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400731 struct wl_resource *input_resource, uint32_t time)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500732{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400733 struct wl_selection *selection = resource->data;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400734 struct wlsc_input_device *wd = input_resource->data;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500735 struct wl_display *display = wl_client_get_display (client);
Kristian Høgsberga8873122011-11-23 10:39:34 -0500736 struct wlsc_compositor *compositor = wd->compositor;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500737
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400738 selection->input_device = &wd->input_device;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500739
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400740 selection->selection_offer.resource.object.interface =
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500741 &wl_selection_offer_interface;
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400742 selection->selection_offer.resource.object.implementation =
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500743 (void (**)(void)) &selection_offer_interface;
744
Kristian Høgsbergd9551a32011-08-19 12:07:44 -0400745 wl_display_add_global(display,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400746 &wl_selection_offer_interface, selection, NULL);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500747
748 if (wd->selection) {
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400749 wl_resource_post_event(&wd->selection->resource,
750 WL_SELECTION_CANCELLED);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500751 }
752 wd->selection = selection;
753
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400754 wlsc_selection_set_focus(compositor->shell, selection,
755 wd->input_device.keyboard_focus, time);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500756}
757
758static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400759selection_destroy(struct wl_client *client, struct wl_resource *resource)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500760{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400761 wl_resource_destroy(resource, wlsc_compositor_get_time());
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500762}
763
764static const struct wl_selection_interface selection_interface = {
765 selection_offer,
766 selection_activate,
767 selection_destroy
768};
769
770static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400771destroy_selection(struct wl_resource *resource)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500772{
773 struct wl_selection *selection =
774 container_of(resource, struct wl_selection, resource);
775 struct wlsc_input_device *wd =
776 (struct wlsc_input_device *) selection->input_device;
Kristian Høgsberga8873122011-11-23 10:39:34 -0500777 struct wlsc_compositor *compositor = wd->compositor;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500778
779 if (wd && wd->selection == selection) {
780 wd->selection = NULL;
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400781 wlsc_selection_set_focus(compositor->shell,
782 selection, NULL,
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400783 wlsc_compositor_get_time());
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500784 }
785
786 wl_list_remove(&selection->selection_focus_listener.link);
787 free(selection);
788}
789
790static void
791selection_handle_surface_destroy(struct wl_listener *listener,
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200792 struct wl_resource *resource, uint32_t time)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500793{
794}
795
796static void
797shell_create_selection(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400798 struct wl_resource *resource, uint32_t id)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500799{
800 struct wl_selection *selection;
801
802 selection = malloc(sizeof *selection);
803 if (selection == NULL) {
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400804 wl_resource_post_no_memory(resource);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500805 return;
806 }
807
808 memset(selection, 0, sizeof *selection);
809 selection->resource.object.id = id;
810 selection->resource.object.interface = &wl_selection_interface;
811 selection->resource.object.implementation =
812 (void (**)(void)) &selection_interface;
813
814 selection->client = client;
815 selection->resource.destroy = destroy_selection;
816 selection->selection_focus = NULL;
817
818 selection->selection_focus_listener.func =
819 selection_handle_surface_destroy;
820 wl_list_init(&selection->selection_focus_listener.link);
821
822 wl_client_add_resource(client, &selection->resource);
823}
824
Kristian Høgsberg75840622011-09-06 13:48:16 -0400825static const struct wl_shell_interface shell_interface = {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500826 shell_move,
827 shell_resize,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500828 shell_create_drag,
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400829 shell_create_selection,
830 shell_set_toplevel,
831 shell_set_transient,
832 shell_set_fullscreen
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500833};
834
Kristian Høgsberg07937562011-04-12 17:25:42 -0400835static void
Kristian Høgsberg75840622011-09-06 13:48:16 -0400836desktop_shell_set_background(struct wl_client *client,
837 struct wl_resource *resource,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100838 struct wl_resource *output_resource,
Kristian Høgsberg75840622011-09-06 13:48:16 -0400839 struct wl_resource *surface_resource)
840{
841 struct wl_shell *shell = resource->data;
842 struct wlsc_surface *surface = surface_resource->data;
Pekka Paalanen57da4a82011-11-23 16:42:16 +0200843 struct shell_surface *priv;
Kristian Høgsberg75840622011-09-06 13:48:16 -0400844
Pekka Paalanen57da4a82011-11-23 16:42:16 +0200845 priv = get_shell_surface(surface);
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500846 priv->type = SHELL_SURFACE_BACKGROUND;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100847 priv->output = output_resource->data;
848
849 wl_list_insert(&shell->backgrounds, &priv->link);
850
851 surface->x = priv->output->x;
852 surface->y = priv->output->y;
Pekka Paalanen57da4a82011-11-23 16:42:16 +0200853
Kristian Høgsberg75840622011-09-06 13:48:16 -0400854 wl_resource_post_event(resource,
855 DESKTOP_SHELL_CONFIGURE,
856 wlsc_compositor_get_time(), 0, surface,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100857 priv->output->current->width,
858 priv->output->current->height);
Kristian Høgsberg75840622011-09-06 13:48:16 -0400859}
860
861static void
862desktop_shell_set_panel(struct wl_client *client,
863 struct wl_resource *resource,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100864 struct wl_resource *output_resource,
Kristian Høgsberg75840622011-09-06 13:48:16 -0400865 struct wl_resource *surface_resource)
866{
867 struct wl_shell *shell = resource->data;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100868 struct wlsc_surface *surface = surface_resource->data;
Pekka Paalanen57da4a82011-11-23 16:42:16 +0200869 struct shell_surface *priv;
Kristian Høgsberg75840622011-09-06 13:48:16 -0400870
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100871 priv = get_shell_surface(surface);
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500872 priv->type = SHELL_SURFACE_PANEL;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100873 priv->output = output_resource->data;
874
875 wl_list_insert(&shell->panels, &priv->link);
876
877 surface->x = priv->output->x;
878 surface->y = priv->output->y;
Pekka Paalanen57da4a82011-11-23 16:42:16 +0200879
Kristian Høgsberg75840622011-09-06 13:48:16 -0400880 wl_resource_post_event(resource,
881 DESKTOP_SHELL_CONFIGURE,
882 wlsc_compositor_get_time(), 0, surface_resource,
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100883 priv->output->current->width,
884 priv->output->current->height);
Kristian Høgsberg75840622011-09-06 13:48:16 -0400885}
886
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200887static void
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500888handle_lock_surface_destroy(struct wl_listener *listener,
889 struct wl_resource *resource, uint32_t time)
890{
891 struct wl_shell *shell =
Pekka Paalanen2ca86302011-11-16 13:47:35 +0200892 container_of(listener, struct wl_shell, lock_surface_listener);
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500893
894 fprintf(stderr, "lock surface gone\n");
895 shell->lock_surface = NULL;
896}
897
898static void
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200899desktop_shell_set_lock_surface(struct wl_client *client,
900 struct wl_resource *resource,
901 struct wl_resource *surface_resource)
902{
Kristian Høgsbergaf867cc2011-11-15 13:34:49 +0200903 struct wl_shell *shell = resource->data;
Pekka Paalanen57da4a82011-11-23 16:42:16 +0200904 struct shell_surface *priv;
Kristian Høgsbergaf867cc2011-11-15 13:34:49 +0200905
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +0200906 shell->prepare_event_sent = false;
Kristian Høgsbergaf867cc2011-11-15 13:34:49 +0200907
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +0200908 if (!shell->locked)
909 return;
910
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500911 shell->lock_surface = surface_resource->data;
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +0200912
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500913 shell->lock_surface_listener.func = handle_lock_surface_destroy;
914 wl_list_insert(&surface_resource->destroy_listener_list,
915 &shell->lock_surface_listener.link);
Pekka Paalanen57da4a82011-11-23 16:42:16 +0200916
917 priv = get_shell_surface(shell->lock_surface);
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500918 priv->type = SHELL_SURFACE_LOCK;
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +0200919}
920
921static void
922resume_desktop(struct wl_shell *shell)
923{
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500924 struct wlsc_surface *surface;
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100925 struct shell_surface *background;
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +0200926
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500927 wl_list_for_each(surface, &shell->hidden_surface_list, link)
928 wlsc_surface_configure(surface, surface->x, surface->y,
929 surface->width, surface->height);
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +0200930
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100931 background = container_of(shell->backgrounds.prev,
932 struct shell_surface, link);
933 wl_list_insert_list(background->surface->link.prev,
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500934 &shell->hidden_surface_list);
935 wl_list_init(&shell->hidden_surface_list);
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +0200936
937 shell->locked = false;
938 wlsc_compositor_repick(shell->compositor);
Kristian Høgsbergaf867cc2011-11-15 13:34:49 +0200939 wlsc_compositor_wake(shell->compositor);
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200940}
941
942static void
943desktop_shell_unlock(struct wl_client *client,
944 struct wl_resource *resource)
945{
946 struct wl_shell *shell = resource->data;
947
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200948 shell->prepare_event_sent = false;
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +0200949
950 if (shell->locked)
951 resume_desktop(shell);
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200952}
953
Kristian Høgsberg75840622011-09-06 13:48:16 -0400954static const struct desktop_shell_interface desktop_shell_implementation = {
955 desktop_shell_set_background,
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200956 desktop_shell_set_panel,
957 desktop_shell_set_lock_surface,
958 desktop_shell_unlock
Kristian Høgsberg75840622011-09-06 13:48:16 -0400959};
960
961static void
Kristian Høgsberg07937562011-04-12 17:25:42 -0400962move_binding(struct wl_input_device *device, uint32_t time,
963 uint32_t key, uint32_t button, uint32_t state, void *data)
964{
Kristian Høgsberg07937562011-04-12 17:25:42 -0400965 struct wlsc_surface *surface =
966 (struct wlsc_surface *) device->pointer_focus;
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500967 struct shell_surface *priv;
968
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100969 if (surface == NULL)
970 return;
Kristian Høgsberg07937562011-04-12 17:25:42 -0400971
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100972 priv = get_shell_surface(surface);
973 switch (priv->type) {
974 case SHELL_SURFACE_PANEL:
975 case SHELL_SURFACE_BACKGROUND:
976 case SHELL_SURFACE_FULLSCREEN:
977 return;
978 default:
979 break;
980 }
Kristian Høgsberg10f097e2011-04-13 11:52:54 -0400981
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400982 wlsc_surface_move(surface, (struct wlsc_input_device *) device, time);
Kristian Høgsberg07937562011-04-12 17:25:42 -0400983}
984
985static void
986resize_binding(struct wl_input_device *device, uint32_t time,
987 uint32_t key, uint32_t button, uint32_t state, void *data)
988{
Kristian Høgsberg07937562011-04-12 17:25:42 -0400989 struct wlsc_surface *surface =
990 (struct wlsc_surface *) device->pointer_focus;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400991 struct wl_resource *resource;
Kristian Høgsberg07937562011-04-12 17:25:42 -0400992 uint32_t edges = 0;
993 int32_t x, y;
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500994 struct shell_surface *priv;
995
Benjamin Franzked0f79ab2011-11-22 12:43:52 +0100996 if (surface == NULL)
997 return;
998
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500999 priv = get_shell_surface(surface);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +01001000 switch (priv->type) {
1001 case SHELL_SURFACE_PANEL:
1002 case SHELL_SURFACE_BACKGROUND:
1003 case SHELL_SURFACE_FULLSCREEN:
1004 return;
1005 default:
1006 break;
1007 }
Kristian Høgsberg10f097e2011-04-13 11:52:54 -04001008
Kristian Høgsberg07937562011-04-12 17:25:42 -04001009 x = device->grab_x - surface->x;
1010 y = device->grab_y - surface->y;
1011
1012 if (x < surface->width / 3)
1013 edges |= WL_SHELL_RESIZE_LEFT;
1014 else if (x < 2 * surface->width / 3)
1015 edges |= 0;
1016 else
1017 edges |= WL_SHELL_RESIZE_RIGHT;
1018
1019 if (y < surface->height / 3)
1020 edges |= WL_SHELL_RESIZE_TOP;
1021 else if (y < 2 * surface->height / 3)
1022 edges |= 0;
1023 else
1024 edges |= WL_SHELL_RESIZE_BOTTOM;
1025
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -04001026 resource = /* Find shell resource for surface client */ 0;
1027
1028 /* ... or use wl_shell_surface */
1029
1030 wlsc_surface_resize(surface, (struct wlsc_input_device *) device,
1031 time, edges, resource);
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04001032}
1033
1034static void
Kristian Høgsberg75840622011-09-06 13:48:16 -04001035activate(struct wlsc_shell *base, struct wlsc_surface *es,
1036 struct wlsc_input_device *device, uint32_t time)
1037{
1038 struct wl_shell *shell = container_of(base, struct wl_shell, shell);
1039 struct wlsc_compositor *compositor = shell->compositor;
Pekka Paalanen57da4a82011-11-23 16:42:16 +02001040 struct shell_surface *priv;
1041
1042 priv = get_shell_surface(es);
Kristian Høgsberg75840622011-09-06 13:48:16 -04001043
1044 wlsc_surface_activate(es, device, time);
1045
Kristian Høgsbergd6e55252011-10-11 23:41:17 -04001046 if (compositor->wxs)
1047 wlsc_xserver_surface_activate(es);
1048
Kristian Høgsbergd2abb832011-11-23 10:52:40 -05001049 switch (priv->type) {
Pekka Paalanen57da4a82011-11-23 16:42:16 +02001050 case SHELL_SURFACE_BACKGROUND:
1051 /* put background back to bottom */
Kristian Høgsberg75840622011-09-06 13:48:16 -04001052 wl_list_remove(&es->link);
1053 wl_list_insert(compositor->surface_list.prev, &es->link);
Pekka Paalanen57da4a82011-11-23 16:42:16 +02001054 break;
1055 case SHELL_SURFACE_PANEL:
1056 /* already put on top */
1057 break;
1058 default:
Benjamin Franzked0f79ab2011-11-22 12:43:52 +01001059 if (!shell->locked) {
Pekka Paalanen57da4a82011-11-23 16:42:16 +02001060 /* bring panel back to top */
Benjamin Franzked0f79ab2011-11-22 12:43:52 +01001061 struct shell_surface *panel;
1062 wl_list_for_each(panel, &shell->panels, link) {
1063 wl_list_remove(&panel->surface->link);
1064 wl_list_insert(&compositor->surface_list,
1065 &panel->surface->link);
1066 }
Pekka Paalanen57da4a82011-11-23 16:42:16 +02001067 }
Kristian Høgsberg75840622011-09-06 13:48:16 -04001068 }
1069}
1070
1071static void
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02001072lock(struct wlsc_shell *base)
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04001073{
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02001074 struct wl_shell *shell = container_of(base, struct wl_shell, shell);
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02001075 struct wl_list *surface_list = &shell->compositor->surface_list;
1076 struct wlsc_surface *cur;
1077 struct wlsc_surface *tmp;
Pekka Paalanen57da4a82011-11-23 16:42:16 +02001078 struct shell_surface *priv;
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02001079 struct wlsc_input_device *device;
1080 uint32_t time;
1081
1082 if (shell->locked)
1083 return;
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02001084
1085 shell->locked = true;
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02001086
1087 /* Move all surfaces from compositor's list to our hidden list,
1088 * except the background. This way nothing else can show or
1089 * receive input events while we are locked. */
1090
1091 if (!wl_list_empty(&shell->hidden_surface_list)) {
1092 fprintf(stderr,
1093 "%s: Assertion failed: hidden_surface_list is not empty.\n",
1094 __func__);
1095 }
1096
1097 wl_list_for_each_safe(cur, tmp, surface_list, link) {
1098 /* skip input device sprites, cur->surface is uninitialised */
1099 if (cur->surface.resource.client == NULL)
1100 continue;
1101
Pekka Paalanen57da4a82011-11-23 16:42:16 +02001102 priv = get_shell_surface(cur);
Kristian Høgsbergd2abb832011-11-23 10:52:40 -05001103 if (priv->type == SHELL_SURFACE_BACKGROUND)
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02001104 continue;
1105
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -05001106 cur->output = NULL;
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02001107 wl_list_remove(&cur->link);
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -05001108 wl_list_insert(shell->hidden_surface_list.prev, &cur->link);
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02001109 }
1110
1111 /* reset pointer foci */
1112 wlsc_compositor_repick(shell->compositor);
1113
1114 /* reset keyboard foci */
1115 time = wlsc_compositor_get_time();
1116 wl_list_for_each(device, &shell->compositor->input_device_list, link) {
1117 wl_input_device_set_keyboard_focus(&device->input_device,
1118 NULL, time);
1119 }
1120
1121 /* TODO: disable bindings that should not work while locked. */
1122
1123 /* All this must be undone in resume_desktop(). */
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02001124}
1125
1126static void
1127unlock(struct wlsc_shell *base)
1128{
1129 struct wl_shell *shell = container_of(base, struct wl_shell, shell);
1130
Pekka Paalanend81c2162011-11-16 13:47:34 +02001131 if (!shell->locked || shell->lock_surface) {
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02001132 wlsc_compositor_wake(shell->compositor);
1133 return;
1134 }
1135
1136 /* If desktop-shell client has gone away, unlock immediately. */
1137 if (!shell->child.desktop_shell) {
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02001138 resume_desktop(shell);
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02001139 return;
1140 }
1141
1142 if (shell->prepare_event_sent)
1143 return;
1144
1145 wl_resource_post_event(shell->child.desktop_shell,
1146 DESKTOP_SHELL_PREPARE_LOCK_SURFACE);
1147 shell->prepare_event_sent = true;
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04001148}
1149
1150static void
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -05001151map(struct wlsc_shell *base,
1152 struct wlsc_surface *surface, int32_t width, int32_t height)
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04001153{
Kristian Høgsberg75840622011-09-06 13:48:16 -04001154 struct wl_shell *shell = container_of(base, struct wl_shell, shell);
1155 struct wlsc_compositor *compositor = shell->compositor;
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -05001156 struct wl_list *list;
Pekka Paalanen57da4a82011-11-23 16:42:16 +02001157 struct shell_surface *priv;
1158
1159 priv = get_shell_surface(surface);
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -05001160
1161 if (shell->locked)
1162 list = &shell->hidden_surface_list;
1163 else
1164 list = &compositor->surface_list;
Kristian Høgsberg75840622011-09-06 13:48:16 -04001165
Pekka Paalanend3dd6e12011-11-16 13:47:33 +02001166 /* surface stacking order, see also activate() */
Kristian Høgsbergd2abb832011-11-23 10:52:40 -05001167 switch (priv->type) {
Pekka Paalanen57da4a82011-11-23 16:42:16 +02001168 case SHELL_SURFACE_BACKGROUND:
Pekka Paalanend3dd6e12011-11-16 13:47:33 +02001169 /* background always visible, at the bottom */
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -05001170 wl_list_insert(compositor->surface_list.prev, &surface->link);
Pekka Paalanen57da4a82011-11-23 16:42:16 +02001171 break;
1172 case SHELL_SURFACE_PANEL:
Pekka Paalanend3dd6e12011-11-16 13:47:33 +02001173 /* panel always on top, hidden while locked */
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -05001174 wl_list_insert(list, &surface->link);
Pekka Paalanen57da4a82011-11-23 16:42:16 +02001175 break;
1176 case SHELL_SURFACE_LOCK:
Pekka Paalanend3dd6e12011-11-16 13:47:33 +02001177 /* lock surface always visible, on top */
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -05001178 wl_list_insert(&compositor->surface_list, &surface->link);
Pekka Paalanend3dd6e12011-11-16 13:47:33 +02001179
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -05001180 wlsc_compositor_repick(compositor);
Pekka Paalanen57da4a82011-11-23 16:42:16 +02001181 wlsc_compositor_wake(compositor);
1182 break;
1183 default:
Pekka Paalanend3dd6e12011-11-16 13:47:33 +02001184 /* everything else just below the panel */
Benjamin Franzked0f79ab2011-11-22 12:43:52 +01001185 if (!wl_list_empty(&shell->panels)) {
1186 struct shell_surface *panel =
1187 container_of(shell->panels.prev,
1188 struct shell_surface, link);
1189 wl_list_insert(&panel->surface->link, &surface->link);
1190 } else {
Pekka Paalanen57da4a82011-11-23 16:42:16 +02001191 wl_list_insert(list, &surface->link);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +01001192 }
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02001193 }
1194
Kristian Høgsbergd2abb832011-11-23 10:52:40 -05001195 if (priv->type == SHELL_SURFACE_TOPLEVEL) {
Kristian Høgsberg46770132011-11-09 12:38:53 -05001196 surface->x = 10 + random() % 400;
1197 surface->y = 10 + random() % 400;
1198 }
1199
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -05001200 surface->width = width;
1201 surface->height = height;
Kristian Høgsbergd2abb832011-11-23 10:52:40 -05001202 if (!shell->locked || priv->type == SHELL_SURFACE_LOCK)
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -05001203 wlsc_surface_configure(surface,
1204 surface->x, surface->y, width, height);
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -05001205}
1206
1207static void
1208configure(struct wlsc_shell *shell, struct wlsc_surface *surface,
1209 int32_t x, int32_t y, int32_t width, int32_t height)
1210{
1211 struct wlsc_mode *current;
Kristian Høgsbergd2abb832011-11-23 10:52:40 -05001212 struct shell_surface *priv;
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -05001213
Kristian Høgsbergd2abb832011-11-23 10:52:40 -05001214 priv = get_shell_surface(surface);
1215 switch (priv->type) {
1216 case SHELL_SURFACE_FULLSCREEN:
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -05001217 current = surface->fullscreen_output->current;
1218 x = (current->width - surface->width) / 2;
1219 y = (current->height - surface->height) / 2;
Kristian Høgsbergd2abb832011-11-23 10:52:40 -05001220 break;
1221 default:
1222 break;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -04001223 }
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -05001224
1225 wlsc_surface_configure(surface, x, y, width, height);
Kristian Høgsberg07937562011-04-12 17:25:42 -04001226}
1227
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -04001228static void
Pekka Paalanen6cd281a2011-11-03 14:11:32 +02001229desktop_shell_sigchld(struct wlsc_process *process, int status)
1230{
1231 struct wl_shell *shell =
1232 container_of(process, struct wl_shell, child.process);
1233
1234 shell->child.process.pid = 0;
1235 shell->child.client = NULL; /* already destroyed by wayland */
1236}
1237
1238static int
1239launch_desktop_shell_process(struct wl_shell *shell)
1240{
Kristian Høgsbergc4693c42011-11-14 14:57:17 -05001241 const char *shell_exe = LIBEXECDIR "/wayland-desktop-shell";
Pekka Paalanen6cd281a2011-11-03 14:11:32 +02001242 struct wlsc_compositor *compositor = shell->compositor;
1243 char s[32];
1244 int sv[2], flags;
1245
1246 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sv) < 0) {
1247 fprintf(stderr, "socketpair failed\n");
1248 return -1;
1249 }
1250
1251 shell->child.process.pid = fork();
1252 shell->child.process.cleanup = desktop_shell_sigchld;
1253
1254 switch (shell->child.process.pid) {
1255 case 0:
1256 /* SOCK_CLOEXEC closes both ends, so we need to unset
1257 * the flag on the client fd. */
1258 flags = fcntl(sv[1], F_GETFD);
1259 if (flags != -1)
1260 fcntl(sv[1], F_SETFD, flags & ~FD_CLOEXEC);
1261
1262 snprintf(s, sizeof s, "%d", sv[1]);
1263 setenv("WAYLAND_SOCKET", s, 1);
1264 if (execl(shell_exe, shell_exe, NULL) < 0)
1265 fprintf(stderr, "%s: running '%s' failed: %m\n",
1266 __func__, shell_exe);
1267 exit(-1);
1268
1269 default:
1270 close(sv[1]);
1271 shell->child.client =
1272 wl_client_create(compositor->wl_display, sv[0]);
1273 wlsc_watch_process(&shell->child.process);
1274 break;
1275
1276 case -1:
1277 fprintf(stderr, "%s: fork failed: %m\n", __func__);
1278 return -1;
1279 }
1280 return 0;
1281}
1282
1283static void
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -04001284bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
1285{
1286 struct wl_shell *shell = data;
1287
1288 wl_client_add_object(client, &wl_shell_interface,
1289 &shell_interface, id, shell);
1290}
1291
Kristian Høgsberg75840622011-09-06 13:48:16 -04001292static void
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02001293unbind_desktop_shell(struct wl_resource *resource)
1294{
1295 struct wl_shell *shell = resource->data;
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -05001296
1297 if (shell->locked)
1298 resume_desktop(shell);
1299
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02001300 shell->child.desktop_shell = NULL;
1301 shell->prepare_event_sent = false;
1302 free(resource);
1303}
1304
1305static void
Kristian Høgsberg75840622011-09-06 13:48:16 -04001306bind_desktop_shell(struct wl_client *client,
1307 void *data, uint32_t version, uint32_t id)
1308{
1309 struct wl_shell *shell = data;
Pekka Paalanenbbe60522011-11-03 14:11:33 +02001310 struct wl_resource *resource;
Kristian Høgsberg75840622011-09-06 13:48:16 -04001311
Pekka Paalanenbbe60522011-11-03 14:11:33 +02001312 resource = wl_client_add_object(client, &desktop_shell_interface,
1313 &desktop_shell_implementation,
1314 id, shell);
1315
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02001316 if (client == shell->child.client) {
1317 resource->destroy = unbind_desktop_shell;
1318 shell->child.desktop_shell = resource;
Pekka Paalanenbbe60522011-11-03 14:11:33 +02001319 return;
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02001320 }
Pekka Paalanenbbe60522011-11-03 14:11:33 +02001321
1322 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
1323 "permission to bind desktop_shell denied");
1324 wl_resource_destroy(resource, 0);
Kristian Høgsberg75840622011-09-06 13:48:16 -04001325}
1326
Kristian Høgsberg6c709a32011-05-06 14:52:41 -04001327int
1328shell_init(struct wlsc_compositor *ec);
1329
Kristian Høgsberg1c562182011-05-02 22:09:20 -04001330WL_EXPORT int
1331shell_init(struct wlsc_compositor *ec)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -05001332{
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04001333 struct wl_shell *shell;
1334
1335 shell = malloc(sizeof *shell);
1336 if (shell == NULL)
1337 return -1;
1338
Kristian Høgsbergf0d91162011-10-11 22:44:23 -04001339 memset(shell, 0, sizeof *shell);
Kristian Høgsberg75840622011-09-06 13:48:16 -04001340 shell->compositor = ec;
1341 shell->shell.activate = activate;
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04001342 shell->shell.lock = lock;
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02001343 shell->shell.unlock = unlock;
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -05001344 shell->shell.map = map;
1345 shell->shell.configure = configure;
Kristian Høgsberg1c562182011-05-02 22:09:20 -04001346 shell->shell.set_selection_focus = wlsc_selection_set_focus;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -05001347
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02001348 wl_list_init(&shell->hidden_surface_list);
Benjamin Franzked0f79ab2011-11-22 12:43:52 +01001349 wl_list_init(&shell->backgrounds);
1350 wl_list_init(&shell->panels);
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02001351
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -04001352 if (wl_display_add_global(ec->wl_display, &wl_shell_interface,
1353 shell, bind_shell) == NULL)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -05001354 return -1;
1355
Kristian Høgsberg75840622011-09-06 13:48:16 -04001356 if (wl_display_add_global(ec->wl_display,
1357 &desktop_shell_interface,
1358 shell, bind_desktop_shell) == NULL)
1359 return -1;
1360
Pekka Paalanen6cd281a2011-11-03 14:11:32 +02001361 if (launch_desktop_shell_process(shell) != 0)
1362 return -1;
1363
Kristian Høgsberg07937562011-04-12 17:25:42 -04001364 wlsc_compositor_add_binding(ec, 0, BTN_LEFT, MODIFIER_SUPER,
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04001365 move_binding, shell);
Kristian Høgsberg07937562011-04-12 17:25:42 -04001366 wlsc_compositor_add_binding(ec, 0, BTN_MIDDLE, MODIFIER_SUPER,
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04001367 resize_binding, shell);
1368
1369 ec->shell = &shell->shell;
Kristian Høgsberg07937562011-04-12 17:25:42 -04001370
Kristian Høgsberg4cca3492011-01-18 07:53:49 -05001371 return 0;
1372}