summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2020-08-05 16:19:19 +0000
committerMatthias Clasen <mclasen@redhat.com>2020-08-05 16:19:19 +0000
commitd7c4f93c76eaeab7d90fef486bc6eed9e3c6580c (patch)
treeabf8dfa7f2b159397c61b93ce1383dcff09262bb
parent0b0f7dc9c0d6350babaacad26156f7a06eb69585 (diff)
parent2ff74eb667c2cbe293c7309d5661fa438e8431c4 (diff)
downloadgtk+-d7c4f93c76eaeab7d90fef486bc6eed9e3c6580c.tar.gz
Merge branch 'wip/compute-size' into 'master'
Compute size via signal See merge request GNOME/gtk!2325
-rw-r--r--docs/reference/gdk/gdk4-sections.txt14
-rw-r--r--gdk/broadway/gdksurface-broadway.c34
-rw-r--r--gdk/gdk.h1
-rw-r--r--gdk/gdksurface.c8
-rw-r--r--gdk/gdksurface.h4
-rw-r--r--gdk/gdktoplevel.c64
-rw-r--r--gdk/gdktoplevel.h2
-rw-r--r--gdk/gdktoplevellayout.c43
-rw-r--r--gdk/gdktoplevellayout.h8
-rw-r--r--gdk/gdktoplevelprivate.h8
-rw-r--r--gdk/gdktoplevelsize.c119
-rw-r--r--gdk/gdktoplevelsize.h62
-rw-r--r--gdk/gdktoplevelsizeprivate.h39
-rw-r--r--gdk/macos/gdkmacostoplevelsurface.c33
-rw-r--r--gdk/meson.build3
-rw-r--r--gdk/wayland/gdksurface-wayland.c139
-rw-r--r--gdk/win32/gdksurface-win32.c35
-rw-r--r--gdk/x11/gdksurface-x11.c45
-rw-r--r--gtk/gtkwindow.c252
-rw-r--r--gtk/inspector/general.c4
-rw-r--r--tests/rendernode.c2
-rw-r--r--tests/showrendernode.c4
-rw-r--r--tests/testfullscreen.c14
-rw-r--r--testsuite/gsk/compare-render.c2
-rw-r--r--testsuite/gtk/defaultvalue.c2
-rw-r--r--testsuite/gtk/notify.c2
-rw-r--r--testsuite/gtk/shortcuts.c2
-rw-r--r--testsuite/gtk/test-focus-chain.c25
28 files changed, 748 insertions, 222 deletions
diff --git a/docs/reference/gdk/gdk4-sections.txt b/docs/reference/gdk/gdk4-sections.txt
index a7c942a4e5..5cff88eb65 100644
--- a/docs/reference/gdk/gdk4-sections.txt
+++ b/docs/reference/gdk/gdk4-sections.txt
@@ -633,8 +633,6 @@ gdk_toplevel_layout_get_maximized
gdk_toplevel_layout_set_fullscreen
gdk_toplevel_layout_get_fullscreen
gdk_toplevel_layout_get_fullscreen_monitor
-gdk_toplevel_layout_get_min_width
-gdk_toplevel_layout_get_min_height
gdk_toplevel_layout_set_resizable
gdk_toplevel_layout_get_resizable
<SUBSECTION Standard>
@@ -643,6 +641,18 @@ gdk_toplevel_layout_get_type
</SECTION>
<SECTION>
+<FILE>gdktoplevelsize</FILE>
+<TITLE>GdkToplevelSize</TITLE>
+GdkToplevelSize
+gdk_toplevel_size_get_bounds
+gdk_toplevel_size_set_size
+gdk_toplevel_size_set_min_size
+<SUBSECTION Standard>
+GDK_TYPE_TOPLEVEL_SIZE
+gdk_toplevel_size_get_type
+</SECTION>
+
+<SECTION>
<FILE>gdktoplevel</FILE>
<TITLE>GdkToplevel</TITLE>
GdkToplevel
diff --git a/gdk/broadway/gdksurface-broadway.c b/gdk/broadway/gdksurface-broadway.c
index fb03675ece..7f5f9a79e4 100644
--- a/gdk/broadway/gdksurface-broadway.c
+++ b/gdk/broadway/gdksurface-broadway.c
@@ -41,6 +41,7 @@
#include "gdktextureprivate.h"
#include "gdktoplevelprivate.h"
+#include <graphene.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -1524,20 +1525,45 @@ show_surface (GdkSurface *surface)
static gboolean
gdk_broadway_toplevel_present (GdkToplevel *toplevel,
- int width,
- int height,
GdkToplevelLayout *layout)
{
GdkSurface *surface = GDK_SURFACE (toplevel);
+ GdkDisplay *display = gdk_surface_get_display (surface);
+ GdkMonitor *monitor;
+ GdkToplevelSize size;
+ int bounds_width, bounds_height;
+ int width, height;
GdkGeometry geometry;
GdkSurfaceHints mask;
gdk_broadway_surface_unminimize (surface);
+ monitor = gdk_display_get_monitor_at_surface (display, surface);
+ if (monitor)
+ {
+ GdkRectangle monitor_geometry;
+
+ gdk_monitor_get_geometry (monitor, &monitor_geometry);
+ bounds_width = monitor_geometry.width;
+ bounds_height = monitor_geometry.height;
+ }
+ else
+ {
+ bounds_width = G_MAXINT;
+ bounds_height = G_MAXINT;
+ }
+
+ gdk_toplevel_size_init (&size, bounds_width, bounds_height);
+ gdk_toplevel_notify_compute_size (toplevel, &size);
+ g_warn_if_fail (size.width > 0);
+ g_warn_if_fail (size.height > 0);
+ width = size.width;
+ height = size.height;
+
if (gdk_toplevel_layout_get_resizable (layout))
{
- geometry.min_width = gdk_toplevel_layout_get_min_width (layout);
- geometry.min_height = gdk_toplevel_layout_get_min_height (layout);
+ geometry.min_width = size.min_width;
+ geometry.min_height = size.min_height;
mask = GDK_HINT_MIN_SIZE;
}
else
diff --git a/gdk/gdk.h b/gdk/gdk.h
index d15dd7d922..8b6489cbf0 100644
--- a/gdk/gdk.h
+++ b/gdk/gdk.h
@@ -70,6 +70,7 @@
#include <gdk/gdktexture.h>
#include <gdk/gdktoplevel.h>
#include <gdk/gdktoplevellayout.h>
+#include <gdk/gdktoplevelsize.h>
#include <gdk/gdktypes.h>
#include <gdk/gdkversionmacros.h>
#include <gdk/gdkvulkancontext.h>
diff --git a/gdk/gdksurface.c b/gdk/gdksurface.c
index 6d8b84ee34..75c35d6d50 100644
--- a/gdk/gdksurface.c
+++ b/gdk/gdksurface.c
@@ -795,22 +795,18 @@ gdk_surface_new (GdkDisplay *display,
/**
* gdk_surface_new_toplevel: (constructor)
* @display: the display to create the surface on
- * @width: width of new surface
- * @height: height of new surface
*
* Creates a new toplevel surface.
*
* Returns: (transfer full): the new #GdkSurface
**/
GdkSurface *
-gdk_surface_new_toplevel (GdkDisplay *display,
- int width,
- int height)
+gdk_surface_new_toplevel (GdkDisplay *display)
{
g_return_val_if_fail (GDK_IS_DISPLAY (display), NULL);
return gdk_surface_new (display, GDK_SURFACE_TOPLEVEL,
- NULL, 0, 0, width, height);
+ NULL, 0, 0, 0, 0);
}
/**
diff --git a/gdk/gdksurface.h b/gdk/gdksurface.h
index 077c012a3f..9b1613147f 100644
--- a/gdk/gdksurface.h
+++ b/gdk/gdksurface.h
@@ -139,9 +139,7 @@ typedef struct _GdkSurfaceClass GdkSurfaceClass;
GDK_AVAILABLE_IN_ALL
GType gdk_surface_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_ALL
-GdkSurface * gdk_surface_new_toplevel (GdkDisplay *display,
- int width,
- int height);
+GdkSurface * gdk_surface_new_toplevel (GdkDisplay *display);
GDK_AVAILABLE_IN_ALL
GdkSurface * gdk_surface_new_popup (GdkSurface *parent,
gboolean autohide);
diff --git a/gdk/gdktoplevel.c b/gdk/gdktoplevel.c
index a69f13fa62..3b8a22a611 100644
--- a/gdk/gdktoplevel.c
+++ b/gdk/gdktoplevel.c
@@ -23,6 +23,7 @@
#include "gdk-private.h"
#include "gdktoplevelprivate.h"
+#include <graphene-gobject.h>
#include <math.h>
/**
@@ -35,10 +36,17 @@
G_DEFINE_INTERFACE (GdkToplevel, gdk_toplevel, GDK_TYPE_SURFACE)
+enum
+{
+ COMPUTE_SIZE,
+
+ N_SIGNALS
+};
+
+static guint signals[N_SIGNALS] = { 0 };
+
static gboolean
gdk_toplevel_default_present (GdkToplevel *toplevel,
- int width,
- int height,
GdkToplevelLayout *layout)
{
return FALSE;
@@ -86,6 +94,13 @@ gdk_toplevel_default_restore_system_shortcuts (GdkToplevel *toplevel)
{
}
+void
+gdk_toplevel_notify_compute_size (GdkToplevel *toplevel,
+ GdkToplevelSize *size)
+{
+ g_signal_emit (toplevel, signals[COMPUTE_SIZE], 0, size);
+}
+
static void
gdk_toplevel_default_init (GdkToplevelInterface *iface)
{
@@ -158,6 +173,37 @@ gdk_toplevel_default_init (GdkToplevelInterface *iface)
"Whether keyboard shortcuts are inhibited",
FALSE,
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY));
+
+ /**
+ * GdkToplevel::compute-size:
+ * @toplevel: a #GdkToplevel
+ * @size: (type Gdk.ToplevelSize) (out caller-allocates): a #GdkToplevelSize
+ *
+ * Compute the desired size of the toplevel, given the information passed via
+ * the #GdkToplevelSize object.
+ *
+ * It will normally be emitted during or after gdk_toplevel_present(),
+ * depending on the configuration received by the windowing system. It may
+ * also be emitted at any other point in time, in response to the windowing
+ * system spontaneously changing the configuration.
+ *
+ * It is the responsibility of the GdkToplevel user to handle this signal;
+ * failing to do so will result in an arbitrary fixed size being used as a
+ * result. The signal may be emitted with the pointer to the @size being
+ * %NULL, in which case only the minimum and maximum size needs to be
+ * computed. This could happen for example if the toplevel configuration is in
+ * a state where the size is decided by the windowing system, such as
+ * maximized or fullscreen.
+ */
+ signals[COMPUTE_SIZE] =
+ g_signal_new ("compute-size",
+ GDK_TYPE_TOPLEVEL,
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ NULL,
+ G_TYPE_NONE, 1,
+ GDK_TYPE_TOPLEVEL_SIZE | G_SIGNAL_TYPE_STATIC_SCOPE);
}
guint
@@ -181,30 +227,28 @@ gdk_toplevel_install_properties (GObjectClass *object_class,
/**
* gdk_toplevel_present:
* @toplevel: the #GdkToplevel to show
- * @width: the unconstrained toplevel width to layout
- * @height: the unconstrained toplevel height to layout
* @layout: the #GdkToplevelLayout object used to layout
*
* Present @toplevel after having processed the #GdkToplevelLayout rules.
- * If the toplevel was previously now showing, it will be showed,
+ * If the toplevel was previously not showing, it will be showed,
* otherwise it will change layout according to @layout.
*
+ * GDK may emit the 'compute-size' signal to let the user of this toplevel
+ * compute the preferred size of the toplevel surface. See
+ * #GdkToplevel::compute-size for details.
+ *
* Presenting may fail.
*
* Returns: %FALSE if @toplevel failed to be presented, otherwise %TRUE.
*/
gboolean
gdk_toplevel_present (GdkToplevel *toplevel,
- int width,
- int height,
GdkToplevelLayout *layout)
{
g_return_val_if_fail (GDK_IS_TOPLEVEL (toplevel), FALSE);
- g_return_val_if_fail (width > 0, FALSE);
- g_return_val_if_fail (height > 0, FALSE);
g_return_val_if_fail (layout != NULL, FALSE);
- return GDK_TOPLEVEL_GET_IFACE (toplevel)->present (toplevel, width, height, layout);
+ return GDK_TOPLEVEL_GET_IFACE (toplevel)->present (toplevel, layout);
}
/**
diff --git a/gdk/gdktoplevel.h b/gdk/gdktoplevel.h
index 20b3fc5d4b..cd1bb74241 100644
--- a/gdk/gdktoplevel.h
+++ b/gdk/gdktoplevel.h
@@ -37,8 +37,6 @@ G_DECLARE_INTERFACE (GdkToplevel, gdk_toplevel, GDK, TOPLEVEL, GObject)
GDK_AVAILABLE_IN_ALL
gboolean gdk_toplevel_present (GdkToplevel *toplevel,
- int width,
- int height,
GdkToplevelLayout *layout);
GDK_AVAILABLE_IN_ALL
diff --git a/gdk/gdktoplevellayout.c b/gdk/gdktoplevellayout.c
index 8f4a6b56aa..577b03be41 100644
--- a/gdk/gdktoplevellayout.c
+++ b/gdk/gdktoplevellayout.c
@@ -39,8 +39,6 @@ struct _GdkToplevelLayout
/* < private >*/
grefcount ref_count;
- int min_width;
- int min_height;
guint resizable : 1;
guint maximized : 1;
guint fullscreen : 1;
@@ -53,8 +51,6 @@ G_DEFINE_BOXED_TYPE (GdkToplevelLayout, gdk_toplevel_layout,
/**
* gdk_toplevel_layout_new: (constructor)
- * @min_width: the minimum width for the layout
- * @min_height: the minimum height for the layout
*
* Create a toplevel layout description.
*
@@ -67,15 +63,12 @@ G_DEFINE_BOXED_TYPE (GdkToplevelLayout, gdk_toplevel_layout,
* Returns: (transfer full): newly created instance of #GdkToplevelLayout
*/
GdkToplevelLayout *
-gdk_toplevel_layout_new (int min_width,
- int min_height)
+gdk_toplevel_layout_new (void)
{
GdkToplevelLayout *layout;
layout = g_new0 (GdkToplevelLayout, 1);
g_ref_count_init (&layout->ref_count);
- layout->min_width = min_width;
- layout->min_height = min_height;
layout->resizable = TRUE;
layout->maximized = FALSE;
layout->fullscreen = FALSE;
@@ -131,8 +124,6 @@ gdk_toplevel_layout_copy (GdkToplevelLayout *layout)
new_layout = g_new0 (GdkToplevelLayout, 1);
g_ref_count_init (&new_layout->ref_count);
- new_layout->min_width = layout->min_width;
- new_layout->min_height = layout->min_height;
new_layout->resizable = layout->resizable;
new_layout->maximized = layout->maximized;
new_layout->fullscreen = layout->fullscreen;
@@ -159,43 +150,13 @@ gdk_toplevel_layout_equal (GdkToplevelLayout *layout,
g_return_val_if_fail (layout, FALSE);
g_return_val_if_fail (other, FALSE);
- return layout->min_width == other->min_width &&
- layout->min_height == other->min_height &&
- layout->resizable == other->resizable &&
+ return layout->resizable == other->resizable &&
layout->maximized == other->maximized &&
layout->fullscreen == other->fullscreen &&
layout->fullscreen_monitor == other->fullscreen_monitor;
}
/**
- * gdk_toplevel_layout_get_min_width:
- * @layout: a #GdkToplevelLayout
- *
- * Returns the minimum width of the given layout.
- *
- * Returns: the minimum width of @layout
- */
-int
-gdk_toplevel_layout_get_min_width (GdkToplevelLayout *layout)
-{
- return layout->min_width;
-}
-
-/**
- * gdk_toplevel_layout_get_min_height:
- * @layout: a #GdkToplevelLayout
- *
- * Returns the minimum height of the given layout.
- *
- * Returns: the minimum height of @layout
- */
-int
-gdk_toplevel_layout_get_min_height (GdkToplevelLayout *layout)
-{
- return layout->min_height;
-}
-
-/**
* gdk_toplevel_layout_set_resizable:
* @layout: a #GdkToplevelLayout
* @resizable: %TRUE to allow resizing
diff --git a/gdk/gdktoplevellayout.h b/gdk/gdktoplevellayout.h
index 5be9aee83c..23b2660414 100644
--- a/gdk/gdktoplevellayout.h
+++ b/gdk/gdktoplevellayout.h
@@ -42,8 +42,7 @@ GDK_AVAILABLE_IN_ALL
GType gdk_toplevel_layout_get_type (void);
GDK_AVAILABLE_IN_ALL
-GdkToplevelLayout * gdk_toplevel_layout_new (int min_width,
- int min_height);
+GdkToplevelLayout * gdk_toplevel_layout_new (void);
GDK_AVAILABLE_IN_ALL
GdkToplevelLayout * gdk_toplevel_layout_ref (GdkToplevelLayout *layout);
@@ -67,11 +66,6 @@ void gdk_toplevel_layout_set_fullscreen (GdkToplevelLayout *l
GdkMonitor *monitor);
GDK_AVAILABLE_IN_ALL
-int gdk_toplevel_layout_get_min_width (GdkToplevelLayout *layout);
-GDK_AVAILABLE_IN_ALL
-int gdk_toplevel_layout_get_min_height (GdkToplevelLayout *layout);
-
-GDK_AVAILABLE_IN_ALL
gboolean gdk_toplevel_layout_get_maximized (GdkToplevelLayout *layout);
GDK_AVAILABLE_IN_ALL
diff --git a/gdk/gdktoplevelprivate.h b/gdk/gdktoplevelprivate.h
index 6cdccca8b7..989ac29c46 100644
--- a/gdk/gdktoplevelprivate.h
+++ b/gdk/gdktoplevelprivate.h
@@ -2,6 +2,9 @@
#define __GDK_TOPLEVEL_PRIVATE_H__
#include "gdktoplevel.h"
+#include "gdktoplevelsizeprivate.h"
+
+#include <graphene.h>
G_BEGIN_DECLS
@@ -11,8 +14,6 @@ struct _GdkToplevelInterface
GTypeInterface g_iface;
gboolean (* present) (GdkToplevel *toplevel,
- int width,
- int height,
GdkToplevelLayout *layout);
gboolean (* minimize) (GdkToplevel *toplevel);
gboolean (* lower) (GdkToplevel *toplevel);
@@ -57,6 +58,9 @@ typedef enum
guint gdk_toplevel_install_properties (GObjectClass *object_class,
guint first_prop);
+void gdk_toplevel_notify_compute_size (GdkToplevel *toplevel,
+ GdkToplevelSize *size);
+
G_END_DECLS
#endif /* __GDK_TOPLEVEL_PRIVATE_H__ */
diff --git a/gdk/gdktoplevelsize.c b/gdk/gdktoplevelsize.c
new file mode 100644
index 0000000000..18933523ff
--- /dev/null
+++ b/gdk/gdktoplevelsize.c
@@ -0,0 +1,119 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 2020 Red Hat
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "config.h"
+
+#include "gdktoplevelsizeprivate.h"
+
+/**
+ * SECTION:gdktoplevelsize
+ * @Title: GdkToplevelSize
+ * @Short_description: Information for computing toplevel size
+ *
+ * The GdkToplevelSIze struct contains information that may be useful
+ * for users of GdkToplevel to compute a surface size. It also carries
+ * information back with the computational result.
+ */
+
+G_DEFINE_POINTER_TYPE (GdkToplevelSize, gdk_toplevel_size)
+
+#define UNCONFIGURED_WIDTH 400
+#define UNCONFIGURED_HEIGHT 300
+
+void
+gdk_toplevel_size_init (GdkToplevelSize *size,
+ int bounds_width,
+ int bounds_height)
+{
+ *size = (GdkToplevelSize) { 0 };
+
+ size->bounds_width = bounds_width;
+ size->bounds_height = bounds_height;
+
+ size->width = UNCONFIGURED_WIDTH;
+ size->height = UNCONFIGURED_HEIGHT;
+}
+
+/**
+ * gdk_toplevel_size_get_bounds:
+ * @size: a #GdkToplevelSize
+ * @bounds_width: (out): return location for width
+ * @bounds_height: (out): return location for height
+ *
+ * Retrieves the bounds the toplevel is placed within.
+ *
+ * The bounds represent the largest size a toplevel may have while still being
+ * able to fit within some type of boundery. Depending on the backend, this may
+ * be equivalent to the dimensions of the work area or the monitor on which the
+ * window is being presented on, or something else that limits the way a
+ * toplevel can be presented.
+ */
+void
+gdk_toplevel_size_get_bounds (GdkToplevelSize *size,
+ int *bounds_width,
+ int *bounds_height)
+{
+ g_return_if_fail (bounds_width);
+ g_return_if_fail (bounds_height);
+
+ *bounds_width = size->bounds_width;
+ *bounds_height = size->bounds_height;
+}
+
+/**
+ * gdk_toplevel_size_set_size:
+ * @size: a #GdkToplevelSize
+ * @width: the width
+ * @height: the height
+ *
+ * Sets the size the toplevel prefers to be resized to. The size should be
+ * within the bounds (see gdk_toplevel_size_get_bounds()). The set size should
+ * be considered as a hint, and should not be assumed to be respected by the
+ * windowing system, or backend.
+ */
+void
+gdk_toplevel_size_set_size (GdkToplevelSize *size,
+ int width,
+ int height)
+{
+ size->width = width;
+ size->height = height;
+}
+
+/**
+ * gdk_toplevel_size_set_min_size:
+ * @size: a #GdkToplevelSize
+ * @min_width: the minimum width
+ * @min_height: the minimum height
+ *
+ * The minimum size corresponds to the limitations the toplevel can be shrunk
+ * to, without resulting in incorrect painting. A user of a #GdkToplevel should
+ * calculate these given both the existing size, and the bounds retrieved from
+ * the #GdkToplevelSize object.
+ *
+ * The minimum size should be within the bounds (see
+ * gdk_toplevel_size_get_bounds()).
+ */
+void
+gdk_toplevel_size_set_min_size (GdkToplevelSize *size,
+ int min_width,
+ int min_height)
+{
+ size->min_width = min_width;
+ size->min_height = min_height;
+}
diff --git a/gdk/gdktoplevelsize.h b/gdk/gdktoplevelsize.h
new file mode 100644
index 0000000000..731ea6379a
--- /dev/null
+++ b/gdk/gdktoplevelsize.h
@@ -0,0 +1,62 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 2020 Red Hat
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __GDK_TOPLEVEL_SIZE_H__
+#define __GDK_TOPLEVEL_SIZE_H__
+
+#if !defined(__GDK_H_INSIDE__) && !defined(GTK_COMPILATION)
+#error "Only <gdk/gdk.h> can be included directly."
+#endif
+
+#include <gdk/gdktypes.h>
+#include <gdk/gdkversionmacros.h>
+
+G_BEGIN_DECLS
+
+/**
+ * GdkTopLevelSize:
+ *
+ * Struct containing information for computing the size of a #GdkToplevel.
+ */
+typedef struct _GdkToplevelSize GdkToplevelSize;
+
+#define GDK_TYPE_TOPLEVEL_SIZE (gdk_toplevel_size_get_type ())
+
+GDK_AVAILABLE_IN_ALL
+GType gdk_toplevel_size_get_type (void);
+
+void gdk_toplevel_size_get_bounds (GdkToplevelSize *size,
+ int *bounds_width,
+ int *bounds_height);
+
+GDK_AVAILABLE_IN_ALL
+void gdk_toplevel_size_set_size (GdkToplevelSize *size,
+ int width,
+ int height);
+GDK_AVAILABLE_IN_ALL
+void gdk_toplevel_size_set_min_size (GdkToplevelSize *size,
+ int min_width,
+ int min_height);
+GDK_AVAILABLE_IN_ALL
+void gdk_toplevel_size_set_max_size (GdkToplevelSize *size,
+ int max_width,
+ int max_height);
+
+G_END_DECLS
+
+#endif /* __GDK_TOPLEVEL_SIZE_H__ */
diff --git a/gdk/gdktoplevelsizeprivate.h b/gdk/gdktoplevelsizeprivate.h
new file mode 100644
index 0000000000..eaddefba0b
--- /dev/null
+++ b/gdk/gdktoplevelsizeprivate.h
@@ -0,0 +1,39 @@
+/* GDK - The GIMP Drawing Kit
+ * Copyright (C) 2020 Red Hat
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __GDK_TOPLEVEL_SIZE_PRIVATE_H__
+#define __GDK_TOPLEVEL_SIZE_PRIVATE_H__
+
+#include "gdktoplevelsize.h"
+
+struct _GdkToplevelSize
+{
+ int bounds_width;
+ int bounds_height;
+
+ int width;
+ int height;
+ int min_width;
+ int min_height;
+};
+
+void gdk_toplevel_size_init (GdkToplevelSize *size,
+ int bounds_width,
+ int bounds_height);
+
+#endif /* __GDK_TOPLEVEL_SIZE_PRIVATE_H__ */
diff --git a/gdk/macos/gdkmacostoplevelsurface.c b/gdk/macos/gdkmacostoplevelsurface.c
index a399150fe0..0e5a2a0ae7 100644
--- a/gdk/macos/gdkmacostoplevelsurface.c
+++ b/gdk/macos/gdkmacostoplevelsurface.c
@@ -93,12 +93,15 @@ _gdk_macos_toplevel_surface_unmaximize (GdkMacosToplevelSurface *self)
static gboolean
_gdk_macos_toplevel_surface_present (GdkToplevel *toplevel,
- int width,
- int height,
GdkToplevelLayout *layout)
{
GdkMacosToplevelSurface *self = (GdkMacosToplevelSurface *)toplevel;
NSWindow *nswindow = _gdk_macos_surface_get_native (GDK_MACOS_SURFACE (self));
+ GdkDisplay *display = gdk_surface_get_display (surface);
+ GdkMonitor *monitor;
+ GdkToplevelSize size;
+ int bounds_width, bounds_height;
+ int width, height;
GdkGeometry geometry;
GdkSurfaceHints mask;
NSWindowStyleMask style_mask;
@@ -108,10 +111,32 @@ _gdk_macos_toplevel_surface_present (GdkToplevel *toplevel,
style_mask = [nswindow styleMask];
+ monitor = gdk_display_get_monitor_at_surface (display, surface);
+ if (monitor)
+ {
+ GdkRectangle workarea;
+
+ gdk_macos_monitor_get_workarea (monitor, &workarea);
+ bounds_width = workarea.width;
+ bounds_height = workarea.height;
+ }
+ else
+ {
+ bounds_width = G_MAXINT;
+ bounds_height = G_MAXINT;
+ }
+
+ gdk_toplevel_size_init (&size, bounds_width, bounds_height);
+ gdk_toplevel_notify_compute_size (toplevel, &size);
+ g_warn_if_fail (size.width > 0);
+ g_warn_if_fail (size.height > 0);
+ width = size.width;
+ height = size.height;
+
if (gdk_toplevel_layout_get_resizable (layout))
{
- geometry.min_width = gdk_toplevel_layout_get_min_width (layout);
- geometry.min_height = gdk_toplevel_layout_get_min_height (layout);
+ geometry.min_width = size.min_width;
+ geometry.min_height = size.min_height;
mask = GDK_HINT_MIN_SIZE;
/* Only set 'Resizable' mask to get native resize zones if the window is
diff --git a/gdk/meson.build b/gdk/meson.build
index eebc9b2a97..76d60dd2e6 100644
--- a/gdk/meson.build
+++ b/gdk/meson.build
@@ -47,6 +47,7 @@ gdk_public_sources = files([
'gdkprofiler.c',
'gdkpopup.c',
'gdktoplevellayout.c',
+ 'gdktoplevelsize.c',
'gdktoplevel.c',
'gdkdragsurface.c',
])
@@ -95,6 +96,7 @@ gdk_public_headers = files([
'gdkpopuplayout.h',
'gdkpopup.h',
'gdktoplevellayout.h',
+ 'gdktoplevelsize.h',
'gdktoplevel.h',
'gdkdragsurface.h',
])
@@ -107,6 +109,7 @@ gdk_private_h_sources = files([
'gdkdevicetoolprivate.h',
'gdkmonitorprivate.h',
'gdkseatdefaultprivate.h',
+ 'gdktoplevelsizeprivate.h',
])
gdk_gresource_xml = configure_file(output : 'gdk.gresource.xml',
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;
}
diff --git a/gdk/win32/gdksurface-win32.c b/gdk/win32/gdksurface-win32.c
index 5a61919d95..a559cb3271 100644
--- a/gdk/win32/gdksurface-win32.c
+++ b/gdk/win32/gdksurface-win32.c
@@ -4941,18 +4941,43 @@ show_surface (GdkSurface *surface)
static gboolean
gdk_win32_toplevel_present (GdkToplevel *toplevel,
- int width,
- int height,
- GdkToplevelLayout *layout)
+ GdkToplevelLayout *layout)
{
GdkSurface *surface = GDK_SURFACE (toplevel);
+ GdkDisplay *display = gdk_surface_get_display (surface);
+ GdkMonitor *monitor;
+ GdkToplevelSize size;
+ int bounds_width, bounds_height;
+ int width, height;
GdkGeometry geometry;
GdkSurfaceHints mask;
+ monitor = gdk_display_get_monitor_at_surface (display, surface);
+ if (monitor)
+ {
+ GdkRectangle workarea;
+
+ gdk_win32_monitor_get_workarea (monitor, &workarea);
+ bounds_width = workarea.width;
+ bounds_height = workarea.height;
+ }
+ else
+ {
+ bounds_width = G_MAXINT;
+ bounds_height = G_MAXINT;
+ }
+
+ gdk_toplevel_size_init (&size, bounds_width, bounds_height);
+ gdk_toplevel_notify_compute_size (toplevel, &size);
+ g_warn_if_fail (size.width > 0);
+ g_warn_if_fail (size.height > 0);
+ width = size.width;
+ height = size.height;
+
if (gdk_toplevel_layout_get_resizable (layout))
{
- geometry.min_width = gdk_toplevel_layout_get_min_width (layout);
- geometry.min_height = gdk_toplevel_layout_get_min_height (layout);
+ geometry.min_width = size.min_width;
+ geometry.min_height = size.min_height;
mask = GDK_HINT_MIN_SIZE;
}
else
diff --git a/gdk/x11/gdksurface-x11.c b/gdk/x11/gdksurface-x11.c
index d797368d79..b0a49cc737 100644
--- a/gdk/x11/gdksurface-x11.c
+++ b/gdk/x11/gdksurface-x11.c
@@ -43,6 +43,7 @@
#include "gdktextureprivate.h"
#include "gdk-private.h"
+#include <graphene.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@@ -1017,7 +1018,8 @@ _gdk_x11_display_create_surface (GdkDisplay *display,
impl->xid = XCreateWindow (xdisplay, xparent,
(surface->x + abs_x) * impl->surface_scale,
(surface->y + abs_y) * impl->surface_scale,
- surface->width * impl->surface_scale, surface->height * impl->surface_scale,
+ MAX (1, surface->width * impl->surface_scale),
+ MAX (1, surface->height * impl->surface_scale),
0, depth, class, xvisual,
xattributes_mask, &xattributes);
@@ -4830,21 +4832,46 @@ gdk_x11_toplevel_class_init (GdkX11ToplevelClass *class)
static gboolean
gdk_x11_toplevel_present (GdkToplevel *toplevel,
- int width,
- int height,
GdkToplevelLayout *layout)
{
GdkSurface *surface = GDK_SURFACE (toplevel);
+ GdkDisplay *display = gdk_surface_get_display (surface);
+ GdkMonitor *monitor;
+ GdkToplevelSize size;
+ int bounds_width, bounds_height;
+ int width, height;
GdkGeometry geometry;
GdkSurfaceHints mask;
gboolean was_mapped;
gdk_x11_surface_unminimize (surface);
+ monitor = gdk_display_get_monitor_at_surface (display, surface);
+ if (monitor)
+ {
+ GdkRectangle workarea;
+
+ gdk_x11_monitor_get_workarea (monitor, &workarea);
+ bounds_width = workarea.width;
+ bounds_height = workarea.height;
+ }
+ else
+ {
+ bounds_width = G_MAXINT;
+ bounds_height = G_MAXINT;
+ }
+
+ gdk_toplevel_size_init (&size, bounds_width, bounds_height);
+ gdk_toplevel_notify_compute_size (toplevel, &size);
+ g_warn_if_fail (size.width > 0);
+ g_warn_if_fail (size.height > 0);
+ width = size.width;
+ height = size.height;
+
if (gdk_toplevel_layout_get_resizable (layout))
{
- geometry.min_width = gdk_toplevel_layout_get_min_width (layout);
- geometry.min_height = gdk_toplevel_layout_get_min_height (layout);
+ geometry.min_width = size.min_width;
+ geometry.min_height = size.min_height;
mask = GDK_HINT_MIN_SIZE;
}
else
@@ -4864,9 +4891,11 @@ gdk_x11_toplevel_present (GdkToplevel *toplevel,
if (gdk_toplevel_layout_get_fullscreen (layout))
{
- GdkMonitor *monitor = gdk_toplevel_layout_get_fullscreen_monitor (layout);
- if (monitor)
- gdk_x11_surface_fullscreen_on_monitor (surface, monitor);
+ GdkMonitor *fullscreen_monitor =
+ gdk_toplevel_layout_get_fullscreen_monitor (layout);
+
+ if (fullscreen_monitor)
+ gdk_x11_surface_fullscreen_on_monitor (surface, fullscreen_monitor);
else
gdk_x11_surface_fullscreen (surface);
}
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 066b1dd873..e22f2e2bfd 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -453,9 +453,7 @@ static void _gtk_window_set_is_active (GtkWindow *window,
gboolean is_active);
static void gtk_window_present_toplevel (GtkWindow *window);
static void gtk_window_update_toplevel (GtkWindow *window);
-static GdkToplevelLayout * gtk_window_compute_layout (GtkWindow *window,
- int min_width,
- int min_height);
+static GdkToplevelLayout * gtk_window_compute_layout (GtkWindow *window);
static void gtk_window_release_application (GtkWindow *window);
@@ -3807,14 +3805,12 @@ gtk_window_hide (GtkWidget *widget)
}
static GdkToplevelLayout *
-gtk_window_compute_layout (GtkWindow *window,
- int min_width,
- int min_height)
+gtk_window_compute_layout (GtkWindow *window)
{
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
GdkToplevelLayout *layout;
- layout = gdk_toplevel_layout_new (min_width, min_height);
+ layout = gdk_toplevel_layout_new ();
gdk_toplevel_layout_set_resizable (layout, priv->resizable);
gdk_toplevel_layout_set_maximized (layout, priv->maximize_initially);
@@ -3829,23 +3825,11 @@ static void
gtk_window_present_toplevel (GtkWindow *window)
{
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
- GdkRectangle request;
- GdkGeometry geometry;
- GdkSurfaceHints flags;
-
- gtk_window_compute_configure_request (window, &request,
- &geometry, &flags);
-
- if (!(flags & GDK_HINT_MIN_SIZE))
- geometry.min_width = geometry.min_height = 1;
if (!priv->layout)
- priv->layout = gtk_window_compute_layout (window, geometry.min_width, geometry.min_height);
+ priv->layout = gtk_window_compute_layout (window);
- gdk_toplevel_present (GDK_TOPLEVEL (priv->surface),
- request.width,
- request.height,
- priv->layout);
+ gdk_toplevel_present (GDK_TOPLEVEL (priv->surface), priv->layout);
}
static void
@@ -3855,22 +3839,10 @@ gtk_window_update_toplevel (GtkWindow *window)
if (priv->surface && gdk_surface_get_mapped (priv->surface))
{
- int min_width = 1;
- int min_height = 1;
-
- if (priv->layout)
- {
- min_width = gdk_toplevel_layout_get_min_width (priv->layout);
- min_height = gdk_toplevel_layout_get_min_height (priv->layout);
- }
-
g_clear_pointer (&priv->layout, gdk_toplevel_layout_unref);
- priv->layout = gtk_window_compute_layout (window, min_width, min_height);
+ priv->layout = gtk_window_compute_layout (window);
- gdk_toplevel_present (GDK_TOPLEVEL (priv->surface),
- gdk_surface_get_width (priv->surface),
- gdk_surface_get_height (priv->surface),
- priv->layout);
+ gdk_toplevel_present (GDK_TOPLEVEL (priv->surface), priv->layout);
}
}
@@ -3898,9 +3870,6 @@ gtk_window_map (GtkWidget *widget)
gtk_window_set_theme_variant (window);
- /* No longer use the default settings */
- priv->need_default_size = FALSE;
-
if (!disable_startup_notification)
{
/* Do we have a custom startup-notification id? */
@@ -3982,7 +3951,7 @@ gtk_window_guess_default_size (GtkWindow *window,
GtkWidget *widget;
GdkSurface *surface;
GdkDisplay *display;
- GdkMonitor *monitor;
+ GdkMonitor *monitor = NULL;
GdkRectangle geometry;
int minimum, natural;
@@ -3993,21 +3962,22 @@ gtk_window_guess_default_size (GtkWindow *window,
if (surface)
{
monitor = gdk_display_get_monitor_at_surface (display, surface);
+ if (monitor)
+ g_object_ref (monitor);
+ }
+
+ if (!monitor)
+ monitor = g_list_model_get_item (gdk_display_get_monitors (display), 0);
+
+ if (monitor)
+ {
gdk_monitor_get_geometry (monitor, &geometry);
+ g_object_unref (monitor);
}
else
{
- monitor = g_list_model_get_item (gdk_display_get_monitors (display), 0);
- if (monitor)
- {
- gdk_monitor_get_geometry (monitor, &geometry);
- g_object_unref (monitor);
- }
- else
- {
- geometry.width = G_MAXINT;
- geometry.height = G_MAXINT;
- }
+ geometry.width = G_MAXINT;
+ geometry.height = G_MAXINT;
}
*width = geometry.width;
@@ -4046,19 +4016,11 @@ gtk_window_get_remembered_size (GtkWindow *window,
int *width,
int *height)
{
- GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
GtkWindowGeometryInfo *info;
*width = 0;
*height = 0;
- if (priv->surface)
- {
- *width = gdk_surface_get_width (priv->surface);
- *height = gdk_surface_get_height (priv->surface);
- return;
- }
-
info = gtk_window_get_geometry_info (window, FALSE);
if (info)
{
@@ -4254,13 +4216,149 @@ update_realized_window_properties (GtkWindow *window)
}
static void
+gtk_window_compute_default_size (GtkWindow *window,
+ int max_width,
+ int max_height,
+ int *width,
+ int *height)
+{
+ GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+ GtkWidget *widget = GTK_WIDGET (window);
+
+ *width = max_width;
+ *height = max_height;
+ if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT)
+ {
+ int minimum, natural;
+
+ gtk_widget_measure (widget, GTK_ORIENTATION_VERTICAL, -1,
+ &minimum, &natural,
+ NULL, NULL);
+ *height = MAX (minimum, MIN (*height, natural));
+
+ gtk_widget_measure (widget, GTK_ORIENTATION_HORIZONTAL,
+ *height,
+ &minimum, &natural,
+ NULL, NULL);
+ *width = MAX (minimum, MIN (*width, natural));
+ }
+ else /* GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH or CONSTANT_SIZE */
+ {
+ int minimum, natural;
+
+ gtk_widget_measure (widget, GTK_ORIENTATION_HORIZONTAL, -1,
+ &minimum, &natural,
+ NULL, NULL);
+ *width = MAX (minimum, MIN (*width, natural));
+
+ gtk_widget_measure (widget, GTK_ORIENTATION_VERTICAL,
+ *width,
+ &minimum, &natural,
+ NULL, NULL);
+ *height = MAX (minimum, MIN (*height, natural));
+ }
+
+ /* No longer use the default settings */
+ priv->need_default_size = FALSE;
+}
+
+static void
+toplevel_compute_size (GdkToplevel *toplevel,
+ GdkToplevelSize *size,
+ GtkWidget *widget)
+{
+ GtkWindow *window = GTK_WINDOW (widget);
+ GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
+ GtkWindowGeometryInfo *info;
+ int width, height;
+ GtkBorder shadow;
+ int min_width, min_height;
+
+ info = gtk_window_get_geometry_info (window, FALSE);
+
+ if (priv->need_default_size)
+ {
+ int remembered_width;
+ int remembered_height;
+ int bounds_width;
+ int bounds_height;
+
+ gdk_toplevel_size_get_bounds (size, &bounds_width, &bounds_height);
+
+ gtk_window_compute_default_size (window,
+ bounds_width, bounds_height,
+ &width, &height);
+ gtk_window_get_remembered_size (window,
+ &remembered_width, &remembered_height);
+ width = MAX (width, remembered_width);
+ height = MAX (height, remembered_height);
+
+ /* Override with default size */
+ if (info)
+ {
+ /* Take width of shadows/headerbar into account. We want to set the
+ * default size of the content area and not the window area.
+ */
+ int default_width_csd = info->default_width;
+ int default_height_csd = info->default_height;
+ gtk_window_update_csd_size (window,
+ &default_width_csd, &default_height_csd,
+ INCLUDE_CSD_SIZE);
+
+ if (info->default_width > 0)
+ width = default_width_csd;
+ if (info->default_height > 0)
+ height = default_height_csd;
+ }
+ }
+ else
+ {
+ /* Default to keeping current size */
+ gtk_window_get_remembered_size (window, &width, &height);
+ }
+
+ /* Override any size with gtk_window_resize() values */
+ if (priv->maximized || priv->fullscreen)
+ {
+ /* Unless we are maximized or fullscreen */
+ gtk_window_get_remembered_size (window, &width, &height);
+ }
+ else if (info)
+ {
+ int resize_width_csd = info->resize_width;
+ int resize_height_csd = info->resize_height;
+ gtk_window_update_csd_size (window,
+ &resize_width_csd, &resize_height_csd,
+ INCLUDE_CSD_SIZE);
+
+ if (info->resize_width > 0)
+ width = resize_width_csd;
+ if (info->resize_height > 0)
+ height = resize_height_csd;
+ }
+
+ /* Don't ever request zero width or height, it's not supported by
+ gdk. The size allocation code will round it to 1 anyway but if
+ we do it then the value returned from this function will is
+ not comparable to the size allocation read from the GtkWindow. */
+ width = MAX (width, 1);
+ height = MAX (height, 1);
+
+ gdk_toplevel_size_set_size (size, width, height);
+
+ get_shadow_width (window, &shadow);
+
+ min_width = width + shadow.left + shadow.right;
+ min_height = height + shadow.top + shadow.bottom;
+ gdk_toplevel_size_set_min_size (size, min_width, min_height);
+}
+
+static void
gtk_window_realize (GtkWidget *widget)
{
GtkWindow *window = GTK_WINDOW (widget);
GtkWindowPrivate *priv = gtk_window_get_instance_private (window);
- GtkAllocation allocation;
GdkSurface *surface;
- GtkBorder shadow;
/* Create default title bar */
if (!priv->client_decorated && gtk_window_should_use_csd (window))
@@ -4284,32 +4382,7 @@ gtk_window_realize (GtkWidget *widget)
}
}
- get_shadow_width (window, &shadow);
-
- /* ensure widget tree is properly size allocated */
- if (_gtk_widget_get_alloc_needed (widget))
- {
- GdkRectangle request;
-
- gtk_window_compute_configure_request (window, &request, NULL, NULL);
-
- allocation.x = shadow.left;
- allocation.y = shadow.top;
- allocation.width = request.width - shadow.left - shadow.right;
- allocation.height = request.height - shadow.top - shadow.bottom;
-
- gtk_widget_size_allocate (widget, &allocation, -1);
-
- gtk_widget_queue_resize (widget);
-
- g_return_if_fail (!_gtk_widget_get_realized (widget));
- }
-
- gtk_widget_get_allocation (widget, &allocation);
-
- surface = gdk_surface_new_toplevel (gtk_widget_get_display (widget),
- MAX (1, allocation.width + shadow.left + shadow.right),
- MAX (1, allocation.height + shadow.top + shadow.bottom));
+ surface = gdk_surface_new_toplevel (gtk_widget_get_display (widget));
priv->surface = surface;
gdk_surface_set_widget (surface, widget);
@@ -4317,6 +4390,7 @@ gtk_window_realize (GtkWidget *widget)
g_signal_connect_swapped (surface, "size-changed", G_CALLBACK (surface_size_changed), widget);
g_signal_connect (surface, "render", G_CALLBACK (surface_render), widget);
g_signal_connect (surface, "event", G_CALLBACK (surface_event), widget);
+ g_signal_connect (surface, "compute-size", G_CALLBACK (toplevel_compute_size), widget);
GTK_WIDGET_CLASS (gtk_window_parent_class)->realize (widget);
@@ -5352,7 +5426,7 @@ gtk_window_move_resize (GtkWindow *window)
new_geometry.min_width = new_geometry.min_height = 1;
g_clear_pointer (&priv->layout, gdk_toplevel_layout_unref);
- priv->layout = gtk_window_compute_layout (window, new_geometry.min_width, new_geometry.min_height);
+ priv->layout = gtk_window_compute_layout (window);
/* This check implies the invariant that we never set info->last
* without setting the hints and sending off a configure request.
@@ -5549,9 +5623,7 @@ gtk_window_move_resize (GtkWindow *window)
if (configure_request_pos_changed)
g_warning ("configure request position changed. This should not happen. Ignoring the position");
- gdk_toplevel_present (GDK_TOPLEVEL (priv->surface),
- new_request.width, new_request.height,
- priv->layout);
+ gdk_toplevel_present (GDK_TOPLEVEL (priv->surface), priv->layout);
}
else
{
diff --git a/gtk/inspector/general.c b/gtk/inspector/general.c
index 2e610a6672..76bd0011e2 100644
--- a/gtk/inspector/general.c
+++ b/gtk/inspector/general.c
@@ -141,7 +141,7 @@ init_version (GtkInspectorGeneral *gen)
#endif
backend = "Unknown";
- surface = gdk_surface_new_toplevel (gen->display, 10, 10);
+ surface = gdk_surface_new_toplevel (gen->display);
gsk_renderer = gsk_renderer_new_for_surface (surface);
if (strcmp (G_OBJECT_TYPE_NAME (gsk_renderer), "GskVulkanRenderer") == 0)
renderer = "Vulkan";
@@ -402,7 +402,7 @@ init_vulkan (GtkInspectorGeneral *gen)
GdkSurface *surface;
GdkVulkanContext *context;
- surface = gdk_surface_new_toplevel (gen->display, 10, 10);
+ surface = gdk_surface_new_toplevel (gen->display);
context = gdk_surface_create_vulkan_context (surface, NULL);
gdk_surface_destroy (surface);
diff --git a/tests/rendernode.c b/tests/rendernode.c
index 49a6c8601c..786cc6d050 100644
--- a/tests/rendernode.c
+++ b/tests/rendernode.c
@@ -128,7 +128,7 @@ main(int argc, char **argv)
GdkSurface *window;
GdkTexture *texture = NULL;
- window = gdk_surface_new_toplevel (gdk_display_get_default(), 10 , 10);
+ window = gdk_surface_new_toplevel (gdk_display_get_default());
renderer = gsk_renderer_new_for_surface (window);
for (run = 0; run < runs; run++)
diff --git a/tests/showrendernode.c b/tests/showrendernode.c
index 670e776e1d..25e9960251 100644
--- a/tests/showrendernode.c
+++ b/tests/showrendernode.c
@@ -181,7 +181,7 @@ main (int argc, char **argv)
if (write_to_filename != NULL)
{
- GdkSurface *surface = gdk_surface_new_toplevel (gdk_display_get_default(), 10 , 10);
+ GdkSurface *surface = gdk_surface_new_toplevel (gdk_display_get_default());
GskRenderer *renderer = gsk_renderer_new_for_surface (surface);
GdkTexture *texture = gsk_renderer_render_texture (renderer, GTK_NODE_VIEW (nodeview)->node, NULL);
@@ -201,7 +201,7 @@ main (int argc, char **argv)
if (compare_node)
{
GtkWidget *box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
- GdkSurface *gdk_surface = gdk_surface_new_toplevel (gdk_display_get_default(), 10 , 10);
+ GdkSurface *gdk_surface = gdk_surface_new_toplevel (gdk_display_get_default());
GskRenderer *renderer = gsk_renderer_new_for_surface (gdk_surface);
GdkTexture *texture = gsk_renderer_render_texture (renderer, GTK_NODE_VIEW (nodeview)->node, NULL);
GtkWidget *image = gtk_image_new_from_paintable (GDK_PAINTABLE (texture));
diff --git a/tests/testfullscreen.c b/tests/testfullscreen.c
index c7deda5e92..3adc82310f 100644
--- a/tests/testfullscreen.c
+++ b/tests/testfullscreen.c
@@ -34,13 +34,10 @@ set_fullscreen_monitor_cb (GtkWidget *widget, gpointer user_data)
monitor = gdk_display_get_monitor_at_surface (display, surface);
else
monitor = NULL;
- layout = gdk_toplevel_layout_new (0, 0);
+ layout = gdk_toplevel_layout_new ();
gdk_toplevel_layout_set_resizable (layout, TRUE);
gdk_toplevel_layout_set_fullscreen (layout, TRUE, monitor);
- gdk_toplevel_present (GDK_TOPLEVEL (surface),
- gdk_surface_get_width (surface),
- gdk_surface_get_height (surface),
- layout);
+ gdk_toplevel_present (GDK_TOPLEVEL (surface), layout);
gdk_toplevel_layout_unref (layout);
}
@@ -51,13 +48,10 @@ remove_fullscreen_cb (GtkWidget *widget, gpointer user_data)
GdkToplevelLayout *layout;
surface = gtk_native_get_surface (gtk_widget_get_native (widget));
- layout = gdk_toplevel_layout_new (0, 0);
+ layout = gdk_toplevel_layout_new ();
gdk_toplevel_layout_set_resizable (layout, TRUE);
gdk_toplevel_layout_set_fullscreen (layout, FALSE, NULL);
- gdk_toplevel_present (GDK_TOPLEVEL (surface),
- gdk_surface_get_width (surface),
- gdk_surface_get_height (surface),
- layout);
+ gdk_toplevel_present (GDK_TOPLEVEL (surface), layout);
gdk_toplevel_layout_unref (layout);
}
diff --git a/testsuite/gsk/compare-render.c b/testsuite/gsk/compare-render.c
index c3d1c570b8..c71ee55b7c 100644
--- a/testsuite/gsk/compare-render.c
+++ b/testsuite/gsk/compare-render.c
@@ -173,7 +173,7 @@ main (int argc, char **argv)
node_file = argv[1];
png_file = argv[2];
- window = gdk_surface_new_toplevel (gdk_display_get_default(), 10 , 10);
+ window = gdk_surface_new_toplevel (gdk_display_get_default());
renderer = gsk_renderer_new_for_surface (window);
g_print ("Node file: '%s'\n", node_file);
diff --git a/testsuite/gtk/defaultvalue.c b/testsuite/gtk/defaultvalue.c
index 4947dac52f..f1b4d1f7fc 100644
--- a/testsuite/gtk/defaultvalue.c
+++ b/testsuite/gtk/defaultvalue.c
@@ -110,7 +110,7 @@ test_type (gconstpointer data)
instance = G_OBJECT (g_object_ref (gtk_settings_get_default ()));
else if (g_type_is_a (type, GDK_TYPE_SURFACE))
{
- instance = G_OBJECT (g_object_ref (gdk_surface_new_toplevel (display, 100, 100)));
+ instance = G_OBJECT (g_object_ref (gdk_surface_new_toplevel (display)));
}
else if (g_type_is_a (type, GTK_TYPE_FILTER_LIST_MODEL) ||
g_type_is_a (type, GTK_TYPE_NO_SELECTION) ||
diff --git a/testsuite/gtk/notify.c b/testsuite/gtk/notify.c
index 5dd4499577..797d05d594 100644
--- a/testsuite/gtk/notify.c
+++ b/testsuite/gtk/notify.c
@@ -430,7 +430,7 @@ test_type (gconstpointer data)
instance = G_OBJECT (g_object_ref (gtk_settings_get_default ()));
else if (g_type_is_a (type, GDK_TYPE_SURFACE))
{
- instance = G_OBJECT (g_object_ref (gdk_surface_new_toplevel (display, 100, 100)));
+ instance = G_OBJECT (g_object_ref (gdk_surface_new_toplevel (display)));
}
else if (g_str_equal (g_type_name (type), "GdkX11Cursor"))
instance = g_object_new (type, "display", display, NULL);
diff --git a/testsuite/gtk/shortcuts.c b/testsuite/gtk/shortcuts.c
index e0ce9c6509..ad5e9c798b 100644
--- a/testsuite/gtk/shortcuts.c
+++ b/testsuite/gtk/shortcuts.c
@@ -322,7 +322,7 @@ test_trigger_trigger (void)
g_object_ref (trigger[2]));
device = gdk_seat_get_keyboard (seat);
- surface = gdk_surface_new_toplevel (display, 100, 100);
+ surface = gdk_surface_new_toplevel (display);
for (i = 0; i < G_N_ELEMENTS (tests); i++)
{
diff --git a/testsuite/gtk/test-focus-chain.c b/testsuite/gtk/test-focus-chain.c
index 2e52388f63..033cec98b5 100644
--- a/testsuite/gtk/test-focus-chain.c
+++ b/testsuite/gtk/test-focus-chain.c
@@ -218,6 +218,16 @@ get_dir_for_file (const char *path)
}
static gboolean
+quit_iteration_loop (gpointer user_data)
+{
+ gboolean *keep_running = user_data;
+
+ *keep_running = FALSE;
+
+ return G_SOURCE_REMOVE;
+}
+
+static gboolean
load_ui_file (GFile *ui_file,
GFile *ref_file,
const char *ext)
@@ -230,6 +240,8 @@ load_ui_file (GFile *ui_file,
GError *error = NULL;
GtkDirectionType dir;
gboolean success = FALSE;
+ gboolean keep_running = TRUE;
+ guint timeout_handle_id;
ui_path = g_file_get_path (ui_file);
@@ -238,6 +250,19 @@ load_ui_file (GFile *ui_file,
g_assert (window != NULL);
+ gtk_widget_show (window);
+
+ timeout_handle_id = g_timeout_add (2000,
+ quit_iteration_loop,
+ &keep_running);
+ while (keep_running)
+ {
+ if (!g_main_context_iteration (NULL, FALSE))
+ break;
+ }
+ if (keep_running)
+ g_source_remove (timeout_handle_id);
+
if (ext)
{
int i;