toytoolkit: Don't draw shadows for maximized windows.
[profile/ivi/weston.git] / clients / window.c
1 /*
2  * Copyright © 2008 Kristian Høgsberg
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that copyright
7  * notice and this permission notice appear in supporting documentation, and
8  * that the name of the copyright holders not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission.  The copyright holders make no representations
11  * about the suitability of this software for any purpose.  It is provided "as
12  * is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20  * OF THIS SOFTWARE.
21  */
22
23 #define _GNU_SOURCE
24
25 #include "../config.h"
26
27 #include <stdint.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <fcntl.h>
32 #include <unistd.h>
33 #include <math.h>
34 #include <assert.h>
35 #include <time.h>
36 #include <cairo.h>
37 #include <sys/mman.h>
38 #include <sys/epoll.h>
39 #include <sys/timerfd.h>
40
41 #include <pixman.h>
42
43 #include <wayland-egl.h>
44
45 #ifdef USE_CAIRO_GLESV2
46 #include <GLES2/gl2.h>
47 #include <GLES2/gl2ext.h>
48 #else
49 #include <GL/gl.h>
50 #endif
51 #include <EGL/egl.h>
52 #include <EGL/eglext.h>
53
54 #ifdef HAVE_CAIRO_EGL
55 #include <cairo-gl.h>
56 #endif
57
58 #include <xkbcommon/xkbcommon.h>
59 #include <wayland-cursor.h>
60
61 #include <linux/input.h>
62 #include <wayland-client.h>
63 #include "../shared/cairo-util.h"
64 #include "text-cursor-position-client-protocol.h"
65 #include "workspaces-client-protocol.h"
66 #include "../shared/os-compatibility.h"
67
68 #include "window.h"
69
70 struct shm_pool;
71
72 struct display {
73         struct wl_display *display;
74         struct wl_compositor *compositor;
75         struct wl_shell *shell;
76         struct wl_shm *shm;
77         struct wl_data_device_manager *data_device_manager;
78         struct text_cursor_position *text_cursor_position;
79         struct workspace_manager *workspace_manager;
80         EGLDisplay dpy;
81         EGLConfig argb_config;
82         EGLContext argb_ctx;
83         cairo_device_t *argb_device;
84         uint32_t serial;
85
86         int display_fd;
87         uint32_t display_fd_events;
88         uint32_t mask;
89         struct task display_task;
90
91         int epoll_fd;
92         struct wl_list deferred_list;
93
94         int running;
95
96         struct wl_list window_list;
97         struct wl_list input_list;
98         struct wl_list output_list;
99
100         struct theme *theme;
101
102         struct wl_cursor_theme *cursor_theme;
103         struct wl_cursor **cursors;
104
105         PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d;
106         PFNEGLCREATEIMAGEKHRPROC create_image;
107         PFNEGLDESTROYIMAGEKHRPROC destroy_image;
108
109         display_output_handler_t output_configure_handler;
110
111         void *user_data;
112
113         struct xkb_context *xkb_context;
114
115         uint32_t workspace;
116         uint32_t workspace_count;
117 };
118
119 enum {
120         TYPE_NONE,
121         TYPE_TOPLEVEL,
122         TYPE_FULLSCREEN,
123         TYPE_MAXIMIZED,
124         TYPE_TRANSIENT,
125         TYPE_MENU,
126         TYPE_CUSTOM
127 };
128
129 struct window_output {
130         struct output *output;
131         struct wl_list link;
132 };
133
134 struct window {
135         struct display *display;
136         struct window *parent;
137         struct wl_list window_output_list;
138         struct wl_surface *surface;
139         struct wl_shell_surface *shell_surface;
140         struct wl_region *input_region;
141         struct wl_region *opaque_region;
142         char *title;
143         struct rectangle allocation, saved_allocation, server_allocation;
144         struct rectangle min_allocation;
145         struct rectangle pending_allocation;
146         int x, y;
147         int resize_edges;
148         int redraw_scheduled;
149         int redraw_needed;
150         struct task redraw_task;
151         int resize_needed;
152         int type;
153         int transparent;
154         int focus_count;
155
156         enum window_buffer_type buffer_type;
157
158         cairo_surface_t *cairo_surface;
159
160         struct shm_pool *pool;
161
162         window_key_handler_t key_handler;
163         window_keyboard_focus_handler_t keyboard_focus_handler;
164         window_data_handler_t data_handler;
165         window_drop_handler_t drop_handler;
166         window_close_handler_t close_handler;
167         window_fullscreen_handler_t fullscreen_handler;
168
169         struct wl_callback *frame_cb;
170
171         struct frame *frame;
172         struct widget *widget;
173
174         void *user_data;
175         struct wl_list link;
176 };
177
178 struct widget {
179         struct window *window;
180         struct tooltip *tooltip;
181         struct wl_list child_list;
182         struct wl_list link;
183         struct rectangle allocation;
184         widget_resize_handler_t resize_handler;
185         widget_redraw_handler_t redraw_handler;
186         widget_enter_handler_t enter_handler;
187         widget_leave_handler_t leave_handler;
188         widget_motion_handler_t motion_handler;
189         widget_button_handler_t button_handler;
190         widget_axis_handler_t axis_handler;
191         void *user_data;
192         int opaque;
193         int tooltip_count;
194 };
195
196 struct input {
197         struct display *display;
198         struct wl_seat *seat;
199         struct wl_pointer *pointer;
200         struct wl_keyboard *keyboard;
201         struct window *pointer_focus;
202         struct window *keyboard_focus;
203         int current_cursor;
204         uint32_t cursor_anim_start;
205         struct wl_callback *cursor_frame_cb;
206         struct wl_surface *pointer_surface;
207         uint32_t modifiers;
208         uint32_t pointer_enter_serial;
209         uint32_t cursor_serial;
210         float sx, sy;
211         struct wl_list link;
212
213         struct widget *focus_widget;
214         struct widget *grab;
215         uint32_t grab_button;
216
217         struct wl_data_device *data_device;
218         struct data_offer *drag_offer;
219         struct data_offer *selection_offer;
220
221         struct {
222                 struct xkb_keymap *keymap;
223                 struct xkb_state *state;
224                 xkb_mod_mask_t control_mask;
225                 xkb_mod_mask_t alt_mask;
226                 xkb_mod_mask_t shift_mask;
227         } xkb;
228
229         struct task repeat_task;
230         int repeat_timer_fd;
231         uint32_t repeat_sym;
232         uint32_t repeat_key;
233         uint32_t repeat_time;
234 };
235
236 struct output {
237         struct display *display;
238         struct wl_output *output;
239         struct rectangle allocation;
240         struct wl_list link;
241
242         display_output_handler_t destroy_handler;
243         void *user_data;
244 };
245
246 enum frame_button_action {
247         FRAME_BUTTON_NULL = 0,
248         FRAME_BUTTON_ICON = 1,
249         FRAME_BUTTON_CLOSE = 2,
250         FRAME_BUTTON_MINIMIZE = 3,
251         FRAME_BUTTON_MAXIMIZE = 4,
252 };
253
254 enum frame_button_pointer {
255         FRAME_BUTTON_DEFAULT = 0,
256         FRAME_BUTTON_OVER = 1,
257         FRAME_BUTTON_ACTIVE = 2,
258 };
259
260 enum frame_button_align {
261         FRAME_BUTTON_RIGHT = 0,
262         FRAME_BUTTON_LEFT = 1,
263 };
264
265 enum frame_button_decoration {
266         FRAME_BUTTON_NONE = 0,
267         FRAME_BUTTON_FANCY = 1,
268 };
269
270 struct frame_button {
271         struct widget *widget;
272         struct frame *frame;
273         cairo_surface_t *icon;
274         enum frame_button_action type;
275         enum frame_button_pointer state;
276         struct wl_list link;    /* buttons_list */
277         enum frame_button_align align;
278         enum frame_button_decoration decoration;
279 };
280
281 struct frame {
282         struct widget *widget;
283         struct widget *child;
284         struct wl_list buttons_list;
285 };
286
287 struct menu {
288         struct window *window;
289         struct widget *widget;
290         struct input *input;
291         const char **entries;
292         uint32_t time;
293         int current;
294         int count;
295         menu_func_t func;
296 };
297
298 struct tooltip {
299         struct widget *parent;
300         struct window *window;
301         struct widget *widget;
302         char *entry;
303         struct task tooltip_task;
304         int tooltip_fd;
305         float x, y;
306 };
307
308 struct shm_pool {
309         struct wl_shm_pool *pool;
310         size_t size;
311         size_t used;
312         void *data;
313 };
314
315 enum {
316         CURSOR_DEFAULT = 100,
317         CURSOR_UNSET
318 };
319
320 enum window_location {
321         WINDOW_INTERIOR = 0,
322         WINDOW_RESIZING_TOP = 1,
323         WINDOW_RESIZING_BOTTOM = 2,
324         WINDOW_RESIZING_LEFT = 4,
325         WINDOW_RESIZING_TOP_LEFT = 5,
326         WINDOW_RESIZING_BOTTOM_LEFT = 6,
327         WINDOW_RESIZING_RIGHT = 8,
328         WINDOW_RESIZING_TOP_RIGHT = 9,
329         WINDOW_RESIZING_BOTTOM_RIGHT = 10,
330         WINDOW_RESIZING_MASK = 15,
331         WINDOW_EXTERIOR = 16,
332         WINDOW_TITLEBAR = 17,
333         WINDOW_CLIENT_AREA = 18,
334 };
335
336 static const cairo_user_data_key_t surface_data_key;
337 struct surface_data {
338         struct wl_buffer *buffer;
339 };
340
341 #define MULT(_d,c,a,t) \
342         do { t = c * a + 0x7f; _d = ((t >> 8) + t) >> 8; } while (0)
343
344 #ifdef HAVE_CAIRO_EGL
345
346 struct egl_window_surface_data {
347         struct display *display;
348         struct wl_surface *surface;
349         struct wl_egl_window *window;
350         EGLSurface surf;
351 };
352
353 static void
354 egl_window_surface_data_destroy(void *p)
355 {
356         struct egl_window_surface_data *data = p;
357         struct display *d = data->display;
358
359         eglDestroySurface(d->dpy, data->surf);
360         wl_egl_window_destroy(data->window);
361         data->surface = NULL;
362
363         free(p);
364 }
365
366 static cairo_surface_t *
367 display_create_egl_window_surface(struct display *display,
368                                   struct wl_surface *surface,
369                                   uint32_t flags,
370                                   struct rectangle *rectangle)
371 {
372         cairo_surface_t *cairo_surface;
373         struct egl_window_surface_data *data;
374         EGLConfig config;
375         cairo_device_t *device;
376
377         data = malloc(sizeof *data);
378         if (data == NULL)
379                 return NULL;
380
381         data->display = display;
382         data->surface = surface;
383
384         config = display->argb_config;
385         device = display->argb_device;
386
387         data->window = wl_egl_window_create(surface,
388                                             rectangle->width,
389                                             rectangle->height);
390
391         data->surf = eglCreateWindowSurface(display->dpy, config,
392                                             data->window, NULL);
393
394         cairo_surface = cairo_gl_surface_create_for_egl(device,
395                                                         data->surf,
396                                                         rectangle->width,
397                                                         rectangle->height);
398
399         cairo_surface_set_user_data(cairo_surface, &surface_data_key,
400                                     data, egl_window_surface_data_destroy);
401
402         return cairo_surface;
403 }
404
405 #endif
406
407 struct wl_buffer *
408 display_get_buffer_for_surface(struct display *display,
409                                cairo_surface_t *surface)
410 {
411         struct surface_data *data;
412
413         data = cairo_surface_get_user_data (surface, &surface_data_key);
414
415         return data->buffer;
416 }
417
418 struct shm_surface_data {
419         struct surface_data data;
420         struct shm_pool *pool;
421 };
422
423 static void
424 shm_pool_destroy(struct shm_pool *pool);
425
426 static void
427 shm_surface_data_destroy(void *p)
428 {
429         struct shm_surface_data *data = p;
430
431         wl_buffer_destroy(data->data.buffer);
432         if (data->pool)
433                 shm_pool_destroy(data->pool);
434
435         free(data);
436 }
437
438 static struct wl_shm_pool *
439 make_shm_pool(struct display *display, int size, void **data)
440 {
441         struct wl_shm_pool *pool;
442         int fd;
443
444         fd = os_create_anonymous_file(size);
445         if (fd < 0) {
446                 fprintf(stderr, "creating a buffer file for %d B failed: %m\n",
447                         size);
448                 return NULL;
449         }
450
451         *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
452         if (*data == MAP_FAILED) {
453                 fprintf(stderr, "mmap failed: %m\n");
454                 close(fd);
455                 return NULL;
456         }
457
458         pool = wl_shm_create_pool(display->shm, fd, size);
459
460         close(fd);
461
462         return pool;
463 }
464
465 static struct shm_pool *
466 shm_pool_create(struct display *display, size_t size)
467 {
468         struct shm_pool *pool = malloc(sizeof *pool);
469
470         if (!pool)
471                 return NULL;
472
473         pool->pool = make_shm_pool(display, size, &pool->data);
474         if (!pool->pool) {
475                 free(pool);
476                 return NULL;
477         }
478
479         pool->size = size;
480         pool->used = 0;
481
482         return pool;
483 }
484
485 static void *
486 shm_pool_allocate(struct shm_pool *pool, size_t size, int *offset)
487 {
488         if (pool->used + size > pool->size)
489                 return NULL;
490
491         *offset = pool->used;
492         pool->used += size;
493
494         return (char *) pool->data + *offset;
495 }
496
497 /* destroy the pool. this does not unmap the memory though */
498 static void
499 shm_pool_destroy(struct shm_pool *pool)
500 {
501         munmap(pool->data, pool->size);
502         wl_shm_pool_destroy(pool->pool);
503         free(pool);
504 }
505
506 /* Start allocating from the beginning of the pool again */
507 static void
508 shm_pool_reset(struct shm_pool *pool)
509 {
510         pool->used = 0;
511 }
512
513 static int
514 data_length_for_shm_surface(struct rectangle *rect)
515 {
516         int stride;
517
518         stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32,
519                                                 rect->width);
520         return stride * rect->height;
521 }
522
523 static cairo_surface_t *
524 display_create_shm_surface_from_pool(struct display *display,
525                                      struct rectangle *rectangle,
526                                      uint32_t flags, struct shm_pool *pool)
527 {
528         struct shm_surface_data *data;
529         uint32_t format;
530         cairo_surface_t *surface;
531         int stride, length, offset;
532         void *map;
533
534         data = malloc(sizeof *data);
535         if (data == NULL)
536                 return NULL;
537
538         stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32,
539                                                 rectangle->width);
540         length = stride * rectangle->height;
541         data->pool = NULL;
542         map = shm_pool_allocate(pool, length, &offset);
543
544         if (!map) {
545                 free(data);
546                 return NULL;
547         }
548
549         surface = cairo_image_surface_create_for_data (map,
550                                                        CAIRO_FORMAT_ARGB32,
551                                                        rectangle->width,
552                                                        rectangle->height,
553                                                        stride);
554
555         cairo_surface_set_user_data (surface, &surface_data_key,
556                                      data, shm_surface_data_destroy);
557
558         if (flags & SURFACE_OPAQUE)
559                 format = WL_SHM_FORMAT_XRGB8888;
560         else
561                 format = WL_SHM_FORMAT_ARGB8888;
562
563         data->data.buffer = wl_shm_pool_create_buffer(pool->pool, offset,
564                                                       rectangle->width,
565                                                       rectangle->height,
566                                                       stride, format);
567
568         return surface;
569 }
570
571 static cairo_surface_t *
572 display_create_shm_surface(struct display *display,
573                            struct rectangle *rectangle, uint32_t flags,
574                            struct window *window)
575 {
576         struct shm_surface_data *data;
577         struct shm_pool *pool;
578         cairo_surface_t *surface;
579
580         if (window && window->pool) {
581                 shm_pool_reset(window->pool);
582                 surface = display_create_shm_surface_from_pool(display,
583                                                                rectangle,
584                                                                flags,
585                                                                window->pool);
586                 if (surface)
587                         return surface;
588         }
589
590         pool = shm_pool_create(display,
591                                data_length_for_shm_surface(rectangle));
592         if (!pool)
593                 return NULL;
594
595         surface =
596                 display_create_shm_surface_from_pool(display, rectangle,
597                                                      flags, pool);
598
599         if (!surface) {
600                 shm_pool_destroy(pool);
601                 return NULL;
602         }
603
604         /* make sure we destroy the pool when the surface is destroyed */
605         data = cairo_surface_get_user_data(surface, &surface_data_key);
606         data->pool = pool;
607
608         return surface;
609 }
610
611 static int
612 check_size(struct rectangle *rect)
613 {
614         if (rect->width && rect->height)
615                 return 0;
616
617         fprintf(stderr, "tried to create surface of "
618                 "width: %d, height: %d\n", rect->width, rect->height);
619         return -1;
620 }
621
622 cairo_surface_t *
623 display_create_surface(struct display *display,
624                        struct wl_surface *surface,
625                        struct rectangle *rectangle,
626                        uint32_t flags)
627 {
628         if (check_size(rectangle) < 0)
629                 return NULL;
630 #ifdef HAVE_CAIRO_EGL
631         if (display->dpy && !(flags & SURFACE_SHM))
632                 return display_create_egl_window_surface(display,
633                                                          surface,
634                                                          flags,
635                                                          rectangle);
636 #endif
637         return display_create_shm_surface(display, rectangle, flags, NULL);
638 }
639
640 /*
641  * The following correspondences between file names and cursors was copied
642  * from: https://bugs.kde.org/attachment.cgi?id=67313
643  */
644
645 static const char *bottom_left_corners[] = {
646         "bottom_left_corner",
647         "sw-resize"
648 };
649
650 static const char *bottom_right_corners[] = {
651         "bottom_right_corner",
652         "se-resize"
653 };
654
655 static const char *bottom_sides[] = {
656         "bottom_side",
657         "s-resize"
658 };
659
660 static const char *grabbings[] = {
661         "grabbing",
662         "closedhand",
663         "208530c400c041818281048008011002"
664 };
665
666 static const char *left_ptrs[] = {
667         "left_ptr",
668         "default",
669         "top_left_arrow",
670         "left-arrow"
671 };
672
673 static const char *left_sides[] = {
674         "left_side",
675         "w-resize"
676 };
677
678 static const char *right_sides[] = {
679         "right_side",
680         "e-resize"
681 };
682
683 static const char *top_left_corners[] = {
684         "top_left_corner",
685         "nw-resize"
686 };
687
688 static const char *top_right_corners[] = {
689         "top_right_corner",
690         "ne-resize"
691 };
692
693 static const char *top_sides[] = {
694         "top_side",
695         "n-resize"
696 };
697
698 static const char *xterms[] = {
699         "xterm",
700         "ibeam",
701         "text"
702 };
703
704 static const char *hand1s[] = {
705         "hand1",
706         "pointer",
707         "pointing_hand",
708         "e29285e634086352946a0e7090d73106"
709 };
710
711 static const char *watches[] = {
712         "watch",
713         "wait",
714         "0426c94ea35c87780ff01dc239897213"
715 };
716
717 struct cursor_alternatives {
718         const char **names;
719         size_t count;
720 };
721
722 static const struct cursor_alternatives cursors[] = {
723         {bottom_left_corners, ARRAY_LENGTH(bottom_left_corners)},
724         {bottom_right_corners, ARRAY_LENGTH(bottom_right_corners)},
725         {bottom_sides, ARRAY_LENGTH(bottom_sides)},
726         {grabbings, ARRAY_LENGTH(grabbings)},
727         {left_ptrs, ARRAY_LENGTH(left_ptrs)},
728         {left_sides, ARRAY_LENGTH(left_sides)},
729         {right_sides, ARRAY_LENGTH(right_sides)},
730         {top_left_corners, ARRAY_LENGTH(top_left_corners)},
731         {top_right_corners, ARRAY_LENGTH(top_right_corners)},
732         {top_sides, ARRAY_LENGTH(top_sides)},
733         {xterms, ARRAY_LENGTH(xterms)},
734         {hand1s, ARRAY_LENGTH(hand1s)},
735         {watches, ARRAY_LENGTH(watches)},
736 };
737
738 static void
739 create_cursors(struct display *display)
740 {
741         char *config_file;
742         char *theme = NULL;
743         unsigned int i, j;
744         struct wl_cursor *cursor;
745         struct config_key shell_keys[] = {
746                 { "cursor-theme", CONFIG_KEY_STRING, &theme },
747         };
748         struct config_section cs[] = {
749                 { "shell", shell_keys, ARRAY_LENGTH(shell_keys), NULL },
750         };
751
752         config_file = config_file_path("weston.ini");
753         parse_config_file(config_file, cs, ARRAY_LENGTH(cs), NULL);
754         free(config_file);
755
756         display->cursor_theme = wl_cursor_theme_load(theme, 32, display->shm);
757         display->cursors =
758                 malloc(ARRAY_LENGTH(cursors) * sizeof display->cursors[0]);
759
760         for (i = 0; i < ARRAY_LENGTH(cursors); i++) {
761                 cursor = NULL;
762                 for (j = 0; !cursor && j < cursors[i].count; ++j)
763                         cursor = wl_cursor_theme_get_cursor(
764                             display->cursor_theme, cursors[i].names[j]);
765
766                 if (!cursor)
767                         fprintf(stderr, "could not load cursor '%s'\n",
768                                 cursors[i].names[0]);
769
770                 display->cursors[i] = cursor;
771         }
772 }
773
774 static void
775 destroy_cursors(struct display *display)
776 {
777         wl_cursor_theme_destroy(display->cursor_theme);
778         free(display->cursors);
779 }
780
781 struct wl_cursor_image *
782 display_get_pointer_image(struct display *display, int pointer)
783 {
784         struct wl_cursor *cursor = display->cursors[pointer];
785
786         return cursor ? cursor->images[0] : NULL;
787 }
788
789 static void
790 window_get_resize_dx_dy(struct window *window, int *x, int *y)
791 {
792         if (window->resize_edges & WINDOW_RESIZING_LEFT)
793                 *x = window->server_allocation.width - window->allocation.width;
794         else
795                 *x = 0;
796
797         if (window->resize_edges & WINDOW_RESIZING_TOP)
798                 *y = window->server_allocation.height -
799                         window->allocation.height;
800         else
801                 *y = 0;
802
803         window->resize_edges = 0;
804 }
805
806 static void
807 window_attach_surface(struct window *window)
808 {
809         struct display *display = window->display;
810         struct wl_buffer *buffer;
811 #ifdef HAVE_CAIRO_EGL
812         struct egl_window_surface_data *data;
813 #endif
814         int32_t x, y;
815
816         if (window->type == TYPE_NONE) {
817                 window->type = TYPE_TOPLEVEL;
818                 if (display->shell)
819                         wl_shell_surface_set_toplevel(window->shell_surface);
820         }
821
822         switch (window->buffer_type) {
823 #ifdef HAVE_CAIRO_EGL
824         case WINDOW_BUFFER_TYPE_EGL_WINDOW:
825                 data = cairo_surface_get_user_data(window->cairo_surface,
826                                                    &surface_data_key);
827
828                 cairo_gl_surface_swapbuffers(window->cairo_surface);
829                 wl_egl_window_get_attached_size(data->window,
830                                 &window->server_allocation.width,
831                                 &window->server_allocation.height);
832                 break;
833 #endif
834         case WINDOW_BUFFER_TYPE_SHM:
835                 buffer =
836                         display_get_buffer_for_surface(display,
837                                                        window->cairo_surface);
838
839                 window_get_resize_dx_dy(window, &x, &y);
840                 wl_surface_attach(window->surface, buffer, x, y);
841                 wl_surface_damage(window->surface, 0, 0,
842                                   window->allocation.width,
843                                   window->allocation.height);
844                 window->server_allocation = window->allocation;
845                 cairo_surface_destroy(window->cairo_surface);
846                 window->cairo_surface = NULL;
847                 break;
848         default:
849                 return;
850         }
851
852         if (window->input_region) {
853                 wl_surface_set_input_region(window->surface,
854                                             window->input_region);
855                 wl_region_destroy(window->input_region);
856                 window->input_region = NULL;
857         }
858
859         if (window->opaque_region) {
860                 wl_surface_set_opaque_region(window->surface,
861                                              window->opaque_region);
862                 wl_region_destroy(window->opaque_region);
863                 window->opaque_region = NULL;
864         }
865 }
866
867 int
868 window_has_focus(struct window *window)
869 {
870         return window->focus_count > 0;
871 }
872
873 void
874 window_flush(struct window *window)
875 {
876         if (window->cairo_surface)
877                 window_attach_surface(window);
878 }
879
880 void
881 window_set_surface(struct window *window, cairo_surface_t *surface)
882 {
883         cairo_surface_reference(surface);
884
885         if (window->cairo_surface != NULL)
886                 cairo_surface_destroy(window->cairo_surface);
887
888         window->cairo_surface = surface;
889 }
890
891 #ifdef HAVE_CAIRO_EGL
892 static void
893 window_resize_cairo_window_surface(struct window *window)
894 {
895         struct egl_window_surface_data *data;
896         int x, y;
897
898         data = cairo_surface_get_user_data(window->cairo_surface,
899                                            &surface_data_key);
900
901         window_get_resize_dx_dy(window, &x, &y),
902         wl_egl_window_resize(data->window,
903                              window->allocation.width,
904                              window->allocation.height,
905                              x,y);
906
907         cairo_gl_surface_set_size(window->cairo_surface,
908                                   window->allocation.width,
909                                   window->allocation.height);
910 }
911 #endif
912
913 struct display *
914 window_get_display(struct window *window)
915 {
916         return window->display;
917 }
918
919 void
920 window_create_surface(struct window *window)
921 {
922         cairo_surface_t *surface;
923         uint32_t flags = 0;
924         
925         if (!window->transparent)
926                 flags = SURFACE_OPAQUE;
927         
928         switch (window->buffer_type) {
929 #ifdef HAVE_CAIRO_EGL
930         case WINDOW_BUFFER_TYPE_EGL_WINDOW:
931                 if (window->cairo_surface) {
932                         window_resize_cairo_window_surface(window);
933                         return;
934                 }
935                 surface = display_create_surface(window->display,
936                                                  window->surface,
937                                                  &window->allocation, flags);
938                 break;
939 #endif
940         case WINDOW_BUFFER_TYPE_SHM:
941                 surface = display_create_shm_surface(window->display,
942                                                      &window->allocation,
943                                                      flags, window);
944                 break;
945         default:
946                 surface = NULL;
947                 break;
948         }
949
950         window_set_surface(window, surface);
951         cairo_surface_destroy(surface);
952 }
953
954 static void frame_destroy(struct frame *frame);
955
956 void
957 window_destroy(struct window *window)
958 {
959         struct display *display = window->display;
960         struct input *input;
961         struct window_output *window_output;
962         struct window_output *window_output_tmp;
963
964         if (window->redraw_scheduled)
965                 wl_list_remove(&window->redraw_task.link);
966
967         wl_list_for_each(input, &display->input_list, link) {
968                 if (input->pointer_focus == window)
969                         input->pointer_focus = NULL;
970                 if (input->keyboard_focus == window)
971                         input->keyboard_focus = NULL;
972                 if (input->focus_widget &&
973                     input->focus_widget->window == window)
974                         input->focus_widget = NULL;
975         }
976
977         wl_list_for_each_safe(window_output, window_output_tmp,
978                               &window->window_output_list, link) {
979                 free (window_output);
980         }
981
982         if (window->input_region)
983                 wl_region_destroy(window->input_region);
984         if (window->opaque_region)
985                 wl_region_destroy(window->opaque_region);
986
987         if (window->frame)
988                 frame_destroy(window->frame);
989
990         if (window->shell_surface)
991                 wl_shell_surface_destroy(window->shell_surface);
992         wl_surface_destroy(window->surface);
993         wl_list_remove(&window->link);
994
995         if (window->cairo_surface != NULL)
996                 cairo_surface_destroy(window->cairo_surface);
997
998         if (window->frame_cb)
999                 wl_callback_destroy(window->frame_cb);
1000         free(window->title);
1001         free(window);
1002 }
1003
1004 static struct widget *
1005 widget_find_widget(struct widget *widget, int32_t x, int32_t y)
1006 {
1007         struct widget *child, *target;
1008
1009         wl_list_for_each(child, &widget->child_list, link) {
1010                 target = widget_find_widget(child, x, y);
1011                 if (target)
1012                         return target;
1013         }
1014
1015         if (widget->allocation.x <= x &&
1016             x < widget->allocation.x + widget->allocation.width &&
1017             widget->allocation.y <= y &&
1018             y < widget->allocation.y + widget->allocation.height) {
1019                 return widget;
1020         }
1021
1022         return NULL;
1023 }
1024
1025 static struct widget *
1026 widget_create(struct window *window, void *data)
1027 {
1028         struct widget *widget;
1029
1030         widget = malloc(sizeof *widget);
1031         memset(widget, 0, sizeof *widget);
1032         widget->window = window;
1033         widget->user_data = data;
1034         widget->allocation = window->allocation;
1035         wl_list_init(&widget->child_list);
1036         widget->opaque = 0;
1037         widget->tooltip = NULL;
1038         widget->tooltip_count = 0;
1039
1040         return widget;
1041 }
1042
1043 struct widget *
1044 window_add_widget(struct window *window, void *data)
1045 {
1046         window->widget = widget_create(window, data);
1047         wl_list_init(&window->widget->link);
1048
1049         return window->widget;
1050 }
1051
1052 struct widget *
1053 widget_add_widget(struct widget *parent, void *data)
1054 {
1055         struct widget *widget;
1056
1057         widget = widget_create(parent->window, data);
1058         wl_list_insert(parent->child_list.prev, &widget->link);
1059
1060         return widget;
1061 }
1062
1063 void
1064 widget_destroy(struct widget *widget)
1065 {
1066         struct display *display = widget->window->display;
1067         struct input *input;
1068
1069         if (widget->tooltip) {
1070                 free(widget->tooltip);
1071                 widget->tooltip = NULL;
1072         }
1073
1074         wl_list_for_each(input, &display->input_list, link) {
1075                 if (input->focus_widget == widget)
1076                         input->focus_widget = NULL;
1077         }
1078
1079         wl_list_remove(&widget->link);
1080         free(widget);
1081 }
1082
1083 void
1084 widget_get_allocation(struct widget *widget, struct rectangle *allocation)
1085 {
1086         *allocation = widget->allocation;
1087 }
1088
1089 void
1090 widget_set_size(struct widget *widget, int32_t width, int32_t height)
1091 {
1092         widget->allocation.width = width;
1093         widget->allocation.height = height;
1094 }
1095
1096 void
1097 widget_set_allocation(struct widget *widget,
1098                       int32_t x, int32_t y, int32_t width, int32_t height)
1099 {
1100         widget->allocation.x = x;
1101         widget->allocation.y = y;
1102         widget_set_size(widget, width, height);
1103 }
1104
1105 void
1106 widget_set_transparent(struct widget *widget, int transparent)
1107 {
1108         widget->opaque = !transparent;
1109 }
1110
1111 void *
1112 widget_get_user_data(struct widget *widget)
1113 {
1114         return widget->user_data;
1115 }
1116
1117 void
1118 widget_set_resize_handler(struct widget *widget,
1119                           widget_resize_handler_t handler)
1120 {
1121         widget->resize_handler = handler;
1122 }
1123
1124 void
1125 widget_set_redraw_handler(struct widget *widget,
1126                           widget_redraw_handler_t handler)
1127 {
1128         widget->redraw_handler = handler;
1129 }
1130
1131 void
1132 widget_set_enter_handler(struct widget *widget, widget_enter_handler_t handler)
1133 {
1134         widget->enter_handler = handler;
1135 }
1136
1137 void
1138 widget_set_leave_handler(struct widget *widget, widget_leave_handler_t handler)
1139 {
1140         widget->leave_handler = handler;
1141 }
1142
1143 void
1144 widget_set_motion_handler(struct widget *widget,
1145                           widget_motion_handler_t handler)
1146 {
1147         widget->motion_handler = handler;
1148 }
1149
1150 void
1151 widget_set_button_handler(struct widget *widget,
1152                           widget_button_handler_t handler)
1153 {
1154         widget->button_handler = handler;
1155 }
1156
1157 void
1158 widget_set_axis_handler(struct widget *widget,
1159                         widget_axis_handler_t handler)
1160 {
1161         widget->axis_handler = handler;
1162 }
1163
1164 void
1165 widget_schedule_redraw(struct widget *widget)
1166 {
1167         window_schedule_redraw(widget->window);
1168 }
1169
1170 cairo_surface_t *
1171 window_get_surface(struct window *window)
1172 {
1173         return cairo_surface_reference(window->cairo_surface);
1174 }
1175
1176 struct wl_surface *
1177 window_get_wl_surface(struct window *window)
1178 {
1179         return window->surface;
1180 }
1181
1182 struct wl_shell_surface *
1183 window_get_wl_shell_surface(struct window *window)
1184 {
1185         return window->shell_surface;
1186 }
1187
1188 static void
1189 tooltip_redraw_handler(struct widget *widget, void *data)
1190 {
1191         cairo_t *cr;
1192         const int32_t r = 3;
1193         struct tooltip *tooltip = data;
1194         int32_t width, height;
1195         struct window *window = widget->window;
1196
1197         cr = cairo_create(window->cairo_surface);
1198         cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
1199         cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0);
1200         cairo_paint(cr);
1201
1202         width = window->allocation.width;
1203         height = window->allocation.height;
1204         rounded_rect(cr, 0, 0, width, height, r);
1205
1206         cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
1207         cairo_set_source_rgba(cr, 0.0, 0.0, 0.4, 0.8);
1208         cairo_fill(cr);
1209
1210         cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
1211         cairo_move_to(cr, 10, 16);
1212         cairo_show_text(cr, tooltip->entry);
1213         cairo_destroy(cr);
1214 }
1215
1216 static cairo_text_extents_t
1217 get_text_extents(struct tooltip *tooltip)
1218 {
1219         struct window *window;
1220         cairo_t *cr;
1221         cairo_text_extents_t extents;
1222
1223         /* we borrow cairo_surface from the parent cause tooltip's wasn't
1224          * created yet */
1225         window = tooltip->widget->window->parent;
1226         cr = cairo_create(window->cairo_surface);
1227         cairo_text_extents(cr, tooltip->entry, &extents);
1228         cairo_destroy(cr);
1229
1230         return extents;
1231 }
1232
1233 static int
1234 window_create_tooltip(struct tooltip *tooltip)
1235 {
1236         struct widget *parent = tooltip->parent;
1237         struct display *display = parent->window->display;
1238         struct window *window;
1239         const int offset_y = 27;
1240         const int margin = 3;
1241         cairo_text_extents_t extents;
1242
1243         if (tooltip->widget)
1244                 return 0;
1245
1246         window = window_create_transient(display, parent->window, tooltip->x,
1247                                          tooltip->y + offset_y,
1248                                          WL_SHELL_SURFACE_TRANSIENT_INACTIVE);
1249         if (!window)
1250                 return -1;
1251
1252         tooltip->window = window;
1253         tooltip->widget = window_add_widget(tooltip->window, tooltip);
1254
1255         extents = get_text_extents(tooltip);
1256         widget_set_redraw_handler(tooltip->widget, tooltip_redraw_handler);
1257         window_schedule_resize(window, extents.width + 20, 20 + margin * 2);
1258
1259         return 0;
1260 }
1261
1262 void
1263 widget_destroy_tooltip(struct widget *parent)
1264 {
1265         struct tooltip *tooltip = parent->tooltip;
1266
1267         parent->tooltip_count = 0;
1268         if (!tooltip)
1269                 return;
1270
1271         if (tooltip->widget) {
1272                 widget_destroy(tooltip->widget);
1273                 window_destroy(tooltip->window);
1274                 tooltip->widget = NULL;
1275                 tooltip->window = NULL;
1276         }
1277
1278         close(tooltip->tooltip_fd);
1279         free(tooltip->entry);
1280         free(tooltip);
1281         parent->tooltip = NULL;
1282 }
1283
1284 static void
1285 tooltip_func(struct task *task, uint32_t events)
1286 {
1287         struct tooltip *tooltip =
1288                 container_of(task, struct tooltip, tooltip_task);
1289         uint64_t exp;
1290
1291         if (read(tooltip->tooltip_fd, &exp, sizeof (uint64_t)) != sizeof (uint64_t))
1292                 abort();
1293         window_create_tooltip(tooltip);
1294 }
1295
1296 #define TOOLTIP_TIMEOUT 500
1297 static int
1298 tooltip_timer_reset(struct tooltip *tooltip)
1299 {
1300         struct itimerspec its;
1301
1302         its.it_interval.tv_sec = 0;
1303         its.it_interval.tv_nsec = 0;
1304         its.it_value.tv_sec = TOOLTIP_TIMEOUT / 1000;
1305         its.it_value.tv_nsec = (TOOLTIP_TIMEOUT % 1000) * 1000 * 1000;
1306         if (timerfd_settime(tooltip->tooltip_fd, 0, &its, NULL) < 0) {
1307                 fprintf(stderr, "could not set timerfd\n: %m");
1308                 return -1;
1309         }
1310
1311         return 0;
1312 }
1313
1314 int
1315 widget_set_tooltip(struct widget *parent, char *entry, float x, float y)
1316 {
1317         struct tooltip *tooltip = parent->tooltip;
1318
1319         parent->tooltip_count++;
1320         if (tooltip) {
1321                 tooltip->x = x;
1322                 tooltip->y = y;
1323                 tooltip_timer_reset(tooltip);
1324                 return 0;
1325         }
1326
1327         /* the handler might be triggered too fast via input device motion, so
1328          * we need this check here to make sure tooltip is fully initialized */
1329         if (parent->tooltip_count > 1)
1330                 return 0;
1331
1332         tooltip = malloc(sizeof *tooltip);
1333         if (!tooltip)
1334                 return -1;
1335
1336         parent->tooltip = tooltip;
1337         tooltip->parent = parent;
1338         tooltip->widget = NULL;
1339         tooltip->window = NULL;
1340         tooltip->x = x;
1341         tooltip->y = y;
1342         tooltip->entry = strdup(entry);
1343         tooltip->tooltip_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
1344         if (tooltip->tooltip_fd < 0) {
1345                 fprintf(stderr, "could not create timerfd\n: %m");
1346                 return -1;
1347         }
1348
1349         tooltip->tooltip_task.run = tooltip_func;
1350         display_watch_fd(parent->window->display, tooltip->tooltip_fd,
1351                          EPOLLIN, &tooltip->tooltip_task);
1352         tooltip_timer_reset(tooltip);
1353
1354         return 0;
1355 }
1356
1357 static void
1358 workspace_manager_state(void *data,
1359                         struct workspace_manager *workspace_manager,
1360                         uint32_t current,
1361                         uint32_t count)
1362 {
1363         struct display *display = data;
1364
1365         display->workspace = current;
1366         display->workspace_count = count;
1367 }
1368
1369 static const struct workspace_manager_listener workspace_manager_listener = {
1370         workspace_manager_state
1371 };
1372
1373 static void
1374 frame_resize_handler(struct widget *widget,
1375                      int32_t width, int32_t height, void *data)
1376 {
1377         struct frame *frame = data;
1378         struct widget *child = frame->child;
1379         struct rectangle allocation;
1380         struct display *display = widget->window->display;
1381         struct frame_button * button;
1382         struct theme *t = display->theme;
1383         int x_l, x_r, y, w, h;
1384         int decoration_width, decoration_height;
1385         int opaque_margin, shadow_margin;
1386
1387         switch (widget->window->type) {
1388         case TYPE_FULLSCREEN:
1389                 decoration_width = 0;
1390                 decoration_height = 0;
1391
1392                 allocation.x = 0;
1393                 allocation.y = 0;
1394                 allocation.width = width;
1395                 allocation.height = height;
1396                 opaque_margin = 0;
1397
1398                 wl_list_for_each(button, &frame->buttons_list, link)
1399                         button->widget->opaque = 1;
1400                 break;
1401         case TYPE_MAXIMIZED:
1402                 decoration_width = t->width * 2;
1403                 decoration_height = t->width + t->titlebar_height;
1404
1405                 allocation.x = t->width;
1406                 allocation.y = t->titlebar_height;
1407                 allocation.width = width - decoration_width;
1408                 allocation.height = height - decoration_height;
1409
1410                 opaque_margin = 0;
1411
1412                 wl_list_for_each(button, &frame->buttons_list, link)
1413                         button->widget->opaque = 0;
1414                 break;
1415         default:
1416                 decoration_width = (t->width + t->margin) * 2;
1417                 decoration_height = t->width +
1418                         t->titlebar_height + t->margin * 2;
1419
1420                 allocation.x = t->width + t->margin;
1421                 allocation.y = t->titlebar_height + t->margin;
1422                 allocation.width = width - decoration_width;
1423                 allocation.height = height - decoration_height;
1424
1425                 opaque_margin = t->margin + t->frame_radius;
1426
1427                 wl_list_for_each(button, &frame->buttons_list, link)
1428                         button->widget->opaque = 0;
1429                 break;
1430         }
1431
1432         widget_set_allocation(child, allocation.x, allocation.y,
1433                               allocation.width, allocation.height);
1434
1435         if (child->resize_handler)
1436                 child->resize_handler(child,
1437                                       allocation.width,
1438                                       allocation.height,
1439                                       child->user_data);
1440
1441         width = child->allocation.width + decoration_width;
1442         height = child->allocation.height + decoration_height;
1443
1444         shadow_margin = widget->window->type == TYPE_MAXIMIZED ? 0 : t->margin;
1445
1446         if (widget->window->type != TYPE_FULLSCREEN) {
1447                 widget->window->input_region =
1448                         wl_compositor_create_region(display->compositor);
1449                 wl_region_add(widget->window->input_region,
1450                               shadow_margin, shadow_margin,
1451                               width - 2 * shadow_margin,
1452                               height - 2 * shadow_margin);
1453         }
1454
1455         widget_set_allocation(widget, 0, 0, width, height);
1456
1457         if (child->opaque) {
1458                 widget->window->opaque_region =
1459                         wl_compositor_create_region(display->compositor);
1460                 wl_region_add(widget->window->opaque_region,
1461                               opaque_margin, opaque_margin,
1462                               widget->allocation.width - 2 * opaque_margin,
1463                               widget->allocation.height - 2 * opaque_margin);
1464         }
1465
1466         /* frame internal buttons */
1467         x_r = frame->widget->allocation.width - t->width - shadow_margin;
1468         x_l = t->width + shadow_margin;
1469         y = t->width + shadow_margin;
1470         wl_list_for_each(button, &frame->buttons_list, link) {
1471                 const int button_padding = 4;
1472                 w = cairo_image_surface_get_width(button->icon);
1473                 h = cairo_image_surface_get_height(button->icon);
1474
1475                 if (button->decoration == FRAME_BUTTON_FANCY)
1476                         w += 10;
1477
1478                 if (button->align == FRAME_BUTTON_LEFT) {
1479                         widget_set_allocation(button->widget,
1480                                               x_l, y , w + 1, h + 1);
1481                         x_l += w;
1482                         x_l += button_padding;
1483                 } else {
1484                         x_r -= w;
1485                         widget_set_allocation(button->widget,
1486                                               x_r, y , w + 1, h + 1);
1487                         x_r -= button_padding;
1488                 }
1489         }
1490 }
1491
1492 static int
1493 frame_button_enter_handler(struct widget *widget,
1494                            struct input *input, float x, float y, void *data)
1495 {
1496         struct frame_button *frame_button = data;
1497
1498         widget_schedule_redraw(frame_button->widget);
1499         frame_button->state = FRAME_BUTTON_OVER;
1500
1501         return CURSOR_LEFT_PTR;
1502 }
1503
1504 static void
1505 frame_button_leave_handler(struct widget *widget, struct input *input, void *data)
1506 {
1507         struct frame_button *frame_button = data;
1508
1509         widget_schedule_redraw(frame_button->widget);
1510         frame_button->state = FRAME_BUTTON_DEFAULT;
1511 }
1512
1513 static void
1514 frame_button_button_handler(struct widget *widget,
1515                             struct input *input, uint32_t time,
1516                             uint32_t button,
1517                             enum wl_pointer_button_state state, void *data)
1518 {
1519         struct frame_button *frame_button = data;
1520         struct window *window = widget->window;
1521         int was_pressed = (frame_button->state == FRAME_BUTTON_ACTIVE);
1522
1523         if (button != BTN_LEFT)
1524                 return;
1525
1526         switch (state) {
1527         case WL_POINTER_BUTTON_STATE_PRESSED:
1528                 frame_button->state = FRAME_BUTTON_ACTIVE;
1529                 widget_schedule_redraw(frame_button->widget);
1530
1531                 if (frame_button->type == FRAME_BUTTON_ICON)
1532                         window_show_frame_menu(window, input, time);
1533                 return;
1534         case WL_POINTER_BUTTON_STATE_RELEASED:
1535                 frame_button->state = FRAME_BUTTON_DEFAULT;
1536                 widget_schedule_redraw(frame_button->widget);
1537                 break;
1538         }
1539
1540         if (!was_pressed)
1541                 return;
1542
1543         switch (frame_button->type) {
1544         case FRAME_BUTTON_CLOSE:
1545                 if (window->close_handler)
1546                         window->close_handler(window->parent,
1547                                               window->user_data);
1548                 else
1549                         display_exit(window->display);
1550                 break;
1551         case FRAME_BUTTON_MINIMIZE:
1552                 fprintf(stderr,"Minimize stub\n");
1553                 break;
1554         case FRAME_BUTTON_MAXIMIZE:
1555                 window_set_maximized(window, window->type != TYPE_MAXIMIZED);
1556                 break;
1557         default:
1558                 /* Unknown operation */
1559                 break;
1560         }
1561 }
1562
1563 static int
1564 frame_button_motion_handler(struct widget *widget,
1565                             struct input *input, uint32_t time,
1566                             float x, float y, void *data)
1567 {
1568         struct frame_button *frame_button = data;
1569         enum frame_button_pointer previous_button_state = frame_button->state;
1570
1571         /* only track state for a pressed button */
1572         if (input->grab != widget)
1573                 return CURSOR_LEFT_PTR;
1574
1575         if (x > widget->allocation.x &&
1576             x < (widget->allocation.x + widget->allocation.width) &&
1577             y > widget->allocation.y &&
1578             y < (widget->allocation.y + widget->allocation.height)) {
1579                 frame_button->state = FRAME_BUTTON_ACTIVE;
1580         } else {
1581                 frame_button->state = FRAME_BUTTON_DEFAULT;
1582         }
1583
1584         if (frame_button->state != previous_button_state)
1585                 widget_schedule_redraw(frame_button->widget);
1586
1587         return CURSOR_LEFT_PTR;
1588 }
1589
1590 static void
1591 frame_button_redraw_handler(struct widget *widget, void *data)
1592 {
1593         struct frame_button *frame_button = data;
1594         cairo_t *cr;
1595         int width, height, x, y;
1596         struct window *window = widget->window;
1597
1598         x = widget->allocation.x;
1599         y = widget->allocation.y;
1600         width = widget->allocation.width;
1601         height = widget->allocation.height;
1602
1603         if (!width)
1604                 return;
1605         if (!height)
1606                 return;
1607         if (widget->opaque)
1608                 return;
1609
1610         cr = cairo_create(window->cairo_surface);
1611
1612         if (frame_button->decoration == FRAME_BUTTON_FANCY) {
1613                 cairo_set_line_width(cr, 1);
1614
1615                 cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
1616                 cairo_rectangle (cr, x, y, 25, 16);
1617
1618                 cairo_stroke_preserve(cr);
1619
1620                 switch (frame_button->state) {
1621                 case FRAME_BUTTON_DEFAULT:
1622                         cairo_set_source_rgb(cr, 0.88, 0.88, 0.88);
1623                         break;
1624                 case FRAME_BUTTON_OVER:
1625                         cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
1626                         break;
1627                 case FRAME_BUTTON_ACTIVE:
1628                         cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
1629                         break;
1630                 }
1631
1632                 cairo_fill (cr);
1633
1634                 x += 4;
1635         }
1636
1637         cairo_set_source_surface(cr, frame_button->icon, x, y);
1638         cairo_paint(cr);
1639
1640         cairo_destroy(cr);
1641 }
1642
1643 static struct widget *
1644 frame_button_create(struct frame *frame, void *data, enum frame_button_action type,
1645         enum frame_button_align align, enum frame_button_decoration style)
1646 {
1647         struct frame_button *frame_button;
1648         const char *icon = data;
1649
1650         frame_button = malloc (sizeof *frame_button);
1651         memset(frame_button, 0, sizeof *frame_button);
1652
1653         frame_button->icon = cairo_image_surface_create_from_png(icon);
1654         frame_button->widget = widget_add_widget(frame->widget, frame_button);
1655         frame_button->frame = frame;
1656         frame_button->type = type;
1657         frame_button->align = align;
1658         frame_button->decoration = style;
1659
1660         wl_list_insert(frame->buttons_list.prev, &frame_button->link);
1661
1662         widget_set_redraw_handler(frame_button->widget, frame_button_redraw_handler);
1663         widget_set_enter_handler(frame_button->widget, frame_button_enter_handler);
1664         widget_set_leave_handler(frame_button->widget, frame_button_leave_handler);
1665         widget_set_button_handler(frame_button->widget, frame_button_button_handler);
1666         widget_set_motion_handler(frame_button->widget, frame_button_motion_handler);
1667         return frame_button->widget;
1668 }
1669
1670 static void
1671 frame_button_destroy(struct frame_button *frame_button)
1672 {
1673         widget_destroy(frame_button->widget);
1674         wl_list_remove(&frame_button->link);
1675         cairo_surface_destroy(frame_button->icon);
1676         free(frame_button);
1677
1678         return;
1679 }
1680
1681 static void
1682 frame_redraw_handler(struct widget *widget, void *data)
1683 {
1684         cairo_t *cr;
1685         struct window *window = widget->window;
1686         struct theme *t = window->display->theme;
1687         uint32_t flags = 0;
1688
1689         if (window->type == TYPE_FULLSCREEN)
1690                 return;
1691
1692         cr = cairo_create(window->cairo_surface);
1693
1694         if (window->focus_count)
1695                 flags |= THEME_FRAME_ACTIVE;
1696         if (window->type == TYPE_MAXIMIZED)
1697                 flags |= THEME_FRAME_MAXIMIZED;
1698         theme_render_frame(t, cr, widget->allocation.width,
1699                            widget->allocation.height, window->title, flags);
1700
1701         cairo_destroy(cr);
1702 }
1703
1704 static int
1705 frame_get_pointer_image_for_location(struct frame *frame, struct input *input)
1706 {
1707         struct theme *t = frame->widget->window->display->theme;
1708         struct window *window = frame->widget->window;
1709         int location;
1710
1711         location = theme_get_location(t, input->sx, input->sy,
1712                                       frame->widget->allocation.width,
1713                                       frame->widget->allocation.height,
1714                                       window->type == TYPE_MAXIMIZED ?
1715                                       THEME_FRAME_MAXIMIZED : 0);
1716
1717         switch (location) {
1718         case THEME_LOCATION_RESIZING_TOP:
1719                 return CURSOR_TOP;
1720         case THEME_LOCATION_RESIZING_BOTTOM:
1721                 return CURSOR_BOTTOM;
1722         case THEME_LOCATION_RESIZING_LEFT:
1723                 return CURSOR_LEFT;
1724         case THEME_LOCATION_RESIZING_RIGHT:
1725                 return CURSOR_RIGHT;
1726         case THEME_LOCATION_RESIZING_TOP_LEFT:
1727                 return CURSOR_TOP_LEFT;
1728         case THEME_LOCATION_RESIZING_TOP_RIGHT:
1729                 return CURSOR_TOP_RIGHT;
1730         case THEME_LOCATION_RESIZING_BOTTOM_LEFT:
1731                 return CURSOR_BOTTOM_LEFT;
1732         case THEME_LOCATION_RESIZING_BOTTOM_RIGHT:
1733                 return CURSOR_BOTTOM_RIGHT;
1734         case THEME_LOCATION_EXTERIOR:
1735         case THEME_LOCATION_TITLEBAR:
1736         default:
1737                 return CURSOR_LEFT_PTR;
1738         }
1739 }
1740
1741 static void
1742 frame_menu_func(struct window *window, int index, void *data)
1743 {
1744         struct display *display;
1745
1746         switch (index) {
1747         case 0: /* close */
1748                 if (window->close_handler)
1749                         window->close_handler(window->parent,
1750                                               window->user_data);
1751                 else
1752                         display_exit(window->display);
1753                 break;
1754         case 1: /* fullscreen */
1755                 /* we don't have a way to get out of fullscreen for now */
1756                 if (window->fullscreen_handler)
1757                         window->fullscreen_handler(window, window->user_data);
1758                 break;
1759         case 2: /* move to workspace above */
1760                 display = window->display;
1761                 if (display->workspace > 0)
1762                         workspace_manager_move_surface(display->workspace_manager,
1763                                                        window->surface,
1764                                                        display->workspace - 1);
1765                 break;
1766         case 3: /* move to workspace below */
1767                 display = window->display;
1768                 if (display->workspace < display->workspace_count - 1)
1769                         workspace_manager_move_surface(display->workspace_manager,
1770                                                        window->surface,
1771                                                        display->workspace + 1);
1772                 break;
1773         }
1774 }
1775
1776 void
1777 window_show_frame_menu(struct window *window,
1778                        struct input *input, uint32_t time)
1779 {
1780         int32_t x, y;
1781
1782         static const char *entries[] = {
1783                 "Close", "Fullscreen",
1784                 "Move to workspace above", "Move to workspace below"
1785         };
1786
1787         input_get_position(input, &x, &y);
1788         window_show_menu(window->display, input, time, window,
1789                          x - 10, y - 10, frame_menu_func, entries,
1790                          ARRAY_LENGTH(entries));
1791 }
1792
1793 static int
1794 frame_enter_handler(struct widget *widget,
1795                     struct input *input, float x, float y, void *data)
1796 {
1797         return frame_get_pointer_image_for_location(data, input);
1798 }
1799
1800 static int
1801 frame_motion_handler(struct widget *widget,
1802                      struct input *input, uint32_t time,
1803                      float x, float y, void *data)
1804 {
1805         return frame_get_pointer_image_for_location(data, input);
1806 }
1807
1808 static void
1809 frame_button_handler(struct widget *widget,
1810                      struct input *input, uint32_t time,
1811                      uint32_t button, enum wl_pointer_button_state state,
1812                      void *data)
1813
1814 {
1815         struct frame *frame = data;
1816         struct window *window = widget->window;
1817         struct display *display = window->display;
1818         int location;
1819
1820         location = theme_get_location(display->theme, input->sx, input->sy,
1821                                       frame->widget->allocation.width,
1822                                       frame->widget->allocation.height,
1823                                       window->type == TYPE_MAXIMIZED ?
1824                                       THEME_FRAME_MAXIMIZED : 0);
1825
1826         if (window->display->shell && button == BTN_LEFT &&
1827             state == WL_POINTER_BUTTON_STATE_PRESSED) {
1828                 switch (location) {
1829                 case THEME_LOCATION_TITLEBAR:
1830                         if (!window->shell_surface)
1831                                 break;
1832                         input_set_pointer_image(input, CURSOR_DRAGGING);
1833                         input_ungrab(input);
1834                         wl_shell_surface_move(window->shell_surface,
1835                                               input_get_seat(input),
1836                                               display->serial);
1837                         break;
1838                 case THEME_LOCATION_RESIZING_TOP:
1839                 case THEME_LOCATION_RESIZING_BOTTOM:
1840                 case THEME_LOCATION_RESIZING_LEFT:
1841                 case THEME_LOCATION_RESIZING_RIGHT:
1842                 case THEME_LOCATION_RESIZING_TOP_LEFT:
1843                 case THEME_LOCATION_RESIZING_TOP_RIGHT:
1844                 case THEME_LOCATION_RESIZING_BOTTOM_LEFT:
1845                 case THEME_LOCATION_RESIZING_BOTTOM_RIGHT:
1846                         if (!window->shell_surface)
1847                                 break;
1848                         input_ungrab(input);
1849
1850                         if (!display->dpy) {
1851                                 /* If we're using shm, allocate a big
1852                                    pool to create buffers out of while
1853                                    we resize.  We should probably base
1854                                    this number on the size of the output. */
1855                                 window->pool =
1856                                         shm_pool_create(display, 6 * 1024 * 1024);
1857                         }
1858
1859                         wl_shell_surface_resize(window->shell_surface,
1860                                                 input_get_seat(input),
1861                                                 display->serial, location);
1862                         break;
1863                 }
1864         } else if (button == BTN_RIGHT &&
1865                    state == WL_POINTER_BUTTON_STATE_PRESSED) {
1866                 window_show_frame_menu(window, input, time);
1867         }
1868 }
1869
1870 struct widget *
1871 frame_create(struct window *window, void *data)
1872 {
1873         struct frame *frame;
1874
1875         frame = malloc(sizeof *frame);
1876         memset(frame, 0, sizeof *frame);
1877
1878         frame->widget = window_add_widget(window, frame);
1879         frame->child = widget_add_widget(frame->widget, data);
1880
1881         widget_set_redraw_handler(frame->widget, frame_redraw_handler);
1882         widget_set_resize_handler(frame->widget, frame_resize_handler);
1883         widget_set_enter_handler(frame->widget, frame_enter_handler);
1884         widget_set_motion_handler(frame->widget, frame_motion_handler);
1885         widget_set_button_handler(frame->widget, frame_button_handler);
1886
1887         /* Create empty list for frame buttons */
1888         wl_list_init(&frame->buttons_list);
1889
1890         frame_button_create(frame, DATADIR "/weston/icon_window.png",
1891                 FRAME_BUTTON_ICON, FRAME_BUTTON_LEFT, FRAME_BUTTON_NONE);
1892
1893         frame_button_create(frame, DATADIR "/weston/sign_close.png",
1894                 FRAME_BUTTON_CLOSE, FRAME_BUTTON_RIGHT, FRAME_BUTTON_FANCY);
1895
1896         frame_button_create(frame, DATADIR "/weston/sign_maximize.png",
1897                 FRAME_BUTTON_MAXIMIZE, FRAME_BUTTON_RIGHT, FRAME_BUTTON_FANCY);
1898
1899         frame_button_create(frame, DATADIR "/weston/sign_minimize.png",
1900                 FRAME_BUTTON_MINIMIZE, FRAME_BUTTON_RIGHT, FRAME_BUTTON_FANCY);
1901
1902         window->frame = frame;
1903
1904         return frame->child;
1905 }
1906
1907 void
1908 frame_set_child_size(struct widget *widget, int child_width, int child_height)
1909 {
1910         struct display *display = widget->window->display;
1911         struct theme *t = display->theme;
1912         int decoration_width, decoration_height;
1913         int width, height;
1914         int margin = widget->window->type == TYPE_MAXIMIZED ? 0 : t->margin;
1915
1916         if (widget->window->type != TYPE_FULLSCREEN) {
1917                 decoration_width = (t->width + margin) * 2;
1918                 decoration_height = t->width +
1919                         t->titlebar_height + margin * 2;
1920
1921                 width = child_width + decoration_width;
1922                 height = child_height + decoration_height;
1923         } else {
1924                 width = child_width;
1925                 height = child_height;
1926         }
1927
1928         window_schedule_resize(widget->window, width, height);
1929 }
1930
1931 static void
1932 frame_destroy(struct frame *frame)
1933 {
1934         struct frame_button *button, *tmp;
1935
1936         wl_list_for_each_safe(button, tmp, &frame->buttons_list, link)
1937                 frame_button_destroy(button);
1938
1939         /* frame->child must be destroyed by the application */
1940         widget_destroy(frame->widget);
1941         free(frame);
1942 }
1943
1944 static void
1945 input_set_focus_widget(struct input *input, struct widget *focus,
1946                        float x, float y)
1947 {
1948         struct widget *old, *widget;
1949         int pointer = CURSOR_LEFT_PTR;
1950
1951         if (focus == input->focus_widget)
1952                 return;
1953
1954         old = input->focus_widget;
1955         if (old) {
1956                 widget = old;
1957                 if (input->grab)
1958                         widget = input->grab;
1959                 if (widget->leave_handler)
1960                         widget->leave_handler(old, input, widget->user_data);
1961                 input->focus_widget = NULL;
1962         }
1963
1964         if (focus) {
1965                 widget = focus;
1966                 if (input->grab)
1967                         widget = input->grab;
1968                 input->focus_widget = focus;
1969                 if (widget->enter_handler)
1970                         pointer = widget->enter_handler(focus, input, x, y,
1971                                                         widget->user_data);
1972
1973                 input_set_pointer_image(input, pointer);
1974         }
1975 }
1976
1977 void
1978 input_grab(struct input *input, struct widget *widget, uint32_t button)
1979 {
1980         input->grab = widget;
1981         input->grab_button = button;
1982 }
1983
1984 void
1985 input_ungrab(struct input *input)
1986 {
1987         struct widget *widget;
1988
1989         input->grab = NULL;
1990         if (input->pointer_focus) {
1991                 widget = widget_find_widget(input->pointer_focus->widget,
1992                                             input->sx, input->sy);
1993                 input_set_focus_widget(input, widget, input->sx, input->sy);
1994         }
1995 }
1996
1997 static void
1998 input_remove_pointer_focus(struct input *input)
1999 {
2000         struct window *window = input->pointer_focus;
2001
2002         if (!window)
2003                 return;
2004
2005         input_set_focus_widget(input, NULL, 0, 0);
2006
2007         input->pointer_focus = NULL;
2008         input->current_cursor = CURSOR_UNSET;
2009 }
2010
2011 static void
2012 pointer_handle_enter(void *data, struct wl_pointer *pointer,
2013                      uint32_t serial, struct wl_surface *surface,
2014                      wl_fixed_t sx_w, wl_fixed_t sy_w)
2015 {
2016         struct input *input = data;
2017         struct window *window;
2018         struct widget *widget;
2019         float sx = wl_fixed_to_double(sx_w);
2020         float sy = wl_fixed_to_double(sy_w);
2021
2022         if (!surface) {
2023                 /* enter event for a window we've just destroyed */
2024                 return;
2025         }
2026
2027         input->display->serial = serial;
2028         input->pointer_enter_serial = serial;
2029         input->pointer_focus = wl_surface_get_user_data(surface);
2030         window = input->pointer_focus;
2031
2032         if (window->pool) {
2033                 shm_pool_destroy(window->pool);
2034                 window->pool = NULL;
2035                 /* Schedule a redraw to free the pool */
2036                 window_schedule_redraw(window);
2037         }
2038
2039         input->sx = sx;
2040         input->sy = sy;
2041
2042         widget = widget_find_widget(window->widget, sx, sy);
2043         input_set_focus_widget(input, widget, sx, sy);
2044 }
2045
2046 static void
2047 pointer_handle_leave(void *data, struct wl_pointer *pointer,
2048                      uint32_t serial, struct wl_surface *surface)
2049 {
2050         struct input *input = data;
2051
2052         input->display->serial = serial;
2053         input_remove_pointer_focus(input);
2054 }
2055
2056 static void
2057 pointer_handle_motion(void *data, struct wl_pointer *pointer,
2058                       uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w)
2059 {
2060         struct input *input = data;
2061         struct window *window = input->pointer_focus;
2062         struct widget *widget;
2063         int cursor = CURSOR_LEFT_PTR;
2064         float sx = wl_fixed_to_double(sx_w);
2065         float sy = wl_fixed_to_double(sy_w);
2066
2067         input->sx = sx;
2068         input->sy = sy;
2069
2070         if (!window)
2071                 return;
2072
2073         if (!(input->grab && input->grab_button)) {
2074                 widget = widget_find_widget(window->widget, sx, sy);
2075                 input_set_focus_widget(input, widget, sx, sy);
2076         }
2077
2078         if (input->grab)
2079                 widget = input->grab;
2080         else
2081                 widget = input->focus_widget;
2082         if (widget && widget->motion_handler)
2083                 cursor = widget->motion_handler(widget,
2084                                                 input, time, sx, sy,
2085                                                 widget->user_data);
2086
2087         input_set_pointer_image(input, cursor);
2088 }
2089
2090 static void
2091 pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
2092                       uint32_t time, uint32_t button, uint32_t state_w)
2093 {
2094         struct input *input = data;
2095         struct widget *widget;
2096         enum wl_pointer_button_state state = state_w;
2097
2098         input->display->serial = serial;
2099         if (input->focus_widget && input->grab == NULL &&
2100             state == WL_POINTER_BUTTON_STATE_PRESSED)
2101                 input_grab(input, input->focus_widget, button);
2102
2103         widget = input->grab;
2104         if (widget && widget->button_handler)
2105                 (*widget->button_handler)(widget,
2106                                           input, time,
2107                                           button, state,
2108                                           input->grab->user_data);
2109
2110         if (input->grab && input->grab_button == button &&
2111             state == WL_POINTER_BUTTON_STATE_RELEASED)
2112                 input_ungrab(input);
2113 }
2114
2115 static void
2116 pointer_handle_axis(void *data, struct wl_pointer *pointer,
2117                     uint32_t time, uint32_t axis, wl_fixed_t value)
2118 {
2119         struct input *input = data;
2120         struct widget *widget;
2121
2122         widget = input->focus_widget;
2123         if (input->grab)
2124                 widget = input->grab;
2125         if (widget && widget->axis_handler)
2126                 (*widget->axis_handler)(widget,
2127                                         input, time,
2128                                         axis, value,
2129                                         widget->user_data);
2130 }
2131
2132 static const struct wl_pointer_listener pointer_listener = {
2133         pointer_handle_enter,
2134         pointer_handle_leave,
2135         pointer_handle_motion,
2136         pointer_handle_button,
2137         pointer_handle_axis,
2138 };
2139
2140 static void
2141 input_remove_keyboard_focus(struct input *input)
2142 {
2143         struct window *window = input->keyboard_focus;
2144         struct itimerspec its;
2145
2146         its.it_interval.tv_sec = 0;
2147         its.it_interval.tv_nsec = 0;
2148         its.it_value.tv_sec = 0;
2149         its.it_value.tv_nsec = 0;
2150         timerfd_settime(input->repeat_timer_fd, 0, &its, NULL);
2151
2152         if (!window)
2153                 return;
2154
2155         window->focus_count--;
2156         if (window->keyboard_focus_handler)
2157                 (*window->keyboard_focus_handler)(window, NULL,
2158                                                   window->user_data);
2159
2160         input->keyboard_focus = NULL;
2161 }
2162
2163 static void
2164 keyboard_repeat_func(struct task *task, uint32_t events)
2165 {
2166         struct input *input =
2167                 container_of(task, struct input, repeat_task);
2168         struct window *window = input->keyboard_focus;
2169         uint64_t exp;
2170
2171         if (read(input->repeat_timer_fd, &exp, sizeof exp) != sizeof exp)
2172                 /* If we change the timer between the fd becoming
2173                  * readable and getting here, there'll be nothing to
2174                  * read and we get EAGAIN. */
2175                 return;
2176
2177         if (window && window->key_handler) {
2178                 (*window->key_handler)(window, input, input->repeat_time,
2179                                        input->repeat_key, input->repeat_sym,
2180                                        WL_KEYBOARD_KEY_STATE_PRESSED,
2181                                        window->user_data);
2182         }
2183 }
2184
2185 static void
2186 keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
2187                        uint32_t format, int fd, uint32_t size)
2188 {
2189         struct input *input = data;
2190         char *map_str;
2191
2192         if (!data) {
2193                 close(fd);
2194                 return;
2195         }
2196
2197         if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
2198                 close(fd);
2199                 return;
2200         }
2201
2202         map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
2203         if (map_str == MAP_FAILED) {
2204                 close(fd);
2205                 return;
2206         }
2207
2208         input->xkb.keymap = xkb_map_new_from_string(input->display->xkb_context,
2209                                                     map_str,
2210                                                     XKB_KEYMAP_FORMAT_TEXT_V1,
2211                                                     0);
2212         munmap(map_str, size);
2213         close(fd);
2214
2215         if (!input->xkb.keymap) {
2216                 fprintf(stderr, "failed to compile keymap\n");
2217                 return;
2218         }
2219
2220         input->xkb.state = xkb_state_new(input->xkb.keymap);
2221         if (!input->xkb.state) {
2222                 fprintf(stderr, "failed to create XKB state\n");
2223                 xkb_map_unref(input->xkb.keymap);
2224                 input->xkb.keymap = NULL;
2225                 return;
2226         }
2227
2228         input->xkb.control_mask =
2229                 1 << xkb_map_mod_get_index(input->xkb.keymap, "Control");
2230         input->xkb.alt_mask =
2231                 1 << xkb_map_mod_get_index(input->xkb.keymap, "Mod1");
2232         input->xkb.shift_mask =
2233                 1 << xkb_map_mod_get_index(input->xkb.keymap, "Shift");
2234 }
2235
2236 static void
2237 keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
2238                       uint32_t serial, struct wl_surface *surface,
2239                       struct wl_array *keys)
2240 {
2241         struct input *input = data;
2242         struct window *window;
2243
2244         input->display->serial = serial;
2245         input->keyboard_focus = wl_surface_get_user_data(surface);
2246
2247         window = input->keyboard_focus;
2248         window->focus_count++;
2249         if (window->keyboard_focus_handler)
2250                 (*window->keyboard_focus_handler)(window,
2251                                                   input, window->user_data);
2252 }
2253
2254 static void
2255 keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
2256                       uint32_t serial, struct wl_surface *surface)
2257 {
2258         struct input *input = data;
2259
2260         input->display->serial = serial;
2261         input_remove_keyboard_focus(input);
2262 }
2263
2264 static void
2265 keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
2266                     uint32_t serial, uint32_t time, uint32_t key,
2267                     uint32_t state_w)
2268 {
2269         struct input *input = data;
2270         struct window *window = input->keyboard_focus;
2271         uint32_t code, num_syms;
2272         enum wl_keyboard_key_state state = state_w;
2273         const xkb_keysym_t *syms;
2274         xkb_keysym_t sym;
2275         xkb_mod_mask_t mask;
2276         struct itimerspec its;
2277
2278         input->display->serial = serial;
2279         code = key + 8;
2280         if (!window || !input->xkb.state)
2281                 return;
2282
2283         num_syms = xkb_key_get_syms(input->xkb.state, code, &syms);
2284
2285         mask = xkb_state_serialize_mods(input->xkb.state,
2286                                         XKB_STATE_DEPRESSED |
2287                                         XKB_STATE_LATCHED);
2288         input->modifiers = 0;
2289         if (mask & input->xkb.control_mask)
2290                 input->modifiers |= MOD_CONTROL_MASK;
2291         if (mask & input->xkb.alt_mask)
2292                 input->modifiers |= MOD_ALT_MASK;
2293         if (mask & input->xkb.shift_mask)
2294                 input->modifiers |= MOD_SHIFT_MASK;
2295
2296         sym = XKB_KEY_NoSymbol;
2297         if (num_syms == 1)
2298                 sym = syms[0];
2299
2300         if (sym == XKB_KEY_F5 && input->modifiers == MOD_ALT_MASK) {
2301                 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
2302                         window_set_maximized(window,
2303                                              window->type != TYPE_MAXIMIZED);
2304         } else if (sym == XKB_KEY_F11 &&
2305                    window->fullscreen_handler &&
2306                    state == WL_KEYBOARD_KEY_STATE_PRESSED) {
2307                 window->fullscreen_handler(window, window->user_data);
2308         } else if (sym == XKB_KEY_F4 &&
2309                    input->modifiers == MOD_ALT_MASK &&
2310                    state == WL_KEYBOARD_KEY_STATE_PRESSED) {
2311                 if (window->close_handler)
2312                         window->close_handler(window->parent,
2313                                               window->user_data);
2314                 else
2315                         display_exit(window->display);
2316         } else if (window->key_handler) {
2317                 (*window->key_handler)(window, input, time, key,
2318                                        sym, state, window->user_data);
2319         }
2320
2321         if (state == WL_KEYBOARD_KEY_STATE_RELEASED &&
2322             key == input->repeat_key) {
2323                 its.it_interval.tv_sec = 0;
2324                 its.it_interval.tv_nsec = 0;
2325                 its.it_value.tv_sec = 0;
2326                 its.it_value.tv_nsec = 0;
2327                 timerfd_settime(input->repeat_timer_fd, 0, &its, NULL);
2328         } else if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
2329                 input->repeat_sym = sym;
2330                 input->repeat_key = key;
2331                 input->repeat_time = time;
2332                 its.it_interval.tv_sec = 0;
2333                 its.it_interval.tv_nsec = 25 * 1000 * 1000;
2334                 its.it_value.tv_sec = 0;
2335                 its.it_value.tv_nsec = 400 * 1000 * 1000;
2336                 timerfd_settime(input->repeat_timer_fd, 0, &its, NULL);
2337         }
2338 }
2339
2340 static void
2341 keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
2342                           uint32_t serial, uint32_t mods_depressed,
2343                           uint32_t mods_latched, uint32_t mods_locked,
2344                           uint32_t group)
2345 {
2346         struct input *input = data;
2347
2348         xkb_state_update_mask(input->xkb.state, mods_depressed, mods_latched,
2349                               mods_locked, 0, 0, group);
2350 }
2351
2352 static const struct wl_keyboard_listener keyboard_listener = {
2353         keyboard_handle_keymap,
2354         keyboard_handle_enter,
2355         keyboard_handle_leave,
2356         keyboard_handle_key,
2357         keyboard_handle_modifiers,
2358 };
2359
2360 static void
2361 seat_handle_capabilities(void *data, struct wl_seat *seat,
2362                          enum wl_seat_capability caps)
2363 {
2364         struct input *input = data;
2365
2366         if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->pointer) {
2367                 input->pointer = wl_seat_get_pointer(seat);
2368                 wl_pointer_set_user_data(input->pointer, input);
2369                 wl_pointer_add_listener(input->pointer, &pointer_listener,
2370                                         input);
2371         } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->pointer) {
2372                 wl_pointer_destroy(input->pointer);
2373                 input->pointer = NULL;
2374         }
2375
2376         if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input->keyboard) {
2377                 input->keyboard = wl_seat_get_keyboard(seat);
2378                 wl_keyboard_set_user_data(input->keyboard, input);
2379                 wl_keyboard_add_listener(input->keyboard, &keyboard_listener,
2380                                          input);
2381         } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->keyboard) {
2382                 wl_keyboard_destroy(input->keyboard);
2383                 input->keyboard = NULL;
2384         }
2385 }
2386
2387 static const struct wl_seat_listener seat_listener = {
2388         seat_handle_capabilities,
2389 };
2390
2391 void
2392 input_get_position(struct input *input, int32_t *x, int32_t *y)
2393 {
2394         *x = input->sx;
2395         *y = input->sy;
2396 }
2397
2398 struct display *
2399 input_get_display(struct input *input)
2400 {
2401         return input->display;
2402 }
2403
2404 struct wl_seat *
2405 input_get_seat(struct input *input)
2406 {
2407         return input->seat;
2408 }
2409
2410 uint32_t
2411 input_get_modifiers(struct input *input)
2412 {
2413         return input->modifiers;
2414 }
2415
2416 struct widget *
2417 input_get_focus_widget(struct input *input)
2418 {
2419         return input->focus_widget;
2420 }
2421
2422 struct data_offer {
2423         struct wl_data_offer *offer;
2424         struct input *input;
2425         struct wl_array types;
2426         int refcount;
2427
2428         struct task io_task;
2429         int fd;
2430         data_func_t func;
2431         int32_t x, y;
2432         void *user_data;
2433 };
2434
2435 static void
2436 data_offer_offer(void *data, struct wl_data_offer *wl_data_offer, const char *type)
2437 {
2438         struct data_offer *offer = data;
2439         char **p;
2440
2441         p = wl_array_add(&offer->types, sizeof *p);
2442         *p = strdup(type);
2443 }
2444
2445 static const struct wl_data_offer_listener data_offer_listener = {
2446         data_offer_offer,
2447 };
2448
2449 static void
2450 data_offer_destroy(struct data_offer *offer)
2451 {
2452         char **p;
2453
2454         offer->refcount--;
2455         if (offer->refcount == 0) {
2456                 wl_data_offer_destroy(offer->offer);
2457                 for (p = offer->types.data; *p; p++)
2458                         free(*p);
2459                 wl_array_release(&offer->types);
2460                 free(offer);
2461         }
2462 }
2463
2464 static void
2465 data_device_data_offer(void *data,
2466                        struct wl_data_device *data_device,
2467                        struct wl_data_offer *_offer)
2468 {
2469         struct data_offer *offer;
2470
2471         offer = malloc(sizeof *offer);
2472
2473         wl_array_init(&offer->types);
2474         offer->refcount = 1;
2475         offer->input = data;
2476         offer->offer = _offer;
2477         wl_data_offer_add_listener(offer->offer,
2478                                    &data_offer_listener, offer);
2479 }
2480
2481 static void
2482 data_device_enter(void *data, struct wl_data_device *data_device,
2483                   uint32_t serial, struct wl_surface *surface,
2484                   wl_fixed_t x_w, wl_fixed_t y_w,
2485                   struct wl_data_offer *offer)
2486 {
2487         struct input *input = data;
2488         struct window *window;
2489         void *types_data;
2490         float x = wl_fixed_to_double(x_w);
2491         float y = wl_fixed_to_double(y_w);
2492         char **p;
2493
2494         input->pointer_enter_serial = serial;
2495         window = wl_surface_get_user_data(surface);
2496         input->pointer_focus = window;
2497
2498         if (offer) {
2499                 input->drag_offer = wl_data_offer_get_user_data(offer);
2500
2501                 p = wl_array_add(&input->drag_offer->types, sizeof *p);
2502                 *p = NULL;
2503
2504                 types_data = input->drag_offer->types.data;
2505         } else {
2506                 input->drag_offer = NULL;
2507                 types_data = NULL;
2508         }
2509
2510         window = input->pointer_focus;
2511         if (window->data_handler)
2512                 window->data_handler(window, input, x, y, types_data,
2513                                      window->user_data);
2514 }
2515
2516 static void
2517 data_device_leave(void *data, struct wl_data_device *data_device)
2518 {
2519         struct input *input = data;
2520
2521         if (input->drag_offer) {
2522                 data_offer_destroy(input->drag_offer);
2523                 input->drag_offer = NULL;
2524         }
2525 }
2526
2527 static void
2528 data_device_motion(void *data, struct wl_data_device *data_device,
2529                    uint32_t time, wl_fixed_t x_w, wl_fixed_t y_w)
2530 {
2531         struct input *input = data;
2532         struct window *window = input->pointer_focus;
2533         float x = wl_fixed_to_double(x_w);
2534         float y = wl_fixed_to_double(y_w);
2535         void *types_data;
2536
2537         input->sx = x;
2538         input->sy = y;
2539
2540         if (input->drag_offer)
2541                 types_data = input->drag_offer->types.data;
2542         else
2543                 types_data = NULL;
2544
2545         if (window->data_handler)
2546                 window->data_handler(window, input, x, y, types_data,
2547                                      window->user_data);
2548 }
2549
2550 static void
2551 data_device_drop(void *data, struct wl_data_device *data_device)
2552 {
2553         struct input *input = data;
2554         struct window *window = input->pointer_focus;
2555
2556         if (window->drop_handler)
2557                 window->drop_handler(window, input,
2558                                      input->sx, input->sy, window->user_data);
2559 }
2560
2561 static void
2562 data_device_selection(void *data,
2563                       struct wl_data_device *wl_data_device,
2564                       struct wl_data_offer *offer)
2565 {
2566         struct input *input = data;
2567         char **p;
2568
2569         if (input->selection_offer)
2570                 data_offer_destroy(input->selection_offer);
2571
2572         if (offer) {
2573                 input->selection_offer = wl_data_offer_get_user_data(offer);
2574                 p = wl_array_add(&input->selection_offer->types, sizeof *p);
2575                 *p = NULL;
2576         } else {
2577                 input->selection_offer = NULL;
2578         }
2579 }
2580
2581 static const struct wl_data_device_listener data_device_listener = {
2582         data_device_data_offer,
2583         data_device_enter,
2584         data_device_leave,
2585         data_device_motion,
2586         data_device_drop,
2587         data_device_selection
2588 };
2589
2590 static void
2591 input_set_pointer_image_index(struct input *input, int index)
2592 {
2593         struct wl_buffer *buffer;
2594         struct wl_cursor *cursor;
2595         struct wl_cursor_image *image;
2596
2597         cursor = input->display->cursors[input->current_cursor];
2598         if (!cursor)
2599                 return;
2600
2601         if (index >= (int) cursor->image_count) {
2602                 fprintf(stderr, "cursor index out of range\n");
2603                 return;
2604         }
2605
2606         image = cursor->images[index];
2607         buffer = wl_cursor_image_get_buffer(image);
2608         if (!buffer)
2609                 return;
2610
2611         wl_pointer_set_cursor(input->pointer, input->pointer_enter_serial,
2612                               input->pointer_surface,
2613                               image->hotspot_x, image->hotspot_y);
2614         wl_surface_attach(input->pointer_surface, buffer, 0, 0);
2615         wl_surface_damage(input->pointer_surface, 0, 0,
2616                           image->width, image->height);
2617 }
2618
2619 static const struct wl_callback_listener pointer_surface_listener;
2620
2621 static void
2622 pointer_surface_frame_callback(void *data, struct wl_callback *callback,
2623                                uint32_t time)
2624 {
2625         struct input *input = data;
2626         struct wl_cursor *cursor;
2627         int i;
2628
2629         if (callback) {
2630                 assert(callback == input->cursor_frame_cb);
2631                 wl_callback_destroy(callback);
2632                 input->cursor_frame_cb = NULL;
2633         }
2634
2635         if (input->current_cursor == CURSOR_BLANK) {
2636                 wl_pointer_set_cursor(input->pointer,
2637                                       input->pointer_enter_serial,
2638                                       NULL, 0, 0);
2639                 return;
2640         }
2641
2642         if (input->current_cursor == CURSOR_UNSET)
2643                 return;
2644         cursor = input->display->cursors[input->current_cursor];
2645         if (!cursor)
2646                 return;
2647
2648         /* FIXME We don't have the current time on the first call so we set
2649          * the animation start to the time of the first frame callback. */
2650         if (time == 0)
2651                 input->cursor_anim_start = 0;
2652         else if (input->cursor_anim_start == 0)
2653                 input->cursor_anim_start = time;
2654
2655         if (time == 0 || input->cursor_anim_start == 0)
2656                 i = 0;
2657         else
2658                 i = wl_cursor_frame(cursor, time - input->cursor_anim_start);
2659
2660         input_set_pointer_image_index(input, i);
2661
2662         if (cursor->image_count == 1)
2663                 return;
2664
2665         input->cursor_frame_cb = wl_surface_frame(input->pointer_surface);
2666         wl_callback_add_listener(input->cursor_frame_cb,
2667                                  &pointer_surface_listener, input);
2668 }
2669
2670 static const struct wl_callback_listener pointer_surface_listener = {
2671         pointer_surface_frame_callback
2672 };
2673
2674 void
2675 input_set_pointer_image(struct input *input, int pointer)
2676 {
2677         int force = 0;
2678
2679         if (input->pointer_enter_serial > input->cursor_serial)
2680                 force = 1;
2681
2682         if (!force && pointer == input->current_cursor)
2683                 return;
2684
2685         input->current_cursor = pointer;
2686         input->cursor_serial = input->pointer_enter_serial;
2687         if (!input->cursor_frame_cb)
2688                 pointer_surface_frame_callback(input, NULL, 0);
2689         else if (force) {
2690                 /* The current frame callback may be stuck if, for instance,
2691                  * the set cursor request was processed by the server after
2692                  * this client lost the focus. In this case the cursor surface
2693                  * might not be mapped and the frame callback wouldn't ever
2694                  * complete. Send a set_cursor and attach to try to map the
2695                  * cursor surface again so that the callback will finish */
2696                 input_set_pointer_image_index(input, 0);
2697         }
2698 }
2699
2700 struct wl_data_device *
2701 input_get_data_device(struct input *input)
2702 {
2703         return input->data_device;
2704 }
2705
2706 void
2707 input_set_selection(struct input *input,
2708                     struct wl_data_source *source, uint32_t time)
2709 {
2710         wl_data_device_set_selection(input->data_device, source, time);
2711 }
2712
2713 void
2714 input_accept(struct input *input, const char *type)
2715 {
2716         wl_data_offer_accept(input->drag_offer->offer,
2717                              input->pointer_enter_serial, type);
2718 }
2719
2720 static void
2721 offer_io_func(struct task *task, uint32_t events)
2722 {
2723         struct data_offer *offer =
2724                 container_of(task, struct data_offer, io_task);
2725         unsigned int len;
2726         char buffer[4096];
2727
2728         len = read(offer->fd, buffer, sizeof buffer);
2729         offer->func(buffer, len,
2730                     offer->x, offer->y, offer->user_data);
2731
2732         if (len == 0) {
2733                 close(offer->fd);
2734                 data_offer_destroy(offer);
2735         }
2736 }
2737
2738 static void
2739 data_offer_receive_data(struct data_offer *offer, const char *mime_type,
2740                         data_func_t func, void *user_data)
2741 {
2742         int p[2];
2743
2744         if (pipe2(p, O_CLOEXEC) == -1)
2745                 return;
2746
2747         wl_data_offer_receive(offer->offer, mime_type, p[1]);
2748         close(p[1]);
2749
2750         offer->io_task.run = offer_io_func;
2751         offer->fd = p[0];
2752         offer->func = func;
2753         offer->refcount++;
2754         offer->user_data = user_data;
2755
2756         display_watch_fd(offer->input->display,
2757                          offer->fd, EPOLLIN, &offer->io_task);
2758 }
2759
2760 void
2761 input_receive_drag_data(struct input *input, const char *mime_type,
2762                         data_func_t func, void *data)
2763 {
2764         data_offer_receive_data(input->drag_offer, mime_type, func, data);
2765         input->drag_offer->x = input->sx;
2766         input->drag_offer->y = input->sy;
2767 }
2768
2769 int
2770 input_receive_selection_data(struct input *input, const char *mime_type,
2771                              data_func_t func, void *data)
2772 {
2773         char **p;
2774
2775         if (input->selection_offer == NULL)
2776                 return -1;
2777
2778         for (p = input->selection_offer->types.data; *p; p++)
2779                 if (strcmp(mime_type, *p) == 0)
2780                         break;
2781
2782         if (*p == NULL)
2783                 return -1;
2784
2785         data_offer_receive_data(input->selection_offer,
2786                                 mime_type, func, data);
2787         return 0;
2788 }
2789
2790 int
2791 input_receive_selection_data_to_fd(struct input *input,
2792                                    const char *mime_type, int fd)
2793 {
2794         if (input->selection_offer)
2795                 wl_data_offer_receive(input->selection_offer->offer,
2796                                       mime_type, fd);
2797
2798         return 0;
2799 }
2800
2801 void
2802 window_move(struct window *window, struct input *input, uint32_t serial)
2803 {
2804         if (!window->shell_surface)
2805                 return;
2806
2807         wl_shell_surface_move(window->shell_surface, input->seat, serial);
2808 }
2809
2810 static void
2811 idle_resize(struct window *window)
2812 {
2813         struct widget *widget;
2814
2815         window->resize_needed = 0;
2816         widget = window->widget;
2817         widget_set_allocation(widget,
2818                               window->pending_allocation.x,
2819                               window->pending_allocation.y,
2820                               window->pending_allocation.width,
2821                               window->pending_allocation.height);
2822
2823         if (window->input_region) {
2824                 wl_region_destroy(window->input_region);
2825                 window->input_region = NULL;
2826         }
2827
2828         if (window->opaque_region) {
2829                 wl_region_destroy(window->opaque_region);
2830                 window->opaque_region = NULL;
2831         }
2832
2833         if (widget->resize_handler)
2834                 widget->resize_handler(widget,
2835                                        widget->allocation.width,
2836                                        widget->allocation.height,
2837                                        widget->user_data);
2838
2839         if (window->allocation.width != widget->allocation.width ||
2840             window->allocation.height != widget->allocation.height) {
2841                 window->allocation = widget->allocation;
2842                 window_schedule_redraw(window);
2843         }
2844 }
2845
2846 void
2847 window_schedule_resize(struct window *window, int width, int height)
2848 {
2849         window->pending_allocation.x = 0;
2850         window->pending_allocation.y = 0;
2851         window->pending_allocation.width = width;
2852         window->pending_allocation.height = height;
2853
2854         if (window->min_allocation.width == 0)
2855                 window->min_allocation = window->pending_allocation;
2856         if (window->pending_allocation.width < window->min_allocation.width)
2857                 window->pending_allocation.width = window->min_allocation.width;
2858         if (window->pending_allocation.height < window->min_allocation.height)
2859                 window->pending_allocation.height = window->min_allocation.height;
2860
2861         window->resize_needed = 1;
2862         window_schedule_redraw(window);
2863 }
2864
2865 void
2866 widget_schedule_resize(struct widget *widget, int32_t width, int32_t height)
2867 {
2868         window_schedule_resize(widget->window, width, height);
2869 }
2870
2871 static void
2872 handle_ping(void *data, struct wl_shell_surface *shell_surface,
2873                                                         uint32_t serial)
2874 {
2875         wl_shell_surface_pong(shell_surface, serial);
2876 }
2877
2878 static void
2879 handle_configure(void *data, struct wl_shell_surface *shell_surface,
2880                  uint32_t edges, int32_t width, int32_t height)
2881 {
2882         struct window *window = data;
2883
2884         window->resize_edges = edges;
2885         window_schedule_resize(window, width, height);
2886 }
2887
2888 static void
2889 menu_destroy(struct menu *menu)
2890 {
2891         widget_destroy(menu->widget);
2892         window_destroy(menu->window);
2893         free(menu);
2894 }
2895
2896 static void
2897 handle_popup_done(void *data, struct wl_shell_surface *shell_surface)
2898 {
2899         struct window *window = data;
2900         struct menu *menu = window->widget->user_data;
2901
2902         /* FIXME: Need more context in this event, at least the input
2903          * device.  Or just use wl_callback.  And this really needs to
2904          * be a window vfunc that the menu can set.  And we need the
2905          * time. */
2906
2907         menu->func(window->parent, menu->current, window->parent->user_data);
2908         input_ungrab(menu->input);
2909         menu_destroy(menu);
2910 }
2911
2912 static const struct wl_shell_surface_listener shell_surface_listener = {
2913         handle_ping,
2914         handle_configure,
2915         handle_popup_done
2916 };
2917
2918 void
2919 window_get_allocation(struct window *window,
2920                       struct rectangle *allocation)
2921 {
2922         *allocation = window->allocation;
2923 }
2924
2925 static void
2926 widget_redraw(struct widget *widget)
2927 {
2928         struct widget *child;
2929
2930         if (widget->redraw_handler)
2931                 widget->redraw_handler(widget, widget->user_data);
2932         wl_list_for_each(child, &widget->child_list, link)
2933                 widget_redraw(child);
2934 }
2935
2936 static void
2937 frame_callback(void *data, struct wl_callback *callback, uint32_t time)
2938 {
2939         struct window *window = data;
2940
2941         assert(callback == window->frame_cb);
2942         wl_callback_destroy(callback);
2943         window->frame_cb = 0;
2944         window->redraw_scheduled = 0;
2945         if (window->redraw_needed)
2946                 window_schedule_redraw(window);
2947 }
2948
2949 static const struct wl_callback_listener listener = {
2950         frame_callback
2951 };
2952
2953 static void
2954 idle_redraw(struct task *task, uint32_t events)
2955 {
2956         struct window *window = container_of(task, struct window, redraw_task);
2957
2958         if (window->resize_needed)
2959                 idle_resize(window);
2960
2961         window_create_surface(window);
2962         widget_redraw(window->widget);
2963         window_flush(window);
2964         window->redraw_needed = 0;
2965         wl_list_init(&window->redraw_task.link);
2966
2967         window->frame_cb = wl_surface_frame(window->surface);
2968         wl_callback_add_listener(window->frame_cb, &listener, window);
2969 }
2970
2971 void
2972 window_schedule_redraw(struct window *window)
2973 {
2974         window->redraw_needed = 1;
2975         if (!window->redraw_scheduled) {
2976                 window->redraw_task.run = idle_redraw;
2977                 display_defer(window->display, &window->redraw_task);
2978                 window->redraw_scheduled = 1;
2979         }
2980 }
2981
2982 void
2983 window_set_fullscreen(struct window *window, int fullscreen)
2984 {
2985         if (!window->display->shell)
2986                 return;
2987
2988         if ((window->type == TYPE_FULLSCREEN) == fullscreen)
2989                 return;
2990
2991         if (fullscreen) {
2992                 window->type = TYPE_FULLSCREEN;
2993                 window->saved_allocation = window->allocation;
2994                 wl_shell_surface_set_fullscreen(window->shell_surface,
2995                                                 WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
2996                                                 0, NULL);
2997         } else {
2998                 window->type = TYPE_TOPLEVEL;
2999                 wl_shell_surface_set_toplevel(window->shell_surface);
3000                 window_schedule_resize(window,
3001                                        window->saved_allocation.width,
3002                                        window->saved_allocation.height);
3003         }
3004 }
3005
3006 void
3007 window_set_maximized(struct window *window, int maximized)
3008 {
3009         if (!window->display->shell)
3010                 return;
3011
3012         if ((window->type == TYPE_MAXIMIZED) == maximized)
3013                 return;
3014
3015         if (window->type == TYPE_TOPLEVEL) {
3016                 window->saved_allocation = window->allocation;
3017                 wl_shell_surface_set_maximized(window->shell_surface, NULL);
3018                 window->type = TYPE_MAXIMIZED;
3019         } else {
3020                 wl_shell_surface_set_toplevel(window->shell_surface);
3021                 window->type = TYPE_TOPLEVEL;
3022                 window_schedule_resize(window,
3023                                        window->saved_allocation.width,
3024                                        window->saved_allocation.height);
3025         }
3026 }
3027
3028 void
3029 window_set_user_data(struct window *window, void *data)
3030 {
3031         window->user_data = data;
3032 }
3033
3034 void *
3035 window_get_user_data(struct window *window)
3036 {
3037         return window->user_data;
3038 }
3039
3040 void
3041 window_set_key_handler(struct window *window,
3042                        window_key_handler_t handler)
3043 {
3044         window->key_handler = handler;
3045 }
3046
3047 void
3048 window_set_keyboard_focus_handler(struct window *window,
3049                                   window_keyboard_focus_handler_t handler)
3050 {
3051         window->keyboard_focus_handler = handler;
3052 }
3053
3054 void
3055 window_set_data_handler(struct window *window, window_data_handler_t handler)
3056 {
3057         window->data_handler = handler;
3058 }
3059
3060 void
3061 window_set_drop_handler(struct window *window, window_drop_handler_t handler)
3062 {
3063         window->drop_handler = handler;
3064 }
3065
3066 void
3067 window_set_close_handler(struct window *window,
3068                          window_close_handler_t handler)
3069 {
3070         window->close_handler = handler;
3071 }
3072
3073 void
3074 window_set_fullscreen_handler(struct window *window,
3075                               window_fullscreen_handler_t handler)
3076 {
3077         window->fullscreen_handler = handler;
3078 }
3079
3080 void
3081 window_set_title(struct window *window, const char *title)
3082 {
3083         free(window->title);
3084         window->title = strdup(title);
3085         if (window->shell_surface)
3086                 wl_shell_surface_set_title(window->shell_surface, title);
3087 }
3088
3089 const char *
3090 window_get_title(struct window *window)
3091 {
3092         return window->title;
3093 }
3094
3095 void
3096 window_set_text_cursor_position(struct window *window, int32_t x, int32_t y)
3097 {
3098         struct text_cursor_position *text_cursor_position =
3099                                         window->display->text_cursor_position;
3100
3101         if (!text_cursor_position)
3102                 return;
3103
3104         text_cursor_position_notify(text_cursor_position,
3105                                                 window->surface,
3106                                                 wl_fixed_from_int(x),
3107                                                 wl_fixed_from_int(y));
3108 }
3109
3110 void
3111 window_damage(struct window *window, int32_t x, int32_t y,
3112               int32_t width, int32_t height)
3113 {
3114         wl_surface_damage(window->surface, x, y, width, height);
3115 }
3116
3117 static void
3118 surface_enter(void *data,
3119               struct wl_surface *wl_surface, struct wl_output *wl_output)
3120 {
3121         struct window *window = data;
3122         struct output *output;
3123         struct output *output_found = NULL;
3124         struct window_output *window_output;
3125
3126         wl_list_for_each(output, &window->display->output_list, link) {
3127                 if (output->output == wl_output) {
3128                         output_found = output;
3129                         break;
3130                 }
3131         }
3132
3133         if (!output_found)
3134                 return;
3135
3136         window_output = malloc (sizeof *window_output);
3137         window_output->output = output_found;
3138
3139         wl_list_insert (&window->window_output_list, &window_output->link);
3140 }
3141
3142 static void
3143 surface_leave(void *data,
3144               struct wl_surface *wl_surface, struct wl_output *output)
3145 {
3146         struct window *window = data;
3147         struct window_output *window_output;
3148         struct window_output *window_output_found = NULL;
3149
3150         wl_list_for_each(window_output, &window->window_output_list, link) {
3151                 if (window_output->output->output == output) {
3152                         window_output_found = window_output;
3153                         break;
3154                 }
3155         }
3156
3157         if (window_output_found) {
3158                 wl_list_remove(&window_output_found->link);
3159                 free(window_output_found);
3160         }
3161 }
3162
3163 static const struct wl_surface_listener surface_listener = {
3164         surface_enter,
3165         surface_leave
3166 };
3167
3168 static struct window *
3169 window_create_internal(struct display *display,
3170                        struct window *parent, int type)
3171 {
3172         struct window *window;
3173
3174         window = malloc(sizeof *window);
3175         if (window == NULL)
3176                 return NULL;
3177
3178         memset(window, 0, sizeof *window);
3179         window->display = display;
3180         window->parent = parent;
3181         window->surface = wl_compositor_create_surface(display->compositor);
3182         wl_surface_add_listener(window->surface, &surface_listener, window);
3183         if (type != TYPE_CUSTOM && display->shell) {
3184                 window->shell_surface =
3185                         wl_shell_get_shell_surface(display->shell,
3186                                                    window->surface);
3187         }
3188         window->allocation.x = 0;
3189         window->allocation.y = 0;
3190         window->allocation.width = 0;
3191         window->allocation.height = 0;
3192         window->saved_allocation = window->allocation;
3193         window->transparent = 1;
3194         window->type = type;
3195         window->input_region = NULL;
3196         window->opaque_region = NULL;
3197
3198         if (display->dpy)
3199 #ifdef HAVE_CAIRO_EGL
3200                 window->buffer_type = WINDOW_BUFFER_TYPE_EGL_WINDOW;
3201 #else
3202                 window->buffer_type = WINDOW_BUFFER_TYPE_SHM;
3203 #endif
3204         else
3205                 window->buffer_type = WINDOW_BUFFER_TYPE_SHM;
3206
3207         wl_surface_set_user_data(window->surface, window);
3208         wl_list_insert(display->window_list.prev, &window->link);
3209         wl_list_init(&window->redraw_task.link);
3210
3211         if (window->shell_surface) {
3212                 wl_shell_surface_set_user_data(window->shell_surface, window);
3213                 wl_shell_surface_add_listener(window->shell_surface,
3214                                               &shell_surface_listener, window);
3215         }
3216
3217         wl_list_init (&window->window_output_list);
3218
3219         return window;
3220 }
3221
3222 struct window *
3223 window_create(struct display *display)
3224 {
3225         struct window *window;
3226
3227         window = window_create_internal(display, NULL, TYPE_NONE);
3228         if (!window)
3229                 return NULL;
3230
3231         return window;
3232 }
3233
3234 struct window *
3235 window_create_custom(struct display *display)
3236 {
3237         struct window *window;
3238
3239         window = window_create_internal(display, NULL, TYPE_CUSTOM);
3240         if (!window)
3241                 return NULL;
3242
3243         return window;
3244 }
3245
3246 struct window *
3247 window_create_transient(struct display *display, struct window *parent,
3248                         int32_t x, int32_t y, uint32_t flags)
3249 {
3250         struct window *window;
3251
3252         window = window_create_internal(parent->display,
3253                                         parent, TYPE_TRANSIENT);
3254         if (!window)
3255                 return NULL;
3256
3257         window->x = x;
3258         window->y = y;
3259
3260         if (display->shell)
3261                 wl_shell_surface_set_transient(window->shell_surface,
3262                                                window->parent->surface,
3263                                                window->x, window->y, flags);
3264
3265         return window;
3266 }
3267
3268 static void
3269 menu_set_item(struct menu *menu, int sy)
3270 {
3271         int next;
3272
3273         next = (sy - 8) / 20;
3274         if (menu->current != next) {
3275                 menu->current = next;
3276                 widget_schedule_redraw(menu->widget);
3277         }
3278 }
3279
3280 static int
3281 menu_motion_handler(struct widget *widget,
3282                     struct input *input, uint32_t time,
3283                     float x, float y, void *data)
3284 {
3285         struct menu *menu = data;
3286
3287         if (widget == menu->widget)
3288                 menu_set_item(data, y);
3289
3290         return CURSOR_LEFT_PTR;
3291 }
3292
3293 static int
3294 menu_enter_handler(struct widget *widget,
3295                    struct input *input, float x, float y, void *data)
3296 {
3297         struct menu *menu = data;
3298
3299         if (widget == menu->widget)
3300                 menu_set_item(data, y);
3301
3302         return CURSOR_LEFT_PTR;
3303 }
3304
3305 static void
3306 menu_leave_handler(struct widget *widget, struct input *input, void *data)
3307 {
3308         struct menu *menu = data;
3309
3310         if (widget == menu->widget)
3311                 menu_set_item(data, -200);
3312 }
3313
3314 static void
3315 menu_button_handler(struct widget *widget,
3316                     struct input *input, uint32_t time,
3317                     uint32_t button, enum wl_pointer_button_state state,
3318                     void *data)
3319
3320 {
3321         struct menu *menu = data;
3322
3323         if (state == WL_POINTER_BUTTON_STATE_PRESSED &&
3324             time - menu->time > 500) {
3325                 /* Either relase after press-drag-release or
3326                  * click-motion-click. */
3327                 menu->func(menu->window->parent, 
3328                            menu->current, menu->window->parent->user_data);
3329                 input_ungrab(input);
3330                 menu_destroy(menu);
3331         }
3332 }
3333
3334 static void
3335 menu_redraw_handler(struct widget *widget, void *data)
3336 {
3337         cairo_t *cr;
3338         const int32_t r = 3, margin = 3;
3339         struct menu *menu = data;
3340         int32_t width, height, i;
3341         struct window *window = widget->window;
3342
3343         cr = cairo_create(window->cairo_surface);
3344         cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
3345         cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0);
3346         cairo_paint(cr);
3347
3348         width = window->allocation.width;
3349         height = window->allocation.height;
3350         rounded_rect(cr, 0, 0, width, height, r);
3351
3352         cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
3353         cairo_set_source_rgba(cr, 0.0, 0.0, 0.4, 0.8);
3354         cairo_fill(cr);
3355
3356         for (i = 0; i < menu->count; i++) {
3357                 if (i == menu->current) {
3358                         cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
3359                         cairo_rectangle(cr, margin, i * 20 + margin,
3360                                         width - 2 * margin, 20);
3361                         cairo_fill(cr);
3362                         cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
3363                         cairo_move_to(cr, 10, i * 20 + 16);
3364                         cairo_show_text(cr, menu->entries[i]);
3365                 } else {
3366                         cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
3367                         cairo_move_to(cr, 10, i * 20 + 16);
3368                         cairo_show_text(cr, menu->entries[i]);
3369                 }
3370         }
3371
3372         cairo_destroy(cr);
3373 }
3374
3375 void
3376 window_show_menu(struct display *display,
3377                  struct input *input, uint32_t time, struct window *parent,
3378                  int32_t x, int32_t y,
3379                  menu_func_t func, const char **entries, int count)
3380 {
3381         struct window *window;
3382         struct menu *menu;
3383         const int32_t margin = 3;
3384
3385         menu = malloc(sizeof *menu);
3386         if (!menu)
3387                 return;
3388
3389         window = window_create_internal(parent->display, parent, TYPE_MENU);
3390         if (!window) {
3391                 free(menu);
3392                 return;
3393         }
3394
3395         menu->window = window;
3396         menu->widget = window_add_widget(menu->window, menu);
3397         menu->entries = entries;
3398         menu->count = count;
3399         menu->current = -1;
3400         menu->time = time;
3401         menu->func = func;
3402         menu->input = input;
3403         window->type = TYPE_MENU;
3404         window->x = x;
3405         window->y = y;
3406
3407         input_ungrab(input);
3408         wl_shell_surface_set_popup(window->shell_surface, input->seat,
3409                                    display_get_serial(window->display),
3410                                    window->parent->surface,
3411                                    window->x, window->y, 0);
3412
3413         widget_set_redraw_handler(menu->widget, menu_redraw_handler);
3414         widget_set_enter_handler(menu->widget, menu_enter_handler);
3415         widget_set_leave_handler(menu->widget, menu_leave_handler);
3416         widget_set_motion_handler(menu->widget, menu_motion_handler);
3417         widget_set_button_handler(menu->widget, menu_button_handler);
3418
3419         input_grab(input, menu->widget, 0);
3420         window_schedule_resize(window, 200, count * 20 + margin * 2);
3421 }
3422
3423 void
3424 window_set_buffer_type(struct window *window, enum window_buffer_type type)
3425 {
3426         window->buffer_type = type;
3427 }
3428
3429
3430 static void
3431 display_handle_geometry(void *data,
3432                         struct wl_output *wl_output,
3433                         int x, int y,
3434                         int physical_width,
3435                         int physical_height,
3436                         int subpixel,
3437                         const char *make,
3438                         const char *model,
3439                         int transform)
3440 {
3441         struct output *output = data;
3442
3443         output->allocation.x = x;
3444         output->allocation.y = y;
3445 }
3446
3447 static void
3448 display_handle_mode(void *data,
3449                     struct wl_output *wl_output,
3450                     uint32_t flags,
3451                     int width,
3452                     int height,
3453                     int refresh)
3454 {
3455         struct output *output = data;
3456         struct display *display = output->display;
3457
3458         if (flags & WL_OUTPUT_MODE_CURRENT) {
3459                 output->allocation.width = width;
3460                 output->allocation.height = height;
3461                 if (display->output_configure_handler)
3462                         (*display->output_configure_handler)(
3463                                                 output, display->user_data);
3464         }
3465 }
3466
3467 static const struct wl_output_listener output_listener = {
3468         display_handle_geometry,
3469         display_handle_mode
3470 };
3471
3472 static void
3473 display_add_output(struct display *d, uint32_t id)
3474 {
3475         struct output *output;
3476
3477         output = malloc(sizeof *output);
3478         if (output == NULL)
3479                 return;
3480
3481         memset(output, 0, sizeof *output);
3482         output->display = d;
3483         output->output =
3484                 wl_display_bind(d->display, id, &wl_output_interface);
3485         wl_list_insert(d->output_list.prev, &output->link);
3486
3487         wl_output_add_listener(output->output, &output_listener, output);
3488 }
3489
3490 static void
3491 output_destroy(struct output *output)
3492 {
3493         if (output->destroy_handler)
3494                 (*output->destroy_handler)(output, output->user_data);
3495
3496         wl_output_destroy(output->output);
3497         wl_list_remove(&output->link);
3498         free(output);
3499 }
3500
3501 void
3502 display_set_output_configure_handler(struct display *display,
3503                                      display_output_handler_t handler)
3504 {
3505         struct output *output;
3506
3507         display->output_configure_handler = handler;
3508         if (!handler)
3509                 return;
3510
3511         wl_list_for_each(output, &display->output_list, link)
3512                 (*display->output_configure_handler)(output,
3513                                                      display->user_data);
3514 }
3515
3516 void
3517 output_set_user_data(struct output *output, void *data)
3518 {
3519         output->user_data = data;
3520 }
3521
3522 void *
3523 output_get_user_data(struct output *output)
3524 {
3525         return output->user_data;
3526 }
3527
3528 void
3529 output_set_destroy_handler(struct output *output,
3530                            display_output_handler_t handler)
3531 {
3532         output->destroy_handler = handler;
3533         /* FIXME: implement this, once we have way to remove outputs */
3534 }
3535
3536 void
3537 output_get_allocation(struct output *output, struct rectangle *allocation)
3538 {
3539         *allocation = output->allocation;
3540 }
3541
3542 struct wl_output *
3543 output_get_wl_output(struct output *output)
3544 {
3545         return output->output;
3546 }
3547
3548 static void
3549 fini_xkb(struct input *input)
3550 {
3551         xkb_state_unref(input->xkb.state);
3552         xkb_map_unref(input->xkb.keymap);
3553 }
3554
3555 static void
3556 display_add_input(struct display *d, uint32_t id)
3557 {
3558         struct input *input;
3559
3560         input = malloc(sizeof *input);
3561         if (input == NULL)
3562                 return;
3563
3564         memset(input, 0, sizeof *input);
3565         input->display = d;
3566         input->seat = wl_display_bind(d->display, id, &wl_seat_interface);
3567         input->pointer_focus = NULL;
3568         input->keyboard_focus = NULL;
3569         wl_list_insert(d->input_list.prev, &input->link);
3570
3571         wl_seat_add_listener(input->seat, &seat_listener, input);
3572         wl_seat_set_user_data(input->seat, input);
3573
3574         input->data_device =
3575                 wl_data_device_manager_get_data_device(d->data_device_manager,
3576                                                        input->seat);
3577         wl_data_device_add_listener(input->data_device, &data_device_listener,
3578                                     input);
3579
3580         input->pointer_surface = wl_compositor_create_surface(d->compositor);
3581
3582         input->repeat_timer_fd = timerfd_create(CLOCK_MONOTONIC,
3583                                                 TFD_CLOEXEC | TFD_NONBLOCK);
3584         input->repeat_task.run = keyboard_repeat_func;
3585         display_watch_fd(d, input->repeat_timer_fd,
3586                          EPOLLIN, &input->repeat_task);
3587 }
3588
3589 static void
3590 input_destroy(struct input *input)
3591 {
3592         input_remove_keyboard_focus(input);
3593         input_remove_pointer_focus(input);
3594
3595         if (input->drag_offer)
3596                 data_offer_destroy(input->drag_offer);
3597
3598         if (input->selection_offer)
3599                 data_offer_destroy(input->selection_offer);
3600
3601         wl_data_device_destroy(input->data_device);
3602         fini_xkb(input);
3603
3604         wl_surface_destroy(input->pointer_surface);
3605
3606         wl_list_remove(&input->link);
3607         wl_seat_destroy(input->seat);
3608         close(input->repeat_timer_fd);
3609         free(input);
3610 }
3611
3612 static void
3613 init_workspace_manager(struct display *d, uint32_t id)
3614 {
3615         d->workspace_manager =
3616                 wl_display_bind(d->display, id, &workspace_manager_interface);
3617         if (d->workspace_manager != NULL)
3618                 workspace_manager_add_listener(d->workspace_manager,
3619                                                &workspace_manager_listener,
3620                                                d);
3621 }
3622
3623 static void
3624 display_handle_global(struct wl_display *display, uint32_t id,
3625                       const char *interface, uint32_t version, void *data)
3626 {
3627         struct display *d = data;
3628
3629         if (strcmp(interface, "wl_compositor") == 0) {
3630                 d->compositor =
3631                         wl_display_bind(display, id, &wl_compositor_interface);
3632         } else if (strcmp(interface, "wl_output") == 0) {
3633                 display_add_output(d, id);
3634         } else if (strcmp(interface, "wl_seat") == 0) {
3635                 display_add_input(d, id);
3636         } else if (strcmp(interface, "wl_shell") == 0) {
3637                 d->shell = wl_display_bind(display, id, &wl_shell_interface);
3638         } else if (strcmp(interface, "wl_shm") == 0) {
3639                 d->shm = wl_display_bind(display, id, &wl_shm_interface);
3640         } else if (strcmp(interface, "wl_data_device_manager") == 0) {
3641                 d->data_device_manager =
3642                         wl_display_bind(display, id,
3643                                         &wl_data_device_manager_interface);
3644         } else if (strcmp(interface, "text_cursor_position") == 0) {
3645                 d->text_cursor_position =
3646                         wl_display_bind(display, id,
3647                                         &text_cursor_position_interface);
3648         } else if (strcmp(interface, "workspace_manager") == 0) {
3649                 init_workspace_manager(d, id);
3650         }
3651 }
3652
3653 #ifdef HAVE_CAIRO_EGL
3654 static int
3655 init_egl(struct display *d)
3656 {
3657         EGLint major, minor;
3658         EGLint n;
3659
3660 #ifdef USE_CAIRO_GLESV2
3661 #  define GL_BIT EGL_OPENGL_ES2_BIT
3662 #else
3663 #  define GL_BIT EGL_OPENGL_BIT
3664 #endif
3665
3666         static const EGLint argb_cfg_attribs[] = {
3667                 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PIXMAP_BIT,
3668                 EGL_RED_SIZE, 1,
3669                 EGL_GREEN_SIZE, 1,
3670                 EGL_BLUE_SIZE, 1,
3671                 EGL_ALPHA_SIZE, 1,
3672                 EGL_DEPTH_SIZE, 1,
3673                 EGL_RENDERABLE_TYPE, GL_BIT,
3674                 EGL_NONE
3675         };
3676
3677 #ifdef USE_CAIRO_GLESV2
3678         static const EGLint context_attribs[] = {
3679                 EGL_CONTEXT_CLIENT_VERSION, 2,
3680                 EGL_NONE
3681         };
3682         EGLint api = EGL_OPENGL_ES_API;
3683 #else
3684         EGLint *context_attribs = NULL;
3685         EGLint api = EGL_OPENGL_API;
3686 #endif
3687
3688         d->dpy = eglGetDisplay(d->display);
3689         if (!eglInitialize(d->dpy, &major, &minor)) {
3690                 fprintf(stderr, "failed to initialize display\n");
3691                 return -1;
3692         }
3693
3694         if (!eglBindAPI(api)) {
3695                 fprintf(stderr, "failed to bind api EGL_OPENGL_API\n");
3696                 return -1;
3697         }
3698
3699         if (!eglChooseConfig(d->dpy, argb_cfg_attribs,
3700                              &d->argb_config, 1, &n) || n != 1) {
3701                 fprintf(stderr, "failed to choose argb config\n");
3702                 return -1;
3703         }
3704
3705         d->argb_ctx = eglCreateContext(d->dpy, d->argb_config,
3706                                        EGL_NO_CONTEXT, context_attribs);
3707         if (d->argb_ctx == NULL) {
3708                 fprintf(stderr, "failed to create context\n");
3709                 return -1;
3710         }
3711
3712         if (!eglMakeCurrent(d->dpy, NULL, NULL, d->argb_ctx)) {
3713                 fprintf(stderr, "failed to make context current\n");
3714                 return -1;
3715         }
3716
3717 #ifdef HAVE_CAIRO_EGL
3718         d->argb_device = cairo_egl_device_create(d->dpy, d->argb_ctx);
3719         if (cairo_device_status(d->argb_device) != CAIRO_STATUS_SUCCESS) {
3720                 fprintf(stderr, "failed to get cairo egl argb device\n");
3721                 return -1;
3722         }
3723 #endif
3724
3725         return 0;
3726 }
3727
3728 static void
3729 fini_egl(struct display *display)
3730 {
3731 #ifdef HAVE_CAIRO_EGL
3732         cairo_device_destroy(display->argb_device);
3733 #endif
3734
3735         eglMakeCurrent(display->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE,
3736                        EGL_NO_CONTEXT);
3737
3738         eglTerminate(display->dpy);
3739         eglReleaseThread();
3740 }
3741 #endif
3742
3743 static int
3744 event_mask_update(uint32_t mask, void *data)
3745 {
3746         struct display *d = data;
3747
3748         d->mask = mask;
3749
3750         return 0;
3751 }
3752
3753 static void
3754 handle_display_data(struct task *task, uint32_t events)
3755 {
3756         struct display *display =
3757                 container_of(task, struct display, display_task);
3758
3759         display->display_fd_events = events;
3760
3761         if (events & EPOLLERR || events & EPOLLHUP) {
3762                 display_exit(display);
3763                 return;
3764         }
3765
3766         wl_display_iterate(display->display, display->mask);
3767 }
3768
3769 struct display *
3770 display_create(int argc, char *argv[])
3771 {
3772         struct display *d;
3773
3774         d = malloc(sizeof *d);
3775         if (d == NULL)
3776                 return NULL;
3777
3778         memset(d, 0, sizeof *d);
3779
3780         d->display = wl_display_connect(NULL);
3781         if (d->display == NULL) {
3782                 fprintf(stderr, "failed to create display: %m\n");
3783                 return NULL;
3784         }
3785
3786         d->epoll_fd = os_epoll_create_cloexec();
3787         d->display_fd = wl_display_get_fd(d->display, event_mask_update, d);
3788         d->display_task.run = handle_display_data;
3789         display_watch_fd(d, d->display_fd, EPOLLIN | EPOLLERR | EPOLLHUP,
3790                          &d->display_task);
3791
3792         wl_list_init(&d->deferred_list);
3793         wl_list_init(&d->input_list);
3794         wl_list_init(&d->output_list);
3795
3796         d->xkb_context = xkb_context_new(0);
3797         if (d->xkb_context == NULL) {
3798                 fprintf(stderr, "Failed to create XKB context\n");
3799                 return NULL;
3800         }
3801
3802         d->workspace = 0;
3803         d->workspace_count = 1;
3804
3805         /* Set up listener so we'll catch all events. */
3806         wl_display_add_global_listener(d->display,
3807                                        display_handle_global, d);
3808
3809         /* Process connection events. */
3810         wl_display_iterate(d->display, WL_DISPLAY_READABLE);
3811 #ifdef HAVE_CAIRO_EGL
3812         if (init_egl(d) < 0)
3813                 return NULL;
3814 #endif
3815
3816         d->image_target_texture_2d =
3817                 (void *) eglGetProcAddress("glEGLImageTargetTexture2DOES");
3818         d->create_image = (void *) eglGetProcAddress("eglCreateImageKHR");
3819         d->destroy_image = (void *) eglGetProcAddress("eglDestroyImageKHR");
3820
3821         create_cursors(d);
3822
3823         d->theme = theme_create();
3824
3825         wl_list_init(&d->window_list);
3826
3827         return d;
3828 }
3829
3830 static void
3831 display_destroy_outputs(struct display *display)
3832 {
3833         struct output *tmp;
3834         struct output *output;
3835
3836         wl_list_for_each_safe(output, tmp, &display->output_list, link)
3837                 output_destroy(output);
3838 }
3839
3840 static void
3841 display_destroy_inputs(struct display *display)
3842 {
3843         struct input *tmp;
3844         struct input *input;
3845
3846         wl_list_for_each_safe(input, tmp, &display->input_list, link)
3847                 input_destroy(input);
3848 }
3849
3850 void
3851 display_destroy(struct display *display)
3852 {
3853         if (!wl_list_empty(&display->window_list))
3854                 fprintf(stderr, "toytoolkit warning: %d windows exist.\n",
3855                         wl_list_length(&display->window_list));
3856
3857         if (!wl_list_empty(&display->deferred_list))
3858                 fprintf(stderr, "toytoolkit warning: deferred tasks exist.\n");
3859
3860         display_destroy_outputs(display);
3861         display_destroy_inputs(display);
3862
3863         xkb_context_unref(display->xkb_context);
3864
3865         theme_destroy(display->theme);
3866         destroy_cursors(display);
3867
3868 #ifdef HAVE_CAIRO_EGL
3869         fini_egl(display);
3870 #endif
3871
3872         if (display->shell)
3873                 wl_shell_destroy(display->shell);
3874
3875         if (display->shm)
3876                 wl_shm_destroy(display->shm);
3877
3878         if (display->data_device_manager)
3879                 wl_data_device_manager_destroy(display->data_device_manager);
3880
3881         wl_compositor_destroy(display->compositor);
3882
3883         close(display->epoll_fd);
3884
3885         if (!(display->display_fd_events & EPOLLERR) &&
3886             !(display->display_fd_events & EPOLLHUP))
3887                 wl_display_flush(display->display);
3888
3889         wl_display_disconnect(display->display);
3890         free(display);
3891 }
3892
3893 void
3894 display_set_user_data(struct display *display, void *data)
3895 {
3896         display->user_data = data;
3897 }
3898
3899 void *
3900 display_get_user_data(struct display *display)
3901 {
3902         return display->user_data;
3903 }
3904
3905 struct wl_display *
3906 display_get_display(struct display *display)
3907 {
3908         return display->display;
3909 }
3910
3911 struct output *
3912 display_get_output(struct display *display)
3913 {
3914         return container_of(display->output_list.next, struct output, link);
3915 }
3916
3917 struct wl_compositor *
3918 display_get_compositor(struct display *display)
3919 {
3920         return display->compositor;
3921 }
3922
3923 uint32_t
3924 display_get_serial(struct display *display)
3925 {
3926         return display->serial;
3927 }
3928
3929 EGLDisplay
3930 display_get_egl_display(struct display *d)
3931 {
3932         return d->dpy;
3933 }
3934
3935 struct wl_data_source *
3936 display_create_data_source(struct display *display)
3937 {
3938         return wl_data_device_manager_create_data_source(display->data_device_manager);
3939 }
3940
3941 EGLConfig
3942 display_get_argb_egl_config(struct display *d)
3943 {
3944         return d->argb_config;
3945 }
3946
3947 struct wl_shell *
3948 display_get_shell(struct display *display)
3949 {
3950         return display->shell;
3951 }
3952
3953 int
3954 display_acquire_window_surface(struct display *display,
3955                                struct window *window,
3956                                EGLContext ctx)
3957 {
3958 #ifdef HAVE_CAIRO_EGL
3959         struct egl_window_surface_data *data;
3960         cairo_device_t *device;
3961
3962         if (!window->cairo_surface)
3963                 return -1;
3964         device = cairo_surface_get_device(window->cairo_surface);
3965         if (!device)
3966                 return -1;
3967
3968         if (!ctx) {
3969                 if (device == display->argb_device)
3970                         ctx = display->argb_ctx;
3971                 else
3972                         assert(0);
3973         }
3974
3975         data = cairo_surface_get_user_data(window->cairo_surface,
3976                                            &surface_data_key);
3977
3978         cairo_device_flush(device);
3979         cairo_device_acquire(device);
3980         if (!eglMakeCurrent(display->dpy, data->surf, data->surf, ctx))
3981                 fprintf(stderr, "failed to make surface current\n");
3982
3983         return 0;
3984 #else
3985         return -1;
3986 #endif
3987 }
3988
3989 void
3990 display_release_window_surface(struct display *display,
3991                                struct window *window)
3992 {
3993 #ifdef HAVE_CAIRO_EGL
3994         cairo_device_t *device;
3995         
3996         device = cairo_surface_get_device(window->cairo_surface);
3997         if (!device)
3998                 return;
3999
4000         if (!eglMakeCurrent(display->dpy, NULL, NULL, display->argb_ctx))
4001                 fprintf(stderr, "failed to make context current\n");
4002         cairo_device_release(device);
4003 #endif
4004 }
4005
4006 void
4007 display_defer(struct display *display, struct task *task)
4008 {
4009         wl_list_insert(&display->deferred_list, &task->link);
4010 }
4011
4012 void
4013 display_watch_fd(struct display *display,
4014                  int fd, uint32_t events, struct task *task)
4015 {
4016         struct epoll_event ep;
4017
4018         ep.events = events;
4019         ep.data.ptr = task;
4020         epoll_ctl(display->epoll_fd, EPOLL_CTL_ADD, fd, &ep);
4021 }
4022
4023 void
4024 display_run(struct display *display)
4025 {
4026         struct task *task;
4027         struct epoll_event ep[16];
4028         int i, count;
4029
4030         display->running = 1;
4031         while (1) {
4032                 wl_display_flush(display->display);
4033
4034                 while (!wl_list_empty(&display->deferred_list)) {
4035                         task = container_of(display->deferred_list.prev,
4036                                             struct task, link);
4037                         wl_list_remove(&task->link);
4038                         task->run(task, 0);
4039                 }
4040
4041                 if (!display->running)
4042                         break;
4043
4044                 wl_display_flush(display->display);
4045
4046                 count = epoll_wait(display->epoll_fd,
4047                                    ep, ARRAY_LENGTH(ep), -1);
4048                 for (i = 0; i < count; i++) {
4049                         task = ep[i].data.ptr;
4050                         task->run(task, ep[i].events);
4051                 }
4052         }
4053 }
4054
4055 void
4056 display_exit(struct display *display)
4057 {
4058         display->running = 0;
4059 }