diff options
author | Tomas Popela <tpopela@redhat.com> | 2014-06-19 21:02:29 +0800 |
---|---|---|
committer | Tomas Popela <tpopela@redhat.com> | 2014-06-19 21:23:17 +0800 |
commit | 74047473d334c3c5fb87fd37816b22693b7c260f (patch) | |
tree | 50667d29b31a1ab01dd5a718238997b83f78a170 /e-util/e-html-editor-view.c | |
parent | 5524dbf7a2b66907cfa72181bfdeb44e268e5718 (diff) | |
download | gsoc2013-evolution-74047473d334c3c5fb87fd37816b22693b7c260f.tar gsoc2013-evolution-74047473d334c3c5fb87fd37816b22693b7c260f.tar.gz gsoc2013-evolution-74047473d334c3c5fb87fd37816b22693b7c260f.tar.bz2 gsoc2013-evolution-74047473d334c3c5fb87fd37816b22693b7c260f.tar.lz gsoc2013-evolution-74047473d334c3c5fb87fd37816b22693b7c260f.tar.xz gsoc2013-evolution-74047473d334c3c5fb87fd37816b22693b7c260f.tar.zst gsoc2013-evolution-74047473d334c3c5fb87fd37816b22693b7c260f.zip |
Bug 731766 - [webkit-composer] Emoticon cannot be inserted at the end of the email
Rework how the emoticons are inserted into composer. There were certain
situations where the previous version failed from various reasons like
wrongly saved caret position. Together with previous commits
(preventing the selection markers to be saved into body) this change
fixes the insertion of emoticons.
Diffstat (limited to 'e-util/e-html-editor-view.c')
-rw-r--r-- | e-util/e-html-editor-view.c | 177 |
1 files changed, 137 insertions, 40 deletions
diff --git a/e-util/e-html-editor-view.c b/e-util/e-html-editor-view.c index 85555147b5..ba10b1bc13 100644 --- a/e-util/e-html-editor-view.c +++ b/e-util/e-html-editor-view.c @@ -1037,15 +1037,17 @@ emoticon_read_async_cb (GFile *file, EHTMLEditorView *view = load_context->view; EEmoticon *emoticon = load_context->emoticon; GError *error = NULL; - gchar *html, *node_text = NULL, *mime_type; + gboolean misplaced_selection = FALSE, empty = FALSE; + gchar *html, *node_text = NULL, *mime_type, *content; gchar *base64_encoded, *output, *data; const gchar *emoticon_start; GFileInputStream *input_stream; GOutputStream *output_stream; gssize size; WebKitDOMDocument *document; - WebKitDOMElement *span, *caret_position; - WebKitDOMNode *node; + WebKitDOMElement *span, *selection_start_marker, *selection_end_marker; + WebKitDOMNode *node, *insert_before, *prev_sibling, *next_sibling; + WebKitDOMNode *selection_end_marker_parent; WebKitDOMRange *range; input_stream = g_file_read_finish (file, result, &error); @@ -1060,48 +1062,98 @@ emoticon_read_async_cb (GFile *file, if (error || (size == -1)) goto out; - caret_position = e_html_editor_selection_save_caret_position ( - e_html_editor_view_get_selection (view)); - - if (caret_position) { - WebKitDOMNode *parent; + e_html_editor_selection_save (e_html_editor_view_get_selection (view)); - parent = webkit_dom_node_get_parent_node ( - WEBKIT_DOM_NODE (caret_position)); - - /* Situation when caret is restored in body and not in paragraph */ - if (WEBKIT_DOM_IS_HTML_BODY_ELEMENT (parent)) { - caret_position = WEBKIT_DOM_ELEMENT ( - webkit_dom_node_remove_child ( - WEBKIT_DOM_NODE (parent), - WEBKIT_DOM_NODE (caret_position), - NULL)); + document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view)); + selection_start_marker = webkit_dom_document_get_element_by_id ( + document, "-x-evo-selection-start-marker"); + selection_end_marker = webkit_dom_document_get_element_by_id ( + document, "-x-evo-selection-end-marker"); + + /* If the selection was not saved, move it into the first child of body */ + if (!selection_start_marker || !selection_end_marker) { + WebKitDOMHTMLElement *body; + + body = webkit_dom_document_get_body (document); + selection_start_marker = webkit_dom_document_create_element ( + document, "SPAN", NULL); + webkit_dom_element_set_id ( + selection_start_marker, "-x-evo-selection-start-marker"); + webkit_dom_node_insert_before ( + webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body)), + WEBKIT_DOM_NODE (selection_start_marker), + webkit_dom_node_get_first_child ( + webkit_dom_node_get_first_child ( + WEBKIT_DOM_NODE (body))), + NULL); + selection_end_marker = webkit_dom_document_create_element ( + document, "SPAN", NULL); + webkit_dom_element_set_id ( + selection_end_marker, "-x-evo-selection-end-marker"); + webkit_dom_node_insert_before ( + webkit_dom_node_get_first_child (WEBKIT_DOM_NODE (body)), + WEBKIT_DOM_NODE (selection_end_marker), + webkit_dom_node_get_first_child ( + webkit_dom_node_get_first_child ( + WEBKIT_DOM_NODE (body))), + NULL); + } - caret_position = WEBKIT_DOM_ELEMENT ( - webkit_dom_node_insert_before ( - webkit_dom_node_get_first_child ( - WEBKIT_DOM_NODE (parent)), - WEBKIT_DOM_NODE (caret_position), - webkit_dom_node_get_first_child ( - webkit_dom_node_get_first_child ( - WEBKIT_DOM_NODE (parent))), - NULL)); - } + /* Sometimes selection end marker is in body. Move it into next sibling */ + selection_end_marker_parent = webkit_dom_node_get_parent_node ( + WEBKIT_DOM_NODE (selection_end_marker)); + if (WEBKIT_DOM_IS_HTML_BODY_ELEMENT (selection_end_marker_parent)) { + webkit_dom_node_insert_before ( + webkit_dom_node_get_parent_node ( + WEBKIT_DOM_NODE (selection_start_marker)), + WEBKIT_DOM_NODE (selection_end_marker), + WEBKIT_DOM_NODE (selection_start_marker), + NULL); } + selection_end_marker_parent = webkit_dom_node_get_parent_node ( + WEBKIT_DOM_NODE (selection_end_marker)); + + /* Determine before what node we have to insert the smiley */ + insert_before = WEBKIT_DOM_NODE (selection_start_marker); + prev_sibling = webkit_dom_node_get_previous_sibling ( + WEBKIT_DOM_NODE (selection_start_marker)); + if (prev_sibling) { + if (webkit_dom_node_is_same_node ( + prev_sibling, WEBKIT_DOM_NODE (selection_end_marker))) { + insert_before = WEBKIT_DOM_NODE (selection_end_marker); + } else { + prev_sibling = webkit_dom_node_get_previous_sibling (prev_sibling); + if (prev_sibling && + webkit_dom_node_is_same_node ( + prev_sibling, WEBKIT_DOM_NODE (selection_end_marker))) { + insert_before = WEBKIT_DOM_NODE (selection_end_marker); + } + } + } else + insert_before = WEBKIT_DOM_NODE (selection_start_marker); + + /* Look if selection is misplaced - that means that the selection was + * restored before the previously inserted smiley in situations when we + * are writing more smileys in a row */ + next_sibling = webkit_dom_node_get_next_sibling (WEBKIT_DOM_NODE (selection_end_marker)); + if (next_sibling && WEBKIT_DOM_IS_ELEMENT (next_sibling)) + if (element_has_class (WEBKIT_DOM_ELEMENT (next_sibling), "-x-evo-smiley-wrapper")) + misplaced_selection = TRUE; mime_type = g_content_type_get_mime_type (load_context->content_type); - document = webkit_web_view_get_dom_document (WEBKIT_WEB_VIEW (view)); range = html_editor_view_get_dom_range (view); node = webkit_dom_range_get_end_container (range, NULL); if (WEBKIT_DOM_IS_TEXT (node)) node_text = webkit_dom_text_get_whole_text (WEBKIT_DOM_TEXT (node)); - span = webkit_dom_document_create_element (document, "SPAN", NULL); data = g_memory_output_stream_get_data (G_MEMORY_OUTPUT_STREAM (output_stream)); - base64_encoded = g_base64_encode ((const guchar *) data, size); output = g_strconcat ("data:", mime_type, ";base64,", base64_encoded, NULL); + content = webkit_dom_node_get_text_content (selection_end_marker_parent); + empty = !*content || (g_strcmp0 (content, UNICODE_ZERO_WIDTH_SPACE) == 0); + g_free (content); + /* Insert span with image representation and another one with text * represetation and hide/show them dependant on active composer mode */ /* ​ == UNICODE_ZERO_WIDTH_SPACE */ @@ -1110,17 +1162,39 @@ emoticon_read_async_cb (GFile *file, "<img src=\"%s\" alt=\"%s\" x-evo-smiley=\"%s\" " "class=\"-x-evo-smiley-img\" data-inline data-name=\"%s\"/>" "<span class=\"-x-evo-smiley-text\" style=\"display: none;\">%s" - "</span></span>​", + "</span></span>%s", output, emoticon ? emoticon->text_face : "", emoticon->icon_name, - load_context->name, emoticon ? emoticon->text_face : ""); + load_context->name, emoticon ? emoticon->text_face : "", + empty ? "​" : ""); + + span = webkit_dom_document_create_element (document, "SPAN", NULL); - span = WEBKIT_DOM_ELEMENT ( + if (misplaced_selection) { + /* Insert smiley and selection markers after it */ webkit_dom_node_insert_before ( - webkit_dom_node_get_parent_node ( - WEBKIT_DOM_NODE (caret_position)), - WEBKIT_DOM_NODE (span), - WEBKIT_DOM_NODE (caret_position), - NULL)); + webkit_dom_node_get_parent_node (insert_before), + WEBKIT_DOM_NODE (selection_start_marker), + webkit_dom_node_get_next_sibling (next_sibling), + NULL); + webkit_dom_node_insert_before ( + webkit_dom_node_get_parent_node (insert_before), + WEBKIT_DOM_NODE (selection_end_marker), + webkit_dom_node_get_next_sibling (next_sibling), + NULL); + span = WEBKIT_DOM_ELEMENT ( + webkit_dom_node_insert_before ( + webkit_dom_node_get_parent_node (insert_before), + WEBKIT_DOM_NODE (span), + webkit_dom_node_get_next_sibling (next_sibling), + NULL)); + } else { + span = WEBKIT_DOM_ELEMENT ( + webkit_dom_node_insert_before ( + webkit_dom_node_get_parent_node (insert_before), + WEBKIT_DOM_NODE (span), + insert_before, + NULL)); + } webkit_dom_html_element_set_outer_html ( WEBKIT_DOM_HTML_ELEMENT (span), html, NULL); @@ -1137,7 +1211,7 @@ emoticon_read_async_cb (GFile *file, } } - e_html_editor_selection_restore_caret_position ( + e_html_editor_selection_restore ( e_html_editor_view_get_selection (view)); e_html_editor_view_set_changed (view, TRUE); @@ -1773,6 +1847,27 @@ html_editor_view_key_press_event (GtkWidget *widget, } static void +fix_paragraph_structure_after_pressing_enter_after_smiley (EHTMLEditorSelection *selection, + WebKitDOMDocument *document) +{ + WebKitDOMElement *element; + + element = webkit_dom_document_query_selector ( + document, "span.-x-evo-smiley-wrapper > br", NULL); + + if (element) { + WebKitDOMNode *parent; + + parent = webkit_dom_node_get_parent_node (WEBKIT_DOM_NODE (element)); + webkit_dom_html_element_set_inner_html ( + WEBKIT_DOM_HTML_ELEMENT ( + webkit_dom_node_get_parent_node (parent)), + UNICODE_ZERO_WIDTH_SPACE, + NULL); + } +} + +static void mark_node_as_paragraph_after_ending_list (EHTMLEditorSelection *selection, WebKitDOMDocument *document) { @@ -1855,6 +1950,8 @@ html_editor_view_key_release_event (GtkWidget *widget, if (is_return_key (event) || (event->keyval == GDK_KEY_space)) { html_editor_view_check_magic_links (view, range, FALSE, event); mark_node_as_paragraph_after_ending_list (selection, document); + if (view->priv->html_mode) + fix_paragraph_structure_after_pressing_enter_after_smiley (selection, document); } else { WebKitDOMNode *node; |