summaryrefslogtreecommitdiff
path: root/gdk/wayland/gdksurface-wayland.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdk/wayland/gdksurface-wayland.c')
-rw-r--r--gdk/wayland/gdksurface-wayland.c139
1 files changed, 120 insertions, 19 deletions
diff --git a/gdk/wayland/gdksurface-wayland.c b/gdk/wayland/gdksurface-wayland.c
index d30d7a8a12..2d6cafd187 100644
--- a/gdk/wayland/gdksurface-wayland.c
+++ b/gdk/wayland/gdksurface-wayland.c
@@ -146,12 +146,22 @@ struct _GdkWaylandSurface
cairo_region_t *input_region;
gboolean input_region_dirty;
+ GdkRectangle last_sent_window_geometry;
+ int last_sent_min_width;
+ int last_sent_min_height;
+ int last_sent_max_width;
+ int last_sent_max_height;
+
int saved_width;
int saved_height;
gulong parent_surface_committed_handler;
struct {
+ GdkToplevelLayout *layout;
+ } toplevel;
+
+ struct {
GdkPopupLayout *layout;
int unconstrained_width;
int unconstrained_height;
@@ -1112,6 +1122,9 @@ gdk_wayland_surface_sync_margin (GdkSurface *surface)
&impl->geometry_hints,
impl->geometry_mask);
+ if (gdk_rectangle_equal (&geometry, &impl->last_sent_window_geometry))
+ return;
+
switch (display_wayland->shell_variant)
{
case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
@@ -1131,6 +1144,8 @@ gdk_wayland_surface_sync_margin (GdkSurface *surface)
default:
g_assert_not_reached ();
}
+
+ impl->last_sent_window_geometry = geometry;
}
static struct wl_region *
@@ -1266,6 +1281,50 @@ gdk_wayland_surface_create_surface (GdkSurface *surface)
}
static void
+configure_surface_geometry (GdkSurface *surface)
+{
+ GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
+ GdkDisplay *display = gdk_surface_get_display (surface);
+ GdkMonitor *monitor;
+ GdkRectangle monitor_geometry;
+ int bounds_width, bounds_height;
+ GdkToplevelSize size;
+ int width, height;
+ GdkToplevelLayout *layout;
+ GdkGeometry geometry;
+ GdkSurfaceHints mask;
+
+ monitor = g_list_model_get_item (gdk_display_get_monitors (display), 0);
+ gdk_monitor_get_geometry (monitor, &monitor_geometry);
+ bounds_width = monitor_geometry.width;
+ bounds_height = monitor_geometry.height;
+
+ gdk_toplevel_size_init (&size, bounds_width, bounds_height);
+ gdk_toplevel_notify_compute_size (GDK_TOPLEVEL (surface), &size);
+ width = size.width;
+ height = size.height;
+ g_warn_if_fail (width > 0);
+ g_warn_if_fail (height > 0);
+
+ layout = impl->toplevel.layout;
+ if (gdk_toplevel_layout_get_resizable (layout))
+ {
+ geometry.min_width = size.min_width;
+ geometry.min_height = size.min_height;
+ mask = GDK_HINT_MIN_SIZE;
+ }
+ else
+ {
+ geometry.max_width = geometry.min_width = width;
+ geometry.max_height = geometry.min_height = height;
+ mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE;
+ }
+ gdk_wayland_surface_set_geometry_hints (surface, &geometry, mask);
+ gdk_surface_constrain_size (&geometry, mask, width, height, &width, &height);
+ gdk_wayland_surface_resize (surface, width, height, impl->scale);
+}
+
+static void
gdk_wayland_surface_configure_toplevel (GdkSurface *surface)
{
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
@@ -1322,6 +1381,10 @@ gdk_wayland_surface_configure_toplevel (GdkSurface *surface)
gdk_wayland_surface_resize (surface, width, height, impl->scale);
}
+ else
+ {
+ configure_surface_geometry (surface);
+ }
GDK_DISPLAY_NOTE (gdk_surface_get_display (surface), EVENTS,
g_message ("configure, surface %p %dx%d,%s%s%s%s",
@@ -2729,6 +2792,7 @@ gdk_wayland_surface_hide_surface (GdkSurface *surface)
g_slist_free (impl->display_server.outputs);
impl->display_server.outputs = NULL;
+ g_clear_pointer (&impl->toplevel.layout, gdk_toplevel_layout_unref);
g_clear_pointer (&impl->popup.layout, gdk_popup_layout_unref);
}
@@ -3369,6 +3433,12 @@ gdk_wayland_surface_set_geometry_hints (GdkSurface *surface,
max_height = 0;
}
+ if (impl->last_sent_min_width == min_width &&
+ impl->last_sent_min_height == min_height &&
+ impl->last_sent_max_width == max_width &&
+ impl->last_sent_max_height == max_height)
+ return;
+
switch (display_wayland->shell_variant)
{
case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL:
@@ -3386,6 +3456,11 @@ gdk_wayland_surface_set_geometry_hints (GdkSurface *surface,
default:
g_assert_not_reached ();
}
+
+ impl->last_sent_min_width = min_width;
+ impl->last_sent_min_height = min_height;
+ impl->last_sent_max_width = max_width;
+ impl->last_sent_max_height = max_height;
}
static void
@@ -4676,37 +4751,41 @@ show_surface (GdkSurface *surface)
gdk_surface_invalidate_rect (surface, NULL);
}
+static void
+reconfigure_callback (void *data,
+ struct wl_callback *callback,
+ uint32_t time)
+{
+ gboolean *done = (gboolean *) data;
+
+ *done = TRUE;
+}
+
+static const struct wl_callback_listener reconfigure_listener = {
+ reconfigure_callback
+};
+
static gboolean
gdk_wayland_toplevel_present (GdkToplevel *toplevel,
- int width,
- int height,
GdkToplevelLayout *layout)
{
GdkSurface *surface = GDK_SURFACE (toplevel);
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
- GdkGeometry geometry;
- GdkSurfaceHints mask;
+ GdkWaylandDisplay *display_wayland;
+ struct wl_callback *callback;
+ gboolean done = FALSE;
+ int last_configure_serial = impl->last_configure_serial;
+ gboolean needs_reconfigure = TRUE;
- if (gdk_toplevel_layout_get_resizable (layout))
+ if (gdk_toplevel_layout_get_maximized (layout))
{
- geometry.min_width = gdk_toplevel_layout_get_min_width (layout);
- geometry.min_height = gdk_toplevel_layout_get_min_height (layout);
- mask = GDK_HINT_MIN_SIZE;
+ gdk_wayland_surface_maximize (surface);
+ needs_reconfigure = FALSE;
}
else
{
- geometry.max_width = geometry.min_width = width;
- geometry.max_height = geometry.min_height = height;
- mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE;
+ gdk_wayland_surface_unmaximize (surface);
}
- gdk_wayland_surface_set_geometry_hints (surface, &geometry, mask);
- gdk_surface_constrain_size (&geometry, mask, width, height, &width, &height);
- gdk_wayland_surface_resize (surface, width, height, impl->scale);
-
- if (gdk_toplevel_layout_get_maximized (layout))
- gdk_wayland_surface_maximize (surface);
- else
- gdk_wayland_surface_unmaximize (surface);
if (gdk_toplevel_layout_get_fullscreen (layout))
{
@@ -4715,12 +4794,34 @@ gdk_wayland_toplevel_present (GdkToplevel *toplevel,
gdk_wayland_surface_fullscreen_on_monitor (surface, monitor);
else
gdk_wayland_surface_fullscreen (surface);
+ needs_reconfigure = FALSE;
}
else
gdk_wayland_surface_unfullscreen (surface);
+ g_clear_pointer (&impl->toplevel.layout, gdk_toplevel_layout_unref);
+ impl->toplevel.layout = gdk_toplevel_layout_copy (layout);
+
show_surface (surface);
+ display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface));
+ callback = wl_display_sync (display_wayland->wl_display);
+ wl_proxy_set_queue ((struct wl_proxy *) callback, impl->event_queue);
+ wl_callback_add_listener (callback,
+ &reconfigure_listener,
+ &done);
+ while (is_realized_toplevel (surface) &&
+ !impl->initial_configure_received &&
+ !done)
+ wl_display_dispatch_queue (display_wayland->wl_display, impl->event_queue);
+
+ if (needs_reconfigure &&
+ last_configure_serial == impl->last_configure_serial &&
+ !(surface->state & (GDK_SURFACE_STATE_MAXIMIZED |
+ GDK_SURFACE_STATE_FULLSCREEN |
+ GDK_SURFACE_STATE_TILED)))
+ configure_surface_geometry (surface);
+
return TRUE;
}