]> www.fi.muni.cz Git - evince.git/blob - shell/ev-application.c
[shell] Update to current GDBus API
[evince.git] / shell / ev-application.c
1 /* this file is part of evince, a gnome document viewer
2  *
3  *  Copyright (C) 2004 Martin Kretzschmar
4  *  Copyright © 2010 Christian Persch
5  *
6  *  Author:
7  *    Martin Kretzschmar <martink@gnome.org>
8  *
9  * Evince is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Evince is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22  */
23
24
25 #include <config.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include <glib.h>
30 #include <glib/gi18n.h>
31 #include <glib/gstdio.h>
32 #include <gtk/gtk.h>
33 #ifdef GDK_WINDOWING_X11
34 #include <gdk/gdkx.h>
35 #endif
36 #include <unistd.h>
37
38 #include "totem-scrsaver.h"
39
40 #ifdef WITH_SMCLIENT
41 #include "eggsmclient.h"
42 #endif
43
44 #include "ev-application.h"
45 #include "ev-file-helpers.h"
46 #include "ev-stock-icons.h"
47
48 #ifdef ENABLE_DBUS
49 #include "ev-media-player-keys.h"
50 #endif /* ENABLE_DBUS */
51
52 #ifdef ENABLE_DBUS
53 #endif
54
55 struct _EvApplication {
56         GObject base_instance;
57
58         gchar *uri;
59
60         gchar *dot_dir;
61         gchar *data_dir;
62
63 #ifdef ENABLE_DBUS
64         GDBusConnection *connection;
65         guint registration_id;
66         EvMediaPlayerKeys *keys;
67 #endif
68
69         TotemScrsaver *scr_saver;
70
71 #ifdef WITH_SMCLIENT
72         EggSMClient *smclient;
73 #endif
74
75         gchar *filechooser_open_uri;
76         gchar *filechooser_save_uri;
77 };
78
79 struct _EvApplicationClass {
80         GObjectClass base_class;
81 };
82
83 static EvApplication *instance;
84
85 G_DEFINE_TYPE (EvApplication, ev_application, G_TYPE_OBJECT);
86
87 #ifdef ENABLE_DBUS
88 #define APPLICATION_DBUS_OBJECT_PATH "/org/gnome/evince/Evince"
89 #define APPLICATION_DBUS_INTERFACE   "org.gnome.evince.Application"
90 #endif
91
92 static const gchar *userdir = NULL;
93
94 /**
95  * ev_application_get_instance:
96  *
97  * Checks for #EvApplication instance, if it doesn't exist it does create it.
98  *
99  * Returns: an instance of the #EvApplication data.
100  */
101 EvApplication *
102 ev_application_get_instance (void)
103 {
104         if (!instance) {
105                 instance = EV_APPLICATION (g_object_new (EV_TYPE_APPLICATION, NULL));
106         }
107
108         return instance;
109 }
110
111 /* Session */
112 gboolean
113 ev_application_load_session (EvApplication *application)
114 {
115         GKeyFile *state_file;
116         gchar    *uri;
117
118 #ifdef WITH_SMCLIENT
119         if (egg_sm_client_is_resumed (application->smclient)) {
120                 state_file = egg_sm_client_get_state_file (application->smclient);
121                 if (!state_file)
122                         return FALSE;
123         } else
124 #endif /* WITH_SMCLIENT */
125                 return FALSE;
126
127         uri = g_key_file_get_string (state_file, "Evince", "uri", NULL);
128         if (!uri)
129                 return FALSE;
130
131         ev_application_open_uri_at_dest (application, uri,
132                                          gdk_screen_get_default (),
133                                          NULL, 0, NULL,
134                                          GDK_CURRENT_TIME);
135         g_free (uri);
136         g_key_file_free (state_file);
137
138         return TRUE;
139 }
140
141 #ifdef WITH_SMCLIENT
142
143 static void
144 smclient_save_state_cb (EggSMClient   *client,
145                         GKeyFile      *state_file,
146                         EvApplication *application)
147 {
148         if (!application->uri)
149                 return;
150
151         g_key_file_set_string (state_file, "Evince", "uri", application->uri);
152 }
153
154 static void
155 smclient_quit_cb (EggSMClient   *client,
156                   EvApplication *application)
157 {
158         ev_application_shutdown (application);
159 }
160 #endif /* WITH_SMCLIENT */
161
162 static void
163 ev_application_init_session (EvApplication *application)
164 {
165 #ifdef WITH_SMCLIENT
166         application->smclient = egg_sm_client_get ();
167         g_signal_connect (application->smclient, "save_state",
168                           G_CALLBACK (smclient_save_state_cb),
169                           application);
170         g_signal_connect (application->smclient, "quit",
171                           G_CALLBACK (smclient_quit_cb),
172                           application);
173 #endif
174 }
175
176 /**
177  * ev_display_open_if_needed:
178  * @name: the name of the display to be open if it's needed.
179  *
180  * Search among all the open displays if any of them have the same name as the
181  * passed name. If the display isn't found it tries the open it.
182  *
183  * Returns: a #GdkDisplay of the display with the passed name.
184  */
185 static GdkDisplay *
186 ev_display_open_if_needed (const gchar *name)
187 {
188         GSList     *displays;
189         GSList     *l;
190         GdkDisplay *display = NULL;
191
192         displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
193
194         for (l = displays; l != NULL; l = l->next) {
195                 const gchar *display_name = gdk_display_get_name ((GdkDisplay *) l->data);
196
197                 if (g_ascii_strcasecmp (display_name, name) == 0) {
198                         display = l->data;
199                         break;
200                 }
201         }
202
203         g_slist_free (displays);
204
205         return display != NULL ? display : gdk_display_open (name);
206 }
207
208 static void
209 child_setup (gpointer user_data)
210 {
211         gchar *startup_id;
212
213         startup_id = g_strdup_printf ("_TIME%lu",
214                                       (unsigned long)GPOINTER_TO_INT (user_data));
215         g_setenv ("DESKTOP_STARTUP_ID", startup_id, TRUE);
216         g_free (startup_id);
217 }
218
219 static void
220 ev_spawn (const char     *uri,
221           GdkScreen      *screen,
222           EvLinkDest     *dest,
223           EvWindowRunMode mode,
224           const gchar    *search_string,
225           guint           timestamp)
226 {
227         gchar   *argv[6];
228         guint    arg = 0;
229         gint     i;
230         gboolean res;
231         GError  *error = NULL;
232
233 #ifdef G_OS_WIN32
234 {
235         gchar *dir;
236
237         dir = g_win32_get_package_installation_directory_of_module (NULL);
238         argv[arg++] = g_build_filename (dir, "bin", "evince", NULL);
239         g_free (dir);
240 }
241 #else
242         argv[arg++] = g_build_filename (BINDIR, "evince", NULL);
243 #endif
244
245         /* Page label */
246         if (dest) {
247                 const gchar *page_label;
248
249                 page_label = ev_link_dest_get_page_label (dest);
250                 if (page_label)
251                         argv[arg++] = g_strdup_printf ("--page-label=%s", page_label);
252                 else
253                         argv[arg++] = g_strdup_printf ("--page-label=%d",
254                                                        ev_link_dest_get_page (dest));
255         }
256
257         /* Find string */
258         if (search_string) {
259                 argv[arg++] = g_strdup_printf ("--find=%s", search_string);
260         }
261
262         /* Mode */
263         switch (mode) {
264         case EV_WINDOW_MODE_FULLSCREEN:
265                 argv[arg++] = g_strdup ("-f");
266                 break;
267         case EV_WINDOW_MODE_PRESENTATION:
268                 argv[arg++] = g_strdup ("-s");
269                 break;
270         default:
271                 break;
272         }
273
274         argv[arg++] = (gchar *)uri;
275         argv[arg] = NULL;
276
277         res = gdk_spawn_on_screen (screen, NULL /* wd */, argv, NULL /* env */,
278                                    0,
279                                    child_setup,
280                                    GINT_TO_POINTER(timestamp),
281                                    NULL, &error);
282         if (!res) {
283                 g_warning ("Error launching evince %s: %s\n", uri, error->message);
284                 g_error_free (error);
285         }
286
287         for (i = 0; i < arg - 1; i++) {
288                 g_free (argv[i]);
289         }
290 }
291
292 static GList *
293 ev_application_get_windows (EvApplication *application)
294 {
295         GList *l, *toplevels;
296         GList *windows = NULL;
297
298         toplevels = gtk_window_list_toplevels ();
299
300         for (l = toplevels; l != NULL; l = l->next) {
301                 if (EV_IS_WINDOW (l->data)) {
302                         windows = g_list_append (windows, l->data);
303                 }
304         }
305
306         g_list_free (toplevels);
307
308         return windows;
309 }
310
311 static EvWindow *
312 ev_application_get_empty_window (EvApplication *application,
313                                  GdkScreen     *screen)
314 {
315         EvWindow *empty_window = NULL;
316         GList    *windows = ev_application_get_windows (application);
317         GList    *l;
318
319         for (l = windows; l != NULL; l = l->next) {
320                 EvWindow *window = EV_WINDOW (l->data);
321
322                 if (ev_window_is_empty (window) &&
323                     gtk_window_get_screen (GTK_WINDOW (window)) == screen) {
324                         empty_window = window;
325                         break;
326                 }
327         }
328
329         g_list_free (windows);
330
331         return empty_window;
332 }
333
334
335 #ifdef ENABLE_DBUS
336 /*
337  * ev_application_register_uri:
338  * @application:
339  * @uri:
340  * @screen:
341  * @dest:
342  * @mode:
343  * @search_string:
344  * @timestamp:
345  *
346  * Registers @uri with evince-daemon.
347  *
348  * Returns: %TRUE to continue by opening @uri in this instance,
349  *   or %FALSE if the request was forwarded to an existing evince
350  *   instance for @uri
351  */
352 static gboolean
353 ev_application_register_uri (EvApplication *application,
354                              const gchar   *uri,
355                              GdkScreen      *screen,
356                              EvLinkDest     *dest,
357                              EvWindowRunMode mode,
358                              const gchar    *search_string,
359                              guint          timestamp)
360 {
361         GVariant *value, *value2;
362         const gchar *owner;
363         GVariantBuilder builder;
364         GError *error = NULL;
365
366         if (!application->connection)
367                 return TRUE;
368
369         /* FIXME: Don't make sync dbus calls, they block the UI! */
370         value = g_dbus_connection_call_sync
371                    (application->connection,
372                     "org.gnome.evince.Daemon",
373                     "/org/gnome/evince/Daemon",
374                     "org.gnome.evince.Daemon",
375                     "RegisterDocument",
376                     g_variant_new ("(s)", uri),
377                     G_VARIANT_TYPE ("(s)"),
378                     G_DBUS_CALL_FLAGS_NONE,
379                     -1,
380                     NULL,
381                     &error);
382         if (value == NULL) {
383                 g_warning ("Error registering document: %s\n", error->message);
384                 g_error_free (error);
385                 return TRUE;
386         }
387
388         g_variant_get (value, "(&s)", &owner);
389
390         /* This means that the document wasn't already registered; go
391          * ahead with opening it.
392          */
393         if (owner[0] == '\0') {
394                 g_variant_unref (value);
395                 return TRUE;
396         }
397
398         /* Already registered */
399         g_variant_builder_init (&builder, G_VARIANT_TYPE ("(sa{sv}u)"));
400         g_variant_builder_add (&builder, "s", uri);
401
402         g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{sv}"));
403         g_variant_builder_add (&builder, "{sv}",
404                                "display",
405                                g_variant_new_string (gdk_display_get_name (gdk_screen_get_display (screen))));
406         g_variant_builder_add (&builder, "{sv}",
407                                "screen",
408                                g_variant_new_int32 (gdk_screen_get_number (screen)));
409         if (dest) {
410                 g_variant_builder_add (&builder, "{sv}",
411                                        "page-label",
412                                        g_variant_new_string (ev_link_dest_get_page_label (dest)));
413         }
414         if (search_string) {
415                 g_variant_builder_add (&builder, "{sv}",
416                                        "find-string",
417                                        g_variant_new_string (search_string));
418         }
419         if (mode != EV_WINDOW_MODE_NORMAL) {
420                 g_variant_builder_add (&builder, "{sv}",
421                                        "mode",
422                                        g_variant_new_uint32 (mode));
423         }
424         g_variant_builder_close (&builder);
425
426         g_variant_builder_add (&builder, "u", timestamp);
427
428         value2 = g_dbus_connection_call_sync
429                     (application->connection,
430                      owner,
431                      APPLICATION_DBUS_OBJECT_PATH,
432                      APPLICATION_DBUS_INTERFACE,
433                      "OpenURI",
434                      g_variant_builder_end (&builder),
435                      NULL,
436                      G_DBUS_CALL_FLAGS_NONE,
437                      -1,
438                      NULL,
439                      &error);
440         if (value2 == NULL) {
441                 g_warning ("Failed to OpenURI: %s", error->message);
442                 g_error_free (error);
443                 return FALSE;
444         }
445
446         g_variant_unref (value);
447         g_variant_unref (value2);
448
449         /* Do not continue opening this document */
450         return FALSE;
451 }
452
453 static void
454 ev_application_unregister_uri (EvApplication *application,
455                                const gchar   *uri)
456 {
457         GVariant *value;
458         GError *error = NULL;
459
460         if (!application->connection)
461                 return;
462
463         /* FIXME: Don't make sync dbus calls, they block the UI! */
464         value = g_dbus_connection_call_sync
465                    (application->connection,
466                     "org.gnome.evince.Daemon",
467                     "/org/gnome/evince/Daemon",
468                     "org.gnome.evince.Daemon",
469                     "UnregisterDocument",
470                     g_variant_new ("(s)", uri),
471                     NULL,
472                     G_DBUS_CALL_FLAGS_NO_AUTO_START,
473                     -1,
474                     NULL,
475                     &error);
476         if (value == NULL) {
477                 g_warning ("Error unregistering document: %s\n", error->message);
478                 g_error_free (error);
479         } else {
480                 g_variant_unref (value);
481         }
482 }
483 #endif /* ENABLE_DBUS */
484
485 static void
486 ev_application_open_uri_in_window (EvApplication  *application,
487                                    const char     *uri,
488                                    EvWindow       *ev_window,
489                                    GdkScreen      *screen,
490                                    EvLinkDest     *dest,
491                                    EvWindowRunMode mode,
492                                    const gchar    *search_string,
493                                    guint           timestamp)
494 {
495 #ifdef GDK_WINDOWING_X11
496         GdkWindow *gdk_window;
497 #endif
498
499         if (screen) {
500                 ev_stock_icons_set_screen (screen);
501                 gtk_window_set_screen (GTK_WINDOW (ev_window), screen);
502         }
503
504         /* We need to load uri before showing the window, so
505            we can restore window size without flickering */
506         ev_window_open_uri (ev_window, uri, dest, mode, search_string);
507
508         if (!gtk_widget_get_realized (GTK_WIDGET (ev_window)))
509                 gtk_widget_realize (GTK_WIDGET (ev_window));
510
511 #ifdef GDK_WINDOWING_X11
512         gdk_window = gtk_widget_get_window (GTK_WIDGET (ev_window));
513
514         if (timestamp <= 0)
515                 timestamp = gdk_x11_get_server_time (gdk_window);
516         gdk_x11_window_set_user_time (gdk_window, timestamp);
517
518         gtk_window_present (GTK_WINDOW (ev_window));
519 #else
520         gtk_window_present_with_time (GTK_WINDOW (ev_window), timestamp);
521 #endif /* GDK_WINDOWING_X11 */
522 }
523
524 /**
525  * ev_application_open_uri_at_dest:
526  * @application: The instance of the application.
527  * @uri: The uri to be opened.
528  * @screen: Thee screen where the link will be shown.
529  * @dest: The #EvLinkDest of the document.
530  * @mode: The run mode of the window.
531  * @timestamp: Current time value.
532  */
533 void
534 ev_application_open_uri_at_dest (EvApplication  *application,
535                                  const char     *uri,
536                                  GdkScreen      *screen,
537                                  EvLinkDest     *dest,
538                                  EvWindowRunMode mode,
539                                  const gchar    *search_string,
540                                  guint           timestamp)
541 {
542         EvWindow *ev_window;
543
544         g_return_if_fail (uri != NULL);
545
546         if (application->uri && strcmp (application->uri, uri) != 0) {
547                 /* spawn a new evince process */
548                 ev_spawn (uri, screen, dest, mode, search_string, timestamp);
549                 return;
550         } else {
551 #ifdef ENABLE_DBUS
552                 gboolean    ret;
553
554                 /* Register the uri or send OpenURI to
555                  * remote instance if already registered
556                  */
557                 ret = ev_application_register_uri (application, uri, screen, dest, mode, search_string, timestamp);
558                 if (!ret)
559                         return;
560 #endif /* ENABLE_DBUS */
561
562                 ev_window = ev_application_get_empty_window (application, screen);
563                 if (!ev_window)
564                         ev_window = EV_WINDOW (ev_window_new ());
565         }
566
567         application->uri = g_strdup (uri);
568
569         ev_application_open_uri_in_window (application, uri, ev_window,
570                                            screen, dest, mode,
571                                            search_string,
572                                            timestamp);
573 }
574
575 /**
576  * ev_application_open_window:
577  * @application: The instance of the application.
578  * @timestamp: Current time value.
579  *
580  * Creates a new window
581  */
582 void
583 ev_application_open_window (EvApplication *application,
584                             GdkScreen     *screen,
585                             guint32        timestamp)
586 {
587         GtkWidget *new_window = ev_window_new ();
588 #ifdef GDK_WINDOWING_X11
589         GdkWindow *gdk_window;
590 #endif
591
592         if (screen) {
593                 ev_stock_icons_set_screen (screen);
594                 gtk_window_set_screen (GTK_WINDOW (new_window), screen);
595         }
596
597         if (!gtk_widget_get_realized (new_window))
598                 gtk_widget_realize (new_window);
599
600 #ifdef GDK_WINDOWING_X11
601         gdk_window = gtk_widget_get_window (GTK_WIDGET (new_window));
602
603         if (timestamp <= 0)
604                 timestamp = gdk_x11_get_server_time (gdk_window);
605         gdk_x11_window_set_user_time (gdk_window, timestamp);
606
607         gtk_window_present (GTK_WINDOW (new_window));
608 #else
609         gtk_window_present_with_time (GTK_WINDOW (new_window), timestamp);
610 #endif /* GDK_WINDOWING_X11 */
611 }
612
613 static void
614 method_call_cb (GDBusConnection       *connection,
615                 const gchar           *sender,
616                 const gchar           *object_path,
617                 const gchar           *interface_name,
618                 const gchar           *method_name,
619                 GVariant              *parameters,
620                 GDBusMethodInvocation *invocation,
621                 gpointer               user_data)
622 {
623         EvApplication   *application = EV_APPLICATION (user_data);
624         GList           *windows, *l;
625         const gchar     *uri;
626         guint            timestamp;
627         GVariantIter    *iter;
628         const gchar     *key;
629         GVariant        *value;
630         GdkDisplay      *display = NULL;
631         int              screen_number = 0;
632         EvLinkDest      *dest = NULL;
633         EvWindowRunMode  mode = EV_WINDOW_MODE_NORMAL;
634         const gchar     *search_string = NULL;
635         GdkScreen       *screen = NULL;
636
637         if (g_strcmp0 (method_name, "OpenURI") != 0)
638                 return;
639
640         g_variant_get (parameters, "(&sa{sv}u)", &uri, &iter, &timestamp);
641
642         /* FIXME: we don't need uri anymore,
643          * maybe this method should be renamed
644          * as reload, refresh or something like that
645          */
646         if (g_strcmp0 (application->uri, uri) != 0) {
647                 g_dbus_method_invocation_return_error (invocation,
648                                                        G_DBUS_ERROR,
649                                                        G_DBUS_ERROR_INVALID_ARGS,
650                                                        "Unexpected URI \"%s\"",
651                                                        uri);
652                 g_variant_iter_free (iter);
653                 return;
654         }
655
656         while (g_variant_iter_loop (iter, "{&sv}", &key, &value)) {
657                 if (strcmp (key, "display") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
658                         display = ev_display_open_if_needed (g_variant_get_string (value, NULL));
659                 } else if (strcmp (key, "screen") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
660                         screen_number = g_variant_get_int32 (value);
661                 } else if (strcmp (key, "mode") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_UINT32) {
662                         mode = g_variant_get_uint32 (value);
663                 } else if (strcmp (key, "page-label") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
664                         dest = ev_link_dest_new_page_label (g_variant_get_string (value, NULL));
665                 } else if (strcmp (key, "find-string") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
666                         search_string = g_variant_get_string (value, NULL);
667                 }
668         }
669         g_variant_iter_free (iter);
670
671         if (display != NULL &&
672             screen_number >= 0 &&
673             screen_number < gdk_display_get_n_screens (display))
674                 screen = gdk_display_get_screen (display, screen_number);
675         else
676                 screen = gdk_screen_get_default ();
677
678         windows = ev_application_get_windows (application);
679         for (l = windows; l != NULL; l = g_list_next (l)) {
680                 EvWindow *ev_window = EV_WINDOW (l->data);
681
682                 ev_application_open_uri_in_window (application, uri, ev_window,
683                                                    screen, dest, mode,
684                                                    search_string,
685                                                    timestamp);
686         }
687         g_list_free (windows);
688
689         if (dest)
690                 g_object_unref (dest);
691
692         g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
693 }
694
695 void
696 ev_application_open_uri_list (EvApplication *application,
697                               GSList        *uri_list,
698                               GdkScreen     *screen,
699                               guint          timestamp)
700 {
701         GSList *l;
702
703         for (l = uri_list; l != NULL; l = l->next) {
704                 ev_application_open_uri_at_dest (application, (char *)l->data,
705                                                  screen, NULL, 0, NULL,
706                                                  timestamp);
707         }
708 }
709
710 static void
711 ev_application_accel_map_save (EvApplication *application)
712 {
713         gchar *accel_map_file;
714         gchar *tmp_filename;
715         gint   fd;
716
717         if (userdir) {
718                 accel_map_file = g_build_filename (userdir, "accels",
719                                                    "evince", NULL);
720         } else {
721                 accel_map_file = g_build_filename (g_get_home_dir (),
722                                                    ".gnome2", "accels",
723                                                    "evince", NULL);
724         }
725
726         tmp_filename = g_strdup_printf ("%s.XXXXXX", accel_map_file);
727
728         fd = g_mkstemp (tmp_filename);
729         if (fd == -1) {
730                 g_free (accel_map_file);
731                 g_free (tmp_filename);
732
733                 return;
734         }
735         gtk_accel_map_save_fd (fd);
736         close (fd);
737
738         if (g_rename (tmp_filename, accel_map_file) == -1) {
739                 /* FIXME: win32? */
740                 g_unlink (tmp_filename);
741         }
742
743         g_free (accel_map_file);
744         g_free (tmp_filename);
745 }
746
747 static void
748 ev_application_accel_map_load (EvApplication *application)
749 {
750         gchar *accel_map_file;
751
752         if (userdir) {
753                 accel_map_file = g_build_filename (userdir, "accels",
754                                                    "evince", NULL);
755         } else {
756                 accel_map_file = g_build_filename (g_get_home_dir (),
757                                                    ".gnome2", "accels",
758                                                    "evince", NULL);
759         }
760
761         gtk_accel_map_load (accel_map_file);
762         g_free (accel_map_file);
763 }
764
765 void
766 ev_application_shutdown (EvApplication *application)
767 {
768         if (application->uri) {
769 #ifdef ENABLE_DBUS
770                 ev_application_unregister_uri (application,
771                                                application->uri);
772 #endif
773                 g_free (application->uri);
774                 application->uri = NULL;
775         }
776
777         ev_application_accel_map_save (application);
778
779         g_object_unref (application->scr_saver);
780         application->scr_saver = NULL;
781
782 #ifdef ENABLE_DBUS
783         if (application->keys) {
784                 g_object_unref (application->keys);
785                 application->keys = NULL;
786         }
787         if (application->registration_id != 0) {
788                 g_dbus_connection_unregister_object (application->connection,
789                                                      application->registration_id);
790                 application->registration_id = 0;
791         }
792         if (application->connection != NULL) {
793                 g_object_unref (application->connection);
794                 application->connection = NULL;
795         }
796 #endif /* ENABLE_DBUS */
797         
798         g_free (application->dot_dir);
799         application->dot_dir = NULL;
800         g_free (application->data_dir);
801         application->data_dir = NULL;
802         g_free (application->filechooser_open_uri);
803         application->filechooser_open_uri = NULL;
804         g_free (application->filechooser_save_uri);
805         application->filechooser_save_uri = NULL;
806
807         g_object_unref (application);
808         instance = NULL;
809         
810         gtk_main_quit ();
811 }
812
813 static void
814 ev_application_class_init (EvApplicationClass *ev_application_class)
815 {
816 }
817
818 static void
819 ev_application_init (EvApplication *ev_application)
820 {
821         GError *error = NULL;
822
823         userdir = g_getenv ("GNOME22_USER_DIR");
824         if (userdir)
825                 ev_application->dot_dir = g_build_filename (userdir, "evince", NULL);
826         else
827                 ev_application->dot_dir = g_build_filename (g_get_home_dir (),
828                                                             ".gnome2",
829                                                             "evince",
830                                                             NULL);
831
832 #ifdef G_OS_WIN32
833 {
834         gchar *dir;
835
836         dir = g_win32_get_package_installation_directory_of_module (NULL);
837         ev_application->data_dir = g_build_filename (dir, "share", "evince", NULL);
838         g_free (dir);
839 }
840 #else
841         ev_application->data_dir = g_strdup (DATADIR);
842 #endif
843
844         ev_application_init_session (ev_application);
845
846         ev_application_accel_map_load (ev_application);
847
848 #ifdef ENABLE_DBUS
849 {
850         static const char introspection_xml[] =
851                 "<node>"
852                   "<interface name='org.gnome.evince.Daemon'>"
853                     "<method name='OpenURI'>"
854                       "<arg type='s' name='uri' direction='in'/>"
855                       "<arg type='a{sv}' name='args' direction='in'/>"
856                       "<arg type='u' name='timestamp' direction='in'/>"
857                     "</method>"
858                   "</interface>"
859                 "</node>";
860
861         static const GDBusInterfaceVTable interface_vtable = {
862                 method_call_cb,
863                 NULL,
864                 NULL
865         };
866
867         GDBusNodeInfo *introspection_data;
868
869         ev_application->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
870         if (ev_application->connection != NULL) {
871                 introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
872                 g_assert (introspection_data != NULL);
873
874
875                 ev_application->registration_id =
876                     g_dbus_connection_register_object (ev_application->connection,
877                                                        APPLICATION_DBUS_OBJECT_PATH,
878                                                        introspection_data->interfaces[0],
879                                                        &interface_vtable,
880                                                        ev_application, NULL,
881                                                        &error);
882                 if (ev_application->registration_id == 0) {
883                         g_printerr ("Failed to register bus object: %s\n", error->message);
884                         g_error_free (error);
885                 }
886                 
887         } else {
888                 g_printerr ("Failed to get bus connection: %s\n", error->message);
889                 g_error_free (error);
890         }
891
892         ev_application->keys = ev_media_player_keys_new ();
893
894         ev_application->scr_saver = totem_scrsaver_new ();
895 }
896 #else
897         ev_application->scr_saver = totem_scrsaver_new ();
898 #endif /* ENABLE_DBUS */
899 }
900
901 gboolean
902 ev_application_has_window (EvApplication *application)
903 {
904         GList   *windows = ev_application_get_windows (application);
905         gboolean retval = windows != NULL;
906
907         g_list_free (windows);
908
909         return retval;
910 }
911
912 const gchar *
913 ev_application_get_uri (EvApplication *application)
914 {
915         return application->uri;
916 }
917
918 /**
919  * ev_application_get_media_keys:
920  * @application: The instance of the application.
921  *
922  * It gives you access to the media player keys handler object.
923  *
924  * Returns: A #EvMediaPlayerKeys.
925  */
926 GObject *
927 ev_application_get_media_keys (EvApplication *application)
928 {
929 #ifdef ENABLE_DBUS
930         return G_OBJECT (application->keys);
931 #else
932         return NULL;
933 #endif /* ENABLE_DBUS */
934 }
935
936 void
937 ev_application_set_filechooser_uri (EvApplication       *application,
938                                     GtkFileChooserAction action,
939                                     const gchar         *uri)
940 {
941         if (action == GTK_FILE_CHOOSER_ACTION_OPEN) {
942                 g_free (application->filechooser_open_uri);
943                 application->filechooser_open_uri = g_strdup (uri);
944         } else if (action == GTK_FILE_CHOOSER_ACTION_SAVE) {
945                 g_free (application->filechooser_save_uri);
946                 application->filechooser_save_uri = g_strdup (uri);
947         }
948 }
949
950 const gchar *
951 ev_application_get_filechooser_uri (EvApplication       *application,
952                                     GtkFileChooserAction action)
953 {
954         if (action == GTK_FILE_CHOOSER_ACTION_OPEN) {
955                 if (application->filechooser_open_uri)
956                         return application->filechooser_open_uri;
957         } else if (action == GTK_FILE_CHOOSER_ACTION_SAVE) {
958                 if (application->filechooser_save_uri)
959                         return application->filechooser_save_uri;
960         }
961
962         return NULL;
963 }
964
965 void
966 ev_application_screensaver_enable (EvApplication *application)
967 {
968         totem_scrsaver_enable (application->scr_saver);
969 }
970
971 void
972 ev_application_screensaver_disable (EvApplication *application)
973 {
974         totem_scrsaver_disable (application->scr_saver);
975 }
976
977 const gchar *
978 ev_application_get_dot_dir (EvApplication *application,
979                             gboolean create)
980 {
981         if (create)
982                 g_mkdir_with_parents (application->dot_dir, 0700);
983
984         return application->dot_dir;
985 }
986
987 const gchar *
988 ev_application_get_data_dir (EvApplication   *application)
989 {
990         return application->data_dir;
991 }