[gtk+] Use GdkFrameClock for relayout
- From: Owen Taylor <otaylor src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+] Use GdkFrameClock for relayout
- Date: Thu, 14 Feb 2013 22:23:11 +0000 (UTC)
commit 7753883add412a4bbc6b49b9bc7ef037c5a34c36
Author: Owen W. Taylor <otaylor fishsoup net>
Date: Tue Sep 18 09:00:57 2012 -0400
Use GdkFrameClock for relayout
Add a ::layout signal to GdkFrameClock and use it instead of an idle
handler to drive the restyling and relayout of containers.
https://bugzilla.gnome.org/show_bug.cgi?id=685460
gdk/gdkframeclock.c | 21 +++++++++++
gdk/gdkframeclock.h | 1 +
gtk/gtkcontainer.c | 83 ++++++++++++++++++++++++--------------------
gtk/gtkcontainerprivate.h | 1 +
gtk/gtkwidget.c | 3 ++
5 files changed, 71 insertions(+), 38 deletions(-)
---
diff --git a/gdk/gdkframeclock.c b/gdk/gdkframeclock.c
index 6b23ce6..ca54840 100644
--- a/gdk/gdkframeclock.c
+++ b/gdk/gdkframeclock.c
@@ -79,6 +79,7 @@ G_DEFINE_INTERFACE (GdkFrameClock, gdk_frame_clock, G_TYPE_OBJECT)
enum {
FRAME_REQUESTED,
BEFORE_PAINT,
+ LAYOUT,
PAINT,
AFTER_PAINT,
LAST_SIGNAL
@@ -123,6 +124,23 @@ gdk_frame_clock_default_init (GdkFrameClockInterface *iface)
G_TYPE_NONE, 0);
/**
+ * GdkFrameClock::layout:
+ * @clock: the frame clock emitting the signal
+ *
+ * This signal is emitted immediately before the paint signal and
+ * indicates that the frame time has been updated, and signal
+ * handlers should perform any preparatory work before painting.
+ */
+ signals[LAYOUT] =
+ g_signal_new (g_intern_static_string ("layout"),
+ GDK_TYPE_FRAME_CLOCK,
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ /**
* GdkFrameClock::paint:
* @clock: the frame clock emitting the signal
*
@@ -280,6 +298,9 @@ gdk_frame_clock_paint (GdkFrameClock *clock)
signals[BEFORE_PAINT], 0);
g_signal_emit (G_OBJECT (clock),
+ signals[LAYOUT], 0);
+
+ g_signal_emit (G_OBJECT (clock),
signals[PAINT], 0);
g_signal_emit (G_OBJECT (clock),
diff --git a/gdk/gdkframeclock.h b/gdk/gdkframeclock.h
index 62124e2..043a890 100644
--- a/gdk/gdkframeclock.h
+++ b/gdk/gdkframeclock.h
@@ -54,6 +54,7 @@ struct _GdkFrameClockInterface
/* signals */
/* void (* frame_requested) (GdkFrameClock *clock); */
/* void (* before_paint) (GdkFrameClock *clock); */
+ /* void (* layout) 1(GdkFrameClock *clock); */
/* void (* paint) (GdkFrameClock *clock); */
/* void (* after_paint) (GdkFrameClock *clock); */
};
diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c
index 4377a5f..938887e 100644
--- a/gtk/gtkcontainer.c
+++ b/gtk/gtkcontainer.c
@@ -236,6 +236,9 @@ struct _GtkContainerPrivate
{
GtkWidget *focus_child;
+ guint resize_handler;
+ GdkFrameClock *resize_clock;
+
guint border_width : 16;
guint has_focus_chain : 1;
@@ -344,8 +347,6 @@ static const gchar vadjustment_key[] = "gtk-vadjustment";
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;
@@ -1357,10 +1358,15 @@ gtk_container_destroy (GtkWidget *widget)
if (priv->resize_pending)
_gtk_container_dequeue_resize_handler (container);
+
if (priv->restyle_pending)
+ priv->restyle_pending = FALSE;
+
+ if (priv->resize_handler)
{
- container_restyle_queue = g_slist_remove (container_restyle_queue, container);
- priv->restyle_pending = FALSE;
+ g_signal_handler_disconnect (priv->resize_clock, priv->resize_handler);
+ priv->resize_handler = 0;
+ priv->resize_clock = NULL;
}
if (priv->focus_child)
@@ -1553,7 +1559,6 @@ _gtk_container_dequeue_resize_handler (GtkContainer *container)
g_return_if_fail (GTK_IS_CONTAINER (container));
g_return_if_fail (container->priv->resize_pending);
- container_resize_queue = g_slist_remove (container_resize_queue, container);
container->priv->resize_pending = FALSE;
}
@@ -1630,12 +1635,10 @@ gtk_container_set_reallocate_redraws (GtkContainer *container,
container->priv->reallocate_redraws = needs_redraws ? TRUE : FALSE;
}
-static gboolean
-gtk_container_idle_sizer (gpointer data)
+static void
+gtk_container_idle_sizer (GdkFrameClock *clock,
+ GtkContainer *container)
{
- GSList *slist;
- gint64 current_time;
-
/* 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,
@@ -1646,16 +1649,13 @@ gtk_container_idle_sizer (gpointer data)
* 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 ();
- slist = container_restyle_queue;
- container_restyle_queue = NULL;
- while (slist)
+ if (container->priv->restyle_pending)
{
- GSList *next = slist->next;
- GtkContainer *container = slist->data;
GtkBitmask *empty;
+ gint64 current_time;
empty = _gtk_bitmask_new ();
+ current_time = g_get_monotonic_time ();
container->priv->restyle_pending = FALSE;
_gtk_style_context_validate (gtk_widget_get_style_context (GTK_WIDGET (container)),
@@ -1663,8 +1663,6 @@ gtk_container_idle_sizer (gpointer data)
0,
empty);
- g_slist_free_1 (slist);
- slist = next;
_gtk_bitmask_free (empty);
}
@@ -1674,35 +1672,40 @@ gtk_container_idle_sizer (gpointer data)
* than trying to explicitely work around them with some extra flags,
* since it doesn't cause any actual harm.
*/
- while (container_resize_queue)
+ if (container->priv->resize_pending)
{
- GtkContainer *container;
-
- slist = container_resize_queue;
- container_resize_queue = slist->next;
- container = slist->data;
- g_slist_free_1 (slist);
-
container->priv->resize_pending = FALSE;
gtk_container_check_resize (container);
}
- gdk_window_process_all_updates ();
-
- return container_resize_queue != NULL || container_restyle_queue != NULL;
+ if (!container->priv->restyle_pending && !container->priv->resize_pending)
+ {
+ g_signal_handler_disconnect (clock, container->priv->resize_handler);
+ container->priv->resize_handler = 0;
+ container->priv->resize_clock = NULL;
+ }
+ else
+ {
+ gdk_frame_clock_request_frame (clock);
+ }
}
static void
gtk_container_start_idle_sizer (GtkContainer *container)
{
- /* already started */
- if (container_resize_queue != NULL ||
- container_restyle_queue != NULL)
+ GdkFrameClock *clock;
+
+ if (container->priv->resize_handler != 0)
+ return;
+
+ clock = gtk_widget_get_frame_clock (GTK_WIDGET (container));
+ if (clock == NULL)
return;
- gdk_threads_add_idle_full (GTK_PRIORITY_RESIZE,
- gtk_container_idle_sizer,
- NULL, NULL);
+ container->priv->resize_clock = clock;
+ container->priv->resize_handler = g_signal_connect (clock, "layout",
+ G_CALLBACK (gtk_container_idle_sizer), container);
+ gdk_frame_clock_request_frame (clock);
}
static void
@@ -1725,7 +1728,6 @@ gtk_container_queue_resize_handler (GtkContainer *container)
{
container->priv->resize_pending = TRUE;
gtk_container_start_idle_sizer (container);
- container_resize_queue = g_slist_prepend (container_resize_queue, container);
}
break;
@@ -1780,8 +1782,6 @@ _gtk_container_queue_restyle (GtkContainer *container)
return;
gtk_container_start_idle_sizer (container);
-
- container_restyle_queue = g_slist_prepend (container_restyle_queue, container);
priv->restyle_pending = TRUE;
}
@@ -1816,6 +1816,13 @@ _gtk_container_resize_invalidate (GtkContainer *container)
}
void
+_gtk_container_maybe_start_idle_sizer (GtkContainer *container)
+{
+ if (container->priv->restyle_pending || container->priv->resize_pending)
+ gtk_container_start_idle_sizer (container);
+}
+
+void
gtk_container_check_resize (GtkContainer *container)
{
g_return_if_fail (GTK_IS_CONTAINER (container));
diff --git a/gtk/gtkcontainerprivate.h b/gtk/gtkcontainerprivate.h
index f12148b..cd4bc5b 100644
--- a/gtk/gtkcontainerprivate.h
+++ b/gtk/gtkcontainerprivate.h
@@ -39,6 +39,7 @@ GList * _gtk_container_focus_sort (GtkContainer *container,
GtkWidget *old_focus);
gboolean _gtk_container_get_reallocate_redraws (GtkContainer *container);
+void _gtk_container_maybe_start_idle_sizer (GtkContainer *container);
G_END_DECLS
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index a3509c4..e1cf124 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -4585,6 +4585,9 @@ gtk_widget_realize (GtkWidget *widget)
_gtk_widget_enable_device_events (widget);
gtk_widget_update_devices_mask (widget, TRUE);
+ if (GTK_IS_CONTAINER (widget))
+ _gtk_container_maybe_start_idle_sizer (GTK_CONTAINER (widget));
+
gtk_widget_pop_verify_invariants (widget);
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]