+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:
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 \
ev-history.h \
ev-marshal.c \
ev-marshal.h \
+ $(DBUS_SOURCES) \
ev-message-area.c \
ev-message-area.h \
ev-metadata-manager.c \
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
#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>
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;
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 */
}
/**
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)
{
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);
VOID:NONE
VOID:OBJECT,OBJECT
VOID:ENUM,BOOLEAN
+VOID:STRING,STRING
--- /dev/null
+/* -*- 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);
+}
+
--- /dev/null
+/* -*- 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 */
#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>
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)
{
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)
{
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)
{
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)
{
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)
{
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);
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);
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 */