]> www.fi.muni.cz Git - evince.git/blobdiff - shell/ev-application.c
[shell] Pass the GDBusConnection to TotemScrsaver
[evince.git] / shell / ev-application.c
index e2f066344b212a0e32a6070773e503d9c9f08ade..191c6fb94274356955bc322aa5552b36bb9ac206 100644 (file)
@@ -17,7 +17,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  *
  * 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.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  */
 
 
  */
 
 
 
 #include <glib.h>
 #include <glib/gi18n.h>
 
 #include <glib.h>
 #include <glib/gi18n.h>
+#include <glib/gstdio.h>
 #include <gtk/gtk.h>
 #ifdef GDK_WINDOWING_X11
 #include <gdk/gdkx.h>
 #endif
 #include <gtk/gtk.h>
 #ifdef GDK_WINDOWING_X11
 #include <gdk/gdkx.h>
 #endif
+#include <unistd.h>
 
 #include "totem-scrsaver.h"
 
 
 #include "totem-scrsaver.h"
 
@@ -39,9 +41,7 @@
 #endif
 
 #include "ev-application.h"
 #endif
 
 #include "ev-application.h"
-#include "ev-document-factory.h"
 #include "ev-file-helpers.h"
 #include "ev-file-helpers.h"
-#include "ev-utils.h"
 #include "ev-stock-icons.h"
 
 #ifdef ENABLE_DBUS
 #include "ev-stock-icons.h"
 
 #ifdef ENABLE_DBUS
 #endif /* ENABLE_DBUS */
 
 #ifdef ENABLE_DBUS
 #endif /* ENABLE_DBUS */
 
 #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
 
 struct _EvApplication {
 #endif
 
 struct _EvApplication {
@@ -65,10 +58,10 @@ struct _EvApplication {
 
        gchar *dot_dir;
        gchar *data_dir;
 
        gchar *dot_dir;
        gchar *data_dir;
-       gchar *accel_map_file;
 
 #ifdef ENABLE_DBUS
 
 #ifdef ENABLE_DBUS
-       DBusGConnection *connection;
+       GDBusConnection *connection;
+        guint registration_id;
        EvMediaPlayerKeys *keys;
 #endif
 
        EvMediaPlayerKeys *keys;
 #endif
 
@@ -95,6 +88,8 @@ G_DEFINE_TYPE (EvApplication, ev_application, G_TYPE_OBJECT);
 #define APPLICATION_DBUS_INTERFACE   "org.gnome.evince.Application"
 #endif
 
 #define APPLICATION_DBUS_INTERFACE   "org.gnome.evince.Application"
 #endif
 
+static const gchar *userdir = NULL;
+
 /**
  * ev_application_get_instance:
  *
 /**
  * ev_application_get_instance:
  *
@@ -209,181 +204,6 @@ ev_display_open_if_needed (const gchar *name)
        return display != NULL ? display : gdk_display_open (name);
 }
 
        return display != NULL ? display : gdk_display_open (name);
 }
 
-/**
- * get_screen_from_args:
- * @args: a #GHashTable with data passed to the application.
- *
- * Looks for the screen in the display available in the hash table passed to the
- * application. If the display isn't opened, it's opened and the #GdkScreen
- * assigned to the screen in that display returned.
- *
- * Returns: the #GdkScreen assigned to the screen on the display indicated by
- *          the data on the #GHashTable.
- */
-static GdkScreen *
-get_screen_from_args (GHashTable *args)
-{
-       GValue     *value = NULL;
-       GdkDisplay *display = NULL;
-       GdkScreen  *screen = NULL;
-
-       g_assert (args != NULL);
-       
-       value = g_hash_table_lookup (args, "display");
-       if (value) {
-               const gchar *display_name;
-               
-               display_name = g_value_get_string (value);
-               display = ev_display_open_if_needed (display_name);
-       }
-       
-       value = g_hash_table_lookup (args, "screen");
-       if (value) {
-               gint screen_number;
-               
-               screen_number = g_value_get_int (value);
-               screen = gdk_display_get_screen (display, screen_number);
-       }
-
-       return screen;
-}
-
-/**
- * get_window_run_mode_from_args:
- * @args: a #GHashTable with data passed to the application.
- *
- * It does look if the mode option has been passed from command line, using it
- * as the window run mode, otherwise the run mode will be the normal mode.
- *
- * Returns: The window run mode passed from command line or
- *          EV_WINDOW_MODE_NORMAL in other case.
- */
-static EvWindowRunMode
-get_window_run_mode_from_args (GHashTable *args)
-{
-       EvWindowRunMode  mode = EV_WINDOW_MODE_NORMAL;
-       GValue          *value = NULL;
-
-       g_assert (args != NULL);
-
-       value = g_hash_table_lookup (args, "mode");
-       if (value) {
-               mode = g_value_get_uint (value);
-       }
-
-       return mode;
-}
-
-/**
- * get_destination_from_args:
- * @args: a #GHashTable with data passed to the application.
- *
- * It does look for the page-label argument parsed from the command line and
- * if it does exist, it returns an #EvLinkDest.
- *
- * Returns: An #EvLinkDest to page-label if it has been passed from the command
- *          line, NULL in other case.
- */
-static EvLinkDest *
-get_destination_from_args (GHashTable *args)
-{
-       EvLinkDest *dest = NULL;
-       GValue     *value = NULL;
-       
-       g_assert (args != NULL);
-       
-       value = g_hash_table_lookup (args, "page-label");
-       if (value) {
-               const gchar *page_label;
-
-               page_label = g_value_get_string (value);
-               dest = ev_link_dest_new_page_label (page_label);
-       }
-
-       return dest;
-}
-
-static const gchar *
-get_find_string_from_args (GHashTable *args)
-{
-       GValue *value = NULL;
-
-       g_assert (args != NULL);
-
-       value = g_hash_table_lookup (args, "find-string");
-       
-       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;
-}
-
 static void
 child_setup (gpointer user_data)
 {
 static void
 child_setup (gpointer user_data)
 {
@@ -409,7 +229,17 @@ ev_spawn (const char     *uri,
        gboolean res;
        GError  *error = NULL;
 
        gboolean res;
        GError  *error = NULL;
 
+#ifdef G_OS_WIN32
+{
+       gchar *dir;
+
+       dir = g_win32_get_package_installation_directory_of_module (NULL);
+       argv[arg++] = g_build_filename (dir, "bin", "evince", NULL);
+       g_free (dir);
+}
+#else
        argv[arg++] = g_build_filename (BINDIR, "evince", NULL);
        argv[arg++] = g_build_filename (BINDIR, "evince", NULL);
+#endif
 
        /* Page label */
        if (dest) {
 
        /* Page label */
        if (dest) {
@@ -502,92 +332,149 @@ ev_application_get_empty_window (EvApplication *application,
 
 
 #ifdef ENABLE_DBUS
 
 
 #ifdef ENABLE_DBUS
+/*
+ * ev_application_register_uri:
+ * @application:
+ * @uri:
+ * @screen:
+ * @dest:
+ * @mode:
+ * @search_string:
+ * @timestamp:
+ *
+ * Registers @uri with evince-daemon.
+ *
+ * Returns: %TRUE to continue by opening @uri in this instance,
+ *   or %FALSE if the request was forwarded to an existing evince
+ *   instance for @uri
+ */
 static gboolean
 ev_application_register_uri (EvApplication *application,
                             const gchar   *uri,
 static gboolean
 ev_application_register_uri (EvApplication *application,
                             const gchar   *uri,
-                            GHashTable    *args,
+                             GdkScreen      *screen,
+                             EvLinkDest     *dest,
+                             EvWindowRunMode mode,
+                             const gchar    *search_string,
                             guint          timestamp)
 {
                             guint          timestamp)
 {
-       DBusGProxy *proxy;
-       gchar      *owner;
-       gboolean    retval = TRUE;
-       GError     *error = NULL;
+       GVariant *value, *value2;
+       const gchar *owner;
+        GVariantBuilder builder;
+       GError *error = NULL;
 
        if (!application->connection)
                return TRUE;
 
 
        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)) {
+        /* FIXME: Don't make sync dbus calls, they block the UI! */
+        value = g_dbus_connection_call_sync
+                   (application->connection,
+                    "org.gnome.evince.Daemon",
+                    "/org/gnome/evince/Daemon",
+                    "org.gnome.evince.Daemon",
+                    "RegisterDocument",
+                    g_variant_new ("(s)", uri),
+                    G_DBUS_CALL_FLAGS_NONE,
+                    -1,
+                    NULL,
+                    &error);
+        if (value == NULL) {
                g_warning ("Error registering document: %s\n", error->message);
                g_error_free (error);
                g_warning ("Error registering document: %s\n", error->message);
                g_error_free (error);
-               g_object_unref (proxy);
-
                return TRUE;
        }
                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_variant_get (value, "(&s)", &owner);
 
 
-       g_free (owner);
+        /* This means that the document wasn't already registered; go
+         * ahead with opening it.
+         */
+       if (owner[0] == '\0') {
+                g_variant_unref (value);
+                return TRUE;
+        }
 
 
-       return retval;
+        /* Already registered */
+        g_variant_builder_init (&builder, G_VARIANT_TYPE ("(sa{sv}u)"));
+        g_variant_builder_add (&builder, "s", uri);
+
+        g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{sv}"));
+        g_variant_builder_add (&builder, "{sv}",
+                               "display",
+                               g_variant_new_string (gdk_display_get_name (gdk_screen_get_display (screen))));
+        g_variant_builder_add (&builder, "{sv}",
+                               "screen",
+                               g_variant_new_int32 (gdk_screen_get_number (screen)));
+       if (dest) {
+                g_variant_builder_add (&builder, "{sv}",
+                                       "page-label",
+                                       g_variant_new_string (ev_link_dest_get_page_label (dest)));
+       }
+       if (search_string) {
+                g_variant_builder_add (&builder, "{sv}",
+                                       "find-string",
+                                       g_variant_new_string (search_string));
+       }
+       if (mode != EV_WINDOW_MODE_NORMAL) {
+                g_variant_builder_add (&builder, "{sv}",
+                                       "mode",
+                                       g_variant_new_uint32 (mode));
+       }
+        g_variant_builder_close (&builder);
+
+        g_variant_builder_add (&builder, "u", timestamp);
+
+        value2 = g_dbus_connection_call_sync
+                    (application->connection,
+                     owner,
+                     APPLICATION_DBUS_OBJECT_PATH,
+                     APPLICATION_DBUS_INTERFACE,
+                     "OpenURI",
+                     g_variant_builder_end (&builder),
+                     G_DBUS_CALL_FLAGS_NONE,
+                     -1,
+                     NULL,
+                     &error);
+        if (value2 == NULL) {
+                g_warning ("Failed to OpenURI: %s", error->message);
+                g_error_free (error);
+                return FALSE;
+        }
+
+       g_variant_unref (value);
+       g_variant_unref (value2);
+
+        /* Do not continue opening this document */
+       return FALSE;
 }
 
 static void
 ev_application_unregister_uri (EvApplication *application,
                               const gchar   *uri)
 {
 }
 
 static void
 ev_application_unregister_uri (EvApplication *application,
                               const gchar   *uri)
 {
-       DBusGProxy *proxy;
-       GError     *error = NULL;
+        GVariant *value;
+       GError *error = NULL;
 
        if (!application->connection)
                return;
 
 
        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)) {
+        /* FIXME: Don't make sync dbus calls, they block the UI! */
+        value = g_dbus_connection_call_sync
+                   (application->connection,
+                    "org.gnome.evince.Daemon",
+                    "/org/gnome/evince/Daemon",
+                    "org.gnome.evince.Daemon",
+                    "UnregisterDocument",
+                    g_variant_new ("(s)", uri),
+                    G_DBUS_CALL_FLAGS_NO_AUTO_START,
+                    -1,
+                    NULL,
+                    &error);
+        if (value == NULL) {
                g_warning ("Error unregistering document: %s\n", error->message);
                g_error_free (error);
                g_warning ("Error unregistering document: %s\n", error->message);
                g_error_free (error);
+       } else {
+                g_variant_unref (value);
        }
        }
-
-       g_object_unref (proxy);
 }
 #endif /* ENABLE_DBUS */
 
 }
 #endif /* ENABLE_DBUS */
 
@@ -601,6 +488,10 @@ ev_application_open_uri_in_window (EvApplication  *application,
                                   const gchar    *search_string,
                                   guint           timestamp)
 {
                                   const gchar    *search_string,
                                   guint           timestamp)
 {
+#ifdef GDK_WINDOWING_X11
+       GdkWindow *gdk_window;
+#endif
+
        if (screen) {
                ev_stock_icons_set_screen (screen);
                gtk_window_set_screen (GTK_WINDOW (ev_window), screen);
        if (screen) {
                ev_stock_icons_set_screen (screen);
                gtk_window_set_screen (GTK_WINDOW (ev_window), screen);
@@ -610,21 +501,19 @@ ev_application_open_uri_in_window (EvApplication  *application,
           we can restore window size without flickering */
        ev_window_open_uri (ev_window, uri, dest, mode, search_string);
 
           we can restore window size without flickering */
        ev_window_open_uri (ev_window, uri, dest, mode, search_string);
 
-       if (!GTK_WIDGET_REALIZED (GTK_WIDGET (ev_window)))
+       if (!gtk_widget_get_realized (GTK_WIDGET (ev_window)))
                gtk_widget_realize (GTK_WIDGET (ev_window));
 
 #ifdef GDK_WINDOWING_X11
                gtk_widget_realize (GTK_WIDGET (ev_window));
 
 #ifdef GDK_WINDOWING_X11
+       gdk_window = gtk_widget_get_window (GTK_WIDGET (ev_window));
+
        if (timestamp <= 0)
        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);
+               timestamp = gdk_x11_get_server_time (gdk_window);
+       gdk_x11_window_set_user_time (gdk_window, timestamp);
 
 
-       ev_document_fc_mutex_lock ();
        gtk_window_present (GTK_WINDOW (ev_window));
        gtk_window_present (GTK_WINDOW (ev_window));
-       ev_document_fc_mutex_unlock ();
 #else
 #else
-       ev_document_fc_mutex_lock ();
        gtk_window_present_with_time (GTK_WINDOW (ev_window), timestamp);
        gtk_window_present_with_time (GTK_WINDOW (ev_window), timestamp);
-       ev_document_fc_mutex_unlock ();
 #endif /* GDK_WINDOWING_X11 */
 }
 
 #endif /* GDK_WINDOWING_X11 */
 }
 
@@ -656,14 +545,12 @@ ev_application_open_uri_at_dest (EvApplication  *application,
                return;
        } else {
 #ifdef ENABLE_DBUS
                return;
        } else {
 #ifdef ENABLE_DBUS
-               GHashTable *args = build_args (screen, dest, mode, search_string);
                gboolean    ret;
 
                /* Register the uri or send OpenURI to
                 * remote instance if already registered
                 */
                gboolean    ret;
 
                /* 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);
+               ret = ev_application_register_uri (application, uri, screen, dest, mode, search_string, timestamp);
                if (!ret)
                        return;
 #endif /* ENABLE_DBUS */
                if (!ret)
                        return;
 #endif /* ENABLE_DBUS */
@@ -694,19 +581,24 @@ ev_application_open_window (EvApplication *application,
                            guint32        timestamp)
 {
        GtkWidget *new_window = ev_window_new ();
                            guint32        timestamp)
 {
        GtkWidget *new_window = ev_window_new ();
+#ifdef GDK_WINDOWING_X11
+       GdkWindow *gdk_window;
+#endif
 
        if (screen) {
                ev_stock_icons_set_screen (screen);
                gtk_window_set_screen (GTK_WINDOW (new_window), screen);
        }
 
 
        if (screen) {
                ev_stock_icons_set_screen (screen);
                gtk_window_set_screen (GTK_WINDOW (new_window), screen);
        }
 
-       if (!GTK_WIDGET_REALIZED (new_window))
+       if (!gtk_widget_get_realized (new_window))
                gtk_widget_realize (new_window);
 
 #ifdef GDK_WINDOWING_X11
                gtk_widget_realize (new_window);
 
 #ifdef GDK_WINDOWING_X11
+       gdk_window = gtk_widget_get_window (GTK_WIDGET (new_window));
+
        if (timestamp <= 0)
        if (timestamp <= 0)
-               timestamp = gdk_x11_get_server_time (new_window->window);
-       gdk_x11_window_set_user_time (new_window->window, timestamp);
+               timestamp = gdk_x11_get_server_time (gdk_window);
+       gdk_x11_window_set_user_time (gdk_window, timestamp);
 
        gtk_window_present (GTK_WINDOW (new_window));
 #else
 
        gtk_window_present (GTK_WINDOW (new_window));
 #else
@@ -714,45 +606,70 @@ ev_application_open_window (EvApplication *application,
 #endif /* GDK_WINDOWING_X11 */
 }
 
 #endif /* GDK_WINDOWING_X11 */
 }
 
-/**
- * ev_application_open_uri:
- * @application: The instance of the application.
- * @uri: The uri to be opened
- * @args: A #GHashTable with the arguments data.
- * @timestamp: Current time value.
- * @error: The #GError facility.
- */
-static gboolean
-ev_application_open_uri (EvApplication  *application,
-                        const char     *uri,
-                        GHashTable     *args,
-                        guint           timestamp,
-                        GError        **error)
-{
+static void
+method_call_cb (GDBusConnection       *connection,
+                const gchar           *sender,
+                const gchar           *object_path,
+                const gchar           *interface_name,
+                const gchar           *method_name,
+                GVariant              *parameters,
+                GDBusMethodInvocation *invocation,
+                gpointer               user_data)
+{
+        EvApplication   *application = EV_APPLICATION (user_data);
        GList           *windows, *l;
        GList           *windows, *l;
+        const gchar     *uri;
+        guint            timestamp;
+        GVariantIter    *iter;
+        const gchar     *key;
+        GVariant        *value;
+        GdkDisplay      *display = NULL;
+        int              screen_number = 0;
        EvLinkDest      *dest = NULL;
        EvWindowRunMode  mode = EV_WINDOW_MODE_NORMAL;
        const gchar     *search_string = NULL;
        GdkScreen       *screen = NULL;
 
        EvLinkDest      *dest = NULL;
        EvWindowRunMode  mode = EV_WINDOW_MODE_NORMAL;
        const gchar     *search_string = NULL;
        GdkScreen       *screen = NULL;
 
-       g_assert (application->uri != NULL);
+        if (g_strcmp0 (method_name, "OpenURI") != 0)
+                return;
+
+        g_variant_get (parameters, "(&sa{sv}u)", &uri, &iter, &timestamp);
 
        /* FIXME: we don't need uri anymore,
         * maybe this method should be renamed
         * as reload, refresh or something like that
         */
 
        /* FIXME: we don't need uri anymore,
         * maybe this method should be renamed
         * as reload, refresh or something like that
         */
-       if (!application->uri || strcmp (application->uri, uri)) {
-               g_warning ("Invalid uri: %s, expected %s\n",
-                          uri, application->uri);
-               return TRUE;
+       if (g_strcmp0 (application->uri, uri) != 0) {
+                g_dbus_method_invocation_return_error (invocation,
+                                                       G_DBUS_ERROR,
+                                                       G_DBUS_ERROR_INVALID_ARGS,
+                                                       "Unexpected URI \"%s\"",
+                                                       uri);
+                g_variant_iter_free (iter);
+               return;
        }
 
        }
 
-       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);
-       }
+        while (g_variant_iter_loop (iter, "{&sv}", &key, &value)) {
+                if (strcmp (key, "display") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
+                        display = ev_display_open_if_needed (g_variant_get_string (value, NULL));
+                } else if (strcmp (key, "screen") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
+                        screen_number = g_variant_get_int32 (value);
+                } else if (strcmp (key, "mode") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_UINT32) {
+                        mode = g_variant_get_uint32 (value);
+                } else if (strcmp (key, "page-label") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
+                        dest = ev_link_dest_new_page_label (g_variant_get_string (value, NULL));
+                } else if (strcmp (key, "find-string") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
+                        search_string = g_variant_get_string (value, NULL);
+                }
+        }
+        g_variant_iter_free (iter);
+
+        if (display != NULL &&
+            screen_number >= 0 &&
+            screen_number < gdk_display_get_n_screens (display))
+                screen = gdk_display_get_screen (display, screen_number);
+        else
+                screen = gdk_screen_get_default ();
 
        windows = ev_application_get_windows (application);
        for (l = windows; l != NULL; l = g_list_next (l)) {
 
        windows = ev_application_get_windows (application);
        for (l = windows; l != NULL; l = g_list_next (l)) {
@@ -768,7 +685,7 @@ ev_application_open_uri (EvApplication  *application,
        if (dest)
                g_object_unref (dest);
 
        if (dest)
                g_object_unref (dest);
 
-       return TRUE;
+       g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
 }
 
 void
 }
 
 void
@@ -786,6 +703,61 @@ ev_application_open_uri_list (EvApplication *application,
        }
 }
 
        }
 }
 
+static void
+ev_application_accel_map_save (EvApplication *application)
+{
+       gchar *accel_map_file;
+       gchar *tmp_filename;
+       gint   fd;
+
+       if (userdir) {
+               accel_map_file = g_build_filename (userdir, "accels",
+                                                  "evince", NULL);
+       } else {
+               accel_map_file = g_build_filename (g_get_home_dir (),
+                                                  ".gnome2", "accels",
+                                                  "evince", NULL);
+       }
+
+       tmp_filename = g_strdup_printf ("%s.XXXXXX", accel_map_file);
+
+       fd = g_mkstemp (tmp_filename);
+       if (fd == -1) {
+               g_free (accel_map_file);
+               g_free (tmp_filename);
+
+               return;
+       }
+       gtk_accel_map_save_fd (fd);
+       close (fd);
+
+       if (g_rename (tmp_filename, accel_map_file) == -1) {
+               /* FIXME: win32? */
+               g_unlink (tmp_filename);
+       }
+
+       g_free (accel_map_file);
+       g_free (tmp_filename);
+}
+
+static void
+ev_application_accel_map_load (EvApplication *application)
+{
+       gchar *accel_map_file;
+
+       if (userdir) {
+               accel_map_file = g_build_filename (userdir, "accels",
+                                                  "evince", NULL);
+       } else {
+               accel_map_file = g_build_filename (g_get_home_dir (),
+                                                  ".gnome2", "accels",
+                                                  "evince", NULL);
+       }
+
+       gtk_accel_map_load (accel_map_file);
+       g_free (accel_map_file);
+}
+
 void
 ev_application_shutdown (EvApplication *application)
 {
 void
 ev_application_shutdown (EvApplication *application)
 {
@@ -798,17 +770,25 @@ ev_application_shutdown (EvApplication *application)
                application->uri = NULL;
        }
 
                application->uri = NULL;
        }
 
-       if (application->accel_map_file) {
-               gtk_accel_map_save (application->accel_map_file);
-               g_free (application->accel_map_file);
-               application->accel_map_file = NULL;
-       }
-       
+       ev_application_accel_map_save (application);
+
+       g_object_unref (application->scr_saver);
+       application->scr_saver = NULL;
+
 #ifdef ENABLE_DBUS
        if (application->keys) {
                g_object_unref (application->keys);
                application->keys = NULL;
        }
 #ifdef ENABLE_DBUS
        if (application->keys) {
                g_object_unref (application->keys);
                application->keys = NULL;
        }
+        if (application->registration_id != 0) {
+                g_dbus_connection_unregister_object (application->connection,
+                                                     application->registration_id);
+                application->registration_id = 0;
+        }
+        if (application->connection != NULL) {
+                g_object_unref (application->connection);
+                application->connection = NULL;
+        }
 #endif /* ENABLE_DBUS */
        
         g_free (application->dot_dir);
 #endif /* ENABLE_DBUS */
        
         g_free (application->dot_dir);
@@ -829,26 +809,21 @@ ev_application_shutdown (EvApplication *application)
 static void
 ev_application_class_init (EvApplicationClass *ev_application_class)
 {
 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
 ev_application_init (EvApplication *ev_application)
 {
 }
 
 static void
 ev_application_init (EvApplication *ev_application)
 {
-       const gchar *home_dir;
        GError *error = NULL;
 
        GError *error = NULL;
 
-        ev_application->dot_dir = g_build_filename (g_get_home_dir (),
-                                                    ".gnome2",
-                                                    "evince",
-                                                    NULL);
-
-        /* FIXME: why make this fatal? */
-        if (!ev_dir_ensure_exists (ev_application->dot_dir, 0700))
-                exit (1);
+       userdir = g_getenv ("GNOME22_USER_DIR");
+       if (userdir)
+               ev_application->dot_dir = g_build_filename (userdir, "evince", NULL);
+       else
+               ev_application->dot_dir = g_build_filename (g_get_home_dir (),
+                                                           ".gnome2",
+                                                           "evince",
+                                                           NULL);
 
 #ifdef G_OS_WIN32
 {
 
 #ifdef G_OS_WIN32
 {
@@ -864,28 +839,59 @@ ev_application_init (EvApplication *ev_application)
 
        ev_application_init_session (ev_application);
 
 
        ev_application_init_session (ev_application);
 
-       home_dir = g_get_home_dir ();
-       if (home_dir) {
-               ev_application->accel_map_file = g_build_filename (home_dir,
-                                                                  ".gnome2",
-                                                                  "accels",
-                                                                  "evince",
-                                                                  NULL);
-               gtk_accel_map_load (ev_application->accel_map_file);
-       }
+       ev_application_accel_map_load (ev_application);
 
 #ifdef ENABLE_DBUS
 
 #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->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 ();
+{
+        static const char introspection_xml[] =
+                "<node>"
+                  "<interface name='org.gnome.evince.Daemon'>"
+                    "<method name='OpenURI'>"
+                      "<arg type='s' name='uri' direction='in'/>"
+                      "<arg type='a{sv}' name='args' direction='in'/>"
+                      "<arg type='u' name='timestamp' direction='in'/>"
+                    "</method>"
+                  "</interface>"
+                "</node>";
+
+        static const GDBusInterfaceVTable interface_vtable = {
+                method_call_cb,
+                NULL,
+                NULL
+        };
+
+        GDBusNodeInfo *introspection_data;
+
+        ev_application->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
+        if (ev_application->connection != NULL) {
+                introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
+                g_assert (introspection_data != NULL);
+
+
+                ev_application->registration_id =
+                    g_dbus_connection_register_object (ev_application->connection,
+                                                       APPLICATION_DBUS_OBJECT_PATH,
+                                                       APPLICATION_DBUS_INTERFACE,
+                                                       introspection_data->interfaces[0],
+                                                       &interface_vtable,
+                                                       ev_application, NULL,
+                                                       &error);
+                if (ev_application->registration_id == 0) {
+                        g_printerr ("Failed to register bus object: %s\n", error->message);
+                        g_error_free (error);
+                }
+                
+        } else {
+                g_printerr ("Failed to get bus connection: %s\n", error->message);
+                g_error_free (error);
+        }
+
+       ev_application->keys = ev_media_player_keys_new (ev_application->connection);
+
+       ev_application->scr_saver = totem_scrsaver_new (ev_application->connection);
+}
+#else
+        ev_application->scr_saver = totem_scrsaver_new ();
 #endif /* ENABLE_DBUS */
 }
 
 #endif /* ENABLE_DBUS */
 }
 
@@ -956,20 +962,22 @@ ev_application_get_filechooser_uri (EvApplication       *application,
 void
 ev_application_screensaver_enable (EvApplication *application)
 {
 void
 ev_application_screensaver_enable (EvApplication *application)
 {
-       if (application->scr_saver)
-               totem_scrsaver_enable (application->scr_saver); 
+       totem_scrsaver_enable (application->scr_saver);
 }
 
 void
 ev_application_screensaver_disable (EvApplication *application)
 {
 }
 
 void
 ev_application_screensaver_disable (EvApplication *application)
 {
-       if (application->scr_saver)
-               totem_scrsaver_disable (application->scr_saver);        
+       totem_scrsaver_disable (application->scr_saver);
 }
 
 const gchar *
 }
 
 const gchar *
-ev_application_get_dot_dir (EvApplication   *application)
+ev_application_get_dot_dir (EvApplication *application,
+                            gboolean create)
 {
 {
+        if (create)
+                g_mkdir_with_parents (application->dot_dir, 0700);
+
        return application->dot_dir;
 }
 
        return application->dot_dir;
 }