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