]> www.fi.muni.cz Git - evince.git/blob - shell/ev-application.c
[shell] Optimize ev_application_has_window()
[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                 g_variant_get (parameters, "(a{sv}u)", &iter, &timestamp);
756
757                 while (g_variant_iter_loop (iter, "{&sv}", &key, &value)) {
758                         if (strcmp (key, "display") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
759                                 display = ev_display_open_if_needed (g_variant_get_string (value, NULL));
760                         } else if (strcmp (key, "screen") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
761                                 screen_number = g_variant_get_int32 (value);
762                         } else if (strcmp (key, "mode") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_UINT32) {
763                         mode = g_variant_get_uint32 (value);
764                         } else if (strcmp (key, "page-label") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
765                                 dest = ev_link_dest_new_page_label (g_variant_get_string (value, NULL));
766                         } else if (strcmp (key, "find-string") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
767                                 search_string = g_variant_get_string (value, NULL);
768                         }
769                 }
770                 g_variant_iter_free (iter);
771
772                 if (display != NULL &&
773                     screen_number >= 0 &&
774                     screen_number < gdk_display_get_n_screens (display))
775                         screen = gdk_display_get_screen (display, screen_number);
776                 else
777                         screen = gdk_screen_get_default ();
778
779                 windows = ev_application_get_windows (application);
780                 for (l = windows; l != NULL; l = g_list_next (l)) {
781                         EvWindow *ev_window = EV_WINDOW (l->data);
782
783                         ev_application_open_uri_in_window (application, application->uri,
784                                                            ev_window,
785                                                            screen, dest, mode,
786                                                            search_string,
787                                                            timestamp);
788                 }
789                 g_list_free (windows);
790
791                 if (dest)
792                         g_object_unref (dest);
793
794                 g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
795         } else if (g_strcmp0 (method_name, "GetWindowList") == 0) {
796                 GList          *windows = ev_application_get_windows (application);
797                 GVariantBuilder builder;
798                 GList          *l;
799
800                 g_variant_builder_init (&builder, G_VARIANT_TYPE ("(ao)"));
801                 g_variant_builder_open (&builder, G_VARIANT_TYPE ("ao"));
802
803                 for (l = windows; l; l = g_list_next (l)) {
804                         EvWindow *window = (EvWindow *)l->data;
805
806                         g_variant_builder_add (&builder, "o", ev_window_get_dbus_object_path (window));
807                 }
808
809                 g_variant_builder_close (&builder);
810                 g_list_free (windows);
811
812                 g_dbus_method_invocation_return_value (invocation, g_variant_builder_end (&builder));
813         }
814 }
815
816 static const char introspection_xml[] =
817         "<node>"
818           "<interface name='org.gnome.evince.Application'>"
819             "<method name='Reload'>"
820               "<arg type='a{sv}' name='args' direction='in'/>"
821               "<arg type='u' name='timestamp' direction='in'/>"
822             "</method>"
823             "<method name='GetWindowList'>"
824               "<arg type='ao' name='window_list' direction='out'/>"
825             "</method>"
826           "</interface>"
827         "</node>";
828
829 static const GDBusInterfaceVTable interface_vtable = {
830         method_call_cb,
831         NULL,
832         NULL
833 };
834
835 static GDBusNodeInfo *introspection_data;
836 #endif /* ENABLE_DBUS */
837
838 void
839 ev_application_open_uri_list (EvApplication *application,
840                               GSList        *uri_list,
841                               GdkScreen     *screen,
842                               guint          timestamp)
843 {
844         GSList *l;
845
846         for (l = uri_list; l != NULL; l = l->next) {
847                 ev_application_open_uri_at_dest (application, (char *)l->data,
848                                                  screen, NULL, 0, NULL,
849                                                  timestamp);
850         }
851 }
852
853 static void
854 ev_application_accel_map_save (EvApplication *application)
855 {
856         gchar *accel_map_file;
857         gchar *tmp_filename;
858         gint   fd;
859
860         if (userdir) {
861                 accel_map_file = g_build_filename (userdir, "accels",
862                                                    "evince", NULL);
863         } else {
864                 accel_map_file = g_build_filename (g_get_home_dir (),
865                                                    ".gnome2", "accels",
866                                                    "evince", NULL);
867         }
868
869         tmp_filename = g_strdup_printf ("%s.XXXXXX", accel_map_file);
870
871         fd = g_mkstemp (tmp_filename);
872         if (fd == -1) {
873                 g_free (accel_map_file);
874                 g_free (tmp_filename);
875
876                 return;
877         }
878         gtk_accel_map_save_fd (fd);
879         close (fd);
880
881         if (g_rename (tmp_filename, accel_map_file) == -1) {
882                 /* FIXME: win32? */
883                 g_unlink (tmp_filename);
884         }
885
886         g_free (accel_map_file);
887         g_free (tmp_filename);
888 }
889
890 static void
891 ev_application_accel_map_load (EvApplication *application)
892 {
893         gchar *accel_map_file;
894
895         if (userdir) {
896                 accel_map_file = g_build_filename (userdir, "accels",
897                                                    "evince", NULL);
898         } else {
899                 accel_map_file = g_build_filename (g_get_home_dir (),
900                                                    ".gnome2", "accels",
901                                                    "evince", NULL);
902         }
903
904         gtk_accel_map_load (accel_map_file);
905         g_free (accel_map_file);
906 }
907
908 void
909 ev_application_shutdown (EvApplication *application)
910 {
911         if (application->uri) {
912 #ifdef ENABLE_DBUS
913                 ev_application_unregister_uri (application,
914                                                application->uri);
915 #endif
916                 g_free (application->uri);
917                 application->uri = NULL;
918         }
919
920         ev_application_accel_map_save (application);
921
922         g_object_unref (application->scr_saver);
923         application->scr_saver = NULL;
924
925 #ifdef ENABLE_DBUS
926         if (application->keys) {
927                 g_object_unref (application->keys);
928                 application->keys = NULL;
929         }
930         if (application->registration_id != 0) {
931                 g_dbus_connection_unregister_object (application->connection,
932                                                      application->registration_id);
933                 application->registration_id = 0;
934         }
935         if (application->connection != NULL) {
936                 g_object_unref (application->connection);
937                 application->connection = NULL;
938         }
939         if (introspection_data) {
940                 g_dbus_node_info_ref (introspection_data);
941                 introspection_data = NULL;
942         }
943 #endif /* ENABLE_DBUS */
944         
945         g_free (application->dot_dir);
946         application->dot_dir = NULL;
947         g_free (application->data_dir);
948         application->data_dir = NULL;
949         g_free (application->filechooser_open_uri);
950         application->filechooser_open_uri = NULL;
951         g_free (application->filechooser_save_uri);
952         application->filechooser_save_uri = NULL;
953
954         g_object_unref (application);
955         instance = NULL;
956         
957         gtk_main_quit ();
958 }
959
960 static void
961 ev_application_class_init (EvApplicationClass *ev_application_class)
962 {
963 }
964
965 static void
966 ev_application_init (EvApplication *ev_application)
967 {
968         GError *error = NULL;
969
970         userdir = g_getenv ("GNOME22_USER_DIR");
971         if (userdir)
972                 ev_application->dot_dir = g_build_filename (userdir, "evince", NULL);
973         else
974                 ev_application->dot_dir = g_build_filename (g_get_home_dir (),
975                                                             ".gnome2",
976                                                             "evince",
977                                                             NULL);
978
979 #ifdef G_OS_WIN32
980 {
981         gchar *dir;
982
983         dir = g_win32_get_package_installation_directory_of_module (NULL);
984         ev_application->data_dir = g_build_filename (dir, "share", "evince", NULL);
985         g_free (dir);
986 }
987 #else
988         ev_application->data_dir = g_strdup (DATADIR);
989 #endif
990
991         ev_application_init_session (ev_application);
992
993         ev_application_accel_map_load (ev_application);
994
995 #ifdef ENABLE_DBUS
996         ev_application->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
997         if (ev_application->connection != NULL) {
998                 introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
999                 g_assert (introspection_data != NULL);
1000
1001                 ev_application->registration_id =
1002                     g_dbus_connection_register_object (ev_application->connection,
1003                                                        APPLICATION_DBUS_OBJECT_PATH,
1004                                                        introspection_data->interfaces[0],
1005                                                        &interface_vtable,
1006                                                        ev_application, NULL,
1007                                                        &error);
1008                 if (ev_application->registration_id == 0) {
1009                         g_printerr ("Failed to register bus object: %s\n", error->message);
1010                         g_error_free (error);
1011                 }
1012         } else {
1013                 g_printerr ("Failed to get bus connection: %s\n", error->message);
1014                 g_error_free (error);
1015         }
1016
1017         ev_application->keys = ev_media_player_keys_new ();
1018 #endif /* ENABLE_DBUS */
1019
1020         ev_application->scr_saver = totem_scrsaver_new ();
1021         g_object_set (ev_application->scr_saver,
1022                       "reason", _("Running in presentation mode"),
1023                       NULL);
1024 }
1025
1026 GDBusConnection *
1027 ev_application_get_dbus_connection (EvApplication *application)
1028 {
1029 #ifdef ENABLE_DBUS
1030         return application->connection;
1031 #else
1032         return NULL;
1033 #endif
1034 }
1035
1036 gboolean
1037 ev_application_has_window (EvApplication *application)
1038 {
1039         GList    *l, *toplevels;
1040         gboolean  retval = FALSE;
1041
1042         toplevels = gtk_window_list_toplevels ();
1043
1044         for (l = toplevels; l != NULL && !retval; l = l->next) {
1045                 if (EV_IS_WINDOW (l->data))
1046                         retval = TRUE;
1047         }
1048
1049         g_list_free (toplevels);
1050
1051         return retval;
1052 }
1053
1054 const gchar *
1055 ev_application_get_uri (EvApplication *application)
1056 {
1057         return application->uri;
1058 }
1059
1060 /**
1061  * ev_application_get_media_keys:
1062  * @application: The instance of the application.
1063  *
1064  * It gives you access to the media player keys handler object.
1065  *
1066  * Returns: A #EvMediaPlayerKeys.
1067  */
1068 GObject *
1069 ev_application_get_media_keys (EvApplication *application)
1070 {
1071 #ifdef ENABLE_DBUS
1072         return G_OBJECT (application->keys);
1073 #else
1074         return NULL;
1075 #endif /* ENABLE_DBUS */
1076 }
1077
1078 void
1079 ev_application_set_filechooser_uri (EvApplication       *application,
1080                                     GtkFileChooserAction action,
1081                                     const gchar         *uri)
1082 {
1083         if (action == GTK_FILE_CHOOSER_ACTION_OPEN) {
1084                 g_free (application->filechooser_open_uri);
1085                 application->filechooser_open_uri = g_strdup (uri);
1086         } else if (action == GTK_FILE_CHOOSER_ACTION_SAVE) {
1087                 g_free (application->filechooser_save_uri);
1088                 application->filechooser_save_uri = g_strdup (uri);
1089         }
1090 }
1091
1092 const gchar *
1093 ev_application_get_filechooser_uri (EvApplication       *application,
1094                                     GtkFileChooserAction action)
1095 {
1096         if (action == GTK_FILE_CHOOSER_ACTION_OPEN) {
1097                 if (application->filechooser_open_uri)
1098                         return application->filechooser_open_uri;
1099         } else if (action == GTK_FILE_CHOOSER_ACTION_SAVE) {
1100                 if (application->filechooser_save_uri)
1101                         return application->filechooser_save_uri;
1102         }
1103
1104         return NULL;
1105 }
1106
1107 void
1108 ev_application_screensaver_enable (EvApplication *application)
1109 {
1110         totem_scrsaver_enable (application->scr_saver);
1111 }
1112
1113 void
1114 ev_application_screensaver_disable (EvApplication *application)
1115 {
1116         totem_scrsaver_disable (application->scr_saver);
1117 }
1118
1119 const gchar *
1120 ev_application_get_dot_dir (EvApplication *application,
1121                             gboolean create)
1122 {
1123         if (create)
1124                 g_mkdir_with_parents (application->dot_dir, 0700);
1125
1126         return application->dot_dir;
1127 }
1128
1129 const gchar *
1130 ev_application_get_data_dir (EvApplication   *application)
1131 {
1132         return application->data_dir;
1133 }