From d0215c4032f4301e6b6068febc95d2f0fbc167b1 Mon Sep 17 00:00:00 2001 From: Christian Dywan Date: Tue, 3 Nov 2009 23:47:33 +0100 Subject: [PATCH] Support keyboard hotkeys that GTK+ considers invalid We re-implement the usual key handling by overriding the key press handler, emulating the according steps but leaving out the validation that normally rejects certain combinations. Single key hotkeys work unless an entry is focussed, in which case the entry receives the input, and Control+Tab works as well. The shortcuts extension is adjusted to accept any hotkeys. --- extensions/shortcuts.c | 1 + midori/midori-browser.c | 35 +++++++++++++++++++++++++++++++++++ midori/sokoke.c | 38 ++++++++++++++++++++++++++++++++++++++ midori/sokoke.h | 4 ++++ 4 files changed, 78 insertions(+) diff --git a/extensions/shortcuts.c b/extensions/shortcuts.c index e555b97c..9791dc82 100644 --- a/extensions/shortcuts.c +++ b/extensions/shortcuts.c @@ -88,6 +88,7 @@ shortcuts_preferences_render_accel (GtkTreeViewColumn* column, g_object_set (renderer, "accel-key", key.accel_key, "accel-mods", key.accel_mods, + "accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER, NULL); else g_object_set (renderer, "text", _("None"), NULL); diff --git a/midori/midori-browser.c b/midori/midori-browser.c index f9b18ab0..e1ed1b71 100644 --- a/midori/midori-browser.c +++ b/midori/midori-browser.c @@ -1684,9 +1684,41 @@ _midori_browser_quit (MidoriBrowser* browser) /* Nothing to do */ } +static gboolean +midori_browser_key_press_event (GtkWidget* widget, + GdkEventKey* event) +{ + GtkWindow* window = GTK_WINDOW (widget); + GtkWidget* focus = gtk_window_get_focus (window); + GtkWidgetClass* widget_class; + gboolean priority = GTK_IS_EDITABLE (focus) || GTK_IS_TEXT_VIEW (focus) + || WEBKIT_IS_WEB_VIEW (focus); + + if (priority && !event->state && gtk_window_propagate_key_event (window, event)) + return TRUE; + + if (event->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK)) + if (sokoke_window_activate_key (window, event)) + return TRUE; + + if (gtk_window_propagate_key_event (window, event)) + return TRUE; + + if (!(event->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK))) + if (sokoke_window_activate_key (window, event)) + return TRUE; + + if (!priority && event->state && gtk_window_propagate_key_event (window, event)) + return TRUE; + + widget_class = g_type_class_peek_static (g_type_parent (GTK_TYPE_WINDOW)); + return widget_class->key_press_event (widget, event); +} + static void midori_browser_class_init (MidoriBrowserClass* class) { + GtkWidgetClass* gtkwidget_class; GObjectClass* gobject_class; GParamFlags flags; @@ -1844,6 +1876,9 @@ midori_browser_class_init (MidoriBrowserClass* class) class->activate_action = _midori_browser_activate_action; class->quit = _midori_browser_quit; + gtkwidget_class = GTK_WIDGET_CLASS (class); + gtkwidget_class->key_press_event = midori_browser_key_press_event; + gobject_class = G_OBJECT_CLASS (class); gobject_class->dispose = midori_browser_dispose; gobject_class->finalize = midori_browser_finalize; diff --git a/midori/sokoke.c b/midori/sokoke.c index cc50277b..e87d797c 100644 --- a/midori/sokoke.c +++ b/midori/sokoke.c @@ -1260,3 +1260,41 @@ sokoke_replace_variables (const gchar* template, return result; } + +/** + * sokoke_window_activate_key: + * @window: a #GtkWindow + * @event: a #GdkEventKey + * + * Attempts to activate they key from the event, much + * like gtk_window_activate_key(), including keys + * that gtk_accelerator_valid() considers invalid. + * + * Return value: %TRUE on success + **/ +gboolean +sokoke_window_activate_key (GtkWindow* window, + GdkEventKey* event) +{ + gchar *accel_name; + GQuark accel_quark; + GObject* object; + GSList *slist; + + if (gtk_window_activate_key (window, event)) + return TRUE; + + /* We don't use gtk_accel_groups_activate because it refuses to + activate anything that gtk_accelerator_valid doesn't like. */ + accel_name = gtk_accelerator_name (event->keyval, (event->state & gtk_accelerator_get_default_mod_mask ())); + accel_quark = g_quark_from_string (accel_name); + g_free (accel_name); + object = G_OBJECT (window); + + for (slist = gtk_accel_groups_from_object (object); slist; slist = slist->next) + if (gtk_accel_group_activate (slist->data, accel_quark, + object, event->keyval, event->state)) + return TRUE; + + return FALSE; +} diff --git a/midori/sokoke.h b/midori/sokoke.h index 5074d74a..1039a70a 100644 --- a/midori/sokoke.h +++ b/midori/sokoke.h @@ -172,4 +172,8 @@ gchar* sokoke_replace_variables (const gchar* template, const gchar* variable_first, ...); +gboolean +sokoke_window_activate_key (GtkWindow* window, + GdkEventKey* event); + #endif /* !__SOKOKE_H__ */ -- 2.39.5