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.
This commit is contained in:
Christian Dywan 2009-11-03 23:47:33 +01:00
parent 3a491840f5
commit d0215c4032
4 changed files with 78 additions and 0 deletions

View 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);

View 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;

View 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;
}

View 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__ */