aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomas Popela <tpopela@redhat.com>2014-06-19 21:02:29 +0800
committerTomas Popela <tpopela@redhat.com>2014-06-19 21:23:17 +0800
commit74047473d334c3c5fb87fd37816b22693b7c260f (patch)
tree50667d29b31a1ab01dd5a718238997b83f78a170
parent5524dbf7a2b66907cfa72181bfdeb44e268e5718 (diff)
downloadgsoc2013-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.
-rw-r--r--e-util/e-html-editor-view.c177
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 */
/* &#8203 == 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>&#8203;",
+ "</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 ? "&#8203;" : "");
+
+ 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;