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