]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkcontainer.c
stylecontext: Do invalidation on first resize container
[~andy/gtk] / gtk / gtkcontainer.c
index f985173b59d0b67fe1023363d132002e4d20b58e..ce16fe4df42e224471754b0886415b08b200e474 100644 (file)
@@ -42,6 +42,7 @@
 #include "gtkmain.h"
 #include "gtkmarshalers.h"
 #include "gtksizerequest.h"
+#include "gtksizerequestcacheprivate.h"
 #include "gtkwidgetprivate.h"
 #include "gtkwindow.h"
 #include "gtkassistant.h"
@@ -235,6 +236,9 @@ struct _GtkContainerPrivate
 {
   GtkWidget *focus_child;
 
+  guint resize_handler;
+  GdkFrameClock *resize_clock;
+
   guint border_width : 16;
 
   guint has_focus_chain    : 1;
@@ -343,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;
@@ -1356,11 +1358,9 @@ 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;
-    }
+    priv->restyle_pending = FALSE;
 
   if (priv->focus_child)
     {
@@ -1552,7 +1552,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;
 }
 
@@ -1629,12 +1628,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,
@@ -1645,16 +1642,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)),
@@ -1662,8 +1656,6 @@ gtk_container_idle_sizer (gpointer data)
                                    0,
                                    empty);
 
-      g_slist_free_1 (slist);
-      slist = next;
       _gtk_bitmask_free (empty);
     }
 
@@ -1673,35 +1665,52 @@ 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)
+    {
+      _gtk_container_stop_idle_sizer (container);
+    }
+  else
+    {
+      gdk_frame_clock_request_phase (clock,
+                                     GDK_FRAME_CLOCK_PHASE_LAYOUT);
+    }
 }
 
 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;
+
+  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_phase (clock,
+                                 GDK_FRAME_CLOCK_PHASE_LAYOUT);
+}
+
+void
+_gtk_container_stop_idle_sizer (GtkContainer *container)
+{
+  if (container->priv->resize_handler == 0)
     return;
 
-  gdk_threads_add_idle_full (GTK_PRIORITY_RESIZE,
-                             gtk_container_idle_sizer,
-                             NULL, NULL);
+  g_signal_handler_disconnect (container->priv->resize_clock,
+                               container->priv->resize_handler);
+  container->priv->resize_handler = 0;
+  container->priv->resize_clock = NULL;
 }
 
 static void
@@ -1724,7 +1733,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;
 
@@ -1753,8 +1761,7 @@ _gtk_container_queue_resize_internal (GtkContainer *container,
   do
     {
       _gtk_widget_set_alloc_needed (widget, TRUE);
-      _gtk_widget_set_width_request_needed (widget, TRUE);
-      _gtk_widget_set_height_request_needed (widget, TRUE);
+      _gtk_size_request_cache_clear (_gtk_widget_peek_request_cache (widget));
 
       if (GTK_IS_RESIZE_CONTAINER (widget))
         break;
@@ -1780,8 +1787,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;
 }
 
@@ -1815,6 +1820,13 @@ _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)
+    gtk_container_start_idle_sizer (container);
+}
+
 void
 gtk_container_check_resize (GtkContainer *container)
 {
@@ -1918,32 +1930,11 @@ gtk_container_adjust_size_allocation (GtkWidget         *widget,
 
   container = GTK_CONTAINER (widget);
 
-  if (!GTK_CONTAINER_GET_CLASS (widget)->_handle_border_width)
+  if (GTK_CONTAINER_GET_CLASS (widget)->_handle_border_width)
     {
-      parent_class->adjust_size_allocation (widget, orientation,
-                                            minimum_size, natural_size, allocated_pos,
-                                            allocated_size);
-      return;
-    }
-
-  border_width = container->priv->border_width;
-
-  *allocated_size -= border_width * 2;
-
-  /* If we get a pathological too-small allocation to hold
-   * even the border width, leave all allocation to the actual
-   * widget, and leave x,y unchanged. (GtkWidget's min size is
-   * 1x1 if you're wondering why <1 and not <0)
-   *
-   * As long as we have space, set x,y properly.
-   */
+      border_width = container->priv->border_width;
 
-  if (*allocated_size < 1)
-    {
-      *allocated_size += border_width * 2;
-    }
-  else
-    {
+      *allocated_size -= border_width * 2;
       *allocated_pos += border_width;
       *minimum_size -= border_width * 2;
       *natural_size -= border_width * 2;
@@ -1989,27 +1980,17 @@ count_request_modes (GtkWidget        *widget,
 static GtkSizeRequestMode 
 gtk_container_get_request_mode (GtkWidget *widget)
 {
-  GtkContainer        *container = GTK_CONTAINER (widget);
-  GtkContainerPrivate *priv      = container->priv;
-
-  /* Recalculate the request mode of the children by majority
-   * vote whenever the internal content changes */
-  if (_gtk_widget_get_width_request_needed (widget) ||
-      _gtk_widget_get_height_request_needed (widget))
-    {
-      RequestModeCount count = { 0, 0 };
-
-      gtk_container_forall (container, (GtkCallback)count_request_modes, &count);
+  GtkContainer *container = GTK_CONTAINER (widget);
+  RequestModeCount count = { 0, 0 };
 
-      if (!count.hfw && !count.wfh)
-       priv->request_mode = GTK_SIZE_REQUEST_CONSTANT_SIZE;
-      else
-       priv->request_mode = count.wfh > count.hfw ? 
-         GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT :
-         GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
-    }
+  gtk_container_forall (container, (GtkCallback)count_request_modes, &count);
 
-  return priv->request_mode;
+  if (!count.hfw && !count.wfh)
+    return GTK_SIZE_REQUEST_CONSTANT_SIZE;
+  else
+    return count.wfh > count.hfw ? 
+        GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT :
+       GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH;
 }
 
 /**