[gtk/wip/matthiasc/popup2: 318/353] Redo the idle sizer



commit 55ddbec2469412a49086e6c93fb179f0e8fa93a8
Author: Matthias Clasen <mclasen redhat com>
Date:   Sun Mar 17 00:36:08 2019 -0400

    Redo the idle sizer
    
    Move the idle sizer from GtkContainer to GtkRoot
    and call it layout phase.

 gtk/gtkcontainer.c        | 120 ----------------------------------------------
 gtk/gtkcontainerprivate.h |   3 --
 gtk/gtkroot.c             | 119 +++++++++++++++++++++++++++++++++++++++++++++
 gtk/gtkroot.h             |   1 +
 gtk/gtkrootprivate.h      |   7 ++-
 5 files changed, 126 insertions(+), 124 deletions(-)
---
diff --git a/gtk/gtkcontainer.c b/gtk/gtkcontainer.c
index bbc6968bdf..da469960d7 100644
--- a/gtk/gtkcontainer.c
+++ b/gtk/gtkcontainer.c
@@ -85,14 +85,6 @@
  * See more about implementing custom widgets at https://wiki.gnome.org/HowDoI/CustomWidgets
  */
 
-
-struct _GtkContainerPrivate
-{
-  guint resize_handler;
-
-  guint restyle_pending    : 1;
-};
-
 enum {
   ADD,
   REMOVE,
@@ -126,7 +118,6 @@ static GQuark                hadjustment_key_id;
 static guint                 container_signals[LAST_SIGNAL] = { 0 };
 
 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GtkContainer, gtk_container, GTK_TYPE_WIDGET,
-                                  G_ADD_PRIVATE (GtkContainer)
                                   G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
                                                          gtk_container_buildable_init))
 
@@ -245,10 +236,6 @@ static void
 gtk_container_destroy (GtkWidget *widget)
 {
   GtkContainer *container = GTK_CONTAINER (widget);
-  GtkContainerPrivate *priv = gtk_container_get_instance_private (container);
-
-  if (priv->restyle_pending)
-    priv->restyle_pending = FALSE;
 
   gtk_container_foreach (container, (GtkCallback) gtk_widget_destroy, NULL);
 
@@ -333,113 +320,6 @@ gtk_container_remove (GtkContainer *container,
   g_object_unref (container);
 }
 
-static gboolean
-gtk_container_needs_idle_sizer (GtkContainer *container)
-{
-  GtkContainerPrivate *priv = gtk_container_get_instance_private (container);
-
-  if (priv->restyle_pending)
-    return TRUE;
-
-  return gtk_widget_needs_allocate (GTK_WIDGET (container));
-}
-
-static void
-gtk_container_idle_sizer (GdkFrameClock *clock,
-                         GtkContainer  *container)
-{
-  GtkContainerPrivate *priv = gtk_container_get_instance_private (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 (priv->restyle_pending)
-    {
-      priv->restyle_pending = FALSE;
-      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
-        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)
-{
-  GtkContainerPrivate *priv = gtk_container_get_instance_private (container);
-
-  g_return_if_fail (GTK_CONTAINER (container));
-
-  if (priv->restyle_pending)
-    return;
-
-  priv->restyle_pending = TRUE;
-  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/gtkroot.c b/gtk/gtkroot.c
index 249d7405b1..34528f8cca 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"
 #include "gtkprivate.h"
 #include "gtkintl.h"
@@ -61,12 +63,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;
 
   g_object_interface_install_property (iface,
       g_param_spec_object ("focus-widget",
@@ -193,3 +201,114 @@ gtk_root_install_properties (GObjectClass *object_class,
   g_object_class_override_property (object_class, first_prop + GTK_ROOT_PROP_FOCUS_WIDGET, "focus-widget");
   return GTK_ROOT_NUM_PROPERTIES;
 }
+
+static void
+gtk_root_check_resize (GtkRoot *self)
+{
+  g_return_if_fail (GTK_IS_ROOT (self));
+
+  GTK_ROOT_GET_IFACE (self)->check_resize (self);
+}
+
+static gboolean
+gtk_root_get_restyle_pending (GtkRoot *root)
+{
+  return GPOINTER_TO_INT (g_object_get_data (G_OBJECT (root), "restyle-pending"));
+}
+
+static void
+gtk_root_set_restyle_pending (GtkRoot  *root,
+                              gboolean  pending)
+{
+  g_object_set_data (G_OBJECT (root), "restyle-pending", GINT_TO_POINTER (pending));
+}
+
+static gboolean
+gtk_root_needs_layout_phase (GtkRoot *root)
+{
+  return gtk_root_get_restyle_pending (root) ||
+         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_root_get_restyle_pending (root))
+    {
+      gtk_root_set_restyle_pending (root, FALSE);
+      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_root_get_restyle_pending (root))
+    return;
+
+  gtk_root_set_restyle_pending (root, TRUE);
+  gtk_root_start_layout_phase (root);
+}
diff --git a/gtk/gtkroot.h b/gtk/gtkroot.h
index 4c7ae89e37..32a528e582 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 357bc6441f..c7c942c203 100644
--- a/gtk/gtkrootprivate.h
+++ b/gtk/gtkrootprivate.h
@@ -5,12 +5,17 @@
 
 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); 
+
 enum {
   GTK_ROOT_PROP_FOCUS_WIDGET,
   GTK_ROOT_NUM_PROPERTIES


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