From: Alice Mikhaylenko Date: Thu, 1 Jun 2023 02:27:10 +0000 (+0400) Subject: actionmuxer: Correctly notify actions after reparenting X-Git-Tag: archive/raspbian/4.12.3+ds-1+rpi1~1^2^2^2~22^2~3^2~1^2~11 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=dfc66ffd936f50a50d0a9c280ea9fa02e7dac8f3;p=gtk4.git actionmuxer: Correctly notify actions after reparenting When registering an observer, we send a notification and for that we need to query the action's state and param type. When setting up a muxer parent, same thing happens, except the action is queried on the parent instead. This means that the muxer will notify observers about the parent's actions, but not about its own. Add a test to verify it works. Fixes https://gitlab.gnome.org/GNOME/gtk/-/issues/5861 --- diff --git a/gtk/gtkactionmuxer.c b/gtk/gtkactionmuxer.c index 47aaf0c92c..d4cce2f918 100644 --- a/gtk/gtkactionmuxer.c +++ b/gtk/gtkactionmuxer.c @@ -455,7 +455,7 @@ notify_observers_added (GtkActionMuxer *muxer, gtk_action_observable_register_observer (GTK_ACTION_OBSERVABLE (parent), action_name, GTK_ACTION_OBSERVER (muxer)); - if (!action_muxer_query_action (parent, action_name, + if (!action_muxer_query_action (muxer, action_name, &enabled, ¶meter_type, NULL, NULL, &state, TRUE)) diff --git a/testsuite/gtk/action.c b/testsuite/gtk/action.c index 95bb071d4b..d99b16c33b 100644 --- a/testsuite/gtk/action.c +++ b/testsuite/gtk/action.c @@ -717,6 +717,60 @@ test_enabled (void) g_object_unref (g_object_ref_sink (text)); } +#define MY_TYPE_GTK_ACTIONABLE (my_gtk_actionable_get_type ()) +G_DECLARE_FINAL_TYPE (MyGtkActionable, my_gtk_actionable, MY, GTK_ACTIONABLE, GtkButton) + +struct _MyGtkActionable +{ + GtkButton parent_instance; +}; + +G_DEFINE_FINAL_TYPE (MyGtkActionable, my_gtk_actionable, GTK_TYPE_BUTTON); + +static void +test_cb (GtkWidget *sender, + const char *name, + GVariant *param) +{ +} + +static void +my_gtk_actionable_init (MyGtkActionable *actionable) +{ + gtk_actionable_set_action_name (GTK_ACTIONABLE (actionable), "test.test"); +} + +static void +my_gtk_actionable_class_init (MyGtkActionableClass *klass) +{ + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + + gtk_widget_class_install_action (widget_class, "test.test", NULL, test_cb); +} + +/* Test that actions are correctly notified after reparenting */ +static void +test_reparenting (void) +{ + GtkWidget *window, *actionable; + + window = gtk_window_new (); + + actionable = g_object_new (MY_TYPE_GTK_ACTIONABLE, NULL); + gtk_window_set_child (GTK_WINDOW (window), actionable); + g_assert_true (gtk_widget_get_sensitive (actionable)); + + g_object_ref (actionable); + gtk_window_set_child (GTK_WINDOW (window), NULL); + g_assert_false (gtk_widget_get_sensitive (actionable)); + + gtk_window_set_child (GTK_WINDOW (window), actionable); + g_object_unref (actionable); + g_assert_true (gtk_widget_get_sensitive (actionable)); + + g_object_unref (window); +} + int main (int argc, char *argv[]) @@ -732,6 +786,7 @@ main (int argc, g_test_add_func ("/action/overlap2", test_overlap2); g_test_add_func ("/action/introspection", test_introspection); g_test_add_func ("/action/enabled", test_enabled); + g_test_add_func ("/action/reparenting", test_reparenting); return g_test_run(); }