Compare commits

...

32 Commits

Author SHA1 Message Date
Benjamin Otte
562bfc901d container: Don't keep our own variable trying to track need for resize
Insteaad, introduce gtk_widget_needs_allocate() and use that.
2015-10-09 15:32:11 +02:00
Benjamin Otte
0b92fab921 widget: Make invisible widgets not propagate resizes
Do not queue a resize on the parent if the widget is not visible.
Invisible widgets do not influence the parents size.
2015-10-09 15:32:11 +02:00
Benjamin Otte
1a59583fda window: Don't queue resizes when inhibiting resizes
Since the frame clock, the inhibit happens on the GDK level, so this
code is no longer necessary.
2015-10-09 15:32:11 +02:00
Benjamin Otte
99c52058c6 widget: Make gtk_widget_queue_allocate() not resize
This commit toggles the big switch. We now don't run size_allocate()
from the toplevel up anymore in cases where we don't need to.

Things might be broken in subtle ways as a result of this commit. We'll
have to find them and fix them.
2015-10-09 15:28:40 +02:00
Benjamin Otte
b4c7ce2bf4 widget: Track if a child needs an allocation
This is not used so far.
2015-10-09 15:26:46 +02:00
Benjamin Otte
28ddddd498 widget: Refactor function
Turn it from a loop into tail-calling itself.
2015-10-09 15:26:46 +02:00
Benjamin Otte
9a42cdfce3 widget: Move resize function into gtkwidget.c
There's no sizegroup specific code left in it, but lots of
widget-specifics.
2015-10-09 15:26:46 +02:00
Benjamin Otte
dfe75cf413 sizegroup: Merge function into only caller 2015-10-09 15:26:46 +02:00
Benjamin Otte
f1a1a3d336 sizegroup: Simplify widget's size group invalidation
Since we do not queue resizes twice anymore, we can just walk the list
of groups without deduplication.
2015-10-09 15:26:45 +02:00
Benjamin Otte
9770f637f4 sizegroup: Skip resizes on widgets that have resize queued
Widgets that already have a resize queued don't need to walk the whole
parent chain and queue another resize. It's enough to do it once per
resize.

This also means that sizegroups cannot use the shortcut of just
invalidating the first widget in the group anymore. That widget might
already have a resize queued while others don't.
2015-10-09 15:26:45 +02:00
Benjamin Otte
a41184b74b widget: Warn on calls to queue_resize() during size_allocate()
This happens way too much, so it's disabled unless GTK_DEBUG=geometry is
on.

Also, we can't detect it in the call to queue_resize() yet, only during
size_allocate(), so the warning comes after the signal emission.
2015-10-09 15:26:45 +02:00
Benjamin Otte
b5954ee4f2 widget: Clear pending resizes after size_allocate()
This catches the cases where widgets call gtk_widget_queue_resize()
in their size_allocate() callback.
2015-10-09 15:26:45 +02:00
Benjamin Otte
c4eead047d widget: Warn if size-unqueried widgets get allocated
Widgets should have gtk_widget_get_preferred_width/height() called
on them before gtk_widget_size_allocate() gets called.
Add a check for this.
2015-10-09 15:26:45 +02:00
Benjamin Otte
0f377b9fc3 widget: Add a resize_needed flag
... and API to set and unset it.

It is set when gtk_widget_queue_resize() is called.
It is unset when gtk_widget_get_preferred_width/height() is called.

So far it is not used.
2015-10-09 15:26:45 +02:00
Benjamin Otte
86b25ad2ee widget: Add a function that does actual resize
It's just shuffling code around.
2015-10-09 15:26:45 +02:00
Benjamin Otte
b926061ca9 sizegroup: Merge function into only caller
Both functions were running the same loop. Just running the loop once
seems advantageous.
2015-10-09 15:26:44 +02:00
Benjamin Otte
64390e6bbe sizegroup: Don't invalidate over resize containers.
Before this commit, a widget tree like this:
  Window
    AnyContainer (part of SizeGroup1)
      GtkClutterEmbed
        SomeWidget
when calling gtk_widget_queue_resize(SomeWidget), would invalidate
SizeGroup1, when it should have stopped at the GtkClutterEmbed (which is
a RESIZE_IMMEDIATE child).
2015-10-09 15:26:44 +02:00
Benjamin Otte
7064185529 sizegroup: Refactor function
Get rid of continues in loop. This allows doing more complex things in
future commits.
2015-10-09 15:26:44 +02:00
Benjamin Otte
a7780d70e5 sizegroup: Refactor function 2015-10-09 15:26:44 +02:00
Benjamin Otte
c84c4017ba sizegroup: Remove special case before loop
The loop actually does the right thing already. There's no need to
complicate things.
2015-10-09 15:26:44 +02:00
Benjamin Otte
7b88c1470c sizegroup: refactor
The code looks a lot less dangerous if it doesn't look like we're
casting a random widget to a container.
2015-10-09 15:26:44 +02:00
Benjamin Otte
ad94755a03 sizegroup: Fold function into only caller 2015-10-09 15:26:44 +02:00
Benjamin Otte
ff40f5e137 sizegroup: Move container function into its only caller 2015-10-09 15:26:44 +02:00
Benjamin Otte
c5c99faa44 widget: Use gtk_widget_queue_allocate() when clip changes
There's no need to queue a full resize there.
2015-10-09 15:26:44 +02:00
Benjamin Otte
4c6c9bf7a1 API: widget: Add gtk_widget_queue_allocate()
This is so widgets can queue a rerun of their allocation logic, but
without triggering resizes everywhere.

For now, it just calls gtk_widget_queue_resize().
2015-10-09 15:26:43 +02:00
Benjamin Otte
73e415c1b5 container: Use correct allocation for calling size_allocate() 2015-10-09 15:26:41 +02:00
Benjamin Otte
886021dd02 API: widget: Add gtk_widget_get_allocated_size()
See docs for what this is.
2015-10-09 15:26:03 +02:00
Benjamin Otte
384a7223e2 sizegroup: Remove GtkQueueResizeFlags
They were only used with geometry widgets.
2015-10-09 15:26:03 +02:00
Benjamin Otte
bc58b428e5 widget: Remove _gtk_widget_override_size_request()
The function was only used by the geometry widget.
2015-10-09 15:26:03 +02:00
Benjamin Otte
97f6e5de4c window: Ignore geometry widget
Ignore the geometry widget passed to gtk_window_set_geometry_hints().
Usind the widget itself was a hack that complicates the size request
machinery.

It is also incorrect in that it doesn't respect height-for-width.

Last but not least, it was only used by gnome-terminal and that
application can easily work without it.
2015-10-09 15:26:03 +02:00
Benjamin Otte
acd7048269 container: Don't randomly call gtk_widget_set_allocation()
gtk_widget_size_allocate() does that already.
2015-10-09 15:26:03 +02:00
Benjamin Otte
4305a65885 entry: Always render like with is_cellrenderer
And remove the API to set that variable.
If you want the entry to not fill its whole allocated area,
  gtk_widget_set_valign (entry, GTK_ALIGN_FILL);
will give you the old behavior.
2015-10-09 15:26:02 +02:00
13 changed files with 317 additions and 432 deletions

View File

@@ -5553,6 +5553,7 @@ gtk_widget_get_allocated_height
gtk_widget_get_allocation
gtk_widget_set_allocation
gtk_widget_get_allocated_baseline
gtk_widget_get_allocated_size
gtk_widget_get_clip
gtk_widget_set_clip
gtk_widget_get_app_paintable

View File

@@ -1490,10 +1490,6 @@ gtk_combo_box_add (GtkContainer *container,
if (priv->has_entry)
{
/* this flag is a hack to tell the entry to fill its allocation.
*/
_gtk_entry_set_is_cell_renderer (GTK_ENTRY (widget), TRUE);
g_signal_connect (widget, "changed",
G_CALLBACK (gtk_combo_box_entry_contents_changed),
combo_box);
@@ -1521,7 +1517,6 @@ gtk_combo_box_remove (GtkContainer *container,
g_signal_handlers_disconnect_by_func (widget,
gtk_combo_box_entry_contents_changed,
container);
_gtk_entry_set_is_cell_renderer (GTK_ENTRY (widget), FALSE);
}
}

View File

@@ -264,7 +264,6 @@ struct _GtkContainerPrivate
guint has_focus_chain : 1;
guint reallocate_redraws : 1;
guint resize_pending : 1;
guint restyle_pending : 1;
guint resize_mode : 2;
guint request_mode : 2;
@@ -1670,9 +1669,6 @@ gtk_container_destroy (GtkWidget *widget)
GtkContainer *container = GTK_CONTAINER (widget);
GtkContainerPrivate *priv = container->priv;
if (priv->resize_pending)
_gtk_container_dequeue_resize_handler (container);
if (priv->restyle_pending)
priv->restyle_pending = FALSE;
@@ -1901,15 +1897,6 @@ gtk_container_remove (GtkContainer *container,
g_object_unref (container);
}
void
_gtk_container_dequeue_resize_handler (GtkContainer *container)
{
g_return_if_fail (GTK_IS_CONTAINER (container));
g_return_if_fail (container->priv->resize_pending);
container->priv->resize_pending = FALSE;
}
/**
* gtk_container_set_resize_mode:
* @container: a #GtkContainer
@@ -2020,13 +2007,12 @@ gtk_container_idle_sizer (GdkFrameClock *clock,
* than trying to explicitly work around them with some extra flags,
* since it doesn't cause any actual harm.
*/
if (container->priv->resize_pending)
if (gtk_widget_needs_allocate (GTK_WIDGET (container)))
{
container->priv->resize_pending = FALSE;
gtk_container_check_resize (container);
}
if (!container->priv->restyle_pending && !container->priv->resize_pending)
if (!container->priv->restyle_pending && !gtk_widget_needs_allocate (GTK_WIDGET (container)))
{
_gtk_container_stop_idle_sizer (container);
}
@@ -2068,7 +2054,7 @@ _gtk_container_stop_idle_sizer (GtkContainer *container)
container->priv->resize_clock = NULL;
}
static void
void
gtk_container_queue_resize_handler (GtkContainer *container)
{
GtkWidget *widget;
@@ -2086,11 +2072,8 @@ gtk_container_queue_resize_handler (GtkContainer *container)
switch (container->priv->resize_mode)
{
case GTK_RESIZE_QUEUE:
if (!container->priv->resize_pending)
{
container->priv->resize_pending = TRUE;
gtk_container_start_idle_sizer (container);
}
if (gtk_widget_needs_allocate (widget))
gtk_container_start_idle_sizer (container);
break;
case GTK_RESIZE_IMMEDIATE:
@@ -2105,32 +2088,6 @@ gtk_container_queue_resize_handler (GtkContainer *container)
}
}
static void
_gtk_container_queue_resize_internal (GtkContainer *container,
gboolean invalidate_only)
{
GtkWidget *widget;
widget = (GtkWidget*)container;
do
{
_gtk_widget_set_alloc_needed (widget, TRUE);
_gtk_size_request_cache_clear (_gtk_widget_peek_request_cache (widget));
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
if (((GtkContainer*)widget)->priv->resize_mode != GTK_RESIZE_PARENT)
break;
G_GNUC_END_IGNORE_DEPRECATIONS;
widget = _gtk_widget_get_parent (widget);
}
while (widget);
if (widget && !invalidate_only)
gtk_container_queue_resize_handler ((GtkContainer*)widget);
}
void
_gtk_container_queue_restyle (GtkContainer *container)
{
@@ -2147,40 +2104,13 @@ _gtk_container_queue_restyle (GtkContainer *container)
priv->restyle_pending = TRUE;
}
/**
* _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 recomputed, 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_maybe_start_idle_sizer (GtkContainer *container)
{
if (container->priv->restyle_pending || container->priv->resize_pending)
if (!GTK_IS_RESIZE_CONTAINER (container))
return;
if (container->priv->restyle_pending || gtk_widget_needs_allocate (GTK_WIDGET (container)))
gtk_container_start_idle_sizer (container);
}
@@ -2198,27 +2128,33 @@ gtk_container_real_check_resize (GtkContainer *container)
GtkWidget *widget = GTK_WIDGET (container);
GtkAllocation allocation;
GtkRequisition requisition;
int baseline;
gtk_widget_get_preferred_size (widget, &requisition, NULL);
_gtk_widget_get_allocation (widget, &allocation);
if (requisition.width > allocation.width ||
requisition.height > allocation.height)
if (_gtk_widget_get_alloc_needed (widget))
{
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
if (GTK_IS_RESIZE_CONTAINER (container))
gtk_widget_get_preferred_size (widget, &requisition, NULL);
gtk_widget_get_allocated_size (widget, &allocation, &baseline);
if (requisition.width > allocation.width ||
requisition.height > allocation.height)
{
gtk_widget_size_allocate (widget, &allocation);
gtk_widget_set_allocation (widget, &allocation);
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
if (GTK_IS_RESIZE_CONTAINER (container))
{
gtk_widget_size_allocate (widget, &allocation);
}
else
gtk_widget_queue_resize (widget);
G_GNUC_END_IGNORE_DEPRECATIONS;
}
else
gtk_widget_queue_resize (widget);
G_GNUC_END_IGNORE_DEPRECATIONS;
{
gtk_widget_size_allocate_with_baseline (widget, &allocation, baseline);
}
}
else
{
gtk_widget_size_allocate (widget, &allocation);
gtk_widget_set_allocation (widget, &allocation);
gtk_widget_ensure_allocate (widget);
}
}
@@ -2240,6 +2176,7 @@ gtk_container_resize_children (GtkContainer *container)
{
GtkAllocation allocation;
GtkWidget *widget;
gint baseline;
/* resizing invariants:
* toplevels have *always* resize_mode != GTK_RESIZE_PARENT set.
@@ -2249,10 +2186,9 @@ gtk_container_resize_children (GtkContainer *container)
g_return_if_fail (GTK_IS_CONTAINER (container));
widget = GTK_WIDGET (container);
_gtk_widget_get_allocation (widget, &allocation);
gtk_widget_get_allocated_size (widget, &allocation, &baseline);
gtk_widget_size_allocate (widget, &allocation);
gtk_widget_set_allocation (widget, &allocation);
gtk_widget_size_allocate_with_baseline (widget, &allocation, baseline);
}
static void

View File

@@ -25,9 +25,8 @@
G_BEGIN_DECLS
void _gtk_container_queue_resize (GtkContainer *container);
void gtk_container_queue_resize_handler (GtkContainer *container);
void _gtk_container_queue_restyle (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);

View File

@@ -218,7 +218,6 @@ struct _GtkEntryPrivate
guint cursor_visible : 1;
guint editing_canceled : 1; /* Only used by GtkCellRendererText */
guint in_click : 1; /* Flag so we don't select all when clicking in entry to focus in */
guint is_cell_renderer : 1;
guint invisible_char_set : 1;
guint mouse_cursor_obscured : 1;
guint need_im_reset : 1;
@@ -2654,7 +2653,6 @@ gtk_entry_init (GtkEntry *entry)
priv->dnd_position = -1;
priv->width_chars = -1;
priv->max_width_chars = -1;
priv->is_cell_renderer = FALSE;
priv->editing_canceled = FALSE;
priv->truncate_multiline = FALSE;
priv->shadow_type = GTK_SHADOW_IN;
@@ -3588,45 +3586,25 @@ gtk_entry_get_frame_size (GtkEntry *entry,
gint *width,
gint *height)
{
GtkEntryPrivate *priv = entry->priv;
GtkAllocation allocation;
GtkWidget *widget = GTK_WIDGET (entry);
gint baseline;
gint req_height, req_baseline, unused;
gtk_entry_get_preferred_height_and_baseline_for_width (widget, -1, &req_height, &unused, &req_baseline, &unused);
gtk_widget_get_allocation (widget, &allocation);
baseline = gtk_widget_get_allocated_baseline (widget);
if (x)
*x = allocation.x;
if (y)
{
if (priv->is_cell_renderer)
*y = 0;
else
{
if (baseline == -1)
*y = (allocation.height - req_height) / 2;
else
*y = baseline - req_baseline;
}
*y += allocation.y;
}
*y = allocation.y;
if (width)
*width = allocation.width;
if (height)
{
if (priv->is_cell_renderer)
*height = allocation.height;
else
*height = req_height;
}
*height = allocation.height;
}
static void
@@ -5260,11 +5238,6 @@ static void
gtk_entry_start_editing (GtkCellEditable *cell_editable,
GdkEvent *event)
{
GtkEntry *entry = GTK_ENTRY (cell_editable);
GtkEntryPrivate *priv = entry->priv;
priv->is_cell_renderer = TRUE;
g_signal_connect (cell_editable, "activate",
G_CALLBACK (gtk_cell_editable_entry_activated), NULL);
g_signal_connect (cell_editable, "key-press-event",
@@ -10938,24 +10911,6 @@ keymap_state_changed (GdkKeymap *keymap,
remove_capslock_feedback (entry);
}
/*
* _gtk_entry_set_is_cell_renderer:
* @entry: a #GtkEntry
* @is_cell_renderer: new value
*
* This is a helper function for GtkComboBox. A GtkEntry in a GtkComboBox
* is supposed to behave like a GtkCellEditable when placed in a combo box.
*
* I.e take up its allocation and get GtkEntry->is_cell_renderer = TRUE.
*
*/
void
_gtk_entry_set_is_cell_renderer (GtkEntry *entry,
gboolean is_cell_renderer)
{
entry->priv->is_cell_renderer = is_cell_renderer;
}
/**
* gtk_entry_set_input_purpose:
* @entry: a #GtkEntry

View File

@@ -86,8 +86,6 @@ gchar* _gtk_entry_get_display_text (GtkEntry *entry,
void _gtk_entry_get_borders (GtkEntry *entry,
GtkBorder *borders);
GtkIMContext* _gtk_entry_get_im_context (GtkEntry *entry);
void _gtk_entry_set_is_cell_renderer (GtkEntry *entry,
gboolean is_cell_renderer);
void _gtk_entry_grab_focus (GtkEntry *entry,
gboolean select_all);

View File

@@ -23,26 +23,8 @@
G_BEGIN_DECLS
/*
* GtkQueueResizeFlags:
* @GTK_QUEUE_RESIZE_INVALIDATE_ONLY: invalidate all cached sizes
* as we would normally do when a widget is queued for resize,
* but dont 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;
GHashTable * _gtk_size_group_get_widget_peers (GtkWidget *for_widget,
GtkOrientation orientation);
void _gtk_size_group_queue_resize (GtkWidget *widget,
GtkQueueResizeFlags flags);
G_END_DECLS

View File

@@ -26,7 +26,6 @@
#include "gtktypebuiltins.h"
#include "gtkprivate.h"
#include "gtksizegroup-private.h"
#include "gtksizerequestcacheprivate.h"
#include "gtkwidgetprivate.h"
#include "gtkcontainerprivate.h"
@@ -204,99 +203,15 @@ _gtk_size_group_get_widget_peers (GtkWidget *for_widget,
}
static void
real_queue_resize (GtkWidget *widget,
GtkQueueResizeFlags flags)
{
GtkWidget *container;
_gtk_widget_set_alloc_needed (widget, TRUE);
_gtk_size_request_cache_clear (_gtk_widget_peek_request_cache (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
queue_resize_on_widget (GtkWidget *widget,
gboolean check_siblings,
GtkQueueResizeFlags flags)
{
GHashTable *widgets;
GHashTable *groups;
GtkWidget *parent;
widgets = g_hash_table_new (NULL, NULL);
groups = g_hash_table_new (NULL, NULL);
parent = widget;
while (parent)
{
GSList *widget_groups;
GHashTableIter iter;
gpointer current;
if (widget == parent && !check_siblings)
{
real_queue_resize (widget, flags);
parent = _gtk_widget_get_parent (parent);
continue;
}
widget_groups = _gtk_widget_get_sizegroups (parent);
if (!widget_groups)
{
if (widget == parent)
real_queue_resize (widget, flags);
parent = _gtk_widget_get_parent (parent);
continue;
}
g_hash_table_remove_all (widgets);
g_hash_table_remove_all (groups);
add_widget_to_closure (widgets, groups, parent, -1);
g_hash_table_iter_init (&iter, widgets);
while (g_hash_table_iter_next (&iter, &current, NULL))
{
if (current == parent)
{
if (widget == parent)
real_queue_resize (parent, flags);
}
else if (current == widget)
{
g_warning ("A container and its child are part of this SizeGroup");
}
else
queue_resize_on_widget (current, FALSE, flags);
}
parent = _gtk_widget_get_parent (parent);
}
g_hash_table_destroy (widgets);
g_hash_table_destroy (groups);
}
static void
queue_resize_on_group (GtkSizeGroup *size_group)
queue_resize_on_group (GtkSizeGroup *size_group)
{
GtkSizeGroupPrivate *priv = size_group->priv;
GSList *list;
if (priv->widgets)
queue_resize_on_widget (priv->widgets->data, TRUE, 0);
for (list = priv->widgets; list; list = list->next)
{
gtk_widget_queue_resize (list->data);
}
}
static void
@@ -604,19 +519,6 @@ gtk_size_group_get_widgets (GtkSizeGroup *size_group)
return size_group->priv->widgets;
}
/**
* _gtk_size_group_queue_resize:
* @widget: a #GtkWidget
*
* Queue a resize on a widget, and on all other widgets grouped with this widget.
**/
void
_gtk_size_group_queue_resize (GtkWidget *widget,
GtkQueueResizeFlags flags)
{
queue_resize_on_widget (widget, TRUE, flags);
}
typedef struct {
gchar *name;
gint line;

View File

@@ -149,6 +149,8 @@ gtk_widget_query_size_for_orientation (GtkWidget *widget,
gint nat_baseline = -1;
gboolean found_in_cache;
gtk_widget_ensure_resize (widget);
if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_CONSTANT_SIZE)
for_size = -1;

View File

@@ -805,8 +805,7 @@ static gboolean setup_template_child (GtkWidgetTemplat
static void gtk_widget_set_usize_internal (GtkWidget *widget,
gint width,
gint height,
GtkQueueResizeFlags flags);
gint height);
static void gtk_widget_add_events_internal (GtkWidget *widget,
GdkDevice *device,
@@ -3670,10 +3669,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, 0);
gtk_widget_set_usize_internal (widget, g_value_get_int (value), -2);
break;
case PROP_HEIGHT_REQUEST:
gtk_widget_set_usize_internal (widget, -2, g_value_get_int (value), 0);
gtk_widget_set_usize_internal (widget, -2, g_value_get_int (value));
break;
case PROP_VISIBLE:
gtk_widget_set_visible (widget, g_value_get_boolean (value));
@@ -4328,6 +4327,7 @@ gtk_widget_init (GTypeInstance *instance, gpointer g_class)
priv->double_buffered = TRUE;
priv->redraw_on_alloc = TRUE;
priv->alloc_needed = TRUE;
priv->alloc_needed_on_child = TRUE;
switch (_gtk_widget_get_direction (widget))
{
@@ -5574,6 +5574,72 @@ gtk_widget_queue_draw (GtkWidget *widget)
0, 0, rect.width, rect.height);
}
static void
gtk_widget_set_alloc_needed (GtkWidget *widget);
/**
* gtk_widget_queue_allocate:
* @widget: a #GtkWidget
*
* This function is only for use in widget implementations.
*
* Flags the widget for a rerun of the GtkWidgetClass::size_allocate
* function. Use this function instead of gtk_widget_queue_resize()
* when the @widget's size request didn't change but it wants to
* reposition its contents.
*
* An example user of this function is gtk_widget_set_halign().
*/
void
gtk_widget_queue_allocate (GtkWidget *widget)
{
g_return_if_fail (GTK_IS_WIDGET (widget));
gtk_widget_set_alloc_needed (widget);
}
/**
* gtk_widget_queue_resize_internal:
* @widget: a #GtkWidget
*
* Queue a resize on a widget, and on all other widgets grouped with this widget.
**/
void
gtk_widget_queue_resize_internal (GtkWidget *widget)
{
GSList *groups, *l, *widgets;
if (gtk_widget_get_resize_needed (widget))
return;
gtk_widget_queue_resize_on_widget (widget);
groups = _gtk_widget_get_sizegroups (widget);
for (l = groups; l; l = l->next)
{
if (gtk_size_group_get_ignore_hidden (l->data) && !gtk_widget_is_visible (widget))
continue;
for (widgets = gtk_size_group_get_widgets (l->data); widgets; widgets = widgets->next)
{
gtk_widget_queue_resize_internal (widgets->data);
}
}
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
if (GTK_IS_RESIZE_CONTAINER (widget))
{
gtk_container_queue_resize_handler (GTK_CONTAINER (widget));
G_GNUC_END_IGNORE_DEPRECATIONS;
}
else if (_gtk_widget_get_visible (widget))
{
GtkWidget *parent = _gtk_widget_get_parent (widget);
if (parent)
gtk_widget_queue_resize_internal (parent);
}
}
/**
* gtk_widget_queue_resize:
* @widget: a #GtkWidget
@@ -5597,7 +5663,7 @@ gtk_widget_queue_resize (GtkWidget *widget)
if (_gtk_widget_get_realized (widget))
gtk_widget_queue_draw (widget);
_gtk_size_group_queue_resize (widget, 0);
gtk_widget_queue_resize_internal (widget);
}
/**
@@ -5614,7 +5680,7 @@ gtk_widget_queue_resize_no_redraw (GtkWidget *widget)
{
g_return_if_fail (GTK_IS_WIDGET (widget));
_gtk_size_group_queue_resize (widget, 0);
gtk_widget_queue_resize_internal (widget);
}
/**
@@ -5821,6 +5887,13 @@ gtk_widget_size_allocate_with_baseline (GtkWidget *widget,
gtk_widget_push_verify_invariants (widget);
#ifdef G_ENABLE_DEBUG
if (gtk_widget_get_resize_needed (widget))
{
g_warning ("Allocating size to %s %p without calling gtk_widget_get_preferred_width/height(). "
"How does the code know the size to allocate?",
gtk_widget_get_name (widget), widget);
}
if (GTK_DEBUG_CHECK (GEOMETRY))
{
gint depth;
@@ -5862,6 +5935,9 @@ gtk_widget_size_allocate_with_baseline (GtkWidget *widget,
old_baseline = priv->allocated_baseline;
real_allocation = *allocation;
priv->allocated_size = *allocation;
priv->allocated_size_baseline = baseline;
adjusted_allocation = real_allocation;
if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH)
{
@@ -5957,7 +6033,16 @@ gtk_widget_size_allocate_with_baseline (GtkWidget *widget,
GTK_WIDGET_GET_CLASS (widget)->size_allocate (widget, &real_allocation);
/* Size allocation is god... after consulting god, no further requests or allocations are needed */
#ifdef G_ENABLE_DEBUG
if (GTK_DEBUG_CHECK (GEOMETRY) && gtk_widget_get_resize_needed (widget))
{
g_warning ("%s %p or a child called gtk_widget_queue_resize() during size_allocte().",
gtk_widget_get_name (widget), widget);
}
#endif
gtk_widget_ensure_resize (widget);
priv->alloc_needed = FALSE;
priv->alloc_needed_on_child = FALSE;
size_changed |= (old_clip.width != priv->clip.width ||
old_clip.height != priv->clip.height);
@@ -5998,6 +6083,9 @@ gtk_widget_size_allocate_with_baseline (GtkWidget *widget,
}
out:
if (priv->alloc_needed_on_child)
gtk_widget_ensure_allocate (widget);
gtk_widget_pop_verify_invariants (widget);
}
@@ -7082,6 +7170,7 @@ gtk_widget_draw (GtkWidget *widget,
{
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (!widget->priv->alloc_needed);
g_return_if_fail (!widget->priv->alloc_needed_on_child);
g_return_if_fail (cr != NULL);
cairo_save (cr);
@@ -8126,16 +8215,19 @@ gtk_widget_real_style_updated (GtkWidget *widget)
if (widget->priv->anchored)
{
static GtkBitmask *affects_size, *affects_redraw;
static GtkBitmask *affects_size, *affects_redraw, *affects_allocate;
if (G_UNLIKELY (affects_size == NULL))
{
affects_size = _gtk_css_style_property_get_mask_affecting (GTK_CSS_AFFECTS_SIZE | GTK_CSS_AFFECTS_CLIP);
affects_size = _gtk_css_style_property_get_mask_affecting (GTK_CSS_AFFECTS_SIZE);
affects_allocate = _gtk_css_style_property_get_mask_affecting (GTK_CSS_AFFECTS_CLIP);
affects_redraw = _gtk_css_style_property_get_mask_affecting (GTK_CSS_AFFECTS_REDRAW);
}
if (changes == NULL || _gtk_bitmask_intersects (changes, affects_size))
gtk_widget_queue_resize (widget);
else if (_gtk_bitmask_intersects (changes, affects_allocate))
gtk_widget_queue_allocate (widget);
else if (_gtk_bitmask_intersects (changes, affects_redraw))
gtk_widget_queue_draw (widget);
}
@@ -8896,6 +8988,8 @@ _gtk_widget_set_visible_flag (GtkWidget *widget,
priv->allocation.width = 1;
priv->allocation.height = 1;
memset (&priv->clip, 0, sizeof (priv->clip));
memset (&priv->allocated_size, 0, sizeof (priv->allocated_size));
priv->allocated_size_baseline = 0;
}
}
@@ -10972,7 +11066,7 @@ gtk_widget_error_bell (GtkWidget *widget)
settings = gtk_widget_get_settings (widget);
if (!settings)
return;
return;
g_object_get (settings,
"gtk-error-bell", &beep,
@@ -10985,8 +11079,7 @@ gtk_widget_error_bell (GtkWidget *widget)
static void
gtk_widget_set_usize_internal (GtkWidget *widget,
gint width,
gint height,
GtkQueueResizeFlags flags)
gint height)
{
GtkWidgetPrivate *priv = widget->priv;
gboolean changed = FALSE;
@@ -10995,25 +11088,20 @@ gtk_widget_set_usize_internal (GtkWidget *widget,
if (width > -2 && priv->width != width)
{
if ((flags & GTK_QUEUE_RESIZE_INVALIDATE_ONLY) == 0)
g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_WIDTH_REQUEST]);
g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_WIDTH_REQUEST]);
priv->width = width;
changed = TRUE;
}
if (height > -2 && priv->height != height)
{
if ((flags & GTK_QUEUE_RESIZE_INVALIDATE_ONLY) == 0)
g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_HEIGHT_REQUEST]);
g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_HEIGHT_REQUEST]);
priv->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);
gtk_widget_queue_resize (widget);
}
g_object_thaw_notify (G_OBJECT (widget));
@@ -11070,7 +11158,7 @@ gtk_widget_set_size_request (GtkWidget *widget,
if (height == 0)
height = 1;
gtk_widget_set_usize_internal (widget, width, height, 0);
gtk_widget_set_usize_internal (widget, width, height);
}
@@ -11115,52 +11203,6 @@ gtk_widget_has_size_request (GtkWidget *widget)
return !(widget->priv->width == -1 && widget->priv->height == -1);
}
/**
* _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_height: location to store previous forced minimum height
*
* Temporarily establishes a forced minimum size for a widget; this
* is used by GtkWindow when calculating the size to add to the
* windows geometry widget. Cached sizes for the widget and its
* parents are invalidated, so that subsequent calls to the size
* negotiation machinery produce the overridden 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
@@ -14589,7 +14631,7 @@ gtk_widget_set_halign (GtkWidget *widget,
return;
widget->priv->halign = align;
gtk_widget_queue_resize (widget);
gtk_widget_queue_allocate (widget);
g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_HALIGN]);
}
@@ -14655,7 +14697,7 @@ gtk_widget_set_valign (GtkWidget *widget,
return;
widget->priv->valign = align;
gtk_widget_queue_resize (widget);
gtk_widget_queue_allocate (widget);
g_object_notify_by_pspec (G_OBJECT (widget), widget_props[PROP_VALIGN]);
}
@@ -15582,6 +15624,42 @@ _gtk_widget_set_simple_clip (GtkWidget *widget,
gtk_widget_set_clip (widget, &clip);
}
/**
* gtk_widget_get_allocated_size:
* @widget: a #GtkWidget
* @allocation: (out) (allow-none): a pointer to a #GtkAllocation to copy to
* @baseline: (out) (allow-none): a pointer to an integer to copy to
*
* Retrieves the widgets allocated size.
*
* This function returns the last values passed to
* gtk_widget_size_allocate_with_baseline(). The value differs from
* the size returned in gtk_widget_get_allocation() in that functions
* like gtk_widget_set_halign() can adjust the allocation, but not
* the value returned by this function.
*
* If a widget is not visible, its allocated size is 0.
*
* Since: 3.20
*/
void
gtk_widget_get_allocated_size (GtkWidget *widget,
GtkAllocation *allocation,
int *baseline)
{
GtkWidgetPrivate *priv;
g_return_if_fail (GTK_IS_WIDGET (widget));
g_return_if_fail (allocation != NULL);
priv = widget->priv;
if (allocation)
*allocation = priv->allocated_size;
if (baseline)
*baseline = priv->allocated_size_baseline;
}
/**
* gtk_widget_get_allocation:
* @widget: a #GtkWidget
@@ -16140,11 +16218,107 @@ _gtk_widget_get_alloc_needed (GtkWidget *widget)
return widget->priv->alloc_needed;
}
void
_gtk_widget_set_alloc_needed (GtkWidget *widget,
gboolean alloc_needed)
static void
gtk_widget_set_alloc_needed (GtkWidget *widget)
{
widget->priv->alloc_needed = alloc_needed;
GtkWidgetPrivate *priv = widget->priv;
priv->alloc_needed = TRUE;
do
{
if (priv->alloc_needed_on_child)
break;
priv->alloc_needed_on_child = TRUE;
if (!priv->visible)
break;
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
if (GTK_IS_RESIZE_CONTAINER (widget))
{
gtk_container_queue_resize_handler (GTK_CONTAINER (widget));
break;
}
G_GNUC_END_IGNORE_DEPRECATIONS;
widget = priv->parent;
if (widget == NULL)
break;
priv = widget->priv;
}
while (TRUE);
}
gboolean
gtk_widget_needs_allocate (GtkWidget *widget)
{
GtkWidgetPrivate *priv = widget->priv;
if (!priv->visible || !priv->child_visible)
return FALSE;
if (priv->resize_needed || priv->alloc_needed || priv->alloc_needed_on_child)
return TRUE;
return FALSE;
}
void
gtk_widget_ensure_allocate (GtkWidget *widget)
{
GtkWidgetPrivate *priv = widget->priv;
if (!gtk_widget_needs_allocate (widget))
return;
gtk_widget_ensure_resize (widget);
/* This code assumes that we only reach here if the previous
* allocation is still valid (ie no resize was queued).
* If that wasn't true, the parent would have taken care of
* things.
*/
if (priv->alloc_needed)
{
GtkAllocation allocation;
int baseline;
gtk_widget_get_allocated_size (widget, &allocation, &baseline);
gtk_widget_size_allocate_with_baseline (widget, &allocation, baseline);
}
else if (priv->alloc_needed_on_child)
{
priv->alloc_needed_on_child = FALSE;
if (GTK_IS_CONTAINER (widget))
gtk_container_foreach (GTK_CONTAINER (widget),
(GtkCallback) gtk_widget_ensure_allocate,
NULL);
}
}
void
gtk_widget_queue_resize_on_widget (GtkWidget *widget)
{
GtkWidgetPrivate *priv = widget->priv;
priv->resize_needed = TRUE;
gtk_widget_set_alloc_needed (widget);
}
void
gtk_widget_ensure_resize (GtkWidget *widget)
{
GtkWidgetPrivate *priv = widget->priv;
if (!priv->resize_needed)
return;
priv->resize_needed = FALSE;
_gtk_size_request_cache_clear (&priv->requests);
}
void

View File

@@ -663,6 +663,8 @@ GDK_AVAILABLE_IN_ALL
void gtk_widget_queue_resize (GtkWidget *widget);
GDK_AVAILABLE_IN_ALL
void gtk_widget_queue_resize_no_redraw (GtkWidget *widget);
GDK_AVAILABLE_IN_3_20
void gtk_widget_queue_allocate (GtkWidget *widget);
GDK_AVAILABLE_IN_3_8
GdkFrameClock* gtk_widget_get_frame_clock (GtkWidget *widget);
@@ -918,6 +920,10 @@ GDK_AVAILABLE_IN_ALL
int gtk_widget_get_allocated_height (GtkWidget *widget);
GDK_AVAILABLE_IN_3_10
int gtk_widget_get_allocated_baseline (GtkWidget *widget);
GDK_AVAILABLE_IN_3_20
void gtk_widget_get_allocated_size (GtkWidget *widget,
GtkAllocation *allocation,
int *baseline);
GDK_AVAILABLE_IN_ALL
void gtk_widget_get_allocation (GtkWidget *widget,

View File

@@ -72,7 +72,9 @@ struct _GtkWidgetPrivate
guint in_reparent : 1;
/* Queue-resize related flags */
guint alloc_needed : 1;
guint resize_needed : 1; /* queue_resize() has been called but no get_preferred_size() yet */
guint alloc_needed : 1; /* this widget needs a size_allocate() call */
guint alloc_needed_on_child : 1; /* 0 or more children - or this widget - need a size_allocate() call */
/* Expand-related flags */
guint need_compute_expand : 1; /* Need to recompute computed_[hv]_expand */
@@ -130,6 +132,8 @@ struct _GtkWidgetPrivate
GtkStyleContext *context;
/* The widget's allocated size */
GtkAllocation allocated_size;
gint allocated_size_baseline;
GtkAllocation allocation;
GtkAllocation clip;
gint allocated_baseline;
@@ -163,8 +167,10 @@ gboolean _gtk_widget_get_shadowed (GtkWidget *widget);
void _gtk_widget_set_shadowed (GtkWidget *widget,
gboolean shadowed);
gboolean _gtk_widget_get_alloc_needed (GtkWidget *widget);
void _gtk_widget_set_alloc_needed (GtkWidget *widget,
gboolean alloc_needed);
gboolean gtk_widget_needs_allocate (GtkWidget *widget);
void gtk_widget_queue_resize_on_widget (GtkWidget *widget);
void gtk_widget_ensure_resize (GtkWidget *widget);
void gtk_widget_ensure_allocate (GtkWidget *widget);
void _gtk_widget_draw (GtkWidget *widget,
cairo_t *cr);
void _gtk_widget_scale_changed (GtkWidget *widget);
@@ -181,14 +187,6 @@ void _gtk_widget_add_attached_window (GtkWidget *widget,
void _gtk_widget_remove_attached_window (GtkWidget *widget,
GtkWindow *window);
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);
void _gtk_widget_get_preferred_size_for_size (GtkWidget *widget,
GtkOrientation orientation,
gint size,
@@ -293,6 +291,12 @@ gboolean gtk_widget_has_size_request (GtkWidget *widget);
/* inline getters */
static inline gboolean
gtk_widget_get_resize_needed (GtkWidget *widget)
{
return widget->priv->resize_needed;
}
static inline GtkWidget *
_gtk_widget_get_parent (GtkWidget *widget)
{

View File

@@ -346,7 +346,6 @@ struct _GtkWindowGeometryInfo
*/
GdkGeometry geometry; /* Geometry hints */
GdkWindowHints mask;
GtkWidget *widget; /* subwidget to which hints apply */
/* from last gtk_window_resize () - if > 0, indicates that
* we should resize to this size.
*/
@@ -3916,7 +3915,6 @@ gtk_window_get_geometry_info (GtkWindow *window,
info->last.configure_request.y = 0;
info->last.configure_request.width = -1;
info->last.configure_request.height = -1;
info->widget = NULL;
info->mask = 0;
priv->geometry_info = info;
}
@@ -3927,7 +3925,9 @@ gtk_window_get_geometry_info (GtkWindow *window,
/**
* gtk_window_set_geometry_hints:
* @window: a #GtkWindow
* @geometry_widget: (allow-none): widget the geometry hints will be applied to or %NULL
* @geometry_widget: (allow-none): widget the geometry hints used to be applied to
* or %NULL. Since 3.18 this argument is ignored and GTK behaves as if %NULL was
* set.
* @geometry: (allow-none): struct containing geometry information or %NULL
* @geom_mask: mask indicating which struct fields should be paid attention to
*
@@ -3950,17 +3950,6 @@ gtk_window_set_geometry_hints (GtkWindow *window,
info = gtk_window_get_geometry_info (window, TRUE);
if (info->widget)
g_signal_handlers_disconnect_by_func (info->widget,
gtk_widget_destroyed,
&info->widget);
info->widget = geometry_widget;
if (info->widget)
g_signal_connect (geometry_widget, "destroy",
G_CALLBACK (gtk_widget_destroyed),
&info->widget);
if (geometry)
info->geometry = *geometry;
@@ -5695,10 +5684,6 @@ gtk_window_finalize (GObject *object)
if (priv->geometry_info)
{
if (priv->geometry_info->widget)
g_signal_handlers_disconnect_by_func (priv->geometry_info->widget,
gtk_widget_destroyed,
&priv->geometry_info->widget);
g_free (priv->geometry_info);
}
@@ -7559,7 +7544,8 @@ gtk_window_configure_event (GtkWidget *widget,
priv->configure_notify_received = TRUE;
gtk_widget_queue_resize (widget);
gtk_widget_queue_allocate (widget);
gtk_container_queue_resize_handler (GTK_CONTAINER (widget));
return TRUE;
}
@@ -8120,6 +8106,8 @@ gtk_window_check_resize (GtkContainer *container)
* so handle it like a normal window */
if (!_gtk_widget_is_toplevel (GTK_WIDGET (container)))
GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
else if (!_gtk_widget_get_alloc_needed (GTK_WIDGET (container)))
GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container);
else if (gtk_widget_get_visible (GTK_WIDGET (container)))
gtk_window_move_resize (GTK_WINDOW (container));
}
@@ -9498,13 +9486,6 @@ gtk_window_move_resize (GtkWindow *window)
* FIXME: we should also dequeue the pending redraws here, since
* we handle those ourselves upon ->configure_notify_received==TRUE.
*/
G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
if (gtk_container_get_resize_mode (container) == GTK_RESIZE_QUEUE)
{
gtk_widget_queue_resize_no_redraw (widget);
_gtk_container_dequeue_resize_handler (container);
}
G_GNUC_END_IGNORE_DEPRECATIONS;
}
}
else
@@ -9638,56 +9619,6 @@ gtk_window_compute_hints (GtkWindow *window,
*new_flags = 0;
}
if (geometry_info && geometry_info->widget)
{
/* 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*.
*
* +----------+
* |AAAAAAAAA | At small sizes, the minimum sizes of widgets
* |GGGGG B| in the border can confuse things
* |GGGGG B|
* | B|
* +----------+
*
* +-----------+
* |AAAAAAAAA | When the geometry widget is large, things are
* |GGGGGGGGGGB| clearer.
* |GGGGGGGGGGB|
* |GGGGGGGGGG |
* +-----------+
*/
#define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */
GtkRequisition req;
int current_width, current_height;
_gtk_widget_override_size_request (geometry_info->widget,
TEMPORARY_SIZE, TEMPORARY_SIZE,
&current_width, &current_height);
gtk_widget_get_preferred_size (widget,
&req, NULL);
_gtk_widget_restore_size_request (geometry_info->widget,
current_width, current_height);
extra_width = req.width - TEMPORARY_SIZE;
extra_height = req.height - TEMPORARY_SIZE;
if (extra_width < 0 || extra_height < 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
* in gtk_window_move_resize() when we want the position
* honored.