From beaba95f398844b553e95b02196344e08a61e23f Mon Sep 17 00:00:00 2001 From: Phillip Wood Date: Tue, 4 Mar 2014 11:06:30 +0000 Subject: [PATCH] Window: Focus custom titlebar with F10 As discussed on desktop-devel-list [1], "There should be an intuitive, consistent, immediate way to jump to the widgets that live in the header bar." F10 has been suggested for this as it is already used to active menubars. F10 will focus the custom titlebar widget if the window has one and it isn't already focused. If the titlebar widget doesn't exist or is already focused then F10 focuses the menubar if there is one. [1] https://mail.gnome.org/archives/desktop-devel-list/2014-February/msg00176.html https://bugzilla.gnome.org/show_bug.cgi?id=725141 --- gtk/gtkmenubar.c | 78 ++---------------------------------------------- gtk/gtkmenubar.h | 2 ++ gtk/gtkwindow.c | 68 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 72 insertions(+), 76 deletions(-) diff --git a/gtk/gtkmenubar.c b/gtk/gtkmenubar.c index 3b5f7752e7..46aca862e2 100644 --- a/gtk/gtkmenubar.c +++ b/gtk/gtkmenubar.c @@ -656,8 +656,8 @@ get_menu_bars (GtkWindow *window) return g_object_get_data (G_OBJECT (window), "gtk-menu-bar-list"); } -static GList * -get_viewable_menu_bars (GtkWindow *window) +GList * +_gtk_menu_bar_get_viewable_menu_bars (GtkWindow *window) { GList *menu_bars; GList *viewable_menu_bars = NULL; @@ -691,76 +691,12 @@ set_menu_bars (GtkWindow *window, g_object_set_data (G_OBJECT (window), I_("gtk-menu-bar-list"), menubars); } -static gboolean -window_key_press_handler (GtkWidget *widget, - GdkEventKey *event, - gpointer data) -{ - gchar *accel = NULL; - gboolean retval = FALSE; - - g_object_get (gtk_widget_get_settings (widget), - "gtk-menu-bar-accel", &accel, - NULL); - - if (accel && *accel) - { - guint keyval = 0; - GdkModifierType mods = 0; - - gtk_accelerator_parse (accel, &keyval, &mods); - - if (keyval == 0) - g_warning ("Failed to parse menu bar accelerator '%s'\n", accel); - - /* FIXME this is wrong, needs to be in the global accel resolution - * thing, to properly consider i18n etc., but that probably requires - * AccelGroup changes etc. - */ - if (event->keyval == keyval && - ((event->state & gtk_accelerator_get_default_mod_mask ()) == - (mods & gtk_accelerator_get_default_mod_mask ()))) - { - GList *tmp_menubars = get_viewable_menu_bars (GTK_WINDOW (widget)); - GList *menubars; - - menubars = _gtk_container_focus_sort (GTK_CONTAINER (widget), tmp_menubars, - GTK_DIR_TAB_FORWARD, NULL); - g_list_free (tmp_menubars); - - if (menubars) - { - GtkMenuShell *menu_shell = GTK_MENU_SHELL (menubars->data); - - _gtk_menu_shell_set_keyboard_mode (menu_shell, TRUE); - gtk_menu_shell_select_first (menu_shell, FALSE); - - g_list_free (menubars); - - retval = TRUE; - } - } - } - - g_free (accel); - - return retval; -} - static void add_to_window (GtkWindow *window, GtkMenuBar *menubar) { GList *menubars = get_menu_bars (window); - if (!menubars) - { - g_signal_connect (window, - "key-press-event", - G_CALLBACK (window_key_press_handler), - NULL); - } - set_menu_bars (window, g_list_prepend (menubars, menubar)); } @@ -771,14 +707,6 @@ remove_from_window (GtkWindow *window, GList *menubars = get_menu_bars (window); menubars = g_list_remove (menubars, menubar); - - if (!menubars) - { - g_signal_handlers_disconnect_by_func (window, - window_key_press_handler, - NULL); - } - set_menu_bars (window, menubars); } @@ -816,7 +744,7 @@ _gtk_menu_bar_cycle_focus (GtkMenuBar *menubar, if (gtk_widget_is_toplevel (toplevel)) { - GList *tmp_menubars = get_viewable_menu_bars (GTK_WINDOW (toplevel)); + GList *tmp_menubars = _gtk_menu_bar_get_viewable_menu_bars (GTK_WINDOW (toplevel)); GList *menubars; GList *current; diff --git a/gtk/gtkmenubar.h b/gtk/gtkmenubar.h index fc0e38b806..f1d71837c1 100644 --- a/gtk/gtkmenubar.h +++ b/gtk/gtkmenubar.h @@ -88,6 +88,8 @@ void gtk_menu_bar_set_child_pack_direction (GtkMenuBar *menuba /* Private functions */ void _gtk_menu_bar_cycle_focus (GtkMenuBar *menubar, GtkDirectionType dir); +GList* _gtk_menu_bar_get_viewable_menu_bars (GtkWindow *window); + G_END_DECLS diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 68e6ffa800..d996af13eb 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -42,6 +42,7 @@ #include "gtkmain.h" #include "gtkmnemonichash.h" #include "gtkmenubar.h" +#include "gtkmenushellprivate.h" #include "gtkicontheme.h" #include "gtkmarshalers.h" #include "gtkplug.h" @@ -11552,6 +11553,71 @@ gtk_window_parse_geometry (GtkWindow *window, return result != 0; } +static gboolean +gtk_window_activate_menubar (GtkWindow *window, + GdkEventKey *event) +{ + GtkWindowPrivate *priv = window->priv; + gchar *accel = NULL; + guint keyval = 0; + GdkModifierType mods = 0; + + g_object_get (gtk_widget_get_settings (GTK_WIDGET (window)), + "gtk-menu-bar-accel", &accel, + NULL); + + if (accel == NULL || *accel == 0) + return FALSE; + + gtk_accelerator_parse (accel, &keyval, &mods); + g_free (accel); + + if (keyval == 0) + { + g_warning ("Failed to parse menu bar accelerator '%s'\n", accel); + return FALSE; + } + + /* FIXME this is wrong, needs to be in the global accel resolution + * thing, to properly consider i18n etc., but that probably requires + * AccelGroup changes etc. + */ + if (event->keyval == keyval && + ((event->state & gtk_accelerator_get_default_mod_mask ()) == + (mods & gtk_accelerator_get_default_mod_mask ()))) + { + GList *tmp_menubars; + GList *menubars; + GtkMenuShell *menu_shell; + + if (priv->title_box != NULL && + !gtk_widget_is_ancestor (gtk_window_get_focus (window), priv->title_box) && + gtk_widget_child_focus (priv->title_box, GTK_DIR_TAB_FORWARD)) + return TRUE; + + tmp_menubars = _gtk_menu_bar_get_viewable_menu_bars (window); + if (tmp_menubars == NULL) + return FALSE; + + menubars = _gtk_container_focus_sort (GTK_CONTAINER (window), tmp_menubars, + GTK_DIR_TAB_FORWARD, NULL); + g_list_free (tmp_menubars); + + if (menubars == NULL) + return FALSE; + + menu_shell = GTK_MENU_SHELL (menubars->data); + + _gtk_menu_shell_set_keyboard_mode (menu_shell, TRUE); + gtk_menu_shell_select_first (menu_shell, FALSE); + + g_list_free (menubars); + + return TRUE; + } + return FALSE; +} + static void gtk_window_mnemonic_hash_foreach (guint keyval, GSList *targets, @@ -11775,7 +11841,7 @@ gtk_window_activate_key (GtkWindow *window, } } - return FALSE; + return gtk_window_activate_menubar (window, event); } static void