]> www.fi.muni.cz Git - evince.git/blob - shell/ev-application.c
[shell] Port EvApplication to GDBus
[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;
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         value = 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 (value == NULL) {
419                 g_warning ("%s", error->message);
420                 g_error_free (error);
421         }
422
423         g_variant_unref (value);
424
425         /* Do not continue opening this document */
426         return FALSE;
427 }
428
429 static void
430 ev_application_unregister_uri (EvApplication *application,
431                                const gchar   *uri)
432 {
433         GVariant *value;
434         GError *error = NULL;
435
436         if (!application->connection)
437                 return;
438
439         /* FIXME: Don't make sync dbus calls, they block the UI! */
440         value = g_dbus_connection_invoke_method_sync
441                    (application->connection,
442                     "org.gnome.evince.Daemon",
443                     "/org/gnome/evince/Daemon",
444                     "org.gnome.evince.Daemon",
445                     "UnregisterDocument",
446                     g_variant_new ("(s)", uri),
447                     G_DBUS_INVOKE_METHOD_FLAGS_NONE,
448                     -1,
449                     NULL,
450                     &error);
451         if (value == NULL) {
452                 g_warning ("Error unregistering document: %s\n", error->message);
453                 g_error_free (error);
454         } else {
455                 g_variant_unref (value);
456         }
457 }
458 #endif /* ENABLE_DBUS */
459
460 static void
461 ev_application_open_uri_in_window (EvApplication  *application,
462                                    const char     *uri,
463                                    EvWindow       *ev_window,
464                                    GdkScreen      *screen,
465                                    EvLinkDest     *dest,
466                                    EvWindowRunMode mode,
467                                    const gchar    *search_string,
468                                    guint           timestamp)
469 {
470 #ifdef GDK_WINDOWING_X11
471         GdkWindow *gdk_window;
472 #endif
473
474         if (screen) {
475                 ev_stock_icons_set_screen (screen);
476                 gtk_window_set_screen (GTK_WINDOW (ev_window), screen);
477         }
478
479         /* We need to load uri before showing the window, so
480            we can restore window size without flickering */
481         ev_window_open_uri (ev_window, uri, dest, mode, search_string);
482
483         if (!gtk_widget_get_realized (GTK_WIDGET (ev_window)))
484                 gtk_widget_realize (GTK_WIDGET (ev_window));
485
486 #ifdef GDK_WINDOWING_X11
487         gdk_window = gtk_widget_get_window (GTK_WIDGET (ev_window));
488
489         if (timestamp <= 0)
490                 timestamp = gdk_x11_get_server_time (gdk_window);
491         gdk_x11_window_set_user_time (gdk_window, timestamp);
492
493         gtk_window_present (GTK_WINDOW (ev_window));
494 #else
495         gtk_window_present_with_time (GTK_WINDOW (ev_window), timestamp);
496 #endif /* GDK_WINDOWING_X11 */
497 }
498
499 /**
500  * ev_application_open_uri_at_dest:
501  * @application: The instance of the application.
502  * @uri: The uri to be opened.
503  * @screen: Thee screen where the link will be shown.
504  * @dest: The #EvLinkDest of the document.
505  * @mode: The run mode of the window.
506  * @timestamp: Current time value.
507  */
508 void
509 ev_application_open_uri_at_dest (EvApplication  *application,
510                                  const char     *uri,
511                                  GdkScreen      *screen,
512                                  EvLinkDest     *dest,
513                                  EvWindowRunMode mode,
514                                  const gchar    *search_string,
515                                  guint           timestamp)
516 {
517         EvWindow *ev_window;
518
519         g_return_if_fail (uri != NULL);
520
521         if (application->uri && strcmp (application->uri, uri) != 0) {
522                 /* spawn a new evince process */
523                 ev_spawn (uri, screen, dest, mode, search_string, timestamp);
524                 return;
525         } else {
526 #ifdef ENABLE_DBUS
527                 gboolean    ret;
528
529                 /* Register the uri or send OpenURI to
530                  * remote instance if already registered
531                  */
532                 ret = ev_application_register_uri (application, uri, screen, dest, mode, search_string, timestamp);
533                 if (!ret)
534                         return;
535 #endif /* ENABLE_DBUS */
536
537                 ev_window = ev_application_get_empty_window (application, screen);
538                 if (!ev_window)
539                         ev_window = EV_WINDOW (ev_window_new ());
540         }
541
542         application->uri = g_strdup (uri);
543
544         ev_application_open_uri_in_window (application, uri, ev_window,
545                                            screen, dest, mode,
546                                            search_string,
547                                            timestamp);
548 }
549
550 /**
551  * ev_application_open_window:
552  * @application: The instance of the application.
553  * @timestamp: Current time value.
554  *
555  * Creates a new window
556  */
557 void
558 ev_application_open_window (EvApplication *application,
559                             GdkScreen     *screen,
560                             guint32        timestamp)
561 {
562         GtkWidget *new_window = ev_window_new ();
563 #ifdef GDK_WINDOWING_X11
564         GdkWindow *gdk_window;
565 #endif
566
567         if (screen) {
568                 ev_stock_icons_set_screen (screen);
569                 gtk_window_set_screen (GTK_WINDOW (new_window), screen);
570         }
571
572         if (!gtk_widget_get_realized (new_window))
573                 gtk_widget_realize (new_window);
574
575 #ifdef GDK_WINDOWING_X11
576         gdk_window = gtk_widget_get_window (GTK_WIDGET (new_window));
577
578         if (timestamp <= 0)
579                 timestamp = gdk_x11_get_server_time (gdk_window);
580         gdk_x11_window_set_user_time (gdk_window, timestamp);
581
582         gtk_window_present (GTK_WINDOW (new_window));
583 #else
584         gtk_window_present_with_time (GTK_WINDOW (new_window), timestamp);
585 #endif /* GDK_WINDOWING_X11 */
586 }
587
588 static void
589 method_call_cb (GDBusConnection       *connection,
590                 const gchar           *sender,
591                 const gchar           *object_path,
592                 const gchar           *interface_name,
593                 const gchar           *method_name,
594                 GVariant              *parameters,
595                 GDBusMethodInvocation *invocation,
596                 gpointer               user_data)
597 {
598         EvApplication   *application = EV_APPLICATION (user_data);
599         GList           *windows, *l;
600         const gchar     *uri;
601         guint            timestamp;
602         GVariantIter    *iter;
603         const gchar     *key;
604         GVariant        *value;
605         GdkDisplay      *display = NULL;
606         int              screen_number = 0;
607         EvLinkDest      *dest = NULL;
608         EvWindowRunMode  mode = EV_WINDOW_MODE_NORMAL;
609         const gchar     *search_string = NULL;
610         GdkScreen       *screen = NULL;
611
612         if (g_strcmp0 (method_name, "OpenURI") != 0)
613                 return;
614
615         g_variant_get (parameters, "(&sa{sv}u)", &uri, &iter, &timestamp);
616
617         /* FIXME: we don't need uri anymore,
618          * maybe this method should be renamed
619          * as reload, refresh or something like that
620          */
621         if (g_strcmp0 (application->uri, uri) != 0) {
622                 g_dbus_method_invocation_return_error (invocation,
623                                                        G_DBUS_ERROR,
624                                                        G_DBUS_ERROR_INVALID_ARGS,
625                                                        "Unexpected URI \"%s\"",
626                                                        uri);
627                 g_variant_iter_free (iter);
628                 return;
629         }
630
631         while (g_variant_iter_loop (iter, "{sv}", &key, &value)) {
632                 if (strcmp (key, "display") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
633                         display = ev_display_open_if_needed (g_variant_get_string (value, NULL));
634                 } else if (strcmp (key, "screen") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
635                         screen_number = g_variant_get_int32 (value);
636                 } else if (strcmp (key, "mode") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_UINT32) {
637                         mode = g_variant_get_uint32 (value);
638                 } else if (strcmp (key, "page-label") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
639                         dest = ev_link_dest_new_page_label (g_variant_get_string (value, NULL));
640                 } else if (strcmp (key, "find-string") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
641                         search_string = g_variant_get_string (value, NULL);
642                 }
643         }
644         g_variant_iter_free (iter);
645
646         if (display != NULL)
647                 screen = gdk_display_get_screen (display, screen_number);
648         else
649                 screen = gdk_screen_get_default ();
650
651         windows = ev_application_get_windows (application);
652         for (l = windows; l != NULL; l = g_list_next (l)) {
653                 EvWindow *ev_window = EV_WINDOW (l->data);
654
655                 ev_application_open_uri_in_window (application, uri, ev_window,
656                                                    screen, dest, mode,
657                                                    search_string,
658                                                    timestamp);
659         }
660         g_list_free (windows);
661
662         if (dest)
663                 g_object_unref (dest);
664
665         g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
666 }
667
668 void
669 ev_application_open_uri_list (EvApplication *application,
670                               GSList        *uri_list,
671                               GdkScreen     *screen,
672                               guint          timestamp)
673 {
674         GSList *l;
675
676         for (l = uri_list; l != NULL; l = l->next) {
677                 ev_application_open_uri_at_dest (application, (char *)l->data,
678                                                  screen, NULL, 0, NULL,
679                                                  timestamp);
680         }
681 }
682
683 static void
684 ev_application_accel_map_save (EvApplication *application)
685 {
686         gchar *accel_map_file;
687         gchar *tmp_filename;
688         gint   fd;
689
690         if (userdir) {
691                 accel_map_file = g_build_filename (userdir, "accels",
692                                                    "evince", NULL);
693         } else {
694                 accel_map_file = g_build_filename (g_get_home_dir (),
695                                                    ".gnome2", "accels",
696                                                    "evince", NULL);
697         }
698
699         tmp_filename = g_strdup_printf ("%s.XXXXXX", accel_map_file);
700
701         fd = g_mkstemp (tmp_filename);
702         if (fd == -1) {
703                 g_free (accel_map_file);
704                 g_free (tmp_filename);
705
706                 return;
707         }
708         gtk_accel_map_save_fd (fd);
709         close (fd);
710
711         if (g_rename (tmp_filename, accel_map_file) == -1) {
712                 /* FIXME: win32? */
713                 g_unlink (tmp_filename);
714         }
715
716         g_free (accel_map_file);
717         g_free (tmp_filename);
718 }
719
720 static void
721 ev_application_accel_map_load (EvApplication *application)
722 {
723         gchar *accel_map_file;
724
725         if (userdir) {
726                 accel_map_file = g_build_filename (userdir, "accels",
727                                                    "evince", NULL);
728         } else {
729                 accel_map_file = g_build_filename (g_get_home_dir (),
730                                                    ".gnome2", "accels",
731                                                    "evince", NULL);
732         }
733
734         gtk_accel_map_load (accel_map_file);
735         g_free (accel_map_file);
736 }
737
738 void
739 ev_application_shutdown (EvApplication *application)
740 {
741         if (application->uri) {
742 #ifdef ENABLE_DBUS
743                 ev_application_unregister_uri (application,
744                                                application->uri);
745 #endif
746                 g_free (application->uri);
747                 application->uri = NULL;
748         }
749
750         ev_application_accel_map_save (application);
751
752         g_object_unref (application->scr_saver);
753         application->scr_saver = NULL;
754
755 #ifdef ENABLE_DBUS
756         if (application->keys) {
757                 g_object_unref (application->keys);
758                 application->keys = NULL;
759         }
760         if (application->registration_id != 0) {
761                 g_dbus_connection_unregister_object (application->connection,
762                                                      application->registration_id);
763                 application->registration_id = 0;
764         }
765         if (application->connection != NULL) {
766                 g_object_unref (application->connection);
767                 application->connection = NULL;
768         }
769 #endif /* ENABLE_DBUS */
770         
771         g_free (application->dot_dir);
772         application->dot_dir = NULL;
773         g_free (application->data_dir);
774         application->data_dir = NULL;
775         g_free (application->filechooser_open_uri);
776         application->filechooser_open_uri = NULL;
777         g_free (application->filechooser_save_uri);
778         application->filechooser_save_uri = NULL;
779
780         g_object_unref (application);
781         instance = NULL;
782         
783         gtk_main_quit ();
784 }
785
786 static void
787 ev_application_class_init (EvApplicationClass *ev_application_class)
788 {
789 }
790
791 static void
792 ev_application_init (EvApplication *ev_application)
793 {
794         GError *error = NULL;
795
796         userdir = g_getenv ("GNOME22_USER_DIR");
797         if (userdir)
798                 ev_application->dot_dir = g_build_filename (userdir, "evince", NULL);
799         else
800                 ev_application->dot_dir = g_build_filename (g_get_home_dir (),
801                                                             ".gnome2",
802                                                             "evince",
803                                                             NULL);
804
805 #ifdef G_OS_WIN32
806 {
807         gchar *dir;
808
809         dir = g_win32_get_package_installation_directory_of_module (NULL);
810         ev_application->data_dir = g_build_filename (dir, "share", "evince", NULL);
811         g_free (dir);
812 }
813 #else
814         ev_application->data_dir = g_strdup (DATADIR);
815 #endif
816
817         ev_application_init_session (ev_application);
818
819         ev_application_accel_map_load (ev_application);
820
821         ev_application->scr_saver = totem_scrsaver_new ();
822
823 #ifdef ENABLE_DBUS
824 {
825         static const char introspection_xml[] =
826                 "<node>"
827                   "<interface name='org.gnome.evince.Daemon'>"
828                     "<method name='OpenURI'>"
829                       "<arg type='s' name='uri' direction='in'/>"
830                       "<arg type='a{sv}' name='args' direction='in'/>"
831                       "<arg type='u' name='timestamp' direction='in'/>"
832                     "</method>"
833                   "</interface>"
834                 "</node>";
835
836         static const GDBusInterfaceVTable interface_vtable = {
837                 method_call_cb,
838                 NULL,
839                 NULL
840         };
841
842         GDBusNodeInfo *introspection_data;
843
844         ev_application->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
845         if (ev_application->connection != NULL) {
846                 introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
847                 g_assert (introspection_data != NULL);
848
849
850                 ev_application->registration_id =
851                     g_dbus_connection_register_object (ev_application->connection,
852                                                        APPLICATION_DBUS_OBJECT_PATH,
853                                                        APPLICATION_DBUS_INTERFACE,
854                                                        introspection_data->interfaces[0],
855                                                        &interface_vtable,
856                                                        ev_application, NULL,
857                                                        &error);
858                 if (ev_application->registration_id == 0) {
859                         g_printerr ("Failed to register bus object: %s\n", error->message);
860                         g_error_free (error);
861                 }
862                 
863         } else {
864                 g_printerr ("Failed to get bus connection: %s\n", error->message);
865                 g_error_free (error);
866         }
867
868         ev_application->keys = ev_media_player_keys_new ();
869 }
870 #endif /* ENABLE_DBUS */
871 }
872
873 gboolean
874 ev_application_has_window (EvApplication *application)
875 {
876         GList   *windows = ev_application_get_windows (application);
877         gboolean retval = windows != NULL;
878
879         g_list_free (windows);
880
881         return retval;
882 }
883
884 const gchar *
885 ev_application_get_uri (EvApplication *application)
886 {
887         return application->uri;
888 }
889
890 /**
891  * ev_application_get_media_keys:
892  * @application: The instance of the application.
893  *
894  * It gives you access to the media player keys handler object.
895  *
896  * Returns: A #EvMediaPlayerKeys.
897  */
898 GObject *
899 ev_application_get_media_keys (EvApplication *application)
900 {
901 #ifdef ENABLE_DBUS
902         return G_OBJECT (application->keys);
903 #else
904         return NULL;
905 #endif /* ENABLE_DBUS */
906 }
907
908 void
909 ev_application_set_filechooser_uri (EvApplication       *application,
910                                     GtkFileChooserAction action,
911                                     const gchar         *uri)
912 {
913         if (action == GTK_FILE_CHOOSER_ACTION_OPEN) {
914                 g_free (application->filechooser_open_uri);
915                 application->filechooser_open_uri = g_strdup (uri);
916         } else if (action == GTK_FILE_CHOOSER_ACTION_SAVE) {
917                 g_free (application->filechooser_save_uri);
918                 application->filechooser_save_uri = g_strdup (uri);
919         }
920 }
921
922 const gchar *
923 ev_application_get_filechooser_uri (EvApplication       *application,
924                                     GtkFileChooserAction action)
925 {
926         if (action == GTK_FILE_CHOOSER_ACTION_OPEN) {
927                 if (application->filechooser_open_uri)
928                         return application->filechooser_open_uri;
929         } else if (action == GTK_FILE_CHOOSER_ACTION_SAVE) {
930                 if (application->filechooser_save_uri)
931                         return application->filechooser_save_uri;
932         }
933
934         return NULL;
935 }
936
937 void
938 ev_application_screensaver_enable (EvApplication *application)
939 {
940         totem_scrsaver_enable (application->scr_saver);
941 }
942
943 void
944 ev_application_screensaver_disable (EvApplication *application)
945 {
946         totem_scrsaver_disable (application->scr_saver);
947 }
948
949 const gchar *
950 ev_application_get_dot_dir (EvApplication *application,
951                             gboolean create)
952 {
953         if (create)
954                 g_mkdir_with_parents (application->dot_dir, 0700);
955
956         return application->dot_dir;
957 }
958
959 const gchar *
960 ev_application_get_data_dir (EvApplication   *application)
961 {
962         return application->data_dir;
963 }