1
0
mirror of https://gitlab.gnome.org/GNOME/evince synced 2024-07-05 00:59:07 +00:00

Run evince instances in different processes instead of single instance

- When built with DBus support a daemon is used to keep track of opened
   documents and reload them when reopened.

 - Crash recovery code has been removed.

 - Metadata migration code has been moved from main.c to ev-daemon.c, so
   that it's only run once on daemon startup.

Fixes bgo#583680, bgo#434966, bgo#497388, bgo#524633 and bgo#586087.
This commit is contained in:
Carlos Garcia Campos 2009-10-19 19:27:45 +02:00
parent 3f28adc16f
commit 66e5636dca
10 changed files with 862 additions and 654 deletions

View File

@ -269,6 +269,10 @@ AC_SUBST([DBUS_LIBS])
AM_CONDITIONAL([ENABLE_DBUS], [test "$enable_dbus" = "yes"])
if test "$enable_dbus" = "yes"; then
PKG_CHECK_MODULES([EV_DAEMON], [gthread-2.0 gio-2.0 >= $GLIB_REQUIRED dbus-glib-1 >= $DBUS_GLIB_REQUIRED])
fi
dnl ========= Check for GConf
AC_MSG_CHECKING([whether GConf support is requested])
@ -339,6 +343,10 @@ FRONTEND_LIBS="$FRONTEND_CORE_LIBS -lz"
AC_SUBST(FRONTEND_CFLAGS)
AC_SUBST(FRONTEND_LIBS)
EV_DAEMON_CFLAGS="$EV_DAEMON_CFLAGS $DEBUG_FLAGS"
AC_SUBST([EV_DAEMON_CFLAGS])
AC_SUBST([EV_DAEMON_LIBS])
# Check for Nautilus property page build
AC_ARG_ENABLE([nautilus],
[AS_HELP_STRING([--disable-nautilus],[Build the nautilus extensions])],

View File

@ -36,6 +36,17 @@ DESKTOP_FILES= $(DESKTOP_IN_FILES:.desktop.in.in=.desktop)
desktopdir = $(datadir)/applications
desktop_DATA = $(DESKTOP_FILES)
#
# DBus servide file
#
if ENABLE_DBUS
servicedir = $(datadir)/dbus-1/services
service_in_files = org.gnome.evince.Daemon.service.in
service_DATA = $(service_in_files:.service.in=.service)
$(service_DATA): $(service_in_files) Makefile
@sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
endif
#
# GConf schema
@ -102,12 +113,13 @@ update-icon-cache:
# Extra files to be included in the tarball
#
EXTRA_DIST = \
$(ui_DATA) \
$(DESKTOP_IN_FILES) \
$(schema_in_files) \
$(man_MANS) \
$(NULL)
EXTRA_DIST = \
$(ui_DATA) \
$(DESKTOP_IN_FILES) \
$(schema_in_files) \
org.gnome.evince.Daemon.service.in \
$(man_MANS) \
$(NULL)
#
# Clean up properly
@ -115,4 +127,5 @@ EXTRA_DIST = \
DISTCLEANFILES = \
$(DESKTOP_FILES) \
$(schema_DATA)
$(schema_DATA) \
$(service_DATA)

View File

@ -0,0 +1,3 @@
[D-BUS Service]
Name=org.gnome.evince.Daemon
Exec=@libexecdir@/evinced

View File

@ -26,6 +26,9 @@ INCLUDES= \
bin_PROGRAMS=evince
libexec_PROGRAMS=evince-convert-metadata
if ENABLE_DBUS
libexec_PROGRAMS += evinced
endif
EV_MEDIA_PLAYER_KEYS_SOURCES = ev-media-player-keys.c ev-media-player-keys.h
if ENABLE_DBUS
@ -119,10 +122,30 @@ evince_convert_metadata_SOURCES= \
evince_convert_metadata_LDADD= \
$(SHELL_LIBS)
if ENABLE_DBUS
BUILT_SOURCES += ev-daemon-service.h
evinced_SOURCES= \
ev-daemon.c
evinced_CFLAGS= \
-DDATADIR=\"$(pkgdatadir)\" \
-DGNOMEDATADIR=\"$(datadir)\" \
-I$(top_srcdir) \
-I$(top_builddir) \
-DLIBEXECDIR=\""$(libexecdir)"\" \
-DEVINCE_COMPILATION \
$(EV_DAEMON_CFLAGS) \
$(WARN_CFLAGS) \
$(DISABLE_DEPRECATED)
evinced_LDADD= \
$(EV_DAEMON_LIBS)
endif
EXTRA_DIST = ev-marshal.list \
ev-application-service.xml \
ev-daemon-service.xml \
$(EV_MEDIA_PLAYER_KEYS_SOURCES)
@ -133,8 +156,12 @@ ev-marshal.c: $(srcdir)/ev-marshal.list
echo '#include "ev-marshal.h"' > ev-marshal.c
$(AM_V_GEN)$(GLIB_GENMARSHAL) --prefix=ev_marshal $(srcdir)/ev-marshal.list --body >> ev-marshal.c
DISTCLEANFILES= \
ev-application-service.h
DISTCLEANFILES= \
ev-application-service.h \
ev-daemon-service.h
ev-application-service.h: $(srcdir)/ev-application-service.xml
$(AM_V_GEN)dbus-binding-tool --prefix=ev_application --mode=glib-server --output=ev-application-service.h $(srcdir)/ev-application-service.xml
ev-daemon-service.h: $(srcdir)/ev-daemon-service.xml
$(AM_V_GEN)dbus-binding-tool --prefix=ev_daemon --mode=glib-server --output=ev-daemon-service.h $(srcdir)/ev-daemon-service.xml

View File

@ -5,12 +5,6 @@
<interface name="org.gnome.evince.Application">
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="ev_application"/>
<method name="OpenWindow">
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="ev_application_open_window"/>
<arg type="a{sv}" name="args" direction="in"/>
<arg type="u" name="timestamp" direction="in"/>
</method>
<method name="OpenURI">
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="ev_application_open_uri"/>
<arg type="s" name="uri" direction="in"/>

View File

@ -50,6 +50,11 @@
#ifdef ENABLE_DBUS
#include <dbus/dbus-glib-bindings.h>
static gboolean ev_application_open_uri (EvApplication *application,
const char *uri,
GHashTable *args,
guint timestamp,
GError **error);
#include "ev-application-service.h"
#endif
@ -64,8 +69,9 @@ struct _EvApplication {
gchar *toolbars_file;
#ifdef ENABLE_DBUS
gchar *crashed_file;
guint crashed_idle;
DBusGConnection *connection;
GHashTable *windows;
guint doc_counter;
#endif
EggToolbarsModel *toolbars_model;
@ -96,65 +102,15 @@ static EvApplication *instance;
G_DEFINE_TYPE (EvApplication, ev_application, G_TYPE_OBJECT);
#define APPLICATION_SERVICE_NAME "org.gnome.evince.ApplicationService"
#ifdef ENABLE_DBUS
#define APPLICATION_DBUS_OBJECT_PATH "/org/gnome/evince/Evince"
#define APPLICATION_DBUS_INTERFACE "org.gnome.evince.Application"
#endif
#define EV_PRINT_SETTINGS_FILE "print-settings"
#define EV_PRINT_SETTINGS_GROUP "Print Settings"
#define EV_PAGE_SETUP_GROUP "Page Setup"
#ifdef ENABLE_DBUS
gboolean
ev_application_register_service (EvApplication *application)
{
static DBusGConnection *connection = NULL;
DBusGProxy *driver_proxy;
GError *err = NULL;
guint request_name_result;
if (connection) {
g_warning ("Service already registered.");
return FALSE;
}
connection = dbus_g_bus_get (DBUS_BUS_STARTER, &err);
if (connection == NULL) {
g_warning ("Service registration failed.");
g_error_free (err);
return FALSE;
}
driver_proxy = dbus_g_proxy_new_for_name (connection,
DBUS_SERVICE_DBUS,
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS);
if (!org_freedesktop_DBus_request_name (driver_proxy,
APPLICATION_SERVICE_NAME,
DBUS_NAME_FLAG_DO_NOT_QUEUE,
&request_name_result, &err)) {
g_warning ("Service registration failed.");
g_clear_error (&err);
}
g_object_unref (driver_proxy);
if (request_name_result == DBUS_REQUEST_NAME_REPLY_EXISTS) {
return FALSE;
}
dbus_g_object_type_install_info (EV_TYPE_APPLICATION,
&dbus_glib_ev_application_object_info);
dbus_g_connection_register_g_object (connection,
"/org/gnome/evince/Evince",
G_OBJECT (application));
application->scr_saver = totem_scrsaver_new (connection);
return TRUE;
}
#endif /* ENABLE_DBUS */
/**
* ev_application_get_instance:
*
@ -172,8 +128,7 @@ ev_application_get_instance (void)
return instance;
}
#if defined (WITH_SMCLIENT) || defined (ENABLE_DBUS)
#if defined (WITH_SMCLIENT)
/* Session */
static void
save_session (EvApplication *application,
@ -202,173 +157,7 @@ save_session (EvApplication *application,
g_free (uri_list);
}
#endif /* WITH_SMCLIENT || ENABLE_DBUS */
#ifdef ENABLE_DBUS
static void
ev_application_save_session_crashed (EvApplication *application)
{
GList *windows;
windows = ev_application_get_windows (application);
if (windows) {
GKeyFile *crashed_file;
gchar *data;
gssize data_length;
GError *error = NULL;
crashed_file = g_key_file_new ();
save_session (application, windows, crashed_file);
data = g_key_file_to_data (crashed_file, (gsize *)&data_length, NULL);
g_file_set_contents (application->crashed_file, data, data_length, &error);
if (error) {
g_warning ("%s", error->message);
g_error_free (error);
}
g_free (data);
g_key_file_free (crashed_file);
} else if (g_file_test (application->crashed_file, G_FILE_TEST_IS_REGULAR)) {
GFile *file;
file = g_file_new_for_path (application->crashed_file);
g_file_delete (file, NULL, NULL);
g_object_unref (file);
}
}
static gboolean
save_session_crashed_in_idle_cb (EvApplication *application)
{
ev_application_save_session_crashed (application);
application->crashed_idle = 0;
return FALSE;
}
static void
save_session_crashed_in_idle (EvApplication *application)
{
if (application->crashed_idle > 0)
g_source_remove (application->crashed_idle);
application->crashed_idle =
g_idle_add ((GSourceFunc)save_session_crashed_in_idle_cb,
application);
}
static gboolean
ev_application_run_crash_recovery_dialog (EvApplication *application)
{
GtkWidget *dialog;
gint response;
dialog = gtk_message_dialog_new (NULL,
GTK_DIALOG_MODAL,
GTK_MESSAGE_WARNING,
GTK_BUTTONS_NONE,
_("Recover previous documents?"));
gtk_message_dialog_format_secondary_text (
GTK_MESSAGE_DIALOG (dialog),
_("Evince appears to have exited unexpectedly the last time "
"it was run. You can recover the opened documents."));
gtk_dialog_add_button (GTK_DIALOG (dialog),
_("_Don't Recover"),
GTK_RESPONSE_CANCEL);
gtk_dialog_add_button (GTK_DIALOG (dialog),
_("_Recover"),
GTK_RESPONSE_ACCEPT);
gtk_window_set_title (GTK_WINDOW (dialog), _("Crash Recovery"));
gtk_window_set_icon_name (GTK_WINDOW (dialog), "evince");
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), FALSE);
gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
response = gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
return response == GTK_RESPONSE_ACCEPT;
}
static gboolean
is_in_command_line (GFile *file,
const gchar **files)
{
gint i;
if (!files)
return FALSE;
for (i = 0; files[i]; i++) {
GFile *cfile;
cfile = g_file_new_for_commandline_arg (files[i]);
if (g_file_equal (cfile, file)) {
g_object_unref (cfile);
return TRUE;
}
g_object_unref (cfile);
}
return FALSE;
}
static GKeyFile *
ev_application_get_files_to_recover (EvApplication *application,
const gchar **files)
{
GKeyFile *state_file;
gchar **uri_list;
gchar **dest_list = NULL;
gint i, j;
state_file = g_key_file_new ();
g_key_file_load_from_file (state_file,
application->crashed_file,
G_KEY_FILE_NONE,
NULL);
uri_list = g_key_file_get_string_list (state_file,
"Evince",
"documents",
NULL, NULL);
if (!uri_list) {
g_key_file_free (state_file);
return NULL;
}
for (i = 0, j = 0; uri_list[i]; i++) {
GFile *file = g_file_new_for_uri (uri_list[i]);
if (!g_file_query_exists (file, NULL) ||
is_in_command_line (file, files)) {
g_object_unref (file);
continue;
}
if (!dest_list)
dest_list = g_new (gchar *, g_strv_length (uri_list) - i);
dest_list[j++] = uri_list[i];
}
if (j > 0) {
g_key_file_set_string_list (state_file,
"Evince",
"documents",
(const gchar **)dest_list,
j);
} else {
g_key_file_free (state_file);
state_file = NULL;
}
g_free (dest_list);
g_strfreev (uri_list);
return state_file;
}
#endif /* ENABLE_DBUS */
#endif /* WITH_SMCLIENT */
gboolean
ev_application_load_session (EvApplication *application,
@ -384,18 +173,6 @@ ev_application_load_session (EvApplication *application,
return FALSE;
} else
#endif /* WITH_SMCLIENT */
#ifdef ENABLE_DBUS
if (g_file_test (application->crashed_file, G_FILE_TEST_IS_REGULAR)) {
state_file = ev_application_get_files_to_recover (application, files);
if (!state_file)
return FALSE;
if (!ev_application_run_crash_recovery_dialog (application)) {
g_key_file_free (state_file);
return FALSE;
}
} else
#endif /* ENABLE_DBUS */
return FALSE;
uri_list = g_key_file_get_string_list (state_file,
@ -404,12 +181,14 @@ ev_application_load_session (EvApplication *application,
NULL, NULL);
if (uri_list) {
gint i;
GdkScreen *screen = gdk_screen_get_default ();
for (i = 0; uri_list[i]; i++) {
if (g_ascii_strcasecmp (uri_list[i], "empty-window") == 0)
ev_application_open_window (application, NULL, GDK_CURRENT_TIME, NULL);
ev_application_open_window (application, screen, GDK_CURRENT_TIME);
else
ev_application_open_uri (application, uri_list[i], NULL, GDK_CURRENT_TIME, NULL);
ev_application_open_uri_at_dest (application, uri_list[i], screen,
NULL, 0, NULL, GDK_CURRENT_TIME);
}
g_strfreev (uri_list);
}
@ -446,11 +225,6 @@ smclient_quit_cb (EggSMClient *client,
static void
ev_application_init_session (EvApplication *application)
{
#ifdef ENABLE_DBUS
application->crashed_file = g_build_filename (application->dot_dir,
"evince-crashed", NULL);
#endif
#ifdef WITH_SMCLIENT
application->smclient = egg_sm_client_get ();
g_signal_connect (application->smclient, "save_state",
@ -600,58 +374,106 @@ get_find_string_from_args (GHashTable *args)
return value ? g_value_get_string (value) : NULL;
}
static void
value_free (GValue *value)
{
g_value_unset (value);
g_free (value);
}
static GHashTable *
build_args (GdkScreen *screen,
EvLinkDest *dest,
EvWindowRunMode mode,
const gchar *search_string)
{
GHashTable *args;
GValue *value;
GdkDisplay *display;
const gchar *display_name;
gint screen_number;
args = g_hash_table_new_full (g_str_hash,
g_str_equal,
(GDestroyNotify)g_free,
(GDestroyNotify)value_free);
/* Display */
display = gdk_screen_get_display (screen);
display_name = gdk_display_get_name (display);
value = g_new0 (GValue, 1);
g_value_init (value, G_TYPE_STRING);
g_value_set_string (value, display_name);
g_hash_table_insert (args, g_strdup ("display"), value);
/* Screen */
screen_number = gdk_screen_get_number (screen);
value = g_new0 (GValue, 1);
g_value_init (value, G_TYPE_INT);
g_value_set_int (value, screen_number);
g_hash_table_insert (args, g_strdup ("screen"), value);
/* Page label */
if (dest) {
value = g_new0 (GValue, 1);
g_value_init (value, G_TYPE_STRING);
g_value_set_string (value, ev_link_dest_get_page_label (dest));
g_hash_table_insert (args, g_strdup ("page-label"), value);
}
/* Find string */
if (search_string) {
value = g_new0 (GValue, 1);
g_value_init (value, G_TYPE_STRING);
g_value_set_string (value, search_string);
g_hash_table_insert (args, g_strdup ("find-string"), value);
}
/* Mode */
if (mode != EV_WINDOW_MODE_NORMAL) {
value = g_new0 (GValue, 1);
g_value_init (value, G_TYPE_UINT);
g_value_set_uint (value, mode);
g_hash_table_insert (args, g_strdup ("mode"), value);
}
return args;
}
/**
* ev_application_open_window:
* @application: The instance of the application.
* @args: A #GHashTable with the arguments data.
* @timestamp: Current time value.
* @error: The #GError facility.
*
* Creates a new window and if the args are available, it's not NULL, it gets
* the screen from them and assigns the just created window to it. At last it
* does show it.
*
* Returns: %TRUE.
* Creates a new window
*/
gboolean
ev_application_open_window (EvApplication *application,
GHashTable *args,
guint32 timestamp,
GError **error)
void
ev_application_open_window (EvApplication *application,
GdkScreen *screen,
guint32 timestamp)
{
GtkWidget *new_window = ev_window_new ();
GdkScreen *screen = NULL;
if (args) {
screen = get_screen_from_args (args);
}
if (screen) {
ev_stock_icons_set_screen (screen);
gtk_window_set_screen (GTK_WINDOW (new_window), screen);
}
#ifdef ENABLE_DBUS
ev_application_save_session_crashed (application);
g_signal_connect_swapped (new_window, "destroy",
G_CALLBACK (save_session_crashed_in_idle),
application);
#endif
if (!GTK_WIDGET_REALIZED (new_window))
gtk_widget_realize (new_window);
#ifdef GDK_WINDOWING_X11
if (timestamp <= 0)
timestamp = gdk_x11_get_server_time (GTK_WIDGET (new_window)->window);
gdk_x11_window_set_user_time (GTK_WIDGET (new_window)->window, timestamp);
gtk_window_present (GTK_WINDOW (new_window));
#else
gtk_window_present_with_time (GTK_WINDOW (new_window), timestamp);
#endif /* GDK_WINDOWING_X11 */
return TRUE;
}
/**
@ -725,6 +547,152 @@ ev_application_get_uri_window (EvApplication *application, const char *uri)
return uri_window;
}
#ifdef ENABLE_DBUS
static gboolean
ev_application_register_uri (EvApplication *application,
const gchar *uri,
GHashTable *args,
guint timestamp)
{
DBusGProxy *proxy;
gchar *owner;
gboolean retval = TRUE;
GError *error = NULL;
if (!application->connection)
return TRUE;
proxy = dbus_g_proxy_new_for_name (application->connection,
"org.gnome.evince.Daemon",
"/org/gnome/evince/Daemon",
"org.gnome.evince.Daemon");
if (!dbus_g_proxy_call (proxy, "RegisterDocument", &error,
G_TYPE_STRING, uri,
G_TYPE_INVALID,
G_TYPE_STRING, &owner,
G_TYPE_INVALID)) {
g_warning ("Error registering document: %s\n", error->message);
g_error_free (error);
g_object_unref (proxy);
return TRUE;
}
g_object_unref (proxy);
if (*owner == ':') {
/* Already registered */
proxy = dbus_g_proxy_new_for_name_owner (application->connection,
owner,
APPLICATION_DBUS_OBJECT_PATH,
APPLICATION_DBUS_INTERFACE,
&error);
if (proxy) {
if (!dbus_g_proxy_call (proxy, "OpenURI", &error,
G_TYPE_STRING, uri,
dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), args,
G_TYPE_UINT, timestamp,
G_TYPE_INVALID,
G_TYPE_INVALID)) {
g_warning ("%s", error->message);
g_error_free (error);
}
g_object_unref (proxy);
} else {
g_warning ("Error creating proxy: %s\n", error->message);
g_error_free (error);
}
/* Do not continue opening this document */
retval = FALSE;
}
g_free (owner);
return retval;
}
static void
ev_application_unregister_uri (EvApplication *application,
const gchar *uri)
{
DBusGProxy *proxy;
GError *error = NULL;
if (!application->connection)
return;
proxy = dbus_g_proxy_new_for_name (application->connection,
"org.gnome.evince.Daemon",
"/org/gnome/evince/Daemon",
"org.gnome.evince.Daemon");
if (!dbus_g_proxy_call (proxy, "UnregisterDocument", &error,
G_TYPE_STRING, uri,
G_TYPE_INVALID,
G_TYPE_INVALID)) {
g_warning ("Error unregistering document: %s\n", error->message);
g_error_free (error);
}
g_object_unref (proxy);
}
static void
ev_application_window_destroyed (EvApplication *application,
EvWindow *ev_window)
{
gchar *uri = g_hash_table_lookup (application->windows, ev_window);
ev_application_unregister_uri (application, uri);
g_hash_table_remove (application->windows, ev_window);
}
#endif /* ENABLE_DBUS */
static void
ev_application_open_uri_in_window (EvApplication *application,
const char *uri,
EvWindow *ev_window,
GdkScreen *screen,
EvLinkDest *dest,
EvWindowRunMode mode,
const gchar *search_string,
guint timestamp)
{
if (screen) {
ev_stock_icons_set_screen (screen);
gtk_window_set_screen (GTK_WINDOW (ev_window), screen);
}
/* We need to load uri before showing the window, so
we can restore window size without flickering */
ev_window_open_uri (ev_window, uri, dest, mode, search_string);
#ifdef ENABLE_DBUS
if (!g_hash_table_lookup (application->windows, ev_window)) {
g_hash_table_insert (application->windows, ev_window, g_strdup (uri));
g_signal_connect_swapped (ev_window, "destroy",
G_CALLBACK (ev_application_window_destroyed),
application);
}
#endif
if (!GTK_WIDGET_REALIZED (GTK_WIDGET (ev_window)))
gtk_widget_realize (GTK_WIDGET (ev_window));
#ifdef GDK_WINDOWING_X11
if (timestamp <= 0)
timestamp = gdk_x11_get_server_time (GTK_WIDGET (ev_window)->window);
gdk_x11_window_set_user_time (GTK_WIDGET (ev_window)->window, timestamp);
ev_document_fc_mutex_lock ();
gtk_window_present (GTK_WINDOW (ev_window));
ev_document_fc_mutex_unlock ();
#else
ev_document_fc_mutex_lock ();
gtk_window_present_with_time (GTK_WINDOW (ev_window), timestamp);
ev_document_fc_mutex_unlock ();
#endif /* GDK_WINDOWING_X11 */
}
/**
* ev_application_open_uri_at_dest:
* @application: The instance of the application.
@ -743,52 +711,37 @@ ev_application_open_uri_at_dest (EvApplication *application,
const gchar *search_string,
guint timestamp)
{
EvWindow *new_window;
EvWindow *ev_window;
g_return_if_fail (uri != NULL);
new_window = ev_application_get_uri_window (application, uri);
if (new_window == NULL) {
new_window = ev_application_get_empty_window (application, screen);
}
if (new_window == NULL) {
new_window = EV_WINDOW (ev_window_new ());
}
if (screen) {
ev_stock_icons_set_screen (screen);
gtk_window_set_screen (GTK_WINDOW (new_window), screen);
}
/* We need to load uri before showing the window, so
we can restore window size without flickering */
ev_window_open_uri (new_window, uri, dest, mode, search_string);
ev_window = ev_application_get_uri_window (application, uri);
#ifdef ENABLE_DBUS
ev_application_save_session_crashed (application);
g_signal_connect_swapped (new_window, "destroy",
G_CALLBACK (save_session_crashed_in_idle),
application);
#endif
if (!ev_window) {
GHashTable *args = build_args (screen, dest, mode, search_string);
gboolean ret;
if (!GTK_WIDGET_REALIZED (GTK_WIDGET (new_window)))
gtk_widget_realize (GTK_WIDGET (new_window));
/* Register the uri or send OpenURI to
* remote instance if already registered
*/
ret = ev_application_register_uri (application, uri, args, timestamp);
g_hash_table_destroy (args);
if (!ret)
return;
}
#endif /* ENABLE_DBUS */
#ifdef GDK_WINDOWING_X11
if (timestamp <= 0)
timestamp = gdk_x11_get_server_time (GTK_WIDGET (new_window)->window);
gdk_x11_window_set_user_time (GTK_WIDGET (new_window)->window, timestamp);
if (ev_window == NULL) {
ev_window = ev_application_get_empty_window (application, screen);
}
ev_document_fc_mutex_lock ();
gtk_window_present (GTK_WINDOW (new_window));
ev_document_fc_mutex_unlock ();
#else
ev_document_fc_mutex_lock ();
gtk_window_present_with_time (GTK_WINDOW (new_window), timestamp);
ev_document_fc_mutex_unlock ();
#endif /* GDK_WINDOWING_X11 */
if (ev_window == NULL) {
ev_window = EV_WINDOW (ev_window_new ());
}
ev_application_open_uri_in_window (application, uri, ev_window,
screen, dest, mode, search_string,
timestamp);
}
/**
@ -799,28 +752,32 @@ ev_application_open_uri_at_dest (EvApplication *application,
* @timestamp: Current time value.
* @error: The #GError facility.
*/
gboolean
static gboolean
ev_application_open_uri (EvApplication *application,
const char *uri,
GHashTable *args,
guint timestamp,
GError **error)
{
EvWindow *ev_window;
EvLinkDest *dest = NULL;
EvWindowRunMode mode = EV_WINDOW_MODE_NORMAL;
const gchar *search_string = NULL;
GdkScreen *screen = NULL;
ev_window = ev_application_get_uri_window (application, uri);
g_assert (ev_window != NULL);
if (args) {
screen = get_screen_from_args (args);
dest = get_destination_from_args (args);
mode = get_window_run_mode_from_args (args);
search_string = get_find_string_from_args (args);
}
ev_application_open_uri_at_dest (application, uri, screen,
dest, mode, search_string,
timestamp);
ev_application_open_uri_in_window (application, uri, ev_window,
screen, dest, mode, search_string,
timestamp);
if (dest)
g_object_unref (dest);
@ -847,10 +804,9 @@ void
ev_application_shutdown (EvApplication *application)
{
#ifdef ENABLE_DBUS
if (application->crashed_file) {
ev_application_save_session_crashed (application);
g_free (application->crashed_file);
application->crashed_file = NULL;
if (application->windows) {
g_hash_table_destroy (application->windows);
application->windows = NULL;
}
#endif
@ -909,6 +865,10 @@ ev_application_shutdown (EvApplication *application)
static void
ev_application_class_init (EvApplicationClass *ev_application_class)
{
#ifdef ENABLE_DBUS
dbus_g_object_type_install_info (EV_TYPE_APPLICATION,
&dbus_glib_ev_application_object_info);
#endif
}
static void
@ -917,6 +877,7 @@ ev_application_init (EvApplication *ev_application)
gint i;
const gchar *home_dir;
gchar *toolbar_path;
GError *error = NULL;
ev_application->dot_dir = g_build_filename (g_get_home_dir (),
".gnome2",
@ -988,6 +949,20 @@ ev_application_init (EvApplication *ev_application)
EGG_TB_MODEL_NOT_REMOVABLE);
#ifdef ENABLE_DBUS
ev_application->connection = dbus_g_bus_get (DBUS_BUS_STARTER, &error);
if (ev_application->connection) {
dbus_g_connection_register_g_object (ev_application->connection,
APPLICATION_DBUS_OBJECT_PATH,
G_OBJECT (ev_application));
ev_application->windows = g_hash_table_new_full (g_direct_hash,
g_direct_equal,
NULL,
(GDestroyNotify)g_free);
ev_application->scr_saver = totem_scrsaver_new (ev_application->connection);
} else {
g_warning ("Error connection to DBus: %s\n", error->message);
g_error_free (error);
}
ev_application->keys = ev_media_player_keys_new ();
#endif /* ENABLE_DBUS */
}

View File

@ -55,15 +55,9 @@ void ev_application_shutdown (EvApplication *application);
gboolean ev_application_load_session (EvApplication *application,
const gchar **files);
gboolean ev_application_open_window (EvApplication *application,
GHashTable *args,
guint32 timestamp,
GError **error);
gboolean ev_application_open_uri (EvApplication *application,
const char *uri,
GHashTable *args,
guint timestamp,
GError **error);
void ev_application_open_window (EvApplication *application,
GdkScreen *screen,
guint32 timestamp);
void ev_application_open_uri_at_dest (EvApplication *application,
const char *uri,
GdkScreen *screen,
@ -94,7 +88,7 @@ GtkPageSetup *ev_application_get_page_setup (EvApplication *applicati
void ev_application_set_page_setup (EvApplication *application,
GtkPageSetup *page_setup);
const gchar *ev_application_get_dot_dir (EvApplication *application);
const gchar *ev_application_get_data_dir (EvApplication *application);
const gchar *ev_application_get_data_dir (EvApplication *application);
G_END_DECLS

View File

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8" ?>
<node name="/org/gnome/evince/Daemon">
<interface name="org.gnome.evince.Daemon">
<annotation name="org.freedesktop.DBus.GLib.CSymbol" value="ev_daemon"/>
<method name="RegisterDocument">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg type="s" name="uri" direction="in"/>
<arg type="s" name="owner" direction="out"/>
</method>
<method name="UnregisterDocument">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg type="s" name="uri" direction="in"/>
</method>
</interface>
</node>

442
shell/ev-daemon.c Normal file
View File

@ -0,0 +1,442 @@
/* ev-metadata.c
* this file is part of evince, a gnome document viewer
*
* Copyright (C) 2009 Carlos Garcia Campos <carlosgc@gnome.org>
*
* Evince 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.
*
* Evince 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
*/
#include "config.h"
#include <glib.h>
#include <glib/gstdio.h>
#include <gio/gio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <dbus/dbus-glib-bindings.h>
#include <dbus/dbus-glib-lowlevel.h>
#define EV_DBUS_DAEMON_NAME "org.gnome.evince.Daemon"
#define EV_DBUS_DAEMON_OBJECT_PATH "/org/gnome/evince/Daemon"
#define EV_TYPE_DAEMON (ev_daemon_get_type ())
#define EV_DAEMON(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_DAEMON, EvDaemon))
#define EV_DAEMON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_DAEMON, EvDaemonClass))
#define EV_IS_DAEMON(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_DAEMON))
typedef struct _EvDaemon EvDaemon;
typedef struct _EvDaemonClass EvDaemonClass;
struct _EvDaemon {
GObject base;
DBusGProxy *bus_proxy;
GList *docs;
guint n_docs;
guint timer_id;
};
struct _EvDaemonClass {
GObjectClass base_class;
};
static GType ev_daemon_get_type (void) G_GNUC_CONST;
static gboolean ev_daemon_register_document (EvDaemon *ev_daemon,
const gchar *uri,
DBusGMethodInvocation *context);
static gboolean ev_daemon_unregister_document (EvDaemon *ev_daemon,
const gchar *uri,
DBusGMethodInvocation *context);
#include "ev-daemon-service.h"
static EvDaemon *ev_daemon = NULL;
G_DEFINE_TYPE(EvDaemon, ev_daemon, G_TYPE_OBJECT)
typedef struct {
gchar *dbus_name;
gchar *uri;
} EvDoc;
static void
ev_doc_free (EvDoc *doc)
{
if (!doc)
return;
g_free (doc->dbus_name);
g_free (doc->uri);
g_free (doc);
}
static EvDoc *
ev_daemon_find_doc (EvDaemon *ev_daemon,
const gchar *uri)
{
GList *l;
for (l = ev_daemon->docs; l; l = g_list_next (l)) {
EvDoc *doc = (EvDoc *)l->data;
if (strcmp (doc->uri, uri) == 0)
return doc;
}
return NULL;
}
static void
ev_daemon_finalize (GObject *object)
{
EvDaemon *ev_daemon = EV_DAEMON (object);
if (ev_daemon->docs) {
g_list_foreach (ev_daemon->docs, (GFunc)ev_doc_free, NULL);
g_list_free (ev_daemon->docs);
ev_daemon->docs = NULL;
}
if (ev_daemon->bus_proxy) {
g_object_unref (ev_daemon->bus_proxy);
ev_daemon->bus_proxy = NULL;
}
G_OBJECT_CLASS (ev_daemon_parent_class)->finalize (object);
}
static void
ev_daemon_init (EvDaemon *ev_daemon)
{
}
static void
ev_daemon_class_init (EvDaemonClass *klass)
{
GObjectClass *g_object_class = G_OBJECT_CLASS (klass);
g_object_class->finalize = ev_daemon_finalize;
dbus_g_object_type_install_info (EV_TYPE_DAEMON,
&dbus_glib_ev_daemon_object_info);
}
static gboolean
ev_daemon_shutdown (EvDaemon *ev_daemon)
{
g_object_unref (ev_daemon);
return FALSE;
}
static void
ev_daemon_stop_killtimer (EvDaemon *ev_daemon)
{
if (ev_daemon->timer_id > 0)
g_source_remove (ev_daemon->timer_id);
ev_daemon->timer_id = 0;
}
static void
ev_daemon_start_killtimer (EvDaemon *ev_daemon)
{
ev_daemon_stop_killtimer (ev_daemon);
ev_daemon->timer_id =
g_timeout_add_seconds (30,
(GSourceFunc) ev_daemon_shutdown,
ev_daemon);
}
static void
ev_daemon_name_owner_changed (DBusGProxy *proxy,
const gchar *name,
const gchar *old_owner,
const gchar *new_owner,
EvDaemon *ev_daemon)
{
GList *l, *next = NULL;
if (*name == ':' && *new_owner == '\0') {
for (l = ev_daemon->docs; l; l = next) {
EvDoc *doc = (EvDoc *)l->data;
next = l->next;
if (strcmp (doc->dbus_name, name) == 0) {
ev_doc_free (doc);
ev_daemon->docs = g_list_delete_link (ev_daemon->docs, l);
if (--ev_daemon->n_docs == 0)
ev_daemon_start_killtimer (ev_daemon);
}
}
}
}
static EvDaemon *
ev_daemon_get (void)
{
DBusGConnection *connection;
guint request_name_result;
GError *error = NULL;
if (ev_daemon)
return ev_daemon;
connection = dbus_g_bus_get (DBUS_BUS_STARTER, &error);
if (!connection) {
g_printerr ("Failed to connect to the D-BUS daemon: %s\n", error->message);
g_error_free (error);
return NULL;
}
ev_daemon = g_object_new (EV_TYPE_DAEMON, NULL);
ev_daemon->bus_proxy = dbus_g_proxy_new_for_name (connection,
DBUS_SERVICE_DBUS,
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS);
if (!org_freedesktop_DBus_request_name (ev_daemon->bus_proxy,
EV_DBUS_DAEMON_NAME,
DBUS_NAME_FLAG_DO_NOT_QUEUE,
&request_name_result, &error)) {
g_printerr ("Failed to acquire daemon name: %s", error->message);
g_error_free (error);
g_object_unref (ev_daemon);
return NULL;
}
switch (request_name_result) {
case DBUS_REQUEST_NAME_REPLY_EXISTS:
g_printerr ("Evince daemon already running, exiting.\n");
g_object_unref (ev_daemon);
return NULL;
case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
dbus_g_connection_register_g_object (connection,
EV_DBUS_DAEMON_OBJECT_PATH,
G_OBJECT (ev_daemon));
break;
default:
g_printerr ("Not primary owner of the service, exiting.\n");
g_object_unref (ev_daemon);
return NULL;
}
dbus_g_proxy_add_signal (ev_daemon->bus_proxy,
"NameOwnerChanged",
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_INVALID);
dbus_g_proxy_connect_signal (ev_daemon->bus_proxy, "NameOwnerChanged",
G_CALLBACK (ev_daemon_name_owner_changed),
ev_daemon, NULL);
ev_daemon_start_killtimer (ev_daemon);
return ev_daemon;
}
static gboolean
ev_daemon_register_document (EvDaemon *ev_daemon,
const gchar *uri,
DBusGMethodInvocation *method)
{
EvDoc *doc;
const gchar *owner = NULL;
doc = ev_daemon_find_doc (ev_daemon, uri);
if (doc) {
/* Already registered */
owner = doc->dbus_name;
} else {
doc = g_new (EvDoc, 1);
doc->dbus_name = dbus_g_method_get_sender (method);
doc->uri = g_strdup (uri);
ev_daemon->docs = g_list_prepend (ev_daemon->docs, doc);
if (ev_daemon->n_docs++ == 0)
ev_daemon_stop_killtimer (ev_daemon);
}
dbus_g_method_return (method, owner);
return TRUE;
}
static gboolean
ev_daemon_unregister_document (EvDaemon *ev_daemon,
const gchar *uri,
DBusGMethodInvocation *method)
{
EvDoc *doc;
gchar *sender;
doc = ev_daemon_find_doc (ev_daemon, uri);
if (!doc) {
g_warning ("Document %s is not registered\n", uri);
dbus_g_method_return (method);
return TRUE;
}
sender = dbus_g_method_get_sender (method);
if (strcmp (doc->dbus_name, sender) != 0) {
g_warning ("Failed to unregister document %s: invalid owner %s, expected %s\n",
uri, sender, doc->dbus_name);
g_free (sender);
dbus_g_method_return (method);
return TRUE;
}
g_free (sender);
ev_daemon->docs = g_list_remove (ev_daemon->docs, doc);
ev_doc_free (doc);
if (--ev_daemon->n_docs == 0)
ev_daemon_start_killtimer (ev_daemon);
dbus_g_method_return (method);
return TRUE;
}
static void
do_exit (GMainLoop *loop,
GObject *object)
{
if (g_main_loop_is_running (loop))
g_main_loop_quit (loop);
}
static gboolean
convert_metadata (const gchar *metadata)
{
GFile *file;
gchar *cmd;
gint exit_status;
GFileAttributeInfoList *namespaces;
gboolean supported = FALSE;
GError *error = NULL;
gboolean retval;
/* If metadata is not supported for a local file
* is likely because and old gvfs version is running.
*/
file = g_file_new_for_path (metadata);
namespaces = g_file_query_writable_namespaces (file, NULL, NULL);
if (namespaces) {
gint i;
for (i = 0; i < namespaces->n_infos; i++) {
if (strcmp (namespaces->infos[i].name, "metadata") == 0) {
supported = TRUE;
break;
}
}
g_file_attribute_info_list_unref (namespaces);
}
if (!supported) {
g_warning ("%s\n",
"GVFS metadata not supported, "
"Evince will run without metadata support");
g_object_unref (file);
return FALSE;
}
g_object_unref (file);
cmd = g_strdup_printf ("%s %s", LIBEXECDIR"/evince-convert-metadata", metadata);
retval = g_spawn_command_line_sync (cmd, NULL, NULL, &exit_status, &error);
g_free (cmd);
if (!retval) {
g_printerr ("Error migrating metadata: %s\n", error->message);
g_error_free (error);
}
return retval && exit_status == 0;
}
static void
ev_migrate_metadata (void)
{
gchar *updated;
gchar *metadata;
gchar *dot_dir;
dot_dir = g_build_filename (g_get_home_dir (),
".gnome2",
"evince",
NULL);
updated = g_build_filename (dot_dir, "migrated-to-gvfs", NULL);
if (g_file_test (updated, G_FILE_TEST_EXISTS)) {
/* Already migrated */
g_free (updated);
g_free (dot_dir);
return;
}
metadata = g_build_filename (dot_dir, "ev-metadata.xml", NULL);
if (g_file_test (metadata, G_FILE_TEST_EXISTS)) {
if (convert_metadata (metadata)) {
gint fd;
fd = g_creat (updated, 0600);
if (fd != -1) {
close (fd);
}
}
}
g_free (dot_dir);
g_free (updated);
g_free (metadata);
}
gint
main (gint argc, gchar **argv)
{
GMainLoop *loop;
/* Init glib threads asap */
if (!g_thread_supported ())
g_thread_init (NULL);
g_type_init ();
if (!ev_daemon_get ())
return 1;
ev_migrate_metadata ();
loop = g_main_loop_new (NULL, FALSE);
g_object_weak_ref (G_OBJECT (ev_daemon),
(GWeakNotify) do_exit,
loop);
g_main_loop_run (loop);
g_main_loop_unref (loop);
return 0;
}

View File

@ -26,20 +26,7 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#ifndef G_OS_WIN32
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#endif
#ifdef ENABLE_DBUS
#include <gdk/gdkx.h>
#include <dbus/dbus-glib-bindings.h>
#endif
#include "ev-application.h"
#include "ev-backends-manager.h"
#include "ev-debug.h"
#include "ev-init.h"
#include "ev-file-helpers.h"
@ -154,167 +141,6 @@ launch_previewer (void)
return retval;
}
#ifndef G_OS_WIN32
static gboolean
convert_metadata (const gchar *metadata)
{
GFile *file;
gchar *cmd;
gint exit_status;
GError *error = NULL;
gboolean retval;
/* If metadata is not supported for a local file
* is likely because and old gvfs version is running.
*/
file = g_file_new_for_path (metadata);
if (!ev_is_metadata_supported_for_file (file)) {
g_warning ("%s\n",
"GVFS metadata not supported, "
"Evince will run without metadata support");
g_object_unref (file);
return FALSE;
}
g_object_unref (file);
cmd = g_strdup_printf ("%s %s", LIBEXECDIR"/evince-convert-metadata", metadata);
retval = g_spawn_command_line_sync (cmd, NULL, NULL, &exit_status, &error);
g_free (cmd);
if (!retval) {
g_printerr ("Error migrating metadata: %s\n", error->message);
g_error_free (error);
}
return retval && exit_status == 0;
}
static void
ev_migrate_metadata (void)
{
gchar *updated;
gchar *metadata;
updated = g_build_filename (ev_application_get_dot_dir (EV_APP),
"migrated-to-gvfs", NULL);
if (g_file_test (updated, G_FILE_TEST_EXISTS)) {
/* Already migrated */
g_free (updated);
return;
}
metadata = g_build_filename (ev_application_get_dot_dir (EV_APP),
"ev-metadata.xml", NULL);
if (g_file_test (metadata, G_FILE_TEST_EXISTS)) {
if (convert_metadata (metadata)) {
gint fd;
fd = g_creat (updated, 0600);
if (fd != -1) {
close (fd);
}
}
}
g_free (updated);
g_free (metadata);
}
#endif /* !G_OS_WIN32 */
static void
value_free (GValue *value)
{
g_value_unset (value);
g_free (value);
}
/**
* arguments_parse:
*
* Parses the arguments and creates a #GHashTable with this data.
*
* key -> value
*
* dislay -> display at the default screen.
* screen -> screen number.
* page-label -> only if the page label argument has been passed,
* the page of the document to display.
* mode -> only if the view mode is one of the availables,
* the view mode.
*
* Returns: a pointer into #GHashTable with data from the arguments.
*/
static GHashTable *
arguments_parse (void)
{
GHashTable *args;
GValue *value;
EvWindowRunMode mode;
GdkScreen *screen;
GdkDisplay *display;
const gchar *display_name;
gint screen_number;
args = g_hash_table_new_full (g_str_hash,
g_str_equal,
(GDestroyNotify)g_free,
(GDestroyNotify)value_free);
screen = gdk_screen_get_default ();
display = gdk_screen_get_display (screen);
display_name = gdk_display_get_name (display);
screen_number = gdk_screen_get_number (screen);
value = g_new0 (GValue, 1);
g_value_init (value, G_TYPE_STRING);
g_value_set_string (value, display_name);
g_hash_table_insert (args, g_strdup ("display"), value);
value = g_new0 (GValue, 1);
g_value_init (value, G_TYPE_INT);
g_value_set_int (value, screen_number);
g_hash_table_insert (args, g_strdup ("screen"), value);
if (ev_page_label) {
value = g_new0 (GValue, 1);
g_value_init (value, G_TYPE_STRING);
g_value_set_string (value, ev_page_label);
g_hash_table_insert (args, g_strdup ("page-label"), value);
g_free (ev_page_label);
ev_page_label = NULL;
}
if (ev_find_string) {
value = g_new0 (GValue, 1);
g_value_init (value, G_TYPE_STRING);
g_value_set_string (value, ev_find_string);
g_hash_table_insert (args, g_strdup ("find-string"), value);
g_free (ev_find_string);
ev_page_label = NULL;
}
if (fullscreen_mode)
mode = EV_WINDOW_MODE_FULLSCREEN;
else if (presentation_mode)
mode = EV_WINDOW_MODE_PRESENTATION;
else
return args;
value = g_new0 (GValue, 1);
g_value_init (value, G_TYPE_UINT);
g_value_set_uint (value, mode);
g_hash_table_insert (args, g_strdup ("mode"), value);
return args;
}
static gint
find_window_list (EvWindow *window,
const gchar *uri)
@ -323,27 +149,37 @@ find_window_list (EvWindow *window,
}
static void
load_files (const char **files,
GHashTable *args)
load_files (const char **files)
{
int i;
GList *windows;
GdkScreen *screen = gdk_screen_get_default ();
EvWindowRunMode mode = EV_WINDOW_MODE_NORMAL;
GList *windows;
gint i;
EvLinkDest *global_dest = NULL;
windows = ev_application_get_windows (EV_APP);
if (!files) {
if (!windows)
ev_application_open_window (EV_APP, args, GDK_CURRENT_TIME, NULL);
ev_application_open_window (EV_APP, screen, GDK_CURRENT_TIME);
else
g_list_free (windows);
return;
}
if (ev_page_label)
global_dest = ev_link_dest_new_page_label (ev_page_label);
if (fullscreen_mode)
mode = EV_WINDOW_MODE_FULLSCREEN;
else if (presentation_mode)
mode = EV_WINDOW_MODE_PRESENTATION;
for (i = 0; files[i]; i++) {
char *uri;
char *label;
GValue *old = NULL;
GFile *file;
gchar *uri;
gchar *label;
GFile *file;
EvLinkDest *dest = NULL;
file = g_file_new_for_commandline_arg (files[i]);
uri = g_file_get_uri (file);
@ -355,122 +191,31 @@ load_files (const char **files,
}
label = strchr (uri, '#');
if (label) {
GValue *new;
*label = 0; label++;
old = g_hash_table_lookup (args, "page-label");
new = g_new0 (GValue, 1);
g_value_init (new, G_TYPE_STRING);
g_value_set_string (new, label);
g_hash_table_insert (args, g_strdup ("page-label"), new);
*label = 0;
label++;
dest = ev_link_dest_new_page_label (label);
} else if (global_dest) {
dest = g_object_ref (global_dest);
}
ev_application_open_uri (EV_APP, uri, args,
GDK_CURRENT_TIME, NULL);
ev_application_open_uri_at_dest (EV_APP, uri, screen, dest,
mode, ev_find_string,
GDK_CURRENT_TIME);
if (old)
g_hash_table_insert (args, g_strdup ("page-label"), old);
if (dest)
g_object_unref (dest);
g_free (uri);
}
g_list_free (windows);
}
#ifdef ENABLE_DBUS
static gboolean
load_files_remote (const char **files,
GHashTable *args)
{
int i;
GError *error = NULL;
DBusGConnection *connection;
gboolean result = FALSE;
DBusGProxy *remote_object;
GdkDisplay *display;
guint32 timestamp;
display = gdk_display_get_default ();
timestamp = gdk_x11_display_get_user_time (display);
connection = dbus_g_bus_get (DBUS_BUS_STARTER, &error);
if (connection == NULL) {
g_warning ("%s", error->message);
g_error_free (error);
return FALSE;
}
remote_object = dbus_g_proxy_new_for_name (connection,
"org.gnome.evince.ApplicationService",
"/org/gnome/evince/Evince",
"org.gnome.evince.Application");
if (!files) {
if (!dbus_g_proxy_call (remote_object, "OpenWindow", &error,
dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), args,
G_TYPE_UINT, timestamp,
G_TYPE_INVALID,
G_TYPE_INVALID)) {
g_warning ("%s", error->message);
g_clear_error (&error);
g_object_unref (remote_object);
dbus_g_connection_unref (connection);
return FALSE;
}
g_object_unref (remote_object);
dbus_g_connection_unref (connection);
return TRUE;
}
for (i = 0; files[i]; i++) {
const char *page_label;
GFile *file;
char *uri;
file = g_file_new_for_commandline_arg (files[i]);
uri = g_file_get_uri (file);
g_object_unref (file);
page_label = ev_page_label ? ev_page_label : "";
if (!dbus_g_proxy_call (remote_object, "OpenURI", &error,
G_TYPE_STRING, uri,
dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), args,
G_TYPE_UINT, timestamp,
G_TYPE_INVALID,
G_TYPE_INVALID)) {
g_warning ("%s", error->message);
g_clear_error (&error);
g_free (uri);
continue;
}
g_free (uri);
result = TRUE;
}
g_object_unref (remote_object);
dbus_g_connection_unref (connection);
gdk_notify_startup_complete ();
return result;
}
#endif /* ENABLE_DBUS */
int
main (int argc, char *argv[])
{
GOptionContext *context;
GHashTable *args;
GList *toplevels;
GError *error = NULL;
#ifdef G_OS_WIN32
@ -536,25 +281,9 @@ main (int argc, char *argv[])
return retval ? 0 : 1;
}
args = arguments_parse ();
#ifdef ENABLE_DBUS
if (!ev_application_register_service (EV_APP)) {
if (load_files_remote (file_arguments, args)) {
g_hash_table_destroy (args);
return 0;
}
}
#endif /* ENABLE_DBUS */
if (!ev_init ())
return 1;
#ifndef G_OS_WIN32
ev_migrate_metadata ();
#endif
ev_stock_icons_init ();
#if defined(WITH_SMCLIENT) && defined(GDK_WINDOWING_X11)
@ -566,15 +295,17 @@ main (int argc, char *argv[])
#endif /* WITH_SMCLIENT && GDK_WINDOWING_X11 */
ev_application_load_session (EV_APP, file_arguments);
load_files (file_arguments, args);
g_hash_table_destroy (args);
load_files (file_arguments);
toplevels = gtk_window_list_toplevels ();
if (toplevels) {
g_list_free (toplevels);
/* Change directory so we don't prevent unmounting in case the initial cwd
* is on an external device (see bug #575436)
*/
g_chdir (g_get_home_dir ());
/* Change directory so we don't prevent unmounting in case the initial cwd
* is on an external device (see bug #575436)
*/
g_chdir (g_get_home_dir ());
gtk_main ();
gtk_main ();
}
ev_shutdown ();
ev_stock_icons_shutdown ();