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