blob: ed2637df16d8efe87716f521ff0c20d392de7c42 [file] [log] [blame]
Kristian Høgsberg4cca3492011-01-18 07:53:49 -05001/*
2 * Copyright © 2010 Intel Corporation
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#include <stdlib.h>
Kristian Høgsberg75840622011-09-06 13:48:16 -040024#include <stdio.h>
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050025#include <string.h>
26#include <unistd.h>
Kristian Høgsberg07937562011-04-12 17:25:42 -040027#include <linux/input.h>
Pekka Paalanen6cd281a2011-11-03 14:11:32 +020028#include <sys/types.h>
29#include <sys/socket.h>
30#include <fcntl.h>
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050031
32#include "wayland-server.h"
33#include "compositor.h"
Kristian Høgsberg75840622011-09-06 13:48:16 -040034#include "desktop-shell-server-protocol.h"
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050035
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -040036struct wl_shell {
Kristian Høgsberg75840622011-09-06 13:48:16 -040037 struct wlsc_compositor *compositor;
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -040038 struct wlsc_shell shell;
Kristian Høgsberg75840622011-09-06 13:48:16 -040039 struct wlsc_surface *panel;
40 struct wl_listener panel_listener;
41 struct wlsc_surface *background;
42 struct wl_listener background_listener;
Pekka Paalanen6cd281a2011-11-03 14:11:32 +020043
44 struct {
45 struct wlsc_process process;
46 struct wl_client *client;
47 } child;
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -040048};
49
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050050struct wlsc_move_grab {
51 struct wl_grab grab;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -050052 struct wlsc_surface *surface;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050053 int32_t dx, dy;
54};
55
56static void
57move_grab_motion(struct wl_grab *grab,
58 uint32_t time, int32_t x, int32_t y)
59{
60 struct wlsc_move_grab *move = (struct wlsc_move_grab *) grab;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -050061 struct wlsc_surface *es = move->surface;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050062
Kristian Høgsberga691aee2011-06-23 21:43:50 -040063 wlsc_surface_configure(es, x + move->dx, y + move->dy,
64 es->width, es->height);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050065}
66
67static void
68move_grab_button(struct wl_grab *grab,
69 uint32_t time, int32_t button, int32_t state)
70{
71}
72
73static void
74move_grab_end(struct wl_grab *grab, uint32_t time)
75{
76 free(grab);
77}
78
79static const struct wl_grab_interface move_grab_interface = {
80 move_grab_motion,
81 move_grab_button,
82 move_grab_end
83};
84
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -040085static int
86wlsc_surface_move(struct wlsc_surface *es,
87 struct wlsc_input_device *wd, uint32_t time)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050088{
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050089 struct wlsc_move_grab *move;
90
91 move = malloc(sizeof *move);
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -040092 if (!move)
93 return -1;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050094
95 move->grab.interface = &move_grab_interface;
96 move->dx = es->x - wd->input_device.grab_x;
97 move->dy = es->y - wd->input_device.grab_y;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -050098 move->surface = es;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050099
100 if (wl_input_device_update_grab(&wd->input_device,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400101 &move->grab, &es->surface, time) < 0)
102 return 0;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500103
104 wlsc_input_device_set_pointer_image(wd, WLSC_POINTER_DRAGGING);
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400105 wl_input_device_set_pointer_focus(&wd->input_device,
106 NULL, time, 0, 0, 0, 0);
107
108 return 0;
109}
110
111static void
112shell_move(struct wl_client *client, struct wl_resource *resource,
113 struct wl_resource *surface_resource,
114 struct wl_resource *input_resource, uint32_t time)
115{
116 struct wlsc_input_device *wd = input_resource->data;
117 struct wlsc_surface *es = surface_resource->data;
118
119 if (wlsc_surface_move(es, wd, time) < 0)
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400120 wl_resource_post_no_memory(resource);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500121}
122
123struct wlsc_resize_grab {
124 struct wl_grab grab;
125 uint32_t edges;
126 int32_t dx, dy, width, height;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500127 struct wlsc_surface *surface;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400128 struct wl_resource *resource;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500129};
130
131static void
132resize_grab_motion(struct wl_grab *grab,
133 uint32_t time, int32_t x, int32_t y)
134{
135 struct wlsc_resize_grab *resize = (struct wlsc_resize_grab *) grab;
136 struct wl_input_device *device = grab->input_device;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500137 struct wl_surface *surface = &resize->surface->surface;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500138 int32_t width, height;
139
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500140 if (resize->edges & WL_SHELL_RESIZE_LEFT) {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500141 width = device->grab_x - x + resize->width;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500142 } else if (resize->edges & WL_SHELL_RESIZE_RIGHT) {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500143 width = x - device->grab_x + resize->width;
144 } else {
145 width = resize->width;
146 }
147
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500148 if (resize->edges & WL_SHELL_RESIZE_TOP) {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500149 height = device->grab_y - y + resize->height;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500150 } else if (resize->edges & WL_SHELL_RESIZE_BOTTOM) {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500151 height = y - device->grab_y + resize->height;
152 } else {
153 height = resize->height;
154 }
155
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400156 wl_resource_post_event(resize->resource,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400157 WL_SHELL_CONFIGURE, time, resize->edges,
158 surface, width, height);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500159}
160
161static void
162resize_grab_button(struct wl_grab *grab,
163 uint32_t time, int32_t button, int32_t state)
164{
165}
166
167static void
168resize_grab_end(struct wl_grab *grab, uint32_t time)
169{
170 free(grab);
171}
172
173static const struct wl_grab_interface resize_grab_interface = {
174 resize_grab_motion,
175 resize_grab_button,
176 resize_grab_end
177};
178
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400179static int
180wlsc_surface_resize(struct wlsc_surface *es,
181 struct wlsc_input_device *wd,
182 uint32_t time, uint32_t edges,
183 struct wl_resource *resource)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500184{
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500185 struct wlsc_resize_grab *resize;
186 enum wlsc_pointer_type pointer = WLSC_POINTER_LEFT_PTR;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500187
Kristian Høgsberg0ce24572011-01-28 15:18:33 -0500188 /* FIXME: Reject if fullscreen */
189
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500190 resize = malloc(sizeof *resize);
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400191 if (!resize)
192 return -1;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500193
194 resize->grab.interface = &resize_grab_interface;
195 resize->edges = edges;
196 resize->dx = es->x - wd->input_device.grab_x;
197 resize->dy = es->y - wd->input_device.grab_y;
198 resize->width = es->width;
199 resize->height = es->height;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500200 resize->surface = es;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400201 resize->resource = resource;
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400202
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500203 if (edges == 0 || edges > 15 ||
204 (edges & 3) == 3 || (edges & 12) == 12)
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400205 return 0;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500206
207 switch (edges) {
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500208 case WL_SHELL_RESIZE_TOP:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500209 pointer = WLSC_POINTER_TOP;
210 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500211 case WL_SHELL_RESIZE_BOTTOM:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500212 pointer = WLSC_POINTER_BOTTOM;
213 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500214 case WL_SHELL_RESIZE_LEFT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500215 pointer = WLSC_POINTER_LEFT;
216 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500217 case WL_SHELL_RESIZE_TOP_LEFT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500218 pointer = WLSC_POINTER_TOP_LEFT;
219 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500220 case WL_SHELL_RESIZE_BOTTOM_LEFT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500221 pointer = WLSC_POINTER_BOTTOM_LEFT;
222 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500223 case WL_SHELL_RESIZE_RIGHT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500224 pointer = WLSC_POINTER_RIGHT;
225 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500226 case WL_SHELL_RESIZE_TOP_RIGHT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500227 pointer = WLSC_POINTER_TOP_RIGHT;
228 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500229 case WL_SHELL_RESIZE_BOTTOM_RIGHT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500230 pointer = WLSC_POINTER_BOTTOM_RIGHT;
231 break;
232 }
233
234 if (wl_input_device_update_grab(&wd->input_device,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400235 &resize->grab, &es->surface, time) < 0)
236 return 0;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500237
238 wlsc_input_device_set_pointer_image(wd, pointer);
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400239 wl_input_device_set_pointer_focus(&wd->input_device,
240 NULL, time, 0, 0, 0, 0);
241
242 return 0;
243}
244
245static void
246shell_resize(struct wl_client *client, struct wl_resource *resource,
247 struct wl_resource *surface_resource,
248 struct wl_resource *input_resource, uint32_t time, uint32_t edges)
249{
250 struct wlsc_input_device *wd = input_resource->data;
251 struct wlsc_surface *es = surface_resource->data;
252
253 /* FIXME: Reject if fullscreen */
254
255 if (wlsc_surface_resize(es, wd, time, edges, resource) < 0)
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400256 wl_resource_post_no_memory(resource);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500257}
258
259static void
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400260shell_set_toplevel(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400261 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400262 struct wl_resource *surface_resource)
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400263
264{
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400265 struct wlsc_surface *es = surface_resource->data;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400266 struct wlsc_compositor *ec = es->compositor;
267
268 if (es->map_type == WLSC_SURFACE_MAP_FULLSCREEN) {
269 es->x = es->saved_x;
270 es->y = es->saved_y;
271 } else if (es->map_type == WLSC_SURFACE_MAP_UNMAPPED) {
272 es->x = 10 + random() % 400;
273 es->y = 10 + random() % 400;
274 /* assign to first output */
275 es->output = container_of(ec->output_list.next,
276 struct wlsc_output, link);
277 }
278
279 wlsc_surface_damage(es);
280 es->map_type = WLSC_SURFACE_MAP_TOPLEVEL;
281 es->fullscreen_output = NULL;
282}
283
284static void
285shell_set_transient(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400286 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400287 struct wl_resource *surface_resource,
288 struct wl_resource *parent_resource,
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400289 int x, int y, uint32_t flags)
290{
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400291 struct wlsc_surface *es = surface_resource->data;
292 struct wlsc_surface *pes = parent_resource->data;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400293
294 /* assign to parents output */
295 es->output = pes->output;
296
297 es->x = pes->x + x;
298 es->y = pes->y + y;
299
300 wlsc_surface_damage(es);
301 es->map_type = WLSC_SURFACE_MAP_TRANSIENT;
302}
303
304static void
305shell_set_fullscreen(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400306 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400307 struct wl_resource *surface_resource)
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400308
309{
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400310 struct wlsc_surface *es = surface_resource->data;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400311 struct wlsc_output *output;
312
313 /* FIXME: Fullscreen on first output */
314 /* FIXME: Handle output going away */
315 output = container_of(es->compositor->output_list.next,
316 struct wlsc_output, link);
317 es->output = output;
318
319 es->saved_x = es->x;
320 es->saved_y = es->y;
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400321 es->x = (output->current->width - es->width) / 2;
322 es->y = (output->current->height - es->height) / 2;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400323 es->fullscreen_output = output;
324 wlsc_surface_damage(es);
325 es->map_type = WLSC_SURFACE_MAP_FULLSCREEN;
326}
327
328static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400329destroy_drag(struct wl_resource *resource)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500330{
331 struct wl_drag *drag =
332 container_of(resource, struct wl_drag, resource);
333
334 wl_list_remove(&drag->drag_focus_listener.link);
335 if (drag->grab.input_device)
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400336 wl_input_device_end_grab(drag->grab.input_device,
337 wlsc_compositor_get_time());
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500338
339 free(drag);
340}
341
342
343static void
344wl_drag_set_pointer_focus(struct wl_drag *drag,
345 struct wl_surface *surface, uint32_t time,
346 int32_t x, int32_t y, int32_t sx, int32_t sy)
347{
348 char **p, **end;
349
350 if (drag->drag_focus == surface)
351 return;
352
353 if (drag->drag_focus &&
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400354 (!surface ||
355 drag->drag_focus->resource.client != surface->resource.client))
356 wl_resource_post_event(&drag->drag_offer.resource,
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500357 WL_DRAG_OFFER_POINTER_FOCUS,
358 time, NULL, 0, 0, 0, 0);
359
360 if (surface &&
361 (!drag->drag_focus ||
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400362 drag->drag_focus->resource.client != surface->resource.client)) {
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400363
364 drag->drag_offer.resource.client = surface->resource.client;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500365 end = drag->types.data + drag->types.size;
366 for (p = drag->types.data; p < end; p++)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400367 wl_resource_post_event(&drag->drag_offer.resource,
368 WL_DRAG_OFFER_OFFER, *p);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500369 }
370
371 if (surface) {
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400372 wl_resource_post_event(&drag->drag_offer.resource,
373 WL_DRAG_OFFER_POINTER_FOCUS,
374 time, surface,
375 x, y, sx, sy);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500376
377 }
378
379 drag->drag_focus = surface;
380 drag->pointer_focus_time = time;
381 drag->target = NULL;
382
383 wl_list_remove(&drag->drag_focus_listener.link);
384 if (surface)
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200385 wl_list_insert(surface->resource.destroy_listener_list.prev,
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500386 &drag->drag_focus_listener.link);
387}
388
389static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400390drag_offer_accept(struct wl_client *client, struct wl_resource *resource,
391 uint32_t time, const char *type)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500392{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400393 struct wl_drag_offer *offer = resource->data;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500394 struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer);
395 char **p, **end;
396
397 /* If the client responds to drag pointer_focus or motion
398 * events after the pointer has left the surface, we just
399 * discard the accept requests. The drag source just won't
400 * get the corresponding 'target' events and eventually the
401 * next surface/root will start sending events. */
402 if (time < drag->pointer_focus_time)
403 return;
404
405 drag->target = client;
406 drag->type = NULL;
407 end = drag->types.data + drag->types.size;
408 for (p = drag->types.data; p < end; p++)
409 if (type && strcmp(*p, type) == 0)
410 drag->type = *p;
411
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400412 wl_resource_post_event(&drag->resource, WL_DRAG_TARGET, drag->type);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500413}
414
415static void
416drag_offer_receive(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400417 struct wl_resource *resource, int fd)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500418{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400419 struct wl_drag_offer *offer = resource->data;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500420 struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer);
421
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400422 wl_resource_post_event(&drag->resource, WL_DRAG_FINISH, fd);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500423 close(fd);
424}
425
426static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400427drag_offer_reject(struct wl_client *client, struct wl_resource *resource)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500428{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400429 struct wl_drag_offer *offer = resource->data;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500430 struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer);
431
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400432 wl_resource_post_event(&drag->resource, WL_DRAG_REJECT);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500433}
434
435static const struct wl_drag_offer_interface drag_offer_interface = {
436 drag_offer_accept,
437 drag_offer_receive,
438 drag_offer_reject
439};
440
441static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400442drag_offer(struct wl_client *client,
443 struct wl_resource *resource, const char *type)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500444{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400445 struct wl_drag *drag = resource->data;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500446 char **p;
447
448 p = wl_array_add(&drag->types, sizeof *p);
449 if (p)
450 *p = strdup(type);
451 if (!p || !*p)
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400452 wl_resource_post_no_memory(resource);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500453}
454
455static void
456drag_grab_motion(struct wl_grab *grab,
457 uint32_t time, int32_t x, int32_t y)
458{
459 struct wl_drag *drag = container_of(grab, struct wl_drag, grab);
460 struct wlsc_surface *es;
461 int32_t sx, sy;
462
463 es = pick_surface(grab->input_device, &sx, &sy);
464 wl_drag_set_pointer_focus(drag, &es->surface, time, x, y, sx, sy);
465 if (es)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400466 wl_resource_post_event(&drag->drag_offer.resource,
467 WL_DRAG_OFFER_MOTION,
468 time, x, y, sx, sy);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500469}
470
471static void
472drag_grab_button(struct wl_grab *grab,
473 uint32_t time, int32_t button, int32_t state)
474{
475}
476
477static void
478drag_grab_end(struct wl_grab *grab, uint32_t time)
479{
480 struct wl_drag *drag = container_of(grab, struct wl_drag, grab);
481
482 if (drag->target)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400483 wl_resource_post_event(&drag->drag_offer.resource,
484 WL_DRAG_OFFER_DROP);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500485
486 wl_drag_set_pointer_focus(drag, NULL, time, 0, 0, 0, 0);
487}
488
489static const struct wl_grab_interface drag_grab_interface = {
490 drag_grab_motion,
491 drag_grab_button,
492 drag_grab_end
493};
494
495static void
496drag_activate(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400497 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400498 struct wl_resource *surface_resource,
499 struct wl_resource *device_resource, uint32_t time)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500500{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400501 struct wl_drag *drag = resource->data;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400502 struct wl_surface *surface = surface_resource->data;
503 struct wl_input_device *device = device_resource->data;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500504 struct wl_display *display = wl_client_get_display (client);
505 struct wlsc_surface *target;
506 int32_t sx, sy;
507
508 if (wl_input_device_update_grab(device,
509 &drag->grab, surface, time) < 0)
510 return;
511
512 drag->grab.interface = &drag_grab_interface;
513
514 drag->source = surface;
515
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400516 drag->drag_offer.resource.object.interface = &wl_drag_offer_interface;
517 drag->drag_offer.resource.object.implementation =
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500518 (void (**)(void)) &drag_offer_interface;
519
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400520 wl_display_add_global(display, &wl_drag_offer_interface, drag, NULL);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500521
522 target = pick_surface(device, &sx, &sy);
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500523 wl_input_device_set_pointer_focus(device, NULL, time, 0, 0, 0, 0);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500524 wl_drag_set_pointer_focus(drag, &target->surface, time,
525 device->x, device->y, sx, sy);
526}
527
528static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400529drag_destroy(struct wl_client *client, struct wl_resource *resource)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500530{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400531 wl_resource_destroy(resource, wlsc_compositor_get_time());
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500532}
533
534static const struct wl_drag_interface drag_interface = {
535 drag_offer,
536 drag_activate,
537 drag_destroy,
538};
539
540static void
541drag_handle_surface_destroy(struct wl_listener *listener,
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200542 struct wl_resource *resource, uint32_t time)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500543{
544 struct wl_drag *drag =
545 container_of(listener, struct wl_drag, drag_focus_listener);
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200546 struct wl_surface *surface = (struct wl_surface *) resource;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500547
548 if (drag->drag_focus == surface)
549 wl_drag_set_pointer_focus(drag, NULL, time, 0, 0, 0, 0);
550}
551
552static void
553shell_create_drag(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400554 struct wl_resource *resource, uint32_t id)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500555{
556 struct wl_drag *drag;
557
558 drag = malloc(sizeof *drag);
559 if (drag == NULL) {
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400560 wl_resource_post_no_memory(resource);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500561 return;
562 }
563
564 memset(drag, 0, sizeof *drag);
565 drag->resource.object.id = id;
566 drag->resource.object.interface = &wl_drag_interface;
567 drag->resource.object.implementation =
568 (void (**)(void)) &drag_interface;
569
Pekka Paalanen02ebfb12011-10-24 17:34:53 +0300570 drag->resource.data = drag;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500571 drag->resource.destroy = destroy_drag;
572
573 drag->drag_focus_listener.func = drag_handle_surface_destroy;
574 wl_list_init(&drag->drag_focus_listener.link);
575
576 wl_client_add_resource(client, &drag->resource);
577}
578
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400579static void
580wlsc_selection_set_focus(struct wlsc_shell *shell,
581 struct wl_selection *selection,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500582 struct wl_surface *surface, uint32_t time)
583{
584 char **p, **end;
585
586 if (selection->selection_focus == surface)
587 return;
588
589 if (selection->selection_focus != NULL)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400590 wl_resource_post_event(&selection->selection_offer.resource,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500591 WL_SELECTION_OFFER_KEYBOARD_FOCUS,
592 NULL);
593
594 if (surface) {
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500595
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400596 selection->selection_offer.resource.client = surface->resource.client;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500597 end = selection->types.data + selection->types.size;
598 for (p = selection->types.data; p < end; p++)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400599 wl_resource_post_event(&selection->selection_offer.resource,
600 WL_SELECTION_OFFER_OFFER, *p);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500601
602 wl_list_remove(&selection->selection_focus_listener.link);
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200603 wl_list_insert(surface->resource.destroy_listener_list.prev,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500604 &selection->selection_focus_listener.link);
605
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400606 wl_resource_post_event(&selection->selection_offer.resource,
607 WL_SELECTION_OFFER_KEYBOARD_FOCUS,
608 selection->input_device);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500609 }
610
611 selection->selection_focus = surface;
612
613 wl_list_remove(&selection->selection_focus_listener.link);
614 if (surface)
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200615 wl_list_insert(surface->resource.destroy_listener_list.prev,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500616 &selection->selection_focus_listener.link);
617}
618
619static void
620selection_offer_receive(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400621 struct wl_resource *resource,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500622 const char *mime_type, int fd)
623{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400624 struct wl_selection_offer *offer = resource->data;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500625 struct wl_selection *selection =
626 container_of(offer, struct wl_selection, selection_offer);
627
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400628 wl_resource_post_event(&selection->resource,
629 WL_SELECTION_SEND, mime_type, fd);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500630 close(fd);
631}
632
633static const struct wl_selection_offer_interface selection_offer_interface = {
634 selection_offer_receive
635};
636
637static void
638selection_offer(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400639 struct wl_resource *resource, const char *type)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500640{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400641 struct wl_selection *selection = resource->data;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500642 char **p;
643
644 p = wl_array_add(&selection->types, sizeof *p);
645 if (p)
646 *p = strdup(type);
647 if (!p || !*p)
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400648 wl_resource_post_no_memory(resource);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500649}
650
651static void
652selection_activate(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400653 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400654 struct wl_resource *input_resource, uint32_t time)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500655{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400656 struct wl_selection *selection = resource->data;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400657 struct wlsc_input_device *wd = input_resource->data;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500658 struct wl_display *display = wl_client_get_display (client);
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400659 struct wlsc_compositor *compositor =
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400660 (struct wlsc_compositor *) wd->input_device.compositor;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500661
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400662 selection->input_device = &wd->input_device;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500663
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400664 selection->selection_offer.resource.object.interface =
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500665 &wl_selection_offer_interface;
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400666 selection->selection_offer.resource.object.implementation =
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500667 (void (**)(void)) &selection_offer_interface;
668
Kristian Høgsbergd9551a32011-08-19 12:07:44 -0400669 wl_display_add_global(display,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400670 &wl_selection_offer_interface, selection, NULL);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500671
672 if (wd->selection) {
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400673 wl_resource_post_event(&wd->selection->resource,
674 WL_SELECTION_CANCELLED);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500675 }
676 wd->selection = selection;
677
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400678 wlsc_selection_set_focus(compositor->shell, selection,
679 wd->input_device.keyboard_focus, time);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500680}
681
682static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400683selection_destroy(struct wl_client *client, struct wl_resource *resource)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500684{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400685 wl_resource_destroy(resource, wlsc_compositor_get_time());
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500686}
687
688static const struct wl_selection_interface selection_interface = {
689 selection_offer,
690 selection_activate,
691 selection_destroy
692};
693
694static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400695destroy_selection(struct wl_resource *resource)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500696{
697 struct wl_selection *selection =
698 container_of(resource, struct wl_selection, resource);
699 struct wlsc_input_device *wd =
700 (struct wlsc_input_device *) selection->input_device;
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400701 struct wlsc_compositor *compositor =
702 (struct wlsc_compositor *) wd->input_device.compositor;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500703
704 if (wd && wd->selection == selection) {
705 wd->selection = NULL;
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400706 wlsc_selection_set_focus(compositor->shell,
707 selection, NULL,
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400708 wlsc_compositor_get_time());
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500709 }
710
711 wl_list_remove(&selection->selection_focus_listener.link);
712 free(selection);
713}
714
715static void
716selection_handle_surface_destroy(struct wl_listener *listener,
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200717 struct wl_resource *resource, uint32_t time)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500718{
719}
720
721static void
722shell_create_selection(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400723 struct wl_resource *resource, uint32_t id)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500724{
725 struct wl_selection *selection;
726
727 selection = malloc(sizeof *selection);
728 if (selection == NULL) {
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400729 wl_resource_post_no_memory(resource);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500730 return;
731 }
732
733 memset(selection, 0, sizeof *selection);
734 selection->resource.object.id = id;
735 selection->resource.object.interface = &wl_selection_interface;
736 selection->resource.object.implementation =
737 (void (**)(void)) &selection_interface;
738
739 selection->client = client;
740 selection->resource.destroy = destroy_selection;
741 selection->selection_focus = NULL;
742
743 selection->selection_focus_listener.func =
744 selection_handle_surface_destroy;
745 wl_list_init(&selection->selection_focus_listener.link);
746
747 wl_client_add_resource(client, &selection->resource);
748}
749
Kristian Høgsberg75840622011-09-06 13:48:16 -0400750static const struct wl_shell_interface shell_interface = {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500751 shell_move,
752 shell_resize,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500753 shell_create_drag,
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400754 shell_create_selection,
755 shell_set_toplevel,
756 shell_set_transient,
757 shell_set_fullscreen
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500758};
759
Kristian Høgsberg07937562011-04-12 17:25:42 -0400760static void
Kristian Høgsberg75840622011-09-06 13:48:16 -0400761handle_background_surface_destroy(struct wl_listener *listener,
762 struct wl_resource *resource, uint32_t time)
763{
764 struct wl_shell *shell =
765 container_of(listener, struct wl_shell, background_listener);
766
767 fprintf(stderr, "background surface gone\n");
768 shell->background = NULL;
769}
770
771static void
772desktop_shell_set_background(struct wl_client *client,
773 struct wl_resource *resource,
774 struct wl_resource *surface_resource)
775{
776 struct wl_shell *shell = resource->data;
777 struct wlsc_surface *surface = surface_resource->data;
778 struct wlsc_output *output =
779 container_of(shell->compositor->output_list.next,
780 struct wlsc_output, link);
781
782 shell->background = surface_resource->data;
783 shell->background_listener.func = handle_background_surface_destroy;
784 wl_list_insert(&surface_resource->destroy_listener_list,
785 &shell->background_listener.link);
786
787 wl_resource_post_event(resource,
788 DESKTOP_SHELL_CONFIGURE,
789 wlsc_compositor_get_time(), 0, surface,
790 output->current->width,
791 output->current->height);
792}
793
794static void
795handle_panel_surface_destroy(struct wl_listener *listener,
796 struct wl_resource *resource, uint32_t time)
797{
798 struct wl_shell *shell =
799 container_of(listener, struct wl_shell, panel_listener);
800
801 fprintf(stderr, "panel surface gone\n");
802 shell->panel = NULL;
803}
804
805static void
806desktop_shell_set_panel(struct wl_client *client,
807 struct wl_resource *resource,
808 struct wl_resource *surface_resource)
809{
810 struct wl_shell *shell = resource->data;
811 struct wlsc_output *output =
812 container_of(shell->compositor->output_list.next,
813 struct wlsc_output, link);
814
815 shell->panel = surface_resource->data;
816
817 shell->panel_listener.func = handle_panel_surface_destroy;
818 wl_list_insert(&surface_resource->destroy_listener_list,
819 &shell->panel_listener.link);
820
821 wl_resource_post_event(resource,
822 DESKTOP_SHELL_CONFIGURE,
823 wlsc_compositor_get_time(), 0, surface_resource,
824 output->current->width,
825 output->current->height);
826}
827
828static const struct desktop_shell_interface desktop_shell_implementation = {
829 desktop_shell_set_background,
830 desktop_shell_set_panel
831};
832
833static void
Kristian Høgsberg07937562011-04-12 17:25:42 -0400834move_binding(struct wl_input_device *device, uint32_t time,
835 uint32_t key, uint32_t button, uint32_t state, void *data)
836{
Kristian Høgsberg75840622011-09-06 13:48:16 -0400837 struct wl_shell *shell = data;
Kristian Høgsberg07937562011-04-12 17:25:42 -0400838 struct wlsc_surface *surface =
839 (struct wlsc_surface *) device->pointer_focus;
840
Kristian Høgsberga4a42f02011-09-08 16:56:57 -0400841 if (surface == NULL ||
842 surface->map_type == WLSC_SURFACE_MAP_FULLSCREEN)
Kristian Høgsberg10f097e2011-04-13 11:52:54 -0400843 return;
Kristian Høgsberg75840622011-09-06 13:48:16 -0400844 if (surface == shell->panel)
845 return;
846 if (surface == shell->background)
847 return;
Kristian Høgsberg10f097e2011-04-13 11:52:54 -0400848
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400849 wlsc_surface_move(surface, (struct wlsc_input_device *) device, time);
Kristian Høgsberg07937562011-04-12 17:25:42 -0400850}
851
852static void
853resize_binding(struct wl_input_device *device, uint32_t time,
854 uint32_t key, uint32_t button, uint32_t state, void *data)
855{
Kristian Høgsberg75840622011-09-06 13:48:16 -0400856 struct wl_shell *shell = data;
Kristian Høgsberg07937562011-04-12 17:25:42 -0400857 struct wlsc_surface *surface =
858 (struct wlsc_surface *) device->pointer_focus;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400859 struct wl_resource *resource;
Kristian Høgsberg07937562011-04-12 17:25:42 -0400860 uint32_t edges = 0;
861 int32_t x, y;
862
Kristian Høgsberga4a42f02011-09-08 16:56:57 -0400863 if (surface == NULL ||
864 surface->map_type == WLSC_SURFACE_MAP_FULLSCREEN)
Kristian Høgsberg75840622011-09-06 13:48:16 -0400865 if (surface == shell->panel)
866 return;
867 if (surface == shell->background)
868 return;
Kristian Høgsberg10f097e2011-04-13 11:52:54 -0400869
Kristian Høgsberg07937562011-04-12 17:25:42 -0400870 x = device->grab_x - surface->x;
871 y = device->grab_y - surface->y;
872
873 if (x < surface->width / 3)
874 edges |= WL_SHELL_RESIZE_LEFT;
875 else if (x < 2 * surface->width / 3)
876 edges |= 0;
877 else
878 edges |= WL_SHELL_RESIZE_RIGHT;
879
880 if (y < surface->height / 3)
881 edges |= WL_SHELL_RESIZE_TOP;
882 else if (y < 2 * surface->height / 3)
883 edges |= 0;
884 else
885 edges |= WL_SHELL_RESIZE_BOTTOM;
886
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400887 resource = /* Find shell resource for surface client */ 0;
888
889 /* ... or use wl_shell_surface */
890
891 wlsc_surface_resize(surface, (struct wlsc_input_device *) device,
892 time, edges, resource);
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400893}
894
895static void
Kristian Høgsberg75840622011-09-06 13:48:16 -0400896activate(struct wlsc_shell *base, struct wlsc_surface *es,
897 struct wlsc_input_device *device, uint32_t time)
898{
899 struct wl_shell *shell = container_of(base, struct wl_shell, shell);
900 struct wlsc_compositor *compositor = shell->compositor;
901
902 wlsc_surface_activate(es, device, time);
903
Kristian Høgsbergd6e55252011-10-11 23:41:17 -0400904 if (compositor->wxs)
905 wlsc_xserver_surface_activate(es);
906
Kristian Høgsberg75840622011-09-06 13:48:16 -0400907 if (es == shell->background) {
908 wl_list_remove(&es->link);
909 wl_list_insert(compositor->surface_list.prev, &es->link);
910 } else if (shell->panel) {
911 wl_list_remove(&shell->panel->link);
912 wl_list_insert(&compositor->surface_list, &shell->panel->link);
913 }
914}
915
916static void
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400917lock(struct wlsc_shell *shell)
918{
919}
920
921static void
Kristian Høgsberg75840622011-09-06 13:48:16 -0400922attach(struct wlsc_shell *base, struct wlsc_surface *es)
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400923{
Kristian Høgsberg75840622011-09-06 13:48:16 -0400924 struct wl_shell *shell = container_of(base, struct wl_shell, shell);
925 struct wlsc_compositor *compositor = shell->compositor;
926
927 if (es == shell->background) {
928 wl_list_remove(&es->link);
929 wl_list_insert(compositor->surface_list.prev, &es->link);
930 } else if (es->map_type == WLSC_SURFACE_MAP_FULLSCREEN) {
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400931 es->x = (es->fullscreen_output->current->width - es->width) / 2;
932 es->y = (es->fullscreen_output->current->height - es->height) / 2;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400933 }
Kristian Høgsberg07937562011-04-12 17:25:42 -0400934}
935
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400936static void
Pekka Paalanen6cd281a2011-11-03 14:11:32 +0200937desktop_shell_sigchld(struct wlsc_process *process, int status)
938{
939 struct wl_shell *shell =
940 container_of(process, struct wl_shell, child.process);
941
942 shell->child.process.pid = 0;
943 shell->child.client = NULL; /* already destroyed by wayland */
944}
945
946static int
947launch_desktop_shell_process(struct wl_shell *shell)
948{
949 const char *shell_exe = "./clients/desktop-shell";
950 struct wlsc_compositor *compositor = shell->compositor;
951 char s[32];
952 int sv[2], flags;
953
954 if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sv) < 0) {
955 fprintf(stderr, "socketpair failed\n");
956 return -1;
957 }
958
959 shell->child.process.pid = fork();
960 shell->child.process.cleanup = desktop_shell_sigchld;
961
962 switch (shell->child.process.pid) {
963 case 0:
964 /* SOCK_CLOEXEC closes both ends, so we need to unset
965 * the flag on the client fd. */
966 flags = fcntl(sv[1], F_GETFD);
967 if (flags != -1)
968 fcntl(sv[1], F_SETFD, flags & ~FD_CLOEXEC);
969
970 snprintf(s, sizeof s, "%d", sv[1]);
971 setenv("WAYLAND_SOCKET", s, 1);
972 if (execl(shell_exe, shell_exe, NULL) < 0)
973 fprintf(stderr, "%s: running '%s' failed: %m\n",
974 __func__, shell_exe);
975 exit(-1);
976
977 default:
978 close(sv[1]);
979 shell->child.client =
980 wl_client_create(compositor->wl_display, sv[0]);
981 wlsc_watch_process(&shell->child.process);
982 break;
983
984 case -1:
985 fprintf(stderr, "%s: fork failed: %m\n", __func__);
986 return -1;
987 }
988 return 0;
989}
990
991static void
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400992bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
993{
994 struct wl_shell *shell = data;
995
996 wl_client_add_object(client, &wl_shell_interface,
997 &shell_interface, id, shell);
998}
999
Kristian Høgsberg75840622011-09-06 13:48:16 -04001000static void
1001bind_desktop_shell(struct wl_client *client,
1002 void *data, uint32_t version, uint32_t id)
1003{
1004 struct wl_shell *shell = data;
Pekka Paalanenbbe60522011-11-03 14:11:33 +02001005 struct wl_resource *resource;
Kristian Høgsberg75840622011-09-06 13:48:16 -04001006
Pekka Paalanenbbe60522011-11-03 14:11:33 +02001007 resource = wl_client_add_object(client, &desktop_shell_interface,
1008 &desktop_shell_implementation,
1009 id, shell);
1010
1011 if (client == shell->child.client)
1012 return;
1013
1014 wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
1015 "permission to bind desktop_shell denied");
1016 wl_resource_destroy(resource, 0);
Kristian Høgsberg75840622011-09-06 13:48:16 -04001017}
1018
Kristian Høgsberg6c709a32011-05-06 14:52:41 -04001019int
1020shell_init(struct wlsc_compositor *ec);
1021
Kristian Høgsberg1c562182011-05-02 22:09:20 -04001022WL_EXPORT int
1023shell_init(struct wlsc_compositor *ec)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -05001024{
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04001025 struct wl_shell *shell;
1026
1027 shell = malloc(sizeof *shell);
1028 if (shell == NULL)
1029 return -1;
1030
Kristian Høgsbergf0d91162011-10-11 22:44:23 -04001031 memset(shell, 0, sizeof *shell);
Kristian Høgsberg75840622011-09-06 13:48:16 -04001032 shell->compositor = ec;
1033 shell->shell.activate = activate;
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04001034 shell->shell.lock = lock;
1035 shell->shell.attach = attach;
Kristian Høgsberg1c562182011-05-02 22:09:20 -04001036 shell->shell.set_selection_focus = wlsc_selection_set_focus;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -05001037
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -04001038 if (wl_display_add_global(ec->wl_display, &wl_shell_interface,
1039 shell, bind_shell) == NULL)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -05001040 return -1;
1041
Kristian Høgsberg75840622011-09-06 13:48:16 -04001042 if (wl_display_add_global(ec->wl_display,
1043 &desktop_shell_interface,
1044 shell, bind_desktop_shell) == NULL)
1045 return -1;
1046
Pekka Paalanen6cd281a2011-11-03 14:11:32 +02001047 if (launch_desktop_shell_process(shell) != 0)
1048 return -1;
1049
Kristian Høgsberg07937562011-04-12 17:25:42 -04001050 wlsc_compositor_add_binding(ec, 0, BTN_LEFT, MODIFIER_SUPER,
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04001051 move_binding, shell);
Kristian Høgsberg07937562011-04-12 17:25:42 -04001052 wlsc_compositor_add_binding(ec, 0, BTN_MIDDLE, MODIFIER_SUPER,
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -04001053 resize_binding, shell);
1054
1055 ec->shell = &shell->shell;
Kristian Høgsberg07937562011-04-12 17:25:42 -04001056
Kristian Høgsberg4cca3492011-01-18 07:53:49 -05001057 return 0;
1058}