[evolution/wip/tpopela/freeze-fixes: 5/7] Bug 746277 - Typing text in composer destroys primary clipboard content



commit 7b4f64c182b5181d1d6f03e090ad6f69b0fe9cec
Author: Tomas Popela <tpopela redhat com>
Date:   Wed Mar 18 14:04:59 2015 +0100

    Bug 746277 - Typing text in composer destroys primary clipboard content
    
    Rework how the history is saved for input and delete to avoid
    introducing a selection in composer that led to overwriting the primary
    clipboard content.

 e-util/e-html-editor-view.c |  134 ++++++++++++++++++++++++++++++++-----------
 1 files changed, 100 insertions(+), 34 deletions(-)
---
diff --git a/e-util/e-html-editor-view.c b/e-util/e-html-editor-view.c
index 92faea3..4822a8f 100644
--- a/e-util/e-html-editor-view.c
+++ b/e-util/e-html-editor-view.c
@@ -421,6 +421,20 @@ html_editor_view_selection_changed_cb (EHTMLEditorView *view,
        }
 }
 
+static void
+block_selection_changed_callbacks (EHTMLEditorView *view)
+{
+       e_html_editor_selection_block_selection_changed (view->priv->selection);
+       g_signal_handlers_block_by_func (view, html_editor_view_selection_changed_cb, NULL);
+}
+
+static void
+unblock_selection_changed_callbacks (EHTMLEditorView *view)
+{
+       e_html_editor_selection_unblock_selection_changed (view->priv->selection);
+       g_signal_handlers_unblock_by_func (view, html_editor_view_selection_changed_cb, NULL);
+}
+
 static gboolean
 html_editor_view_should_show_delete_interface_for_element (EHTMLEditorView *view,
                                                            WebKitDOMHTMLElement *element)
@@ -494,9 +508,7 @@ e_html_editor_view_force_spell_check_for_current_paragraph (EHTMLEditorView *vie
        /* Block callbacks of selection-changed signal as we don't want to
         * recount all the block format things in EHTMLEditorSelection and here as well
         * when we are moving with caret */
-       g_signal_handlers_block_by_func (
-               view, html_editor_view_selection_changed_cb, NULL);
-       e_html_editor_selection_block_selection_changed (selection);
+       block_selection_changed_callbacks (view);
 
        parent = get_parent_block_element (WEBKIT_DOM_NODE (selection_end_marker));
 
@@ -539,9 +551,7 @@ e_html_editor_view_force_spell_check_for_current_paragraph (EHTMLEditorView *vie
        remove_node (WEBKIT_DOM_NODE (text));
 
        /* Unblock the callbacks */
-       g_signal_handlers_unblock_by_func (
-               view, html_editor_view_selection_changed_cb, NULL);
-       e_html_editor_selection_unblock_selection_changed (selection);
+       unblock_selection_changed_callbacks (view);
 
        e_html_editor_selection_restore (selection);
 }
@@ -682,9 +692,7 @@ refresh_spell_check (EHTMLEditorView *view,
        /* Block callbacks of selection-changed signal as we don't want to
         * recount all the block format things in EHTMLEditorSelection and here as well
         * when we are moving with caret */
-       g_signal_handlers_block_by_func (
-               view, html_editor_view_selection_changed_cb, NULL);
-       e_html_editor_selection_block_selection_changed (selection);
+       block_selection_changed_callbacks (view);
 
        /* Append some text on the end of the body */
        text = webkit_dom_document_create_text_node (document, "-x-evo-end");
@@ -717,9 +725,7 @@ refresh_spell_check (EHTMLEditorView *view,
        remove_node (WEBKIT_DOM_NODE (text));
 
        /* Unblock the callbacks */
-       g_signal_handlers_unblock_by_func (
-               view, html_editor_view_selection_changed_cb, NULL);
-       e_html_editor_selection_unblock_selection_changed (selection);
+       unblock_selection_changed_callbacks (view);
 
        e_html_editor_selection_restore (selection);
 }
@@ -2417,11 +2423,13 @@ static void
 save_history_for_input (EHTMLEditorView *view)
 {
        EHTMLEditorViewHistoryEvent *ev;
+       glong offset;
        WebKitDOMDocument *document;
        WebKitDOMDocumentFragment *fragment;
        WebKitDOMDOMWindow *dom_window;
        WebKitDOMDOMSelection *dom_selection;
-       WebKitDOMRange *range;
+       WebKitDOMRange *range, *range_clone;
+       WebKitDOMNode *start_container;
 
        document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view));
        dom_window = webkit_dom_document_get_default_view (document);
@@ -2433,20 +2441,67 @@ save_history_for_input (EHTMLEditorView *view)
        ev = g_new0 (EHTMLEditorViewHistoryEvent, 1);
        ev->type = HISTORY_INPUT;
 
+       block_selection_changed_callbacks (view);
+
        e_html_editor_selection_get_selection_coordinates (
                view->priv->selection,
                &ev->after.start.x,
                &ev->after.start.y,
                &ev->after.end.x,
                &ev->after.end.y);
-       webkit_dom_dom_selection_modify (dom_selection, "extend", "left", "character");
+
        range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
-       fragment = webkit_dom_range_clone_contents (range, NULL);
+       range_clone = webkit_dom_range_clone_range (range, NULL);
+       offset = webkit_dom_range_get_start_offset (range_clone, NULL);
+       start_container = webkit_dom_range_get_start_container (range_clone, NULL);
+       if (offset > 0)
+               webkit_dom_range_set_start (
+                       range_clone,
+                       start_container,
+                       offset - 1,
+                       NULL);
+       fragment = webkit_dom_range_clone_contents (range_clone, NULL);
        /* We have to specialy handle Return key press */
        if (view->priv->return_key_pressed) {
-               WebKitDOMNode *node;
+               WebKitDOMElement *element_start, *element_end;
+               WebKitDOMNode *parent_start, *parent_end, *node;
+
+               element_start = webkit_dom_document_create_element (document, "span", NULL);
+               webkit_dom_range_surround_contents (range, WEBKIT_DOM_NODE (element_start), NULL);
+               webkit_dom_dom_selection_modify (dom_selection, "move", "left", "character");
+               range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
+               element_end = webkit_dom_document_create_element (document, "span", NULL);
+               webkit_dom_range_surround_contents (range, WEBKIT_DOM_NODE (element_end), NULL);
+
+               parent_start = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element_start));
+               parent_end = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element_end));
+
+               while (!webkit_dom_node_is_same_node (parent_start, parent_end)) {
+                       webkit_dom_node_insert_before (
+                               WEBKIT_DOM_NODE (fragment),
+                               webkit_dom_node_clone_node (parent_start, FALSE),
+                               webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment)),
+                               NULL);
+                       parent_start = webkit_dom_node_get_parent_node (parent_start);
+                       parent_end = webkit_dom_node_get_parent_node (parent_end);
+               }
 
                node = webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment));
+               while (webkit_dom_node_get_next_sibling (node)) {
+                       WebKitDOMNode *last_child;
+
+                       last_child = webkit_dom_node_get_last_child (WEBKIT_DOM_NODE (fragment));
+                       webkit_dom_node_append_child (
+                               webkit_dom_node_get_previous_sibling (last_child),
+                               last_child,
+                               NULL);
+               }
+
+               node = webkit_dom_node_get_last_child (WEBKIT_DOM_NODE (fragment));
+               while (webkit_dom_node_get_last_child (node)) {
+                       node = webkit_dom_node_get_last_child (node);
+               }
+
                webkit_dom_node_append_child (
                        node,
                        WEBKIT_DOM_NODE (
@@ -2463,7 +2518,10 @@ save_history_for_input (EHTMLEditorView *view)
                                create_selection_marker (document, FALSE)),
                        NULL);
 
-               remove_node (webkit_dom_node_get_last_child (WEBKIT_DOM_NODE (fragment)));
+               remove_node (WEBKIT_DOM_NODE (element_start));
+               remove_node (WEBKIT_DOM_NODE (element_end));
+
+               webkit_dom_dom_selection_modify (dom_selection, "move", "right", "character");
        } else {
                webkit_dom_node_append_child (
                        WEBKIT_DOM_NODE (fragment),
@@ -2477,7 +2535,8 @@ save_history_for_input (EHTMLEditorView *view)
                        NULL);
        }
 
-       webkit_dom_dom_selection_modify (dom_selection, "move", "right", "character");
+
+       unblock_selection_changed_callbacks (view);
 
        ev->data.fragment = fragment;
        e_html_editor_view_insert_new_history_event (view, ev);
@@ -3874,36 +3933,41 @@ save_history_for_delete_or_backspace (EHTMLEditorView *view,
        range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
 
        if (webkit_dom_range_get_collapsed (range, NULL)) {
-               WebKitDOMNode *node = webkit_dom_range_get_end_container (range, NULL);
+               WebKitDOMRange *range_clone;
 
-               if (delete_key && !webkit_dom_node_get_next_sibling (node)) {
-                       g_free (ev);
-                       return;
-               }
+               block_selection_changed_callbacks (view);
 
-               if (delete_key)
-                       webkit_dom_dom_selection_modify (dom_selection, "extend", "right", "character");
-               else
-                       webkit_dom_dom_selection_modify (dom_selection, "extend", "left", "character");
-
-               range = webkit_dom_dom_selection_get_range_at (dom_selection, 0, NULL);
-               fragment = webkit_dom_range_clone_contents (range, NULL);
+               range_clone = webkit_dom_range_clone_range (range, NULL);
+               if (delete_key) {
+                       glong offset = webkit_dom_range_get_start_offset (range_clone, NULL);
+                       webkit_dom_range_set_end (
+                               range_clone,
+                               webkit_dom_range_get_end_container (range_clone, NULL),
+                               offset + 1,
+                               NULL);
+               } else {
+                       webkit_dom_range_set_start (
+                               range_clone,
+                               webkit_dom_range_get_start_container (range_clone, NULL),
+                               webkit_dom_range_get_start_offset (range_clone, NULL) - 1,
+                               NULL);
+               }
 
+               fragment = webkit_dom_range_clone_contents (range_clone, NULL);
                if (!webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (fragment))) {
                        g_free (ev);
+                       unblock_selection_changed_callbacks (view);
                        return;
                }
 
                if (delete_key) {
-                       webkit_dom_dom_selection_collapse_to_start (dom_selection, NULL);
-
                        e_html_editor_selection_get_selection_coordinates (
                                selection, &ev->after.start.x, &ev->after.start.y, &ev->after.end.x, 
&ev->after.end.y);
                } else {
+                       webkit_dom_dom_selection_modify (dom_selection, "move", "left", "character");
                        e_html_editor_selection_get_selection_coordinates (
                                selection, &ev->after.start.x, &ev->after.start.y, &ev->after.end.x, 
&ev->after.end.y);
-
-                       webkit_dom_dom_selection_collapse_to_end (dom_selection, NULL);
+                       webkit_dom_dom_selection_modify (dom_selection, "move", "right", "character");
                }
 
                if (!delete_key) {
@@ -3936,6 +4000,8 @@ save_history_for_delete_or_backspace (EHTMLEditorView *view,
                                        create_selection_marker (document, FALSE)),
                                NULL);
                }
+
+               unblock_selection_changed_callbacks (view);
        } else {
                ev->after.start.x = ev->before.start.x;
                ev->after.start.y = ev->before.start.y;


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