]> www.fi.muni.cz Git - evince.git/commitdiff
When building with D-Bus support, listen for multimedia key events from
authorBastien Nocera <hadess@hadess.net>
Tue, 24 Jun 2008 18:15:12 +0000 (18:15 +0000)
committerBastien Nocera <hadess@src.gnome.org>
Tue, 24 Jun 2008 18:15:12 +0000 (18:15 +0000)
2008-06-24  Bastien Nocera  <hadess@hadess.net>

* shell/Makefile.am:
* shell/ev-application.c (ev_application_init),
(ev_application_get_media_keys):
* shell/ev-application.h:
* shell/ev-marshal.list:
* shell/ev-media-player-keys.c (ev_media_player_keys_class_init),
(proxy_destroy), (on_media_player_key_pressed),
(ev_media_player_keys_init), (ev_media_player_keys_focused),
(ev_media_player_keys_finalize), (ev_media_player_keys_new):
* shell/ev-media-player-keys.h:
* shell/ev-window.c (ev_window_go_previous_page),
(ev_window_go_next_page), (ev_window_go_first_page),
(ev_window_go_last_page), (ev_window_start_presentation),
(ev_window_dispose), (view_actions_focus_in_cb):
* shell/ev-window.h: When building with D-Bus support, listen
for multimedia key events from gnome-settings-daemon. This allows
to go to the next/previous/first/last pages using, respectively,
Next/Previous/Rewing/Fast Forward. The Play button is used to start
a presentation. Fixes bug #539971.

svn path=/trunk/; revision=3059

ChangeLog
shell/Makefile.am
shell/ev-application.c
shell/ev-application.h
shell/ev-marshal.list
shell/ev-media-player-keys.c [new file with mode: 0644]
shell/ev-media-player-keys.h [new file with mode: 0644]
shell/ev-window.c
shell/ev-window.h

index 8892d4d736b5700be81994d0a60da905cfc8ba9c..96e81d8daa1bdef763e99cb75d4fd61ff2c437a7 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2008-06-24  Bastien Nocera  <hadess@hadess.net>
+
+       * shell/Makefile.am:
+       * shell/ev-application.c (ev_application_init),
+       (ev_application_get_media_keys):
+       * shell/ev-application.h:
+       * shell/ev-marshal.list:
+       * shell/ev-media-player-keys.c (ev_media_player_keys_class_init),
+       (proxy_destroy), (on_media_player_key_pressed),
+       (ev_media_player_keys_init), (ev_media_player_keys_focused),
+       (ev_media_player_keys_finalize), (ev_media_player_keys_new):
+       * shell/ev-media-player-keys.h:
+       * shell/ev-window.c (ev_window_go_previous_page),
+       (ev_window_go_next_page), (ev_window_go_first_page),
+       (ev_window_go_last_page), (ev_window_start_presentation),
+       (ev_window_dispose), (view_actions_focus_in_cb):
+       * shell/ev-window.h: When building with D-Bus support, listen
+       for multimedia key events from gnome-settings-daemon. This allows
+       to go to the next/previous/first/last pages using, respectively,
+       Next/Previous/Rewing/Fast Forward. The Play button is used to start
+       a presentation. Fixes bug #539971.
+
 2008-06-19  Nickolay V. Shmyrev  <nshmyrev@yandex.ru>
 
        * configure.ac:
index 824cf3f7a43c5933cc34e3eedc60a378de5d3762..3d857716858fa66c75760a9605d87d7cd4d8e56b 100644 (file)
@@ -16,6 +16,13 @@ INCLUDES=                                            \
 
 bin_PROGRAMS=evince
 
+EV_MEDIA_PLAYER_KEYS_SOURCES = ev-media-player-keys.c ev-media-player-keys.h
+if ENABLE_DBUS
+DBUS_SOURCES = $(EV_MEDIA_PLAYER_KEYS_SOURCES)
+else
+DBUS_SOURCES = $(null)
+endif
+
 evince_SOURCES=                                \
        eggfindbar.c                    \
        eggfindbar.h                    \
@@ -31,6 +38,7 @@ evince_SOURCES=                               \
        ev-history.h                    \
        ev-marshal.c                    \
        ev-marshal.h                    \
+       $(DBUS_SOURCES)                 \
        ev-message-area.c               \
        ev-message-area.h               \
        ev-metadata-manager.c           \
@@ -105,7 +113,8 @@ BUILT_SOURCES += ev-application-service.h
 endif
 
 EXTRA_DIST = ev-marshal.list           \
-       ev-application-service.xml
+       ev-application-service.xml      \
+       $(EV_MEDIA_PLAYER_KEYS_SOURCES)
 
 
 ev-marshal.h: $(srcdir)/ev-marshal.list
index 6e7a6e673ea9afedd7a16981b21a3672b164a4fb..7ad13820dd9d8f2de408a93d0edde90f29d9c83b 100644 (file)
@@ -25,6 +25,9 @@
 #include "ev-utils.h"
 #include "ev-file-helpers.h"
 #include "ev-document-factory.h"
+#ifdef ENABLE_DBUS
+#include "ev-media-player-keys.h"
+#endif /* ENABLE_DBUS */
 #include "totem-scrsaver.h"
 
 #include <glib.h>
@@ -59,6 +62,10 @@ struct _EvApplication {
 
        gchar *last_chooser_uri;
 
+#ifdef ENABLE_DBUS
+       EvMediaPlayerKeys *keys;
+#endif /* ENABLE_DBUS */
+
        GtkPrintSettings *print_settings;
 #if GTK_CHECK_VERSION (2, 11, 0)
        gchar            *print_settings_file;
@@ -715,6 +722,10 @@ ev_application_init (EvApplication *ev_application)
 
        egg_toolbars_model_set_flags (ev_application->toolbars_model, 0,
                                      EGG_TB_MODEL_NOT_REMOVABLE);
+
+#ifdef ENABLE_DBUS
+       ev_application->keys = ev_media_player_keys_new ();
+#endif /* ENABLE_DBUS */
 }
 
 /**
@@ -744,6 +755,26 @@ ev_application_get_windows (EvApplication *application)
        return windows;
 }
 
+/**
+ * ev_application_get_media_keys:
+ * @application: The instance of the application.
+ *
+ * It gives you access to the media player keys handler object.
+ *
+ * Returns: A #EvMediaPlayerKeys.
+ */
+GObject
+*ev_application_get_media_keys (EvApplication *application)
+{
+#ifdef ENABLE_DBUS
+       if (!application->keys)
+               return NULL;
+       return g_object_ref (G_OBJECT (application->keys));
+#else
+       return NULL;
+#endif /* ENABLE_DBUS */
+}
+
 EggToolbarsModel *
 ev_application_get_toolbars_model (EvApplication *application)
 {
index 4525590e910cdb1fd715db7f9d977a3561f009fb..efaf0b63d86ef21f3713306ba72bea2b0b317c65 100644 (file)
@@ -78,6 +78,7 @@ void            ev_application_open_uri_list       (EvApplication   *application,
                                                      GdkScreen       *screen,
                                                      guint32          timestamp);
 GList           *ev_application_get_windows         (EvApplication   *application);
+GObject                 *ev_application_get_media_keys      (EvApplication   *application);
 
 EggToolbarsModel *ev_application_get_toolbars_model  (EvApplication   *application);
 void              ev_application_save_toolbars_model (EvApplication   *application);
index c2a026bf2dd58e05e4386f63aeef73611d36e0bb..d3b99fd95f3d43ae5afece585540fea322ef0beb 100644 (file)
@@ -1,3 +1,4 @@
 VOID:NONE
 VOID:OBJECT,OBJECT
 VOID:ENUM,BOOLEAN
+VOID:STRING,STRING
diff --git a/shell/ev-media-player-keys.c b/shell/ev-media-player-keys.c
new file mode 100644 (file)
index 0000000..c244b2e
--- /dev/null
@@ -0,0 +1,191 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* 
+ * Copyright (C) 2007 Jan Arne Petersen <jap@gnome.org>
+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
+ *
+ */
+
+#include "config.h"
+
+#include <glib.h>
+#include <glib-object.h>
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+#include <dbus/dbus-glib.h>
+#include <string.h>
+
+#include "ev-media-player-keys.h"
+
+#include "ev-marshal.h"
+
+struct _EvMediaPlayerKeys
+{
+       GObject        parent;
+       DBusGProxy    *media_player_keys_proxy;
+       EvWindow      *window;
+};
+
+struct _EvMediaPlayerKeysClass
+{
+       GObjectClass parent_class;
+};
+
+G_DEFINE_TYPE (EvMediaPlayerKeys, ev_media_player_keys, G_TYPE_OBJECT)
+
+static void ev_media_player_keys_init          (EvMediaPlayerKeys *keys);
+static void ev_media_player_keys_finalize      (GObject *object);
+
+static void
+ev_media_player_keys_class_init (EvMediaPlayerKeysClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->finalize = ev_media_player_keys_finalize;
+}
+
+static void
+proxy_destroy (DBusGProxy *proxy,
+              EvMediaPlayerKeys* keys)
+{
+       keys->media_player_keys_proxy = NULL;
+}
+
+static void
+on_media_player_key_pressed (DBusGProxy *proxy, const gchar *application, const gchar *key, EvMediaPlayerKeys *keys)
+{
+       if (strcmp ("Evince", application) == 0 && keys->window != NULL) {
+               /* Note how Previous/Next only go to the
+                * next/previous page despite their icon telling you
+                * they should go to the beginning/end.
+                *
+                * There's very few keyboards with FFW/RWD though,
+                * so we stick the most useful keybinding on the most
+                * often seen keys
+                */
+               if (strcmp ("Play", key) == 0) {
+                       ev_window_start_presentation (keys->window);
+               } else if (strcmp ("Previous", key) == 0) {
+                       ev_window_go_previous_page (keys->window);
+               } else if (strcmp ("Next", key) == 0) {
+                       ev_window_go_next_page (keys->window);
+               } else if (strcmp ("FastForward", key) == 0) {
+                       ev_window_go_last_page (keys->window);
+               } else if (strcmp ("Rewind", key) == 0) {
+                       ev_window_go_first_page (keys->window);
+               }
+       }
+}
+
+static void
+ev_media_player_keys_init (EvMediaPlayerKeys *keys)
+{
+       DBusGConnection *connection;
+       GError *err = NULL;
+
+       connection = dbus_g_bus_get (DBUS_BUS_SESSION, &err);
+       if (connection == NULL) {
+               g_warning ("Error connecting to D-Bus: %s", err->message);
+               return;
+       }
+
+       /* Try the gnome-settings-daemon version,
+        * then the gnome-control-center version of things */
+       keys->media_player_keys_proxy = dbus_g_proxy_new_for_name_owner (connection,
+                                                                      "org.gnome.SettingsDaemon",
+                                                                      "/org/gnome/SettingsDaemon/MediaKeys",
+                                                                      "org.gnome.SettingsDaemon.MediaKeys",
+                                                                      NULL);
+       if (keys->media_player_keys_proxy == NULL) {
+               keys->media_player_keys_proxy = dbus_g_proxy_new_for_name_owner (connection,
+                                                                              "org.gnome.SettingsDaemon",
+                                                                              "/org/gnome/SettingsDaemon",
+                                                                              "org.gnome.SettingsDaemon",
+                                                                              &err);
+       }
+
+       dbus_g_connection_unref (connection);
+       if (err != NULL) {
+               g_warning ("Failed to create dbus proxy for org.gnome.SettingsDaemon: %s",
+                          err->message);
+               g_error_free (err);
+               return;
+       } else {
+               g_signal_connect_object (keys->media_player_keys_proxy,
+                                        "destroy",
+                                        G_CALLBACK (proxy_destroy),
+                                        keys, 0);
+       }
+
+       dbus_g_proxy_call (keys->media_player_keys_proxy,
+                          "GrabMediaPlayerKeys", NULL,
+                          G_TYPE_STRING, "Evince", G_TYPE_UINT, 0, G_TYPE_INVALID,
+                          G_TYPE_INVALID);
+
+       dbus_g_object_register_marshaller (ev_marshal_VOID__STRING_STRING,
+                                          G_TYPE_NONE, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+       dbus_g_proxy_add_signal (keys->media_player_keys_proxy, "MediaPlayerKeyPressed",
+                                G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+
+       dbus_g_proxy_connect_signal (keys->media_player_keys_proxy, "MediaPlayerKeyPressed",
+                                    G_CALLBACK (on_media_player_key_pressed), keys, NULL);
+}
+
+void
+ev_media_player_keys_focused (EvMediaPlayerKeys *keys, EvWindow *window)
+{
+       if (keys->media_player_keys_proxy != NULL) {
+               if (keys->window != NULL) {
+                       g_object_unref (keys->window);
+                       keys->window = NULL;
+               }
+               if (window != NULL) {
+                       dbus_g_proxy_call (keys->media_player_keys_proxy,
+                                          "GrabMediaPlayerKeys", NULL,
+                                          G_TYPE_STRING, "Evince", G_TYPE_UINT, 0, G_TYPE_INVALID,
+                                          G_TYPE_INVALID);
+                       keys->window = g_object_ref (window);
+               }
+       }
+}
+
+static void
+ev_media_player_keys_finalize (GObject *object)
+{
+       EvMediaPlayerKeys *keys = EV_MEDIA_PLAYER_KEYS (object);
+
+       if (keys->media_player_keys_proxy != NULL) {
+               dbus_g_proxy_call (keys->media_player_keys_proxy,
+                                  "ReleaseMediaPlayerKeys", NULL,
+                                  G_TYPE_STRING, "Ev", G_TYPE_INVALID, G_TYPE_INVALID);
+               g_object_unref (keys->media_player_keys_proxy);
+               keys->media_player_keys_proxy = NULL;
+       }
+
+       if (keys->window != NULL) {
+               g_object_unref (keys->window);
+               keys->window = NULL;
+       }
+
+       G_OBJECT_CLASS (ev_media_player_keys_parent_class)->finalize (object);
+}
+
+EvMediaPlayerKeys *
+ev_media_player_keys_new (void)
+{
+       return g_object_new (EV_TYPE_MEDIA_PLAYER_KEYS, NULL);
+}
+
diff --git a/shell/ev-media-player-keys.h b/shell/ev-media-player-keys.h
new file mode 100644 (file)
index 0000000..135aa81
--- /dev/null
@@ -0,0 +1,49 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/* 
+ * Copyright (C) 2007 Jan Arne Petersen <jap@gnome.org>
+ * Copyright (C) 2008 Bastien Nocera <hadess@hadess.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA.
+ *
+ */
+
+#ifndef EV_MEDIA_PLAYER_KEYS_H
+#define EV_MEDIA_PLAYER_KEYS_H
+
+#include "ev-window.h"
+
+G_BEGIN_DECLS
+
+#define EV_TYPE_MEDIA_PLAYER_KEYS              (ev_media_player_keys_get_type ())
+#define EV_MEDIA_PLAYER_KEYS(o)                        (G_TYPE_CHECK_INSTANCE_CAST ((o), EV_TYPE_MEDIA_PLAYER_KEYS, EvMediaPlayerKeys))
+#define EV_MEDIA_PLAYER_KEYS_CLASS(k)          (G_TYPE_CHECK_CLASS_CAST((k), EV_TYPE_MEDIA_PLAYER_KEYS, EvMediaPlayerKeysClass))
+#define EV_IS_MEDIA_PLAYER_KEYS(o)             (G_TYPE_CHECK_INSTANCE_TYPE ((o), EV_TYPE_MEDIA_PLAYER_KEYS))
+#define EV_IS_MEDIA_PLAYER_KEYS_CLASS(k)       (G_TYPE_CHECK_CLASS_TYPE ((k), EV_TYPE_MEDIA_PLAYER_KEYS))
+#define EV_MEDIA_PLAYER_KEYS_GET_CLASS(o)      (G_TYPE_INSTANCE_GET_CLASS ((o), EV_TYPE_MEDIA_PLAYER_KEYS, EvMediaPlayerKeysClass))
+
+typedef struct _EvMediaPlayerKeys EvMediaPlayerKeys;
+typedef struct _EvMediaPlayerKeysClass EvMediaPlayerKeysClass;
+
+
+GType  ev_media_player_keys_get_type           (void) G_GNUC_CONST;
+
+EvMediaPlayerKeys * ev_media_player_keys_new   (void);
+
+void ev_media_player_keys_focused              (EvMediaPlayerKeys *keys,
+                                                EvWindow *window);
+
+G_END_DECLS
+
+#endif /* !EV_MEDIA_PLAYER_KEYS_H */
index 81efe3d78b83bfc0573b79cebbcf335ac8f22d90..6849b2406795fc206dafc6323f2a56a1caa35ba3 100644 (file)
@@ -68,6 +68,9 @@
 #include "ev-message-area.h"
 #include "ev-mount-operation.h"
 #include "ev-file-monitor.h"
+#ifdef ENABLE_DBUS
+#include "ev-media-player-keys.h"
+#endif /* ENABLE_DBUS */
 
 #include <gtk/gtkprintunixdialog.h>
 
@@ -3231,6 +3234,12 @@ ev_window_cmd_go_previous_page (GtkAction *action, EvWindow *ev_window)
        ev_view_previous_page (EV_VIEW (ev_window->priv->view));
 }
 
+void
+ev_window_go_previous_page (EvWindow *ev_window)
+{
+       ev_window_cmd_go_previous_page (NULL, ev_window);
+}
+
 static void
 ev_window_cmd_go_next_page (GtkAction *action, EvWindow *ev_window)
 {
@@ -3239,6 +3248,12 @@ ev_window_cmd_go_next_page (GtkAction *action, EvWindow *ev_window)
        ev_view_next_page (EV_VIEW (ev_window->priv->view));
 }
 
+void
+ev_window_go_next_page (EvWindow *ev_window)
+{
+       ev_window_cmd_go_next_page (NULL, ev_window);
+}
+
 static void
 ev_window_cmd_go_first_page (GtkAction *action, EvWindow *ev_window)
 {
@@ -3247,6 +3262,12 @@ ev_window_cmd_go_first_page (GtkAction *action, EvWindow *ev_window)
        ev_page_cache_set_current_page (ev_window->priv->page_cache, 0);
 }
 
+void
+ev_window_go_first_page (EvWindow *ev_window)
+{
+       ev_window_cmd_go_first_page (NULL, ev_window);
+}
+
 static void
 ev_window_cmd_go_last_page (GtkAction *action, EvWindow *ev_window)
 {
@@ -3258,6 +3279,12 @@ ev_window_cmd_go_last_page (GtkAction *action, EvWindow *ev_window)
        ev_page_cache_set_current_page (ev_window->priv->page_cache, n_pages - 1);
 }
 
+void
+ev_window_go_last_page (EvWindow *ev_window)
+{
+       ev_window_cmd_go_last_page (NULL, ev_window);
+}
+
 static void
 ev_window_cmd_go_forward (GtkAction *action, EvWindow *ev_window)
 {
@@ -3358,6 +3385,12 @@ ev_window_cmd_start_presentation (GtkAction *action, EvWindow *window)
        ev_window_run_presentation (window);
 }
 
+void
+ev_window_start_presentation (EvWindow *ev_window)
+{
+       ev_window_run_presentation (ev_window);
+}
+
 static gboolean
 ev_window_enumerate_printer_cb (GtkPrinter *printer,
                                EvWindow   *window)
@@ -4101,6 +4134,15 @@ ev_window_dispose (GObject *object)
 {
        EvWindow *window = EV_WINDOW (object);
        EvWindowPrivate *priv = window->priv;
+#ifdef ENABLE_DBUS
+       GObject *keys;
+
+       keys = ev_application_get_media_keys (EV_APP);
+       if (keys) {
+               ev_media_player_keys_focused (EV_MEDIA_PLAYER_KEYS (keys), NULL);
+               g_object_unref (keys);
+       }
+#endif /* ENABLE_DBUS */
 
        if (priv->monitor) {
                g_object_unref (priv->monitor);
@@ -4624,6 +4666,16 @@ sidebar_widget_model_set (EvSidebarLinks *ev_sidebar_links,
 static gboolean
 view_actions_focus_in_cb (GtkWidget *widget, GdkEventFocus *event, EvWindow *window)
 {
+#ifdef ENABLE_DBUS
+       GObject *keys;
+
+       keys = ev_application_get_media_keys (EV_APP);
+       if (keys) {
+               ev_media_player_keys_focused (EV_MEDIA_PLAYER_KEYS (keys), window);
+               g_object_unref (keys);
+       }
+#endif /* ENABLE_DBUS */
+
        update_chrome_flag (window, EV_CHROME_RAISE_TOOLBAR, FALSE);
        ev_window_set_action_sensitive (window, "ViewToolbar", TRUE);
 
index 3680bbff91a34e1287680789654d453409b2f7b7..ebaff35a2b7b93bdcf46270cf28d8115371907b2 100644 (file)
@@ -86,6 +86,13 @@ void         ev_window_print_range     (EvWindow       *ev_window,
                                           int             first_page,
                                           int             last_page);
 
+void           ev_window_go_last_page    (EvWindow       *ev_window);
+void           ev_window_go_first_page   (EvWindow       *ev_window);
+void           ev_window_go_next_page    (EvWindow       *ev_window);
+void           ev_window_go_previous_page(EvWindow       *ev_window);
+void           ev_window_start_presentation
+                                         (EvWindow       *ev_window);
+
 G_END_DECLS
 
 #endif /* !EV_WINDOW_H */