]> www.fi.muni.cz Git - evince.git/blob - shell/ev-application.c
[shell] Migrate user config dir to XDG fdo directories spec
[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 void _ev_application_open_uri_at_dest (EvApplication  *application,
95                                               const gchar    *uri,
96                                               GdkScreen      *screen,
97                                               EvLinkDest     *dest,
98                                               EvWindowRunMode mode,
99                                               const gchar    *search_string,
100                                               guint           timestamp);
101 static void ev_application_open_uri_in_window (EvApplication  *application,
102                                                const char     *uri,
103                                                EvWindow       *ev_window,
104                                                GdkScreen      *screen,
105                                                EvLinkDest     *dest,
106                                                EvWindowRunMode mode,
107                                                const gchar    *search_string,
108                                                guint           timestamp);
109
110 /**
111  * ev_application_get_instance:
112  *
113  * Checks for #EvApplication instance, if it doesn't exist it does create it.
114  *
115  * Returns: an instance of the #EvApplication data.
116  */
117 EvApplication *
118 ev_application_get_instance (void)
119 {
120         if (!instance) {
121                 instance = EV_APPLICATION (g_object_new (EV_TYPE_APPLICATION, NULL));
122         }
123
124         return instance;
125 }
126
127 /* Session */
128 gboolean
129 ev_application_load_session (EvApplication *application)
130 {
131         GKeyFile *state_file;
132         gchar    *uri;
133
134 #ifdef WITH_SMCLIENT
135         if (egg_sm_client_is_resumed (application->smclient)) {
136                 state_file = egg_sm_client_get_state_file (application->smclient);
137                 if (!state_file)
138                         return FALSE;
139         } else
140 #endif /* WITH_SMCLIENT */
141                 return FALSE;
142
143         uri = g_key_file_get_string (state_file, "Evince", "uri", NULL);
144         if (!uri)
145                 return FALSE;
146
147         ev_application_open_uri_at_dest (application, uri,
148                                          gdk_screen_get_default (),
149                                          NULL, 0, NULL,
150                                          GDK_CURRENT_TIME);
151         g_free (uri);
152         g_key_file_free (state_file);
153
154         return TRUE;
155 }
156
157 #ifdef WITH_SMCLIENT
158
159 static void
160 smclient_save_state_cb (EggSMClient   *client,
161                         GKeyFile      *state_file,
162                         EvApplication *application)
163 {
164         if (!application->uri)
165                 return;
166
167         g_key_file_set_string (state_file, "Evince", "uri", application->uri);
168 }
169
170 static void
171 smclient_quit_cb (EggSMClient   *client,
172                   EvApplication *application)
173 {
174         ev_application_shutdown (application);
175 }
176 #endif /* WITH_SMCLIENT */
177
178 static void
179 ev_application_init_session (EvApplication *application)
180 {
181 #ifdef WITH_SMCLIENT
182         application->smclient = egg_sm_client_get ();
183         g_signal_connect (application->smclient, "save_state",
184                           G_CALLBACK (smclient_save_state_cb),
185                           application);
186         g_signal_connect (application->smclient, "quit",
187                           G_CALLBACK (smclient_quit_cb),
188                           application);
189 #endif
190 }
191
192 /**
193  * ev_display_open_if_needed:
194  * @name: the name of the display to be open if it's needed.
195  *
196  * Search among all the open displays if any of them have the same name as the
197  * passed name. If the display isn't found it tries the open it.
198  *
199  * Returns: a #GdkDisplay of the display with the passed name.
200  */
201 static GdkDisplay *
202 ev_display_open_if_needed (const gchar *name)
203 {
204         GSList     *displays;
205         GSList     *l;
206         GdkDisplay *display = NULL;
207
208         displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
209
210         for (l = displays; l != NULL; l = l->next) {
211                 const gchar *display_name = gdk_display_get_name ((GdkDisplay *) l->data);
212
213                 if (g_ascii_strcasecmp (display_name, name) == 0) {
214                         display = l->data;
215                         break;
216                 }
217         }
218
219         g_slist_free (displays);
220
221         return display != NULL ? display : gdk_display_open (name);
222 }
223
224 static void
225 child_setup (gpointer user_data)
226 {
227         gchar *startup_id;
228
229         startup_id = g_strdup_printf ("_TIME%lu",
230                                       (unsigned long)GPOINTER_TO_INT (user_data));
231         g_setenv ("DESKTOP_STARTUP_ID", startup_id, TRUE);
232         g_free (startup_id);
233 }
234
235 static void
236 ev_spawn (const char     *uri,
237           GdkScreen      *screen,
238           EvLinkDest     *dest,
239           EvWindowRunMode mode,
240           const gchar    *search_string,
241           guint           timestamp)
242 {
243         gchar   *argv[6];
244         guint    arg = 0;
245         gint     i;
246         gboolean res;
247         GError  *error = NULL;
248
249 #ifdef G_OS_WIN32
250 {
251         gchar *dir;
252
253         dir = g_win32_get_package_installation_directory_of_module (NULL);
254         argv[arg++] = g_build_filename (dir, "bin", "evince", NULL);
255         g_free (dir);
256 }
257 #else
258         argv[arg++] = g_build_filename (BINDIR, "evince", NULL);
259 #endif
260
261         /* Page label */
262         if (dest) {
263                 const gchar *page_label;
264
265                 page_label = ev_link_dest_get_page_label (dest);
266                 if (page_label)
267                         argv[arg++] = g_strdup_printf ("--page-label=%s", page_label);
268                 else
269                         argv[arg++] = g_strdup_printf ("--page-label=%d",
270                                                        ev_link_dest_get_page (dest));
271         }
272
273         /* Find string */
274         if (search_string) {
275                 argv[arg++] = g_strdup_printf ("--find=%s", search_string);
276         }
277
278         /* Mode */
279         switch (mode) {
280         case EV_WINDOW_MODE_FULLSCREEN:
281                 argv[arg++] = g_strdup ("-f");
282                 break;
283         case EV_WINDOW_MODE_PRESENTATION:
284                 argv[arg++] = g_strdup ("-s");
285                 break;
286         default:
287                 break;
288         }
289
290         argv[arg++] = (gchar *)uri;
291         argv[arg] = NULL;
292
293         res = gdk_spawn_on_screen (screen, NULL /* wd */, argv, NULL /* env */,
294                                    0,
295                                    child_setup,
296                                    GINT_TO_POINTER(timestamp),
297                                    NULL, &error);
298         if (!res) {
299                 g_warning ("Error launching evince %s: %s\n", uri, error->message);
300                 g_error_free (error);
301         }
302
303         for (i = 0; i < arg - 1; i++) {
304                 g_free (argv[i]);
305         }
306 }
307
308 static GList *
309 ev_application_get_windows (EvApplication *application)
310 {
311         GList *l, *toplevels;
312         GList *windows = NULL;
313
314         toplevels = gtk_window_list_toplevels ();
315
316         for (l = toplevels; l != NULL; l = l->next) {
317                 if (EV_IS_WINDOW (l->data)) {
318                         windows = g_list_append (windows, l->data);
319                 }
320         }
321
322         g_list_free (toplevels);
323
324         return windows;
325 }
326
327 static EvWindow *
328 ev_application_get_empty_window (EvApplication *application,
329                                  GdkScreen     *screen)
330 {
331         EvWindow *empty_window = NULL;
332         GList    *windows = ev_application_get_windows (application);
333         GList    *l;
334
335         for (l = windows; l != NULL; l = l->next) {
336                 EvWindow *window = EV_WINDOW (l->data);
337
338                 if (ev_window_is_empty (window) &&
339                     gtk_window_get_screen (GTK_WINDOW (window)) == screen) {
340                         empty_window = window;
341                         break;
342                 }
343         }
344
345         g_list_free (windows);
346
347         return empty_window;
348 }
349
350
351 #ifdef ENABLE_DBUS
352 typedef struct {
353         gchar          *uri;
354         GdkScreen      *screen;
355         EvLinkDest     *dest;
356         EvWindowRunMode mode;
357         gchar          *search_string;
358         guint           timestamp;
359 } EvRegisterDocData;
360
361 static void
362 ev_register_doc_data_free (EvRegisterDocData *data)
363 {
364         if (!data)
365                 return;
366
367         g_free (data->uri);
368         if (data->search_string)
369                 g_free (data->search_string);
370         if (data->dest)
371                 g_object_unref (data->dest);
372
373         g_free (data);
374 }
375
376 static void
377 on_reload_cb (GObject      *source_object,
378               GAsyncResult *res,
379               gpointer      user_data)
380 {
381         GDBusConnection *connection = G_DBUS_CONNECTION (source_object);
382         GVariant        *value;
383         GError          *error = NULL;
384
385         value = g_dbus_connection_call_finish (connection, res, &error);
386         if (!value) {
387                 g_warning ("Failed to Reload: %s", error->message);
388                 g_error_free (error);
389         }
390         g_variant_unref (value);
391
392         ev_application_shutdown (EV_APP);
393 }
394
395 static void
396 on_register_uri_cb (GObject      *source_object,
397                     GAsyncResult *res,
398                     gpointer      user_data)
399 {
400         GDBusConnection   *connection = G_DBUS_CONNECTION (source_object);
401         EvRegisterDocData *data = (EvRegisterDocData *)user_data;
402         EvApplication     *application = EV_APP;
403         GVariant          *value;
404         const gchar       *owner;
405         GVariantBuilder    builder;
406         GError            *error = NULL;
407
408         value = g_dbus_connection_call_finish (connection, res, &error);
409         if (!value) {
410                 g_warning ("Error registering document: %s\n", error->message);
411                 g_error_free (error);
412
413                 _ev_application_open_uri_at_dest (application,
414                                                   data->uri,
415                                                   data->screen,
416                                                   data->dest,
417                                                   data->mode,
418                                                   data->search_string,
419                                                   data->timestamp);
420                 ev_register_doc_data_free (data);
421
422                 return;
423         }
424
425         g_variant_get (value, "(&s)", &owner);
426
427         /* This means that the document wasn't already registered; go
428          * ahead with opening it.
429          */
430         if (owner[0] == '\0') {
431                 g_variant_unref (value);
432
433                 application->doc_registered = TRUE;
434
435                 _ev_application_open_uri_at_dest (application,
436                                                   data->uri,
437                                                   data->screen,
438                                                   data->dest,
439                                                   data->mode,
440                                                   data->search_string,
441                                                   data->timestamp);
442                 ev_register_doc_data_free (data);
443
444                 return;
445         }
446
447         /* Already registered */
448         g_variant_builder_init (&builder, G_VARIANT_TYPE ("(a{sv}u)"));
449         g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{sv}"));
450         g_variant_builder_add (&builder, "{sv}",
451                                "display",
452                                g_variant_new_string (gdk_display_get_name (gdk_screen_get_display (data->screen))));
453         g_variant_builder_add (&builder, "{sv}",
454                                "screen",
455                                g_variant_new_int32 (gdk_screen_get_number (data->screen)));
456         if (data->dest) {
457                 g_variant_builder_add (&builder, "{sv}",
458                                        "page-label",
459                                        g_variant_new_string (ev_link_dest_get_page_label (data->dest)));
460         }
461         if (data->search_string) {
462                 g_variant_builder_add (&builder, "{sv}",
463                                        "find-string",
464                                        g_variant_new_string (data->search_string));
465         }
466         if (data->mode != EV_WINDOW_MODE_NORMAL) {
467                 g_variant_builder_add (&builder, "{sv}",
468                                        "mode",
469                                        g_variant_new_uint32 (data->mode));
470         }
471         g_variant_builder_close (&builder);
472
473         g_variant_builder_add (&builder, "u", data->timestamp);
474
475         g_dbus_connection_call (connection,
476                                 owner,
477                                 APPLICATION_DBUS_OBJECT_PATH,
478                                 APPLICATION_DBUS_INTERFACE,
479                                 "Reload",
480                                 g_variant_builder_end (&builder),
481                                 NULL,
482                                 G_DBUS_CALL_FLAGS_NONE,
483                                 -1,
484                                 NULL,
485                                 on_reload_cb,
486                                 NULL);
487         g_variant_unref (value);
488         ev_register_doc_data_free (data);
489 }
490
491 /*
492  * ev_application_register_uri:
493  * @application:
494  * @uri:
495  * @screen:
496  * @dest:
497  * @mode:
498  * @search_string:
499  * @timestamp:
500  *
501  * Registers @uri with evince-daemon.
502  *
503  */
504 static void
505 ev_application_register_uri (EvApplication  *application,
506                              const gchar    *uri,
507                              GdkScreen      *screen,
508                              EvLinkDest     *dest,
509                              EvWindowRunMode mode,
510                              const gchar    *search_string,
511                              guint           timestamp)
512 {
513         EvRegisterDocData *data;
514
515         if (!application->connection)
516                 return;
517
518         if (application->doc_registered) {
519                 /* Already registered, reload */
520                 GList *windows, *l;
521
522                 windows = ev_application_get_windows (application);
523                 for (l = windows; l != NULL; l = g_list_next (l)) {
524                         EvWindow *ev_window = EV_WINDOW (l->data);
525
526                         ev_application_open_uri_in_window (application, uri, ev_window,
527                                                            screen, dest, mode,
528                                                            search_string,
529                                                            timestamp);
530                 }
531                 g_list_free (windows);
532
533                 return;
534         }
535
536         data = g_new (EvRegisterDocData, 1);
537         data->uri = g_strdup (uri);
538         data->screen = screen;
539         data->dest = dest ? g_object_ref (dest) : NULL;
540         data->mode = mode;
541         data->search_string = search_string ? g_strdup (search_string) : NULL;
542         data->timestamp = timestamp;
543
544         g_dbus_connection_call (application->connection,
545                                 EVINCE_DAEMON_SERVICE,
546                                 EVINCE_DAEMON_OBJECT_PATH,
547                                 EVINCE_DAEMON_INTERFACE,
548                                 "RegisterDocument",
549                                 g_variant_new ("(s)", uri),
550                                 G_VARIANT_TYPE ("(s)"),
551                                 G_DBUS_CALL_FLAGS_NONE,
552                                 -1,
553                                 NULL,
554                                 on_register_uri_cb,
555                                 data);
556 }
557
558 static void
559 ev_application_unregister_uri (EvApplication *application,
560                                const gchar   *uri)
561 {
562         GVariant *value;
563         GError   *error = NULL;
564
565         if (!application->doc_registered)
566                 return;
567
568         /* This is called from ev_application_shutdown(),
569          * so it's safe to use the sync api
570          */
571         value = g_dbus_connection_call_sync (
572                 application->connection,
573                 EVINCE_DAEMON_SERVICE,
574                 EVINCE_DAEMON_OBJECT_PATH,
575                 EVINCE_DAEMON_INTERFACE,
576                 "UnregisterDocument",
577                 g_variant_new ("(s)", uri),
578                 NULL,
579                 G_DBUS_CALL_FLAGS_NO_AUTO_START,
580                 -1,
581                 NULL,
582                 &error);
583         if (value == NULL) {
584                 g_warning ("Error unregistering document: %s\n", error->message);
585                 g_error_free (error);
586         } else {
587                 g_variant_unref (value);
588         }
589 }
590 #endif /* ENABLE_DBUS */
591
592 static void
593 ev_application_open_uri_in_window (EvApplication  *application,
594                                    const char     *uri,
595                                    EvWindow       *ev_window,
596                                    GdkScreen      *screen,
597                                    EvLinkDest     *dest,
598                                    EvWindowRunMode mode,
599                                    const gchar    *search_string,
600                                    guint           timestamp)
601 {
602 #ifdef GDK_WINDOWING_X11
603         GdkWindow *gdk_window;
604 #endif
605
606         if (screen) {
607                 ev_stock_icons_set_screen (screen);
608                 gtk_window_set_screen (GTK_WINDOW (ev_window), screen);
609         }
610
611         /* We need to load uri before showing the window, so
612            we can restore window size without flickering */
613         ev_window_open_uri (ev_window, uri, dest, mode, search_string);
614
615         if (!gtk_widget_get_realized (GTK_WIDGET (ev_window)))
616                 gtk_widget_realize (GTK_WIDGET (ev_window));
617
618 #ifdef GDK_WINDOWING_X11
619         gdk_window = gtk_widget_get_window (GTK_WIDGET (ev_window));
620
621         if (timestamp <= 0)
622                 timestamp = gdk_x11_get_server_time (gdk_window);
623         gdk_x11_window_set_user_time (gdk_window, timestamp);
624
625         gtk_window_present (GTK_WINDOW (ev_window));
626 #else
627         gtk_window_present_with_time (GTK_WINDOW (ev_window), timestamp);
628 #endif /* GDK_WINDOWING_X11 */
629 }
630
631 static void
632 _ev_application_open_uri_at_dest (EvApplication  *application,
633                                   const gchar    *uri,
634                                   GdkScreen      *screen,
635                                   EvLinkDest     *dest,
636                                   EvWindowRunMode mode,
637                                   const gchar    *search_string,
638                                   guint           timestamp)
639 {
640         EvWindow *ev_window;
641
642         ev_window = ev_application_get_empty_window (application, screen);
643         if (!ev_window)
644                 ev_window = EV_WINDOW (ev_window_new ());
645
646         ev_application_open_uri_in_window (application, uri, ev_window,
647                                            screen, dest, mode,
648                                            search_string,
649                                            timestamp);
650 }
651
652 /**
653  * ev_application_open_uri_at_dest:
654  * @application: The instance of the application.
655  * @uri: The uri to be opened.
656  * @screen: Thee screen where the link will be shown.
657  * @dest: The #EvLinkDest of the document.
658  * @mode: The run mode of the window.
659  * @timestamp: Current time value.
660  */
661 void
662 ev_application_open_uri_at_dest (EvApplication  *application,
663                                  const char     *uri,
664                                  GdkScreen      *screen,
665                                  EvLinkDest     *dest,
666                                  EvWindowRunMode mode,
667                                  const gchar    *search_string,
668                                  guint           timestamp)
669 {
670         g_return_if_fail (uri != NULL);
671
672         if (application->uri && strcmp (application->uri, uri) != 0) {
673                 /* spawn a new evince process */
674                 ev_spawn (uri, screen, dest, mode, search_string, timestamp);
675                 return;
676         } else if (!application->uri) {
677                 application->uri = g_strdup (uri);
678         }
679
680 #ifdef ENABLE_DBUS
681         /* Register the uri or send Reload to
682          * remote instance if already registered
683          */
684         ev_application_register_uri (application, uri, screen, dest, mode, search_string, timestamp);
685 #else
686         _ev_application_open_uri_at_dest (application, uri, screen, dest, mode, search_string, timestamp);
687 #endif /* ENABLE_DBUS */
688 }
689
690 /**
691  * ev_application_open_window:
692  * @application: The instance of the application.
693  * @timestamp: Current time value.
694  *
695  * Creates a new window
696  */
697 void
698 ev_application_open_window (EvApplication *application,
699                             GdkScreen     *screen,
700                             guint32        timestamp)
701 {
702         GtkWidget *new_window = ev_window_new ();
703 #ifdef GDK_WINDOWING_X11
704         GdkWindow *gdk_window;
705 #endif
706
707         if (screen) {
708                 ev_stock_icons_set_screen (screen);
709                 gtk_window_set_screen (GTK_WINDOW (new_window), screen);
710         }
711
712         if (!gtk_widget_get_realized (new_window))
713                 gtk_widget_realize (new_window);
714
715 #ifdef GDK_WINDOWING_X11
716         gdk_window = gtk_widget_get_window (GTK_WIDGET (new_window));
717
718         if (timestamp <= 0)
719                 timestamp = gdk_x11_get_server_time (gdk_window);
720         gdk_x11_window_set_user_time (gdk_window, timestamp);
721
722         gtk_window_present (GTK_WINDOW (new_window));
723 #else
724         gtk_window_present_with_time (GTK_WINDOW (new_window), timestamp);
725 #endif /* GDK_WINDOWING_X11 */
726 }
727
728 #ifdef ENABLE_DBUS
729 static void
730 method_call_cb (GDBusConnection       *connection,
731                 const gchar           *sender,
732                 const gchar           *object_path,
733                 const gchar           *interface_name,
734                 const gchar           *method_name,
735                 GVariant              *parameters,
736                 GDBusMethodInvocation *invocation,
737                 gpointer               user_data)
738 {
739         EvApplication   *application = EV_APPLICATION (user_data);
740         GList           *windows, *l;
741         guint            timestamp;
742         GVariantIter    *iter;
743         const gchar     *key;
744         GVariant        *value;
745         GdkDisplay      *display = NULL;
746         int              screen_number = 0;
747         EvLinkDest      *dest = NULL;
748         EvWindowRunMode  mode = EV_WINDOW_MODE_NORMAL;
749         const gchar     *search_string = NULL;
750         GdkScreen       *screen = NULL;
751
752         if (g_strcmp0 (method_name, "Reload") == 0) {
753                 g_variant_get (parameters, "(a{sv}u)", &iter, &timestamp);
754
755                 while (g_variant_iter_loop (iter, "{&sv}", &key, &value)) {
756                         if (strcmp (key, "display") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
757                                 display = ev_display_open_if_needed (g_variant_get_string (value, NULL));
758                         } else if (strcmp (key, "screen") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
759                                 screen_number = g_variant_get_int32 (value);
760                         } else if (strcmp (key, "mode") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_UINT32) {
761                         mode = g_variant_get_uint32 (value);
762                         } else if (strcmp (key, "page-label") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
763                                 dest = ev_link_dest_new_page_label (g_variant_get_string (value, NULL));
764                         } else if (strcmp (key, "find-string") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
765                                 search_string = g_variant_get_string (value, NULL);
766                         }
767                 }
768                 g_variant_iter_free (iter);
769
770                 if (display != NULL &&
771                     screen_number >= 0 &&
772                     screen_number < gdk_display_get_n_screens (display))
773                         screen = gdk_display_get_screen (display, screen_number);
774                 else
775                         screen = gdk_screen_get_default ();
776
777                 windows = ev_application_get_windows (application);
778                 for (l = windows; l != NULL; l = g_list_next (l)) {
779                         EvWindow *ev_window = EV_WINDOW (l->data);
780
781                         ev_application_open_uri_in_window (application, application->uri,
782                                                            ev_window,
783                                                            screen, dest, mode,
784                                                            search_string,
785                                                            timestamp);
786                 }
787                 g_list_free (windows);
788
789                 if (dest)
790                         g_object_unref (dest);
791
792                 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
793         } else if (g_strcmp0 (method_name, "GetWindowList") == 0) {
794                 GList          *windows = ev_application_get_windows (application);
795                 GVariantBuilder builder;
796                 GList          *l;
797
798                 g_variant_builder_init (&builder, G_VARIANT_TYPE ("(ao)"));
799                 g_variant_builder_open (&builder, G_VARIANT_TYPE ("ao"));
800
801                 for (l = windows; l; l = g_list_next (l)) {
802                         EvWindow *window = (EvWindow *)l->data;
803
804                         g_variant_builder_add (&builder, "o", ev_window_get_dbus_object_path (window));
805                 }
806
807                 g_variant_builder_close (&builder);
808                 g_list_free (windows);
809
810                 g_dbus_method_invocation_return_value (invocation, g_variant_builder_end (&builder));
811         }
812 }
813
814 static const char introspection_xml[] =
815         "<node>"
816           "<interface name='org.gnome.evince.Application'>"
817             "<method name='Reload'>"
818               "<arg type='a{sv}' name='args' direction='in'/>"
819               "<arg type='u' name='timestamp' direction='in'/>"
820             "</method>"
821             "<method name='GetWindowList'>"
822               "<arg type='ao' name='window_list' direction='out'/>"
823             "</method>"
824           "</interface>"
825         "</node>";
826
827 static const GDBusInterfaceVTable interface_vtable = {
828         method_call_cb,
829         NULL,
830         NULL
831 };
832
833 static GDBusNodeInfo *introspection_data;
834 #endif /* ENABLE_DBUS */
835
836 void
837 ev_application_open_uri_list (EvApplication *application,
838                               GSList        *uri_list,
839                               GdkScreen     *screen,
840                               guint          timestamp)
841 {
842         GSList *l;
843
844         for (l = uri_list; l != NULL; l = l->next) {
845                 ev_application_open_uri_at_dest (application, (char *)l->data,
846                                                  screen, NULL, 0, NULL,
847                                                  timestamp);
848         }
849 }
850
851 static void
852 ev_application_accel_map_save (EvApplication *application)
853 {
854         gchar *accel_map_file;
855         gchar *tmp_filename;
856         gint   fd;
857
858         accel_map_file = g_build_filename (application->dot_dir, "accels", NULL);
859         tmp_filename = g_strdup_printf ("%s.XXXXXX", accel_map_file);
860
861         fd = g_mkstemp (tmp_filename);
862         if (fd == -1) {
863                 g_free (accel_map_file);
864                 g_free (tmp_filename);
865
866                 return;
867         }
868         gtk_accel_map_save_fd (fd);
869         close (fd);
870
871         g_mkdir_with_parents (application->dot_dir, 0700);
872         if (g_rename (tmp_filename, accel_map_file) == -1) {
873                 /* FIXME: win32? */
874                 g_unlink (tmp_filename);
875         }
876
877         g_free (accel_map_file);
878         g_free (tmp_filename);
879 }
880
881 static void
882 ev_application_accel_map_load (EvApplication *application)
883 {
884         gchar *accel_map_file;
885
886         accel_map_file = g_build_filename (application->dot_dir, "accels", NULL);
887         gtk_accel_map_load (accel_map_file);
888         g_free (accel_map_file);
889 }
890
891 static void
892 ev_application_migrate_config_dir (EvApplication *application)
893 {
894         const gchar        *userdir;
895         gchar              *old_dot_dir;
896         gchar              *old_accels;
897         GError             *error;
898         gint                i;
899         gboolean            dir_created = FALSE;
900         static const gchar *config_files[] = {
901                 "evince_toolbar.xml",
902                 "print-settings",
903                 NULL
904         };
905
906         userdir = g_getenv ("GNOME22_USER_DIR");
907         if (userdir) {
908                 old_dot_dir = g_build_filename (userdir, "evince", NULL);
909                 old_accels = g_build_filename (userdir, "accels", "evince", NULL);
910         } else {
911                 old_dot_dir = g_build_filename (g_get_home_dir (),
912                                                 ".gnome2",
913                                                 "evince",
914                                                 NULL);
915                 old_accels = g_build_filename (g_get_home_dir (),
916                                                ".gnome2", "accels",
917                                                "evince", NULL);
918         }
919
920         if (g_file_test (old_dot_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
921                 for (i = 0; config_files[i]; i++) {
922                         gchar   *old_filename;
923                         gchar   *new_filename;
924                         GFile   *old_file;
925                         GFile   *new_file;
926
927                         old_filename = g_build_filename (old_dot_dir, config_files[i], NULL);
928                         if (!g_file_test (old_filename, G_FILE_TEST_EXISTS)) {
929                                 g_free (old_filename);
930                                 continue;
931                         }
932
933                         if (!dir_created) {
934                                 g_mkdir_with_parents (application->dot_dir, 0700);
935                                 dir_created = TRUE;
936                         }
937
938                         new_filename = g_build_filename (application->dot_dir, config_files[i], NULL);
939                         old_file = g_file_new_for_path (old_filename);
940                         new_file = g_file_new_for_path (new_filename);
941
942                         error = NULL;
943                         g_file_move (old_file, new_file, 0, NULL, NULL, NULL, &error);
944                         if (error) {
945                                 g_warning ("Error migrating config file %s: %s\n",
946                                            old_filename, error->message);
947                                 g_error_free (error);
948                         }
949
950                         g_free (old_filename);
951                         g_free (new_filename);
952                         g_object_unref (old_file);
953                         g_object_unref (new_file);
954                 }
955         }
956
957         g_free (old_dot_dir);
958
959         if (g_file_test (old_accels, G_FILE_TEST_EXISTS)) {
960                 gchar *new_accels;
961                 GFile *old_accels_file;
962                 GFile *new_accels_file;
963
964                 if (!dir_created)
965                         g_mkdir_with_parents (application->dot_dir, 0700);
966
967                 new_accels = g_build_filename (application->dot_dir, "accels", NULL);
968                 old_accels_file = g_file_new_for_path (old_accels);
969                 new_accels_file = g_file_new_for_path (new_accels);
970
971                 error = NULL;
972                 g_file_move (old_accels_file, new_accels_file, 0, NULL, NULL, NULL, &error);
973                 if (error) {
974                         g_warning ("Error migrating accelerator specifications file %s: %s\n",
975                                    old_accels, error->message);
976                         g_error_free (error);
977                 }
978
979                 g_free (new_accels);
980                 g_object_unref (old_accels_file);
981                 g_object_unref (new_accels_file);
982         }
983
984         g_free (old_accels);
985 }
986
987 void
988 ev_application_shutdown (EvApplication *application)
989 {
990         if (application->uri) {
991 #ifdef ENABLE_DBUS
992                 ev_application_unregister_uri (application,
993                                                application->uri);
994 #endif
995                 g_free (application->uri);
996                 application->uri = NULL;
997         }
998
999         ev_application_accel_map_save (application);
1000
1001         g_object_unref (application->scr_saver);
1002         application->scr_saver = NULL;
1003
1004 #ifdef ENABLE_DBUS
1005         if (application->keys) {
1006                 g_object_unref (application->keys);
1007                 application->keys = NULL;
1008         }
1009         if (application->registration_id != 0) {
1010                 g_dbus_connection_unregister_object (application->connection,
1011                                                      application->registration_id);
1012                 application->registration_id = 0;
1013         }
1014         if (application->connection != NULL) {
1015                 g_object_unref (application->connection);
1016                 application->connection = NULL;
1017         }
1018         if (introspection_data) {
1019                 g_dbus_node_info_ref (introspection_data);
1020                 introspection_data = NULL;
1021         }
1022 #endif /* ENABLE_DBUS */
1023         
1024         g_free (application->dot_dir);
1025         application->dot_dir = NULL;
1026         g_free (application->data_dir);
1027         application->data_dir = NULL;
1028         g_free (application->filechooser_open_uri);
1029         application->filechooser_open_uri = NULL;
1030         g_free (application->filechooser_save_uri);
1031         application->filechooser_save_uri = NULL;
1032
1033         g_object_unref (application);
1034         instance = NULL;
1035         
1036         gtk_main_quit ();
1037 }
1038
1039 static void
1040 ev_application_class_init (EvApplicationClass *ev_application_class)
1041 {
1042 }
1043
1044 static void
1045 ev_application_init (EvApplication *ev_application)
1046 {
1047         GError *error = NULL;
1048
1049         ev_application->dot_dir = g_build_filename (g_get_user_config_dir (),
1050                                                     "evince", NULL);
1051         if (!g_file_test (ev_application->dot_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
1052                 ev_application_migrate_config_dir (ev_application);
1053
1054 #ifdef G_OS_WIN32
1055 {
1056         gchar *dir;
1057
1058         dir = g_win32_get_package_installation_directory_of_module (NULL);
1059         ev_application->data_dir = g_build_filename (dir, "share", "evince", NULL);
1060         g_free (dir);
1061 }
1062 #else
1063         ev_application->data_dir = g_strdup (EVINCEDATADIR);
1064 #endif
1065
1066         ev_application_init_session (ev_application);
1067
1068         ev_application_accel_map_load (ev_application);
1069
1070 #ifdef ENABLE_DBUS
1071         ev_application->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
1072         if (ev_application->connection != NULL) {
1073                 introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
1074                 g_assert (introspection_data != NULL);
1075
1076                 ev_application->registration_id =
1077                     g_dbus_connection_register_object (ev_application->connection,
1078                                                        APPLICATION_DBUS_OBJECT_PATH,
1079                                                        introspection_data->interfaces[0],
1080                                                        &interface_vtable,
1081                                                        ev_application, NULL,
1082                                                        &error);
1083                 if (ev_application->registration_id == 0) {
1084                         g_printerr ("Failed to register bus object: %s\n", error->message);
1085                         g_error_free (error);
1086                 }
1087         } else {
1088                 g_printerr ("Failed to get bus connection: %s\n", error->message);
1089                 g_error_free (error);
1090         }
1091
1092         ev_application->keys = ev_media_player_keys_new ();
1093 #endif /* ENABLE_DBUS */
1094
1095         ev_application->scr_saver = totem_scrsaver_new ();
1096         g_object_set (ev_application->scr_saver,
1097                       "reason", _("Running in presentation mode"),
1098                       NULL);
1099 }
1100
1101 GDBusConnection *
1102 ev_application_get_dbus_connection (EvApplication *application)
1103 {
1104 #ifdef ENABLE_DBUS
1105         return application->connection;
1106 #else
1107         return NULL;
1108 #endif
1109 }
1110
1111 gboolean
1112 ev_application_has_window (EvApplication *application)
1113 {
1114         GList    *l, *toplevels;
1115         gboolean  retval = FALSE;
1116
1117         toplevels = gtk_window_list_toplevels ();
1118
1119         for (l = toplevels; l != NULL && !retval; l = l->next) {
1120                 if (EV_IS_WINDOW (l->data))
1121                         retval = TRUE;
1122         }
1123
1124         g_list_free (toplevels);
1125
1126         return retval;
1127 }
1128
1129 guint
1130 ev_application_get_n_windows (EvApplication *application)
1131 {
1132         GList *l, *toplevels;
1133         guint  retval = 0;
1134
1135         toplevels = gtk_window_list_toplevels ();
1136
1137         for (l = toplevels; l != NULL; l = l->next) {
1138                 if (EV_IS_WINDOW (l->data))
1139                         retval++;
1140         }
1141
1142         g_list_free (toplevels);
1143
1144         return retval;
1145 }
1146
1147 const gchar *
1148 ev_application_get_uri (EvApplication *application)
1149 {
1150         return application->uri;
1151 }
1152
1153 /**
1154  * ev_application_get_media_keys:
1155  * @application: The instance of the application.
1156  *
1157  * It gives you access to the media player keys handler object.
1158  *
1159  * Returns: A #EvMediaPlayerKeys.
1160  */
1161 GObject *
1162 ev_application_get_media_keys (EvApplication *application)
1163 {
1164 #ifdef ENABLE_DBUS
1165         return G_OBJECT (application->keys);
1166 #else
1167         return NULL;
1168 #endif /* ENABLE_DBUS */
1169 }
1170
1171 void
1172 ev_application_set_filechooser_uri (EvApplication       *application,
1173                                     GtkFileChooserAction action,
1174                                     const gchar         *uri)
1175 {
1176         if (action == GTK_FILE_CHOOSER_ACTION_OPEN) {
1177                 g_free (application->filechooser_open_uri);
1178                 application->filechooser_open_uri = g_strdup (uri);
1179         } else if (action == GTK_FILE_CHOOSER_ACTION_SAVE) {
1180                 g_free (application->filechooser_save_uri);
1181                 application->filechooser_save_uri = g_strdup (uri);
1182         }
1183 }
1184
1185 const gchar *
1186 ev_application_get_filechooser_uri (EvApplication       *application,
1187                                     GtkFileChooserAction action)
1188 {
1189         if (action == GTK_FILE_CHOOSER_ACTION_OPEN) {
1190                 if (application->filechooser_open_uri)
1191                         return application->filechooser_open_uri;
1192         } else if (action == GTK_FILE_CHOOSER_ACTION_SAVE) {
1193                 if (application->filechooser_save_uri)
1194                         return application->filechooser_save_uri;
1195         }
1196
1197         return NULL;
1198 }
1199
1200 void
1201 ev_application_screensaver_enable (EvApplication *application)
1202 {
1203         totem_scrsaver_enable (application->scr_saver);
1204 }
1205
1206 void
1207 ev_application_screensaver_disable (EvApplication *application)
1208 {
1209         totem_scrsaver_disable (application->scr_saver);
1210 }
1211
1212 const gchar *
1213 ev_application_get_dot_dir (EvApplication *application,
1214                             gboolean create)
1215 {
1216         if (create)
1217                 g_mkdir_with_parents (application->dot_dir, 0700);
1218
1219         return application->dot_dir;
1220 }
1221
1222 const gchar *
1223 ev_application_get_data_dir (EvApplication   *application)
1224 {
1225         return application->data_dir;
1226 }