From 100e0e1bf17e496dbe728a3637d199157d93b10e Mon Sep 17 00:00:00 2001 From: Thomas Martitz Date: Sat, 24 May 2014 14:37:24 +0200 Subject: [PATCH] infobars: Intercept some keys when the info bar is shown to allow interacting with it using the keyboard only. When the info bar is shown tab/shift+tab and escape are intercepted. * tab/shift+tab change the focus to the info bar buttons which can then be cycled through with more tab presses * escape closes the info bar (same as clicking cancel) Both keys aren't needed for the document because it's read-only. Other keys, such arrow/page up/down, remain to the document for navigating. --- src/document.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/src/document.c b/src/document.c index 8c7b13db1d..39c16f7407 100644 --- a/src/document.c +++ b/src/document.c @@ -75,6 +75,8 @@ /*#define USE_GIO_FILEMON 1*/ #include +#include + GeanyFilePrefs file_prefs; @@ -3152,6 +3154,45 @@ static void on_monitor_reload_file_response(GtkWidget *bar, gint response_id, Ge doc->priv->info_bars[MSG_TYPE_RELOAD] = NULL; } +static gboolean on_sci_key(GtkWidget *w, GdkEventKey *event, gpointer data) +{ + GtkInfoBar *bar = GTK_INFO_BAR(data); + + g_return_val_if_fail(event->type == GDK_KEY_PRESS, FALSE); + + switch (event->keyval) + { + case GDK_KEY_Tab: + case GDK_KEY_ISO_Left_Tab: + { + GtkWidget *w = gtk_info_bar_get_action_area(bar); + GtkDirectionType dir = event->keyval == GDK_KEY_Tab ? GTK_DIR_TAB_FORWARD : GTK_DIR_TAB_BACKWARD; + gtk_widget_child_focus(w, dir); + return TRUE; + } + case GDK_KEY_Escape: + { + gtk_info_bar_response(bar, GTK_RESPONSE_CANCEL); + return TRUE; + } + default: + return FALSE; + } +} + +/* g_signal_handlers_disconnect_by_data is a macro that cannot be used as GCallback */ +static gint nonmacro_g_signal_handlers_disconnect_by_data(gpointer instance, gpointer data) +{ + return g_signal_handlers_disconnect_by_data(instance, data); +} + +static void enable_key_intercept(GeanyDocument *doc, GtkWidget *bar) +{ + g_signal_connect(doc->editor->sci, "key-press-event", G_CALLBACK(on_sci_key), bar); + /* make the signal disconnect automatically */ + g_signal_connect_swapped(bar, "unrealize", + G_CALLBACK(nonmacro_g_signal_handlers_disconnect_by_data), doc->editor->sci); +} static void monitor_reload_file(GeanyDocument *doc) { @@ -3172,6 +3213,7 @@ static void monitor_reload_file(GeanyDocument *doc) protect_document(doc); doc->priv->info_bars[MSG_TYPE_RELOAD] = bar; + enable_key_intercept(doc, bar); } g_free(base_name); } @@ -3221,6 +3263,7 @@ static void monitor_resave_missing_file(GeanyDocument *doc) protect_document(doc); doc->priv->info_bars[MSG_TYPE_RESAVE] = bar; + enable_key_intercept(doc, bar); } }