[epiphany] Add internal pdf viewer using evince



commit 91508a2be9d830343300763889a27f4feb8612b7
Author: Jan-Michael Brummer <jan brummer tabos org>
Date:   Mon Dec 17 11:16:36 2018 +0100

    Add internal pdf viewer using evince
    
    Based on an initial patch by: Carlos Garcia Campos
    
    Fixes: https://gitlab.gnome.org/GNOME/epiphany/issues/264

 embed/ephy-download.c             |  18 ++
 embed/ephy-download.h             |  41 ++---
 embed/ephy-embed-shell.c          |   8 +
 embed/ephy-embed-utils.c          |  25 +++
 embed/ephy-embed-utils.h          |  27 +--
 embed/ephy-embed.c                |  62 +++++++
 embed/ephy-embed.h                |  10 ++
 embed/ephy-evince-document-view.c | 334 ++++++++++++++++++++++++++++++++++++++
 embed/ephy-evince-document-view.h |  47 ++++++
 embed/ephy-web-view.c             |   8 +
 embed/meson.build                 |   3 +
 flatpak/org.gnome.Epiphany.json   |  51 ++++++
 meson.build                       |   2 +
 src/ephy-action-bar-end.c         |  18 ++
 src/ephy-main.c                   |   3 +
 src/window-commands.c             |   2 +
 16 files changed, 626 insertions(+), 33 deletions(-)
---
diff --git a/embed/ephy-download.c b/embed/ephy-download.c
index e10dabf05..d3118822f 100644
--- a/embed/ephy-download.c
+++ b/embed/ephy-download.c
@@ -25,6 +25,7 @@
 #include "ephy-embed.h"
 #include "ephy-embed-shell.h"
 #include "ephy-embed-type-builtins.h"
+#include "ephy-evince-document-view.h"
 #include "ephy-file-helpers.h"
 #include "ephy-prefs.h"
 #include "ephy-settings.h"
@@ -42,6 +43,7 @@ struct _EphyDownload {
   char *content_type;
 
   gboolean show_notification;
+  gboolean in_document_mode;
 
   EphyDownloadActionType action;
   guint32 start_time;
@@ -630,6 +632,16 @@ download_decide_destination_cb (WebKitDownload *wk_download,
                                 const gchar    *suggested_filename,
                                 EphyDownload   *download)
 {
+  if (download->in_document_mode) {
+    g_autofree gchar *tmp_file = g_strdup_printf ("%s/%s", g_get_user_cache_dir (), suggested_filename);
+    g_autofree gchar *file_uri = g_filename_to_uri (tmp_file, NULL, NULL);
+
+    webkit_download_set_allow_overwrite (wk_download, TRUE);
+    webkit_download_set_destination (wk_download, file_uri);
+
+    return TRUE;
+  }
+
   if (webkit_download_get_destination (wk_download))
     return TRUE;
 
@@ -812,3 +824,9 @@ ephy_download_disable_desktop_notification (EphyDownload *download)
 
   download->show_notification = FALSE;
 }
+
+void
+ephy_download_enable_evince_document_mode (EphyDownload *download)
+{
+  download->in_document_mode = TRUE;
+}
diff --git a/embed/ephy-download.h b/embed/ephy-download.h
index d2435812f..fa6bc917f 100644
--- a/embed/ephy-download.h
+++ b/embed/ephy-download.h
@@ -36,32 +36,33 @@ typedef enum
   EPHY_DOWNLOAD_ACTION_OPEN
 } EphyDownloadActionType;
 
-EphyDownload *ephy_download_new                   (WebKitDownload *download);
-EphyDownload *ephy_download_new_for_uri           (const char     *uri);
+EphyDownload *ephy_download_new                        (WebKitDownload *download);
+EphyDownload *ephy_download_new_for_uri                (const char     *uri);
 
-void          ephy_download_cancel                (EphyDownload *download);
-gboolean      ephy_download_is_active             (EphyDownload *download);
-gboolean      ephy_download_succeeded             (EphyDownload *download);
-gboolean      ephy_download_failed                (EphyDownload *download,
-                                                   GError      **error);
+void          ephy_download_cancel                     (EphyDownload *download);
+gboolean      ephy_download_is_active                  (EphyDownload *download);
+gboolean      ephy_download_succeeded                  (EphyDownload *download);
+gboolean      ephy_download_failed                     (EphyDownload *download,
+                                                        GError      **error);
 
-void          ephy_download_set_destination_uri   (EphyDownload *download,
-                                                   const char *destination);
+void          ephy_download_set_destination_uri        (EphyDownload *download,
+                                                        const char *destination);
 
-WebKitDownload *ephy_download_get_webkit_download (EphyDownload *download);
+WebKitDownload *ephy_download_get_webkit_download      (EphyDownload *download);
 
-const char   *ephy_download_get_destination_uri   (EphyDownload *download);
-const char   *ephy_download_get_content_type      (EphyDownload *download);
+const char   *ephy_download_get_destination_uri        (EphyDownload *download);
+const char   *ephy_download_get_content_type           (EphyDownload *download);
 
-guint32       ephy_download_get_start_time        (EphyDownload *download);
+guint32       ephy_download_get_start_time             (EphyDownload *download);
 
-EphyDownloadActionType ephy_download_get_action   (EphyDownload *download);
-void          ephy_download_set_action            (EphyDownload *download,
-                                                   EphyDownloadActionType action);
-gboolean      ephy_download_do_download_action    (EphyDownload          *download,
-                                                   EphyDownloadActionType action,
-                                                   guint32                user_time);
+EphyDownloadActionType ephy_download_get_action        (EphyDownload *download);
+void          ephy_download_set_action                 (EphyDownload *download,
+                                                        EphyDownloadActionType action);
+gboolean      ephy_download_do_download_action         (EphyDownload          *download,
+                                                        EphyDownloadActionType action,
+                                                        guint32                user_time);
 void          ephy_download_disable_desktop_notification
-                                                  (EphyDownload *download);
+                                                        (EphyDownload *download);
+void          ephy_download_enable_evince_document_mode (EphyDownload *download);
 
 G_END_DECLS
diff --git a/embed/ephy-embed-shell.c b/embed/ephy-embed-shell.c
index d2e9d2d8a..02aedc24a 100644
--- a/embed/ephy-embed-shell.c
+++ b/embed/ephy-embed-shell.c
@@ -1149,6 +1149,8 @@ download_started_cb (WebKitWebContext *web_context,
 {
   EphyEmbedShellPrivate *priv = ephy_embed_shell_get_instance_private (shell);
   EphyDownload *ephy_download;
+  EphyEmbed *embed;
+  GtkWindow *window;
   gboolean ephy_download_set;
 
   /* Is download locked down? */
@@ -1168,6 +1170,12 @@ download_started_cb (WebKitWebContext *web_context,
     return;
 
   ephy_download = ephy_download_new (download);
+
+  window = gtk_application_get_active_window (GTK_APPLICATION (shell));
+  embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window));
+  if (embed != NULL)
+    ephy_embed_download_started (embed, ephy_download);
+
   ephy_downloads_manager_add_download (priv->downloads_manager, ephy_download);
   g_object_unref (ephy_download);
 }
diff --git a/embed/ephy-embed-utils.c b/embed/ephy-embed-utils.c
index be9389630..97b61fcc7 100644
--- a/embed/ephy-embed-utils.c
+++ b/embed/ephy-embed-utils.c
@@ -30,6 +30,7 @@
 #include "ephy-string.h"
 #include "ephy-view-source-handler.h"
 
+#include <evince-document.h>
 #include <glib/gi18n.h>
 #include <jsc/jsc.h>
 #include <libsoup/soup.h>
@@ -415,3 +416,27 @@ ephy_embed_utils_shutdown (void)
   g_clear_pointer (&non_search_regex, g_regex_unref);
   g_clear_pointer (&domain_regex, g_regex_unref);
 }
+
+gboolean
+ephy_embed_utils_mime_type_is_supported_evince_document (const char *mime_type)
+{
+  GList *doc_types = ev_backends_manager_get_all_types_info ();
+  GList *l;
+  gboolean found = FALSE;
+
+  for (l = doc_types; l != NULL && !found; l = l->next) {
+    EvTypeInfo *info = (EvTypeInfo *)l->data;
+    guint i;
+
+    for (i = 0; info->mime_types[i] != NULL; ++i) {
+      if (g_ascii_strcasecmp (mime_type, info->mime_types[i]) == 0) {
+        found = TRUE;
+        break;
+      }
+    }
+  }
+
+  g_list_free (doc_types);
+
+  return found;
+}
diff --git a/embed/ephy-embed-utils.h b/embed/ephy-embed-utils.h
index 3f99b7d89..4bd0f6502 100644
--- a/embed/ephy-embed-utils.h
+++ b/embed/ephy-embed-utils.h
@@ -36,18 +36,19 @@ G_BEGIN_DECLS
 
 #define EPHY_WEBKIT_BACK_FORWARD_LIMIT 100
 
-char*    ephy_embed_utils_link_message_parse                    (const char *message);
-gboolean ephy_embed_utils_address_has_web_scheme                (const char *address);
-gboolean ephy_embed_utils_address_is_existing_absolute_filename (const char *address);
-gboolean ephy_embed_utils_address_is_valid                      (const char *address);
-char*    ephy_embed_utils_normalize_address                     (const char *address);
-char *   ephy_embed_utils_autosearch_address                    (const char *search_key);
-char *   ephy_embed_utils_normalize_or_autosearch_address       (const char *address);
-gboolean ephy_embed_utils_url_is_empty                          (const char *location);
-gboolean ephy_embed_utils_is_no_show_address                    (const char *address);
-char    *ephy_embed_utils_get_title_from_address                (const char *address);
-gboolean ephy_embed_utils_urls_have_same_origin                 (const char *a_url,
-                                                                 const char *b_url);
-void     ephy_embed_utils_shutdown                              (void);
+char*    ephy_embed_utils_link_message_parse                     (const char *message);
+gboolean ephy_embed_utils_address_has_web_scheme                 (const char *address);
+gboolean ephy_embed_utils_address_is_existing_absolute_filename  (const char *address);
+gboolean ephy_embed_utils_address_is_valid                       (const char *address);
+char*    ephy_embed_utils_normalize_address                      (const char *address);
+char *   ephy_embed_utils_autosearch_address                     (const char *search_key);
+char *   ephy_embed_utils_normalize_or_autosearch_address        (const char *address);
+gboolean ephy_embed_utils_url_is_empty                           (const char *location);
+gboolean ephy_embed_utils_is_no_show_address                     (const char *address);
+char    *ephy_embed_utils_get_title_from_address                 (const char *address);
+gboolean ephy_embed_utils_urls_have_same_origin                  (const char *a_url,
+                                                                  const char *b_url);
+void     ephy_embed_utils_shutdown                               (void);
+gboolean ephy_embed_utils_mime_type_is_supported_evince_document (const char *mime_type);
 
 G_END_DECLS
diff --git a/embed/ephy-embed.c b/embed/ephy-embed.c
index 0b101ab14..cfac6919c 100644
--- a/embed/ephy-embed.c
+++ b/embed/ephy-embed.c
@@ -29,6 +29,7 @@
 #include "ephy-embed-prefs.h"
 #include "ephy-embed-shell.h"
 #include "ephy-embed-utils.h"
+#include "ephy-evince-document-view.h"
 #include "ephy-find-toolbar.h"
 #include "ephy-notification-container.h"
 #include "ephy-prefs.h"
@@ -65,6 +66,7 @@ struct _EphyEmbed {
   GtkWidget *floating_bar;
   GtkWidget *progress;
   GtkWidget *fullscreen_message_label;
+  GtkWidget *document_view;
 
   char *title;
   WebKitURIRequest *delayed_request;
@@ -74,6 +76,8 @@ struct _EphyEmbed {
   GSList *messages;
   GSList *keys;
 
+  EphyEmbedMode mode;
+
   guint seq_context_id;
   guint seq_message_id;
 
@@ -1018,3 +1022,61 @@ ephy_embed_detach_notification_container (EphyEmbed *embed)
     gtk_container_remove (GTK_CONTAINER (embed->overlay), g_object_ref (GTK_WIDGET (container)));
   }
 }
+
+void
+ephy_embed_set_mode (EphyEmbed *embed, EphyEmbedMode mode)
+{
+  g_assert (EPHY_IS_EMBED (embed));
+
+  if (embed->mode == mode)
+    return;
+
+  switch (mode) {
+  case EPHY_EMBED_MODE_WEB_VIEW:
+    if (embed->document_view != NULL) {
+      gtk_widget_destroy (embed->document_view);
+      embed->document_view = NULL;
+    }
+    gtk_widget_set_visible (GTK_WIDGET (embed->paned), TRUE);
+    break;
+  case EPHY_EMBED_MODE_EVINCE_DOCUMENT:
+    gtk_widget_set_visible (GTK_WIDGET (embed->paned), FALSE);
+    embed->document_view = ephy_evince_document_view_new ();
+    ephy_evince_document_set_embed (EPHY_EVINCE_DOCUMENT_VIEW (embed->document_view), embed);
+    gtk_box_pack_start (GTK_BOX (embed),
+                        embed->document_view,
+                        TRUE, TRUE, 0);
+    gtk_widget_show_all (embed->document_view);
+    break;
+  }
+
+  embed->mode = mode;
+}
+
+EphyEmbedMode
+ephy_embed_get_mode (EphyEmbed *embed)
+{
+  return embed->mode;
+}
+
+static void
+document_download_finished_cb (WebKitDownload *download,
+                               EphyEmbed      *embed)
+{
+  const char *document_uri = webkit_download_get_destination (download);
+
+  ephy_evince_document_view_load_uri (EPHY_EVINCE_DOCUMENT_VIEW (embed->document_view),
+                                      document_uri);
+}
+
+void
+ephy_embed_download_started (EphyEmbed    *embed,
+                             EphyDownload *ephy_download)
+{
+  WebKitDownload *download = ephy_download_get_webkit_download (ephy_download);
+
+  if (embed->mode == EPHY_EMBED_MODE_EVINCE_DOCUMENT) {
+    ephy_download_enable_evince_document_mode (ephy_download);
+    g_signal_connect (download, "finished", G_CALLBACK (document_download_finished_cb), embed);
+  }
+}
diff --git a/embed/ephy-embed.h b/embed/ephy-embed.h
index 919a6d366..8cf658ce7 100644
--- a/embed/ephy-embed.h
+++ b/embed/ephy-embed.h
@@ -37,6 +37,11 @@ typedef enum {
   EPHY_EMBED_TOP_WIDGET_POLICY_DESTROY_ON_TRANSITION
 } EphyEmbedTopWidgetPolicy;
 
+typedef enum {
+  EPHY_EMBED_MODE_WEB_VIEW,
+  EPHY_EMBED_MODE_EVINCE_DOCUMENT
+} EphyEmbedMode;
+
 EphyWebView*     ephy_embed_get_web_view                  (EphyEmbed  *embed);
 EphyFindToolbar* ephy_embed_get_find_toolbar              (EphyEmbed  *embed);
 void             ephy_embed_add_top_widget                (EphyEmbed                *embed,
@@ -54,5 +59,10 @@ gboolean         ephy_embed_inspector_is_loaded           (EphyEmbed *embed);
 const char      *ephy_embed_get_title                     (EphyEmbed *embed);
 void             ephy_embed_attach_notification_container (EphyEmbed *embed);
 void             ephy_embed_detach_notification_container (EphyEmbed *embed);
+void             ephy_embed_set_mode                      (EphyEmbed     *embed,
+                                                           EphyEmbedMode  mode);
+EphyEmbedMode    ephy_embed_get_mode                      (EphyEmbed *embed);
+void             ephy_embed_download_started              (EphyEmbed    *embed,
+                                                           EphyDownload *ephy_download);
 
 G_END_DECLS
diff --git a/embed/ephy-evince-document-view.c b/embed/ephy-evince-document-view.c
new file mode 100644
index 000000000..4052c1907
--- /dev/null
+++ b/embed/ephy-evince-document-view.c
@@ -0,0 +1,334 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
+/* vim: set sw=2 ts=2 sts=2 et: */
+/*
+ *  Copyright © 2012 Igalia S.L.
+ *  Copyright © 2018 Jan-Michael Brummer
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+#include "ephy-evince-document-view.h"
+#include "ephy-embed-shell.h"
+
+#include <evince-view.h>
+
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <libsoup/soup.h>
+
+struct _EphyEvinceDocumentView {
+  GtkBox parent_instance;
+
+  GtkWidget *view;
+  GtkWidget *current_page;
+  GtkWidget *total_page;
+  GtkWidget *sizing_mode;
+  GtkWidget *popup;
+
+  EphyEmbed *embed;
+
+  EvJob *job;
+  EvDocumentModel *model;
+  SoupURI *uri;
+};
+
+G_DEFINE_TYPE (EphyEvinceDocumentView, ephy_evince_document_view, GTK_TYPE_BOX)
+
+static void
+ephy_evince_document_view_finalize (GObject *object)
+{
+  EphyEvinceDocumentView *self = EPHY_EVINCE_DOCUMENT_VIEW (object);
+
+  if (self->uri != NULL) {
+    g_unlink (self->uri->path);
+
+    g_clear_pointer (&self->uri, soup_uri_free);
+  }
+
+  if (self->job != NULL) {
+    ev_job_cancel (self->job);
+    g_clear_object (&self->job);
+  }
+
+  g_clear_object (&self->model);
+
+  G_OBJECT_CLASS (ephy_evince_document_view_parent_class)->finalize (object);
+}
+
+static void
+on_save_button_clicked (GtkButton              *button,
+                        EphyEvinceDocumentView *self)
+{
+  g_autoptr (GtkFileChooserNative) native = NULL;
+  GtkFileChooser *chooser;
+  GError *error = NULL;
+  gint res;
+  g_autofree gchar *basename = g_path_get_basename (self->uri->path);
+
+  native = gtk_file_chooser_native_new (_("Save File"),
+                                        NULL,
+                                        GTK_FILE_CHOOSER_ACTION_SAVE,
+                                        NULL,
+                                        NULL);
+
+  chooser = GTK_FILE_CHOOSER (native);
+
+  gtk_file_chooser_set_do_overwrite_confirmation (chooser, TRUE);
+
+  gtk_file_chooser_set_current_name (chooser, basename);
+
+  res = gtk_native_dialog_run (GTK_NATIVE_DIALOG (native));
+  if (res == GTK_RESPONSE_ACCEPT) {
+    g_autofree gchar *filename;
+    GFile *source = g_file_new_for_uri (self->uri->path);
+    GFile *dest;
+
+    filename = gtk_file_chooser_get_filename (chooser);
+    dest = g_file_new_for_path (filename);
+
+    if (!g_file_copy (source, dest, G_FILE_COPY_NONE, NULL, NULL, NULL, &error)) {
+      g_warning ("%s(): Could not copy file: %s\n", __FUNCTION__, error->message);
+      g_error_free (error);
+    }
+  }
+}
+
+static void
+view_external_link_cb (EvView                 *view,
+                       EvLinkAction           *action,
+                       EphyEvinceDocumentView *self)
+{
+  EvLinkActionType type = ev_link_action_get_action_type (action);
+  EphyWebView *webview;
+  const gchar *url;
+
+  if (type != EV_LINK_ACTION_TYPE_EXTERNAL_URI)
+    return;
+
+  url = ev_link_action_get_uri (action);
+
+  webview = ephy_embed_get_web_view (self->embed);
+  ephy_web_view_load_url (webview, url);
+}
+
+static void
+ephy_evince_document_view_constructed (GObject *object)
+{
+  EphyEvinceDocumentView *self = EPHY_EVINCE_DOCUMENT_VIEW (object);
+  GtkWidget *box;
+  GtkWidget *entry_box;
+  GtkWidget *save_button;
+  GtkWidget *scrolled_window;
+  GtkWidget *separator;
+
+  G_OBJECT_CLASS (ephy_evince_document_view_parent_class)->constructed (object);
+
+  scrolled_window = gtk_scrolled_window_new (NULL, NULL);
+
+  self->view = ev_view_new ();
+  g_signal_connect (self->view, "external-link", G_CALLBACK (view_external_link_cb), self);
+  gtk_container_add (GTK_CONTAINER (scrolled_window), self->view);
+  gtk_box_pack_start (GTK_BOX (self), scrolled_window, TRUE, TRUE, 0);
+
+  self->model = ev_document_model_new ();
+  ev_view_set_model (EV_VIEW (self->view), self->model);
+
+  separator = gtk_separator_new (GTK_ORIENTATION_HORIZONTAL);
+  gtk_box_pack_start (GTK_BOX (self), separator, FALSE, TRUE, 0);
+
+  box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+  gtk_widget_set_margin_start (box, 6);
+  gtk_widget_set_margin_end (box, 6);
+  gtk_widget_set_margin_top (box, 6);
+  gtk_widget_set_margin_bottom (box, 6);
+  gtk_box_pack_start (GTK_BOX (self), box, FALSE, TRUE, 0);
+
+  entry_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
+  gtk_style_context_add_class (gtk_widget_get_style_context (entry_box), GTK_STYLE_CLASS_LINKED);
+  gtk_style_context_add_class (gtk_widget_get_style_context (entry_box), GTK_STYLE_CLASS_RAISED);
+  gtk_box_pack_start (GTK_BOX (box), entry_box, FALSE, TRUE, 0);
+
+  self->current_page = gtk_entry_new ();
+  gtk_entry_set_width_chars (GTK_ENTRY (self->current_page), 2);
+  gtk_box_pack_start (GTK_BOX (entry_box), self->current_page, FALSE, TRUE, 0);
+
+  self->total_page = gtk_entry_new ();
+  gtk_entry_set_width_chars (GTK_ENTRY (self->total_page), 5);
+  gtk_widget_set_sensitive (self->total_page, FALSE);
+  gtk_box_pack_start (GTK_BOX (entry_box), self->total_page, FALSE, TRUE, 0);
+
+  save_button = gtk_button_new_from_icon_name ("document-save-symbolic", GTK_ICON_SIZE_SMALL_TOOLBAR);
+  g_signal_connect (save_button, "clicked", G_CALLBACK (on_save_button_clicked), self);
+  gtk_box_pack_end (GTK_BOX (box), save_button, FALSE, TRUE, 0);
+
+  self->sizing_mode = gtk_combo_box_text_new ();
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (self->sizing_mode), _("Fit Page"));
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (self->sizing_mode), _("Fit Width"));
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (self->sizing_mode), _("Free"));
+  gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (self->sizing_mode), _("Automatic"));
+  gtk_box_pack_end (GTK_BOX (box), self->sizing_mode, FALSE, TRUE, 0);
+}
+
+static void
+ephy_evince_document_view_class_init (EphyEvinceDocumentViewClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->constructed = ephy_evince_document_view_constructed;
+  object_class->finalize = ephy_evince_document_view_finalize;
+}
+
+static void
+ephy_evince_document_view_init (EphyEvinceDocumentView *self)
+{
+}
+
+GtkWidget *
+ephy_evince_document_view_new (void)
+{
+  return g_object_new (EPHY_TYPE_EVINCE_DOCUMENT_VIEW,
+                       "orientation", GTK_ORIENTATION_VERTICAL,
+                       NULL);
+}
+
+static void
+on_page_changed (EvDocumentModel        *model,
+                 gint                    old_page,
+                 gint                    new_page,
+                 EphyEvinceDocumentView *self)
+{
+  g_autofree gchar *page = g_strdup_printf ("%d", new_page + 1);
+
+  gtk_entry_set_text (GTK_ENTRY (self->current_page), page);
+}
+
+static void
+on_current_page_activate (GtkEntry               *entry,
+                          EphyEvinceDocumentView *self)
+{
+  const gchar *text = gtk_entry_get_text (entry);
+  gint page = atoi (text);
+
+  ev_document_model_set_page (self->model, page - 1);
+}
+
+static void
+on_sizing_mode_changed (GtkComboBox            *widget,
+                        EphyEvinceDocumentView *self)
+{
+  gint index = gtk_combo_box_get_active (widget);
+
+  ev_document_model_set_sizing_mode (self->model, index);
+}
+
+static void
+on_popup_copy_activate (GtkMenuItem            *menuitem,
+                        EphyEvinceDocumentView *self)
+{
+  GtkClipboard *clipboard;
+  g_autofree gchar *selected_text = ev_view_get_selected_text (EV_VIEW (self->view));
+
+  clipboard = gtk_widget_get_clipboard (GTK_WIDGET (self), GDK_SELECTION_CLIPBOARD);
+  gtk_clipboard_set_text (GTK_CLIPBOARD (clipboard), selected_text, strlen (selected_text));
+}
+
+static gboolean
+on_view_popup_cb (EvView                 *view,
+                  GList                  *items,
+                  EphyEvinceDocumentView *self)
+{
+  if (!ev_view_get_has_selection (view))
+    return TRUE;
+
+  if (!self->popup) {
+    GtkWidget *copy = gtk_menu_item_new_with_label (_("Copy"));
+    self->popup = gtk_menu_new ();
+    g_signal_connect (copy, "activate", G_CALLBACK (on_popup_copy_activate), self);
+    gtk_menu_shell_append (GTK_MENU_SHELL (self->popup), copy);
+    gtk_menu_attach_to_widget (GTK_MENU (self->popup), GTK_WIDGET (self), NULL);
+    gtk_widget_show_all (self->popup);
+  }
+
+  gtk_menu_popup_at_pointer (GTK_MENU (self->popup), NULL);
+
+  return TRUE;
+}
+
+static void
+document_load_job_finished (EvJob                  *job,
+                            EphyEvinceDocumentView *self)
+{
+  g_autofree gchar *total_pages = NULL;
+  gint n_pages;
+
+  if (ev_job_is_failed (job)) {
+    g_warning ("Failed to load document: %s", job->error->message);
+    g_error_free (job->error);
+
+    return;
+  }
+
+  ev_document_model_set_document (self->model, job->document);
+  n_pages = ev_document_get_n_pages (job->document);
+
+  /* Translators: Number of x total pages */
+  total_pages = g_strdup_printf (_("of %d"), n_pages);
+  g_signal_connect (self->model, "page-changed", G_CALLBACK (on_page_changed), self);
+  g_signal_connect (self->current_page, "activate", G_CALLBACK (on_current_page_activate), self);
+  gtk_entry_set_text (GTK_ENTRY (self->total_page), total_pages);
+  gtk_entry_set_text (GTK_ENTRY (self->current_page), "1");
+  g_signal_connect (self->sizing_mode, "changed", G_CALLBACK (on_sizing_mode_changed), self);
+  gtk_combo_box_set_active (GTK_COMBO_BOX (self->sizing_mode), ev_document_model_get_sizing_mode 
(self->model));
+
+  g_signal_connect_object (self->view, "popup", G_CALLBACK (on_view_popup_cb), self, 0);
+}
+
+void
+ephy_evince_document_view_load_uri (EphyEvinceDocumentView *self,
+                                    const char             *uri)
+{
+  g_return_if_fail (EPHY_EVINCE_DOCUMENT_VIEW (self));
+  g_return_if_fail (uri != NULL);
+
+  if (self->uri != NULL) {
+    if (strcmp (self->uri->path, uri) != 0)
+      g_unlink (self->uri->path);
+
+    g_clear_pointer (&self->uri, soup_uri_free);
+  }
+
+  if (self->job != NULL) {
+    ev_job_cancel (self->job);
+
+    g_clear_object (&self->job);
+  }
+
+  self->uri = soup_uri_new (uri);
+
+  self->job = ev_job_load_new (uri);
+  g_signal_connect (self->job, "finished",
+                    G_CALLBACK (document_load_job_finished),
+                    self);
+  ev_job_scheduler_push_job (self->job, EV_JOB_PRIORITY_NONE);
+}
+
+void
+ephy_evince_document_set_embed (EphyEvinceDocumentView *self,
+                                EphyEmbed              *embed)
+{
+  self->embed = embed;
+}
diff --git a/embed/ephy-evince-document-view.h b/embed/ephy-evince-document-view.h
new file mode 100644
index 000000000..6f9b0617f
--- /dev/null
+++ b/embed/ephy-evince-document-view.h
@@ -0,0 +1,47 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2; -*- */
+/* vim: set sw=2 ts=2 sts=2 et: */
+/*
+ *  Copyright © 2012 Igalia S.L.
+ *  Copyright © 2018 Jan-Michael Brummer
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef _EPHY_EVINCE_DOCUMENT_VIEW_H
+#define _EPHY_EVINCE_DOCUMENT_VIEW_H
+
+#include <gtk/gtk.h>
+
+#include "ephy-embed.h"
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_EVINCE_DOCUMENT_VIEW (ephy_evince_document_view_get_type ())
+
+G_DECLARE_FINAL_TYPE (EphyEvinceDocumentView, ephy_evince_document_view, EPHY, EVINCE_DOCUMENT_VIEW, GtkBox)
+
+
+GType      ephy_evince_document_view_get_type (void);
+
+GtkWidget *ephy_evince_document_view_new (void);
+void       ephy_evince_document_view_load_uri (EphyEvinceDocumentView *self,
+                                               const char             *uri);
+void       ephy_evince_document_set_embed (EphyEvinceDocumentView *self,
+                                           EphyEmbed              *embed);
+
+G_END_DECLS
+
+#endif /* _EPHY_EVINCE_DOCUMENT_VIEW_H */
diff --git a/embed/ephy-web-view.c b/embed/ephy-web-view.c
index 2155d482b..5b3b10f00 100644
--- a/embed/ephy-web-view.c
+++ b/embed/ephy-web-view.c
@@ -1430,6 +1430,12 @@ decide_policy_cb (WebKitWebView           *web_view,
   response = webkit_response_policy_decision_get_response (response_decision);
   mime_type = webkit_uri_response_get_mime_type (response);
 
+  if (ephy_embed_utils_mime_type_is_supported_evince_document (mime_type)) {
+    EphyEmbed *embed = EPHY_GET_EMBED_FROM_EPHY_WEB_VIEW (web_view);
+
+    ephy_embed_set_mode (embed, EPHY_EMBED_MODE_EVINCE_DOCUMENT);
+  }
+
   /* If WebKit can't handle the mime type start the download
      process */
   if (webkit_response_policy_decision_is_mime_type_supported (response_decision))
@@ -1885,6 +1891,7 @@ load_changed_cb (WebKitWebView  *web_view,
                  gpointer        user_data)
 {
   EphyWebView *view = EPHY_WEB_VIEW (web_view);
+  EphyEmbed *embed = EPHY_GET_EMBED_FROM_EPHY_WEB_VIEW (web_view);
   GObject *object = G_OBJECT (web_view);
 
   g_object_freeze_notify (object);
@@ -1894,6 +1901,7 @@ load_changed_cb (WebKitWebView  *web_view,
       const char *loading_uri = NULL;
 
       view->load_failed = FALSE;
+      ephy_embed_set_mode (embed, EPHY_EMBED_MODE_WEB_VIEW);
 
       if (view->snapshot_timeout_id) {
         g_source_remove (view->snapshot_timeout_id);
diff --git a/embed/meson.build b/embed/meson.build
index e3a217c34..be048a121 100644
--- a/embed/meson.build
+++ b/embed/meson.build
@@ -22,6 +22,7 @@ libephyembed_sources = [
   'ephy-embed-utils.c',
   'ephy-encoding.c',
   'ephy-encodings.c',
+  'ephy-evince-document-view.c',
   'ephy-file-monitor.c',
   'ephy-filters-manager.c',
   'ephy-find-toolbar.c',
@@ -34,6 +35,8 @@ libephyembed_sources = [
 libephyembed_deps = [
   libdazzle_dep,
   ephymisc_dep,
+  evince_document_dep,
+  evince_view_dep,
   gio_dep,
   glib_dep,
   gtk_dep,
diff --git a/flatpak/org.gnome.Epiphany.json b/flatpak/org.gnome.Epiphany.json
index d05da0f2c..06056ab13 100644
--- a/flatpak/org.gnome.Epiphany.json
+++ b/flatpak/org.gnome.Epiphany.json
@@ -98,6 +98,57 @@
                 }
             ]
         },
+        {
+            "name": "openjpeg2",
+            "buildsystem": "cmake-ninja",
+            "builddir": true,
+            "sources": [
+                {
+                    "type": "git",
+                    "url": "https://github.com/szukw000/openjpeg.git";,
+                    "branch": "v2.1.2"
+                }
+            ]
+        },
+        {
+            "name" : "poppler",
+            "buildsystem" : "cmake-ninja",
+            "builddir": true,
+            "config-opts" : [
+                "-DENABLE_TESTING=OFF"
+            ],
+            "sources" : [
+                {
+                    "type" : "git",
+                    "url" : "https://anongit.freedesktop.org/git/poppler/poppler.git";
+                }
+            ]
+        },
+        {
+            "name" : "evince",
+            "buildsystem" : "meson",
+            "config-opts" : [
+                "-Dplatform=gnome",
+                "-Dviewer=false",
+                "-Dpreviewer=false",
+                "-Dthumbnailer=false",
+                "-Dnautilus=false",
+                "-Dgtk_doc=false",
+                "-Dintrospection=false",
+                "-Ddbus=false",
+                "-Dkeyring=disabled",
+                "-Dgtk_unix_print=disabled",
+                "-Dthumbnail_cache=disabled",
+                "-Dgspell=disabled",
+                "-Dsystemduserunitdir=no"
+            ],
+            "sources" : [
+                {
+                    "type" : "git",
+                    "url" : "https://gitlab.gnome.org/GNOME/evince.git";
+                }
+            ]
+        },
         {
             "name" : "epiphany",
             "config-opts" : [
diff --git a/meson.build b/meson.build
index b50bb4f40..047352d6b 100644
--- a/meson.build
+++ b/meson.build
@@ -85,6 +85,8 @@ nettle_requirement = '>= 3.4'
 webkitgtk_requirement = '>= 2.21.92'
 
 cairo_dep = dependency('cairo', version: '>= 1.2')
+evince_document_dep = dependency('evince-document-3.0')
+evince_view_dep = dependency('evince-view-3.0')
 gcr_dep = dependency('gcr-3', version: '>= 3.5.5')
 gdk_dep = dependency('gdk-3.0', version: gtk_requirement)
 gdk_pixbuf_dep = dependency('gdk-pixbuf-2.0', version: '>= 2.36.5')
diff --git a/src/ephy-action-bar-end.c b/src/ephy-action-bar-end.c
index 934fac09b..307773a8b 100644
--- a/src/ephy-action-bar-end.c
+++ b/src/ephy-action-bar-end.c
@@ -23,6 +23,8 @@
 
 #include "ephy-downloads-popover.h"
 #include "ephy-downloads-progress-icon.h"
+#include "ephy-embed.h"
+#include "ephy-embed-container.h"
 #include "ephy-shell.h"
 #include "ephy-window.h"
 
@@ -50,11 +52,27 @@ is_for_active_window (EphyActionBarEnd *action_bar_end)
   return active_window == GTK_WINDOW (ancestor);
 }
 
+static gboolean
+is_document_view_active (void)
+{
+  EphyShell *shell = ephy_shell_get_default ();
+  GtkWindow *window;
+  EphyEmbed *embed;
+
+  window = gtk_application_get_active_window (GTK_APPLICATION (shell));
+  embed = ephy_embed_container_get_active_child (EPHY_EMBED_CONTAINER (window));
+
+  return ephy_embed_get_mode (embed) == EPHY_EMBED_MODE_EVINCE_DOCUMENT;
+}
+
 static void
 download_added_cb (EphyDownloadsManager *manager,
                    EphyDownload         *download,
                    EphyActionBarEnd     *action_bar_end)
 {
+  if (is_document_view_active ())
+    return;
+
   if (!action_bar_end->downloads_popover) {
     action_bar_end->downloads_popover = ephy_downloads_popover_new (action_bar_end->downloads_button);
     gtk_menu_button_set_popover (GTK_MENU_BUTTON (action_bar_end->downloads_button),
diff --git a/src/ephy-main.c b/src/ephy-main.c
index 877952075..0796393c8 100644
--- a/src/ephy-main.c
+++ b/src/ephy-main.c
@@ -33,6 +33,7 @@
 #include "ephy-web-app-utils.h"
 
 #include <errno.h>
+#include <evince-document.h>
 #include <glib/gi18n.h>
 #include <glib-unix.h>
 #include <gtk/gtk.h>
@@ -408,6 +409,7 @@ main (int   argc,
   }
 
   hdy_init (&argc, &argv);
+  ev_init ();
 
   _ephy_shell_create_instance (mode);
 
@@ -433,6 +435,7 @@ main (int   argc,
   if (notify_is_initted ())
     notify_uninit ();
 
+  ev_shutdown ();
   ephy_settings_shutdown ();
   ephy_file_helpers_shutdown ();
   xmlCleanupParser ();
diff --git a/src/window-commands.c b/src/window-commands.c
index ef6c99023..5b695294e 100644
--- a/src/window-commands.c
+++ b/src/window-commands.c
@@ -668,7 +668,9 @@ window_cmd_navigation (GSimpleAction *action,
   web_view = EPHY_GET_WEBKIT_WEB_VIEW_FROM_EMBED (embed);
 
   if (strstr (g_action_get_name (G_ACTION (action)), "back")) {
+    ephy_embed_set_mode (embed, EPHY_EMBED_MODE_WEB_VIEW);
     webkit_web_view_go_back (web_view);
+
     gtk_widget_grab_focus (GTK_WIDGET (embed));
   } else {
     webkit_web_view_go_forward (web_view);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]