[gtk+] container: Redo style validation handling
- From: Benjamin Otte <otte src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] container: Redo style validation handling
- Date: Tue, 17 Apr 2012 07:22:49 +0000 (UTC)
commit 04c85a5b3bfe5ed276eb0530ce7bddd55dc7c204
Author: Benjamin Otte <otte redhat com>
Date: Fri Apr 13 17:27:47 2012 +0200
container: Redo style validation handling
Instead of using 1 global queue for both resizes and style validation,
use 2 queues. This makes the code a lot simpler and fixes a bug where we
could accidentally stop restylying for very delayed restyles.
gtk/gtkcontainer.c | 84 +++++++++++++++++++++++++++++++++------------
gtk/gtkcontainerprivate.h | 2 +-
gtk/gtkstylecontext.c | 2 +-
3 files changed, 64 insertions(+), 24 deletions(-)
---
diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c
index ad76313..856df7d 100644
--- a/gtk/gtkcontainer.c
+++ b/gtk/gtkcontainer.c
@@ -240,6 +240,7 @@ 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;
};
@@ -343,6 +344,7 @@ static guint vadjustment_key_id = 0;
static const gchar hadjustment_key[] = "gtk-hadjustment";
static guint hadjustment_key_id = 0;
static GSList *container_resize_queue = NULL;
+static GSList *container_restyle_queue = NULL;
static guint container_signals[LAST_SIGNAL] = { 0 };
static GtkWidgetClass *parent_class = NULL;
extern GParamSpecPool *_gtk_widget_child_property_pool;
@@ -1354,6 +1356,11 @@ gtk_container_destroy (GtkWidget *widget)
if (priv->resize_pending)
_gtk_container_dequeue_resize_handler (container);
+ if (priv->restyle_pending)
+ {
+ container_restyle_queue = g_slist_remove (container_restyle_queue, container);
+ priv->restyle_pending = FALSE;
+ }
if (priv->focus_child)
{
@@ -1628,27 +1635,35 @@ gtk_container_idle_sizer (gpointer data)
GSList *slist;
gint64 current_time;
- /* we may be invoked with a container_resize_queue of NULL, because
- * queue_resize could have been adding an extra idle function while
- * the queue still got processed. we better just ignore such case
- * than trying to explicitely work around them with some extra flags,
- * since it doesn't cause any actual harm.
- */
-
/* We validate the style contexts in a single loop before even trying
* to handle resizes instead of doing validations inline.
* This is mostly necessary for compatibility reasons with old code,
- * because size_allocate functions often change styles and so could
- * cause infinite loops in this function.
+ * because both style_updated and size_allocate functions often change
+ * styles and so could cause infinite loops in this function.
+ *
+ * It's important to note that even an invalid style context returns
+ * sane values. So the result of an invalid style context will never be
+ * a program crash, but only a wrong layout or rendering.
*/
current_time = g_get_monotonic_time ();
- for (slist = container_resize_queue; slist; slist = slist->next)
+ slist = container_restyle_queue;
+ container_restyle_queue = NULL;
+ for (; slist; slist = slist->next)
{
- _gtk_style_context_validate (gtk_widget_get_style_context (slist->data),
+ GtkContainer *container = slist->data;
+
+ container->priv->restyle_pending = FALSE;
+ _gtk_style_context_validate (gtk_widget_get_style_context (GTK_WIDGET (container)),
current_time,
0);
}
+ /* we may be invoked with a container_resize_queue of NULL, because
+ * queue_resize could have been adding an extra idle function while
+ * the queue still got processed. we better just ignore such case
+ * than trying to explicitely work around them with some extra flags,
+ * since it doesn't cause any actual harm.
+ */
while (container_resize_queue)
{
GtkContainer *container;
@@ -1664,11 +1679,24 @@ gtk_container_idle_sizer (gpointer data)
gdk_window_process_all_updates ();
- return FALSE;
+ return container_resize_queue != NULL || container_restyle_queue != NULL;
}
-void
-_gtk_container_queue_resize_handler (GtkContainer *container)
+static void
+gtk_container_start_idle_sizer (GtkContainer *container)
+{
+ /* already started */
+ if (container_resize_queue != NULL ||
+ container_restyle_queue != NULL)
+ return;
+
+ gdk_threads_add_idle_full (GTK_PRIORITY_RESIZE,
+ gtk_container_idle_sizer,
+ NULL, NULL);
+}
+
+static void
+gtk_container_queue_resize_handler (GtkContainer *container)
{
GtkWidget *widget;
@@ -1686,18 +1714,12 @@ _gtk_container_queue_resize_handler (GtkContainer *container)
if (!container->priv->resize_pending)
{
container->priv->resize_pending = TRUE;
- if (container_resize_queue == NULL)
- gdk_threads_add_idle_full (GTK_PRIORITY_RESIZE,
- gtk_container_idle_sizer,
- NULL, NULL);
+ gtk_container_start_idle_sizer (container);
container_resize_queue = g_slist_prepend (container_resize_queue, container);
}
break;
case GTK_RESIZE_IMMEDIATE:
- _gtk_style_context_validate (gtk_widget_get_style_context (widget),
- g_get_monotonic_time (),
- 0);
gtk_container_check_resize (container);
case GTK_RESIZE_PARENT:
@@ -1732,7 +1754,25 @@ _gtk_container_queue_resize_internal (GtkContainer *container,
while (widget);
if (widget && !invalidate_only)
- _gtk_container_queue_resize_handler (GTK_CONTAINER (widget));
+ gtk_container_queue_resize_handler (GTK_CONTAINER (widget));
+}
+
+void
+_gtk_container_queue_restyle (GtkContainer *container)
+{
+ GtkContainerPrivate *priv;
+
+ g_return_if_fail (GTK_CONTAINER (container));
+
+ priv = container->priv;
+
+ if (priv->restyle_pending)
+ return;
+
+ gtk_container_start_idle_sizer (container);
+
+ container_restyle_queue = g_slist_prepend (container_restyle_queue, container);
+ priv->restyle_pending = TRUE;
}
/**
diff --git a/gtk/gtkcontainerprivate.h b/gtk/gtkcontainerprivate.h
index 81b485d..f12148b 100644
--- a/gtk/gtkcontainerprivate.h
+++ b/gtk/gtkcontainerprivate.h
@@ -27,11 +27,11 @@ G_BEGIN_DECLS
GList * _gtk_container_get_all_children (GtkContainer *container);
void _gtk_container_queue_resize (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);
-void _gtk_container_queue_resize_handler (GtkContainer *container);
void _gtk_container_dequeue_resize_handler (GtkContainer *container);
GList * _gtk_container_focus_sort (GtkContainer *container,
GList *children,
diff --git a/gtk/gtkstylecontext.c b/gtk/gtkstylecontext.c
index cf79e11..f18c8ab 100644
--- a/gtk/gtkstylecontext.c
+++ b/gtk/gtkstylecontext.c
@@ -1029,7 +1029,7 @@ gtk_style_context_set_invalid (GtkStyleContext *context,
if (priv->parent)
gtk_style_context_set_invalid (priv->parent, TRUE);
else if (GTK_IS_RESIZE_CONTAINER (priv->widget))
- _gtk_container_queue_resize_handler (GTK_CONTAINER (priv->widget));
+ _gtk_container_queue_restyle (GTK_CONTAINER (priv->widget));
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]