diff options
Diffstat (limited to 'clients/window.c')
-rw-r--r-- | clients/window.c | 641 |
1 files changed, 339 insertions, 302 deletions
diff --git a/clients/window.c b/clients/window.c index d8d79d04..e770a040 100644 --- a/clients/window.c +++ b/clients/window.c @@ -65,6 +65,7 @@ typedef void *EGLContext; #include <linux/input.h> #include <wayland-client.h> #include "../shared/cairo-util.h" +#include "xdg-shell-client-protocol.h" #include "text-cursor-position-client-protocol.h" #include "workspaces-client-protocol.h" #include "../shared/os-compatibility.h" @@ -85,11 +86,11 @@ struct display { struct wl_registry *registry; struct wl_compositor *compositor; struct wl_subcompositor *subcompositor; - struct wl_shell *shell; struct wl_shm *shm; struct wl_data_device_manager *data_device_manager; struct text_cursor_position *text_cursor_position; struct workspace_manager *workspace_manager; + struct xdg_shell *xdg_shell; EGLDisplay dpy; EGLConfig argb_config; EGLContext argb_ctx; @@ -134,16 +135,6 @@ struct display { int seat_version; }; -enum { - TYPE_NONE, - TYPE_TOPLEVEL, - TYPE_FULLSCREEN, - TYPE_MAXIMIZED, - TYPE_TRANSIENT, - TYPE_MENU, - TYPE_CUSTOM -}; - struct window_output { struct output *output; struct wl_list link; @@ -227,18 +218,17 @@ struct window { struct rectangle min_allocation; struct rectangle pending_allocation; int x, y; - int resize_edges; int redraw_needed; int redraw_task_scheduled; struct task redraw_task; int resize_needed; - int saved_type; - int type; - int focus_count; + int custom; + int focused; int resizing; - int fullscreen_method; - int configure_requests; + + int fullscreen; + int maximized; enum preferred_format preferred_format; @@ -251,7 +241,10 @@ struct window { window_output_handler_t output_handler; struct surface *main_surface; - struct wl_shell_surface *shell_surface; + struct xdg_surface *xdg_surface; + struct xdg_popup *xdg_popup; + + struct window *transient_for; struct window_frame *frame; @@ -355,6 +348,8 @@ struct output { struct wl_list link; int transform; int scale; + char *make; + char *model; display_output_handler_t destroy_handler; void *user_data; @@ -382,7 +377,6 @@ struct menu { struct tooltip { struct widget *parent; - struct window *window; struct widget *widget; char *entry; struct task tooltip_task; @@ -402,22 +396,6 @@ enum { CURSOR_UNSET }; -enum window_location { - WINDOW_INTERIOR = 0, - WINDOW_RESIZING_TOP = 1, - WINDOW_RESIZING_BOTTOM = 2, - WINDOW_RESIZING_LEFT = 4, - WINDOW_RESIZING_TOP_LEFT = 5, - WINDOW_RESIZING_BOTTOM_LEFT = 6, - WINDOW_RESIZING_RIGHT = 8, - WINDOW_RESIZING_TOP_RIGHT = 9, - WINDOW_RESIZING_BOTTOM_RIGHT = 10, - WINDOW_RESIZING_MASK = 15, - WINDOW_EXTERIOR = 16, - WINDOW_TITLEBAR = 17, - WINDOW_CLIENT_AREA = 18, -}; - static const cairo_user_data_key_t shm_surface_data_key; /* #define DEBUG */ @@ -1303,6 +1281,10 @@ create_cursors(struct display *display) weston_config_destroy(config); display->cursor_theme = wl_cursor_theme_load(theme, size, display->shm); + if (!display->cursor_theme) { + fprintf(stderr, "could not load theme '%s'\n", theme); + return; + } free(theme); display->cursors = xmalloc(ARRAY_LENGTH(cursors) * sizeof display->cursors[0]); @@ -1367,28 +1349,16 @@ surface_flush(struct surface *surface) int window_has_focus(struct window *window) { - return window->focus_count > 0; + return window->focused; } static void -window_flush(struct window *window) +window_close(struct window *window) { - struct surface *surface; - - if (window->type == TYPE_NONE) { - window->type = TYPE_TOPLEVEL; - if (window->shell_surface) - wl_shell_surface_set_toplevel(window->shell_surface); - } - - wl_list_for_each(surface, &window->subsurface_list, link) { - if (surface == window->main_surface) - continue; - - surface_flush(surface); - } - - surface_flush(window->main_surface); + if (window->close_handler) + window->close_handler(window->user_data); + else + display_exit(window->display); } struct display * @@ -1398,7 +1368,7 @@ window_get_display(struct window *window) } static void -surface_create_surface(struct surface *surface, int dx, int dy, uint32_t flags) +surface_create_surface(struct surface *surface, uint32_t flags) { struct display *display = surface->window->display; struct rectangle allocation = surface->allocation; @@ -1418,7 +1388,7 @@ surface_create_surface(struct surface *surface, int dx, int dy, uint32_t flags) flags, &allocation); surface->cairo_surface = surface->toysurface->prepare( - surface->toysurface, dx, dy, + surface->toysurface, 0, 0, allocation.width, allocation.height, flags, surface->buffer_transform, surface->buffer_scale); } @@ -1428,8 +1398,6 @@ window_create_main_surface(struct window *window) { struct surface *surface = window->main_surface; uint32_t flags = 0; - int dx = 0; - int dy = 0; if (window->resizing) flags |= SURFACE_HINT_RESIZE; @@ -1437,17 +1405,7 @@ window_create_main_surface(struct window *window) if (window->preferred_format == WINDOW_PREFERRED_FORMAT_RGB565) flags |= SURFACE_HINT_RGB565; - if (window->resize_edges & WINDOW_RESIZING_LEFT) - dx = surface->server_allocation.width - - surface->allocation.width; - - if (window->resize_edges & WINDOW_RESIZING_TOP) - dy = surface->server_allocation.height - - surface->allocation.height; - - window->resize_edges = 0; - - surface_create_surface(surface, dx, dy, flags); + surface_create_surface(surface, flags); } int @@ -1552,8 +1510,10 @@ window_destroy(struct window *window) if (window->frame) window_frame_destroy(window->frame); - if (window->shell_surface) - wl_shell_surface_destroy(window->shell_surface); + if (window->xdg_surface) + xdg_surface_destroy(window->xdg_surface); + if (window->xdg_popup) + xdg_popup_destroy(window->xdg_popup); surface_destroy(window->main_surface); @@ -1717,7 +1677,7 @@ widget_get_cairo_surface(struct widget *widget) if (surface == window->main_surface) window_create_main_surface(window); else - surface_create_surface(surface, 0, 0, 0); + surface_create_surface(surface, 0); } return surface->cairo_surface; @@ -1977,6 +1937,7 @@ tooltip_redraw_handler(struct widget *widget, void *data) int32_t width, height; cr = widget_cairo_create(widget); + cairo_translate(cr, widget->allocation.x, widget->allocation.y); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0); cairo_paint(cr); @@ -1996,7 +1957,7 @@ tooltip_redraw_handler(struct widget *widget, void *data) } static cairo_text_extents_t -get_text_extents(struct tooltip *tooltip) +get_text_extents(struct display *display, struct tooltip *tooltip) { cairo_t *cr; cairo_text_extents_t extents; @@ -2005,7 +1966,7 @@ get_text_extents(struct tooltip *tooltip) * created yet, and parent does not have a valid surface * outside repaint, either. */ - cr = cairo_create(tooltip->window->display->dummy_surface); + cr = cairo_create(display->dummy_surface); cairo_text_extents(cr, tooltip->entry, &extents); cairo_destroy(cr); @@ -2017,7 +1978,6 @@ window_create_tooltip(struct tooltip *tooltip) { struct widget *parent = tooltip->parent; struct display *display = parent->window->display; - struct window *window; const int offset_y = 27; const int margin = 3; cairo_text_extents_t extents; @@ -2025,18 +1985,13 @@ window_create_tooltip(struct tooltip *tooltip) if (tooltip->widget) return 0; - window = window_create_transient(display, parent->window, tooltip->x, - tooltip->y + offset_y, - WL_SHELL_SURFACE_TRANSIENT_INACTIVE); - if (!window) - return -1; + tooltip->widget = window_add_subsurface(parent->window, tooltip, SUBSURFACE_DESYNCHRONIZED); - tooltip->window = window; - tooltip->widget = window_add_widget(tooltip->window, tooltip); - - extents = get_text_extents(tooltip); + extents = get_text_extents(display, tooltip); widget_set_redraw_handler(tooltip->widget, tooltip_redraw_handler); - window_schedule_resize(window, extents.width + 20, 20 + margin * 2); + widget_set_allocation(tooltip->widget, + tooltip->x, tooltip->y + offset_y, + extents.width + 20, 20 + margin * 2); return 0; } @@ -2052,9 +2007,7 @@ widget_destroy_tooltip(struct widget *parent) if (tooltip->widget) { widget_destroy(tooltip->widget); - window_destroy(tooltip->window); tooltip->widget = NULL; - tooltip->window = NULL; } close(tooltip->tooltip_fd); @@ -2118,7 +2071,6 @@ widget_set_tooltip(struct widget *parent, char *entry, float x, float y) parent->tooltip = tooltip; tooltip->parent = parent; tooltip->widget = NULL; - tooltip->window = NULL; tooltip->x = x; tooltip->y = y; tooltip->entry = strdup(entry); @@ -2162,13 +2114,13 @@ frame_resize_handler(struct widget *widget, struct rectangle input; struct rectangle opaque; - if (widget->window->type == TYPE_FULLSCREEN) { + if (widget->window->fullscreen) { interior.x = 0; interior.y = 0; interior.width = width; interior.height = height; } else { - if (widget->window->type == TYPE_MAXIMIZED) { + if (widget->window->maximized) { frame_set_flag(frame->frame, FRAME_FLAG_MAXIMIZED); } else { frame_unset_flag(frame->frame, FRAME_FLAG_MAXIMIZED); @@ -2186,7 +2138,7 @@ frame_resize_handler(struct widget *widget, child->resize_handler(child, interior.width, interior.height, child->user_data); - if (widget->window->type == TYPE_FULLSCREEN) { + if (widget->window->fullscreen) { width = child->allocation.width; height = child->allocation.height; } else { @@ -2202,7 +2154,7 @@ frame_resize_handler(struct widget *widget, widget->surface->input_region = wl_compositor_create_region(widget->window->display->compositor); - if (widget->window->type != TYPE_FULLSCREEN) { + if (!widget->window->fullscreen) { frame_input_rect(frame->frame, &input.x, &input.y, &input.width, &input.height); wl_region_add(widget->surface->input_region, @@ -2214,7 +2166,7 @@ frame_resize_handler(struct widget *widget, widget_set_allocation(widget, 0, 0, width, height); if (child->opaque) { - if (widget->window->type != TYPE_FULLSCREEN) { + if (!widget->window->fullscreen) { frame_opaque_rect(frame->frame, &opaque.x, &opaque.y, &opaque.width, &opaque.height); @@ -2238,10 +2190,10 @@ frame_redraw_handler(struct widget *widget, void *data) struct window_frame *frame = data; struct window *window = widget->window; - if (window->type == TYPE_FULLSCREEN) + if (window->fullscreen) return; - if (window->focus_count) { + if (window->focused) { frame_set_flag(frame->frame, FRAME_FLAG_ACTIVE); } else { frame_unset_flag(frame->frame, FRAME_FLAG_ACTIVE); @@ -2260,7 +2212,7 @@ frame_get_pointer_image_for_location(struct window_frame *frame, { struct window *window = frame->widget->window; - if (window->type != TYPE_TOPLEVEL) + if (window->custom) return CURSOR_LEFT_PTR; switch (location) { @@ -2295,10 +2247,7 @@ frame_menu_func(struct window *window, switch (index) { case 0: /* close */ - if (window->close_handler) - window->close_handler(window->user_data); - else - display_exit(window->display); + window_close(window); break; case 1: /* move to workspace above */ display = window->display; @@ -2398,8 +2347,10 @@ frame_handle_status(struct window_frame *frame, struct input *input, if (status & FRAME_STATUS_REPAINT) widget_schedule_redraw(frame->widget); - if (status & FRAME_STATUS_MINIMIZE) - fprintf(stderr,"Minimize stub\n"); + if (status & FRAME_STATUS_MINIMIZE) { + window_set_minimized(window); + frame_status_clear(frame->frame, FRAME_STATUS_MINIMIZE); + } if (status & FRAME_STATUS_MENU) { window_show_frame_menu(window, input, time); @@ -2407,35 +2358,32 @@ frame_handle_status(struct window_frame *frame, struct input *input, } if (status & FRAME_STATUS_MAXIMIZE) { - window_set_maximized(window, window->type != TYPE_MAXIMIZED); + window_set_maximized(window, !window->maximized); frame_status_clear(frame->frame, FRAME_STATUS_MAXIMIZE); } if (status & FRAME_STATUS_CLOSE) { - if (window->close_handler) - window->close_handler(window->user_data); - else - display_exit(window->display); + window_close(window); return; } - if ((status & FRAME_STATUS_MOVE) && window->shell_surface) { + if ((status & FRAME_STATUS_MOVE) && window->xdg_surface) { input_ungrab(input); - wl_shell_surface_move(window->shell_surface, - input_get_seat(input), - window->display->serial); + xdg_surface_move(window->xdg_surface, + input_get_seat(input), + window->display->serial); frame_status_clear(frame->frame, FRAME_STATUS_MOVE); } - if ((status & FRAME_STATUS_RESIZE) && window->shell_surface) { + if ((status & FRAME_STATUS_RESIZE) && window->xdg_surface) { input_ungrab(input); window->resizing = 1; - wl_shell_surface_resize(window->shell_surface, - input_get_seat(input), - window->display->serial, - location); + xdg_surface_resize(window->xdg_surface, + input_get_seat(input), + window->display->serial, + location); frame_status_clear(frame->frame, FRAME_STATUS_RESIZE); } @@ -2483,7 +2431,7 @@ window_frame_create(struct window *window, void *data) struct window_frame *frame; uint32_t buttons; - if (window->type == TYPE_CUSTOM) { + if (window->custom) { buttons = FRAME_BUTTON_NONE; } else { buttons = FRAME_BUTTON_ALL; @@ -2518,9 +2466,9 @@ window_frame_set_child_size(struct widget *widget, int child_width, struct theme *t = display->theme; int decoration_width, decoration_height; int width, height; - int margin = widget->window->type == TYPE_MAXIMIZED ? 0 : t->margin; + int margin = widget->window->maximized ? 0 : t->margin; - if (widget->window->type != TYPE_FULLSCREEN) { + if (!widget->window->fullscreen) { decoration_width = (t->width + margin) * 2; decoration_height = t->width + t->titlebar_height + margin * 2; @@ -2795,7 +2743,6 @@ input_remove_keyboard_focus(struct input *input) if (!window) return; - window->focus_count--; if (window->keyboard_focus_handler) (*window->keyboard_focus_handler)(window, NULL, window->user_data); @@ -2894,7 +2841,6 @@ keyboard_handle_enter(void *data, struct wl_keyboard *keyboard, input->keyboard_focus = wl_surface_get_user_data(surface); window = input->keyboard_focus; - window->focus_count++; if (window->keyboard_focus_handler) (*window->keyboard_focus_handler)(window, input, window->user_data); @@ -2937,8 +2883,7 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard, if (sym == XKB_KEY_F5 && input->modifiers == MOD_ALT_MASK) { if (state == WL_KEYBOARD_KEY_STATE_PRESSED) - window_set_maximized(window, - window->type != TYPE_MAXIMIZED); + window_set_maximized(window, !window->maximized); } else if (sym == XKB_KEY_F11 && window->fullscreen_handler && state == WL_KEYBOARD_KEY_STATE_PRESSED) { @@ -2946,10 +2891,7 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard, } else if (sym == XKB_KEY_F4 && input->modifiers == MOD_ALT_MASK && state == WL_KEYBOARD_KEY_STATE_PRESSED) { - if (window->close_handler) - window->close_handler(window->user_data); - else - display_exit(window->display); + window_close(window); } else if (window->key_handler) { (*window->key_handler)(window, input, time, key, sym, state, window->user_data); @@ -2962,7 +2904,8 @@ keyboard_handle_key(void *data, struct wl_keyboard *keyboard, its.it_value.tv_sec = 0; its.it_value.tv_nsec = 0; timerfd_settime(input->repeat_timer_fd, 0, &its, NULL); - } else if (state == WL_KEYBOARD_KEY_STATE_PRESSED) { + } else if (state == WL_KEYBOARD_KEY_STATE_PRESSED && + xkb_keymap_key_repeats(input->xkb.keymap, code)) { input->repeat_sym = sym; input->repeat_key = key; input->repeat_time = time; @@ -3458,13 +3401,13 @@ input_set_pointer_image_index(struct input *input, int index) if (!buffer) return; - wl_pointer_set_cursor(input->pointer, input->pointer_enter_serial, - input->pointer_surface, - image->hotspot_x, image->hotspot_y); wl_surface_attach(input->pointer_surface, buffer, 0, 0); wl_surface_damage(input->pointer_surface, 0, 0, image->width, image->height); wl_surface_commit(input->pointer_surface); + wl_pointer_set_cursor(input->pointer, input->pointer_enter_serial, + input->pointer_surface, + image->hotspot_x, image->hotspot_y); } static const struct wl_callback_listener pointer_surface_listener; @@ -3564,7 +3507,8 @@ void input_set_selection(struct input *input, struct wl_data_source *source, uint32_t time) { - wl_data_device_set_selection(input->data_device, source, time); + if (input->data_device) + wl_data_device_set_selection(input->data_device, source, time); } void @@ -3668,10 +3612,10 @@ input_receive_selection_data_to_fd(struct input *input, void window_move(struct window *window, struct input *input, uint32_t serial) { - if (!window->shell_surface) + if (!window->xdg_surface) return; - wl_shell_surface_move(window->shell_surface, input->seat, serial); + xdg_surface_move(window->xdg_surface, input->seat, serial); } static void @@ -3800,6 +3744,9 @@ window_do_resize(struct window *window) surface_set_synchronized(surface); surface_resize(surface); } + + if (!window->fullscreen && !window->maximized) + window->saved_allocation = window->pending_allocation; } static void @@ -3880,52 +3827,137 @@ widget_schedule_resize(struct widget *widget, int32_t width, int32_t height) } static void -handle_ping(void *data, struct wl_shell_surface *shell_surface, - uint32_t serial) +handle_surface_configure(void *data, struct xdg_surface *xdg_surface, + int32_t width, int32_t height) { - wl_shell_surface_pong(shell_surface, serial); + struct window *window = data; + + window_schedule_resize(window, width, height); } static void -handle_configure(void *data, struct wl_shell_surface *shell_surface, - uint32_t edges, int32_t width, int32_t height) +handle_surface_change_state(void *data, struct xdg_surface *xdg_surface, + uint32_t state, + uint32_t value, + uint32_t serial) { struct window *window = data; - window->resize_edges = edges; - window_schedule_resize(window, width, height); + switch (state) { + case XDG_SURFACE_STATE_MAXIMIZED: + window->maximized = value; + break; + case XDG_SURFACE_STATE_FULLSCREEN: + window->fullscreen = value; + break; + } + + if (!window->fullscreen && !window->maximized) + window_schedule_resize(window, + window->saved_allocation.width, + window->saved_allocation.height); + + xdg_surface_ack_change_state(xdg_surface, state, value, serial); + window_schedule_redraw(window); } static void -menu_destroy(struct menu *menu) +handle_surface_activated(void *data, struct xdg_surface *xdg_surface) { - widget_destroy(menu->widget); - window_destroy(menu->window); - frame_destroy(menu->frame); - free(menu); + struct window *window = data; + window->focused = 1; } static void -handle_popup_done(void *data, struct wl_shell_surface *shell_surface) +handle_surface_deactivated(void *data, struct xdg_surface *xdg_surface) { struct window *window = data; - struct menu *menu = window->main_surface->widget->user_data; - - /* FIXME: Need more context in this event, at least the input - * device. Or just use wl_callback. And this really needs to - * be a window vfunc that the menu can set. And we need the - * time. */ + window->focused = 0; +} - input_ungrab(menu->input); - menu_destroy(menu); +static void +handle_surface_delete(void *data, struct xdg_surface *xdg_surface) +{ + struct window *window = data; + window_close(window); } -static const struct wl_shell_surface_listener shell_surface_listener = { - handle_ping, - handle_configure, - handle_popup_done +static const struct xdg_surface_listener xdg_surface_listener = { + handle_surface_configure, + handle_surface_change_state, + handle_surface_activated, + handle_surface_deactivated, + handle_surface_delete, }; +static void +window_sync_transient_for(struct window *window) +{ + struct wl_surface *parent_surface; + + if (!window->xdg_surface) + return; + + if (window->transient_for) + parent_surface = window->transient_for->main_surface->surface; + else + parent_surface = NULL; + + xdg_surface_set_transient_for(window->xdg_surface, parent_surface); +} + +static void +window_sync_margin(struct window *window) +{ + int margin; + + if (!window->xdg_surface) + return; + + if (!window->frame) + return; + + margin = frame_get_shadow_margin(window->frame->frame); + + /* Shadow size is the same on every side. */ + xdg_surface_set_margin(window->xdg_surface, + margin, + margin, + margin, + margin); +} + +static void +window_flush(struct window *window) +{ + struct surface *surface; + + if (!window->custom) { + if (window->xdg_surface) { + window_sync_transient_for(window); + window_sync_margin(window); + } + } + + wl_list_for_each(surface, &window->subsurface_list, link) { + if (surface == window->main_surface) + continue; + + surface_flush(surface); + } + + surface_flush(window->main_surface); +} + +static void +menu_destroy(struct menu *menu) +{ + widget_destroy(menu->widget); + window_destroy(menu->window); + frame_destroy(menu->frame); + free(menu); +} + void window_get_allocation(struct window *window, struct rectangle *allocation) @@ -4057,8 +4089,6 @@ idle_redraw(struct task *task, uint32_t events) static void window_schedule_redraw_task(struct window *window) { - if (window->configure_requests) - return; if (!window->redraw_task_scheduled) { window->redraw_task.run = idle_redraw; display_defer(window->display, &window->redraw_task); @@ -4082,117 +4112,52 @@ window_schedule_redraw(struct window *window) int window_is_fullscreen(struct window *window) { - return window->type == TYPE_FULLSCREEN; -} - -int -window_is_transient(struct window *window) -{ - return window->type == TYPE_TRANSIENT; -} - -static void -configure_request_completed(void *data, struct wl_callback *callback, uint32_t time) -{ - struct window *window = data; - - wl_callback_destroy(callback); - window->configure_requests--; - - if (!window->configure_requests) - window_schedule_redraw(window); -} - -static struct wl_callback_listener configure_request_listener = { - configure_request_completed, -}; - -static void -window_defer_redraw_until_configure(struct window* window) -{ - struct wl_callback *callback; - - if (window->redraw_task_scheduled) { - wl_list_remove(&window->redraw_task.link); - window->redraw_task_scheduled = 0; - } - - callback = wl_display_sync(window->display->display); - wl_callback_add_listener(callback, &configure_request_listener, window); - window->configure_requests++; + return window->fullscreen; } void window_set_fullscreen(struct window *window, int fullscreen) { - if (!window->display->shell) + if (!window->xdg_surface) return; - if ((window->type == TYPE_FULLSCREEN) == fullscreen) + if (window->fullscreen == fullscreen) return; - if (fullscreen) { - window->saved_type = window->type; - if (window->type == TYPE_TOPLEVEL) { - window->saved_allocation = window->main_surface->allocation; - } - window->type = TYPE_FULLSCREEN; - wl_shell_surface_set_fullscreen(window->shell_surface, - window->fullscreen_method, - 0, NULL); - window_defer_redraw_until_configure (window); - } else { - if (window->saved_type == TYPE_MAXIMIZED) { - window_set_maximized(window, 1); - } else { - window->type = TYPE_TOPLEVEL; - wl_shell_surface_set_toplevel(window->shell_surface); - window_schedule_resize(window, - window->saved_allocation.width, - window->saved_allocation.height); - } - - } -} - -void -window_set_fullscreen_method(struct window *window, - enum wl_shell_surface_fullscreen_method method) -{ - window->fullscreen_method = method; + xdg_surface_request_change_state(window->xdg_surface, + XDG_SURFACE_STATE_FULLSCREEN, + fullscreen ? 1 : 0, + 0); } int window_is_maximized(struct window *window) { - return window->type == TYPE_MAXIMIZED; + return window->maximized; } void window_set_maximized(struct window *window, int maximized) { - if (!window->display->shell) + if (!window->xdg_surface) return; - if ((window->type == TYPE_MAXIMIZED) == maximized) + if (window->maximized == maximized) return; - if (window->type == TYPE_TOPLEVEL) { - window->saved_allocation = window->main_surface->allocation; - wl_shell_surface_set_maximized(window->shell_surface, NULL); - window->type = TYPE_MAXIMIZED; - window_defer_redraw_until_configure(window); - } else if (window->type == TYPE_FULLSCREEN) { - wl_shell_surface_set_maximized(window->shell_surface, NULL); - window->type = TYPE_MAXIMIZED; - window_defer_redraw_until_configure(window); - } else { - wl_shell_surface_set_toplevel(window->shell_surface); - window->type = TYPE_TOPLEVEL; - window_schedule_resize(window, - window->saved_allocation.width, - window->saved_allocation.height); - } + xdg_surface_request_change_state(window->xdg_surface, + XDG_SURFACE_STATE_MAXIMIZED, + maximized ? 1 : 0, + 0); +} + +void +window_set_minimized(struct window *window) +{ + if (!window->xdg_surface) + return; + + xdg_surface_set_minimized(window->xdg_surface); } void @@ -4263,8 +4228,8 @@ window_set_title(struct window *window, const char *title) frame_set_title(window->frame->frame, title); widget_schedule_redraw(window->frame->widget); } - if (window->shell_surface) - wl_shell_surface_set_title(window->shell_surface, title); + if (window->xdg_surface) + xdg_surface_set_title(window->xdg_surface, title); } const char * @@ -4377,7 +4342,7 @@ surface_create(struct window *window) } static struct window * -window_create_internal(struct display *display, int type) +window_create_internal(struct display *display, int custom) { struct window *window; struct surface *surface; @@ -4389,16 +4354,9 @@ window_create_internal(struct display *display, int type) surface = surface_create(window); window->main_surface = surface; - if (type != TYPE_CUSTOM && display->shell) { - window->shell_surface = - wl_shell_get_shell_surface(display->shell, - surface->surface); - fail_on_null(window->shell_surface); - } + assert(custom || display->xdg_shell); - window->type = type; - window->fullscreen_method = WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT; - window->configure_requests = 0; + window->custom = custom; window->preferred_format = WINDOW_PREFERRED_FORMAT_NONE; if (display->argb_device) @@ -4414,12 +4372,6 @@ window_create_internal(struct display *display, int type) wl_list_insert(display->window_list.prev, &window->link); wl_list_init(&window->redraw_task.link); - if (window->shell_surface) { - wl_shell_surface_set_user_data(window->shell_surface, window); - wl_shell_surface_add_listener(window->shell_surface, - &shell_surface_listener, window); - } - wl_list_init (&window->window_output_list); return window; @@ -4428,33 +4380,40 @@ window_create_internal(struct display *display, int type) struct window * window_create(struct display *display) { - return window_create_internal(display, TYPE_NONE); + struct window *window; + + window = window_create_internal(display, 0); + + window->xdg_surface = + xdg_shell_get_xdg_surface(window->display->xdg_shell, + window->main_surface->surface); + fail_on_null(window->xdg_surface); + + xdg_surface_set_user_data(window->xdg_surface, window); + xdg_surface_add_listener(window->xdg_surface, + &xdg_surface_listener, window); + + return window; } struct window * window_create_custom(struct display *display) { - return window_create_internal(display, TYPE_CUSTOM); + return window_create_internal(display, 1); } -struct window * -window_create_transient(struct display *display, struct window *parent, - int32_t x, int32_t y, uint32_t flags) +void +window_set_transient_for(struct window *window, + struct window *parent_window) { - struct window *window; - - window = window_create_internal(parent->display, TYPE_TRANSIENT); - - window->x = x; - window->y = y; - - if (display->shell) - wl_shell_surface_set_transient( - window->shell_surface, - parent->main_surface->surface, - window->x, window->y, flags); + window->transient_for = parent_window; + window_sync_transient_for(window); +} - return window; +struct window * +window_get_transient_for(struct window *window) +{ + return window->transient_for; } static void @@ -4567,6 +4526,20 @@ menu_redraw_handler(struct widget *widget, void *data) cairo_destroy(cr); } +static void +handle_popup_popup_done(void *data, struct xdg_popup *xdg_popup, uint32_t serial) +{ + struct window *window = data; + struct menu *menu = window->main_surface->widget->user_data; + + input_ungrab(menu->input); + menu_destroy(menu); +} + +static const struct xdg_popup_listener xdg_popup_listener = { + handle_popup_popup_done, +}; + void window_show_menu(struct display *display, struct input *input, uint32_t time, struct window *parent, @@ -4581,7 +4554,7 @@ window_show_menu(struct display *display, if (!menu) return; - window = window_create_internal(parent->display, TYPE_MENU); + window = window_create_internal(parent->display, 0); if (!window) { free(menu); return; @@ -4602,7 +4575,6 @@ window_show_menu(struct display *display, menu->time = time; menu->func = func; menu->input = input; - window->type = TYPE_MENU; window->x = x; window->y = y; @@ -4621,10 +4593,20 @@ window_show_menu(struct display *display, frame_height(menu->frame)); frame_interior(menu->frame, &ix, &iy, NULL, NULL); - wl_shell_surface_set_popup(window->shell_surface, input->seat, - display_get_serial(window->display), - parent->main_surface->surface, - window->x - ix, window->y - iy, 0); + + window->xdg_popup = xdg_shell_get_xdg_popup(display->xdg_shell, + window->main_surface->surface, + parent->main_surface->surface, + input->seat, + display_get_serial(window->display), + window->x - ix, + window->y - iy, + 0); + fail_on_null(window->xdg_popup); + + xdg_popup_set_user_data(window->xdg_popup, window); + xdg_popup_add_listener(window->xdg_popup, + &xdg_popup_listener, window); } void @@ -4633,6 +4615,12 @@ window_set_buffer_type(struct window *window, enum window_buffer_type type) window->main_surface->buffer_type = type; } +enum window_buffer_type +window_get_buffer_type(struct window *window) +{ + return window->main_surface->buffer_type; +} + void window_set_preferred_format(struct window *window, enum preferred_format format) @@ -4650,6 +4638,7 @@ window_add_subsurface(struct window *window, void *data, struct wl_subcompositor *subcompo = window->display->subcompositor; surface = surface_create(window); + surface->buffer_type = window_get_buffer_type(window); widget = widget_create(window, surface, data); wl_list_init(&widget->link); surface->widget = widget; @@ -4671,6 +4660,9 @@ window_add_subsurface(struct window *window, void *data, assert(!"bad enum subsurface_mode"); } + window->resize_needed = 1; + window_schedule_redraw(window); + return widget; } @@ -4690,6 +4682,14 @@ display_handle_geometry(void *data, output->allocation.x = x; output->allocation.y = y; output->transform = transform; + + if (output->make) + free(output->make); + output->make = strdup(make); + + if (output->model) + free(output->model); + output->model = strdup(model); } static void @@ -4877,6 +4877,18 @@ output_get_scale(struct output *output) return output->scale; } +const char * +output_get_make(struct output *output) +{ + return output->make; +} + +const char * +output_get_model(struct output *output) +{ + return output->model; +} + static void fini_xkb(struct input *input) { @@ -4904,11 +4916,14 @@ display_add_input(struct display *d, uint32_t id) wl_seat_add_listener(input->seat, &seat_listener, input); wl_seat_set_user_data(input->seat, input); - input->data_device = - wl_data_device_manager_get_data_device(d->data_device_manager, - input->seat); - wl_data_device_add_listener(input->data_device, &data_device_listener, - input); + if (d->data_device_manager) { + input->data_device = + wl_data_device_manager_get_data_device(d->data_device_manager, + input->seat); + wl_data_device_add_listener(input->data_device, + &data_device_listener, + input); + } input->pointer_surface = wl_compositor_create_surface(d->compositor); @@ -4931,7 +4946,8 @@ input_destroy(struct input *input) if (input->selection_offer) data_offer_destroy(input->selection_offer); - wl_data_device_destroy(input->data_device); + if (input->data_device) + wl_data_device_destroy(input->data_device); if (input->display->seat_version >= 3) { if (input->pointer) @@ -4976,6 +4992,22 @@ struct wl_shm_listener shm_listener = { }; static void +xdg_shell_ping(void *data, struct xdg_shell *shell, uint32_t serial) +{ + xdg_shell_pong(shell, serial); +} + +static const struct xdg_shell_listener xdg_shell_listener = { + xdg_shell_ping, +}; + +#define XDG_VERSION 3 /* The version of xdg-shell that we implement */ +#ifdef static_assert +static_assert(XDG_VERSION == XDG_SHELL_VERSION_CURRENT, + "Interface version doesn't match implementation version"); +#endif + +static void registry_handle_global(void *data, struct wl_registry *registry, uint32_t id, const char *interface, uint32_t version) { @@ -4996,9 +5028,6 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t id, } else if (strcmp(interface, "wl_seat") == 0) { d->seat_version = version; display_add_input(d, id); - } else if (strcmp(interface, "wl_shell") == 0) { - d->shell = wl_registry_bind(registry, - id, &wl_shell_interface, 1); } else if (strcmp(interface, "wl_shm") == 0) { d->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1); wl_shm_add_listener(d->shm, &shm_listener, d); @@ -5006,6 +5035,11 @@ registry_handle_global(void *data, struct wl_registry *registry, uint32_t id, d->data_device_manager = wl_registry_bind(registry, id, &wl_data_device_manager_interface, 1); + } else if (strcmp(interface, "xdg_shell") == 0) { + d->xdg_shell = wl_registry_bind(registry, id, + &xdg_shell_interface, 1); + xdg_shell_use_unstable_version(d->xdg_shell, XDG_VERSION); + xdg_shell_add_listener(d->xdg_shell, &xdg_shell_listener, d); } else if (strcmp(interface, "text_cursor_position") == 0) { d->text_cursor_position = wl_registry_bind(registry, id, @@ -5312,8 +5346,8 @@ display_destroy(struct display *display) if (display->subcompositor) wl_subcompositor_destroy(display->subcompositor); - if (display->shell) - wl_shell_destroy(display->shell); + if (display->xdg_shell) + xdg_shell_destroy(display->xdg_shell); if (display->shm) wl_shm_destroy(display->shm); @@ -5396,7 +5430,10 @@ display_get_egl_display(struct display *d) struct wl_data_source * display_create_data_source(struct display *display) { - return wl_data_device_manager_create_data_source(display->data_device_manager); + if (display->data_device_manager) + return wl_data_device_manager_create_data_source(display->data_device_manager); + else + return NULL; } EGLConfig |