Commit 4357544d authored by Tomas Popela's avatar Tomas Popela

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.
parent a4b0c91a
......@@ -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 (parent_start && parent_end && !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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment