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 <sys/epoll.h>
39 #include <sys/timerfd.h>
43 #include <wayland-egl.h>
45 #ifdef USE_CAIRO_GLESV2
46 #include <GLES2/gl2.h>
47 #include <GLES2/gl2ext.h>
52 #include <EGL/eglext.h>
58 #include <xkbcommon/xkbcommon.h>
59 #include <wayland-cursor.h>
61 #include <linux/input.h>
62 #include <wayland-client.h>
63 #include "../shared/cairo-util.h"
64 #include "text-cursor-position-client-protocol.h"
65 #include "workspaces-client-protocol.h"
66 #include "../shared/os-compatibility.h"
73 struct wl_display *display;
74 struct wl_compositor *compositor;
75 struct wl_shell *shell;
77 struct wl_data_device_manager *data_device_manager;
78 struct text_cursor_position *text_cursor_position;
79 struct workspace_manager *workspace_manager;
81 EGLConfig argb_config;
83 cairo_device_t *argb_device;
88 struct task display_task;
91 struct wl_list deferred_list;
95 struct wl_list window_list;
96 struct wl_list input_list;
97 struct wl_list output_list;
101 struct wl_cursor_theme *cursor_theme;
102 struct wl_cursor **cursors;
104 PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d;
105 PFNEGLCREATEIMAGEKHRPROC create_image;
106 PFNEGLDESTROYIMAGEKHRPROC destroy_image;
108 display_output_handler_t output_configure_handler;
112 struct xkb_context *xkb_context;
115 uint32_t workspace_count;
128 struct window_output {
129 struct output *output;
134 struct display *display;
135 struct window *parent;
136 struct wl_list window_output_list;
137 struct wl_surface *surface;
138 struct wl_shell_surface *shell_surface;
139 struct wl_region *input_region;
140 struct wl_region *opaque_region;
142 struct rectangle allocation, saved_allocation, server_allocation;
143 struct rectangle min_allocation;
144 struct rectangle pending_allocation;
147 int redraw_scheduled;
149 struct task redraw_task;
155 enum window_buffer_type buffer_type;
157 cairo_surface_t *cairo_surface;
159 struct shm_pool *pool;
161 window_key_handler_t key_handler;
162 window_keyboard_focus_handler_t keyboard_focus_handler;
163 window_data_handler_t data_handler;
164 window_drop_handler_t drop_handler;
165 window_close_handler_t close_handler;
166 window_fullscreen_handler_t fullscreen_handler;
168 struct wl_callback *frame_cb;
171 struct widget *widget;
178 struct window *window;
179 struct tooltip *tooltip;
180 struct wl_list child_list;
182 struct rectangle allocation;
183 widget_resize_handler_t resize_handler;
184 widget_redraw_handler_t redraw_handler;
185 widget_enter_handler_t enter_handler;
186 widget_leave_handler_t leave_handler;
187 widget_motion_handler_t motion_handler;
188 widget_button_handler_t button_handler;
189 widget_axis_handler_t axis_handler;
196 struct display *display;
197 struct wl_seat *seat;
198 struct wl_pointer *pointer;
199 struct wl_keyboard *keyboard;
200 struct window *pointer_focus;
201 struct window *keyboard_focus;
203 uint32_t cursor_anim_start;
204 struct wl_callback *cursor_frame_cb;
205 struct wl_surface *pointer_surface;
207 uint32_t pointer_enter_serial;
208 uint32_t cursor_serial;
212 struct widget *focus_widget;
214 uint32_t grab_button;
216 struct wl_data_device *data_device;
217 struct data_offer *drag_offer;
218 struct data_offer *selection_offer;
221 struct xkb_keymap *keymap;
222 struct xkb_state *state;
223 xkb_mod_mask_t control_mask;
224 xkb_mod_mask_t alt_mask;
225 xkb_mod_mask_t shift_mask;
228 struct task repeat_task;
232 uint32_t repeat_time;
236 struct display *display;
237 struct wl_output *output;
238 struct rectangle allocation;
241 display_output_handler_t destroy_handler;
245 enum frame_button_action {
246 FRAME_BUTTON_NULL = 0,
247 FRAME_BUTTON_ICON = 1,
248 FRAME_BUTTON_CLOSE = 2,
249 FRAME_BUTTON_MINIMIZE = 3,
250 FRAME_BUTTON_MAXIMIZE = 4,
253 enum frame_button_pointer {
254 FRAME_BUTTON_DEFAULT = 0,
255 FRAME_BUTTON_OVER = 1,
256 FRAME_BUTTON_ACTIVE = 2,
259 enum frame_button_align {
260 FRAME_BUTTON_RIGHT = 0,
261 FRAME_BUTTON_LEFT = 1,
264 enum frame_button_decoration {
265 FRAME_BUTTON_NONE = 0,
266 FRAME_BUTTON_FANCY = 1,
269 struct frame_button {
270 struct widget *widget;
272 cairo_surface_t *icon;
273 enum frame_button_action type;
274 enum frame_button_pointer state;
275 struct wl_list link; /* buttons_list */
276 enum frame_button_align align;
277 enum frame_button_decoration decoration;
281 struct widget *widget;
282 struct widget *child;
283 struct wl_list buttons_list;
287 struct window *window;
288 struct widget *widget;
290 const char **entries;
298 struct widget *parent;
299 struct window *window;
300 struct widget *widget;
302 struct task tooltip_task;
308 struct wl_shm_pool *pool;
315 CURSOR_DEFAULT = 100,
319 enum window_location {
321 WINDOW_RESIZING_TOP = 1,
322 WINDOW_RESIZING_BOTTOM = 2,
323 WINDOW_RESIZING_LEFT = 4,
324 WINDOW_RESIZING_TOP_LEFT = 5,
325 WINDOW_RESIZING_BOTTOM_LEFT = 6,
326 WINDOW_RESIZING_RIGHT = 8,
327 WINDOW_RESIZING_TOP_RIGHT = 9,
328 WINDOW_RESIZING_BOTTOM_RIGHT = 10,
329 WINDOW_RESIZING_MASK = 15,
330 WINDOW_EXTERIOR = 16,
331 WINDOW_TITLEBAR = 17,
332 WINDOW_CLIENT_AREA = 18,
335 static const cairo_user_data_key_t surface_data_key;
336 struct surface_data {
337 struct wl_buffer *buffer;
340 #define MULT(_d,c,a,t) \
341 do { t = c * a + 0x7f; _d = ((t >> 8) + t) >> 8; } while (0)
343 #ifdef HAVE_CAIRO_EGL
345 struct egl_window_surface_data {
346 struct display *display;
347 struct wl_surface *surface;
348 struct wl_egl_window *window;
353 egl_window_surface_data_destroy(void *p)
355 struct egl_window_surface_data *data = p;
356 struct display *d = data->display;
358 eglDestroySurface(d->dpy, data->surf);
359 wl_egl_window_destroy(data->window);
360 data->surface = NULL;
365 static cairo_surface_t *
366 display_create_egl_window_surface(struct display *display,
367 struct wl_surface *surface,
369 struct rectangle *rectangle)
371 cairo_surface_t *cairo_surface;
372 struct egl_window_surface_data *data;
374 cairo_device_t *device;
376 data = malloc(sizeof *data);
380 data->display = display;
381 data->surface = surface;
383 config = display->argb_config;
384 device = display->argb_device;
386 data->window = wl_egl_window_create(surface,
390 data->surf = eglCreateWindowSurface(display->dpy, config,
393 cairo_surface = cairo_gl_surface_create_for_egl(device,
398 cairo_surface_set_user_data(cairo_surface, &surface_data_key,
399 data, egl_window_surface_data_destroy);
401 return cairo_surface;
407 display_get_buffer_for_surface(struct display *display,
408 cairo_surface_t *surface)
410 struct surface_data *data;
412 data = cairo_surface_get_user_data (surface, &surface_data_key);
417 struct shm_surface_data {
418 struct surface_data data;
419 struct shm_pool *pool;
423 shm_pool_destroy(struct shm_pool *pool);
426 shm_surface_data_destroy(void *p)
428 struct shm_surface_data *data = p;
430 wl_buffer_destroy(data->data.buffer);
432 shm_pool_destroy(data->pool);
437 static struct wl_shm_pool *
438 make_shm_pool(struct display *display, int size, void **data)
440 struct wl_shm_pool *pool;
443 fd = os_create_anonymous_file(size);
445 fprintf(stderr, "creating a buffer file for %d B failed: %m\n",
450 *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
451 if (*data == MAP_FAILED) {
452 fprintf(stderr, "mmap failed: %m\n");
457 pool = wl_shm_create_pool(display->shm, fd, size);
464 static struct shm_pool *
465 shm_pool_create(struct display *display, size_t size)
467 struct shm_pool *pool = malloc(sizeof *pool);
472 pool->pool = make_shm_pool(display, size, &pool->data);
485 shm_pool_allocate(struct shm_pool *pool, size_t size, int *offset)
487 if (pool->used + size > pool->size)
490 *offset = pool->used;
493 return (char *) pool->data + *offset;
496 /* destroy the pool. this does not unmap the memory though */
498 shm_pool_destroy(struct shm_pool *pool)
500 munmap(pool->data, pool->size);
501 wl_shm_pool_destroy(pool->pool);
505 /* Start allocating from the beginning of the pool again */
507 shm_pool_reset(struct shm_pool *pool)
513 data_length_for_shm_surface(struct rectangle *rect)
517 stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32,
519 return stride * rect->height;
522 static cairo_surface_t *
523 display_create_shm_surface_from_pool(struct display *display,
524 struct rectangle *rectangle,
525 uint32_t flags, struct shm_pool *pool)
527 struct shm_surface_data *data;
529 cairo_surface_t *surface;
530 int stride, length, offset;
533 data = malloc(sizeof *data);
537 stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32,
539 length = stride * rectangle->height;
541 map = shm_pool_allocate(pool, length, &offset);
548 surface = cairo_image_surface_create_for_data (map,
554 cairo_surface_set_user_data (surface, &surface_data_key,
555 data, shm_surface_data_destroy);
557 if (flags & SURFACE_OPAQUE)
558 format = WL_SHM_FORMAT_XRGB8888;
560 format = WL_SHM_FORMAT_ARGB8888;
562 data->data.buffer = wl_shm_pool_create_buffer(pool->pool, offset,
570 static cairo_surface_t *
571 display_create_shm_surface(struct display *display,
572 struct rectangle *rectangle, uint32_t flags,
573 struct window *window)
575 struct shm_surface_data *data;
576 struct shm_pool *pool;
577 cairo_surface_t *surface;
579 if (window && window->pool) {
580 shm_pool_reset(window->pool);
581 surface = display_create_shm_surface_from_pool(display,
589 pool = shm_pool_create(display,
590 data_length_for_shm_surface(rectangle));
595 display_create_shm_surface_from_pool(display, rectangle,
599 shm_pool_destroy(pool);
603 /* make sure we destroy the pool when the surface is destroyed */
604 data = cairo_surface_get_user_data(surface, &surface_data_key);
611 check_size(struct rectangle *rect)
613 if (rect->width && rect->height)
616 fprintf(stderr, "tried to create surface of "
617 "width: %d, height: %d\n", rect->width, rect->height);
622 display_create_surface(struct display *display,
623 struct wl_surface *surface,
624 struct rectangle *rectangle,
627 if (check_size(rectangle) < 0)
629 #ifdef HAVE_CAIRO_EGL
630 if (display->dpy && !(flags & SURFACE_SHM))
631 return display_create_egl_window_surface(display,
636 return display_create_shm_surface(display, rectangle, flags, NULL);
640 * The following correspondences between file names and cursors was copied
641 * from: https://bugs.kde.org/attachment.cgi?id=67313
644 static const char *bottom_left_corners[] = {
645 "bottom_left_corner",
649 static const char *bottom_right_corners[] = {
650 "bottom_right_corner",
654 static const char *bottom_sides[] = {
659 static const char *grabbings[] = {
662 "208530c400c041818281048008011002"
665 static const char *left_ptrs[] = {
672 static const char *left_sides[] = {
677 static const char *right_sides[] = {
682 static const char *top_left_corners[] = {
687 static const char *top_right_corners[] = {
692 static const char *top_sides[] = {
697 static const char *xterms[] = {
703 static const char *hand1s[] = {
707 "e29285e634086352946a0e7090d73106"
710 static const char *watches[] = {
713 "0426c94ea35c87780ff01dc239897213"
716 struct cursor_alternatives {
721 static const struct cursor_alternatives cursors[] = {
722 {bottom_left_corners, ARRAY_LENGTH(bottom_left_corners)},
723 {bottom_right_corners, ARRAY_LENGTH(bottom_right_corners)},
724 {bottom_sides, ARRAY_LENGTH(bottom_sides)},
725 {grabbings, ARRAY_LENGTH(grabbings)},
726 {left_ptrs, ARRAY_LENGTH(left_ptrs)},
727 {left_sides, ARRAY_LENGTH(left_sides)},
728 {right_sides, ARRAY_LENGTH(right_sides)},
729 {top_left_corners, ARRAY_LENGTH(top_left_corners)},
730 {top_right_corners, ARRAY_LENGTH(top_right_corners)},
731 {top_sides, ARRAY_LENGTH(top_sides)},
732 {xterms, ARRAY_LENGTH(xterms)},
733 {hand1s, ARRAY_LENGTH(hand1s)},
734 {watches, ARRAY_LENGTH(watches)},
738 create_cursors(struct display *display)
743 struct wl_cursor *cursor;
744 struct config_key shell_keys[] = {
745 { "cursor-theme", CONFIG_KEY_STRING, &theme },
747 struct config_section cs[] = {
748 { "shell", shell_keys, ARRAY_LENGTH(shell_keys), NULL },
751 config_file = config_file_path("weston.ini");
752 parse_config_file(config_file, cs, ARRAY_LENGTH(cs), NULL);
755 display->cursor_theme = wl_cursor_theme_load(theme, 32, display->shm);
757 malloc(ARRAY_LENGTH(cursors) * sizeof display->cursors[0]);
759 for (i = 0; i < ARRAY_LENGTH(cursors); i++) {
761 for (j = 0; !cursor && j < cursors[i].count; ++j)
762 cursor = wl_cursor_theme_get_cursor(
763 display->cursor_theme, cursors[i].names[j]);
766 fprintf(stderr, "could not load cursor '%s'\n",
767 cursors[i].names[0]);
769 display->cursors[i] = cursor;
774 destroy_cursors(struct display *display)
776 wl_cursor_theme_destroy(display->cursor_theme);
777 free(display->cursors);
780 struct wl_cursor_image *
781 display_get_pointer_image(struct display *display, int pointer)
783 struct wl_cursor *cursor = display->cursors[pointer];
785 return cursor ? cursor->images[0] : NULL;
789 window_get_resize_dx_dy(struct window *window, int *x, int *y)
791 if (window->resize_edges & WINDOW_RESIZING_LEFT)
792 *x = window->server_allocation.width - window->allocation.width;
796 if (window->resize_edges & WINDOW_RESIZING_TOP)
797 *y = window->server_allocation.height -
798 window->allocation.height;
802 window->resize_edges = 0;
806 window_attach_surface(struct window *window)
808 struct display *display = window->display;
809 struct wl_buffer *buffer;
810 #ifdef HAVE_CAIRO_EGL
811 struct egl_window_surface_data *data;
815 if (window->type == TYPE_NONE) {
816 window->type = TYPE_TOPLEVEL;
818 wl_shell_surface_set_toplevel(window->shell_surface);
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);
833 case WINDOW_BUFFER_TYPE_SHM:
835 display_get_buffer_for_surface(display,
836 window->cairo_surface);
838 window_get_resize_dx_dy(window, &x, &y);
839 wl_surface_attach(window->surface, buffer, x, y);
840 wl_surface_damage(window->surface, 0, 0,
841 window->allocation.width,
842 window->allocation.height);
843 window->server_allocation = window->allocation;
844 cairo_surface_destroy(window->cairo_surface);
845 window->cairo_surface = NULL;
851 if (window->input_region) {
852 wl_surface_set_input_region(window->surface,
853 window->input_region);
854 wl_region_destroy(window->input_region);
855 window->input_region = NULL;
858 if (window->opaque_region) {
859 wl_surface_set_opaque_region(window->surface,
860 window->opaque_region);
861 wl_region_destroy(window->opaque_region);
862 window->opaque_region = NULL;
867 window_has_focus(struct window *window)
869 return window->focus_count > 0;
873 window_flush(struct window *window)
875 if (window->cairo_surface)
876 window_attach_surface(window);
880 window_set_surface(struct window *window, cairo_surface_t *surface)
882 cairo_surface_reference(surface);
884 if (window->cairo_surface != NULL)
885 cairo_surface_destroy(window->cairo_surface);
887 window->cairo_surface = surface;
890 #ifdef HAVE_CAIRO_EGL
892 window_resize_cairo_window_surface(struct window *window)
894 struct egl_window_surface_data *data;
897 data = cairo_surface_get_user_data(window->cairo_surface,
900 window_get_resize_dx_dy(window, &x, &y),
901 wl_egl_window_resize(data->window,
902 window->allocation.width,
903 window->allocation.height,
906 cairo_gl_surface_set_size(window->cairo_surface,
907 window->allocation.width,
908 window->allocation.height);
913 window_get_display(struct window *window)
915 return window->display;
919 window_create_surface(struct window *window)
921 cairo_surface_t *surface;
924 if (!window->transparent)
925 flags = SURFACE_OPAQUE;
927 switch (window->buffer_type) {
928 #ifdef HAVE_CAIRO_EGL
929 case WINDOW_BUFFER_TYPE_EGL_WINDOW:
930 if (window->cairo_surface) {
931 window_resize_cairo_window_surface(window);
934 surface = display_create_surface(window->display,
936 &window->allocation, flags);
939 case WINDOW_BUFFER_TYPE_SHM:
940 surface = display_create_shm_surface(window->display,
949 window_set_surface(window, surface);
950 cairo_surface_destroy(surface);
953 static void frame_destroy(struct frame *frame);
956 window_destroy(struct window *window)
958 struct display *display = window->display;
960 struct window_output *window_output;
961 struct window_output *window_output_tmp;
963 if (window->redraw_scheduled)
964 wl_list_remove(&window->redraw_task.link);
966 wl_list_for_each(input, &display->input_list, link) {
967 if (input->pointer_focus == window)
968 input->pointer_focus = NULL;
969 if (input->keyboard_focus == window)
970 input->keyboard_focus = NULL;
971 if (input->focus_widget &&
972 input->focus_widget->window == window)
973 input->focus_widget = NULL;
976 wl_list_for_each_safe(window_output, window_output_tmp,
977 &window->window_output_list, link) {
978 free (window_output);
981 if (window->input_region)
982 wl_region_destroy(window->input_region);
983 if (window->opaque_region)
984 wl_region_destroy(window->opaque_region);
987 frame_destroy(window->frame);
989 if (window->shell_surface)
990 wl_shell_surface_destroy(window->shell_surface);
991 wl_surface_destroy(window->surface);
992 wl_list_remove(&window->link);
994 if (window->cairo_surface != NULL)
995 cairo_surface_destroy(window->cairo_surface);
997 if (window->frame_cb)
998 wl_callback_destroy(window->frame_cb);
1003 static struct widget *
1004 widget_find_widget(struct widget *widget, int32_t x, int32_t y)
1006 struct widget *child, *target;
1008 wl_list_for_each(child, &widget->child_list, link) {
1009 target = widget_find_widget(child, x, y);
1014 if (widget->allocation.x <= x &&
1015 x < widget->allocation.x + widget->allocation.width &&
1016 widget->allocation.y <= y &&
1017 y < widget->allocation.y + widget->allocation.height) {
1024 static struct widget *
1025 widget_create(struct window *window, void *data)
1027 struct widget *widget;
1029 widget = malloc(sizeof *widget);
1030 memset(widget, 0, sizeof *widget);
1031 widget->window = window;
1032 widget->user_data = data;
1033 widget->allocation = window->allocation;
1034 wl_list_init(&widget->child_list);
1036 widget->tooltip = NULL;
1037 widget->tooltip_count = 0;
1043 window_add_widget(struct window *window, void *data)
1045 window->widget = widget_create(window, data);
1046 wl_list_init(&window->widget->link);
1048 return window->widget;
1052 widget_add_widget(struct widget *parent, void *data)
1054 struct widget *widget;
1056 widget = widget_create(parent->window, data);
1057 wl_list_insert(parent->child_list.prev, &widget->link);
1063 widget_destroy(struct widget *widget)
1065 struct display *display = widget->window->display;
1066 struct input *input;
1068 if (widget->tooltip) {
1069 free(widget->tooltip);
1070 widget->tooltip = NULL;
1073 wl_list_for_each(input, &display->input_list, link) {
1074 if (input->focus_widget == widget)
1075 input->focus_widget = NULL;
1078 wl_list_remove(&widget->link);
1083 widget_get_allocation(struct widget *widget, struct rectangle *allocation)
1085 *allocation = widget->allocation;
1089 widget_set_size(struct widget *widget, int32_t width, int32_t height)
1091 widget->allocation.width = width;
1092 widget->allocation.height = height;
1096 widget_set_allocation(struct widget *widget,
1097 int32_t x, int32_t y, int32_t width, int32_t height)
1099 widget->allocation.x = x;
1100 widget->allocation.y = y;
1101 widget_set_size(widget, width, height);
1105 widget_set_transparent(struct widget *widget, int transparent)
1107 widget->opaque = !transparent;
1111 widget_get_user_data(struct widget *widget)
1113 return widget->user_data;
1117 widget_set_resize_handler(struct widget *widget,
1118 widget_resize_handler_t handler)
1120 widget->resize_handler = handler;
1124 widget_set_redraw_handler(struct widget *widget,
1125 widget_redraw_handler_t handler)
1127 widget->redraw_handler = handler;
1131 widget_set_enter_handler(struct widget *widget, widget_enter_handler_t handler)
1133 widget->enter_handler = handler;
1137 widget_set_leave_handler(struct widget *widget, widget_leave_handler_t handler)
1139 widget->leave_handler = handler;
1143 widget_set_motion_handler(struct widget *widget,
1144 widget_motion_handler_t handler)
1146 widget->motion_handler = handler;
1150 widget_set_button_handler(struct widget *widget,
1151 widget_button_handler_t handler)
1153 widget->button_handler = handler;
1157 widget_set_axis_handler(struct widget *widget,
1158 widget_axis_handler_t handler)
1160 widget->axis_handler = handler;
1164 widget_schedule_redraw(struct widget *widget)
1166 window_schedule_redraw(widget->window);
1170 window_get_surface(struct window *window)
1172 return cairo_surface_reference(window->cairo_surface);
1176 window_get_wl_surface(struct window *window)
1178 return window->surface;
1181 struct wl_shell_surface *
1182 window_get_wl_shell_surface(struct window *window)
1184 return window->shell_surface;
1188 tooltip_redraw_handler(struct widget *widget, void *data)
1191 const int32_t r = 3;
1192 struct tooltip *tooltip = data;
1193 int32_t width, height;
1194 struct window *window = widget->window;
1196 cr = cairo_create(window->cairo_surface);
1197 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
1198 cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0);
1201 width = window->allocation.width;
1202 height = window->allocation.height;
1203 rounded_rect(cr, 0, 0, width, height, r);
1205 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
1206 cairo_set_source_rgba(cr, 0.0, 0.0, 0.4, 0.8);
1209 cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
1210 cairo_move_to(cr, 10, 16);
1211 cairo_show_text(cr, tooltip->entry);
1215 static cairo_text_extents_t
1216 get_text_extents(struct tooltip *tooltip)
1218 struct window *window;
1220 cairo_text_extents_t extents;
1222 /* we borrow cairo_surface from the parent cause tooltip's wasn't
1224 window = tooltip->widget->window->parent;
1225 cr = cairo_create(window->cairo_surface);
1226 cairo_text_extents(cr, tooltip->entry, &extents);
1233 window_create_tooltip(struct tooltip *tooltip)
1235 struct widget *parent = tooltip->parent;
1236 struct display *display = parent->window->display;
1237 struct window *window;
1238 const int offset_y = 27;
1239 const int margin = 3;
1240 cairo_text_extents_t extents;
1242 if (tooltip->widget)
1245 window = window_create_transient(display, parent->window, tooltip->x,
1246 tooltip->y + offset_y,
1247 WL_SHELL_SURFACE_TRANSIENT_INACTIVE);
1251 tooltip->window = window;
1252 tooltip->widget = window_add_widget(tooltip->window, tooltip);
1254 extents = get_text_extents(tooltip);
1255 widget_set_redraw_handler(tooltip->widget, tooltip_redraw_handler);
1256 window_schedule_resize(window, extents.width + 20, 20 + margin * 2);
1262 widget_destroy_tooltip(struct widget *parent)
1264 struct tooltip *tooltip = parent->tooltip;
1266 parent->tooltip_count = 0;
1270 if (tooltip->widget) {
1271 widget_destroy(tooltip->widget);
1272 window_destroy(tooltip->window);
1273 tooltip->widget = NULL;
1274 tooltip->window = NULL;
1277 close(tooltip->tooltip_fd);
1278 free(tooltip->entry);
1280 parent->tooltip = NULL;
1284 tooltip_func(struct task *task, uint32_t events)
1286 struct tooltip *tooltip =
1287 container_of(task, struct tooltip, tooltip_task);
1290 if (read(tooltip->tooltip_fd, &exp, sizeof (uint64_t)) != sizeof (uint64_t))
1292 window_create_tooltip(tooltip);
1295 #define TOOLTIP_TIMEOUT 500
1297 tooltip_timer_reset(struct tooltip *tooltip)
1299 struct itimerspec its;
1301 its.it_interval.tv_sec = 0;
1302 its.it_interval.tv_nsec = 0;
1303 its.it_value.tv_sec = TOOLTIP_TIMEOUT / 1000;
1304 its.it_value.tv_nsec = (TOOLTIP_TIMEOUT % 1000) * 1000 * 1000;
1305 if (timerfd_settime(tooltip->tooltip_fd, 0, &its, NULL) < 0) {
1306 fprintf(stderr, "could not set timerfd\n: %m");
1314 widget_set_tooltip(struct widget *parent, char *entry, float x, float y)
1316 struct tooltip *tooltip = parent->tooltip;
1318 parent->tooltip_count++;
1322 tooltip_timer_reset(tooltip);
1326 /* the handler might be triggered too fast via input device motion, so
1327 * we need this check here to make sure tooltip is fully initialized */
1328 if (parent->tooltip_count > 1)
1331 tooltip = malloc(sizeof *tooltip);
1335 parent->tooltip = tooltip;
1336 tooltip->parent = parent;
1337 tooltip->widget = NULL;
1338 tooltip->window = NULL;
1341 tooltip->entry = strdup(entry);
1342 tooltip->tooltip_fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
1343 if (tooltip->tooltip_fd < 0) {
1344 fprintf(stderr, "could not create timerfd\n: %m");
1348 tooltip->tooltip_task.run = tooltip_func;
1349 display_watch_fd(parent->window->display, tooltip->tooltip_fd,
1350 EPOLLIN, &tooltip->tooltip_task);
1351 tooltip_timer_reset(tooltip);
1357 workspace_manager_state(void *data,
1358 struct workspace_manager *workspace_manager,
1362 struct display *display = data;
1364 display->workspace = current;
1365 display->workspace_count = count;
1368 static const struct workspace_manager_listener workspace_manager_listener = {
1369 workspace_manager_state
1373 frame_resize_handler(struct widget *widget,
1374 int32_t width, int32_t height, void *data)
1376 struct frame *frame = data;
1377 struct widget *child = frame->child;
1378 struct rectangle allocation;
1379 struct display *display = widget->window->display;
1380 struct frame_button * button;
1381 struct theme *t = display->theme;
1382 int x_l, x_r, y, w, h;
1383 int decoration_width, decoration_height;
1386 if (widget->window->type != TYPE_FULLSCREEN) {
1387 decoration_width = (t->width + t->margin) * 2;
1388 decoration_height = t->width +
1389 t->titlebar_height + t->margin * 2;
1391 allocation.x = t->width + t->margin;
1392 allocation.y = t->titlebar_height + t->margin;
1393 allocation.width = width - decoration_width;
1394 allocation.height = height - decoration_height;
1396 opaque_margin = t->margin + t->frame_radius;
1398 wl_list_for_each(button, &frame->buttons_list, link)
1399 button->widget->opaque = 0;
1401 decoration_width = 0;
1402 decoration_height = 0;
1406 allocation.width = width;
1407 allocation.height = height;
1410 wl_list_for_each(button, &frame->buttons_list, link)
1411 button->widget->opaque = 1;
1414 widget_set_allocation(child, allocation.x, allocation.y,
1415 allocation.width, allocation.height);
1417 if (child->resize_handler)
1418 child->resize_handler(child,
1423 width = child->allocation.width + decoration_width;
1424 height = child->allocation.height + decoration_height;
1426 if (widget->window->type != TYPE_FULLSCREEN) {
1427 widget->window->input_region =
1428 wl_compositor_create_region(display->compositor);
1429 wl_region_add(widget->window->input_region,
1430 t->margin, t->margin,
1431 width - 2 * t->margin,
1432 height - 2 * t->margin);
1435 widget_set_allocation(widget, 0, 0, width, height);
1437 if (child->opaque) {
1438 widget->window->opaque_region =
1439 wl_compositor_create_region(display->compositor);
1440 wl_region_add(widget->window->opaque_region,
1441 opaque_margin, opaque_margin,
1442 widget->allocation.width - 2 * opaque_margin,
1443 widget->allocation.height - 2 * opaque_margin);
1446 /* frame internal buttons */
1447 x_r = frame->widget->allocation.width - t->width - t->margin;
1448 x_l = t->width + t->margin;
1449 y = t->width + t->margin;
1450 wl_list_for_each(button, &frame->buttons_list, link) {
1451 const int button_padding = 4;
1452 w = cairo_image_surface_get_width(button->icon);
1453 h = cairo_image_surface_get_height(button->icon);
1455 if (button->decoration == FRAME_BUTTON_FANCY)
1458 if (button->align == FRAME_BUTTON_LEFT) {
1459 widget_set_allocation(button->widget,
1460 x_l, y , w + 1, h + 1);
1462 x_l += button_padding;
1465 widget_set_allocation(button->widget,
1466 x_r, y , w + 1, h + 1);
1467 x_r -= button_padding;
1473 frame_button_enter_handler(struct widget *widget,
1474 struct input *input, float x, float y, void *data)
1476 struct frame_button *frame_button = data;
1478 widget_schedule_redraw(frame_button->widget);
1479 frame_button->state = FRAME_BUTTON_OVER;
1481 return CURSOR_LEFT_PTR;
1485 frame_button_leave_handler(struct widget *widget, struct input *input, void *data)
1487 struct frame_button *frame_button = data;
1489 widget_schedule_redraw(frame_button->widget);
1490 frame_button->state = FRAME_BUTTON_DEFAULT;
1494 frame_button_button_handler(struct widget *widget,
1495 struct input *input, uint32_t time,
1497 enum wl_pointer_button_state state, void *data)
1499 struct frame_button *frame_button = data;
1500 struct window *window = widget->window;
1501 int was_pressed = (frame_button->state == FRAME_BUTTON_ACTIVE);
1503 if (button != BTN_LEFT)
1507 case WL_POINTER_BUTTON_STATE_PRESSED:
1508 frame_button->state = FRAME_BUTTON_ACTIVE;
1509 widget_schedule_redraw(frame_button->widget);
1511 if (frame_button->type == FRAME_BUTTON_ICON)
1512 window_show_frame_menu(window, input, time);
1514 case WL_POINTER_BUTTON_STATE_RELEASED:
1515 frame_button->state = FRAME_BUTTON_DEFAULT;
1516 widget_schedule_redraw(frame_button->widget);
1523 switch (frame_button->type) {
1524 case FRAME_BUTTON_CLOSE:
1525 if (window->close_handler)
1526 window->close_handler(window->parent,
1529 display_exit(window->display);
1531 case FRAME_BUTTON_MINIMIZE:
1532 fprintf(stderr,"Minimize stub\n");
1534 case FRAME_BUTTON_MAXIMIZE:
1535 window_set_maximized(window, window->type != TYPE_MAXIMIZED);
1538 /* Unknown operation */
1544 frame_button_motion_handler(struct widget *widget,
1545 struct input *input, uint32_t time,
1546 float x, float y, void *data)
1548 struct frame_button *frame_button = data;
1549 enum frame_button_pointer previous_button_state = frame_button->state;
1551 /* only track state for a pressed button */
1552 if (input->grab != widget)
1553 return CURSOR_LEFT_PTR;
1555 if (x > widget->allocation.x &&
1556 x < (widget->allocation.x + widget->allocation.width) &&
1557 y > widget->allocation.y &&
1558 y < (widget->allocation.y + widget->allocation.height)) {
1559 frame_button->state = FRAME_BUTTON_ACTIVE;
1561 frame_button->state = FRAME_BUTTON_DEFAULT;
1564 if (frame_button->state != previous_button_state)
1565 widget_schedule_redraw(frame_button->widget);
1567 return CURSOR_LEFT_PTR;
1571 frame_button_redraw_handler(struct widget *widget, void *data)
1573 struct frame_button *frame_button = data;
1575 int width, height, x, y;
1576 struct window *window = widget->window;
1578 x = widget->allocation.x;
1579 y = widget->allocation.y;
1580 width = widget->allocation.width;
1581 height = widget->allocation.height;
1590 cr = cairo_create(window->cairo_surface);
1592 if (frame_button->decoration == FRAME_BUTTON_FANCY) {
1593 cairo_set_line_width(cr, 1);
1595 cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
1596 cairo_rectangle (cr, x, y, 25, 16);
1598 cairo_stroke_preserve(cr);
1600 switch (frame_button->state) {
1601 case FRAME_BUTTON_DEFAULT:
1602 cairo_set_source_rgb(cr, 0.88, 0.88, 0.88);
1604 case FRAME_BUTTON_OVER:
1605 cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
1607 case FRAME_BUTTON_ACTIVE:
1608 cairo_set_source_rgb(cr, 0.7, 0.7, 0.7);
1617 cairo_set_source_surface(cr, frame_button->icon, x, y);
1623 static struct widget *
1624 frame_button_create(struct frame *frame, void *data, enum frame_button_action type,
1625 enum frame_button_align align, enum frame_button_decoration style)
1627 struct frame_button *frame_button;
1628 const char *icon = data;
1630 frame_button = malloc (sizeof *frame_button);
1631 memset(frame_button, 0, sizeof *frame_button);
1633 frame_button->icon = cairo_image_surface_create_from_png(icon);
1634 frame_button->widget = widget_add_widget(frame->widget, frame_button);
1635 frame_button->frame = frame;
1636 frame_button->type = type;
1637 frame_button->align = align;
1638 frame_button->decoration = style;
1640 wl_list_insert(frame->buttons_list.prev, &frame_button->link);
1642 widget_set_redraw_handler(frame_button->widget, frame_button_redraw_handler);
1643 widget_set_enter_handler(frame_button->widget, frame_button_enter_handler);
1644 widget_set_leave_handler(frame_button->widget, frame_button_leave_handler);
1645 widget_set_button_handler(frame_button->widget, frame_button_button_handler);
1646 widget_set_motion_handler(frame_button->widget, frame_button_motion_handler);
1647 return frame_button->widget;
1651 frame_button_destroy(struct frame_button *frame_button)
1653 widget_destroy(frame_button->widget);
1654 wl_list_remove(&frame_button->link);
1655 cairo_surface_destroy(frame_button->icon);
1662 frame_redraw_handler(struct widget *widget, void *data)
1665 struct window *window = widget->window;
1666 struct theme *t = window->display->theme;
1669 if (window->type == TYPE_FULLSCREEN)
1672 cr = cairo_create(window->cairo_surface);
1674 if (window->focus_count)
1675 flags |= THEME_FRAME_ACTIVE;
1676 theme_render_frame(t, cr, widget->allocation.width,
1677 widget->allocation.height, window->title, flags);
1683 frame_get_pointer_image_for_location(struct frame *frame, struct input *input)
1685 struct theme *t = frame->widget->window->display->theme;
1688 location = theme_get_location(t, input->sx, input->sy,
1689 frame->widget->allocation.width,
1690 frame->widget->allocation.height);
1693 case THEME_LOCATION_RESIZING_TOP:
1695 case THEME_LOCATION_RESIZING_BOTTOM:
1696 return CURSOR_BOTTOM;
1697 case THEME_LOCATION_RESIZING_LEFT:
1699 case THEME_LOCATION_RESIZING_RIGHT:
1700 return CURSOR_RIGHT;
1701 case THEME_LOCATION_RESIZING_TOP_LEFT:
1702 return CURSOR_TOP_LEFT;
1703 case THEME_LOCATION_RESIZING_TOP_RIGHT:
1704 return CURSOR_TOP_RIGHT;
1705 case THEME_LOCATION_RESIZING_BOTTOM_LEFT:
1706 return CURSOR_BOTTOM_LEFT;
1707 case THEME_LOCATION_RESIZING_BOTTOM_RIGHT:
1708 return CURSOR_BOTTOM_RIGHT;
1709 case THEME_LOCATION_EXTERIOR:
1710 case THEME_LOCATION_TITLEBAR:
1712 return CURSOR_LEFT_PTR;
1717 frame_menu_func(struct window *window, int index, void *data)
1719 struct display *display;
1723 if (window->close_handler)
1724 window->close_handler(window->parent,
1727 display_exit(window->display);
1729 case 1: /* fullscreen */
1730 /* we don't have a way to get out of fullscreen for now */
1731 if (window->fullscreen_handler)
1732 window->fullscreen_handler(window, window->user_data);
1734 case 2: /* move to workspace above */
1735 display = window->display;
1736 if (display->workspace > 0)
1737 workspace_manager_move_surface(display->workspace_manager,
1739 display->workspace - 1);
1741 case 3: /* move to workspace below */
1742 display = window->display;
1743 if (display->workspace < display->workspace_count - 1)
1744 workspace_manager_move_surface(display->workspace_manager,
1746 display->workspace + 1);
1752 window_show_frame_menu(struct window *window,
1753 struct input *input, uint32_t time)
1757 static const char *entries[] = {
1758 "Close", "Fullscreen",
1759 "Move to workspace above", "Move to workspace below"
1762 input_get_position(input, &x, &y);
1763 window_show_menu(window->display, input, time, window,
1764 x - 10, y - 10, frame_menu_func, entries,
1765 ARRAY_LENGTH(entries));
1769 frame_enter_handler(struct widget *widget,
1770 struct input *input, float x, float y, void *data)
1772 return frame_get_pointer_image_for_location(data, input);
1776 frame_motion_handler(struct widget *widget,
1777 struct input *input, uint32_t time,
1778 float x, float y, void *data)
1780 return frame_get_pointer_image_for_location(data, input);
1784 frame_button_handler(struct widget *widget,
1785 struct input *input, uint32_t time,
1786 uint32_t button, enum wl_pointer_button_state state,
1790 struct frame *frame = data;
1791 struct window *window = widget->window;
1792 struct display *display = window->display;
1795 location = theme_get_location(display->theme, input->sx, input->sy,
1796 frame->widget->allocation.width,
1797 frame->widget->allocation.height);
1799 if (window->display->shell && button == BTN_LEFT &&
1800 state == WL_POINTER_BUTTON_STATE_PRESSED) {
1802 case THEME_LOCATION_TITLEBAR:
1803 if (!window->shell_surface)
1805 input_set_pointer_image(input, CURSOR_DRAGGING);
1806 input_ungrab(input);
1807 wl_shell_surface_move(window->shell_surface,
1808 input_get_seat(input),
1811 case THEME_LOCATION_RESIZING_TOP:
1812 case THEME_LOCATION_RESIZING_BOTTOM:
1813 case THEME_LOCATION_RESIZING_LEFT:
1814 case THEME_LOCATION_RESIZING_RIGHT:
1815 case THEME_LOCATION_RESIZING_TOP_LEFT:
1816 case THEME_LOCATION_RESIZING_TOP_RIGHT:
1817 case THEME_LOCATION_RESIZING_BOTTOM_LEFT:
1818 case THEME_LOCATION_RESIZING_BOTTOM_RIGHT:
1819 if (!window->shell_surface)
1821 input_ungrab(input);
1823 if (!display->dpy) {
1824 /* If we're using shm, allocate a big
1825 pool to create buffers out of while
1826 we resize. We should probably base
1827 this number on the size of the output. */
1829 shm_pool_create(display, 6 * 1024 * 1024);
1832 wl_shell_surface_resize(window->shell_surface,
1833 input_get_seat(input),
1834 display->serial, location);
1837 } else if (button == BTN_RIGHT &&
1838 state == WL_POINTER_BUTTON_STATE_PRESSED) {
1839 window_show_frame_menu(window, input, time);
1844 frame_create(struct window *window, void *data)
1846 struct frame *frame;
1848 frame = malloc(sizeof *frame);
1849 memset(frame, 0, sizeof *frame);
1851 frame->widget = window_add_widget(window, frame);
1852 frame->child = widget_add_widget(frame->widget, data);
1854 widget_set_redraw_handler(frame->widget, frame_redraw_handler);
1855 widget_set_resize_handler(frame->widget, frame_resize_handler);
1856 widget_set_enter_handler(frame->widget, frame_enter_handler);
1857 widget_set_motion_handler(frame->widget, frame_motion_handler);
1858 widget_set_button_handler(frame->widget, frame_button_handler);
1860 /* Create empty list for frame buttons */
1861 wl_list_init(&frame->buttons_list);
1863 frame_button_create(frame, DATADIR "/weston/icon_window.png",
1864 FRAME_BUTTON_ICON, FRAME_BUTTON_LEFT, FRAME_BUTTON_NONE);
1866 frame_button_create(frame, DATADIR "/weston/sign_close.png",
1867 FRAME_BUTTON_CLOSE, FRAME_BUTTON_RIGHT, FRAME_BUTTON_FANCY);
1869 frame_button_create(frame, DATADIR "/weston/sign_maximize.png",
1870 FRAME_BUTTON_MAXIMIZE, FRAME_BUTTON_RIGHT, FRAME_BUTTON_FANCY);
1872 frame_button_create(frame, DATADIR "/weston/sign_minimize.png",
1873 FRAME_BUTTON_MINIMIZE, FRAME_BUTTON_RIGHT, FRAME_BUTTON_FANCY);
1875 window->frame = frame;
1877 return frame->child;
1881 frame_set_child_size(struct widget *widget, int child_width, int child_height)
1883 struct display *display = widget->window->display;
1884 struct theme *t = display->theme;
1885 int decoration_width, decoration_height;
1888 if (widget->window->type != TYPE_FULLSCREEN) {
1889 decoration_width = (t->width + t->margin) * 2;
1890 decoration_height = t->width +
1891 t->titlebar_height + t->margin * 2;
1893 width = child_width + decoration_width;
1894 height = child_height + decoration_height;
1896 width = child_width;
1897 height = child_height;
1900 window_schedule_resize(widget->window, width, height);
1904 frame_destroy(struct frame *frame)
1906 struct frame_button *button, *tmp;
1908 wl_list_for_each_safe(button, tmp, &frame->buttons_list, link)
1909 frame_button_destroy(button);
1911 /* frame->child must be destroyed by the application */
1912 widget_destroy(frame->widget);
1917 input_set_focus_widget(struct input *input, struct widget *focus,
1920 struct widget *old, *widget;
1921 int pointer = CURSOR_LEFT_PTR;
1923 if (focus == input->focus_widget)
1926 old = input->focus_widget;
1930 widget = input->grab;
1931 if (widget->leave_handler)
1932 widget->leave_handler(old, input, widget->user_data);
1933 input->focus_widget = NULL;
1939 widget = input->grab;
1940 input->focus_widget = focus;
1941 if (widget->enter_handler)
1942 pointer = widget->enter_handler(focus, input, x, y,
1945 input_set_pointer_image(input, pointer);
1950 input_grab(struct input *input, struct widget *widget, uint32_t button)
1952 input->grab = widget;
1953 input->grab_button = button;
1957 input_ungrab(struct input *input)
1959 struct widget *widget;
1962 if (input->pointer_focus) {
1963 widget = widget_find_widget(input->pointer_focus->widget,
1964 input->sx, input->sy);
1965 input_set_focus_widget(input, widget, input->sx, input->sy);
1970 input_remove_pointer_focus(struct input *input)
1972 struct window *window = input->pointer_focus;
1977 input_set_focus_widget(input, NULL, 0, 0);
1979 input->pointer_focus = NULL;
1980 input->current_cursor = CURSOR_UNSET;
1984 pointer_handle_enter(void *data, struct wl_pointer *pointer,
1985 uint32_t serial, struct wl_surface *surface,
1986 wl_fixed_t sx_w, wl_fixed_t sy_w)
1988 struct input *input = data;
1989 struct window *window;
1990 struct widget *widget;
1991 float sx = wl_fixed_to_double(sx_w);
1992 float sy = wl_fixed_to_double(sy_w);
1995 /* enter event for a window we've just destroyed */
1999 input->display->serial = serial;
2000 input->pointer_enter_serial = serial;
2001 input->pointer_focus = wl_surface_get_user_data(surface);
2002 window = input->pointer_focus;
2005 shm_pool_destroy(window->pool);
2006 window->pool = NULL;
2007 /* Schedule a redraw to free the pool */
2008 window_schedule_redraw(window);
2014 widget = widget_find_widget(window->widget, sx, sy);
2015 input_set_focus_widget(input, widget, sx, sy);
2019 pointer_handle_leave(void *data, struct wl_pointer *pointer,
2020 uint32_t serial, struct wl_surface *surface)
2022 struct input *input = data;
2024 input->display->serial = serial;
2025 input_remove_pointer_focus(input);
2029 pointer_handle_motion(void *data, struct wl_pointer *pointer,
2030 uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w)
2032 struct input *input = data;
2033 struct window *window = input->pointer_focus;
2034 struct widget *widget;
2035 int cursor = CURSOR_LEFT_PTR;
2036 float sx = wl_fixed_to_double(sx_w);
2037 float sy = wl_fixed_to_double(sy_w);
2045 if (!(input->grab && input->grab_button)) {
2046 widget = widget_find_widget(window->widget, sx, sy);
2047 input_set_focus_widget(input, widget, sx, sy);
2051 widget = input->grab;
2053 widget = input->focus_widget;
2054 if (widget && widget->motion_handler)
2055 cursor = widget->motion_handler(widget,
2056 input, time, sx, sy,
2059 input_set_pointer_image(input, cursor);
2063 pointer_handle_button(void *data, struct wl_pointer *pointer, uint32_t serial,
2064 uint32_t time, uint32_t button, uint32_t state_w)
2066 struct input *input = data;
2067 struct widget *widget;
2068 enum wl_pointer_button_state state = state_w;
2070 input->display->serial = serial;
2071 if (input->focus_widget && input->grab == NULL &&
2072 state == WL_POINTER_BUTTON_STATE_PRESSED)
2073 input_grab(input, input->focus_widget, button);
2075 widget = input->grab;
2076 if (widget && widget->button_handler)
2077 (*widget->button_handler)(widget,
2080 input->grab->user_data);
2082 if (input->grab && input->grab_button == button &&
2083 state == WL_POINTER_BUTTON_STATE_RELEASED)
2084 input_ungrab(input);
2088 pointer_handle_axis(void *data, struct wl_pointer *pointer,
2089 uint32_t time, uint32_t axis, wl_fixed_t value)
2091 struct input *input = data;
2092 struct widget *widget;
2094 widget = input->focus_widget;
2096 widget = input->grab;
2097 if (widget && widget->axis_handler)
2098 (*widget->axis_handler)(widget,
2104 static const struct wl_pointer_listener pointer_listener = {
2105 pointer_handle_enter,
2106 pointer_handle_leave,
2107 pointer_handle_motion,
2108 pointer_handle_button,
2109 pointer_handle_axis,
2113 input_remove_keyboard_focus(struct input *input)
2115 struct window *window = input->keyboard_focus;
2116 struct itimerspec its;
2118 its.it_interval.tv_sec = 0;
2119 its.it_interval.tv_nsec = 0;
2120 its.it_value.tv_sec = 0;
2121 its.it_value.tv_nsec = 0;
2122 timerfd_settime(input->repeat_timer_fd, 0, &its, NULL);
2127 window->focus_count--;
2128 if (window->keyboard_focus_handler)
2129 (*window->keyboard_focus_handler)(window, NULL,
2132 input->keyboard_focus = NULL;
2136 keyboard_repeat_func(struct task *task, uint32_t events)
2138 struct input *input =
2139 container_of(task, struct input, repeat_task);
2140 struct window *window = input->keyboard_focus;
2143 if (read(input->repeat_timer_fd, &exp, sizeof exp) != sizeof exp)
2144 /* If we change the timer between the fd becoming
2145 * readable and getting here, there'll be nothing to
2146 * read and we get EAGAIN. */
2149 if (window && window->key_handler) {
2150 (*window->key_handler)(window, input, input->repeat_time,
2151 input->repeat_key, input->repeat_sym,
2152 WL_KEYBOARD_KEY_STATE_PRESSED,
2158 keyboard_handle_keymap(void *data, struct wl_keyboard *keyboard,
2159 uint32_t format, int fd, uint32_t size)
2161 struct input *input = data;
2169 if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
2174 map_str = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
2175 if (map_str == MAP_FAILED) {
2180 input->xkb.keymap = xkb_map_new_from_string(input->display->xkb_context,
2182 XKB_KEYMAP_FORMAT_TEXT_V1,
2184 munmap(map_str, size);
2187 if (!input->xkb.keymap) {
2188 fprintf(stderr, "failed to compile keymap\n");
2192 input->xkb.state = xkb_state_new(input->xkb.keymap);
2193 if (!input->xkb.state) {
2194 fprintf(stderr, "failed to create XKB state\n");
2195 xkb_map_unref(input->xkb.keymap);
2196 input->xkb.keymap = NULL;
2200 input->xkb.control_mask =
2201 1 << xkb_map_mod_get_index(input->xkb.keymap, "Control");
2202 input->xkb.alt_mask =
2203 1 << xkb_map_mod_get_index(input->xkb.keymap, "Mod1");
2204 input->xkb.shift_mask =
2205 1 << xkb_map_mod_get_index(input->xkb.keymap, "Shift");
2209 keyboard_handle_enter(void *data, struct wl_keyboard *keyboard,
2210 uint32_t serial, struct wl_surface *surface,
2211 struct wl_array *keys)
2213 struct input *input = data;
2214 struct window *window;
2216 input->display->serial = serial;
2217 input->keyboard_focus = wl_surface_get_user_data(surface);
2219 window = input->keyboard_focus;
2220 window->focus_count++;
2221 if (window->keyboard_focus_handler)
2222 (*window->keyboard_focus_handler)(window,
2223 input, window->user_data);
2227 keyboard_handle_leave(void *data, struct wl_keyboard *keyboard,
2228 uint32_t serial, struct wl_surface *surface)
2230 struct input *input = data;
2232 input->display->serial = serial;
2233 input_remove_keyboard_focus(input);
2237 keyboard_handle_key(void *data, struct wl_keyboard *keyboard,
2238 uint32_t serial, uint32_t time, uint32_t key,
2241 struct input *input = data;
2242 struct window *window = input->keyboard_focus;
2243 uint32_t code, num_syms;
2244 enum wl_keyboard_key_state state = state_w;
2245 const xkb_keysym_t *syms;
2247 xkb_mod_mask_t mask;
2248 struct itimerspec its;
2250 input->display->serial = serial;
2252 if (!window || !input->xkb.state)
2255 num_syms = xkb_key_get_syms(input->xkb.state, code, &syms);
2257 mask = xkb_state_serialize_mods(input->xkb.state,
2258 XKB_STATE_DEPRESSED |
2260 input->modifiers = 0;
2261 if (mask & input->xkb.control_mask)
2262 input->modifiers |= MOD_CONTROL_MASK;
2263 if (mask & input->xkb.alt_mask)
2264 input->modifiers |= MOD_ALT_MASK;
2265 if (mask & input->xkb.shift_mask)
2266 input->modifiers |= MOD_SHIFT_MASK;
2268 sym = XKB_KEY_NoSymbol;
2272 if (sym == XKB_KEY_F5 && input->modifiers == MOD_ALT_MASK) {
2273 if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
2274 window_set_maximized(window,
2275 window->type != TYPE_MAXIMIZED);
2276 } else if (sym == XKB_KEY_F11 &&
2277 window->fullscreen_handler &&
2278 state == WL_KEYBOARD_KEY_STATE_PRESSED) {
2279 window->fullscreen_handler(window, window->user_data);
2280 } else if (sym == XKB_KEY_F4 &&
2281 input->modifiers == MOD_ALT_MASK &&
2282 state == WL_KEYBOARD_KEY_STATE_PRESSED) {
2283 if (window->close_handler)
2284 window->close_handler(window->parent,
2287 display_exit(window->display);
2288 } else if (window->key_handler) {
2289 (*window->key_handler)(window, input, time, key,
2290 sym, state, window->user_data);
2293 if (state == WL_KEYBOARD_KEY_STATE_RELEASED &&
2294 key == input->repeat_key) {
2295 its.it_interval.tv_sec = 0;
2296 its.it_interval.tv_nsec = 0;
2297 its.it_value.tv_sec = 0;
2298 its.it_value.tv_nsec = 0;
2299 timerfd_settime(input->repeat_timer_fd, 0, &its, NULL);
2300 } else if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
2301 input->repeat_sym = sym;
2302 input->repeat_key = key;
2303 input->repeat_time = time;
2304 its.it_interval.tv_sec = 0;
2305 its.it_interval.tv_nsec = 25 * 1000 * 1000;
2306 its.it_value.tv_sec = 0;
2307 its.it_value.tv_nsec = 400 * 1000 * 1000;
2308 timerfd_settime(input->repeat_timer_fd, 0, &its, NULL);
2313 keyboard_handle_modifiers(void *data, struct wl_keyboard *keyboard,
2314 uint32_t serial, uint32_t mods_depressed,
2315 uint32_t mods_latched, uint32_t mods_locked,
2318 struct input *input = data;
2320 xkb_state_update_mask(input->xkb.state, mods_depressed, mods_latched,
2321 mods_locked, 0, 0, group);
2324 static const struct wl_keyboard_listener keyboard_listener = {
2325 keyboard_handle_keymap,
2326 keyboard_handle_enter,
2327 keyboard_handle_leave,
2328 keyboard_handle_key,
2329 keyboard_handle_modifiers,
2333 seat_handle_capabilities(void *data, struct wl_seat *seat,
2334 enum wl_seat_capability caps)
2336 struct input *input = data;
2338 if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->pointer) {
2339 input->pointer = wl_seat_get_pointer(seat);
2340 wl_pointer_set_user_data(input->pointer, input);
2341 wl_pointer_add_listener(input->pointer, &pointer_listener,
2343 } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->pointer) {
2344 wl_pointer_destroy(input->pointer);
2345 input->pointer = NULL;
2348 if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input->keyboard) {
2349 input->keyboard = wl_seat_get_keyboard(seat);
2350 wl_keyboard_set_user_data(input->keyboard, input);
2351 wl_keyboard_add_listener(input->keyboard, &keyboard_listener,
2353 } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->keyboard) {
2354 wl_keyboard_destroy(input->keyboard);
2355 input->keyboard = NULL;
2359 static const struct wl_seat_listener seat_listener = {
2360 seat_handle_capabilities,
2364 input_get_position(struct input *input, int32_t *x, int32_t *y)
2371 input_get_display(struct input *input)
2373 return input->display;
2377 input_get_seat(struct input *input)
2383 input_get_modifiers(struct input *input)
2385 return input->modifiers;
2389 input_get_focus_widget(struct input *input)
2391 return input->focus_widget;
2395 struct wl_data_offer *offer;
2396 struct input *input;
2397 struct wl_array types;
2400 struct task io_task;
2408 data_offer_offer(void *data, struct wl_data_offer *wl_data_offer, const char *type)
2410 struct data_offer *offer = data;
2413 p = wl_array_add(&offer->types, sizeof *p);
2417 static const struct wl_data_offer_listener data_offer_listener = {
2422 data_offer_destroy(struct data_offer *offer)
2427 if (offer->refcount == 0) {
2428 wl_data_offer_destroy(offer->offer);
2429 for (p = offer->types.data; *p; p++)
2431 wl_array_release(&offer->types);
2437 data_device_data_offer(void *data,
2438 struct wl_data_device *data_device,
2439 struct wl_data_offer *_offer)
2441 struct data_offer *offer;
2443 offer = malloc(sizeof *offer);
2445 wl_array_init(&offer->types);
2446 offer->refcount = 1;
2447 offer->input = data;
2448 offer->offer = _offer;
2449 wl_data_offer_add_listener(offer->offer,
2450 &data_offer_listener, offer);
2454 data_device_enter(void *data, struct wl_data_device *data_device,
2455 uint32_t serial, struct wl_surface *surface,
2456 wl_fixed_t x_w, wl_fixed_t y_w,
2457 struct wl_data_offer *offer)
2459 struct input *input = data;
2460 struct window *window;
2462 float x = wl_fixed_to_double(x_w);
2463 float y = wl_fixed_to_double(y_w);
2466 input->pointer_enter_serial = serial;
2467 window = wl_surface_get_user_data(surface);
2468 input->pointer_focus = window;
2471 input->drag_offer = wl_data_offer_get_user_data(offer);
2473 p = wl_array_add(&input->drag_offer->types, sizeof *p);
2476 types_data = input->drag_offer->types.data;
2478 input->drag_offer = NULL;
2482 window = input->pointer_focus;
2483 if (window->data_handler)
2484 window->data_handler(window, input, x, y, types_data,
2489 data_device_leave(void *data, struct wl_data_device *data_device)
2491 struct input *input = data;
2493 if (input->drag_offer) {
2494 data_offer_destroy(input->drag_offer);
2495 input->drag_offer = NULL;
2500 data_device_motion(void *data, struct wl_data_device *data_device,
2501 uint32_t time, wl_fixed_t x_w, wl_fixed_t y_w)
2503 struct input *input = data;
2504 struct window *window = input->pointer_focus;
2505 float x = wl_fixed_to_double(x_w);
2506 float y = wl_fixed_to_double(y_w);
2512 if (input->drag_offer)
2513 types_data = input->drag_offer->types.data;
2517 if (window->data_handler)
2518 window->data_handler(window, input, x, y, types_data,
2523 data_device_drop(void *data, struct wl_data_device *data_device)
2525 struct input *input = data;
2526 struct window *window = input->pointer_focus;
2528 if (window->drop_handler)
2529 window->drop_handler(window, input,
2530 input->sx, input->sy, window->user_data);
2534 data_device_selection(void *data,
2535 struct wl_data_device *wl_data_device,
2536 struct wl_data_offer *offer)
2538 struct input *input = data;
2541 if (input->selection_offer)
2542 data_offer_destroy(input->selection_offer);
2545 input->selection_offer = wl_data_offer_get_user_data(offer);
2546 p = wl_array_add(&input->selection_offer->types, sizeof *p);
2549 input->selection_offer = NULL;
2553 static const struct wl_data_device_listener data_device_listener = {
2554 data_device_data_offer,
2559 data_device_selection
2563 input_set_pointer_image_index(struct input *input, int index)
2565 struct wl_buffer *buffer;
2566 struct wl_cursor *cursor;
2567 struct wl_cursor_image *image;
2569 cursor = input->display->cursors[input->current_cursor];
2573 if (index >= (int) cursor->image_count) {
2574 fprintf(stderr, "cursor index out of range\n");
2578 image = cursor->images[index];
2579 buffer = wl_cursor_image_get_buffer(image);
2583 wl_pointer_set_cursor(input->pointer, input->pointer_enter_serial,
2584 input->pointer_surface,
2585 image->hotspot_x, image->hotspot_y);
2586 wl_surface_attach(input->pointer_surface, buffer, 0, 0);
2587 wl_surface_damage(input->pointer_surface, 0, 0,
2588 image->width, image->height);
2591 static const struct wl_callback_listener pointer_surface_listener;
2594 pointer_surface_frame_callback(void *data, struct wl_callback *callback,
2597 struct input *input = data;
2598 struct wl_cursor *cursor;
2602 assert(callback == input->cursor_frame_cb);
2603 wl_callback_destroy(callback);
2604 input->cursor_frame_cb = NULL;
2607 if (input->current_cursor == CURSOR_BLANK) {
2608 wl_pointer_set_cursor(input->pointer,
2609 input->pointer_enter_serial,
2614 if (input->current_cursor == CURSOR_UNSET)
2616 cursor = input->display->cursors[input->current_cursor];
2620 /* FIXME We don't have the current time on the first call so we set
2621 * the animation start to the time of the first frame callback. */
2623 input->cursor_anim_start = 0;
2624 else if (input->cursor_anim_start == 0)
2625 input->cursor_anim_start = time;
2627 if (time == 0 || input->cursor_anim_start == 0)
2630 i = wl_cursor_frame(cursor, time - input->cursor_anim_start);
2632 input_set_pointer_image_index(input, i);
2634 if (cursor->image_count == 1)
2637 input->cursor_frame_cb = wl_surface_frame(input->pointer_surface);
2638 wl_callback_add_listener(input->cursor_frame_cb,
2639 &pointer_surface_listener, input);
2642 static const struct wl_callback_listener pointer_surface_listener = {
2643 pointer_surface_frame_callback
2647 input_set_pointer_image(struct input *input, int pointer)
2651 if (input->pointer_enter_serial > input->cursor_serial)
2654 if (!force && pointer == input->current_cursor)
2657 input->current_cursor = pointer;
2658 input->cursor_serial = input->pointer_enter_serial;
2659 if (!input->cursor_frame_cb)
2660 pointer_surface_frame_callback(input, NULL, 0);
2662 /* The current frame callback may be stuck if, for instance,
2663 * the set cursor request was processed by the server after
2664 * this client lost the focus. In this case the cursor surface
2665 * might not be mapped and the frame callback wouldn't ever
2666 * complete. Send a set_cursor and attach to try to map the
2667 * cursor surface again so that the callback will finish */
2668 input_set_pointer_image_index(input, 0);
2672 struct wl_data_device *
2673 input_get_data_device(struct input *input)
2675 return input->data_device;
2679 input_set_selection(struct input *input,
2680 struct wl_data_source *source, uint32_t time)
2682 wl_data_device_set_selection(input->data_device, source, time);
2686 input_accept(struct input *input, const char *type)
2688 wl_data_offer_accept(input->drag_offer->offer,
2689 input->pointer_enter_serial, type);
2693 offer_io_func(struct task *task, uint32_t events)
2695 struct data_offer *offer =
2696 container_of(task, struct data_offer, io_task);
2700 len = read(offer->fd, buffer, sizeof buffer);
2701 offer->func(buffer, len,
2702 offer->x, offer->y, offer->user_data);
2706 data_offer_destroy(offer);
2711 data_offer_receive_data(struct data_offer *offer, const char *mime_type,
2712 data_func_t func, void *user_data)
2716 if (pipe2(p, O_CLOEXEC) == -1)
2719 wl_data_offer_receive(offer->offer, mime_type, p[1]);
2722 offer->io_task.run = offer_io_func;
2726 offer->user_data = user_data;
2728 display_watch_fd(offer->input->display,
2729 offer->fd, EPOLLIN, &offer->io_task);
2733 input_receive_drag_data(struct input *input, const char *mime_type,
2734 data_func_t func, void *data)
2736 data_offer_receive_data(input->drag_offer, mime_type, func, data);
2737 input->drag_offer->x = input->sx;
2738 input->drag_offer->y = input->sy;
2742 input_receive_selection_data(struct input *input, const char *mime_type,
2743 data_func_t func, void *data)
2747 if (input->selection_offer == NULL)
2750 for (p = input->selection_offer->types.data; *p; p++)
2751 if (strcmp(mime_type, *p) == 0)
2757 data_offer_receive_data(input->selection_offer,
2758 mime_type, func, data);
2763 input_receive_selection_data_to_fd(struct input *input,
2764 const char *mime_type, int fd)
2766 if (input->selection_offer)
2767 wl_data_offer_receive(input->selection_offer->offer,
2774 window_move(struct window *window, struct input *input, uint32_t serial)
2776 if (!window->shell_surface)
2779 wl_shell_surface_move(window->shell_surface, input->seat, serial);
2783 idle_resize(struct window *window)
2785 struct widget *widget;
2787 window->resize_needed = 0;
2788 widget = window->widget;
2789 widget_set_allocation(widget,
2790 window->pending_allocation.x,
2791 window->pending_allocation.y,
2792 window->pending_allocation.width,
2793 window->pending_allocation.height);
2795 if (window->input_region) {
2796 wl_region_destroy(window->input_region);
2797 window->input_region = NULL;
2800 if (window->opaque_region) {
2801 wl_region_destroy(window->opaque_region);
2802 window->opaque_region = NULL;
2805 if (widget->resize_handler)
2806 widget->resize_handler(widget,
2807 widget->allocation.width,
2808 widget->allocation.height,
2811 if (window->allocation.width != widget->allocation.width ||
2812 window->allocation.height != widget->allocation.height) {
2813 window->allocation = widget->allocation;
2814 window_schedule_redraw(window);
2819 window_schedule_resize(struct window *window, int width, int height)
2821 window->pending_allocation.x = 0;
2822 window->pending_allocation.y = 0;
2823 window->pending_allocation.width = width;
2824 window->pending_allocation.height = height;
2826 if (window->min_allocation.width == 0)
2827 window->min_allocation = window->pending_allocation;
2828 if (window->pending_allocation.width < window->min_allocation.width)
2829 window->pending_allocation.width = window->min_allocation.width;
2830 if (window->pending_allocation.height < window->min_allocation.height)
2831 window->pending_allocation.height = window->min_allocation.height;
2833 window->resize_needed = 1;
2834 window_schedule_redraw(window);
2838 widget_schedule_resize(struct widget *widget, int32_t width, int32_t height)
2840 window_schedule_resize(widget->window, width, height);
2844 handle_ping(void *data, struct wl_shell_surface *shell_surface,
2847 wl_shell_surface_pong(shell_surface, serial);
2851 handle_configure(void *data, struct wl_shell_surface *shell_surface,
2852 uint32_t edges, int32_t width, int32_t height)
2854 struct window *window = data;
2856 window->resize_edges = edges;
2857 window_schedule_resize(window, width, height);
2861 menu_destroy(struct menu *menu)
2863 widget_destroy(menu->widget);
2864 window_destroy(menu->window);
2869 handle_popup_done(void *data, struct wl_shell_surface *shell_surface)
2871 struct window *window = data;
2872 struct menu *menu = window->widget->user_data;
2874 /* FIXME: Need more context in this event, at least the input
2875 * device. Or just use wl_callback. And this really needs to
2876 * be a window vfunc that the menu can set. And we need the
2879 menu->func(window->parent, menu->current, window->parent->user_data);
2880 input_ungrab(menu->input);
2884 static const struct wl_shell_surface_listener shell_surface_listener = {
2891 window_get_allocation(struct window *window,
2892 struct rectangle *allocation)
2894 *allocation = window->allocation;
2898 widget_redraw(struct widget *widget)
2900 struct widget *child;
2902 if (widget->redraw_handler)
2903 widget->redraw_handler(widget, widget->user_data);
2904 wl_list_for_each(child, &widget->child_list, link)
2905 widget_redraw(child);
2909 frame_callback(void *data, struct wl_callback *callback, uint32_t time)
2911 struct window *window = data;
2913 assert(callback == window->frame_cb);
2914 wl_callback_destroy(callback);
2915 window->frame_cb = 0;
2916 window->redraw_scheduled = 0;
2917 if (window->redraw_needed)
2918 window_schedule_redraw(window);
2921 static const struct wl_callback_listener listener = {
2926 idle_redraw(struct task *task, uint32_t events)
2928 struct window *window = container_of(task, struct window, redraw_task);
2930 if (window->resize_needed)
2931 idle_resize(window);
2933 window_create_surface(window);
2934 widget_redraw(window->widget);
2935 window_flush(window);
2936 window->redraw_needed = 0;
2937 wl_list_init(&window->redraw_task.link);
2939 window->frame_cb = wl_surface_frame(window->surface);
2940 wl_callback_add_listener(window->frame_cb, &listener, window);
2944 window_schedule_redraw(struct window *window)
2946 window->redraw_needed = 1;
2947 if (!window->redraw_scheduled) {
2948 window->redraw_task.run = idle_redraw;
2949 display_defer(window->display, &window->redraw_task);
2950 window->redraw_scheduled = 1;
2955 window_set_fullscreen(struct window *window, int fullscreen)
2957 if (!window->display->shell)
2960 if ((window->type == TYPE_FULLSCREEN) == fullscreen)
2964 window->type = TYPE_FULLSCREEN;
2965 window->saved_allocation = window->allocation;
2966 wl_shell_surface_set_fullscreen(window->shell_surface,
2967 WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
2970 window->type = TYPE_TOPLEVEL;
2971 wl_shell_surface_set_toplevel(window->shell_surface);
2972 window_schedule_resize(window,
2973 window->saved_allocation.width,
2974 window->saved_allocation.height);
2979 window_set_maximized(struct window *window, int maximized)
2981 if (!window->display->shell)
2984 if ((window->type == TYPE_MAXIMIZED) == maximized)
2987 if (window->type == TYPE_TOPLEVEL) {
2988 window->saved_allocation = window->allocation;
2989 wl_shell_surface_set_maximized(window->shell_surface, NULL);
2990 window->type = TYPE_MAXIMIZED;
2992 wl_shell_surface_set_toplevel(window->shell_surface);
2993 window->type = TYPE_TOPLEVEL;
2994 window_schedule_resize(window,
2995 window->saved_allocation.width,
2996 window->saved_allocation.height);
3001 window_set_user_data(struct window *window, void *data)
3003 window->user_data = data;
3007 window_get_user_data(struct window *window)
3009 return window->user_data;
3013 window_set_key_handler(struct window *window,
3014 window_key_handler_t handler)
3016 window->key_handler = handler;
3020 window_set_keyboard_focus_handler(struct window *window,
3021 window_keyboard_focus_handler_t handler)
3023 window->keyboard_focus_handler = handler;
3027 window_set_data_handler(struct window *window, window_data_handler_t handler)
3029 window->data_handler = handler;
3033 window_set_drop_handler(struct window *window, window_drop_handler_t handler)
3035 window->drop_handler = handler;
3039 window_set_close_handler(struct window *window,
3040 window_close_handler_t handler)
3042 window->close_handler = handler;
3046 window_set_fullscreen_handler(struct window *window,
3047 window_fullscreen_handler_t handler)
3049 window->fullscreen_handler = handler;
3053 window_set_title(struct window *window, const char *title)
3055 free(window->title);
3056 window->title = strdup(title);
3057 if (window->shell_surface)
3058 wl_shell_surface_set_title(window->shell_surface, title);
3062 window_get_title(struct window *window)
3064 return window->title;
3068 window_set_text_cursor_position(struct window *window, int32_t x, int32_t y)
3070 struct text_cursor_position *text_cursor_position =
3071 window->display->text_cursor_position;
3073 if (!text_cursor_position)
3076 text_cursor_position_notify(text_cursor_position,
3078 wl_fixed_from_int(x),
3079 wl_fixed_from_int(y));
3083 window_damage(struct window *window, int32_t x, int32_t y,
3084 int32_t width, int32_t height)
3086 wl_surface_damage(window->surface, x, y, width, height);
3090 surface_enter(void *data,
3091 struct wl_surface *wl_surface, struct wl_output *wl_output)
3093 struct window *window = data;
3094 struct output *output;
3095 struct output *output_found = NULL;
3096 struct window_output *window_output;
3098 wl_list_for_each(output, &window->display->output_list, link) {
3099 if (output->output == wl_output) {
3100 output_found = output;
3108 window_output = malloc (sizeof *window_output);
3109 window_output->output = output_found;
3111 wl_list_insert (&window->window_output_list, &window_output->link);
3115 surface_leave(void *data,
3116 struct wl_surface *wl_surface, struct wl_output *output)
3118 struct window *window = data;
3119 struct window_output *window_output;
3120 struct window_output *window_output_found = NULL;
3122 wl_list_for_each(window_output, &window->window_output_list, link) {
3123 if (window_output->output->output == output) {
3124 window_output_found = window_output;
3129 if (window_output_found) {
3130 wl_list_remove(&window_output_found->link);
3131 free(window_output_found);
3135 static const struct wl_surface_listener surface_listener = {
3140 static struct window *
3141 window_create_internal(struct display *display,
3142 struct window *parent, int type)
3144 struct window *window;
3146 window = malloc(sizeof *window);
3150 memset(window, 0, sizeof *window);
3151 window->display = display;
3152 window->parent = parent;
3153 window->surface = wl_compositor_create_surface(display->compositor);
3154 wl_surface_add_listener(window->surface, &surface_listener, window);
3155 if (type != TYPE_CUSTOM && display->shell) {
3156 window->shell_surface =
3157 wl_shell_get_shell_surface(display->shell,
3160 window->allocation.x = 0;
3161 window->allocation.y = 0;
3162 window->allocation.width = 0;
3163 window->allocation.height = 0;
3164 window->saved_allocation = window->allocation;
3165 window->transparent = 1;
3166 window->type = type;
3167 window->input_region = NULL;
3168 window->opaque_region = NULL;
3171 #ifdef HAVE_CAIRO_EGL
3172 window->buffer_type = WINDOW_BUFFER_TYPE_EGL_WINDOW;
3174 window->buffer_type = WINDOW_BUFFER_TYPE_SHM;
3177 window->buffer_type = WINDOW_BUFFER_TYPE_SHM;
3179 wl_surface_set_user_data(window->surface, window);
3180 wl_list_insert(display->window_list.prev, &window->link);
3181 wl_list_init(&window->redraw_task.link);
3183 if (window->shell_surface) {
3184 wl_shell_surface_set_user_data(window->shell_surface, window);
3185 wl_shell_surface_add_listener(window->shell_surface,
3186 &shell_surface_listener, window);
3189 wl_list_init (&window->window_output_list);
3195 window_create(struct display *display)
3197 struct window *window;
3199 window = window_create_internal(display, NULL, TYPE_NONE);
3207 window_create_custom(struct display *display)
3209 struct window *window;
3211 window = window_create_internal(display, NULL, TYPE_CUSTOM);
3219 window_create_transient(struct display *display, struct window *parent,
3220 int32_t x, int32_t y, uint32_t flags)
3222 struct window *window;
3224 window = window_create_internal(parent->display,
3225 parent, TYPE_TRANSIENT);
3233 wl_shell_surface_set_transient(window->shell_surface,
3234 window->parent->surface,
3235 window->x, window->y, flags);
3241 menu_set_item(struct menu *menu, int sy)
3245 next = (sy - 8) / 20;
3246 if (menu->current != next) {
3247 menu->current = next;
3248 widget_schedule_redraw(menu->widget);
3253 menu_motion_handler(struct widget *widget,
3254 struct input *input, uint32_t time,
3255 float x, float y, void *data)
3257 struct menu *menu = data;
3259 if (widget == menu->widget)
3260 menu_set_item(data, y);
3262 return CURSOR_LEFT_PTR;
3266 menu_enter_handler(struct widget *widget,
3267 struct input *input, float x, float y, void *data)
3269 struct menu *menu = data;
3271 if (widget == menu->widget)
3272 menu_set_item(data, y);
3274 return CURSOR_LEFT_PTR;
3278 menu_leave_handler(struct widget *widget, struct input *input, void *data)
3280 struct menu *menu = data;
3282 if (widget == menu->widget)
3283 menu_set_item(data, -200);
3287 menu_button_handler(struct widget *widget,
3288 struct input *input, uint32_t time,
3289 uint32_t button, enum wl_pointer_button_state state,
3293 struct menu *menu = data;
3295 if (state == WL_POINTER_BUTTON_STATE_PRESSED &&
3296 time - menu->time > 500) {
3297 /* Either relase after press-drag-release or
3298 * click-motion-click. */
3299 menu->func(menu->window->parent,
3300 menu->current, menu->window->parent->user_data);
3301 input_ungrab(input);
3307 menu_redraw_handler(struct widget *widget, void *data)
3310 const int32_t r = 3, margin = 3;
3311 struct menu *menu = data;
3312 int32_t width, height, i;
3313 struct window *window = widget->window;
3315 cr = cairo_create(window->cairo_surface);
3316 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
3317 cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0);
3320 width = window->allocation.width;
3321 height = window->allocation.height;
3322 rounded_rect(cr, 0, 0, width, height, r);
3324 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
3325 cairo_set_source_rgba(cr, 0.0, 0.0, 0.4, 0.8);
3328 for (i = 0; i < menu->count; i++) {
3329 if (i == menu->current) {
3330 cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
3331 cairo_rectangle(cr, margin, i * 20 + margin,
3332 width - 2 * margin, 20);
3334 cairo_set_source_rgb(cr, 0.0, 0.0, 0.0);
3335 cairo_move_to(cr, 10, i * 20 + 16);
3336 cairo_show_text(cr, menu->entries[i]);
3338 cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
3339 cairo_move_to(cr, 10, i * 20 + 16);
3340 cairo_show_text(cr, menu->entries[i]);
3348 window_show_menu(struct display *display,
3349 struct input *input, uint32_t time, struct window *parent,
3350 int32_t x, int32_t y,
3351 menu_func_t func, const char **entries, int count)
3353 struct window *window;
3355 const int32_t margin = 3;
3357 menu = malloc(sizeof *menu);
3361 window = window_create_internal(parent->display, parent, TYPE_MENU);
3367 menu->window = window;
3368 menu->widget = window_add_widget(menu->window, menu);
3369 menu->entries = entries;
3370 menu->count = count;
3374 menu->input = input;
3375 window->type = TYPE_MENU;
3379 input_ungrab(input);
3380 wl_shell_surface_set_popup(window->shell_surface, input->seat,
3381 display_get_serial(window->display),
3382 window->parent->surface,
3383 window->x, window->y, 0);
3385 widget_set_redraw_handler(menu->widget, menu_redraw_handler);
3386 widget_set_enter_handler(menu->widget, menu_enter_handler);
3387 widget_set_leave_handler(menu->widget, menu_leave_handler);
3388 widget_set_motion_handler(menu->widget, menu_motion_handler);
3389 widget_set_button_handler(menu->widget, menu_button_handler);
3391 input_grab(input, menu->widget, 0);
3392 window_schedule_resize(window, 200, count * 20 + margin * 2);
3396 window_set_buffer_type(struct window *window, enum window_buffer_type type)
3398 window->buffer_type = type;
3403 display_handle_geometry(void *data,
3404 struct wl_output *wl_output,
3407 int physical_height,
3413 struct output *output = data;
3415 output->allocation.x = x;
3416 output->allocation.y = y;
3420 display_handle_mode(void *data,
3421 struct wl_output *wl_output,
3427 struct output *output = data;
3428 struct display *display = output->display;
3430 if (flags & WL_OUTPUT_MODE_CURRENT) {
3431 output->allocation.width = width;
3432 output->allocation.height = height;
3433 if (display->output_configure_handler)
3434 (*display->output_configure_handler)(
3435 output, display->user_data);
3439 static const struct wl_output_listener output_listener = {
3440 display_handle_geometry,
3445 display_add_output(struct display *d, uint32_t id)
3447 struct output *output;
3449 output = malloc(sizeof *output);
3453 memset(output, 0, sizeof *output);
3454 output->display = d;
3456 wl_display_bind(d->display, id, &wl_output_interface);
3457 wl_list_insert(d->output_list.prev, &output->link);
3459 wl_output_add_listener(output->output, &output_listener, output);
3463 output_destroy(struct output *output)
3465 if (output->destroy_handler)
3466 (*output->destroy_handler)(output, output->user_data);
3468 wl_output_destroy(output->output);
3469 wl_list_remove(&output->link);
3474 display_set_output_configure_handler(struct display *display,
3475 display_output_handler_t handler)
3477 struct output *output;
3479 display->output_configure_handler = handler;
3483 wl_list_for_each(output, &display->output_list, link)
3484 (*display->output_configure_handler)(output,
3485 display->user_data);
3489 output_set_user_data(struct output *output, void *data)
3491 output->user_data = data;
3495 output_get_user_data(struct output *output)
3497 return output->user_data;
3501 output_set_destroy_handler(struct output *output,
3502 display_output_handler_t handler)
3504 output->destroy_handler = handler;
3505 /* FIXME: implement this, once we have way to remove outputs */
3509 output_get_allocation(struct output *output, struct rectangle *allocation)
3511 *allocation = output->allocation;
3515 output_get_wl_output(struct output *output)
3517 return output->output;
3521 fini_xkb(struct input *input)
3523 xkb_state_unref(input->xkb.state);
3524 xkb_map_unref(input->xkb.keymap);
3528 display_add_input(struct display *d, uint32_t id)
3530 struct input *input;
3532 input = malloc(sizeof *input);
3536 memset(input, 0, sizeof *input);
3538 input->seat = wl_display_bind(d->display, id, &wl_seat_interface);
3539 input->pointer_focus = NULL;
3540 input->keyboard_focus = NULL;
3541 wl_list_insert(d->input_list.prev, &input->link);
3543 wl_seat_add_listener(input->seat, &seat_listener, input);
3544 wl_seat_set_user_data(input->seat, input);
3546 input->data_device =
3547 wl_data_device_manager_get_data_device(d->data_device_manager,
3549 wl_data_device_add_listener(input->data_device, &data_device_listener,
3552 input->pointer_surface = wl_compositor_create_surface(d->compositor);
3554 input->repeat_timer_fd = timerfd_create(CLOCK_MONOTONIC,
3555 TFD_CLOEXEC | TFD_NONBLOCK);
3556 input->repeat_task.run = keyboard_repeat_func;
3557 display_watch_fd(d, input->repeat_timer_fd,
3558 EPOLLIN, &input->repeat_task);
3562 input_destroy(struct input *input)
3564 input_remove_keyboard_focus(input);
3565 input_remove_pointer_focus(input);
3567 if (input->drag_offer)
3568 data_offer_destroy(input->drag_offer);
3570 if (input->selection_offer)
3571 data_offer_destroy(input->selection_offer);
3573 wl_data_device_destroy(input->data_device);
3576 wl_surface_destroy(input->pointer_surface);
3578 wl_list_remove(&input->link);
3579 wl_seat_destroy(input->seat);
3580 close(input->repeat_timer_fd);
3585 init_workspace_manager(struct display *d, uint32_t id)
3587 d->workspace_manager =
3588 wl_display_bind(d->display, id, &workspace_manager_interface);
3589 if (d->workspace_manager != NULL)
3590 workspace_manager_add_listener(d->workspace_manager,
3591 &workspace_manager_listener,
3596 display_handle_global(struct wl_display *display, uint32_t id,
3597 const char *interface, uint32_t version, void *data)
3599 struct display *d = data;
3601 if (strcmp(interface, "wl_compositor") == 0) {
3603 wl_display_bind(display, id, &wl_compositor_interface);
3604 } else if (strcmp(interface, "wl_output") == 0) {
3605 display_add_output(d, id);
3606 } else if (strcmp(interface, "wl_seat") == 0) {
3607 display_add_input(d, id);
3608 } else if (strcmp(interface, "wl_shell") == 0) {
3609 d->shell = wl_display_bind(display, id, &wl_shell_interface);
3610 } else if (strcmp(interface, "wl_shm") == 0) {
3611 d->shm = wl_display_bind(display, id, &wl_shm_interface);
3612 } else if (strcmp(interface, "wl_data_device_manager") == 0) {
3613 d->data_device_manager =
3614 wl_display_bind(display, id,
3615 &wl_data_device_manager_interface);
3616 } else if (strcmp(interface, "text_cursor_position") == 0) {
3617 d->text_cursor_position =
3618 wl_display_bind(display, id,
3619 &text_cursor_position_interface);
3620 } else if (strcmp(interface, "workspace_manager") == 0) {
3621 init_workspace_manager(d, id);
3625 #ifdef HAVE_CAIRO_EGL
3627 init_egl(struct display *d)
3629 EGLint major, minor;
3632 #ifdef USE_CAIRO_GLESV2
3633 # define GL_BIT EGL_OPENGL_ES2_BIT
3635 # define GL_BIT EGL_OPENGL_BIT
3638 static const EGLint argb_cfg_attribs[] = {
3639 EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PIXMAP_BIT,
3645 EGL_RENDERABLE_TYPE, GL_BIT,
3649 #ifdef USE_CAIRO_GLESV2
3650 static const EGLint context_attribs[] = {
3651 EGL_CONTEXT_CLIENT_VERSION, 2,
3654 EGLint api = EGL_OPENGL_ES_API;
3656 EGLint *context_attribs = NULL;
3657 EGLint api = EGL_OPENGL_API;
3660 d->dpy = eglGetDisplay(d->display);
3661 if (!eglInitialize(d->dpy, &major, &minor)) {
3662 fprintf(stderr, "failed to initialize display\n");
3666 if (!eglBindAPI(api)) {
3667 fprintf(stderr, "failed to bind api EGL_OPENGL_API\n");
3671 if (!eglChooseConfig(d->dpy, argb_cfg_attribs,
3672 &d->argb_config, 1, &n) || n != 1) {
3673 fprintf(stderr, "failed to choose argb config\n");
3677 d->argb_ctx = eglCreateContext(d->dpy, d->argb_config,
3678 EGL_NO_CONTEXT, context_attribs);
3679 if (d->argb_ctx == NULL) {
3680 fprintf(stderr, "failed to create context\n");
3684 if (!eglMakeCurrent(d->dpy, NULL, NULL, d->argb_ctx)) {
3685 fprintf(stderr, "failed to make context current\n");
3689 #ifdef HAVE_CAIRO_EGL
3690 d->argb_device = cairo_egl_device_create(d->dpy, d->argb_ctx);
3691 if (cairo_device_status(d->argb_device) != CAIRO_STATUS_SUCCESS) {
3692 fprintf(stderr, "failed to get cairo egl argb device\n");
3701 fini_egl(struct display *display)
3703 #ifdef HAVE_CAIRO_EGL
3704 cairo_device_destroy(display->argb_device);
3707 eglMakeCurrent(display->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE,
3710 eglTerminate(display->dpy);
3716 event_mask_update(uint32_t mask, void *data)
3718 struct display *d = data;
3726 handle_display_data(struct task *task, uint32_t events)
3728 struct display *display =
3729 container_of(task, struct display, display_task);
3731 wl_display_iterate(display->display, display->mask);
3735 display_create(int argc, char *argv[])
3739 d = malloc(sizeof *d);
3743 memset(d, 0, sizeof *d);
3745 d->display = wl_display_connect(NULL);
3746 if (d->display == NULL) {
3747 fprintf(stderr, "failed to create display: %m\n");
3751 d->epoll_fd = os_epoll_create_cloexec();
3752 d->display_fd = wl_display_get_fd(d->display, event_mask_update, d);
3753 d->display_task.run = handle_display_data;
3754 display_watch_fd(d, d->display_fd, EPOLLIN, &d->display_task);
3756 wl_list_init(&d->deferred_list);
3757 wl_list_init(&d->input_list);
3758 wl_list_init(&d->output_list);
3760 d->xkb_context = xkb_context_new(0);
3761 if (d->xkb_context == NULL) {
3762 fprintf(stderr, "Failed to create XKB context\n");
3766 /* Set up listener so we'll catch all events. */
3767 wl_display_add_global_listener(d->display,
3768 display_handle_global, d);
3770 /* Process connection events. */
3771 wl_display_iterate(d->display, WL_DISPLAY_READABLE);
3772 #ifdef HAVE_CAIRO_EGL
3773 if (init_egl(d) < 0)
3777 d->image_target_texture_2d =
3778 (void *) eglGetProcAddress("glEGLImageTargetTexture2DOES");
3779 d->create_image = (void *) eglGetProcAddress("eglCreateImageKHR");
3780 d->destroy_image = (void *) eglGetProcAddress("eglDestroyImageKHR");
3784 d->theme = theme_create();
3786 wl_list_init(&d->window_list);
3789 d->workspace_count = 1;
3795 display_destroy_outputs(struct display *display)
3798 struct output *output;
3800 wl_list_for_each_safe(output, tmp, &display->output_list, link)
3801 output_destroy(output);
3805 display_destroy_inputs(struct display *display)
3808 struct input *input;
3810 wl_list_for_each_safe(input, tmp, &display->input_list, link)
3811 input_destroy(input);
3815 display_destroy(struct display *display)
3817 if (!wl_list_empty(&display->window_list))
3818 fprintf(stderr, "toytoolkit warning: windows exist.\n");
3820 if (!wl_list_empty(&display->deferred_list))
3821 fprintf(stderr, "toytoolkit warning: deferred tasks exist.\n");
3823 display_destroy_outputs(display);
3824 display_destroy_inputs(display);
3826 xkb_context_unref(display->xkb_context);
3828 theme_destroy(display->theme);
3829 destroy_cursors(display);
3831 #ifdef HAVE_CAIRO_EGL
3836 wl_shell_destroy(display->shell);
3839 wl_shm_destroy(display->shm);
3841 if (display->data_device_manager)
3842 wl_data_device_manager_destroy(display->data_device_manager);
3844 wl_compositor_destroy(display->compositor);
3846 close(display->epoll_fd);
3848 wl_display_flush(display->display);
3849 wl_display_disconnect(display->display);
3854 display_set_user_data(struct display *display, void *data)
3856 display->user_data = data;
3860 display_get_user_data(struct display *display)
3862 return display->user_data;
3866 display_get_display(struct display *display)
3868 return display->display;
3872 display_get_output(struct display *display)
3874 return container_of(display->output_list.next, struct output, link);
3877 struct wl_compositor *
3878 display_get_compositor(struct display *display)
3880 return display->compositor;
3884 display_get_serial(struct display *display)
3886 return display->serial;
3890 display_get_egl_display(struct display *d)
3895 struct wl_data_source *
3896 display_create_data_source(struct display *display)
3898 return wl_data_device_manager_create_data_source(display->data_device_manager);
3902 display_get_argb_egl_config(struct display *d)
3904 return d->argb_config;
3908 display_get_shell(struct display *display)
3910 return display->shell;
3914 display_acquire_window_surface(struct display *display,
3915 struct window *window,
3918 #ifdef HAVE_CAIRO_EGL
3919 struct egl_window_surface_data *data;
3920 cairo_device_t *device;
3922 if (!window->cairo_surface)
3924 device = cairo_surface_get_device(window->cairo_surface);
3929 if (device == display->argb_device)
3930 ctx = display->argb_ctx;
3935 data = cairo_surface_get_user_data(window->cairo_surface,
3938 cairo_device_flush(device);
3939 cairo_device_acquire(device);
3940 if (!eglMakeCurrent(display->dpy, data->surf, data->surf, ctx))
3941 fprintf(stderr, "failed to make surface current\n");
3950 display_release_window_surface(struct display *display,
3951 struct window *window)
3953 #ifdef HAVE_CAIRO_EGL
3954 cairo_device_t *device;
3956 device = cairo_surface_get_device(window->cairo_surface);
3960 if (!eglMakeCurrent(display->dpy, NULL, NULL, display->argb_ctx))
3961 fprintf(stderr, "failed to make context current\n");
3962 cairo_device_release(device);
3967 display_defer(struct display *display, struct task *task)
3969 wl_list_insert(&display->deferred_list, &task->link);
3973 display_watch_fd(struct display *display,
3974 int fd, uint32_t events, struct task *task)
3976 struct epoll_event ep;
3980 epoll_ctl(display->epoll_fd, EPOLL_CTL_ADD, fd, &ep);
3984 display_run(struct display *display)
3987 struct epoll_event ep[16];
3990 display->running = 1;
3992 wl_display_flush(display->display);
3994 while (!wl_list_empty(&display->deferred_list)) {
3995 task = container_of(display->deferred_list.prev,
3997 wl_list_remove(&task->link);
4001 if (!display->running)
4004 wl_display_flush(display->display);
4006 count = epoll_wait(display->epoll_fd,
4007 ep, ARRAY_LENGTH(ep), -1);
4008 for (i = 0; i < count; i++) {
4009 task = ep[i].data.ptr;
4010 task->run(task, ep[i].events);
4016 display_exit(struct display *display)
4018 display->running = 0;