From b968ced5676aa793613cd3ac02444d75826708a9 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 28 Apr 2020 18:34:23 -0400 Subject: [PATCH 1/2] Reshuffle action muxer initialization We were having a problem where property actions were not getting state updates because prop_actions_connect was triggered from some instance_init function while the widget class is not in place yet. Delay that call until the widget is fully constructed, so we can guarantee that we are dealing with the correct class private struct, and see all class actions. --- gtk/gtkactionmuxer.c | 9 ++------- gtk/gtkactionmuxerprivate.h | 1 + gtk/gtkwidget.c | 15 +++++++++++++++ 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/gtk/gtkactionmuxer.c b/gtk/gtkactionmuxer.c index 26ca311efc..256406fa81 100644 --- a/gtk/gtkactionmuxer.c +++ b/gtk/gtkactionmuxer.c @@ -864,14 +864,10 @@ gtk_action_muxer_dispose (GObject *object) ->dispose (object); } -static void -gtk_action_muxer_constructed (GObject *object) +void +gtk_action_muxer_connect_class_actions (GtkActionMuxer *muxer) { - GtkActionMuxer *muxer = GTK_ACTION_MUXER (object); - prop_actions_connect (muxer); - - G_OBJECT_CLASS (gtk_action_muxer_parent_class)->constructed (object); } static void @@ -949,7 +945,6 @@ gtk_action_muxer_class_init (GObjectClass *class) { class->get_property = gtk_action_muxer_get_property; class->set_property = gtk_action_muxer_set_property; - class->constructed = gtk_action_muxer_constructed; class->finalize = gtk_action_muxer_finalize; class->dispose = gtk_action_muxer_dispose; diff --git a/gtk/gtkactionmuxerprivate.h b/gtk/gtkactionmuxerprivate.h index 0c5670c6f8..516e2420d7 100644 --- a/gtk/gtkactionmuxerprivate.h +++ b/gtk/gtkactionmuxerprivate.h @@ -81,6 +81,7 @@ gtk_action_muxer_action_state_changed (GtkActionMuxer *muxer, const gchar *action_name, GVariant *state); +void gtk_action_muxer_connect_class_actions (GtkActionMuxer *muxer); /* No better place for these... */ gchar * gtk_print_action_and_target (const gchar *action_namespace, diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index e060581b6d..8ee76a263d 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -865,6 +865,20 @@ gtk_widget_real_unroot (GtkWidget *widget) gtk_widget_forall (widget, (GtkCallback) gtk_widget_unroot, NULL); } +static void +gtk_widget_constructed (GObject *object) +{ + G_OBJECT_CLASS (gtk_widget_parent_class)->constructed (object); + + if (GTK_WIDGET_GET_CLASS (object)->priv->actions) + { + GtkActionMuxer *muxer; + + muxer = _gtk_widget_get_action_muxer (GTK_WIDGET (object), TRUE); + gtk_action_muxer_connect_class_actions (muxer); + } +} + static void gtk_widget_class_init (GtkWidgetClass *klass) { @@ -882,6 +896,7 @@ gtk_widget_class_init (GtkWidgetClass *klass) quark_font_options = g_quark_from_static_string ("gtk-widget-font-options"); quark_font_map = g_quark_from_static_string ("gtk-widget-font-map"); + gobject_class->constructed = gtk_widget_constructed; gobject_class->dispose = gtk_widget_dispose; gobject_class->finalize = gtk_widget_finalize; gobject_class->set_property = gtk_widget_set_property; From c4a47e218f67eccb21a7aafec0189311cbc8a876 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Tue, 28 Apr 2020 20:22:26 -0400 Subject: [PATCH 2/2] Speed up class action hookup No need to construct a detailed signal name for every action when we can just look up the signal ID once and use the quark that the GParamSpec already has. Also, we don't need to loop over the actions every time we get a notification. --- gtk/gtkactionmuxer.c | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/gtk/gtkactionmuxer.c b/gtk/gtkactionmuxer.c index 256406fa81..f84173fe05 100644 --- a/gtk/gtkactionmuxer.c +++ b/gtk/gtkactionmuxer.c @@ -533,24 +533,15 @@ prop_action_notify (GObject *object, GParamSpec *pspec, gpointer user_data) { - GtkActionMuxer *muxer = user_data; - GtkWidgetClass *klass = GTK_WIDGET_GET_CLASS (muxer->widget); - GtkWidgetClassPrivate *priv = klass->priv; - GtkWidgetAction *action = NULL; + GtkWidget *widget = GTK_WIDGET (object); + GtkWidgetAction *action = user_data; + GtkActionMuxer *muxer = _gtk_widget_get_action_muxer (widget, TRUE); GVariant *state; - g_assert ((GObject *)muxer->widget == object); - - for (action = priv->actions; action; action = action->next) - { - if (action->pspec == pspec) - break; - } - - g_assert (action != NULL); + g_assert (muxer->widget == widget); g_assert (action->pspec == pspec); - state = prop_action_get_state (muxer->widget, action); + state = prop_action_get_state (widget, action); gtk_action_muxer_action_state_changed (muxer, action->name, state); g_variant_unref (state); } @@ -561,6 +552,7 @@ prop_actions_connect (GtkActionMuxer *muxer) GtkWidgetClassPrivate *priv; GtkWidgetAction *action; GtkWidgetClass *klass; + guint signal_id; if (!muxer->widget) return; @@ -570,17 +562,20 @@ prop_actions_connect (GtkActionMuxer *muxer) if (!priv->actions) return; + signal_id = g_signal_lookup ("notify", G_TYPE_OBJECT); + for (action = priv->actions; action; action = action->next) { - char *detailed; - if (!action->pspec) continue; - detailed = g_strconcat ("notify::", action->pspec->name, NULL); - g_signal_connect (muxer->widget, detailed, - G_CALLBACK (prop_action_notify), muxer); - g_free (detailed); + g_signal_connect_closure_by_id (muxer->widget, + signal_id, + g_param_spec_get_name_quark (action->pspec), + g_cclosure_new (G_CALLBACK (prop_action_notify), + action, + NULL), + FALSE); } }