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:
parent
3a491840f5
commit
d0215c4032
4 changed files with 78 additions and 0 deletions
|
@ -88,6 +88,7 @@ shortcuts_preferences_render_accel (GtkTreeViewColumn* column,
|
||||||
g_object_set (renderer,
|
g_object_set (renderer,
|
||||||
"accel-key", key.accel_key,
|
"accel-key", key.accel_key,
|
||||||
"accel-mods", key.accel_mods,
|
"accel-mods", key.accel_mods,
|
||||||
|
"accel-mode", GTK_CELL_RENDERER_ACCEL_MODE_OTHER,
|
||||||
NULL);
|
NULL);
|
||||||
else
|
else
|
||||||
g_object_set (renderer, "text", _("None"), NULL);
|
g_object_set (renderer, "text", _("None"), NULL);
|
||||||
|
|
|
@ -1684,9 +1684,41 @@ _midori_browser_quit (MidoriBrowser* browser)
|
||||||
/* Nothing to do */
|
/* 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
|
static void
|
||||||
midori_browser_class_init (MidoriBrowserClass* class)
|
midori_browser_class_init (MidoriBrowserClass* class)
|
||||||
{
|
{
|
||||||
|
GtkWidgetClass* gtkwidget_class;
|
||||||
GObjectClass* gobject_class;
|
GObjectClass* gobject_class;
|
||||||
GParamFlags flags;
|
GParamFlags flags;
|
||||||
|
|
||||||
|
@ -1844,6 +1876,9 @@ midori_browser_class_init (MidoriBrowserClass* class)
|
||||||
class->activate_action = _midori_browser_activate_action;
|
class->activate_action = _midori_browser_activate_action;
|
||||||
class->quit = _midori_browser_quit;
|
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 = G_OBJECT_CLASS (class);
|
||||||
gobject_class->dispose = midori_browser_dispose;
|
gobject_class->dispose = midori_browser_dispose;
|
||||||
gobject_class->finalize = midori_browser_finalize;
|
gobject_class->finalize = midori_browser_finalize;
|
||||||
|
|
|
@ -1260,3 +1260,41 @@ sokoke_replace_variables (const gchar* template,
|
||||||
|
|
||||||
return result;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -172,4 +172,8 @@ gchar*
|
||||||
sokoke_replace_variables (const gchar* template,
|
sokoke_replace_variables (const gchar* template,
|
||||||
const gchar* variable_first, ...);
|
const gchar* variable_first, ...);
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
sokoke_window_activate_key (GtkWindow* window,
|
||||||
|
GdkEventKey* event);
|
||||||
|
|
||||||
#endif /* !__SOKOKE_H__ */
|
#endif /* !__SOKOKE_H__ */
|
||||||
|
|
Loading…
Reference in a new issue