blob: 2dfe95b041a483919f06caf612a56620563887cf [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>
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050028
29#include "wayland-server.h"
30#include "compositor.h"
Kristian Høgsberg75840622011-09-06 13:48:16 -040031#include "desktop-shell-server-protocol.h"
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050032
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -040033struct wl_shell {
Kristian Høgsberg75840622011-09-06 13:48:16 -040034 struct wlsc_compositor *compositor;
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -040035 struct wlsc_shell shell;
Kristian Høgsberg75840622011-09-06 13:48:16 -040036 struct wlsc_surface *panel;
37 struct wl_listener panel_listener;
38 struct wlsc_surface *background;
39 struct wl_listener background_listener;
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -040040};
41
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050042struct wlsc_move_grab {
43 struct wl_grab grab;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -050044 struct wlsc_surface *surface;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050045 int32_t dx, dy;
46};
47
48static void
49move_grab_motion(struct wl_grab *grab,
50 uint32_t time, int32_t x, int32_t y)
51{
52 struct wlsc_move_grab *move = (struct wlsc_move_grab *) grab;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -050053 struct wlsc_surface *es = move->surface;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050054
Kristian Høgsberga691aee2011-06-23 21:43:50 -040055 wlsc_surface_configure(es, x + move->dx, y + move->dy,
56 es->width, es->height);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050057}
58
59static void
60move_grab_button(struct wl_grab *grab,
61 uint32_t time, int32_t button, int32_t state)
62{
63}
64
65static void
66move_grab_end(struct wl_grab *grab, uint32_t time)
67{
68 free(grab);
69}
70
71static const struct wl_grab_interface move_grab_interface = {
72 move_grab_motion,
73 move_grab_button,
74 move_grab_end
75};
76
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -040077static int
78wlsc_surface_move(struct wlsc_surface *es,
79 struct wlsc_input_device *wd, uint32_t time)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050080{
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050081 struct wlsc_move_grab *move;
82
83 move = malloc(sizeof *move);
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -040084 if (!move)
85 return -1;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050086
87 move->grab.interface = &move_grab_interface;
88 move->dx = es->x - wd->input_device.grab_x;
89 move->dy = es->y - wd->input_device.grab_y;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -050090 move->surface = es;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050091
92 if (wl_input_device_update_grab(&wd->input_device,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -040093 &move->grab, &es->surface, time) < 0)
94 return 0;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050095
96 wlsc_input_device_set_pointer_image(wd, WLSC_POINTER_DRAGGING);
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -040097 wl_input_device_set_pointer_focus(&wd->input_device,
98 NULL, time, 0, 0, 0, 0);
99
100 return 0;
101}
102
103static void
104shell_move(struct wl_client *client, struct wl_resource *resource,
105 struct wl_resource *surface_resource,
106 struct wl_resource *input_resource, uint32_t time)
107{
108 struct wlsc_input_device *wd = input_resource->data;
109 struct wlsc_surface *es = surface_resource->data;
110
111 if (wlsc_surface_move(es, wd, time) < 0)
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400112 wl_resource_post_no_memory(resource);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500113}
114
115struct wlsc_resize_grab {
116 struct wl_grab grab;
117 uint32_t edges;
118 int32_t dx, dy, width, height;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500119 struct wlsc_surface *surface;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400120 struct wl_resource *resource;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500121};
122
123static void
124resize_grab_motion(struct wl_grab *grab,
125 uint32_t time, int32_t x, int32_t y)
126{
127 struct wlsc_resize_grab *resize = (struct wlsc_resize_grab *) grab;
128 struct wl_input_device *device = grab->input_device;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500129 struct wl_surface *surface = &resize->surface->surface;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500130 int32_t width, height;
131
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500132 if (resize->edges & WL_SHELL_RESIZE_LEFT) {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500133 width = device->grab_x - x + resize->width;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500134 } else if (resize->edges & WL_SHELL_RESIZE_RIGHT) {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500135 width = x - device->grab_x + resize->width;
136 } else {
137 width = resize->width;
138 }
139
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500140 if (resize->edges & WL_SHELL_RESIZE_TOP) {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500141 height = device->grab_y - y + resize->height;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500142 } else if (resize->edges & WL_SHELL_RESIZE_BOTTOM) {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500143 height = y - device->grab_y + resize->height;
144 } else {
145 height = resize->height;
146 }
147
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400148 wl_resource_post_event(resize->resource,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400149 WL_SHELL_CONFIGURE, time, resize->edges,
150 surface, width, height);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500151}
152
153static void
154resize_grab_button(struct wl_grab *grab,
155 uint32_t time, int32_t button, int32_t state)
156{
157}
158
159static void
160resize_grab_end(struct wl_grab *grab, uint32_t time)
161{
162 free(grab);
163}
164
165static const struct wl_grab_interface resize_grab_interface = {
166 resize_grab_motion,
167 resize_grab_button,
168 resize_grab_end
169};
170
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400171static int
172wlsc_surface_resize(struct wlsc_surface *es,
173 struct wlsc_input_device *wd,
174 uint32_t time, uint32_t edges,
175 struct wl_resource *resource)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500176{
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500177 struct wlsc_resize_grab *resize;
178 enum wlsc_pointer_type pointer = WLSC_POINTER_LEFT_PTR;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500179
Kristian Høgsberg0ce24572011-01-28 15:18:33 -0500180 /* FIXME: Reject if fullscreen */
181
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500182 resize = malloc(sizeof *resize);
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400183 if (!resize)
184 return -1;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500185
186 resize->grab.interface = &resize_grab_interface;
187 resize->edges = edges;
188 resize->dx = es->x - wd->input_device.grab_x;
189 resize->dy = es->y - wd->input_device.grab_y;
190 resize->width = es->width;
191 resize->height = es->height;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500192 resize->surface = es;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400193 resize->resource = resource;
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400194
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500195 if (edges == 0 || edges > 15 ||
196 (edges & 3) == 3 || (edges & 12) == 12)
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400197 return 0;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500198
199 switch (edges) {
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500200 case WL_SHELL_RESIZE_TOP:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500201 pointer = WLSC_POINTER_TOP;
202 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500203 case WL_SHELL_RESIZE_BOTTOM:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500204 pointer = WLSC_POINTER_BOTTOM;
205 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500206 case WL_SHELL_RESIZE_LEFT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500207 pointer = WLSC_POINTER_LEFT;
208 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500209 case WL_SHELL_RESIZE_TOP_LEFT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500210 pointer = WLSC_POINTER_TOP_LEFT;
211 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500212 case WL_SHELL_RESIZE_BOTTOM_LEFT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500213 pointer = WLSC_POINTER_BOTTOM_LEFT;
214 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500215 case WL_SHELL_RESIZE_RIGHT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500216 pointer = WLSC_POINTER_RIGHT;
217 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500218 case WL_SHELL_RESIZE_TOP_RIGHT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500219 pointer = WLSC_POINTER_TOP_RIGHT;
220 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500221 case WL_SHELL_RESIZE_BOTTOM_RIGHT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500222 pointer = WLSC_POINTER_BOTTOM_RIGHT;
223 break;
224 }
225
226 if (wl_input_device_update_grab(&wd->input_device,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400227 &resize->grab, &es->surface, time) < 0)
228 return 0;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500229
230 wlsc_input_device_set_pointer_image(wd, pointer);
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400231 wl_input_device_set_pointer_focus(&wd->input_device,
232 NULL, time, 0, 0, 0, 0);
233
234 return 0;
235}
236
237static void
238shell_resize(struct wl_client *client, struct wl_resource *resource,
239 struct wl_resource *surface_resource,
240 struct wl_resource *input_resource, uint32_t time, uint32_t edges)
241{
242 struct wlsc_input_device *wd = input_resource->data;
243 struct wlsc_surface *es = surface_resource->data;
244
245 /* FIXME: Reject if fullscreen */
246
247 if (wlsc_surface_resize(es, wd, time, edges, resource) < 0)
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400248 wl_resource_post_no_memory(resource);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500249}
250
251static void
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400252shell_set_toplevel(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400253 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400254 struct wl_resource *surface_resource)
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400255
256{
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400257 struct wlsc_surface *es = surface_resource->data;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400258 struct wlsc_compositor *ec = es->compositor;
259
260 if (es->map_type == WLSC_SURFACE_MAP_FULLSCREEN) {
261 es->x = es->saved_x;
262 es->y = es->saved_y;
263 } else if (es->map_type == WLSC_SURFACE_MAP_UNMAPPED) {
264 es->x = 10 + random() % 400;
265 es->y = 10 + random() % 400;
266 /* assign to first output */
267 es->output = container_of(ec->output_list.next,
268 struct wlsc_output, link);
269 }
270
271 wlsc_surface_damage(es);
272 es->map_type = WLSC_SURFACE_MAP_TOPLEVEL;
273 es->fullscreen_output = NULL;
274}
275
276static void
277shell_set_transient(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400278 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400279 struct wl_resource *surface_resource,
280 struct wl_resource *parent_resource,
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400281 int x, int y, uint32_t flags)
282{
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400283 struct wlsc_surface *es = surface_resource->data;
284 struct wlsc_surface *pes = parent_resource->data;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400285
286 /* assign to parents output */
287 es->output = pes->output;
288
289 es->x = pes->x + x;
290 es->y = pes->y + y;
291
292 wlsc_surface_damage(es);
293 es->map_type = WLSC_SURFACE_MAP_TRANSIENT;
294}
295
296static void
297shell_set_fullscreen(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400298 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400299 struct wl_resource *surface_resource)
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400300
301{
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400302 struct wlsc_surface *es = surface_resource->data;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400303 struct wlsc_output *output;
304
305 /* FIXME: Fullscreen on first output */
306 /* FIXME: Handle output going away */
307 output = container_of(es->compositor->output_list.next,
308 struct wlsc_output, link);
309 es->output = output;
310
311 es->saved_x = es->x;
312 es->saved_y = es->y;
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400313 es->x = (output->current->width - es->width) / 2;
314 es->y = (output->current->height - es->height) / 2;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400315 es->fullscreen_output = output;
316 wlsc_surface_damage(es);
317 es->map_type = WLSC_SURFACE_MAP_FULLSCREEN;
318}
319
320static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400321destroy_drag(struct wl_resource *resource)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500322{
323 struct wl_drag *drag =
324 container_of(resource, struct wl_drag, resource);
325
326 wl_list_remove(&drag->drag_focus_listener.link);
327 if (drag->grab.input_device)
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400328 wl_input_device_end_grab(drag->grab.input_device,
329 wlsc_compositor_get_time());
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500330
331 free(drag);
332}
333
334
335static void
336wl_drag_set_pointer_focus(struct wl_drag *drag,
337 struct wl_surface *surface, uint32_t time,
338 int32_t x, int32_t y, int32_t sx, int32_t sy)
339{
340 char **p, **end;
341
342 if (drag->drag_focus == surface)
343 return;
344
345 if (drag->drag_focus &&
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400346 (!surface ||
347 drag->drag_focus->resource.client != surface->resource.client))
348 wl_resource_post_event(&drag->drag_offer.resource,
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500349 WL_DRAG_OFFER_POINTER_FOCUS,
350 time, NULL, 0, 0, 0, 0);
351
352 if (surface &&
353 (!drag->drag_focus ||
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400354 drag->drag_focus->resource.client != surface->resource.client)) {
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400355
356 drag->drag_offer.resource.client = surface->resource.client;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500357 end = drag->types.data + drag->types.size;
358 for (p = drag->types.data; p < end; p++)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400359 wl_resource_post_event(&drag->drag_offer.resource,
360 WL_DRAG_OFFER_OFFER, *p);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500361 }
362
363 if (surface) {
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400364 wl_resource_post_event(&drag->drag_offer.resource,
365 WL_DRAG_OFFER_POINTER_FOCUS,
366 time, surface,
367 x, y, sx, sy);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500368
369 }
370
371 drag->drag_focus = surface;
372 drag->pointer_focus_time = time;
373 drag->target = NULL;
374
375 wl_list_remove(&drag->drag_focus_listener.link);
376 if (surface)
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200377 wl_list_insert(surface->resource.destroy_listener_list.prev,
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500378 &drag->drag_focus_listener.link);
379}
380
381static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400382drag_offer_accept(struct wl_client *client, struct wl_resource *resource,
383 uint32_t time, const char *type)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500384{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400385 struct wl_drag_offer *offer = resource->data;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500386 struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer);
387 char **p, **end;
388
389 /* If the client responds to drag pointer_focus or motion
390 * events after the pointer has left the surface, we just
391 * discard the accept requests. The drag source just won't
392 * get the corresponding 'target' events and eventually the
393 * next surface/root will start sending events. */
394 if (time < drag->pointer_focus_time)
395 return;
396
397 drag->target = client;
398 drag->type = NULL;
399 end = drag->types.data + drag->types.size;
400 for (p = drag->types.data; p < end; p++)
401 if (type && strcmp(*p, type) == 0)
402 drag->type = *p;
403
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400404 wl_resource_post_event(&drag->resource, WL_DRAG_TARGET, drag->type);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500405}
406
407static void
408drag_offer_receive(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400409 struct wl_resource *resource, int fd)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500410{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400411 struct wl_drag_offer *offer = resource->data;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500412 struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer);
413
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400414 wl_resource_post_event(&drag->resource, WL_DRAG_FINISH, fd);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500415 close(fd);
416}
417
418static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400419drag_offer_reject(struct wl_client *client, struct wl_resource *resource)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500420{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400421 struct wl_drag_offer *offer = resource->data;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500422 struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer);
423
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400424 wl_resource_post_event(&drag->resource, WL_DRAG_REJECT);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500425}
426
427static const struct wl_drag_offer_interface drag_offer_interface = {
428 drag_offer_accept,
429 drag_offer_receive,
430 drag_offer_reject
431};
432
433static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400434drag_offer(struct wl_client *client,
435 struct wl_resource *resource, const char *type)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500436{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400437 struct wl_drag *drag = resource->data;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500438 char **p;
439
440 p = wl_array_add(&drag->types, sizeof *p);
441 if (p)
442 *p = strdup(type);
443 if (!p || !*p)
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400444 wl_resource_post_no_memory(resource);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500445}
446
447static void
448drag_grab_motion(struct wl_grab *grab,
449 uint32_t time, int32_t x, int32_t y)
450{
451 struct wl_drag *drag = container_of(grab, struct wl_drag, grab);
452 struct wlsc_surface *es;
453 int32_t sx, sy;
454
455 es = pick_surface(grab->input_device, &sx, &sy);
456 wl_drag_set_pointer_focus(drag, &es->surface, time, x, y, sx, sy);
457 if (es)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400458 wl_resource_post_event(&drag->drag_offer.resource,
459 WL_DRAG_OFFER_MOTION,
460 time, x, y, sx, sy);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500461}
462
463static void
464drag_grab_button(struct wl_grab *grab,
465 uint32_t time, int32_t button, int32_t state)
466{
467}
468
469static void
470drag_grab_end(struct wl_grab *grab, uint32_t time)
471{
472 struct wl_drag *drag = container_of(grab, struct wl_drag, grab);
473
474 if (drag->target)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400475 wl_resource_post_event(&drag->drag_offer.resource,
476 WL_DRAG_OFFER_DROP);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500477
478 wl_drag_set_pointer_focus(drag, NULL, time, 0, 0, 0, 0);
479}
480
481static const struct wl_grab_interface drag_grab_interface = {
482 drag_grab_motion,
483 drag_grab_button,
484 drag_grab_end
485};
486
487static void
488drag_activate(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400489 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400490 struct wl_resource *surface_resource,
491 struct wl_resource *device_resource, uint32_t time)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500492{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400493 struct wl_drag *drag = resource->data;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400494 struct wl_surface *surface = surface_resource->data;
495 struct wl_input_device *device = device_resource->data;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500496 struct wl_display *display = wl_client_get_display (client);
497 struct wlsc_surface *target;
498 int32_t sx, sy;
499
500 if (wl_input_device_update_grab(device,
501 &drag->grab, surface, time) < 0)
502 return;
503
504 drag->grab.interface = &drag_grab_interface;
505
506 drag->source = surface;
507
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400508 drag->drag_offer.resource.object.interface = &wl_drag_offer_interface;
509 drag->drag_offer.resource.object.implementation =
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500510 (void (**)(void)) &drag_offer_interface;
511
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400512 wl_display_add_global(display, &wl_drag_offer_interface, drag, NULL);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500513
514 target = pick_surface(device, &sx, &sy);
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500515 wl_input_device_set_pointer_focus(device, NULL, time, 0, 0, 0, 0);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500516 wl_drag_set_pointer_focus(drag, &target->surface, time,
517 device->x, device->y, sx, sy);
518}
519
520static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400521drag_destroy(struct wl_client *client, struct wl_resource *resource)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500522{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400523 wl_resource_destroy(resource, wlsc_compositor_get_time());
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500524}
525
526static const struct wl_drag_interface drag_interface = {
527 drag_offer,
528 drag_activate,
529 drag_destroy,
530};
531
532static void
533drag_handle_surface_destroy(struct wl_listener *listener,
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200534 struct wl_resource *resource, uint32_t time)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500535{
536 struct wl_drag *drag =
537 container_of(listener, struct wl_drag, drag_focus_listener);
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200538 struct wl_surface *surface = (struct wl_surface *) resource;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500539
540 if (drag->drag_focus == surface)
541 wl_drag_set_pointer_focus(drag, NULL, time, 0, 0, 0, 0);
542}
543
544static void
545shell_create_drag(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400546 struct wl_resource *resource, uint32_t id)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500547{
548 struct wl_drag *drag;
549
550 drag = malloc(sizeof *drag);
551 if (drag == NULL) {
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400552 wl_resource_post_no_memory(resource);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500553 return;
554 }
555
556 memset(drag, 0, sizeof *drag);
557 drag->resource.object.id = id;
558 drag->resource.object.interface = &wl_drag_interface;
559 drag->resource.object.implementation =
560 (void (**)(void)) &drag_interface;
561
562 drag->resource.destroy = destroy_drag;
563
564 drag->drag_focus_listener.func = drag_handle_surface_destroy;
565 wl_list_init(&drag->drag_focus_listener.link);
566
567 wl_client_add_resource(client, &drag->resource);
568}
569
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400570static void
571wlsc_selection_set_focus(struct wlsc_shell *shell,
572 struct wl_selection *selection,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500573 struct wl_surface *surface, uint32_t time)
574{
575 char **p, **end;
576
577 if (selection->selection_focus == surface)
578 return;
579
580 if (selection->selection_focus != NULL)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400581 wl_resource_post_event(&selection->selection_offer.resource,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500582 WL_SELECTION_OFFER_KEYBOARD_FOCUS,
583 NULL);
584
585 if (surface) {
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500586
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400587 selection->selection_offer.resource.client = surface->resource.client;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500588 end = selection->types.data + selection->types.size;
589 for (p = selection->types.data; p < end; p++)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400590 wl_resource_post_event(&selection->selection_offer.resource,
591 WL_SELECTION_OFFER_OFFER, *p);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500592
593 wl_list_remove(&selection->selection_focus_listener.link);
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200594 wl_list_insert(surface->resource.destroy_listener_list.prev,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500595 &selection->selection_focus_listener.link);
596
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400597 wl_resource_post_event(&selection->selection_offer.resource,
598 WL_SELECTION_OFFER_KEYBOARD_FOCUS,
599 selection->input_device);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500600 }
601
602 selection->selection_focus = surface;
603
604 wl_list_remove(&selection->selection_focus_listener.link);
605 if (surface)
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200606 wl_list_insert(surface->resource.destroy_listener_list.prev,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500607 &selection->selection_focus_listener.link);
608}
609
610static void
611selection_offer_receive(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400612 struct wl_resource *resource,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500613 const char *mime_type, int fd)
614{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400615 struct wl_selection_offer *offer = resource->data;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500616 struct wl_selection *selection =
617 container_of(offer, struct wl_selection, selection_offer);
618
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400619 wl_resource_post_event(&selection->resource,
620 WL_SELECTION_SEND, mime_type, fd);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500621 close(fd);
622}
623
624static const struct wl_selection_offer_interface selection_offer_interface = {
625 selection_offer_receive
626};
627
628static void
629selection_offer(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400630 struct wl_resource *resource, const char *type)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500631{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400632 struct wl_selection *selection = resource->data;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500633 char **p;
634
635 p = wl_array_add(&selection->types, sizeof *p);
636 if (p)
637 *p = strdup(type);
638 if (!p || !*p)
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400639 wl_resource_post_no_memory(resource);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500640}
641
642static void
643selection_activate(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400644 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400645 struct wl_resource *input_resource, uint32_t time)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500646{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400647 struct wl_selection *selection = resource->data;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400648 struct wlsc_input_device *wd = input_resource->data;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500649 struct wl_display *display = wl_client_get_display (client);
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400650 struct wlsc_compositor *compositor =
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400651 (struct wlsc_compositor *) wd->input_device.compositor;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500652
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400653 selection->input_device = &wd->input_device;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500654
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400655 selection->selection_offer.resource.object.interface =
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500656 &wl_selection_offer_interface;
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400657 selection->selection_offer.resource.object.implementation =
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500658 (void (**)(void)) &selection_offer_interface;
659
Kristian Høgsbergd9551a32011-08-19 12:07:44 -0400660 wl_display_add_global(display,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400661 &wl_selection_offer_interface, selection, NULL);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500662
663 if (wd->selection) {
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400664 wl_resource_post_event(&wd->selection->resource,
665 WL_SELECTION_CANCELLED);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500666 }
667 wd->selection = selection;
668
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400669 wlsc_selection_set_focus(compositor->shell, selection,
670 wd->input_device.keyboard_focus, time);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500671}
672
673static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400674selection_destroy(struct wl_client *client, struct wl_resource *resource)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500675{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400676 wl_resource_destroy(resource, wlsc_compositor_get_time());
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500677}
678
679static const struct wl_selection_interface selection_interface = {
680 selection_offer,
681 selection_activate,
682 selection_destroy
683};
684
685static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400686destroy_selection(struct wl_resource *resource)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500687{
688 struct wl_selection *selection =
689 container_of(resource, struct wl_selection, resource);
690 struct wlsc_input_device *wd =
691 (struct wlsc_input_device *) selection->input_device;
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400692 struct wlsc_compositor *compositor =
693 (struct wlsc_compositor *) wd->input_device.compositor;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500694
695 if (wd && wd->selection == selection) {
696 wd->selection = NULL;
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400697 wlsc_selection_set_focus(compositor->shell,
698 selection, NULL,
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400699 wlsc_compositor_get_time());
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500700 }
701
702 wl_list_remove(&selection->selection_focus_listener.link);
703 free(selection);
704}
705
706static void
707selection_handle_surface_destroy(struct wl_listener *listener,
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200708 struct wl_resource *resource, uint32_t time)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500709{
710}
711
712static void
713shell_create_selection(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400714 struct wl_resource *resource, uint32_t id)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500715{
716 struct wl_selection *selection;
717
718 selection = malloc(sizeof *selection);
719 if (selection == NULL) {
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400720 wl_resource_post_no_memory(resource);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500721 return;
722 }
723
724 memset(selection, 0, sizeof *selection);
725 selection->resource.object.id = id;
726 selection->resource.object.interface = &wl_selection_interface;
727 selection->resource.object.implementation =
728 (void (**)(void)) &selection_interface;
729
730 selection->client = client;
731 selection->resource.destroy = destroy_selection;
732 selection->selection_focus = NULL;
733
734 selection->selection_focus_listener.func =
735 selection_handle_surface_destroy;
736 wl_list_init(&selection->selection_focus_listener.link);
737
738 wl_client_add_resource(client, &selection->resource);
739}
740
Kristian Høgsberg75840622011-09-06 13:48:16 -0400741static const struct wl_shell_interface shell_interface = {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500742 shell_move,
743 shell_resize,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500744 shell_create_drag,
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400745 shell_create_selection,
746 shell_set_toplevel,
747 shell_set_transient,
748 shell_set_fullscreen
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500749};
750
Kristian Høgsberg07937562011-04-12 17:25:42 -0400751static void
Kristian Høgsberg75840622011-09-06 13:48:16 -0400752handle_background_surface_destroy(struct wl_listener *listener,
753 struct wl_resource *resource, uint32_t time)
754{
755 struct wl_shell *shell =
756 container_of(listener, struct wl_shell, background_listener);
757
758 fprintf(stderr, "background surface gone\n");
759 shell->background = NULL;
760}
761
762static void
763desktop_shell_set_background(struct wl_client *client,
764 struct wl_resource *resource,
765 struct wl_resource *surface_resource)
766{
767 struct wl_shell *shell = resource->data;
768 struct wlsc_surface *surface = surface_resource->data;
769 struct wlsc_output *output =
770 container_of(shell->compositor->output_list.next,
771 struct wlsc_output, link);
772
773 shell->background = surface_resource->data;
774 shell->background_listener.func = handle_background_surface_destroy;
775 wl_list_insert(&surface_resource->destroy_listener_list,
776 &shell->background_listener.link);
777
778 wl_resource_post_event(resource,
779 DESKTOP_SHELL_CONFIGURE,
780 wlsc_compositor_get_time(), 0, surface,
781 output->current->width,
782 output->current->height);
783}
784
785static void
786handle_panel_surface_destroy(struct wl_listener *listener,
787 struct wl_resource *resource, uint32_t time)
788{
789 struct wl_shell *shell =
790 container_of(listener, struct wl_shell, panel_listener);
791
792 fprintf(stderr, "panel surface gone\n");
793 shell->panel = NULL;
794}
795
796static void
797desktop_shell_set_panel(struct wl_client *client,
798 struct wl_resource *resource,
799 struct wl_resource *surface_resource)
800{
801 struct wl_shell *shell = resource->data;
802 struct wlsc_output *output =
803 container_of(shell->compositor->output_list.next,
804 struct wlsc_output, link);
805
806 shell->panel = surface_resource->data;
807
808 shell->panel_listener.func = handle_panel_surface_destroy;
809 wl_list_insert(&surface_resource->destroy_listener_list,
810 &shell->panel_listener.link);
811
812 wl_resource_post_event(resource,
813 DESKTOP_SHELL_CONFIGURE,
814 wlsc_compositor_get_time(), 0, surface_resource,
815 output->current->width,
816 output->current->height);
817}
818
819static const struct desktop_shell_interface desktop_shell_implementation = {
820 desktop_shell_set_background,
821 desktop_shell_set_panel
822};
823
824static void
Kristian Høgsberg07937562011-04-12 17:25:42 -0400825move_binding(struct wl_input_device *device, uint32_t time,
826 uint32_t key, uint32_t button, uint32_t state, void *data)
827{
Kristian Høgsberg75840622011-09-06 13:48:16 -0400828 struct wl_shell *shell = data;
Kristian Høgsberg07937562011-04-12 17:25:42 -0400829 struct wlsc_surface *surface =
830 (struct wlsc_surface *) device->pointer_focus;
831
Kristian Høgsberga4a42f02011-09-08 16:56:57 -0400832 if (surface == NULL ||
833 surface->map_type == WLSC_SURFACE_MAP_FULLSCREEN)
Kristian Høgsberg10f097e2011-04-13 11:52:54 -0400834 return;
Kristian Høgsberg75840622011-09-06 13:48:16 -0400835 if (surface == shell->panel)
836 return;
837 if (surface == shell->background)
838 return;
Kristian Høgsberg10f097e2011-04-13 11:52:54 -0400839
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400840 wlsc_surface_move(surface, (struct wlsc_input_device *) device, time);
Kristian Høgsberg07937562011-04-12 17:25:42 -0400841}
842
843static void
844resize_binding(struct wl_input_device *device, uint32_t time,
845 uint32_t key, uint32_t button, uint32_t state, void *data)
846{
Kristian Høgsberg75840622011-09-06 13:48:16 -0400847 struct wl_shell *shell = data;
Kristian Høgsberg07937562011-04-12 17:25:42 -0400848 struct wlsc_surface *surface =
849 (struct wlsc_surface *) device->pointer_focus;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400850 struct wl_resource *resource;
Kristian Høgsberg07937562011-04-12 17:25:42 -0400851 uint32_t edges = 0;
852 int32_t x, y;
853
Kristian Høgsberga4a42f02011-09-08 16:56:57 -0400854 if (surface == NULL ||
855 surface->map_type == WLSC_SURFACE_MAP_FULLSCREEN)
Kristian Høgsberg75840622011-09-06 13:48:16 -0400856 if (surface == shell->panel)
857 return;
858 if (surface == shell->background)
859 return;
Kristian Høgsberg10f097e2011-04-13 11:52:54 -0400860
Kristian Høgsberg07937562011-04-12 17:25:42 -0400861 x = device->grab_x - surface->x;
862 y = device->grab_y - surface->y;
863
864 if (x < surface->width / 3)
865 edges |= WL_SHELL_RESIZE_LEFT;
866 else if (x < 2 * surface->width / 3)
867 edges |= 0;
868 else
869 edges |= WL_SHELL_RESIZE_RIGHT;
870
871 if (y < surface->height / 3)
872 edges |= WL_SHELL_RESIZE_TOP;
873 else if (y < 2 * surface->height / 3)
874 edges |= 0;
875 else
876 edges |= WL_SHELL_RESIZE_BOTTOM;
877
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400878 resource = /* Find shell resource for surface client */ 0;
879
880 /* ... or use wl_shell_surface */
881
882 wlsc_surface_resize(surface, (struct wlsc_input_device *) device,
883 time, edges, resource);
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400884}
885
886static void
Kristian Høgsberg75840622011-09-06 13:48:16 -0400887activate(struct wlsc_shell *base, struct wlsc_surface *es,
888 struct wlsc_input_device *device, uint32_t time)
889{
890 struct wl_shell *shell = container_of(base, struct wl_shell, shell);
891 struct wlsc_compositor *compositor = shell->compositor;
892
893 wlsc_surface_activate(es, device, time);
894
895 if (es == shell->background) {
896 wl_list_remove(&es->link);
897 wl_list_insert(compositor->surface_list.prev, &es->link);
898 } else if (shell->panel) {
899 wl_list_remove(&shell->panel->link);
900 wl_list_insert(&compositor->surface_list, &shell->panel->link);
901 }
902}
903
904static void
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400905lock(struct wlsc_shell *shell)
906{
907}
908
909static void
Kristian Høgsberg75840622011-09-06 13:48:16 -0400910attach(struct wlsc_shell *base, struct wlsc_surface *es)
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400911{
Kristian Høgsberg75840622011-09-06 13:48:16 -0400912 struct wl_shell *shell = container_of(base, struct wl_shell, shell);
913 struct wlsc_compositor *compositor = shell->compositor;
914
915 if (es == shell->background) {
916 wl_list_remove(&es->link);
917 wl_list_insert(compositor->surface_list.prev, &es->link);
918 } else if (es->map_type == WLSC_SURFACE_MAP_FULLSCREEN) {
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400919 es->x = (es->fullscreen_output->current->width - es->width) / 2;
920 es->y = (es->fullscreen_output->current->height - es->height) / 2;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400921 }
Kristian Høgsberg07937562011-04-12 17:25:42 -0400922}
923
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400924static void
925bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
926{
927 struct wl_shell *shell = data;
928
929 wl_client_add_object(client, &wl_shell_interface,
930 &shell_interface, id, shell);
931}
932
Kristian Høgsberg75840622011-09-06 13:48:16 -0400933static void
934bind_desktop_shell(struct wl_client *client,
935 void *data, uint32_t version, uint32_t id)
936{
937 struct wl_shell *shell = data;
938
939 wl_client_add_object(client, &desktop_shell_interface,
940 &desktop_shell_implementation, id, shell);
941}
942
Kristian Høgsberg6c709a32011-05-06 14:52:41 -0400943int
944shell_init(struct wlsc_compositor *ec);
945
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400946WL_EXPORT int
947shell_init(struct wlsc_compositor *ec)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500948{
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400949 struct wl_shell *shell;
950
951 shell = malloc(sizeof *shell);
952 if (shell == NULL)
953 return -1;
954
Kristian Høgsbergf0d91162011-10-11 22:44:23 -0400955 memset(shell, 0, sizeof *shell);
Kristian Høgsberg75840622011-09-06 13:48:16 -0400956 shell->compositor = ec;
957 shell->shell.activate = activate;
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400958 shell->shell.lock = lock;
959 shell->shell.attach = attach;
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400960 shell->shell.set_selection_focus = wlsc_selection_set_focus;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500961
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400962 if (wl_display_add_global(ec->wl_display, &wl_shell_interface,
963 shell, bind_shell) == NULL)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500964 return -1;
965
Kristian Høgsberg75840622011-09-06 13:48:16 -0400966 if (wl_display_add_global(ec->wl_display,
967 &desktop_shell_interface,
968 shell, bind_desktop_shell) == NULL)
969 return -1;
970
Kristian Høgsberg07937562011-04-12 17:25:42 -0400971 wlsc_compositor_add_binding(ec, 0, BTN_LEFT, MODIFIER_SUPER,
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400972 move_binding, shell);
Kristian Høgsberg07937562011-04-12 17:25:42 -0400973 wlsc_compositor_add_binding(ec, 0, BTN_MIDDLE, MODIFIER_SUPER,
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400974 resize_binding, shell);
975
976 ec->shell = &shell->shell;
Kristian Høgsberg07937562011-04-12 17:25:42 -0400977
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500978 return 0;
979}