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