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