30 #include <glib/gi18n.h>
31 #include <glib/gstdio.h>
33 #ifdef GDK_WINDOWING_X11
43 #include "ev-gdbus-generated.h"
55 EvEvinceApplication *skeleton;
57 gboolean doc_registered;
68 #define APPLICATION_DBUS_OBJECT_PATH "/org/gnome/evince/Evince"
69 #define APPLICATION_DBUS_INTERFACE "org.gnome.evince.Application"
71 #define EVINCE_DAEMON_SERVICE "org.gnome.evince.Daemon"
72 #define EVINCE_DAEMON_OBJECT_PATH "/org/gnome/evince/Daemon"
73 #define EVINCE_DAEMON_INTERFACE "org.gnome.evince.Daemon"
81 const gchar *search_string,
89 const gchar *search_string,
102 const GApplicationFlags flags = G_APPLICATION_NON_UNIQUE;
105 "application-id", NULL,
121 ev_display_open_if_needed (
const gchar *
name)
125 GdkDisplay *display = NULL;
127 displays = gdk_display_manager_list_displays (gdk_display_manager_get ());
129 for (l = displays; l != NULL; l = l->next) {
130 const gchar *display_name = gdk_display_get_name ((GdkDisplay *) l->data);
135 if (g_str_has_prefix (name, display_name)) {
141 g_slist_free (displays);
143 return display != NULL ? display : gdk_display_open (name);
152 const gchar *search_string,
156 gchar *path, *cmdline;
158 GError *error = NULL;
160 cmd = g_string_new (NULL);
166 dir = g_win32_get_package_installation_directory_of_module (NULL);
167 path = g_build_filename (dir,
"bin",
"evince", NULL);
172 path = g_build_filename (BINDIR,
"evince", NULL);
175 g_string_append_printf (cmd,
" %s", path);
182 g_string_append_printf (cmd,
" --page-label=%s",
186 g_string_append_printf (cmd,
" --page-index=%d",
190 g_string_append_printf (cmd,
" --named-dest=%s",
200 g_string_append_printf (cmd,
" --find=%s", search_string);
206 g_string_append (cmd,
" -f");
209 g_string_append (cmd,
" -s");
215 cmdline = g_string_free (cmd,
FALSE);
216 app = g_app_info_create_from_commandline (cmdline, NULL, G_APP_INFO_CREATE_SUPPORTS_URIS, &error);
221 GdkAppLaunchContext *ctx;
223 ctx = gdk_display_get_app_launch_context (gdk_screen_get_display (screen));
224 gdk_app_launch_context_set_screen (ctx, screen);
225 gdk_app_launch_context_set_timestamp (ctx, timestamp);
234 uri_list.data = (gchar *)uri;
235 uri_list.prev = uri_list.next = NULL;
238 g_app_info_launch_uris (app, uris, G_APP_LAUNCH_CONTEXT (ctx), &error);
240 g_object_unref (app);
241 g_object_unref (ctx);
245 g_printerr (
"Error launching evince %s: %s\n", uri, error->message);
246 g_error_free (error);
259 windows = gtk_application_get_windows (GTK_APPLICATION (application));
260 for (l = windows; l != NULL; l = l->next) {
269 gtk_window_get_screen (GTK_WINDOW (window)) == screen) {
285 gchar *search_string;
290 ev_register_doc_data_free (EvRegisterDocData *data)
296 if (data->search_string)
297 g_free (data->search_string);
299 g_object_unref (data->dest);
305 on_reload_cb (GObject *source_object,
309 GDBusConnection *connection = G_DBUS_CONNECTION (source_object);
311 GError *error = NULL;
313 g_application_release (g_application_get_default ());
315 value = g_dbus_connection_call_finish (connection, res, &error);
317 g_variant_unref (value);
319 g_printerr (
"Failed to Reload: %s\n", error->message);
320 g_error_free (error);
325 gdk_notify_startup_complete ();
329 on_register_uri_cb (GObject *source_object,
333 GDBusConnection *connection = G_DBUS_CONNECTION (source_object);
334 EvRegisterDocData *data = (EvRegisterDocData *)user_data;
338 GVariantBuilder builder;
339 GError *error = NULL;
341 g_application_release (G_APPLICATION (application));
343 value = g_dbus_connection_call_finish (connection, res, &error);
345 g_printerr (
"Error registering document: %s\n", error->message);
346 g_error_free (error);
355 ev_register_doc_data_free (data);
360 g_variant_get (value,
"(&s)", &owner);
365 if (owner[0] ==
'\0') {
366 g_variant_unref (value);
368 application->doc_registered =
TRUE;
377 ev_register_doc_data_free (data);
383 g_variant_builder_init (&builder, G_VARIANT_TYPE (
"(a{sv}u)"));
384 g_variant_builder_open (&builder, G_VARIANT_TYPE (
"a{sv}"));
385 g_variant_builder_add (&builder,
"{sv}",
387 g_variant_new_string (gdk_display_get_name (gdk_screen_get_display (data->screen))));
391 g_variant_builder_add (&builder,
"{sv}",
"page-label",
395 g_variant_builder_add (&builder,
"{sv}",
"page-index",
399 g_variant_builder_add (&builder,
"{sv}",
"named-dest",
406 if (data->search_string) {
407 g_variant_builder_add (&builder,
"{sv}",
409 g_variant_new_string (data->search_string));
412 g_variant_builder_add (&builder,
"{sv}",
414 g_variant_new_uint32 (data->mode));
416 g_variant_builder_close (&builder);
418 g_variant_builder_add (&builder,
"u", data->timestamp);
420 g_dbus_connection_call (connection,
422 APPLICATION_DBUS_OBJECT_PATH,
423 APPLICATION_DBUS_INTERFACE,
425 g_variant_builder_end (&builder),
427 G_DBUS_CALL_FLAGS_NONE,
432 g_application_hold (G_APPLICATION (application));
433 g_variant_unref (value);
434 ev_register_doc_data_free (data);
456 const gchar *search_string,
459 EvRegisterDocData *data;
462 if (!application->skeleton) {
467 if (application->doc_registered) {
471 windows = gtk_application_get_windows (GTK_APPLICATION (application));
472 for (l = windows; l != NULL; l = g_list_next (l)) {
486 data = g_new (EvRegisterDocData, 1);
487 data->uri = g_strdup (uri);
488 data->screen = screen;
489 data->dest = dest ? g_object_ref (dest) : NULL;
491 data->search_string = search_string ? g_strdup (search_string) : NULL;
492 data->timestamp = timestamp;
494 g_dbus_connection_call (g_application_get_dbus_connection (G_APPLICATION (application)),
495 EVINCE_DAEMON_SERVICE,
496 EVINCE_DAEMON_OBJECT_PATH,
497 EVINCE_DAEMON_INTERFACE,
499 g_variant_new (
"(s)", uri),
500 G_VARIANT_TYPE (
"(s)"),
501 G_DBUS_CALL_FLAGS_NONE,
507 g_application_hold (G_APPLICATION (application));
515 GError *error = NULL;
517 if (!application->doc_registered)
523 value = g_dbus_connection_call_sync (
524 g_application_get_dbus_connection (G_APPLICATION (application)),
525 EVINCE_DAEMON_SERVICE,
526 EVINCE_DAEMON_OBJECT_PATH,
527 EVINCE_DAEMON_INTERFACE,
528 "UnregisterDocument",
529 g_variant_new (
"(s)", uri),
531 G_DBUS_CALL_FLAGS_NO_AUTO_START,
536 g_printerr (
"Error unregistering document: %s\n", error->message);
537 g_error_free (error);
539 g_variant_unref (value);
551 const gchar *search_string,
554 #ifdef GDK_WINDOWING_X11
555 GdkWindow *gdk_window;
559 uri = application->uri;
563 gtk_window_set_screen (GTK_WINDOW (ev_window), screen);
570 if (!gtk_widget_get_realized (GTK_WIDGET (ev_window)))
571 gtk_widget_realize (GTK_WIDGET (ev_window));
573 #ifdef GDK_WINDOWING_X11
574 gdk_window = gtk_widget_get_window (GTK_WIDGET (ev_window));
575 if (GDK_IS_X11_WINDOW (gdk_window)) {
577 timestamp = gdk_x11_get_server_time (gdk_window);
578 gdk_x11_window_set_user_time (gdk_window, timestamp);
580 gtk_window_present (GTK_WINDOW (ev_window));
584 gtk_window_present_with_time (GTK_WINDOW (ev_window), timestamp);
594 const gchar *search_string,
625 const gchar *search_string,
628 g_return_if_fail (uri != NULL);
630 if (application->uri && strcmp (application->uri, uri) != 0) {
632 ev_spawn (uri, screen, dest, mode, search_string, timestamp);
634 }
else if (!application->uri) {
635 application->uri = g_strdup (uri);
642 ev_application_register_uri (application, uri, screen, dest, mode, search_string, timestamp);
673 #ifdef GDK_WINDOWING_X11
674 GdkWindow *gdk_window;
679 gtk_window_set_screen (GTK_WINDOW (new_window), screen);
682 if (!gtk_widget_get_realized (new_window))
683 gtk_widget_realize (new_window);
685 #ifdef GDK_WINDOWING_X11
686 gdk_window = gtk_widget_get_window (GTK_WIDGET (new_window));
687 if (GDK_IS_X11_WINDOW (gdk_window)) {
689 timestamp = gdk_x11_get_server_time (gdk_window);
690 gdk_x11_window_set_user_time (gdk_window, timestamp);
692 gtk_window_present (GTK_WINDOW (new_window));
696 gtk_window_present_with_time (GTK_WINDOW (new_window), timestamp);
702 handle_get_window_list_cb (EvEvinceApplication *
object,
703 GDBusMethodInvocation *invocation,
709 paths = g_ptr_array_new ();
711 windows = gtk_application_get_windows (GTK_APPLICATION (application));
712 for (l = windows; l; l = g_list_next (l)) {
719 g_ptr_array_add (paths, NULL);
720 ev_evince_application_complete_get_window_list (
object, invocation,
721 (
const char *
const *) paths->pdata);
723 g_ptr_array_free (paths,
TRUE);
729 handle_reload_cb (EvEvinceApplication *
object,
730 GDBusMethodInvocation *invocation,
739 GdkDisplay *display = NULL;
742 const gchar *search_string = NULL;
743 GdkScreen *screen = NULL;
745 g_variant_iter_init (&iter, args);
747 while (g_variant_iter_loop (&iter,
"{&sv}", &key, &value)) {
748 if (strcmp (key,
"display") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
749 display = ev_display_open_if_needed (g_variant_get_string (value, NULL));
750 }
else if (strcmp (key,
"mode") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_UINT32) {
751 mode = g_variant_get_uint32 (value);
752 }
else if (strcmp (key,
"page-label") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
754 }
else if (strcmp (key,
"named-dest") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
756 }
else if (strcmp (key,
"page-index") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_UINT32) {
758 }
else if (strcmp (key,
"find-string") == 0 && g_variant_classify (value) == G_VARIANT_CLASS_STRING) {
759 search_string = g_variant_get_string (value, NULL);
764 screen = gdk_display_get_default_screen (display);
766 screen = gdk_screen_get_default ();
768 windows = gtk_application_get_windows (GTK_APPLICATION ((application)));
769 for (l = windows; l != NULL; l = g_list_next (l)) {
781 g_object_unref (dest);
783 ev_evince_application_complete_reload (
object, invocation);
797 for (l = uri_list; l != NULL; l = l->next) {
799 screen, NULL, 0, NULL,
807 gchar *accel_map_file;
811 accel_map_file = g_build_filename (application->dot_dir,
"accels", NULL);
812 tmp_filename = g_strdup_printf (
"%s.XXXXXX", accel_map_file);
814 fd = g_mkstemp (tmp_filename);
816 g_free (accel_map_file);
817 g_free (tmp_filename);
821 gtk_accel_map_save_fd (fd);
824 g_mkdir_with_parents (application->dot_dir, 0700);
825 if (g_rename (tmp_filename, accel_map_file) == -1) {
827 g_unlink (tmp_filename);
830 g_free (accel_map_file);
831 g_free (tmp_filename);
837 gchar *accel_map_file;
839 accel_map_file = g_build_filename (application->dot_dir,
"accels", NULL);
840 gtk_accel_map_load (accel_map_file);
841 g_free (accel_map_file);
847 const gchar *userdir;
852 gboolean dir_created =
FALSE;
853 static const gchar *config_files[] = {
854 "evince_toolbar.xml",
859 userdir = g_getenv (
"GNOME22_USER_DIR");
861 old_dot_dir = g_build_filename (userdir,
"evince", NULL);
862 old_accels = g_build_filename (userdir,
"accels",
"evince", NULL);
864 old_dot_dir = g_build_filename (g_get_home_dir (),
868 old_accels = g_build_filename (g_get_home_dir (),
873 if (g_file_test (old_dot_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
874 for (i = 0; config_files[i]; i++) {
880 old_filename = g_build_filename (old_dot_dir, config_files[i], NULL);
881 if (!g_file_test (old_filename, G_FILE_TEST_EXISTS)) {
882 g_free (old_filename);
887 g_mkdir_with_parents (application->dot_dir, 0700);
891 new_filename = g_build_filename (application->dot_dir, config_files[i], NULL);
892 old_file = g_file_new_for_path (old_filename);
893 new_file = g_file_new_for_path (new_filename);
896 g_file_move (old_file, new_file, 0, NULL, NULL, NULL, &error);
898 g_printerr (
"Error migrating config file %s: %s\n",
899 old_filename, error->message);
900 g_error_free (error);
903 g_free (old_filename);
904 g_free (new_filename);
905 g_object_unref (old_file);
906 g_object_unref (new_file);
910 g_free (old_dot_dir);
912 if (g_file_test (old_accels, G_FILE_TEST_EXISTS)) {
914 GFile *old_accels_file;
915 GFile *new_accels_file;
918 g_mkdir_with_parents (application->dot_dir, 0700);
920 new_accels = g_build_filename (application->dot_dir,
"accels", NULL);
921 old_accels_file = g_file_new_for_path (old_accels);
922 new_accels_file = g_file_new_for_path (new_accels);
925 g_file_move (old_accels_file, new_accels_file, 0, NULL, NULL, NULL, &error);
927 g_printerr (
"Error migrating accelerator specifications file %s: %s\n",
928 old_accels, error->message);
929 g_error_free (error);
933 g_object_unref (old_accels_file);
934 g_object_unref (new_accels_file);
949 windows = gtk_application_get_windows (GTK_APPLICATION (application));
950 for (l = windows; l != NULL; l = l->next) {
952 window = GTK_WINDOW (l->data);
958 window ? gtk_window_get_screen (window) : gdk_screen_get_default (),
959 gtk_get_current_event_time ());
979 const char *authors[] = {
980 "Martin Kretzschmar <m_kretzschmar@gmx.net>",
981 "Jonathan Blandford <jrb@gnome.org>",
982 "Marco Pesenti Gritti <marco@gnome.org>",
983 "Nickolay V. Shmyrev <nshmyrev@yandex.ru>",
984 "Bryan Clark <clarkbw@gnome.org>",
985 "Carlos Garcia Campos <carlosgc@gnome.org>",
986 "Wouter Bolsterlee <wbolster@gnome.org>",
987 "Christian Persch <chpe" "\100" "gnome.org>",
990 const char *documenters[] = {
991 "Nickolay V. Shmyrev <nshmyrev@yandex.ru>",
992 "Phil Bull <philbull@gmail.com>",
993 "Tiffany Antpolski <tiffany.antopolski@gmail.com>",
996 const char *license[] = {
997 N_(
"Evince is free software; you can redistribute it and/or modify "
998 "it under the terms of the GNU General Public License as published by "
999 "the Free Software Foundation; either version 2 of the License, or "
1000 "(at your option) any later version.\n"),
1001 N_(
"Evince is distributed in the hope that it will be useful, "
1002 "but WITHOUT ANY WARRANTY; without even the implied warranty of "
1003 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the "
1004 "GNU General Public License for more details.\n"),
1005 N_(
"You should have received a copy of the GNU General Public License "
1006 "along with Evince; if not, write to the Free Software Foundation, Inc., "
1007 "51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA\n")
1009 char *license_trans;
1013 for (p = authors; *p; ++p)
1016 for (p = documenters; *p; ++p)
1020 license_trans = g_strconcat (
_(license[0]),
"\n",
1021 _(license[1]),
"\n",
1022 _(license[2]),
"\n",
1025 gtk_show_about_dialog (gtk_application_get_active_window (GTK_APPLICATION (application)),
1026 "name",
_(
"Evince"),
1028 "copyright",
_(
"© 1996–2014 The Evince authors"),
1029 "license", license_trans,
1030 "website",
"https://wiki.gnome.org/Apps/Evince",
1031 "comments",
_(
"Document Viewer"),
1033 "documenters", documenters,
1034 "translator-credits",
_(
"translator-credits"),
1035 "logo-icon-name",
"evince",
1036 "wrap-license",
TRUE,
1039 g_free (license_trans);
1045 const GActionEntry app_menu_actions[] = {
1051 const gchar *action_accels[] = {
1052 "win.open",
"<Ctrl>O", NULL,
1053 "win.open-copy",
"<Ctrl>N", NULL,
1054 "win.save-copy",
"<Ctrl>S", NULL,
1055 "win.print",
"<Ctrl>P", NULL,
1056 "win.show-properties",
"<alt>Return", NULL,
1057 "win.copy",
"<Ctrl>C",
"<Ctrl>Insert", NULL,
1058 "win.select-all",
"<Ctrl>A", NULL,
1059 "win.save-settings",
"<Ctrl>T", NULL,
1060 "win.add-bookmark",
"<Ctrl>D", NULL,
1061 "win.close",
"<Ctrl>W", NULL,
1062 "win.escape",
"Escape", NULL,
1063 "win.find",
"<Ctrl>F",
"slash", NULL,
1064 "win.find-next",
"<Ctrl>G", NULL,
1065 "win.find-previous",
"<Ctrl><Shift>G", NULL,
1066 "win.select-page",
"<Ctrl>L", NULL,
1067 "win.go-backwards",
"<Shift>Page_Up", NULL,
1068 "win.go-forward",
"<Shift>Page_Down", NULL,
1069 "win.go-next-page",
"n", NULL,
1070 "win.go-previous-page",
"p", NULL,
1071 "win.go-back-history",
"<alt>P", NULL,
1072 "win.go-forward-history",
"<alt>N", NULL,
1073 "win.sizing-mode::fit-page",
"f", NULL,
1074 "win.sizing-mode::fit-width",
"w", NULL,
1075 "win.open-menu",
"F10", NULL,
1076 "win.caret-navigation",
"F7", NULL,
1077 "win.zoom-in",
"plus",
"<Ctrl>plus",
"KP_Add",
"<Ctrl>KP_Add",
"equal",
"<Ctrl>equal", NULL,
1078 "win.zoom-out",
"minus",
"<Ctrl>minus",
"KP_Subtract",
"<Ctrl>KP_Subtract", NULL,
1079 "win.show-side-pane",
"F9", NULL,
1080 "win.fullscreen",
"F11", NULL,
1081 "win.presentation",
"F5", NULL,
1082 "win.continuous",
"c", NULL,
1083 "win.dual-page",
"d", NULL,
1084 "win.rotate-left",
"<Ctrl>Left", NULL,
1085 "win.rotate-right",
"<Ctrl>Right", NULL,
1086 "win.inverted-colors",
"<Ctrl>I", NULL,
1087 "win.reload",
"<Ctrl>R", NULL,
1094 g_application_set_resource_base_path (gapplication,
"/org/gnome/evince");
1096 G_APPLICATION_CLASS (ev_application_parent_class)->startup (gapplication);
1098 g_action_map_add_action_entries (G_ACTION_MAP (application),
1099 app_menu_actions, G_N_ELEMENTS (app_menu_actions),
1102 for (it = action_accels; it[0]; it += g_strv_length ((gchar **)it) + 1)
1103 gtk_application_set_accels_for_action (GTK_APPLICATION (application), it[0], &it[1]);
1111 if (application->uri) {
1113 ev_application_unregister_uri (application,
1116 g_free (application->uri);
1117 application->uri = NULL;
1122 g_free (application->dot_dir);
1123 application->dot_dir = NULL;
1125 G_APPLICATION_CLASS (ev_application_parent_class)->shutdown (gapplication);
1134 windows = gtk_application_get_windows (GTK_APPLICATION (application));
1135 for (l = windows; l != NULL; l = l->next) {
1139 gtk_window_present (GTK_WINDOW (l->data));
1145 ev_application_dbus_register (GApplication *gapplication,
1146 GDBusConnection *connection,
1147 const gchar *object_path,
1151 EvEvinceApplication *skeleton;
1153 if (!G_APPLICATION_CLASS (ev_application_parent_class)->dbus_register (gapplication,
1159 skeleton = ev_evince_application_skeleton_new ();
1160 if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (skeleton),
1162 APPLICATION_DBUS_OBJECT_PATH,
1164 g_object_unref (skeleton);
1169 application->skeleton = skeleton;
1170 g_signal_connect (skeleton,
"handle-get-window-list",
1171 G_CALLBACK (handle_get_window_list_cb),
1173 g_signal_connect (skeleton,
"handle-reload",
1174 G_CALLBACK (handle_reload_cb),
1182 ev_application_dbus_unregister (GApplication *gapplication,
1183 GDBusConnection *connection,
1184 const gchar *object_path)
1188 if (application->keys) {
1189 g_object_unref (application->keys);
1190 application->keys = NULL;
1192 if (application->skeleton != NULL) {
1193 g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (application->skeleton));
1194 g_object_unref (application->skeleton);
1195 application->skeleton = NULL;
1198 G_APPLICATION_CLASS (ev_application_parent_class)->dbus_unregister (gapplication,
1208 GApplicationClass *g_application_class = G_APPLICATION_CLASS (ev_application_class);
1215 g_application_class->dbus_register = ev_application_dbus_register;
1216 g_application_class->dbus_unregister = ev_application_dbus_unregister;
1223 ev_application->dot_dir = g_build_filename (g_get_user_config_dir (),
1225 if (!g_file_test (ev_application->dot_dir, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))
1236 windows = gtk_application_get_windows (GTK_APPLICATION (application));
1237 for (l = windows; l != NULL; l = l->next) {
1253 windows = gtk_application_get_windows (GTK_APPLICATION (application));
1254 for (l = windows; l != NULL && !retval; l = l->next) {
1267 return application->uri;
1282 return G_OBJECT (application->keys);
1293 g_mkdir_with_parents (application->dot_dir, 0700);
1295 return application->dot_dir;
1312 char *escaped_topic, *uri;
1314 if (topic != NULL) {
1315 escaped_topic = g_uri_escape_string (topic, NULL,
TRUE);
1316 uri = g_strdup_printf (
"help:evince/%s", escaped_topic);
1317 g_free (escaped_topic);
1319 uri = g_strdup (
"help:evince");
1322 gtk_show_uri (screen, uri, gtk_get_current_event_time (), NULL);