68c1eadf1f4d9988ebabf9fb4d2bed1927bb45b3
[profile/ivi/weston.git] / clients / window.c
1 /*
2  * Copyright © 2008 Kristian Høgsberg
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that copyright
7  * notice and this permission notice appear in supporting documentation, and
8  * that the name of the copyright holders not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission.  The copyright holders make no representations
11  * about the suitability of this software for any purpose.  It is provided "as
12  * is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20  * OF THIS SOFTWARE.
21  */
22
23 #include "../config.h"
24
25 #include <stdint.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <fcntl.h>
30 #include <unistd.h>
31 #include <math.h>
32 #include <time.h>
33 #include <cairo.h>
34 #include <glib.h>
35 #include <glib-object.h>
36 #include <gdk-pixbuf/gdk-pixbuf.h>
37 #include <sys/mman.h>
38
39 #include <wayland-egl.h>
40
41 #include <GL/gl.h>
42 #include <EGL/egl.h>
43 #include <EGL/eglext.h>
44
45 #ifdef HAVE_CAIRO_EGL
46 #include <cairo-gl.h>
47 #endif
48
49 #include <X11/extensions/XKBcommon.h>
50
51 #include <linux/input.h>
52 #include "wayland-util.h"
53 #include "wayland-client.h"
54 #include "wayland-glib.h"
55 #include "cairo-util.h"
56
57 #include "window.h"
58
59 struct display {
60         struct wl_display *display;
61         struct wl_compositor *compositor;
62         struct wl_shell *shell;
63         struct wl_shm *shm;
64         struct wl_output *output;
65         struct rectangle screen_allocation;
66         int authenticated;
67         EGLDisplay dpy;
68         EGLConfig rgb_config;
69         EGLConfig premultiplied_argb_config;
70         EGLContext ctx;
71         cairo_device_t *device;
72         int fd;
73         GMainLoop *loop;
74         GSource *source;
75         struct wl_list window_list;
76         struct wl_list input_list;
77         char *device_name;
78         cairo_surface_t *active_frame, *inactive_frame, *shadow;
79         struct xkb_desc *xkb;
80         cairo_surface_t **pointer_surfaces;
81
82         PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d;
83         PFNEGLCREATEIMAGEKHRPROC create_image;
84         PFNEGLDESTROYIMAGEKHRPROC destroy_image;
85 };
86
87 struct window {
88         struct display *display;
89         struct window *parent;
90         struct wl_surface *surface;
91         char *title;
92         struct rectangle allocation, saved_allocation, server_allocation;
93         int x, y;
94         int resize_edges;
95         int redraw_scheduled;
96         int minimum_width, minimum_height;
97         int margin;
98         int fullscreen;
99         int decoration;
100         int transparent;
101         struct input *grab_device;
102         struct input *keyboard_device;
103         uint32_t name;
104         enum window_buffer_type buffer_type;
105
106         EGLImageKHR *image;
107         cairo_surface_t *cairo_surface, *pending_surface;
108
109         window_resize_handler_t resize_handler;
110         window_redraw_handler_t redraw_handler;
111         window_key_handler_t key_handler;
112         window_button_handler_t button_handler;
113         window_keyboard_focus_handler_t keyboard_focus_handler;
114         window_motion_handler_t motion_handler;
115
116         void *user_data;
117         struct wl_list link;
118 };
119
120 struct input {
121         struct display *display;
122         struct wl_input_device *input_device;
123         struct window *pointer_focus;
124         struct window *keyboard_focus;
125         struct selection_offer *offer;
126         uint32_t current_pointer_image;
127         uint32_t modifiers;
128         int32_t x, y, sx, sy;
129         struct wl_list link;
130 };
131
132 enum {
133         POINTER_DEFAULT = 100,
134         POINTER_UNSET
135 };
136
137 enum window_location {
138         WINDOW_INTERIOR = 0,
139         WINDOW_RESIZING_TOP = 1,
140         WINDOW_RESIZING_BOTTOM = 2,
141         WINDOW_RESIZING_LEFT = 4,
142         WINDOW_RESIZING_TOP_LEFT = 5,
143         WINDOW_RESIZING_BOTTOM_LEFT = 6,
144         WINDOW_RESIZING_RIGHT = 8,
145         WINDOW_RESIZING_TOP_RIGHT = 9,
146         WINDOW_RESIZING_BOTTOM_RIGHT = 10,
147         WINDOW_RESIZING_MASK = 15,
148         WINDOW_EXTERIOR = 16,
149         WINDOW_TITLEBAR = 17,
150         WINDOW_CLIENT_AREA = 18,
151 };
152
153 const char *option_xkb_layout = "us";
154 const char *option_xkb_variant = "";
155 const char *option_xkb_options = "";
156
157 static const GOptionEntry xkb_option_entries[] = {
158         { "xkb-layout", 0, 0, G_OPTION_ARG_STRING,
159           &option_xkb_layout, "XKB Layout" },
160         { "xkb-variant", 0, 0, G_OPTION_ARG_STRING,
161           &option_xkb_variant, "XKB Variant" },
162         { "xkb-options", 0, 0, G_OPTION_ARG_STRING,
163           &option_xkb_options, "XKB Options" },
164         { NULL }
165 };
166
167 static void
168 rounded_rect(cairo_t *cr, int x0, int y0, int x1, int y1, int radius)
169 {
170         cairo_move_to(cr, x0, y0 + radius);
171         cairo_arc(cr, x0 + radius, y0 + radius, radius, M_PI, 3 * M_PI / 2);
172         cairo_line_to(cr, x1 - radius, y0);
173         cairo_arc(cr, x1 - radius, y0 + radius, radius, 3 * M_PI / 2, 2 * M_PI);
174         cairo_line_to(cr, x1, y1 - radius);
175         cairo_arc(cr, x1 - radius, y1 - radius, radius, 0, M_PI / 2);
176         cairo_line_to(cr, x0 + radius, y1);
177         cairo_arc(cr, x0 + radius, y1 - radius, radius, M_PI / 2, M_PI);
178         cairo_close_path(cr);
179 }
180
181 static const cairo_user_data_key_t surface_data_key;
182 struct surface_data {
183         struct wl_buffer *buffer;
184 };
185
186 #define MULT(_d,c,a,t) \
187         do { t = c * a + 0x7f; _d = ((t >> 8) + t) >> 8; } while (0)
188
189 #ifdef HAVE_CAIRO_EGL
190
191 struct egl_window_surface_data {
192         struct display *display;
193         struct wl_surface *surface;
194         struct wl_egl_window *window;
195         EGLSurface surf;
196 };
197
198 static void
199 egl_window_surface_data_destroy(void *p)
200 {
201         struct egl_window_surface_data *data = p;
202         struct display *d = data->display;
203
204         eglDestroySurface(d->dpy, data->surf);
205         wl_egl_window_destroy(data->window);
206         data->surface = NULL;
207
208         free(p);
209 }
210
211 static cairo_surface_t *
212 display_create_egl_window_surface(struct display *display,
213                                   struct wl_surface *surface,
214                                   uint32_t flags,
215                                   struct rectangle *rectangle)
216 {
217         cairo_surface_t *cairo_surface;
218         struct egl_window_surface_data *data;
219         EGLConfig config;
220         const EGLint *attribs;
221
222         static const EGLint premul_attribs[] = {
223                 EGL_ALPHA_FORMAT, EGL_ALPHA_FORMAT_PRE,
224                 EGL_NONE
225         };
226         
227         data = malloc(sizeof *data);
228         if (data == NULL)
229                 return NULL;
230
231         data->display = display;
232         data->surface = surface;
233
234         if (flags & SURFACE_OPAQUE) {
235                 config = display->rgb_config;
236                 attribs = NULL;
237         } else {
238                 config = display->premultiplied_argb_config;
239                 attribs = premul_attribs;
240         }
241
242         data->window = wl_egl_window_create(surface,
243                                             rectangle->width,
244                                             rectangle->height);
245
246         data->surf = eglCreateWindowSurface(display->dpy, config,
247                                             data->window, attribs);
248
249         cairo_surface = cairo_gl_surface_create_for_egl(display->device,
250                                                         data->surf,
251                                                         rectangle->width,
252                                                         rectangle->height);
253
254         cairo_surface_set_user_data(cairo_surface, &surface_data_key,
255                                     data, egl_window_surface_data_destroy);
256
257         return cairo_surface;
258 }
259
260 struct egl_image_surface_data {
261         struct surface_data data;
262         EGLImageKHR image;
263         GLuint texture;
264         struct display *display;
265         struct wl_egl_pixmap *pixmap;
266 };
267
268 static void
269 egl_image_surface_data_destroy(void *p)
270 {
271         struct egl_image_surface_data *data = p;
272         struct display *d = data->display;
273
274         cairo_device_acquire(d->device);
275         glDeleteTextures(1, &data->texture);
276         cairo_device_release(d->device);
277
278         d->destroy_image(d->dpy, data->image);
279         wl_buffer_destroy(data->data.buffer);
280         wl_egl_pixmap_destroy(data->pixmap);
281         free(p);
282 }
283
284 EGLImageKHR
285 display_get_image_for_egl_image_surface(struct display *display,
286                                         cairo_surface_t *surface)
287 {
288         struct egl_image_surface_data *data;
289
290         data = cairo_surface_get_user_data (surface, &surface_data_key);
291
292         return data->image;
293 }
294
295 static cairo_surface_t *
296 display_create_egl_image_surface(struct display *display,
297                                  uint32_t flags,
298                                  struct rectangle *rectangle)
299 {
300         struct egl_image_surface_data *data;
301         EGLDisplay dpy = display->dpy;
302         cairo_surface_t *surface;
303         EGLConfig config;
304
305         data = malloc(sizeof *data);
306         if (data == NULL)
307                 return NULL;
308
309         data->display = display;
310
311         data->pixmap = wl_egl_pixmap_create(rectangle->width,
312                                             rectangle->height, 0);
313         if (data->pixmap == NULL) {
314                 free(data);
315                 return NULL;
316         }
317
318         if (flags & SURFACE_OPAQUE)
319                 config = display->rgb_config;
320         else
321                 config = display->premultiplied_argb_config;
322
323         data->image = display->create_image(dpy, NULL,
324                                             EGL_NATIVE_PIXMAP_KHR,
325                                             (EGLClientBuffer) data->pixmap,
326                                             NULL);
327         if (data->image == EGL_NO_IMAGE_KHR) {
328                 wl_egl_pixmap_destroy(data->pixmap);
329                 free(data);
330                 return NULL;
331         }
332
333         data->data.buffer =
334                 wl_egl_pixmap_create_buffer(data->pixmap);
335
336         cairo_device_acquire(display->device);
337         glGenTextures(1, &data->texture);
338         glBindTexture(GL_TEXTURE_2D, data->texture);
339         display->image_target_texture_2d(GL_TEXTURE_2D, data->image);
340         cairo_device_release(display->device);
341
342         surface = cairo_gl_surface_create_for_texture(display->device,
343                                                       CAIRO_CONTENT_COLOR_ALPHA,
344                                                       data->texture,
345                                                       rectangle->width,
346                                                       rectangle->height);
347
348         cairo_surface_set_user_data (surface, &surface_data_key,
349                                      data, egl_image_surface_data_destroy);
350
351         return surface;
352 }
353
354 static cairo_surface_t *
355 display_create_egl_image_surface_from_file(struct display *display,
356                                            const char *filename,
357                                            struct rectangle *rect)
358 {
359         cairo_surface_t *surface;
360         GdkPixbuf *pixbuf;
361         GError *error = NULL;
362         int stride, i;
363         unsigned char *pixels, *p, *end;
364         struct egl_image_surface_data *data;
365
366         pixbuf = gdk_pixbuf_new_from_file_at_scale(filename,
367                                                    rect->width, rect->height,
368                                                    FALSE, &error);
369         if (error != NULL)
370                 return NULL;
371
372         if (!gdk_pixbuf_get_has_alpha(pixbuf) ||
373             gdk_pixbuf_get_n_channels(pixbuf) != 4) {
374                 g_object_unref(pixbuf);
375                 return NULL;
376         }
377
378
379         stride = gdk_pixbuf_get_rowstride(pixbuf);
380         pixels = gdk_pixbuf_get_pixels(pixbuf);
381
382         for (i = 0; i < rect->height; i++) {
383                 p = pixels + i * stride;
384                 end = p + rect->width * 4;
385                 while (p < end) {
386                         unsigned int t;
387
388                         MULT(p[0], p[0], p[3], t);
389                         MULT(p[1], p[1], p[3], t);
390                         MULT(p[2], p[2], p[3], t);
391                         p += 4;
392
393                 }
394         }
395
396         surface = display_create_egl_image_surface(display, 0, rect);
397         if (surface == NULL) {
398                 g_object_unref(pixbuf);
399                 return NULL;
400         }
401
402         data = cairo_surface_get_user_data(surface, &surface_data_key);
403
404         cairo_device_acquire(display->device);
405         glBindTexture(GL_TEXTURE_2D, data->texture);
406         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rect->width, rect->height,
407                         GL_RGBA, GL_UNSIGNED_BYTE, pixels);
408         cairo_device_release(display->device);
409
410         g_object_unref(pixbuf);
411
412         return surface;
413 }
414
415 #endif
416
417 struct wl_buffer *
418 display_get_buffer_for_surface(struct display *display,
419                                cairo_surface_t *surface)
420 {
421         struct surface_data *data;
422
423         data = cairo_surface_get_user_data (surface, &surface_data_key);
424
425         return data->buffer;
426 }
427
428 struct shm_surface_data {
429         struct surface_data data;
430         void *map;
431         size_t length;
432 };
433
434 static void
435 shm_surface_data_destroy(void *p)
436 {
437         struct shm_surface_data *data = p;
438
439         wl_buffer_destroy(data->data.buffer);
440         munmap(data->map, data->length);
441 }
442
443 static cairo_surface_t *
444 display_create_shm_surface(struct display *display,
445                            struct rectangle *rectangle, uint32_t flags)
446 {
447         struct shm_surface_data *data;
448         uint32_t format;
449         cairo_surface_t *surface;
450         int stride, fd;
451         char filename[] = "/tmp/wayland-shm-XXXXXX";
452
453         data = malloc(sizeof *data);
454         if (data == NULL)
455                 return NULL;
456
457         stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32,
458                                                 rectangle->width);
459         data->length = stride * rectangle->height;
460         fd = mkstemp(filename);
461         if (fd < 0) {
462                 fprintf(stderr, "open %s failed: %m\n", filename);
463                 return NULL;
464         }
465         if (ftruncate(fd, data->length) < 0) {
466                 fprintf(stderr, "ftruncate failed: %m\n");
467                 close(fd);
468                 return NULL;
469         }
470
471         data->map = mmap(NULL, data->length,
472                          PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
473         unlink(filename);
474
475         if (data->map == MAP_FAILED) {
476                 fprintf(stderr, "mmap failed: %m\n");
477                 close(fd);
478                 return NULL;
479         }
480
481         surface = cairo_image_surface_create_for_data (data->map,
482                                                        CAIRO_FORMAT_ARGB32,
483                                                        rectangle->width,
484                                                        rectangle->height,
485                                                        stride);
486
487         cairo_surface_set_user_data (surface, &surface_data_key,
488                                      data, shm_surface_data_destroy);
489
490         if (flags & SURFACE_OPAQUE)
491                 format = WL_SHM_FORMAT_XRGB32;
492         else
493                 format = WL_SHM_FORMAT_PREMULTIPLIED_ARGB32;
494
495         data->data.buffer = wl_shm_create_buffer(display->shm,
496                                                  fd,
497                                                  rectangle->width,
498                                                  rectangle->height,
499                                                  stride, format);
500
501         close(fd);
502
503         return surface;
504 }
505
506 static cairo_surface_t *
507 display_create_shm_surface_from_file(struct display *display,
508                                      const char *filename,
509                                      struct rectangle *rect)
510 {
511         cairo_surface_t *surface;
512         GdkPixbuf *pixbuf;
513         GError *error = NULL;
514         int stride, i;
515         unsigned char *pixels, *p, *end, *dest_data;
516         int dest_stride;
517         uint32_t *d;
518
519         pixbuf = gdk_pixbuf_new_from_file_at_scale(filename,
520                                                    rect->width, rect->height,
521                                                    FALSE, &error);
522         if (error != NULL)
523                 return NULL;
524
525         if (!gdk_pixbuf_get_has_alpha(pixbuf) ||
526             gdk_pixbuf_get_n_channels(pixbuf) != 4) {
527                 g_object_unref(pixbuf);
528                 return NULL;
529         }
530
531         stride = gdk_pixbuf_get_rowstride(pixbuf);
532         pixels = gdk_pixbuf_get_pixels(pixbuf);
533
534         surface = display_create_shm_surface(display, rect, 0);
535         if (surface == NULL) {
536                 g_object_unref(pixbuf);
537                 return NULL;
538         }
539
540         dest_data = cairo_image_surface_get_data (surface);
541         dest_stride = cairo_image_surface_get_stride (surface);
542
543         for (i = 0; i < rect->height; i++) {
544                 d = (uint32_t *) (dest_data + i * dest_stride);
545                 p = pixels + i * stride;
546                 end = p + rect->width * 4;
547                 while (p < end) {
548                         unsigned int t;
549                         unsigned char a, r, g, b;
550
551                         a = p[3];
552                         MULT(r, p[0], a, t);
553                         MULT(g, p[1], a, t);
554                         MULT(b, p[2], a, t);
555                         p += 4;
556                         *d++ = (a << 24) | (r << 16) | (g << 8) | b;
557                 }
558         }
559
560         g_object_unref(pixbuf);
561
562         return surface;
563 }
564
565 static int
566 check_size(struct rectangle *rect)
567 {
568         if (rect->width && rect->height)
569                 return 0;
570
571         fprintf(stderr, "tried to create surface of "
572                 "width: %d, height: %d\n", rect->width, rect->height);
573         return -1;
574 }
575
576 cairo_surface_t *
577 display_create_surface(struct display *display,
578                        struct wl_surface *surface,
579                        struct rectangle *rectangle,
580                        uint32_t flags)
581 {
582         if (check_size(rectangle) < 0)
583                 return NULL;
584 #ifdef HAVE_CAIRO_EGL
585         if (display->dpy) {
586                 if (surface)
587                         return display_create_egl_window_surface(display,
588                                                                  surface,
589                                                                  flags,
590                                                                  rectangle);
591                 else
592                         return display_create_egl_image_surface(display,
593                                                                 flags,
594                                                                 rectangle);
595         }
596 #endif
597         return display_create_shm_surface(display, rectangle, flags);
598 }
599
600 static cairo_surface_t *
601 display_create_surface_from_file(struct display *display,
602                                  const char *filename,
603                                  struct rectangle *rectangle)
604 {
605         if (check_size(rectangle) < 0)
606                 return NULL;
607 #ifdef HAVE_CAIRO_EGL
608         if (display->dpy) {
609                 return display_create_egl_image_surface_from_file(display,
610                                                                   filename,
611                                                                   rectangle);
612         }
613 #endif
614         return display_create_shm_surface_from_file(display, filename, rectangle);
615 }
616  static const struct {
617         const char *filename;
618         int hotspot_x, hotspot_y;
619 } pointer_images[] = {
620         { DATADIR "/wayland/bottom_left_corner.png",     6, 30 },
621         { DATADIR "/wayland/bottom_right_corner.png",   28, 28 },
622         { DATADIR "/wayland/bottom_side.png",           16, 20 },
623         { DATADIR "/wayland/grabbing.png",              20, 17 },
624         { DATADIR "/wayland/left_ptr.png",              10,  5 },
625         { DATADIR "/wayland/left_side.png",             10, 20 },
626         { DATADIR "/wayland/right_side.png",            30, 19 },
627         { DATADIR "/wayland/top_left_corner.png",        8,  8 },
628         { DATADIR "/wayland/top_right_corner.png",      26,  8 },
629         { DATADIR "/wayland/top_side.png",              18,  8 },
630         { DATADIR "/wayland/xterm.png",                 15, 15 },
631         { DATADIR "/wayland/hand1.png",                 18, 11 }
632 };
633
634 static void
635 create_pointer_surfaces(struct display *display)
636 {
637         int i, count;
638         const int width = 32, height = 32;
639         struct rectangle rect;
640
641         count = ARRAY_LENGTH(pointer_images);
642         display->pointer_surfaces =
643                 malloc(count * sizeof *display->pointer_surfaces);
644         rect.width = width;
645         rect.height = height;
646         for (i = 0; i < count; i++) {
647                 display->pointer_surfaces[i] =
648                         display_create_surface_from_file(display,
649                                                          pointer_images[i].filename,
650                                                          &rect);
651         }
652
653 }
654
655 cairo_surface_t *
656 display_get_pointer_surface(struct display *display, int pointer,
657                             int *width, int *height,
658                             int *hotspot_x, int *hotspot_y)
659 {
660         cairo_surface_t *surface;
661
662         surface = display->pointer_surfaces[pointer];
663 #if HAVE_CAIRO_EGL
664         *width = cairo_gl_surface_get_width(surface);
665         *height = cairo_gl_surface_get_height(surface);
666 #else
667         *width = cairo_image_surface_get_width(surface);
668         *height = cairo_image_surface_get_height(surface);
669 #endif
670         *hotspot_x = pointer_images[pointer].hotspot_x;
671         *hotspot_y = pointer_images[pointer].hotspot_y;
672
673         return cairo_surface_reference(surface);
674 }
675
676
677 static void
678 window_attach_surface(struct window *window);
679
680 static void
681 free_surface(void *data, struct wl_callback *callback, uint32_t time)
682 {
683         struct window *window = data;
684
685         wl_callback_destroy(callback);
686         cairo_surface_destroy(window->pending_surface);
687         window->pending_surface = NULL;
688         if (window->cairo_surface)
689                 window_attach_surface(window);
690 }
691
692 static const struct wl_callback_listener free_surface_listener = {
693         free_surface
694 };
695
696 static void
697 window_get_resize_dx_dy(struct window *window, int *x, int *y)
698 {
699         if (window->resize_edges & WINDOW_RESIZING_LEFT)
700                 *x = window->server_allocation.width - window->allocation.width;
701         else
702                 *x = 0;
703
704         if (window->resize_edges & WINDOW_RESIZING_TOP)
705                 *y = window->server_allocation.height -
706                         window->allocation.height;
707         else
708                 *y = 0;
709
710         window->resize_edges = 0;
711 }
712
713 static void
714 window_attach_surface(struct window *window)
715 {
716         struct display *display = window->display;
717         struct wl_buffer *buffer;
718         struct wl_callback *cb;
719 #ifdef HAVE_CAIRO_EGL
720         struct egl_window_surface_data *data;
721 #endif
722         int32_t x, y;
723
724         switch (window->buffer_type) {
725 #ifdef HAVE_CAIRO_EGL
726         case WINDOW_BUFFER_TYPE_EGL_WINDOW:
727                 data = cairo_surface_get_user_data(window->cairo_surface,
728                                                    &surface_data_key);
729
730                 cairo_gl_surface_swapbuffers(window->cairo_surface);
731                 wl_egl_window_get_attached_size(data->window,
732                                 &window->server_allocation.width,
733                                 &window->server_allocation.height);
734                 break;
735         case WINDOW_BUFFER_TYPE_EGL_IMAGE:
736 #endif
737         case WINDOW_BUFFER_TYPE_SHM:
738                 window_get_resize_dx_dy(window, &x, &y);
739
740                 if (window->pending_surface != NULL)
741                         return;
742
743                 window->pending_surface = window->cairo_surface;
744                 window->cairo_surface = NULL;
745
746                 buffer =
747                         display_get_buffer_for_surface(display,
748                                                        window->pending_surface);
749
750                 wl_surface_attach(window->surface, buffer, x, y);
751                 window->server_allocation = window->allocation;
752                 cb = wl_display_sync(display->display);
753                 wl_callback_add_listener(cb, &free_surface_listener, window);
754                 break;
755         default:
756                 return;
757         }
758
759         if (window->fullscreen)
760                 wl_shell_set_fullscreen(display->shell, window->surface);
761         else if (!window->parent)
762                 wl_shell_set_toplevel(display->shell, window->surface);
763         else
764                 wl_shell_set_transient(display->shell, window->surface,
765                                        window->parent->surface,
766                                        window->x, window->y, 0);
767
768         wl_surface_damage(window->surface, 0, 0,
769                           window->allocation.width,
770                           window->allocation.height);
771 }
772
773 void
774 window_flush(struct window *window)
775 {
776         if (window->cairo_surface) {
777                 switch (window->buffer_type) {
778                 case WINDOW_BUFFER_TYPE_EGL_IMAGE:
779                 case WINDOW_BUFFER_TYPE_SHM:
780                         display_surface_damage(window->display,
781                                                window->cairo_surface,
782                                                0, 0,
783                                                window->allocation.width,
784                                                window->allocation.height);
785                         break;
786                 default:
787                         break;
788                 }
789                 window_attach_surface(window);
790         }
791 }
792
793 void
794 window_set_surface(struct window *window, cairo_surface_t *surface)
795 {
796         cairo_surface_reference(surface);
797
798         if (window->cairo_surface != NULL)
799                 cairo_surface_destroy(window->cairo_surface);
800
801         window->cairo_surface = surface;
802 }
803
804 #ifdef HAVE_CAIRO_EGL
805 static void
806 window_resize_cairo_window_surface(struct window *window)
807 {
808         struct egl_window_surface_data *data;
809         int x, y;
810
811         data = cairo_surface_get_user_data(window->cairo_surface,
812                                            &surface_data_key);
813
814         window_get_resize_dx_dy(window, &x, &y),
815         wl_egl_window_resize(data->window,
816                              window->allocation.width,
817                              window->allocation.height,
818                              x,y);
819
820         cairo_gl_surface_set_size(window->cairo_surface,
821                                   window->allocation.width,
822                                   window->allocation.height);
823 }
824 #endif
825
826 void
827 window_create_surface(struct window *window)
828 {
829         cairo_surface_t *surface;
830         uint32_t flags = 0;
831         
832         if (!window->transparent)
833                 flags = SURFACE_OPAQUE;
834         
835         switch (window->buffer_type) {
836 #ifdef HAVE_CAIRO_EGL
837         case WINDOW_BUFFER_TYPE_EGL_WINDOW:
838                 if (window->cairo_surface) {
839                         window_resize_cairo_window_surface(window);
840                         return;
841                 }
842                 surface = display_create_surface(window->display,
843                                                  window->surface,
844                                                  &window->allocation, flags);
845                 break;
846         case WINDOW_BUFFER_TYPE_EGL_IMAGE:
847                 surface = display_create_surface(window->display,
848                                                  NULL,
849                                                  &window->allocation, flags);
850                 break;
851 #endif
852         case WINDOW_BUFFER_TYPE_SHM:
853                 surface = display_create_shm_surface(window->display,
854                                                      &window->allocation, flags);
855                 break;
856         default:
857                 surface = NULL;
858                 break;
859         }
860
861         window_set_surface(window, surface);
862         cairo_surface_destroy(surface);
863 }
864
865 static void
866 window_draw_menu(struct window *window)
867 {
868         cairo_t *cr;
869         int width, height, r = 5;
870
871         window_create_surface(window);
872
873         cr = cairo_create(window->cairo_surface);
874         cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
875         cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0);
876         cairo_paint(cr);
877
878         width = window->allocation.width;
879         height = window->allocation.height;
880         rounded_rect(cr, r, r, width - r, height - r, r);
881         cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
882         cairo_set_source_rgba(cr, 1.0, 1.0, 0.0, 0.5);
883         cairo_fill(cr);
884         cairo_destroy(cr);
885 }
886
887 static void
888 window_draw_decorations(struct window *window)
889 {
890         cairo_t *cr;
891         cairo_text_extents_t extents;
892         cairo_surface_t *frame;
893         int width, height, shadow_dx = 3, shadow_dy = 3;
894
895         window_create_surface(window);
896
897         width = window->allocation.width;
898         height = window->allocation.height;
899
900         cr = cairo_create(window->cairo_surface);
901
902         cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
903         cairo_set_source_rgba(cr, 0, 0, 0, 0);
904         cairo_paint(cr);
905
906         cairo_set_source_rgba(cr, 0, 0, 0, 0.6);
907         tile_mask(cr, window->display->shadow,
908                   shadow_dx, shadow_dy, width, height,
909                   window->margin + 10 - shadow_dx,
910                   window->margin + 10 - shadow_dy);
911
912         if (window->keyboard_device)
913                 frame = window->display->active_frame;
914         else
915                 frame = window->display->inactive_frame;
916
917         tile_source(cr, frame, 0, 0, width, height,
918                     window->margin + 10, window->margin + 50);
919
920         cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
921         cairo_set_font_size(cr, 14);
922         cairo_text_extents(cr, window->title, &extents);
923         cairo_move_to(cr, (width - extents.width) / 2, 32 - extents.y_bearing);
924         if (window->keyboard_device)
925                 cairo_set_source_rgb(cr, 0, 0, 0);
926         else
927                 cairo_set_source_rgb(cr, 0.8, 0.8, 0.8);
928         cairo_show_text(cr, window->title);
929
930         cairo_destroy(cr);
931
932         /* FIXME: this breakes gears, fix cairo? */
933 #if 0 
934         cairo_device_flush (window->display->device);
935 #endif
936 }
937
938 void
939 window_destroy(struct window *window)
940 {
941         wl_surface_destroy(window->surface);
942         wl_list_remove(&window->link);
943         free(window);
944 }
945
946 void
947 display_flush_cairo_device(struct display *display)
948 {
949         cairo_device_flush (display->device);
950 }
951
952 void
953 window_draw(struct window *window)
954 {
955         if (window->parent)
956                 window_draw_menu(window);
957         else if (window->fullscreen || !window->decoration)
958                 window_create_surface(window);
959         else
960                 window_draw_decorations(window);
961 }
962
963 cairo_surface_t *
964 window_get_surface(struct window *window)
965 {
966         return cairo_surface_reference(window->cairo_surface);
967 }
968
969 struct wl_surface *
970 window_get_wl_surface(struct window *window)
971 {
972         return window->surface;
973 }
974
975 static int
976 get_pointer_location(struct window *window, int32_t x, int32_t y)
977 {
978         int vlocation, hlocation, location;
979         const int grip_size = 8;
980
981         if (!window->decoration)
982                 return WINDOW_CLIENT_AREA;
983
984         if (x < window->margin)
985                 hlocation = WINDOW_EXTERIOR;
986         else if (window->margin <= x && x < window->margin + grip_size)
987                 hlocation = WINDOW_RESIZING_LEFT;
988         else if (x < window->allocation.width - window->margin - grip_size)
989                 hlocation = WINDOW_INTERIOR;
990         else if (x < window->allocation.width - window->margin)
991                 hlocation = WINDOW_RESIZING_RIGHT;
992         else
993                 hlocation = WINDOW_EXTERIOR;
994
995         if (y < window->margin)
996                 vlocation = WINDOW_EXTERIOR;
997         else if (window->margin <= y && y < window->margin + grip_size)
998                 vlocation = WINDOW_RESIZING_TOP;
999         else if (y < window->allocation.height - window->margin - grip_size)
1000                 vlocation = WINDOW_INTERIOR;
1001         else if (y < window->allocation.height - window->margin)
1002                 vlocation = WINDOW_RESIZING_BOTTOM;
1003         else
1004                 vlocation = WINDOW_EXTERIOR;
1005
1006         location = vlocation | hlocation;
1007         if (location & WINDOW_EXTERIOR)
1008                 location = WINDOW_EXTERIOR;
1009         if (location == WINDOW_INTERIOR && y < window->margin + 50)
1010                 location = WINDOW_TITLEBAR;
1011         else if (location == WINDOW_INTERIOR)
1012                 location = WINDOW_CLIENT_AREA;
1013
1014         return location;
1015 }
1016
1017 static void
1018 set_pointer_image(struct input *input, uint32_t time, int pointer)
1019 {
1020         struct display *display = input->display;
1021         struct wl_buffer *buffer;
1022         cairo_surface_t *surface;
1023         int location;
1024
1025         location = get_pointer_location(input->pointer_focus,
1026                                         input->sx, input->sy);
1027         switch (location) {
1028         case WINDOW_RESIZING_TOP:
1029                 pointer = POINTER_TOP;
1030                 break;
1031         case WINDOW_RESIZING_BOTTOM:
1032                 pointer = POINTER_BOTTOM;
1033                 break;
1034         case WINDOW_RESIZING_LEFT:
1035                 pointer = POINTER_LEFT;
1036                 break;
1037         case WINDOW_RESIZING_RIGHT:
1038                 pointer = POINTER_RIGHT;
1039                 break;
1040         case WINDOW_RESIZING_TOP_LEFT:
1041                 pointer = POINTER_TOP_LEFT;
1042                 break;
1043         case WINDOW_RESIZING_TOP_RIGHT:
1044                 pointer = POINTER_TOP_RIGHT;
1045                 break;
1046         case WINDOW_RESIZING_BOTTOM_LEFT:
1047                 pointer = POINTER_BOTTOM_LEFT;
1048                 break;
1049         case WINDOW_RESIZING_BOTTOM_RIGHT:
1050                 pointer = POINTER_BOTTOM_RIGHT;
1051                 break;
1052         case WINDOW_EXTERIOR:
1053         case WINDOW_TITLEBAR:
1054                 if (input->current_pointer_image == POINTER_DEFAULT)
1055                         return;
1056
1057                 wl_input_device_attach(input->input_device, time, NULL, 0, 0);
1058                 input->current_pointer_image = POINTER_DEFAULT;
1059                 return;
1060         default:
1061                 break;
1062         }
1063
1064         if (pointer == input->current_pointer_image)
1065                 return;
1066
1067         input->current_pointer_image = pointer;
1068         surface = display->pointer_surfaces[pointer];
1069         buffer = display_get_buffer_for_surface(display, surface);
1070         wl_input_device_attach(input->input_device, time, buffer,
1071                                pointer_images[pointer].hotspot_x,
1072                                pointer_images[pointer].hotspot_y);
1073 }
1074
1075 static void
1076 window_handle_motion(void *data, struct wl_input_device *input_device,
1077                      uint32_t time,
1078                      int32_t x, int32_t y, int32_t sx, int32_t sy)
1079 {
1080         struct input *input = data;
1081         struct window *window = input->pointer_focus;
1082         int pointer = POINTER_LEFT_PTR;
1083
1084         input->x = x;
1085         input->y = y;
1086         input->sx = sx;
1087         input->sy = sy;
1088
1089         if (window->motion_handler)
1090                 pointer = (*window->motion_handler)(window, input, time,
1091                                                     x, y, sx, sy,
1092                                                     window->user_data);
1093
1094         set_pointer_image(input, time, pointer);
1095 }
1096
1097 static void
1098 window_handle_button(void *data,
1099                      struct wl_input_device *input_device,
1100                      uint32_t time, uint32_t button, uint32_t state)
1101 {
1102         struct input *input = data;
1103         struct window *window = input->pointer_focus;
1104         int location;
1105
1106         location = get_pointer_location(window, input->sx, input->sy);
1107
1108         if (button == BTN_LEFT && state == 1) {
1109                 switch (location) {
1110                 case WINDOW_TITLEBAR:
1111                         wl_shell_move(window->display->shell,
1112                                       window->surface, input_device, time);
1113                         break;
1114                 case WINDOW_RESIZING_TOP:
1115                 case WINDOW_RESIZING_BOTTOM:
1116                 case WINDOW_RESIZING_LEFT:
1117                 case WINDOW_RESIZING_RIGHT:
1118                 case WINDOW_RESIZING_TOP_LEFT:
1119                 case WINDOW_RESIZING_TOP_RIGHT:
1120                 case WINDOW_RESIZING_BOTTOM_LEFT:
1121                 case WINDOW_RESIZING_BOTTOM_RIGHT:
1122                         wl_shell_resize(window->display->shell,
1123                                         window->surface, input_device, time,
1124                                         location);
1125                         break;
1126                 case WINDOW_CLIENT_AREA:
1127                         if (window->button_handler)
1128                                 (*window->button_handler)(window,
1129                                                           input, time,
1130                                                           button, state,
1131                                                           window->user_data);
1132                         break;
1133                 }
1134         } else {
1135                 if (window->button_handler)
1136                         (*window->button_handler)(window,
1137                                                   input, time,
1138                                                   button, state,
1139                                                   window->user_data);
1140         }
1141 }
1142
1143 static void
1144 window_handle_key(void *data, struct wl_input_device *input_device,
1145                   uint32_t time, uint32_t key, uint32_t state)
1146 {
1147         struct input *input = data;
1148         struct window *window = input->keyboard_focus;
1149         struct display *d = window->display;
1150         uint32_t code, sym, level;
1151
1152         code = key + d->xkb->min_key_code;
1153         if (window->keyboard_device != input)
1154                 return;
1155
1156         level = 0;
1157         if (input->modifiers & XKB_COMMON_SHIFT_MASK &&
1158             XkbKeyGroupWidth(d->xkb, code, 0) > 1)
1159                 level = 1;
1160
1161         sym = XkbKeySymEntry(d->xkb, code, level, 0);
1162
1163         if (state)
1164                 input->modifiers |= d->xkb->map->modmap[code];
1165         else
1166                 input->modifiers &= ~d->xkb->map->modmap[code];
1167
1168         if (window->key_handler)
1169                 (*window->key_handler)(window, input, time, key, sym, state,
1170                                        window->user_data);
1171 }
1172
1173 static void
1174 window_handle_pointer_focus(void *data,
1175                             struct wl_input_device *input_device,
1176                             uint32_t time, struct wl_surface *surface,
1177                             int32_t x, int32_t y, int32_t sx, int32_t sy)
1178 {
1179         struct input *input = data;
1180         struct window *window;
1181         int pointer;
1182
1183         if (surface) {
1184                 input->pointer_focus = wl_surface_get_user_data(surface);
1185                 window = input->pointer_focus;
1186
1187                 input->x = x;
1188                 input->y = y;
1189                 input->sx = sx;
1190                 input->sy = sy;
1191
1192                 pointer = POINTER_LEFT_PTR;
1193                 if (window->motion_handler)
1194                         pointer = (*window->motion_handler)(window,
1195                                                             input, time,
1196                                                             x, y, sx, sy,
1197                                                             window->user_data);
1198
1199                 set_pointer_image(input, time, pointer);
1200         } else {
1201                 input->pointer_focus = NULL;
1202                 input->current_pointer_image = POINTER_UNSET;
1203         }
1204 }
1205
1206 static void
1207 window_handle_keyboard_focus(void *data,
1208                              struct wl_input_device *input_device,
1209                              uint32_t time,
1210                              struct wl_surface *surface,
1211                              struct wl_array *keys)
1212 {
1213         struct input *input = data;
1214         struct window *window = input->keyboard_focus;
1215         struct display *d = input->display;
1216         uint32_t *k, *end;
1217
1218         window = input->keyboard_focus;
1219         if (window) {
1220                 window->keyboard_device = NULL;
1221                 if (window->keyboard_focus_handler)
1222                         (*window->keyboard_focus_handler)(window, NULL,
1223                                                           window->user_data);
1224         }
1225
1226         if (surface)
1227                 input->keyboard_focus = wl_surface_get_user_data(surface);
1228         else
1229                 input->keyboard_focus = NULL;
1230
1231         end = keys->data + keys->size;
1232         input->modifiers = 0;
1233         for (k = keys->data; k < end; k++)
1234                 input->modifiers |= d->xkb->map->modmap[*k];
1235
1236         window = input->keyboard_focus;
1237         if (window) {
1238                 window->keyboard_device = input;
1239                 if (window->keyboard_focus_handler)
1240                         (*window->keyboard_focus_handler)(window,
1241                                                           window->keyboard_device,
1242                                                           window->user_data);
1243         }
1244 }
1245
1246 static const struct wl_input_device_listener input_device_listener = {
1247         window_handle_motion,
1248         window_handle_button,
1249         window_handle_key,
1250         window_handle_pointer_focus,
1251         window_handle_keyboard_focus,
1252 };
1253
1254 void
1255 input_get_position(struct input *input, int32_t *x, int32_t *y)
1256 {
1257         *x = input->sx;
1258         *y = input->sy;
1259 }
1260
1261 struct wl_input_device *
1262 input_get_input_device(struct input *input)
1263 {
1264         return input->input_device;
1265 }
1266
1267 uint32_t
1268 input_get_modifiers(struct input *input)
1269 {
1270         return input->modifiers;
1271 }
1272
1273 struct wl_drag *
1274 window_create_drag(struct window *window)
1275 {
1276         cairo_device_flush (window->display->device);
1277
1278         return wl_shell_create_drag(window->display->shell);
1279 }
1280
1281 void
1282 window_move(struct window *window, struct input *input, uint32_t time)
1283 {
1284         wl_shell_move(window->display->shell,
1285                       window->surface, input->input_device, time);
1286 }
1287
1288 void
1289 window_activate_drag(struct wl_drag *drag, struct window *window,
1290                      struct input *input, uint32_t time)
1291 {
1292         wl_drag_activate(drag, window->surface, input->input_device, time);
1293 }
1294
1295 static void
1296 handle_configure(void *data, struct wl_shell *shell,
1297                  uint32_t time, uint32_t edges,
1298                  struct wl_surface *surface, int32_t width, int32_t height)
1299 {
1300         struct window *window = wl_surface_get_user_data(surface);
1301         int32_t child_width, child_height;
1302
1303         /* FIXME: this is probably the wrong place to check for width
1304          * or height <= 0, but it prevents the compositor from crashing
1305          */
1306         if (width <= 0 || height <= 0)
1307                 return;
1308
1309         window->resize_edges = edges;
1310
1311         if (window->resize_handler) {
1312                 child_width = width - 20 - window->margin * 2;
1313                 child_height = height - 60 - window->margin * 2;
1314
1315                 (*window->resize_handler)(window,
1316                                           child_width, child_height,
1317                                           window->user_data);
1318         } else {
1319                 window->allocation.width = width;
1320                 window->allocation.height = height;
1321
1322                 if (window->redraw_handler)
1323                         window_schedule_redraw(window);
1324         }
1325 }
1326
1327 static const struct wl_shell_listener shell_listener = {
1328         handle_configure,
1329 };
1330
1331 void
1332 window_get_allocation(struct window *window,
1333                       struct rectangle *allocation)
1334 {
1335         *allocation = window->allocation;
1336 }
1337
1338 void
1339 window_get_child_allocation(struct window *window,
1340                             struct rectangle *allocation)
1341 {
1342         if (window->fullscreen || !window->decoration) {
1343                 *allocation = window->allocation;
1344         } else {
1345                 allocation->x = window->margin + 10;
1346                 allocation->y = window->margin + 50;
1347                 allocation->width =
1348                         window->allocation.width - 20 - window->margin * 2;
1349                 allocation->height =
1350                         window->allocation.height - 60 - window->margin * 2;
1351         }
1352 }
1353
1354 void
1355 window_set_child_size(struct window *window, int32_t width, int32_t height)
1356 {
1357         if (!window->fullscreen && window->decoration) {
1358                 window->allocation.x = 20 + window->margin;
1359                 window->allocation.y = 60 + window->margin;
1360                 window->allocation.width = width + 20 + window->margin * 2;
1361                 window->allocation.height = height + 60 + window->margin * 2;
1362         } else {
1363                 window->allocation.x = 0;
1364                 window->allocation.y = 0;
1365                 window->allocation.width = width;
1366                 window->allocation.height = height;
1367         }
1368 }
1369
1370 static gboolean
1371 idle_redraw(void *data)
1372 {
1373         struct window *window = data;
1374
1375         window->redraw_handler(window, window->user_data);
1376
1377         window->redraw_scheduled = 0;
1378
1379         return FALSE;
1380 }
1381
1382 void
1383 window_schedule_redraw(struct window *window)
1384 {
1385         if (!window->redraw_scheduled) {
1386                 g_idle_add(idle_redraw, window);
1387                 window->redraw_scheduled = 1;
1388         }
1389 }
1390
1391 void
1392 window_set_fullscreen(struct window *window, int fullscreen)
1393 {
1394         int32_t width, height;
1395
1396         if (window->fullscreen == fullscreen)
1397                 return;
1398
1399         window->fullscreen = fullscreen;
1400         if (window->fullscreen) {
1401                 window->saved_allocation = window->allocation;
1402                 width = window->display->screen_allocation.width;
1403                 height = window->display->screen_allocation.height;
1404         } else {
1405                 width = window->saved_allocation.width - 20 - window->margin * 2;
1406                 height = window->saved_allocation.height - 60 - window->margin * 2;
1407         }
1408
1409         (*window->resize_handler)(window, width, height, window->user_data);
1410 }
1411
1412 void
1413 window_set_decoration(struct window *window, int decoration)
1414 {
1415         window->decoration = decoration;
1416 }
1417
1418 void
1419 window_set_user_data(struct window *window, void *data)
1420 {
1421         window->user_data = data;
1422 }
1423
1424 void *
1425 window_get_user_data(struct window *window)
1426 {
1427         return window->user_data;
1428 }
1429
1430 void
1431 window_set_resize_handler(struct window *window,
1432                           window_resize_handler_t handler)
1433 {
1434         window->resize_handler = handler;
1435 }
1436
1437 void
1438 window_set_redraw_handler(struct window *window,
1439                           window_redraw_handler_t handler)
1440 {
1441         window->redraw_handler = handler;
1442 }
1443
1444 void
1445 window_set_key_handler(struct window *window,
1446                        window_key_handler_t handler)
1447 {
1448         window->key_handler = handler;
1449 }
1450
1451 void
1452 window_set_button_handler(struct window *window,
1453                           window_button_handler_t handler)
1454 {
1455         window->button_handler = handler;
1456 }
1457
1458 void
1459 window_set_motion_handler(struct window *window,
1460                           window_motion_handler_t handler)
1461 {
1462         window->motion_handler = handler;
1463 }
1464
1465 void
1466 window_set_keyboard_focus_handler(struct window *window,
1467                                   window_keyboard_focus_handler_t handler)
1468 {
1469         window->keyboard_focus_handler = handler;
1470 }
1471
1472 void
1473 window_set_transparent(struct window *window, int transparent)
1474 {
1475         window->transparent = transparent;
1476 }
1477
1478 void
1479 window_set_title(struct window *window, const char *title)
1480 {
1481         free(window->title);
1482         window->title = strdup(title);
1483 }
1484
1485 const char *
1486 window_get_title(struct window *window)
1487 {
1488         return window->title;
1489 }
1490
1491 void
1492 display_surface_damage(struct display *display, cairo_surface_t *cairo_surface,
1493                        int32_t x, int32_t y, int32_t width, int32_t height)
1494 {
1495         struct wl_buffer *buffer;
1496
1497         buffer = display_get_buffer_for_surface(display, cairo_surface);
1498
1499         wl_buffer_damage(buffer, x, y, width, height);
1500 }
1501
1502 void
1503 window_damage(struct window *window, int32_t x, int32_t y,
1504               int32_t width, int32_t height)
1505 {
1506         wl_surface_damage(window->surface, x, y, width, height);
1507 }
1508
1509 static struct window *
1510 window_create_internal(struct display *display, struct window *parent,
1511                         int32_t width, int32_t height)
1512 {
1513         struct window *window;
1514
1515         window = malloc(sizeof *window);
1516         if (window == NULL)
1517                 return NULL;
1518
1519         memset(window, 0, sizeof *window);
1520         window->display = display;
1521         window->parent = parent;
1522         window->surface = wl_compositor_create_surface(display->compositor);
1523         window->allocation.x = 0;
1524         window->allocation.y = 0;
1525         window->allocation.width = width;
1526         window->allocation.height = height;
1527         window->saved_allocation = window->allocation;
1528         window->margin = 16;
1529         window->decoration = 1;
1530         window->transparent = 1;
1531
1532         if (display->dpy)
1533 #ifdef HAVE_CAIRO_EGL
1534                 /* FIXME: make TYPE_EGL_IMAGE choosable for testing */
1535                 window->buffer_type = WINDOW_BUFFER_TYPE_EGL_WINDOW;
1536 #else
1537                 window->buffer_type = WINDOW_BUFFER_TYPE_SHM;
1538 #endif
1539         else
1540                 window->buffer_type = WINDOW_BUFFER_TYPE_SHM;
1541
1542         wl_surface_set_user_data(window->surface, window);
1543         wl_list_insert(display->window_list.prev, &window->link);
1544
1545         return window;
1546 }
1547
1548 struct window *
1549 window_create(struct display *display, int32_t width, int32_t height)
1550 {
1551         struct window *window;
1552
1553         window = window_create_internal(display, NULL, width, height);
1554         if (!window)
1555                 return NULL;
1556
1557         return window;
1558 }
1559
1560 struct window *
1561 window_create_transient(struct display *display, struct window *parent,
1562                         int32_t x, int32_t y, int32_t width, int32_t height)
1563 {
1564         struct window *window;
1565
1566         window = window_create_internal(parent->display,
1567                                         parent, width, height);
1568         if (!window)
1569                 return NULL;
1570
1571         window->x = x;
1572         window->y = y;
1573
1574         return window;
1575 }
1576
1577 void
1578 window_set_buffer_type(struct window *window, enum window_buffer_type type)
1579 {
1580         window->buffer_type = type;
1581 }
1582
1583
1584 static void
1585 display_handle_geometry(void *data,
1586                         struct wl_output *wl_output,
1587                         int x, int y,
1588                         int physical_width,
1589                         int physical_height,
1590                         int subpixel,
1591                         const char *make,
1592                         const char *model)
1593 {
1594         struct display *display = data;
1595
1596         display->screen_allocation.x = x;
1597         display->screen_allocation.y = y;
1598 }
1599
1600 static void
1601 display_handle_mode(void *data,
1602                     struct wl_output *wl_output,
1603                     uint32_t flags,
1604                     int width,
1605                     int height,
1606                     int refresh)
1607 {
1608         struct display *display = data;
1609
1610         display->screen_allocation.width = width;
1611         display->screen_allocation.height = height;
1612 }
1613
1614 static const struct wl_output_listener output_listener = {
1615         display_handle_geometry,
1616         display_handle_mode
1617 };
1618
1619 static void
1620 display_add_input(struct display *d, uint32_t id)
1621 {
1622         struct input *input;
1623
1624         input = malloc(sizeof *input);
1625         if (input == NULL)
1626                 return;
1627
1628         memset(input, 0, sizeof *input);
1629         input->display = d;
1630         input->input_device =
1631                 wl_display_bind(d->display, id, &wl_input_device_interface);
1632         input->pointer_focus = NULL;
1633         input->keyboard_focus = NULL;
1634         wl_list_insert(d->input_list.prev, &input->link);
1635
1636         wl_input_device_add_listener(input->input_device,
1637                                      &input_device_listener, input);
1638         wl_input_device_set_user_data(input->input_device, input);
1639 }
1640
1641 struct selection_offer {
1642         struct display *display;
1643         struct wl_selection_offer *offer;
1644         struct wl_array types;
1645         struct input *input;
1646 };
1647
1648 int
1649 input_offers_mime_type(struct input *input, const char *type)
1650 {
1651         struct selection_offer *offer = input->offer;
1652         char **p, **end;
1653
1654         if (offer == NULL)
1655                 return 0;
1656
1657         end = offer->types.data + offer->types.size;
1658         for (p = offer->types.data; p < end; p++)
1659                 if (strcmp(*p, type) == 0)
1660                         return 1;
1661
1662         return 0;
1663 }
1664
1665 void
1666 input_receive_mime_type(struct input *input, const char *type, int fd)
1667 {
1668         struct selection_offer *offer = input->offer;
1669
1670         /* FIXME: A number of things can go wrong here: the object may
1671          * not be the current selection offer any more (which could
1672          * still work, but the source may have gone away or just
1673          * destroyed its wl_selection) or the offer may not have the
1674          * requested type after all (programmer/client error,
1675          * typically) */
1676         wl_selection_offer_receive(offer->offer, type, fd);
1677 }
1678
1679 static void
1680 selection_offer_offer(void *data,
1681                       struct wl_selection_offer *selection_offer,
1682                       const char *type)
1683 {
1684         struct selection_offer *offer = data;
1685
1686         char **p;
1687
1688         p = wl_array_add(&offer->types, sizeof *p);
1689         if (p)
1690                 *p = strdup(type);
1691 };
1692
1693 static void
1694 selection_offer_keyboard_focus(void *data,
1695                                struct wl_selection_offer *selection_offer,
1696                                struct wl_input_device *input_device)
1697 {
1698         struct selection_offer *offer = data;
1699         struct input *input;
1700         char **p, **end;
1701
1702         if (input_device == NULL) {
1703                 printf("selection offer retracted %p\n", selection_offer);
1704                 input = offer->input;
1705                 input->offer = NULL;
1706                 wl_selection_offer_destroy(selection_offer);
1707                 wl_array_release(&offer->types);
1708                 free(offer);
1709                 return;
1710         }
1711
1712         input = wl_input_device_get_user_data(input_device);
1713         printf("new selection offer %p:", selection_offer);
1714
1715         offer->input = input;
1716         input->offer = offer;
1717         end = offer->types.data + offer->types.size;
1718         for (p = offer->types.data; p < end; p++)
1719                 printf(" %s", *p);
1720
1721         printf("\n");
1722 }
1723
1724 struct wl_selection_offer_listener selection_offer_listener = {
1725         selection_offer_offer,
1726         selection_offer_keyboard_focus
1727 };
1728
1729 static void
1730 add_selection_offer(struct display *d, uint32_t id)
1731 {
1732         struct selection_offer *offer;
1733
1734         offer = malloc(sizeof *offer);
1735         if (offer == NULL)
1736                 return;
1737
1738         offer->offer =
1739                 wl_display_bind(d->display, id, &wl_selection_offer_interface);
1740         offer->display = d;
1741         wl_array_init(&offer->types);
1742         offer->input = NULL;
1743
1744         wl_selection_offer_add_listener(offer->offer,
1745                                         &selection_offer_listener, offer);
1746 }
1747
1748 static void
1749 display_handle_global(struct wl_display *display, uint32_t id,
1750                       const char *interface, uint32_t version, void *data)
1751 {
1752         struct display *d = data;
1753
1754         if (strcmp(interface, "wl_compositor") == 0) {
1755                 d->compositor =
1756                         wl_display_bind(display, id, &wl_compositor_interface);
1757         } else if (strcmp(interface, "wl_output") == 0) {
1758                 d->output = wl_display_bind(display, id, &wl_output_interface);
1759                 wl_output_add_listener(d->output, &output_listener, d);
1760         } else if (strcmp(interface, "wl_input_device") == 0) {
1761                 display_add_input(d, id);
1762         } else if (strcmp(interface, "wl_shell") == 0) {
1763                 d->shell = wl_display_bind(display, id, &wl_shell_interface);
1764                 wl_shell_add_listener(d->shell, &shell_listener, d);
1765         } else if (strcmp(interface, "wl_shm") == 0) {
1766                 d->shm = wl_display_bind(display, id, &wl_shm_interface);
1767         } else if (strcmp(interface, "wl_selection_offer") == 0) {
1768                 add_selection_offer(d, id);
1769         }
1770 }
1771
1772 static void
1773 display_render_frame(struct display *d)
1774 {
1775         int radius = 8;
1776         cairo_t *cr;
1777
1778         d->shadow = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 128, 128);
1779         cr = cairo_create(d->shadow);
1780         cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
1781         cairo_set_source_rgba(cr, 0, 0, 0, 1);
1782         rounded_rect(cr, 16, 16, 112, 112, radius);
1783         cairo_fill(cr);
1784         cairo_destroy(cr);
1785         blur_surface(d->shadow, 64);
1786
1787         d->active_frame =
1788                 cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 128, 128);
1789         cr = cairo_create(d->active_frame);
1790         cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
1791         cairo_set_source_rgba(cr, 0.8, 0.8, 0.4, 1);
1792         rounded_rect(cr, 16, 16, 112, 112, radius);
1793         cairo_fill(cr);
1794         cairo_destroy(cr);
1795
1796         d->inactive_frame =
1797                 cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 128, 128);
1798         cr = cairo_create(d->inactive_frame);
1799         cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
1800         cairo_set_source_rgba(cr, 0.6, 0.6, 0.6, 1);
1801         rounded_rect(cr, 16, 16, 112, 112, radius);
1802         cairo_fill(cr);
1803         cairo_destroy(cr);
1804 }
1805
1806 static void
1807 init_xkb(struct display *d)
1808 {
1809         struct xkb_rule_names names;
1810
1811         names.rules = "evdev";
1812         names.model = "pc105";
1813         names.layout = option_xkb_layout;
1814         names.variant = option_xkb_variant;
1815         names.options = option_xkb_options;
1816
1817         d->xkb = xkb_compile_keymap_from_rules(&names);
1818         if (!d->xkb) {
1819                 fprintf(stderr, "Failed to compile keymap\n");
1820                 exit(1);
1821         }
1822 }
1823
1824 static int
1825 init_egl(struct display *d)
1826 {
1827         EGLint major, minor;
1828         EGLint n;
1829
1830         static const EGLint premul_argb_cfg_attribs[] = {
1831                 EGL_SURFACE_TYPE,
1832                         EGL_WINDOW_BIT | EGL_PIXMAP_BIT |
1833                         EGL_VG_ALPHA_FORMAT_PRE_BIT,
1834                 EGL_RED_SIZE, 1,
1835                 EGL_GREEN_SIZE, 1,
1836                 EGL_BLUE_SIZE, 1,
1837                 EGL_ALPHA_SIZE, 1,
1838                 EGL_DEPTH_SIZE, 1,
1839                 EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
1840                 EGL_NONE
1841         };
1842
1843         static const EGLint rgb_cfg_attribs[] = {
1844                 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PIXMAP_BIT,
1845                 EGL_RED_SIZE, 1,
1846                 EGL_GREEN_SIZE, 1,
1847                 EGL_BLUE_SIZE, 1,
1848                 EGL_ALPHA_SIZE, 0,
1849                 EGL_DEPTH_SIZE, 1,
1850                 EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
1851                 EGL_NONE
1852         };
1853
1854         d->dpy = eglGetDisplay(d->display);
1855         if (!eglInitialize(d->dpy, &major, &minor)) {
1856                 fprintf(stderr, "failed to initialize display\n");
1857                 return -1;
1858         }
1859
1860         if (!eglBindAPI(EGL_OPENGL_API)) {
1861                 fprintf(stderr, "failed to bind api EGL_OPENGL_API\n");
1862                 return -1;
1863         }
1864
1865         if (!eglChooseConfig(d->dpy, premul_argb_cfg_attribs,
1866                              &d->premultiplied_argb_config, 1, &n) || n != 1) {
1867                 fprintf(stderr, "failed to choose premul argb config\n");
1868                 return -1;
1869         }
1870
1871         if (!eglChooseConfig(d->dpy, rgb_cfg_attribs,
1872                              &d->rgb_config, 1, &n) || n != 1) {
1873                 fprintf(stderr, "failed to choose rgb config\n");
1874                 return -1;
1875         }
1876
1877         d->ctx = eglCreateContext(d->dpy, d->rgb_config, EGL_NO_CONTEXT, NULL);
1878         if (d->ctx == NULL) {
1879                 fprintf(stderr, "failed to create context\n");
1880                 return -1;
1881         }
1882
1883         if (!eglMakeCurrent(d->dpy, NULL, NULL, d->ctx)) {
1884                 fprintf(stderr, "failed to make context current\n");
1885                 return -1;
1886         }
1887
1888 #ifdef HAVE_CAIRO_EGL
1889         d->device = cairo_egl_device_create(d->dpy, d->ctx);
1890         if (cairo_device_status(d->device) != CAIRO_STATUS_SUCCESS) {
1891                 fprintf(stderr, "failed to get cairo egl device\n");
1892                 return -1;
1893         }
1894 #endif
1895
1896         return 0;
1897 }
1898
1899 struct display *
1900 display_create(int *argc, char **argv[], const GOptionEntry *option_entries)
1901 {
1902         struct display *d;
1903         GOptionContext *context;
1904         GOptionGroup *xkb_option_group;
1905         GError *error;
1906
1907         g_type_init();
1908
1909         context = g_option_context_new(NULL);
1910         if (option_entries)
1911                 g_option_context_add_main_entries(context, option_entries, "Wayland View");
1912
1913         xkb_option_group = g_option_group_new("xkb",
1914                                               "Keyboard options",
1915                                               "Show all XKB options",
1916                                               NULL, NULL);
1917         g_option_group_add_entries(xkb_option_group, xkb_option_entries);
1918         g_option_context_add_group (context, xkb_option_group);
1919
1920         if (!g_option_context_parse(context, argc, argv, &error)) {
1921                 fprintf(stderr, "option parsing failed: %s\n", error->message);
1922                 exit(EXIT_FAILURE);
1923         }
1924
1925         g_option_context_free(context);
1926
1927         d = malloc(sizeof *d);
1928         if (d == NULL)
1929                 return NULL;
1930
1931         memset(d, 0, sizeof *d);
1932
1933         d->display = wl_display_connect(NULL);
1934         if (d->display == NULL) {
1935                 fprintf(stderr, "failed to create display: %m\n");
1936                 return NULL;
1937         }
1938
1939         wl_list_init(&d->input_list);
1940
1941         /* Set up listener so we'll catch all events. */
1942         wl_display_add_global_listener(d->display,
1943                                        display_handle_global, d);
1944
1945         /* Process connection events. */
1946         wl_display_iterate(d->display, WL_DISPLAY_READABLE);
1947         if (init_egl(d) < 0)
1948                 return NULL;
1949
1950         d->image_target_texture_2d =
1951                 (void *) eglGetProcAddress("glEGLImageTargetTexture2DOES");
1952         d->create_image = (void *) eglGetProcAddress("eglCreateImageKHR");
1953         d->destroy_image = (void *) eglGetProcAddress("eglDestroyImageKHR");
1954
1955         create_pointer_surfaces(d);
1956
1957         display_render_frame(d);
1958
1959         d->loop = g_main_loop_new(NULL, FALSE);
1960         d->source = wl_glib_source_new(d->display);
1961         g_source_attach(d->source, NULL);
1962
1963         wl_list_init(&d->window_list);
1964
1965         init_xkb(d);
1966
1967         return d;
1968 }
1969
1970 struct wl_display *
1971 display_get_display(struct display *display)
1972 {
1973         return display->display;
1974 }
1975
1976 struct wl_compositor *
1977 display_get_compositor(struct display *display)
1978 {
1979         return display->compositor;
1980 }
1981
1982 EGLDisplay
1983 display_get_egl_display(struct display *d)
1984 {
1985         return d->dpy;
1986 }
1987
1988 EGLConfig
1989 display_get_egl_config(struct display *d)
1990 {
1991         return d->rgb_config;
1992 }
1993
1994 struct wl_shell *
1995 display_get_shell(struct display *display)
1996 {
1997         return display->shell;
1998 }
1999
2000 void
2001 display_acquire_window_surface(struct display *display,
2002                                struct window *window,
2003                                EGLContext ctx)
2004 {
2005 #ifdef HAVE_CAIRO_EGL
2006         struct egl_window_surface_data *data;
2007
2008         if (!window->cairo_surface)
2009                 return;
2010
2011         if (!ctx)
2012                 ctx = display->ctx;
2013
2014         data = cairo_surface_get_user_data(window->cairo_surface,
2015                                            &surface_data_key);
2016
2017         cairo_device_acquire(display->device);
2018         if (!eglMakeCurrent(display->dpy, data->surf, data->surf, ctx))
2019                 fprintf(stderr, "failed to make surface current\n");
2020 #endif
2021 }
2022
2023 void
2024 display_release(struct display *display)
2025 {
2026         if (!eglMakeCurrent(display->dpy, NULL, NULL, display->ctx))
2027                 fprintf(stderr, "failed to make context current\n");
2028         cairo_device_release(display->device);
2029 }
2030
2031 void
2032 display_run(struct display *d)
2033 {
2034         g_main_loop_run(d->loop);
2035 }