summaryrefslogtreecommitdiff
path: root/clients/window.c
diff options
context:
space:
mode:
Diffstat (limited to 'clients/window.c')
-rw-r--r--clients/window.c641
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