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:
parent
3f28adc16f
commit
66e5636dca
|
@ -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])],
|
||||
|
|
|
@ -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)
|
||||
|
|
3
data/org.gnome.evince.Daemon.service.in
Normal file
3
data/org.gnome.evince.Daemon.service.in
Normal file
|
@ -0,0 +1,3 @@
|
|||
[D-BUS Service]
|
||||
Name=org.gnome.evince.Daemon
|
||||
Exec=@libexecdir@/evinced
|
|
@ -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
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
21
shell/ev-daemon-service.xml
Normal file
21
shell/ev-daemon-service.xml
Normal 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
442
shell/ev-daemon.c
Normal 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;
|
||||
}
|
349
shell/main.c
349
shell/main.c
|
@ -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 ();
|
||||
|
|
Loading…
Reference in New Issue
Block a user