[balsa/gtk3] Initial check in support for WebKitGtk2



commit 5b3b0b735f5f44998753e45720c9b91838a59dd6
Author: Peter Bloomfield <PeterBloomfield bellsouth net>
Date:   Sun Mar 24 23:31:59 2013 -0400

    Initial check in support for WebKitGtk2
    
        * configure.ac: add webkit2 as an html-engine option; default is
        still webkit.
        * libbalsa/html.c (lbh_get_body_content_utf8),
        (lbh_webkit_info_free), (lbh_mouse_target_changed_cb),
        (lbh_navigation_policy_decision), (lbh_new_window_policy_decision),
        (lbh_response_policy_decision), (lbh_decide_policy_cb),
        (lbh_info_bar_response_cb), (lbh_show_info_bar),
        (lbh_resource_load_started_cb), (lbh_web_process_crashed_cb),
        (libbalsa_html_new), (libbalsa_html_to_string), (lbh_get_web_view),
        (libbalsa_html_can_zoom), (libbalsa_html_zoom),
        (libbalsa_html_can_select), (libbalsa_html_select_all),
        (libbalsa_html_copy), (libbalsa_html_can_search),
        (lbh_js_run_script), (lbh_js_object_get_property),
        (libbalsa_html_search_text), (libbalsa_html_get_selection_bounds),
        (libbalsa_html_popup_menu_widget), (libbalsa_html_get_view_widget),
        (libbalsa_html_can_print), (libbalsa_html_print): support
        webkit2 option.

 ChangeLog       |   22 ++
 configure.ac    |   17 ++-
 libbalsa/html.c |  624 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 658 insertions(+), 5 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 4813512..b822c09 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2013-03-24  Peter Bloomfield
+
+       Initial check in support for WebKitGtk2
+
+       * configure.ac: add webkit2 as an html-engine option; default is
+       still webkit.
+       * libbalsa/html.c (lbh_get_body_content_utf8),
+       (lbh_webkit_info_free), (lbh_mouse_target_changed_cb),
+       (lbh_navigation_policy_decision), (lbh_new_window_policy_decision),
+       (lbh_response_policy_decision), (lbh_decide_policy_cb),
+       (lbh_info_bar_response_cb), (lbh_show_info_bar),
+       (lbh_resource_load_started_cb), (lbh_web_process_crashed_cb),
+       (libbalsa_html_new), (libbalsa_html_to_string), (lbh_get_web_view),
+       (libbalsa_html_can_zoom), (libbalsa_html_zoom),
+       (libbalsa_html_can_select), (libbalsa_html_select_all),
+       (libbalsa_html_copy), (libbalsa_html_can_search),
+       (lbh_js_run_script), (lbh_js_object_get_property),
+       (libbalsa_html_search_text), (libbalsa_html_get_selection_bounds),
+       (libbalsa_html_popup_menu_widget), (libbalsa_html_get_view_widget),
+       (libbalsa_html_can_print), (libbalsa_html_print): support
+       webkit2 option.
+
 2013-03-21  Peter Bloomfield
 
        * libbalsa/mailbox.c (libbalsa_mailbox_set_view_filter): clean
diff --git a/configure.ac b/configure.ac
index dcdce5d..341a132 100644
--- a/configure.ac
+++ b/configure.ac
@@ -413,17 +413,26 @@ case "$use_html_widget" in
              [AC_MSG_ERROR([*** You enabled gtkhtml4 but it was not found.])])])
         AC_DEFINE(HAVE_GTKHTML4,1,[Defined when GtkHtml-4 can be used.])
     ;;
-    webkit)
+    webkit | webkit2)
         AC_MSG_RESULT([$use_html_widget])
         if test x"$use_threads" = xno ; then
             if ! $PKG_CONFIG --atleast-version=2.24.0 glib-2.0; then
                 AC_MSG_ERROR([WebKit cannot be used with threads disabled and glib older than version 2.24.])
             fi
         fi
-        if $PKG_CONFIG --atleast-version=1.5.1 webkitgtk-3.0 ; then
-            PKG_CHECK_MODULES(HTML, [webkitgtk-3.0 javascriptcoregtk-3.0])
+        if test $use_html_widget = webkit2 ; then
+            if $PKG_CONFIG --atleast-version=1.11.92 webkitgtk-3.0 ; then
+                PKG_CHECK_MODULES(HTML, [webkit2gtk-3.0 javascriptcoregtk-3.0])
+                AC_DEFINE(USE_WEBKIT2,1,[Defined when WebKit2 is requested.])
+            else
+                AC_MSG_ERROR([Webkit2 requires version at least 1.11.92])
+            fi
         else
-            PKG_CHECK_MODULES(HTML, [webkitgtk-3.0])
+            if $PKG_CONFIG --atleast-version=1.5.1 webkitgtk-3.0 ; then
+                PKG_CHECK_MODULES(HTML, [webkitgtk-3.0 javascriptcoregtk-3.0])
+            else
+                PKG_CHECK_MODULES(HTML, [webkitgtk-3.0])
+            fi
         fi
         AC_DEFINE(HAVE_WEBKIT,1,[Defined when WebKit can be used.])
     ;;
diff --git a/libbalsa/html.c b/libbalsa/html.c
index ef1457b..1504574 100644
--- a/libbalsa/html.c
+++ b/libbalsa/html.c
@@ -79,11 +79,632 @@ lbh_get_body_content(LibBalsaMessageBody * body, gchar ** buf)
 }
 
 # if defined(HAVE_WEBKIT)
+#  if defined(USE_WEBKIT2)
 
 /*
- * Experimental support for WebKit.
+ * Experimental support for WebKit2.
  */
 
+#include <webkit2/webkit2.h>
+#include <JavaScriptCore/JavaScript.h>
+
+typedef struct {
+    LibBalsaMessageBody  *body;
+    LibBalsaHtmlCallback  hover_cb;
+    LibBalsaHtmlCallback  clicked_cb;
+    gboolean              download_images;
+    GtkWidget            *vbox;
+    gboolean              has_info_bar;
+    WebKitWebView        *web_view;
+    gchar                *uri;
+} LibBalsaWebKitInfo;
+
+/*
+ * Unlike older HTML widgets, webkit2 wants UTF-8 text
+ */
+static gssize
+lbh_get_body_content_utf8(LibBalsaMessageBody  * body,
+                          gchar               ** utf8_text)
+{
+    gchar *text;
+    gssize len;
+    const gchar *charset;
+    gsize utf8_len;
+
+    len = lbh_get_body_content(body, &text);
+    if (len < 0)
+        return len;
+
+    charset = libbalsa_message_body_charset(body);
+    if (charset) {
+        *utf8_text = g_convert(text, len, "UTF-8", charset,
+                               NULL, &utf8_len, NULL);
+        g_free(text);
+    } else {
+        *utf8_text = text;
+        utf8_len = len;
+    }
+
+    return utf8_len;
+}
+
+/*
+ * GDestroyNotify func
+ */
+static void
+lbh_webkit_info_free(LibBalsaWebKitInfo * info)
+{
+    if (info->uri) {
+        g_free(info->uri);
+        (*info->hover_cb) (NULL);
+    }
+    g_free(info);
+}
+
+/*
+ * Callback for the "mouse-target-changed" signal
+ */
+static void
+lbh_mouse_target_changed_cb(WebKitWebView       * web_view,
+                            WebKitHitTestResult * hit_test_result,
+                            guint                 modifiers,
+                            gpointer              data)
+{
+    LibBalsaWebKitInfo *info = data;
+    const gchar *uri;
+
+    uri = webkit_hit_test_result_get_link_uri(hit_test_result);
+
+    if ((!uri && !info->uri)
+        || (uri && info->uri && !strcmp(uri, info->uri)))
+        /* No change */
+        return;
+
+    if (info->uri) {
+        g_free(info->uri);
+        info->uri = NULL;
+        (*info->hover_cb) (NULL);
+    }
+
+    if (uri) {
+        info->uri = g_strdup(uri);
+        (*info->hover_cb) (uri);
+    }
+}
+
+/*
+ * Callback for the "decide-policy" signal
+ *
+ * First, handlers for the three types of decision
+ */
+
+static void
+lbh_navigation_policy_decision(WebKitPolicyDecision * decision,
+                               gpointer               data)
+{
+    WebKitNavigationPolicyDecision *navigation_decision =
+        WEBKIT_NAVIGATION_POLICY_DECISION(decision);
+    LibBalsaWebKitInfo *info = data;
+    WebKitURIRequest *request;
+
+    switch (webkit_navigation_policy_decision_get_navigation_type
+            (navigation_decision)) {
+    case WEBKIT_NAVIGATION_TYPE_OTHER:
+        webkit_policy_decision_use(decision);
+        break;
+    case WEBKIT_NAVIGATION_TYPE_LINK_CLICKED:
+        request =
+            webkit_navigation_policy_decision_get_request
+            (navigation_decision);
+        (*info->clicked_cb) (webkit_uri_request_get_uri(request));
+    default:
+        webkit_policy_decision_ignore(decision);
+    }
+}
+
+static void
+lbh_new_window_policy_decision(WebKitPolicyDecision * decision,
+                               gpointer               data)
+{
+    WebKitNavigationPolicyDecision *navigation_decision =
+        WEBKIT_NAVIGATION_POLICY_DECISION(decision);
+
+    g_print("%s type %d\n", __func__,
+            webkit_navigation_policy_decision_get_navigation_type
+            (navigation_decision));
+    webkit_policy_decision_ignore(decision);
+}
+
+static void
+lbh_response_policy_decision(WebKitPolicyDecision * decision,
+                             gpointer               data)
+{
+    WebKitResponsePolicyDecision *response =
+        WEBKIT_RESPONSE_POLICY_DECISION(decision);
+    WebKitURIRequest *request;
+    const gchar *uri;
+
+    request = webkit_response_policy_decision_get_request(response);
+    uri = webkit_uri_request_get_uri(request);
+    g_print("%s uri %s\n", __func__, uri);
+    webkit_policy_decision_ignore(decision);
+}
+
+static gboolean
+lbh_decide_policy_cb(WebKitWebView           * web_view,
+                     WebKitPolicyDecision    * decision,
+                     WebKitPolicyDecisionType  decision_type,
+                     gpointer                  data)
+{
+    switch (decision_type) {
+    case WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION:
+        lbh_navigation_policy_decision(decision, data);
+        break;
+    case WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION:
+        lbh_new_window_policy_decision(decision, data);
+        break;
+    case WEBKIT_POLICY_DECISION_TYPE_RESPONSE:
+        lbh_response_policy_decision(decision, data);
+        break;
+    default:
+        /* Making no decision results in
+         * webkit_policy_decision_use(). */
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+/*
+ * Show the GtkInfoBar for asking about downloading images
+ */
+
+static void
+lbh_info_bar_response_cb(GtkInfoBar * info_bar,
+                         gint response_id, gpointer data)
+{
+    LibBalsaWebKitInfo *info = data;
+
+    if (response_id == GTK_RESPONSE_OK) {
+        gchar *text;
+
+        if (lbh_get_body_content_utf8(info->body, &text) >= 0) {
+            info->download_images = TRUE;
+            webkit_web_view_reload_bypass_cache(info->web_view);
+            webkit_web_view_load_html(info->web_view, text, NULL);
+            g_free(text);
+        }
+    }
+
+    gtk_widget_destroy(GTK_WIDGET(info_bar));
+}
+
+static void
+lbh_show_info_bar(LibBalsaWebKitInfo * info)
+{
+    GtkWidget *info_bar_widget;
+    GtkInfoBar *info_bar;
+    GtkWidget *label;
+    GtkWidget *content_area;
+    gchar *text = _("This message part contains images "
+                    "from a remote server. "
+                    "To protect your privacy, "
+                    "Balsa has not downloaded them. "
+                    "You may choose to download them "
+                    "if you trust the server.");
+
+    if (info->has_info_bar)
+        return;
+
+    info_bar_widget =
+        gtk_info_bar_new_with_buttons(_("_Download images"),
+                                     GTK_RESPONSE_OK,
+                                     GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
+                                     NULL);
+    gtk_box_pack_start(GTK_BOX(info->vbox), info_bar_widget,
+                       FALSE, FALSE, 0);
+
+    info_bar = GTK_INFO_BAR(info_bar_widget);
+
+    label = gtk_label_new(text);
+    gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
+
+    content_area = gtk_info_bar_get_content_area(info_bar);
+    gtk_container_add(GTK_CONTAINER(content_area), label);
+
+    g_signal_connect(info_bar, "response",
+                     G_CALLBACK(lbh_info_bar_response_cb), info);
+    gtk_info_bar_set_default_response(info_bar, GTK_RESPONSE_CLOSE);
+    gtk_info_bar_set_message_type(info_bar, GTK_MESSAGE_QUESTION);
+
+    info->has_info_bar = TRUE;
+    gtk_widget_show_all(info_bar_widget);
+}
+
+/*
+ * Callback for the "resource-load-started" signal
+ */
+static void
+lbh_resource_load_started_cb(WebKitWebView     * web_view,
+                             WebKitWebResource * resource,
+                             WebKitURIRequest  * request,
+                             gpointer            data)
+{
+    LibBalsaWebKitInfo *info = data;
+    const gchar *uri;
+
+    uri = webkit_uri_request_get_uri(request);
+    if (!g_ascii_strcasecmp(uri, "about:blank"))
+        return;
+
+    if (g_ascii_strncasecmp(uri, "cid:", 4)) {
+        /* Not a "cid:" request: disable loading. */
+        static GHashTable *cache = NULL;
+
+        if (!cache)
+            cache = g_hash_table_new_full(g_str_hash, g_str_equal,
+                                          g_free, NULL);
+
+        if (!g_hash_table_lookup(cache, uri)) {
+            if (info->download_images) {
+                g_hash_table_insert(cache, g_strdup(uri),
+                                    GINT_TO_POINTER(TRUE));
+            } else {
+                webkit_uri_request_set_uri(request, "about:blank");
+                lbh_show_info_bar(info);
+            }
+        }
+    } else {
+        LibBalsaMessageBody *body;
+
+        /* Replace "cid:" request with a "file:" request. */
+        if ((body =
+             libbalsa_message_get_part_by_id(info->body->message, uri + 4))
+            && libbalsa_message_body_save_temporary(body, NULL)) {
+            gchar *file_uri =
+                g_strconcat("file://", body->temp_filename, NULL);
+            webkit_uri_request_set_uri(request, file_uri);
+            g_free(file_uri);
+        }
+    }
+}
+
+/*
+ * Callback for the "web-process-crashed" signal
+ */
+static gboolean
+lbh_web_process_crashed_cb(WebKitWebView * web_view,
+                           gpointer        data)
+{
+    g_print("%s\n", __func__);
+    return FALSE;
+}
+
+/* Create a new WebKitWebView widget:
+ * body                LibBalsaMessageBody that belongs to the
+ *                      LibBalsaMessage from which to extract any
+ *                     HTML objects (by url);
+ * hover_cb             callback for link-hover signal;
+ * clicked_cb          callback for the "link-clicked" signal;
+ */
+
+GtkWidget *
+libbalsa_html_new(LibBalsaMessageBody * body,
+                  LibBalsaHtmlCallback  hover_cb,
+                  LibBalsaHtmlCallback  clicked_cb)
+{
+    gchar *text;
+    gssize len;
+    GtkWidget *vbox;
+    GtkWidget *widget;
+    WebKitWebView *web_view;
+    LibBalsaWebKitInfo *info;
+    WebKitSettings *settings;
+
+    len = lbh_get_body_content_utf8(body, &text);
+    if (len < 0)
+        return NULL;
+
+    info = g_new(LibBalsaWebKitInfo, 1);
+    info->body            = body;
+    info->hover_cb        = hover_cb;
+    info->clicked_cb      = clicked_cb;
+    info->download_images = FALSE;
+    info->has_info_bar    = FALSE;
+    info->vbox = vbox     = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
+    info->uri             = NULL;
+
+    widget = webkit_web_view_new();
+    gtk_box_pack_end(GTK_BOX(vbox), widget, TRUE, TRUE, 0);
+
+    info->web_view = web_view = WEBKIT_WEB_VIEW(widget);
+    g_object_set_data(G_OBJECT(vbox), "libbalsa-html-web-view", web_view);
+    g_object_set_data_full(G_OBJECT(web_view), "libbalsa-html-info", info,
+                           (GDestroyNotify) lbh_webkit_info_free);
+
+    settings = webkit_web_view_get_settings(web_view);
+    webkit_settings_set_auto_load_images(settings, FALSE);
+    webkit_settings_set_enable_plugins(settings, FALSE);
+
+    g_signal_connect(web_view, "mouse-target-changed",
+                     G_CALLBACK(lbh_mouse_target_changed_cb), info);
+    g_signal_connect(web_view, "decide-policy",
+                     G_CALLBACK(lbh_decide_policy_cb), info);
+    g_signal_connect(web_view, "resource-load-started",
+                     G_CALLBACK(lbh_resource_load_started_cb), info);
+    g_signal_connect(web_view, "web-process-crashed",
+                     G_CALLBACK(lbh_web_process_crashed_cb), info);
+
+    webkit_web_view_load_html(web_view, text, NULL);
+    g_free(text);
+
+    return vbox;
+}
+
+void
+libbalsa_html_to_string(gchar ** text, size_t len)
+{
+    return; /* this widget does not support conversion to a string. The
+             * string won't be altered. Other alternative would be to set
+             * it to an empty string. */
+}
+
+static gboolean
+lbh_get_web_view(GtkWidget * widget, WebKitWebView ** web_view)
+{
+    *web_view =
+        g_object_get_data(G_OBJECT(widget), "libbalsa-html-web-view");
+
+    return *web_view && WEBKIT_IS_WEB_VIEW(*web_view);
+}
+
+/*
+ * Does the widget support zoom?
+ */
+gboolean
+libbalsa_html_can_zoom(GtkWidget * widget)
+{
+    WebKitWebView *web_view;
+
+    return lbh_get_web_view(widget, &web_view);
+}
+
+/*
+ * Zoom the widget.
+ */
+#define LIBBALSA_HTML_ZOOM_FACTOR 1.25
+void
+libbalsa_html_zoom(GtkWidget * widget, gint in_out)
+{
+    WebKitWebView *web_view;
+
+    if (lbh_get_web_view(widget, &web_view)) {
+        gdouble zoom_level;
+
+        zoom_level = webkit_web_view_get_zoom_level(web_view);
+
+        switch (in_out) {
+        case +1:
+            zoom_level *= LIBBALSA_HTML_ZOOM_FACTOR;
+            break;
+        case -1:
+            zoom_level /= LIBBALSA_HTML_ZOOM_FACTOR;
+            break;
+        case 0:
+            zoom_level = 1.0;
+            break;
+        default:
+            break;
+        }
+
+        webkit_web_view_set_zoom_level(web_view, zoom_level);
+    }
+}
+
+/*
+ * Does the widget support selecting text?
+ */
+gboolean
+libbalsa_html_can_select(GtkWidget * widget)
+{
+    WebKitWebView *web_view;
+
+    return lbh_get_web_view(widget, &web_view);
+}
+
+/*
+ * Select all the text.
+ */
+void
+libbalsa_html_select_all(GtkWidget * widget)
+{
+    WebKitWebView *web_view;
+
+    if (lbh_get_web_view(widget, &web_view))
+        webkit_web_view_execute_editing_command
+            (web_view, WEBKIT_EDITING_COMMAND_SELECT_ALL);
+}
+
+/*
+ * Copy selected text to the clipboard.
+ */
+void
+libbalsa_html_copy(GtkWidget * widget)
+{
+    WebKitWebView *web_view;
+
+    if (lbh_get_web_view(widget, &web_view))
+        webkit_web_view_execute_editing_command
+            (web_view, WEBKIT_EDITING_COMMAND_COPY);
+}
+
+/*
+ * Does the widget support searching text?
+ */
+gboolean
+libbalsa_html_can_search(GtkWidget * widget)
+{
+    WebKitWebView *web_view;
+
+    return lbh_get_web_view(widget, &web_view);
+}
+
+/*
+ * JavaScript-based helpers for text search
+ */
+static JSValueRef
+lbh_js_run_script(JSContextRef  ctx,
+                  const gchar * script)
+{
+    JSStringRef str;
+    JSValueRef value;
+
+    str = JSStringCreateWithUTF8CString(script);
+    value = JSEvaluateScript(ctx, str, NULL, NULL, 0, NULL);
+    JSStringRelease(str);
+
+    return value;
+}
+
+static gint
+lbh_js_object_get_property(JSContextRef  ctx,
+                           JSObjectRef   object,
+                           const gchar * property_name)
+{
+    JSStringRef str  = JSStringCreateWithUTF8CString(property_name);
+    JSValueRef value = JSObjectGetProperty(ctx, object, str, NULL);
+    JSStringRelease(str);
+
+    return (gint) JSValueToNumber(ctx, value, NULL);
+}
+
+/*
+ * Search for the text; if text is empty, return TRUE (for consistency
+ * with GtkTextIter methods).
+ */
+gboolean
+libbalsa_html_search_text(GtkWidget   * widget,
+                          const gchar * text,
+                          gboolean      find_forward,
+                          gboolean      wrap)
+{
+    WebKitWebView *web_view;
+    WebKitFindController *find_controller;
+    guint find_options;
+
+    if (!lbh_get_web_view(widget, &web_view))
+        return FALSE;
+
+    if (!*text) {
+        JSGlobalContextRef ctx;
+        gchar script[] = "window.getSelection().removeAllRanges()";
+
+        ctx = webkit_web_view_get_javascript_global_context(web_view);
+        lbh_js_run_script(ctx, script);
+
+        return TRUE;
+    }
+
+    find_options = WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE;
+    if (!find_forward)
+        find_options |= WEBKIT_FIND_OPTIONS_BACKWARDS;
+    if (wrap)
+        find_options |= WEBKIT_FIND_OPTIONS_WRAP_AROUND;
+
+    find_controller = webkit_web_view_get_find_controller(web_view);
+    webkit_find_controller_search(find_controller, text, find_options,
+                                  G_MAXUINT);
+
+    return FALSE;
+}
+
+/*
+ * Get the rectangle containing the currently selected text, for
+ * scrolling.
+ */
+void
+libbalsa_html_get_selection_bounds(GtkWidget    * widget,
+                                   GdkRectangle * selection_bounds)
+{
+    WebKitWebView *web_view;
+    JSGlobalContextRef ctx;
+    gchar script[] =
+        "window.getSelection().getRangeAt(0).getBoundingClientRect()";
+    JSValueRef value;
+
+    if (!lbh_get_web_view(widget, &web_view))
+        return;
+
+    ctx = webkit_web_view_get_javascript_global_context(web_view);
+    value = lbh_js_run_script(ctx, script);
+
+    if (value && JSValueIsObject(ctx, value)) {
+        JSObjectRef object = JSValueToObject(ctx, value, NULL);
+        gint x, y;
+
+        x = lbh_js_object_get_property(ctx, object, "left");
+        y = lbh_js_object_get_property(ctx, object, "top");
+
+        gtk_widget_translate_coordinates(GTK_WIDGET(web_view), widget,
+                                         x, y,
+                                         &selection_bounds->x,
+                                         &selection_bounds->y);
+
+        selection_bounds->width =
+            lbh_js_object_get_property(ctx, object, "width");
+        selection_bounds->height =
+            lbh_js_object_get_property(ctx, object, "height");
+    }
+}
+
+/*
+ * Get the WebKitWebView widget from the container; we need to connect
+ * to its "populate-popup" signal.
+ */
+GtkWidget *
+libbalsa_html_popup_menu_widget(GtkWidget * widget)
+{
+    /* FIXME Need new API to access webkit2's "context-menu" signal */
+    return NULL;
+}
+
+GtkWidget *
+libbalsa_html_get_view_widget(GtkWidget * widget)
+{
+    WebKitWebView *web_view;
+
+    return lbh_get_web_view(widget, &web_view) ?
+        GTK_WIDGET(web_view) : NULL;
+}
+
+/*
+ * Does the widget support printing?
+ */
+gboolean
+libbalsa_html_can_print(GtkWidget * widget)
+{
+    WebKitWebView *web_view;
+
+    return lbh_get_web_view(widget, &web_view);
+}
+
+/*
+ * Print the widget's content.
+ */
+void
+libbalsa_html_print(GtkWidget * widget)
+{
+    WebKitWebView *web_view;
+
+    if (lbh_get_web_view(widget, &web_view)) {
+        WebKitPrintOperation *print_operation;
+
+        print_operation = webkit_print_operation_new(web_view);
+        webkit_print_operation_print(print_operation);
+    }
+}
+
+#  else                         /* defined(USE_WEBKIT2) */
 #include <webkit/webkit.h>
 #include <JavaScriptCore/JavaScript.h>
 
@@ -668,6 +1289,7 @@ libbalsa_html_print(GtkWidget * widget)
     }
 }
 
+#  endif                        /* defined(USE_WEBKIT2) */
 # else                          /* defined(HAVE_WEBKIT) */
 
 /* Common code for both GtkHtml widgets. */


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