summaryrefslogtreecommitdiff
path: root/libview
diff options
context:
space:
mode:
authorStefano Karapetsas <[email protected]>2014-09-21 17:11:13 +0200
committerStefano Karapetsas <[email protected]>2014-09-21 17:11:13 +0200
commit5ac452a8a78841bf88dee6e7b0a9ea421299f669 (patch)
tree9989800bd8b0496fce4687673f8410b63b02a69f /libview
parent1bdae54253b68f2042f1d7f43ac0f36654c9b432 (diff)
parent67bb00b6c5105dc840b968db513a1e26bac7b2e0 (diff)
downloadatril-5ac452a8a78841bf88dee6e7b0a9ea421299f669.tar.bz2
atril-5ac452a8a78841bf88dee6e7b0a9ea421299f669.tar.xz
Merge pull request #84 from rootAvish/epub
Epub support in Atril
Diffstat (limited to 'libview')
-rw-r--r--libview/Makefile.am6
-rw-r--r--libview/ev-document-model.h4
-rw-r--r--libview/ev-jobs.c210
-rw-r--r--libview/ev-jobs.h13
-rwxr-xr-x[-rw-r--r--]libview/ev-view.c38
-rwxr-xr-x[-rw-r--r--]libview/ev-view.h2
-rw-r--r--libview/ev-web-view.c873
-rw-r--r--libview/ev-web-view.h89
8 files changed, 1211 insertions, 24 deletions
diff --git a/libview/Makefile.am b/libview/Makefile.am
index 7dd0a950..96e80ea3 100644
--- a/libview/Makefile.am
+++ b/libview/Makefile.am
@@ -19,6 +19,7 @@ INST_H_SRC_FILES = \
ev-print-operation.h \
ev-stock-icons.h \
ev-view.h \
+ ev-web-view.h \
ev-view-presentation.h
INST_H_FILES = \
@@ -41,6 +42,7 @@ libatrilview_la_SOURCES = \
ev-timeline.c \
ev-transition-animation.c \
ev-view.c \
+ ev-web-view.c \
ev-view-accessible.c \
ev-view-marshal.c \
ev-view-cursor.c \
@@ -63,6 +65,7 @@ libatrilview_la_CFLAGS = \
$(LIBVIEW_CFLAGS) \
$(WARN_CFLAGS) \
$(DISABLE_DEPRECATED) \
+ $(WEBKIT_CFLAGS) \
$(AM_CFLAGS)
libatrilview_la_LDFLAGS = \
@@ -73,7 +76,8 @@ libatrilview_la_LDFLAGS = \
libatrilview_la_LIBADD = \
$(top_builddir)/libdocument/libatrildocument.la \
- $(LIBVIEW_LIBS)
+ $(LIBVIEW_LIBS) \
+ $(WEBKIT_LIBS)
BUILT_SOURCES = \
ev-view-marshal.h \
diff --git a/libview/ev-document-model.h b/libview/ev-document-model.h
index b8bea62c..f9d175c0 100644
--- a/libview/ev-document-model.h
+++ b/libview/ev-document-model.h
@@ -69,7 +69,9 @@ EvSizingMode ev_document_model_get_sizing_mode (EvDocumentModel *model);
void ev_document_model_set_rotation (EvDocumentModel *model,
gint rotation);
gint ev_document_model_get_rotation (EvDocumentModel *model);
-void ev_document_model_set_inverted_colors (EvDocumentModel *model,
+void ev_document_model_set_inverted_colors (EvDocumentModel *model,
+ gboolean inverted_colors);
+void atril_web_document_set_inverted_colors(EvDocumentModel *model,
gboolean inverted_colors);
gboolean ev_document_model_get_inverted_colors (EvDocumentModel *model);
void ev_document_model_set_continuous (EvDocumentModel *model,
diff --git a/libview/ev-jobs.c b/libview/ev-jobs.c
index d8d3043d..3590d822 100644
--- a/libview/ev-jobs.c
+++ b/libview/ev-jobs.c
@@ -24,6 +24,7 @@
#include "ev-document-thumbnails.h"
#include "ev-document-links.h"
#include "ev-document-images.h"
+#include "ev-job-scheduler.h"
#include "ev-document-forms.h"
#include "ev-file-exporter.h"
#include "ev-document-factory.h"
@@ -39,6 +40,14 @@
#include "ev-document-text.h"
#include "ev-debug.h"
+#include <gtk/gtk.h>
+#ifdef ENABLE_EPUB
+#if GTK_CHECK_VERSION(3, 0, 0)
+#include <webkit2/webkit2.h>
+#else
+#include <webkit/webkit.h>
+#endif
+#endif
#include <errno.h>
#include <glib/gstdio.h>
#include <glib/gi18n-lib.h>
@@ -58,8 +67,8 @@ static void ev_job_page_data_init (EvJobPageData *job);
static void ev_job_page_data_class_init (EvJobPageDataClass *class);
static void ev_job_thumbnail_init (EvJobThumbnail *job);
static void ev_job_thumbnail_class_init (EvJobThumbnailClass *class);
-static void ev_job_load_init (EvJobLoad *job);
-static void ev_job_load_class_init (EvJobLoadClass *class);
+static void ev_job_load_init (EvJobLoad *job);
+static void ev_job_load_class_init (EvJobLoadClass *class);
static void ev_job_save_init (EvJobSave *job);
static void ev_job_save_class_init (EvJobSaveClass *class);
static void ev_job_find_init (EvJobFind *job);
@@ -87,6 +96,9 @@ enum {
FIND_LAST_SIGNAL
};
+static GtkWidget* webview;
+static GtkWidget* offscreenwindow;
+
static guint job_signals[LAST_SIGNAL] = { 0 };
static guint job_fonts_signals[FONTS_LAST_SIGNAL] = { 0 };
static guint job_find_signals[FIND_LAST_SIGNAL] = { 0 };
@@ -211,7 +223,7 @@ ev_job_run (EvJob *job)
{
EvJobClass *class = EV_JOB_GET_CLASS (job);
- return class->run (job);
+ return class-> run (job);
}
void
@@ -568,6 +580,24 @@ ev_job_render_run (EvJob *job)
ev_document_fc_mutex_lock ();
ev_page = ev_document_get_page (job->document, job_render->page);
+
+ if ( job->document->iswebdocument == TRUE )
+ {
+ return TRUE;
+
+ if (g_cancellable_is_cancelled (job->cancellable)) {
+ ev_document_fc_mutex_unlock ();
+ ev_document_doc_mutex_unlock ();
+ g_object_unref (rc);
+
+ return FALSE;
+ }
+
+ ev_document_fc_mutex_unlock ();
+ ev_document_doc_mutex_unlock ();
+ ev_job_succeeded (job);
+ return FALSE;
+ }
rc = ev_render_context_new (ev_page, job_render->rotation, job_render->scale);
g_object_unref (ev_page);
@@ -740,7 +770,7 @@ ev_job_page_data_new (EvDocument *document,
static void
ev_job_thumbnail_init (EvJobThumbnail *job)
{
- EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
+ EV_JOB (job)->run_mode = EV_JOB_RUN_THREAD;
}
static void
@@ -760,28 +790,140 @@ ev_job_thumbnail_dispose (GObject *object)
(* G_OBJECT_CLASS (ev_job_thumbnail_parent_class)->dispose) (object);
}
+#if !GTK_CHECK_VERSION(3, 0, 0)
+static gboolean
+web_thumbnail_get_screenshot_cb(EvJobThumbnail *job_thumb)
+{
+ if (webkit_web_view_get_load_status (WEBKIT_WEB_VIEW(webview)) != WEBKIT_LOAD_FINISHED) {
+ return TRUE;
+ }
+
+ EvPage *page = ev_document_get_page (EV_JOB(job_thumb)->document, job_thumb->page);
+ job_thumb->surface = webkit_web_view_get_snapshot (WEBKIT_WEB_VIEW(webview));
+ EvRenderContext *rc = ev_render_context_new (page, job_thumb->rotation, job_thumb->scale);
+ EvPage *screenshotpage;
+ screenshotpage = ev_page_new(job_thumb->page);
+ screenshotpage->backend_page = (EvBackendPage)job_thumb->surface;
+ screenshotpage->backend_destroy_func = (EvBackendPageDestroyFunc)cairo_surface_destroy ;
+ ev_render_context_set_page(rc,screenshotpage);
+
+ job_thumb->thumbnail = ev_document_thumbnails_get_thumbnail (EV_DOCUMENT_THUMBNAILS (EV_JOB(job_thumb)->document),
+ rc, TRUE);
+ g_object_unref(screenshotpage);
+ g_object_unref(rc);
+
+ ev_document_doc_mutex_unlock();
+ ev_job_succeeded(EV_JOB(job_thumb));
+ return FALSE;
+}
+#else
+
+static void
+snapshot_callback(WebKitWebView *webview,
+ GAsyncResult *results,
+ EvJobThumbnail *job_thumb)
+{
+ EvPage *page = ev_document_get_page (EV_JOB(job_thumb)->document, job_thumb->page);
+ job_thumb->surface = webkit_web_view_get_snapshot_finish (webview,
+ results,
+ NULL);
+ EvRenderContext *rc = ev_render_context_new (page, job_thumb->rotation, job_thumb->scale);
+ EvPage *screenshotpage;
+ screenshotpage = ev_page_new(job_thumb->page);
+ screenshotpage->backend_page = (EvBackendPage)job_thumb->surface;
+ screenshotpage->backend_destroy_func = (EvBackendPageDestroyFunc)cairo_surface_destroy ;
+ ev_render_context_set_page(rc,screenshotpage);
+
+ job_thumb->thumbnail = ev_document_thumbnails_get_thumbnail (EV_DOCUMENT_THUMBNAILS (EV_JOB(job_thumb)->document),
+ rc, TRUE);
+ g_object_unref(screenshotpage);
+ g_object_unref(rc);
+
+ ev_document_doc_mutex_unlock();
+ ev_job_succeeded(EV_JOB(job_thumb));
+}
+
+static void
+web_thumbnail_get_screenshot_cb (WebKitWebView *webview,
+ WebKitLoadEvent event,
+ EvJobThumbnail *job_thumb)
+{
+ if (event != WEBKIT_LOAD_FINISHED) {
+ return;
+ }
+
+ webkit_web_view_get_snapshot (webview,
+ WEBKIT_SNAPSHOT_REGION_VISIBLE,
+ WEBKIT_SNAPSHOT_OPTIONS_NONE,
+ NULL,
+ (GAsyncReadyCallback)snapshot_callback,
+ g_object_ref(job_thumb));
+}
+#endif
+
static gboolean
ev_job_thumbnail_run (EvJob *job)
{
EvJobThumbnail *job_thumb = EV_JOB_THUMBNAIL (job);
EvRenderContext *rc;
EvPage *page;
-
ev_debug_message (DEBUG_JOBS, "%d (%p)", job_thumb->page, job);
ev_profiler_start (EV_PROFILE_JOBS, "%s (%p)", EV_GET_TYPE_NAME (job), job);
-
- ev_document_doc_mutex_lock ();
+
+ if (job->document->iswebdocument) {
+ /* Do not block the main loop */
+ if (!ev_document_doc_mutex_trylock ())
+ return TRUE;
+ }
+ else {
+ ev_document_doc_mutex_lock ();
+ }
page = ev_document_get_page (job->document, job_thumb->page);
- rc = ev_render_context_new (page, job_thumb->rotation, job_thumb->scale);
+ if (job->document->iswebdocument == TRUE ) {
+ rc = ev_render_context_new (page, 0, job_thumb->scale);
+ }
+ else {
+ rc = ev_render_context_new (page, job_thumb->rotation, job_thumb->scale);
+ }
g_object_unref (page);
- job_thumb->thumbnail = ev_document_thumbnails_get_thumbnail (EV_DOCUMENT_THUMBNAILS (job->document),
- rc, TRUE);
- g_object_unref (rc);
- ev_document_doc_mutex_unlock ();
+ if (job->document->iswebdocument == TRUE) {
+ if (!webview) {
+ webview = webkit_web_view_new();
+ }
+
+ if (!offscreenwindow) {
+ offscreenwindow = gtk_offscreen_window_new();
+
+ gtk_container_add(GTK_CONTAINER(offscreenwindow),GTK_WIDGET(webview));
+
+ gtk_window_set_default_size (GTK_WINDOW(offscreenwindow),800,1080);
+
+ gtk_widget_show_all(offscreenwindow);
+ }
+
+ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webview),(gchar*)rc->page->backend_page);
+#if !GTK_CHECK_VERSION (3, 0, 0)
+ g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
+ (GSourceFunc)web_thumbnail_get_screenshot_cb,
+ g_object_ref (job_thumb),
+ (GDestroyNotify)g_object_unref);
+#else
+ g_signal_connect(WEBKIT_WEB_VIEW(webview),"load-changed",
+ G_CALLBACK(web_thumbnail_get_screenshot_cb),
+ g_object_ref(job_thumb));
- ev_job_succeeded (job);
+#endif
+ }
+ else {
+ job_thumb->thumbnail = ev_document_thumbnails_get_thumbnail (EV_DOCUMENT_THUMBNAILS (job->document),
+ rc, TRUE);
+ ev_document_doc_mutex_unlock ();
+
+ ev_job_succeeded (job);
+ }
+ g_object_unref (rc);
return FALSE;
}
@@ -1185,6 +1327,10 @@ ev_job_find_dispose (GObject *object)
g_free (job->pages);
job->pages = NULL;
}
+
+ if (job->results) {
+ g_free(job->results);
+ }
(* G_OBJECT_CLASS (ev_job_find_parent_class)->dispose) (object);
}
@@ -1196,7 +1342,6 @@ ev_job_find_run (EvJob *job)
EvDocumentFind *find = EV_DOCUMENT_FIND (job->document);
EvPage *ev_page;
GList *matches;
-
ev_debug_message (DEBUG_JOBS, NULL);
/* Do not block the main loop */
@@ -1210,16 +1355,30 @@ ev_job_find_run (EvJob *job)
#endif
ev_page = ev_document_get_page (job->document, job_find->current_page);
- matches = ev_document_find_find_text (find, ev_page, job_find->text,
- job_find->case_sensitive);
+
+ if (job->document->iswebdocument) {
+ job_find->results[job_find->current_page] = ev_document_find_check_for_hits(find, ev_page, job_find->text,
+ job_find->case_sensitive);
+ }else {
+ matches = ev_document_find_find_text (find, ev_page, job_find->text,
+ job_find->case_sensitive);
+ }
+
g_object_unref (ev_page);
ev_document_doc_mutex_unlock ();
- if (!job_find->has_results)
+ if (!job_find->has_results && !job->document->iswebdocument) {
job_find->has_results = (matches != NULL);
+ }
+ else if (!job_find->has_results && job->document->iswebdocument){
+ job_find->has_results = (job_find->results[job_find->current_page] > 0);
+ }
+
+ if (job->document->iswebdocument == FALSE) {
+ job_find->pages[job_find->current_page] = matches;
+ }
- job_find->pages[job_find->current_page] = matches;
g_signal_emit (job_find, job_find_signals[FIND_UPDATED], 0, job_find->current_page);
job_find->current_page = (job_find->current_page + 1) % job_find->n_pages;
@@ -1269,7 +1428,13 @@ ev_job_find_new (EvDocument *document,
job->start_page = start_page;
job->current_page = start_page;
job->n_pages = n_pages;
- job->pages = g_new0 (GList *, n_pages);
+
+ if (document->iswebdocument) {
+ job->results = g_malloc0 (sizeof(guint) *n_pages);
+ }
+ else {
+ job->pages = g_new0 (GList *, n_pages);
+ }
job->text = g_strdup (text);
job->case_sensitive = case_sensitive;
job->has_results = FALSE;
@@ -1281,7 +1446,12 @@ gint
ev_job_find_get_n_results (EvJobFind *job,
gint page)
{
- return g_list_length (job->pages[page]);
+ if (EV_JOB(job)->document->iswebdocument) {
+ return job->results[page];
+ }
+ else {
+ return g_list_length (job->pages[page]);
+ }
}
gdouble
diff --git a/libview/ev-jobs.h b/libview/ev-jobs.h
index e6ae4552..fdc23bae 100644
--- a/libview/ev-jobs.h
+++ b/libview/ev-jobs.h
@@ -45,6 +45,9 @@ typedef struct _EvJobPageDataClass EvJobPageDataClass;
typedef struct _EvJobThumbnail EvJobThumbnail;
typedef struct _EvJobThumbnailClass EvJobThumbnailClass;
+typedef struct _EvJobWebThumbnail EvJobWebThumbnail;
+typedef struct _EvJobWebThumbnailClass EvJobWebThumbnailClass;
+
typedef struct _EvJobLinks EvJobLinks;
typedef struct _EvJobLinksClass EvJobLinksClass;
@@ -111,6 +114,11 @@ typedef struct _EvJobPrintClass EvJobPrintClass;
#define EV_JOB_THUMBNAIL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_JOB_THUMBNAIL, EvJobThumbnailClass))
#define EV_IS_JOB_THUMBNAIL(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_JOB_THUMBNAIL))
+#define EV_TYPE_JOB_WEB_THUMBNAIL (ev_job_web_thumbnail_get_type())
+#define EV_JOB_WEB_THUMBNAIL(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_JOB_WEB_THUMBNAIL, EvJobWebThumbnail))
+#define EV_JOB_WEB_THUMBNAIL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_JOB_WEB_THUMBNAIL, EvJobWebThumbnailClass))
+#define EV_IS_JOB_WEB_THUMBNAIL(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), EV_TYPE_JOB_WEB_THUMBNAIL))
+
#define EV_TYPE_JOB_FONTS (ev_job_fonts_get_type())
#define EV_JOB_FONTS(object) (G_TYPE_CHECK_INSTANCE_CAST((object), EV_TYPE_JOB_FONTS, EvJobFonts))
#define EV_JOB_FONTS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), EV_TYPE_JOB_FONTS, EvJobFontsClass))
@@ -281,11 +289,10 @@ struct _EvJobPageDataClass
struct _EvJobThumbnail
{
EvJob parent;
-
gint page;
gint rotation;
gdouble scale;
-
+ cairo_surface_t *surface;
GdkPixbuf *thumbnail;
};
@@ -343,6 +350,7 @@ struct _EvJobFind
gint current_page;
gint n_pages;
GList **pages;
+ guint *results;
gchar *text;
gboolean case_sensitive;
gboolean has_results;
@@ -450,6 +458,7 @@ EvJob *ev_job_thumbnail_new (EvDocument *document,
gint page,
gint rotation,
gdouble scale);
+
/* EvJobFonts */
GType ev_job_fonts_get_type (void) G_GNUC_CONST;
EvJob *ev_job_fonts_new (EvDocument *document);
diff --git a/libview/ev-view.c b/libview/ev-view.c
index 7bb56cae..ec378758 100644..100755
--- a/libview/ev-view.c
+++ b/libview/ev-view.c
@@ -6568,3 +6568,41 @@ ev_view_previous_page (EvView *view)
}
}
+/**
+ * ev_view_disconnect_handlers
+ * @view: #EvView instance
+ *
+ * Disconnect all signal handlers from the model, to ensure error free operation of the webview,
+ * we have an equivalent function for the webview.
+ */
+void
+ev_view_disconnect_handlers(EvView *view)
+{
+ g_signal_handlers_disconnect_by_func(view->model,
+ G_CALLBACK (ev_view_rotation_changed_cb),
+ view);
+ g_signal_handlers_disconnect_by_func(view->model,
+ G_CALLBACK (ev_view_inverted_colors_changed_cb),
+ view);
+ g_signal_handlers_disconnect_by_func(view->model,
+ G_CALLBACK (ev_view_sizing_mode_changed_cb),
+ view);
+ g_signal_handlers_disconnect_by_func(view->model,
+ G_CALLBACK (ev_view_scale_changed_cb),
+ view);
+ g_signal_handlers_disconnect_by_func(view->model,
+ G_CALLBACK (ev_view_continuous_changed_cb),
+ view);
+ g_signal_handlers_disconnect_by_func(view->model,
+ G_CALLBACK (ev_view_dual_page_changed_cb),
+ view);
+ g_signal_handlers_disconnect_by_func(view->model,
+ G_CALLBACK (ev_view_fullscreen_changed_cb),
+ view);
+ g_signal_handlers_disconnect_by_func(view->model,
+ G_CALLBACK (ev_view_page_changed_cb),
+ view);
+ g_signal_handlers_disconnect_by_func(view->model,
+ G_CALLBACK (ev_view_document_changed_cb),
+ view);
+} \ No newline at end of file
diff --git a/libview/ev-view.h b/libview/ev-view.h
index 402b9895..0a9e1718 100644..100755
--- a/libview/ev-view.h
+++ b/libview/ev-view.h
@@ -110,6 +110,8 @@ void ev_view_begin_add_annotation (EvView *view,
EvAnnotationType annot_type);
void ev_view_cancel_add_annotation (EvView *view);
+/*For epub*/
+void ev_view_disconnect_handlers (EvView *view);
G_END_DECLS
#endif /* __EV_VIEW_H__ */
diff --git a/libview/ev-web-view.c b/libview/ev-web-view.c
new file mode 100644
index 00000000..b42da163
--- /dev/null
+++ b/libview/ev-web-view.c
@@ -0,0 +1,873 @@
+/* this file is part of atril, a mate document viewer
+ *
+ * Copyright (C) 2014 Avishkar Gupta
+ * Based on ev-view.c, also a part of atril, a mate document viewer.
+ *
+ * Atril 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 of the License, or
+ * (at your option) any later version.
+ *
+ * Atril 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 <glib/gi18n-lib.h>
+#include <gtk/gtk.h>
+#include <stdlib.h>
+
+#if GTK_CHECK_VERSION (3, 0, 0)
+#include <webkit2/webkit2.h>
+#else
+#include <webkit/webkit.h>
+#endif
+
+#include "ev-web-view.h"
+#include "ev-document-model.h"
+#include "ev-jobs.h"
+
+#define EV_WEB_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EV_TYPE_WEB_VIEW, EvWebViewClass))
+#define EV_IS_WEB_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EV_TYPE_WEB_VIEW))
+#define EV_WEB_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EV_TYPE_WEB_VIEW, EvWebViewClass))
+
+ typedef enum {
+ EV_WEB_VIEW_FIND_NEXT,
+ EV_WEB_VIEW_FIND_PREV
+ } EvWebViewFindDirection;
+
+typedef struct _SearchParams {
+ gboolean case_sensitive;
+ gchar* search_string;
+ EvWebViewFindDirection direction;
+ gboolean search_jump;
+ gint on_result;
+ guint *results;
+}SearchParams;
+
+struct _EvWebView
+{
+ WebKitWebView web_view;
+ EvDocument *document;
+ EvDocumentModel *model;
+ gint current_page;
+ gboolean inverted_stylesheet ;
+ gboolean fullscreen;
+ SearchParams *search;
+#if GTK_CHECK_VERSION (3, 0, 0)
+ WebKitFindController *findcontroller;
+ WebKitFindOptions findoptions;
+ gdouble zoom_level;
+#endif
+ gchar *hlink;
+};
+
+struct _EvWebViewClass
+{
+ WebKitWebViewClass base_class;
+};
+
+/*** Callbacks ***/
+static void ev_web_view_change_page (EvWebView *webview,
+ gint new_page);
+
+static void ev_web_view_page_changed_cb (EvDocumentModel *model,
+ gint old_page,
+ gint new_page,
+ EvWebView *webview);
+/*** GObject ***/
+static void ev_web_view_dispose (GObject *object);
+
+static void ev_web_view_finalize (GObject *object);
+static void ev_web_view_class_init (EvWebViewClass *klass);
+static void ev_web_view_init (EvWebView *webview);
+
+G_DEFINE_TYPE (EvWebView, ev_web_view, WEBKIT_TYPE_WEB_VIEW)
+
+static void
+web_view_update_range_and_current_page (EvWebView *webview)
+{
+ g_return_if_fail(EV_IS_WEB_VIEW(webview));
+
+ if (ev_document_get_n_pages (webview->document) <= 0)
+ return;
+
+ ev_document_model_set_page(webview->model, 0);
+ webview->current_page = 0;
+ EvPage *webpage = ev_document_get_page(webview->document,0);
+ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webview),(gchar*)webpage->backend_page);
+}
+
+static void
+ev_web_view_dispose (GObject *object)
+{
+ EvWebView *webview = EV_WEB_VIEW (object);
+
+ if (webview->document) {
+ g_object_unref(webview->document);
+ webview->document = NULL ;
+ }
+
+ if (webview->model) {
+ g_object_unref(webview->model);
+ webview->model = NULL;
+ }
+
+ if (webview->hlink) {
+ g_free(webview->hlink);
+ webview->hlink = NULL;
+ }
+
+ if (webview->search) {
+ g_free(webview->search);
+ webview->search = NULL;
+ }
+
+ G_OBJECT_CLASS (ev_web_view_parent_class)->dispose (object);
+}
+
+static void
+ev_web_view_class_init (EvWebViewClass *klass)
+{
+ G_OBJECT_CLASS(klass)->finalize = ev_web_view_finalize;
+ G_OBJECT_CLASS(klass)->dispose = ev_web_view_dispose;
+}
+
+static void
+ev_web_view_init (EvWebView *webview)
+{
+ gtk_widget_set_can_focus (GTK_WIDGET (webview), TRUE);
+
+ gtk_widget_set_has_window (GTK_WIDGET (webview), TRUE);
+
+ webview->current_page = 0;
+
+ webview->search = g_new0(SearchParams, 1);
+ webview->search->search_string = NULL;
+
+ webview->search->on_result = -1 ;
+ webview->search->results = NULL;
+ webview->search->search_jump = TRUE ;
+
+ webview->fullscreen = FALSE;
+ webview->inverted_stylesheet = FALSE;
+ webview->hlink = NULL;
+}
+
+static void
+ev_web_view_finalize (GObject *object)
+{
+ G_OBJECT_CLASS(ev_web_view_parent_class)->finalize(object);
+}
+
+/*** Callbacks ***/
+
+static void
+ev_web_view_change_page (EvWebView *webview,
+ gint new_page)
+{
+ g_return_if_fail(EV_IS_WEB_VIEW(webview));
+
+ EvDocumentClass *klass = EV_DOCUMENT_GET_CLASS(webview->document);
+
+ webview->current_page = new_page;
+ ev_document_model_set_page(webview->model,new_page);
+#if GTK_CHECK_VERSION (3, 0, 0)
+ webkit_find_controller_search_finish(webview->findcontroller);
+#else
+ webkit_web_view_unmark_text_matches (WEBKIT_WEB_VIEW(webview));
+#endif
+ if (webview->hlink) {
+ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webview),(gchar*)webview->hlink);
+ g_free(webview->hlink);
+ webview->hlink = NULL;
+ }
+ else {
+ EvPage *page = klass->get_page(webview->document,new_page);
+ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webview),(gchar*)page->backend_page);
+ }
+}
+
+static void
+ev_web_view_page_changed_cb (EvDocumentModel *model,
+ gint old_page,
+ gint new_page,
+ EvWebView *webview)
+{
+ if (!webview->document)
+ return;
+
+ if (webview->current_page != new_page) {
+ ev_web_view_change_page (webview, new_page);
+ } else {
+ webkit_web_view_reload (WEBKIT_WEB_VIEW(webview));
+ }
+}
+
+GtkWidget*
+ev_web_view_new (void)
+{
+ GtkWidget *webview;
+
+ webview = g_object_new (EV_TYPE_WEB_VIEW, NULL);
+
+ #if GTK_CHECK_VERSION (3, 0, 0)
+ EV_WEB_VIEW(webview)->findcontroller = webkit_web_view_get_find_controller (WEBKIT_WEB_VIEW(webview));
+ EV_WEB_VIEW(webview)->findoptions = webkit_find_controller_get_options (EV_WEB_VIEW(webview)->findcontroller);
+
+ EV_WEB_VIEW(webview)->zoom_level = 1.0;
+
+ EV_WEB_VIEW(webview)->findoptions |= WEBKIT_FIND_OPTIONS_NONE;
+ #endif
+
+ return webview;
+}
+
+static void
+ev_web_view_document_changed_cb (EvDocumentModel *model,
+ GParamSpec *pspec,
+ EvWebView *webview)
+{
+ g_return_if_fail(EV_IS_WEB_VIEW(webview));
+
+ EvDocument *document = ev_document_model_get_document (model);
+
+ if (document != webview->document) {
+
+ if (webview->document )
+ g_object_unref(webview->document);
+
+ webview->document = document ;
+
+ if(webview->document) {
+ g_object_ref(webview->document);
+ }
+ webview->inverted_stylesheet = FALSE;
+ gint current_page = ev_document_model_get_page(model);
+
+ ev_web_view_change_page (webview, current_page);
+
+ }
+}
+
+static void
+ev_web_view_inverted_colors_changed_cb (EvDocumentModel *model,
+ GParamSpec *pspec,
+ EvWebView *webview)
+{
+ EvDocument *document = ev_document_model_get_document(model);
+
+ if (ev_document_model_get_inverted_colors(model) == TRUE) {
+ if (document == NULL) {
+ ev_document_model_set_inverted_colors(model,FALSE);
+ return;
+ }
+ if (webview->inverted_stylesheet == FALSE) {
+ ev_document_check_add_night_sheet(document);
+ webview->inverted_stylesheet = TRUE;
+ }
+ ev_document_toggle_night_mode(document,TRUE);
+ webkit_web_view_reload(WEBKIT_WEB_VIEW(webview));
+ }
+ else {
+ if (document != NULL) {
+ ev_document_toggle_night_mode(document,FALSE);
+ webkit_web_view_reload(WEBKIT_WEB_VIEW(webview));
+ }
+ }
+}
+
+void
+ev_web_view_set_model (EvWebView *webview,
+ EvDocumentModel *model)
+{
+ g_return_if_fail (EV_IS_WEB_VIEW (webview));
+ g_return_if_fail (EV_IS_DOCUMENT_MODEL (model));
+
+ if (model == webview->model)
+ return;
+
+ if (webview->model) {
+ g_signal_handlers_disconnect_by_func (webview->model,
+ ev_web_view_document_changed_cb,
+ webview);
+ g_signal_handlers_disconnect_by_func (webview->model,
+ ev_web_view_page_changed_cb,
+ webview);
+ g_object_unref (webview->model);
+ }
+ webview->model = g_object_ref (model);
+
+ /* Initialize webview from model */
+ webview->fullscreen = ev_document_model_get_fullscreen (webview->model);
+ webview->document = ev_document_model_get_document(webview->model);
+
+ ev_web_view_document_changed_cb (webview->model, NULL, webview);
+
+ g_signal_connect (webview->model, "notify::document",
+ G_CALLBACK (ev_web_view_document_changed_cb),
+ webview);
+ g_signal_connect (webview->model, "notify::inverted-colors",
+ G_CALLBACK (ev_web_view_inverted_colors_changed_cb),
+ webview);
+ g_signal_connect (webview->model,"page-changed",
+ G_CALLBACK(ev_web_view_page_changed_cb),
+ webview);
+}
+
+void
+ev_web_view_reload_page (EvWebView *webview,
+ gint page)
+{
+ webkit_web_view_reload (WEBKIT_WEB_VIEW(webview));
+}
+
+void
+ev_web_view_reload (EvWebView *webview)
+{
+ web_view_update_range_and_current_page (webview);
+}
+
+
+gboolean
+ev_web_view_next_page (EvWebView *webview)
+{
+ int page, n_pages;
+
+ g_return_val_if_fail (EV_IS_WEB_VIEW (webview), FALSE);
+
+ if (!webview->document)
+ return FALSE;
+
+ page = ev_document_model_get_page (webview->model);
+ n_pages = ev_document_get_n_pages (webview->document);
+
+ page = page + 1;
+
+ if (page < n_pages) {
+ ev_document_model_set_page (webview->model, page);
+ EvPage *webpage = ev_document_get_page(webview->document,page);
+ webview->current_page = page ;
+ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webview),(gchar*)webpage->backend_page);
+ return TRUE;
+ } else if (page == n_pages) {
+ ev_document_model_set_page (webview->model, page - 1);
+ EvPage *webpage = ev_document_get_page(webview->document,page);
+ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webview),(gchar*)webpage->backend_page);
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+gboolean
+ev_web_view_previous_page (EvWebView *webview)
+{
+ int page;
+
+ g_return_val_if_fail (EV_IS_WEB_VIEW (webview), FALSE);
+
+ if (!webview->document)
+ return FALSE;
+
+ page = ev_document_model_get_page (webview->model);
+
+ page = page - 1 ;
+
+ if (page >= 0) {
+ ev_document_model_set_page (webview->model, page);
+ EvPage *webpage = ev_document_get_page(webview->document,page);
+ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webview),(gchar*)webpage->backend_page);
+ return TRUE;
+ } else if (page == -1) {
+ ev_document_model_set_page (webview->model, 0);
+ EvPage *webpage = ev_document_get_page(webview->document,page);
+ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webview),(gchar*)webpage->backend_page);
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+void
+ev_web_view_handle_link(EvWebView *webview,EvLink *link)
+{
+ EvLinkAction *action = NULL;
+ EvLinkDest *dest = NULL;
+ EvLinkDestType dest_type ;
+ action = ev_link_get_action(link);
+
+ if (action == NULL)
+ return;
+
+ dest = ev_link_action_get_dest(action);
+
+ if (dest == NULL)
+ return;
+
+ dest_type = ev_link_dest_get_dest_type(dest);
+
+ switch(dest_type) {
+ case EV_LINK_DEST_TYPE_PAGE: {
+ ev_document_model_set_page(webview->model,ev_link_dest_get_page(dest));
+ break;
+ }
+
+ case EV_LINK_DEST_TYPE_PAGE_LABEL: {
+ const gchar *text = ev_link_dest_get_page_label (dest);
+ gint page = atoi(text);
+
+ if (page <= ev_document_get_n_pages(webview->document) && page > 0) {
+ ev_document_model_set_page(webview->model,page-1);
+ }
+ break;
+ }
+ case EV_LINK_DEST_TYPE_HLINK: {
+ const gchar *uri = ev_link_dest_get_named_dest(dest);
+ ev_document_model_set_page(webview->model,ev_link_dest_get_page(dest));
+ webkit_web_view_load_uri(WEBKIT_WEB_VIEW(webview),uri);
+ break;
+
+ default:return;
+ }
+ }
+}
+/* Searching */
+
+#if !GTK_CHECK_VERSION (3, 0, 0)
+static void
+jump_to_find_result_on_page(EvWebView *webview,
+ EvWebViewFindDirection direction)
+{
+ gboolean forward,wrap;
+
+ if (direction == EV_WEB_VIEW_FIND_NEXT) {
+ forward = TRUE;
+ wrap = FALSE;
+ }
+ else {
+ forward = FALSE;
+ wrap = FALSE;
+ }
+
+ if (webview->search->search_jump) {
+ wrap = TRUE;
+ }
+ webkit_web_view_search_text (WEBKIT_WEB_VIEW(webview),
+ webview->search->search_string,
+ webview->search->case_sensitive,
+ forward,
+ wrap);
+
+ webview->search->search_jump = FALSE;
+}
+#endif
+
+#if GTK_CHECK_VERSION (3, 0, 0)
+static void
+results_counted_cb(WebKitFindController *findcontroller,
+ guint match_count,
+ EvWebView *webview)
+{
+ if (match_count > 0 && webview->search->on_result < match_count) {
+ webkit_find_controller_search(findcontroller,
+ webview->search->search_string,
+ webview->findoptions,
+ match_count);
+ webview->search->search_jump = FALSE;
+ }
+}
+#endif
+/*
+ * Jump to find results once we have changed the page in the webview.
+ */
+#if GTK_CHECK_VERSION (3, 0, 0)
+static void
+jump_to_find_results(EvWebView *webview,
+ WebKitLoadEvent load_event,
+ gpointer data)
+#else
+static void
+jump_to_find_results(EvWebView *webview,
+ GParamSpec *pspec,
+ gpointer data)
+#endif
+{
+ #if !GTK_CHECK_VERSION (3, 0, 0)
+ gint n_results;
+ gboolean forward ;
+ gboolean wrap ;
+
+ if (webkit_web_view_get_load_status(WEBKIT_WEB_VIEW(webview)) != WEBKIT_LOAD_FINISHED) {
+ return;
+ }
+#else
+ if ( load_event != WEBKIT_LOAD_FINISHED) {
+ return;
+ }
+#endif
+ if (!webview->search->search_string) {
+ return;
+ }
+
+#if GTK_CHECK_VERSION (3, 0, 0)
+ if (webview->search->direction == EV_WEB_VIEW_FIND_NEXT) {
+ webview->findoptions &= ~WEBKIT_FIND_OPTIONS_BACKWARDS;
+ webview->findoptions &= ~WEBKIT_FIND_OPTIONS_WRAP_AROUND;
+ }
+ else {
+ webview->findoptions |= WEBKIT_FIND_OPTIONS_BACKWARDS;
+ webview->findoptions |= WEBKIT_FIND_OPTIONS_WRAP_AROUND;
+ }
+
+ webkit_find_controller_count_matches (webview->findcontroller,
+ webview->search->search_string,
+ webview->findoptions,
+ G_MAXUINT);
+#else
+ n_results = webkit_web_view_mark_text_matches (WEBKIT_WEB_VIEW(webview),
+ webview->search->search_string,
+ webview->search->case_sensitive,
+ 0);
+
+ ev_web_view_find_set_highlight_search(webview,TRUE);
+
+ if (webview->search->direction == EV_WEB_VIEW_FIND_NEXT) {
+ forward = TRUE ;
+ wrap = FALSE;
+ }
+ else {
+ forward = FALSE;
+ wrap = TRUE ;
+ }
+
+ if (n_results > 0 && webview->search->on_result < n_results) {
+ webkit_web_view_search_text (WEBKIT_WEB_VIEW(webview),
+ webview->search->search_string,
+ webview->search->case_sensitive,
+ forward,
+ wrap);
+
+ webview->search->search_jump = FALSE;
+ }
+#endif
+ webview->search->search_jump = FALSE;
+}
+
+static gint
+ev_web_view_find_get_n_results (EvWebView *webview, gint page)
+{
+ return webview->search->results[page];
+}
+
+/**
+ * jump_to_find_page
+ * @webview: #EvWebView instance
+ * @direction: Direction to look
+ * @shift: Shift from current page
+ *
+ * Jumps to the first page that has occurences of searched word.
+ * Uses a direction where to look and a shift from current page.
+**/
+static void
+jump_to_find_page (EvWebView *webview, EvWebViewFindDirection direction, gint shift)
+{
+ int n_pages, i;
+
+ n_pages = ev_document_get_n_pages (webview->document);
+
+ for (i = 0; i < n_pages; i++) {
+ int page;
+
+ if (direction == EV_WEB_VIEW_FIND_NEXT)
+ page = webview->current_page + i;
+ else
+ page = webview->current_page - i;
+ page += shift;
+
+ if (page >= n_pages) {
+ page = page - n_pages;
+ } else if (page < 0)
+ page = page + n_pages;
+
+ if (page == webview->current_page && ev_web_view_find_get_n_results(webview,page) > 0) {
+#if !GTK_CHECK_VERSION (3, 0, 0)
+ jump_to_find_result_on_page(webview,EV_WEB_VIEW_FIND_NEXT);
+#else
+ if (direction == EV_WEB_VIEW_FIND_PREV) {
+ webview->findoptions |= WEBKIT_FIND_OPTIONS_WRAP_AROUND;
+ webview->findoptions |= WEBKIT_FIND_OPTIONS_BACKWARDS;
+ }
+ else {
+ if (webview->search->search_jump)
+ webview->findoptions |= WEBKIT_FIND_OPTIONS_WRAP_AROUND;
+ else
+ webview->findoptions &= ~WEBKIT_FIND_OPTIONS_WRAP_AROUND;
+
+ webview->findoptions &= ~WEBKIT_FIND_OPTIONS_BACKWARDS;
+ }
+
+ webkit_find_controller_search (webview->findcontroller,
+ webview->search->search_string,
+ webview->findoptions,
+ /*Highlight all the results.*/
+ G_MAXUINT);
+ webview->search->search_jump = FALSE;
+#endif
+ break;
+ }
+
+ if (ev_web_view_find_get_n_results (webview, page) > 0) {
+ webview->search->direction = direction;
+#if !GTK_CHECK_VERSION (3, 0, 0)
+ webkit_web_view_unmark_text_matches (WEBKIT_WEB_VIEW(webview));
+#else
+ webkit_find_controller_search_finish(webview->findcontroller);
+#endif
+ ev_document_model_set_page (webview->model, page);
+ break;
+ }
+ }
+}
+
+void
+ev_web_view_find_changed (EvWebView *webview, guint *results, gchar *text,gboolean case_sensitive)
+{
+ webview->search->results = results;
+ webview->search->on_result = 0;
+ webview->search->search_string = g_strdup(text);
+ webview->search->case_sensitive = case_sensitive;
+ if (webview->search->search_jump == TRUE) {
+#if GTK_CHECK_VERSION (3, 0, 0)
+ if (!case_sensitive) {
+ webview->findoptions |= WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE;
+ }
+ else {
+ webview->findoptions &= ~WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE;
+ }
+#endif
+ jump_to_find_page (webview, EV_WEB_VIEW_FIND_NEXT, 0);
+ }
+}
+
+void
+ev_web_view_find_next (EvWebView *webview)
+{
+ gint n_results;
+
+ n_results = ev_web_view_find_get_n_results (webview, webview->current_page);
+ webview->search->on_result++;
+
+ if (webview->search->on_result >= n_results) {
+ webview->search->on_result = 0;
+ jump_to_find_page (webview, EV_WEB_VIEW_FIND_NEXT, 1);
+ }
+ else {
+#if GTK_CHECK_VERSION (3, 0, 0)
+ webkit_find_controller_search_next(webview->findcontroller);
+#else
+ jump_to_find_result_on_page (webview, EV_WEB_VIEW_FIND_NEXT);
+#endif
+ }
+}
+
+void
+ev_web_view_find_previous (EvWebView *webview)
+{
+ webview->search->on_result--;
+
+ if (webview->search->on_result < 0) {
+ jump_to_find_page (webview, EV_WEB_VIEW_FIND_PREV, -1);
+ webview->search->on_result = MAX (0, ev_web_view_find_get_n_results (webview, webview->current_page) - 1);
+ } else {
+#if GTK_CHECK_VERSION (3, 0, 0)
+ webkit_find_controller_search_previous(webview->findcontroller);
+#else
+ jump_to_find_result_on_page (webview,EV_WEB_VIEW_FIND_PREV);
+#endif
+ }
+}
+
+void
+ev_web_view_find_search_changed (EvWebView *webview)
+{
+ /* search string has changed, focus on new search result */
+#if !GTK_CHECK_VERSION(3, 0, 0)
+ webkit_web_view_unmark_text_matches(WEBKIT_WEB_VIEW(webview));
+#endif
+ if (webview->search->search_string) {
+ g_free(webview->search->search_string);
+ webview->search->search_string = NULL;
+ }
+#if GTK_CHECK_VERSION(3, 0, 0)
+ webkit_find_controller_search_finish(webview->findcontroller);
+#endif
+
+ webview->search->search_jump = TRUE;
+}
+
+#if !GTK_CHECK_VERSION (3, 0, 0)
+void
+ev_web_view_find_set_highlight_search (EvWebView *webview, gboolean value)
+{
+ webkit_web_view_set_highlight_text_matches (WEBKIT_WEB_VIEW(webview),value);
+}
+#endif
+
+void
+ev_web_view_find_cancel (EvWebView *webview)
+{
+#if GTK_CHECK_VERSION (3, 0, 0)
+ webkit_find_controller_search_finish (webview->findcontroller);
+#else
+ webkit_web_view_unmark_text_matches(WEBKIT_WEB_VIEW(webview));
+ ev_web_view_find_set_highlight_search(webview,FALSE);
+#endif
+}
+
+
+
+void
+ev_web_view_set_handler(EvWebView *webview,gboolean visible)
+{
+ if (visible) {
+ g_signal_connect(webview,
+#if GTK_CHECK_VERSION (3, 0, 0)
+ "load-changed",
+#else
+ "notify::load-status",
+#endif
+ G_CALLBACK(jump_to_find_results),
+ NULL);
+#if GTK_CHECK_VERSION (3, 0, 0)
+ g_signal_connect(webview->findcontroller,
+ "counted-matches",
+ G_CALLBACK(results_counted_cb),
+ webview);
+#endif
+ }
+ else {
+ g_signal_handlers_disconnect_by_func(webview,
+ jump_to_find_results,
+ NULL);
+#if GTK_CHECK_VERSION (3, 0, 0)
+ g_signal_handlers_disconnect_by_func(webview,
+ results_counted_cb,
+ NULL);
+#endif
+ }
+}
+
+/* Selection and copying*/
+#if !GTK_CHECK_VERSION (3, 0, 0)
+gboolean
+ev_web_view_get_has_selection(EvWebView *webview)
+{
+ return webkit_web_view_has_selection(WEBKIT_WEB_VIEW(webview));
+}
+#endif
+
+void
+ev_web_view_select_all(EvWebView *webview)
+{
+#if GTK_CHECK_VERSION (3, 0, 0)
+ webkit_web_view_execute_editing_command(WEBKIT_WEB_VIEW(webview),
+ WEBKIT_EDITING_COMMAND_SELECT_ALL);
+#else
+ webkit_web_view_select_all(WEBKIT_WEB_VIEW(webview));
+#endif
+}
+
+#if GTK_CHECK_VERSION (3, 0, 0)
+static void
+copy_text_cb(WebKitWebView *webview,
+ GAsyncResult *res,
+ gpointer data)
+{
+ gboolean okay_to_copy = webkit_web_view_can_execute_editing_command_finish (WEBKIT_WEB_VIEW(webview),
+ res,
+ NULL);
+
+ if (okay_to_copy) {
+ webkit_web_view_execute_editing_command (WEBKIT_WEB_VIEW(webview),
+ WEBKIT_EDITING_COMMAND_COPY);
+ }
+}
+#endif
+
+void
+ev_web_view_copy(EvWebView *webview)
+{
+#if !GTK_CHECK_VERSION (3, 0, 0)
+ /* If for some reason we don't have a selection any longer,best to be safe */
+ if (ev_web_view_get_has_selection(webview) == FALSE)
+ return;
+ if (webkit_web_view_can_copy_clipboard(WEBKIT_WEB_VIEW(webview))) {
+ webkit_web_view_copy_clipboard(WEBKIT_WEB_VIEW(webview));
+ }
+#else
+ webkit_web_view_can_execute_editing_command(WEBKIT_WEB_VIEW(webview),
+ WEBKIT_EDITING_COMMAND_COPY,
+ NULL,
+ (GAsyncReadyCallback)copy_text_cb,
+ NULL);
+
+#endif
+
+}
+
+/*Zoom control*/
+gboolean
+ev_web_view_zoom_in(EvWebView *webview)
+{
+#if GTK_CHECK_VERSION (3, 0, 0)
+ webkit_web_view_set_zoom_level (WEBKIT_WEB_VIEW(webview),
+ (webview->zoom_level+= 0.1));
+#else
+ webkit_web_view_zoom_in(WEBKIT_WEB_VIEW(webview));
+#endif
+ return TRUE;
+}
+
+gboolean
+ev_web_view_zoom_out(EvWebView *webview)
+{
+#if GTK_CHECK_VERSION (3, 0, 0)
+ if (webview->zoom_level == 1)
+ return FALSE;
+
+ webkit_web_view_set_zoom_level (WEBKIT_WEB_VIEW(webview),
+ (webview->zoom_level -= 0.1));
+#else
+ webkit_web_view_zoom_out(WEBKIT_WEB_VIEW(webview));
+#endif
+ return TRUE;
+}
+
+/**
+ * ev_web_view_disconnect_handlers
+ * @webview : #EvWebView instance
+ *
+ * This function call will disconnect all model signal handlers from the webview, to ensure smooth operation of the Atril-view.
+ * Equivalent to function ev_view_disconnect_handlers in ev-view.c
+ */
+void
+ev_web_view_disconnect_handlers(EvWebView *webview)
+{
+ g_signal_handlers_disconnect_by_func(webview->model,
+ ev_web_view_document_changed_cb,
+ webview);
+ g_signal_handlers_disconnect_by_func(webview->model,
+ ev_web_view_inverted_colors_changed_cb,
+ webview);
+ g_signal_handlers_disconnect_by_func(webview->model,
+ ev_web_view_page_changed_cb,
+ webview);
+} \ No newline at end of file
diff --git a/libview/ev-web-view.h b/libview/ev-web-view.h
new file mode 100644
index 00000000..74b7eb6b
--- /dev/null
+++ b/libview/ev-web-view.h
@@ -0,0 +1,89 @@
+/* this file is part of atril, a mate document viewer
+ *
+ * Copyright (C) 2014 Avishkar Gupta
+ * Based on ev-view.h, also a part of atril, a mate document viewer
+ *
+ * Atril 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 of the License, or
+ * (at your option) any later version.
+ *
+ * Atril 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.
+ */
+
+#if !defined (__EV_ATRIL_VIEW_H_INSIDE__) && !defined (ATRIL_COMPILATION)
+#error "Only <atril-web_view.h> can be included directly."
+#endif
+
+#ifndef __EV_WEB_VIEW_H__
+#define __EV_WEB_VIEW_H__
+
+#include <gtk/gtk.h>
+
+#include <atril-document.h>
+#include "ev-jobs.h"
+#include "ev-document-model.h"
+#include <glib-object.h>
+G_BEGIN_DECLS
+
+
+typedef struct _EvWebView EvWebView;
+typedef struct _EvWebViewClass EvWebViewClass;
+
+#define EV_TYPE_WEB_VIEW (ev_web_view_get_type ())
+#define EV_WEB_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EV_TYPE_WEB_VIEW, EvWebView))
+#define EV_IS_WEB_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EV_TYPE_WEB_VIEW))
+
+GType ev_web_view_get_type (void) G_GNUC_CONST;
+
+GtkWidget* ev_web_view_new (void);
+
+void ev_web_view_set_model (EvWebView *webview,
+ EvDocumentModel *model);
+
+void ev_web_view_reload (EvWebView *webview);
+
+void ev_web_view_reload_page (EvWebView *webview,
+ gint page);
+
+/* Navigation */
+gboolean ev_web_view_next_page (EvWebView *webview);
+gboolean ev_web_view_previous_page (EvWebView *webview);
+
+/* Sidebar links */
+void ev_web_view_handle_link (EvWebView *webview, EvLink* link);
+
+/* Searching */
+void ev_web_view_find_next (EvWebView *webview);
+void ev_web_view_find_previous (EvWebView *webview);
+
+void ev_web_view_find_changed (EvWebView *webview,
+ guint *results,
+ gchar *text,
+ gboolean case_sensitive);
+
+void ev_web_view_find_search_changed (EvWebView *webview);
+void ev_web_view_find_cancel (EvWebView *webview);
+void ev_web_view_find_set_highlight_search (EvWebView *webview,gboolean visible);
+void ev_web_view_set_handler (EvWebView *webview,gboolean visible);
+/* Selection */
+gboolean ev_web_view_get_has_selection (EvWebView *webview);
+void ev_web_view_select_all (EvWebView *webview);
+void ev_web_view_copy (EvWebView *webview);
+
+/* Zoom control */
+gboolean ev_web_view_zoom_in (EvWebView *webview);
+gboolean ev_web_view_zoom_out (EvWebView *webview);
+
+/*For safe replacement by an EvView*/
+void ev_web_view_disconnect_handlers (EvWebView *webview);
+G_END_DECLS
+
+#endif /* __EV_WEB_VIEW_H__ */