]> www.fi.muni.cz Git - evince.git/blob - shell/ev-application.c
Remove hard-coded reason in totem-scrsaver
[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 #ifdef ENABLE_DBUS
53 #endif
54
55 struct _EvApplication {
56         GObject base_instance;
57
58         gchar *uri;
59
60         gchar *dot_dir;
61         gchar *data_dir;
62
63 #ifdef ENABLE_DBUS
64         GDBusConnection *connection;
65         guint registration_id;
66         EvMediaPlayerKeys *keys;
67         gboolean doc_registered;
68 #endif
69
70         TotemScrsaver *scr_saver;
71
72 #ifdef WITH_SMCLIENT
73         EggSMClient *smclient;
74 #endif
75
76         gchar *filechooser_open_uri;
77         gchar *filechooser_save_uri;
78 };
79
80 struct _EvApplicationClass {
81         GObjectClass base_class;
82 };
83
84 static EvApplication *instance;
85
86 G_DEFINE_TYPE (EvApplication, ev_application, G_TYPE_OBJECT);
87
88 #ifdef ENABLE_DBUS
89 #define APPLICATION_DBUS_OBJECT_PATH "/org/gnome/evince/Evince"
90 #define APPLICATION_DBUS_INTERFACE   "org.gnome.evince.Application"
91
92 #define EVINCE_DAEMON_SERVICE        "org.gnome.evince.Daemon"
93 #define EVINCE_DAEMON_OBJECT_PATH    "/org/gnome/evince/Daemon"
94 #define EVINCE_DAEMON_INTERFACE      "org.gnome.evince.Daemon"
95 #endif
96
97 static const gchar *userdir = NULL;
98
99 static void _ev_application_open_uri_at_dest (EvApplication  *application,
100                                               const gchar    *uri,
101                                               GdkScreen      *screen,
102                                               EvLinkDest     *dest,
103                                               EvWindowRunMode mode,
104                                               const gchar    *search_string,
105                                               guint           timestamp);
106 static void ev_application_open_uri_in_window (EvApplication  *application,
107                                                const char     *uri,
108                                                EvWindow       *ev_window,
109                                                GdkScreen      *screen,
110                                                EvLinkDest     *dest,
111                                                EvWindowRunMode mode,
112                                                const gchar    *search_string,
113                                                guint           timestamp);
114
115 /**
116  * ev_application_get_instance:
117  *
118  * Checks for #EvApplication instance, if it doesn't exist it does create it.
119  *
120  * Returns: an instance of the #EvApplication data.
121  */
122 EvApplication *
123 ev_application_get_instance (void)
124 {
125         if (!instance) {
126                 instance = EV_APPLICATION (g_object_new (EV_TYPE_APPLICATION, NULL));
127         }
128
129         return instance;
130 }
131
132 /* Session */
133 gboolean
134 ev_application_load_session (EvApplication *application)
135 {
136         GKeyFile *state_file;
137         gchar    *uri;
138
139 #ifdef WITH_SMCLIENT
140         if (egg_sm_client_is_resumed (application->smclient)) {
141                 state_file = egg_sm_client_get_state_file (application->smclient);
142                 if (!state_file)
143                         return FALSE;
144         } else
145 #endif /* WITH_SMCLIENT */
146                 return FALSE;
147
148         uri = g_key_file_get_string (state_file, "Evince", "uri", NULL);
149         if (!uri)
150                 return FALSE;
151
152         ev_application_open_uri_at_dest (application, uri,
153                                          gdk_screen_get_default (),
154                                          NULL, 0, NULL,
155                                          GDK_CURRENT_TIME);
156         g_free (uri);
157         g_key_file_free (state_file);
158
159         return TRUE;
160 }
161
162 #ifdef WITH_SMCLIENT
163
164 static void
165 smclient_save_state_cb (EggSMClient   *client,
166                         GKeyFile      *state_file,
167                         EvApplication *application)
168 {
169         if (!application->uri)
170                 return;
171
172         g_key_file_set_string (state_file, "Evince", "uri", application->uri);
173 }
174
175 static void
176 smclient_quit_cb (EggSMClient   *client,
177                   EvApplication *application)
178 {
179         ev_application_shutdown (application);
180 }
181 #endif /* WITH_SMCLIENT */
182
183 static void
184 ev_application_init_session (EvApplication *application)
185 {
186 #ifdef WITH_SMCLIENT
187         application->smclient = egg_sm_client_get ();
188         g_signal_connect (application->smclient, "save_state",
189                           G_CALLBACK (smclient_save_state_cb),
190                           application);
191         g_signal_connect (application->smclient, "quit",
192                           G_CALLBACK (smclient_quit_cb),
193                           application);
194 #endif
195 }
196
197 /**
198  * ev_display_open_if_needed:
199  * @name: the name of the display to be open if it's needed.
200  *
201  * Search among all the open displays if any of them have the same name as the
202  * passed name. If the display isn't found it tries the open it.
203  *
204  * Returns: a #GdkDisplay of the display with the passed name.
205  */
206 static GdkDisplay *
207 ev_display_open_if_needed (const gchar *name)
208 {
209         GSList     *displays;
210         GSList     *l;
211         GdkDisplay *display = NULL;
212
213         displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
214
215         for (l = displays; l != NULL; l = l->next) {
216                 const gchar *display_name = gdk_display_get_name ((GdkDisplay *) l->data);
217
218                 if (g_ascii_strcasecmp (display_name, name) == 0) {
219                         display = l->data;
220                         break;
221                 }
222         }
223
224         g_slist_free (displays);
225
226         return display != NULL ? display : gdk_display_open (name);
227 }
228
229 static void
230 child_setup (gpointer user_data)
231 {
232         gchar *startup_id;
233
234         startup_id = g_strdup_printf ("_TIME%lu",
235                                       (unsigned long)GPOINTER_TO_INT (user_data));
236         g_setenv ("DESKTOP_STARTUP_ID", startup_id, TRUE);
237         g_free (startup_id);
238 }
239
240 static void
241 ev_spawn (const char     *uri,
242           GdkScreen      *screen,
243           EvLinkDest     *dest,
244           EvWindowRunMode mode,
245           const gchar    *search_string,
246           guint           timestamp)
247 {
248         gchar   *argv[6];
249         guint    arg = 0;
250         gint     i;
251         gboolean res;
252         GError  *error = NULL;
253
254 #ifdef G_OS_WIN32
255 {
256         gchar *dir;
257
258         dir = g_win32_get_package_installation_directory_of_module (NULL);
259         argv[arg++] = g_build_filename (dir, "bin", "evince", NULL);
260         g_free (dir);
261 }
262 #else
263         argv[arg++] = g_build_filename (BINDIR, "evince", NULL);
264 #endif
265
266         /* Page label */
267         if (dest) {
268                 const gchar *page_label;
269
270                 page_label = ev_link_dest_get_page_label (dest);
271                 if (page_label)
272                         argv[arg++] = g_strdup_printf ("--page-label=%s", page_label);
273                 else
274                         argv[arg++] = g_strdup_printf ("--page-label=%d",
275                                                        ev_link_dest_get_page (dest));
276         }
277
278         /* Find string */
279         if (search_string) {
280                 argv[arg++] = g_strdup_printf ("--find=%s", search_string);
281         }
282
283         /* Mode */
284         switch (mode) {
285         case EV_WINDOW_MODE_FULLSCREEN:
286                 argv[arg++] = g_strdup ("-f");
287                 break;
288         case EV_WINDOW_MODE_PRESENTATION:
289                 argv[arg++] = g_strdup ("-s");
290                 break;
291         default:
292                 break;
293         }
294
295         argv[arg++] = (gchar *)uri;
296         argv[arg] = NULL;
297
298         res = gdk_spawn_on_screen (screen, NULL /* wd */, argv, NULL /* env */,
299                                    0,
300                                    child_setup,
301                                    GINT_TO_POINTER(timestamp),
302                                    NULL, &error);
303         if (!res) {
304                 g_warning ("Error launching evince %s: %s\n", uri, error->message);
305                 g_error_free (error);
306         }
307
308         for (i = 0; i < arg - 1; i++) {
309                 g_free (argv[i]);
310         }
311 }
312
313 static GList *
314 ev_application_get_windows (EvApplication *application)
315 {
316         GList *l, *toplevels;
317         GList *windows = NULL;
318
319         toplevels = gtk_window_list_toplevels ();
320
321         for (l = toplevels; l != NULL; l = l->next) {
322                 if (EV_IS_WINDOW (l->data)) {
323                         windows = g_list_append (windows, l->data);
324                 }
325         }
326
327         g_list_free (toplevels);
328
329         return windows;
330 }
331
332 static EvWindow *
333 ev_application_get_empty_window (EvApplication *application,
334                                  GdkScreen     *screen)
335 {
336         EvWindow *empty_window = NULL;
337         GList    *windows = ev_application_get_windows (application);
338         GList    *l;
339
340         for (l = windows; l != NULL; l = l->next) {
341                 EvWindow *window = EV_WINDOW (l->data);
342
343                 if (ev_window_is_empty (window) &&
344                     gtk_window_get_screen (GTK_WINDOW (window)) == screen) {
345                         empty_window = window;
346                         break;
347                 }
348         }
349
350         g_list_free (windows);
351
352         return empty_window;
353 }
354
355
356 #ifdef ENABLE_DBUS
357 typedef struct {
358         gchar          *uri;
359         GdkScreen      *screen;
360         EvLinkDest     *dest;
361         EvWindowRunMode mode;
362         gchar          *search_string;
363         guint           timestamp;
364 } EvRegisterDocData;
365
366 static void
367 ev_register_doc_data_free (EvRegisterDocData *data)
368 {
369         if (!data)
370                 return;
371
372         g_free (data->uri);
373         if (data->search_string)
374                 g_free (data->search_string);
375         if (data->dest)
376                 g_object_unref (data->dest);
377
378         g_free (data);
379 }
380
381 static void
382 on_open_uri_cb (GObject      *source_object,
383                 GAsyncResult *res,
384                 gpointer      user_data)
385 {
386         GDBusConnection *connection = G_DBUS_CONNECTION (source_object);
387         GVariant        *value;
388         GError          *error = NULL;
389
390         value = g_dbus_connection_call_finish (connection, res, &error);
391         if (!value) {
392                 g_warning ("Failed to OpenURI: %s", error->message);
393                 g_error_free (error);
394         }
395         g_variant_unref (value);
396
397         ev_application_shutdown (EV_APP);
398 }
399
400 static void
401 on_register_uri_cb (GObject      *source_object,
402                     GAsyncResult *res,
403                     gpointer      user_data)
404 {
405         GDBusConnection   *connection = G_DBUS_CONNECTION (source_object);
406         EvRegisterDocData *data = (EvRegisterDocData *)user_data;
407         EvApplication     *application = EV_APP;
408         GVariant          *value;
409         const gchar       *owner;
410         GVariantBuilder    builder;
411         GError            *error = NULL;
412
413         value = g_dbus_connection_call_finish (connection, res, &error);
414         if (!value) {
415                 g_warning ("Error registering document: %s\n", error->message);
416                 g_error_free (error);
417
418                 _ev_application_open_uri_at_dest (application,
419                                                   data->uri,
420                                                   data->screen,
421                                                   data->dest,
422                                                   data->mode,
423                                                   data->search_string,
424                                                   data->timestamp);
425                 ev_register_doc_data_free (data);
426
427                 return;
428         }
429
430         g_variant_get (value, "(&s)", &owner);
431
432         /* This means that the document wasn't already registered; go
433          * ahead with opening it.
434          */
435         if (owner[0] == '\0') {
436                 g_variant_unref (value);
437
438                 application->doc_registered = TRUE;
439
440                 _ev_application_open_uri_at_dest (application,
441                                                   data->uri,
442                                                   data->screen,
443                                                   data->dest,
444                                                   data->mode,
445                                                   data->search_string,
446                                                   data->timestamp);
447                 ev_register_doc_data_free (data);
448
449                 return;
450         }
451
452         /* Already registered */
453         g_variant_builder_init (&builder, G_VARIANT_TYPE ("(sa{sv}u)"));
454         g_variant_builder_add (&builder, "s", data->uri);
455
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                                 "OpenURI",
487                                 g_variant_builder_end (&builder),
488                                 NULL,
489                                 G_DBUS_CALL_FLAGS_NONE,
490                                 -1,
491                                 NULL,
492                                 on_open_uri_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 OpenURI 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         const gchar     *uri;
749         guint            timestamp;
750         GVariantIter    *iter;
751         const gchar     *key;
752         GVariant        *value;
753         GdkDisplay      *display = NULL;
754         int              screen_number = 0;
755         EvLinkDest      *dest = NULL;
756         EvWindowRunMode  mode = EV_WINDOW_MODE_NORMAL;
757         const gchar     *search_string = NULL;
758         GdkScreen       *screen = NULL;
759
760         if (g_strcmp0 (method_name, "OpenURI") != 0)
761                 return;
762
763         g_variant_get (parameters, "(&sa{sv}u)", &uri, &iter, &timestamp);
764
765         /* FIXME: we don't need uri anymore,
766          * maybe this method should be renamed
767          * as reload, refresh or something like that
768          */
769         if (g_strcmp0 (application->uri, uri) != 0) {
770                 g_dbus_method_invocation_return_error (invocation,
771                                                        G_DBUS_ERROR,
772                                                        G_DBUS_ERROR_INVALID_ARGS,
773                                                        "Unexpected URI \"%s\"",
774                                                        uri);
775                 g_variant_iter_free (iter);
776                 return;
777         }
778
779         while (g_variant_iter_loop (iter, "{&sv}", &key, &value)) {
780                 if (strcmp (key, "display") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
781                         display = ev_display_open_if_needed (g_variant_get_string (value, NULL));
782                 } else if (strcmp (key, "screen") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
783                         screen_number = g_variant_get_int32 (value);
784                 } else if (strcmp (key, "mode") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_UINT32) {
785                         mode = g_variant_get_uint32 (value);
786                 } else if (strcmp (key, "page-label") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
787                         dest = ev_link_dest_new_page_label (g_variant_get_string (value, NULL));
788                 } else if (strcmp (key, "find-string") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
789                         search_string = g_variant_get_string (value, NULL);
790                 }
791         }
792         g_variant_iter_free (iter);
793
794         if (display != NULL &&
795             screen_number >= 0 &&
796             screen_number < gdk_display_get_n_screens (display))
797                 screen = gdk_display_get_screen (display, screen_number);
798         else
799                 screen = gdk_screen_get_default ();
800
801         windows = ev_application_get_windows (application);
802         for (l = windows; l != NULL; l = g_list_next (l)) {
803                 EvWindow *ev_window = EV_WINDOW (l->data);
804
805                 ev_application_open_uri_in_window (application, uri, ev_window,
806                                                    screen, dest, mode,
807                                                    search_string,
808                                                    timestamp);
809         }
810         g_list_free (windows);
811
812         if (dest)
813                 g_object_unref (dest);
814
815         g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
816 }
817
818 static const char introspection_xml[] =
819         "<node>"
820           "<interface name='org.gnome.evince.Application'>"
821             "<method name='OpenURI'>"
822               "<arg type='s' name='uri' direction='in'/>"
823               "<arg type='a{sv}' name='args' direction='in'/>"
824               "<arg type='u' name='timestamp' direction='in'/>"
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 #endif /* ENABLE_DBUS */
940         
941         g_free (application->dot_dir);
942         application->dot_dir = NULL;
943         g_free (application->data_dir);
944         application->data_dir = NULL;
945         g_free (application->filechooser_open_uri);
946         application->filechooser_open_uri = NULL;
947         g_free (application->filechooser_save_uri);
948         application->filechooser_save_uri = NULL;
949
950         g_object_unref (application);
951         instance = NULL;
952         
953         gtk_main_quit ();
954 }
955
956 static void
957 ev_application_class_init (EvApplicationClass *ev_application_class)
958 {
959 }
960
961 static void
962 ev_application_init (EvApplication *ev_application)
963 {
964         GError *error = NULL;
965
966         userdir = g_getenv ("GNOME22_USER_DIR");
967         if (userdir)
968                 ev_application->dot_dir = g_build_filename (userdir, "evince", NULL);
969         else
970                 ev_application->dot_dir = g_build_filename (g_get_home_dir (),
971                                                             ".gnome2",
972                                                             "evince",
973                                                             NULL);
974
975 #ifdef G_OS_WIN32
976 {
977         gchar *dir;
978
979         dir = g_win32_get_package_installation_directory_of_module (NULL);
980         ev_application->data_dir = g_build_filename (dir, "share", "evince", NULL);
981         g_free (dir);
982 }
983 #else
984         ev_application->data_dir = g_strdup (DATADIR);
985 #endif
986
987         ev_application_init_session (ev_application);
988
989         ev_application_accel_map_load (ev_application);
990
991 #ifdef ENABLE_DBUS
992         ev_application->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
993         if (ev_application->connection != NULL) {
994                 introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
995                 g_assert (introspection_data != NULL);
996
997                 ev_application->registration_id =
998                     g_dbus_connection_register_object (ev_application->connection,
999                                                        APPLICATION_DBUS_OBJECT_PATH,
1000                                                        introspection_data->interfaces[0],
1001                                                        &interface_vtable,
1002                                                        ev_application, NULL,
1003                                                        &error);
1004                 if (ev_application->registration_id == 0) {
1005                         g_printerr ("Failed to register bus object: %s\n", error->message);
1006                         g_error_free (error);
1007                 }
1008         } else {
1009                 g_printerr ("Failed to get bus connection: %s\n", error->message);
1010                 g_error_free (error);
1011         }
1012
1013         ev_application->keys = ev_media_player_keys_new ();
1014 #endif /* ENABLE_DBUS */
1015
1016         ev_application->scr_saver = totem_scrsaver_new ();
1017         g_object_set (ev_application->scr_saver,
1018                       "reason", _("Running in presentation mode"),
1019                       NULL);
1020 }
1021
1022 gboolean
1023 ev_application_has_window (EvApplication *application)
1024 {
1025         GList   *windows = ev_application_get_windows (application);
1026         gboolean retval = windows != NULL;
1027
1028         g_list_free (windows);
1029
1030         return retval;
1031 }
1032
1033 const gchar *
1034 ev_application_get_uri (EvApplication *application)
1035 {
1036         return application->uri;
1037 }
1038
1039 /**
1040  * ev_application_get_media_keys:
1041  * @application: The instance of the application.
1042  *
1043  * It gives you access to the media player keys handler object.
1044  *
1045  * Returns: A #EvMediaPlayerKeys.
1046  */
1047 GObject *
1048 ev_application_get_media_keys (EvApplication *application)
1049 {
1050 #ifdef ENABLE_DBUS
1051         return G_OBJECT (application->keys);
1052 #else
1053         return NULL;
1054 #endif /* ENABLE_DBUS */
1055 }
1056
1057 void
1058 ev_application_set_filechooser_uri (EvApplication       *application,
1059                                     GtkFileChooserAction action,
1060                                     const gchar         *uri)
1061 {
1062         if (action == GTK_FILE_CHOOSER_ACTION_OPEN) {
1063                 g_free (application->filechooser_open_uri);
1064                 application->filechooser_open_uri = g_strdup (uri);
1065         } else if (action == GTK_FILE_CHOOSER_ACTION_SAVE) {
1066                 g_free (application->filechooser_save_uri);
1067                 application->filechooser_save_uri = g_strdup (uri);
1068         }
1069 }
1070
1071 const gchar *
1072 ev_application_get_filechooser_uri (EvApplication       *application,
1073                                     GtkFileChooserAction action)
1074 {
1075         if (action == GTK_FILE_CHOOSER_ACTION_OPEN) {
1076                 if (application->filechooser_open_uri)
1077                         return application->filechooser_open_uri;
1078         } else if (action == GTK_FILE_CHOOSER_ACTION_SAVE) {
1079                 if (application->filechooser_save_uri)
1080                         return application->filechooser_save_uri;
1081         }
1082
1083         return NULL;
1084 }
1085
1086 void
1087 ev_application_screensaver_enable (EvApplication *application)
1088 {
1089         totem_scrsaver_enable (application->scr_saver);
1090 }
1091
1092 void
1093 ev_application_screensaver_disable (EvApplication *application)
1094 {
1095         totem_scrsaver_disable (application->scr_saver);
1096 }
1097
1098 const gchar *
1099 ev_application_get_dot_dir (EvApplication *application,
1100                             gboolean create)
1101 {
1102         if (create)
1103                 g_mkdir_with_parents (application->dot_dir, 0700);
1104
1105         return application->dot_dir;
1106 }
1107
1108 const gchar *
1109 ev_application_get_data_dir (EvApplication   *application)
1110 {
1111         return application->data_dir;
1112 }