forked from AuroraMiddleware/gtk
Fix handling of the geometry widget
The geometry widget feature of gtk_window_set_geometry_hints() has never really worked right because the calculation that GTK+ did to compute the base size of the window only worked when the geometry widget had a larger minimum size than anything else in the window. Setup: * Move the GtkSizeGroup private functions to a new private header gtksizegroup-private.h * Add the possibilty to pass flags to _gtk_size_group_queue_resize(), with the flag GTK_QUEUE_RESIZE_INVALIDATE_ONLY to suppress adding the widget's toplevel to the resize queue. * _gtk_container_resize_invalidate() is added to implement that feature * _gtk_widget_override_size_request()/_gtk_widget_restore_size_request() allow temporarily forcing a large minimum size on the geometry widget without creating resize loops. GtkWindow: * Compute the extra width/height around the geometry widget correctly; print a warning if the computation fails. * Always make the minimum size at least the natural minimum size of the toplevel; GTK+ now fails badly with underallocation. * Always set the base size hint; we were failing to set it properly when the specified minimum size was overriden, but it's harmless to always set it. Tests: * New test 'testgeometry' that replaces the 'gridded geometry' test from testgtk. The new test is roughly similar but creates a bunch of windows showing different possibilities. * The testgtk test is removed. No need to have both. https://bugzilla.gnome.org/show_bug.cgi?id=68668
This commit is contained in:
parent
c250a7e673
commit
88cf547029
@ -382,6 +382,7 @@ gtk_private_h_sources = \
|
||||
gtkrecentchooserdefault.h \
|
||||
gtkrecentchooserprivate.h \
|
||||
gtkrecentchooserutils.h \
|
||||
gtksizegroup-private.h \
|
||||
gtksocketprivate.h \
|
||||
gtktextbtree.h \
|
||||
gtktextbufferserialize.h\
|
||||
|
@ -1609,8 +1609,9 @@ gtk_container_idle_sizer (gpointer data)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
_gtk_container_queue_resize (GtkContainer *container)
|
||||
static void
|
||||
_gtk_container_queue_resize_internal (GtkContainer *container,
|
||||
gboolean invalidate_only)
|
||||
{
|
||||
GtkContainerPrivate *priv;
|
||||
GtkContainer *resize_container;
|
||||
@ -1637,7 +1638,7 @@ _gtk_container_queue_resize (GtkContainer *container)
|
||||
widget = parent;
|
||||
}
|
||||
|
||||
if (resize_container)
|
||||
if (resize_container && !invalidate_only)
|
||||
{
|
||||
if (gtk_widget_get_visible (GTK_WIDGET (resize_container)) &&
|
||||
(gtk_widget_is_toplevel (GTK_WIDGET (resize_container)) ||
|
||||
@ -1677,6 +1678,36 @@ _gtk_container_queue_resize (GtkContainer *container)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_container_queue_resize:
|
||||
* @container: a #GtkContainer
|
||||
*
|
||||
* Determines the "resize container" in the hierarchy above this container
|
||||
* (typically the toplevel, but other containers can be set as resize
|
||||
* containers with gtk_container_set_resize_mode()), marks the container
|
||||
* and all parents up to and including the resize container as needing
|
||||
* to have sizes recompted, and if necessary adds the resize container
|
||||
* to the queue of containers that will be resized out at idle.
|
||||
*/
|
||||
void
|
||||
_gtk_container_queue_resize (GtkContainer *container)
|
||||
{
|
||||
_gtk_container_queue_resize_internal (container, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_container_resize_invalidate:
|
||||
* @container: a #GtkContainer
|
||||
*
|
||||
* Invalidates cached sizes like _gtk_container_queue_resize() but doesn't
|
||||
* actually queue the resize container for resize.
|
||||
*/
|
||||
void
|
||||
_gtk_container_resize_invalidate (GtkContainer *container)
|
||||
{
|
||||
_gtk_container_queue_resize_internal (container, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
gtk_container_check_resize (GtkContainer *container)
|
||||
{
|
||||
|
@ -210,6 +210,7 @@ void gtk_container_class_handle_border_width (GtkContainerClass *klass);
|
||||
|
||||
/* Non-public methods */
|
||||
void _gtk_container_queue_resize (GtkContainer *container);
|
||||
void _gtk_container_resize_invalidate (GtkContainer *container);
|
||||
void _gtk_container_clear_resize_widgets (GtkContainer *container);
|
||||
gchar* _gtk_container_child_composite_name (GtkContainer *container,
|
||||
GtkWidget *child);
|
||||
|
@ -55,6 +55,15 @@ gboolean _gtk_widget_get_height_request_needed (GtkWidget *widget);
|
||||
void _gtk_widget_set_height_request_needed (GtkWidget *widget,
|
||||
gboolean height_request_needed);
|
||||
|
||||
void _gtk_widget_override_size_request (GtkWidget *widget,
|
||||
int width,
|
||||
int height,
|
||||
int *old_width,
|
||||
int *old_height);
|
||||
void _gtk_widget_restore_size_request (GtkWidget *widget,
|
||||
int old_width,
|
||||
int old_height);
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
|
||||
const gchar *_gtk_get_datadir ();
|
||||
|
49
gtk/gtksizegroup-private.h
Normal file
49
gtk/gtksizegroup-private.h
Normal file
@ -0,0 +1,49 @@
|
||||
/* GTK - The GIMP Toolkit
|
||||
* gtksizegroup-private.h:
|
||||
* Copyright (C) 2000-2010 Red Hat Software
|
||||
*
|
||||
* 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, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef __GTK_SIZE_GROUP_PRIVATE_H__
|
||||
#define __GTK_SIZE_GROUP_PRIVATE_H__
|
||||
|
||||
#include <gtk/gtksizegroup.h>
|
||||
|
||||
/**
|
||||
* GtkQueueResizeFlags:
|
||||
* @GTK_QUEUE_RESIZE_INVALIDATE_ONLY: invalidate all cached sizes
|
||||
* as we would normally do when a widget is queued for resize,
|
||||
* but don't actually add the toplevel resize container to the
|
||||
* resize queue. Useful if we want to change the size of a widget
|
||||
* see how that would affect the overall layout, then restore
|
||||
* the old size.
|
||||
*
|
||||
* Flags that affect the operation of queueing a widget for resize.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
GTK_QUEUE_RESIZE_INVALIDATE_ONLY = 1 << 0
|
||||
} GtkQueueResizeFlags;
|
||||
|
||||
void _gtk_size_group_bump_requisition (GtkWidget *widget,
|
||||
GtkSizeGroupMode mode,
|
||||
gint *minimum,
|
||||
gint *natural);
|
||||
void _gtk_size_group_queue_resize (GtkWidget *widget,
|
||||
GtkQueueResizeFlags flags);
|
||||
|
||||
#endif /* __GTK_SIZE_GROUP_PRIVATE_H__ */
|
@ -23,7 +23,7 @@
|
||||
#include "gtkcontainer.h"
|
||||
#include "gtkintl.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtksizegroup.h"
|
||||
#include "gtksizegroup-private.h"
|
||||
#include "gtkbuildable.h"
|
||||
|
||||
|
||||
@ -182,19 +182,27 @@ add_widget_to_closure (GtkWidget *widget,
|
||||
}
|
||||
|
||||
static void
|
||||
real_queue_resize (GtkWidget *widget)
|
||||
real_queue_resize (GtkWidget *widget,
|
||||
GtkQueueResizeFlags flags)
|
||||
{
|
||||
GtkWidget *parent;
|
||||
GtkWidget *container;
|
||||
|
||||
_gtk_widget_set_alloc_needed (widget, TRUE);
|
||||
_gtk_widget_set_width_request_needed (widget, TRUE);
|
||||
_gtk_widget_set_height_request_needed (widget, TRUE);
|
||||
|
||||
parent = gtk_widget_get_parent (widget);
|
||||
if (parent)
|
||||
_gtk_container_queue_resize (GTK_CONTAINER (parent));
|
||||
else if (gtk_widget_is_toplevel (widget) && GTK_IS_CONTAINER (widget))
|
||||
_gtk_container_queue_resize (GTK_CONTAINER (widget));
|
||||
container = gtk_widget_get_parent (widget);
|
||||
if (!container &&
|
||||
gtk_widget_is_toplevel (widget) && GTK_IS_CONTAINER (widget))
|
||||
container = widget;
|
||||
|
||||
if (container)
|
||||
{
|
||||
if (flags & GTK_QUEUE_RESIZE_INVALIDATE_ONLY)
|
||||
_gtk_container_resize_invalidate (GTK_CONTAINER (container));
|
||||
else
|
||||
_gtk_container_queue_resize (GTK_CONTAINER (container));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -215,7 +223,8 @@ reset_group_sizes (GSList *groups)
|
||||
|
||||
static void
|
||||
queue_resize_on_widget (GtkWidget *widget,
|
||||
gboolean check_siblings)
|
||||
gboolean check_siblings,
|
||||
GtkQueueResizeFlags flags)
|
||||
{
|
||||
GtkWidget *parent = widget;
|
||||
GSList *tmp_list;
|
||||
@ -228,7 +237,7 @@ queue_resize_on_widget (GtkWidget *widget,
|
||||
|
||||
if (widget == parent && !check_siblings)
|
||||
{
|
||||
real_queue_resize (widget);
|
||||
real_queue_resize (widget, flags);
|
||||
parent = gtk_widget_get_parent (parent);
|
||||
continue;
|
||||
}
|
||||
@ -237,7 +246,7 @@ queue_resize_on_widget (GtkWidget *widget,
|
||||
if (!widget_groups)
|
||||
{
|
||||
if (widget == parent)
|
||||
real_queue_resize (widget);
|
||||
real_queue_resize (widget, flags);
|
||||
|
||||
parent = gtk_widget_get_parent (parent);
|
||||
continue;
|
||||
@ -258,14 +267,14 @@ queue_resize_on_widget (GtkWidget *widget,
|
||||
if (tmp_list->data == parent)
|
||||
{
|
||||
if (widget == parent)
|
||||
real_queue_resize (parent);
|
||||
real_queue_resize (parent, flags);
|
||||
}
|
||||
else if (tmp_list->data == widget)
|
||||
{
|
||||
g_warning ("A container and its child are part of this SizeGroup");
|
||||
}
|
||||
else
|
||||
queue_resize_on_widget (tmp_list->data, FALSE);
|
||||
queue_resize_on_widget (tmp_list->data, FALSE, flags);
|
||||
|
||||
tmp_list = tmp_list->next;
|
||||
}
|
||||
@ -288,14 +297,14 @@ queue_resize_on_widget (GtkWidget *widget,
|
||||
if (tmp_list->data == parent)
|
||||
{
|
||||
if (widget == parent)
|
||||
real_queue_resize (parent);
|
||||
real_queue_resize (parent, flags);
|
||||
}
|
||||
else if (tmp_list->data == widget)
|
||||
{
|
||||
g_warning ("A container and its child are part of this SizeGroup");
|
||||
}
|
||||
else
|
||||
queue_resize_on_widget (tmp_list->data, FALSE);
|
||||
queue_resize_on_widget (tmp_list->data, FALSE, flags);
|
||||
|
||||
tmp_list = tmp_list->next;
|
||||
}
|
||||
@ -313,7 +322,7 @@ queue_resize_on_group (GtkSizeGroup *size_group)
|
||||
GtkSizeGroupPrivate *priv = size_group->priv;
|
||||
|
||||
if (priv->widgets)
|
||||
queue_resize_on_widget (priv->widgets->data, TRUE);
|
||||
queue_resize_on_widget (priv->widgets->data, TRUE, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -806,11 +815,12 @@ _gtk_size_group_bump_requisition (GtkWidget *widget,
|
||||
* Queue a resize on a widget, and on all other widgets grouped with this widget.
|
||||
**/
|
||||
void
|
||||
_gtk_size_group_queue_resize (GtkWidget *widget)
|
||||
_gtk_size_group_queue_resize (GtkWidget *widget,
|
||||
GtkQueueResizeFlags flags)
|
||||
{
|
||||
initialize_size_group_quarks ();
|
||||
|
||||
queue_resize_on_widget (widget, TRUE);
|
||||
queue_resize_on_widget (widget, TRUE, flags);
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
|
@ -92,15 +92,6 @@ void gtk_size_group_remove_widget (GtkSizeGroup *size_group,
|
||||
GtkWidget *widget);
|
||||
GSList * gtk_size_group_get_widgets (GtkSizeGroup *size_group);
|
||||
|
||||
|
||||
|
||||
void _gtk_size_group_bump_requisition (GtkWidget *widget,
|
||||
GtkSizeGroupMode mode,
|
||||
gint *minimum,
|
||||
gint *natural);
|
||||
void _gtk_size_group_queue_resize (GtkWidget *widget);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GTK_SIZE_GROUP_H__ */
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
#include <config.h>
|
||||
#include "gtksizerequest.h"
|
||||
#include "gtksizegroup.h"
|
||||
#include "gtksizegroup-private.h"
|
||||
#include "gtkdebug.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtkintl.h"
|
||||
|
@ -40,7 +40,7 @@
|
||||
#include "gtkrc.h"
|
||||
#include "gtkselection.h"
|
||||
#include "gtksettings.h"
|
||||
#include "gtksizegroup.h"
|
||||
#include "gtksizegroup-private.h"
|
||||
#include "gtkwidget.h"
|
||||
#include "gtkwindow.h"
|
||||
#include "gtkbindings.h"
|
||||
@ -565,7 +565,8 @@ static void gtk_widget_real_adjust_size_allocation (GtkWidget
|
||||
|
||||
static void gtk_widget_set_usize_internal (GtkWidget *widget,
|
||||
gint width,
|
||||
gint height);
|
||||
gint height,
|
||||
GtkQueueResizeFlags flags);
|
||||
|
||||
static void gtk_widget_add_events_internal (GtkWidget *widget,
|
||||
GdkDevice *device,
|
||||
@ -3022,10 +3023,10 @@ gtk_widget_set_property (GObject *object,
|
||||
gtk_container_add (GTK_CONTAINER (g_value_get_object (value)), widget);
|
||||
break;
|
||||
case PROP_WIDTH_REQUEST:
|
||||
gtk_widget_set_usize_internal (widget, g_value_get_int (value), -2);
|
||||
gtk_widget_set_usize_internal (widget, g_value_get_int (value), -2, 0);
|
||||
break;
|
||||
case PROP_HEIGHT_REQUEST:
|
||||
gtk_widget_set_usize_internal (widget, -2, g_value_get_int (value));
|
||||
gtk_widget_set_usize_internal (widget, -2, g_value_get_int (value), 0);
|
||||
break;
|
||||
case PROP_VISIBLE:
|
||||
gtk_widget_set_visible (widget, g_value_get_boolean (value));
|
||||
@ -4207,7 +4208,7 @@ gtk_widget_queue_resize (GtkWidget *widget)
|
||||
if (gtk_widget_get_realized (widget))
|
||||
gtk_widget_queue_shallow_draw (widget);
|
||||
|
||||
_gtk_size_group_queue_resize (widget);
|
||||
_gtk_size_group_queue_resize (widget, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -4224,7 +4225,7 @@ gtk_widget_queue_resize_no_redraw (GtkWidget *widget)
|
||||
{
|
||||
g_return_if_fail (GTK_IS_WIDGET (widget));
|
||||
|
||||
_gtk_size_group_queue_resize (widget);
|
||||
_gtk_size_group_queue_resize (widget, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -8645,7 +8646,8 @@ gtk_widget_error_bell (GtkWidget *widget)
|
||||
static void
|
||||
gtk_widget_set_usize_internal (GtkWidget *widget,
|
||||
gint width,
|
||||
gint height)
|
||||
gint height,
|
||||
GtkQueueResizeFlags flags)
|
||||
{
|
||||
GtkWidgetAuxInfo *aux_info;
|
||||
gboolean changed = FALSE;
|
||||
@ -8656,19 +8658,26 @@ gtk_widget_set_usize_internal (GtkWidget *widget,
|
||||
|
||||
if (width > -2 && aux_info->width != width)
|
||||
{
|
||||
if ((flags & GTK_QUEUE_RESIZE_INVALIDATE_ONLY) == 0)
|
||||
g_object_notify (G_OBJECT (widget), "width-request");
|
||||
aux_info->width = width;
|
||||
changed = TRUE;
|
||||
}
|
||||
if (height > -2 && aux_info->height != height)
|
||||
{
|
||||
if ((flags & GTK_QUEUE_RESIZE_INVALIDATE_ONLY) == 0)
|
||||
g_object_notify (G_OBJECT (widget), "height-request");
|
||||
aux_info->height = height;
|
||||
changed = TRUE;
|
||||
}
|
||||
|
||||
if (gtk_widget_get_visible (widget) && changed)
|
||||
{
|
||||
if ((flags & GTK_QUEUE_RESIZE_INVALIDATE_ONLY) == 0)
|
||||
gtk_widget_queue_resize (widget);
|
||||
else
|
||||
_gtk_size_group_queue_resize (widget, GTK_QUEUE_RESIZE_INVALIDATE_ONLY);
|
||||
}
|
||||
|
||||
g_object_thaw_notify (G_OBJECT (widget));
|
||||
}
|
||||
@ -8728,7 +8737,7 @@ gtk_widget_set_size_request (GtkWidget *widget,
|
||||
if (height == 0)
|
||||
height = 1;
|
||||
|
||||
gtk_widget_set_usize_internal (widget, width, height);
|
||||
gtk_widget_set_usize_internal (widget, width, height, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -8764,6 +8773,52 @@ gtk_widget_get_size_request (GtkWidget *widget,
|
||||
*height = aux_info->height;
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_widget_override_size_request:
|
||||
* @widget: a #GtkWidget
|
||||
* @width: new forced minimum width
|
||||
* @height: new forced minimum height
|
||||
* @old_width: location to store previous forced minimum width
|
||||
* @old_width: location to store previous forced minumum height
|
||||
*
|
||||
* Temporarily establishes a forced minimum size for a widget; this
|
||||
* is used by GtkWindow when calculating the size to add to the
|
||||
* window's geometry widget. Cached sizes for the widget and its
|
||||
* parents are invalidated, so that subsequent calls to the size
|
||||
* negotiation machinery produce the overriden result, but the
|
||||
* widget is not queued for relayout or redraw. The old size must
|
||||
* be restored with _gtk_widget_restore_size_request() or things
|
||||
* will go screwy.
|
||||
*/
|
||||
void
|
||||
_gtk_widget_override_size_request (GtkWidget *widget,
|
||||
int width,
|
||||
int height,
|
||||
int *old_width,
|
||||
int *old_height)
|
||||
{
|
||||
gtk_widget_get_size_request (widget, old_width, old_height);
|
||||
gtk_widget_set_usize_internal (widget, width, height,
|
||||
GTK_QUEUE_RESIZE_INVALIDATE_ONLY);
|
||||
}
|
||||
|
||||
/**
|
||||
* _gtk_widget_restore_size_request:
|
||||
* @widget: a #GtkWidget
|
||||
* @old_width: saved forced minimum size
|
||||
* @old_height: saved forced minimum size
|
||||
*
|
||||
* Undoes the operation of_gtk_widget_override_size_request().
|
||||
*/
|
||||
void
|
||||
_gtk_widget_restore_size_request (GtkWidget *widget,
|
||||
int old_width,
|
||||
int old_height)
|
||||
{
|
||||
gtk_widget_set_usize_internal (widget, old_width, old_height,
|
||||
GTK_QUEUE_RESIZE_INVALIDATE_ONLY);
|
||||
}
|
||||
|
||||
/**
|
||||
* gtk_widget_set_events:
|
||||
* @widget: a #GtkWidget
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "gtkicontheme.h"
|
||||
#include "gtkmarshalers.h"
|
||||
#include "gtkplug.h"
|
||||
#include "gtkprivate.h"
|
||||
#include "gtkbuildable.h"
|
||||
|
||||
#ifdef GDK_WINDOWING_X11
|
||||
@ -7021,28 +7022,52 @@ gtk_window_compute_hints (GtkWindow *window,
|
||||
|
||||
if (geometry_info && geometry_info->widget)
|
||||
{
|
||||
GtkRequisition requisition;
|
||||
GtkRequisition child_requisition;
|
||||
|
||||
/* FIXME: This really isn't right. It gets the min size wrong and forces
|
||||
* callers to do horrible hacks like set a huge usize on the child requisition
|
||||
* to get the base size right. We really want to find the answers to:
|
||||
/* If the geometry widget is set, then the hints really apply to that
|
||||
* widget. This is pretty much meaningless unless the window layout
|
||||
* is such that the rest of the window adds fixed size borders to
|
||||
* the geometry widget. Our job is to figure the size of the borders;
|
||||
* We do that by asking how big the toplevel would be if the
|
||||
* geometry widget was *really big*.
|
||||
*
|
||||
* - If the geometry widget was infinitely big, how much extra space
|
||||
* would be needed for the stuff around it.
|
||||
* +----------+
|
||||
* |AAAAAAAAA | At small sizes, the minimum sizes of widgets
|
||||
* |GGGGG B| in the border can confuse things
|
||||
* |GGGGG B|
|
||||
* | B|
|
||||
* +----------+
|
||||
*
|
||||
* - If the geometry widget was infinitely small, how big would the
|
||||
* window still have to be.
|
||||
*
|
||||
* Finding these answers would be a bit of a mess here. (Bug #68668)
|
||||
* +-----------+
|
||||
* |AAAAAAAAA | When the geometry widget is large, things are
|
||||
* |GGGGGGGGGGB| clearer.
|
||||
* |GGGGGGGGGGB|
|
||||
* |GGGGGGGGGG |
|
||||
* +-----------+
|
||||
*/
|
||||
gtk_widget_get_preferred_size (geometry_info->widget,
|
||||
&child_requisition, NULL);
|
||||
#define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
|
||||
GtkRequisition requisition;
|
||||
int current_width, current_height;
|
||||
|
||||
_gtk_widget_override_size_request (geometry_info->widget,
|
||||
TEMPORARY_SIZE, TEMPORARY_SIZE,
|
||||
¤t_width, ¤t_height);
|
||||
gtk_widget_get_preferred_size (widget,
|
||||
&requisition, NULL);
|
||||
extra_width = requisition.width - child_requisition.width;
|
||||
extra_height = requisition.height - child_requisition.height;
|
||||
_gtk_widget_restore_size_request (geometry_info->widget,
|
||||
current_width, current_height);
|
||||
|
||||
extra_width = requisition.width - TEMPORARY_SIZE;
|
||||
extra_height = requisition.height - TEMPORARY_SIZE;
|
||||
|
||||
if (extra_width < 0 || extra_width < 0)
|
||||
{
|
||||
g_warning("Toplevel size doesn't seem to directly depend on the "
|
||||
"size of the geometry widget from gtk_window_set_geometry_hints(). "
|
||||
"The geometry widget might not be in the window, or it might not "
|
||||
"be packed into the window appropriately");
|
||||
extra_width = MAX(extra_width, 0);
|
||||
extra_height = MAX(extra_height, 0);
|
||||
}
|
||||
#undef TEMPORARY_SIZE
|
||||
}
|
||||
|
||||
/* We don't want to set GDK_HINT_POS in here, we just set it
|
||||
@ -7055,14 +7080,25 @@ gtk_window_compute_hints (GtkWindow *window,
|
||||
new_geometry->base_width += extra_width;
|
||||
new_geometry->base_height += extra_height;
|
||||
}
|
||||
else if (!(*new_flags & GDK_HINT_MIN_SIZE) &&
|
||||
(*new_flags & GDK_HINT_RESIZE_INC) &&
|
||||
((extra_width != 0) || (extra_height != 0)))
|
||||
else
|
||||
{
|
||||
/* For simplicity, we always set the base hint, even when we
|
||||
* don't expect it to have any visible effect.
|
||||
*/
|
||||
*new_flags |= GDK_HINT_BASE_SIZE;
|
||||
|
||||
new_geometry->base_width = extra_width;
|
||||
new_geometry->base_height = extra_height;
|
||||
|
||||
/* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the
|
||||
* base size is the minimum size */
|
||||
if (*new_flags & GDK_HINT_MIN_SIZE)
|
||||
{
|
||||
if (new_geometry->min_width > 0)
|
||||
new_geometry->base_width += new_geometry->min_width;
|
||||
if (new_geometry->min_height > 0)
|
||||
new_geometry->base_height += new_geometry->min_height;
|
||||
}
|
||||
}
|
||||
|
||||
if (*new_flags & GDK_HINT_MIN_SIZE)
|
||||
@ -7070,12 +7106,12 @@ gtk_window_compute_hints (GtkWindow *window,
|
||||
if (new_geometry->min_width < 0)
|
||||
new_geometry->min_width = requisition.width;
|
||||
else
|
||||
new_geometry->min_width += extra_width;
|
||||
new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width);
|
||||
|
||||
if (new_geometry->min_height < 0)
|
||||
new_geometry->min_height = requisition.height;
|
||||
else
|
||||
new_geometry->min_height += extra_height;
|
||||
new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -47,6 +47,7 @@ noinst_PROGRAMS = $(TEST_PROGS) \
|
||||
testfilechooser \
|
||||
testfilechooserbutton \
|
||||
testframe \
|
||||
testgeometry \
|
||||
testgtk \
|
||||
testheightforwidth \
|
||||
testiconview \
|
||||
@ -136,6 +137,7 @@ testerrors_DEPENDENCIES = $(TEST_DEPS)
|
||||
testfilechooser_DEPENDENCIES = $(TEST_DEPS)
|
||||
testfilechooserbutton_DEPENDENCIES = $(TEST_DEPS)
|
||||
testframe_DEPENDENCIES = $(TEST_DEPS)
|
||||
testgeometry_DEPENDENCIES = $(TEST_DEPS)
|
||||
testgtk_DEPENDENCIES = $(TEST_DEPS)
|
||||
testinput_DEPENDENCIES = $(TEST_DEPS)
|
||||
testimage_DEPENDENCIES = $(TEST_DEPS)
|
||||
@ -201,6 +203,7 @@ testerrors_LDADD = $(LDADDS)
|
||||
testfilechooser_LDADD = $(LDADDS)
|
||||
testfilechooserbutton_LDADD = $(LDADDS)
|
||||
testframe_LDADD = $(LDADDS)
|
||||
testgeometry_LDADD = $(LDADDS)
|
||||
testgtk_LDADD = $(LDADDS)
|
||||
testheightforwidth_LDADD = $(LDADDS)
|
||||
testicontheme_LDADD = $(LDADDS)
|
||||
@ -322,6 +325,9 @@ testbuttons_SOURCES = \
|
||||
testframe_SOURCES = \
|
||||
testframe.c
|
||||
|
||||
testgeometry_SOURCES = \
|
||||
testgeometry.c
|
||||
|
||||
testiconview_SOURCES = \
|
||||
testiconview.c \
|
||||
prop-editor.c
|
||||
|
203
tests/testgeometry.c
Normal file
203
tests/testgeometry.c
Normal file
@ -0,0 +1,203 @@
|
||||
/* testgeometry.c
|
||||
* Author: Owen Taylor <otaylor@redhat.com>
|
||||
* Copyright © 2010 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#define GRID_SIZE 20
|
||||
#define BORDER 6
|
||||
|
||||
static int window_count = 0;
|
||||
const char *geometry_string;
|
||||
|
||||
static void
|
||||
on_window_destroy (GtkWidget *widget)
|
||||
{
|
||||
window_count--;
|
||||
if (window_count == 0)
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_drawing_area_draw (GtkWidget *drawing_area,
|
||||
cairo_t *cr,
|
||||
gpointer data)
|
||||
{
|
||||
int width = gtk_widget_get_allocated_width (drawing_area);
|
||||
int height = gtk_widget_get_allocated_height (drawing_area);
|
||||
int x, y;
|
||||
int border = 0;
|
||||
GdkWindowHints mask = GPOINTER_TO_UINT(data);
|
||||
|
||||
cairo_set_source_rgb (cr, 1, 1, 1);
|
||||
cairo_paint (cr);
|
||||
|
||||
if ((mask & GDK_HINT_BASE_SIZE) != 0)
|
||||
border = BORDER;
|
||||
|
||||
cairo_set_source_rgb (cr, 0, 0, 0);
|
||||
for (y = 0; y < height - 2 * border; y += GRID_SIZE)
|
||||
for (x = 0; x < width - 2 * border; x += GRID_SIZE)
|
||||
if (((x + y) / GRID_SIZE) % 2 == 0)
|
||||
{
|
||||
cairo_rectangle (cr, border + x, border + y, GRID_SIZE, GRID_SIZE);
|
||||
cairo_fill (cr);
|
||||
}
|
||||
|
||||
if (border > 0)
|
||||
{
|
||||
cairo_set_source_rgb (cr, 0, 0, 1);
|
||||
cairo_save (cr);
|
||||
cairo_set_line_width (cr, border);
|
||||
cairo_rectangle (cr,
|
||||
border / 2., border / 2., width - border, height - border);
|
||||
cairo_stroke (cr);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
create_window (GdkWindowHints mask)
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkWidget *drawing_area;
|
||||
GtkWidget *table;
|
||||
GtkWidget *label;
|
||||
GdkGeometry geometry;
|
||||
GString *label_text = g_string_new (NULL);
|
||||
int border = 0;
|
||||
|
||||
if ((mask & GDK_HINT_RESIZE_INC) != 0)
|
||||
g_string_append (label_text, "Gridded\n");
|
||||
if ((mask & GDK_HINT_BASE_SIZE) != 0)
|
||||
g_string_append (label_text, "Base\n");
|
||||
if ((mask & GDK_HINT_MIN_SIZE) != 0)
|
||||
{
|
||||
g_string_append (label_text, "Minimum\n");
|
||||
if ((mask & GDK_HINT_BASE_SIZE) == 0)
|
||||
g_string_append (label_text, "(base=min)\n");
|
||||
}
|
||||
if ((mask & GDK_HINT_MAX_SIZE) != 0)
|
||||
g_string_append (label_text, "Maximum\n");
|
||||
|
||||
if (label_text->len > 0)
|
||||
g_string_erase (label_text, label_text->len - 1, 1);
|
||||
else
|
||||
g_string_append (label_text, "No Options");
|
||||
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
g_signal_connect (window, "destroy",
|
||||
G_CALLBACK (on_window_destroy), NULL);
|
||||
|
||||
table = gtk_table_new (0, 0, FALSE);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (table), 10);
|
||||
|
||||
label = gtk_label_new (label_text->str);
|
||||
gtk_table_attach (GTK_TABLE (table), label,
|
||||
0, 1, 0, 1,
|
||||
GTK_EXPAND | GTK_FILL, GTK_FILL,
|
||||
0, 0);
|
||||
|
||||
label = gtk_label_new ("A\nB\nC\nD\nE");
|
||||
gtk_table_attach (GTK_TABLE (table), label,
|
||||
1, 2, 1, 2,
|
||||
GTK_FILL, GTK_EXPAND | GTK_FILL,
|
||||
0, 0);
|
||||
|
||||
drawing_area = gtk_drawing_area_new ();
|
||||
g_signal_connect (drawing_area, "draw",
|
||||
G_CALLBACK (on_drawing_area_draw),
|
||||
GUINT_TO_POINTER (mask));
|
||||
gtk_table_attach (GTK_TABLE (table), drawing_area,
|
||||
0, 1, 1, 2,
|
||||
GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
|
||||
0, 0);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (window), table);
|
||||
|
||||
if ((mask & GDK_HINT_BASE_SIZE) != 0)
|
||||
{
|
||||
border = BORDER;
|
||||
geometry.base_width = border * 2;
|
||||
geometry.base_height = border * 2;
|
||||
}
|
||||
|
||||
if ((mask & GDK_HINT_RESIZE_INC) != 0)
|
||||
{
|
||||
geometry.width_inc = GRID_SIZE;
|
||||
geometry.height_inc = GRID_SIZE;
|
||||
}
|
||||
|
||||
if ((mask & GDK_HINT_MIN_SIZE) != 0)
|
||||
{
|
||||
geometry.min_width = 5 * GRID_SIZE + 2 * border;
|
||||
geometry.min_height = 5 * GRID_SIZE + 2 * border;
|
||||
}
|
||||
|
||||
if ((mask & GDK_HINT_MAX_SIZE) != 0)
|
||||
{
|
||||
geometry.max_width = 15 * GRID_SIZE + 2 * border;
|
||||
geometry.max_height = 15 * GRID_SIZE + 2 * border;
|
||||
}
|
||||
|
||||
/* Contents must be set up before gtk_window_parse_geometry() */
|
||||
gtk_widget_show_all (table);
|
||||
|
||||
gtk_window_set_geometry_hints (GTK_WINDOW (window),
|
||||
drawing_area,
|
||||
&geometry,
|
||||
mask);
|
||||
|
||||
if ((mask & GDK_HINT_RESIZE_INC) != 0)
|
||||
{
|
||||
if (geometry_string)
|
||||
gtk_window_parse_geometry (GTK_WINDOW (window), geometry_string);
|
||||
}
|
||||
|
||||
gtk_widget_show (window);
|
||||
window_count++;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
GError *error;
|
||||
GOptionEntry options[] = {
|
||||
{ "geometry", 'g', 0, G_OPTION_ARG_STRING, &geometry_string, "Window geometry (only for gridded windows)", "GEOMETRY" },
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
if (!gtk_init_with_args (&argc, &argv, "", options, NULL, &error))
|
||||
{
|
||||
g_print ("Failed to parse args: %s\n", error->message);
|
||||
g_error_free (error);
|
||||
return 1;
|
||||
}
|
||||
|
||||
create_window (GDK_HINT_MIN_SIZE);
|
||||
create_window (GDK_HINT_MIN_SIZE | GDK_HINT_BASE_SIZE);
|
||||
create_window (GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE);
|
||||
create_window (GDK_HINT_RESIZE_INC | GDK_HINT_MIN_SIZE);
|
||||
create_window (GDK_HINT_RESIZE_INC | GDK_HINT_MAX_SIZE);
|
||||
create_window (GDK_HINT_RESIZE_INC | GDK_HINT_BASE_SIZE);
|
||||
create_window (GDK_HINT_RESIZE_INC | GDK_HINT_BASE_SIZE | GDK_HINT_MIN_SIZE);
|
||||
|
||||
gtk_main ();
|
||||
}
|
168
tests/testgtk.c
168
tests/testgtk.c
@ -1644,173 +1644,6 @@ create_statusbar (GtkWidget *widget)
|
||||
gtk_widget_destroy (window);
|
||||
}
|
||||
|
||||
/*
|
||||
* Gridded geometry
|
||||
*/
|
||||
#define GRID_SIZE 20
|
||||
#define DEFAULT_GEOMETRY "10x10"
|
||||
|
||||
static gboolean
|
||||
gridded_geometry_draw (GtkWidget *widget,
|
||||
cairo_t *cr)
|
||||
{
|
||||
GtkStateType state;
|
||||
GtkStyle *style;
|
||||
int i, j, width, height;
|
||||
|
||||
style = gtk_widget_get_style (widget);
|
||||
state = gtk_widget_get_state (widget);
|
||||
width = gtk_widget_get_allocated_width (widget);
|
||||
height = gtk_widget_get_allocated_height (widget);
|
||||
|
||||
gdk_cairo_set_source_color (cr, &style->base[state]);
|
||||
cairo_paint (cr);
|
||||
|
||||
for (i = 0 ; i * GRID_SIZE < width; i++)
|
||||
for (j = 0 ; j * GRID_SIZE < height; j++)
|
||||
{
|
||||
if ((i + j) % 2 == 0)
|
||||
cairo_rectangle (cr, i * GRID_SIZE, j * GRID_SIZE, GRID_SIZE, GRID_SIZE);
|
||||
}
|
||||
|
||||
gdk_cairo_set_source_color (cr, &style->text[state]);
|
||||
cairo_fill (cr);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gridded_geometry_subresponse (GtkDialog *dialog,
|
||||
gint response_id,
|
||||
gchar *geometry_string)
|
||||
{
|
||||
if (response_id == GTK_RESPONSE_NONE)
|
||||
{
|
||||
gtk_widget_destroy (GTK_WIDGET (dialog));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!gtk_window_parse_geometry (GTK_WINDOW (dialog), geometry_string))
|
||||
{
|
||||
g_print ("Can't parse geometry string %s\n", geometry_string);
|
||||
gtk_window_parse_geometry (GTK_WINDOW (dialog), DEFAULT_GEOMETRY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gridded_geometry_response (GtkDialog *dialog,
|
||||
gint response_id,
|
||||
GtkEntry *entry)
|
||||
{
|
||||
if (response_id == GTK_RESPONSE_NONE)
|
||||
{
|
||||
gtk_widget_destroy (GTK_WIDGET (dialog));
|
||||
}
|
||||
else
|
||||
{
|
||||
gchar *geometry_string = g_strdup (gtk_entry_get_text (entry));
|
||||
gchar *title = g_strdup_printf ("Gridded window at: %s", geometry_string);
|
||||
GtkWidget *content_area;
|
||||
GtkWidget *window;
|
||||
GtkWidget *drawing_area;
|
||||
GtkWidget *box;
|
||||
GdkGeometry geometry;
|
||||
|
||||
window = gtk_dialog_new_with_buttons (title,
|
||||
NULL, 0,
|
||||
"Reset", 1,
|
||||
GTK_STOCK_CLOSE, GTK_RESPONSE_NONE,
|
||||
NULL);
|
||||
|
||||
gtk_window_set_screen (GTK_WINDOW (window),
|
||||
gtk_widget_get_screen (GTK_WIDGET (dialog)));
|
||||
g_free (title);
|
||||
g_signal_connect (window, "response",
|
||||
G_CALLBACK (gridded_geometry_subresponse), geometry_string);
|
||||
|
||||
content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
|
||||
|
||||
box = gtk_vbox_new (FALSE, 0);
|
||||
gtk_box_pack_start (GTK_BOX (content_area), box, TRUE, TRUE, 0);
|
||||
|
||||
gtk_container_set_border_width (GTK_CONTAINER (box), 7);
|
||||
|
||||
drawing_area = gtk_drawing_area_new ();
|
||||
g_signal_connect (drawing_area, "draw",
|
||||
G_CALLBACK (gridded_geometry_draw), NULL);
|
||||
gtk_box_pack_start (GTK_BOX (box), drawing_area, TRUE, TRUE, 0);
|
||||
|
||||
/* Gross hack to work around bug 68668... if we set the size request
|
||||
* large enough, then the current
|
||||
*
|
||||
* request_of_window - request_of_geometry_widget
|
||||
*
|
||||
* method of getting the base size works more or less works.
|
||||
*/
|
||||
gtk_widget_set_size_request (drawing_area, 2000, 2000);
|
||||
|
||||
geometry.base_width = 0;
|
||||
geometry.base_height = 0;
|
||||
geometry.min_width = 2 * GRID_SIZE;
|
||||
geometry.min_height = 2 * GRID_SIZE;
|
||||
geometry.width_inc = GRID_SIZE;
|
||||
geometry.height_inc = GRID_SIZE;
|
||||
|
||||
gtk_window_set_geometry_hints (GTK_WINDOW (window), drawing_area,
|
||||
&geometry,
|
||||
GDK_HINT_BASE_SIZE | GDK_HINT_MIN_SIZE | GDK_HINT_RESIZE_INC);
|
||||
|
||||
if (!gtk_window_parse_geometry (GTK_WINDOW (window), geometry_string))
|
||||
{
|
||||
g_print ("Can't parse geometry string %s\n", geometry_string);
|
||||
gtk_window_parse_geometry (GTK_WINDOW (window), DEFAULT_GEOMETRY);
|
||||
}
|
||||
|
||||
gtk_widget_show_all (window);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
create_gridded_geometry (GtkWidget *widget)
|
||||
{
|
||||
static GtkWidget *window = NULL;
|
||||
gpointer window_ptr;
|
||||
GtkWidget *content_area;
|
||||
GtkWidget *entry;
|
||||
GtkWidget *label;
|
||||
|
||||
if (!window)
|
||||
{
|
||||
window = gtk_dialog_new_with_buttons ("Gridded Geometry",
|
||||
NULL, 0,
|
||||
"Create", 1,
|
||||
GTK_STOCK_CLOSE, GTK_RESPONSE_NONE,
|
||||
NULL);
|
||||
|
||||
gtk_window_set_screen (GTK_WINDOW (window),
|
||||
gtk_widget_get_screen (widget));
|
||||
|
||||
content_area = gtk_dialog_get_content_area (GTK_DIALOG (window));
|
||||
|
||||
label = gtk_label_new ("Geometry string:");
|
||||
gtk_box_pack_start (GTK_BOX (content_area), label, FALSE, FALSE, 0);
|
||||
|
||||
entry = gtk_entry_new ();
|
||||
gtk_entry_set_text (GTK_ENTRY (entry), DEFAULT_GEOMETRY);
|
||||
gtk_box_pack_start (GTK_BOX (content_area), entry, FALSE, FALSE, 0);
|
||||
|
||||
g_signal_connect (window, "response",
|
||||
G_CALLBACK (gridded_geometry_response), entry);
|
||||
window_ptr = &window;
|
||||
g_object_add_weak_pointer (G_OBJECT (window), window_ptr);
|
||||
|
||||
gtk_widget_show_all (window);
|
||||
}
|
||||
else
|
||||
gtk_widget_destroy (window);
|
||||
}
|
||||
|
||||
/*
|
||||
* GtkHandleBox
|
||||
*/
|
||||
@ -10152,7 +9985,6 @@ struct {
|
||||
{ "flipping", create_flipping },
|
||||
{ "focus", create_focus },
|
||||
{ "font selection", create_font_selection },
|
||||
{ "gridded geometry", create_gridded_geometry },
|
||||
{ "handle box", create_handle_box },
|
||||
{ "image", create_image },
|
||||
{ "key lookup", create_key_lookup },
|
||||
|
Loading…
Reference in New Issue
Block a user