2 * Copyright © 2008 Kristian Høgsberg
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.
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
25 #include "../config.h"
38 #include <gdk-pixbuf/gdk-pixbuf.h>
40 #include <sys/epoll.h>
42 #include <wayland-egl.h>
46 #include <EGL/eglext.h>
52 #include <X11/extensions/XKBcommon.h>
54 #include <linux/input.h>
55 #include <wayland-client.h>
56 #include "cairo-util.h"
61 struct wl_display *display;
62 struct wl_compositor *compositor;
63 struct wl_shell *shell;
65 struct wl_data_device_manager *data_device_manager;
68 EGLConfig premultiplied_argb_config;
71 cairo_device_t *rgb_device;
72 cairo_device_t *argb_device;
76 struct task display_task;
79 struct wl_list deferred_list;
83 struct wl_list window_list;
84 struct wl_list input_list;
85 struct wl_list output_list;
86 cairo_surface_t *active_frame, *inactive_frame, *shadow;
88 cairo_surface_t **pointer_surfaces;
90 PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d;
91 PFNEGLCREATEIMAGEKHRPROC create_image;
92 PFNEGLDESTROYIMAGEKHRPROC destroy_image;
94 display_output_handler_t output_configure_handler;
108 struct display *display;
109 struct window *parent;
110 struct wl_surface *surface;
111 struct wl_shell_surface *shell_surface;
113 struct rectangle allocation, saved_allocation, server_allocation;
116 int redraw_scheduled;
117 struct task redraw_task;
118 int minimum_width, minimum_height;
123 struct input *keyboard_device;
125 enum window_buffer_type buffer_type;
127 cairo_surface_t *cairo_surface, *pending_surface;
129 window_resize_handler_t resize_handler;
130 window_redraw_handler_t redraw_handler;
131 window_key_handler_t key_handler;
132 window_button_handler_t button_handler;
133 window_keyboard_focus_handler_t keyboard_focus_handler;
134 window_motion_handler_t motion_handler;
135 window_enter_handler_t enter_handler;
136 window_leave_handler_t leave_handler;
137 window_widget_focus_handler_t widget_focus_handler;
138 window_data_handler_t data_handler;
139 window_drop_handler_t drop_handler;
140 window_close_handler_t close_handler;
142 struct wl_list widget_list;
143 struct widget *focus_widget;
144 uint32_t widget_grab_button;
154 struct rectangle allocation;
159 struct display *display;
160 struct wl_input_device *input_device;
161 struct window *pointer_focus;
162 struct window *keyboard_focus;
163 uint32_t current_pointer_image;
165 int32_t x, y, sx, sy;
168 struct wl_data_device *data_device;
169 struct data_offer *drag_offer;
170 struct data_offer *selection_offer;
174 struct display *display;
175 struct wl_output *output;
176 struct rectangle allocation;
179 display_output_handler_t destroy_handler;
184 struct window *window;
185 const char **entries;
193 POINTER_DEFAULT = 100,
197 enum window_location {
199 WINDOW_RESIZING_TOP = 1,
200 WINDOW_RESIZING_BOTTOM = 2,
201 WINDOW_RESIZING_LEFT = 4,
202 WINDOW_RESIZING_TOP_LEFT = 5,
203 WINDOW_RESIZING_BOTTOM_LEFT = 6,
204 WINDOW_RESIZING_RIGHT = 8,
205 WINDOW_RESIZING_TOP_RIGHT = 9,
206 WINDOW_RESIZING_BOTTOM_RIGHT = 10,
207 WINDOW_RESIZING_MASK = 15,
208 WINDOW_EXTERIOR = 16,
209 WINDOW_TITLEBAR = 17,
210 WINDOW_CLIENT_AREA = 18,
213 const char *option_xkb_layout = "us";
214 const char *option_xkb_variant = "";
215 const char *option_xkb_options = "";
217 static const GOptionEntry xkb_option_entries[] = {
218 { "xkb-layout", 0, 0, G_OPTION_ARG_STRING,
219 &option_xkb_layout, "XKB Layout" },
220 { "xkb-variant", 0, 0, G_OPTION_ARG_STRING,
221 &option_xkb_variant, "XKB Variant" },
222 { "xkb-options", 0, 0, G_OPTION_ARG_STRING,
223 &option_xkb_options, "XKB Options" },
227 static const cairo_user_data_key_t surface_data_key;
228 struct surface_data {
229 struct wl_buffer *buffer;
232 #define MULT(_d,c,a,t) \
233 do { t = c * a + 0x7f; _d = ((t >> 8) + t) >> 8; } while (0)
235 #ifdef HAVE_CAIRO_EGL
237 struct egl_window_surface_data {
238 struct display *display;
239 struct wl_surface *surface;
240 struct wl_egl_window *window;
245 egl_window_surface_data_destroy(void *p)
247 struct egl_window_surface_data *data = p;
248 struct display *d = data->display;
250 eglDestroySurface(d->dpy, data->surf);
251 wl_egl_window_destroy(data->window);
252 data->surface = NULL;
257 static cairo_surface_t *
258 display_create_egl_window_surface(struct display *display,
259 struct wl_surface *surface,
261 struct rectangle *rectangle)
263 cairo_surface_t *cairo_surface;
264 struct egl_window_surface_data *data;
266 const EGLint *attribs;
267 cairo_device_t *device;
269 static const EGLint premul_attribs[] = {
270 EGL_ALPHA_FORMAT, EGL_ALPHA_FORMAT_PRE,
274 data = malloc(sizeof *data);
278 data->display = display;
279 data->surface = surface;
281 if (flags & SURFACE_OPAQUE) {
282 config = display->rgb_config;
283 device = display->rgb_device;
286 config = display->premultiplied_argb_config;
287 device = display->argb_device;
288 attribs = premul_attribs;
291 data->window = wl_egl_window_create(surface,
295 data->surf = eglCreateWindowSurface(display->dpy, config,
296 data->window, attribs);
298 cairo_surface = cairo_gl_surface_create_for_egl(device,
303 cairo_surface_set_user_data(cairo_surface, &surface_data_key,
304 data, egl_window_surface_data_destroy);
306 return cairo_surface;
309 struct egl_image_surface_data {
310 struct surface_data data;
311 cairo_device_t *device;
314 struct display *display;
315 struct wl_egl_pixmap *pixmap;
319 egl_image_surface_data_destroy(void *p)
321 struct egl_image_surface_data *data = p;
322 struct display *d = data->display;
324 cairo_device_acquire(data->device);
325 glDeleteTextures(1, &data->texture);
326 cairo_device_release(data->device);
328 d->destroy_image(d->dpy, data->image);
329 wl_buffer_destroy(data->data.buffer);
330 wl_egl_pixmap_destroy(data->pixmap);
335 display_get_image_for_egl_image_surface(struct display *display,
336 cairo_surface_t *surface)
338 struct egl_image_surface_data *data;
340 data = cairo_surface_get_user_data (surface, &surface_data_key);
345 static cairo_surface_t *
346 display_create_egl_image_surface(struct display *display,
348 struct rectangle *rectangle)
350 struct egl_image_surface_data *data;
351 EGLDisplay dpy = display->dpy;
352 cairo_surface_t *surface;
353 cairo_content_t content;
355 data = malloc(sizeof *data);
359 data->display = display;
361 data->pixmap = wl_egl_pixmap_create(rectangle->width,
362 rectangle->height, 0);
363 if (data->pixmap == NULL) {
368 if (flags & SURFACE_OPAQUE) {
369 data->device = display->rgb_device;
370 content = CAIRO_CONTENT_COLOR;
372 data->device = display->argb_device;
373 content = CAIRO_CONTENT_COLOR_ALPHA;
376 data->image = display->create_image(dpy, NULL,
377 EGL_NATIVE_PIXMAP_KHR,
378 (EGLClientBuffer) data->pixmap,
380 if (data->image == EGL_NO_IMAGE_KHR) {
381 wl_egl_pixmap_destroy(data->pixmap);
387 wl_egl_pixmap_create_buffer(data->pixmap);
389 cairo_device_acquire(data->device);
390 glGenTextures(1, &data->texture);
391 glBindTexture(GL_TEXTURE_2D, data->texture);
392 display->image_target_texture_2d(GL_TEXTURE_2D, data->image);
393 cairo_device_release(data->device);
395 surface = cairo_gl_surface_create_for_texture(data->device,
401 cairo_surface_set_user_data (surface, &surface_data_key,
402 data, egl_image_surface_data_destroy);
407 static cairo_surface_t *
408 display_create_egl_image_surface_from_file(struct display *display,
409 const char *filename,
410 struct rectangle *rect)
412 cairo_surface_t *surface;
414 GError *error = NULL;
416 unsigned char *pixels, *p, *end;
417 struct egl_image_surface_data *data;
419 pixbuf = gdk_pixbuf_new_from_file_at_scale(filename,
420 rect->width, rect->height,
425 if (!gdk_pixbuf_get_has_alpha(pixbuf) ||
426 gdk_pixbuf_get_n_channels(pixbuf) != 4) {
427 g_object_unref(pixbuf);
432 stride = gdk_pixbuf_get_rowstride(pixbuf);
433 pixels = gdk_pixbuf_get_pixels(pixbuf);
435 for (i = 0; i < rect->height; i++) {
436 p = pixels + i * stride;
437 end = p + rect->width * 4;
441 MULT(p[0], p[0], p[3], t);
442 MULT(p[1], p[1], p[3], t);
443 MULT(p[2], p[2], p[3], t);
449 surface = display_create_egl_image_surface(display, 0, rect);
450 if (surface == NULL) {
451 g_object_unref(pixbuf);
455 data = cairo_surface_get_user_data(surface, &surface_data_key);
457 cairo_device_acquire(display->argb_device);
458 glBindTexture(GL_TEXTURE_2D, data->texture);
459 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rect->width, rect->height,
460 GL_RGBA, GL_UNSIGNED_BYTE, pixels);
461 cairo_device_release(display->argb_device);
463 g_object_unref(pixbuf);
471 display_get_buffer_for_surface(struct display *display,
472 cairo_surface_t *surface)
474 struct surface_data *data;
476 data = cairo_surface_get_user_data (surface, &surface_data_key);
481 struct shm_surface_data {
482 struct surface_data data;
488 shm_surface_data_destroy(void *p)
490 struct shm_surface_data *data = p;
492 wl_buffer_destroy(data->data.buffer);
493 munmap(data->map, data->length);
496 static cairo_surface_t *
497 display_create_shm_surface(struct display *display,
498 struct rectangle *rectangle, uint32_t flags)
500 struct shm_surface_data *data;
502 cairo_surface_t *surface;
504 char filename[] = "/tmp/wayland-shm-XXXXXX";
506 data = malloc(sizeof *data);
510 stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32,
512 data->length = stride * rectangle->height;
513 fd = mkstemp(filename);
515 fprintf(stderr, "open %s failed: %m\n", filename);
518 if (ftruncate(fd, data->length) < 0) {
519 fprintf(stderr, "ftruncate failed: %m\n");
524 data->map = mmap(NULL, data->length,
525 PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
528 if (data->map == MAP_FAILED) {
529 fprintf(stderr, "mmap failed: %m\n");
534 surface = cairo_image_surface_create_for_data (data->map,
540 cairo_surface_set_user_data (surface, &surface_data_key,
541 data, shm_surface_data_destroy);
543 if (flags & SURFACE_OPAQUE)
544 format = WL_SHM_FORMAT_XRGB32;
546 format = WL_SHM_FORMAT_PREMULTIPLIED_ARGB32;
548 data->data.buffer = wl_shm_create_buffer(display->shm,
559 static cairo_surface_t *
560 display_create_shm_surface_from_file(struct display *display,
561 const char *filename,
562 struct rectangle *rect)
564 cairo_surface_t *surface;
566 GError *error = NULL;
568 unsigned char *pixels, *p, *end, *dest_data;
572 pixbuf = gdk_pixbuf_new_from_file_at_scale(filename,
573 rect->width, rect->height,
578 if (!gdk_pixbuf_get_has_alpha(pixbuf) ||
579 gdk_pixbuf_get_n_channels(pixbuf) != 4) {
580 g_object_unref(pixbuf);
584 stride = gdk_pixbuf_get_rowstride(pixbuf);
585 pixels = gdk_pixbuf_get_pixels(pixbuf);
587 surface = display_create_shm_surface(display, rect, 0);
588 if (surface == NULL) {
589 g_object_unref(pixbuf);
593 dest_data = cairo_image_surface_get_data (surface);
594 dest_stride = cairo_image_surface_get_stride (surface);
596 for (i = 0; i < rect->height; i++) {
597 d = (uint32_t *) (dest_data + i * dest_stride);
598 p = pixels + i * stride;
599 end = p + rect->width * 4;
602 unsigned char a, r, g, b;
609 *d++ = (a << 24) | (r << 16) | (g << 8) | b;
613 g_object_unref(pixbuf);
619 check_size(struct rectangle *rect)
621 if (rect->width && rect->height)
624 fprintf(stderr, "tried to create surface of "
625 "width: %d, height: %d\n", rect->width, rect->height);
630 display_create_surface(struct display *display,
631 struct wl_surface *surface,
632 struct rectangle *rectangle,
635 if (check_size(rectangle) < 0)
637 #ifdef HAVE_CAIRO_EGL
640 return display_create_egl_window_surface(display,
645 return display_create_egl_image_surface(display,
650 return display_create_shm_surface(display, rectangle, flags);
653 static cairo_surface_t *
654 display_create_surface_from_file(struct display *display,
655 const char *filename,
656 struct rectangle *rectangle)
658 if (check_size(rectangle) < 0)
660 #ifdef HAVE_CAIRO_EGL
662 return display_create_egl_image_surface_from_file(display,
667 return display_create_shm_surface_from_file(display, filename, rectangle);
669 static const struct {
670 const char *filename;
671 int hotspot_x, hotspot_y;
672 } pointer_images[] = {
673 { DATADIR "/weston/bottom_left_corner.png", 6, 30 },
674 { DATADIR "/weston/bottom_right_corner.png", 28, 28 },
675 { DATADIR "/weston/bottom_side.png", 16, 20 },
676 { DATADIR "/weston/grabbing.png", 20, 17 },
677 { DATADIR "/weston/left_ptr.png", 10, 5 },
678 { DATADIR "/weston/left_side.png", 10, 20 },
679 { DATADIR "/weston/right_side.png", 30, 19 },
680 { DATADIR "/weston/top_left_corner.png", 8, 8 },
681 { DATADIR "/weston/top_right_corner.png", 26, 8 },
682 { DATADIR "/weston/top_side.png", 18, 8 },
683 { DATADIR "/weston/xterm.png", 15, 15 },
684 { DATADIR "/weston/hand1.png", 18, 11 }
688 create_pointer_surfaces(struct display *display)
691 const int width = 32, height = 32;
692 struct rectangle rect;
694 count = ARRAY_LENGTH(pointer_images);
695 display->pointer_surfaces =
696 malloc(count * sizeof *display->pointer_surfaces);
698 rect.height = height;
699 for (i = 0; i < count; i++) {
700 display->pointer_surfaces[i] =
701 display_create_surface_from_file(display,
702 pointer_images[i].filename,
704 if (!display->pointer_surfaces[i]) {
705 fprintf(stderr, "Error loading pointer image: %s\n",
706 pointer_images[i].filename);
713 destroy_pointer_surfaces(struct display *display)
717 count = ARRAY_LENGTH(pointer_images);
718 for (i = 0; i < count; ++i) {
719 if (display->pointer_surfaces[i])
720 cairo_surface_destroy(display->pointer_surfaces[i]);
722 free(display->pointer_surfaces);
726 display_get_pointer_surface(struct display *display, int pointer,
727 int *width, int *height,
728 int *hotspot_x, int *hotspot_y)
730 cairo_surface_t *surface;
732 surface = display->pointer_surfaces[pointer];
734 *width = cairo_gl_surface_get_width(surface);
735 *height = cairo_gl_surface_get_height(surface);
737 *width = cairo_image_surface_get_width(surface);
738 *height = cairo_image_surface_get_height(surface);
740 *hotspot_x = pointer_images[pointer].hotspot_x;
741 *hotspot_y = pointer_images[pointer].hotspot_y;
743 return cairo_surface_reference(surface);
747 window_attach_surface(struct window *window);
750 free_surface(void *data, struct wl_callback *callback, uint32_t time)
752 struct window *window = data;
754 wl_callback_destroy(callback);
755 cairo_surface_destroy(window->pending_surface);
756 window->pending_surface = NULL;
757 if (window->cairo_surface)
758 window_attach_surface(window);
761 static const struct wl_callback_listener free_surface_listener = {
766 window_get_resize_dx_dy(struct window *window, int *x, int *y)
768 if (window->resize_edges & WINDOW_RESIZING_LEFT)
769 *x = window->server_allocation.width - window->allocation.width;
773 if (window->resize_edges & WINDOW_RESIZING_TOP)
774 *y = window->server_allocation.height -
775 window->allocation.height;
779 window->resize_edges = 0;
783 window_set_type(struct window *window)
785 if (!window->shell_surface)
788 switch (window->type) {
789 case TYPE_FULLSCREEN:
790 wl_shell_surface_set_fullscreen(window->shell_surface);
793 wl_shell_surface_set_toplevel(window->shell_surface);
796 wl_shell_surface_set_transient(window->shell_surface,
797 window->parent->shell_surface,
798 window->x, window->y, 0);
808 window_attach_surface(struct window *window)
810 struct display *display = window->display;
811 struct wl_buffer *buffer;
812 struct wl_callback *cb;
813 #ifdef HAVE_CAIRO_EGL
814 struct egl_window_surface_data *data;
819 window_set_type(window);
821 switch (window->buffer_type) {
822 #ifdef HAVE_CAIRO_EGL
823 case WINDOW_BUFFER_TYPE_EGL_WINDOW:
824 data = cairo_surface_get_user_data(window->cairo_surface,
827 cairo_gl_surface_swapbuffers(window->cairo_surface);
828 wl_egl_window_get_attached_size(data->window,
829 &window->server_allocation.width,
830 &window->server_allocation.height);
832 case WINDOW_BUFFER_TYPE_EGL_IMAGE:
834 case WINDOW_BUFFER_TYPE_SHM:
835 window_get_resize_dx_dy(window, &x, &y);
837 if (window->pending_surface != NULL)
840 window->pending_surface = window->cairo_surface;
841 window->cairo_surface = NULL;
844 display_get_buffer_for_surface(display,
845 window->pending_surface);
847 wl_surface_attach(window->surface, buffer, x, y);
848 window->server_allocation = window->allocation;
849 cb = wl_display_sync(display->display);
850 wl_callback_add_listener(cb, &free_surface_listener, window);
856 wl_surface_damage(window->surface, 0, 0,
857 window->allocation.width,
858 window->allocation.height);
862 window_flush(struct window *window)
864 if (window->cairo_surface) {
865 switch (window->buffer_type) {
866 case WINDOW_BUFFER_TYPE_EGL_IMAGE:
867 case WINDOW_BUFFER_TYPE_SHM:
868 display_surface_damage(window->display,
869 window->cairo_surface,
871 window->allocation.width,
872 window->allocation.height);
877 window_attach_surface(window);
882 window_set_surface(struct window *window, cairo_surface_t *surface)
884 cairo_surface_reference(surface);
886 if (window->cairo_surface != NULL)
887 cairo_surface_destroy(window->cairo_surface);
889 window->cairo_surface = surface;
892 #ifdef HAVE_CAIRO_EGL
894 window_resize_cairo_window_surface(struct window *window)
896 struct egl_window_surface_data *data;
899 data = cairo_surface_get_user_data(window->cairo_surface,
902 window_get_resize_dx_dy(window, &x, &y),
903 wl_egl_window_resize(data->window,
904 window->allocation.width,
905 window->allocation.height,
908 cairo_gl_surface_set_size(window->cairo_surface,
909 window->allocation.width,
910 window->allocation.height);
915 window_get_display(struct window *window)
917 return window->display;
921 window_create_surface(struct window *window)
923 cairo_surface_t *surface;
926 if (!window->transparent)
927 flags = SURFACE_OPAQUE;
929 switch (window->buffer_type) {
930 #ifdef HAVE_CAIRO_EGL
931 case WINDOW_BUFFER_TYPE_EGL_WINDOW:
932 if (window->cairo_surface) {
933 window_resize_cairo_window_surface(window);
936 surface = display_create_surface(window->display,
938 &window->allocation, flags);
940 case WINDOW_BUFFER_TYPE_EGL_IMAGE:
941 surface = display_create_surface(window->display,
943 &window->allocation, flags);
946 case WINDOW_BUFFER_TYPE_SHM:
947 surface = display_create_shm_surface(window->display,
948 &window->allocation, flags);
955 window_set_surface(window, surface);
956 cairo_surface_destroy(surface);
960 window_draw_decorations(struct window *window)
963 cairo_text_extents_t extents;
964 cairo_surface_t *frame;
965 int width, height, shadow_dx = 3, shadow_dy = 3;
967 window_create_surface(window);
969 width = window->allocation.width;
970 height = window->allocation.height;
972 cr = cairo_create(window->cairo_surface);
974 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
975 cairo_set_source_rgba(cr, 0, 0, 0, 0);
978 cairo_set_source_rgba(cr, 0, 0, 0, 0.6);
979 tile_mask(cr, window->display->shadow,
980 shadow_dx, shadow_dy, width, height,
981 window->margin + 10 - shadow_dx,
982 window->margin + 10 - shadow_dy);
984 if (window->keyboard_device)
985 frame = window->display->active_frame;
987 frame = window->display->inactive_frame;
989 tile_source(cr, frame, 0, 0, width, height,
990 window->margin + 10, window->margin + 50);
992 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
993 cairo_set_font_size(cr, 14);
994 cairo_text_extents(cr, window->title, &extents);
995 cairo_move_to(cr, (width - extents.width) / 2, 32 - extents.y_bearing);
996 if (window->keyboard_device)
997 cairo_set_source_rgb(cr, 0, 0, 0);
999 cairo_set_source_rgb(cr, 0.8, 0.8, 0.8);
1000 cairo_show_text(cr, window->title);
1006 window_destroy(struct window *window)
1008 struct display *display = window->display;
1009 struct input *input;
1011 if (window->redraw_scheduled)
1012 wl_list_remove(&window->redraw_task.link);
1014 wl_list_for_each(input, &display->input_list, link) {
1015 if (input->pointer_focus == window)
1016 input->pointer_focus = NULL;
1017 if (input->keyboard_focus == window)
1018 input->keyboard_focus = NULL;
1021 if (window->shell_surface)
1022 wl_shell_surface_destroy(window->shell_surface);
1023 wl_surface_destroy(window->surface);
1024 wl_list_remove(&window->link);
1026 if (window->cairo_surface != NULL)
1027 cairo_surface_destroy(window->cairo_surface);
1028 if (window->pending_surface != NULL)
1029 cairo_surface_destroy(window->pending_surface);
1031 free(window->title);
1035 static struct widget *
1036 window_find_widget(struct window *window, int32_t x, int32_t y)
1038 struct widget *widget;
1040 wl_list_for_each(widget, &window->widget_list, link) {
1041 if (widget->allocation.x <= x &&
1042 x < widget->allocation.x + widget->allocation.width &&
1043 widget->allocation.y <= y &&
1044 y < widget->allocation.y + widget->allocation.height) {
1053 window_add_widget(struct window *window, void *data)
1055 struct widget *widget;
1057 widget = malloc(sizeof *widget);
1058 memset(widget, 0, sizeof *widget);
1059 widget->user_data = data;
1060 wl_list_insert(window->widget_list.prev, &widget->link);
1066 window_for_each_widget(struct window *window, widget_func_t func, void *data)
1068 struct widget *widget;
1070 wl_list_for_each(widget, &window->widget_list, link)
1075 window_get_focus_widget(struct window *window)
1077 return window->focus_widget;
1081 widget_get_allocation(struct widget *widget, struct rectangle *allocation)
1083 *allocation = widget->allocation;
1087 widget_set_allocation(struct widget *widget,
1088 int32_t x, int32_t y, int32_t width, int32_t height)
1090 widget->allocation.x = x;
1091 widget->allocation.y = y;
1092 widget->allocation.width = width;
1093 widget->allocation.height = height;
1097 widget_get_user_data(struct widget *widget)
1099 return widget->user_data;
1103 window_draw(struct window *window)
1105 if (!window->decoration)
1106 window_create_surface(window);
1108 window_draw_decorations(window);
1112 window_get_surface(struct window *window)
1114 return cairo_surface_reference(window->cairo_surface);
1118 window_get_wl_surface(struct window *window)
1120 return window->surface;
1123 struct wl_shell_surface *
1124 window_get_wl_shell_surface(struct window *window)
1126 return window->shell_surface;
1130 get_pointer_location(struct window *window, int32_t x, int32_t y)
1132 int vlocation, hlocation, location;
1133 const int grip_size = 8;
1135 if (!window->decoration)
1136 return WINDOW_CLIENT_AREA;
1138 if (x < window->margin)
1139 hlocation = WINDOW_EXTERIOR;
1140 else if (window->margin <= x && x < window->margin + grip_size)
1141 hlocation = WINDOW_RESIZING_LEFT;
1142 else if (x < window->allocation.width - window->margin - grip_size)
1143 hlocation = WINDOW_INTERIOR;
1144 else if (x < window->allocation.width - window->margin)
1145 hlocation = WINDOW_RESIZING_RIGHT;
1147 hlocation = WINDOW_EXTERIOR;
1149 if (y < window->margin)
1150 vlocation = WINDOW_EXTERIOR;
1151 else if (window->margin <= y && y < window->margin + grip_size)
1152 vlocation = WINDOW_RESIZING_TOP;
1153 else if (y < window->allocation.height - window->margin - grip_size)
1154 vlocation = WINDOW_INTERIOR;
1155 else if (y < window->allocation.height - window->margin)
1156 vlocation = WINDOW_RESIZING_BOTTOM;
1158 vlocation = WINDOW_EXTERIOR;
1160 location = vlocation | hlocation;
1161 if (location & WINDOW_EXTERIOR)
1162 location = WINDOW_EXTERIOR;
1163 if (location == WINDOW_INTERIOR && y < window->margin + 50)
1164 location = WINDOW_TITLEBAR;
1165 else if (location == WINDOW_INTERIOR)
1166 location = WINDOW_CLIENT_AREA;
1172 input_get_pointer_image_for_location(struct input *input, int pointer)
1176 location = get_pointer_location(input->pointer_focus,
1177 input->sx, input->sy);
1179 case WINDOW_RESIZING_TOP:
1181 case WINDOW_RESIZING_BOTTOM:
1182 return POINTER_BOTTOM;
1183 case WINDOW_RESIZING_LEFT:
1184 return POINTER_LEFT;
1185 case WINDOW_RESIZING_RIGHT:
1186 return POINTER_RIGHT;
1187 case WINDOW_RESIZING_TOP_LEFT:
1188 return POINTER_TOP_LEFT;
1189 case WINDOW_RESIZING_TOP_RIGHT:
1190 return POINTER_TOP_RIGHT;
1191 case WINDOW_RESIZING_BOTTOM_LEFT:
1192 return POINTER_BOTTOM_LEFT;
1193 case WINDOW_RESIZING_BOTTOM_RIGHT:
1194 return POINTER_BOTTOM_RIGHT;
1195 case WINDOW_EXTERIOR:
1196 case WINDOW_TITLEBAR:
1197 return POINTER_LEFT_PTR;
1204 input_set_pointer_image(struct input *input, uint32_t time, int pointer)
1206 struct display *display = input->display;
1207 struct wl_buffer *buffer;
1208 cairo_surface_t *surface;
1210 if (pointer == input->current_pointer_image)
1213 input->current_pointer_image = pointer;
1214 surface = display->pointer_surfaces[pointer];
1219 buffer = display_get_buffer_for_surface(display, surface);
1220 wl_input_device_attach(input->input_device, time, buffer,
1221 pointer_images[pointer].hotspot_x,
1222 pointer_images[pointer].hotspot_y);
1226 window_set_focus_widget(struct window *window, struct widget *focus)
1230 if (focus == window->focus_widget)
1233 window->focus_widget = focus;
1234 data = focus ? focus->user_data : NULL;
1235 if (window->widget_focus_handler)
1236 window->widget_focus_handler(window, focus, data);
1240 input_handle_motion(void *data, struct wl_input_device *input_device,
1242 int32_t x, int32_t y, int32_t sx, int32_t sy)
1244 struct input *input = data;
1245 struct window *window = input->pointer_focus;
1246 struct widget *widget;
1247 int pointer = POINTER_LEFT_PTR;
1254 if (!window->focus_widget || !window->widget_grab_button) {
1255 widget = window_find_widget(window, sx, sy);
1256 window_set_focus_widget(window, widget);
1259 if (window->motion_handler)
1260 pointer = (*window->motion_handler)(window, input, time,
1264 pointer = input_get_pointer_image_for_location(input, pointer);
1265 input_set_pointer_image(input, time, pointer);
1269 window_menu_func(struct window *window, int index, void *data)
1273 if (window->close_handler)
1274 window->close_handler(window->parent,
1279 case 1: /* fullscreen */
1280 /* we don't have a way to get out of fullscreen for now */
1281 window_set_fullscreen(window, 1);
1283 case 2: /* rotate */
1291 input_handle_button(void *data,
1292 struct wl_input_device *input_device,
1293 uint32_t time, uint32_t button, uint32_t state)
1295 struct input *input = data;
1296 struct window *window = input->pointer_focus;
1297 struct widget *widget;
1300 static const char *entries[] = {
1301 "Close", "Fullscreen", "Rotate", "Scale"
1304 if (window->focus_widget && window->widget_grab_button == 0 && state)
1305 window->widget_grab_button = button;
1307 location = get_pointer_location(window, input->sx, input->sy);
1309 if (window->display->shell && button == BTN_LEFT && state == 1) {
1311 case WINDOW_TITLEBAR:
1312 if (!window->shell_surface)
1314 input_set_pointer_image(input, time, POINTER_DRAGGING);
1315 wl_shell_surface_move(window->shell_surface,
1316 input_device, time);
1318 case WINDOW_RESIZING_TOP:
1319 case WINDOW_RESIZING_BOTTOM:
1320 case WINDOW_RESIZING_LEFT:
1321 case WINDOW_RESIZING_RIGHT:
1322 case WINDOW_RESIZING_TOP_LEFT:
1323 case WINDOW_RESIZING_TOP_RIGHT:
1324 case WINDOW_RESIZING_BOTTOM_LEFT:
1325 case WINDOW_RESIZING_BOTTOM_RIGHT:
1326 if (!window->shell_surface)
1328 wl_shell_surface_resize(window->shell_surface,
1332 case WINDOW_CLIENT_AREA:
1333 if (window->button_handler)
1334 (*window->button_handler)(window,
1340 } else if (button == BTN_RIGHT && state == 1) {
1343 input_get_position(input, &x, &y);
1344 window->menu = window_create_menu(window->display,
1350 window_schedule_redraw(window->menu);
1352 case WINDOW_CLIENT_AREA:
1353 if (window->button_handler)
1354 (*window->button_handler)(window,
1361 if (window->button_handler)
1362 (*window->button_handler)(window,
1368 if (window->focus_widget &&
1369 window->widget_grab_button == button && !state) {
1370 window->widget_grab_button = 0;
1371 widget = window_find_widget(window, input->sx, input->sy);
1372 window_set_focus_widget(window, widget);
1377 input_handle_key(void *data, struct wl_input_device *input_device,
1378 uint32_t time, uint32_t key, uint32_t state)
1380 struct input *input = data;
1381 struct window *window = input->keyboard_focus;
1382 struct display *d = input->display;
1383 uint32_t code, sym, level;
1385 code = key + d->xkb->min_key_code;
1386 if (!window || window->keyboard_device != input)
1390 if (input->modifiers & XKB_COMMON_SHIFT_MASK &&
1391 XkbKeyGroupWidth(d->xkb, code, 0) > 1)
1394 sym = XkbKeySymEntry(d->xkb, code, level, 0);
1397 input->modifiers |= d->xkb->map->modmap[code];
1399 input->modifiers &= ~d->xkb->map->modmap[code];
1401 if (window->key_handler)
1402 (*window->key_handler)(window, input, time, key, sym, state,
1407 input_remove_pointer_focus(struct input *input, uint32_t time)
1409 struct window *window = input->pointer_focus;
1414 window_set_focus_widget(window, NULL);
1416 if (window->leave_handler)
1417 window->leave_handler(window, input, time, window->user_data);
1418 input->pointer_focus = NULL;
1419 input->current_pointer_image = POINTER_UNSET;
1423 input_handle_pointer_focus(void *data,
1424 struct wl_input_device *input_device,
1425 uint32_t time, struct wl_surface *surface,
1426 int32_t x, int32_t y, int32_t sx, int32_t sy)
1428 struct input *input = data;
1429 struct window *window;
1430 struct widget *widget;
1433 window = input->pointer_focus;
1434 if (window && window->surface != surface)
1435 input_remove_pointer_focus(input, time);
1438 input->pointer_focus = wl_surface_get_user_data(surface);
1439 window = input->pointer_focus;
1446 pointer = POINTER_LEFT_PTR;
1447 if (window->enter_handler)
1448 pointer = window->enter_handler(window, input,
1452 widget = window_find_widget(window, x, y);
1453 window_set_focus_widget(window, widget);
1455 pointer = input_get_pointer_image_for_location(input, pointer);
1456 input_set_pointer_image(input, time, pointer);
1461 input_remove_keyboard_focus(struct input *input)
1463 struct window *window = input->keyboard_focus;
1468 window->keyboard_device = NULL;
1469 if (window->keyboard_focus_handler)
1470 (*window->keyboard_focus_handler)(window, NULL,
1473 input->keyboard_focus = NULL;
1477 input_handle_keyboard_focus(void *data,
1478 struct wl_input_device *input_device,
1480 struct wl_surface *surface,
1481 struct wl_array *keys)
1483 struct input *input = data;
1484 struct window *window;
1485 struct display *d = input->display;
1488 input_remove_keyboard_focus(input);
1491 input->keyboard_focus = wl_surface_get_user_data(surface);
1493 end = keys->data + keys->size;
1494 input->modifiers = 0;
1495 for (k = keys->data; k < end; k++)
1496 input->modifiers |= d->xkb->map->modmap[*k];
1498 window = input->keyboard_focus;
1500 window->keyboard_device = input;
1501 if (window->keyboard_focus_handler)
1502 (*window->keyboard_focus_handler)(window,
1503 window->keyboard_device,
1509 input_handle_touch_down(void *data,
1510 struct wl_input_device *wl_input_device,
1511 uint32_t time, struct wl_surface *surface,
1512 int32_t id, int32_t x, int32_t y)
1517 input_handle_touch_up(void *data,
1518 struct wl_input_device *wl_input_device,
1519 uint32_t time, int32_t id)
1524 input_handle_touch_motion(void *data,
1525 struct wl_input_device *wl_input_device,
1526 uint32_t time, int32_t id, int32_t x, int32_t y)
1531 input_handle_touch_frame(void *data,
1532 struct wl_input_device *wl_input_device)
1537 input_handle_touch_cancel(void *data,
1538 struct wl_input_device *wl_input_device)
1542 static const struct wl_input_device_listener input_device_listener = {
1543 input_handle_motion,
1544 input_handle_button,
1546 input_handle_pointer_focus,
1547 input_handle_keyboard_focus,
1548 input_handle_touch_down,
1549 input_handle_touch_up,
1550 input_handle_touch_motion,
1551 input_handle_touch_frame,
1552 input_handle_touch_cancel,
1556 input_get_position(struct input *input, int32_t *x, int32_t *y)
1562 struct wl_input_device *
1563 input_get_input_device(struct input *input)
1565 return input->input_device;
1569 input_get_modifiers(struct input *input)
1571 return input->modifiers;
1575 struct wl_data_offer *offer;
1576 struct input *input;
1577 struct wl_array types;
1580 struct task io_task;
1588 data_offer_offer(void *data, struct wl_data_offer *wl_data_offer, const char *type)
1590 struct data_offer *offer = data;
1593 p = wl_array_add(&offer->types, sizeof *p);
1597 static const struct wl_data_offer_listener data_offer_listener = {
1602 data_offer_destroy(struct data_offer *offer)
1607 if (offer->refcount == 0) {
1608 wl_data_offer_destroy(offer->offer);
1609 for (p = offer->types.data; *p; p++)
1611 wl_array_release(&offer->types);
1617 data_device_data_offer(void *data,
1618 struct wl_data_device *data_device, uint32_t id)
1620 struct data_offer *offer;
1622 offer = malloc(sizeof *offer);
1624 wl_array_init(&offer->types);
1625 offer->refcount = 1;
1626 offer->input = data;
1628 /* FIXME: Generate typesafe wrappers for this */
1629 offer->offer = (struct wl_data_offer *)
1630 wl_proxy_create_for_id((struct wl_proxy *) data_device,
1631 id, &wl_data_offer_interface);
1633 wl_data_offer_add_listener(offer->offer,
1634 &data_offer_listener, offer);
1638 data_device_enter(void *data, struct wl_data_device *data_device,
1639 uint32_t time, struct wl_surface *surface,
1640 int32_t x, int32_t y, struct wl_data_offer *offer)
1642 struct input *input = data;
1643 struct window *window;
1646 input->drag_offer = wl_data_offer_get_user_data(offer);
1647 window = wl_surface_get_user_data(surface);
1648 input->pointer_focus = window;
1650 p = wl_array_add(&input->drag_offer->types, sizeof *p);
1653 window = input->pointer_focus;
1654 if (window->data_handler)
1655 window->data_handler(window, input, time, x, y,
1656 input->drag_offer->types.data,
1661 data_device_leave(void *data, struct wl_data_device *data_device)
1663 struct input *input = data;
1665 data_offer_destroy(input->drag_offer);
1666 input->drag_offer = NULL;
1670 data_device_motion(void *data, struct wl_data_device *data_device,
1671 uint32_t time, int32_t x, int32_t y)
1673 struct input *input = data;
1674 struct window *window = input->pointer_focus;
1679 if (window->data_handler)
1680 window->data_handler(window, input, time, x, y,
1681 input->drag_offer->types.data,
1686 data_device_drop(void *data, struct wl_data_device *data_device)
1688 struct input *input = data;
1689 struct window *window = input->pointer_focus;
1691 if (window->drop_handler)
1692 window->drop_handler(window, input,
1693 input->sx, input->sy, window->user_data);
1697 data_device_selection(void *data,
1698 struct wl_data_device *wl_data_device,
1699 struct wl_data_offer *offer)
1701 struct input *input = data;
1704 if (input->selection_offer)
1705 data_offer_destroy(input->selection_offer);
1707 input->selection_offer = wl_data_offer_get_user_data(offer);
1708 p = wl_array_add(&input->selection_offer->types, sizeof *p);
1712 static const struct wl_data_device_listener data_device_listener = {
1713 data_device_data_offer,
1718 data_device_selection
1721 struct wl_data_device *
1722 input_get_data_device(struct input *input)
1724 return input->data_device;
1728 input_set_selection(struct input *input,
1729 struct wl_data_source *source, uint32_t time)
1731 wl_data_device_set_selection(input->data_device, source, time);
1735 input_accept(struct input *input, uint32_t time, const char *type)
1737 wl_data_offer_accept(input->drag_offer->offer, time, type);
1741 offer_io_func(struct task *task, uint32_t events)
1743 struct data_offer *offer =
1744 container_of(task, struct data_offer, io_task);
1748 len = read(offer->fd, buffer, sizeof buffer);
1749 offer->func(buffer, len,
1750 offer->x, offer->y, offer->user_data);
1754 data_offer_destroy(offer);
1759 data_offer_receive_data(struct data_offer *offer, const char *mime_type,
1760 data_func_t func, void *user_data)
1764 pipe2(p, O_CLOEXEC);
1765 wl_data_offer_receive(offer->offer, mime_type, p[1]);
1768 offer->io_task.run = offer_io_func;
1772 offer->user_data = user_data;
1774 display_watch_fd(offer->input->display,
1775 offer->fd, EPOLLIN, &offer->io_task);
1779 input_receive_drag_data(struct input *input, const char *mime_type,
1780 data_func_t func, void *data)
1782 data_offer_receive_data(input->drag_offer, mime_type, func, data);
1783 input->drag_offer->x = input->sx;
1784 input->drag_offer->y = input->sy;
1788 input_receive_selection_data(struct input *input, const char *mime_type,
1789 data_func_t func, void *data)
1793 if (input->selection_offer == NULL)
1796 for (p = input->selection_offer->types.data; *p; p++)
1797 if (strcmp(mime_type, *p) == 0)
1803 data_offer_receive_data(input->selection_offer,
1804 mime_type, func, data);
1809 input_receive_selection_data_to_fd(struct input *input,
1810 const char *mime_type, int fd)
1812 wl_data_offer_receive(input->selection_offer->offer, mime_type, fd);
1818 window_move(struct window *window, struct input *input, uint32_t time)
1820 if (!window->shell_surface)
1823 wl_shell_surface_move(window->shell_surface,
1824 input->input_device, time);
1828 handle_configure(void *data, struct wl_shell_surface *shell_surface,
1829 uint32_t time, uint32_t edges,
1830 int32_t width, int32_t height)
1832 struct window *window = data;
1833 int32_t child_width, child_height;
1835 /* FIXME: this is probably the wrong place to check for width
1836 * or height <= 0, but it prevents the compositor from crashing
1838 if (width <= 0 || height <= 0)
1841 window->resize_edges = edges;
1843 if (window->resize_handler) {
1844 child_width = width - 20 - window->margin * 2;
1845 child_height = height - 60 - window->margin * 2;
1847 (*window->resize_handler)(window,
1848 child_width, child_height,
1851 window->allocation.width = width;
1852 window->allocation.height = height;
1854 if (window->redraw_handler)
1855 window_schedule_redraw(window);
1860 handle_popup_done(void *data, struct wl_shell_surface *shell_surface)
1862 struct window *window = data;
1863 struct menu *menu = window_get_user_data(window);
1864 /* FIXME: Need more context in this event, at least the input
1865 * device. Or just use wl_callback. */
1867 menu->func(window->parent, menu->current, window->parent->user_data);
1868 window_destroy(window);
1871 static const struct wl_shell_surface_listener shell_surface_listener = {
1877 window_get_allocation(struct window *window,
1878 struct rectangle *allocation)
1880 *allocation = window->allocation;
1884 window_get_child_allocation(struct window *window,
1885 struct rectangle *allocation)
1887 if (!window->decoration) {
1888 *allocation = window->allocation;
1890 allocation->x = window->margin + 10;
1891 allocation->y = window->margin + 50;
1893 window->allocation.width - 20 - window->margin * 2;
1894 allocation->height =
1895 window->allocation.height - 60 - window->margin * 2;
1900 window_set_child_size(struct window *window, int32_t width, int32_t height)
1902 if (window->decoration) {
1903 window->allocation.x = 20 + window->margin;
1904 window->allocation.y = 60 + window->margin;
1905 window->allocation.width = width + 20 + window->margin * 2;
1906 window->allocation.height = height + 60 + window->margin * 2;
1908 window->allocation.x = 0;
1909 window->allocation.y = 0;
1910 window->allocation.width = width;
1911 window->allocation.height = height;
1916 idle_redraw(struct task *task, uint32_t events)
1918 struct window *window =
1919 container_of(task, struct window, redraw_task);
1921 window->redraw_handler(window, window->user_data);
1922 window->redraw_scheduled = 0;
1926 window_schedule_redraw(struct window *window)
1928 if (!window->redraw_scheduled) {
1929 window->redraw_task.run = idle_redraw;
1930 display_defer(window->display, &window->redraw_task);
1931 window->redraw_scheduled = 1;
1936 window_set_custom(struct window *window)
1938 window->type = TYPE_CUSTOM;
1942 window_set_fullscreen(struct window *window, int fullscreen)
1944 int32_t width, height;
1945 struct output *output;
1947 if ((window->type == TYPE_FULLSCREEN) == fullscreen)
1951 output = display_get_output(window->display);
1952 window->type = TYPE_FULLSCREEN;
1953 window->saved_allocation = window->allocation;
1954 width = output->allocation.width;
1955 height = output->allocation.height;
1956 window->decoration = 0;
1958 window->type = TYPE_TOPLEVEL;
1959 width = window->saved_allocation.width - 20 - window->margin * 2;
1960 height = window->saved_allocation.height - 60 - window->margin * 2;
1961 window->decoration = 1;
1964 (*window->resize_handler)(window, width, height, window->user_data);
1968 window_set_decoration(struct window *window, int decoration)
1970 window->decoration = decoration;
1974 window_set_user_data(struct window *window, void *data)
1976 window->user_data = data;
1980 window_get_user_data(struct window *window)
1982 return window->user_data;
1986 window_set_resize_handler(struct window *window,
1987 window_resize_handler_t handler)
1989 window->resize_handler = handler;
1993 window_set_redraw_handler(struct window *window,
1994 window_redraw_handler_t handler)
1996 window->redraw_handler = handler;
2000 window_set_key_handler(struct window *window,
2001 window_key_handler_t handler)
2003 window->key_handler = handler;
2007 window_set_button_handler(struct window *window,
2008 window_button_handler_t handler)
2010 window->button_handler = handler;
2014 window_set_motion_handler(struct window *window,
2015 window_motion_handler_t handler)
2017 window->motion_handler = handler;
2021 window_set_enter_handler(struct window *window,
2022 window_enter_handler_t handler)
2024 window->enter_handler = handler;
2028 window_set_leave_handler(struct window *window,
2029 window_leave_handler_t handler)
2031 window->leave_handler = handler;
2035 window_set_keyboard_focus_handler(struct window *window,
2036 window_keyboard_focus_handler_t handler)
2038 window->keyboard_focus_handler = handler;
2042 window_set_widget_focus_handler(struct window *window,
2043 window_widget_focus_handler_t handler)
2045 window->widget_focus_handler = handler;
2049 window_set_data_handler(struct window *window, window_data_handler_t handler)
2051 window->data_handler = handler;
2055 window_set_drop_handler(struct window *window, window_drop_handler_t handler)
2057 window->drop_handler = handler;
2061 window_set_close_handler(struct window *window,
2062 window_close_handler_t handler)
2064 window->close_handler = handler;
2068 window_set_transparent(struct window *window, int transparent)
2070 window->transparent = transparent;
2074 window_set_title(struct window *window, const char *title)
2076 free(window->title);
2077 window->title = strdup(title);
2081 window_get_title(struct window *window)
2083 return window->title;
2087 display_surface_damage(struct display *display, cairo_surface_t *cairo_surface,
2088 int32_t x, int32_t y, int32_t width, int32_t height)
2090 struct wl_buffer *buffer;
2092 buffer = display_get_buffer_for_surface(display, cairo_surface);
2094 wl_buffer_damage(buffer, x, y, width, height);
2098 window_damage(struct window *window, int32_t x, int32_t y,
2099 int32_t width, int32_t height)
2101 wl_surface_damage(window->surface, x, y, width, height);
2104 static struct window *
2105 window_create_internal(struct display *display, struct window *parent,
2106 int32_t width, int32_t height)
2108 struct window *window;
2110 window = malloc(sizeof *window);
2114 memset(window, 0, sizeof *window);
2115 window->display = display;
2116 window->parent = parent;
2117 window->surface = wl_compositor_create_surface(display->compositor);
2118 if (display->shell) {
2119 window->shell_surface =
2120 wl_shell_get_shell_surface(display->shell,
2123 window->allocation.x = 0;
2124 window->allocation.y = 0;
2125 window->allocation.width = width;
2126 window->allocation.height = height;
2127 window->saved_allocation = window->allocation;
2128 window->margin = 16;
2129 window->decoration = 1;
2130 window->transparent = 1;
2131 wl_list_init(&window->widget_list);
2134 #ifdef HAVE_CAIRO_EGL
2135 /* FIXME: make TYPE_EGL_IMAGE choosable for testing */
2136 window->buffer_type = WINDOW_BUFFER_TYPE_EGL_WINDOW;
2138 window->buffer_type = WINDOW_BUFFER_TYPE_SHM;
2141 window->buffer_type = WINDOW_BUFFER_TYPE_SHM;
2143 wl_surface_set_user_data(window->surface, window);
2144 wl_list_insert(display->window_list.prev, &window->link);
2146 if (window->shell_surface) {
2147 wl_shell_surface_set_user_data(window->shell_surface, window);
2148 wl_shell_surface_add_listener(window->shell_surface,
2149 &shell_surface_listener, window);
2156 window_create(struct display *display, int32_t width, int32_t height)
2158 struct window *window;
2160 window = window_create_internal(display, NULL, width, height);
2168 window_create_transient(struct display *display, struct window *parent,
2169 int32_t x, int32_t y, int32_t width, int32_t height)
2171 struct window *window;
2173 window = window_create_internal(parent->display,
2174 parent, width, height);
2178 window->type = TYPE_TRANSIENT;
2186 menu_set_widget(struct window *window, struct menu *menu, int sy)
2190 next = (sy - 8) / 20;
2191 if (menu->current != next) {
2192 menu->current = next;
2193 window_schedule_redraw(window);
2196 return POINTER_LEFT_PTR;
2200 menu_motion_handler(struct window *window,
2201 struct input *input, uint32_t time,
2202 int32_t x, int32_t y,
2203 int32_t sx, int32_t sy, void *data)
2205 return menu_set_widget(window, data, sy);
2209 menu_enter_handler(struct window *window,
2210 struct input *input, uint32_t time,
2211 int32_t x, int32_t y, void *data)
2213 return menu_set_widget(window, data, y);
2217 menu_leave_handler(struct window *window,
2218 struct input *input, uint32_t time, void *data)
2220 menu_set_widget(window, data, -200);
2224 menu_button_handler(struct window *window,
2225 struct input *input, uint32_t time,
2226 int button, int state, void *data)
2229 struct menu *menu = data;
2231 /* Either relase after press-drag-release or click-motion-click. */
2232 if (state == 0 && time - menu->time > 500) {
2233 menu->func(window->parent,
2234 menu->current, window->parent->user_data);
2235 window_destroy(window);
2240 menu_redraw_handler(struct window *window, void *data)
2243 const int32_t r = 3, margin = 3;
2244 struct menu *menu = data;
2245 int32_t width, height, i;
2248 height = menu->count * 20 + margin * 2;
2249 window_set_child_size(window, width, height);
2250 window_create_surface(window);
2252 cr = cairo_create(window->cairo_surface);
2253 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
2254 cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0);
2257 width = window->allocation.width;
2258 height = window->allocation.height;
2259 rounded_rect(cr, 0, 0, width, height, r);
2260 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
2261 cairo_set_source_rgba(cr, 0.0, 0.0, 0.4, 0.8);
2264 for (i = 0; i < menu->count; i++) {
2265 if (i == menu->current) {
2266 cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
2267 cairo_rectangle(cr, margin, i * 20 + margin,
2268 width - 2 * margin, 20);
2270 cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
2271 cairo_move_to(cr, 10, i * 20 + 16);
2272 cairo_show_text(cr, menu->entries[i]);
2274 cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
2275 cairo_move_to(cr, 10, i * 20 + 16);
2276 cairo_show_text(cr, menu->entries[i]);
2281 window_flush(window);
2285 window_create_menu(struct display *display,
2286 struct input *input, uint32_t time, struct window *parent,
2287 int32_t x, int32_t y,
2288 menu_func_t func, const char **entries, int count)
2290 struct window *window;
2293 menu = malloc(sizeof *menu);
2297 window = window_create_internal(parent->display, parent, 0, 0);
2301 menu->window = window;
2302 menu->entries = entries;
2303 menu->count = count;
2306 window->decoration = 0;
2307 window->type = TYPE_MENU;
2311 wl_shell_surface_set_popup(window->shell_surface,
2312 input->input_device, time,
2313 window->parent->shell_surface,
2314 window->x, window->y, 0);
2316 window_set_motion_handler(window, menu_motion_handler);
2317 window_set_enter_handler(window, menu_enter_handler);
2318 window_set_leave_handler(window, menu_leave_handler);
2319 window_set_button_handler(window, menu_button_handler);
2320 window_set_redraw_handler(window, menu_redraw_handler);
2321 window_set_user_data(window, menu);
2327 window_set_buffer_type(struct window *window, enum window_buffer_type type)
2329 window->buffer_type = type;
2334 display_handle_geometry(void *data,
2335 struct wl_output *wl_output,
2338 int physical_height,
2343 struct output *output = data;
2345 output->allocation.x = x;
2346 output->allocation.y = y;
2350 display_handle_mode(void *data,
2351 struct wl_output *wl_output,
2357 struct output *output = data;
2358 struct display *display = output->display;
2360 if (flags & WL_OUTPUT_MODE_CURRENT) {
2361 output->allocation.width = width;
2362 output->allocation.height = height;
2363 if (display->output_configure_handler)
2364 (*display->output_configure_handler)(
2365 output, display->user_data);
2369 static const struct wl_output_listener output_listener = {
2370 display_handle_geometry,
2375 display_add_output(struct display *d, uint32_t id)
2377 struct output *output;
2379 output = malloc(sizeof *output);
2383 memset(output, 0, sizeof *output);
2384 output->display = d;
2386 wl_display_bind(d->display, id, &wl_output_interface);
2387 wl_list_insert(d->output_list.prev, &output->link);
2389 wl_output_add_listener(output->output, &output_listener, output);
2393 output_destroy(struct output *output)
2395 if (output->destroy_handler)
2396 (*output->destroy_handler)(output, output->user_data);
2398 wl_output_destroy(output->output);
2399 wl_list_remove(&output->link);
2404 display_set_output_configure_handler(struct display *display,
2405 display_output_handler_t handler)
2407 struct output *output;
2409 display->output_configure_handler = handler;
2413 wl_list_for_each(output, &display->output_list, link)
2414 (*display->output_configure_handler)(output,
2415 display->user_data);
2419 output_set_user_data(struct output *output, void *data)
2421 output->user_data = data;
2425 output_get_user_data(struct output *output)
2427 return output->user_data;
2431 output_set_destroy_handler(struct output *output,
2432 display_output_handler_t handler)
2434 output->destroy_handler = handler;
2435 /* FIXME: implement this, once we have way to remove outputs */
2439 output_get_allocation(struct output *output, struct rectangle *allocation)
2441 *allocation = output->allocation;
2445 output_get_wl_output(struct output *output)
2447 return output->output;
2451 display_add_input(struct display *d, uint32_t id)
2453 struct input *input;
2455 input = malloc(sizeof *input);
2459 memset(input, 0, sizeof *input);
2461 input->input_device =
2462 wl_display_bind(d->display, id, &wl_input_device_interface);
2463 input->pointer_focus = NULL;
2464 input->keyboard_focus = NULL;
2465 wl_list_insert(d->input_list.prev, &input->link);
2467 wl_input_device_add_listener(input->input_device,
2468 &input_device_listener, input);
2469 wl_input_device_set_user_data(input->input_device, input);
2471 input->data_device =
2472 wl_data_device_manager_get_data_device(d->data_device_manager,
2473 input->input_device);
2474 wl_data_device_add_listener(input->data_device,
2475 &data_device_listener, input);
2479 input_destroy(struct input *input)
2481 input_remove_keyboard_focus(input);
2482 input_remove_pointer_focus(input, 0);
2484 if (input->drag_offer)
2485 data_offer_destroy(input->drag_offer);
2487 if (input->selection_offer)
2488 data_offer_destroy(input->selection_offer);
2490 wl_data_device_destroy(input->data_device);
2491 wl_list_remove(&input->link);
2492 wl_input_device_destroy(input->input_device);
2497 display_handle_global(struct wl_display *display, uint32_t id,
2498 const char *interface, uint32_t version, void *data)
2500 struct display *d = data;
2502 if (strcmp(interface, "wl_compositor") == 0) {
2504 wl_display_bind(display, id, &wl_compositor_interface);
2505 } else if (strcmp(interface, "wl_output") == 0) {
2506 display_add_output(d, id);
2507 } else if (strcmp(interface, "wl_input_device") == 0) {
2508 display_add_input(d, id);
2509 } else if (strcmp(interface, "wl_shell") == 0) {
2510 d->shell = wl_display_bind(display, id, &wl_shell_interface);
2511 } else if (strcmp(interface, "wl_shm") == 0) {
2512 d->shm = wl_display_bind(display, id, &wl_shm_interface);
2513 } else if (strcmp(interface, "wl_data_device_manager") == 0) {
2514 d->data_device_manager =
2515 wl_display_bind(display, id,
2516 &wl_data_device_manager_interface);
2521 display_render_frame(struct display *d)
2526 d->shadow = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 128, 128);
2527 cr = cairo_create(d->shadow);
2528 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
2529 cairo_set_source_rgba(cr, 0, 0, 0, 1);
2530 rounded_rect(cr, 16, 16, 112, 112, radius);
2533 blur_surface(d->shadow, 64);
2536 cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 128, 128);
2537 cr = cairo_create(d->active_frame);
2538 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
2539 cairo_set_source_rgba(cr, 0.8, 0.8, 0.4, 1);
2540 rounded_rect(cr, 16, 16, 112, 112, radius);
2545 cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 128, 128);
2546 cr = cairo_create(d->inactive_frame);
2547 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
2548 cairo_set_source_rgba(cr, 0.6, 0.6, 0.6, 1);
2549 rounded_rect(cr, 16, 16, 112, 112, radius);
2555 init_xkb(struct display *d)
2557 struct xkb_rule_names names;
2559 names.rules = "evdev";
2560 names.model = "pc105";
2561 names.layout = option_xkb_layout;
2562 names.variant = option_xkb_variant;
2563 names.options = option_xkb_options;
2565 d->xkb = xkb_compile_keymap_from_rules(&names);
2567 fprintf(stderr, "Failed to compile keymap\n");
2573 fini_xkb(struct display *display)
2575 xkb_free_keymap(display->xkb);
2579 init_egl(struct display *d)
2581 EGLint major, minor;
2584 static const EGLint premul_argb_cfg_attribs[] = {
2586 EGL_WINDOW_BIT | EGL_PIXMAP_BIT |
2587 EGL_VG_ALPHA_FORMAT_PRE_BIT,
2593 EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
2597 static const EGLint rgb_cfg_attribs[] = {
2598 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PIXMAP_BIT,
2604 EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
2608 d->dpy = eglGetDisplay(d->display);
2609 if (!eglInitialize(d->dpy, &major, &minor)) {
2610 fprintf(stderr, "failed to initialize display\n");
2614 if (!eglBindAPI(EGL_OPENGL_API)) {
2615 fprintf(stderr, "failed to bind api EGL_OPENGL_API\n");
2619 if (!eglChooseConfig(d->dpy, premul_argb_cfg_attribs,
2620 &d->premultiplied_argb_config, 1, &n) || n != 1) {
2621 fprintf(stderr, "failed to choose premul argb config\n");
2625 if (!eglChooseConfig(d->dpy, rgb_cfg_attribs,
2626 &d->rgb_config, 1, &n) || n != 1) {
2627 fprintf(stderr, "failed to choose rgb config\n");
2631 d->rgb_ctx = eglCreateContext(d->dpy, d->rgb_config, EGL_NO_CONTEXT, NULL);
2632 if (d->rgb_ctx == NULL) {
2633 fprintf(stderr, "failed to create context\n");
2636 d->argb_ctx = eglCreateContext(d->dpy, d->premultiplied_argb_config,
2637 EGL_NO_CONTEXT, NULL);
2638 if (d->argb_ctx == NULL) {
2639 fprintf(stderr, "failed to create context\n");
2643 if (!eglMakeCurrent(d->dpy, NULL, NULL, d->rgb_ctx)) {
2644 fprintf(stderr, "failed to make context current\n");
2648 #ifdef HAVE_CAIRO_EGL
2649 d->rgb_device = cairo_egl_device_create(d->dpy, d->rgb_ctx);
2650 if (cairo_device_status(d->rgb_device) != CAIRO_STATUS_SUCCESS) {
2651 fprintf(stderr, "failed to get cairo egl device\n");
2654 d->argb_device = cairo_egl_device_create(d->dpy, d->argb_ctx);
2655 if (cairo_device_status(d->argb_device) != CAIRO_STATUS_SUCCESS) {
2656 fprintf(stderr, "failed to get cairo egl argb device\n");
2665 fini_egl(struct display *display)
2667 #ifdef HAVE_CAIRO_EGL
2668 cairo_device_destroy(display->argb_device);
2669 cairo_device_destroy(display->rgb_device);
2672 eglMakeCurrent(display->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE,
2675 eglTerminate(display->dpy);
2680 event_mask_update(uint32_t mask, void *data)
2682 struct display *d = data;
2690 handle_display_data(struct task *task, uint32_t events)
2692 struct display *display =
2693 container_of(task, struct display, display_task);
2695 wl_display_iterate(display->display, display->mask);
2699 display_create(int *argc, char **argv[], const GOptionEntry *option_entries)
2702 GOptionContext *context;
2703 GOptionGroup *xkb_option_group;
2708 context = g_option_context_new(NULL);
2710 g_option_context_add_main_entries(context, option_entries, "Wayland View");
2712 xkb_option_group = g_option_group_new("xkb",
2714 "Show all XKB options",
2716 g_option_group_add_entries(xkb_option_group, xkb_option_entries);
2717 g_option_context_add_group (context, xkb_option_group);
2719 if (!g_option_context_parse(context, argc, argv, &error)) {
2720 fprintf(stderr, "option parsing failed: %s\n", error->message);
2724 g_option_context_free(context);
2726 d = malloc(sizeof *d);
2730 memset(d, 0, sizeof *d);
2732 d->display = wl_display_connect(NULL);
2733 if (d->display == NULL) {
2734 fprintf(stderr, "failed to create display: %m\n");
2738 d->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
2739 d->display_fd = wl_display_get_fd(d->display, event_mask_update, d);
2740 d->display_task.run = handle_display_data;
2741 display_watch_fd(d, d->display_fd, EPOLLIN, &d->display_task);
2743 wl_list_init(&d->deferred_list);
2744 wl_list_init(&d->input_list);
2745 wl_list_init(&d->output_list);
2747 /* Set up listener so we'll catch all events. */
2748 wl_display_add_global_listener(d->display,
2749 display_handle_global, d);
2751 /* Process connection events. */
2752 wl_display_iterate(d->display, WL_DISPLAY_READABLE);
2753 if (init_egl(d) < 0)
2756 d->image_target_texture_2d =
2757 (void *) eglGetProcAddress("glEGLImageTargetTexture2DOES");
2758 d->create_image = (void *) eglGetProcAddress("eglCreateImageKHR");
2759 d->destroy_image = (void *) eglGetProcAddress("eglDestroyImageKHR");
2761 create_pointer_surfaces(d);
2763 display_render_frame(d);
2765 wl_list_init(&d->window_list);
2773 display_destroy_outputs(struct display *display)
2776 struct output *output;
2778 wl_list_for_each_safe(output, tmp, &display->output_list, link)
2779 output_destroy(output);
2783 display_destroy_inputs(struct display *display)
2786 struct input *input;
2788 wl_list_for_each_safe(input, tmp, &display->input_list, link)
2789 input_destroy(input);
2793 display_destroy(struct display *display)
2795 if (!wl_list_empty(&display->window_list))
2796 fprintf(stderr, "toytoolkit warning: windows exist.\n");
2798 if (!wl_list_empty(&display->deferred_list))
2799 fprintf(stderr, "toytoolkit warning: deferred tasks exist.\n");
2801 display_destroy_outputs(display);
2802 display_destroy_inputs(display);
2806 cairo_surface_destroy(display->active_frame);
2807 cairo_surface_destroy(display->inactive_frame);
2808 cairo_surface_destroy(display->shadow);
2809 destroy_pointer_surfaces(display);
2814 wl_shell_destroy(display->shell);
2817 wl_shm_destroy(display->shm);
2819 if (display->data_device_manager)
2820 wl_data_device_manager_destroy(display->data_device_manager);
2822 wl_compositor_destroy(display->compositor);
2824 close(display->epoll_fd);
2826 wl_display_flush(display->display);
2827 wl_display_destroy(display->display);
2832 display_set_user_data(struct display *display, void *data)
2834 display->user_data = data;
2838 display_get_user_data(struct display *display)
2840 return display->user_data;
2844 display_get_display(struct display *display)
2846 return display->display;
2850 display_get_output(struct display *display)
2852 return container_of(display->output_list.next, struct output, link);
2855 struct wl_compositor *
2856 display_get_compositor(struct display *display)
2858 return display->compositor;
2862 display_get_egl_display(struct display *d)
2867 struct wl_data_source *
2868 display_create_data_source(struct display *display)
2870 return wl_data_device_manager_create_data_source(display->data_device_manager);
2874 display_get_rgb_egl_config(struct display *d)
2876 return d->rgb_config;
2880 display_get_argb_egl_config(struct display *d)
2882 return d->premultiplied_argb_config;
2886 display_get_shell(struct display *display)
2888 return display->shell;
2892 display_acquire_window_surface(struct display *display,
2893 struct window *window,
2896 #ifdef HAVE_CAIRO_EGL
2897 struct egl_window_surface_data *data;
2898 cairo_device_t *device;
2900 if (!window->cairo_surface)
2902 device = cairo_surface_get_device(window->cairo_surface);
2907 if (device == display->rgb_device)
2908 ctx = display->rgb_ctx;
2909 else if (device == display->argb_device)
2910 ctx = display->argb_ctx;
2915 data = cairo_surface_get_user_data(window->cairo_surface,
2918 cairo_device_flush(device);
2919 cairo_device_acquire(device);
2920 if (!eglMakeCurrent(display->dpy, data->surf, data->surf, ctx))
2921 fprintf(stderr, "failed to make surface current\n");
2930 display_release_window_surface(struct display *display,
2931 struct window *window)
2933 #ifdef HAVE_CAIRO_EGL
2934 cairo_device_t *device;
2936 device = cairo_surface_get_device(window->cairo_surface);
2940 if (!eglMakeCurrent(display->dpy, NULL, NULL, display->rgb_ctx))
2941 fprintf(stderr, "failed to make context current\n");
2942 cairo_device_release(device);
2947 display_defer(struct display *display, struct task *task)
2949 wl_list_insert(&display->deferred_list, &task->link);
2953 display_watch_fd(struct display *display,
2954 int fd, uint32_t events, struct task *task)
2956 struct epoll_event ep;
2960 epoll_ctl(display->epoll_fd, EPOLL_CTL_ADD, fd, &ep);
2964 display_run(struct display *display)
2967 struct epoll_event ep[16];
2970 display->running = 1;
2972 while (display->mask & WL_DISPLAY_WRITABLE)
2973 wl_display_iterate(display->display,
2974 WL_DISPLAY_WRITABLE);
2976 if (!display->running)
2979 count = epoll_wait(display->epoll_fd,
2980 ep, ARRAY_LENGTH(ep), -1);
2981 for (i = 0; i < count; i++) {
2982 task = ep[i].data.ptr;
2983 task->run(task, ep[i].events);
2986 while (!wl_list_empty(&display->deferred_list)) {
2987 task = container_of(display->deferred_list.next,
2989 wl_list_remove(&task->link);
2996 display_exit(struct display *display)
2998 display->running = 0;