]> www.fi.muni.cz Git - evince.git/blob - shell/ev-application.c
[shell] Free dbus introspection data on application shutdown
[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  *  Copyright © 2010 Christian Persch
5  *
6  *  Author:
7  *    Martin Kretzschmar <martink@gnome.org>
8  *
9  * Evince is free software; you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Evince is distributed in the hope that it will be useful, but
15  * WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22  */
23
24
25 #include <config.h>
26 #include <stdlib.h>
27 #include <string.h>
28
29 #include <glib.h>
30 #include <glib/gi18n.h>
31 #include <glib/gstdio.h>
32 #include <gtk/gtk.h>
33 #ifdef GDK_WINDOWING_X11
34 #include <gdk/gdkx.h>
35 #endif
36 #include <unistd.h>
37
38 #include "totem-scrsaver.h"
39
40 #ifdef WITH_SMCLIENT
41 #include "eggsmclient.h"
42 #endif
43
44 #include "ev-application.h"
45 #include "ev-file-helpers.h"
46 #include "ev-stock-icons.h"
47
48 #ifdef ENABLE_DBUS
49 #include "ev-media-player-keys.h"
50 #endif /* ENABLE_DBUS */
51
52 struct _EvApplication {
53         GObject base_instance;
54
55         gchar *uri;
56
57         gchar *dot_dir;
58         gchar *data_dir;
59
60 #ifdef ENABLE_DBUS
61         GDBusConnection *connection;
62         guint registration_id;
63         EvMediaPlayerKeys *keys;
64         gboolean doc_registered;
65 #endif
66
67         TotemScrsaver *scr_saver;
68
69 #ifdef WITH_SMCLIENT
70         EggSMClient *smclient;
71 #endif
72
73         gchar *filechooser_open_uri;
74         gchar *filechooser_save_uri;
75 };
76
77 struct _EvApplicationClass {
78         GObjectClass base_class;
79 };
80
81 static EvApplication *instance;
82
83 G_DEFINE_TYPE (EvApplication, ev_application, G_TYPE_OBJECT);
84
85 #ifdef ENABLE_DBUS
86 #define APPLICATION_DBUS_OBJECT_PATH "/org/gnome/evince/Evince"
87 #define APPLICATION_DBUS_INTERFACE   "org.gnome.evince.Application"
88
89 #define EVINCE_DAEMON_SERVICE        "org.gnome.evince.Daemon"
90 #define EVINCE_DAEMON_OBJECT_PATH    "/org/gnome/evince/Daemon"
91 #define EVINCE_DAEMON_INTERFACE      "org.gnome.evince.Daemon"
92 #endif
93
94 static const gchar *userdir = NULL;
95
96 static void _ev_application_open_uri_at_dest (EvApplication  *application,
97                                               const gchar    *uri,
98                                               GdkScreen      *screen,
99                                               EvLinkDest     *dest,
100                                               EvWindowRunMode mode,
101                                               const gchar    *search_string,
102                                               guint           timestamp);
103 static void ev_application_open_uri_in_window (EvApplication  *application,
104                                                const char     *uri,
105                                                EvWindow       *ev_window,
106                                                GdkScreen      *screen,
107                                                EvLinkDest     *dest,
108                                                EvWindowRunMode mode,
109                                                const gchar    *search_string,
110                                                guint           timestamp);
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 static void
227 child_setup (gpointer user_data)
228 {
229         gchar *startup_id;
230
231         startup_id = g_strdup_printf ("_TIME%lu",
232                                       (unsigned long)GPOINTER_TO_INT (user_data));
233         g_setenv ("DESKTOP_STARTUP_ID", startup_id, TRUE);
234         g_free (startup_id);
235 }
236
237 static void
238 ev_spawn (const char     *uri,
239           GdkScreen      *screen,
240           EvLinkDest     *dest,
241           EvWindowRunMode mode,
242           const gchar    *search_string,
243           guint           timestamp)
244 {
245         gchar   *argv[6];
246         guint    arg = 0;
247         gint     i;
248         gboolean res;
249         GError  *error = NULL;
250
251 #ifdef G_OS_WIN32
252 {
253         gchar *dir;
254
255         dir = g_win32_get_package_installation_directory_of_module (NULL);
256         argv[arg++] = g_build_filename (dir, "bin", "evince", NULL);
257         g_free (dir);
258 }
259 #else
260         argv[arg++] = g_build_filename (BINDIR, "evince", NULL);
261 #endif
262
263         /* Page label */
264         if (dest) {
265                 const gchar *page_label;
266
267                 page_label = ev_link_dest_get_page_label (dest);
268                 if (page_label)
269                         argv[arg++] = g_strdup_printf ("--page-label=%s", page_label);
270                 else
271                         argv[arg++] = g_strdup_printf ("--page-label=%d",
272                                                        ev_link_dest_get_page (dest));
273         }
274
275         /* Find string */
276         if (search_string) {
277                 argv[arg++] = g_strdup_printf ("--find=%s", search_string);
278         }
279
280         /* Mode */
281         switch (mode) {
282         case EV_WINDOW_MODE_FULLSCREEN:
283                 argv[arg++] = g_strdup ("-f");
284                 break;
285         case EV_WINDOW_MODE_PRESENTATION:
286                 argv[arg++] = g_strdup ("-s");
287                 break;
288         default:
289                 break;
290         }
291
292         argv[arg++] = (gchar *)uri;
293         argv[arg] = NULL;
294
295         res = gdk_spawn_on_screen (screen, NULL /* wd */, argv, NULL /* env */,
296                                    0,
297                                    child_setup,
298                                    GINT_TO_POINTER(timestamp),
299                                    NULL, &error);
300         if (!res) {
301                 g_warning ("Error launching evince %s: %s\n", uri, error->message);
302                 g_error_free (error);
303         }
304
305         for (i = 0; i < arg - 1; i++) {
306                 g_free (argv[i]);
307         }
308 }
309
310 static GList *
311 ev_application_get_windows (EvApplication *application)
312 {
313         GList *l, *toplevels;
314         GList *windows = NULL;
315
316         toplevels = gtk_window_list_toplevels ();
317
318         for (l = toplevels; l != NULL; l = l->next) {
319                 if (EV_IS_WINDOW (l->data)) {
320                         windows = g_list_append (windows, l->data);
321                 }
322         }
323
324         g_list_free (toplevels);
325
326         return windows;
327 }
328
329 static EvWindow *
330 ev_application_get_empty_window (EvApplication *application,
331                                  GdkScreen     *screen)
332 {
333         EvWindow *empty_window = NULL;
334         GList    *windows = ev_application_get_windows (application);
335         GList    *l;
336
337         for (l = windows; l != NULL; l = l->next) {
338                 EvWindow *window = EV_WINDOW (l->data);
339
340                 if (ev_window_is_empty (window) &&
341                     gtk_window_get_screen (GTK_WINDOW (window)) == screen) {
342                         empty_window = window;
343                         break;
344                 }
345         }
346
347         g_list_free (windows);
348
349         return empty_window;
350 }
351
352
353 #ifdef ENABLE_DBUS
354 typedef struct {
355         gchar          *uri;
356         GdkScreen      *screen;
357         EvLinkDest     *dest;
358         EvWindowRunMode mode;
359         gchar          *search_string;
360         guint           timestamp;
361 } EvRegisterDocData;
362
363 static void
364 ev_register_doc_data_free (EvRegisterDocData *data)
365 {
366         if (!data)
367                 return;
368
369         g_free (data->uri);
370         if (data->search_string)
371                 g_free (data->search_string);
372         if (data->dest)
373                 g_object_unref (data->dest);
374
375         g_free (data);
376 }
377
378 static void
379 on_open_uri_cb (GObject      *source_object,
380                 GAsyncResult *res,
381                 gpointer      user_data)
382 {
383         GDBusConnection *connection = G_DBUS_CONNECTION (source_object);
384         GVariant        *value;
385         GError          *error = NULL;
386
387         value = g_dbus_connection_call_finish (connection, res, &error);
388         if (!value) {
389                 g_warning ("Failed to OpenURI: %s", error->message);
390                 g_error_free (error);
391         }
392         g_variant_unref (value);
393
394         ev_application_shutdown (EV_APP);
395 }
396
397 static void
398 on_register_uri_cb (GObject      *source_object,
399                     GAsyncResult *res,
400                     gpointer      user_data)
401 {
402         GDBusConnection   *connection = G_DBUS_CONNECTION (source_object);
403         EvRegisterDocData *data = (EvRegisterDocData *)user_data;
404         EvApplication     *application = EV_APP;
405         GVariant          *value;
406         const gchar       *owner;
407         GVariantBuilder    builder;
408         GError            *error = NULL;
409
410         value = g_dbus_connection_call_finish (connection, res, &error);
411         if (!value) {
412                 g_warning ("Error registering document: %s\n", error->message);
413                 g_error_free (error);
414
415                 _ev_application_open_uri_at_dest (application,
416                                                   data->uri,
417                                                   data->screen,
418                                                   data->dest,
419                                                   data->mode,
420                                                   data->search_string,
421                                                   data->timestamp);
422                 ev_register_doc_data_free (data);
423
424                 return;
425         }
426
427         g_variant_get (value, "(&s)", &owner);
428
429         /* This means that the document wasn't already registered; go
430          * ahead with opening it.
431          */
432         if (owner[0] == '\0') {
433                 g_variant_unref (value);
434
435                 application->doc_registered = TRUE;
436
437                 _ev_application_open_uri_at_dest (application,
438                                                   data->uri,
439                                                   data->screen,
440                                                   data->dest,
441                                                   data->mode,
442                                                   data->search_string,
443                                                   data->timestamp);
444                 ev_register_doc_data_free (data);
445
446                 return;
447         }
448
449         /* Already registered */
450         g_variant_builder_init (&builder, G_VARIANT_TYPE ("(sa{sv}u)"));
451         g_variant_builder_add (&builder, "s", data->uri);
452
453         g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{sv}"));
454         g_variant_builder_add (&builder, "{sv}",
455                                "display",
456                                g_variant_new_string (gdk_display_get_name (gdk_screen_get_display (data->screen))));
457         g_variant_builder_add (&builder, "{sv}",
458                                "screen",
459                                g_variant_new_int32 (gdk_screen_get_number (data->screen)));
460         if (data->dest) {
461                 g_variant_builder_add (&builder, "{sv}",
462                                        "page-label",
463                                        g_variant_new_string (ev_link_dest_get_page_label (data->dest)));
464         }
465         if (data->search_string) {
466                 g_variant_builder_add (&builder, "{sv}",
467                                        "find-string",
468                                        g_variant_new_string (data->search_string));
469         }
470         if (data->mode != EV_WINDOW_MODE_NORMAL) {
471                 g_variant_builder_add (&builder, "{sv}",
472                                        "mode",
473                                        g_variant_new_uint32 (data->mode));
474         }
475         g_variant_builder_close (&builder);
476
477         g_variant_builder_add (&builder, "u", data->timestamp);
478
479         g_dbus_connection_call (connection,
480                                 owner,
481                                 APPLICATION_DBUS_OBJECT_PATH,
482                                 APPLICATION_DBUS_INTERFACE,
483                                 "OpenURI",
484                                 g_variant_builder_end (&builder),
485                                 NULL,
486                                 G_DBUS_CALL_FLAGS_NONE,
487                                 -1,
488                                 NULL,
489                                 on_open_uri_cb,
490                                 NULL);
491         g_variant_unref (value);
492         ev_register_doc_data_free (data);
493 }
494
495 /*
496  * ev_application_register_uri:
497  * @application:
498  * @uri:
499  * @screen:
500  * @dest:
501  * @mode:
502  * @search_string:
503  * @timestamp:
504  *
505  * Registers @uri with evince-daemon.
506  *
507  */
508 static void
509 ev_application_register_uri (EvApplication  *application,
510                              const gchar    *uri,
511                              GdkScreen      *screen,
512                              EvLinkDest     *dest,
513                              EvWindowRunMode mode,
514                              const gchar    *search_string,
515                              guint           timestamp)
516 {
517         EvRegisterDocData *data;
518
519         if (!application->connection)
520                 return;
521
522         if (application->doc_registered) {
523                 /* Already registered, reload */
524                 GList *windows, *l;
525
526                 windows = ev_application_get_windows (application);
527                 for (l = windows; l != NULL; l = g_list_next (l)) {
528                         EvWindow *ev_window = EV_WINDOW (l->data);
529
530                         ev_application_open_uri_in_window (application, uri, ev_window,
531                                                            screen, dest, mode,
532                                                            search_string,
533                                                            timestamp);
534                 }
535                 g_list_free (windows);
536
537                 return;
538         }
539
540         data = g_new (EvRegisterDocData, 1);
541         data->uri = g_strdup (uri);
542         data->screen = screen;
543         data->dest = dest ? g_object_ref (dest) : NULL;
544         data->mode = mode;
545         data->search_string = search_string ? g_strdup (search_string) : NULL;
546         data->timestamp = timestamp;
547
548         g_dbus_connection_call (application->connection,
549                                 EVINCE_DAEMON_SERVICE,
550                                 EVINCE_DAEMON_OBJECT_PATH,
551                                 EVINCE_DAEMON_INTERFACE,
552                                 "RegisterDocument",
553                                 g_variant_new ("(s)", uri),
554                                 G_VARIANT_TYPE ("(s)"),
555                                 G_DBUS_CALL_FLAGS_NONE,
556                                 -1,
557                                 NULL,
558                                 on_register_uri_cb,
559                                 data);
560 }
561
562 static void
563 ev_application_unregister_uri (EvApplication *application,
564                                const gchar   *uri)
565 {
566         GVariant *value;
567         GError   *error = NULL;
568
569         if (!application->doc_registered)
570                 return;
571
572         /* This is called from ev_application_shutdown(),
573          * so it's safe to use the sync api
574          */
575         value = g_dbus_connection_call_sync (
576                 application->connection,
577                 EVINCE_DAEMON_SERVICE,
578                 EVINCE_DAEMON_OBJECT_PATH,
579                 EVINCE_DAEMON_INTERFACE,
580                 "UnregisterDocument",
581                 g_variant_new ("(s)", uri),
582                 NULL,
583                 G_DBUS_CALL_FLAGS_NO_AUTO_START,
584                 -1,
585                 NULL,
586                 &error);
587         if (value == NULL) {
588                 g_warning ("Error unregistering document: %s\n", error->message);
589                 g_error_free (error);
590         } else {
591                 g_variant_unref (value);
592         }
593 }
594 #endif /* ENABLE_DBUS */
595
596 static void
597 ev_application_open_uri_in_window (EvApplication  *application,
598                                    const char     *uri,
599                                    EvWindow       *ev_window,
600                                    GdkScreen      *screen,
601                                    EvLinkDest     *dest,
602                                    EvWindowRunMode mode,
603                                    const gchar    *search_string,
604                                    guint           timestamp)
605 {
606 #ifdef GDK_WINDOWING_X11
607         GdkWindow *gdk_window;
608 #endif
609
610         if (screen) {
611                 ev_stock_icons_set_screen (screen);
612                 gtk_window_set_screen (GTK_WINDOW (ev_window), screen);
613         }
614
615         /* We need to load uri before showing the window, so
616            we can restore window size without flickering */
617         ev_window_open_uri (ev_window, uri, dest, mode, search_string);
618
619         if (!gtk_widget_get_realized (GTK_WIDGET (ev_window)))
620                 gtk_widget_realize (GTK_WIDGET (ev_window));
621
622 #ifdef GDK_WINDOWING_X11
623         gdk_window = gtk_widget_get_window (GTK_WIDGET (ev_window));
624
625         if (timestamp <= 0)
626                 timestamp = gdk_x11_get_server_time (gdk_window);
627         gdk_x11_window_set_user_time (gdk_window, timestamp);
628
629         gtk_window_present (GTK_WINDOW (ev_window));
630 #else
631         gtk_window_present_with_time (GTK_WINDOW (ev_window), timestamp);
632 #endif /* GDK_WINDOWING_X11 */
633 }
634
635 static void
636 _ev_application_open_uri_at_dest (EvApplication  *application,
637                                   const gchar    *uri,
638                                   GdkScreen      *screen,
639                                   EvLinkDest     *dest,
640                                   EvWindowRunMode mode,
641                                   const gchar    *search_string,
642                                   guint           timestamp)
643 {
644         EvWindow *ev_window;
645
646         ev_window = ev_application_get_empty_window (application, screen);
647         if (!ev_window)
648                 ev_window = EV_WINDOW (ev_window_new ());
649
650         ev_application_open_uri_in_window (application, uri, ev_window,
651                                            screen, dest, mode,
652                                            search_string,
653                                            timestamp);
654 }
655
656 /**
657  * ev_application_open_uri_at_dest:
658  * @application: The instance of the application.
659  * @uri: The uri to be opened.
660  * @screen: Thee screen where the link will be shown.
661  * @dest: The #EvLinkDest of the document.
662  * @mode: The run mode of the window.
663  * @timestamp: Current time value.
664  */
665 void
666 ev_application_open_uri_at_dest (EvApplication  *application,
667                                  const char     *uri,
668                                  GdkScreen      *screen,
669                                  EvLinkDest     *dest,
670                                  EvWindowRunMode mode,
671                                  const gchar    *search_string,
672                                  guint           timestamp)
673 {
674         g_return_if_fail (uri != NULL);
675
676         if (application->uri && strcmp (application->uri, uri) != 0) {
677                 /* spawn a new evince process */
678                 ev_spawn (uri, screen, dest, mode, search_string, timestamp);
679                 return;
680         } else if (!application->uri) {
681                 application->uri = g_strdup (uri);
682         }
683
684 #ifdef ENABLE_DBUS
685         /* Register the uri or send OpenURI to
686          * remote instance if already registered
687          */
688         ev_application_register_uri (application, uri, screen, dest, mode, search_string, timestamp);
689 #else
690         _ev_application_open_uri_at_dest (application, uri, screen, dest, mode, search_string, timestamp);
691 #endif /* ENABLE_DBUS */
692 }
693
694 /**
695  * ev_application_open_window:
696  * @application: The instance of the application.
697  * @timestamp: Current time value.
698  *
699  * Creates a new window
700  */
701 void
702 ev_application_open_window (EvApplication *application,
703                             GdkScreen     *screen,
704                             guint32        timestamp)
705 {
706         GtkWidget *new_window = ev_window_new ();
707 #ifdef GDK_WINDOWING_X11
708         GdkWindow *gdk_window;
709 #endif
710
711         if (screen) {
712                 ev_stock_icons_set_screen (screen);
713                 gtk_window_set_screen (GTK_WINDOW (new_window), screen);
714         }
715
716         if (!gtk_widget_get_realized (new_window))
717                 gtk_widget_realize (new_window);
718
719 #ifdef GDK_WINDOWING_X11
720         gdk_window = gtk_widget_get_window (GTK_WIDGET (new_window));
721
722         if (timestamp <= 0)
723                 timestamp = gdk_x11_get_server_time (gdk_window);
724         gdk_x11_window_set_user_time (gdk_window, timestamp);
725
726         gtk_window_present (GTK_WINDOW (new_window));
727 #else
728         gtk_window_present_with_time (GTK_WINDOW (new_window), timestamp);
729 #endif /* GDK_WINDOWING_X11 */
730 }
731
732 #ifdef ENABLE_DBUS
733 static void
734 method_call_cb (GDBusConnection       *connection,
735                 const gchar           *sender,
736                 const gchar           *object_path,
737                 const gchar           *interface_name,
738                 const gchar           *method_name,
739                 GVariant              *parameters,
740                 GDBusMethodInvocation *invocation,
741                 gpointer               user_data)
742 {
743         EvApplication   *application = EV_APPLICATION (user_data);
744         GList           *windows, *l;
745         const gchar     *uri;
746         guint            timestamp;
747         GVariantIter    *iter;
748         const gchar     *key;
749         GVariant        *value;
750         GdkDisplay      *display = NULL;
751         int              screen_number = 0;
752         EvLinkDest      *dest = NULL;
753         EvWindowRunMode  mode = EV_WINDOW_MODE_NORMAL;
754         const gchar     *search_string = NULL;
755         GdkScreen       *screen = NULL;
756
757         if (g_strcmp0 (method_name, "OpenURI") != 0)
758                 return;
759
760         g_variant_get (parameters, "(&sa{sv}u)", &uri, &iter, &timestamp);
761
762         /* FIXME: we don't need uri anymore,
763          * maybe this method should be renamed
764          * as reload, refresh or something like that
765          */
766         if (g_strcmp0 (application->uri, uri) != 0) {
767                 g_dbus_method_invocation_return_error (invocation,
768                                                        G_DBUS_ERROR,
769                                                        G_DBUS_ERROR_INVALID_ARGS,
770                                                        "Unexpected URI \"%s\"",
771                                                        uri);
772                 g_variant_iter_free (iter);
773                 return;
774         }
775
776         while (g_variant_iter_loop (iter, "{&sv}", &key, &value)) {
777                 if (strcmp (key, "display") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
778                         display = ev_display_open_if_needed (g_variant_get_string (value, NULL));
779                 } else if (strcmp (key, "screen") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
780                         screen_number = g_variant_get_int32 (value);
781                 } else if (strcmp (key, "mode") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_UINT32) {
782                         mode = g_variant_get_uint32 (value);
783                 } else if (strcmp (key, "page-label") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
784                         dest = ev_link_dest_new_page_label (g_variant_get_string (value, NULL));
785                 } else if (strcmp (key, "find-string") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
786                         search_string = g_variant_get_string (value, NULL);
787                 }
788         }
789         g_variant_iter_free (iter);
790
791         if (display != NULL &&
792             screen_number >= 0 &&
793             screen_number < gdk_display_get_n_screens (display))
794                 screen = gdk_display_get_screen (display, screen_number);
795         else
796                 screen = gdk_screen_get_default ();
797
798         windows = ev_application_get_windows (application);
799         for (l = windows; l != NULL; l = g_list_next (l)) {
800                 EvWindow *ev_window = EV_WINDOW (l->data);
801
802                 ev_application_open_uri_in_window (application, uri, ev_window,
803                                                    screen, dest, mode,
804                                                    search_string,
805                                                    timestamp);
806         }
807         g_list_free (windows);
808
809         if (dest)
810                 g_object_unref (dest);
811
812         g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
813 }
814
815 static const char introspection_xml[] =
816         "<node>"
817           "<interface name='org.gnome.evince.Application'>"
818             "<method name='OpenURI'>"
819               "<arg type='s' name='uri' direction='in'/>"
820               "<arg type='a{sv}' name='args' direction='in'/>"
821               "<arg type='u' name='timestamp' direction='in'/>"
822             "</method>"
823           "</interface>"
824         "</node>";
825
826 static const GDBusInterfaceVTable interface_vtable = {
827         method_call_cb,
828         NULL,
829         NULL
830 };
831
832 static GDBusNodeInfo *introspection_data;
833 #endif /* ENABLE_DBUS */
834
835 void
836 ev_application_open_uri_list (EvApplication *application,
837                               GSList        *uri_list,
838                               GdkScreen     *screen,
839                               guint          timestamp)
840 {
841         GSList *l;
842
843         for (l = uri_list; l != NULL; l = l->next) {
844                 ev_application_open_uri_at_dest (application, (char *)l->data,
845                                                  screen, NULL, 0, NULL,
846                                                  timestamp);
847         }
848 }
849
850 static void
851 ev_application_accel_map_save (EvApplication *application)
852 {
853         gchar *accel_map_file;
854         gchar *tmp_filename;
855         gint   fd;
856
857         if (userdir) {
858                 accel_map_file = g_build_filename (userdir, "accels",
859                                                    "evince", NULL);
860         } else {
861                 accel_map_file = g_build_filename (g_get_home_dir (),
862                                                    ".gnome2", "accels",
863                                                    "evince", NULL);
864         }
865
866         tmp_filename = g_strdup_printf ("%s.XXXXXX", accel_map_file);
867
868         fd = g_mkstemp (tmp_filename);
869         if (fd == -1) {
870                 g_free (accel_map_file);
871                 g_free (tmp_filename);
872
873                 return;
874         }
875         gtk_accel_map_save_fd (fd);
876         close (fd);
877
878         if (g_rename (tmp_filename, accel_map_file) == -1) {
879                 /* FIXME: win32? */
880                 g_unlink (tmp_filename);
881         }
882
883         g_free (accel_map_file);
884         g_free (tmp_filename);
885 }
886
887 static void
888 ev_application_accel_map_load (EvApplication *application)
889 {
890         gchar *accel_map_file;
891
892         if (userdir) {
893                 accel_map_file = g_build_filename (userdir, "accels",
894                                                    "evince", NULL);
895         } else {
896                 accel_map_file = g_build_filename (g_get_home_dir (),
897                                                    ".gnome2", "accels",
898                                                    "evince", NULL);
899         }
900
901         gtk_accel_map_load (accel_map_file);
902         g_free (accel_map_file);
903 }
904
905 void
906 ev_application_shutdown (EvApplication *application)
907 {
908         if (application->uri) {
909 #ifdef ENABLE_DBUS
910                 ev_application_unregister_uri (application,
911                                                application->uri);
912 #endif
913                 g_free (application->uri);
914                 application->uri = NULL;
915         }
916
917         ev_application_accel_map_save (application);
918
919         g_object_unref (application->scr_saver);
920         application->scr_saver = NULL;
921
922 #ifdef ENABLE_DBUS
923         if (application->keys) {
924                 g_object_unref (application->keys);
925                 application->keys = NULL;
926         }
927         if (application->registration_id != 0) {
928                 g_dbus_connection_unregister_object (application->connection,
929                                                      application->registration_id);
930                 application->registration_id = 0;
931         }
932         if (application->connection != NULL) {
933                 g_object_unref (application->connection);
934                 application->connection = NULL;
935         }
936         if (introspection_data) {
937                 g_dbus_node_info_ref (introspection_data);
938                 introspection_data = NULL;
939         }
940 #endif /* ENABLE_DBUS */
941         
942         g_free (application->dot_dir);
943         application->dot_dir = NULL;
944         g_free (application->data_dir);
945         application->data_dir = NULL;
946         g_free (application->filechooser_open_uri);
947         application->filechooser_open_uri = NULL;
948         g_free (application->filechooser_save_uri);
949         application->filechooser_save_uri = NULL;
950
951         g_object_unref (application);
952         instance = NULL;
953         
954         gtk_main_quit ();
955 }
956
957 static void
958 ev_application_class_init (EvApplicationClass *ev_application_class)
959 {
960 }
961
962 static void
963 ev_application_init (EvApplication *ev_application)
964 {
965         GError *error = NULL;
966
967         userdir = g_getenv ("GNOME22_USER_DIR");
968         if (userdir)
969                 ev_application->dot_dir = g_build_filename (userdir, "evince", NULL);
970         else
971                 ev_application->dot_dir = g_build_filename (g_get_home_dir (),
972                                                             ".gnome2",
973                                                             "evince",
974                                                             NULL);
975
976 #ifdef G_OS_WIN32
977 {
978         gchar *dir;
979
980         dir = g_win32_get_package_installation_directory_of_module (NULL);
981         ev_application->data_dir = g_build_filename (dir, "share", "evince", NULL);
982         g_free (dir);
983 }
984 #else
985         ev_application->data_dir = g_strdup (DATADIR);
986 #endif
987
988         ev_application_init_session (ev_application);
989
990         ev_application_accel_map_load (ev_application);
991
992 #ifdef ENABLE_DBUS
993         ev_application->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
994         if (ev_application->connection != NULL) {
995                 introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
996                 g_assert (introspection_data != NULL);
997
998                 ev_application->registration_id =
999                     g_dbus_connection_register_object (ev_application->connection,
1000                                                        APPLICATION_DBUS_OBJECT_PATH,
1001                                                        introspection_data->interfaces[0],
1002                                                        &interface_vtable,
1003                                                        ev_application, NULL,
1004                                                        &error);
1005                 if (ev_application->registration_id == 0) {
1006                         g_printerr ("Failed to register bus object: %s\n", error->message);
1007                         g_error_free (error);
1008                 }
1009         } else {
1010                 g_printerr ("Failed to get bus connection: %s\n", error->message);
1011                 g_error_free (error);
1012         }
1013
1014         ev_application->keys = ev_media_player_keys_new ();
1015 #endif /* ENABLE_DBUS */
1016
1017         ev_application->scr_saver = totem_scrsaver_new ();
1018         g_object_set (ev_application->scr_saver,
1019                       "reason", _("Running in presentation mode"),
1020                       NULL);
1021 }
1022
1023 gboolean
1024 ev_application_has_window (EvApplication *application)
1025 {
1026         GList   *windows = ev_application_get_windows (application);
1027         gboolean retval = windows != NULL;
1028
1029         g_list_free (windows);
1030
1031         return retval;
1032 }
1033
1034 const gchar *
1035 ev_application_get_uri (EvApplication *application)
1036 {
1037         return application->uri;
1038 }
1039
1040 /**
1041  * ev_application_get_media_keys:
1042  * @application: The instance of the application.
1043  *
1044  * It gives you access to the media player keys handler object.
1045  *
1046  * Returns: A #EvMediaPlayerKeys.
1047  */
1048 GObject *
1049 ev_application_get_media_keys (EvApplication *application)
1050 {
1051 #ifdef ENABLE_DBUS
1052         return G_OBJECT (application->keys);
1053 #else
1054         return NULL;
1055 #endif /* ENABLE_DBUS */
1056 }
1057
1058 void
1059 ev_application_set_filechooser_uri (EvApplication       *application,
1060                                     GtkFileChooserAction action,
1061                                     const gchar         *uri)
1062 {
1063         if (action == GTK_FILE_CHOOSER_ACTION_OPEN) {
1064                 g_free (application->filechooser_open_uri);
1065                 application->filechooser_open_uri = g_strdup (uri);
1066         } else if (action == GTK_FILE_CHOOSER_ACTION_SAVE) {
1067                 g_free (application->filechooser_save_uri);
1068                 application->filechooser_save_uri = g_strdup (uri);
1069         }
1070 }
1071
1072 const gchar *
1073 ev_application_get_filechooser_uri (EvApplication       *application,
1074                                     GtkFileChooserAction action)
1075 {
1076         if (action == GTK_FILE_CHOOSER_ACTION_OPEN) {
1077                 if (application->filechooser_open_uri)
1078                         return application->filechooser_open_uri;
1079         } else if (action == GTK_FILE_CHOOSER_ACTION_SAVE) {
1080                 if (application->filechooser_save_uri)
1081                         return application->filechooser_save_uri;
1082         }
1083
1084         return NULL;
1085 }
1086
1087 void
1088 ev_application_screensaver_enable (EvApplication *application)
1089 {
1090         totem_scrsaver_enable (application->scr_saver);
1091 }
1092
1093 void
1094 ev_application_screensaver_disable (EvApplication *application)
1095 {
1096         totem_scrsaver_disable (application->scr_saver);
1097 }
1098
1099 const gchar *
1100 ev_application_get_dot_dir (EvApplication *application,
1101                             gboolean create)
1102 {
1103         if (create)
1104                 g_mkdir_with_parents (application->dot_dir, 0700);
1105
1106         return application->dot_dir;
1107 }
1108
1109 const gchar *
1110 ev_application_get_data_dir (EvApplication   *application)
1111 {
1112         return application->data_dir;
1113 }