diff options
author | Matthias Clasen <mclasen@redhat.com> | 2020-08-05 16:19:19 +0000 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2020-08-05 16:19:19 +0000 |
commit | d7c4f93c76eaeab7d90fef486bc6eed9e3c6580c (patch) | |
tree | abf8dfa7f2b159397c61b93ce1383dcff09262bb | |
parent | 0b0f7dc9c0d6350babaacad26156f7a06eb69585 (diff) | |
parent | 2ff74eb667c2cbe293c7309d5661fa438e8431c4 (diff) | |
download | gtk+-d7c4f93c76eaeab7d90fef486bc6eed9e3c6580c.tar.gz |
Merge branch 'wip/compute-size' into 'master'
Compute size via signal
See merge request GNOME/gtk!2325
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 @@ -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; |