diff options
author | Matthias Clasen <mclasen@redhat.com> | 2020-04-25 21:03:57 -0400 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2020-04-25 21:03:57 -0400 |
commit | 637890517b40e060322222101cf4eb1f53fe318c (patch) | |
tree | 79bde2c33a612bbeb4f2f2ad874b139b34a58b43 /gtk/gtkroot.c | |
parent | ae7fd6f12984e579464d276abe085e5ba3ce6f98 (diff) | |
download | gtk+-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.c | 103 |
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); +} + |