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