a11y: Fix keybindings in menus

GtkMenuItemAccessible was assuming that an accel label is
always the immediate child of a menu item. It also did not
deal with manually set accels.  Fix both of these.
https://bugzilla.gnome.org/show_bug.cgi?id=721086
This commit is contained in:
Matthias Clasen
2014-01-05 11:56:31 -05:00
parent 7e3f68d950
commit e015102fa9

View File

@ -462,6 +462,33 @@ find_accel_by_closure (GtkAccelKey *key,
return data == (gpointer) closure; return data == (gpointer) closure;
} }
static GtkWidget *
find_item_label (GtkWidget *item)
{
GtkWidget *child;
child = gtk_bin_get_child (GTK_BIN (item));
if (GTK_IS_CONTAINER (child))
{
GList *children, *l;
children = gtk_container_get_children (GTK_CONTAINER (child));
for (l = children; l; l = l->next)
{
if (GTK_IS_LABEL (l->data))
{
child = l->data;
break;
}
}
g_list_free (children);
}
if (GTK_IS_LABEL (child))
return child;
return NULL;
}
/* This function returns a string of the form A;B;C where A is /* This function returns a string of the form A;B;C where A is
* the keybinding for the widget; B is the keybinding to traverse * the keybinding for the widget; B is the keybinding to traverse
* from the menubar and C is the accelerator. The items in the * from the menubar and C is the accelerator. The items in the
@ -494,8 +521,7 @@ gtk_menu_item_accessible_get_keybinding (AtkAction *action,
guint key_val; guint key_val;
gchar *key, *temp_keybinding; gchar *key, *temp_keybinding;
child = gtk_bin_get_child (GTK_BIN (temp_item)); if (gtk_bin_get_child (GTK_BIN (temp_item)) == NULL)
if (child == NULL)
return NULL; return NULL;
parent = gtk_widget_get_parent (temp_item); parent = gtk_widget_get_parent (temp_item);
@ -513,6 +539,7 @@ gtk_menu_item_accessible_get_keybinding (AtkAction *action,
gtk_window_get_mnemonic_modifier (GTK_WINDOW (toplevel)); gtk_window_get_mnemonic_modifier (GTK_WINDOW (toplevel));
} }
child = find_item_label (temp_item);
if (GTK_IS_LABEL (child)) if (GTK_IS_LABEL (child))
{ {
key_val = gtk_label_get_mnemonic_keyval (GTK_LABEL (child)); key_val = gtk_label_get_mnemonic_keyval (GTK_LABEL (child));
@ -560,17 +587,27 @@ gtk_menu_item_accessible_get_keybinding (AtkAction *action,
parent = gtk_widget_get_parent (item); parent = gtk_widget_get_parent (item);
if (GTK_IS_MENU (parent)) if (GTK_IS_MENU (parent))
{ {
GtkAccelGroup *group; child = find_item_label (item);
GtkAccelKey *key; if (GTK_IS_ACCEL_LABEL (child))
group = gtk_menu_get_accel_group (GTK_MENU (parent));
if (group)
key = gtk_accel_group_find (group, find_accel_by_widget, item);
else
{ {
key = NULL; guint accel_key;
child = gtk_bin_get_child (GTK_BIN (item)); GdkModifierType accel_mods;
if (GTK_IS_ACCEL_LABEL (child))
gtk_accel_label_get_accel (GTK_ACCEL_LABEL (child), &accel_key, &accel_mods);
if (accel_key)
accelerator = gtk_accelerator_name (accel_key, accel_mods);
}
if (!accelerator)
{
GtkAccelGroup *group;
GtkAccelKey *key = NULL;
group = gtk_menu_get_accel_group (GTK_MENU (parent));
if (group)
key = gtk_accel_group_find (group, find_accel_by_widget, item);
else if (GTK_IS_ACCEL_LABEL (child))
{ {
GtkAccelLabel *accel_label; GtkAccelLabel *accel_label;
GClosure *accel_closure; GClosure *accel_closure;
@ -585,10 +622,10 @@ gtk_menu_item_accessible_get_keybinding (AtkAction *action,
g_closure_unref (accel_closure); g_closure_unref (accel_closure);
} }
} }
}
if (key) if (key)
accelerator = gtk_accelerator_name (key->accel_key, key->accel_mods); accelerator = gtk_accelerator_name (key->accel_key, key->accel_mods);
}
} }
/* Concatenate the bindings */ /* Concatenate the bindings */