Workaround for a WebKit bug [0] which appeared in 1.9.x series. When message is loaded, the content is zoomed in and out to force WebKit to recalculate and redraw the iframe so that the content is correctly visible [0] https://bugs.webkit.org/show_bug.cgi?id=89553
2942 lines
72 KiB
C
2942 lines
72 KiB
C
/*
|
|
* e-web-view.c
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) version 3.
|
|
*
|
|
* 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
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with the program; if not, see <http://www.gnu.org/licenses/>
|
|
*
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include "e-web-view.h"
|
|
|
|
#include <math.h>
|
|
|
|
#include <string.h>
|
|
#include <glib/gi18n-lib.h>
|
|
#include <pango/pango.h>
|
|
|
|
#include <camel/camel.h>
|
|
#include <libebackend/libebackend.h>
|
|
|
|
#include <e-util/e-util.h>
|
|
#include <libevolution-utils/e-alert-dialog.h>
|
|
#include <libevolution-utils/e-alert-sink.h>
|
|
#include <e-util/e-plugin-ui.h>
|
|
#include <e-util/e-file-request.h>
|
|
#include <e-util/e-stock-request.h>
|
|
|
|
#define LIBSOUP_USE_UNSTABLE_REQUEST_API
|
|
#include <libsoup/soup.h>
|
|
#include <libsoup/soup-requester.h>
|
|
|
|
#include "e-popup-action.h"
|
|
#include "e-selectable.h"
|
|
#include <stdlib.h>
|
|
|
|
#define E_WEB_VIEW_GET_PRIVATE(obj) \
|
|
(G_TYPE_INSTANCE_GET_PRIVATE \
|
|
((obj), E_TYPE_WEB_VIEW, EWebViewPrivate))
|
|
|
|
typedef struct _EWebViewRequest EWebViewRequest;
|
|
|
|
struct _EWebViewPrivate {
|
|
GList *requests;
|
|
GtkUIManager *ui_manager;
|
|
gchar *selected_uri;
|
|
GdkPixbufAnimation *cursor_image;
|
|
gchar *cursor_image_src;
|
|
|
|
GSList *highlights;
|
|
|
|
GtkAction *open_proxy;
|
|
GtkAction *print_proxy;
|
|
GtkAction *save_as_proxy;
|
|
|
|
/* Lockdown Options */
|
|
guint disable_printing : 1;
|
|
guint disable_save_to_disk : 1;
|
|
|
|
guint caret_mode : 1;
|
|
|
|
GSettings *font_settings;
|
|
GSettings *aliasing_settings;
|
|
};
|
|
|
|
enum {
|
|
PROP_0,
|
|
PROP_CARET_MODE,
|
|
PROP_COPY_TARGET_LIST,
|
|
PROP_CURSOR_IMAGE,
|
|
PROP_CURSOR_IMAGE_SRC,
|
|
PROP_DISABLE_PRINTING,
|
|
PROP_DISABLE_SAVE_TO_DISK,
|
|
PROP_INLINE_SPELLING,
|
|
PROP_MAGIC_LINKS,
|
|
PROP_MAGIC_SMILEYS,
|
|
PROP_OPEN_PROXY,
|
|
PROP_PRINT_PROXY,
|
|
PROP_SAVE_AS_PROXY,
|
|
PROP_SELECTED_URI
|
|
};
|
|
|
|
enum {
|
|
POPUP_EVENT,
|
|
STATUS_MESSAGE,
|
|
STOP_LOADING,
|
|
UPDATE_ACTIONS,
|
|
PROCESS_MAILTO,
|
|
LAST_SIGNAL
|
|
};
|
|
|
|
static guint signals[LAST_SIGNAL];
|
|
|
|
static const gchar *ui =
|
|
"<ui>"
|
|
" <popup name='context'>"
|
|
" <menuitem action='copy-clipboard'/>"
|
|
" <separator/>"
|
|
" <placeholder name='custom-actions-1'>"
|
|
" <menuitem action='open'/>"
|
|
" <menuitem action='save-as'/>"
|
|
" <menuitem action='http-open'/>"
|
|
" <menuitem action='send-message'/>"
|
|
" <menuitem action='print'/>"
|
|
" </placeholder>"
|
|
" <placeholder name='custom-actions-2'>"
|
|
" <menuitem action='uri-copy'/>"
|
|
" <menuitem action='mailto-copy'/>"
|
|
" <menuitem action='image-copy'/>"
|
|
" </placeholder>"
|
|
" <placeholder name='custom-actions-3'/>"
|
|
" <separator/>"
|
|
" <menuitem action='select-all'/>"
|
|
" <placeholder name='inspect-menu' />"
|
|
" </popup>"
|
|
"</ui>";
|
|
|
|
/* Forward Declarations */
|
|
static void e_web_view_alert_sink_init (EAlertSinkInterface *interface);
|
|
static void e_web_view_selectable_init (ESelectableInterface *interface);
|
|
|
|
G_DEFINE_TYPE_WITH_CODE (
|
|
EWebView,
|
|
e_web_view,
|
|
WEBKIT_TYPE_WEB_VIEW,
|
|
G_IMPLEMENT_INTERFACE (
|
|
E_TYPE_EXTENSIBLE, NULL)
|
|
G_IMPLEMENT_INTERFACE (
|
|
E_TYPE_ALERT_SINK,
|
|
e_web_view_alert_sink_init)
|
|
G_IMPLEMENT_INTERFACE (
|
|
E_TYPE_SELECTABLE,
|
|
e_web_view_selectable_init))
|
|
|
|
static void
|
|
action_copy_clipboard_cb (GtkAction *action,
|
|
EWebView *web_view)
|
|
{
|
|
e_web_view_copy_clipboard (web_view);
|
|
}
|
|
|
|
static void
|
|
action_http_open_cb (GtkAction *action,
|
|
EWebView *web_view)
|
|
{
|
|
const gchar *uri;
|
|
gpointer parent;
|
|
|
|
parent = gtk_widget_get_toplevel (GTK_WIDGET (web_view));
|
|
parent = gtk_widget_is_toplevel (parent) ? parent : NULL;
|
|
|
|
uri = e_web_view_get_selected_uri (web_view);
|
|
g_return_if_fail (uri != NULL);
|
|
|
|
e_show_uri (parent, uri);
|
|
}
|
|
|
|
static void
|
|
action_mailto_copy_cb (GtkAction *action,
|
|
EWebView *web_view)
|
|
{
|
|
CamelURL *curl;
|
|
CamelInternetAddress *inet_addr;
|
|
GtkClipboard *clipboard;
|
|
const gchar *uri;
|
|
gchar *text;
|
|
|
|
uri = e_web_view_get_selected_uri (web_view);
|
|
g_return_if_fail (uri != NULL);
|
|
|
|
/* This should work because we checked it in update_actions(). */
|
|
curl = camel_url_new (uri, NULL);
|
|
g_return_if_fail (curl != NULL);
|
|
|
|
inet_addr = camel_internet_address_new ();
|
|
camel_address_decode (CAMEL_ADDRESS (inet_addr), curl->path);
|
|
text = camel_address_format (CAMEL_ADDRESS (inet_addr));
|
|
if (text == NULL || *text == '\0')
|
|
text = g_strdup (uri + strlen ("mailto:"));
|
|
|
|
g_object_unref (inet_addr);
|
|
camel_url_free (curl);
|
|
|
|
clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
|
|
gtk_clipboard_set_text (clipboard, text, -1);
|
|
gtk_clipboard_store (clipboard);
|
|
|
|
clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
|
|
gtk_clipboard_set_text (clipboard, text, -1);
|
|
gtk_clipboard_store (clipboard);
|
|
|
|
g_free (text);
|
|
}
|
|
|
|
static void
|
|
action_select_all_cb (GtkAction *action,
|
|
EWebView *web_view)
|
|
{
|
|
e_web_view_select_all (web_view);
|
|
}
|
|
|
|
static void
|
|
action_send_message_cb (GtkAction *action,
|
|
EWebView *web_view)
|
|
{
|
|
const gchar *uri;
|
|
gpointer parent;
|
|
gboolean handled;
|
|
|
|
parent = gtk_widget_get_toplevel (GTK_WIDGET (web_view));
|
|
parent = gtk_widget_is_toplevel (parent) ? parent : NULL;
|
|
|
|
uri = e_web_view_get_selected_uri (web_view);
|
|
g_return_if_fail (uri != NULL);
|
|
|
|
handled = FALSE;
|
|
g_signal_emit (web_view, signals[PROCESS_MAILTO], 0, uri, &handled);
|
|
|
|
if (!handled)
|
|
e_show_uri (parent, uri);
|
|
}
|
|
|
|
static void
|
|
action_uri_copy_cb (GtkAction *action,
|
|
EWebView *web_view)
|
|
{
|
|
GtkClipboard *clipboard;
|
|
const gchar *uri;
|
|
|
|
clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
|
|
uri = e_web_view_get_selected_uri (web_view);
|
|
g_return_if_fail (uri != NULL);
|
|
|
|
gtk_clipboard_set_text (clipboard, uri, -1);
|
|
gtk_clipboard_store (clipboard);
|
|
}
|
|
|
|
static void
|
|
action_image_copy_cb (GtkAction *action,
|
|
EWebView *web_view)
|
|
{
|
|
GtkClipboard *clipboard;
|
|
GdkPixbufAnimation *animation;
|
|
GdkPixbuf *pixbuf;
|
|
|
|
clipboard = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD);
|
|
animation = e_web_view_get_cursor_image (web_view);
|
|
g_return_if_fail (animation != NULL);
|
|
|
|
pixbuf = gdk_pixbuf_animation_get_static_image (animation);
|
|
if (!pixbuf)
|
|
return;
|
|
|
|
gtk_clipboard_set_image (clipboard, pixbuf);
|
|
gtk_clipboard_store (clipboard);
|
|
}
|
|
|
|
static GtkActionEntry uri_entries[] = {
|
|
|
|
{ "uri-copy",
|
|
GTK_STOCK_COPY,
|
|
N_("_Copy Link Location"),
|
|
NULL,
|
|
N_("Copy the link to the clipboard"),
|
|
G_CALLBACK (action_uri_copy_cb) }
|
|
};
|
|
|
|
static GtkActionEntry http_entries[] = {
|
|
|
|
{ "http-open",
|
|
"emblem-web",
|
|
N_("_Open Link in Browser"),
|
|
NULL,
|
|
N_("Open the link in a web browser"),
|
|
G_CALLBACK (action_http_open_cb) }
|
|
};
|
|
|
|
static GtkActionEntry mailto_entries[] = {
|
|
|
|
{ "mailto-copy",
|
|
GTK_STOCK_COPY,
|
|
N_("_Copy Email Address"),
|
|
NULL,
|
|
N_("Copy the email address to the clipboard"),
|
|
G_CALLBACK (action_mailto_copy_cb) },
|
|
|
|
{ "send-message",
|
|
"mail-message-new",
|
|
N_("_Send New Message To..."),
|
|
NULL,
|
|
N_("Send a mail message to this address"),
|
|
G_CALLBACK (action_send_message_cb) }
|
|
};
|
|
|
|
static GtkActionEntry image_entries[] = {
|
|
|
|
{ "image-copy",
|
|
GTK_STOCK_COPY,
|
|
N_("_Copy Image"),
|
|
NULL,
|
|
N_("Copy the image to the clipboard"),
|
|
G_CALLBACK (action_image_copy_cb) }
|
|
};
|
|
|
|
static GtkActionEntry selection_entries[] = {
|
|
|
|
{ "copy-clipboard",
|
|
GTK_STOCK_COPY,
|
|
NULL,
|
|
NULL,
|
|
N_("Copy the selection"),
|
|
G_CALLBACK (action_copy_clipboard_cb) },
|
|
};
|
|
|
|
static GtkActionEntry standard_entries[] = {
|
|
|
|
{ "select-all",
|
|
GTK_STOCK_SELECT_ALL,
|
|
NULL,
|
|
NULL,
|
|
N_("Select all text and images"),
|
|
G_CALLBACK (action_select_all_cb) }
|
|
};
|
|
|
|
static void
|
|
web_view_menu_item_select_cb (EWebView *web_view,
|
|
GtkWidget *widget)
|
|
{
|
|
GtkAction *action;
|
|
GtkActivatable *activatable;
|
|
const gchar *tooltip;
|
|
|
|
activatable = GTK_ACTIVATABLE (widget);
|
|
action = gtk_activatable_get_related_action (activatable);
|
|
tooltip = gtk_action_get_tooltip (action);
|
|
|
|
if (tooltip == NULL)
|
|
return;
|
|
|
|
e_web_view_status_message (web_view, tooltip);
|
|
}
|
|
|
|
static void
|
|
replace_text (WebKitDOMNode *node,
|
|
const gchar *text,
|
|
WebKitDOMNode *replacement)
|
|
{
|
|
/* NodeType 3 = TEXT_NODE */
|
|
if (webkit_dom_node_get_node_type (node) == 3) {
|
|
|
|
gint text_length = strlen (text);
|
|
|
|
while (node) {
|
|
|
|
WebKitDOMNode *current_node, *replacement_node;
|
|
const gchar *node_data, *offset;
|
|
goffset split_offset;
|
|
gint data_length;
|
|
|
|
current_node = node;
|
|
|
|
/* Don't use the WEBKIT_DOM_CHARACTER_DATA macro for
|
|
* casting. WebKit lies about type of the object and
|
|
* GLib will throw runtime warning about node not being
|
|
* WebKitDOMCharacterData, but the function will return
|
|
* correct and valid data.
|
|
* IMO it's bug in the Gtk bindings and WebKit internally
|
|
* handles it by the nodeType so therefor it works
|
|
* event for "invalid" objects. But really, who knows..?
|
|
*/
|
|
node_data = webkit_dom_character_data_get_data (
|
|
(WebKitDOMCharacterData *) node);
|
|
|
|
offset = strstr (node_data, text);
|
|
if (!offset) {
|
|
node = NULL;
|
|
continue;
|
|
}
|
|
|
|
split_offset = offset - node_data + text_length;
|
|
replacement_node =
|
|
webkit_dom_node_clone_node (replacement, TRUE);
|
|
|
|
data_length = webkit_dom_character_data_get_length (
|
|
(WebKitDOMCharacterData *) node);
|
|
if (split_offset < data_length) {
|
|
|
|
WebKitDOMNode *parent_node;
|
|
|
|
node = WEBKIT_DOM_NODE (
|
|
webkit_dom_text_split_text (
|
|
(WebKitDOMText *) node,
|
|
offset - node_data + text_length,
|
|
NULL));
|
|
parent_node = webkit_dom_node_get_parent_node (node);
|
|
webkit_dom_node_insert_before (
|
|
parent_node, replacement_node,
|
|
node, NULL);
|
|
|
|
} else {
|
|
WebKitDOMNode *parent_node;
|
|
|
|
parent_node = webkit_dom_node_get_parent_node (node);
|
|
webkit_dom_node_append_child (
|
|
parent_node,
|
|
replacement_node, NULL);
|
|
}
|
|
|
|
webkit_dom_character_data_delete_data (
|
|
(WebKitDOMCharacterData *) (current_node),
|
|
offset - node_data, text_length, NULL);
|
|
}
|
|
|
|
} else {
|
|
|
|
WebKitDOMNode *child, *next_child;
|
|
|
|
/* Iframe? Let's traverse inside! */
|
|
if (WEBKIT_DOM_IS_HTML_IFRAME_ELEMENT (node)) {
|
|
|
|
WebKitDOMDocument *frame_document;
|
|
|
|
frame_document =
|
|
webkit_dom_html_iframe_element_get_content_document (
|
|
WEBKIT_DOM_HTML_IFRAME_ELEMENT (node));
|
|
replace_text (WEBKIT_DOM_NODE (frame_document),
|
|
text, replacement);
|
|
|
|
} else {
|
|
|
|
child = webkit_dom_node_get_first_child (node);
|
|
while (child) {
|
|
next_child = webkit_dom_node_get_next_sibling (child);
|
|
replace_text (child, text, replacement);
|
|
child = next_child;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
static void
|
|
web_view_update_document_highlights (EWebView *web_view)
|
|
{
|
|
WebKitDOMDocument *document;
|
|
GSList *iter;
|
|
|
|
document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (web_view));
|
|
|
|
for (iter = web_view->priv->highlights; iter; iter = iter->next) {
|
|
|
|
WebKitDOMDocumentFragment *frag;
|
|
WebKitDOMElement *span;
|
|
|
|
span = webkit_dom_document_create_element (document, "span", NULL);
|
|
|
|
/* See https://bugzilla.gnome.org/show_bug.cgi?id=681400
|
|
* FIXME: This can be removed once we require WebKitGtk 1.10+ */
|
|
#if WEBKIT_CHECK_VERSION (1, 9, 6)
|
|
webkit_dom_element_set_class_name (
|
|
span, "__evo-highlight");
|
|
#else
|
|
webkit_dom_html_element_set_class_name (
|
|
WEBKIT_DOM_HTML_ELEMENT (span), "__evo-highlight");
|
|
#endif
|
|
|
|
webkit_dom_html_element_set_inner_text (
|
|
WEBKIT_DOM_HTML_ELEMENT (span), iter->data, NULL);
|
|
|
|
frag = webkit_dom_document_create_document_fragment (document);
|
|
webkit_dom_node_append_child (
|
|
WEBKIT_DOM_NODE (frag), WEBKIT_DOM_NODE (span), NULL);
|
|
|
|
replace_text (WEBKIT_DOM_NODE (document),
|
|
iter->data, WEBKIT_DOM_NODE (frag));
|
|
}
|
|
}
|
|
|
|
static void
|
|
web_view_menu_item_deselect_cb (EWebView *web_view)
|
|
{
|
|
e_web_view_status_message (web_view, NULL);
|
|
}
|
|
|
|
static void
|
|
web_view_connect_proxy_cb (EWebView *web_view,
|
|
GtkAction *action,
|
|
GtkWidget *proxy)
|
|
{
|
|
if (!GTK_IS_MENU_ITEM (proxy))
|
|
return;
|
|
|
|
g_signal_connect_swapped (
|
|
proxy, "select",
|
|
G_CALLBACK (web_view_menu_item_select_cb), web_view);
|
|
|
|
g_signal_connect_swapped (
|
|
proxy, "deselect",
|
|
G_CALLBACK (web_view_menu_item_deselect_cb), web_view);
|
|
}
|
|
|
|
static GtkWidget *
|
|
web_view_create_plugin_widget_cb (EWebView *web_view,
|
|
const gchar *mime_type,
|
|
const gchar *uri,
|
|
GHashTable *param)
|
|
{
|
|
EWebViewClass *class;
|
|
|
|
/* XXX WebKitWebView does not provide a class method for
|
|
* this signal, so we do so we can override the default
|
|
* behavior from subclasses for special URI types. */
|
|
|
|
class = E_WEB_VIEW_GET_CLASS (web_view);
|
|
g_return_val_if_fail (class->create_plugin_widget != NULL, NULL);
|
|
|
|
return class->create_plugin_widget (web_view, mime_type, uri, param);
|
|
}
|
|
|
|
static void
|
|
web_view_hovering_over_link_cb (EWebView *web_view,
|
|
const gchar *title,
|
|
const gchar *uri)
|
|
{
|
|
EWebViewClass *class;
|
|
|
|
/* XXX WebKitWebView does not provide a class method for
|
|
* this signal, so we do so we can override the default
|
|
* behavior from subclasses for special URI types. */
|
|
|
|
class = E_WEB_VIEW_GET_CLASS (web_view);
|
|
g_return_if_fail (class->hovering_over_link != NULL);
|
|
|
|
class->hovering_over_link (web_view, title, uri);
|
|
}
|
|
|
|
static gboolean
|
|
web_view_navigation_policy_decision_requested_cb (EWebView *web_view,
|
|
WebKitWebFrame *frame,
|
|
WebKitNetworkRequest *request,
|
|
WebKitWebNavigationAction *navigation_action,
|
|
WebKitWebPolicyDecision *policy_decision)
|
|
{
|
|
EWebViewClass *class;
|
|
WebKitWebNavigationReason reason;
|
|
const gchar *uri;
|
|
|
|
reason = webkit_web_navigation_action_get_reason (navigation_action);
|
|
if (reason != WEBKIT_WEB_NAVIGATION_REASON_LINK_CLICKED)
|
|
return FALSE;
|
|
|
|
/* XXX WebKitWebView does not provide a class method for
|
|
* this signal, so we do so we can override the default
|
|
* behavior from subclasses for special URI types. */
|
|
|
|
class = E_WEB_VIEW_GET_CLASS (web_view);
|
|
g_return_val_if_fail (class->link_clicked != NULL, FALSE);
|
|
|
|
webkit_web_policy_decision_ignore (policy_decision);
|
|
|
|
uri = webkit_network_request_get_uri (request);
|
|
|
|
class->link_clicked (web_view, uri);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
web_view_load_status_changed_cb (WebKitWebView *webkit_web_view,
|
|
GParamSpec *pspec,
|
|
gpointer user_data)
|
|
{
|
|
WebKitLoadStatus status;
|
|
EWebView *web_view;
|
|
|
|
status = webkit_web_view_get_load_status (webkit_web_view);
|
|
if (status != WEBKIT_LOAD_FINISHED)
|
|
return;
|
|
|
|
web_view = E_WEB_VIEW (webkit_web_view);
|
|
web_view_update_document_highlights (web_view);
|
|
|
|
/* Workaround webkit bug https://bugs.webkit.org/show_bug.cgi?id=89553 */
|
|
e_web_view_zoom_in (web_view);
|
|
e_web_view_zoom_out (web_view);
|
|
}
|
|
|
|
static void
|
|
web_view_set_property (GObject *object,
|
|
guint property_id,
|
|
const GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
switch (property_id) {
|
|
case PROP_CARET_MODE:
|
|
e_web_view_set_caret_mode (
|
|
E_WEB_VIEW (object),
|
|
g_value_get_boolean (value));
|
|
return;
|
|
|
|
case PROP_CURSOR_IMAGE:
|
|
e_web_view_set_cursor_image (
|
|
E_WEB_VIEW (object),
|
|
g_value_get_object (value));
|
|
return;
|
|
|
|
case PROP_CURSOR_IMAGE_SRC:
|
|
e_web_view_set_cursor_image_src (
|
|
E_WEB_VIEW (object),
|
|
g_value_get_string (value));
|
|
return;
|
|
|
|
case PROP_DISABLE_PRINTING:
|
|
e_web_view_set_disable_printing (
|
|
E_WEB_VIEW (object),
|
|
g_value_get_boolean (value));
|
|
return;
|
|
|
|
case PROP_DISABLE_SAVE_TO_DISK:
|
|
e_web_view_set_disable_save_to_disk (
|
|
E_WEB_VIEW (object),
|
|
g_value_get_boolean (value));
|
|
return;
|
|
|
|
case PROP_INLINE_SPELLING:
|
|
e_web_view_set_inline_spelling (
|
|
E_WEB_VIEW (object),
|
|
g_value_get_boolean (value));
|
|
return;
|
|
|
|
case PROP_MAGIC_LINKS:
|
|
e_web_view_set_magic_links (
|
|
E_WEB_VIEW (object),
|
|
g_value_get_boolean (value));
|
|
return;
|
|
|
|
case PROP_MAGIC_SMILEYS:
|
|
e_web_view_set_magic_smileys (
|
|
E_WEB_VIEW (object),
|
|
g_value_get_boolean (value));
|
|
return;
|
|
|
|
case PROP_OPEN_PROXY:
|
|
e_web_view_set_open_proxy (
|
|
E_WEB_VIEW (object),
|
|
g_value_get_object (value));
|
|
return;
|
|
|
|
case PROP_PRINT_PROXY:
|
|
e_web_view_set_print_proxy (
|
|
E_WEB_VIEW (object),
|
|
g_value_get_object (value));
|
|
return;
|
|
|
|
case PROP_SAVE_AS_PROXY:
|
|
e_web_view_set_save_as_proxy (
|
|
E_WEB_VIEW (object),
|
|
g_value_get_object (value));
|
|
return;
|
|
|
|
case PROP_SELECTED_URI:
|
|
e_web_view_set_selected_uri (
|
|
E_WEB_VIEW (object),
|
|
g_value_get_string (value));
|
|
return;
|
|
}
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
}
|
|
|
|
static void
|
|
web_view_get_property (GObject *object,
|
|
guint property_id,
|
|
GValue *value,
|
|
GParamSpec *pspec)
|
|
{
|
|
switch (property_id) {
|
|
case PROP_CARET_MODE:
|
|
g_value_set_boolean (
|
|
value, e_web_view_get_caret_mode (
|
|
E_WEB_VIEW (object)));
|
|
return;
|
|
|
|
case PROP_CURSOR_IMAGE:
|
|
g_value_set_object (
|
|
value, e_web_view_get_cursor_image (
|
|
E_WEB_VIEW (object)));
|
|
return;
|
|
|
|
case PROP_CURSOR_IMAGE_SRC:
|
|
g_value_set_string (
|
|
value, e_web_view_get_cursor_image_src (
|
|
E_WEB_VIEW (object)));
|
|
return;
|
|
|
|
case PROP_DISABLE_PRINTING:
|
|
g_value_set_boolean (
|
|
value, e_web_view_get_disable_printing (
|
|
E_WEB_VIEW (object)));
|
|
return;
|
|
|
|
case PROP_DISABLE_SAVE_TO_DISK:
|
|
g_value_set_boolean (
|
|
value, e_web_view_get_disable_save_to_disk (
|
|
E_WEB_VIEW (object)));
|
|
return;
|
|
|
|
case PROP_INLINE_SPELLING:
|
|
g_value_set_boolean (
|
|
value, e_web_view_get_inline_spelling (
|
|
E_WEB_VIEW (object)));
|
|
return;
|
|
|
|
case PROP_MAGIC_LINKS:
|
|
g_value_set_boolean (
|
|
value, e_web_view_get_magic_links (
|
|
E_WEB_VIEW (object)));
|
|
return;
|
|
|
|
case PROP_MAGIC_SMILEYS:
|
|
g_value_set_boolean (
|
|
value, e_web_view_get_magic_smileys (
|
|
E_WEB_VIEW (object)));
|
|
return;
|
|
|
|
case PROP_OPEN_PROXY:
|
|
g_value_set_object (
|
|
value, e_web_view_get_open_proxy (
|
|
E_WEB_VIEW (object)));
|
|
return;
|
|
|
|
case PROP_PRINT_PROXY:
|
|
g_value_set_object (
|
|
value, e_web_view_get_print_proxy (
|
|
E_WEB_VIEW (object)));
|
|
return;
|
|
|
|
case PROP_SAVE_AS_PROXY:
|
|
g_value_set_object (
|
|
value, e_web_view_get_save_as_proxy (
|
|
E_WEB_VIEW (object)));
|
|
return;
|
|
|
|
case PROP_SELECTED_URI:
|
|
g_value_set_string (
|
|
value, e_web_view_get_selected_uri (
|
|
E_WEB_VIEW (object)));
|
|
return;
|
|
|
|
}
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
|
}
|
|
|
|
static void
|
|
web_view_dispose (GObject *object)
|
|
{
|
|
EWebViewPrivate *priv;
|
|
|
|
priv = E_WEB_VIEW_GET_PRIVATE (object);
|
|
|
|
if (priv->ui_manager != NULL) {
|
|
g_object_unref (priv->ui_manager);
|
|
priv->ui_manager = NULL;
|
|
}
|
|
|
|
if (priv->open_proxy != NULL) {
|
|
g_object_unref (priv->open_proxy);
|
|
priv->open_proxy = NULL;
|
|
}
|
|
|
|
if (priv->print_proxy != NULL) {
|
|
g_object_unref (priv->print_proxy);
|
|
priv->print_proxy = NULL;
|
|
}
|
|
|
|
if (priv->save_as_proxy != NULL) {
|
|
g_object_unref (priv->save_as_proxy);
|
|
priv->save_as_proxy = NULL;
|
|
}
|
|
|
|
if (priv->cursor_image != NULL) {
|
|
g_object_unref (priv->cursor_image);
|
|
priv->cursor_image = NULL;
|
|
}
|
|
|
|
if (priv->cursor_image_src != NULL) {
|
|
g_free (priv->cursor_image_src);
|
|
priv->cursor_image_src = NULL;
|
|
}
|
|
|
|
if (priv->highlights != NULL) {
|
|
g_slist_free_full (priv->highlights, g_free);
|
|
priv->highlights = NULL;
|
|
}
|
|
|
|
if (priv->aliasing_settings != NULL) {
|
|
g_object_unref (priv->aliasing_settings);
|
|
priv->aliasing_settings = NULL;
|
|
}
|
|
|
|
if (priv->font_settings != NULL) {
|
|
g_object_unref (priv->font_settings);
|
|
priv->font_settings = NULL;
|
|
}
|
|
|
|
/* Chain up to parent's dispose() method. */
|
|
G_OBJECT_CLASS (e_web_view_parent_class)->dispose (object);
|
|
}
|
|
|
|
static void
|
|
web_view_finalize (GObject *object)
|
|
{
|
|
EWebViewPrivate *priv;
|
|
|
|
priv = E_WEB_VIEW_GET_PRIVATE (object);
|
|
|
|
/* All URI requests should be complete or cancelled by now. */
|
|
if (priv->requests != NULL)
|
|
g_warning ("Finalizing EWebView with active URI requests");
|
|
|
|
g_free (priv->selected_uri);
|
|
|
|
/* Chain up to parent's finalize() method. */
|
|
G_OBJECT_CLASS (e_web_view_parent_class)->finalize (object);
|
|
}
|
|
|
|
static void
|
|
web_view_constructed (GObject *object)
|
|
{
|
|
#ifndef G_OS_WIN32
|
|
GSettings *settings;
|
|
|
|
settings = g_settings_new ("org.gnome.desktop.lockdown");
|
|
|
|
g_settings_bind (
|
|
settings, "disable-printing",
|
|
object, "disable-printing",
|
|
G_SETTINGS_BIND_GET);
|
|
|
|
g_settings_bind (
|
|
settings, "disable-save-to-disk",
|
|
object, "disable-save-to-disk",
|
|
G_SETTINGS_BIND_GET);
|
|
|
|
g_object_unref (settings);
|
|
#endif
|
|
|
|
e_extensible_load_extensions (E_EXTENSIBLE (object));
|
|
|
|
/* Chain up to parent's constructed() method. */
|
|
G_OBJECT_CLASS (e_web_view_parent_class)->constructed (object);
|
|
}
|
|
|
|
static gboolean
|
|
web_view_button_press_event (GtkWidget *widget,
|
|
GdkEventButton *event)
|
|
{
|
|
GtkWidgetClass *widget_class;
|
|
EWebView *web_view;
|
|
gboolean event_handled = FALSE;
|
|
gchar *uri;
|
|
|
|
web_view = E_WEB_VIEW (widget);
|
|
|
|
if (event) {
|
|
WebKitHitTestResult *test;
|
|
WebKitHitTestResultContext context;
|
|
|
|
if (web_view->priv->cursor_image) {
|
|
g_object_unref (web_view->priv->cursor_image);
|
|
web_view->priv->cursor_image = NULL;
|
|
}
|
|
|
|
if (web_view->priv->cursor_image_src) {
|
|
g_free (web_view->priv->cursor_image_src);
|
|
web_view->priv->cursor_image_src = NULL;
|
|
}
|
|
|
|
test = webkit_web_view_get_hit_test_result (WEBKIT_WEB_VIEW (web_view), event);
|
|
if (!test)
|
|
goto chainup;
|
|
|
|
g_object_get (G_OBJECT (test), "context", &context, NULL);
|
|
if (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE) {
|
|
WebKitWebDataSource *data_source;
|
|
WebKitWebFrame *frame;
|
|
GList *subresources, *res;
|
|
|
|
g_object_get (G_OBJECT (test), "image-uri", &uri, NULL);
|
|
|
|
if (!uri)
|
|
goto chainup;
|
|
|
|
if (web_view->priv->cursor_image_src)
|
|
g_free (web_view->priv->cursor_image_src);
|
|
web_view->priv->cursor_image_src = uri;
|
|
|
|
/* Iterate through all resources of the loaded webpage and
|
|
try to find resource with URI matching cursor_image_src */
|
|
frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (web_view));
|
|
data_source = webkit_web_frame_get_data_source (frame);
|
|
subresources = webkit_web_data_source_get_subresources (data_source);
|
|
for (res = subresources; res; res = res->next) {
|
|
WebKitWebResource *src = res->data;
|
|
GdkPixbufLoader *loader;
|
|
GString *data;
|
|
|
|
if (g_strcmp0 (webkit_web_resource_get_uri (src),
|
|
web_view->priv->cursor_image_src) != 0)
|
|
continue;
|
|
|
|
data = webkit_web_resource_get_data (src);
|
|
if (!data)
|
|
break;
|
|
|
|
loader = gdk_pixbuf_loader_new ();
|
|
if (!gdk_pixbuf_loader_write (loader,
|
|
(guchar *) data->str, data->len, NULL)) {
|
|
g_object_unref (loader);
|
|
break;
|
|
}
|
|
gdk_pixbuf_loader_close (loader, NULL);
|
|
|
|
if (web_view->priv->cursor_image)
|
|
g_object_unref (web_view->priv->cursor_image);
|
|
|
|
web_view->priv->cursor_image =
|
|
g_object_ref (gdk_pixbuf_loader_get_animation (loader));
|
|
|
|
g_object_unref (loader);
|
|
break;
|
|
}
|
|
g_list_free (subresources);
|
|
}
|
|
|
|
g_object_unref (test);
|
|
}
|
|
|
|
if (event != NULL && event->button != 3)
|
|
goto chainup;
|
|
|
|
uri = e_web_view_extract_uri (web_view, event);
|
|
|
|
g_signal_emit (
|
|
web_view, signals[POPUP_EVENT], 0,
|
|
event, uri, &event_handled);
|
|
|
|
g_free (uri);
|
|
|
|
if (event_handled)
|
|
return TRUE;
|
|
|
|
chainup:
|
|
/* Chain up to parent's button_press_event() method. */
|
|
widget_class = GTK_WIDGET_CLASS (e_web_view_parent_class);
|
|
return widget_class->button_press_event (widget, event);
|
|
}
|
|
|
|
static gboolean
|
|
web_view_scroll_event (GtkWidget *widget,
|
|
GdkEventScroll *event)
|
|
{
|
|
if (event->state & GDK_CONTROL_MASK) {
|
|
GdkScrollDirection direction = event->direction;
|
|
|
|
#if GTK_CHECK_VERSION(3,3,18)
|
|
if (direction == GDK_SCROLL_SMOOTH) {
|
|
static gdouble total_delta_y = 0.0;
|
|
|
|
total_delta_y += event->delta_y;
|
|
|
|
if (total_delta_y >= 1.0) {
|
|
total_delta_y = 0.0;
|
|
direction = GDK_SCROLL_DOWN;
|
|
} else if (total_delta_y <= -1.0) {
|
|
total_delta_y = 0.0;
|
|
direction = GDK_SCROLL_UP;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
switch (direction) {
|
|
case GDK_SCROLL_UP:
|
|
e_web_view_zoom_in (E_WEB_VIEW (widget));
|
|
return TRUE;
|
|
case GDK_SCROLL_DOWN:
|
|
e_web_view_zoom_out (E_WEB_VIEW (widget));
|
|
return TRUE;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static GtkWidget *
|
|
web_view_create_plugin_widget (EWebView *web_view,
|
|
const gchar *mime_type,
|
|
const gchar *uri,
|
|
GHashTable *param)
|
|
{
|
|
GtkWidget *widget = NULL;
|
|
|
|
if (g_strcmp0 (mime_type, "image/x-themed-icon") == 0) {
|
|
GtkIconTheme *icon_theme;
|
|
GdkPixbuf *pixbuf;
|
|
gpointer data;
|
|
glong size = 0;
|
|
GError *error = NULL;
|
|
|
|
icon_theme = gtk_icon_theme_get_default ();
|
|
|
|
if (size == 0) {
|
|
data = g_hash_table_lookup (param, "width");
|
|
if (data != NULL)
|
|
size = MAX (size, strtol (data, NULL, 10));
|
|
}
|
|
|
|
if (size == 0) {
|
|
data = g_hash_table_lookup (param, "height");
|
|
if (data != NULL)
|
|
size = MAX (size, strtol (data, NULL, 10));
|
|
}
|
|
|
|
if (size == 0)
|
|
size = 32; /* arbitrary default */
|
|
|
|
pixbuf = gtk_icon_theme_load_icon (
|
|
icon_theme, uri, size, 0, &error);
|
|
if (pixbuf != NULL) {
|
|
widget = gtk_image_new_from_pixbuf (pixbuf);
|
|
g_object_unref (pixbuf);
|
|
} else if (error != NULL) {
|
|
g_warning ("%s", error->message);
|
|
g_error_free (error);
|
|
}
|
|
}
|
|
|
|
return widget;
|
|
}
|
|
|
|
static gchar *
|
|
web_view_extract_uri (EWebView *web_view,
|
|
GdkEventButton *event)
|
|
{
|
|
WebKitHitTestResult *result;
|
|
WebKitHitTestResultContext context;
|
|
gchar *uri = NULL;
|
|
|
|
result = webkit_web_view_get_hit_test_result (
|
|
WEBKIT_WEB_VIEW (web_view), event);
|
|
|
|
g_object_get (result, "context", &context, "link-uri", &uri, NULL);
|
|
g_object_unref (result);
|
|
|
|
if (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_LINK)
|
|
return uri;
|
|
|
|
g_free (uri);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static void
|
|
web_view_hovering_over_link (EWebView *web_view,
|
|
const gchar *title,
|
|
const gchar *uri)
|
|
{
|
|
CamelInternetAddress *address;
|
|
CamelURL *curl;
|
|
const gchar *format = NULL;
|
|
gchar *message = NULL;
|
|
gchar *who;
|
|
|
|
if (uri == NULL || *uri == '\0')
|
|
goto exit;
|
|
|
|
if (g_str_has_prefix (uri, "mailto:"))
|
|
format = _("Click to mail %s");
|
|
else if (g_str_has_prefix (uri, "callto:"))
|
|
format = _("Click to call %s");
|
|
else if (g_str_has_prefix (uri, "h323:"))
|
|
format = _("Click to call %s");
|
|
else if (g_str_has_prefix (uri, "sip:"))
|
|
format = _("Click to call %s");
|
|
else if (g_str_has_prefix (uri, "##"))
|
|
message = g_strdup (_("Click to hide/unhide addresses"));
|
|
else
|
|
message = g_strdup_printf (_("Click to open %s"), uri);
|
|
|
|
if (format == NULL)
|
|
goto exit;
|
|
|
|
/* XXX Use something other than Camel here. Surely
|
|
* there's other APIs around that can do this. */
|
|
curl = camel_url_new (uri, NULL);
|
|
address = camel_internet_address_new ();
|
|
camel_address_decode (CAMEL_ADDRESS (address), curl->path);
|
|
who = camel_address_format (CAMEL_ADDRESS (address));
|
|
g_object_unref (address);
|
|
camel_url_free (curl);
|
|
|
|
if (who == NULL)
|
|
who = g_strdup (strchr (uri, ':') + 1);
|
|
|
|
message = g_strdup_printf (format, who);
|
|
|
|
g_free (who);
|
|
|
|
exit:
|
|
e_web_view_status_message (web_view, message);
|
|
|
|
g_free (message);
|
|
}
|
|
|
|
static void
|
|
web_view_link_clicked (EWebView *web_view,
|
|
const gchar *uri)
|
|
{
|
|
gpointer parent;
|
|
|
|
if (uri && g_ascii_strncasecmp (uri, "mailto:", 7) == 0) {
|
|
gboolean handled = FALSE;
|
|
|
|
g_signal_emit (web_view, signals[PROCESS_MAILTO], 0, uri, &handled);
|
|
|
|
if (handled)
|
|
return;
|
|
}
|
|
|
|
parent = gtk_widget_get_toplevel (GTK_WIDGET (web_view));
|
|
parent = gtk_widget_is_toplevel (parent) ? parent : NULL;
|
|
|
|
e_show_uri (parent, uri);
|
|
}
|
|
|
|
static void
|
|
web_view_load_string (EWebView *web_view,
|
|
const gchar *string)
|
|
{
|
|
if (string == NULL)
|
|
string = "";
|
|
|
|
webkit_web_view_load_string (
|
|
WEBKIT_WEB_VIEW (web_view),
|
|
string, "text/html", "UTF-8", "evo-file:///");
|
|
}
|
|
|
|
static void
|
|
web_view_load_uri (EWebView *web_view,
|
|
const gchar *uri)
|
|
{
|
|
if (uri == NULL)
|
|
uri = "about:blank";
|
|
|
|
webkit_web_view_load_uri (
|
|
WEBKIT_WEB_VIEW (web_view), uri);
|
|
}
|
|
|
|
static void
|
|
web_view_frame_load_string (EWebView *web_view,
|
|
const gchar *frame_name,
|
|
const gchar *string)
|
|
{
|
|
WebKitWebFrame *main_frame, *frame;
|
|
|
|
if (string == NULL)
|
|
string = "";
|
|
|
|
main_frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (web_view));
|
|
if (main_frame) {
|
|
frame = webkit_web_frame_find_frame (main_frame, frame_name);
|
|
|
|
if (frame)
|
|
webkit_web_frame_load_string (
|
|
frame, string, "text/html", "UTF-8", "evo-file:///");
|
|
}
|
|
}
|
|
|
|
static void
|
|
web_view_frame_load_uri (EWebView *web_view,
|
|
const gchar *frame_name,
|
|
const gchar *uri)
|
|
{
|
|
WebKitWebFrame *main_frame, *frame;
|
|
|
|
if (uri == NULL)
|
|
uri = "about:blank";
|
|
|
|
main_frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (web_view));
|
|
if (main_frame) {
|
|
frame = webkit_web_frame_find_frame (main_frame, frame_name);
|
|
|
|
if (frame)
|
|
webkit_web_frame_load_uri (frame, uri);
|
|
}
|
|
}
|
|
|
|
static gboolean
|
|
web_view_popup_event (EWebView *web_view,
|
|
GdkEventButton *event,
|
|
const gchar *uri)
|
|
{
|
|
e_web_view_set_selected_uri (web_view, uri);
|
|
e_web_view_show_popup_menu (web_view, event, NULL, NULL);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
web_view_stop_loading (EWebView *web_view)
|
|
{
|
|
webkit_web_view_stop_loading (WEBKIT_WEB_VIEW (web_view));
|
|
}
|
|
|
|
static void
|
|
web_view_update_actions (EWebView *web_view,
|
|
GdkEventButton *event)
|
|
{
|
|
GtkActionGroup *action_group;
|
|
gboolean can_copy;
|
|
gboolean scheme_is_http = FALSE;
|
|
gboolean scheme_is_mailto = FALSE;
|
|
gboolean uri_is_valid = FALSE;
|
|
gboolean has_cursor_image;
|
|
gboolean visible;
|
|
WebKitHitTestResult *hit_test;
|
|
WebKitHitTestResultContext context;
|
|
const gchar *group_name;
|
|
const gchar *uri;
|
|
|
|
uri = e_web_view_get_selected_uri (web_view);
|
|
can_copy = webkit_web_view_can_copy_clipboard (
|
|
WEBKIT_WEB_VIEW (web_view));
|
|
hit_test = webkit_web_view_get_hit_test_result (
|
|
WEBKIT_WEB_VIEW (web_view), event);
|
|
g_object_get (G_OBJECT (hit_test), "context", &context, NULL);
|
|
|
|
has_cursor_image = (context & WEBKIT_HIT_TEST_RESULT_CONTEXT_IMAGE);
|
|
|
|
/* Parse the URI early so we know if the actions will work. */
|
|
if (uri != NULL) {
|
|
CamelURL *curl;
|
|
|
|
curl = camel_url_new (uri, NULL);
|
|
uri_is_valid = (curl != NULL);
|
|
camel_url_free (curl);
|
|
|
|
scheme_is_http =
|
|
(g_ascii_strncasecmp (uri, "http:", 5) == 0) ||
|
|
(g_ascii_strncasecmp (uri, "https:", 6) == 0);
|
|
|
|
scheme_is_mailto =
|
|
(g_ascii_strncasecmp (uri, "mailto:", 7) == 0);
|
|
}
|
|
|
|
/* Allow copying the URI even if it's malformed. */
|
|
group_name = "uri";
|
|
visible = (uri != NULL) && !scheme_is_mailto;
|
|
action_group = e_web_view_get_action_group (web_view, group_name);
|
|
gtk_action_group_set_visible (action_group, visible);
|
|
|
|
group_name = "http";
|
|
visible = uri_is_valid && scheme_is_http;
|
|
action_group = e_web_view_get_action_group (web_view, group_name);
|
|
gtk_action_group_set_visible (action_group, visible);
|
|
|
|
group_name = "mailto";
|
|
visible = uri_is_valid && scheme_is_mailto;
|
|
action_group = e_web_view_get_action_group (web_view, group_name);
|
|
gtk_action_group_set_visible (action_group, visible);
|
|
|
|
group_name = "image";
|
|
visible = has_cursor_image;
|
|
action_group = e_web_view_get_action_group (web_view, group_name);
|
|
gtk_action_group_set_visible (action_group, visible);
|
|
|
|
group_name = "selection";
|
|
visible = can_copy;
|
|
action_group = e_web_view_get_action_group (web_view, group_name);
|
|
gtk_action_group_set_visible (action_group, visible);
|
|
|
|
group_name = "standard";
|
|
visible = (uri == NULL);
|
|
action_group = e_web_view_get_action_group (web_view, group_name);
|
|
gtk_action_group_set_visible (action_group, visible);
|
|
|
|
group_name = "lockdown-printing";
|
|
visible = (uri == NULL) && !web_view->priv->disable_printing;
|
|
action_group = e_web_view_get_action_group (web_view, group_name);
|
|
gtk_action_group_set_visible (action_group, visible);
|
|
|
|
group_name = "lockdown-save-to-disk";
|
|
visible = (uri == NULL) && !web_view->priv->disable_save_to_disk;
|
|
action_group = e_web_view_get_action_group (web_view, group_name);
|
|
gtk_action_group_set_visible (action_group, visible);
|
|
}
|
|
|
|
static void
|
|
web_view_submit_alert (EAlertSink *alert_sink,
|
|
EAlert *alert)
|
|
{
|
|
EWebView *web_view;
|
|
GtkWidget *dialog;
|
|
GString *buffer;
|
|
const gchar *icon_name = NULL;
|
|
gpointer parent;
|
|
|
|
web_view = E_WEB_VIEW (alert_sink);
|
|
|
|
parent = gtk_widget_get_toplevel (GTK_WIDGET (web_view));
|
|
parent = gtk_widget_is_toplevel (parent) ? parent : NULL;
|
|
|
|
switch (e_alert_get_message_type (alert)) {
|
|
case GTK_MESSAGE_INFO:
|
|
icon_name = GTK_STOCK_DIALOG_INFO;
|
|
break;
|
|
|
|
case GTK_MESSAGE_WARNING:
|
|
icon_name = GTK_STOCK_DIALOG_WARNING;
|
|
break;
|
|
|
|
case GTK_MESSAGE_ERROR:
|
|
icon_name = GTK_STOCK_DIALOG_ERROR;
|
|
break;
|
|
|
|
default:
|
|
dialog = e_alert_dialog_new (parent, alert);
|
|
gtk_dialog_run (GTK_DIALOG (dialog));
|
|
gtk_widget_destroy (dialog);
|
|
return;
|
|
}
|
|
|
|
buffer = g_string_sized_new (512);
|
|
|
|
g_string_append (
|
|
buffer,
|
|
"<html>"
|
|
"<head>"
|
|
"<meta http-equiv=\"content-type\""
|
|
" content=\"text/html; charset=utf-8\">"
|
|
"</head>"
|
|
"<body>");
|
|
|
|
g_string_append (
|
|
buffer,
|
|
"<table bgcolor='#000000' width='100%'"
|
|
" cellpadding='1' cellspacing='0'>"
|
|
"<tr>"
|
|
"<td>"
|
|
"<table bgcolor='#dddddd' width='100%' cellpadding='6'>"
|
|
"<tr>");
|
|
|
|
g_string_append_printf (
|
|
buffer,
|
|
"<tr>"
|
|
"<td valign='top'>"
|
|
"<img src='gtk-stock://%s/?size=%d'/>"
|
|
"</td>"
|
|
"<td align='left' width='100%%'>"
|
|
"<h3>%s</h3>"
|
|
"%s"
|
|
"</td>"
|
|
"</tr>",
|
|
icon_name,
|
|
GTK_ICON_SIZE_DIALOG,
|
|
e_alert_get_primary_text (alert),
|
|
e_alert_get_secondary_text (alert));
|
|
|
|
g_string_append (
|
|
buffer,
|
|
"</table>"
|
|
"</td>"
|
|
"</tr>"
|
|
"</table>"
|
|
"</body>"
|
|
"</html>");
|
|
|
|
e_web_view_load_string (web_view, buffer->str);
|
|
|
|
g_string_free (buffer, TRUE);
|
|
}
|
|
|
|
static void
|
|
web_view_selectable_update_actions (ESelectable *selectable,
|
|
EFocusTracker *focus_tracker,
|
|
GdkAtom *clipboard_targets,
|
|
gint n_clipboard_targets)
|
|
{
|
|
WebKitWebView *web_view;
|
|
GtkAction *action;
|
|
gboolean sensitive;
|
|
const gchar *tooltip;
|
|
|
|
web_view = WEBKIT_WEB_VIEW (selectable);
|
|
|
|
action = e_focus_tracker_get_cut_clipboard_action (focus_tracker);
|
|
sensitive = webkit_web_view_can_cut_clipboard (web_view);
|
|
tooltip = _("Cut the selection");
|
|
gtk_action_set_sensitive (action, sensitive);
|
|
gtk_action_set_tooltip (action, tooltip);
|
|
|
|
action = e_focus_tracker_get_copy_clipboard_action (focus_tracker);
|
|
sensitive = webkit_web_view_can_copy_clipboard (web_view);
|
|
tooltip = _("Copy the selection");
|
|
gtk_action_set_sensitive (action, sensitive);
|
|
gtk_action_set_tooltip (action, tooltip);
|
|
|
|
action = e_focus_tracker_get_paste_clipboard_action (focus_tracker);
|
|
sensitive = webkit_web_view_can_paste_clipboard (web_view);
|
|
tooltip = _("Paste the clipboard");
|
|
gtk_action_set_sensitive (action, sensitive);
|
|
gtk_action_set_tooltip (action, tooltip);
|
|
|
|
action = e_focus_tracker_get_select_all_action (focus_tracker);
|
|
sensitive = TRUE;
|
|
tooltip = _("Select all text and images");
|
|
gtk_action_set_sensitive (action, sensitive);
|
|
gtk_action_set_tooltip (action, tooltip);
|
|
}
|
|
|
|
static void
|
|
web_view_selectable_cut_clipboard (ESelectable *selectable)
|
|
{
|
|
e_web_view_cut_clipboard (E_WEB_VIEW (selectable));
|
|
}
|
|
|
|
static void
|
|
web_view_selectable_copy_clipboard (ESelectable *selectable)
|
|
{
|
|
e_web_view_copy_clipboard (E_WEB_VIEW (selectable));
|
|
}
|
|
|
|
static void
|
|
web_view_selectable_paste_clipboard (ESelectable *selectable)
|
|
{
|
|
e_web_view_paste_clipboard (E_WEB_VIEW (selectable));
|
|
}
|
|
|
|
static void
|
|
web_view_selectable_select_all (ESelectable *selectable)
|
|
{
|
|
e_web_view_select_all (E_WEB_VIEW (selectable));
|
|
}
|
|
|
|
static void
|
|
e_web_view_class_init (EWebViewClass *class)
|
|
{
|
|
GObjectClass *object_class;
|
|
GtkWidgetClass *widget_class;
|
|
#if 0 /* WEBKIT */
|
|
GtkHTMLClass *html_class;
|
|
#endif
|
|
|
|
g_type_class_add_private (class, sizeof (EWebViewPrivate));
|
|
|
|
object_class = G_OBJECT_CLASS (class);
|
|
object_class->set_property = web_view_set_property;
|
|
object_class->get_property = web_view_get_property;
|
|
object_class->dispose = web_view_dispose;
|
|
object_class->finalize = web_view_finalize;
|
|
object_class->constructed = web_view_constructed;
|
|
|
|
widget_class = GTK_WIDGET_CLASS (class);
|
|
widget_class->button_press_event = web_view_button_press_event;
|
|
widget_class->scroll_event = web_view_scroll_event;
|
|
|
|
#if 0 /* WEBKIT */
|
|
html_class = GTK_HTML_CLASS (class);
|
|
html_class->url_requested = web_view_url_requested;
|
|
#endif
|
|
|
|
class->create_plugin_widget = web_view_create_plugin_widget;
|
|
class->extract_uri = web_view_extract_uri;
|
|
class->hovering_over_link = web_view_hovering_over_link;
|
|
class->link_clicked = web_view_link_clicked;
|
|
class->load_string = web_view_load_string;
|
|
class->load_uri = web_view_load_uri;
|
|
class->frame_load_string = web_view_frame_load_string;
|
|
class->frame_load_uri = web_view_frame_load_uri;
|
|
class->popup_event = web_view_popup_event;
|
|
class->stop_loading = web_view_stop_loading;
|
|
class->update_actions = web_view_update_actions;
|
|
|
|
g_object_class_install_property (
|
|
object_class,
|
|
PROP_CARET_MODE,
|
|
g_param_spec_boolean (
|
|
"caret-mode",
|
|
"Caret Mode",
|
|
NULL,
|
|
FALSE,
|
|
G_PARAM_READWRITE));
|
|
|
|
g_object_class_install_property (
|
|
object_class,
|
|
PROP_CURSOR_IMAGE,
|
|
g_param_spec_object (
|
|
"cursor-image",
|
|
"Image animation at the mouse cursor",
|
|
NULL,
|
|
GDK_TYPE_PIXBUF_ANIMATION,
|
|
G_PARAM_READWRITE));
|
|
|
|
g_object_class_install_property (
|
|
object_class,
|
|
PROP_CURSOR_IMAGE_SRC,
|
|
g_param_spec_string (
|
|
"cursor-image-src",
|
|
"Image source uri at the mouse cursor",
|
|
NULL,
|
|
NULL,
|
|
G_PARAM_READWRITE));
|
|
|
|
g_object_class_install_property (
|
|
object_class,
|
|
PROP_DISABLE_PRINTING,
|
|
g_param_spec_boolean (
|
|
"disable-printing",
|
|
"Disable Printing",
|
|
NULL,
|
|
FALSE,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT));
|
|
|
|
g_object_class_install_property (
|
|
object_class,
|
|
PROP_DISABLE_SAVE_TO_DISK,
|
|
g_param_spec_boolean (
|
|
"disable-save-to-disk",
|
|
"Disable Save-to-Disk",
|
|
NULL,
|
|
FALSE,
|
|
G_PARAM_READWRITE |
|
|
G_PARAM_CONSTRUCT));
|
|
|
|
g_object_class_install_property (
|
|
object_class,
|
|
PROP_INLINE_SPELLING,
|
|
g_param_spec_boolean (
|
|
"inline-spelling",
|
|
"Inline Spelling",
|
|
NULL,
|
|
FALSE,
|
|
G_PARAM_READWRITE));
|
|
|
|
g_object_class_install_property (
|
|
object_class,
|
|
PROP_MAGIC_LINKS,
|
|
g_param_spec_boolean (
|
|
"magic-links",
|
|
"Magic Links",
|
|
NULL,
|
|
FALSE,
|
|
G_PARAM_READWRITE));
|
|
|
|
g_object_class_install_property (
|
|
object_class,
|
|
PROP_MAGIC_SMILEYS,
|
|
g_param_spec_boolean (
|
|
"magic-smileys",
|
|
"Magic Smileys",
|
|
NULL,
|
|
FALSE,
|
|
G_PARAM_READWRITE));
|
|
|
|
g_object_class_install_property (
|
|
object_class,
|
|
PROP_OPEN_PROXY,
|
|
g_param_spec_object (
|
|
"open-proxy",
|
|
"Open Proxy",
|
|
NULL,
|
|
GTK_TYPE_ACTION,
|
|
G_PARAM_READWRITE));
|
|
|
|
g_object_class_install_property (
|
|
object_class,
|
|
PROP_PRINT_PROXY,
|
|
g_param_spec_object (
|
|
"print-proxy",
|
|
"Print Proxy",
|
|
NULL,
|
|
GTK_TYPE_ACTION,
|
|
G_PARAM_READWRITE));
|
|
|
|
g_object_class_install_property (
|
|
object_class,
|
|
PROP_SAVE_AS_PROXY,
|
|
g_param_spec_object (
|
|
"save-as-proxy",
|
|
"Save As Proxy",
|
|
NULL,
|
|
GTK_TYPE_ACTION,
|
|
G_PARAM_READWRITE));
|
|
|
|
g_object_class_install_property (
|
|
object_class,
|
|
PROP_SELECTED_URI,
|
|
g_param_spec_string (
|
|
"selected-uri",
|
|
"Selected URI",
|
|
NULL,
|
|
NULL,
|
|
G_PARAM_READWRITE));
|
|
|
|
signals[POPUP_EVENT] = g_signal_new (
|
|
"popup-event",
|
|
G_TYPE_FROM_CLASS (class),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (EWebViewClass, popup_event),
|
|
g_signal_accumulator_true_handled, NULL,
|
|
e_marshal_BOOLEAN__BOXED_STRING,
|
|
G_TYPE_BOOLEAN, 2,
|
|
GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE,
|
|
G_TYPE_STRING);
|
|
|
|
signals[STATUS_MESSAGE] = g_signal_new (
|
|
"status-message",
|
|
G_TYPE_FROM_CLASS (class),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (EWebViewClass, status_message),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__STRING,
|
|
G_TYPE_NONE, 1,
|
|
G_TYPE_STRING);
|
|
|
|
signals[STOP_LOADING] = g_signal_new (
|
|
"stop-loading",
|
|
G_TYPE_FROM_CLASS (class),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (EWebViewClass, stop_loading),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__VOID,
|
|
G_TYPE_NONE, 0);
|
|
|
|
signals[UPDATE_ACTIONS] = g_signal_new (
|
|
"update-actions",
|
|
G_TYPE_FROM_CLASS (class),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (EWebViewClass, update_actions),
|
|
NULL, NULL,
|
|
g_cclosure_marshal_VOID__POINTER,
|
|
G_TYPE_NONE, 1, G_TYPE_POINTER);
|
|
|
|
/* return TRUE when a signal handler processed the mailto URI */
|
|
signals[PROCESS_MAILTO] = g_signal_new (
|
|
"process-mailto",
|
|
G_TYPE_FROM_CLASS (class),
|
|
G_SIGNAL_RUN_LAST,
|
|
G_STRUCT_OFFSET (EWebViewClass, process_mailto),
|
|
NULL, NULL,
|
|
e_marshal_BOOLEAN__STRING,
|
|
G_TYPE_BOOLEAN, 1, G_TYPE_STRING);
|
|
}
|
|
|
|
static void
|
|
e_web_view_alert_sink_init (EAlertSinkInterface *interface)
|
|
{
|
|
interface->submit_alert = web_view_submit_alert;
|
|
}
|
|
|
|
static void
|
|
e_web_view_selectable_init (ESelectableInterface *interface)
|
|
{
|
|
interface->update_actions = web_view_selectable_update_actions;
|
|
interface->cut_clipboard = web_view_selectable_cut_clipboard;
|
|
interface->copy_clipboard = web_view_selectable_copy_clipboard;
|
|
interface->paste_clipboard = web_view_selectable_paste_clipboard;
|
|
interface->select_all = web_view_selectable_select_all;
|
|
}
|
|
|
|
static void
|
|
e_web_view_init (EWebView *web_view)
|
|
{
|
|
GtkUIManager *ui_manager;
|
|
GtkActionGroup *action_group;
|
|
EPopupAction *popup_action;
|
|
WebKitWebSettings *web_settings;
|
|
GSettingsSchema *settings_schema;
|
|
GSettings *settings;
|
|
const gchar *domain = GETTEXT_PACKAGE;
|
|
const gchar *id;
|
|
GError *error = NULL;
|
|
|
|
web_view->priv = E_WEB_VIEW_GET_PRIVATE (web_view);
|
|
|
|
web_view->priv->highlights = NULL;
|
|
|
|
g_signal_connect (
|
|
web_view, "create-plugin-widget",
|
|
G_CALLBACK (web_view_create_plugin_widget_cb), NULL);
|
|
|
|
g_signal_connect (
|
|
web_view, "hovering-over-link",
|
|
G_CALLBACK (web_view_hovering_over_link_cb), NULL);
|
|
|
|
g_signal_connect (
|
|
web_view, "navigation-policy-decision-requested",
|
|
G_CALLBACK (web_view_navigation_policy_decision_requested_cb),
|
|
NULL);
|
|
|
|
g_signal_connect (
|
|
web_view, "new-window-policy-decision-requested",
|
|
G_CALLBACK (web_view_navigation_policy_decision_requested_cb),
|
|
NULL);
|
|
|
|
g_signal_connect (
|
|
web_view, "notify::load-status",
|
|
G_CALLBACK (web_view_load_status_changed_cb), NULL);
|
|
|
|
ui_manager = gtk_ui_manager_new ();
|
|
web_view->priv->ui_manager = ui_manager;
|
|
|
|
g_signal_connect_swapped (
|
|
ui_manager, "connect-proxy",
|
|
G_CALLBACK (web_view_connect_proxy_cb), web_view);
|
|
|
|
web_settings = e_web_view_get_default_settings ();
|
|
e_web_view_set_settings (web_view, web_settings);
|
|
g_object_unref (web_settings);
|
|
|
|
e_web_view_install_request_handler (web_view, E_TYPE_FILE_REQUEST);
|
|
e_web_view_install_request_handler (web_view, E_TYPE_STOCK_REQUEST);
|
|
|
|
settings = g_settings_new ("org.gnome.desktop.interface");
|
|
g_signal_connect_swapped (
|
|
settings, "changed::font-name",
|
|
G_CALLBACK (e_web_view_update_fonts), web_view);
|
|
g_signal_connect_swapped (
|
|
settings, "changed::monospace-font-name",
|
|
G_CALLBACK (e_web_view_update_fonts), web_view);
|
|
web_view->priv->font_settings = settings;
|
|
|
|
/* This schema is optional. Use if available. */
|
|
id = "org.gnome.settings-daemon.plugins.xsettings";
|
|
settings_schema = g_settings_schema_source_lookup (
|
|
g_settings_schema_source_get_default (), id, FALSE);
|
|
if (settings_schema != NULL) {
|
|
settings = g_settings_new (id);
|
|
g_signal_connect_swapped (
|
|
settings, "changed::antialiasing",
|
|
G_CALLBACK (e_web_view_update_fonts), web_view);
|
|
web_view->priv->aliasing_settings = settings;
|
|
}
|
|
|
|
e_web_view_update_fonts (web_view);
|
|
|
|
action_group = gtk_action_group_new ("uri");
|
|
gtk_action_group_set_translation_domain (action_group, domain);
|
|
gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
|
|
g_object_unref (action_group);
|
|
|
|
gtk_action_group_add_actions (
|
|
action_group, uri_entries,
|
|
G_N_ELEMENTS (uri_entries), web_view);
|
|
|
|
action_group = gtk_action_group_new ("http");
|
|
gtk_action_group_set_translation_domain (action_group, domain);
|
|
gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
|
|
g_object_unref (action_group);
|
|
|
|
gtk_action_group_add_actions (
|
|
action_group, http_entries,
|
|
G_N_ELEMENTS (http_entries), web_view);
|
|
|
|
action_group = gtk_action_group_new ("mailto");
|
|
gtk_action_group_set_translation_domain (action_group, domain);
|
|
gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
|
|
g_object_unref (action_group);
|
|
|
|
gtk_action_group_add_actions (
|
|
action_group, mailto_entries,
|
|
G_N_ELEMENTS (mailto_entries), web_view);
|
|
|
|
action_group = gtk_action_group_new ("image");
|
|
gtk_action_group_set_translation_domain (action_group, domain);
|
|
gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
|
|
g_object_unref (action_group);
|
|
|
|
gtk_action_group_add_actions (
|
|
action_group, image_entries,
|
|
G_N_ELEMENTS (image_entries), web_view);
|
|
|
|
action_group = gtk_action_group_new ("selection");
|
|
gtk_action_group_set_translation_domain (action_group, domain);
|
|
gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
|
|
g_object_unref (action_group);
|
|
|
|
gtk_action_group_add_actions (
|
|
action_group, selection_entries,
|
|
G_N_ELEMENTS (selection_entries), web_view);
|
|
|
|
action_group = gtk_action_group_new ("standard");
|
|
gtk_action_group_set_translation_domain (action_group, domain);
|
|
gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
|
|
g_object_unref (action_group);
|
|
|
|
gtk_action_group_add_actions (
|
|
action_group, standard_entries,
|
|
G_N_ELEMENTS (standard_entries), web_view);
|
|
|
|
popup_action = e_popup_action_new ("open");
|
|
gtk_action_group_add_action (action_group, GTK_ACTION (popup_action));
|
|
g_object_unref (popup_action);
|
|
|
|
g_object_bind_property (
|
|
web_view, "open-proxy",
|
|
popup_action, "related-action",
|
|
G_BINDING_BIDIRECTIONAL |
|
|
G_BINDING_SYNC_CREATE);
|
|
|
|
/* Support lockdown. */
|
|
|
|
action_group = gtk_action_group_new ("lockdown-printing");
|
|
gtk_action_group_set_translation_domain (action_group, domain);
|
|
gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
|
|
g_object_unref (action_group);
|
|
|
|
popup_action = e_popup_action_new ("print");
|
|
gtk_action_group_add_action (action_group, GTK_ACTION (popup_action));
|
|
g_object_unref (popup_action);
|
|
|
|
g_object_bind_property (
|
|
web_view, "print-proxy",
|
|
popup_action, "related-action",
|
|
G_BINDING_BIDIRECTIONAL |
|
|
G_BINDING_SYNC_CREATE);
|
|
|
|
action_group = gtk_action_group_new ("lockdown-save-to-disk");
|
|
gtk_action_group_set_translation_domain (action_group, domain);
|
|
gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
|
|
g_object_unref (action_group);
|
|
|
|
popup_action = e_popup_action_new ("save-as");
|
|
gtk_action_group_add_action (action_group, GTK_ACTION (popup_action));
|
|
g_object_unref (popup_action);
|
|
|
|
g_object_bind_property (
|
|
web_view, "save-as-proxy",
|
|
popup_action, "related-action",
|
|
G_BINDING_BIDIRECTIONAL |
|
|
G_BINDING_SYNC_CREATE);
|
|
|
|
/* Because we are loading from a hard-coded string, there is
|
|
* no chance of I/O errors. Failure here implies a malformed
|
|
* UI definition. Full stop. */
|
|
gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error);
|
|
if (error != NULL)
|
|
g_error ("%s", error->message);
|
|
|
|
id = "org.gnome.evolution.webview";
|
|
e_plugin_ui_register_manager (ui_manager, id, web_view);
|
|
e_plugin_ui_enable_manager (ui_manager, id);
|
|
}
|
|
|
|
GtkWidget *
|
|
e_web_view_new (void)
|
|
{
|
|
return g_object_new (E_TYPE_WEB_VIEW, NULL);
|
|
}
|
|
|
|
void
|
|
e_web_view_clear (EWebView *web_view)
|
|
{
|
|
GtkStyle *style;
|
|
gchar *html;
|
|
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
style = gtk_widget_get_style (GTK_WIDGET (web_view));
|
|
|
|
html = g_strdup_printf (
|
|
"<html><head></head><body bgcolor=\"#%06x\"></body></html>",
|
|
e_color_to_value (&style->base[GTK_STATE_NORMAL]));
|
|
|
|
webkit_web_view_load_html_string (WEBKIT_WEB_VIEW (web_view), html, NULL);
|
|
|
|
g_free (html);
|
|
}
|
|
|
|
void
|
|
e_web_view_load_string (EWebView *web_view,
|
|
const gchar *string)
|
|
{
|
|
EWebViewClass *class;
|
|
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
class = E_WEB_VIEW_GET_CLASS (web_view);
|
|
g_return_if_fail (class->load_string != NULL);
|
|
|
|
class->load_string (web_view, string);
|
|
}
|
|
|
|
void
|
|
e_web_view_load_uri (EWebView *web_view,
|
|
const gchar *uri)
|
|
{
|
|
EWebViewClass *class;
|
|
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
class = E_WEB_VIEW_GET_CLASS (web_view);
|
|
g_return_if_fail (class->load_uri != NULL);
|
|
|
|
class->load_uri (web_view, uri);
|
|
}
|
|
|
|
void
|
|
e_web_view_reload (EWebView *web_view)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
webkit_web_view_reload (WEBKIT_WEB_VIEW (web_view));
|
|
}
|
|
|
|
const gchar *
|
|
e_web_view_get_uri (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
|
|
|
return webkit_web_view_get_uri (WEBKIT_WEB_VIEW (web_view));
|
|
}
|
|
|
|
void
|
|
e_web_view_frame_load_string (EWebView *web_view,
|
|
const gchar *frame_name,
|
|
const gchar *string)
|
|
{
|
|
EWebViewClass *class;
|
|
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
g_return_if_fail (frame_name != NULL);
|
|
|
|
class = E_WEB_VIEW_GET_CLASS (web_view);
|
|
g_return_if_fail (class->frame_load_string != NULL);
|
|
|
|
class->frame_load_string (web_view, frame_name, string);
|
|
}
|
|
|
|
void
|
|
e_web_view_frame_load_uri (EWebView *web_view,
|
|
const gchar *frame_name,
|
|
const gchar *uri)
|
|
{
|
|
EWebViewClass *class;
|
|
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
g_return_if_fail (frame_name != NULL);
|
|
|
|
class = E_WEB_VIEW_GET_CLASS (web_view);
|
|
g_return_if_fail (class->frame_load_uri != NULL);
|
|
|
|
class->frame_load_uri (web_view, frame_name, uri);
|
|
}
|
|
|
|
const gchar *
|
|
e_web_view_frame_get_uri (EWebView *web_view,
|
|
const gchar *frame_name)
|
|
{
|
|
WebKitWebFrame *main_frame, *frame;
|
|
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
|
g_return_val_if_fail (frame_name != NULL, NULL);
|
|
|
|
main_frame = webkit_web_view_get_main_frame (WEBKIT_WEB_VIEW (web_view));
|
|
if (main_frame) {
|
|
frame = webkit_web_frame_find_frame (main_frame, frame_name);
|
|
|
|
if (frame)
|
|
return webkit_web_frame_get_uri (frame);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
gchar *
|
|
e_web_view_get_html (EWebView *web_view)
|
|
{
|
|
WebKitDOMDocument *document;
|
|
WebKitDOMElement *element;
|
|
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
|
|
|
document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (web_view));
|
|
element = webkit_dom_document_get_document_element (document);
|
|
|
|
return webkit_dom_html_element_get_outer_html (
|
|
WEBKIT_DOM_HTML_ELEMENT (element));
|
|
}
|
|
|
|
gboolean
|
|
e_web_view_get_caret_mode (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
|
|
|
return web_view->priv->caret_mode;
|
|
}
|
|
|
|
void
|
|
e_web_view_set_caret_mode (EWebView *web_view,
|
|
gboolean caret_mode)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
if ((web_view->priv->caret_mode ? 1 : 0) == (caret_mode ? 1 : 0))
|
|
return;
|
|
|
|
web_view->priv->caret_mode = caret_mode;
|
|
|
|
g_object_notify (G_OBJECT (web_view), "caret-mode");
|
|
}
|
|
|
|
GtkTargetList *
|
|
e_web_view_get_copy_target_list (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
|
|
|
return webkit_web_view_get_copy_target_list (
|
|
WEBKIT_WEB_VIEW (web_view));
|
|
}
|
|
|
|
gboolean
|
|
e_web_view_get_disable_printing (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
|
|
|
return web_view->priv->disable_printing;
|
|
}
|
|
|
|
void
|
|
e_web_view_set_disable_printing (EWebView *web_view,
|
|
gboolean disable_printing)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
if ((web_view->priv->disable_printing ? 1 : 0) == (disable_printing ? 1 : 0))
|
|
return;
|
|
|
|
web_view->priv->disable_printing = disable_printing;
|
|
|
|
g_object_notify (G_OBJECT (web_view), "disable-printing");
|
|
}
|
|
|
|
gboolean
|
|
e_web_view_get_disable_save_to_disk (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
|
|
|
return web_view->priv->disable_save_to_disk;
|
|
}
|
|
|
|
void
|
|
e_web_view_set_disable_save_to_disk (EWebView *web_view,
|
|
gboolean disable_save_to_disk)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
if ((web_view->priv->disable_save_to_disk ? 1 : 0) == (disable_save_to_disk ? 1 : 0))
|
|
return;
|
|
|
|
web_view->priv->disable_save_to_disk = disable_save_to_disk;
|
|
|
|
g_object_notify (G_OBJECT (web_view), "disable-save-to-disk");
|
|
}
|
|
|
|
gboolean
|
|
e_web_view_get_enable_frame_flattening (EWebView *web_view)
|
|
{
|
|
WebKitWebSettings *settings;
|
|
gboolean flattening;
|
|
|
|
/* Return TRUE with fail since it's default value we set in _init(). */
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), TRUE);
|
|
|
|
settings = webkit_web_view_get_settings (WEBKIT_WEB_VIEW (web_view));
|
|
g_return_val_if_fail (settings != NULL, TRUE);
|
|
|
|
g_object_get (G_OBJECT (settings), "enable-frame-flattening", &flattening, NULL);
|
|
|
|
return flattening;
|
|
}
|
|
|
|
void
|
|
e_web_view_set_enable_frame_flattening (EWebView *web_view,
|
|
gboolean enable_frame_flattening)
|
|
{
|
|
WebKitWebSettings *settings;
|
|
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
settings = webkit_web_view_get_settings (WEBKIT_WEB_VIEW (web_view));
|
|
g_return_if_fail (settings != NULL);
|
|
|
|
g_object_set (G_OBJECT (settings), "enable-frame-flattening",
|
|
enable_frame_flattening, NULL);
|
|
}
|
|
|
|
gboolean
|
|
e_web_view_get_editable (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
|
|
|
return webkit_web_view_get_editable (WEBKIT_WEB_VIEW (web_view));
|
|
}
|
|
|
|
void
|
|
e_web_view_set_editable (EWebView *web_view,
|
|
gboolean editable)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
webkit_web_view_set_editable (WEBKIT_WEB_VIEW (web_view), editable);
|
|
}
|
|
|
|
gboolean
|
|
e_web_view_get_inline_spelling (EWebView *web_view)
|
|
{
|
|
#if 0 /* WEBKIT - XXX No equivalent property? */
|
|
/* XXX This is just here to maintain symmetry
|
|
* with e_web_view_set_inline_spelling(). */
|
|
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
|
|
|
return gtk_html_get_inline_spelling (GTK_HTML (web_view));
|
|
#endif
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void
|
|
e_web_view_set_inline_spelling (EWebView *web_view,
|
|
gboolean inline_spelling)
|
|
{
|
|
#if 0 /* WEBKIT - XXX No equivalent property? */
|
|
/* XXX GtkHTML does not utilize GObject properties as well
|
|
* as it could. This just wraps gtk_html_set_inline_spelling()
|
|
* so we get a "notify::inline-spelling" signal. */
|
|
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
gtk_html_set_inline_spelling (GTK_HTML (web_view), inline_spelling);
|
|
|
|
g_object_notify (G_OBJECT (web_view), "inline-spelling");
|
|
#endif
|
|
}
|
|
|
|
gboolean
|
|
e_web_view_get_magic_links (EWebView *web_view)
|
|
{
|
|
#if 0 /* WEBKIT - XXX No equivalent property? */
|
|
/* XXX This is just here to maintain symmetry
|
|
* with e_web_view_set_magic_links(). */
|
|
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
|
|
|
return gtk_html_get_magic_links (GTK_HTML (web_view));
|
|
#endif
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void
|
|
e_web_view_set_magic_links (EWebView *web_view,
|
|
gboolean magic_links)
|
|
{
|
|
#if 0 /* WEBKIT - XXX No equivalent property? */
|
|
/* XXX GtkHTML does not utilize GObject properties as well
|
|
* as it could. This just wraps gtk_html_set_magic_links()
|
|
* so we can get a "notify::magic-links" signal. */
|
|
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
gtk_html_set_magic_links (GTK_HTML (web_view), magic_links);
|
|
|
|
g_object_notify (G_OBJECT (web_view), "magic-links");
|
|
#endif
|
|
}
|
|
|
|
gboolean
|
|
e_web_view_get_magic_smileys (EWebView *web_view)
|
|
{
|
|
#if 0 /* WEBKIT - No equivalent property? */
|
|
/* XXX This is just here to maintain symmetry
|
|
* with e_web_view_set_magic_smileys(). */
|
|
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
|
|
|
return gtk_html_get_magic_smileys (GTK_HTML (web_view));
|
|
#endif
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void
|
|
e_web_view_set_magic_smileys (EWebView *web_view,
|
|
gboolean magic_smileys)
|
|
{
|
|
#if 0 /* WEBKIT - No equivalent property? */
|
|
/* XXX GtkHTML does not utilize GObject properties as well
|
|
* as it could. This just wraps gtk_html_set_magic_smileys()
|
|
* so we can get a "notify::magic-smileys" signal. */
|
|
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
gtk_html_set_magic_smileys (GTK_HTML (web_view), magic_smileys);
|
|
|
|
g_object_notify (G_OBJECT (web_view), "magic-smileys");
|
|
#endif
|
|
}
|
|
|
|
const gchar *
|
|
e_web_view_get_selected_uri (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
|
|
|
return web_view->priv->selected_uri;
|
|
}
|
|
|
|
void
|
|
e_web_view_set_selected_uri (EWebView *web_view,
|
|
const gchar *selected_uri)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
if (g_strcmp0 (web_view->priv->selected_uri, selected_uri) == 0)
|
|
return;
|
|
|
|
g_free (web_view->priv->selected_uri);
|
|
web_view->priv->selected_uri = g_strdup (selected_uri);
|
|
|
|
g_object_notify (G_OBJECT (web_view), "selected-uri");
|
|
}
|
|
|
|
GdkPixbufAnimation *
|
|
e_web_view_get_cursor_image (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
|
|
|
return web_view->priv->cursor_image;
|
|
}
|
|
|
|
void
|
|
e_web_view_set_cursor_image (EWebView *web_view,
|
|
GdkPixbufAnimation *image)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
if (web_view->priv->cursor_image == image)
|
|
return;
|
|
|
|
if (image != NULL)
|
|
g_object_ref (image);
|
|
|
|
if (web_view->priv->cursor_image != NULL)
|
|
g_object_unref (web_view->priv->cursor_image);
|
|
|
|
web_view->priv->cursor_image = image;
|
|
|
|
g_object_notify (G_OBJECT (web_view), "cursor-image");
|
|
}
|
|
|
|
const gchar *
|
|
e_web_view_get_cursor_image_src (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
|
|
|
return web_view->priv->cursor_image_src;
|
|
}
|
|
|
|
void
|
|
e_web_view_set_cursor_image_src (EWebView *web_view,
|
|
const gchar *src_uri)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
if (g_strcmp0 (web_view->priv->cursor_image_src, src_uri) == 0)
|
|
return;
|
|
|
|
g_free (web_view->priv->cursor_image_src);
|
|
web_view->priv->cursor_image_src = g_strdup (src_uri);
|
|
|
|
g_object_notify (G_OBJECT (web_view), "cursor-image-src");
|
|
}
|
|
|
|
GtkAction *
|
|
e_web_view_get_open_proxy (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
|
|
|
return web_view->priv->open_proxy;
|
|
}
|
|
|
|
void
|
|
e_web_view_set_open_proxy (EWebView *web_view,
|
|
GtkAction *open_proxy)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
if (web_view->priv->open_proxy == open_proxy)
|
|
return;
|
|
|
|
if (open_proxy != NULL) {
|
|
g_return_if_fail (GTK_IS_ACTION (open_proxy));
|
|
g_object_ref (open_proxy);
|
|
}
|
|
|
|
if (web_view->priv->open_proxy != NULL)
|
|
g_object_unref (web_view->priv->open_proxy);
|
|
|
|
web_view->priv->open_proxy = open_proxy;
|
|
|
|
g_object_notify (G_OBJECT (web_view), "open-proxy");
|
|
}
|
|
|
|
GtkTargetList *
|
|
e_web_view_get_paste_target_list (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
|
|
|
return webkit_web_view_get_paste_target_list (
|
|
WEBKIT_WEB_VIEW (web_view));
|
|
}
|
|
|
|
GtkAction *
|
|
e_web_view_get_print_proxy (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
|
|
|
return web_view->priv->print_proxy;
|
|
}
|
|
|
|
void
|
|
e_web_view_set_print_proxy (EWebView *web_view,
|
|
GtkAction *print_proxy)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
if (web_view->priv->print_proxy == print_proxy)
|
|
return;
|
|
|
|
if (print_proxy != NULL) {
|
|
g_return_if_fail (GTK_IS_ACTION (print_proxy));
|
|
g_object_ref (print_proxy);
|
|
}
|
|
|
|
if (web_view->priv->print_proxy != NULL)
|
|
g_object_unref (web_view->priv->print_proxy);
|
|
|
|
web_view->priv->print_proxy = print_proxy;
|
|
|
|
g_object_notify (G_OBJECT (web_view), "print-proxy");
|
|
}
|
|
|
|
GtkAction *
|
|
e_web_view_get_save_as_proxy (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
|
|
|
return web_view->priv->save_as_proxy;
|
|
}
|
|
|
|
void
|
|
e_web_view_set_save_as_proxy (EWebView *web_view,
|
|
GtkAction *save_as_proxy)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
if (web_view->priv->save_as_proxy == save_as_proxy)
|
|
return;
|
|
|
|
if (save_as_proxy != NULL) {
|
|
g_return_if_fail (GTK_IS_ACTION (save_as_proxy));
|
|
g_object_ref (save_as_proxy);
|
|
}
|
|
|
|
if (web_view->priv->save_as_proxy != NULL)
|
|
g_object_unref (web_view->priv->save_as_proxy);
|
|
|
|
web_view->priv->save_as_proxy = save_as_proxy;
|
|
|
|
g_object_notify (G_OBJECT (web_view), "save-as-proxy");
|
|
}
|
|
|
|
GSList *
|
|
e_web_view_get_highlights (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
|
|
|
return web_view->priv->highlights;
|
|
}
|
|
|
|
void
|
|
e_web_view_add_highlight (EWebView *web_view,
|
|
const gchar *highlight)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
g_return_if_fail (highlight && *highlight);
|
|
|
|
web_view->priv->highlights =
|
|
g_slist_append (web_view->priv->highlights, g_strdup (highlight));
|
|
|
|
web_view_update_document_highlights (web_view);
|
|
}
|
|
|
|
void e_web_view_clear_highlights (EWebView *web_view)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
if (!web_view->priv->highlights)
|
|
return;
|
|
|
|
g_slist_free_full (web_view->priv->highlights, g_free);
|
|
web_view->priv->highlights = NULL;
|
|
|
|
web_view_update_document_highlights (web_view);
|
|
}
|
|
|
|
GtkAction *
|
|
e_web_view_get_action (EWebView *web_view,
|
|
const gchar *action_name)
|
|
{
|
|
GtkUIManager *ui_manager;
|
|
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
|
g_return_val_if_fail (action_name != NULL, NULL);
|
|
|
|
ui_manager = e_web_view_get_ui_manager (web_view);
|
|
|
|
return e_lookup_action (ui_manager, action_name);
|
|
}
|
|
|
|
GtkActionGroup *
|
|
e_web_view_get_action_group (EWebView *web_view,
|
|
const gchar *group_name)
|
|
{
|
|
GtkUIManager *ui_manager;
|
|
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
|
g_return_val_if_fail (group_name != NULL, NULL);
|
|
|
|
ui_manager = e_web_view_get_ui_manager (web_view);
|
|
|
|
return e_lookup_action_group (ui_manager, group_name);
|
|
}
|
|
|
|
gchar *
|
|
e_web_view_extract_uri (EWebView *web_view,
|
|
GdkEventButton *event)
|
|
{
|
|
EWebViewClass *class;
|
|
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
|
|
|
class = E_WEB_VIEW_GET_CLASS (web_view);
|
|
g_return_val_if_fail (class->extract_uri != NULL, NULL);
|
|
|
|
return class->extract_uri (web_view, event);
|
|
}
|
|
|
|
void
|
|
e_web_view_copy_clipboard (EWebView *web_view)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
webkit_web_view_copy_clipboard (WEBKIT_WEB_VIEW (web_view));
|
|
}
|
|
|
|
void
|
|
e_web_view_cut_clipboard (EWebView *web_view)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
webkit_web_view_cut_clipboard (WEBKIT_WEB_VIEW (web_view));
|
|
}
|
|
|
|
gboolean
|
|
e_web_view_is_selection_active (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
|
|
|
return webkit_web_view_has_selection (WEBKIT_WEB_VIEW (web_view));
|
|
}
|
|
|
|
void
|
|
e_web_view_paste_clipboard (EWebView *web_view)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
webkit_web_view_paste_clipboard (WEBKIT_WEB_VIEW (web_view));
|
|
}
|
|
|
|
gboolean
|
|
e_web_view_scroll_forward (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
|
|
|
webkit_web_view_move_cursor (
|
|
WEBKIT_WEB_VIEW (web_view), GTK_MOVEMENT_PAGES, 1);
|
|
|
|
return TRUE; /* XXX This means nothing. */
|
|
}
|
|
|
|
gboolean
|
|
e_web_view_scroll_backward (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
|
|
|
|
webkit_web_view_move_cursor (
|
|
WEBKIT_WEB_VIEW (web_view), GTK_MOVEMENT_PAGES, -1);
|
|
|
|
return TRUE; /* XXX This means nothing. */
|
|
}
|
|
|
|
void
|
|
e_web_view_select_all (EWebView *web_view)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
webkit_web_view_select_all (WEBKIT_WEB_VIEW (web_view));
|
|
}
|
|
|
|
void
|
|
e_web_view_unselect_all (EWebView *web_view)
|
|
{
|
|
#if 0 /* WEBKIT */
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
gtk_html_command (GTK_HTML (web_view), "unselect-all");
|
|
#endif
|
|
}
|
|
|
|
void
|
|
e_web_view_zoom_100 (EWebView *web_view)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
webkit_web_view_set_zoom_level (WEBKIT_WEB_VIEW (web_view), 1.0);
|
|
}
|
|
|
|
void
|
|
e_web_view_zoom_in (EWebView *web_view)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
webkit_web_view_zoom_in (WEBKIT_WEB_VIEW (web_view));
|
|
}
|
|
|
|
void
|
|
e_web_view_zoom_out (EWebView *web_view)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
webkit_web_view_zoom_out (WEBKIT_WEB_VIEW (web_view));
|
|
}
|
|
|
|
GtkUIManager *
|
|
e_web_view_get_ui_manager (EWebView *web_view)
|
|
{
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
|
|
|
return web_view->priv->ui_manager;
|
|
}
|
|
|
|
GtkWidget *
|
|
e_web_view_get_popup_menu (EWebView *web_view)
|
|
{
|
|
GtkUIManager *ui_manager;
|
|
GtkWidget *menu;
|
|
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
|
|
|
ui_manager = e_web_view_get_ui_manager (web_view);
|
|
menu = gtk_ui_manager_get_widget (ui_manager, "/context");
|
|
g_return_val_if_fail (GTK_IS_MENU (menu), NULL);
|
|
|
|
return menu;
|
|
}
|
|
|
|
void
|
|
e_web_view_show_popup_menu (EWebView *web_view,
|
|
GdkEventButton *event,
|
|
GtkMenuPositionFunc func,
|
|
gpointer user_data)
|
|
{
|
|
GtkWidget *menu;
|
|
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
e_web_view_update_actions (web_view, event);
|
|
|
|
menu = e_web_view_get_popup_menu (web_view);
|
|
|
|
if (event != NULL)
|
|
gtk_menu_popup (
|
|
GTK_MENU (menu), NULL, NULL, func,
|
|
user_data, event->button, event->time);
|
|
else
|
|
gtk_menu_popup (
|
|
GTK_MENU (menu), NULL, NULL, func,
|
|
user_data, 0, gtk_get_current_event_time ());
|
|
}
|
|
|
|
void
|
|
e_web_view_status_message (EWebView *web_view,
|
|
const gchar *status_message)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
g_signal_emit (web_view, signals[STATUS_MESSAGE], 0, status_message);
|
|
}
|
|
|
|
void
|
|
e_web_view_stop_loading (EWebView *web_view)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
g_signal_emit (web_view, signals[STOP_LOADING], 0);
|
|
}
|
|
|
|
void
|
|
e_web_view_update_actions (EWebView *web_view,
|
|
GdkEventButton *event)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
g_signal_emit (web_view, signals[UPDATE_ACTIONS], 0, event);
|
|
}
|
|
|
|
static gchar *
|
|
web_view_get_frame_selection_html (WebKitDOMElement *iframe)
|
|
{
|
|
WebKitDOMDocument *document;
|
|
WebKitDOMDOMWindow *window;
|
|
WebKitDOMDOMSelection *selection;
|
|
WebKitDOMNodeList *frames;
|
|
gulong ii, length;
|
|
|
|
document = webkit_dom_html_iframe_element_get_content_document (
|
|
WEBKIT_DOM_HTML_IFRAME_ELEMENT (iframe));
|
|
window = webkit_dom_document_get_default_view (document);
|
|
selection = webkit_dom_dom_window_get_selection (window);
|
|
if (selection && (webkit_dom_dom_selection_get_range_count (selection) > 0)) {
|
|
WebKitDOMRange *range;
|
|
WebKitDOMElement *element;
|
|
WebKitDOMDocumentFragment *fragment;
|
|
|
|
range = webkit_dom_dom_selection_get_range_at (selection, 0, NULL);
|
|
if (range) {
|
|
fragment = webkit_dom_range_clone_contents (
|
|
range, NULL);
|
|
|
|
element = webkit_dom_document_create_element (
|
|
document, "DIV", NULL);
|
|
webkit_dom_node_append_child (
|
|
WEBKIT_DOM_NODE (element),
|
|
WEBKIT_DOM_NODE (fragment), NULL);
|
|
|
|
return webkit_dom_html_element_get_inner_html (
|
|
WEBKIT_DOM_HTML_ELEMENT (element));
|
|
}
|
|
}
|
|
|
|
frames = webkit_dom_document_get_elements_by_tag_name (
|
|
document, "IFRAME");
|
|
length = webkit_dom_node_list_get_length (frames);
|
|
for (ii = 0; ii < length; ii++) {
|
|
WebKitDOMNode *node;
|
|
gchar *text;
|
|
|
|
node = webkit_dom_node_list_item (frames, ii);
|
|
|
|
text = web_view_get_frame_selection_html (
|
|
WEBKIT_DOM_ELEMENT (node));
|
|
|
|
if (text) {
|
|
return text;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
gchar *
|
|
e_web_view_get_selection_html (EWebView *web_view)
|
|
{
|
|
WebKitDOMDocument *document;
|
|
WebKitDOMNodeList *frames;
|
|
gulong ii, length;
|
|
|
|
g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL);
|
|
|
|
if (!webkit_web_view_has_selection (WEBKIT_WEB_VIEW (web_view)))
|
|
return NULL;
|
|
|
|
document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (web_view));
|
|
frames = webkit_dom_document_get_elements_by_tag_name (document, "IFRAME");
|
|
length = webkit_dom_node_list_get_length (frames);
|
|
|
|
for (ii = 0; ii < length; ii++) {
|
|
gchar *text;
|
|
WebKitDOMNode *node;
|
|
|
|
node = webkit_dom_node_list_item (frames, ii);
|
|
|
|
text = web_view_get_frame_selection_html (
|
|
WEBKIT_DOM_ELEMENT (node));
|
|
|
|
if (text) {
|
|
return text;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void
|
|
e_web_view_set_settings (EWebView *web_view,
|
|
WebKitWebSettings *settings)
|
|
{
|
|
g_return_if_fail (E_IS_WEB_VIEW (web_view));
|
|
|
|
if (settings == webkit_web_view_get_settings (WEBKIT_WEB_VIEW (web_view)))
|
|
return;
|
|
|
|
g_object_bind_property (settings, "enable-caret-browsing", web_view, "caret-mode",
|
|
G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE);
|
|
|
|
webkit_web_view_set_settings (WEBKIT_WEB_VIEW (web_view), settings);
|
|
}
|
|
|
|
WebKitWebSettings *
|
|
e_web_view_get_default_settings (void)
|
|
{
|
|
WebKitWebSettings *settings;
|
|
|
|
settings = webkit_web_settings_new ();
|
|
|
|
g_object_set (G_OBJECT (settings),
|
|
"enable-frame-flattening", TRUE,
|
|
"enable-java-applet", FALSE,
|
|
"enable-html5-database", FALSE,
|
|
"enable-html5-local-storage", FALSE,
|
|
"enable-offline-web-application-cache", FALSE,
|
|
"enable-site-specific-quirks", TRUE,
|
|
"enable-scripts", FALSE,
|
|
NULL);
|
|
|
|
return settings;
|
|
}
|
|
|
|
void
|
|
e_web_view_update_fonts (EWebView *web_view)
|
|
{
|
|
GString *stylesheet;
|
|
gchar *base64;
|
|
gchar *aa = NULL;
|
|
WebKitWebSettings *settings;
|
|
PangoFontDescription *min_size, *ms, *vw;
|
|
const gchar *styles[] = { "normal", "oblique", "italic" };
|
|
const gchar *smoothing = NULL;
|
|
GtkStyleContext *context;
|
|
GdkColor *link = NULL;
|
|
GdkColor *visited = NULL;
|
|
|
|
ms = NULL;
|
|
vw = NULL;
|
|
|
|
if (E_WEB_VIEW_GET_CLASS (web_view)->set_fonts)
|
|
E_WEB_VIEW_GET_CLASS (web_view)->set_fonts (web_view, &ms, &vw);
|
|
|
|
if (ms == NULL) {
|
|
gchar *font;
|
|
|
|
font = g_settings_get_string (
|
|
web_view->priv->font_settings,
|
|
"monospace-font-name");
|
|
|
|
ms = pango_font_description_from_string (
|
|
font ? font : "monospace 10");
|
|
|
|
g_free (font);
|
|
}
|
|
|
|
if (vw == NULL) {
|
|
gchar *font;
|
|
|
|
font = g_settings_get_string (
|
|
web_view->priv->font_settings,
|
|
"font-name");
|
|
|
|
vw = pango_font_description_from_string (
|
|
font ? font : "serif 10");
|
|
|
|
g_free (font);
|
|
}
|
|
|
|
if (pango_font_description_get_size (ms) < pango_font_description_get_size (vw)) {
|
|
min_size = ms;
|
|
} else {
|
|
min_size = vw;
|
|
}
|
|
|
|
stylesheet = g_string_new ("");
|
|
g_string_append_printf (stylesheet,
|
|
"body {\n"
|
|
" font-family: '%s';\n"
|
|
" font-size: %dpt;\n"
|
|
" font-weight: %d;\n"
|
|
" font-style: %s;\n",
|
|
pango_font_description_get_family (vw),
|
|
pango_font_description_get_size (vw) / PANGO_SCALE,
|
|
pango_font_description_get_weight (vw),
|
|
styles[pango_font_description_get_style (vw)]);
|
|
|
|
if (web_view->priv->aliasing_settings != NULL)
|
|
aa = g_settings_get_string (
|
|
web_view->priv->aliasing_settings, "antialiasing");
|
|
|
|
if (g_strcmp0 (aa, "none") == 0)
|
|
smoothing = "none";
|
|
else if (g_strcmp0 (aa, "grayscale") == 0)
|
|
smoothing = "antialiased";
|
|
else if (g_strcmp0 (aa, "rgba") == 0)
|
|
smoothing = "subpixel-antialiased";
|
|
|
|
if (smoothing != NULL)
|
|
g_string_append_printf (
|
|
stylesheet,
|
|
" -webkit-font-smoothing: %s;\n",
|
|
smoothing);
|
|
|
|
g_free (aa);
|
|
|
|
g_string_append (stylesheet, "}\n");
|
|
|
|
g_string_append_printf (stylesheet,
|
|
"pre,code,.pre {\n"
|
|
" font-family: '%s';\n"
|
|
" font-size: %dpt;\n"
|
|
" font-weight: %d;\n"
|
|
" font-style: %s;\n"
|
|
"}",
|
|
pango_font_description_get_family (ms),
|
|
pango_font_description_get_size (ms) / PANGO_SCALE,
|
|
pango_font_description_get_weight (ms),
|
|
styles[pango_font_description_get_style (ms)]);
|
|
|
|
context = gtk_widget_get_style_context (GTK_WIDGET (web_view));
|
|
gtk_style_context_get_style (context,
|
|
"link-color", &link,
|
|
"visited-link-color", &visited,
|
|
NULL);
|
|
|
|
if (link == NULL) {
|
|
link = g_slice_new0 (GdkColor);
|
|
link->blue = G_MAXINT16;
|
|
}
|
|
|
|
if (visited == NULL) {
|
|
visited = g_slice_new0 (GdkColor);
|
|
visited->red = G_MAXINT16;
|
|
}
|
|
|
|
g_string_append_printf (stylesheet,
|
|
"a {\n"
|
|
" color: #%06x;\n"
|
|
"}\n"
|
|
"a:visited {\n"
|
|
" color: #%06x;\n"
|
|
"}\n",
|
|
e_color_to_value (link),
|
|
e_color_to_value (visited));
|
|
|
|
gdk_color_free (link);
|
|
gdk_color_free (visited);
|
|
|
|
base64 = g_base64_encode ((guchar *) stylesheet->str, stylesheet->len);
|
|
g_string_free (stylesheet, TRUE);
|
|
|
|
stylesheet = g_string_new ("data:text/css;charset=utf-8;base64,");
|
|
g_string_append (stylesheet, base64);
|
|
g_free (base64);
|
|
|
|
settings = webkit_web_view_get_settings (WEBKIT_WEB_VIEW (web_view));
|
|
g_object_set (G_OBJECT (settings),
|
|
"default-font-size", pango_font_description_get_size (vw) / PANGO_SCALE,
|
|
"default-font-family", pango_font_description_get_family (vw),
|
|
"monospace-font-family", pango_font_description_get_family (ms),
|
|
"default-monospace-font-size", (pango_font_description_get_size (ms) / PANGO_SCALE),
|
|
"minimum-font-size", (pango_font_description_get_size (min_size) / PANGO_SCALE),
|
|
"user-stylesheet-uri", stylesheet->str,
|
|
NULL);
|
|
|
|
g_string_free (stylesheet, TRUE);
|
|
|
|
pango_font_description_free (ms);
|
|
pango_font_description_free (vw);
|
|
}
|
|
|
|
void
|
|
e_web_view_install_request_handler (EWebView *web_view,
|
|
GType handler_type)
|
|
{
|
|
SoupSession *session;
|
|
SoupSessionFeature *feature;
|
|
gboolean new;
|
|
|
|
session = webkit_get_default_session ();
|
|
|
|
feature = soup_session_get_feature (session, SOUP_TYPE_REQUESTER);
|
|
new = FALSE;
|
|
if (feature == NULL) {
|
|
feature = SOUP_SESSION_FEATURE (soup_requester_new ());
|
|
soup_session_add_feature (session, feature);
|
|
new = TRUE;
|
|
}
|
|
|
|
soup_session_feature_add_feature (feature, handler_type);
|
|
|
|
if (new) {
|
|
g_object_unref (feature);
|
|
}
|
|
}
|
|
|