blob: f2d3ef22f08913fa3a84e68147a6d380d7a483ea [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;
Kristian Høgsberg75840622011-09-06 13:48:16 -040042 struct wlsc_surface *panel;
43 struct wl_listener panel_listener;
44 struct wlsc_surface *background;
45 struct wl_listener background_listener;
Pekka Paalanen6cd281a2011-11-03 14:11:32 +020046
47 struct {
48 struct wlsc_process process;
49 struct wl_client *client;
Pekka Paalanen9ef3e012011-11-15 13:34:48 +020050 struct wl_resource *desktop_shell;
Pekka Paalanen6cd281a2011-11-03 14:11:32 +020051 } child;
Pekka Paalanen9ef3e012011-11-15 13:34:48 +020052
53 bool locked;
54 bool prepare_event_sent;
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +020055
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -050056 struct wlsc_surface *lock_surface;
57 struct wl_listener lock_surface_listener;
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +020058 struct wl_list hidden_surface_list;
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -040059};
60
Kristian Høgsbergd2abb832011-11-23 10:52:40 -050061enum shell_surface_type {
Pekka Paalanen57da4a82011-11-23 16:42:16 +020062 SHELL_SURFACE_NORMAL,
Kristian Høgsbergd2abb832011-11-23 10:52:40 -050063
Pekka Paalanen57da4a82011-11-23 16:42:16 +020064 SHELL_SURFACE_PANEL,
65 SHELL_SURFACE_BACKGROUND,
66 SHELL_SURFACE_LOCK,
Kristian Høgsbergd2abb832011-11-23 10:52:40 -050067
68 SHELL_SURFACE_TOPLEVEL,
69 SHELL_SURFACE_TRANSIENT,
70 SHELL_SURFACE_FULLSCREEN
Pekka Paalanen57da4a82011-11-23 16:42:16 +020071};
72
Pekka Paalanen56cdea92011-11-23 16:14:12 +020073struct shell_surface {
74 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;
Pekka Paalanen56cdea92011-11-23 16:14:12 +020078};
79
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050080struct wlsc_move_grab {
81 struct wl_grab grab;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -050082 struct wlsc_surface *surface;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050083 int32_t dx, dy;
84};
85
86static void
Pekka Paalanen56cdea92011-11-23 16:14:12 +020087destroy_shell_surface(struct shell_surface *priv)
88{
89 wl_list_remove(&priv->destroy_listener.link);
90 free(priv);
91}
92
93static void
94handle_shell_surface_destroy(struct wl_listener *listener,
95 struct wl_resource *resource, uint32_t time)
96{
97 struct shell_surface *priv =
98 container_of(listener, struct shell_surface, destroy_listener);
99 destroy_shell_surface(priv);
100}
101
102static struct shell_surface *
103get_shell_surface(struct wlsc_surface *surface)
104{
105 struct shell_surface *priv;
106
107 if (surface->shell_priv)
108 return surface->shell_priv;
109
110 priv = calloc(1, sizeof *priv);
111 if (!priv)
112 return NULL;
113
114 priv->destroy_listener.func = handle_shell_surface_destroy;
115 wl_list_insert(surface->surface.resource.destroy_listener_list.prev,
116 &priv->destroy_listener.link);
117
118 surface->shell_priv = priv;
119
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500120 priv->type = SHELL_SURFACE_NORMAL;
Pekka Paalanen57da4a82011-11-23 16:42:16 +0200121
Pekka Paalanen56cdea92011-11-23 16:14:12 +0200122 return priv;
123}
124
125static void
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500126move_grab_motion(struct wl_grab *grab,
127 uint32_t time, int32_t x, int32_t y)
128{
129 struct wlsc_move_grab *move = (struct wlsc_move_grab *) grab;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500130 struct wlsc_surface *es = move->surface;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500131
Kristian Høgsberga691aee2011-06-23 21:43:50 -0400132 wlsc_surface_configure(es, x + move->dx, y + move->dy,
133 es->width, es->height);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500134}
135
136static void
137move_grab_button(struct wl_grab *grab,
138 uint32_t time, int32_t button, int32_t state)
139{
140}
141
142static void
143move_grab_end(struct wl_grab *grab, uint32_t time)
144{
145 free(grab);
146}
147
148static const struct wl_grab_interface move_grab_interface = {
149 move_grab_motion,
150 move_grab_button,
151 move_grab_end
152};
153
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400154static int
155wlsc_surface_move(struct wlsc_surface *es,
156 struct wlsc_input_device *wd, uint32_t time)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500157{
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500158 struct wlsc_move_grab *move;
159
160 move = malloc(sizeof *move);
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400161 if (!move)
162 return -1;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500163
164 move->grab.interface = &move_grab_interface;
165 move->dx = es->x - wd->input_device.grab_x;
166 move->dy = es->y - wd->input_device.grab_y;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500167 move->surface = es;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500168
169 if (wl_input_device_update_grab(&wd->input_device,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400170 &move->grab, &es->surface, time) < 0)
171 return 0;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500172
173 wlsc_input_device_set_pointer_image(wd, WLSC_POINTER_DRAGGING);
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400174 wl_input_device_set_pointer_focus(&wd->input_device,
175 NULL, time, 0, 0, 0, 0);
176
177 return 0;
178}
179
180static void
181shell_move(struct wl_client *client, struct wl_resource *resource,
182 struct wl_resource *surface_resource,
183 struct wl_resource *input_resource, uint32_t time)
184{
185 struct wlsc_input_device *wd = input_resource->data;
186 struct wlsc_surface *es = surface_resource->data;
187
188 if (wlsc_surface_move(es, wd, time) < 0)
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400189 wl_resource_post_no_memory(resource);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500190}
191
192struct wlsc_resize_grab {
193 struct wl_grab grab;
194 uint32_t edges;
195 int32_t dx, dy, width, height;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500196 struct wlsc_surface *surface;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400197 struct wl_resource *resource;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500198};
199
200static void
201resize_grab_motion(struct wl_grab *grab,
202 uint32_t time, int32_t x, int32_t y)
203{
204 struct wlsc_resize_grab *resize = (struct wlsc_resize_grab *) grab;
205 struct wl_input_device *device = grab->input_device;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500206 struct wl_surface *surface = &resize->surface->surface;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500207 int32_t width, height;
208
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500209 if (resize->edges & WL_SHELL_RESIZE_LEFT) {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500210 width = device->grab_x - x + resize->width;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500211 } else if (resize->edges & WL_SHELL_RESIZE_RIGHT) {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500212 width = x - device->grab_x + resize->width;
213 } else {
214 width = resize->width;
215 }
216
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500217 if (resize->edges & WL_SHELL_RESIZE_TOP) {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500218 height = device->grab_y - y + resize->height;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500219 } else if (resize->edges & WL_SHELL_RESIZE_BOTTOM) {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500220 height = y - device->grab_y + resize->height;
221 } else {
222 height = resize->height;
223 }
224
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400225 wl_resource_post_event(resize->resource,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400226 WL_SHELL_CONFIGURE, time, resize->edges,
227 surface, width, height);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500228}
229
230static void
231resize_grab_button(struct wl_grab *grab,
232 uint32_t time, int32_t button, int32_t state)
233{
234}
235
236static void
237resize_grab_end(struct wl_grab *grab, uint32_t time)
238{
239 free(grab);
240}
241
242static const struct wl_grab_interface resize_grab_interface = {
243 resize_grab_motion,
244 resize_grab_button,
245 resize_grab_end
246};
247
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400248static int
249wlsc_surface_resize(struct wlsc_surface *es,
250 struct wlsc_input_device *wd,
251 uint32_t time, uint32_t edges,
252 struct wl_resource *resource)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500253{
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500254 struct wlsc_resize_grab *resize;
255 enum wlsc_pointer_type pointer = WLSC_POINTER_LEFT_PTR;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500256
Kristian Høgsberg0ce24572011-01-28 15:18:33 -0500257 /* FIXME: Reject if fullscreen */
258
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500259 resize = malloc(sizeof *resize);
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400260 if (!resize)
261 return -1;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500262
263 resize->grab.interface = &resize_grab_interface;
264 resize->edges = edges;
265 resize->dx = es->x - wd->input_device.grab_x;
266 resize->dy = es->y - wd->input_device.grab_y;
267 resize->width = es->width;
268 resize->height = es->height;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500269 resize->surface = es;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400270 resize->resource = resource;
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400271
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500272 if (edges == 0 || edges > 15 ||
273 (edges & 3) == 3 || (edges & 12) == 12)
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400274 return 0;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500275
276 switch (edges) {
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500277 case WL_SHELL_RESIZE_TOP:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500278 pointer = WLSC_POINTER_TOP;
279 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500280 case WL_SHELL_RESIZE_BOTTOM:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500281 pointer = WLSC_POINTER_BOTTOM;
282 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500283 case WL_SHELL_RESIZE_LEFT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500284 pointer = WLSC_POINTER_LEFT;
285 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500286 case WL_SHELL_RESIZE_TOP_LEFT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500287 pointer = WLSC_POINTER_TOP_LEFT;
288 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500289 case WL_SHELL_RESIZE_BOTTOM_LEFT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500290 pointer = WLSC_POINTER_BOTTOM_LEFT;
291 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500292 case WL_SHELL_RESIZE_RIGHT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500293 pointer = WLSC_POINTER_RIGHT;
294 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500295 case WL_SHELL_RESIZE_TOP_RIGHT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500296 pointer = WLSC_POINTER_TOP_RIGHT;
297 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500298 case WL_SHELL_RESIZE_BOTTOM_RIGHT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500299 pointer = WLSC_POINTER_BOTTOM_RIGHT;
300 break;
301 }
302
303 if (wl_input_device_update_grab(&wd->input_device,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400304 &resize->grab, &es->surface, time) < 0)
305 return 0;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500306
307 wlsc_input_device_set_pointer_image(wd, pointer);
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400308 wl_input_device_set_pointer_focus(&wd->input_device,
309 NULL, time, 0, 0, 0, 0);
310
311 return 0;
312}
313
314static void
315shell_resize(struct wl_client *client, struct wl_resource *resource,
316 struct wl_resource *surface_resource,
317 struct wl_resource *input_resource, uint32_t time, uint32_t edges)
318{
319 struct wlsc_input_device *wd = input_resource->data;
320 struct wlsc_surface *es = surface_resource->data;
321
322 /* FIXME: Reject if fullscreen */
323
324 if (wlsc_surface_resize(es, wd, time, edges, resource) < 0)
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400325 wl_resource_post_no_memory(resource);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500326}
327
328static void
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400329shell_set_toplevel(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400330 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400331 struct wl_resource *surface_resource)
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400332
333{
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400334 struct wlsc_surface *es = surface_resource->data;
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500335 struct shell_surface *priv;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400336
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500337 priv = get_shell_surface(es);
338 if (priv->type == SHELL_SURFACE_FULLSCREEN) {
339 es->x = priv->saved_x;
340 es->y = priv->saved_y;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400341 }
342
343 wlsc_surface_damage(es);
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500344 priv->type = SHELL_SURFACE_TOPLEVEL;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400345 es->fullscreen_output = NULL;
346}
347
348static void
349shell_set_transient(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400350 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400351 struct wl_resource *surface_resource,
352 struct wl_resource *parent_resource,
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400353 int x, int y, uint32_t flags)
354{
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400355 struct wlsc_surface *es = surface_resource->data;
356 struct wlsc_surface *pes = parent_resource->data;
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500357 struct shell_surface *priv;
358
359 priv = get_shell_surface(es);
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400360
361 /* assign to parents output */
362 es->output = pes->output;
363
364 es->x = pes->x + x;
365 es->y = pes->y + y;
366
367 wlsc_surface_damage(es);
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500368 priv->type = SHELL_SURFACE_TRANSIENT;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400369}
370
371static void
372shell_set_fullscreen(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400373 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400374 struct wl_resource *surface_resource)
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400375
376{
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400377 struct wlsc_surface *es = surface_resource->data;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400378 struct wlsc_output *output;
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500379 struct shell_surface *priv;
380
381 priv = get_shell_surface(es);
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400382
383 /* FIXME: Fullscreen on first output */
384 /* FIXME: Handle output going away */
385 output = container_of(es->compositor->output_list.next,
386 struct wlsc_output, link);
387 es->output = output;
388
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500389 priv->saved_x = es->x;
390 priv->saved_y = es->y;
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400391 es->x = (output->current->width - es->width) / 2;
392 es->y = (output->current->height - es->height) / 2;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400393 es->fullscreen_output = output;
394 wlsc_surface_damage(es);
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500395 priv->type = SHELL_SURFACE_FULLSCREEN;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400396}
397
398static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400399destroy_drag(struct wl_resource *resource)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500400{
401 struct wl_drag *drag =
402 container_of(resource, struct wl_drag, resource);
403
404 wl_list_remove(&drag->drag_focus_listener.link);
405 if (drag->grab.input_device)
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400406 wl_input_device_end_grab(drag->grab.input_device,
407 wlsc_compositor_get_time());
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500408
409 free(drag);
410}
411
412
413static void
414wl_drag_set_pointer_focus(struct wl_drag *drag,
415 struct wl_surface *surface, uint32_t time,
416 int32_t x, int32_t y, int32_t sx, int32_t sy)
417{
418 char **p, **end;
419
420 if (drag->drag_focus == surface)
421 return;
422
423 if (drag->drag_focus &&
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400424 (!surface ||
425 drag->drag_focus->resource.client != surface->resource.client))
426 wl_resource_post_event(&drag->drag_offer.resource,
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500427 WL_DRAG_OFFER_POINTER_FOCUS,
428 time, NULL, 0, 0, 0, 0);
429
430 if (surface &&
431 (!drag->drag_focus ||
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400432 drag->drag_focus->resource.client != surface->resource.client)) {
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400433
434 drag->drag_offer.resource.client = surface->resource.client;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500435 end = drag->types.data + drag->types.size;
436 for (p = drag->types.data; p < end; p++)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400437 wl_resource_post_event(&drag->drag_offer.resource,
438 WL_DRAG_OFFER_OFFER, *p);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500439 }
440
441 if (surface) {
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400442 wl_resource_post_event(&drag->drag_offer.resource,
443 WL_DRAG_OFFER_POINTER_FOCUS,
444 time, surface,
445 x, y, sx, sy);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500446
447 }
448
449 drag->drag_focus = surface;
450 drag->pointer_focus_time = time;
451 drag->target = NULL;
452
453 wl_list_remove(&drag->drag_focus_listener.link);
454 if (surface)
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200455 wl_list_insert(surface->resource.destroy_listener_list.prev,
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500456 &drag->drag_focus_listener.link);
457}
458
459static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400460drag_offer_accept(struct wl_client *client, struct wl_resource *resource,
461 uint32_t time, const char *type)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500462{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400463 struct wl_drag_offer *offer = resource->data;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500464 struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer);
465 char **p, **end;
466
467 /* If the client responds to drag pointer_focus or motion
468 * events after the pointer has left the surface, we just
469 * discard the accept requests. The drag source just won't
470 * get the corresponding 'target' events and eventually the
471 * next surface/root will start sending events. */
472 if (time < drag->pointer_focus_time)
473 return;
474
475 drag->target = client;
476 drag->type = NULL;
477 end = drag->types.data + drag->types.size;
478 for (p = drag->types.data; p < end; p++)
479 if (type && strcmp(*p, type) == 0)
480 drag->type = *p;
481
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400482 wl_resource_post_event(&drag->resource, WL_DRAG_TARGET, drag->type);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500483}
484
485static void
486drag_offer_receive(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400487 struct wl_resource *resource, int fd)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500488{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400489 struct wl_drag_offer *offer = resource->data;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500490 struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer);
491
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400492 wl_resource_post_event(&drag->resource, WL_DRAG_FINISH, fd);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500493 close(fd);
494}
495
496static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400497drag_offer_reject(struct wl_client *client, struct wl_resource *resource)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500498{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400499 struct wl_drag_offer *offer = resource->data;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500500 struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer);
501
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400502 wl_resource_post_event(&drag->resource, WL_DRAG_REJECT);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500503}
504
505static const struct wl_drag_offer_interface drag_offer_interface = {
506 drag_offer_accept,
507 drag_offer_receive,
508 drag_offer_reject
509};
510
511static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400512drag_offer(struct wl_client *client,
513 struct wl_resource *resource, const char *type)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500514{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400515 struct wl_drag *drag = resource->data;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500516 char **p;
517
518 p = wl_array_add(&drag->types, sizeof *p);
519 if (p)
520 *p = strdup(type);
521 if (!p || !*p)
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400522 wl_resource_post_no_memory(resource);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500523}
524
525static void
526drag_grab_motion(struct wl_grab *grab,
527 uint32_t time, int32_t x, int32_t y)
528{
529 struct wl_drag *drag = container_of(grab, struct wl_drag, grab);
530 struct wlsc_surface *es;
531 int32_t sx, sy;
532
533 es = pick_surface(grab->input_device, &sx, &sy);
534 wl_drag_set_pointer_focus(drag, &es->surface, time, x, y, sx, sy);
535 if (es)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400536 wl_resource_post_event(&drag->drag_offer.resource,
537 WL_DRAG_OFFER_MOTION,
538 time, x, y, sx, sy);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500539}
540
541static void
542drag_grab_button(struct wl_grab *grab,
543 uint32_t time, int32_t button, int32_t state)
544{
545}
546
547static void
548drag_grab_end(struct wl_grab *grab, uint32_t time)
549{
550 struct wl_drag *drag = container_of(grab, struct wl_drag, grab);
551
552 if (drag->target)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400553 wl_resource_post_event(&drag->drag_offer.resource,
554 WL_DRAG_OFFER_DROP);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500555
556 wl_drag_set_pointer_focus(drag, NULL, time, 0, 0, 0, 0);
557}
558
559static const struct wl_grab_interface drag_grab_interface = {
560 drag_grab_motion,
561 drag_grab_button,
562 drag_grab_end
563};
564
565static void
566drag_activate(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400567 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400568 struct wl_resource *surface_resource,
569 struct wl_resource *device_resource, uint32_t time)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500570{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400571 struct wl_drag *drag = resource->data;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400572 struct wl_surface *surface = surface_resource->data;
573 struct wl_input_device *device = device_resource->data;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500574 struct wl_display *display = wl_client_get_display (client);
575 struct wlsc_surface *target;
576 int32_t sx, sy;
577
578 if (wl_input_device_update_grab(device,
579 &drag->grab, surface, time) < 0)
580 return;
581
582 drag->grab.interface = &drag_grab_interface;
583
584 drag->source = surface;
585
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400586 drag->drag_offer.resource.object.interface = &wl_drag_offer_interface;
587 drag->drag_offer.resource.object.implementation =
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500588 (void (**)(void)) &drag_offer_interface;
589
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400590 wl_display_add_global(display, &wl_drag_offer_interface, drag, NULL);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500591
592 target = pick_surface(device, &sx, &sy);
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500593 wl_input_device_set_pointer_focus(device, NULL, time, 0, 0, 0, 0);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500594 wl_drag_set_pointer_focus(drag, &target->surface, time,
595 device->x, device->y, sx, sy);
596}
597
598static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400599drag_destroy(struct wl_client *client, struct wl_resource *resource)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500600{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400601 wl_resource_destroy(resource, wlsc_compositor_get_time());
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500602}
603
604static const struct wl_drag_interface drag_interface = {
605 drag_offer,
606 drag_activate,
607 drag_destroy,
608};
609
610static void
611drag_handle_surface_destroy(struct wl_listener *listener,
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200612 struct wl_resource *resource, uint32_t time)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500613{
614 struct wl_drag *drag =
615 container_of(listener, struct wl_drag, drag_focus_listener);
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200616 struct wl_surface *surface = (struct wl_surface *) resource;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500617
618 if (drag->drag_focus == surface)
619 wl_drag_set_pointer_focus(drag, NULL, time, 0, 0, 0, 0);
620}
621
622static void
623shell_create_drag(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400624 struct wl_resource *resource, uint32_t id)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500625{
626 struct wl_drag *drag;
627
628 drag = malloc(sizeof *drag);
629 if (drag == NULL) {
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400630 wl_resource_post_no_memory(resource);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500631 return;
632 }
633
634 memset(drag, 0, sizeof *drag);
635 drag->resource.object.id = id;
636 drag->resource.object.interface = &wl_drag_interface;
637 drag->resource.object.implementation =
638 (void (**)(void)) &drag_interface;
639
Pekka Paalanen02ebfb12011-10-24 17:34:53 +0300640 drag->resource.data = drag;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500641 drag->resource.destroy = destroy_drag;
642
643 drag->drag_focus_listener.func = drag_handle_surface_destroy;
644 wl_list_init(&drag->drag_focus_listener.link);
645
646 wl_client_add_resource(client, &drag->resource);
647}
648
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400649static void
650wlsc_selection_set_focus(struct wlsc_shell *shell,
651 struct wl_selection *selection,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500652 struct wl_surface *surface, uint32_t time)
653{
654 char **p, **end;
655
656 if (selection->selection_focus == surface)
657 return;
658
659 if (selection->selection_focus != NULL)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400660 wl_resource_post_event(&selection->selection_offer.resource,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500661 WL_SELECTION_OFFER_KEYBOARD_FOCUS,
662 NULL);
663
664 if (surface) {
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500665
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400666 selection->selection_offer.resource.client = surface->resource.client;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500667 end = selection->types.data + selection->types.size;
668 for (p = selection->types.data; p < end; p++)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400669 wl_resource_post_event(&selection->selection_offer.resource,
670 WL_SELECTION_OFFER_OFFER, *p);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500671
672 wl_list_remove(&selection->selection_focus_listener.link);
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200673 wl_list_insert(surface->resource.destroy_listener_list.prev,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500674 &selection->selection_focus_listener.link);
675
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400676 wl_resource_post_event(&selection->selection_offer.resource,
677 WL_SELECTION_OFFER_KEYBOARD_FOCUS,
678 selection->input_device);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500679 }
680
681 selection->selection_focus = surface;
682
683 wl_list_remove(&selection->selection_focus_listener.link);
684 if (surface)
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200685 wl_list_insert(surface->resource.destroy_listener_list.prev,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500686 &selection->selection_focus_listener.link);
687}
688
689static void
690selection_offer_receive(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400691 struct wl_resource *resource,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500692 const char *mime_type, int fd)
693{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400694 struct wl_selection_offer *offer = resource->data;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500695 struct wl_selection *selection =
696 container_of(offer, struct wl_selection, selection_offer);
697
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400698 wl_resource_post_event(&selection->resource,
699 WL_SELECTION_SEND, mime_type, fd);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500700 close(fd);
701}
702
703static const struct wl_selection_offer_interface selection_offer_interface = {
704 selection_offer_receive
705};
706
707static void
708selection_offer(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400709 struct wl_resource *resource, const char *type)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500710{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400711 struct wl_selection *selection = resource->data;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500712 char **p;
713
714 p = wl_array_add(&selection->types, sizeof *p);
715 if (p)
716 *p = strdup(type);
717 if (!p || !*p)
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400718 wl_resource_post_no_memory(resource);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500719}
720
721static void
722selection_activate(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400723 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400724 struct wl_resource *input_resource, uint32_t time)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500725{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400726 struct wl_selection *selection = resource->data;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400727 struct wlsc_input_device *wd = input_resource->data;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500728 struct wl_display *display = wl_client_get_display (client);
Kristian Høgsberga8873122011-11-23 10:39:34 -0500729 struct wlsc_compositor *compositor = wd->compositor;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500730
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400731 selection->input_device = &wd->input_device;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500732
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400733 selection->selection_offer.resource.object.interface =
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500734 &wl_selection_offer_interface;
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400735 selection->selection_offer.resource.object.implementation =
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500736 (void (**)(void)) &selection_offer_interface;
737
Kristian Høgsbergd9551a32011-08-19 12:07:44 -0400738 wl_display_add_global(display,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400739 &wl_selection_offer_interface, selection, NULL);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500740
741 if (wd->selection) {
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400742 wl_resource_post_event(&wd->selection->resource,
743 WL_SELECTION_CANCELLED);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500744 }
745 wd->selection = selection;
746
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400747 wlsc_selection_set_focus(compositor->shell, selection,
748 wd->input_device.keyboard_focus, time);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500749}
750
751static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400752selection_destroy(struct wl_client *client, struct wl_resource *resource)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500753{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400754 wl_resource_destroy(resource, wlsc_compositor_get_time());
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500755}
756
757static const struct wl_selection_interface selection_interface = {
758 selection_offer,
759 selection_activate,
760 selection_destroy
761};
762
763static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400764destroy_selection(struct wl_resource *resource)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500765{
766 struct wl_selection *selection =
767 container_of(resource, struct wl_selection, resource);
768 struct wlsc_input_device *wd =
769 (struct wlsc_input_device *) selection->input_device;
Kristian Høgsberga8873122011-11-23 10:39:34 -0500770 struct wlsc_compositor *compositor = wd->compositor;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500771
772 if (wd && wd->selection == selection) {
773 wd->selection = NULL;
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400774 wlsc_selection_set_focus(compositor->shell,
775 selection, NULL,
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400776 wlsc_compositor_get_time());
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500777 }
778
779 wl_list_remove(&selection->selection_focus_listener.link);
780 free(selection);
781}
782
783static void
784selection_handle_surface_destroy(struct wl_listener *listener,
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200785 struct wl_resource *resource, uint32_t time)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500786{
787}
788
789static void
790shell_create_selection(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400791 struct wl_resource *resource, uint32_t id)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500792{
793 struct wl_selection *selection;
794
795 selection = malloc(sizeof *selection);
796 if (selection == NULL) {
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400797 wl_resource_post_no_memory(resource);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500798 return;
799 }
800
801 memset(selection, 0, sizeof *selection);
802 selection->resource.object.id = id;
803 selection->resource.object.interface = &wl_selection_interface;
804 selection->resource.object.implementation =
805 (void (**)(void)) &selection_interface;
806
807 selection->client = client;
808 selection->resource.destroy = destroy_selection;
809 selection->selection_focus = NULL;
810
811 selection->selection_focus_listener.func =
812 selection_handle_surface_destroy;
813 wl_list_init(&selection->selection_focus_listener.link);
814
815 wl_client_add_resource(client, &selection->resource);
816}
817
Kristian Høgsberg75840622011-09-06 13:48:16 -0400818static const struct wl_shell_interface shell_interface = {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500819 shell_move,
820 shell_resize,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500821 shell_create_drag,
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400822 shell_create_selection,
823 shell_set_toplevel,
824 shell_set_transient,
825 shell_set_fullscreen
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500826};
827
Kristian Høgsberg07937562011-04-12 17:25:42 -0400828static void
Kristian Høgsberg75840622011-09-06 13:48:16 -0400829handle_background_surface_destroy(struct wl_listener *listener,
830 struct wl_resource *resource, uint32_t time)
831{
832 struct wl_shell *shell =
833 container_of(listener, struct wl_shell, background_listener);
834
835 fprintf(stderr, "background surface gone\n");
836 shell->background = NULL;
837}
838
839static void
840desktop_shell_set_background(struct wl_client *client,
841 struct wl_resource *resource,
842 struct wl_resource *surface_resource)
843{
844 struct wl_shell *shell = resource->data;
845 struct wlsc_surface *surface = surface_resource->data;
846 struct wlsc_output *output =
847 container_of(shell->compositor->output_list.next,
848 struct wlsc_output, link);
Pekka Paalanen57da4a82011-11-23 16:42:16 +0200849 struct shell_surface *priv;
Kristian Høgsberg75840622011-09-06 13:48:16 -0400850
851 shell->background = surface_resource->data;
852 shell->background_listener.func = handle_background_surface_destroy;
853 wl_list_insert(&surface_resource->destroy_listener_list,
854 &shell->background_listener.link);
855
Pekka Paalanen57da4a82011-11-23 16:42:16 +0200856 priv = get_shell_surface(surface);
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500857 priv->type = SHELL_SURFACE_BACKGROUND;
Pekka Paalanen57da4a82011-11-23 16:42:16 +0200858
Kristian Høgsberg75840622011-09-06 13:48:16 -0400859 wl_resource_post_event(resource,
860 DESKTOP_SHELL_CONFIGURE,
861 wlsc_compositor_get_time(), 0, surface,
862 output->current->width,
863 output->current->height);
864}
865
866static void
867handle_panel_surface_destroy(struct wl_listener *listener,
868 struct wl_resource *resource, uint32_t time)
869{
870 struct wl_shell *shell =
871 container_of(listener, struct wl_shell, panel_listener);
872
873 fprintf(stderr, "panel surface gone\n");
874 shell->panel = NULL;
875}
876
877static void
878desktop_shell_set_panel(struct wl_client *client,
879 struct wl_resource *resource,
880 struct wl_resource *surface_resource)
881{
882 struct wl_shell *shell = resource->data;
883 struct wlsc_output *output =
884 container_of(shell->compositor->output_list.next,
885 struct wlsc_output, link);
Pekka Paalanen57da4a82011-11-23 16:42:16 +0200886 struct shell_surface *priv;
Kristian Høgsberg75840622011-09-06 13:48:16 -0400887
888 shell->panel = surface_resource->data;
889
890 shell->panel_listener.func = handle_panel_surface_destroy;
891 wl_list_insert(&surface_resource->destroy_listener_list,
892 &shell->panel_listener.link);
893
Pekka Paalanen57da4a82011-11-23 16:42:16 +0200894 priv = get_shell_surface(shell->panel);
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500895 priv->type = SHELL_SURFACE_PANEL;
Pekka Paalanen57da4a82011-11-23 16:42:16 +0200896
Kristian Høgsberg75840622011-09-06 13:48:16 -0400897 wl_resource_post_event(resource,
898 DESKTOP_SHELL_CONFIGURE,
899 wlsc_compositor_get_time(), 0, surface_resource,
900 output->current->width,
901 output->current->height);
902}
903
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200904static void
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500905handle_lock_surface_destroy(struct wl_listener *listener,
906 struct wl_resource *resource, uint32_t time)
907{
908 struct wl_shell *shell =
Pekka Paalanen2ca86302011-11-16 13:47:35 +0200909 container_of(listener, struct wl_shell, lock_surface_listener);
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500910
911 fprintf(stderr, "lock surface gone\n");
912 shell->lock_surface = NULL;
913}
914
915static void
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200916desktop_shell_set_lock_surface(struct wl_client *client,
917 struct wl_resource *resource,
918 struct wl_resource *surface_resource)
919{
Kristian Høgsbergaf867cc2011-11-15 13:34:49 +0200920 struct wl_shell *shell = resource->data;
Pekka Paalanen57da4a82011-11-23 16:42:16 +0200921 struct shell_surface *priv;
Kristian Høgsbergaf867cc2011-11-15 13:34:49 +0200922
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +0200923 shell->prepare_event_sent = false;
Kristian Høgsbergaf867cc2011-11-15 13:34:49 +0200924
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +0200925 if (!shell->locked)
926 return;
927
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500928 shell->lock_surface = surface_resource->data;
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +0200929
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500930 shell->lock_surface_listener.func = handle_lock_surface_destroy;
931 wl_list_insert(&surface_resource->destroy_listener_list,
932 &shell->lock_surface_listener.link);
Pekka Paalanen57da4a82011-11-23 16:42:16 +0200933
934 priv = get_shell_surface(shell->lock_surface);
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500935 priv->type = SHELL_SURFACE_LOCK;
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +0200936}
937
938static void
939resume_desktop(struct wl_shell *shell)
940{
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500941 struct wlsc_surface *surface;
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +0200942
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500943 wl_list_for_each(surface, &shell->hidden_surface_list, link)
944 wlsc_surface_configure(surface, surface->x, surface->y,
945 surface->width, surface->height);
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +0200946
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -0500947 wl_list_insert_list(shell->background->link.prev,
948 &shell->hidden_surface_list);
949 wl_list_init(&shell->hidden_surface_list);
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +0200950
951 shell->locked = false;
952 wlsc_compositor_repick(shell->compositor);
Kristian Høgsbergaf867cc2011-11-15 13:34:49 +0200953 wlsc_compositor_wake(shell->compositor);
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200954}
955
956static void
957desktop_shell_unlock(struct wl_client *client,
958 struct wl_resource *resource)
959{
960 struct wl_shell *shell = resource->data;
961
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200962 shell->prepare_event_sent = false;
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +0200963
964 if (shell->locked)
965 resume_desktop(shell);
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200966}
967
Kristian Høgsberg75840622011-09-06 13:48:16 -0400968static const struct desktop_shell_interface desktop_shell_implementation = {
969 desktop_shell_set_background,
Pekka Paalanen9ef3e012011-11-15 13:34:48 +0200970 desktop_shell_set_panel,
971 desktop_shell_set_lock_surface,
972 desktop_shell_unlock
Kristian Høgsberg75840622011-09-06 13:48:16 -0400973};
974
975static void
Kristian Høgsberg07937562011-04-12 17:25:42 -0400976move_binding(struct wl_input_device *device, uint32_t time,
977 uint32_t key, uint32_t button, uint32_t state, void *data)
978{
Kristian Høgsberg75840622011-09-06 13:48:16 -0400979 struct wl_shell *shell = data;
Kristian Høgsberg07937562011-04-12 17:25:42 -0400980 struct wlsc_surface *surface =
981 (struct wlsc_surface *) device->pointer_focus;
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500982 struct shell_surface *priv;
983
984 priv = get_shell_surface(surface);
Kristian Høgsberg07937562011-04-12 17:25:42 -0400985
Kristian Høgsberga4a42f02011-09-08 16:56:57 -0400986 if (surface == NULL ||
Kristian Høgsbergd2abb832011-11-23 10:52:40 -0500987 priv->type == SHELL_SURFACE_FULLSCREEN)
Kristian Høgsberg10f097e2011-04-13 11:52:54 -0400988 return;
Kristian Høgsberg75840622011-09-06 13:48:16 -0400989 if (surface == shell->panel)
990 return;
991 if (surface == shell->background)
992 return;
Kristian Høgsberg10f097e2011-04-13 11:52:54 -0400993
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400994 wlsc_surface_move(surface, (struct wlsc_input_device *) device, time);
Kristian Høgsberg07937562011-04-12 17:25:42 -0400995}
996
997static void
998resize_binding(struct wl_input_device *device, uint32_t time,
999 uint32_t key, uint32_t button, uint32_t state, void *data)
1000{
Kristian Høgsberg75840622011-09-06 13:48:16 -04001001 struct wl_shell *shell = data;
Kristian Høgsberg07937562011-04-12 17:25:42 -04001002 struct wlsc_surface *surface =
1003 (struct wlsc_surface *) device->pointer_focus;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -04001004 struct wl_resource *resource;
Kristian Høgsberg07937562011-04-12 17:25:42 -04001005 uint32_t edges = 0;
1006 int32_t x, y;
Kristian Høgsbergd2abb832011-11-23 10:52:40 -05001007 struct shell_surface *priv;
1008
1009 priv = get_shell_surface(surface);
Kristian Høgsberg07937562011-04-12 17:25:42 -04001010
Kristian Høgsberga4a42f02011-09-08 16:56:57 -04001011 if (surface == NULL ||
Kristian Høgsbergd2abb832011-11-23 10:52:40 -05001012 priv->type == SHELL_SURFACE_FULLSCREEN)
Kristian Høgsberg75840622011-09-06 13:48:16 -04001013 if (surface == shell->panel)
1014 return;
1015 if (surface == shell->background)
1016 return;
Kristian Høgsberg10f097e2011-04-13 11:52:54 -04001017
Kristian Høgsberg07937562011-04-12 17:25:42 -04001018 x = device->grab_x - surface->x;
1019 y = device->grab_y - surface->y;
1020
1021 if (x < surface->width / 3)
1022 edges |= WL_SHELL_RESIZE_LEFT;
1023 else if (x < 2 * surface->width / 3)
1024 edges |= 0;
1025 else
1026 edges |= WL_SHELL_RESIZE_RIGHT;
1027
1028 if (y < surface->height / 3)
1029 edges |= WL_SHELL_RESIZE_TOP;
1030 else if (y < 2 * surface->height / 3)
1031 edges |= 0;
1032 else
1033 edges |= WL_SHELL_RESIZE_BOTTOM;
1034
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -04001035 resource = /* Find shell resource for surface client */ 0;
1036
1037 /* ... or use wl_shell_surface */
1038
1039 wlsc_surface_resize(surface, (struct wlsc_input_device *) device,
1040 time, edges, resource);
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04001041}
1042
1043static void
Kristian Høgsberg75840622011-09-06 13:48:16 -04001044activate(struct wlsc_shell *base, struct wlsc_surface *es,
1045 struct wlsc_input_device *device, uint32_t time)
1046{
1047 struct wl_shell *shell = container_of(base, struct wl_shell, shell);
1048 struct wlsc_compositor *compositor = shell->compositor;
Pekka Paalanen57da4a82011-11-23 16:42:16 +02001049 struct shell_surface *priv;
1050
1051 priv = get_shell_surface(es);
Kristian Høgsberg75840622011-09-06 13:48:16 -04001052
1053 wlsc_surface_activate(es, device, time);
1054
Kristian Høgsbergd6e55252011-10-11 23:41:17 -04001055 if (compositor->wxs)
1056 wlsc_xserver_surface_activate(es);
1057
Kristian Høgsbergd2abb832011-11-23 10:52:40 -05001058 switch (priv->type) {
Pekka Paalanen57da4a82011-11-23 16:42:16 +02001059 case SHELL_SURFACE_BACKGROUND:
1060 /* put background back to bottom */
Kristian Høgsberg75840622011-09-06 13:48:16 -04001061 wl_list_remove(&es->link);
1062 wl_list_insert(compositor->surface_list.prev, &es->link);
Pekka Paalanen57da4a82011-11-23 16:42:16 +02001063 break;
1064 case SHELL_SURFACE_PANEL:
1065 /* already put on top */
1066 break;
1067 default:
1068 if (shell->panel && !shell->locked) {
1069 /* bring panel back to top */
1070 wl_list_remove(&shell->panel->link);
1071 wl_list_insert(&compositor->surface_list,
1072 &shell->panel->link);
1073 }
Kristian Høgsberg75840622011-09-06 13:48:16 -04001074 }
1075}
1076
1077static void
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02001078lock(struct wlsc_shell *base)
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04001079{
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02001080 struct wl_shell *shell = container_of(base, struct wl_shell, shell);
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02001081 struct wl_list *surface_list = &shell->compositor->surface_list;
1082 struct wlsc_surface *cur;
1083 struct wlsc_surface *tmp;
Pekka Paalanen57da4a82011-11-23 16:42:16 +02001084 struct shell_surface *priv;
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02001085 struct wlsc_input_device *device;
1086 uint32_t time;
1087
1088 if (shell->locked)
1089 return;
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02001090
1091 shell->locked = true;
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02001092
1093 /* Move all surfaces from compositor's list to our hidden list,
1094 * except the background. This way nothing else can show or
1095 * receive input events while we are locked. */
1096
1097 if (!wl_list_empty(&shell->hidden_surface_list)) {
1098 fprintf(stderr,
1099 "%s: Assertion failed: hidden_surface_list is not empty.\n",
1100 __func__);
1101 }
1102
1103 wl_list_for_each_safe(cur, tmp, surface_list, link) {
1104 /* skip input device sprites, cur->surface is uninitialised */
1105 if (cur->surface.resource.client == NULL)
1106 continue;
1107
Pekka Paalanen57da4a82011-11-23 16:42:16 +02001108 priv = get_shell_surface(cur);
Kristian Høgsbergd2abb832011-11-23 10:52:40 -05001109 if (priv->type == SHELL_SURFACE_BACKGROUND)
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02001110 continue;
1111
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -05001112 cur->output = NULL;
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02001113 wl_list_remove(&cur->link);
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -05001114 wl_list_insert(shell->hidden_surface_list.prev, &cur->link);
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02001115 }
1116
1117 /* reset pointer foci */
1118 wlsc_compositor_repick(shell->compositor);
1119
1120 /* reset keyboard foci */
1121 time = wlsc_compositor_get_time();
1122 wl_list_for_each(device, &shell->compositor->input_device_list, link) {
1123 wl_input_device_set_keyboard_focus(&device->input_device,
1124 NULL, time);
1125 }
1126
1127 /* TODO: disable bindings that should not work while locked. */
1128
1129 /* All this must be undone in resume_desktop(). */
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02001130}
1131
1132static void
1133unlock(struct wlsc_shell *base)
1134{
1135 struct wl_shell *shell = container_of(base, struct wl_shell, shell);
1136
Pekka Paalanend81c2162011-11-16 13:47:34 +02001137 if (!shell->locked || shell->lock_surface) {
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02001138 wlsc_compositor_wake(shell->compositor);
1139 return;
1140 }
1141
1142 /* If desktop-shell client has gone away, unlock immediately. */
1143 if (!shell->child.desktop_shell) {
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02001144 resume_desktop(shell);
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02001145 return;
1146 }
1147
1148 if (shell->prepare_event_sent)
1149 return;
1150
1151 wl_resource_post_event(shell->child.desktop_shell,
1152 DESKTOP_SHELL_PREPARE_LOCK_SURFACE);
1153 shell->prepare_event_sent = true;
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04001154}
1155
1156static void
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -05001157map(struct wlsc_shell *base,
1158 struct wlsc_surface *surface, int32_t width, int32_t height)
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04001159{
Kristian Høgsberg75840622011-09-06 13:48:16 -04001160 struct wl_shell *shell = container_of(base, struct wl_shell, shell);
1161 struct wlsc_compositor *compositor = shell->compositor;
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -05001162 struct wl_list *list;
Pekka Paalanen57da4a82011-11-23 16:42:16 +02001163 struct shell_surface *priv;
1164
1165 priv = get_shell_surface(surface);
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -05001166
1167 if (shell->locked)
1168 list = &shell->hidden_surface_list;
1169 else
1170 list = &compositor->surface_list;
Kristian Høgsberg75840622011-09-06 13:48:16 -04001171
Pekka Paalanend3dd6e12011-11-16 13:47:33 +02001172 /* surface stacking order, see also activate() */
Kristian Høgsbergd2abb832011-11-23 10:52:40 -05001173 switch (priv->type) {
Pekka Paalanen57da4a82011-11-23 16:42:16 +02001174 case SHELL_SURFACE_BACKGROUND:
Pekka Paalanend3dd6e12011-11-16 13:47:33 +02001175 /* background always visible, at the bottom */
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -05001176 wl_list_insert(compositor->surface_list.prev, &surface->link);
Pekka Paalanen57da4a82011-11-23 16:42:16 +02001177 break;
1178 case SHELL_SURFACE_PANEL:
Pekka Paalanend3dd6e12011-11-16 13:47:33 +02001179 /* panel always on top, hidden while locked */
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -05001180 wl_list_insert(list, &surface->link);
Pekka Paalanen57da4a82011-11-23 16:42:16 +02001181 break;
1182 case SHELL_SURFACE_LOCK:
Pekka Paalanend3dd6e12011-11-16 13:47:33 +02001183 /* lock surface always visible, on top */
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -05001184 wl_list_insert(&compositor->surface_list, &surface->link);
Pekka Paalanend3dd6e12011-11-16 13:47:33 +02001185
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -05001186 wlsc_compositor_repick(compositor);
Pekka Paalanen57da4a82011-11-23 16:42:16 +02001187 wlsc_compositor_wake(compositor);
1188 break;
1189 default:
Pekka Paalanend3dd6e12011-11-16 13:47:33 +02001190 /* everything else just below the panel */
Pekka Paalanen57da4a82011-11-23 16:42:16 +02001191 if (shell->panel)
1192 wl_list_insert(&shell->panel->link, &surface->link);
1193 else
1194 wl_list_insert(list, &surface->link);
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02001195 }
1196
Kristian Høgsbergd2abb832011-11-23 10:52:40 -05001197 if (priv->type == SHELL_SURFACE_TOPLEVEL) {
Kristian Høgsberg46770132011-11-09 12:38:53 -05001198 surface->x = 10 + random() % 400;
1199 surface->y = 10 + random() % 400;
1200 }
1201
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -05001202 surface->width = width;
1203 surface->height = height;
Kristian Høgsbergd2abb832011-11-23 10:52:40 -05001204 if (!shell->locked || priv->type == SHELL_SURFACE_LOCK)
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -05001205 wlsc_surface_configure(surface,
1206 surface->x, surface->y, width, height);
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -05001207}
1208
1209static void
1210configure(struct wlsc_shell *shell, struct wlsc_surface *surface,
1211 int32_t x, int32_t y, int32_t width, int32_t height)
1212{
1213 struct wlsc_mode *current;
Kristian Høgsbergd2abb832011-11-23 10:52:40 -05001214 struct shell_surface *priv;
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -05001215
Kristian Høgsbergd2abb832011-11-23 10:52:40 -05001216 priv = get_shell_surface(surface);
1217 switch (priv->type) {
1218 case SHELL_SURFACE_FULLSCREEN:
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -05001219 current = surface->fullscreen_output->current;
1220 x = (current->width - surface->width) / 2;
1221 y = (current->height - surface->height) / 2;
Kristian Høgsbergd2abb832011-11-23 10:52:40 -05001222 break;
1223 default:
1224 break;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -04001225 }
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -05001226
1227 wlsc_surface_configure(surface, x, y, width, height);
Kristian Høgsberg07937562011-04-12 17:25:42 -04001228}
1229
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -04001230static void
Pekka Paalanen6cd281a2011-11-03 14:11:32 +02001231desktop_shell_sigchld(struct wlsc_process *process, int status)
1232{
1233 struct wl_shell *shell =
1234 container_of(process, struct wl_shell, child.process);
1235
1236 shell->child.process.pid = 0;
1237 shell->child.client = NULL; /* already destroyed by wayland */
1238}
1239
1240static int
1241launch_desktop_shell_process(struct wl_shell *shell)
1242{
Kristian Høgsbergc4693c42011-11-14 14:57:17 -05001243 const char *shell_exe = LIBEXECDIR "/wayland-desktop-shell";
Pekka Paalanen6cd281a2011-11-03 14:11:32 +02001244 struct wlsc_compositor *compositor = shell->compositor;
1245 char s[32];
1246 int sv[2], flags;
1247
1248 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sv) < 0) {
1249 fprintf(stderr, "socketpair failed\n");
1250 return -1;
1251 }
1252
1253 shell->child.process.pid = fork();
1254 shell->child.process.cleanup = desktop_shell_sigchld;
1255
1256 switch (shell->child.process.pid) {
1257 case 0:
1258 /* SOCK_CLOEXEC closes both ends, so we need to unset
1259 * the flag on the client fd. */
1260 flags = fcntl(sv[1], F_GETFD);
1261 if (flags != -1)
1262 fcntl(sv[1], F_SETFD, flags & ~FD_CLOEXEC);
1263
1264 snprintf(s, sizeof s, "%d", sv[1]);
1265 setenv("WAYLAND_SOCKET", s, 1);
1266 if (execl(shell_exe, shell_exe, NULL) < 0)
1267 fprintf(stderr, "%s: running '%s' failed: %m\n",
1268 __func__, shell_exe);
1269 exit(-1);
1270
1271 default:
1272 close(sv[1]);
1273 shell->child.client =
1274 wl_client_create(compositor->wl_display, sv[0]);
1275 wlsc_watch_process(&shell->child.process);
1276 break;
1277
1278 case -1:
1279 fprintf(stderr, "%s: fork failed: %m\n", __func__);
1280 return -1;
1281 }
1282 return 0;
1283}
1284
1285static void
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -04001286bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
1287{
1288 struct wl_shell *shell = data;
1289
1290 wl_client_add_object(client, &wl_shell_interface,
1291 &shell_interface, id, shell);
1292}
1293
Kristian Høgsberg75840622011-09-06 13:48:16 -04001294static void
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02001295unbind_desktop_shell(struct wl_resource *resource)
1296{
1297 struct wl_shell *shell = resource->data;
Kristian Høgsberg1ec0c312011-11-15 16:39:55 -05001298
1299 if (shell->locked)
1300 resume_desktop(shell);
1301
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02001302 shell->child.desktop_shell = NULL;
1303 shell->prepare_event_sent = false;
1304 free(resource);
1305}
1306
1307static void
Kristian Høgsberg75840622011-09-06 13:48:16 -04001308bind_desktop_shell(struct wl_client *client,
1309 void *data, uint32_t version, uint32_t id)
1310{
1311 struct wl_shell *shell = data;
Pekka Paalanenbbe60522011-11-03 14:11:33 +02001312 struct wl_resource *resource;
Kristian Høgsberg75840622011-09-06 13:48:16 -04001313
Pekka Paalanenbbe60522011-11-03 14:11:33 +02001314 resource = wl_client_add_object(client, &desktop_shell_interface,
1315 &desktop_shell_implementation,
1316 id, shell);
1317
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02001318 if (client == shell->child.client) {
1319 resource->destroy = unbind_desktop_shell;
1320 shell->child.desktop_shell = resource;
Pekka Paalanenbbe60522011-11-03 14:11:33 +02001321 return;
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02001322 }
Pekka Paalanenbbe60522011-11-03 14:11:33 +02001323
1324 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
1325 "permission to bind desktop_shell denied");
1326 wl_resource_destroy(resource, 0);
Kristian Høgsberg75840622011-09-06 13:48:16 -04001327}
1328
Kristian Høgsberg6c709a32011-05-06 14:52:41 -04001329int
1330shell_init(struct wlsc_compositor *ec);
1331
Kristian Høgsberg1c562182011-05-02 22:09:20 -04001332WL_EXPORT int
1333shell_init(struct wlsc_compositor *ec)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -05001334{
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04001335 struct wl_shell *shell;
1336
1337 shell = malloc(sizeof *shell);
1338 if (shell == NULL)
1339 return -1;
1340
Kristian Høgsbergf0d91162011-10-11 22:44:23 -04001341 memset(shell, 0, sizeof *shell);
Kristian Høgsberg75840622011-09-06 13:48:16 -04001342 shell->compositor = ec;
1343 shell->shell.activate = activate;
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04001344 shell->shell.lock = lock;
Pekka Paalanen9ef3e012011-11-15 13:34:48 +02001345 shell->shell.unlock = unlock;
Kristian Høgsberg32e24cc2011-11-09 12:07:35 -05001346 shell->shell.map = map;
1347 shell->shell.configure = configure;
Kristian Høgsberg1c562182011-05-02 22:09:20 -04001348 shell->shell.set_selection_focus = wlsc_selection_set_focus;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -05001349
Pekka Paalanenf0fc70d2011-11-15 13:34:54 +02001350 wl_list_init(&shell->hidden_surface_list);
1351
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}