]> www.fi.muni.cz Git - evince.git/blob - shell/ev-application.c
help: updated Makefile.am
[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                 g_variant_builder_add (&builder, "{sv}",
473                                        "page-label",
474                                        g_variant_new_string (ev_link_dest_get_page_label (data->dest)));
475         }
476         if (data->search_string) {
477                 g_variant_builder_add (&builder, "{sv}",
478                                        "find-string",
479                                        g_variant_new_string (data->search_string));
480         }
481         if (data->mode != EV_WINDOW_MODE_NORMAL) {
482                 g_variant_builder_add (&builder, "{sv}",
483                                        "mode",
484                                        g_variant_new_uint32 (data->mode));
485         }
486         g_variant_builder_close (&builder);
487
488         g_variant_builder_add (&builder, "u", data->timestamp);
489
490         g_dbus_connection_call (connection,
491                                 owner,
492                                 APPLICATION_DBUS_OBJECT_PATH,
493                                 APPLICATION_DBUS_INTERFACE,
494                                 "Reload",
495                                 g_variant_builder_end (&builder),
496                                 NULL,
497                                 G_DBUS_CALL_FLAGS_NONE,
498                                 -1,
499                                 NULL,
500                                 on_reload_cb,
501                                 NULL);
502         g_variant_unref (value);
503         ev_register_doc_data_free (data);
504 }
505
506 /*
507  * ev_application_register_uri:
508  * @application:
509  * @uri:
510  * @screen:
511  * @dest:
512  * @mode:
513  * @search_string:
514  * @timestamp:
515  *
516  * Registers @uri with evince-daemon.
517  *
518  */
519 static void
520 ev_application_register_uri (EvApplication  *application,
521                              const gchar    *uri,
522                              GdkScreen      *screen,
523                              EvLinkDest     *dest,
524                              EvWindowRunMode mode,
525                              const gchar    *search_string,
526                              guint           timestamp)
527 {
528         EvRegisterDocData *data;
529
530         if (!application->connection)
531                 return;
532
533         if (application->doc_registered) {
534                 /* Already registered, reload */
535                 GList *windows, *l;
536
537                 windows = ev_application_get_windows (application);
538                 for (l = windows; l != NULL; l = g_list_next (l)) {
539                         EvWindow *ev_window = EV_WINDOW (l->data);
540
541                         ev_application_open_uri_in_window (application, uri, ev_window,
542                                                            screen, dest, mode,
543                                                            search_string,
544                                                            timestamp);
545                 }
546                 g_list_free (windows);
547
548                 return;
549         }
550
551         data = g_new (EvRegisterDocData, 1);
552         data->uri = g_strdup (uri);
553         data->screen = screen;
554         data->dest = dest ? g_object_ref (dest) : NULL;
555         data->mode = mode;
556         data->search_string = search_string ? g_strdup (search_string) : NULL;
557         data->timestamp = timestamp;
558
559         g_dbus_connection_call (application->connection,
560                                 EVINCE_DAEMON_SERVICE,
561                                 EVINCE_DAEMON_OBJECT_PATH,
562                                 EVINCE_DAEMON_INTERFACE,
563                                 "RegisterDocument",
564                                 g_variant_new ("(s)", uri),
565                                 G_VARIANT_TYPE ("(s)"),
566                                 G_DBUS_CALL_FLAGS_NONE,
567                                 -1,
568                                 NULL,
569                                 on_register_uri_cb,
570                                 data);
571 }
572
573 static void
574 ev_application_unregister_uri (EvApplication *application,
575                                const gchar   *uri)
576 {
577         GVariant *value;
578         GError   *error = NULL;
579
580         if (!application->doc_registered)
581                 return;
582
583         /* This is called from ev_application_shutdown(),
584          * so it's safe to use the sync api
585          */
586         value = g_dbus_connection_call_sync (
587                 application->connection,
588                 EVINCE_DAEMON_SERVICE,
589                 EVINCE_DAEMON_OBJECT_PATH,
590                 EVINCE_DAEMON_INTERFACE,
591                 "UnregisterDocument",
592                 g_variant_new ("(s)", uri),
593                 NULL,
594                 G_DBUS_CALL_FLAGS_NO_AUTO_START,
595                 -1,
596                 NULL,
597                 &error);
598         if (value == NULL) {
599                 g_warning ("Error unregistering document: %s\n", error->message);
600                 g_error_free (error);
601         } else {
602                 g_variant_unref (value);
603         }
604 }
605 #endif /* ENABLE_DBUS */
606
607 static void
608 ev_application_open_uri_in_window (EvApplication  *application,
609                                    const char     *uri,
610                                    EvWindow       *ev_window,
611                                    GdkScreen      *screen,
612                                    EvLinkDest     *dest,
613                                    EvWindowRunMode mode,
614                                    const gchar    *search_string,
615                                    guint           timestamp)
616 {
617 #ifdef GDK_WINDOWING_X11
618         GdkWindow *gdk_window;
619 #endif
620
621         if (screen) {
622                 ev_stock_icons_set_screen (screen);
623                 gtk_window_set_screen (GTK_WINDOW (ev_window), screen);
624         }
625
626         /* We need to load uri before showing the window, so
627            we can restore window size without flickering */
628         ev_window_open_uri (ev_window, uri, dest, mode, search_string);
629
630         if (!gtk_widget_get_realized (GTK_WIDGET (ev_window)))
631                 gtk_widget_realize (GTK_WIDGET (ev_window));
632
633 #ifdef GDK_WINDOWING_X11
634         gdk_window = gtk_widget_get_window (GTK_WIDGET (ev_window));
635
636         if (timestamp <= 0)
637                 timestamp = gdk_x11_get_server_time (gdk_window);
638         gdk_x11_window_set_user_time (gdk_window, timestamp);
639
640         gtk_window_present (GTK_WINDOW (ev_window));
641 #else
642         gtk_window_present_with_time (GTK_WINDOW (ev_window), timestamp);
643 #endif /* GDK_WINDOWING_X11 */
644 }
645
646 static void
647 _ev_application_open_uri_at_dest (EvApplication  *application,
648                                   const gchar    *uri,
649                                   GdkScreen      *screen,
650                                   EvLinkDest     *dest,
651                                   EvWindowRunMode mode,
652                                   const gchar    *search_string,
653                                   guint           timestamp)
654 {
655         EvWindow *ev_window;
656
657         ev_window = ev_application_get_empty_window (application, screen);
658         if (!ev_window)
659                 ev_window = EV_WINDOW (ev_window_new ());
660
661         ev_application_open_uri_in_window (application, uri, ev_window,
662                                            screen, dest, mode,
663                                            search_string,
664                                            timestamp);
665 }
666
667 /**
668  * ev_application_open_uri_at_dest:
669  * @application: The instance of the application.
670  * @uri: The uri to be opened.
671  * @screen: Thee screen where the link will be shown.
672  * @dest: The #EvLinkDest of the document.
673  * @mode: The run mode of the window.
674  * @timestamp: Current time value.
675  */
676 void
677 ev_application_open_uri_at_dest (EvApplication  *application,
678                                  const char     *uri,
679                                  GdkScreen      *screen,
680                                  EvLinkDest     *dest,
681                                  EvWindowRunMode mode,
682                                  const gchar    *search_string,
683                                  guint           timestamp)
684 {
685         g_return_if_fail (uri != NULL);
686
687         if (application->uri && strcmp (application->uri, uri) != 0) {
688                 /* spawn a new evince process */
689                 ev_spawn (uri, screen, dest, mode, search_string, timestamp);
690                 return;
691         } else if (!application->uri) {
692                 application->uri = g_strdup (uri);
693         }
694
695 #ifdef ENABLE_DBUS
696         /* Register the uri or send Reload to
697          * remote instance if already registered
698          */
699         ev_application_register_uri (application, uri, screen, dest, mode, search_string, timestamp);
700 #else
701         _ev_application_open_uri_at_dest (application, uri, screen, dest, mode, search_string, timestamp);
702 #endif /* ENABLE_DBUS */
703 }
704
705 /**
706  * ev_application_open_window:
707  * @application: The instance of the application.
708  * @timestamp: Current time value.
709  *
710  * Creates a new window
711  */
712 void
713 ev_application_open_window (EvApplication *application,
714                             GdkScreen     *screen,
715                             guint32        timestamp)
716 {
717         GtkWidget *new_window = ev_window_new ();
718 #ifdef GDK_WINDOWING_X11
719         GdkWindow *gdk_window;
720 #endif
721
722         if (screen) {
723                 ev_stock_icons_set_screen (screen);
724                 gtk_window_set_screen (GTK_WINDOW (new_window), screen);
725         }
726
727         if (!gtk_widget_get_realized (new_window))
728                 gtk_widget_realize (new_window);
729
730 #ifdef GDK_WINDOWING_X11
731         gdk_window = gtk_widget_get_window (GTK_WIDGET (new_window));
732
733         if (timestamp <= 0)
734                 timestamp = gdk_x11_get_server_time (gdk_window);
735         gdk_x11_window_set_user_time (gdk_window, timestamp);
736
737         gtk_window_present (GTK_WINDOW (new_window));
738 #else
739         gtk_window_present_with_time (GTK_WINDOW (new_window), timestamp);
740 #endif /* GDK_WINDOWING_X11 */
741 }
742
743 #ifdef ENABLE_DBUS
744 static void
745 method_call_cb (GDBusConnection       *connection,
746                 const gchar           *sender,
747                 const gchar           *object_path,
748                 const gchar           *interface_name,
749                 const gchar           *method_name,
750                 GVariant              *parameters,
751                 GDBusMethodInvocation *invocation,
752                 gpointer               user_data)
753 {
754         EvApplication   *application = EV_APPLICATION (user_data);
755         GList           *windows, *l;
756         guint            timestamp;
757         GVariantIter    *iter;
758         const gchar     *key;
759         GVariant        *value;
760         GdkDisplay      *display = NULL;
761         int              screen_number = 0;
762         EvLinkDest      *dest = NULL;
763         EvWindowRunMode  mode = EV_WINDOW_MODE_NORMAL;
764         const gchar     *search_string = NULL;
765         GdkScreen       *screen = NULL;
766
767         if (g_strcmp0 (method_name, "Reload") == 0) {
768                 g_variant_get (parameters, "(a{sv}u)", &iter, &timestamp);
769
770                 while (g_variant_iter_loop (iter, "{&sv}", &key, &value)) {
771                         if (strcmp (key, "display") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
772                                 display = ev_display_open_if_needed (g_variant_get_string (value, NULL));
773                         } else if (strcmp (key, "screen") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
774                                 screen_number = g_variant_get_int32 (value);
775                         } else if (strcmp (key, "mode") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_UINT32) {
776                         mode = g_variant_get_uint32 (value);
777                         } else if (strcmp (key, "page-label") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
778                                 dest = ev_link_dest_new_page_label (g_variant_get_string (value, NULL));
779                         } else if (strcmp (key, "find-string") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
780                                 search_string = g_variant_get_string (value, NULL);
781                         }
782                 }
783                 g_variant_iter_free (iter);
784
785                 if (display != NULL &&
786                     screen_number >= 0 &&
787                     screen_number < gdk_display_get_n_screens (display))
788                         screen = gdk_display_get_screen (display, screen_number);
789                 else
790                         screen = gdk_screen_get_default ();
791
792                 windows = ev_application_get_windows (application);
793                 for (l = windows; l != NULL; l = g_list_next (l)) {
794                         EvWindow *ev_window = EV_WINDOW (l->data);
795
796                         ev_application_open_uri_in_window (application, application->uri,
797                                                            ev_window,
798                                                            screen, dest, mode,
799                                                            search_string,
800                                                            timestamp);
801                 }
802                 g_list_free (windows);
803
804                 if (dest)
805                         g_object_unref (dest);
806
807                 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
808         } else if (g_strcmp0 (method_name, "GetWindowList") == 0) {
809                 GList          *windows = ev_application_get_windows (application);
810                 GVariantBuilder builder;
811                 GList          *l;
812
813                 g_variant_builder_init (&builder, G_VARIANT_TYPE ("(ao)"));
814                 g_variant_builder_open (&builder, G_VARIANT_TYPE ("ao"));
815
816                 for (l = windows; l; l = g_list_next (l)) {
817                         EvWindow *window = (EvWindow *)l->data;
818
819                         g_variant_builder_add (&builder, "o", ev_window_get_dbus_object_path (window));
820                 }
821
822                 g_variant_builder_close (&builder);
823                 g_list_free (windows);
824
825                 g_dbus_method_invocation_return_value (invocation, g_variant_builder_end (&builder));
826         }
827 }
828
829 static const char introspection_xml[] =
830         "<node>"
831           "<interface name='org.gnome.evince.Application'>"
832             "<method name='Reload'>"
833               "<arg type='a{sv}' name='args' direction='in'/>"
834               "<arg type='u' name='timestamp' direction='in'/>"
835             "</method>"
836             "<method name='GetWindowList'>"
837               "<arg type='ao' name='window_list' direction='out'/>"
838             "</method>"
839           "</interface>"
840         "</node>";
841
842 static const GDBusInterfaceVTable interface_vtable = {
843         method_call_cb,
844         NULL,
845         NULL
846 };
847
848 static GDBusNodeInfo *introspection_data;
849 #endif /* ENABLE_DBUS */
850
851 void
852 ev_application_open_uri_list (EvApplication *application,
853                               GSList        *uri_list,
854                               GdkScreen     *screen,
855                               guint          timestamp)
856 {
857         GSList *l;
858
859         for (l = uri_list; l != NULL; l = l->next) {
860                 ev_application_open_uri_at_dest (application, (char *)l->data,
861                                                  screen, NULL, 0, NULL,
862                                                  timestamp);
863         }
864 }
865
866 static void
867 ev_application_accel_map_save (EvApplication *application)
868 {
869         gchar *accel_map_file;
870         gchar *tmp_filename;
871         gint   fd;
872
873         accel_map_file = g_build_filename (application->dot_dir, "accels", NULL);
874         tmp_filename = g_strdup_printf ("%s.XXXXXX", accel_map_file);
875
876         fd = g_mkstemp (tmp_filename);
877         if (fd == -1) {
878                 g_free (accel_map_file);
879                 g_free (tmp_filename);
880
881                 return;
882         }
883         gtk_accel_map_save_fd (fd);
884         close (fd);
885
886         g_mkdir_with_parents (application->dot_dir, 0700);
887         if (g_rename (tmp_filename, accel_map_file) == -1) {
888                 /* FIXME: win32? */
889                 g_unlink (tmp_filename);
890         }
891
892         g_free (accel_map_file);
893         g_free (tmp_filename);
894 }
895
896 static void
897 ev_application_accel_map_load (EvApplication *application)
898 {
899         gchar *accel_map_file;
900
901         accel_map_file = g_build_filename (application->dot_dir, "accels", NULL);
902         gtk_accel_map_load (accel_map_file);
903         g_free (accel_map_file);
904 }
905
906 static void
907 ev_application_migrate_config_dir (EvApplication *application)
908 {
909         const gchar        *userdir;
910         gchar              *old_dot_dir;
911         gchar              *old_accels;
912         GError             *error;
913         gint                i;
914         gboolean            dir_created = FALSE;
915         static const gchar *config_files[] = {
916                 "evince_toolbar.xml",
917                 "print-settings",
918                 NULL
919         };
920
921         userdir = g_getenv ("GNOME22_USER_DIR");
922         if (userdir) {
923                 old_dot_dir = g_build_filename (userdir, "evince", NULL);
924                 old_accels = g_build_filename (userdir, "accels", "evince", NULL);
925         } else {
926                 old_dot_dir = g_build_filename (g_get_home_dir (),
927                                                 ".gnome2",
928                                                 "evince",
929                                                 NULL);
930                 old_accels = g_build_filename (g_get_home_dir (),
931                                                ".gnome2", "accels",
932                                                "evince", NULL);
933         }
934
935         if (g_file_test (old_dot_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
936                 for (i = 0; config_files[i]; i++) {
937                         gchar   *old_filename;
938                         gchar   *new_filename;
939                         GFile   *old_file;
940                         GFile   *new_file;
941
942                         old_filename = g_build_filename (old_dot_dir, config_files[i], NULL);
943                         if (!g_file_test (old_filename, G_FILE_TEST_EXISTS)) {
944                                 g_free (old_filename);
945                                 continue;
946                         }
947
948                         if (!dir_created) {
949                                 g_mkdir_with_parents (application->dot_dir, 0700);
950                                 dir_created = TRUE;
951                         }
952
953                         new_filename = g_build_filename (application->dot_dir, config_files[i], NULL);
954                         old_file = g_file_new_for_path (old_filename);
955                         new_file = g_file_new_for_path (new_filename);
956
957                         error = NULL;
958                         g_file_move (old_file, new_file, 0, NULL, NULL, NULL, &error);
959                         if (error) {
960                                 g_warning ("Error migrating config file %s: %s\n",
961                                            old_filename, error->message);
962                                 g_error_free (error);
963                         }
964
965                         g_free (old_filename);
966                         g_free (new_filename);
967                         g_object_unref (old_file);
968                         g_object_unref (new_file);
969                 }
970         }
971
972         g_free (old_dot_dir);
973
974         if (g_file_test (old_accels, G_FILE_TEST_EXISTS)) {
975                 gchar *new_accels;
976                 GFile *old_accels_file;
977                 GFile *new_accels_file;
978
979                 if (!dir_created)
980                         g_mkdir_with_parents (application->dot_dir, 0700);
981
982                 new_accels = g_build_filename (application->dot_dir, "accels", NULL);
983                 old_accels_file = g_file_new_for_path (old_accels);
984                 new_accels_file = g_file_new_for_path (new_accels);
985
986                 error = NULL;
987                 g_file_move (old_accels_file, new_accels_file, 0, NULL, NULL, NULL, &error);
988                 if (error) {
989                         g_warning ("Error migrating accelerator specifications file %s: %s\n",
990                                    old_accels, error->message);
991                         g_error_free (error);
992                 }
993
994                 g_free (new_accels);
995                 g_object_unref (old_accels_file);
996                 g_object_unref (new_accels_file);
997         }
998
999         g_free (old_accels);
1000 }
1001
1002 void
1003 ev_application_shutdown (EvApplication *application)
1004 {
1005         if (application->uri) {
1006 #ifdef ENABLE_DBUS
1007                 ev_application_unregister_uri (application,
1008                                                application->uri);
1009 #endif
1010                 g_free (application->uri);
1011                 application->uri = NULL;
1012         }
1013
1014         ev_application_accel_map_save (application);
1015
1016         g_object_unref (application->scr_saver);
1017         application->scr_saver = NULL;
1018
1019 #ifdef ENABLE_DBUS
1020         if (application->keys) {
1021                 g_object_unref (application->keys);
1022                 application->keys = NULL;
1023         }
1024         if (application->registration_id != 0) {
1025                 g_dbus_connection_unregister_object (application->connection,
1026                                                      application->registration_id);
1027                 application->registration_id = 0;
1028         }
1029         if (application->connection != NULL) {
1030                 g_object_unref (application->connection);
1031                 application->connection = NULL;
1032         }
1033         if (introspection_data) {
1034                 g_dbus_node_info_ref (introspection_data);
1035                 introspection_data = NULL;
1036         }
1037 #endif /* ENABLE_DBUS */
1038         
1039         g_free (application->dot_dir);
1040         application->dot_dir = NULL;
1041         g_free (application->data_dir);
1042         application->data_dir = NULL;
1043         g_free (application->filechooser_open_uri);
1044         application->filechooser_open_uri = NULL;
1045         g_free (application->filechooser_save_uri);
1046         application->filechooser_save_uri = NULL;
1047
1048         g_object_unref (application);
1049         instance = NULL;
1050         
1051         gtk_main_quit ();
1052 }
1053
1054 static void
1055 ev_application_class_init (EvApplicationClass *ev_application_class)
1056 {
1057 }
1058
1059 static void
1060 ev_application_init (EvApplication *ev_application)
1061 {
1062         GError *error = NULL;
1063
1064         ev_application->dot_dir = g_build_filename (g_get_user_config_dir (),
1065                                                     "evince", NULL);
1066         if (!g_file_test (ev_application->dot_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
1067                 ev_application_migrate_config_dir (ev_application);
1068
1069 #ifdef G_OS_WIN32
1070 {
1071         gchar *dir;
1072
1073         dir = g_win32_get_package_installation_directory_of_module (NULL);
1074         ev_application->data_dir = g_build_filename (dir, "share", "evince", NULL);
1075         g_free (dir);
1076 }
1077 #else
1078         ev_application->data_dir = g_strdup (EVINCEDATADIR);
1079 #endif
1080
1081         ev_application_init_session (ev_application);
1082
1083         ev_application_accel_map_load (ev_application);
1084
1085 #ifdef ENABLE_DBUS
1086         ev_application->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
1087         if (ev_application->connection != NULL) {
1088                 introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
1089                 g_assert (introspection_data != NULL);
1090
1091                 ev_application->registration_id =
1092                     g_dbus_connection_register_object (ev_application->connection,
1093                                                        APPLICATION_DBUS_OBJECT_PATH,
1094                                                        introspection_data->interfaces[0],
1095                                                        &interface_vtable,
1096                                                        ev_application, NULL,
1097                                                        &error);
1098                 if (ev_application->registration_id == 0) {
1099                         g_printerr ("Failed to register bus object: %s\n", error->message);
1100                         g_error_free (error);
1101                 }
1102         } else {
1103                 g_printerr ("Failed to get bus connection: %s\n", error->message);
1104                 g_error_free (error);
1105         }
1106
1107         ev_application->keys = ev_media_player_keys_new ();
1108 #endif /* ENABLE_DBUS */
1109
1110         ev_application->scr_saver = totem_scrsaver_new ();
1111         g_object_set (ev_application->scr_saver,
1112                       "reason", _("Running in presentation mode"),
1113                       NULL);
1114 }
1115
1116 GDBusConnection *
1117 ev_application_get_dbus_connection (EvApplication *application)
1118 {
1119 #ifdef ENABLE_DBUS
1120         return application->connection;
1121 #else
1122         return NULL;
1123 #endif
1124 }
1125
1126 gboolean
1127 ev_application_has_window (EvApplication *application)
1128 {
1129         GList    *l, *toplevels;
1130         gboolean  retval = FALSE;
1131
1132         toplevels = gtk_window_list_toplevels ();
1133
1134         for (l = toplevels; l != NULL && !retval; l = l->next) {
1135                 if (EV_IS_WINDOW (l->data))
1136                         retval = TRUE;
1137         }
1138
1139         g_list_free (toplevels);
1140
1141         return retval;
1142 }
1143
1144 guint
1145 ev_application_get_n_windows (EvApplication *application)
1146 {
1147         GList *l, *toplevels;
1148         guint  retval = 0;
1149
1150         toplevels = gtk_window_list_toplevels ();
1151
1152         for (l = toplevels; l != NULL; l = l->next) {
1153                 if (EV_IS_WINDOW (l->data))
1154                         retval++;
1155         }
1156
1157         g_list_free (toplevels);
1158
1159         return retval;
1160 }
1161
1162 const gchar *
1163 ev_application_get_uri (EvApplication *application)
1164 {
1165         return application->uri;
1166 }
1167
1168 /**
1169  * ev_application_get_media_keys:
1170  * @application: The instance of the application.
1171  *
1172  * It gives you access to the media player keys handler object.
1173  *
1174  * Returns: A #EvMediaPlayerKeys.
1175  */
1176 GObject *
1177 ev_application_get_media_keys (EvApplication *application)
1178 {
1179 #ifdef ENABLE_DBUS
1180         return G_OBJECT (application->keys);
1181 #else
1182         return NULL;
1183 #endif /* ENABLE_DBUS */
1184 }
1185
1186 void
1187 ev_application_set_filechooser_uri (EvApplication       *application,
1188                                     GtkFileChooserAction action,
1189                                     const gchar         *uri)
1190 {
1191         if (action == GTK_FILE_CHOOSER_ACTION_OPEN) {
1192                 g_free (application->filechooser_open_uri);
1193                 application->filechooser_open_uri = g_strdup (uri);
1194         } else if (action == GTK_FILE_CHOOSER_ACTION_SAVE) {
1195                 g_free (application->filechooser_save_uri);
1196                 application->filechooser_save_uri = g_strdup (uri);
1197         }
1198 }
1199
1200 const gchar *
1201 ev_application_get_filechooser_uri (EvApplication       *application,
1202                                     GtkFileChooserAction action)
1203 {
1204         if (action == GTK_FILE_CHOOSER_ACTION_OPEN) {
1205                 if (application->filechooser_open_uri)
1206                         return application->filechooser_open_uri;
1207         } else if (action == GTK_FILE_CHOOSER_ACTION_SAVE) {
1208                 if (application->filechooser_save_uri)
1209                         return application->filechooser_save_uri;
1210         }
1211
1212         return NULL;
1213 }
1214
1215 void
1216 ev_application_screensaver_enable (EvApplication *application)
1217 {
1218         totem_scrsaver_enable (application->scr_saver);
1219 }
1220
1221 void
1222 ev_application_screensaver_disable (EvApplication *application)
1223 {
1224         totem_scrsaver_disable (application->scr_saver);
1225 }
1226
1227 const gchar *
1228 ev_application_get_dot_dir (EvApplication *application,
1229                             gboolean create)
1230 {
1231         if (create)
1232                 g_mkdir_with_parents (application->dot_dir, 0700);
1233
1234         return application->dot_dir;
1235 }
1236
1237 const gchar *
1238 ev_application_get_data_dir (EvApplication   *application)
1239 {
1240         return application->data_dir;
1241 }