GtkWindow: Allow setting size from geometry

If you set a geometry widget via gtk_window_set_geometry_hints() it
becomes very hard to compute appropriate toplevel sizes in pixels
to make the window a particular size. Synthesizing strings and passing
them to gtk_window_parse_geometry() is possible, but to avoid
avoid such ugliness, add functions:

 gtk_window_set_default_geometry()
 gtk_window_resize_to_geometry()

That act like gtk_window_set_default_size() and
gtk_window_resize() but are in terms of the resize increments of the
geometry widget.

https://bugzilla.gnome.org/show_bug.cgi?id=631796
This commit is contained in:
Owen W. Taylor 2010-10-09 22:38:54 -04:00
parent 519d758711
commit a4a7a611f2
3 changed files with 161 additions and 47 deletions

View File

@ -281,11 +281,15 @@ struct _GtkWindowGeometryInfo
*/
guint position_constraints_changed : 1;
/* if true, default_width, height come from gtk_window_parse_geometry,
* and thus should be multiplied by the increments and affect the
* geometry widget only
/* if true, default_width, height should be multiplied by the
* increments and affect the geometry widget only
*/
guint default_is_geometry : 1;
/* if true, resize_width, height should be multiplied by the
* increments and affect the geometry widget only
*/
guint resize_is_geometry : 1;
GtkWindowLastGeometryInfo last;
};
@ -3928,6 +3932,30 @@ gtk_window_set_default_size (GtkWindow *window,
gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE);
}
/**
* gtk_window_set_default_geometry:
* @window: a #GtkWindow
* @width: width in resize increments, or -1 to unset the default width
* @height: height in resize increments, or -1 to unset the default height
*
* Like gtk_window_set_default_size(), but @width and @height are interpreted
* in terms of the base size and increment set with
* gtk_window_set_geometry_hints.
*
* Since: 3.0
*/
void
gtk_window_set_default_geometry (GtkWindow *window,
gint width,
gint height)
{
g_return_if_fail (GTK_IS_WINDOW (window));
g_return_if_fail (width >= -1);
g_return_if_fail (height >= -1);
gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE);
}
/**
* gtk_window_get_default_size:
* @window: a #GtkWindow
@ -3992,6 +4020,39 @@ gtk_window_resize (GtkWindow *window,
info->resize_width = width;
info->resize_height = height;
info->resize_is_geometry = FALSE;
gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
}
/**
* gtk_window_resize_to_geometry:
* @window: a #GtkWindow
* @width: width in resize increments to resize the window to
* @height: height in resize increments to resize the window to
*
* Like gtk_window_resize(), but @width and @height are interpreted
* in terms of the base size and increment set with
* gtk_window_set_geometry_hints.
*
* Since: 3.0
*/
void
gtk_window_resize_to_geometry (GtkWindow *window,
gint width,
gint height)
{
GtkWindowGeometryInfo *info;
g_return_if_fail (GTK_IS_WINDOW (window));
g_return_if_fail (width > 0);
g_return_if_fail (height > 0);
info = gtk_window_get_geometry_info (window, TRUE);
info->resize_width = width;
info->resize_height = height;
info->resize_is_geometry = TRUE;
gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window));
}
@ -6061,11 +6122,48 @@ _gtk_window_unset_focus_and_default (GtkWindow *window,
* Functions related to resizing *
*********************************/
static void
geometry_size_to_pixels (GdkGeometry *geometry,
guint flags,
guint *width,
guint *height)
{
gint base_width = 0;
gint base_height = 0;
gint min_width = 0;
gint min_height = 0;
gint width_inc = 1;
gint height_inc = 1;
if (flags & GDK_HINT_BASE_SIZE)
{
base_width = geometry->base_width;
base_height = geometry->base_height;
}
if (flags & GDK_HINT_MIN_SIZE)
{
min_width = geometry->min_width;
min_height = geometry->min_height;
}
if (flags & GDK_HINT_RESIZE_INC)
{
width_inc = geometry->width_inc;
height_inc = geometry->height_inc;
}
if (width)
*width = MAX (*width * width_inc + base_width, min_width);
if (height)
*height = MAX (*height * height_inc + base_height, min_height);
}
/* This function doesn't constrain to geometry hints */
static void
gtk_window_compute_configure_request_size (GtkWindow *window,
guint *width,
guint *height)
gtk_window_compute_configure_request_size (GtkWindow *window,
GdkGeometry *geometry,
guint flags,
guint *width,
guint *height)
{
GtkWindowPrivate *priv = window->priv;
GtkRequisition requisition;
@ -6098,44 +6196,16 @@ gtk_window_compute_configure_request_size (GtkWindow *window,
/* Override requisition with default size */
if (info)
{
gint base_width = 0;
gint base_height = 0;
gint min_width = 0;
gint min_height = 0;
gint width_inc = 1;
gint height_inc = 1;
if (info->default_is_geometry &&
(info->default_width > 0 || info->default_height > 0))
{
GdkGeometry geometry;
guint flags;
gtk_window_compute_hints (window, &geometry, &flags);
if (flags & GDK_HINT_BASE_SIZE)
{
base_width = geometry.base_width;
base_height = geometry.base_height;
}
if (flags & GDK_HINT_MIN_SIZE)
{
min_width = geometry.min_width;
min_height = geometry.min_height;
}
if (flags & GDK_HINT_RESIZE_INC)
{
width_inc = geometry.width_inc;
height_inc = geometry.height_inc;
}
}
{
if (info->default_width > 0)
*width = MAX (info->default_width * width_inc + base_width, min_width);
*width = info->default_width;
if (info->default_height > 0)
*height = MAX (info->default_height * height_inc + base_height, min_height);
*height = info->default_height;
if (info->default_is_geometry)
geometry_size_to_pixels (geometry, flags,
info->default_width > 0 ? width : NULL,
info->default_height > 0 ? height : NULL);
}
}
else
@ -6153,10 +6223,14 @@ gtk_window_compute_configure_request_size (GtkWindow *window,
if (info)
{
if (info->resize_width > 0)
*width = info->resize_width;
*width = info->resize_width;
if (info->resize_height > 0)
*height = info->resize_height;
*height = info->resize_height;
if (info->resize_is_geometry)
geometry_size_to_pixels (geometry, flags,
info->resize_width > 0 ? width : NULL,
info->resize_height > 0 ? height : NULL);
}
/* Don't ever request zero width or height, its not supported by
@ -6308,9 +6382,11 @@ gtk_window_compute_configure_request (GtkWindow *window,
screen = gtk_window_check_screen (window);
gtk_window_compute_configure_request_size (window, (guint *)&w, (guint *)&h);
gtk_window_compute_hints (window, &new_geometry, &new_flags);
gtk_window_compute_configure_request_size (window,
&new_geometry, new_flags,
(guint *)&w, (guint *)&h);
gtk_window_constrain_size (window,
&new_geometry, new_flags,
w, h,
@ -7084,6 +7160,7 @@ gtk_window_compute_hints (GtkWindow *window,
{
/* For simplicity, we always set the base hint, even when we
* don't expect it to have any visible effect.
* (Note: geometry_size_to_pixels() depends on this.)
*/
*new_flags |= GDK_HINT_BASE_SIZE;

View File

@ -315,6 +315,14 @@ void gtk_window_get_position (GtkWindow *window,
gint *root_y);
gboolean gtk_window_parse_geometry (GtkWindow *window,
const gchar *geometry);
void gtk_window_set_default_geometry (GtkWindow *window,
gint width,
gint height);
void gtk_window_resize_to_geometry (GtkWindow *window,
gint width,
gint height);
GtkWindowGroup *gtk_window_get_group (GtkWindow *window);
gboolean gtk_window_has_group (GtkWindow *window);

View File

@ -73,6 +73,19 @@ on_drawing_area_draw (GtkWidget *drawing_area,
return FALSE;
}
static void
on_resize_clicked (GtkWidget *button,
gpointer data)
{
GtkWidget *window = gtk_widget_get_toplevel (button);
GdkWindowHints mask = GPOINTER_TO_UINT(data);
if ((mask & GDK_HINT_RESIZE_INC) != 0)
gtk_window_resize_to_geometry (GTK_WINDOW (window), 8, 8);
else
gtk_window_resize_to_geometry (GTK_WINDOW (window), 8 * GRID_SIZE, 8 * GRID_SIZE);
}
static void
create_window (GdkWindowHints mask)
{
@ -80,6 +93,7 @@ create_window (GdkWindowHints mask)
GtkWidget *drawing_area;
GtkWidget *table;
GtkWidget *label;
GtkWidget *button;
GdkGeometry geometry;
GString *label_text = g_string_new (NULL);
int border = 0;
@ -130,6 +144,15 @@ create_window (GdkWindowHints mask)
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
0, 0);
button = gtk_button_new_with_label ("Resize");
g_signal_connect (button, "clicked",
G_CALLBACK (on_resize_clicked),
GUINT_TO_POINTER (mask));
gtk_table_attach (GTK_TABLE (table), button,
0, 2, 2, 3,
GTK_EXPAND, 0,
0, 8);
gtk_container_add (GTK_CONTAINER (window), table);
if ((mask & GDK_HINT_BASE_SIZE) != 0)
@ -169,6 +192,12 @@ create_window (GdkWindowHints mask)
{
if (geometry_string)
gtk_window_parse_geometry (GTK_WINDOW (window), geometry_string);
else
gtk_window_set_default_geometry (GTK_WINDOW (window), 10, 10);
}
else
{
gtk_window_set_default_geometry (GTK_WINDOW (window), 10 * GRID_SIZE, 10 * GRID_SIZE);
}
gtk_widget_show (window);