blob: 50c80e9dc9e89f8d5027feca802fa9f5528cb83a [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
Pekka Paalanen02ebfb12011-10-24 17:34:53 +0300562 drag->resource.data = drag;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500563 drag->resource.destroy = destroy_drag;
564
565 drag->drag_focus_listener.func = drag_handle_surface_destroy;
566 wl_list_init(&drag->drag_focus_listener.link);
567
568 wl_client_add_resource(client, &drag->resource);
569}
570
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400571static void
572wlsc_selection_set_focus(struct wlsc_shell *shell,
573 struct wl_selection *selection,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500574 struct wl_surface *surface, uint32_t time)
575{
576 char **p, **end;
577
578 if (selection->selection_focus == surface)
579 return;
580
581 if (selection->selection_focus != NULL)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400582 wl_resource_post_event(&selection->selection_offer.resource,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500583 WL_SELECTION_OFFER_KEYBOARD_FOCUS,
584 NULL);
585
586 if (surface) {
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500587
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400588 selection->selection_offer.resource.client = surface->resource.client;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500589 end = selection->types.data + selection->types.size;
590 for (p = selection->types.data; p < end; p++)
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400591 wl_resource_post_event(&selection->selection_offer.resource,
592 WL_SELECTION_OFFER_OFFER, *p);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500593
594 wl_list_remove(&selection->selection_focus_listener.link);
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200595 wl_list_insert(surface->resource.destroy_listener_list.prev,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500596 &selection->selection_focus_listener.link);
597
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400598 wl_resource_post_event(&selection->selection_offer.resource,
599 WL_SELECTION_OFFER_KEYBOARD_FOCUS,
600 selection->input_device);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500601 }
602
603 selection->selection_focus = surface;
604
605 wl_list_remove(&selection->selection_focus_listener.link);
606 if (surface)
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200607 wl_list_insert(surface->resource.destroy_listener_list.prev,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500608 &selection->selection_focus_listener.link);
609}
610
611static void
612selection_offer_receive(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400613 struct wl_resource *resource,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500614 const char *mime_type, int fd)
615{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400616 struct wl_selection_offer *offer = resource->data;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500617 struct wl_selection *selection =
618 container_of(offer, struct wl_selection, selection_offer);
619
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400620 wl_resource_post_event(&selection->resource,
621 WL_SELECTION_SEND, mime_type, fd);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500622 close(fd);
623}
624
625static const struct wl_selection_offer_interface selection_offer_interface = {
626 selection_offer_receive
627};
628
629static void
630selection_offer(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400631 struct wl_resource *resource, const char *type)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500632{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400633 struct wl_selection *selection = resource->data;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500634 char **p;
635
636 p = wl_array_add(&selection->types, sizeof *p);
637 if (p)
638 *p = strdup(type);
639 if (!p || !*p)
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400640 wl_resource_post_no_memory(resource);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500641}
642
643static void
644selection_activate(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400645 struct wl_resource *resource,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400646 struct wl_resource *input_resource, uint32_t time)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500647{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400648 struct wl_selection *selection = resource->data;
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400649 struct wlsc_input_device *wd = input_resource->data;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500650 struct wl_display *display = wl_client_get_display (client);
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400651 struct wlsc_compositor *compositor =
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400652 (struct wlsc_compositor *) wd->input_device.compositor;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500653
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400654 selection->input_device = &wd->input_device;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500655
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400656 selection->selection_offer.resource.object.interface =
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500657 &wl_selection_offer_interface;
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400658 selection->selection_offer.resource.object.implementation =
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500659 (void (**)(void)) &selection_offer_interface;
660
Kristian Høgsbergd9551a32011-08-19 12:07:44 -0400661 wl_display_add_global(display,
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400662 &wl_selection_offer_interface, selection, NULL);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500663
664 if (wd->selection) {
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400665 wl_resource_post_event(&wd->selection->resource,
666 WL_SELECTION_CANCELLED);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500667 }
668 wd->selection = selection;
669
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400670 wlsc_selection_set_focus(compositor->shell, selection,
671 wd->input_device.keyboard_focus, time);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500672}
673
674static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400675selection_destroy(struct wl_client *client, struct wl_resource *resource)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500676{
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400677 wl_resource_destroy(resource, wlsc_compositor_get_time());
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500678}
679
680static const struct wl_selection_interface selection_interface = {
681 selection_offer,
682 selection_activate,
683 selection_destroy
684};
685
686static void
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400687destroy_selection(struct wl_resource *resource)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500688{
689 struct wl_selection *selection =
690 container_of(resource, struct wl_selection, resource);
691 struct wlsc_input_device *wd =
692 (struct wlsc_input_device *) selection->input_device;
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400693 struct wlsc_compositor *compositor =
694 (struct wlsc_compositor *) wd->input_device.compositor;
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500695
696 if (wd && wd->selection == selection) {
697 wd->selection = NULL;
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400698 wlsc_selection_set_focus(compositor->shell,
699 selection, NULL,
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400700 wlsc_compositor_get_time());
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500701 }
702
703 wl_list_remove(&selection->selection_focus_listener.link);
704 free(selection);
705}
706
707static void
708selection_handle_surface_destroy(struct wl_listener *listener,
Benjamin Franzke4721a3c2011-05-06 17:13:17 +0200709 struct wl_resource *resource, uint32_t time)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500710{
711}
712
713static void
714shell_create_selection(struct wl_client *client,
Kristian Høgsberg904055a2011-08-18 17:55:30 -0400715 struct wl_resource *resource, uint32_t id)
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500716{
717 struct wl_selection *selection;
718
719 selection = malloc(sizeof *selection);
720 if (selection == NULL) {
Kristian Høgsberg9ebcf942011-09-01 09:54:57 -0400721 wl_resource_post_no_memory(resource);
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500722 return;
723 }
724
725 memset(selection, 0, sizeof *selection);
726 selection->resource.object.id = id;
727 selection->resource.object.interface = &wl_selection_interface;
728 selection->resource.object.implementation =
729 (void (**)(void)) &selection_interface;
730
731 selection->client = client;
732 selection->resource.destroy = destroy_selection;
733 selection->selection_focus = NULL;
734
735 selection->selection_focus_listener.func =
736 selection_handle_surface_destroy;
737 wl_list_init(&selection->selection_focus_listener.link);
738
739 wl_client_add_resource(client, &selection->resource);
740}
741
Kristian Høgsberg75840622011-09-06 13:48:16 -0400742static const struct wl_shell_interface shell_interface = {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500743 shell_move,
744 shell_resize,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500745 shell_create_drag,
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400746 shell_create_selection,
747 shell_set_toplevel,
748 shell_set_transient,
749 shell_set_fullscreen
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500750};
751
Kristian Høgsberg07937562011-04-12 17:25:42 -0400752static void
Kristian Høgsberg75840622011-09-06 13:48:16 -0400753handle_background_surface_destroy(struct wl_listener *listener,
754 struct wl_resource *resource, uint32_t time)
755{
756 struct wl_shell *shell =
757 container_of(listener, struct wl_shell, background_listener);
758
759 fprintf(stderr, "background surface gone\n");
760 shell->background = NULL;
761}
762
763static void
764desktop_shell_set_background(struct wl_client *client,
765 struct wl_resource *resource,
766 struct wl_resource *surface_resource)
767{
768 struct wl_shell *shell = resource->data;
769 struct wlsc_surface *surface = surface_resource->data;
770 struct wlsc_output *output =
771 container_of(shell->compositor->output_list.next,
772 struct wlsc_output, link);
773
774 shell->background = surface_resource->data;
775 shell->background_listener.func = handle_background_surface_destroy;
776 wl_list_insert(&surface_resource->destroy_listener_list,
777 &shell->background_listener.link);
778
779 wl_resource_post_event(resource,
780 DESKTOP_SHELL_CONFIGURE,
781 wlsc_compositor_get_time(), 0, surface,
782 output->current->width,
783 output->current->height);
784}
785
786static void
787handle_panel_surface_destroy(struct wl_listener *listener,
788 struct wl_resource *resource, uint32_t time)
789{
790 struct wl_shell *shell =
791 container_of(listener, struct wl_shell, panel_listener);
792
793 fprintf(stderr, "panel surface gone\n");
794 shell->panel = NULL;
795}
796
797static void
798desktop_shell_set_panel(struct wl_client *client,
799 struct wl_resource *resource,
800 struct wl_resource *surface_resource)
801{
802 struct wl_shell *shell = resource->data;
803 struct wlsc_output *output =
804 container_of(shell->compositor->output_list.next,
805 struct wlsc_output, link);
806
807 shell->panel = surface_resource->data;
808
809 shell->panel_listener.func = handle_panel_surface_destroy;
810 wl_list_insert(&surface_resource->destroy_listener_list,
811 &shell->panel_listener.link);
812
813 wl_resource_post_event(resource,
814 DESKTOP_SHELL_CONFIGURE,
815 wlsc_compositor_get_time(), 0, surface_resource,
816 output->current->width,
817 output->current->height);
818}
819
820static const struct desktop_shell_interface desktop_shell_implementation = {
821 desktop_shell_set_background,
822 desktop_shell_set_panel
823};
824
825static void
Kristian Høgsberg07937562011-04-12 17:25:42 -0400826move_binding(struct wl_input_device *device, uint32_t time,
827 uint32_t key, uint32_t button, uint32_t state, void *data)
828{
Kristian Høgsberg75840622011-09-06 13:48:16 -0400829 struct wl_shell *shell = data;
Kristian Høgsberg07937562011-04-12 17:25:42 -0400830 struct wlsc_surface *surface =
831 (struct wlsc_surface *) device->pointer_focus;
832
Kristian Høgsberga4a42f02011-09-08 16:56:57 -0400833 if (surface == NULL ||
834 surface->map_type == WLSC_SURFACE_MAP_FULLSCREEN)
Kristian Høgsberg10f097e2011-04-13 11:52:54 -0400835 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øgsberga4a42f02011-09-08 16:56:57 -0400855 if (surface == NULL ||
856 surface->map_type == WLSC_SURFACE_MAP_FULLSCREEN)
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
Kristian Høgsbergd6e55252011-10-11 23:41:17 -0400896 if (compositor->wxs)
897 wlsc_xserver_surface_activate(es);
898
Kristian Høgsberg75840622011-09-06 13:48:16 -0400899 if (es == shell->background) {
900 wl_list_remove(&es->link);
901 wl_list_insert(compositor->surface_list.prev, &es->link);
902 } else if (shell->panel) {
903 wl_list_remove(&shell->panel->link);
904 wl_list_insert(&compositor->surface_list, &shell->panel->link);
905 }
906}
907
908static void
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400909lock(struct wlsc_shell *shell)
910{
911}
912
913static void
Kristian Høgsberg75840622011-09-06 13:48:16 -0400914attach(struct wlsc_shell *base, struct wlsc_surface *es)
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400915{
Kristian Høgsberg75840622011-09-06 13:48:16 -0400916 struct wl_shell *shell = container_of(base, struct wl_shell, shell);
917 struct wlsc_compositor *compositor = shell->compositor;
918
919 if (es == shell->background) {
920 wl_list_remove(&es->link);
921 wl_list_insert(compositor->surface_list.prev, &es->link);
922 } else if (es->map_type == WLSC_SURFACE_MAP_FULLSCREEN) {
Kristian Høgsberg8f0ce052011-06-21 11:16:58 -0400923 es->x = (es->fullscreen_output->current->width - es->width) / 2;
924 es->y = (es->fullscreen_output->current->height - es->height) / 2;
Kristian Høgsberg7a5c9792011-06-18 06:12:54 -0400925 }
Kristian Høgsberg07937562011-04-12 17:25:42 -0400926}
927
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400928static void
929bind_shell(struct wl_client *client, void *data, uint32_t version, uint32_t id)
930{
931 struct wl_shell *shell = data;
932
933 wl_client_add_object(client, &wl_shell_interface,
934 &shell_interface, id, shell);
935}
936
Kristian Høgsberg75840622011-09-06 13:48:16 -0400937static void
938bind_desktop_shell(struct wl_client *client,
939 void *data, uint32_t version, uint32_t id)
940{
941 struct wl_shell *shell = data;
942
943 wl_client_add_object(client, &desktop_shell_interface,
944 &desktop_shell_implementation, id, shell);
945}
946
Kristian Høgsberg6c709a32011-05-06 14:52:41 -0400947int
948shell_init(struct wlsc_compositor *ec);
949
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400950WL_EXPORT int
951shell_init(struct wlsc_compositor *ec)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500952{
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400953 struct wl_shell *shell;
954
955 shell = malloc(sizeof *shell);
956 if (shell == NULL)
957 return -1;
958
Kristian Høgsbergf0d91162011-10-11 22:44:23 -0400959 memset(shell, 0, sizeof *shell);
Kristian Høgsberg75840622011-09-06 13:48:16 -0400960 shell->compositor = ec;
961 shell->shell.activate = activate;
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400962 shell->shell.lock = lock;
963 shell->shell.attach = attach;
Kristian Høgsberg1c562182011-05-02 22:09:20 -0400964 shell->shell.set_selection_focus = wlsc_selection_set_focus;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500965
Kristian Høgsberg97d44aa2011-08-26 17:21:20 -0400966 if (wl_display_add_global(ec->wl_display, &wl_shell_interface,
967 shell, bind_shell) == NULL)
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500968 return -1;
969
Kristian Høgsberg75840622011-09-06 13:48:16 -0400970 if (wl_display_add_global(ec->wl_display,
971 &desktop_shell_interface,
972 shell, bind_desktop_shell) == NULL)
973 return -1;
974
Kristian Høgsberg07937562011-04-12 17:25:42 -0400975 wlsc_compositor_add_binding(ec, 0, BTN_LEFT, MODIFIER_SUPER,
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400976 move_binding, shell);
Kristian Høgsberg07937562011-04-12 17:25:42 -0400977 wlsc_compositor_add_binding(ec, 0, BTN_MIDDLE, MODIFIER_SUPER,
Kristian Høgsberg02ec0a52011-04-23 13:04:11 -0400978 resize_binding, shell);
979
980 ec->shell = &shell->shell;
Kristian Høgsberg07937562011-04-12 17:25:42 -0400981
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500982 return 0;
983}