blob: c480e9ae3b1df88221dcd864e1c5463505927928 [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>
24#include <string.h>
25#include <unistd.h>
Kristian Høgsberg07937562011-04-12 17:25:42 -040026#include <linux/input.h>
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050027
28#include "wayland-server.h"
29#include "compositor.h"
30
31struct wlsc_move_grab {
32 struct wl_grab grab;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -050033 struct wlsc_surface *surface;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050034 int32_t dx, dy;
35};
36
37static void
38move_grab_motion(struct wl_grab *grab,
39 uint32_t time, int32_t x, int32_t y)
40{
41 struct wlsc_move_grab *move = (struct wlsc_move_grab *) grab;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -050042 struct wlsc_surface *es = move->surface;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050043
Kristian Høgsberg31bd6c72011-02-13 13:00:51 -050044 wlsc_surface_damage(es);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050045 es->x = x + move->dx;
46 es->y = y + move->dy;
Benjamin Franzkeec4d3422011-03-14 12:07:26 +010047 wlsc_surface_assign_output(es);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050048 wlsc_surface_update_matrix(es);
Kristian Høgsberg31bd6c72011-02-13 13:00:51 -050049 wlsc_surface_damage(es);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050050}
51
52static void
53move_grab_button(struct wl_grab *grab,
54 uint32_t time, int32_t button, int32_t state)
55{
56}
57
58static void
59move_grab_end(struct wl_grab *grab, uint32_t time)
60{
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -050061 struct wlsc_surface *es;
62 struct wl_input_device *device = grab->input_device;
63 int32_t sx, sy;
64
65 es = pick_surface(grab->input_device, &sx, &sy);
66 wl_input_device_set_pointer_focus(device,
67 &es->surface, time,
68 device->x, device->y, sx, sy);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050069 free(grab);
70}
71
72static const struct wl_grab_interface move_grab_interface = {
73 move_grab_motion,
74 move_grab_button,
75 move_grab_end
76};
77
Kristian Høgsberg07937562011-04-12 17:25:42 -040078static void
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050079shell_move(struct wl_client *client, struct wl_shell *shell,
80 struct wl_surface *surface,
81 struct wl_input_device *device, uint32_t time)
82{
83 struct wlsc_input_device *wd = (struct wlsc_input_device *) device;
84 struct wlsc_surface *es = (struct wlsc_surface *) surface;
85 struct wlsc_move_grab *move;
86
Kristian Høgsberg0ce24572011-01-28 15:18:33 -050087 /* FIXME: Reject if fullscreen */
88
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050089 move = malloc(sizeof *move);
90 if (!move) {
91 wl_client_post_no_memory(client);
92 return;
93 }
94
95 move->grab.interface = &move_grab_interface;
96 move->dx = es->x - wd->input_device.grab_x;
97 move->dy = es->y - wd->input_device.grab_y;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -050098 move->surface = es;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -050099
100 if (wl_input_device_update_grab(&wd->input_device,
101 &move->grab, surface, time) < 0)
102 return;
103
104 wlsc_input_device_set_pointer_image(wd, WLSC_POINTER_DRAGGING);
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500105 wl_input_device_set_pointer_focus(device, NULL, time, 0, 0, 0, 0);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500106}
107
108struct wlsc_resize_grab {
109 struct wl_grab grab;
110 uint32_t edges;
111 int32_t dx, dy, width, height;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500112 struct wlsc_surface *surface;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500113};
114
115static void
116resize_grab_motion(struct wl_grab *grab,
117 uint32_t time, int32_t x, int32_t y)
118{
119 struct wlsc_resize_grab *resize = (struct wlsc_resize_grab *) grab;
120 struct wl_input_device *device = grab->input_device;
121 struct wlsc_compositor *ec =
122 (struct wlsc_compositor *) device->compositor;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500123 struct wl_surface *surface = &resize->surface->surface;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500124 int32_t width, height;
125
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500126 if (resize->edges & WL_SHELL_RESIZE_LEFT) {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500127 width = device->grab_x - x + resize->width;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500128 } else if (resize->edges & WL_SHELL_RESIZE_RIGHT) {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500129 width = x - device->grab_x + resize->width;
130 } else {
131 width = resize->width;
132 }
133
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500134 if (resize->edges & WL_SHELL_RESIZE_TOP) {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500135 height = device->grab_y - y + resize->height;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500136 } else if (resize->edges & WL_SHELL_RESIZE_BOTTOM) {
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500137 height = y - device->grab_y + resize->height;
138 } else {
139 height = resize->height;
140 }
141
142 wl_client_post_event(surface->client, &ec->shell.object,
143 WL_SHELL_CONFIGURE, time, resize->edges,
144 surface, width, height);
145}
146
147static void
148resize_grab_button(struct wl_grab *grab,
149 uint32_t time, int32_t button, int32_t state)
150{
151}
152
153static void
154resize_grab_end(struct wl_grab *grab, uint32_t time)
155{
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500156 struct wlsc_surface *es;
157 struct wl_input_device *device = grab->input_device;
158 int32_t sx, sy;
159
160 es = pick_surface(grab->input_device, &sx, &sy);
161 wl_input_device_set_pointer_focus(device,
162 &es->surface, time,
163 device->x, device->y, sx, sy);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500164 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øgsberg07937562011-04-12 17:25:42 -0400173static void
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500174shell_resize(struct wl_client *client, struct wl_shell *shell,
175 struct wl_surface *surface,
176 struct wl_input_device *device, uint32_t time, uint32_t edges)
177{
178 struct wlsc_input_device *wd = (struct wlsc_input_device *) device;
179 struct wlsc_resize_grab *resize;
180 enum wlsc_pointer_type pointer = WLSC_POINTER_LEFT_PTR;
181 struct wlsc_surface *es = (struct wlsc_surface *) surface;
182
Kristian Høgsberg0ce24572011-01-28 15:18:33 -0500183 /* FIXME: Reject if fullscreen */
184
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500185 resize = malloc(sizeof *resize);
186 if (!resize) {
187 wl_client_post_no_memory(client);
188 return;
189 }
190
191 resize->grab.interface = &resize_grab_interface;
192 resize->edges = edges;
193 resize->dx = es->x - wd->input_device.grab_x;
194 resize->dy = es->y - wd->input_device.grab_y;
195 resize->width = es->width;
196 resize->height = es->height;
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500197 resize->surface = es;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500198
199 if (edges == 0 || edges > 15 ||
200 (edges & 3) == 3 || (edges & 12) == 12)
201 return;
202
203 switch (edges) {
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500204 case WL_SHELL_RESIZE_TOP:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500205 pointer = WLSC_POINTER_TOP;
206 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500207 case WL_SHELL_RESIZE_BOTTOM:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500208 pointer = WLSC_POINTER_BOTTOM;
209 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500210 case WL_SHELL_RESIZE_LEFT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500211 pointer = WLSC_POINTER_LEFT;
212 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500213 case WL_SHELL_RESIZE_TOP_LEFT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500214 pointer = WLSC_POINTER_TOP_LEFT;
215 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500216 case WL_SHELL_RESIZE_BOTTOM_LEFT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500217 pointer = WLSC_POINTER_BOTTOM_LEFT;
218 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500219 case WL_SHELL_RESIZE_RIGHT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500220 pointer = WLSC_POINTER_RIGHT;
221 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500222 case WL_SHELL_RESIZE_TOP_RIGHT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500223 pointer = WLSC_POINTER_TOP_RIGHT;
224 break;
Kristian Høgsberg027931b2011-01-21 21:57:55 -0500225 case WL_SHELL_RESIZE_BOTTOM_RIGHT:
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500226 pointer = WLSC_POINTER_BOTTOM_RIGHT;
227 break;
228 }
229
230 if (wl_input_device_update_grab(&wd->input_device,
231 &resize->grab, surface, time) < 0)
232 return;
233
234 wlsc_input_device_set_pointer_image(wd, pointer);
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500235 wl_input_device_set_pointer_focus(device, NULL, time, 0, 0, 0, 0);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500236}
237
238static void
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500239destroy_drag(struct wl_resource *resource, struct wl_client *client)
240{
241 struct wl_drag *drag =
242 container_of(resource, struct wl_drag, resource);
243
244 wl_list_remove(&drag->drag_focus_listener.link);
245 if (drag->grab.input_device)
246 wl_input_device_end_grab(drag->grab.input_device, get_time());
247
248 free(drag);
249}
250
251
252static void
253wl_drag_set_pointer_focus(struct wl_drag *drag,
254 struct wl_surface *surface, uint32_t time,
255 int32_t x, int32_t y, int32_t sx, int32_t sy)
256{
257 char **p, **end;
258
259 if (drag->drag_focus == surface)
260 return;
261
262 if (drag->drag_focus &&
263 (!surface || drag->drag_focus->client != surface->client))
264 wl_client_post_event(drag->drag_focus->client,
265 &drag->drag_offer.object,
266 WL_DRAG_OFFER_POINTER_FOCUS,
267 time, NULL, 0, 0, 0, 0);
268
269 if (surface &&
270 (!drag->drag_focus ||
271 drag->drag_focus->client != surface->client)) {
272 wl_client_post_global(surface->client,
273 &drag->drag_offer.object);
274
275 end = drag->types.data + drag->types.size;
276 for (p = drag->types.data; p < end; p++)
277 wl_client_post_event(surface->client,
278 &drag->drag_offer.object,
279 WL_DRAG_OFFER_OFFER, *p);
280 }
281
282 if (surface) {
283 wl_client_post_event(surface->client,
284 &drag->drag_offer.object,
285 WL_DRAG_OFFER_POINTER_FOCUS,
286 time, surface,
287 x, y, sx, sy);
288
289 }
290
291 drag->drag_focus = surface;
292 drag->pointer_focus_time = time;
293 drag->target = NULL;
294
295 wl_list_remove(&drag->drag_focus_listener.link);
296 if (surface)
297 wl_list_insert(surface->destroy_listener_list.prev,
298 &drag->drag_focus_listener.link);
299}
300
301static void
302drag_offer_accept(struct wl_client *client,
303 struct wl_drag_offer *offer, uint32_t time, const char *type)
304{
305 struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer);
306 char **p, **end;
307
308 /* If the client responds to drag pointer_focus or motion
309 * events after the pointer has left the surface, we just
310 * discard the accept requests. The drag source just won't
311 * get the corresponding 'target' events and eventually the
312 * next surface/root will start sending events. */
313 if (time < drag->pointer_focus_time)
314 return;
315
316 drag->target = client;
317 drag->type = NULL;
318 end = drag->types.data + drag->types.size;
319 for (p = drag->types.data; p < end; p++)
320 if (type && strcmp(*p, type) == 0)
321 drag->type = *p;
322
323 wl_client_post_event(drag->source->client, &drag->resource.object,
324 WL_DRAG_TARGET, drag->type);
325}
326
327static void
328drag_offer_receive(struct wl_client *client,
329 struct wl_drag_offer *offer, int fd)
330{
331 struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer);
332
333 wl_client_post_event(drag->source->client, &drag->resource.object,
334 WL_DRAG_FINISH, fd);
335 close(fd);
336}
337
338static void
339drag_offer_reject(struct wl_client *client, struct wl_drag_offer *offer)
340{
341 struct wl_drag *drag = container_of(offer, struct wl_drag, drag_offer);
342
343 wl_client_post_event(drag->source->client, &drag->resource.object,
344 WL_DRAG_REJECT);
345}
346
347static const struct wl_drag_offer_interface drag_offer_interface = {
348 drag_offer_accept,
349 drag_offer_receive,
350 drag_offer_reject
351};
352
353static void
354drag_offer(struct wl_client *client, struct wl_drag *drag, const char *type)
355{
356 char **p;
357
358 p = wl_array_add(&drag->types, sizeof *p);
359 if (p)
360 *p = strdup(type);
361 if (!p || !*p)
362 wl_client_post_no_memory(client);
363}
364
365static void
366drag_grab_motion(struct wl_grab *grab,
367 uint32_t time, int32_t x, int32_t y)
368{
369 struct wl_drag *drag = container_of(grab, struct wl_drag, grab);
370 struct wlsc_surface *es;
371 int32_t sx, sy;
372
373 es = pick_surface(grab->input_device, &sx, &sy);
374 wl_drag_set_pointer_focus(drag, &es->surface, time, x, y, sx, sy);
375 if (es)
376 wl_client_post_event(es->surface.client,
377 &drag->drag_offer.object,
378 WL_DRAG_OFFER_MOTION,
379 time, x, y, sx, sy);
380}
381
382static void
383drag_grab_button(struct wl_grab *grab,
384 uint32_t time, int32_t button, int32_t state)
385{
386}
387
388static void
389drag_grab_end(struct wl_grab *grab, uint32_t time)
390{
391 struct wl_drag *drag = container_of(grab, struct wl_drag, grab);
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500392 struct wlsc_surface *es;
393 struct wl_input_device *device = grab->input_device;
394 int32_t sx, sy;
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500395
396 if (drag->target)
397 wl_client_post_event(drag->target,
398 &drag->drag_offer.object,
399 WL_DRAG_OFFER_DROP);
400
401 wl_drag_set_pointer_focus(drag, NULL, time, 0, 0, 0, 0);
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500402
403 es = pick_surface(grab->input_device, &sx, &sy);
404 wl_input_device_set_pointer_focus(device,
405 &es->surface, time,
406 device->x, device->y, sx, sy);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500407}
408
409static const struct wl_grab_interface drag_grab_interface = {
410 drag_grab_motion,
411 drag_grab_button,
412 drag_grab_end
413};
414
415static void
416drag_activate(struct wl_client *client,
417 struct wl_drag *drag,
418 struct wl_surface *surface,
419 struct wl_input_device *device, uint32_t time)
420{
421 struct wl_display *display = wl_client_get_display (client);
422 struct wlsc_surface *target;
423 int32_t sx, sy;
424
425 if (wl_input_device_update_grab(device,
426 &drag->grab, surface, time) < 0)
427 return;
428
429 drag->grab.interface = &drag_grab_interface;
430
431 drag->source = surface;
432
433 drag->drag_offer.object.interface = &wl_drag_offer_interface;
434 drag->drag_offer.object.implementation =
435 (void (**)(void)) &drag_offer_interface;
436
437 wl_display_add_object(display, &drag->drag_offer.object);
438
439 target = pick_surface(device, &sx, &sy);
Kristian Høgsbergdd4046a2011-01-21 17:00:09 -0500440 wl_input_device_set_pointer_focus(device, NULL, time, 0, 0, 0, 0);
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500441 wl_drag_set_pointer_focus(drag, &target->surface, time,
442 device->x, device->y, sx, sy);
443}
444
445static void
446drag_destroy(struct wl_client *client, struct wl_drag *drag)
447{
448 wl_resource_destroy(&drag->resource, client);
449}
450
451static const struct wl_drag_interface drag_interface = {
452 drag_offer,
453 drag_activate,
454 drag_destroy,
455};
456
457static void
458drag_handle_surface_destroy(struct wl_listener *listener,
459 struct wl_surface *surface, uint32_t time)
460{
461 struct wl_drag *drag =
462 container_of(listener, struct wl_drag, drag_focus_listener);
463
464 if (drag->drag_focus == surface)
465 wl_drag_set_pointer_focus(drag, NULL, time, 0, 0, 0, 0);
466}
467
468static void
469shell_create_drag(struct wl_client *client,
470 struct wl_shell *shell, uint32_t id)
471{
472 struct wl_drag *drag;
473
474 drag = malloc(sizeof *drag);
475 if (drag == NULL) {
476 wl_client_post_no_memory(client);
477 return;
478 }
479
480 memset(drag, 0, sizeof *drag);
481 drag->resource.object.id = id;
482 drag->resource.object.interface = &wl_drag_interface;
483 drag->resource.object.implementation =
484 (void (**)(void)) &drag_interface;
485
486 drag->resource.destroy = destroy_drag;
487
488 drag->drag_focus_listener.func = drag_handle_surface_destroy;
489 wl_list_init(&drag->drag_focus_listener.link);
490
491 wl_client_add_resource(client, &drag->resource);
492}
493
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500494void
495wlsc_selection_set_focus(struct wl_selection *selection,
496 struct wl_surface *surface, uint32_t time)
497{
498 char **p, **end;
499
500 if (selection->selection_focus == surface)
501 return;
502
503 if (selection->selection_focus != NULL)
504 wl_client_post_event(selection->selection_focus->client,
505 &selection->selection_offer.object,
506 WL_SELECTION_OFFER_KEYBOARD_FOCUS,
507 NULL);
508
509 if (surface) {
510 wl_client_post_global(surface->client,
511 &selection->selection_offer.object);
512
513 end = selection->types.data + selection->types.size;
514 for (p = selection->types.data; p < end; p++)
515 wl_client_post_event(surface->client,
516 &selection->selection_offer.object,
517 WL_SELECTION_OFFER_OFFER, *p);
518
519 wl_list_remove(&selection->selection_focus_listener.link);
520 wl_list_insert(surface->destroy_listener_list.prev,
521 &selection->selection_focus_listener.link);
522
523 wl_client_post_event(surface->client,
524 &selection->selection_offer.object,
525 WL_SELECTION_OFFER_KEYBOARD_FOCUS,
526 selection->input_device);
527 }
528
529 selection->selection_focus = surface;
530
531 wl_list_remove(&selection->selection_focus_listener.link);
532 if (surface)
533 wl_list_insert(surface->destroy_listener_list.prev,
534 &selection->selection_focus_listener.link);
535}
536
537static void
538selection_offer_receive(struct wl_client *client,
539 struct wl_selection_offer *offer,
540 const char *mime_type, int fd)
541{
542 struct wl_selection *selection =
543 container_of(offer, struct wl_selection, selection_offer);
544
545 wl_client_post_event(selection->client,
546 &selection->resource.object,
547 WL_SELECTION_SEND, mime_type, fd);
548 close(fd);
549}
550
551static const struct wl_selection_offer_interface selection_offer_interface = {
552 selection_offer_receive
553};
554
555static void
556selection_offer(struct wl_client *client,
557 struct wl_selection *selection, const char *type)
558{
559 char **p;
560
561 p = wl_array_add(&selection->types, sizeof *p);
562 if (p)
563 *p = strdup(type);
564 if (!p || !*p)
565 wl_client_post_no_memory(client);
566}
567
568static void
569selection_activate(struct wl_client *client,
570 struct wl_selection *selection,
571 struct wl_input_device *device, uint32_t time)
572{
573 struct wlsc_input_device *wd = (struct wlsc_input_device *) device;
574 struct wl_display *display = wl_client_get_display (client);
575
576 selection->input_device = device;
577
578 selection->selection_offer.object.interface =
579 &wl_selection_offer_interface;
580 selection->selection_offer.object.implementation =
581 (void (**)(void)) &selection_offer_interface;
582
583 wl_display_add_object(display, &selection->selection_offer.object);
584
585 if (wd->selection) {
586 wl_client_post_event(wd->selection->client,
587 &wd->selection->resource.object,
588 WL_SELECTION_CANCELLED);
589 }
590 wd->selection = selection;
591
592 wlsc_selection_set_focus(selection, device->keyboard_focus, time);
593}
594
595static void
596selection_destroy(struct wl_client *client, struct wl_selection *selection)
597{
598 wl_resource_destroy(&selection->resource, client);
599}
600
601static const struct wl_selection_interface selection_interface = {
602 selection_offer,
603 selection_activate,
604 selection_destroy
605};
606
607static void
608destroy_selection(struct wl_resource *resource, struct wl_client *client)
609{
610 struct wl_selection *selection =
611 container_of(resource, struct wl_selection, resource);
612 struct wlsc_input_device *wd =
613 (struct wlsc_input_device *) selection->input_device;
614
615 if (wd && wd->selection == selection) {
616 wd->selection = NULL;
617 wlsc_selection_set_focus(selection, NULL, get_time());
618 }
619
620 wl_list_remove(&selection->selection_focus_listener.link);
621 free(selection);
622}
623
624static void
625selection_handle_surface_destroy(struct wl_listener *listener,
626 struct wl_surface *surface, uint32_t time)
627{
628}
629
630static void
631shell_create_selection(struct wl_client *client,
632 struct wl_shell *shell, uint32_t id)
633{
634 struct wl_selection *selection;
635
636 selection = malloc(sizeof *selection);
637 if (selection == NULL) {
638 wl_client_post_no_memory(client);
639 return;
640 }
641
642 memset(selection, 0, sizeof *selection);
643 selection->resource.object.id = id;
644 selection->resource.object.interface = &wl_selection_interface;
645 selection->resource.object.implementation =
646 (void (**)(void)) &selection_interface;
647
648 selection->client = client;
649 selection->resource.destroy = destroy_selection;
650 selection->selection_focus = NULL;
651
652 selection->selection_focus_listener.func =
653 selection_handle_surface_destroy;
654 wl_list_init(&selection->selection_focus_listener.link);
655
656 wl_client_add_resource(client, &selection->resource);
657}
658
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500659const static struct wl_shell_interface shell_interface = {
660 shell_move,
661 shell_resize,
Kristian Høgsbergae6c8a62011-01-18 09:08:53 -0500662 shell_create_drag,
663 shell_create_selection
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500664};
665
Kristian Høgsberg07937562011-04-12 17:25:42 -0400666static void
667move_binding(struct wl_input_device *device, uint32_t time,
668 uint32_t key, uint32_t button, uint32_t state, void *data)
669{
670 struct wlsc_compositor *compositor = data;
671 struct wlsc_surface *surface =
672 (struct wlsc_surface *) device->pointer_focus;
673
674 shell_move(NULL,
675 (struct wl_shell *) &compositor->shell,
676 &surface->surface, device, time);
677}
678
679static void
680resize_binding(struct wl_input_device *device, uint32_t time,
681 uint32_t key, uint32_t button, uint32_t state, void *data)
682{
683 struct wlsc_compositor *compositor = data;
684 struct wlsc_surface *surface =
685 (struct wlsc_surface *) device->pointer_focus;
686 uint32_t edges = 0;
687 int32_t x, y;
688
689 x = device->grab_x - surface->x;
690 y = device->grab_y - surface->y;
691
692 if (x < surface->width / 3)
693 edges |= WL_SHELL_RESIZE_LEFT;
694 else if (x < 2 * surface->width / 3)
695 edges |= 0;
696 else
697 edges |= WL_SHELL_RESIZE_RIGHT;
698
699 if (y < surface->height / 3)
700 edges |= WL_SHELL_RESIZE_TOP;
701 else if (y < 2 * surface->height / 3)
702 edges |= 0;
703 else
704 edges |= WL_SHELL_RESIZE_BOTTOM;
705
706 shell_resize(NULL,
707 (struct wl_shell *) &compositor->shell,
708 &surface->surface, device, time, edges);
709}
710
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500711int
712wlsc_shell_init(struct wlsc_compositor *ec)
713{
714 struct wl_shell *shell = &ec->shell;
715
716 shell->object.interface = &wl_shell_interface;
717 shell->object.implementation = (void (**)(void)) &shell_interface;
718 wl_display_add_object(ec->wl_display, &shell->object);
719 if (wl_display_add_global(ec->wl_display, &shell->object, NULL))
720 return -1;
721
Kristian Høgsberg07937562011-04-12 17:25:42 -0400722 wlsc_compositor_add_binding(ec, 0, BTN_LEFT, MODIFIER_SUPER,
723 move_binding, ec);
724 wlsc_compositor_add_binding(ec, 0, BTN_MIDDLE, MODIFIER_SUPER,
725 resize_binding, ec);
726
Kristian Høgsberg4cca3492011-01-18 07:53:49 -0500727 return 0;
728}