GtkAccelLabel: add manual accel API

Add an API to GtkAccelLabel for hardcoding the accel key to be displayed
(ie: allowing us to bypass the GtkAccelGroup lookup).

Use that from the GMenuModel-based GtkMenu construction code instead of
passing around the accel group.

This makes accel labels work in bloatpad again.

This patch effectively removes any hope of automatic runtime accel
changes in GMenuModel-based menus without additional application
support but it leaves the door open for this to be supported again in
the future (if we decide that it's important).

https://bugzilla.gnome.org/show_bug.cgi?id=683738
This commit is contained in:
Ryan Lortie 2012-09-10 14:36:23 -04:00
parent 338b5f6c2d
commit 778aa7ade0
8 changed files with 91 additions and 36 deletions

View File

@ -65,6 +65,7 @@ gtk_accel_label_get_accel_width
gtk_accel_label_get_type gtk_accel_label_get_type
gtk_accel_label_new gtk_accel_label_new
gtk_accel_label_refetch gtk_accel_label_refetch
gtk_accel_label_set_accel
gtk_accel_label_set_accel_closure gtk_accel_label_set_accel_closure
gtk_accel_label_set_accel_widget gtk_accel_label_set_accel_widget
gtk_accel_map_add_entry gtk_accel_map_add_entry

View File

@ -104,6 +104,9 @@ struct _GtkAccelLabelPrivate
gchar *accel_string; /* has set function */ gchar *accel_string; /* has set function */
guint accel_padding; /* should be style property? */ guint accel_padding; /* should be style property? */
guint16 accel_string_width; /* seems to be private */ guint16 accel_string_width; /* seems to be private */
guint accel_key; /* manual accel key specification if != 0 */
GdkModifierType accel_mods;
}; };
static void gtk_accel_label_set_property (GObject *object, static void gtk_accel_label_set_property (GObject *object,
@ -903,19 +906,31 @@ gtk_accel_label_refetch (GtkAccelLabel *accel_label)
"gtk-enable-accels", &enable_accels, "gtk-enable-accels", &enable_accels,
NULL); NULL);
if (enable_accels && accel_label->priv->accel_closure) if (enable_accels && (accel_label->priv->accel_closure || accel_label->priv->accel_key))
{ {
GtkAccelKey *key = gtk_accel_group_find (accel_label->priv->accel_group, find_accel, accel_label->priv->accel_closure); guint accel_key = accel_label->priv->accel_key;
GdkModifierType accel_mods = accel_label->priv->accel_mods;
if (key && key->accel_flags & GTK_ACCEL_VISIBLE) /* If we don't have a hardcoded value, check the accel group */
if (!accel_key)
{
GtkAccelKey *key = gtk_accel_group_find (accel_label->priv->accel_group, find_accel, accel_label->priv->accel_closure);
if (key && key->accel_flags & GTK_ACCEL_VISIBLE)
{
accel_key = key->accel_key;
accel_mods = key->accel_mods;
}
}
/* If we found a key using either method, set it */
if (accel_key)
{ {
GtkAccelLabelClass *klass; GtkAccelLabelClass *klass;
gchar *tmp; gchar *tmp;
klass = GTK_ACCEL_LABEL_GET_CLASS (accel_label); klass = GTK_ACCEL_LABEL_GET_CLASS (accel_label);
tmp = _gtk_accel_label_class_get_accelerator_label (klass, tmp = _gtk_accel_label_class_get_accelerator_label (klass, accel_key, accel_mods);
key->accel_key,
key->accel_mods);
accel_label->priv->accel_string = g_strconcat (" ", tmp, NULL); accel_label->priv->accel_string = g_strconcat (" ", tmp, NULL);
g_free (tmp); g_free (tmp);
} }
@ -930,3 +945,30 @@ gtk_accel_label_refetch (GtkAccelLabel *accel_label)
return FALSE; return FALSE;
} }
/**
* gtk_accel_label_set_accel:
* @accel_label: a #GtkAccelLabel
* @accelerator_key: a keyval, or 0
* @accelerator_mods: the modifier mask for the accel
*
* Manually sets a keyval and modifier mask as the accelerator rendered
* by @accel_label.
*
* If a keyval and modifier are explicitly set then these values are
* used regardless of any associated accel closure or widget.
*
* Providing an @accelerator_key of 0 removes the manual setting.
*
* Since: 3.6
*/
void
gtk_accel_label_set_accel (GtkAccelLabel *accel_label,
guint accelerator_key,
GdkModifierType accelerator_mods)
{
accel_label->priv->accel_key = accelerator_key;
accel_label->priv->accel_mods = accelerator_mods;
gtk_accel_label_reset (accel_label);
}

View File

@ -90,6 +90,10 @@ void gtk_accel_label_set_accel_widget (GtkAccelLabel *accel_label,
void gtk_accel_label_set_accel_closure (GtkAccelLabel *accel_label, void gtk_accel_label_set_accel_closure (GtkAccelLabel *accel_label,
GClosure *accel_closure); GClosure *accel_closure);
gboolean gtk_accel_label_refetch (GtkAccelLabel *accel_label); gboolean gtk_accel_label_refetch (GtkAccelLabel *accel_label);
GDK_AVAILABLE_IN_3_6
void gtk_accel_label_set_accel (GtkAccelLabel *accel_label,
guint accelerator_key,
GdkModifierType accelerator_mods);
/* private */ /* private */
gchar * _gtk_accel_label_class_get_accelerator_label (GtkAccelLabelClass *klass, gchar * _gtk_accel_label_class_get_accelerator_label (GtkAccelLabelClass *klass,

View File

@ -256,7 +256,7 @@ gtk_application_window_update_menubar (GtkApplicationWindow *window)
g_menu_append_section (combined, NULL, G_MENU_MODEL (window->priv->app_menu_section)); g_menu_append_section (combined, NULL, G_MENU_MODEL (window->priv->app_menu_section));
g_menu_append_section (combined, NULL, G_MENU_MODEL (window->priv->menubar_section)); g_menu_append_section (combined, NULL, G_MENU_MODEL (window->priv->menubar_section));
window->priv->menubar = gtk_model_menu_create_menu_bar (G_MENU_MODEL (combined), window->priv->accels); window->priv->menubar = gtk_model_menu_create_menu_bar (G_MENU_MODEL (combined));
gtk_widget_set_parent (window->priv->menubar, GTK_WIDGET (window)); gtk_widget_set_parent (window->priv->menubar, GTK_WIDGET (window));
gtk_widget_show_all (window->priv->menubar); gtk_widget_show_all (window->priv->menubar);
g_object_unref (combined); g_object_unref (combined);

View File

@ -33,7 +33,6 @@
typedef struct { typedef struct {
GMenuModel *model; GMenuModel *model;
GtkAccelGroup *accels;
GtkMenuShell *shell; GtkMenuShell *shell;
guint update_idle; guint update_idle;
GSList *connected; GSList *connected;
@ -107,7 +106,7 @@ gtk_model_menu_binding_append_item (GtkModelMenuBinding *binding,
{ {
GtkMenuItem *item; GtkMenuItem *item;
item = gtk_model_menu_item_new (model, item_index, action_namespace, binding->accels); item = gtk_model_menu_item_new (model, item_index, action_namespace);
gtk_menu_shell_append (binding->shell, GTK_WIDGET (item)); gtk_menu_shell_append (binding->shell, GTK_WIDGET (item));
gtk_widget_show (GTK_WIDGET (item)); gtk_widget_show (GTK_WIDGET (item));
binding->n_items++; binding->n_items++;
@ -254,7 +253,6 @@ gtk_model_menu_bind (GtkMenuShell *shell,
binding = g_slice_new (GtkModelMenuBinding); binding = g_slice_new (GtkModelMenuBinding);
binding->model = g_object_ref (model); binding->model = g_object_ref (model);
binding->accels = NULL;
binding->shell = shell; binding->shell = shell;
binding->update_idle = 0; binding->update_idle = 0;
binding->connected = NULL; binding->connected = NULL;
@ -266,30 +264,25 @@ gtk_model_menu_bind (GtkMenuShell *shell,
static void static void
gtk_model_menu_populate (GtkMenuShell *shell, gtk_model_menu_populate (GtkMenuShell *shell)
GtkAccelGroup *accels)
{ {
GtkModelMenuBinding *binding; GtkModelMenuBinding *binding;
binding = (GtkModelMenuBinding*) g_object_get_data (G_OBJECT (shell), "gtk-model-menu-binding"); binding = (GtkModelMenuBinding*) g_object_get_data (G_OBJECT (shell), "gtk-model-menu-binding");
binding->accels = accels;
gtk_model_menu_binding_populate (binding); gtk_model_menu_binding_populate (binding);
} }
GtkWidget * GtkWidget *
gtk_model_menu_create_menu (GMenuModel *model, gtk_model_menu_create_menu (GMenuModel *model,
const gchar *action_namespace, const gchar *action_namespace)
GtkAccelGroup *accels)
{ {
GtkWidget *menu; GtkWidget *menu;
menu = gtk_menu_new (); menu = gtk_menu_new ();
gtk_menu_set_accel_group (GTK_MENU (menu), accels);
gtk_model_menu_bind (GTK_MENU_SHELL (menu), model, action_namespace, TRUE); gtk_model_menu_bind (GTK_MENU_SHELL (menu), model, action_namespace, TRUE);
gtk_model_menu_populate (GTK_MENU_SHELL (menu), accels); gtk_model_menu_populate (GTK_MENU_SHELL (menu));
return menu; return menu;
} }
@ -317,21 +310,20 @@ gtk_menu_new_from_model (GMenuModel *model)
menu = gtk_menu_new (); menu = gtk_menu_new ();
gtk_model_menu_bind (GTK_MENU_SHELL (menu), model, NULL, TRUE); gtk_model_menu_bind (GTK_MENU_SHELL (menu), model, NULL, TRUE);
gtk_model_menu_populate (GTK_MENU_SHELL (menu), NULL); gtk_model_menu_populate (GTK_MENU_SHELL (menu));
return menu; return menu;
} }
GtkWidget * GtkWidget *
gtk_model_menu_create_menu_bar (GMenuModel *model, gtk_model_menu_create_menu_bar (GMenuModel *model)
GtkAccelGroup *accels)
{ {
GtkWidget *menubar; GtkWidget *menubar;
menubar = gtk_menu_bar_new (); menubar = gtk_menu_bar_new ();
gtk_model_menu_bind (GTK_MENU_SHELL (menubar), model, NULL, FALSE); gtk_model_menu_bind (GTK_MENU_SHELL (menubar), model, NULL, FALSE);
gtk_model_menu_populate (GTK_MENU_SHELL (menubar), accels); gtk_model_menu_populate (GTK_MENU_SHELL (menubar));
return menubar; return menubar;
} }
@ -360,7 +352,7 @@ gtk_menu_bar_new_from_model (GMenuModel *model)
menubar = gtk_menu_bar_new (); menubar = gtk_menu_bar_new ();
gtk_model_menu_bind (GTK_MENU_SHELL (menubar), model, NULL, FALSE); gtk_model_menu_bind (GTK_MENU_SHELL (menubar), model, NULL, FALSE);
gtk_model_menu_populate (GTK_MENU_SHELL (menubar), NULL); gtk_model_menu_populate (GTK_MENU_SHELL (menubar));
return menubar; return menubar;
} }

View File

@ -25,12 +25,10 @@
#include <gio/gio.h> #include <gio/gio.h>
G_GNUC_INTERNAL G_GNUC_INTERNAL
GtkWidget * gtk_model_menu_create_menu_bar (GMenuModel *model, GtkWidget * gtk_model_menu_create_menu_bar (GMenuModel *model);
GtkAccelGroup *accels);
G_GNUC_INTERNAL G_GNUC_INTERNAL
GtkWidget * gtk_model_menu_create_menu (GMenuModel *model, GtkWidget * gtk_model_menu_create_menu (GMenuModel *model,
const gchar *action_namespace, const gchar *action_namespace);
GtkAccelGroup *accels);
#endif /* __GTK_MODEL_MENU_H__ */ #endif /* __GTK_MODEL_MENU_H__ */

View File

@ -25,6 +25,7 @@
#include "gtkactionhelper.h" #include "gtkactionhelper.h"
#include "gtkmodelmenu.h" #include "gtkmodelmenu.h"
#include "gtkwidgetprivate.h" #include "gtkwidgetprivate.h"
#include "gtkaccellabel.h"
struct _GtkModelMenuItem struct _GtkModelMenuItem
{ {
@ -107,8 +108,7 @@ static void
gtk_model_menu_item_setup (GtkModelMenuItem *item, gtk_model_menu_item_setup (GtkModelMenuItem *item,
GMenuModel *model, GMenuModel *model,
gint item_index, gint item_index,
const gchar *action_namespace, const gchar *action_namespace)
GtkAccelGroup *accels)
{ {
GMenuAttributeIter *iter; GMenuAttributeIter *iter;
GMenuModel *submenu; GMenuModel *submenu;
@ -125,12 +125,12 @@ gtk_model_menu_item_setup (GtkModelMenuItem *item,
if (action_namespace) if (action_namespace)
{ {
gchar *namespace = g_strjoin (".", action_namespace, section_namespace, NULL); gchar *namespace = g_strjoin (".", action_namespace, section_namespace, NULL);
menu = gtk_model_menu_create_menu (submenu, namespace, accels); menu = gtk_model_menu_create_menu (submenu, namespace);
g_free (namespace); g_free (namespace);
} }
else else
{ {
menu = gtk_model_menu_create_menu (submenu, section_namespace, accels); menu = gtk_model_menu_create_menu (submenu, section_namespace);
} }
gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu); gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu);
@ -145,6 +145,26 @@ gtk_model_menu_item_setup (GtkModelMenuItem *item,
if (g_str_equal (key, "label") && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)) if (g_str_equal (key, "label") && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
gtk_menu_item_set_label (GTK_MENU_ITEM (item), g_variant_get_string (value, NULL)); gtk_menu_item_set_label (GTK_MENU_ITEM (item), g_variant_get_string (value, NULL));
else if (g_str_equal (key, "accel") && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
{
GdkModifierType modifiers;
guint key;
gtk_accelerator_parse (g_variant_get_string (value, NULL), &key, &modifiers);
if (key)
{
GtkAccelLabel *accel_label;
/* Ensure that the GtkAccelLabel has been created... */
(void) gtk_menu_item_get_label (GTK_MENU_ITEM (item));
accel_label = GTK_ACCEL_LABEL (gtk_bin_get_child (GTK_BIN (item)));
g_assert (accel_label);
gtk_accel_label_set_accel (accel_label, key, modifiers);
}
}
else if (g_str_equal (key, "action") && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING)) else if (g_str_equal (key, "action") && g_variant_is_of_type (value, G_VARIANT_TYPE_STRING))
gtk_actionable_set_namespaced_action_name (GTK_ACTIONABLE (item), action_namespace, gtk_actionable_set_namespaced_action_name (GTK_ACTIONABLE (item), action_namespace,
g_variant_get_string (value, NULL)); g_variant_get_string (value, NULL));
@ -260,14 +280,13 @@ gtk_model_menu_item_class_init (GtkModelMenuItemClass *class)
GtkMenuItem * GtkMenuItem *
gtk_model_menu_item_new (GMenuModel *model, gtk_model_menu_item_new (GMenuModel *model,
gint item_index, gint item_index,
const gchar *action_namespace, const gchar *action_namespace)
GtkAccelGroup *accels)
{ {
GtkModelMenuItem *item; GtkModelMenuItem *item;
item = g_object_new (GTK_TYPE_MODEL_MENU_ITEM, NULL); item = g_object_new (GTK_TYPE_MODEL_MENU_ITEM, NULL);
gtk_model_menu_item_setup (item, model, item_index, action_namespace, accels); gtk_model_menu_item_setup (item, model, item_index, action_namespace);
return GTK_MENU_ITEM (item); return GTK_MENU_ITEM (item);
} }

View File

@ -36,7 +36,6 @@ GType gtk_model_menu_item_get_type (void) G
G_GNUC_INTERNAL G_GNUC_INTERNAL
GtkMenuItem * gtk_model_menu_item_new (GMenuModel *model, GtkMenuItem * gtk_model_menu_item_new (GMenuModel *model,
gint item_index, gint item_index,
const gchar *action_namespace, const gchar *action_namespace);
GtkAccelGroup *accels);
#endif /* __GTK_MODEL_MENU_ITEM_H__ */ #endif /* __GTK_MODEL_MENU_ITEM_H__ */