From 05968c35e519d2774cb1f73c70b6f0fd106b40ac Mon Sep 17 00:00:00 2001 From: Jehan Date: Sun, 5 Feb 2023 22:23:20 +0100 Subject: [PATCH] app: GimpAccelLabel now closure-free. - New gimp_action_get_display_accels() added to GimpAction API to get directly the human-visible strings for actions. - Also adding an "accels-changed" signal to GimpAction. As far as I can see, even though accelerators are now to be set on the GtkApplication, there seems to be no signals or properties to connect to at all on this class. So instead, let's do it on our GimpAction (which means we must absolutely not use gtk_application_set_accels_for_action()). - GimpAccelLabel now uses the proper GimpAction API instead of accelerator closure which is a disappearing concept. --- app/widgets/gimpaccellabel.c | 122 ++++++----------------------------- app/widgets/gimpaction.c | 66 +++++++++++++++++++ app/widgets/gimpaction.h | 11 ++-- 3 files changed, 94 insertions(+), 105 deletions(-) diff --git a/app/widgets/gimpaccellabel.c b/app/widgets/gimpaccellabel.c index cd97206608..4ff7cd9196 100644 --- a/app/widgets/gimpaccellabel.c +++ b/app/widgets/gimpaccellabel.c @@ -46,23 +46,17 @@ struct _GimpAccelLabelPrivate /* local function prototypes */ -static void gimp_accel_label_dispose (GObject *object); -static void gimp_accel_label_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec); -static void gimp_accel_label_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec); +static void gimp_accel_label_dispose (GObject *object); +static void gimp_accel_label_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec); +static void gimp_accel_label_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec); -static void gimp_accel_label_accel_changed (GtkAccelGroup *accel_group, - guint keyval, - GdkModifierType modifier, - GClosure *accel_closure, - GimpAccelLabel *accel_label); - -static void gimp_accel_label_update (GimpAccelLabel *accel_label); +static void gimp_accel_label_update (GimpAccelLabel *accel_label); G_DEFINE_TYPE_WITH_PRIVATE (GimpAccelLabel, gimp_accel_label, GTK_TYPE_LABEL) @@ -144,67 +138,22 @@ gimp_accel_label_get_property (GObject *object, } } -static void -gimp_accel_label_accel_changed (GtkAccelGroup *accel_group, - guint keyval, - GdkModifierType modifier, - GClosure *accel_closure, - GimpAccelLabel *accel_label) -{ - if (accel_closure == - gimp_action_get_accel_closure (accel_label->priv->action)) - { - gimp_accel_label_update (accel_label); - } -} - -static gboolean -gimp_accel_label_update_accel_find_func (GtkAccelKey *key, - GClosure *closure, - gpointer data) -{ - return (GClosure *) data == closure; -} - static void gimp_accel_label_update (GimpAccelLabel *accel_label) { - GClosure *accel_closure; - GtkAccelGroup *accel_group; - GtkAccelKey *accel_key; + gchar **accels; gtk_label_set_label (GTK_LABEL (accel_label), NULL); if (! accel_label->priv->action) return; - accel_closure = gimp_action_get_accel_closure (accel_label->priv->action); + accels = gimp_action_get_display_accels (accel_label->priv->action); - if (! accel_closure) - return; + if (accels && accels[0]) + gtk_label_set_label (GTK_LABEL (accel_label), accels[0]); - accel_group = gtk_accel_group_from_accel_closure (accel_closure); - - if (! accel_group) - return; - - accel_key = gtk_accel_group_find (accel_group, - gimp_accel_label_update_accel_find_func, - accel_closure); - - if (accel_key && - accel_key->accel_key && - (accel_key->accel_flags & GTK_ACCEL_VISIBLE)) - { - gchar *label; - - label = gtk_accelerator_get_label (accel_key->accel_key, - accel_key->accel_mods); - - gtk_label_set_label (GTK_LABEL (accel_label), label); - - g_free (label); - } + g_strfreev (accels); } @@ -230,45 +179,16 @@ gimp_accel_label_set_action (GimpAccelLabel *accel_label, if (action != accel_label->priv->action) { if (accel_label->priv->action) - { - GClosure *accel_closure; - - accel_closure = gimp_action_get_accel_closure ( - accel_label->priv->action); - - if (accel_closure) - { - GtkAccelGroup *accel_group; - - accel_group = gtk_accel_group_from_accel_closure (accel_closure); - - g_signal_handlers_disconnect_by_func ( - accel_group, - gimp_accel_label_accel_changed, - accel_label); - } - } + g_signal_handlers_disconnect_by_func (accel_label->priv->action, + gimp_accel_label_update, + accel_label); g_set_object (&accel_label->priv->action, action); if (accel_label->priv->action) - { - GClosure *accel_closure; - - accel_closure = gimp_action_get_accel_closure ( - accel_label->priv->action); - - if (accel_closure) - { - GtkAccelGroup *accel_group; - - accel_group = gtk_accel_group_from_accel_closure (accel_closure); - - g_signal_connect (accel_group, "accel-changed", - G_CALLBACK (gimp_accel_label_accel_changed), - accel_label); - } - } + g_signal_connect_swapped (action, "accels-changed", + G_CALLBACK (gimp_accel_label_update), + accel_label); gimp_accel_label_update (accel_label); diff --git a/app/widgets/gimpaction.c b/app/widgets/gimpaction.c index 2d4f675256..35a78dd78d 100644 --- a/app/widgets/gimpaction.c +++ b/app/widgets/gimpaction.c @@ -45,6 +45,7 @@ enum { ACTIVATE, CHANGE_STATE, + ACCELS_CHANGED, LAST_SIGNAL }; @@ -105,6 +106,15 @@ gimp_action_default_init (GimpActionInterface *iface) G_TYPE_NONE, 1, G_TYPE_VARIANT); + action_signals[ACCELS_CHANGED] = + g_signal_new ("accels-changed", + G_TYPE_FROM_INTERFACE (iface), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (GimpActionInterface, accels_changed), + NULL, NULL, NULL, + G_TYPE_NONE, 1, + G_TYPE_STRV); + g_object_interface_install_property (iface, g_param_spec_object ("context", NULL, NULL, @@ -407,6 +417,19 @@ gimp_action_connect_accelerator (GimpAction *action) gtk_action_connect_accelerator ((GtkAction *) action); } +/** + * gimp_action_set_accels: + * @action: a #GimpAction + * @accels: accelerators in the format understood by gtk_accelerator_parse(). + * The first accelerator is the main one. + * + * Set the accelerators to be associated with the given @action. + * + * Note that the #GimpAction API will emit the signal "accels-changed" whereas + * GtkApplication has no signal (that we could find) to connect to. It means we + * must always change accelerators with this function. + * Never use gtk_application_set_accels_for_action() directly! + */ void gimp_action_set_accels (GimpAction *action, const gchar **accels) @@ -426,6 +449,8 @@ gimp_action_set_accels (GimpAction *action, detailed_action_name, accels); g_free (detailed_action_name); + + g_signal_emit (action, action_signals[ACCELS_CHANGED], 0, accels); } /** @@ -460,6 +485,47 @@ gimp_action_get_accels (GimpAction *action) return accels; } +/** + * gimp_action_get_display_accels: + * @action: a #GimpAction + * + * Gets the accelerators that are currently associated with the given @action, + * in a format which can be presented to people on the GUI. + * + * Returns: (transfer full): accelerators for @action, as a %NULL-terminated + * array. Free with g_strfreev() when no longer needed + */ +gchar ** +gimp_action_get_display_accels (GimpAction *action) +{ + gchar **accels; + gint i; + + g_return_val_if_fail (GIMP_IS_ACTION (action), NULL); + + accels = gimp_action_get_accels (action); + + for (i = 0; accels[i] != NULL; i++) + { + guint accel_key = 0; + GdkModifierType accel_mods = 0; + + gtk_accelerator_parse (accels[i], &accel_key, &accel_mods); + + if (accel_key != 0 || accel_mods != 0) + { + gchar *accel; + + accel = gtk_accelerator_get_label (accel_key, accel_mods); + + g_free (accels[i]); + accels[i] = accel; + } + } + + return accels; +} + GSList * gimp_action_get_proxies (GimpAction *action) { diff --git a/app/widgets/gimpaction.h b/app/widgets/gimpaction.h index 5a0b4ec712..6aca00a652 100644 --- a/app/widgets/gimpaction.h +++ b/app/widgets/gimpaction.h @@ -47,10 +47,12 @@ struct _GimpActionInterface GTypeInterface base_interface; /* Signals */ - void (* activate) (GimpAction *action, - GVariant *value); - void (* change_state) (GimpAction *action, - GVariant *value); + void (* activate) (GimpAction *action, + GVariant *value); + void (* change_state) (GimpAction *action, + GVariant *value); + void (* accels_changed) (GimpAction *action, + const gchar **accels); }; @@ -114,6 +116,7 @@ void gimp_action_connect_accelerator (GimpAction *action); void gimp_action_set_accels (GimpAction *action, const gchar **accels); gchar ** gimp_action_get_accels (GimpAction *action); +gchar ** gimp_action_get_display_accels (GimpAction *action); GSList * gimp_action_get_proxies (GimpAction *action);