[rhythmbox] replace default window event handling
- From: Jonathan Matthew <jmatthew src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [rhythmbox] replace default window event handling
- Date: Mon, 1 Aug 2016 10:59:51 +0000 (UTC)
commit 6073129ef5baee45fbd60d2747bb013d586d6584
Author: Jonathan Matthew <jonathan d14n org>
Date: Thu Mar 17 20:58:41 2016 +1000
replace default window event handling
This allows us to add default actions for keys without overriding
normal widget behaviour. Some of the playback controls were
overriding tree view shortcuts, which is apparently an outrage.
shell/rb-application.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++
shell/rb-application.h | 3 ++
shell/rb-shell-player.c | 11 ++++--
shell/rb-shell.c | 32 ++++++++++++++-----
4 files changed, 113 insertions(+), 12 deletions(-)
---
diff --git a/shell/rb-application.c b/shell/rb-application.c
index 2b922b3..8e91f1d 100644
--- a/shell/rb-application.c
+++ b/shell/rb-application.c
@@ -53,6 +53,14 @@
static void rb_application_class_init (RBApplicationClass *klass);
static void rb_application_init (RBApplication *app);
+typedef struct {
+ guint keyval;
+ GdkModifierType mods;
+ char *prefix;
+ char *action;
+ GVariant *parameter;
+} RBApplicationAccel;
+
struct _RBApplicationPrivate
{
RBShell *shell;
@@ -69,6 +77,8 @@ struct _RBApplicationPrivate
gboolean disable_plugins;
char *rhythmdb_file;
char *playlists_file;
+
+ GList *accelerators;
};
G_DEFINE_TYPE (RBApplication, rb_application, GTK_TYPE_APPLICATION);
@@ -899,3 +909,72 @@ rb_application_set_menu_accelerators (RBApplication *app, GMenuModel *menu, gboo
g_object_unref (iter);
}
}
+
+/**
+ * rb_application_add_accelerator:
+ * @app: the #RBApplication
+ * @accel: accelerator string
+ * @action: the name of the action to activate
+ * @parameter: parameter to pass when activating the action, or NULL if
+ * the action does not accept an activation parameter.
+ *
+ * Like #gtk_application_add_accelerator, except the accelerator only applies
+ * if the key was not handled by the focused widget.
+ */
+void
+rb_application_add_accelerator (RBApplication *app, const char *accel, const char *action, GVariant
*parameter)
+{
+ RBApplicationAccel *a = g_new0 (RBApplicationAccel, 1);
+ char **bits;
+
+ gtk_accelerator_parse (accel, &a->keyval, &a->mods);
+ if (parameter != NULL)
+ a->parameter = g_variant_ref (parameter);
+
+ bits = g_strsplit (action, ".", 2);
+ a->prefix = bits[0];
+ a->action = bits[1];
+ g_free (bits);
+
+ app->priv->accelerators = g_list_append (app->priv->accelerators, a);
+}
+
+/**
+ * rb_application_activate_key:
+ * @app: the #RBApplication
+ * @event: a #GdkEventKey
+ *
+ * Attempts to activate an accelerator registered using #rb_application_add_accelerator.
+ *
+ * Return value: %TRUE if an accelerator was activated
+ */
+gboolean
+rb_application_activate_key (RBApplication *app, GdkEventKey *event)
+{
+ GList *l;
+ GtkWidget *window;
+ gboolean ret = FALSE;
+
+ g_object_get (app->priv->shell, "window", &window, NULL);
+
+ for (l = app->priv->accelerators; l != NULL; l = l->next) {
+ RBApplicationAccel *accel = l->data;
+ if (accel->keyval == event->keyval &&
+ accel->mods == event->state) {
+ GActionGroup *group;
+
+ group = gtk_widget_get_action_group (window, accel->prefix);
+ if (group == NULL)
+ group = G_ACTION_GROUP (app);
+
+ g_action_group_activate_action (group,
+ accel->action,
+ accel->parameter);
+ ret = TRUE;
+ break;
+ }
+ }
+
+ g_object_unref (window);
+ return ret;
+}
diff --git a/shell/rb-application.h b/shell/rb-application.h
index 747652a..d02e568 100644
--- a/shell/rb-application.h
+++ b/shell/rb-application.h
@@ -69,6 +69,9 @@ GMenuModel * rb_application_get_plugin_menu (RBApplication *app, const char *men
void rb_application_add_plugin_menu_item (RBApplication *app, const char *menu, const char *id,
GMenuItem *item);
void rb_application_remove_plugin_menu_item (RBApplication *app, const char *menu, const char *id);
+void rb_application_add_accelerator (RBApplication *app, const char *accel, const char *action,
GVariant *parameter);
+gboolean rb_application_activate_key (RBApplication *app, GdkEventKey *event);
+
G_END_DECLS
#endif /* RB_APPLICATION_H */
diff --git a/shell/rb-shell-player.c b/shell/rb-shell-player.c
index 8d5933b..5aa03b1 100644
--- a/shell/rb-shell-player.c
+++ b/shell/rb-shell-player.c
@@ -2972,11 +2972,14 @@ rb_shell_player_constructed (GObject *object)
G_N_ELEMENTS (actions),
player);
+ /* these only take effect if the focused widget doesn't handle the event */
+ rb_application_add_accelerator (app, "<Ctrl>Left", "app.play-previous", NULL);
+ rb_application_add_accelerator (app, "<Ctrl>Right", "app.play-next", NULL);
+ rb_application_add_accelerator (app, "<Ctrl>Up", "app.volume-up", NULL);
+ rb_application_add_accelerator (app, "<Ctrl>Down", "app.volume-down", NULL);
+
+ /* these take effect regardless of widget key handling */
gtk_application_add_accelerator (GTK_APPLICATION (app), "<Ctrl>p", "app.play", NULL);
- gtk_application_add_accelerator (GTK_APPLICATION (app), "<Ctrl>Left", "app.play-previous", NULL);
- gtk_application_add_accelerator (GTK_APPLICATION (app), "<Ctrl>Right", "app.play-next", NULL);
- gtk_application_add_accelerator (GTK_APPLICATION (app), "<Ctrl>Up", "app.volume-up", NULL);
- gtk_application_add_accelerator (GTK_APPLICATION (app), "<Ctrl>Down", "app.volume-down", NULL);
gtk_application_add_accelerator (GTK_APPLICATION (app), "<Ctrl>r", "app.play-repeat",
g_variant_new_boolean (TRUE));
gtk_application_add_accelerator (GTK_APPLICATION (app), "<Ctrl>u", "app.play-shuffle",
g_variant_new_boolean (TRUE));
diff --git a/shell/rb-shell.c b/shell/rb-shell.c
index 39e0082..0130337 100644
--- a/shell/rb-shell.c
+++ b/shell/rb-shell.c
@@ -1978,25 +1978,41 @@ rb_shell_key_press_event_cb (GtkWidget *win,
GdkEventKey *event,
RBShell *shell)
{
-#ifndef HAVE_MMKEYS
- return FALSE;
-#else
-
- gboolean retval = TRUE;
+ GtkWindow *window = GTK_WINDOW (win);
+ gboolean handled = FALSE;
+#ifdef HAVE_MMKEYS
switch (event->keyval) {
case XF86XK_Back:
rb_shell_player_do_previous (shell->priv->player_shell, NULL);
+ handled = TRUE;
break;
case XF86XK_Forward:
rb_shell_player_do_next (shell->priv->player_shell, NULL);
+ handled = TRUE;
break;
default:
- retval = FALSE;
+ break;
+ }
+#endif
+
+ if (!handled)
+ handled = gtk_window_activate_key (window, event);
+
+ if (!handled)
+ handled = gtk_window_propagate_key_event (window, event);
+
+ if (!handled)
+ handled = rb_application_activate_key (shell->priv->application, event);
+
+ if (!handled) {
+ GObjectClass *object_class;
+ object_class = G_OBJECT_GET_CLASS (win);
+ handled = GTK_WIDGET_CLASS (g_type_class_peek_parent (object_class))->key_press_event (win,
event);
}
- return retval;
-#endif /* !HAVE_MMKEYS */
+ /* we're completely replacing the default window handling, so always return TRUE */
+ return TRUE;
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]