[evolution/wip/webkit2] Bug 757939 - Undo failure after dragging text



commit 55044235472d9c955bf0c1424bd695caa89cb7e8
Author: Tomas Popela <tpopela redhat com>
Date:   Thu Mar 3 12:22:34 2016 +0100

    Bug 757939 - Undo failure after dragging text

 composer/e-composer-private.c                      |    1 +
 composer/e-composer-private.h                      |    1 +
 composer/e-msg-composer.c                          |   51 ++++-
 .../composer/e-composer-private-dom-functions.c    |  245 +++++++++++++++++++-
 .../composer/e-composer-private-dom-functions.h    |    2 +
 .../composer/e-html-editor-undo-redo-manager.c     |   25 +-
 .../composer/e-html-editor-view-dom-functions.c    |   89 +++++++-
 .../composer/e-html-editor-view-dom-functions.h    |    2 +
 .../composer/e-html-editor-web-extension.c         |   17 ++-
 web-extensions/e-dom-utils.c                       |   20 ++
 web-extensions/e-dom-utils.h                       |    3 +
 11 files changed, 419 insertions(+), 37 deletions(-)
---
diff --git a/composer/e-composer-private.c b/composer/e-composer-private.c
index 486da1d..4aec161 100644
--- a/composer/e-composer-private.c
+++ b/composer/e-composer-private.c
@@ -140,6 +140,7 @@ e_composer_private_constructed (EMsgComposer *composer)
        priv->saved_editable = FALSE;
        priv->drop_occured = FALSE;
        priv->dnd_is_uri = FALSE;
+       priv->dnd_history_saved = FALSE;
 
        priv->focused_entry = NULL;
 
diff --git a/composer/e-composer-private.h b/composer/e-composer-private.h
index 716c829..7586d3f 100644
--- a/composer/e-composer-private.h
+++ b/composer/e-composer-private.h
@@ -103,6 +103,7 @@ struct _EMsgComposerPrivate {
        gboolean drop_occured;
        gboolean dnd_is_uri;
        gboolean is_sending_message;
+       gboolean dnd_history_saved;
 
        gint focused_entry_selection_start;
        gint focused_entry_selection_end;
diff --git a/composer/e-msg-composer.c b/composer/e-msg-composer.c
index 350817b..ce2c532 100644
--- a/composer/e-msg-composer.c
+++ b/composer/e-msg-composer.c
@@ -1831,30 +1831,54 @@ msg_composer_drag_drop_cb (GtkWidget *widget,
        GdkAtom target;
        GtkWidget *source_widget;
 
-       /* When we are doind DnD just inside the web view, the DnD is supposed
+       /* When we are doing DnD just inside the web view, the DnD is supposed
         * to move things around. */
        source_widget = gtk_drag_get_source_widget (context);
        if (E_IS_HTML_EDITOR_VIEW (source_widget)) {
                EHTMLEditor *editor = e_msg_composer_get_editor (composer);
                EHTMLEditorView *editor_view = e_html_editor_get_view (editor);
 
-               if ((gpointer) editor_view == (gpointer) source_widget)
+               if ((gpointer) editor_view == (gpointer) source_widget) {
+                       GDBusProxy *web_extension;
+
+                       web_extension = e_html_editor_view_get_web_extension_proxy (editor_view);
+                       if (web_extension) {
+                               g_dbus_proxy_call_sync (
+                                       web_extension,
+                                       "DOMSaveDragAndDropHistory",
+                                       g_variant_new (
+                                               "(t)",
+                                               webkit_web_view_get_page_id (WEBKIT_WEB_VIEW (editor_view))),
+                                       G_DBUS_CALL_FLAGS_NONE,
+                                       -1,
+                                       NULL,
+                                       NULL);
+                       }
                        return FALSE;
+               }
        }
 
        target = gtk_drag_dest_find_target (widget, context, NULL);
        if (target == GDK_NONE)
                gdk_drag_status (context, 0, time);
        else {
-               /* Prevent WebKit from pasting the URI of file into the view. */
-               if (composer->priv->dnd_is_uri)
+               /* Prevent WebKit from pasting the URI of file into the view. Also
+                * prevent it from inserting the text/plain or text/html content as we
+                * want to insert it ourselves. */
+               if (composer->priv->dnd_is_uri || !E_IS_HTML_EDITOR_VIEW (source_widget))
                        g_signal_stop_emission_by_name (widget, "drag-drop");
 
                composer->priv->dnd_is_uri = FALSE;
 
-               gdk_drag_status (context, GDK_ACTION_COPY, time);
+               if (E_IS_HTML_EDITOR_VIEW (source_widget))
+                       gdk_drag_status (context, GDK_ACTION_MOVE, time);
+               else
+                       gdk_drag_status (context, GDK_ACTION_COPY, time);
+
                composer->priv->drop_occured = TRUE;
                gtk_drag_get_data (widget, context, target, time);
+
+               return TRUE;
        }
 
        return FALSE;
@@ -1875,15 +1899,17 @@ msg_composer_drag_data_received_after_cb (GtkWidget *widget,
        GDBusProxy *web_extension;
 
        if (!composer->priv->drop_occured)
-               return;
+               goto out;
 
-       composer->priv->drop_occured = FALSE;
+       /* Save just history for events handled by WebKit. */
+       if (composer->priv->dnd_history_saved)
+               goto out;
 
        editor = e_msg_composer_get_editor (composer);
        view = e_html_editor_get_view (editor);
        web_extension = e_html_editor_view_get_web_extension_proxy (view);
        if (!web_extension)
-               return;
+               goto out;
 
        g_dbus_proxy_call_sync (
                web_extension,
@@ -1895,6 +1921,10 @@ msg_composer_drag_data_received_after_cb (GtkWidget *widget,
                -1,
                NULL,
                NULL);
+
+ out:
+       composer->priv->drop_occured = FALSE;
+       composer->priv->dnd_history_saved = FALSE;
 }
 
 static gchar *
@@ -1941,7 +1971,9 @@ msg_composer_drag_data_received_cb (GtkWidget *widget,
        view = e_html_editor_get_view (editor);
        html_mode = e_html_editor_view_get_html_mode (view);
 
-       /* When we are doind DnD just inside the web view, the DnD is supposed
+       composer->priv->dnd_history_saved = TRUE;
+
+       /* When we are doing DnD just inside the web view, the DnD is supposed
         * to move things around. */
        source_widget = gtk_drag_get_source_widget (context);
        if (E_IS_HTML_EDITOR_VIEW (source_widget)) {
@@ -1985,6 +2017,7 @@ msg_composer_drag_data_received_cb (GtkWidget *widget,
            info == DND_TARGET_TYPE_STRING ||
            info == DND_TARGET_TYPE_TEXT_PLAIN ||
            info == DND_TARGET_TYPE_TEXT_PLAIN_UTF8) {
+               composer->priv->dnd_history_saved = FALSE;
                gdk_drag_status (context, 0, time);
                return;
        }
diff --git a/web-extensions/composer/e-composer-private-dom-functions.c 
b/web-extensions/composer/e-composer-private-dom-functions.c
index 97c89fc..4fdbf58 100644
--- a/web-extensions/composer/e-composer-private-dom-functions.c
+++ b/web-extensions/composer/e-composer-private-dom-functions.c
@@ -335,24 +335,245 @@ dom_insert_signature (WebKitDOMDocument *document,
        composer_move_caret (document, extension, top_signature, start_bottom);
 }
 
+static void
+insert_nbsp_history_event (WebKitDOMDocument *document,
+                          EHTMLEditorUndoRedoManager *manager,
+                           gboolean delete,
+                           guint x,
+                           guint y)
+{
+       EHTMLEditorHistoryEvent *event;
+       WebKitDOMDocumentFragment *fragment;
+
+       event = g_new0 (EHTMLEditorHistoryEvent, 1);
+       event->type = HISTORY_AND;
+       e_html_editor_undo_redo_manager_insert_history_event (manager, event);
+
+       fragment = webkit_dom_document_create_document_fragment (document);
+       webkit_dom_node_append_child (
+               WEBKIT_DOM_NODE (fragment),
+               WEBKIT_DOM_NODE (
+                       webkit_dom_document_create_text_node (document, UNICODE_NBSP)),
+               NULL);
+
+       event = g_new0 (EHTMLEditorHistoryEvent, 1);
+       event->type = HISTORY_DELETE;
+
+       if (delete)
+               g_object_set_data (
+                       G_OBJECT (fragment), "-x-evo-delete-key", GINT_TO_POINTER (1));
+
+       event->data.fragment = fragment;
+
+       event->before.start.x = x;
+       event->before.start.y = y;
+       event->before.end.x = x;
+       event->before.end.y = y;
+
+       event->after.start.x = x;
+       event->after.start.y = y;
+       event->after.end.x = x;
+       event->after.end.y = y;
+
+       e_html_editor_undo_redo_manager_insert_history_event (manager, event);
+}
+
 void
-dom_clean_after_drag_and_drop (WebKitDOMDocument *document,
-                               EHTMLEditorWebExtension *extension)
+dom_save_drag_and_drop_history (WebKitDOMDocument *document,
+                               EHTMLEditorWebExtension *extension)
 {
-       WebKitDOMDOMWindow *dom_window;
+       EHTMLEditorHistoryEvent *event;
+       EHTMLEditorUndoRedoManager *manager;
+       gboolean start_to_start, end_to_end;
+       gchar *range_text;
+       guint x, y;
+       WebKitDOMDocumentFragment *fragment;
        WebKitDOMDOMSelection *dom_selection;
+       WebKitDOMDOMWindow *dom_window;
+       WebKitDOMRange *beginning_of_line = NULL;
+       WebKitDOMRange *range = NULL, *range_clone = NULL;
+
+       manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
+
+       if (!(dom_window = webkit_dom_document_get_default_view (document)))
+               return;
+
+       if (!(dom_selection = webkit_dom_dom_window_get_selection (dom_window))) {
+               g_object_unref (dom_window);
+               return;
+       }
 
-       dom_window = webkit_dom_document_get_default_view (document);
-       dom_selection = webkit_dom_dom_window_get_selection (dom_window);
+       if (webkit_dom_dom_selection_get_range_count (dom_selection) < 1) {
+               g_object_unref (dom_selection);
+               g_object_unref (dom_window);
+               return;
+       }
+
+       /* Obtain the dragged content. */
+       range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+       range_clone = webkit_dom_range_clone_range (range, NULL);
+
+       /* Create the history event for the content that will
+        * be removed by DnD. */
+       event = g_new0 (EHTMLEditorHistoryEvent, 1);
+       event->type = HISTORY_DELETE;
+
+       dom_selection_get_coordinates (
+               document,
+               &event->before.start.x,
+               &event->before.start.y,
+               &event->before.end.x,
+               &event->before.end.y);
+
+       x = event->before.start.x;
+       y = event->before.start.y;
+
+       event->after.start.x = x;
+       event->after.start.y = y;
+       event->after.end.x = x;
+       event->after.end.y = y;
+
+       /* Save the content that will be removed. */
+       fragment = webkit_dom_range_clone_contents (range_clone, NULL);
+
+       /* Extend the cloned range to point one character after
+        * the selection ends to later check if there is a whitespace
+        * after it. */
+       webkit_dom_range_set_end (
+               range_clone,
+               webkit_dom_range_get_end_container (range_clone, NULL),
+               webkit_dom_range_get_end_offset (range_clone, NULL) + 1,
+               NULL);
+       range_text = webkit_dom_range_get_text (range_clone);
+
+       /* Check if the current selection starts on the beginning
+        * of line. */
+       webkit_dom_dom_selection_modify (
+               dom_selection, "extend", "left", "lineboundary");
+       beginning_of_line = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+       start_to_start = webkit_dom_range_compare_boundary_points (
+               beginning_of_line, 0 /* START_TO_START */, range, NULL) == 0;
+
+       /* Restore the selection to state before the check. */
+       webkit_dom_dom_selection_remove_all_ranges (dom_selection);
+       webkit_dom_dom_selection_add_range (dom_selection, range);
+       g_object_unref (beginning_of_line);
+
+       /* Check if the current selection end on the end of the line. */
+       webkit_dom_dom_selection_modify (
+               dom_selection, "extend", "right", "lineboundary");
+       beginning_of_line = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+       end_to_end = webkit_dom_range_compare_boundary_points (
+               beginning_of_line, 2 /* END_TO_END */, range, NULL) == 0;
+
+       /* Dragging the whole line. */
+       if (start_to_start && end_to_end) {
+               WebKitDOMNode *container, *actual_block, *tmp_block;
+
+               /* Select the whole line (to the beginning of the next
+                * one so we can reuse the undo code while undoing this.
+                * Because of this we need to special mark the event
+                * with -x-evo-drag-and-drop to correct the selection
+                * after undoing it (otherwise the beginning of the next
+                * line will be selected as well. */
+               webkit_dom_dom_selection_modify (
+                       dom_selection, "extend", "right", "character");
+               g_object_unref (beginning_of_line);
+               beginning_of_line = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+
+               container = webkit_dom_range_get_end_container (range, NULL);
+               actual_block = get_parent_block_node_from_child (container);
+
+               tmp_block = webkit_dom_range_get_end_container (beginning_of_line, NULL);
+               if ((tmp_block = get_parent_block_node_from_child (tmp_block))) {
+                       dom_selection_get_coordinates (
+                               document,
+                               &event->before.start.x,
+                               &event->before.start.y,
+                               &event->before.end.x,
+                               &event->before.end.y);
+
+                       /* Create the right content for the history event. */
+                       fragment = webkit_dom_document_create_document_fragment (document);
+                       /* The removed line. */
+                       webkit_dom_node_append_child (
+                               WEBKIT_DOM_NODE (fragment),
+                               webkit_dom_node_clone_node (actual_block, TRUE),
+                               NULL);
+                       /* The following block, but empty. */
+                       webkit_dom_node_append_child (
+                               WEBKIT_DOM_NODE (fragment),
+                               webkit_dom_node_clone_node (tmp_block, FALSE),
+                               NULL);
+                       g_object_set_data (
+                               G_OBJECT (fragment),
+                               "-x-evo-drag-and-drop",
+                               GINT_TO_POINTER (1));
+                       /* It should act as a Delete key press. */
+                       g_object_set_data (G_OBJECT (
+                               fragment),
+                               "-x-evo-delete-key",
+                               GINT_TO_POINTER (1));
+               }
+       }
+
+       event->data.fragment = fragment;
+       e_html_editor_undo_redo_manager_insert_history_event (manager, event);
+
+       /* Selection is ending on the end of the line, check if
+        * there is a space before the selection start. If so, it
+        * will be removed and we need create the history event
+        * for it. */
+       if (end_to_end) {
+               gchar *range_text_start;
+               glong start_offset;
+
+               start_offset = webkit_dom_range_get_start_offset (range_clone, NULL);
+               webkit_dom_range_set_start (
+                       range_clone,
+                       webkit_dom_range_get_start_container (range_clone, NULL),
+                       start_offset > 0 ? start_offset - 1 : 0,
+                       NULL);
+
+               range_text_start = webkit_dom_range_get_text (range_clone);
+               if (g_str_has_prefix (range_text_start, " ") ||
+                   g_str_has_prefix (range_text_start, UNICODE_NBSP))
+                       insert_nbsp_history_event (document, manager, FALSE, x, y);
+
+               g_free (range_text_start);
+       }
+
+       /* WebKit removes the space (if presented) after selection and
+        * we need to create a new history event for it. */
+       if (g_str_has_suffix (range_text, " ") ||
+           g_str_has_suffix (range_text, UNICODE_NBSP))
+               insert_nbsp_history_event (document, manager, TRUE, x, y);
+
+       g_free (range_text);
 
-       /* When text is DnD'ed into the view, WebKit will select it. So let's
-        * collapse it to its end to have the caret after the DnD'ed text. */
-       webkit_dom_dom_selection_collapse_to_end (dom_selection, NULL);
+       /* Restore the selection to original state. */
+       webkit_dom_dom_selection_remove_all_ranges (dom_selection);
+       webkit_dom_dom_selection_add_range (dom_selection, range);
+       g_object_unref (beginning_of_line);
 
-       g_clear_object (&dom_selection);
-       g_clear_object (&dom_window);
+       /* All the things above were about removing the content,
+        * create an AND event to continue later with inserting
+        * the dropped content. */
+       event = g_new0 (EHTMLEditorHistoryEvent, 1);
+       event->type = HISTORY_AND;
+       e_html_editor_undo_redo_manager_insert_history_event (manager, event);
+
+       g_object_unref (dom_selection);
+       g_object_unref (dom_window);
+
+       g_object_unref (range);
+       g_object_unref (range_clone);
+}
 
+void
+dom_clean_after_drag_and_drop (WebKitDOMDocument *document,
+                               EHTMLEditorWebExtension *extension)
+{
+       dom_save_history_for_drop (document, extension);
        dom_check_magic_links (document, extension, FALSE);
-       /* Also force spell check on view. */
-       dom_force_spell_check_in_viewport (document, extension);
 }
diff --git a/web-extensions/composer/e-composer-private-dom-functions.h 
b/web-extensions/composer/e-composer-private-dom-functions.h
index 894d2a0..30c9337 100644
--- a/web-extensions/composer/e-composer-private-dom-functions.h
+++ b/web-extensions/composer/e-composer-private-dom-functions.h
@@ -34,6 +34,8 @@ void          dom_insert_signature            (WebKitDOMDocument *document,
                                                 const gchar *signature_html,
                                                 gboolean top_signature,
                                                 gboolean start_bottom);
+void           dom_save_drag_and_drop_history  (WebKitDOMDocument *document,
+                                                EHTMLEditorWebExtension *extension);
 void           dom_clean_after_drag_and_drop   (WebKitDOMDocument *document,
                                                 EHTMLEditorWebExtension *extension);
 
diff --git a/web-extensions/composer/e-html-editor-undo-redo-manager.c 
b/web-extensions/composer/e-html-editor-undo-redo-manager.c
index 832ba3a..f947a30 100644
--- a/web-extensions/composer/e-html-editor-undo-redo-manager.c
+++ b/web-extensions/composer/e-html-editor-undo-redo-manager.c
@@ -181,25 +181,14 @@ restore_selection_to_history_event_state (WebKitDOMDocument *document,
 static void
 print_node_inner_html (WebKitDOMNode *node)
 {
-       WebKitDOMDocument *document;
-       WebKitDOMElement *div;
        gchar *inner_html;
 
        if (!node) {
                printf ("    none\n");
                return;
        }
-       document = webkit_dom_node_get_owner_document (node);
-       div = webkit_dom_document_create_element (document, "div", NULL);
-       webkit_dom_node_append_child (
-                       WEBKIT_DOM_NODE (div),
-                       webkit_dom_node_clone_node (node, TRUE),
-                       NULL);
-
-       inner_html = webkit_dom_element_get_inner_html (div);
-       remove_node (WEBKIT_DOM_NODE (div));
 
-       printf ("    '%s'\n", inner_html);
+       inner_html = dom_get_node_inner_html (node);
 
        g_free (inner_html);
 }
@@ -743,6 +732,18 @@ undo_delete (WebKitDOMDocument *document,
 
                dom_merge_siblings_if_necessary (document, event->data.fragment);
 
+               /* If undoing drag and drop where the whole line was moved we need
+                * to correct the selection. */
+               if (g_object_get_data (G_OBJECT (event->data.fragment), "-x-evo-drag-and-drop") &&
+                   (element = webkit_dom_document_get_element_by_id (document, 
"-x-evo-selection-end-marker"))) {
+                       WebKitDOMNode *prev_block;
+
+                       prev_block = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element));
+                       if ((prev_block = webkit_dom_node_get_previous_sibling (prev_block)))
+                               webkit_dom_node_append_child (
+                                       prev_block, WEBKIT_DOM_NODE (element), NULL);
+               }
+
                dom_selection_restore (document);
                dom_force_spell_check_in_viewport (document, extension);
        } else {
diff --git a/web-extensions/composer/e-html-editor-view-dom-functions.c 
b/web-extensions/composer/e-html-editor-view-dom-functions.c
index b9c82cd..b774887 100644
--- a/web-extensions/composer/e-html-editor-view-dom-functions.c
+++ b/web-extensions/composer/e-html-editor-view-dom-functions.c
@@ -9570,13 +9570,19 @@ dom_get_caret_position (WebKitDOMDocument *document)
 }
 
 void
-dom_drag_and_drop_end (WebKitDOMDocument *document,
-                       EHTMLEditorWebExtension *extension)
+dom_save_history_for_drop (WebKitDOMDocument *document,
+                          EHTMLEditorWebExtension *extension)
 {
+       EHTMLEditorUndoRedoManager *manager;
+       EHTMLEditorHistoryEvent *event;
        gint ii, length;
-       WebKitDOMDOMWindow *dom_window;
+       WebKitDOMDocumentFragment *fragment;
        WebKitDOMDOMSelection *dom_selection;
+       WebKitDOMDOMWindow *dom_window;
        WebKitDOMNodeList *list;
+       WebKitDOMRange *range;
+
+       manager = e_html_editor_web_extension_get_undo_redo_manager (extension);
 
        /* When the image is DnD inside the view WebKit removes the wrapper that
         * is used for resizing the image, so we have to recreate it again. */
@@ -9604,17 +9610,94 @@ dom_drag_and_drop_end (WebKitDOMDocument *document,
         * lets collapse the selection to have the caret right after the image. */
        dom_window = webkit_dom_document_get_default_view (document);
        dom_selection = webkit_dom_dom_window_get_selection (dom_window);
+
+       range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+
+       /* Remove the last inserted history event as this one was inserted in
+        * body_input_event_cb and is wrong as its type is HISTORY_INPUT. */
+       /* FIXME we could probably disable the HTML input event callback while
+        * doing DnD within the view */
+       /* FIXME WK2 - what if e_html_editor_undo_redo_manager_get_current_history_event() returns NULL? */
+       if (((EHTMLEditorHistoryEvent *) (e_html_editor_undo_redo_manager_get_current_history_event 
(manager)))->type == HISTORY_INPUT)
+               e_html_editor_undo_redo_manager_remove_current_history_event (manager);
+
+       event = g_new0 (EHTMLEditorHistoryEvent, 1);
+       event->type = HISTORY_INSERT_HTML;
+
+       /* Get the dropped content. It's easy as it is selected by WebKit. */
+       fragment = webkit_dom_range_clone_contents (range, NULL);
+       event->data.string.from = NULL;
+       /* Get the HTML content of the dropped content. */
+       event->data.string.to = dom_get_node_inner_html (WEBKIT_DOM_NODE (fragment));
+
+       dom_selection_get_coordinates (
+               document,
+               &event->before.start.x,
+               &event->before.start.y,
+               &event->before.end.x,
+               &event->before.end.y);
+
+       event->before.end.x = event->before.start.x;
+       event->before.end.y = event->before.start.y;
+
        if (length > 0)
                webkit_dom_dom_selection_collapse_to_start (dom_selection, NULL);
        else
                webkit_dom_dom_selection_collapse_to_end (dom_selection, NULL);
 
+       dom_selection_get_coordinates (
+               document,
+               &event->after.start.x,
+               &event->after.start.y,
+               &event->after.end.x,
+               &event->after.end.y);
+
+       e_html_editor_undo_redo_manager_insert_history_event (manager, event);
+
+       if (!e_html_editor_web_extension_get_html_mode (extension)) {
+               WebKitDOMNodeList *list;
+               gint ii, length;
+
+               list = webkit_dom_document_query_selector_all (
+                       document, "span[style^=font-family]", NULL);
+               length = webkit_dom_node_list_get_length (list);
+               if (length > 0)
+                       dom_selection_save (document);
+
+               for (ii = 0; ii < length; ii++) {
+                       WebKitDOMNode *span, *child;
+
+                       span = webkit_dom_node_list_item (list, ii);
+                       while ((child = webkit_dom_node_get_first_child (span)))
+                               webkit_dom_node_insert_before (
+                                       webkit_dom_node_get_parent_node (span),
+                                       child,
+                                       span,
+                                       NULL);
+
+                       remove_node (span);
+                       g_object_unref (span);
+               }
+               g_object_unref (list);
+
+               if (length > 0)
+                       dom_selection_restore (document);
+       }
+
        dom_force_spell_check_in_viewport (document, extension);
 
+       g_object_unref (range);
        g_object_unref (dom_selection);
        g_object_unref (dom_window);
 }
 
+void
+dom_drag_and_drop_end (WebKitDOMDocument *document,
+                       EHTMLEditorWebExtension *extension)
+{
+       dom_save_history_for_drop (document, extension);
+}
+
 static void
 dom_set_link_color_in_document (WebKitDOMDocument *document,
                                const gchar *color,
diff --git a/web-extensions/composer/e-html-editor-view-dom-functions.h 
b/web-extensions/composer/e-html-editor-view-dom-functions.h
index f1e451a..bd968b5 100644
--- a/web-extensions/composer/e-html-editor-view-dom-functions.h
+++ b/web-extensions/composer/e-html-editor-view-dom-functions.h
@@ -211,6 +211,8 @@ WebKitDOMElement *
                                                 WebKitDOMElement *element);
 gint           get_citation_level              (WebKitDOMNode *node,
                                                 gboolean set_plaintext_quoted);
+void           dom_save_history_for_drop       (WebKitDOMDocument *document,
+                                                EHTMLEditorWebExtension *extension);
 
 G_END_DECLS
 
diff --git a/web-extensions/composer/e-html-editor-web-extension.c 
b/web-extensions/composer/e-html-editor-web-extension.c
index ff19560..b611fab 100644
--- a/web-extensions/composer/e-html-editor-web-extension.c
+++ b/web-extensions/composer/e-html-editor-web-extension.c
@@ -630,9 +630,11 @@ static const char introspection_xml[] =
 "      <arg type='b' name='top_signature' direction='in'/>"
 "      <arg type='b' name='start_bottom' direction='in'/>"
 "    </method>"
+"    <method name='DOMSaveDragAndDropHistory'>"
+"      <arg type='t' name='page_id' direction='in'/>"
+"    </method>"
 "    <method name='DOMCleanAfterDragAndDrop'>"
 "      <arg type='t' name='page_id' direction='in'/>"
-"      <arg type='b' name='remove_inserted_uri_on_drop' direction='in'/>"
 "    </method>"
 "<!-- ********************************************************* -->"
 "<!--     Functions that are used in External Editor plugin     -->"
@@ -2326,6 +2328,19 @@ handle_method_call (GDBusConnection *connection,
                dom_insert_signature (document, extension, signature_html, top_signature, start_bottom);
 
                g_dbus_method_invocation_return_value (invocation, NULL);
+       } else if (g_strcmp0 (method_name, "DOMSaveDragAndDropHistory") == 0) {
+               g_variant_get (
+                       parameters, "(t)", &page_id);
+
+               web_page = get_webkit_web_page_or_return_dbus_error (
+                       invocation, web_extension, page_id);
+               if (!web_page)
+                       goto error;
+
+               document = webkit_web_page_get_dom_document (web_page);
+               dom_save_drag_and_drop_history (document, extension);
+
+               g_dbus_method_invocation_return_value (invocation, NULL);
        } else if (g_strcmp0 (method_name, "DOMCleanAfterDragAndDrop") == 0) {
                g_variant_get (
                        parameters, "(t)", &page_id);
diff --git a/web-extensions/e-dom-utils.c b/web-extensions/e-dom-utils.c
index fb70cfb..4019b22 100644
--- a/web-extensions/e-dom-utils.c
+++ b/web-extensions/e-dom-utils.c
@@ -1905,3 +1905,23 @@ get_parent_block_element (WebKitDOMNode *node)
 
        return parent;
 }
+
+gchar *
+dom_get_node_inner_html (WebKitDOMNode *node)
+{
+       gchar *inner_html;
+       WebKitDOMDocument *document;
+       WebKitDOMElement *div;
+
+       document = webkit_dom_node_get_owner_document (node);
+       div = webkit_dom_document_create_element (document, "div", NULL);
+       webkit_dom_node_append_child (
+                       WEBKIT_DOM_NODE (div),
+                       webkit_dom_node_clone_node (node, TRUE),
+                       NULL);
+
+       inner_html = webkit_dom_element_get_inner_html (div);
+       remove_node (WEBKIT_DOM_NODE (div));
+
+       return inner_html;
+}
diff --git a/web-extensions/e-dom-utils.h b/web-extensions/e-dom-utils.h
index 037ce3a..5c65fee 100644
--- a/web-extensions/e-dom-utils.h
+++ b/web-extensions/e-dom-utils.h
@@ -159,6 +159,9 @@ void                merge_list_into_list            (WebKitDOMNode *from,
 void           merge_lists_if_possible         (WebKitDOMNode *list);
 WebKitDOMElement *
                get_parent_block_element        (WebKitDOMNode *node);
+
+gchar *                dom_get_node_inner_html         (WebKitDOMNode *node);
+
 G_END_DECLS
 
 #endif /* E_DOM_UTILS_H */


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