diff --git a/gtk/gtkmenuitem.c b/gtk/gtkmenuitem.c index ced23c099a..1ab96b00a2 100644 --- a/gtk/gtkmenuitem.c +++ b/gtk/gtkmenuitem.c @@ -132,6 +132,11 @@ static void gtk_menu_item_buildable_add_child (GtkBuildable *buildab GtkBuilder *builder, GObject *child, const gchar *type); +static void gtk_menu_item_buildable_custom_finished(GtkBuildable *buildable, + GtkBuilder *builder, + GObject *child, + const gchar *tagname, + gpointer user_data); static void gtk_menu_item_activatable_interface_init (GtkActivatableIface *iface); static void gtk_menu_item_update (GtkActivatable *activatable, @@ -558,6 +563,7 @@ gtk_menu_item_buildable_interface_init (GtkBuildableIface *iface) { parent_buildable_iface = g_type_interface_peek_parent (iface); iface->add_child = gtk_menu_item_buildable_add_child; + iface->custom_finished = gtk_menu_item_buildable_custom_finished; } static void @@ -573,6 +579,46 @@ gtk_menu_item_buildable_add_child (GtkBuildable *buildable, parent_buildable_iface->add_child (buildable, builder, child, type); } + +static void +gtk_menu_item_buildable_custom_finished (GtkBuildable *buildable, + GtkBuilder *builder, + GObject *child, + const gchar *tagname, + gpointer user_data) +{ + GtkWidget *toplevel; + + if (strcmp (tagname, "accelerator") == 0) + { + GtkMenuShell *menu_shell = (GtkMenuShell *) GTK_WIDGET (buildable)->parent; + GtkWidget *attach; + + if (menu_shell) + { + while (GTK_IS_MENU (menu_shell) && + (attach = gtk_menu_get_attach_widget (GTK_MENU (menu_shell))) != NULL) + menu_shell = (GtkMenuShell *)attach->parent; + + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (menu_shell)); + } + else + { + /* Fall back to something ... */ + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (buildable)); + + g_warning ("found a GtkMenuItem '%s' without a parent GtkMenuShell, assigned accelerators wont work.", + gtk_buildable_get_name (buildable)); + } + + /* Feed the correct toplevel to the GtkWidget accelerator parsing code */ + _gtk_widget_buildable_finish_accelerator (GTK_WIDGET (buildable), toplevel, user_data); + } + else + parent_buildable_iface->custom_finished (buildable, builder, child, tagname, user_data); +} + + static void gtk_menu_item_activatable_interface_init (GtkActivatableIface *iface) { diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 8cf4f08b3d..9d1251bd21 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -9806,6 +9806,44 @@ gtk_widget_buildable_custom_tag_start (GtkBuildable *buildable, return FALSE; } +void +_gtk_widget_buildable_finish_accelerator (GtkWidget *widget, + GtkWidget *toplevel, + gpointer user_data) +{ + AccelGroupParserData *accel_data; + GSList *accel_groups; + GtkAccelGroup *accel_group; + + g_return_if_fail (GTK_IS_WIDGET (widget)); + g_return_if_fail (GTK_IS_WIDGET (toplevel)); + g_return_if_fail (user_data != NULL); + + accel_data = (AccelGroupParserData*)user_data; + accel_groups = gtk_accel_groups_from_object (G_OBJECT (toplevel)); + if (g_slist_length (accel_groups) == 0) + { + accel_group = gtk_accel_group_new (); + gtk_window_add_accel_group (GTK_WINDOW (toplevel), accel_group); + } + else + { + g_assert (g_slist_length (accel_groups) == 1); + accel_group = g_slist_nth_data (accel_groups, 0); + } + + gtk_widget_add_accelerator (GTK_WIDGET (accel_data->object), + accel_data->signal, + accel_group, + accel_data->key, + accel_data->modifiers, + GTK_ACCEL_VISIBLE); + + g_object_unref (accel_data->object); + g_free (accel_data->signal); + g_slice_free (AccelGroupParserData, accel_data); +} + static void gtk_widget_buildable_custom_finished (GtkBuildable *buildable, GtkBuilder *builder, @@ -9816,8 +9854,6 @@ gtk_widget_buildable_custom_finished (GtkBuildable *buildable, AccelGroupParserData *accel_data; AccessibilitySubParserData *a11y_data; GtkWidget *toplevel; - GSList *accel_groups; - GtkAccelGroup *accel_group; if (strcmp (tagname, "accelerator") == 0) { @@ -9825,26 +9861,8 @@ gtk_widget_buildable_custom_finished (GtkBuildable *buildable, g_assert (accel_data->object); toplevel = gtk_widget_get_toplevel (GTK_WIDGET (accel_data->object)); - accel_groups = gtk_accel_groups_from_object (G_OBJECT (toplevel)); - if (g_slist_length (accel_groups) == 0) - { - accel_group = gtk_accel_group_new (); - gtk_window_add_accel_group (GTK_WINDOW (toplevel), accel_group); - } - else - { - g_assert (g_slist_length (accel_groups) == 1); - accel_group = g_slist_nth_data (accel_groups, 0); - } - gtk_widget_add_accelerator (GTK_WIDGET (accel_data->object), - accel_data->signal, - accel_group, - accel_data->key, - accel_data->modifiers, - GTK_ACCEL_VISIBLE); - g_object_unref (accel_data->object); - g_free (accel_data->signal); - g_slice_free (AccelGroupParserData, accel_data); + + _gtk_widget_buildable_finish_accelerator (GTK_WIDGET (buildable), toplevel, user_data); } else if (strcmp (tagname, "accessibility") == 0) { diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h index c73e52bba0..2d89fb0e29 100644 --- a/gtk/gtkwidget.h +++ b/gtk/gtkwidget.h @@ -841,6 +841,10 @@ void _gtk_widget_synthesize_crossing (GtkWidget *from, GdkColormap* _gtk_widget_peek_colormap (void); +void _gtk_widget_buildable_finish_accelerator (GtkWidget *widget, + GtkWidget *toplevel, + gpointer user_data); + G_END_DECLS #endif /* __GTK_WIDGET_H__ */