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