[evolution] Bug 775656 - Delete key mapping stops working
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution] Bug 775656 - Delete key mapping stops working
- Date: Mon, 5 Dec 2016 18:58:01 +0000 (UTC)
commit eacfb00b227f82aa29df876806f1385469a3268a
Author: Milan Crha <mcrha redhat com>
Date: Mon Dec 5 19:56:16 2016 +0100
Bug 775656 - Delete key mapping stops working
src/e-util/e-web-view.c | 223 ++++++++++++++--
src/e-util/e-web-view.h | 6 +
src/mail/e-mail-reader.c | 17 +-
src/modules/mail/e-mail-shell-view-private.c | 30 +--
src/web-extensions/e-dom-utils.c | 120 ---------
src/web-extensions/e-dom-utils.h | 3 -
src/web-extensions/e-web-extension.c | 363 ++++++++++++++++++++------
7 files changed, 493 insertions(+), 269 deletions(-)
---
diff --git a/src/e-util/e-web-view.c b/src/e-util/e-web-view.c
index 03cef07..74f4131 100644
--- a/src/e-util/e-web-view.c
+++ b/src/e-util/e-web-view.c
@@ -93,6 +93,12 @@ struct _EWebViewPrivate {
GHashTable *element_clicked_cbs; /* gchar *element_class ~> GPtrArray {ElementClickedData} */
guint web_extension_element_clicked_signal_id;
+
+ guint32 clipboard_flags;
+ guint web_extension_clipboard_flags_changed_signal_id;
+
+ gboolean need_input;
+ guint web_extension_need_input_changed_signal_id;
};
struct _AsyncContext {
@@ -106,10 +112,12 @@ struct _AsyncContext {
enum {
PROP_0,
PROP_CARET_MODE,
+ PROP_CLIPBOARD_FLAGS,
PROP_COPY_TARGET_LIST,
PROP_CURSOR_IMAGE_SRC,
PROP_DISABLE_PRINTING,
PROP_DISABLE_SAVE_TO_DISK,
+ PROP_NEED_INPUT,
PROP_OPEN_PROXY,
PROP_PASTE_TARGET_LIST,
PROP_PRINT_PROXY,
@@ -776,6 +784,12 @@ web_view_set_property (GObject *object,
g_value_get_boolean (value));
return;
+ case PROP_CLIPBOARD_FLAGS:
+ e_web_view_set_clipboard_flags (
+ E_WEB_VIEW (object),
+ g_value_get_uint (value));
+ return;
+
case PROP_COPY_TARGET_LIST:
/* This is a fake property. */
g_warning ("%s: EWebView::copy-target-list not used", G_STRFUNC);
@@ -799,6 +813,12 @@ web_view_set_property (GObject *object,
g_value_get_boolean (value));
return;
+ case PROP_NEED_INPUT:
+ e_web_view_set_need_input (
+ E_WEB_VIEW (object),
+ g_value_get_boolean (value));
+ return;
+
case PROP_OPEN_PROXY:
e_web_view_set_open_proxy (
E_WEB_VIEW (object),
@@ -844,6 +864,12 @@ web_view_get_property (GObject *object,
E_WEB_VIEW (object)));
return;
+ case PROP_CLIPBOARD_FLAGS:
+ g_value_set_uint (
+ value, e_web_view_get_clipboard_flags (
+ E_WEB_VIEW (object)));
+ return;
+
case PROP_COPY_TARGET_LIST:
/* This is a fake property. */
g_value_set_boxed (value, NULL);
@@ -867,6 +893,12 @@ web_view_get_property (GObject *object,
E_WEB_VIEW (object)));
return;
+ case PROP_NEED_INPUT:
+ g_value_set_boolean (
+ value, e_web_view_get_need_input (
+ E_WEB_VIEW (object)));
+ return;
+
case PROP_OPEN_PROXY:
g_value_set_object (
value, e_web_view_get_open_proxy (
@@ -948,6 +980,20 @@ web_view_dispose (GObject *object)
priv->failed_to_find_text_handler_id = 0;
}
+ if (priv->web_extension && priv->web_extension_clipboard_flags_changed_signal_id) {
+ g_dbus_connection_signal_unsubscribe (
+ g_dbus_proxy_get_connection (priv->web_extension),
+ priv->web_extension_clipboard_flags_changed_signal_id);
+ priv->web_extension_clipboard_flags_changed_signal_id = 0;
+ }
+
+ if (priv->web_extension && priv->web_extension_need_input_changed_signal_id) {
+ g_dbus_connection_signal_unsubscribe (
+ g_dbus_proxy_get_connection (priv->web_extension),
+ priv->web_extension_need_input_changed_signal_id);
+ priv->web_extension_need_input_changed_signal_id = 0;
+ }
+
if (priv->web_extension && priv->web_extension_element_clicked_signal_id) {
g_dbus_connection_signal_unsubscribe (
g_dbus_proxy_get_connection (priv->web_extension),
@@ -1395,6 +1441,60 @@ web_view_register_element_clicked_hfunc (gpointer key,
}
static void
+web_view_need_input_changed_signal_cb (GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ EWebView *web_view = user_data;
+ guint64 page_id = 0;
+ gboolean need_input = FALSE;
+
+ if (g_strcmp0 (signal_name, "NeedInputChanged") != 0)
+ return;
+
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
+
+ if (!parameters)
+ return;
+
+ g_variant_get (parameters, "(tb)", &page_id, &need_input);
+
+ if (page_id == webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (web_view)))
+ e_web_view_set_need_input (web_view, need_input);
+}
+
+static void
+web_view_clipboard_flags_changed_signal_cb (GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
+{
+ EWebView *web_view = user_data;
+ guint64 page_id = 0;
+ guint32 clipboard_flags = 0;
+
+ if (g_strcmp0 (signal_name, "ClipboardFlagsChanged") != 0)
+ return;
+
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
+
+ if (!parameters)
+ return;
+
+ g_variant_get (parameters, "(tu)", &page_id, &clipboard_flags);
+
+ if (page_id == webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (web_view)))
+ e_web_view_set_clipboard_flags (web_view, clipboard_flags);
+}
+
+static void
web_view_element_clicked_signal_cb (GDBusConnection *connection,
const gchar *sender_name,
const gchar *object_path,
@@ -1463,6 +1563,32 @@ web_extension_proxy_created_cb (GDBusProxy *proxy,
g_warning ("Error creating web extension proxy: %s\n", error->message);
g_error_free (error);
} else {
+ web_view->priv->web_extension_clipboard_flags_changed_signal_id =
+ g_dbus_connection_signal_subscribe (
+ g_dbus_proxy_get_connection (web_view->priv->web_extension),
+ g_dbus_proxy_get_name (web_view->priv->web_extension),
+ E_WEB_EXTENSION_INTERFACE,
+ "ClipboardFlagsChanged",
+ E_WEB_EXTENSION_OBJECT_PATH,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ web_view_clipboard_flags_changed_signal_cb,
+ web_view,
+ NULL);
+
+ web_view->priv->web_extension_need_input_changed_signal_id =
+ g_dbus_connection_signal_subscribe (
+ g_dbus_proxy_get_connection (web_view->priv->web_extension),
+ g_dbus_proxy_get_name (web_view->priv->web_extension),
+ E_WEB_EXTENSION_INTERFACE,
+ "NeedInputChanged",
+ E_WEB_EXTENSION_OBJECT_PATH,
+ NULL,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ web_view_need_input_changed_signal_cb,
+ web_view,
+ NULL);
+
web_view->priv->web_extension_element_clicked_signal_id =
g_dbus_connection_signal_subscribe (
g_dbus_proxy_get_connection (web_view->priv->web_extension),
@@ -1557,7 +1683,7 @@ static void
web_view_update_actions (EWebView *web_view)
{
GtkActionGroup *action_group;
- gboolean can_copy = FALSE;
+ gboolean can_copy;
gboolean scheme_is_http = FALSE;
gboolean scheme_is_mailto = FALSE;
gboolean uri_is_valid = FALSE;
@@ -1565,21 +1691,11 @@ web_view_update_actions (EWebView *web_view)
const gchar *cursor_image_src;
const gchar *group_name;
const gchar *uri;
- GDBusProxy *web_extension;
-
- uri = e_web_view_get_selected_uri (web_view);
- web_extension = e_web_view_get_web_extension_proxy (web_view);
- if (web_extension) {
- GVariant *result;
- result = g_dbus_proxy_get_cached_property (web_view->priv->web_extension, "ClipboardFlags");
- if (result) {
- EClipboardFlags clipboard_flags = g_variant_get_uint32 (result);
- g_variant_unref (result);
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
- can_copy = (clipboard_flags & E_CLIPBOARD_CAN_COPY);
- }
- }
+ uri = e_web_view_get_selected_uri (web_view);
+ can_copy = (e_web_view_get_clipboard_flags (web_view) & E_CLIPBOARD_CAN_COPY) != 0;
cursor_image_src = e_web_view_get_cursor_image_src (web_view);
/* Parse the URI early so we know if the actions will work. */
@@ -1778,24 +1894,13 @@ web_view_selectable_update_actions (ESelectable *selectable,
gint n_clipboard_targets)
{
EWebView *web_view;
- GDBusProxy *web_extension;
GtkAction *action;
gboolean can_copy = FALSE;
web_view = E_WEB_VIEW (selectable);
- web_extension = e_web_view_get_web_extension_proxy (web_view);
- if (web_extension) {
- GVariant *result;
+ can_copy = (e_web_view_get_clipboard_flags (web_view) & E_CLIPBOARD_CAN_COPY) != 0;
- result = g_dbus_proxy_get_cached_property (web_view->priv->web_extension, "ClipboardFlags");
- if (result) {
- EClipboardFlags clipboard_actions = g_variant_get_uint32 (result);
- g_variant_unref (result);
-
- can_copy = (clipboard_actions & E_CLIPBOARD_CAN_COPY);
- }
- }
action = e_focus_tracker_get_copy_clipboard_action (focus_tracker);
gtk_action_set_sensitive (action, can_copy);
gtk_action_set_tooltip (action, _("Copy the selection"));
@@ -1961,6 +2066,17 @@ e_web_view_class_init (EWebViewClass *class)
FALSE,
G_PARAM_READWRITE));
+ g_object_class_install_property (
+ object_class,
+ PROP_CLIPBOARD_FLAGS,
+ g_param_spec_uint (
+ "clipboard-flags",
+ "Clipboard Flags",
+ NULL,
+ 0, G_MAXUINT, 0,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
/* Inherited from ESelectableInterface; just a fake property here */
g_object_class_override_property (
object_class,
@@ -2007,6 +2123,17 @@ e_web_view_class_init (EWebViewClass *class)
g_object_class_install_property (
object_class,
+ PROP_NEED_INPUT,
+ g_param_spec_boolean (
+ "need-input",
+ "Need Input",
+ NULL,
+ FALSE,
+ G_PARAM_READWRITE |
+ G_PARAM_CONSTRUCT));
+
+ g_object_class_install_property (
+ object_class,
PROP_OPEN_PROXY,
g_param_spec_object (
"open-proxy",
@@ -2638,6 +2765,50 @@ e_web_view_set_editable (EWebView *web_view,
webkit_web_view_set_editable (WEBKIT_WEB_VIEW (web_view), editable);
}
+guint32
+e_web_view_get_clipboard_flags (EWebView *web_view)
+{
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), 0);
+
+ return web_view->priv->clipboard_flags;
+}
+
+void
+e_web_view_set_clipboard_flags (EWebView *web_view,
+ guint32 clipboard_flags)
+{
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
+
+ if (web_view->priv->clipboard_flags == clipboard_flags)
+ return;
+
+ web_view->priv->clipboard_flags = clipboard_flags;
+
+ g_object_notify (G_OBJECT (web_view), "clipboard-flags");
+}
+
+gboolean
+e_web_view_get_need_input (EWebView *web_view)
+{
+ g_return_val_if_fail (E_IS_WEB_VIEW (web_view), FALSE);
+
+ return web_view->priv->need_input;
+}
+
+void
+e_web_view_set_need_input (EWebView *web_view,
+ gboolean need_input)
+{
+ g_return_if_fail (E_IS_WEB_VIEW (web_view));
+
+ if ((!web_view->priv->need_input) == (!need_input))
+ return;
+
+ web_view->priv->need_input = need_input;
+
+ g_object_notify (G_OBJECT (web_view), "need-input");
+}
+
const gchar *
e_web_view_get_selected_uri (EWebView *web_view)
{
diff --git a/src/e-util/e-web-view.h b/src/e-util/e-web-view.h
index f31bf88..fb1692a 100644
--- a/src/e-util/e-web-view.h
+++ b/src/e-util/e-web-view.h
@@ -165,6 +165,12 @@ void e_web_view_set_disable_save_to_disk
gboolean e_web_view_get_editable (EWebView *web_view);
void e_web_view_set_editable (EWebView *web_view,
gboolean editable);
+guint32 e_web_view_get_clipboard_flags (EWebView *web_view);
+void e_web_view_set_clipboard_flags (EWebView *web_view,
+ guint32 clipboard_flags);
+gboolean e_web_view_get_need_input (EWebView *web_view);
+void e_web_view_set_need_input (EWebView *web_view,
+ gboolean need_input);
gboolean e_web_view_get_inline_spelling (EWebView *web_view);
void e_web_view_set_inline_spelling (EWebView *web_view,
gboolean inline_spelling);
diff --git a/src/mail/e-mail-reader.c b/src/mail/e-mail-reader.c
index 0698dc5..58b50ad 100644
--- a/src/mail/e-mail-reader.c
+++ b/src/mail/e-mail-reader.c
@@ -2677,22 +2677,11 @@ mail_reader_key_press_event_cb (EMailReader *reader,
if (!gtk_widget_has_focus (GTK_WIDGET (reader))) {
EMailDisplay *display;
- GDBusProxy *web_extension;
display = e_mail_reader_get_mail_display (reader);
- web_extension = e_web_view_get_web_extension_proxy (E_WEB_VIEW (display));
- if (web_extension) {
- GVariant *result;
-
- result = g_dbus_proxy_get_cached_property (web_extension, "NeedInput");
- if (result) {
- gboolean need_input = g_variant_get_boolean (result);
- g_variant_unref (result);
-
- if (need_input)
- return FALSE;
- }
- }
+ if (e_web_view_get_need_input (E_WEB_VIEW (display)) &&
+ gtk_widget_has_focus (GTK_WIDGET (display)))
+ return FALSE;
}
if ((event->state & GDK_CONTROL_MASK) != 0)
diff --git a/src/modules/mail/e-mail-shell-view-private.c b/src/modules/mail/e-mail-shell-view-private.c
index 7f7a179..d39dff0 100644
--- a/src/modules/mail/e-mail-shell-view-private.c
+++ b/src/modules/mail/e-mail-shell-view-private.c
@@ -248,33 +248,6 @@ mail_shell_view_folder_tree_popup_event_cb (EShellView *shell_view,
}
static gboolean
-mail_shell_view_mail_display_needs_key (EMailShellView *mail_shell_view,
- EMailDisplay *mail_display)
-{
- if (gtk_widget_has_focus (GTK_WIDGET (mail_display))) {
- GDBusProxy *web_extension;
-
- /* Intentionally use Evolution Web Extension */
- web_extension = e_web_view_get_web_extension_proxy (E_WEB_VIEW (mail_display));
- if (web_extension) {
- GVariant *result;
-
- result = g_dbus_proxy_get_cached_property (web_extension, "NeedInput");
- if (result) {
- gboolean need_input;
-
- need_input = g_variant_get_boolean (result);
- g_variant_unref (result);
-
- return need_input;
- }
- }
- }
-
- return FALSE;
-}
-
-static gboolean
mail_shell_view_key_press_event_cb (EMailShellView *mail_shell_view,
GdkEventKey *event)
{
@@ -310,7 +283,8 @@ mail_shell_view_key_press_event_cb (EMailShellView *mail_shell_view,
return FALSE;
}
- if (mail_shell_view_mail_display_needs_key (mail_shell_view, mail_display))
+ if (e_web_view_get_need_input (E_WEB_VIEW (mail_display)) &&
+ gtk_widget_has_focus (GTK_WIDGET (mail_display)))
return FALSE;
gtk_action_activate (action);
diff --git a/src/web-extensions/e-dom-utils.c b/src/web-extensions/e-dom-utils.c
index 0a72064..96e8b03 100644
--- a/src/web-extensions/e-dom-utils.c
+++ b/src/web-extensions/e-dom-utils.c
@@ -805,126 +805,6 @@ e_dom_utils_bind_dom (WebKitDOMDocument *document,
g_clear_object (&nodes);
}
-static void
-e_dom_utils_bind_elements_recursively (WebKitDOMDocument *document,
- const gchar *selector,
- const gchar *event,
- gpointer callback,
- gpointer user_data)
-{
- WebKitDOMNodeList *nodes = NULL;
- WebKitDOMHTMLCollection *frames = NULL;
- gulong ii, length;
-
- nodes = webkit_dom_document_query_selector_all (
- document, selector, NULL);
-
- length = webkit_dom_node_list_get_length (nodes);
- for (ii = 0; ii < length; ii++) {
- WebKitDOMNode *node;
-
- node = webkit_dom_node_list_item (nodes, ii);
- webkit_dom_event_target_add_event_listener (
- WEBKIT_DOM_EVENT_TARGET (node), event,
- G_CALLBACK (callback), FALSE, user_data);
- }
- g_clear_object (&nodes);
-
- frames = webkit_dom_document_get_elements_by_tag_name_as_html_collection (document, "iframe");
- length = webkit_dom_html_collection_get_length (frames);
-
- /* Add rules to every sub document */
- for (ii = 0; ii < length; ii++) {
- WebKitDOMDocument *content_document = NULL;
- WebKitDOMNode *node;
-
- node = webkit_dom_html_collection_item (frames, ii);
- content_document =
- webkit_dom_html_iframe_element_get_content_document (
- WEBKIT_DOM_HTML_IFRAME_ELEMENT (node));
-
- if (!content_document)
- continue;
-
- e_dom_utils_bind_elements_recursively (
- content_document,
- selector,
- event,
- callback,
- user_data);
- }
- g_clear_object (&frames);
-}
-
-static void
-element_focus_cb (WebKitDOMElement *element,
- WebKitDOMEvent *event,
- GDBusConnection *connection)
-{
- g_dbus_connection_call (
- connection,
- E_WEB_EXTENSION_SERVICE_NAME,
- E_WEB_EXTENSION_OBJECT_PATH,
- "org.freedesktop.DBus.Properties",
- "Set",
- g_variant_new (
- "(ssv)",
- E_WEB_EXTENSION_INTERFACE,
- "NeedInput",
- g_variant_new_boolean (TRUE)),
- NULL,
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- NULL,
- NULL);
-}
-
-static void
-element_blur_cb (WebKitDOMElement *element,
- WebKitDOMEvent *event,
- GDBusConnection *connection)
-{
- g_dbus_connection_call (
- connection,
- E_WEB_EXTENSION_SERVICE_NAME,
- E_WEB_EXTENSION_OBJECT_PATH,
- "org.freedesktop.DBus.Properties",
- "Set",
- g_variant_new (
- "(ssv)",
- E_WEB_EXTENSION_INTERFACE,
- "NeedInput",
- g_variant_new_boolean (FALSE)),
- NULL,
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- NULL,
- NULL);
-}
-
-void
-e_dom_utils_bind_focus_on_elements (WebKitDOMDocument *document,
- GDBusConnection *connection)
-{
- const gchar *elements = "input, textarea, select, button, label";
-
- e_dom_utils_bind_elements_recursively (
- document,
- elements,
- "focus",
- element_focus_cb,
- connection);
-
- e_dom_utils_bind_elements_recursively (
- document,
- elements,
- "blur",
- element_blur_cb,
- connection);
-}
-
static gboolean
force_width_is_valid_element (WebKitDOMElement *element)
{
diff --git a/src/web-extensions/e-dom-utils.h b/src/web-extensions/e-dom-utils.h
index 0b24cd2..38bf3e2 100644
--- a/src/web-extensions/e-dom-utils.h
+++ b/src/web-extensions/e-dom-utils.h
@@ -60,9 +60,6 @@ void e_dom_utils_add_css_rule_into_style_sheet
const gchar *style);
void e_dom_utils_eab_contact_formatter_bind_dom
(WebKitDOMDocument *document);
-void e_dom_utils_bind_focus_on_elements
- (WebKitDOMDocument *document,
- GDBusConnection *connection);
void e_dom_resize_document_content_to_preview_width
(WebKitDOMDocument *document);
void e_dom_utils_e_mail_display_bind_dom
diff --git a/src/web-extensions/e-web-extension.c b/src/web-extensions/e-web-extension.c
index 3f11e10..c827be9 100644
--- a/src/web-extensions/e-web-extension.c
+++ b/src/web-extensions/e-web-extension.c
@@ -40,6 +40,12 @@
(G_TYPE_INSTANCE_GET_PRIVATE \
((obj), E_TYPE_WEB_EXTENSION, EWebExtensionPrivate))
+typedef struct _EWebPageData {
+ WebKitWebPage *web_page; /* not referenced */
+ gboolean need_input;
+ guint32 clipboard_flags;
+} EWebPageData;
+
struct _EWebExtensionPrivate {
WebKitWebExtension *wk_extension;
@@ -48,8 +54,7 @@ struct _EWebExtensionPrivate {
gboolean initialized;
- gboolean need_input;
- guint32 clipboard_flags;
+ GHashTable *pages; /* guint64 *webpage_id ~> EWebPageData * */
};
static const char introspection_xml[] =
@@ -178,8 +183,14 @@ static const char introspection_xml[] =
" <arg type='b' name='towards_bottom' direction='in'/>"
" <arg type='b' name='processed' direction='out'/>"
" </method>"
-" <property type='b' name='NeedInput' access='readwrite'/>"
-" <property type='u' name='ClipboardFlags' access='readwrite'/>"
+" <signal name='NeedInputChanged'>"
+" <arg type='t' name='page_id' direction='out'/>"
+" <arg type='b' name='need_input' direction='out'/>"
+" </signal>"
+" <signal name='ClipboardFlagsChanged'>"
+" <arg type='t' name='page_id' direction='out'/>"
+" <arg type='u' name='flags' direction='out'/>"
+" </signal>"
" </interface>"
"</node>";
@@ -325,6 +336,172 @@ web_extension_register_element_clicked_in_document (EWebExtension *extension,
g_clear_object (&collection);
}
+static guint64
+e_web_extension_find_page_id_from_document (WebKitDOMDocument *document)
+{
+ guint64 *ppage_id;
+
+ g_return_val_if_fail (WEBKIT_DOM_IS_DOCUMENT (document), 0);
+
+ while (document) {
+ WebKitDOMDocument *prev_document = document;
+
+ ppage_id = g_object_get_data (G_OBJECT (document), WEB_EXTENSION_PAGE_ID_KEY);
+ if (ppage_id)
+ return *ppage_id;
+
+ document = webkit_dom_node_get_owner_document (WEBKIT_DOM_NODE (document));
+ if (prev_document == document)
+ break;
+ }
+
+ return 0;
+}
+
+static void
+e_web_extension_set_need_input (EWebExtension *extension,
+ guint64 page_id,
+ gboolean need_input)
+{
+ EWebPageData *page_data;
+ GError *error = NULL;
+
+ g_return_if_fail (E_IS_WEB_EXTENSION (extension));
+ g_return_if_fail (page_id != 0);
+
+ page_data = g_hash_table_lookup (extension->priv->pages, &page_id);
+
+ if (!page_data || (!page_data->need_input) == (!need_input))
+ return;
+
+ page_data->need_input = need_input;
+
+ g_dbus_connection_emit_signal (
+ extension->priv->dbus_connection,
+ NULL,
+ E_WEB_EXTENSION_OBJECT_PATH,
+ E_WEB_EXTENSION_INTERFACE,
+ "NeedInputChanged",
+ g_variant_new ("(tb)", page_id, need_input),
+ &error);
+
+ if (error) {
+ g_warning ("Error emitting signal NeedInputChanged: %s\n", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
+element_focus_cb (WebKitDOMElement *element,
+ WebKitDOMEvent *event,
+ EWebExtension *extension)
+{
+ guint64 *ppage_id;
+
+ g_return_if_fail (E_IS_WEB_EXTENSION (extension));
+
+ ppage_id = g_object_get_data (G_OBJECT (element), WEB_EXTENSION_PAGE_ID_KEY);
+ g_return_if_fail (ppage_id != NULL);
+
+ e_web_extension_set_need_input (extension, *ppage_id, TRUE);
+}
+
+static void
+element_blur_cb (WebKitDOMElement *element,
+ WebKitDOMEvent *event,
+ EWebExtension *extension)
+{
+ guint64 *ppage_id;
+
+ g_return_if_fail (E_IS_WEB_EXTENSION (extension));
+
+ ppage_id = g_object_get_data (G_OBJECT (element), WEB_EXTENSION_PAGE_ID_KEY);
+ g_return_if_fail (ppage_id != NULL);
+
+ e_web_extension_set_need_input (extension, *ppage_id, FALSE);
+}
+
+static void
+e_web_extension_bind_focus_and_blur_recursively (EWebExtension *extension,
+ WebKitDOMDocument *document,
+ const gchar *selector,
+ guint64 page_id)
+{
+ WebKitDOMNodeList *nodes = NULL;
+ WebKitDOMHTMLCollection *frames = NULL;
+ gulong ii, length;
+
+ g_return_if_fail (E_IS_WEB_EXTENSION (extension));
+
+ nodes = webkit_dom_document_query_selector_all (document, selector, NULL);
+
+ length = webkit_dom_node_list_get_length (nodes);
+ for (ii = 0; ii < length; ii++) {
+ WebKitDOMNode *node;
+ guint64 *ppage_id;
+
+ node = webkit_dom_node_list_item (nodes, ii);
+
+ ppage_id = g_new (guint64, 1);
+ *ppage_id = page_id;
+
+ g_object_set_data_full (G_OBJECT (node), WEB_EXTENSION_PAGE_ID_KEY, ppage_id, g_free);
+
+ webkit_dom_event_target_add_event_listener (
+ WEBKIT_DOM_EVENT_TARGET (node), "focus",
+ G_CALLBACK (element_focus_cb), FALSE, extension);
+
+ webkit_dom_event_target_add_event_listener (
+ WEBKIT_DOM_EVENT_TARGET (node), "blur",
+ G_CALLBACK (element_blur_cb), FALSE, extension);
+ }
+ g_clear_object (&nodes);
+
+ frames = webkit_dom_document_get_elements_by_tag_name_as_html_collection (document, "iframe");
+ length = webkit_dom_html_collection_get_length (frames);
+
+ /* Add rules to every sub document */
+ for (ii = 0; ii < length; ii++) {
+ WebKitDOMDocument *content_document = NULL;
+ WebKitDOMNode *node;
+
+ node = webkit_dom_html_collection_item (frames, ii);
+ content_document =
+ webkit_dom_html_iframe_element_get_content_document (
+ WEBKIT_DOM_HTML_IFRAME_ELEMENT (node));
+
+ if (!content_document)
+ continue;
+
+ e_web_extension_bind_focus_and_blur_recursively (
+ extension,
+ content_document,
+ selector,
+ page_id);
+ }
+ g_clear_object (&frames);
+}
+
+static void
+e_web_extension_bind_focus_on_elements (EWebExtension *extension,
+ WebKitDOMDocument *document)
+{
+ const gchar *elements = "input, textarea, select, button, label";
+ guint64 page_id;
+
+ g_return_if_fail (E_IS_WEB_EXTENSION (extension));
+ g_return_if_fail (WEBKIT_DOM_IS_DOCUMENT (document));
+
+ page_id = e_web_extension_find_page_id_from_document (document);
+ g_return_if_fail (page_id != 0);
+
+ e_web_extension_bind_focus_and_blur_recursively (
+ extension,
+ document,
+ elements,
+ page_id);
+}
+
static void
handle_method_call (GDBusConnection *connection,
const char *sender,
@@ -644,7 +821,7 @@ handle_method_call (GDBusConnection *connection,
document = webkit_web_page_get_dom_document (web_page);
e_dom_utils_e_mail_display_bind_dom (document, connection);
- e_dom_utils_bind_focus_on_elements (document, connection);
+ e_web_extension_bind_focus_on_elements (extension, document);
g_dbus_method_invocation_return_value (invocation, NULL);
} else if (g_strcmp0 (method_name, "ElementExists") == 0) {
@@ -823,13 +1000,10 @@ handle_get_property (GDBusConnection *connection,
GError **error,
gpointer user_data)
{
- EWebExtension *extension = E_WEB_EXTENSION (user_data);
+ /* EWebExtension *extension = E_WEB_EXTENSION (user_data); */
GVariant *variant = NULL;
- if (g_strcmp0 (property_name, "NeedInput") == 0)
- variant = g_variant_new_boolean (extension->priv->need_input);
- else if (g_strcmp0 (property_name, "ClipboardFlags") == 0)
- variant = g_variant_new_uint32 (extension->priv->clipboard_flags);
+ g_warn_if_reached ();
return variant;
}
@@ -844,54 +1018,9 @@ handle_set_property (GDBusConnection *connection,
GError **error,
gpointer user_data)
{
- EWebExtension *extension = E_WEB_EXTENSION (user_data);
- GError *local_error = NULL;
- GVariantBuilder *builder;
-
- builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY);
-
- if (g_strcmp0 (property_name, "NeedInput") == 0) {
- gboolean value = g_variant_get_boolean (variant);
-
- if (value == extension->priv->need_input)
- goto exit;
-
- extension->priv->need_input = value;
-
- g_variant_builder_add (builder,
- "{sv}",
- "NeedInput",
- g_variant_new_boolean (value));
- } else if (g_strcmp0 (property_name, "ClipboardFlags") == 0) {
- guint32 value = g_variant_get_uint32 (variant);
-
- if (value == extension->priv->clipboard_flags)
- goto exit;
-
- extension->priv->clipboard_flags = value;
-
- g_variant_builder_add (builder,
- "{sv}",
- "ClipboardFlags",
- g_variant_new_uint32 (value));
- }
-
- g_dbus_connection_emit_signal (connection,
- NULL,
- object_path,
- "org.freedesktop.DBus.Properties",
- "PropertiesChanged",
- g_variant_new (
- "(sa{sv}as)",
- interface_name,
- builder,
- NULL),
- &local_error);
+ /* EWebExtension *extension = E_WEB_EXTENSION (user_data); */
- g_assert_no_error (local_error);
-
- exit:
- g_variant_builder_unref (builder);
+ g_warn_if_reached ();
return TRUE;
}
@@ -903,6 +1032,27 @@ static const GDBusInterfaceVTable interface_vtable = {
};
static void
+web_page_gone_cb (gpointer user_data,
+ GObject *gone_web_page)
+{
+ EWebExtension *extension = user_data;
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_return_if_fail (E_IS_WEB_EXTENSION (extension));
+
+ g_hash_table_iter_init (&iter, extension->priv->pages);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ EWebPageData *page_data = value;
+
+ if (page_data->web_page == (gpointer) gone_web_page) {
+ g_hash_table_remove (extension->priv->pages, key);
+ break;
+ }
+ }
+}
+
+static void
e_web_extension_dispose (GObject *object)
{
EWebExtension *extension = E_WEB_EXTENSION (object);
@@ -915,19 +1065,35 @@ e_web_extension_dispose (GObject *object)
extension->priv->dbus_connection = NULL;
}
+ g_hash_table_remove_all (extension->priv->pages);
+
g_clear_object (&extension->priv->wk_extension);
G_OBJECT_CLASS (e_web_extension_parent_class)->dispose (object);
}
static void
+e_web_extension_finalize (GObject *object)
+{
+ EWebExtension *extension = E_WEB_EXTENSION (object);
+
+ if (extension->priv->pages) {
+ g_hash_table_destroy (extension->priv->pages);
+ extension->priv->pages = NULL;
+ }
+
+ G_OBJECT_CLASS (e_web_extension_parent_class)->finalize (object);
+}
+
+static void
e_web_extension_class_init (EWebExtensionClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS (class);
- object_class->dispose = e_web_extension_dispose;
+ g_type_class_add_private (object_class, sizeof (EWebExtensionPrivate));
- g_type_class_add_private (object_class, sizeof(EWebExtensionPrivate));
+ object_class->dispose = e_web_extension_dispose;
+ object_class->finalize = e_web_extension_finalize;
}
static void
@@ -936,8 +1102,7 @@ e_web_extension_init (EWebExtension *extension)
extension->priv = G_TYPE_INSTANCE_GET_PRIVATE (extension, E_TYPE_WEB_EXTENSION, EWebExtensionPrivate);
extension->priv->initialized = FALSE;
- extension->priv->need_input = FALSE;
- extension->priv->clipboard_flags = 0;
+ extension->priv->pages = g_hash_table_new_full (g_int64_hash, g_int64_equal, g_free, g_free);
}
static gpointer
@@ -991,9 +1156,15 @@ web_page_document_loaded_cb (WebKitWebPage *web_page,
gpointer user_data)
{
WebKitDOMDocument *document;
+ guint64 *ppage_id;
document = webkit_web_page_get_dom_document (web_page);
+ ppage_id = g_new (guint64, 1);
+ *ppage_id = webkit_web_page_get_id (web_page);
+
+ g_object_set_data_full (G_OBJECT (document), WEB_EXTENSION_PAGE_ID_KEY, ppage_id, g_free);
+
e_dom_utils_replace_local_image_links (document);
if ((webkit_dom_document_query_selector (
@@ -1012,6 +1183,43 @@ web_page_document_loaded_cb (WebKitWebPage *web_page,
}
static void
+e_web_extension_set_clipboard_flags (EWebExtension *extension,
+ WebKitDOMDocument *document,
+ guint32 clipboard_flags)
+{
+ EWebPageData *page_data;
+ guint64 page_id;
+ GError *error = NULL;
+
+ g_return_if_fail (E_IS_WEB_EXTENSION (extension));
+ g_return_if_fail (WEBKIT_DOM_IS_DOCUMENT (document));
+
+ page_id = e_web_extension_find_page_id_from_document (document);
+ g_return_if_fail (page_id != 0);
+
+ page_data = g_hash_table_lookup (extension->priv->pages, &page_id);
+
+ if (!page_data || page_data->clipboard_flags == clipboard_flags)
+ return;
+
+ page_data->clipboard_flags = clipboard_flags;
+
+ g_dbus_connection_emit_signal (
+ extension->priv->dbus_connection,
+ NULL,
+ E_WEB_EXTENSION_OBJECT_PATH,
+ E_WEB_EXTENSION_INTERFACE,
+ "ClipboardFlagsChanged",
+ g_variant_new ("(tu)", page_id, clipboard_flags),
+ &error);
+
+ if (error) {
+ g_warning ("Error emitting signal ClipboardFlagsChanged: %s\n", error->message);
+ g_error_free (error);
+ }
+}
+
+static void
web_editor_selection_changed_cb (WebKitWebEditor *web_editor,
EWebExtension *extension)
{
@@ -1026,23 +1234,7 @@ web_editor_selection_changed_cb (WebKitWebEditor *web_editor,
if (e_dom_utils_document_has_selection (document))
clipboard_flags |= E_CLIPBOARD_CAN_COPY;
- g_dbus_connection_call (
- extension->priv->dbus_connection,
- E_WEB_EXTENSION_SERVICE_NAME,
- E_WEB_EXTENSION_OBJECT_PATH,
- "org.freedesktop.DBus.Properties",
- "Set",
- g_variant_new (
- "(ssv)",
- E_WEB_EXTENSION_INTERFACE,
- "ClipboardFlags",
- g_variant_new_uint32 (clipboard_flags)),
- NULL,
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL,
- NULL,
- NULL);
+ e_web_extension_set_clipboard_flags (extension, document, clipboard_flags);
}
static void
@@ -1050,6 +1242,21 @@ web_page_created_cb (WebKitWebExtension *wk_extension,
WebKitWebPage *web_page,
EWebExtension *extension)
{
+ EWebPageData *page_data;
+ guint64 *ppage_id;
+
+ ppage_id = g_new (guint64, 1);
+ *ppage_id = webkit_web_page_get_id (web_page);
+
+ page_data = g_new0 (EWebPageData, 1);
+ page_data->web_page = web_page;
+ page_data->need_input = FALSE;
+ page_data->clipboard_flags = 0;
+
+ g_hash_table_insert (extension->priv->pages, ppage_id, page_data);
+
+ g_object_weak_ref (G_OBJECT (web_page), web_page_gone_cb, extension);
+
g_signal_connect_object (
web_page, "send-request",
G_CALLBACK (web_page_send_request_cb),
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]