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