9d5c9d1e7328e45f1e9c3eaf57edc89d02ae46d0
[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 <xf86drm.h>
38 #include <sys/mman.h>
39
40 #define EGL_EGLEXT_PROTOTYPES 1
41 #define GL_GLEXT_PROTOTYPES 1
42 #include <GL/gl.h>
43 #include <EGL/egl.h>
44 #include <EGL/eglext.h>
45
46 #ifdef HAVE_CAIRO_EGL
47 #include <cairo-gl.h>
48 #endif
49
50 #include <X11/extensions/XKBcommon.h>
51
52 #include <linux/input.h>
53 #include "wayland-util.h"
54 #include "wayland-client.h"
55 #include "wayland-glib.h"
56 #include "cairo-util.h"
57
58 #include "window.h"
59
60 struct display {
61         struct wl_display *display;
62         struct wl_compositor *compositor;
63         struct wl_shell *shell;
64         struct wl_drm *drm;
65         struct wl_shm *shm;
66         struct wl_output *output;
67         struct rectangle screen_allocation;
68         int authenticated;
69         EGLDisplay dpy;
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         display_drag_offer_handler_t drag_offer_handler;
83         display_global_handler_t global_handler;
84 };
85
86 struct window {
87         struct display *display;
88         struct wl_surface *surface;
89         const char *title;
90         struct rectangle allocation, saved_allocation, server_allocation;
91         int resize_edges;
92         int redraw_scheduled;
93         int minimum_width, minimum_height;
94         int margin;
95         int fullscreen;
96         int decoration;
97         struct input *grab_device;
98         struct input *keyboard_device;
99         uint32_t name;
100         enum window_buffer_type buffer_type;
101         int mapped;
102
103         EGLImageKHR *image;
104         cairo_surface_t *cairo_surface, *pending_surface;
105
106         window_resize_handler_t resize_handler;
107         window_redraw_handler_t redraw_handler;
108         window_key_handler_t key_handler;
109         window_button_handler_t button_handler;
110         window_keyboard_focus_handler_t keyboard_focus_handler;
111         window_motion_handler_t motion_handler;
112
113         void *user_data;
114         struct wl_list link;
115 };
116
117 struct input {
118         struct display *display;
119         struct wl_input_device *input_device;
120         struct window *pointer_focus;
121         struct window *keyboard_focus;
122         uint32_t current_pointer_image;
123         uint32_t modifiers;
124         int32_t x, y, sx, sy;
125         struct wl_list link;
126 };
127
128 enum {
129         POINTER_DEFAULT = 100,
130         POINTER_UNSET
131 };
132
133 enum window_location {
134         WINDOW_INTERIOR = 0,
135         WINDOW_RESIZING_TOP = 1,
136         WINDOW_RESIZING_BOTTOM = 2,
137         WINDOW_RESIZING_LEFT = 4,
138         WINDOW_RESIZING_TOP_LEFT = 5,
139         WINDOW_RESIZING_BOTTOM_LEFT = 6,
140         WINDOW_RESIZING_RIGHT = 8,
141         WINDOW_RESIZING_TOP_RIGHT = 9,
142         WINDOW_RESIZING_BOTTOM_RIGHT = 10,
143         WINDOW_RESIZING_MASK = 15,
144         WINDOW_EXTERIOR = 16,
145         WINDOW_TITLEBAR = 17,
146         WINDOW_CLIENT_AREA = 18,
147 };
148
149 const char *option_xkb_layout = "us";
150 const char *option_xkb_variant = "";
151 const char *option_xkb_options = "";
152
153 static const GOptionEntry xkb_option_entries[] = {
154         { "xkb-layout", 0, 0, G_OPTION_ARG_STRING,
155           &option_xkb_layout, "XKB Layout" },
156         { "xkb-variant", 0, 0, G_OPTION_ARG_STRING,
157           &option_xkb_variant, "XKB Variant" },
158         { "xkb-options", 0, 0, G_OPTION_ARG_STRING,
159           &option_xkb_options, "XKB Options" },
160         { NULL }
161 };
162
163 static void
164 rounded_rect(cairo_t *cr, int x0, int y0, int x1, int y1, int radius)
165 {
166         cairo_move_to(cr, x0, y0 + radius);
167         cairo_arc(cr, x0 + radius, y0 + radius, radius, M_PI, 3 * M_PI / 2);
168         cairo_line_to(cr, x1 - radius, y0);
169         cairo_arc(cr, x1 - radius, y0 + radius, radius, 3 * M_PI / 2, 2 * M_PI);
170         cairo_line_to(cr, x1, y1 - radius);
171         cairo_arc(cr, x1 - radius, y1 - radius, radius, 0, M_PI / 2);
172         cairo_line_to(cr, x0 + radius, y1);
173         cairo_arc(cr, x0 + radius, y1 - radius, radius, M_PI / 2, M_PI);
174         cairo_close_path(cr);
175 }
176
177 static const cairo_user_data_key_t surface_data_key;
178 struct surface_data {
179         struct wl_buffer *buffer;
180 };
181
182 #define MULT(_d,c,a,t) \
183         do { t = c * a + 0x7f; _d = ((t >> 8) + t) >> 8; } while (0)
184
185 #ifdef HAVE_CAIRO_EGL
186
187 struct drm_surface_data {
188         struct surface_data data;
189         EGLImageKHR image;
190         GLuint texture;
191         struct display *display;
192 };
193
194 static void
195 drm_surface_data_destroy(void *p)
196 {
197         struct drm_surface_data *data = p;
198         struct display *d = data->display;
199
200         cairo_device_acquire(d->device);
201         glDeleteTextures(1, &data->texture);
202         cairo_device_release(d->device);
203
204         eglDestroyImageKHR(d->dpy, data->image);
205         wl_buffer_destroy(data->data.buffer);
206 }
207
208 EGLImageKHR
209 display_get_image_for_drm_surface(struct display *display,
210                                   cairo_surface_t *surface)
211 {
212         struct drm_surface_data *data;
213
214         data = cairo_surface_get_user_data (surface, &surface_data_key);
215
216         return data->image;
217 }
218
219 static cairo_surface_t *
220 display_create_drm_surface(struct display *display,
221                            struct rectangle *rectangle)
222 {
223         struct drm_surface_data *data;
224         EGLDisplay dpy = display->dpy;
225         cairo_surface_t *surface;
226         struct wl_visual *visual;
227         EGLint name, stride;
228
229         EGLint image_attribs[] = {
230                 EGL_WIDTH,              0,
231                 EGL_HEIGHT,             0,
232                 EGL_DRM_BUFFER_FORMAT_MESA,     EGL_DRM_BUFFER_FORMAT_ARGB32_MESA,
233                 EGL_DRM_BUFFER_USE_MESA,        EGL_DRM_BUFFER_USE_SCANOUT_MESA,
234                 EGL_NONE
235         };
236
237         data = malloc(sizeof *data);
238         if (data == NULL)
239                 return NULL;
240
241         data->display = display;
242
243         image_attribs[1] = rectangle->width;
244         image_attribs[3] = rectangle->height;
245         data->image = eglCreateDRMImageMESA(dpy, image_attribs);
246
247         cairo_device_acquire(display->device);
248         glGenTextures(1, &data->texture);
249         glBindTexture(GL_TEXTURE_2D, data->texture);
250         glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, data->image);
251         cairo_device_release(display->device);
252
253         eglExportDRMImageMESA(display->dpy, data->image, &name, NULL, &stride);
254
255         visual = wl_display_get_premultiplied_argb_visual(display->display);
256         data->data.buffer =
257                 wl_drm_create_buffer(display->drm, name, rectangle->width,
258                                      rectangle->height, stride, visual);
259
260         surface = cairo_gl_surface_create_for_texture(display->device,
261                                                       CAIRO_CONTENT_COLOR_ALPHA,
262                                                       data->texture,
263                                                       rectangle->width,
264                                                       rectangle->height);
265
266         cairo_surface_set_user_data (surface, &surface_data_key,
267                                      data, drm_surface_data_destroy);
268
269         return surface;
270 }
271
272 static cairo_surface_t *
273 display_create_drm_surface_from_file(struct display *display,
274                                      const char *filename,
275                                      struct rectangle *rect)
276 {
277         cairo_surface_t *surface;
278         GdkPixbuf *pixbuf;
279         GError *error = NULL;
280         int stride, i;
281         unsigned char *pixels, *p, *end;
282         struct drm_surface_data *data;
283
284         pixbuf = gdk_pixbuf_new_from_file_at_scale(filename,
285                                                    rect->width, rect->height,
286                                                    FALSE, &error);
287         if (error != NULL)
288                 return NULL;
289
290         if (!gdk_pixbuf_get_has_alpha(pixbuf) ||
291             gdk_pixbuf_get_n_channels(pixbuf) != 4) {
292                 gdk_pixbuf_unref(pixbuf);
293                 return NULL;
294         }
295
296
297         stride = gdk_pixbuf_get_rowstride(pixbuf);
298         pixels = gdk_pixbuf_get_pixels(pixbuf);
299
300         for (i = 0; i < rect->height; i++) {
301                 p = pixels + i * stride;
302                 end = p + rect->width * 4;
303                 while (p < end) {
304                         unsigned int t;
305
306                         MULT(p[0], p[0], p[3], t);
307                         MULT(p[1], p[1], p[3], t);
308                         MULT(p[2], p[2], p[3], t);
309                         p += 4;
310
311                 }
312         }
313
314         surface = display_create_drm_surface(display, rect);
315         data = cairo_surface_get_user_data(surface, &surface_data_key);
316
317         cairo_device_acquire(display->device);
318         glBindTexture(GL_TEXTURE_2D, data->texture);
319         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rect->width, rect->height,
320                         GL_RGBA, GL_UNSIGNED_BYTE, pixels);
321         cairo_device_release(display->device);
322
323         gdk_pixbuf_unref(pixbuf);
324
325         return surface;
326 }
327
328 #endif
329
330 struct wl_buffer *
331 display_get_buffer_for_surface(struct display *display,
332                                cairo_surface_t *surface)
333 {
334         struct surface_data *data;
335
336         data = cairo_surface_get_user_data (surface, &surface_data_key);
337
338         return data->buffer;
339 }
340
341 struct shm_surface_data {
342         struct surface_data data;
343         void *map;
344         size_t length;
345 };
346
347 static void
348 shm_surface_data_destroy(void *p)
349 {
350         struct shm_surface_data *data = p;
351
352         wl_buffer_destroy(data->data.buffer);
353         munmap(data->map, data->length);
354 }
355
356 static cairo_surface_t *
357 display_create_shm_surface(struct display *display,
358                            struct rectangle *rectangle)
359 {
360         struct shm_surface_data *data;
361         cairo_surface_t *surface;
362         struct wl_visual *visual;
363         int stride, fd;
364         char filename[] = "/tmp/wayland-shm-XXXXXX";
365
366         data = malloc(sizeof *data);
367         if (data == NULL)
368                 return NULL;
369
370         stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32,
371                                                 rectangle->width);
372         data->length = stride * rectangle->height;
373         fd = mkstemp(filename);
374         if (fd < 0) {
375                 fprintf(stderr, "open %s failed: %m", filename);
376                 return NULL;
377         }
378         if (ftruncate(fd, data->length) < 0) {
379                 fprintf(stderr, "ftruncate failed: %m");
380                 close(fd);
381                 return NULL;
382         }
383
384         data->map = mmap(NULL, data->length,
385                          PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
386         unlink(filename);
387
388         if (data->map == MAP_FAILED) {
389                 fprintf(stderr, "mmap failed: %m");
390                 close(fd);
391                 return NULL;
392         }
393
394         surface = cairo_image_surface_create_for_data (data->map,
395                                                        CAIRO_FORMAT_ARGB32,
396                                                        rectangle->width,
397                                                        rectangle->height,
398                                                        stride);
399
400         cairo_surface_set_user_data (surface, &surface_data_key,
401                                      data, shm_surface_data_destroy);
402
403         visual = wl_display_get_premultiplied_argb_visual(display->display);
404         data->data.buffer = wl_shm_create_buffer(display->shm,
405                                                  fd,
406                                                  rectangle->width,
407                                                  rectangle->height,
408                                                  stride, visual);
409
410         close(fd);
411
412         return surface;
413 }
414
415 static cairo_surface_t *
416 display_create_shm_surface_from_file(struct display *display,
417                                      const char *filename,
418                                      struct rectangle *rect)
419 {
420         cairo_surface_t *surface;
421         GdkPixbuf *pixbuf;
422         GError *error = NULL;
423         int stride, i;
424         unsigned char *pixels, *p, *end, *dest_data;
425         int dest_stride;
426         uint32_t *d;
427
428         pixbuf = gdk_pixbuf_new_from_file_at_scale(filename,
429                                                    rect->width, rect->height,
430                                                    FALSE, &error);
431         if (error != NULL)
432                 return NULL;
433
434         if (!gdk_pixbuf_get_has_alpha(pixbuf) ||
435             gdk_pixbuf_get_n_channels(pixbuf) != 4) {
436                 gdk_pixbuf_unref(pixbuf);
437                 return NULL;
438         }
439
440         stride = gdk_pixbuf_get_rowstride(pixbuf);
441         pixels = gdk_pixbuf_get_pixels(pixbuf);
442
443         surface = display_create_shm_surface(display, rect);
444         dest_data = cairo_image_surface_get_data (surface);
445         dest_stride = cairo_image_surface_get_stride (surface);
446
447         for (i = 0; i < rect->height; i++) {
448                 d = (uint32_t *) (dest_data + i * dest_stride);
449                 p = pixels + i * stride;
450                 end = p + rect->width * 4;
451                 while (p < end) {
452                         unsigned int t;
453                         unsigned char a, r, g, b;
454
455                         a = p[3];
456                         MULT(r, p[0], a, t);
457                         MULT(g, p[1], a, t);
458                         MULT(b, p[2], a, t);
459                         p += 4;
460                         *d++ = (a << 24) | (r << 16) | (g << 8) | b;
461                 }
462         }
463
464         gdk_pixbuf_unref(pixbuf);
465
466         return surface;
467 }
468
469 cairo_surface_t *
470 display_create_surface(struct display *display,
471                        struct rectangle *rectangle)
472 {
473 #ifdef HAVE_CAIRO_EGL
474         if (display->drm) {
475                 return display_create_drm_surface(display, rectangle);
476         }
477 #endif
478         return display_create_shm_surface(display, rectangle);
479 }
480
481 static cairo_surface_t *
482 display_create_surface_from_file(struct display *display,
483                                  const char *filename,
484                                  struct rectangle *rectangle)
485 {
486 #ifdef HAVE_CAIRO_EGL
487         if (display->drm) {
488                 return display_create_drm_surface_from_file(display, filename, rectangle);
489         }
490 #endif
491         return display_create_shm_surface_from_file(display, filename, rectangle);
492 }
493  static const struct {
494         const char *filename;
495         int hotspot_x, hotspot_y;
496 } pointer_images[] = {
497         { DATADIR "/wayland/bottom_left_corner.png",     6, 30 },
498         { DATADIR "/wayland/bottom_right_corner.png",   28, 28 },
499         { DATADIR "/wayland/bottom_side.png",           16, 20 },
500         { DATADIR "/wayland/grabbing.png",              20, 17 },
501         { DATADIR "/wayland/left_ptr.png",              10,  5 },
502         { DATADIR "/wayland/left_side.png",             10, 20 },
503         { DATADIR "/wayland/right_side.png",            30, 19 },
504         { DATADIR "/wayland/top_left_corner.png",        8,  8 },
505         { DATADIR "/wayland/top_right_corner.png",      26,  8 },
506         { DATADIR "/wayland/top_side.png",              18,  8 },
507         { DATADIR "/wayland/xterm.png",                 15, 15 },
508         { DATADIR "/wayland/hand1.png",                 18, 11 }
509 };
510
511 static void
512 create_pointer_surfaces(struct display *display)
513 {
514         int i, count;
515         const int width = 32, height = 32;
516         struct rectangle rect;
517
518         count = ARRAY_LENGTH(pointer_images);
519         display->pointer_surfaces =
520                 malloc(count * sizeof *display->pointer_surfaces);
521         rect.width = width;
522         rect.height = height;
523         for (i = 0; i < count; i++) {
524                 display->pointer_surfaces[i] =
525                         display_create_surface_from_file(display,
526                                                          pointer_images[i].filename,
527                                                          &rect);
528         }
529
530 }
531
532 cairo_surface_t *
533 display_get_pointer_surface(struct display *display, int pointer,
534                             int *width, int *height,
535                             int *hotspot_x, int *hotspot_y)
536 {
537         cairo_surface_t *surface;
538
539         surface = display->pointer_surfaces[pointer];
540 #if HAVE_CAIRO_EGL
541         *width = cairo_gl_surface_get_width(surface);
542         *height = cairo_gl_surface_get_height(surface);
543 #else
544         *width = cairo_image_surface_get_width(surface);
545         *height = cairo_image_surface_get_height(surface);
546 #endif
547         *hotspot_x = pointer_images[pointer].hotspot_x;
548         *hotspot_y = pointer_images[pointer].hotspot_y;
549
550         return cairo_surface_reference(surface);
551 }
552
553
554 static void
555 window_attach_surface(struct window *window);
556
557 static void
558 free_surface(void *data)
559 {
560         struct window *window = data;
561
562         cairo_surface_destroy(window->pending_surface);
563         window->pending_surface = NULL;
564         if (window->cairo_surface)
565                 window_attach_surface(window);
566 }
567
568 static void
569 window_attach_surface(struct window *window)
570 {
571         struct display *display = window->display;
572         struct wl_buffer *buffer;
573         int32_t x, y;
574
575         if (window->pending_surface != NULL)
576                 return;
577
578         window->pending_surface = window->cairo_surface;
579         window->cairo_surface = NULL;
580
581         buffer = display_get_buffer_for_surface(display,
582                                                 window->pending_surface);
583         if (window->resize_edges & WINDOW_RESIZING_LEFT)
584                 x = window->server_allocation.width -
585                         window->allocation.width;
586         else
587                 x = 0;
588
589         if (window->resize_edges & WINDOW_RESIZING_TOP)
590                 y = window->server_allocation.height -
591                         window->allocation.height;
592         else
593                 y = 0;
594
595         window->server_allocation = window->allocation;
596         window->resize_edges = 0;
597         wl_surface_attach(window->surface, buffer, x, y);
598         wl_display_sync_callback(display->display, free_surface, window);
599
600         if (!window->mapped) {
601                 wl_surface_map_toplevel(window->surface);
602                 window->mapped = 1;
603         }
604
605         wl_surface_damage(window->surface, 0, 0,
606                           window->allocation.width,
607                           window->allocation.height);
608 }
609
610 void
611 window_flush(struct window *window)
612 {
613        if (window->cairo_surface)
614                window_attach_surface(window);
615 }
616
617 void
618 window_set_surface(struct window *window, cairo_surface_t *surface)
619 {
620         cairo_surface_reference(surface);
621
622         if (window->cairo_surface != NULL)
623                 cairo_surface_destroy(window->cairo_surface);
624
625         window->cairo_surface = surface;
626 }
627
628 void
629 window_create_surface(struct window *window)
630 {
631         cairo_surface_t *surface;
632
633         switch (window->buffer_type) {
634 #ifdef HAVE_CAIRO_EGL
635         case WINDOW_BUFFER_TYPE_DRM:
636                 surface = display_create_surface(window->display,
637                                                  &window->allocation);
638                 break;
639 #endif
640         case WINDOW_BUFFER_TYPE_SHM:
641                 surface = display_create_shm_surface(window->display,
642                                                      &window->allocation);
643                 break;
644         default:
645                 surface = NULL;
646                 break;
647         }
648
649         window_set_surface(window, surface);
650         cairo_surface_destroy(surface);
651 }
652
653 static void
654 window_draw_decorations(struct window *window)
655 {
656         cairo_t *cr;
657         cairo_text_extents_t extents;
658         cairo_pattern_t *outline, *bright, *dim;
659         cairo_surface_t *frame;
660         int width, height, shadow_dx = 3, shadow_dy = 3;
661
662         window_create_surface(window);
663
664         width = window->allocation.width;
665         height = window->allocation.height;
666
667         outline = cairo_pattern_create_rgb(0.1, 0.1, 0.1);
668         bright = cairo_pattern_create_rgb(0.8, 0.8, 0.8);
669         dim = cairo_pattern_create_rgb(0.4, 0.4, 0.4);
670
671         cr = cairo_create(window->cairo_surface);
672
673         cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
674         cairo_set_source_rgba(cr, 0, 0, 0, 0);
675         cairo_paint(cr);
676
677         cairo_set_source_rgba(cr, 0, 0, 0, 0.6);
678         tile_mask(cr, window->display->shadow,
679                   shadow_dx, shadow_dy, width, height,
680                   window->margin + 10 - shadow_dx,
681                   window->margin + 10 - shadow_dy);
682
683         if (window->keyboard_device)
684                 frame = window->display->active_frame;
685         else
686                 frame = window->display->inactive_frame;
687
688         tile_source(cr, frame, 0, 0, width, height,
689                     window->margin + 10, window->margin + 50);
690
691         cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
692         cairo_set_font_size(cr, 14);
693         cairo_text_extents(cr, window->title, &extents);
694         cairo_move_to(cr, (width - extents.width) / 2, 32 - extents.y_bearing);
695         cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
696         cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
697         cairo_set_line_width (cr, 4);
698         if (window->keyboard_device)
699                 cairo_set_source_rgb(cr, 0, 0, 0);
700         else
701                 cairo_set_source_rgb(cr, 0.8, 0.8, 0.8);
702         cairo_show_text(cr, window->title);
703
704         cairo_destroy(cr);
705
706         cairo_device_flush (window->display->device);
707 }
708
709 void
710 display_flush_cairo_device(struct display *display)
711 {
712         cairo_device_flush (display->device);
713 }
714
715 void
716 window_draw(struct window *window)
717 {
718         if (window->fullscreen || !window->decoration)
719                 window_create_surface(window);
720         else
721                 window_draw_decorations(window);
722 }
723
724 cairo_surface_t *
725 window_get_surface(struct window *window)
726 {
727         return cairo_surface_reference(window->cairo_surface);
728 }
729
730 static int
731 get_pointer_location(struct window *window, int32_t x, int32_t y)
732 {
733         int vlocation, hlocation, location;
734         const int grip_size = 8;
735
736         if (!window->decoration)
737                 return WINDOW_CLIENT_AREA;
738
739         if (x < window->margin)
740                 hlocation = WINDOW_EXTERIOR;
741         else if (window->margin <= x && x < window->margin + grip_size)
742                 hlocation = WINDOW_RESIZING_LEFT;
743         else if (x < window->allocation.width - window->margin - grip_size)
744                 hlocation = WINDOW_INTERIOR;
745         else if (x < window->allocation.width - window->margin)
746                 hlocation = WINDOW_RESIZING_RIGHT;
747         else
748                 hlocation = WINDOW_EXTERIOR;
749
750         if (y < window->margin)
751                 vlocation = WINDOW_EXTERIOR;
752         else if (window->margin <= y && y < window->margin + grip_size)
753                 vlocation = WINDOW_RESIZING_TOP;
754         else if (y < window->allocation.height - window->margin - grip_size)
755                 vlocation = WINDOW_INTERIOR;
756         else if (y < window->allocation.height - window->margin)
757                 vlocation = WINDOW_RESIZING_BOTTOM;
758         else
759                 vlocation = WINDOW_EXTERIOR;
760
761         location = vlocation | hlocation;
762         if (location & WINDOW_EXTERIOR)
763                 location = WINDOW_EXTERIOR;
764         if (location == WINDOW_INTERIOR && y < window->margin + 50)
765                 location = WINDOW_TITLEBAR;
766         else if (location == WINDOW_INTERIOR)
767                 location = WINDOW_CLIENT_AREA;
768
769         return location;
770 }
771
772 static void
773 set_pointer_image(struct input *input, uint32_t time, int pointer)
774 {
775         struct display *display = input->display;
776         struct wl_buffer *buffer;
777         cairo_surface_t *surface;
778         int location;
779
780         location = get_pointer_location(input->pointer_focus,
781                                         input->sx, input->sy);
782         switch (location) {
783         case WINDOW_RESIZING_TOP:
784                 pointer = POINTER_TOP;
785                 break;
786         case WINDOW_RESIZING_BOTTOM:
787                 pointer = POINTER_BOTTOM;
788                 break;
789         case WINDOW_RESIZING_LEFT:
790                 pointer = POINTER_LEFT;
791                 break;
792         case WINDOW_RESIZING_RIGHT:
793                 pointer = POINTER_RIGHT;
794                 break;
795         case WINDOW_RESIZING_TOP_LEFT:
796                 pointer = POINTER_TOP_LEFT;
797                 break;
798         case WINDOW_RESIZING_TOP_RIGHT:
799                 pointer = POINTER_TOP_RIGHT;
800                 break;
801         case WINDOW_RESIZING_BOTTOM_LEFT:
802                 pointer = POINTER_BOTTOM_LEFT;
803                 break;
804         case WINDOW_RESIZING_BOTTOM_RIGHT:
805                 pointer = POINTER_BOTTOM_RIGHT;
806                 break;
807         case WINDOW_EXTERIOR:
808         case WINDOW_TITLEBAR:
809                 if (input->current_pointer_image == POINTER_DEFAULT)
810                         return;
811
812                 wl_input_device_attach(input->input_device, time, NULL, 0, 0);
813                 input->current_pointer_image = POINTER_DEFAULT;
814                 return;
815         default:
816                 break;
817         }
818
819         if (pointer == input->current_pointer_image)
820                 return;
821
822         input->current_pointer_image = pointer;
823         surface = display->pointer_surfaces[pointer];
824         buffer = display_get_buffer_for_surface(display, surface);
825         wl_input_device_attach(input->input_device, time, buffer,
826                                pointer_images[pointer].hotspot_x,
827                                pointer_images[pointer].hotspot_y);
828 }
829
830 static void
831 window_handle_motion(void *data, struct wl_input_device *input_device,
832                      uint32_t time,
833                      int32_t x, int32_t y, int32_t sx, int32_t sy)
834 {
835         struct input *input = data;
836         struct window *window = input->pointer_focus;
837         int location, pointer = POINTER_LEFT_PTR;
838
839         input->x = x;
840         input->y = y;
841         input->sx = sx;
842         input->sy = sy;
843
844         location = get_pointer_location(window, input->sx, input->sy);
845
846         if (window->motion_handler)
847                 pointer = (*window->motion_handler)(window, input, time,
848                                                     x, y, sx, sy,
849                                                     window->user_data);
850
851         set_pointer_image(input, time, pointer);
852 }
853
854 static void
855 window_handle_button(void *data,
856                      struct wl_input_device *input_device,
857                      uint32_t time, uint32_t button, uint32_t state)
858 {
859         struct input *input = data;
860         struct window *window = input->pointer_focus;
861         int location;
862
863         location = get_pointer_location(window, input->sx, input->sy);
864
865         if (button == BTN_LEFT && state == 1) {
866                 switch (location) {
867                 case WINDOW_TITLEBAR:
868                         wl_shell_move(window->display->shell,
869                                       window->surface, input_device, time);
870                         break;
871                 case WINDOW_RESIZING_TOP:
872                 case WINDOW_RESIZING_BOTTOM:
873                 case WINDOW_RESIZING_LEFT:
874                 case WINDOW_RESIZING_RIGHT:
875                 case WINDOW_RESIZING_TOP_LEFT:
876                 case WINDOW_RESIZING_TOP_RIGHT:
877                 case WINDOW_RESIZING_BOTTOM_LEFT:
878                 case WINDOW_RESIZING_BOTTOM_RIGHT:
879                         wl_shell_resize(window->display->shell,
880                                         window->surface, input_device, time,
881                                         location);
882                         break;
883                 case WINDOW_CLIENT_AREA:
884                         if (window->button_handler)
885                                 (*window->button_handler)(window,
886                                                           input, time,
887                                                           button, state,
888                                                           window->user_data);
889                         break;
890                 }
891         } else {
892                 if (window->button_handler)
893                         (*window->button_handler)(window,
894                                                   input, time,
895                                                   button, state,
896                                                   window->user_data);
897         }
898 }
899
900 static void
901 window_handle_key(void *data, struct wl_input_device *input_device,
902                   uint32_t time, uint32_t key, uint32_t state)
903 {
904         struct input *input = data;
905         struct window *window = input->keyboard_focus;
906         struct display *d = window->display;
907         uint32_t code, sym, level;
908
909         code = key + d->xkb->min_key_code;
910         if (window->keyboard_device != input)
911                 return;
912
913         level = 0;
914         if (input->modifiers & WINDOW_MODIFIER_SHIFT &&
915             XkbKeyGroupWidth(d->xkb, code, 0) > 1)
916                 level = 1;
917
918         sym = XkbKeySymEntry(d->xkb, code, level, 0);
919
920         if (state)
921                 input->modifiers |= d->xkb->map->modmap[code];
922         else
923                 input->modifiers &= ~d->xkb->map->modmap[code];
924
925         if (window->key_handler)
926                 (*window->key_handler)(window, key, sym, state,
927                                        input->modifiers, window->user_data);
928 }
929
930 static void
931 window_handle_pointer_focus(void *data,
932                             struct wl_input_device *input_device,
933                             uint32_t time, struct wl_surface *surface,
934                             int32_t x, int32_t y, int32_t sx, int32_t sy)
935 {
936         struct input *input = data;
937         struct window *window;
938         int pointer;
939
940         if (surface) {
941                 input->pointer_focus = wl_surface_get_user_data(surface);
942                 window = input->pointer_focus;
943
944                 pointer = POINTER_LEFT_PTR;
945                 if (window->motion_handler)
946                         pointer = (*window->motion_handler)(window,
947                                                             input, time,
948                                                             x, y, sx, sy,
949                                                             window->user_data);
950
951                 set_pointer_image(input, time, pointer);
952         } else {
953                 input->pointer_focus = NULL;
954                 input->current_pointer_image = POINTER_UNSET;
955         }
956 }
957
958 static void
959 window_handle_keyboard_focus(void *data,
960                              struct wl_input_device *input_device,
961                              uint32_t time,
962                              struct wl_surface *surface,
963                              struct wl_array *keys)
964 {
965         struct input *input = data;
966         struct window *window = input->keyboard_focus;
967         struct display *d = input->display;
968         uint32_t *k, *end;
969
970         window = input->keyboard_focus;
971         if (window) {
972                 window->keyboard_device = NULL;
973                 if (window->keyboard_focus_handler)
974                         (*window->keyboard_focus_handler)(window, NULL,
975                                                           window->user_data);
976         }
977
978         if (surface)
979                 input->keyboard_focus = wl_surface_get_user_data(surface);
980         else
981                 input->keyboard_focus = NULL;
982
983         end = keys->data + keys->size;
984         for (k = keys->data; k < end; k++)
985                 input->modifiers |= d->xkb->map->modmap[*k];
986
987         window = input->keyboard_focus;
988         if (window) {
989                 window->keyboard_device = input;
990                 if (window->keyboard_focus_handler)
991                         (*window->keyboard_focus_handler)(window,
992                                                           window->keyboard_device,
993                                                           window->user_data);
994         }
995 }
996
997 static const struct wl_input_device_listener input_device_listener = {
998         window_handle_motion,
999         window_handle_button,
1000         window_handle_key,
1001         window_handle_pointer_focus,
1002         window_handle_keyboard_focus,
1003 };
1004
1005 void
1006 input_get_position(struct input *input, int32_t *x, int32_t *y)
1007 {
1008         *x = input->sx;
1009         *y = input->sy;
1010 }
1011
1012 struct wl_input_device *
1013 input_get_input_device(struct input *input)
1014 {
1015         return input->input_device;
1016 }
1017
1018 struct wl_drag *
1019 window_create_drag(struct window *window)
1020 {
1021         cairo_device_flush (window->display->device);
1022
1023         return wl_shell_create_drag(window->display->shell);
1024 }
1025
1026 void
1027 window_move(struct window *window, struct input *input, uint32_t time)
1028 {
1029         wl_shell_move(window->display->shell,
1030                       window->surface, input->input_device, time);
1031 }
1032
1033 void
1034 window_activate_drag(struct wl_drag *drag, struct window *window,
1035                      struct input *input, uint32_t time)
1036 {
1037         wl_drag_activate(drag, window->surface, input->input_device, time);
1038 }
1039
1040 static void
1041 handle_configure(void *data, struct wl_shell *shell,
1042                  uint32_t time, uint32_t edges,
1043                  struct wl_surface *surface, int32_t width, int32_t height)
1044 {
1045         struct window *window = wl_surface_get_user_data(surface);
1046         int32_t child_width, child_height;
1047
1048         if (window->resize_handler) {
1049                 child_width = width - 20 - window->margin * 2;
1050                 child_height = height - 60 - window->margin * 2;
1051
1052                 (*window->resize_handler)(window,
1053                                           child_width, child_height,
1054                                           window->user_data);
1055         } else {
1056                 window->resize_edges = edges;
1057                 window->allocation.width = width;
1058                 window->allocation.height = height;
1059
1060                 if (window->redraw_handler)
1061                         window_schedule_redraw(window);
1062         }
1063 }
1064
1065 static const struct wl_shell_listener shell_listener = {
1066         handle_configure,
1067 };
1068
1069 void
1070 window_get_child_allocation(struct window *window,
1071                             struct rectangle *allocation)
1072 {
1073         if (window->fullscreen && !window->decoration) {
1074                 *allocation = window->allocation;
1075         } else {
1076                 allocation->x = window->margin + 10;
1077                 allocation->y = window->margin + 50;
1078                 allocation->width =
1079                         window->allocation.width - 20 - window->margin * 2;
1080                 allocation->height =
1081                         window->allocation.height - 60 - window->margin * 2;
1082         }
1083 }
1084
1085 void
1086 window_set_child_size(struct window *window, int32_t width, int32_t height)
1087 {
1088         if (!window->fullscreen) {
1089                 window->allocation.width = width + 20 + window->margin * 2;
1090                 window->allocation.height = height + 60 + window->margin * 2;
1091         }
1092 }
1093
1094 void
1095 window_copy_image(struct window *window,
1096                   struct rectangle *rectangle, EGLImageKHR image)
1097 {
1098         /* set image as read buffer, copy pixels or something... */
1099 }
1100
1101 void
1102 window_copy_surface(struct window *window,
1103                     struct rectangle *rectangle,
1104                     cairo_surface_t *surface)
1105 {
1106         cairo_t *cr;
1107
1108         cr = cairo_create (window->cairo_surface);
1109
1110         cairo_set_source_surface (cr,
1111                                   surface,
1112                                   rectangle->x, rectangle->y);
1113
1114         cairo_paint (cr);
1115         cairo_destroy (cr);
1116 }
1117
1118 static gboolean
1119 idle_redraw(void *data)
1120 {
1121         struct window *window = data;
1122
1123         window->redraw_handler(window, window->user_data);
1124
1125         window->redraw_scheduled = 0;
1126
1127         return FALSE;
1128 }
1129
1130 void
1131 window_schedule_redraw(struct window *window)
1132 {
1133         if (!window->redraw_scheduled) {
1134                 g_idle_add(idle_redraw, window);
1135                 window->redraw_scheduled = 1;
1136         }
1137 }
1138
1139 void
1140 window_set_fullscreen(struct window *window, int fullscreen)
1141 {
1142         window->fullscreen = fullscreen;
1143         if (window->fullscreen) {
1144                 window->saved_allocation = window->allocation;
1145                 window->allocation = window->display->screen_allocation;
1146         } else {
1147                 window->allocation = window->saved_allocation;
1148         }
1149 }
1150
1151 void
1152 window_set_decoration(struct window *window, int decoration)
1153 {
1154         window->decoration = decoration;
1155 }
1156
1157 void
1158 window_set_user_data(struct window *window, void *data)
1159 {
1160         window->user_data = data;
1161 }
1162
1163 void *
1164 window_get_user_data(struct window *window)
1165 {
1166         return window->user_data;
1167 }
1168
1169 void
1170 window_set_resize_handler(struct window *window,
1171                           window_resize_handler_t handler)
1172 {
1173         window->resize_handler = handler;
1174 }
1175
1176 void
1177 window_set_redraw_handler(struct window *window,
1178                           window_redraw_handler_t handler)
1179 {
1180         window->redraw_handler = handler;
1181 }
1182
1183 void
1184 window_set_key_handler(struct window *window,
1185                        window_key_handler_t handler)
1186 {
1187         window->key_handler = handler;
1188 }
1189
1190 void
1191 window_set_button_handler(struct window *window,
1192                           window_button_handler_t handler)
1193 {
1194         window->button_handler = handler;
1195 }
1196
1197 void
1198 window_set_motion_handler(struct window *window,
1199                           window_motion_handler_t handler)
1200 {
1201         window->motion_handler = handler;
1202 }
1203
1204 void
1205 window_set_keyboard_focus_handler(struct window *window,
1206                                   window_keyboard_focus_handler_t handler)
1207 {
1208         window->keyboard_focus_handler = handler;
1209 }
1210
1211 void
1212 window_damage(struct window *window, int32_t x, int32_t y,
1213               int32_t width, int32_t height)
1214 {
1215         wl_surface_damage(window->surface, x, y, width, height);
1216 }
1217
1218 struct window *
1219 window_create(struct display *display, const char *title,
1220               int32_t width, int32_t height)
1221 {
1222         struct window *window;
1223
1224         window = malloc(sizeof *window);
1225         if (window == NULL)
1226                 return NULL;
1227
1228         memset(window, 0, sizeof *window);
1229         window->display = display;
1230         window->title = strdup(title);
1231         window->surface = wl_compositor_create_surface(display->compositor);
1232         window->allocation.x = 0;
1233         window->allocation.y = 0;
1234         window->allocation.width = width;
1235         window->allocation.height = height;
1236         window->saved_allocation = window->allocation;
1237         window->margin = 16;
1238         window->decoration = 1;
1239
1240         if (display->drm)
1241                 window->buffer_type = WINDOW_BUFFER_TYPE_DRM;
1242         else
1243                 window->buffer_type = WINDOW_BUFFER_TYPE_SHM;
1244
1245         wl_surface_set_user_data(window->surface, window);
1246         wl_list_insert(display->window_list.prev, &window->link);
1247
1248         return window;
1249 }
1250
1251 void
1252 window_set_buffer_type(struct window *window, enum window_buffer_type type)
1253 {
1254         window->buffer_type = type;
1255 }
1256
1257 static void
1258 drm_handle_device(void *data, struct wl_drm *drm, const char *device)
1259 {
1260         struct display *d = data;
1261
1262         d->device_name = strdup(device);
1263 }
1264
1265 static void drm_handle_authenticated(void *data, struct wl_drm *drm)
1266 {
1267         struct display *d = data;
1268
1269         d->authenticated = 1;
1270 }
1271
1272 static const struct wl_drm_listener drm_listener = {
1273         drm_handle_device,
1274         drm_handle_authenticated
1275 };
1276
1277 static void
1278 display_handle_geometry(void *data,
1279                         struct wl_output *output,
1280                         int32_t x, int32_t y, int32_t width, int32_t height)
1281 {
1282         struct display *display = data;
1283
1284         display->screen_allocation.x = x;
1285         display->screen_allocation.y = y;
1286         display->screen_allocation.width = width;
1287         display->screen_allocation.height = height;
1288 }
1289
1290 static const struct wl_output_listener output_listener = {
1291         display_handle_geometry,
1292 };
1293
1294 static void
1295 display_add_input(struct display *d, uint32_t id)
1296 {
1297         struct input *input;
1298
1299         input = malloc(sizeof *input);
1300         if (input == NULL)
1301                 return;
1302
1303         memset(input, 0, sizeof *input);
1304         input->display = d;
1305         input->input_device = wl_input_device_create(d->display, id);
1306         input->pointer_focus = NULL;
1307         input->keyboard_focus = NULL;
1308         wl_list_insert(d->input_list.prev, &input->link);
1309
1310         wl_input_device_add_listener(input->input_device,
1311                                      &input_device_listener, input);
1312         wl_input_device_set_user_data(input->input_device, input);
1313 }
1314
1315 static void
1316 display_handle_global(struct wl_display *display, uint32_t id,
1317                       const char *interface, uint32_t version, void *data)
1318 {
1319         struct display *d = data;
1320         struct wl_drag_offer *offer;
1321
1322         if (strcmp(interface, "compositor") == 0) {
1323                 d->compositor = wl_compositor_create(display, id);
1324         } else if (strcmp(interface, "output") == 0) {
1325                 d->output = wl_output_create(display, id);
1326                 wl_output_add_listener(d->output, &output_listener, d);
1327         } else if (strcmp(interface, "input_device") == 0) {
1328                 display_add_input(d, id);
1329         } else if (strcmp(interface, "shell") == 0) {
1330                 d->shell = wl_shell_create(display, id);
1331                 wl_shell_add_listener(d->shell, &shell_listener, d);
1332         } else if (strcmp(interface, "drm") == 0) {
1333                 d->drm = wl_drm_create(display, id);
1334                 wl_drm_add_listener(d->drm, &drm_listener, d);
1335         } else if (strcmp(interface, "shm") == 0) {
1336                 d->shm = wl_shm_create(display, id);
1337         } else if (strcmp(interface, "drag_offer") == 0) {
1338                 if (d->drag_offer_handler) {
1339                         offer = wl_drag_offer_create(display, id);
1340                         d->drag_offer_handler(offer, d);
1341                 }
1342         } else if (d->global_handler) {
1343                 d->global_handler(d, interface, version);
1344         }
1345 }
1346
1347 static void
1348 display_render_frame(struct display *d)
1349 {
1350         int radius = 8;
1351         cairo_t *cr;
1352
1353         d->shadow = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 128, 128);
1354         cr = cairo_create(d->shadow);
1355         cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
1356         cairo_set_source_rgba(cr, 0, 0, 0, 1);
1357         rounded_rect(cr, 16, 16, 112, 112, radius);
1358         cairo_fill(cr);
1359         cairo_destroy(cr);
1360         blur_surface(d->shadow, 64);
1361
1362         d->active_frame =
1363                 cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 128, 128);
1364         cr = cairo_create(d->active_frame);
1365         cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
1366         cairo_set_source_rgba(cr, 0.8, 0.8, 0.4, 1);
1367         rounded_rect(cr, 16, 16, 112, 112, radius);
1368         cairo_fill(cr);
1369         cairo_destroy(cr);
1370
1371         d->inactive_frame =
1372                 cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 128, 128);
1373         cr = cairo_create(d->inactive_frame);
1374         cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
1375         cairo_set_source_rgba(cr, 0.6, 0.6, 0.6, 1);
1376         rounded_rect(cr, 16, 16, 112, 112, radius);
1377         cairo_fill(cr);
1378         cairo_destroy(cr);
1379 }
1380
1381 static void
1382 init_xkb(struct display *d)
1383 {
1384         struct xkb_rule_names names;
1385
1386         names.rules = "evdev";
1387         names.model = "pc105";
1388         names.layout = option_xkb_layout;
1389         names.variant = option_xkb_variant;
1390         names.options = option_xkb_options;
1391
1392         d->xkb = xkb_compile_keymap_from_rules(&names);
1393         if (!d->xkb) {
1394                 fprintf(stderr, "Failed to compile keymap\n");
1395                 exit(1);
1396         }
1397 }
1398
1399 static int
1400 init_drm(struct display *d)
1401 {
1402         EGLint major, minor;
1403         int fd;
1404         drm_magic_t magic;
1405
1406         fd = open(d->device_name, O_RDWR);
1407         if (fd < 0) {
1408                 fprintf(stderr, "drm open failed: %m\n");
1409                 return -1;
1410         }
1411
1412         if (drmGetMagic(fd, &magic)) {
1413                 fprintf(stderr, "DRI2: failed to get drm magic");
1414                 return -1;
1415         }
1416
1417         /* Wait for authenticated event */
1418         wl_drm_authenticate(d->drm, magic);
1419         wl_display_iterate(d->display, WL_DISPLAY_WRITABLE);
1420         while (!d->authenticated)
1421                 wl_display_iterate(d->display, WL_DISPLAY_READABLE);
1422
1423         d->dpy = eglGetDRMDisplayMESA(fd);
1424         if (!eglInitialize(d->dpy, &major, &minor)) {
1425                 fprintf(stderr, "failed to initialize display\n");
1426                 return -1;
1427         }
1428
1429         if (!eglBindAPI(EGL_OPENGL_API)) {
1430                 fprintf(stderr, "failed to bind api EGL_OPENGL_API\n");
1431                 return -1;
1432         }
1433
1434         d->ctx = eglCreateContext(d->dpy, NULL, EGL_NO_CONTEXT, NULL);
1435         if (d->ctx == NULL) {
1436                 fprintf(stderr, "failed to create context\n");
1437                 return -1;
1438         }
1439
1440         if (!eglMakeCurrent(d->dpy, NULL, NULL, d->ctx)) {
1441                 fprintf(stderr, "faile to make context current\n");
1442                 return -1;
1443         }
1444
1445 #ifdef HAVE_CAIRO_EGL
1446         d->device = cairo_egl_device_create(d->dpy, d->ctx);
1447         if (d->device == NULL) {
1448                 fprintf(stderr, "failed to get cairo drm device\n");
1449                 return -1;
1450         }
1451 #endif
1452
1453         return 0;
1454 }
1455
1456 struct display *
1457 display_create(int *argc, char **argv[], const GOptionEntry *option_entries)
1458 {
1459         struct display *d;
1460         GOptionContext *context;
1461         GOptionGroup *xkb_option_group;
1462         GError *error;
1463
1464         g_type_init();
1465
1466         context = g_option_context_new(NULL);
1467         if (option_entries)
1468                 g_option_context_add_main_entries(context, option_entries, "Wayland View");
1469
1470         xkb_option_group = g_option_group_new("xkb",
1471                                               "Keyboard options",
1472                                               "Show all XKB options",
1473                                               NULL, NULL);
1474         g_option_group_add_entries(xkb_option_group, xkb_option_entries);
1475         g_option_context_add_group (context, xkb_option_group);
1476
1477         if (!g_option_context_parse(context, argc, argv, &error)) {
1478                 fprintf(stderr, "option parsing failed: %s\n", error->message);
1479                 exit(EXIT_FAILURE);
1480         }
1481
1482
1483         d = malloc(sizeof *d);
1484         if (d == NULL)
1485                 return NULL;
1486
1487         d->display = wl_display_connect(NULL);
1488         if (d->display == NULL) {
1489                 fprintf(stderr, "failed to create display: %m\n");
1490                 return NULL;
1491         }
1492
1493         wl_list_init(&d->input_list);
1494
1495         /* Set up listener so we'll catch all events. */
1496         wl_display_add_global_listener(d->display,
1497                                        display_handle_global, d);
1498
1499         /* Process connection events. */
1500         wl_display_iterate(d->display, WL_DISPLAY_READABLE);
1501
1502         if (d->device_name && init_drm(d) < 0)
1503                 return NULL;
1504
1505         create_pointer_surfaces(d);
1506
1507         display_render_frame(d);
1508
1509         d->loop = g_main_loop_new(NULL, FALSE);
1510         d->source = wl_glib_source_new(d->display);
1511         g_source_attach(d->source, NULL);
1512
1513         wl_list_init(&d->window_list);
1514
1515         init_xkb(d);
1516
1517         return d;
1518 }
1519
1520 struct wl_display *
1521 display_get_display(struct display *display)
1522 {
1523         return display->display;
1524 }
1525
1526 struct wl_compositor *
1527 display_get_compositor(struct display *display)
1528 {
1529         return display->compositor;
1530 }
1531
1532 EGLDisplay
1533 display_get_egl_display(struct display *d)
1534 {
1535         return d->dpy;
1536 }
1537
1538 void
1539 display_run(struct display *d)
1540 {
1541         g_main_loop_run(d->loop);
1542 }
1543
1544 void
1545 display_set_drag_offer_handler(struct display *display,
1546                                display_drag_offer_handler_t handler)
1547 {
1548         display->drag_offer_handler = handler;
1549 }
1550
1551 void
1552 display_set_global_handler(struct display *display,
1553                            display_global_handler_t handler)
1554 {
1555         display->global_handler = handler;
1556 }