blob: 393dfee435fe3eb8dc8c95cf908504d9f2ee3e90 [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
Kristian Høgsberg0ce24572011-01-28 15:18:33 -050083 /* FIXME: Reject if fullscreen */
84
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050085 move = malloc(sizeof *move);
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -040086 if (!move)
87 return -1;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050088
89 move->grab.interface = &move_grab_interface;
90 move->dx = es->x - wd->input_device.grab_x;
91 move->dy = es->y - wd->input_device.grab_y;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -050092 move->surface = es;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050093
94 if (wl_input_device_update_grab(&wd->input_device,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -040095 &move->grab, &es->surface, time) < 0)
96 return 0;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050097
98 wlsc_input_device_set_pointer_image(wd, WLSC_POINTER_DRAGGING);
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -040099 wl_input_device_set_pointer_focus(&wd->input_device,
100 NULL, time, 0, 0, 0, 0);
101
102 return 0;
103}
104
105static void
106shell_move(struct wl_client *client, struct wl_resource *resource,
107 struct wl_resource *surface_resource,
108 struct wl_resource *input_resource, uint32_t time)
109{
110 struct wlsc_input_device *wd = input_resource->data;
111 struct wlsc_surface *es = surface_resource->data;
112
113 if (wlsc_surface_move(es, wd, time) < 0)
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400114 wl_resource_post_no_memory(resource);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500115}
116
117struct wlsc_resize_grab {
118 struct wl_grab grab;
119 uint32_t edges;
120 int32_t dx, dy, width, height;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500121 struct wlsc_surface *surface;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400122 struct wl_resource *resource;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500123};
124
125static void
126resize_grab_motion(struct wl_grab *grab,
127 uint32_t time, int32_t x, int32_t y)
128{
129 struct wlsc_resize_grab *resize = (struct wlsc_resize_grab *) grab;
130 struct wl_input_device *device = grab->input_device;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500131 struct wl_surface *surface = &resize->surface->surface;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500132 int32_t width, height;
133
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500134 if (resize->edges & WL_SHELL_RESIZE_LEFT) {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500135 width = device->grab_x - x + resize->width;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500136 } else if (resize->edges & WL_SHELL_RESIZE_RIGHT) {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500137 width = x - device->grab_x + resize->width;
138 } else {
139 width = resize->width;
140 }
141
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500142 if (resize->edges & WL_SHELL_RESIZE_TOP) {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500143 height = device->grab_y - y + resize->height;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500144 } else if (resize->edges & WL_SHELL_RESIZE_BOTTOM) {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500145 height = y - device->grab_y + resize->height;
146 } else {
147 height = resize->height;
148 }
149
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400150 wl_resource_post_event(resize->resource,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400151 WL_SHELL_CONFIGURE, time, resize->edges,
152 surface, width, height);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500153}
154
155static void
156resize_grab_button(struct wl_grab *grab,
157 uint32_t time, int32_t button, int32_t state)
158{
159}
160
161static void
162resize_grab_end(struct wl_grab *grab, uint32_t time)
163{
164 free(grab);
165}
166
167static const struct wl_grab_interface resize_grab_interface = {
168 resize_grab_motion,
169 resize_grab_button,
170 resize_grab_end
171};
172
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400173static int
174wlsc_surface_resize(struct wlsc_surface *es,
175 struct wlsc_input_device *wd,
176 uint32_t time, uint32_t edges,
177 struct wl_resource *resource)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500178{
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500179 struct wlsc_resize_grab *resize;
180 enum wlsc_pointer_type pointer = WLSC_POINTER_LEFT_PTR;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500181
Kristian Høgsberg0ce24572011-01-28 15:18:33 -0500182 /* FIXME: Reject if fullscreen */
183
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500184 resize = malloc(sizeof *resize);
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400185 if (!resize)
186 return -1;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500187
188 resize->grab.interface = &resize_grab_interface;
189 resize->edges = edges;
190 resize->dx = es->x - wd->input_device.grab_x;
191 resize->dy = es->y - wd->input_device.grab_y;
192 resize->width = es->width;
193 resize->height = es->height;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500194 resize->surface = es;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400195 resize->resource = resource;
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400196
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500197 if (edges == 0 || edges > 15 ||
198 (edges & 3) == 3 || (edges & 12) == 12)
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400199 return 0;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500200
201 switch (edges) {
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500202 case WL_SHELL_RESIZE_TOP:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500203 pointer = WLSC_POINTER_TOP;
204 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500205 case WL_SHELL_RESIZE_BOTTOM:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500206 pointer = WLSC_POINTER_BOTTOM;
207 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500208 case WL_SHELL_RESIZE_LEFT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500209 pointer = WLSC_POINTER_LEFT;
210 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500211 case WL_SHELL_RESIZE_TOP_LEFT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500212 pointer = WLSC_POINTER_TOP_LEFT;
213 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500214 case WL_SHELL_RESIZE_BOTTOM_LEFT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500215 pointer = WLSC_POINTER_BOTTOM_LEFT;
216 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500217 case WL_SHELL_RESIZE_RIGHT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500218 pointer = WLSC_POINTER_RIGHT;
219 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500220 case WL_SHELL_RESIZE_TOP_RIGHT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500221 pointer = WLSC_POINTER_TOP_RIGHT;
222 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500223 case WL_SHELL_RESIZE_BOTTOM_RIGHT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500224 pointer = WLSC_POINTER_BOTTOM_RIGHT;
225 break;
226 }
227
228 if (wl_input_device_update_grab(&wd->input_device,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400229 &resize->grab, &es->surface, time) < 0)
230 return 0;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500231
232 wlsc_input_device_set_pointer_image(wd, pointer);
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400233 wl_input_device_set_pointer_focus(&wd->input_device,
234 NULL, time, 0, 0, 0, 0);
235
236 return 0;
237}
238
239static void
240shell_resize(struct wl_client *client, struct wl_resource *resource,
241 struct wl_resource *surface_resource,
242 struct wl_resource *input_resource, uint32_t time, uint32_t edges)
243{
244 struct wlsc_input_device *wd = input_resource->data;
245 struct wlsc_surface *es = surface_resource->data;
246
247 /* FIXME: Reject if fullscreen */
248
249 if (wlsc_surface_resize(es, wd, time, edges, resource) < 0)
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400250 wl_resource_post_no_memory(resource);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500251}
252
253static void
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400254shell_set_toplevel(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400255 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400256 struct wl_resource *surface_resource)
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400257
258{
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400259 struct wlsc_surface *es = surface_resource->data;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400260 struct wlsc_compositor *ec = es->compositor;
261
262 if (es->map_type == WLSC_SURFACE_MAP_FULLSCREEN) {
263 es->x = es->saved_x;
264 es->y = es->saved_y;
265 } else if (es->map_type == WLSC_SURFACE_MAP_UNMAPPED) {
266 es->x = 10 + random() % 400;
267 es->y = 10 + random() % 400;
268 /* assign to first output */
269 es->output = container_of(ec->output_list.next,
270 struct wlsc_output, link);
271 }
272
273 wlsc_surface_damage(es);
274 es->map_type = WLSC_SURFACE_MAP_TOPLEVEL;
275 es->fullscreen_output = NULL;
276}
277
278static void
279shell_set_transient(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400280 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400281 struct wl_resource *surface_resource,
282 struct wl_resource *parent_resource,
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400283 int x, int y, uint32_t flags)
284{
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400285 struct wlsc_surface *es = surface_resource->data;
286 struct wlsc_surface *pes = parent_resource->data;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400287
288 /* assign to parents output */
289 es->output = pes->output;
290
291 es->x = pes->x + x;
292 es->y = pes->y + y;
293
294 wlsc_surface_damage(es);
295 es->map_type = WLSC_SURFACE_MAP_TRANSIENT;
296}
297
298static void
299shell_set_fullscreen(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400300 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400301 struct wl_resource *surface_resource)
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400302
303{
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400304 struct wlsc_surface *es = surface_resource->data;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400305 struct wlsc_output *output;
306
307 /* FIXME: Fullscreen on first output */
308 /* FIXME: Handle output going away */
309 output = container_of(es->compositor->output_list.next,
310 struct wlsc_output, link);
311 es->output = output;
312
313 es->saved_x = es->x;
314 es->saved_y = es->y;
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400315 es->x = (output->current->width - es->width) / 2;
316 es->y = (output->current->height - es->height) / 2;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400317 es->fullscreen_output = output;
318 wlsc_surface_damage(es);
319 es->map_type = WLSC_SURFACE_MAP_FULLSCREEN;
320}
321
322static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400323destroy_drag(struct wl_resource *resource)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500324{
325 struct wl_drag *drag =
326 container_of(resource, struct wl_drag, resource);
327
328 wl_list_remove(&drag->drag_focus_listener.link);
329 if (drag->grab.input_device)
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400330 wl_input_device_end_grab(drag->grab.input_device,
331 wlsc_compositor_get_time());
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500332
333 free(drag);
334}
335
336
337static void
338wl_drag_set_pointer_focus(struct wl_drag *drag,
339 struct wl_surface *surface, uint32_t time,
340 int32_t x, int32_t y, int32_t sx, int32_t sy)
341{
342 char **p, **end;
343
344 if (drag->drag_focus == surface)
345 return;
346
347 if (drag->drag_focus &&
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400348 (!surface ||
349 drag->drag_focus->resource.client != surface->resource.client))
350 wl_resource_post_event(&drag->drag_offer.resource,
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500351 WL_DRAG_OFFER_POINTER_FOCUS,
352 time, NULL, 0, 0, 0, 0);
353
354 if (surface &&
355 (!drag->drag_focus ||
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400356 drag->drag_focus->resource.client != surface->resource.client)) {
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400357
358 drag->drag_offer.resource.client = surface->resource.client;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500359 end = drag->types.data + drag->types.size;
360 for (p = drag->types.data; p < end; p++)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400361 wl_resource_post_event(&drag->drag_offer.resource,
362 WL_DRAG_OFFER_OFFER, *p);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500363 }
364
365 if (surface) {
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400366 wl_resource_post_event(&drag->drag_offer.resource,
367 WL_DRAG_OFFER_POINTER_FOCUS,
368 time, surface,
369 x, y, sx, sy);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500370
371 }
372
373 drag->drag_focus = surface;
374 drag->pointer_focus_time = time;
375 drag->target = NULL;
376
377 wl_list_remove(&drag->drag_focus_listener.link);
378 if (surface)
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200379 wl_list_insert(surface->resource.destroy_listener_list.prev,
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500380 &drag->drag_focus_listener.link);
381}
382
383static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400384drag_offer_accept(struct wl_client *client, struct wl_resource *resource,
385 uint32_t time, const char *type)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500386{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400387 struct wl_drag_offer *offer = resource->data;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500388 struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer);
389 char **p, **end;
390
391 /* If the client responds to drag pointer_focus or motion
392 * events after the pointer has left the surface, we just
393 * discard the accept requests. The drag source just won't
394 * get the corresponding 'target' events and eventually the
395 * next surface/root will start sending events. */
396 if (time < drag->pointer_focus_time)
397 return;
398
399 drag->target = client;
400 drag->type = NULL;
401 end = drag->types.data + drag->types.size;
402 for (p = drag->types.data; p < end; p++)
403 if (type && strcmp(*p, type) == 0)
404 drag->type = *p;
405
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400406 wl_resource_post_event(&drag->resource, WL_DRAG_TARGET, drag->type);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500407}
408
409static void
410drag_offer_receive(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400411 struct wl_resource *resource, int fd)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500412{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400413 struct wl_drag_offer *offer = resource->data;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500414 struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer);
415
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400416 wl_resource_post_event(&drag->resource, WL_DRAG_FINISH, fd);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500417 close(fd);
418}
419
420static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400421drag_offer_reject(struct wl_client *client, struct wl_resource *resource)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500422{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400423 struct wl_drag_offer *offer = resource->data;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500424 struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer);
425
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400426 wl_resource_post_event(&drag->resource, WL_DRAG_REJECT);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500427}
428
429static const struct wl_drag_offer_interface drag_offer_interface = {
430 drag_offer_accept,
431 drag_offer_receive,
432 drag_offer_reject
433};
434
435static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400436drag_offer(struct wl_client *client,
437 struct wl_resource *resource, const char *type)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500438{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400439 struct wl_drag *drag = resource->data;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500440 char **p;
441
442 p = wl_array_add(&drag->types, sizeof *p);
443 if (p)
444 *p = strdup(type);
445 if (!p || !*p)
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400446 wl_resource_post_no_memory(resource);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500447}
448
449static void
450drag_grab_motion(struct wl_grab *grab,
451 uint32_t time, int32_t x, int32_t y)
452{
453 struct wl_drag *drag = container_of(grab, struct wl_drag, grab);
454 struct wlsc_surface *es;
455 int32_t sx, sy;
456
457 es = pick_surface(grab->input_device, &sx, &sy);
458 wl_drag_set_pointer_focus(drag, &es->surface, time, x, y, sx, sy);
459 if (es)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400460 wl_resource_post_event(&drag->drag_offer.resource,
461 WL_DRAG_OFFER_MOTION,
462 time, x, y, sx, sy);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500463}
464
465static void
466drag_grab_button(struct wl_grab *grab,
467 uint32_t time, int32_t button, int32_t state)
468{
469}
470
471static void
472drag_grab_end(struct wl_grab *grab, uint32_t time)
473{
474 struct wl_drag *drag = container_of(grab, struct wl_drag, grab);
475
476 if (drag->target)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400477 wl_resource_post_event(&drag->drag_offer.resource,
478 WL_DRAG_OFFER_DROP);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500479
480 wl_drag_set_pointer_focus(drag, NULL, time, 0, 0, 0, 0);
481}
482
483static const struct wl_grab_interface drag_grab_interface = {
484 drag_grab_motion,
485 drag_grab_button,
486 drag_grab_end
487};
488
489static void
490drag_activate(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400491 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400492 struct wl_resource *surface_resource,
493 struct wl_resource *device_resource, uint32_t time)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500494{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400495 struct wl_drag *drag = resource->data;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400496 struct wl_surface *surface = surface_resource->data;
497 struct wl_input_device *device = device_resource->data;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500498 struct wl_display *display = wl_client_get_display (client);
499 struct wlsc_surface *target;
500 int32_t sx, sy;
501
502 if (wl_input_device_update_grab(device,
503 &drag->grab, surface, time) < 0)
504 return;
505
506 drag->grab.interface = &drag_grab_interface;
507
508 drag->source = surface;
509
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400510 drag->drag_offer.resource.object.interface = &wl_drag_offer_interface;
511 drag->drag_offer.resource.object.implementation =
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500512 (void (**)(void)) &drag_offer_interface;
513
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400514 wl_display_add_global(display, &wl_drag_offer_interface, drag, NULL);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500515
516 target = pick_surface(device, &sx, &sy);
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500517 wl_input_device_set_pointer_focus(device, NULL, time, 0, 0, 0, 0);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500518 wl_drag_set_pointer_focus(drag, &target->surface, time,
519 device->x, device->y, sx, sy);
520}
521
522static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400523drag_destroy(struct wl_client *client, struct wl_resource *resource)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500524{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400525 wl_resource_destroy(resource, wlsc_compositor_get_time());
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500526}
527
528static const struct wl_drag_interface drag_interface = {
529 drag_offer,
530 drag_activate,
531 drag_destroy,
532};
533
534static void
535drag_handle_surface_destroy(struct wl_listener *listener,
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200536 struct wl_resource *resource, uint32_t time)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500537{
538 struct wl_drag *drag =
539 container_of(listener, struct wl_drag, drag_focus_listener);
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200540 struct wl_surface *surface = (struct wl_surface *) resource;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500541
542 if (drag->drag_focus == surface)
543 wl_drag_set_pointer_focus(drag, NULL, time, 0, 0, 0, 0);
544}
545
546static void
547shell_create_drag(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400548 struct wl_resource *resource, uint32_t id)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500549{
550 struct wl_drag *drag;
551
552 drag = malloc(sizeof *drag);
553 if (drag == NULL) {
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400554 wl_resource_post_no_memory(resource);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500555 return;
556 }
557
558 memset(drag, 0, sizeof *drag);
559 drag->resource.object.id = id;
560 drag->resource.object.interface = &wl_drag_interface;
561 drag->resource.object.implementation =
562 (void (**)(void)) &drag_interface;
563
564 drag->resource.destroy = destroy_drag;
565
566 drag->drag_focus_listener.func = drag_handle_surface_destroy;
567 wl_list_init(&drag->drag_focus_listener.link);
568
569 wl_client_add_resource(client, &drag->resource);
570}
571
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400572static void
573wlsc_selection_set_focus(struct wlsc_shell *shell,
574 struct wl_selection *selection,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500575 struct wl_surface *surface, uint32_t time)
576{
577 char **p, **end;
578
579 if (selection->selection_focus == surface)
580 return;
581
582 if (selection->selection_focus != NULL)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400583 wl_resource_post_event(&selection->selection_offer.resource,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500584 WL_SELECTION_OFFER_KEYBOARD_FOCUS,
585 NULL);
586
587 if (surface) {
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500588
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400589 selection->selection_offer.resource.client = surface->resource.client;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500590 end = selection->types.data + selection->types.size;
591 for (p = selection->types.data; p < end; p++)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400592 wl_resource_post_event(&selection->selection_offer.resource,
593 WL_SELECTION_OFFER_OFFER, *p);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500594
595 wl_list_remove(&selection->selection_focus_listener.link);
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200596 wl_list_insert(surface->resource.destroy_listener_list.prev,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500597 &selection->selection_focus_listener.link);
598
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400599 wl_resource_post_event(&selection->selection_offer.resource,
600 WL_SELECTION_OFFER_KEYBOARD_FOCUS,
601 selection->input_device);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500602 }
603
604 selection->selection_focus = surface;
605
606 wl_list_remove(&selection->selection_focus_listener.link);
607 if (surface)
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200608 wl_list_insert(surface->resource.destroy_listener_list.prev,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500609 &selection->selection_focus_listener.link);
610}
611
612static void
613selection_offer_receive(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400614 struct wl_resource *resource,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500615 const char *mime_type, int fd)
616{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400617 struct wl_selection_offer *offer = resource->data;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500618 struct wl_selection *selection =
619 container_of(offer, struct wl_selection, selection_offer);
620
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400621 wl_resource_post_event(&selection->resource,
622 WL_SELECTION_SEND, mime_type, fd);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500623 close(fd);
624}
625
626static const struct wl_selection_offer_interface selection_offer_interface = {
627 selection_offer_receive
628};
629
630static void
631selection_offer(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400632 struct wl_resource *resource, const char *type)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500633{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400634 struct wl_selection *selection = resource->data;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500635 char **p;
636
637 p = wl_array_add(&selection->types, sizeof *p);
638 if (p)
639 *p = strdup(type);
640 if (!p || !*p)
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400641 wl_resource_post_no_memory(resource);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500642}
643
644static void
645selection_activate(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400646 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400647 struct wl_resource *input_resource, uint32_t time)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500648{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400649 struct wl_selection *selection = resource->data;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400650 struct wlsc_input_device *wd = input_resource->data;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500651 struct wl_display *display = wl_client_get_display (client);
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400652 struct wlsc_compositor *compositor =
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400653 (struct wlsc_compositor *) wd->input_device.compositor;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500654
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400655 selection->input_device = &wd->input_device;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500656
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400657 selection->selection_offer.resource.object.interface =
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500658 &wl_selection_offer_interface;
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400659 selection->selection_offer.resource.object.implementation =
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500660 (void (**)(void)) &selection_offer_interface;
661
Kristian Høgsbergd9551a32011-08-19 12:07:44 -0400662 wl_display_add_global(display,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400663 &wl_selection_offer_interface, selection, NULL);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500664
665 if (wd->selection) {
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400666 wl_resource_post_event(&wd->selection->resource,
667 WL_SELECTION_CANCELLED);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500668 }
669 wd->selection = selection;
670
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400671 wlsc_selection_set_focus(compositor->shell, selection,
672 wd->input_device.keyboard_focus, time);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500673}
674
675static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400676selection_destroy(struct wl_client *client, struct wl_resource *resource)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500677{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400678 wl_resource_destroy(resource, wlsc_compositor_get_time());
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500679}
680
681static const struct wl_selection_interface selection_interface = {
682 selection_offer,
683 selection_activate,
684 selection_destroy
685};
686
687static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400688destroy_selection(struct wl_resource *resource)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500689{
690 struct wl_selection *selection =
691 container_of(resource, struct wl_selection, resource);
692 struct wlsc_input_device *wd =
693 (struct wlsc_input_device *) selection->input_device;
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400694 struct wlsc_compositor *compositor =
695 (struct wlsc_compositor *) wd->input_device.compositor;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500696
697 if (wd && wd->selection == selection) {
698 wd->selection = NULL;
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400699 wlsc_selection_set_focus(compositor->shell,
700 selection, NULL,
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400701 wlsc_compositor_get_time());
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500702 }
703
704 wl_list_remove(&selection->selection_focus_listener.link);
705 free(selection);
706}
707
708static void
709selection_handle_surface_destroy(struct wl_listener *listener,
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200710 struct wl_resource *resource, uint32_t time)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500711{
712}
713
714static void
715shell_create_selection(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400716 struct wl_resource *resource, uint32_t id)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500717{
718 struct wl_selection *selection;
719
720 selection = malloc(sizeof *selection);
721 if (selection == NULL) {
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400722 wl_resource_post_no_memory(resource);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500723 return;
724 }
725
726 memset(selection, 0, sizeof *selection);
727 selection->resource.object.id = id;
728 selection->resource.object.interface = &wl_selection_interface;
729 selection->resource.object.implementation =
730 (void (**)(void)) &selection_interface;
731
732 selection->client = client;
733 selection->resource.destroy = destroy_selection;
734 selection->selection_focus = NULL;
735
736 selection->selection_focus_listener.func =
737 selection_handle_surface_destroy;
738 wl_list_init(&selection->selection_focus_listener.link);
739
740 wl_client_add_resource(client, &selection->resource);
741}
742
Kristian Høgsberg75840622011-09-06 13:48:16 -0400743static const struct wl_shell_interface shell_interface = {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500744 shell_move,
745 shell_resize,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500746 shell_create_drag,
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400747 shell_create_selection,
748 shell_set_toplevel,
749 shell_set_transient,
750 shell_set_fullscreen
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500751};
752
Kristian Høgsberg07937562011-04-12 17:25:42 -0400753static void
Kristian Høgsberg75840622011-09-06 13:48:16 -0400754handle_background_surface_destroy(struct wl_listener *listener,
755 struct wl_resource *resource, uint32_t time)
756{
757 struct wl_shell *shell =
758 container_of(listener, struct wl_shell, background_listener);
759
760 fprintf(stderr, "background surface gone\n");
761 shell->background = NULL;
762}
763
764static void
765desktop_shell_set_background(struct wl_client *client,
766 struct wl_resource *resource,
767 struct wl_resource *surface_resource)
768{
769 struct wl_shell *shell = resource->data;
770 struct wlsc_surface *surface = surface_resource->data;
771 struct wlsc_output *output =
772 container_of(shell->compositor->output_list.next,
773 struct wlsc_output, link);
774
775 shell->background = surface_resource->data;
776 shell->background_listener.func = handle_background_surface_destroy;
777 wl_list_insert(&surface_resource->destroy_listener_list,
778 &shell->background_listener.link);
779
780 wl_resource_post_event(resource,
781 DESKTOP_SHELL_CONFIGURE,
782 wlsc_compositor_get_time(), 0, surface,
783 output->current->width,
784 output->current->height);
785}
786
787static void
788handle_panel_surface_destroy(struct wl_listener *listener,
789 struct wl_resource *resource, uint32_t time)
790{
791 struct wl_shell *shell =
792 container_of(listener, struct wl_shell, panel_listener);
793
794 fprintf(stderr, "panel surface gone\n");
795 shell->panel = NULL;
796}
797
798static void
799desktop_shell_set_panel(struct wl_client *client,
800 struct wl_resource *resource,
801 struct wl_resource *surface_resource)
802{
803 struct wl_shell *shell = resource->data;
804 struct wlsc_output *output =
805 container_of(shell->compositor->output_list.next,
806 struct wlsc_output, link);
807
808 shell->panel = surface_resource->data;
809
810 shell->panel_listener.func = handle_panel_surface_destroy;
811 wl_list_insert(&surface_resource->destroy_listener_list,
812 &shell->panel_listener.link);
813
814 wl_resource_post_event(resource,
815 DESKTOP_SHELL_CONFIGURE,
816 wlsc_compositor_get_time(), 0, surface_resource,
817 output->current->width,
818 output->current->height);
819}
820
821static const struct desktop_shell_interface desktop_shell_implementation = {
822 desktop_shell_set_background,
823 desktop_shell_set_panel
824};
825
826static void
Kristian Høgsberg07937562011-04-12 17:25:42 -0400827move_binding(struct wl_input_device *device, uint32_t time,
828 uint32_t key, uint32_t button, uint32_t state, void *data)
829{
Kristian Høgsberg75840622011-09-06 13:48:16 -0400830 struct wl_shell *shell = data;
Kristian Høgsberg07937562011-04-12 17:25:42 -0400831 struct wlsc_surface *surface =
832 (struct wlsc_surface *) device->pointer_focus;
833
Kristian Høgsberg10f097e2011-04-13 11:52:54 -0400834 if (surface == NULL)
835 return;
Kristian Høgsberg75840622011-09-06 13:48:16 -0400836 if (surface == shell->panel)
837 return;
838 if (surface == shell->background)
839 return;
Kristian Høgsberg10f097e2011-04-13 11:52:54 -0400840
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400841 wlsc_surface_move(surface, (struct wlsc_input_device *) device, time);
Kristian Høgsberg07937562011-04-12 17:25:42 -0400842}
843
844static void
845resize_binding(struct wl_input_device *device, uint32_t time,
846 uint32_t key, uint32_t button, uint32_t state, void *data)
847{
Kristian Høgsberg75840622011-09-06 13:48:16 -0400848 struct wl_shell *shell = data;
Kristian Høgsberg07937562011-04-12 17:25:42 -0400849 struct wlsc_surface *surface =
850 (struct wlsc_surface *) device->pointer_focus;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400851 struct wl_resource *resource;
Kristian Høgsberg07937562011-04-12 17:25:42 -0400852 uint32_t edges = 0;
853 int32_t x, y;
854
Kristian Høgsberg10f097e2011-04-13 11:52:54 -0400855 if (surface == NULL)
856 return;
Kristian Høgsberg75840622011-09-06 13:48:16 -0400857 if (surface == shell->panel)
858 return;
859 if (surface == shell->background)
860 return;
Kristian Høgsberg10f097e2011-04-13 11:52:54 -0400861
Kristian Høgsberg07937562011-04-12 17:25:42 -0400862 x = device->grab_x - surface->x;
863 y = device->grab_y - surface->y;
864
865 if (x < surface->width / 3)
866 edges |= WL_SHELL_RESIZE_LEFT;
867 else if (x < 2 * surface->width / 3)
868 edges |= 0;
869 else
870 edges |= WL_SHELL_RESIZE_RIGHT;
871
872 if (y < surface->height / 3)
873 edges |= WL_SHELL_RESIZE_TOP;
874 else if (y < 2 * surface->height / 3)
875 edges |= 0;
876 else
877 edges |= WL_SHELL_RESIZE_BOTTOM;
878
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400879 resource = /* Find shell resource for surface client */ 0;
880
881 /* ... or use wl_shell_surface */
882
883 wlsc_surface_resize(surface, (struct wlsc_input_device *) device,
884 time, edges, resource);
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400885}
886
887static void
Kristian Høgsberg75840622011-09-06 13:48:16 -0400888activate(struct wlsc_shell *base, struct wlsc_surface *es,
889 struct wlsc_input_device *device, uint32_t time)
890{
891 struct wl_shell *shell = container_of(base, struct wl_shell, shell);
892 struct wlsc_compositor *compositor = shell->compositor;
893
894 wlsc_surface_activate(es, device, time);
895
896 if (es == shell->background) {
897 wl_list_remove(&es->link);
898 wl_list_insert(compositor->surface_list.prev, &es->link);
899 } else if (shell->panel) {
900 wl_list_remove(&shell->panel->link);
901 wl_list_insert(&compositor->surface_list, &shell->panel->link);
902 }
903}
904
905static void
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400906lock(struct wlsc_shell *shell)
907{
908}
909
910static void
Kristian Høgsberg75840622011-09-06 13:48:16 -0400911attach(struct wlsc_shell *base, struct wlsc_surface *es)
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400912{
Kristian Høgsberg75840622011-09-06 13:48:16 -0400913 struct wl_shell *shell = container_of(base, struct wl_shell, shell);
914 struct wlsc_compositor *compositor = shell->compositor;
915
916 if (es == shell->background) {
917 wl_list_remove(&es->link);
918 wl_list_insert(compositor->surface_list.prev, &es->link);
919 } else if (es->map_type == WLSC_SURFACE_MAP_FULLSCREEN) {
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400920 es->x = (es->fullscreen_output->current->width - es->width) / 2;
921 es->y = (es->fullscreen_output->current->height - es->height) / 2;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400922 }
Kristian Høgsberg07937562011-04-12 17:25:42 -0400923}
924
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400925static void
926bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
927{
928 struct wl_shell *shell = data;
929
930 wl_client_add_object(client, &wl_shell_interface,
931 &shell_interface, id, shell);
932}
933
Kristian Høgsberg75840622011-09-06 13:48:16 -0400934static void
935bind_desktop_shell(struct wl_client *client,
936 void *data, uint32_t version, uint32_t id)
937{
938 struct wl_shell *shell = data;
939
940 wl_client_add_object(client, &desktop_shell_interface,
941 &desktop_shell_implementation, id, shell);
942}
943
Kristian Høgsberg6c709a32011-05-06 14:52:41 -0400944int
945shell_init(struct wlsc_compositor *ec);
946
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400947WL_EXPORT int
948shell_init(struct wlsc_compositor *ec)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500949{
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400950 struct wl_shell *shell;
951
952 shell = malloc(sizeof *shell);
953 if (shell == NULL)
954 return -1;
955
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}