summaryrefslogtreecommitdiff
path: root/gtk/gtkroot.c
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2020-04-25 21:03:57 -0400
committerMatthias Clasen <mclasen@redhat.com>2020-04-25 21:03:57 -0400
commit637890517b40e060322222101cf4eb1f53fe318c (patch)
tree79bde2c33a612bbeb4f2f2ad874b139b34a58b43 /gtk/gtkroot.c
parentae7fd6f12984e579464d276abe085e5ba3ce6f98 (diff)
downloadgtk+-637890517b40e060322222101cf4eb1f53fe318c.tar.gz
Move the idle sizer to the gtkroot.c
This is needed since we already have a second GtkRoot implementation with GtkDragIcon, and DND is causing critical warnings due to this.
Diffstat (limited to 'gtk/gtkroot.c')
-rw-r--r--gtk/gtkroot.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/gtk/gtkroot.c b/gtk/gtkroot.c
index 0252b85856..24d3860b1d 100644
--- a/gtk/gtkroot.c
+++ b/gtk/gtkroot.c
@@ -43,6 +43,9 @@
* The obvious example of a #GtkRoot is #GtkWindow.
*/
+static GQuark quark_restyle_pending;
+static GQuark quark_resize_handler;
+
G_DEFINE_INTERFACE_WITH_CODE (GtkRoot, gtk_root, GTK_TYPE_WIDGET,
g_type_interface_add_prerequisite (g_define_type_id, GTK_TYPE_NATIVE))
@@ -78,6 +81,9 @@ gtk_root_default_init (GtkRootInterface *iface)
iface->get_constraint_solver = gtk_root_default_get_constraint_solver;
iface->get_focus = gtk_root_default_get_focus;
iface->set_focus = gtk_root_default_set_focus;
+
+ quark_restyle_pending = g_quark_from_static_string ("gtk-root-restyle-pending");
+ quark_resize_handler = g_quark_from_static_string ("gtk-root-resize-handler");
}
/**
@@ -154,3 +160,100 @@ gtk_root_get_focus (GtkRoot *self)
return GTK_ROOT_GET_IFACE (self)->get_focus (self);
}
+
+static gboolean
+gtk_root_needs_layout (GtkRoot *self)
+{
+ if (g_object_get_qdata (G_OBJECT (self), quark_restyle_pending))
+ return TRUE;
+
+ return gtk_widget_needs_allocate (GTK_WIDGET (self));
+}
+
+static void
+gtk_root_layout_cb (GdkFrameClock *clock,
+ GtkRoot *self)
+{
+ GtkWidget *widget = GTK_WIDGET (self);
+
+ /* 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 css_changed 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 (g_object_get_qdata (G_OBJECT (self), quark_restyle_pending))
+ {
+ g_object_set_qdata (G_OBJECT (self), quark_restyle_pending, NULL);
+ gtk_css_node_validate (gtk_widget_get_css_node (widget));
+ }
+
+ /* 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 (widget))
+ gtk_native_check_resize (GTK_NATIVE (self));
+
+ if (!gtk_root_needs_layout (self))
+ gtk_root_stop_layout (self);
+ else
+ gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_LAYOUT);
+}
+
+void
+gtk_root_start_layout (GtkRoot *self)
+{
+ GdkFrameClock *clock;
+ guint resize_handler;
+
+ if (g_object_get_qdata (G_OBJECT (self), quark_resize_handler))
+ return;
+
+ if (!gtk_root_needs_layout (self))
+ return;
+
+ clock = gtk_widget_get_frame_clock (GTK_WIDGET (self));
+ if (clock == NULL)
+ return;
+
+ resize_handler = g_signal_connect (clock, "layout",
+ G_CALLBACK (gtk_root_layout_cb), self);
+ g_object_set_qdata (G_OBJECT (self), quark_resize_handler, GINT_TO_POINTER (resize_handler));
+
+ gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_LAYOUT);
+}
+
+void
+gtk_root_stop_layout (GtkRoot *self)
+{
+ GdkFrameClock *clock;
+ guint resize_handler;
+
+ resize_handler = GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (self), quark_resize_handler));
+
+ if (resize_handler == 0)
+ return;
+
+ clock = gtk_widget_get_frame_clock (GTK_WIDGET (self));
+ g_signal_handler_disconnect (clock, resize_handler);
+ g_object_set_qdata (G_OBJECT (self), quark_resize_handler, NULL);
+}
+
+void
+gtk_root_queue_restyle (GtkRoot *self)
+{
+ if (g_object_get_qdata (G_OBJECT (self), quark_restyle_pending))
+ return;
+
+ g_object_set_qdata (G_OBJECT (self), quark_restyle_pending, GINT_TO_POINTER (1));
+
+ gtk_root_start_layout (self);
+}
+