summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAli Alzyod <ali198724@gmail.com>2019-09-05 14:52:51 +0900
committerWooHyun Jung <wh0705.jung@samsung.com>2019-09-05 14:52:51 +0900
commit7a05d8d76997399bb55893d4b456b24e65a223cc (patch)
tree8a52ec05e312f0189608ce7134254a86cd62440d
parent8dcd638829ce0089f969bd7f6914683cb747b624 (diff)
elm_entry: handle cursor delete/backspace with clusters consist of one or multible glyphs
Summary: Cluster consist of one glyph, expected to be removed on backspace or delete key. Cluster consist of multible glyph, expectd to remove part of on backspace or delete key. This is behaviour founded in Android. (our current way of handling similar to Qt) **New Behaviour** {F3750386} **Old Behaviour** {F3750387} Test Plan: Auto Testing is challenging because there are no easy way to emulate keyboard down on elm_entry ``` #include <Elementary.h> EAPI_MAIN int elm_main(int argc, char **argv) { Evas_Object *win,*box,*entry; elm_policy_set(ELM_POLICY_QUIT, ELM_POLICY_QUIT_LAST_WINDOW_CLOSED); win = elm_win_util_standard_add("", ""); elm_win_autodel_set(win, EINA_TRUE); box = elm_box_add(win); entry = elm_entry_add(box); evas_object_size_hint_weight_set(box,EVAS_HINT_EXPAND,EVAS_HINT_EXPAND); evas_object_size_hint_align_set(box,EVAS_HINT_FILL,EVAS_HINT_FILL); elm_entry_entry_set(entry,"<font=NotoColorEmoji wrap=mixed >🇧🇬อั🇧🇬อั&#x1F600;&#x1F600;&#x1F600;&#x1F600;&#x1F600;อั</font>"); evas_object_size_hint_weight_set(entry,EVAS_HINT_EXPAND,0.9); evas_object_size_hint_align_set(entry,EVAS_HINT_FILL,EVAS_HINT_FILL); evas_object_show(entry); evas_object_show(box); elm_box_pack_end(box,entry); elm_win_resize_object_add(win,box); evas_object_resize(win,320,480); evas_object_size_hint_weight_set(entry,EVAS_HINT_EXPAND,0.1); evas_object_size_hint_align_set(entry,EVAS_HINT_FILL,EVAS_HINT_FILL); evas_object_show(win); elm_run(); return 0; } ELM_MAIN() ``` Reviewers: tasn, woohyun, bowonryu Subscribers: cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D9628
-rw-r--r--src/lib/edje/edje_entry.c52
-rw-r--r--src/lib/evas/Evas_Internal.h11
-rw-r--r--src/lib/evas/canvas/evas_object_textblock.c76
3 files changed, 128 insertions, 11 deletions
diff --git a/src/lib/edje/edje_entry.c b/src/lib/edje/edje_entry.c
index 2363c4b2d3..a15bd64678 100644
--- a/src/lib/edje/edje_entry.c
+++ b/src/lib/edje/edje_entry.c
@@ -1600,11 +1600,23 @@ static void
1600_delete_emit(Edje *ed, Evas_Textblock_Cursor *c, Entry *en, size_t pos, 1600_delete_emit(Edje *ed, Evas_Textblock_Cursor *c, Entry *en, size_t pos,
1601 Eina_Bool backspace) 1601 Eina_Bool backspace)
1602{ 1602{
1603 if (!evas_textblock_cursor_char_next(c)) 1603
1604 if (backspace)
1604 { 1605 {
1605 return; 1606 if (!evas_textblock_cursor_char_prev(c))
1607 {
1608 return;
1609 }
1610 evas_textblock_cursor_char_next(c);
1611 }
1612 else
1613 {
1614 if (!evas_textblock_cursor_char_next(c))
1615 {
1616 return;
1617 }
1618 evas_textblock_cursor_char_prev(c);
1606 } 1619 }
1607 evas_textblock_cursor_char_prev(c);
1608 1620
1609 Edje_Entry_Change_Info *info = calloc(1, sizeof(*info)); 1621 Edje_Entry_Change_Info *info = calloc(1, sizeof(*info));
1610 if (!info) 1622 if (!info)
@@ -1617,16 +1629,40 @@ _delete_emit(Edje *ed, Evas_Textblock_Cursor *c, Entry *en, size_t pos,
1617 info->insert = EINA_FALSE; 1629 info->insert = EINA_FALSE;
1618 if (backspace) 1630 if (backspace)
1619 { 1631 {
1620 info->change.del.start = pos - 1; 1632
1633 Evas_Textblock_Cursor *cc = evas_object_textblock_cursor_new(en->rp->object);
1634 evas_textblock_cursor_copy(c, cc);
1635 Eina_Bool remove_cluster = evas_textblock_cursor_at_cluster_as_single_glyph(cc,EINA_FALSE);
1636 if (remove_cluster)
1637 {
1638 evas_textblock_cursor_cluster_prev(cc);
1639 }
1640 else
1641 {
1642 evas_textblock_cursor_char_prev(cc);
1643 }
1644
1645 info->change.del.start = evas_textblock_cursor_pos_get(cc);
1621 info->change.del.end = pos; 1646 info->change.del.end = pos;
1622 tmp = evas_textblock_cursor_content_get(c); 1647
1623 evas_textblock_cursor_char_delete(c); 1648 tmp = evas_textblock_cursor_range_text_get(c, cc, EVAS_TEXTBLOCK_TEXT_MARKUP);
1649 evas_textblock_cursor_range_delete(c, cc);
1650 evas_textblock_cursor_free(cc);
1624 } 1651 }
1625 else 1652 else
1626 { 1653 {
1627 Evas_Textblock_Cursor *cc = evas_object_textblock_cursor_new(en->rp->object); 1654 Evas_Textblock_Cursor *cc = evas_object_textblock_cursor_new(en->rp->object);
1628 evas_textblock_cursor_copy(c, cc); 1655 evas_textblock_cursor_copy(c, cc);
1629 evas_textblock_cursor_cluster_next(cc); 1656
1657 Eina_Bool remove_cluster = evas_textblock_cursor_at_cluster_as_single_glyph(cc,EINA_TRUE);
1658 if (remove_cluster)
1659 {
1660 evas_textblock_cursor_cluster_next(cc);
1661 }
1662 else
1663 {
1664 evas_textblock_cursor_char_next(cc);
1665 }
1630 1666
1631 info->change.del.start = evas_textblock_cursor_pos_get(cc); 1667 info->change.del.start = evas_textblock_cursor_pos_get(cc);
1632 info->change.del.end = pos; 1668 info->change.del.end = pos;
@@ -1954,7 +1990,7 @@ _edje_key_down_cb(void *data, Evas *e EINA_UNUSED, Evas_Object *obj EINA_UNUSED,
1954 } 1990 }
1955 else 1991 else
1956 { 1992 {
1957 if (evas_textblock_cursor_char_prev(en->cursor)) 1993 //if (evas_textblock_cursor_char_prev(en->cursor))
1958 { 1994 {
1959 _delete_emit(ed, en->cursor, en, old_cur_pos, EINA_TRUE); 1995 _delete_emit(ed, en->cursor, en, old_cur_pos, EINA_TRUE);
1960 } 1996 }
diff --git a/src/lib/evas/Evas_Internal.h b/src/lib/evas/Evas_Internal.h
index 2958977275..15e4ed1e80 100644
--- a/src/lib/evas/Evas_Internal.h
+++ b/src/lib/evas/Evas_Internal.h
@@ -148,6 +148,17 @@ EWAPI extern const Efl_Event_Description _EFL_ANIMATION_PLAYER_EVENT_PRE_STARTED
148#define EFL_ANIMATION_PLAYER_EVENT_PRE_STARTED (&(_EFL_ANIMATION_PLAYER_EVENT_PRE_STARTED)) 148#define EFL_ANIMATION_PLAYER_EVENT_PRE_STARTED (&(_EFL_ANIMATION_PLAYER_EVENT_PRE_STARTED))
149/* Efl.Animation.Player END */ 149/* Efl.Animation.Player END */
150 150
151
152
153/*TextBlock Internal function*/
154/**
155 * Check if cursor is at cluster with one glyph (replace codepoints with new codepoint).
156 *
157 * @param cur the cursor.
158 * @param forward if Eina_True check cluster after cusror position, else before cursor position.
159 */
160EAPI Eina_Bool evas_textblock_cursor_at_cluster_as_single_glyph(Evas_Textblock_Cursor *cur,Eina_Bool forward);
161
151#ifdef __cplusplus 162#ifdef __cplusplus
152} 163}
153#endif 164#endif
diff --git a/src/lib/evas/canvas/evas_object_textblock.c b/src/lib/evas/canvas/evas_object_textblock.c
index 5f8ae177fc..90561f4f90 100644
--- a/src/lib/evas/canvas/evas_object_textblock.c
+++ b/src/lib/evas/canvas/evas_object_textblock.c
@@ -9662,7 +9662,7 @@ _evas_textblock_grapheme_breaks_new(Evas_Object_Textblock_Item *it, size_t len)
9662} 9662}
9663 9663
9664static size_t 9664static size_t
9665_evas_textblock_cursor_cluster_pos_get(Evas_Textblock_Cursor *cur, Eina_Bool inc) 9665_evas_textblock_cursor_cluster_pos_get(Evas_Textblock_Cursor *cur, Eina_Bool inc, Eina_Bool *is_single_glyph)
9666{ 9666{
9667 Evas_Object_Textblock_Paragraph *par; 9667 Evas_Object_Textblock_Paragraph *par;
9668 Efl_Canvas_Text_Data *o; 9668 Efl_Canvas_Text_Data *o;
@@ -9728,6 +9728,64 @@ _evas_textblock_cursor_cluster_pos_get(Evas_Textblock_Cursor *cur, Eina_Bool inc
9728 9728
9729 free(grapheme_breaks); 9729 free(grapheme_breaks);
9730 } 9730 }
9731
9732 if (is_single_glyph)
9733 {
9734 Evas_Object_Textblock_Text_Item *ti = _ITEM_TEXT(last_it);
9735 Evas_Text_Props_Info *info = ti->text_props.info;
9736 int it_index = ((inc) ? cur->pos : ret) - last_it->text_pos;
9737
9738 Evas_Font_OT_Info ot;
9739 if (ti->text_props.len != ti->text_props.text_len)/*if code point count same as glyph count skip it*/
9740 {
9741 Evas_BiDi_Direction itdir = ti->text_props.bidi_dir;
9742 int i = 0;
9743 if (itdir == EFL_TEXT_BIDIRECTIONAL_TYPE_RTL)
9744 {
9745 for (i = ti->text_props.len-1 ; i >= 0; i--)
9746 {
9747 ot = info->ot[i];
9748 if (ot.source_cluster >= (size_t)it_index)
9749 break;
9750 }
9751 if (i <= 0)
9752 {
9753 if (ti->text_props.text_len - ot.source_cluster >= 2)
9754 *is_single_glyph = EINA_TRUE;
9755 }
9756 else
9757 {
9758 Evas_Font_OT_Info ot_next = info->ot[i - 1];
9759 if (ot_next.source_cluster - ot.source_cluster >= 2)
9760 *is_single_glyph = EINA_TRUE;
9761 }
9762 }
9763 else
9764 {
9765 for (i = 0; i < (int) ti->text_props.len; i++)
9766 {
9767 ot = info->ot[i];
9768 if ((int)ot.source_cluster >= it_index)
9769 break;
9770 }
9771 if ((i + 1) >= (int) ti->text_props.len)
9772 {
9773 if (ti->text_props.text_len - ot.source_cluster >= 2)
9774 *is_single_glyph = EINA_TRUE;
9775 }
9776 else
9777 {
9778 Evas_Font_OT_Info ot_next = info->ot[i + 1];
9779 if (ot_next.source_cluster - ot.source_cluster >= 2)
9780 *is_single_glyph = EINA_TRUE;
9781 }
9782 }
9783 }
9784 else
9785 {
9786 is_single_glyph = EINA_FALSE;
9787 }
9788 }
9731 } 9789 }
9732 } 9790 }
9733 } 9791 }
@@ -9735,6 +9793,18 @@ _evas_textblock_cursor_cluster_pos_get(Evas_Textblock_Cursor *cur, Eina_Bool inc
9735 return ret; 9793 return ret;
9736} 9794}
9737 9795
9796EAPI Eina_Bool evas_textblock_cursor_at_cluster_as_single_glyph(Evas_Textblock_Cursor *cur,Eina_Bool forward)
9797{
9798 Eina_Bool is_single_glyph = EINA_FALSE;
9799 size_t ret = _evas_textblock_cursor_cluster_pos_get(cur, forward, &is_single_glyph);
9800
9801 if ((abs(ret-cur->pos) > 1) && is_single_glyph)
9802 {
9803 return EINA_TRUE;
9804 }
9805 return EINA_FALSE;
9806}
9807
9738static Eina_Bool 9808static Eina_Bool
9739_evas_textblock_cursor_next(Evas_Textblock_Cursor *cur, Eina_Bool per_cluster) 9809_evas_textblock_cursor_next(Evas_Textblock_Cursor *cur, Eina_Bool per_cluster)
9740{ 9810{
@@ -9754,7 +9824,7 @@ _evas_textblock_cursor_next(Evas_Textblock_Cursor *cur, Eina_Bool per_cluster)
9754 if (text[ind]) 9824 if (text[ind])
9755 { 9825 {
9756 if (per_cluster) 9826 if (per_cluster)
9757 ind = _evas_textblock_cursor_cluster_pos_get(cur, EINA_TRUE); 9827 ind = _evas_textblock_cursor_cluster_pos_get(cur, EINA_TRUE, NULL);
9758 9828
9759 if (ind <= (int)cur->pos) 9829 if (ind <= (int)cur->pos)
9760 ind = cur->pos + 1; 9830 ind = cur->pos + 1;
@@ -9801,7 +9871,7 @@ _evas_textblock_cursor_prev(Evas_Textblock_Cursor *cur, Eina_Bool per_cluster)
9801 { 9871 {
9802 if (per_cluster) 9872 if (per_cluster)
9803 { 9873 {
9804 size_t ret = _evas_textblock_cursor_cluster_pos_get(cur, EINA_FALSE); 9874 size_t ret = _evas_textblock_cursor_cluster_pos_get(cur, EINA_FALSE, NULL);
9805 9875
9806 if (ret != cur->pos) 9876 if (ret != cur->pos)
9807 { 9877 {