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