+ action = gtk_action_group_get_action (ev_window->priv->action_group, PAGE_SELECTOR_ACTION);
+ ev_page_action_set_links_model (EV_PAGE_ACTION (action), model);
+ g_object_unref (model);
+}
+
+static gboolean
+view_actions_focus_in_cb (GtkWidget *widget, GdkEventFocus *event, EvWindow *window)
+{
+#ifdef ENABLE_DBUS
+ GObject *keys;
+
+ keys = ev_application_get_media_keys (EV_APP);
+ ev_media_player_keys_focused (EV_MEDIA_PLAYER_KEYS (keys));
+#endif /* ENABLE_DBUS */
+
+ update_chrome_flag (window, EV_CHROME_RAISE_TOOLBAR, FALSE);
+ ev_window_set_action_sensitive (window, "ViewToolbar", TRUE);
+
+ ev_window_set_view_accels_sensitivity (window, TRUE);
+
+ update_chrome_visibility (window);
+
+ return FALSE;
+}
+
+static gboolean
+view_actions_focus_out_cb (GtkWidget *widget, GdkEventFocus *event, EvWindow *window)
+{
+ ev_window_set_view_accels_sensitivity (window, FALSE);
+
+ return FALSE;
+}
+
+static void
+sidebar_page_main_widget_update_cb (GObject *ev_sidebar_page,
+ GParamSpec *pspec,
+ EvWindow *ev_window)
+{
+ GtkWidget *widget;
+
+ g_object_get (ev_sidebar_page, "main_widget", &widget, NULL);
+
+ if (widget != NULL) {
+ g_signal_connect_object (widget, "focus_in_event",
+ G_CALLBACK (view_actions_focus_in_cb),
+ ev_window, 0);
+ g_signal_connect_object (widget, "focus_out_event",
+ G_CALLBACK (view_actions_focus_out_cb),
+ ev_window, 0);
+ g_object_unref (widget);
+ }
+}
+
+static gboolean
+window_state_event_cb (EvWindow *window, GdkEventWindowState *event, gpointer dummy)
+{
+ if (!(event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN)) {
+ gboolean maximized;
+
+ maximized = event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED;
+ if (window->priv->metadata && !ev_window_is_empty (window))
+ ev_metadata_set_boolean (window->priv->metadata, "window_maximized", maximized);
+ }
+
+ return FALSE;
+}
+
+static gboolean
+window_configure_event_cb (EvWindow *window, GdkEventConfigure *event, gpointer dummy)
+{
+ GdkWindowState state;
+ gdouble document_width, document_height;
+
+ if (!window->priv->metadata)
+ return FALSE;
+
+ state = gdk_window_get_state (GTK_WIDGET (window)->window);
+
+ if (!(state & GDK_WINDOW_STATE_FULLSCREEN)) {
+ if (!ev_window_is_empty (window) && window->priv->document) {
+ ev_document_get_max_page_size (window->priv->document,
+ &document_width, &document_height);
+ ev_metadata_set_double (window->priv->metadata, "window_width_ratio",
+ (double)event->width / document_width);
+ ev_metadata_set_double (window->priv->metadata, "window_height_ratio",
+ (double)event->height / document_height);
+ ev_metadata_set_int (window->priv->metadata, "window_x", event->x);
+ ev_metadata_set_int (window->priv->metadata, "window_y", event->y);
+ ev_metadata_set_int (window->priv->metadata, "window_width", event->width);
+ ev_metadata_set_int (window->priv->metadata, "window_height", event->height);
+ }
+ }
+
+ return FALSE;
+}
+
+static void
+launch_action (EvWindow *window, EvLinkAction *action)
+{
+ const char *filename = ev_link_action_get_filename (action);
+ GAppInfo *app_info;
+ GFile *file;
+ GList file_list = {NULL};
+ GAppLaunchContext *context;
+ GError *error = NULL;
+
+ if (filename == NULL)
+ return;
+
+ if (g_path_is_absolute (filename)) {
+ file = g_file_new_for_path (filename);
+ } else {
+ GFile *base_file;
+ gchar *dir;
+
+ dir = g_path_get_dirname (window->priv->uri);
+ base_file = g_file_new_for_uri (dir);
+ g_free (dir);
+
+ file = g_file_resolve_relative_path (base_file, filename);
+ g_object_unref (base_file);
+ }
+
+ app_info = g_file_query_default_handler (file, NULL, &error);
+ if (!app_info) {
+ ev_window_error_message (window, error,
+ "%s",
+ _("Unable to launch external application."));
+ g_object_unref (file);
+ g_error_free (error);
+
+ return;
+ }
+
+ context = G_APP_LAUNCH_CONTEXT (gdk_app_launch_context_new ());
+ gdk_app_launch_context_set_screen (GDK_APP_LAUNCH_CONTEXT (context),
+ gtk_window_get_screen (GTK_WINDOW (window)));
+ gdk_app_launch_context_set_timestamp (GDK_APP_LAUNCH_CONTEXT (context),
+ gtk_get_current_event_time ());
+
+ file_list.data = file;
+ if (!g_app_info_launch (app_info, &file_list, context, &error)) {
+ ev_window_error_message (window, error,
+ "%s",
+ _("Unable to launch external application."));
+ g_error_free (error);
+ }
+
+ g_object_unref (app_info);
+ g_object_unref (file);
+ /* FIXMEchpe: unref launch context? */
+
+ /* According to the PDF spec filename can be an executable. I'm not sure
+ allowing to launch executables is a good idea though. -- marco */
+}
+
+static void
+launch_external_uri (EvWindow *window, EvLinkAction *action)
+{
+ const gchar *uri = ev_link_action_get_uri (action);
+ GError *error = NULL;
+ gboolean ret;
+ GAppLaunchContext *context;
+
+ context = G_APP_LAUNCH_CONTEXT (gdk_app_launch_context_new ());
+ gdk_app_launch_context_set_screen (GDK_APP_LAUNCH_CONTEXT (context),
+ gtk_window_get_screen (GTK_WINDOW (window)));
+ gdk_app_launch_context_set_timestamp (GDK_APP_LAUNCH_CONTEXT (context),
+ gtk_get_current_event_time ());
+
+ if (!g_strstr_len (uri, strlen (uri), "://") &&
+ !g_str_has_prefix (uri, "mailto:")) {
+ gchar *new_uri;
+
+ /* Not a valid uri, assume http if it starts with www */
+ if (g_str_has_prefix (uri, "www.")) {
+ new_uri = g_strdup_printf ("http://%s", uri);
+ } else {
+ GFile *file, *parent;
+
+ file = g_file_new_for_uri (window->priv->uri);
+ parent = g_file_get_parent (file);
+ g_object_unref (file);
+ if (parent) {
+ gchar *parent_uri = g_file_get_uri (parent);
+
+ new_uri = g_build_filename (parent_uri, uri, NULL);
+ g_free (parent_uri);
+ g_object_unref (parent);
+ } else {
+ new_uri = g_strdup_printf ("file:///%s", uri);
+ }
+ }
+ ret = g_app_info_launch_default_for_uri (new_uri, context, &error);
+ g_free (new_uri);
+ } else {
+ ret = g_app_info_launch_default_for_uri (uri, context, &error);
+ }
+
+ if (ret == FALSE) {
+ ev_window_error_message (window, error,
+ "%s", _("Unable to open external link"));
+ g_error_free (error);
+ }
+
+ /* FIXMEchpe: unref launch context? */
+}
+
+static void
+open_remote_link (EvWindow *window, EvLinkAction *action)
+{
+ gchar *uri;
+ gchar *dir;
+
+ dir = g_path_get_dirname (window->priv->uri);
+
+ uri = g_build_filename (dir, ev_link_action_get_filename (action),
+ NULL);
+ g_free (dir);
+
+ ev_application_open_uri_at_dest (EV_APP, uri,
+ gtk_window_get_screen (GTK_WINDOW (window)),
+ ev_link_action_get_dest (action),
+ 0,
+ NULL,
+ gtk_get_current_event_time ());
+
+ g_free (uri);
+}
+
+static void
+do_action_named (EvWindow *window, EvLinkAction *action)
+{
+ const gchar *name = ev_link_action_get_name (action);
+
+ if (g_ascii_strcasecmp (name, "FirstPage") == 0) {
+ ev_window_cmd_go_first_page (NULL, window);
+ } else if (g_ascii_strcasecmp (name, "PrevPage") == 0) {
+ ev_window_cmd_go_previous_page (NULL, window);
+ } else if (g_ascii_strcasecmp (name, "NextPage") == 0) {
+ ev_window_cmd_go_next_page (NULL, window);
+ } else if (g_ascii_strcasecmp (name, "LastPage") == 0) {
+ ev_window_cmd_go_last_page (NULL, window);
+ } else if (g_ascii_strcasecmp (name, "GoToPage") == 0) {
+ ev_window_cmd_focus_page_selector (NULL, window);
+ } else if (g_ascii_strcasecmp (name, "Find") == 0) {
+ ev_window_cmd_edit_find (NULL, window);
+ } else if (g_ascii_strcasecmp (name, "Close") == 0) {
+ ev_window_cmd_file_close_window (NULL, window);
+ } else if (g_ascii_strcasecmp (name, "Print") == 0) {
+ ev_window_cmd_file_print (NULL, window);
+ } else {
+ g_warning ("Unimplemented named action: %s, please post a "
+ "bug report in Evince bugzilla "
+ "(http://bugzilla.gnome.org) with a testcase.",
+ name);
+ }
+}
+
+static void
+view_external_link_cb (EvView *view, EvLinkAction *action, EvWindow *window)
+{
+ switch (ev_link_action_get_action_type (action)) {
+ case EV_LINK_ACTION_TYPE_GOTO_DEST: {
+ EvLinkDest *dest;
+
+ dest = ev_link_action_get_dest (action);
+ if (!dest)
+ return;
+
+ ev_window_open_copy_at_dest (window, dest);
+ }
+ break;
+ case EV_LINK_ACTION_TYPE_EXTERNAL_URI:
+ launch_external_uri (window, action);
+ break;
+ case EV_LINK_ACTION_TYPE_LAUNCH:
+ launch_action (window, action);
+ break;
+ case EV_LINK_ACTION_TYPE_GOTO_REMOTE:
+ open_remote_link (window, action);
+ break;
+ case EV_LINK_ACTION_TYPE_NAMED:
+ do_action_named (window, action);
+ break;
+ default:
+ g_assert_not_reached ();
+ }