[gtk/wip/matthiasc/popup] Redo the idle sizer



commit b2ddc7d8673dbe9bb53a0c8b9f152f6015ca2da7
Author: Matthias Clasen <mclasen redhat com>
Date:   Sun Feb 24 22:09:24 2019 -0500

    Redo the idle sizer
    
    Move the idle size code from gtkcontainer.c to
    gtkroot.c, Rename it from 'idle sizer' to 'layout phase',
    and make it work for all roots by adding a check_resize
    vfunc. Implement it for GtkWindow and GtkPopup.
    
    Update all callers.

 gtk/gtkcontainer.c        | 108 ----------------------------------------------
 gtk/gtkcontainerprivate.h |   3 --
 gtk/gtkcsswidgetnode.c    |  17 ++++----
 gtk/gtkpopup.c            |  81 +++++++++++++++++-----------------
 gtk/gtkpopup.h            |   2 -
 gtk/gtkroot.c             | 107 +++++++++++++++++++++++++++++++++++++++++++++
 gtk/gtkroot.h             |   1 +
 gtk/gtkrootprivate.h      |   5 ++-
 gtk/gtkwidget.c           |  13 +++---
 gtk/gtkwindow.c           |   7 +++
 10 files changed, 176 insertions(+), 168 deletions(-)
---
diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c
index e40f68b878..9f0b701e2c 100644
--- a/gtk/gtkcontainer.c
+++ b/gtk/gtkcontainer.c
@@ -118,12 +118,6 @@
  *
  */
 
-
-struct _GtkContainerPrivate
-{
-  guint resize_handler;
-};
-
 enum {
   ADD,
   REMOVE,
@@ -226,9 +220,6 @@ gtk_container_get_type (void)
         g_type_register_static (GTK_TYPE_WIDGET, I_("GtkContainer"),
                                 &container_info, G_TYPE_FLAG_ABSTRACT);
 
-      GtkContainer_private_offset =
-        g_type_add_instance_private (container_type, sizeof (GtkContainerPrivate));
-
       g_type_add_interface_static (container_type,
                                    GTK_TYPE_BUILDABLE,
                                    &buildable_info);
@@ -1339,105 +1330,6 @@ gtk_container_remove (GtkContainer *container,
   g_object_unref (container);
 }
 
-static gboolean
-gtk_container_needs_idle_sizer (GtkContainer *container)
-{
-  if (gtk_css_node_is_invalid (gtk_widget_get_css_node (GTK_WIDGET (container))))
-    return TRUE;
-
-  return gtk_widget_needs_allocate (GTK_WIDGET (container));
-}
-
-static void
-gtk_container_idle_sizer (GdkFrameClock *clock,
-                         GtkContainer  *container)
-{
-  /* 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 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.
-   */
-  if (gtk_css_node_is_invalid (gtk_widget_get_css_node (GTK_WIDGET (container))))
-    gtk_css_node_validate (gtk_widget_get_css_node (GTK_WIDGET (container)));
-
-  /* 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 explicitly work around them with some extra flags,
-   * since it doesn't cause any actual harm.
-   */
-  if (gtk_widget_needs_allocate (GTK_WIDGET (container)))
-    {
-      if (GTK_IS_WINDOW (container))
-        gtk_window_check_resize (GTK_WINDOW (container));
-      else if (GTK_IS_POPUP (container))
-        gtk_popup_check_resize (GTK_POPUP (container));
-      else
-        g_warning ("gtk_container_idle_sizer() called on a non-window");
-    }
-
-  if (!gtk_container_needs_idle_sizer (container))
-    {
-      gtk_container_stop_idle_sizer (container);
-    }
-  else
-    {
-      gdk_frame_clock_request_phase (clock,
-                                     GDK_FRAME_CLOCK_PHASE_LAYOUT);
-    }
-}
-
-void
-gtk_container_start_idle_sizer (GtkContainer *container)
-{
-  GtkContainerPrivate *priv = gtk_container_get_instance_private (container);
-  GdkFrameClock *clock;
-
-  if (priv->resize_handler != 0)
-    return;
-
-  if (!gtk_container_needs_idle_sizer (container))
-    return;
-
-  clock = gtk_widget_get_frame_clock (GTK_WIDGET (container));
-  if (clock == NULL)
-    return;
-
-  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)
-{
-  GtkContainerPrivate *priv = gtk_container_get_instance_private (container);
-
-  if (priv->resize_handler == 0)
-    return;
-
-  g_signal_handler_disconnect (gtk_widget_get_frame_clock (GTK_WIDGET (container)),
-                               priv->resize_handler);
-  priv->resize_handler = 0;
-}
-
-void
-_gtk_container_queue_restyle (GtkContainer *container)
-{
-  g_return_if_fail (GTK_CONTAINER (container));
-
-  if (!gtk_css_node_is_invalid (gtk_widget_get_css_node (GTK_WIDGET (container))))
-    return;
-
-  gtk_container_start_idle_sizer (container);
-}
-
 static GtkSizeRequestMode 
 gtk_container_get_request_mode (GtkWidget *widget)
 {
diff --git a/gtk/gtkcontainerprivate.h b/gtk/gtkcontainerprivate.h
index 74f24ddc90..c5eb15f01a 100644
--- a/gtk/gtkcontainerprivate.h
+++ b/gtk/gtkcontainerprivate.h
@@ -26,9 +26,6 @@
 G_BEGIN_DECLS
 
 
-void     _gtk_container_queue_restyle          (GtkContainer *container);
-void      gtk_container_stop_idle_sizer         (GtkContainer     *container);
-void      gtk_container_start_idle_sizer        (GtkContainer     *container);
 void      gtk_container_set_focus_child         (GtkContainer     *container,
                                                  GtkWidget        *child);
 
diff --git a/gtk/gtkcsswidgetnode.c b/gtk/gtkcsswidgetnode.c
index 3b1440d169..4329a0c1ac 100644
--- a/gtk/gtkcsswidgetnode.c
+++ b/gtk/gtkcsswidgetnode.c
@@ -19,7 +19,7 @@
 
 #include "gtkcsswidgetnodeprivate.h"
 
-#include "gtkcontainerprivate.h"
+#include "gtkrootprivate.h"
 #include "gtkcssanimatedstyleprivate.h"
 #include "gtkprivate.h"
 #include "gtksettingsprivate.h"
@@ -60,7 +60,7 @@ gtk_css_widget_node_queue_callback (GtkWidget     *widget,
   GtkCssNode *node = user_data;
 
   gtk_css_node_invalidate_frame_clock (node, TRUE);
-  _gtk_container_queue_restyle (GTK_CONTAINER (widget));
+  gtk_root_queue_restyle (GTK_ROOT (widget));
 
   return G_SOURCE_CONTINUE;
 }
@@ -70,8 +70,7 @@ gtk_css_widget_node_queue_validate (GtkCssNode *node)
 {
   GtkCssWidgetNode *widget_node = GTK_CSS_WIDGET_NODE (node);
 
-  if (widget_node->widget && _gtk_widget_is_toplevel (widget_node->widget) &&
-      GTK_IS_CONTAINER (widget_node->widget))
+  if (widget_node->widget && GTK_IS_ROOT (widget_node->widget))
     widget_node->validate_cb_id = gtk_widget_add_tick_callback (widget_node->widget,
                                                                 gtk_css_widget_node_queue_callback,
                                                                 node,
@@ -83,10 +82,12 @@ gtk_css_widget_node_dequeue_validate (GtkCssNode *node)
 {
   GtkCssWidgetNode *widget_node = GTK_CSS_WIDGET_NODE (node);
 
-  if (widget_node->widget && _gtk_widget_is_toplevel (widget_node->widget) &&
-      GTK_IS_CONTAINER (widget_node->widget))
-    gtk_widget_remove_tick_callback (widget_node->widget,
-                                     widget_node->validate_cb_id);
+  if (widget_node->validate_cb_id)
+    {
+      gtk_widget_remove_tick_callback (widget_node->widget,
+                                       widget_node->validate_cb_id);
+      widget_node->validate_cb_id = 0;
+    }
 }
 
 static void
diff --git a/gtk/gtkpopup.c b/gtk/gtkpopup.c
index ed81a2fdde..e3b7485af7 100644
--- a/gtk/gtkpopup.c
+++ b/gtk/gtkpopup.c
@@ -76,12 +76,53 @@ gtk_popup_root_get_surface_transform (GtkRoot *root,
   *y = margin.top + border.top + padding.top;
 }
 
+static void
+gtk_popup_move_resize (GtkPopup *popup)
+{
+  GtkPopupPrivate *priv = gtk_popup_get_instance_private (popup);
+  GdkRectangle rect;
+ 
+  rect.x = 0;
+  rect.y = 0;
+  rect.width = gtk_widget_get_width (priv->relative_to);
+  rect.height = gtk_widget_get_height (priv->relative_to);
+  gtk_widget_translate_coordinates (priv->relative_to, gtk_widget_get_toplevel (priv->relative_to),
+                                    rect.x, rect.y, &rect.x, &rect.y);
+
+  gdk_surface_move_to_rect (priv->surface,
+                            &rect,
+                            GDK_GRAVITY_SOUTH,
+                            GDK_GRAVITY_NORTH,
+                            GDK_ANCHOR_FLIP_Y,
+                            0, 10);
+}
+
+static void
+gtk_popup_root_check_resize (GtkRoot *root)
+{
+  GtkPopup *popup = GTK_POPUP (root);
+  GtkPopupPrivate *priv = gtk_popup_get_instance_private (popup);
+  GtkWidget *widget = GTK_WIDGET (popup);
+
+  if (!_gtk_widget_get_alloc_needed (widget))
+    gtk_widget_ensure_allocate (widget);
+  else if (gtk_widget_get_visible (widget))
+    {
+      gtk_popup_move_resize (popup);
+      gtk_widget_allocate (GTK_WIDGET (popup),
+                           gdk_surface_get_width (priv->surface),
+                           gdk_surface_get_height (priv->surface),
+                           -1, NULL);
+    }
+}
+
 static void
 gtk_popup_root_interface_init (GtkRootInterface *iface)
 {
   iface->get_display = gtk_popup_root_get_display;
   iface->get_renderer = gtk_popup_root_get_renderer;
   iface->get_surface_transform = gtk_popup_root_get_surface_transform;
+  iface->check_resize = gtk_popup_root_check_resize;
 }
 
 static void
@@ -219,27 +260,6 @@ gtk_popup_measure (GtkWidget      *widget,
                       minimum_baseline, natural_baseline);
 }
 
-static void
-gtk_popup_move_resize (GtkPopup *popup)
-{
-  GtkPopupPrivate *priv = gtk_popup_get_instance_private (popup);
-  GdkRectangle rect;
- 
-  rect.x = 0;
-  rect.y = 0;
-  rect.width = gtk_widget_get_width (priv->relative_to);
-  rect.height = gtk_widget_get_height (priv->relative_to);
-  gtk_widget_translate_coordinates (priv->relative_to, gtk_widget_get_toplevel (priv->relative_to),
-                                    rect.x, rect.y, &rect.x, &rect.y);
-
-  gdk_surface_move_to_rect (priv->surface,
-                            &rect,
-                            GDK_GRAVITY_SOUTH,
-                            GDK_GRAVITY_NORTH,
-                            GDK_ANCHOR_FLIP_Y,
-                            0, 10);
-}
-
 static void
 gtk_popup_size_allocate (GtkWidget *widget,
                          int        width,
@@ -306,22 +326,3 @@ gtk_popup_set_relative_to (GtkPopup  *popup,
   g_signal_connect (priv->relative_to, "size-allocate", G_CALLBACK (size_changed), popup);
   priv->display = gtk_widget_get_display (relative_to);
 }
-
-void
-gtk_popup_check_resize (GtkPopup *popup)
-{
-  GtkWidget *widget = GTK_WIDGET (popup);
-  GtkPopupPrivate *priv = gtk_popup_get_instance_private (popup);
-
-  if (!_gtk_widget_get_alloc_needed (widget))
-    gtk_widget_ensure_allocate (widget);
-  else if (gtk_widget_get_visible (widget))
-    {
-      gtk_popup_move_resize (popup);
-      gtk_widget_allocate (GTK_WIDGET (popup),
-                           gdk_surface_get_width (priv->surface),
-                           gdk_surface_get_height (priv->surface),
-                           -1, NULL);
-    }
-}
-
diff --git a/gtk/gtkpopup.h b/gtk/gtkpopup.h
index 7760b24878..a316741933 100644
--- a/gtk/gtkpopup.h
+++ b/gtk/gtkpopup.h
@@ -59,8 +59,6 @@ GDK_AVAILABLE_IN_ALL
 void            gtk_popup_set_relative_to (GtkPopup   *popup,
                                            GtkWidget  *relative_to);
 
-void gtk_popup_check_resize (GtkPopup *popup);
-
 G_END_DECLS
 
 #endif /* __GTK_POPUP_H__ */
diff --git a/gtk/gtkroot.c b/gtk/gtkroot.c
index ad93f8791a..bc8390697d 100644
--- a/gtk/gtkroot.c
+++ b/gtk/gtkroot.c
@@ -20,6 +20,8 @@
 #include "config.h"
 
 #include "gtkrootprivate.h"
+#include "gtkcssnodeprivate.h"
+#include "gtkwidgetprivate.h"
 #include "gdk/gdk-private.h"
 
 /**
@@ -59,12 +61,18 @@ gtk_root_default_get_surface_transform (GtkRoot *self,
   *y = 0;
 }
 
+static void
+gtk_root_default_check_resize (GtkRoot *self)
+{
+}
+
 static void
 gtk_root_default_init (GtkRootInterface *iface)
 {
   iface->get_display = gtk_root_default_get_display;
   iface->get_renderer = gtk_root_default_get_renderer;
   iface->get_surface_transform = gtk_root_default_get_surface_transform;
+  iface->check_resize = gtk_root_default_check_resize;
 }
 
 GdkDisplay *
@@ -124,3 +132,102 @@ gtk_root_get_for_surface (GdkSurface *surface)
 
   return NULL;
 }
+
+static void
+gtk_root_check_resize (GtkRoot *self)
+{
+  GtkRootInterface *iface;
+
+  g_return_if_fail (GTK_IS_ROOT (self));
+
+  iface = GTK_ROOT_GET_IFACE (self);
+  iface->check_resize (self);
+}
+
+static gboolean
+gtk_root_needs_layout_phase (GtkRoot *root)
+{
+  if (gtk_css_node_is_invalid (gtk_widget_get_css_node (GTK_WIDGET (root))))
+    return TRUE;
+
+  return gtk_widget_needs_allocate (GTK_WIDGET (root));
+}
+
+static void
+gtk_root_do_layout_phase (GdkFrameClock *clock,
+                          GtkRoot       *root)
+{
+  /* 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 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.
+   */
+
+  if (gtk_css_node_is_invalid (gtk_widget_get_css_node (GTK_WIDGET (root))))
+    gtk_css_node_validate (gtk_widget_get_css_node (GTK_WIDGET (root)));
+
+  /* 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 explicitly work around them with some extra flags,
+   * since it doesn't cause any actual harm.
+   */
+  if (gtk_widget_needs_allocate (GTK_WIDGET (root)))
+    gtk_root_check_resize (root);
+
+  if (!gtk_root_needs_layout_phase (root))
+    gtk_root_stop_layout_phase (root);
+  else
+    gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_LAYOUT);
+}
+
+void
+gtk_root_start_layout_phase (GtkRoot *root)
+{
+  GdkFrameClock *clock;
+  guint resize_handler;
+
+  resize_handler = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (root), "resize-handler"));
+  if (resize_handler != 0)
+    return;
+
+  if (!gtk_root_needs_layout_phase (root))
+    return;
+
+  clock = gtk_widget_get_frame_clock (GTK_WIDGET (root));
+  if (clock == NULL)
+    return;
+
+  resize_handler = g_signal_connect (clock, "layout", G_CALLBACK (gtk_root_do_layout_phase), root);
+  g_object_set_data (G_OBJECT (root), "resize-handler", GUINT_TO_POINTER (resize_handler));
+  gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_LAYOUT);
+}
+
+void
+gtk_root_stop_layout_phase (GtkRoot *root)
+{
+  guint resize_handler;
+
+  resize_handler = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (root), "resize-handler"));
+  if (resize_handler == 0)
+    return;
+
+  g_signal_handler_disconnect (gtk_widget_get_frame_clock (GTK_WIDGET (root)), resize_handler);
+  g_object_set_data (G_OBJECT (root), "resize-handler", NULL);
+}
+
+void
+gtk_root_queue_restyle (GtkRoot *root)
+{
+  g_return_if_fail (GTK_ROOT (root));
+
+  if (!gtk_css_node_is_invalid (gtk_widget_get_css_node (GTK_WIDGET (root))))
+    return;
+
+  gtk_root_start_layout_phase (root);
+}
diff --git a/gtk/gtkroot.h b/gtk/gtkroot.h
index 45e777ba68..0339b485ef 100644
--- a/gtk/gtkroot.h
+++ b/gtk/gtkroot.h
@@ -51,6 +51,7 @@ struct _GtkRootInterface
   void                  (* get_surface_transform)       (GtkRoot                *root,
                                                          int                    *x,
                                                          int                    *y);
+  void                  (* check_resize)                (GtkRoot                *root);
 };
 
 GDK_AVAILABLE_IN_ALL
diff --git a/gtk/gtkrootprivate.h b/gtk/gtkrootprivate.h
index 07ddc380e5..fd95e1abfd 100644
--- a/gtk/gtkrootprivate.h
+++ b/gtk/gtkrootprivate.h
@@ -5,12 +5,15 @@
 
 G_BEGIN_DECLS
 
-GdkDisplay *            gtk_root_get_display            (GtkRoot                *root);
+GdkDisplay *            gtk_root_get_display            (GtkRoot                *self);
 GskRenderer *           gtk_root_get_renderer           (GtkRoot                *self);
 
 void                    gtk_root_get_surface_transform  (GtkRoot                *self,
                                                          int                    *x,
                                                          int                    *y);
+void                    gtk_root_queue_restyle          (GtkRoot                *self); 
+void                    gtk_root_start_layout_phase     (GtkRoot                *self); 
+void                    gtk_root_stop_layout_phase      (GtkRoot                *self); 
 G_END_DECLS
 
 #endif /* __GTK_ROOT_PRIVATE_H__ */
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index 9257b7df3f..0382ea8d4b 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -56,6 +56,7 @@
 #include "gtkprivate.h"
 #include "gtkrenderbackgroundprivate.h"
 #include "gtkrenderborderprivate.h"
+#include "gtkrootprivate.h"
 #include "gtkscrollable.h"
 #include "gtkselection.h"
 #include "gtksettingsprivate.h"
@@ -3690,8 +3691,8 @@ gtk_widget_connect_frame_clock (GtkWidget *widget)
   GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
   GdkFrameClock *frame_clock;
 
-  if (GTK_IS_CONTAINER (widget) && _gtk_widget_is_toplevel (widget))
-    gtk_container_start_idle_sizer (GTK_CONTAINER (widget));
+  if (GTK_IS_ROOT (widget))
+    gtk_root_start_layout_phase (GTK_ROOT (widget));
 
   frame_clock = gtk_widget_get_frame_clock (widget);
 
@@ -3711,8 +3712,8 @@ gtk_widget_disconnect_frame_clock (GtkWidget *widget)
 {
   GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget);
 
-  if (GTK_IS_CONTAINER (widget) && _gtk_widget_is_toplevel (widget))
-    gtk_container_stop_idle_sizer (GTK_CONTAINER (widget));
+  if (GTK_IS_ROOT (widget))
+    gtk_root_stop_layout_phase (GTK_ROOT (widget));
 
   gtk_css_node_invalidate_frame_clock (priv->cssnode, FALSE);
 
@@ -11810,9 +11811,9 @@ gtk_widget_set_alloc_needed (GtkWidget *widget)
       if (!priv->visible)
         break;
 
-      if (_gtk_widget_is_toplevel (widget))
+      if (GTK_IS_ROOT (widget))
         {
-          gtk_container_start_idle_sizer (GTK_CONTAINER (widget));
+          gtk_root_start_layout_phase (GTK_ROOT (widget));
           break;
         }
 
diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c
index 719967cd64..3196320a63 100644
--- a/gtk/gtkwindow.c
+++ b/gtk/gtkwindow.c
@@ -2533,12 +2533,19 @@ gtk_window_root_get_surface_transform (GtkRoot *root,
   *y = margin.top + border.top + padding.top;
 }
 
+static void
+gtk_window_root_check_resize (GtkRoot *root)
+{
+  gtk_window_check_resize (GTK_WINDOW (root));
+}
+
 static void
 gtk_window_root_interface_init (GtkRootInterface *iface)
 {
   iface->get_display = gtk_window_root_get_display;
   iface->get_renderer = gtk_window_root_get_renderer;
   iface->get_surface_transform = gtk_window_root_get_surface_transform;
+  iface->check_resize = gtk_window_root_check_resize;
 }
 
 /**


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]