]> spindle.queued.net Git - midori/commitdiff
Support keyboard hotkeys that GTK+ considers invalid
authorChristian Dywan <christian@twotoasts.de>
Tue, 3 Nov 2009 22:47:33 +0000 (23:47 +0100)
committerChristian Dywan <christian@twotoasts.de>
Wed, 4 Nov 2009 13:31:16 +0000 (14:31 +0100)
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
midori/midori-browser.c
midori/sokoke.c
midori/sokoke.h

index e555b97c6589548aa1a431a7008b1bacfe2f2cf4..9791dc82dbf2989a20d48e78567d021f64c6f3cc 100644 (file)
@@ -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);
index f9b18ab043e05e1d1218527e2a383e267132a624..e1ed1b71c0d23a811a575dcce8c4e94ab2c15fae 100644 (file)
@@ -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;
index cc50277b44459454ff6d0b3dd7f3934ada0b7c6b..e87d797c0ae32bfdf4d4cd4e2db014ba1e154147 100644 (file)
@@ -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;
+}
index 5074d74aa06a8160772ab08cbe5018d62c24e5a1..1039a70a583b1ca6fc4f0846df5f172a4152e7d0 100644 (file)
@@ -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__ */