From 4efaebfc702c83b128abefa5e4896e37838adedc Mon Sep 17 00:00:00 2001 From: WooHyun Jung Date: Fri, 13 Dec 2019 10:33:00 +0900 Subject: [PATCH 01/19] efl_ui_internal_text_interactive: prevent from freed memory accessing If node_format_remove_pair frees node, then next for loop can lead invalid memory accessing. This patch prevents from that case by keeping the next node before freeing. --- .../elementary/efl_ui_internal_text_interactive.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/lib/elementary/efl_ui_internal_text_interactive.c b/src/lib/elementary/efl_ui_internal_text_interactive.c index 017f2a884b..a0bbba6469 100644 --- a/src/lib/elementary/efl_ui_internal_text_interactive.c +++ b/src/lib/elementary/efl_ui_internal_text_interactive.c @@ -158,21 +158,25 @@ Eina_Bool _entry_hide_visible_password(Eo *obj) { Eina_Bool b_ret = EINA_FALSE; - const Evas_Object_Textblock_Node_Format *node; + const Evas_Object_Textblock_Node_Format *node, *node_next; node = evas_textblock_node_format_first_get(obj); - for (; node; node = evas_textblock_node_format_next_get(node)) + + if (!node) return EINA_FALSE; + + do { + node_next = evas_textblock_node_format_next_get(node); const char *text = evas_textblock_node_format_text_get(node); if (text) { if (!strcmp(text, "+ password=off")) { - evas_textblock_node_format_remove_pair(obj, - (Evas_Object_Textblock_Node_Format *)node); + evas_textblock_node_format_remove_pair(obj, (Evas_Object_Textblock_Node_Format *)node); b_ret = EINA_TRUE; } } - } + node = node_next; + } while (node); return b_ret; } From 181ec112f6cc577c4efc7f7a5550a186bf97c9d3 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Fri, 13 Dec 2019 11:52:15 +0900 Subject: [PATCH 02/19] evas vg: fix memory corruption for user entry. Container must have a set parent after construction. efl_add_ref() with a parent won't work this case because container needs some jobs in overriding parent_set() after proper intialization. --- src/lib/evas/canvas/efl_canvas_vg_object.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/lib/evas/canvas/efl_canvas_vg_object.c b/src/lib/evas/canvas/efl_canvas_vg_object.c index 4b6d5221a7..740cfacc6c 100644 --- a/src/lib/evas/canvas/efl_canvas_vg_object.c +++ b/src/lib/evas/canvas/efl_canvas_vg_object.c @@ -369,7 +369,7 @@ _efl_canvas_vg_object_efl_object_constructor(Eo *eo_obj, Efl_Canvas_Vg_Object_Da /* default root node */ pd->obj = obj; - pd->root = efl_add_ref(EFL_CANVAS_VG_CONTAINER_CLASS, eo_obj); + pd->root = efl_add_ref(EFL_CANVAS_VG_CONTAINER_CLASS, NULL); eina_array_step_set(&pd->cleanup, sizeof(pd->cleanup), 8); @@ -381,6 +381,12 @@ _efl_canvas_vg_object_efl_object_finalize(Eo *obj, Efl_Canvas_Vg_Object_Data *pd { Evas *e = evas_object_evas_get(obj); + /* Container must have a set parent after construction. + efl_add_ref() with a parent won't work this case + because container needs some jobs in overriding parent_set() + after proper intialization. */ + efl_parent_set(pd->root, obj); + // TODO: If we start to have to many Evas_Object_VG per canvas, it may be nice // to actually have one event per canvas and one array per canvas to. efl_event_callback_add(e, EFL_CANVAS_SCENE_EVENT_RENDER_POST, _cleanup_reference, pd); From 3372a701d301fef9b1d033b97df0f38de130456f Mon Sep 17 00:00:00 2001 From: Ali Alzyod Date: Fri, 13 Dec 2019 15:10:32 +0900 Subject: [PATCH 03/19] efl_canvas_text: event emitting Summary: 1- Emitting changed event when adding text using cursors. 2- remove attribute,changed event since it is not used now 3- Emitting layout,finished event when finish layouting Reviewers: woohyun, cedric, bu5hm4n Reviewed By: cedric Subscribers: bu5hm4n, cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D10834 --- src/lib/evas/canvas/efl_canvas_textblock.eo | 1 - src/lib/evas/canvas/evas_object_textblock.c | 37 +++++++++++++++++---- src/tests/evas/evas_test_textblock.c | 15 +++++++++ 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/lib/evas/canvas/efl_canvas_textblock.eo b/src/lib/evas/canvas/efl_canvas_textblock.eo index 5d38ecfe6c..2c00967374 100644 --- a/src/lib/evas/canvas/efl_canvas_textblock.eo +++ b/src/lib/evas/canvas/efl_canvas_textblock.eo @@ -558,7 +558,6 @@ class @beta Efl.Canvas.Textblock extends Efl.Canvas.Object implements Efl.Text, } events { changed: void; [[Called when canvas text changed ]] - attributes,changed: void; [[Called when attributes change]] layout,finished: void; [[Called when the object has been layed out]] style_insets,changed: void; [[Called when the property @.style_insets changed.]] } diff --git a/src/lib/evas/canvas/evas_object_textblock.c b/src/lib/evas/canvas/evas_object_textblock.c index 019af5382d..33458fea98 100644 --- a/src/lib/evas/canvas/evas_object_textblock.c +++ b/src/lib/evas/canvas/evas_object_textblock.c @@ -7330,6 +7330,10 @@ _layout_done(Ctxt *c, Evas_Coord *w_ret, Evas_Coord *h_ret) c->o->obstacle_changed = EINA_FALSE; } + else + { + efl_event_callback_call(c->obj, EFL_CANVAS_TEXTBLOCK_EVENT_LAYOUT_FINISHED, NULL); + } } static Eina_Bool @@ -8510,7 +8514,6 @@ _efl_canvas_textblock_efl_text_markup_markup_set(Eo *eo_obj, Efl_Canvas_Textbloc { ASYNC_BLOCK; _evas_object_textblock_text_markup_set(eo_obj, o, text); - efl_event_callback_call(eo_obj, EFL_CANVAS_TEXTBLOCK_EVENT_CHANGED, NULL); } static void @@ -8525,6 +8528,7 @@ _evas_object_textblock_text_markup_prepend(Eo *eo_obj, /* Stop calls for _evas_textblock_changed for each cursor_text_append or cursor_format_append * this should be done once, when markup_prepend finished */ o->pause_change = EINA_TRUE; + if (text) { char *s, *p; @@ -8657,6 +8661,7 @@ _evas_object_textblock_text_markup_prepend(Eo *eo_obj, p++; } } + o->pause_change = EINA_FALSE; _evas_textblock_changed(o, eo_obj); } @@ -11377,7 +11382,7 @@ _evas_textblock_changed(Efl_Canvas_Textblock_Data *o, Evas_Object *eo_obj) If format changed we need to refit content again. If content already fitting then ignore fitting (fitting cause fall to this callback) */ - if (!fit_is_fitting(eo_obj)) + if (!fit_is_fitting(eo_obj) && o->fit_content_config.options != TEXTBLOCK_FIT_MODE_NONE) { fit_cache_clear(&o->fit_content_config, FIT_CACHE_ALL); fit_text_block(eo_obj); @@ -11406,6 +11411,7 @@ _evas_textblock_cursor_text_append(Efl_Text_Cursor_Handle *cur, const char *_tex int len = 0; if (!cur) return 0; + if (!_text || !(*_text)) return 0; Evas_Object_Protected_Data *obj = efl_data_scope_get(cur->obj, EFL_CANVAS_OBJECT_CLASS); evas_object_async_block(obj); text = eina_unicode_utf8_to_unicode(_text, &len); @@ -11465,7 +11471,10 @@ _evas_textblock_cursor_text_append(Efl_Text_Cursor_Handle *cur, const char *_tex _evas_textblock_cursors_update_offset(cur, cur->node, cur->pos, len); if (!o->pause_change) - _evas_textblock_changed(o, cur->obj); + { + _evas_textblock_changed(o, cur->obj); + efl_event_callback_call(cur->obj, EFL_CANVAS_TEXTBLOCK_EVENT_CHANGED, NULL); + } n->dirty = EINA_TRUE; free(text); @@ -15654,7 +15663,7 @@ void fit_style_update(Evas_Object *object, int i_font_size, Eina_Bool disable_el } } - _canvas_text_format_changed(object,o); + _canvas_text_format_changed(object,o); } static void @@ -15806,12 +15815,28 @@ _efl_canvas_textblock_efl_text_text_set(Eo *eo_obj, Efl_Canvas_Textblock_Data *o const char *text) { ASYNC_BLOCK; + const char *old_txt = efl_text_get(eo_obj); + Eina_Bool was_empty = (!old_txt || !(*old_txt)); + + // Nothing to do + if (was_empty && (!text || !(*text))) + return; + + /* + * Reduce changed events to one time emit only, in the appending phase + */ + efl_event_freeze(eo_obj); evas_object_textblock_text_markup_set(eo_obj, ""); - _cursor_text_append(o->cursor, text); + efl_event_thaw(eo_obj); + + if (text && *text) + _cursor_text_append(o->cursor, text); + else if(!was_empty) + efl_event_callback_call(eo_obj, EFL_CANVAS_TEXTBLOCK_EVENT_CHANGED, NULL); + if (eo_obj) { _evas_textblock_changed(o, eo_obj); - efl_event_callback_call(eo_obj, EFL_CANVAS_TEXTBLOCK_EVENT_CHANGED, NULL); } } diff --git a/src/tests/evas/evas_test_textblock.c b/src/tests/evas/evas_test_textblock.c index 1a75153dd9..16fd38f437 100644 --- a/src/tests/evas/evas_test_textblock.c +++ b/src/tests/evas/evas_test_textblock.c @@ -4472,11 +4472,20 @@ EFL_START_TEST(efl_text) } EFL_END_TEST +static void +_increment_int_changed(void *data EINA_UNUSED, const Efl_Event *ev EINA_UNUSED) +{ + int *value = data; + (*value)++; +} + EFL_START_TEST(efl_canvas_textblock_cursor) { START_EFL_CANVAS_TEXTBLOCK_TEST(); int pos; + int changed_emit = 0; + efl_event_callback_add(txt, EFL_CANVAS_TEXTBLOCK_EVENT_CHANGED, _increment_int_changed, &changed_emit); const char *buf = "abcdefghij"; efl_text_set(txt, buf); fail_if(strcmp(efl_text_get(txt), buf)); @@ -4501,6 +4510,12 @@ EFL_START_TEST(efl_canvas_textblock_cursor) pos = efl_text_cursor_position_get(cursor1); ck_assert_int_eq(pos, 1); + efl_text_set(txt, ""); + efl_text_set(txt, ""); + efl_text_cursor_text_insert(cursor1, "aa"); + + ck_assert_int_eq(changed_emit, 3); + END_EFL_CANVAS_TEXTBLOCK_TEST(); } EFL_END_TEST From 4f99f9f2bf17b437aa975c3875812529c2759707 Mon Sep 17 00:00:00 2001 From: Hermet Park Date: Fri, 13 Dec 2019 17:22:54 +0900 Subject: [PATCH 04/19] evas vg: revise buffer caching method. for better precise buffer cache key, We make a unique key name combining root node + size + frame index. Now, we can reuse the root node for animation and caching buffers. --- src/lib/evas/canvas/efl_canvas_vg_object.c | 78 +++++++++++++--------- src/lib/evas/canvas/evas_vg_private.h | 2 + src/lib/evas/vg/evas_vg_cache.c | 33 +++++++++ 3 files changed, 80 insertions(+), 33 deletions(-) diff --git a/src/lib/evas/canvas/efl_canvas_vg_object.c b/src/lib/evas/canvas/efl_canvas_vg_object.c index 740cfacc6c..83a59bd6fe 100644 --- a/src/lib/evas/canvas/efl_canvas_vg_object.c +++ b/src/lib/evas/canvas/efl_canvas_vg_object.c @@ -144,6 +144,8 @@ _efl_canvas_vg_object_root_node_set(Eo *eo_obj, Efl_Canvas_Vg_Object_Data *pd, E // detach/free the old root_node if (pd->user_entry && pd->user_entry->root) { + // drop any surface cache attached to it. + ENFN->ector_surface_cache_drop(_evas_engine_context(obj->layer->evas), pd->user_entry->root); efl_canvas_vg_node_vg_obj_set(pd->user_entry->root, NULL, NULL); efl_replace(&pd->user_entry->root, NULL); } @@ -166,8 +168,6 @@ _efl_canvas_vg_object_root_node_set(Eo *eo_obj, Efl_Canvas_Vg_Object_Data *pd, E } else if (pd->user_entry) { - // drop any surface cache attached to it. - ENFN->ector_surface_cache_drop(_evas_engine_context(obj->layer->evas), pd->user_entry->root); free(pd->user_entry); pd->user_entry = NULL; } @@ -345,7 +345,6 @@ _efl_canvas_vg_object_efl_object_invalidate(Eo *eo_obj, Efl_Canvas_Vg_Object_Dat if (pd->user_entry) { Vg_User_Entry *user_entry = pd->user_entry; - ENFN->ector_surface_cache_drop(ENC, user_entry->root); free(pd->user_entry); } @@ -492,8 +491,8 @@ _evas_vg_render(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd, //renders a vg_tree to an offscreen buffer and push it to the cache. static void * _render_to_buffer(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd, - void *engine, Efl_VG *root, int w, int h, void *buffer, - Eina_Bool do_async, Eina_Bool cacheable) + void *engine, Efl_VG *root, int w, int h, void *buffer, void *ckey, + Eina_Bool do_async) { Ector_Surface *ector; RGBA_Draw_Context *context; @@ -534,11 +533,8 @@ _render_to_buffer(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd ENFN->ector_end(engine, buffer, context, ector, do_async); evas_common_draw_context_free(context); - if (buffer_created && cacheable) - { - //Use root as a cache key. - ENFN->ector_surface_cache_set(engine, root, buffer); - } + if (buffer_created && ckey) + ENFN->ector_surface_cache_set(engine, ckey, buffer); return buffer; } @@ -579,8 +575,8 @@ _cache_vg_entry_render(Evas_Object_Protected_Data *obj, Vg_Cache_Entry *vg_entry = pd->vg_entry; Efl_VG *root; Eina_Position2D offset = {0, 0}; //Offset after keeping aspect ratio. - Eina_Bool drop_cache = EINA_FALSE; void *buffer = NULL; + void *key = NULL; evas_cache_vg_entry_value_provider_update(pd->vg_entry, efl_key_data_get(obj->object, "_vg_value_providers")); @@ -616,7 +612,23 @@ _cache_vg_entry_render(Evas_Object_Protected_Data *obj, //Size is changed, cached data is invalid. if ((size.w != vg_entry->w) || (size.h != vg_entry->h)) { - drop_cache = EINA_TRUE; +//Not necessary, but this might be helpful for precise caching. +#if 0 + if (cacheable) + { + //if the size doesn't match, drop previous cache surface. + key = evas_cache_vg_surface_key_get(pd->vg_entry->root, vg_entry->w, vg_entry->h, 0); + if (key) ENFN->ector_surface_cache_drop(engine, key); + + //Animatable... Try to drop the last frame image. + int last_frame = (int) (evas_cache_vg_anim_frame_count_get(pd->vg_entry) - 1); + if (last_frame > 0) + { + key = evas_cache_vg_surface_key_get(pd->vg_entry->root, vg_entry->w, vg_entry->h, last_frame); + if (key) ENFN->ector_surface_cache_drop(engine, key); + } + } +#endif vg_entry = evas_cache_vg_entry_resize(vg_entry, size.w, size.h); evas_cache_vg_entry_del(pd->vg_entry); pd->vg_entry = vg_entry; @@ -629,27 +641,25 @@ _cache_vg_entry_render(Evas_Object_Protected_Data *obj, if (offset.y > 0) offset.y /= 2; w = size.w; h = size.h; - } root = evas_cache_vg_tree_get(vg_entry, pd->frame_idx); if (!root) return; if (cacheable) { - //if the size doesn't match, drop previous cache surface. - if (drop_cache) - ENFN->ector_surface_cache_drop(engine, (void *) root); - //Cache Hit! - else - buffer = ENFN->ector_surface_cache_get(engine, (void *) root); + key = evas_cache_vg_surface_key_get(root, w, h, pd->frame_idx); + if (key) buffer = ENFN->ector_surface_cache_get(engine, key); } if (!buffer) - buffer = _render_to_buffer(obj, pd, engine, root, w, h, NULL, - do_async, cacheable); + { + buffer = _render_to_buffer(obj, pd, engine, root, w, h, NULL, key, do_async); + } else - //cache reference was increased when we get the cache. - ENFN->ector_surface_cache_drop(engine, (void *) root); + { + //cache reference was increased when we get the cache. + if (key) ENFN->ector_surface_cache_drop(engine, key); + } _render_buffer_to_screen(obj, engine, output, context, surface, @@ -662,8 +672,7 @@ static void _user_vg_entry_render(Evas_Object_Protected_Data *obj, Efl_Canvas_Vg_Object_Data *pd, void *engine, void *output, void *context, void *surface, - int x, int y, int w, int h, Eina_Bool do_async, - Eina_Bool cacheable) + int x, int y, int w, int h, Eina_Bool do_async) { Vg_User_Entry *user_entry = pd->user_entry; @@ -679,14 +688,13 @@ _user_vg_entry_render(Evas_Object_Protected_Data *obj, //if the buffer is not created yet void *buffer = NULL; - if (cacheable) buffer = ENFN->ector_surface_cache_get(engine, user_entry->root); if (!buffer) { // render to the buffer buffer = _render_to_buffer(obj, pd, engine, user_entry->root, - w, h, buffer, do_async, cacheable); + w, h, buffer, user_entry->root, do_async); } else { @@ -694,8 +702,8 @@ _user_vg_entry_render(Evas_Object_Protected_Data *obj, if (pd->changed) buffer = _render_to_buffer(obj, pd, engine, user_entry->root, - w, h, buffer, - do_async, EINA_FALSE); + w, h, buffer, NULL, + do_async); //cache reference was increased when we get the cache. ENFN->ector_surface_cache_drop(engine, user_entry->root); } @@ -704,7 +712,7 @@ _user_vg_entry_render(Evas_Object_Protected_Data *obj, engine, output, context, surface, buffer, x, y, w, h, - do_async, cacheable); + do_async, EINA_TRUE); } static void @@ -729,8 +737,12 @@ _efl_canvas_vg_object_render(Evas_Object *eo_obj EINA_UNUSED, //Cache surface? Eina_Bool cacheable = EINA_FALSE; - /* Try caching buffer only for static images. */ - if (evas_cache_vg_anim_frame_count_get(pd->vg_entry) == 0) + /* Try caching buffer only for first and last frames + because it's an overhead task if it caches all frame images. + We assume the first and last frame images are the most resusable + in generic scenarios. */ + if (pd->frame_idx == 0 || + (pd->frame_idx == (int) (evas_cache_vg_anim_frame_count_get(pd->vg_entry) - 1))) cacheable = EINA_TRUE; if (pd->vg_entry) @@ -745,7 +757,7 @@ _efl_canvas_vg_object_render(Evas_Object *eo_obj EINA_UNUSED, _user_vg_entry_render(obj, pd, engine, output, context, surface, obj->cur->geometry.x + x, obj->cur->geometry.y + y, - obj->cur->geometry.w, obj->cur->geometry.h, do_async, cacheable); + obj->cur->geometry.w, obj->cur->geometry.h, do_async); } pd->changed = EINA_FALSE; } diff --git a/src/lib/evas/canvas/evas_vg_private.h b/src/lib/evas/canvas/evas_vg_private.h index 2a1dbfa0d5..a6a27142ed 100644 --- a/src/lib/evas/canvas/evas_vg_private.h +++ b/src/lib/evas/canvas/evas_vg_private.h @@ -15,6 +15,7 @@ typedef struct _Vg_Cache { Eina_Hash *vfd_hash; Eina_Hash *vg_entry_hash; + Eina_List *vg_surface_keys; int ref; } Vg_Cache; @@ -154,6 +155,7 @@ Eina_Bool evas_cache_vg_anim_sector_set(const Vg_Cache_Entry* Eina_Bool evas_cache_vg_anim_sector_get(const Vg_Cache_Entry* vg_entry, const char *name, int* startframe, int* endframe); unsigned int evas_cache_vg_anim_frame_count_get(const Vg_Cache_Entry *vg_entry); Eina_Size2D evas_cache_vg_entry_default_size_get(const Vg_Cache_Entry *vg_entry); +void * evas_cache_vg_surface_key_get(Efl_Canvas_Vg_Node *root, int w, int h, int frame_idx); void efl_canvas_vg_node_vg_obj_set(Efl_VG *node, Efl_VG *vg_obj, Efl_Canvas_Vg_Object_Data *vd); void efl_canvas_vg_node_change(Efl_VG *node); void efl_canvas_vg_container_vg_obj_update(Efl_VG *obj, Efl_Canvas_Vg_Node_Data *nd); diff --git a/src/lib/evas/vg/evas_vg_cache.c b/src/lib/evas/vg/evas_vg_cache.c index 5c0242db23..2ef31bded2 100644 --- a/src/lib/evas/vg/evas_vg_cache.c +++ b/src/lib/evas/vg/evas_vg_cache.c @@ -269,12 +269,45 @@ evas_cache_vg_init(void) vg_cache->ref++; } +void * +evas_cache_vg_surface_key_get(Efl_Canvas_Vg_Node *root, int w, int h, int frame_idx) +{ + //This make a unique key pointer by arguments. + Eina_Strbuf *hash_key = eina_strbuf_new(); + eina_strbuf_append_printf(hash_key, "%p/%d/%d/%d", root, w, h, frame_idx); + const char *new_key = eina_strbuf_string_get(hash_key); + if (!new_key) return NULL; + + Eina_List *l; + char *key; + EINA_LIST_FOREACH(vg_cache->vg_surface_keys, l, key) + { + //Exisiting key! + if (!strcmp(key, new_key)) + { + eina_strbuf_free(hash_key); + return key; + } + } + + //New key comes. + key = eina_strbuf_string_steal(hash_key); + vg_cache->vg_surface_keys = eina_list_append(vg_cache->vg_surface_keys, key); + return (void *) key; +} + void evas_cache_vg_shutdown(void) { if (!vg_cache) return; vg_cache->ref--; if (vg_cache->ref > 0) return; + + char *key; + EINA_LIST_FREE(vg_cache->vg_surface_keys, key) + free(key); + eina_list_free(vg_cache->vg_surface_keys); + eina_hash_free(vg_cache->vfd_hash); eina_hash_free(vg_cache->vg_entry_hash); free(vg_cache); From 905020bc7cebd466d13191b38af51b7a053a2052 Mon Sep 17 00:00:00 2001 From: Xavi Artigas Date: Fri, 13 Dec 2019 12:37:27 +0100 Subject: [PATCH 05/19] elm_test: Remove unused variable in test_win_stack --- src/bin/elementary/test_win_stack.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bin/elementary/test_win_stack.c b/src/bin/elementary/test_win_stack.c index 72510d0e6c..6bff88efc4 100644 --- a/src/bin/elementary/test_win_stack.c +++ b/src/bin/elementary/test_win_stack.c @@ -14,7 +14,7 @@ static void _bt_popto(void *data, Evas_Object *obj, void *event_info); static void _bt_pressed(void *data, Evas_Object *obj, void *event_info); static Evas_Object * -_win_new(Evas_Object* parent, Evas_Object *stack_top, const char *title) +_win_new(Evas_Object* parent, const char *title) { Evas_Object *bg, *bx, *bt, *lb, *win; @@ -87,7 +87,7 @@ _bt_pressed(void *data, Evas_Object *obj EINA_UNUSED, void *event_info EINA_UNUS level++; snprintf(buf, sizeof(buf), "Level %i", level); - win = _win_new(win, obj, buf); + win = _win_new(win, buf); efl_ui_win_stack_master_id_set(win, efl_ui_win_stack_id_get(data)); } From 94fa81f4f48987d2be513facc36a0f1a9825e8f5 Mon Sep 17 00:00:00 2001 From: Stefan Schmidt Date: Wed, 24 May 2017 13:43:02 +0200 Subject: [PATCH 06/19] po: remove empty ChangeLog file for translations This was never used. Reviewed-by: Massimo Maiurana Differential Revision: https://phab.enlightenment.org/D10871 --- po/ChangeLog | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 po/ChangeLog diff --git a/po/ChangeLog b/po/ChangeLog deleted file mode 100644 index e69de29bb2..0000000000 From cf30efa5ee7eaa717c099f9ba3e8eecb91c6e216 Mon Sep 17 00:00:00 2001 From: Stefan Schmidt Date: Wed, 24 May 2017 13:40:01 +0200 Subject: [PATCH 07/19] po: update LINGUAS file to reflect all translations we currently have This list was quite outdated compared to the po files we have in tree right now. Reviewed-by: Massimo Maiurana Differential Revision: https://phab.enlightenment.org/D10872 --- po/LINGUAS | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/po/LINGUAS b/po/LINGUAS index 0a418cc6ce..c508050b27 100644 --- a/po/LINGUAS +++ b/po/LINGUAS @@ -1,2 +1 @@ -ca cs da de el eo es fi fr gl hu it ja ko lt nl pl pt ru sl sr tr vi zh_CN - +ar az_IR ca cs da de el eo es fa fi fr gl he hu it ja ko_KR ko lt nl pl ps pt ru sl sr tr ur vi yi zh_CN From abc1cb0043fc5a696e169266e3e7cead6012b8b6 Mon Sep 17 00:00:00 2001 From: Ali Alzyod Date: Fri, 13 Dec 2019 15:12:25 +0100 Subject: [PATCH 08/19] efl_canvas_textblock: multiline enabled by default Reviewers: segfaultxavi Reviewed By: segfaultxavi Subscribers: segfaultxavi, tasn, bu5hm4n, cedric, #reviewers, #committers Tags: #efl Differential Revision: https://phab.enlightenment.org/D10859 --- src/lib/evas/canvas/evas_object_textblock.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/evas/canvas/evas_object_textblock.c b/src/lib/evas/canvas/evas_object_textblock.c index 33458fea98..e68f70351a 100644 --- a/src/lib/evas/canvas/evas_object_textblock.c +++ b/src/lib/evas/canvas/evas_object_textblock.c @@ -14247,7 +14247,7 @@ evas_object_textblock_init(Evas_Object *eo_obj) co->obj = eo_obj; evas_object_textblock_text_markup_set(eo_obj, ""); - o->multiline = EINA_FALSE; + o->multiline = EINA_TRUE; #ifdef BIDI_SUPPORT o->inherit_paragraph_direction = EINA_TRUE; #endif From 7a72796920041e9a0410a670f22e57f6c0250c88 Mon Sep 17 00:00:00 2001 From: Marcel Hollerbach Date: Mon, 9 Dec 2019 18:27:37 +0100 Subject: [PATCH 09/19] efl_ui_pan: stop leaking content pans implementation of Efl.Content is different to each other implementation, setting the content to NULL is not really deleting the obejct, since this is done at those widgets that are actaully using the pan. This is weird and fine in the same way, as the pan is only internal. However, when we are shutting down, we must free the content here. Reviewed-by: Cedric BAIL Differential Revision: https://phab.enlightenment.org/D10838 --- src/lib/elementary/efl_ui_pan.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lib/elementary/efl_ui_pan.c b/src/lib/elementary/efl_ui_pan.c index 72e5c60a93..b86d68bdc6 100644 --- a/src/lib/elementary/efl_ui_pan.c +++ b/src/lib/elementary/efl_ui_pan.c @@ -110,7 +110,9 @@ _efl_ui_pan_efl_object_constructor(Eo *obj, Efl_Ui_Pan_Data *_pd EINA_UNUSED) EOLIAN static void _efl_ui_pan_efl_object_destructor(Eo *obj, Efl_Ui_Pan_Data *sd EINA_UNUSED) { - efl_content_set(obj, NULL); + /* our implementation is a little bit incomplete, efl_content_set(obj, NULL) does not delete the content, However, if we do that, list grid and scroller would fail, because the assume ownership of the content */ + Eo *content = efl_content_unset(obj); + efl_del(content); efl_destructor(efl_super(obj, MY_CLASS)); } From 3a712e2497857aa53ddcbe35715261bdaa23c272 Mon Sep 17 00:00:00 2001 From: Marcel Hollerbach Date: Mon, 9 Dec 2019 18:36:24 +0100 Subject: [PATCH 10/19] collection_view: free pan object correctly edje will not take over this part, edje will just reparent it to the ML and go on. Reviewed-by: Cedric BAIL Differential Revision: https://phab.enlightenment.org/D10839 --- src/lib/elementary/efl_ui_collection_view.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lib/elementary/efl_ui_collection_view.c b/src/lib/elementary/efl_ui_collection_view.c index dcf8f91462..ba18264225 100644 --- a/src/lib/elementary/efl_ui_collection_view.c +++ b/src/lib/elementary/efl_ui_collection_view.c @@ -2072,6 +2072,9 @@ _efl_ui_collection_view_efl_object_invalidate(Eo *obj, _all_cleanup(obj, pd); + if (pd->pan) + efl_del(pd->pan); + efl_invalidate(efl_super(obj, EFL_UI_COLLECTION_VIEW_CLASS)); } From e81dc6a02b637b394a59490527134434d4309523 Mon Sep 17 00:00:00 2001 From: Marcel Hollerbach Date: Mon, 9 Dec 2019 18:36:55 +0100 Subject: [PATCH 11/19] efl_ui_scroller: free pan object correctly we need to free the object in the invalidate, not in the destructor. Otherwise we might leak objects in bindings. Reviewed-by: Jaehyun Cho Reviewed-by: Cedric BAIL Differential Revision: https://phab.enlightenment.org/D10840 --- src/lib/elementary/efl_ui_scroller.c | 15 +++++++++++---- src/lib/elementary/efl_ui_scroller.eo | 1 + 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/lib/elementary/efl_ui_scroller.c b/src/lib/elementary/efl_ui_scroller.c index 92b99527bf..5c79c2eec7 100644 --- a/src/lib/elementary/efl_ui_scroller.c +++ b/src/lib/elementary/efl_ui_scroller.c @@ -278,15 +278,22 @@ _efl_ui_scroller_efl_object_finalize(Eo *obj, return obj; } +EOLIAN static void +_efl_ui_scroller_efl_object_invalidate(Eo *obj, Efl_Ui_Scroller_Data *pd) +{ + efl_event_callback_del(pd->pan_obj, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, + _efl_ui_scroller_pan_resized_cb, obj); + efl_del(pd->pan_obj); + pd->pan_obj = NULL; + + efl_invalidate(efl_super(obj, MY_CLASS)); +} + EOLIAN static void _efl_ui_scroller_efl_object_destructor(Eo *obj, Efl_Ui_Scroller_Data *sd) { efl_ui_scroll_connector_unbind(obj); - efl_event_callback_del(sd->pan_obj, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, - _efl_ui_scroller_pan_resized_cb, obj); - efl_del(sd->pan_obj); - sd->pan_obj = NULL; sd->smanager = NULL; efl_destructor(efl_super(obj, MY_CLASS)); diff --git a/src/lib/elementary/efl_ui_scroller.eo b/src/lib/elementary/efl_ui_scroller.eo index 22a99b8a80..46f256382d 100644 --- a/src/lib/elementary/efl_ui_scroller.eo +++ b/src/lib/elementary/efl_ui_scroller.eo @@ -24,6 +24,7 @@ class Efl.Ui.Scroller extends Efl.Ui.Layout_Base implements Efl.Object.constructor; Efl.Object.finalize; Efl.Object.destructor; + Efl.Object.invalidate; Efl.Content.content { get; set; } Efl.Content.content_unset; Efl.Canvas.Group.group_calculate; From eaf2a8d7ecd3a8ae29e48abf0d6f81211041188e Mon Sep 17 00:00:00 2001 From: Marcel Hollerbach Date: Mon, 9 Dec 2019 18:42:02 +0100 Subject: [PATCH 12/19] efl_ui_collection: do not leak this fixes leaking of membership to a pan object, additionally this also fixes the leaking of the pan object. This code was written with the thought that edje deletes its children, long story short: no it does not. While fixing the leak of the pan object, the error was found that the membership of the item to the pan object was leaked, which ended up in the item beeing deleted, even if its not part of the object anymore. Reviewed-by: Cedric BAIL Differential Revision: https://phab.enlightenment.org/D10841 --- src/lib/elementary/efl_ui_collection.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lib/elementary/efl_ui_collection.c b/src/lib/elementary/efl_ui_collection.c index 43b1b19521..f40a366c76 100644 --- a/src/lib/elementary/efl_ui_collection.c +++ b/src/lib/elementary/efl_ui_collection.c @@ -438,6 +438,8 @@ _efl_ui_collection_efl_object_invalidate(Eo *obj, Efl_Ui_Collection_Data *pd EIN while(pd->items) efl_del(pd->items->data); + efl_del(pd->pan); + efl_invalidate(efl_super(obj, MY_CLASS)); } @@ -704,6 +706,7 @@ unregister_item(Eo *obj, Efl_Ui_Collection_Data *pd, Efl_Ui_Item *item) efl_event_callback_array_del(item, active_item(), obj); efl_ui_position_manager_entity_item_removed(pd->pos_man, id, item); efl_ui_item_container_set(item, NULL); + efl_canvas_group_member_remove(pd->pan, item); return EINA_TRUE; } From e0ab85cff942f2ca8b2c2882661439641d02e032 Mon Sep 17 00:00:00 2001 From: Marcel Hollerbach Date: Mon, 9 Dec 2019 18:45:37 +0100 Subject: [PATCH 13/19] efl_ui_spec_test: make this test work I do not know what i was thinking when i initially wrote that test. It never worked, the test created a widget captured all elements, deleted the widget, then checked if there are elements left that are not knon on the canvas yet. Not the test first captures all elements, then creates the widget, then deletes the widget, and checks if there are more elements than expected. This found all the fix leaks prior to this leak. Reviewed-by: Cedric BAIL Differential Revision: https://phab.enlightenment.org/D10842 --- src/tests/elementary/spec/efl_test_basics.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/tests/elementary/spec/efl_test_basics.c b/src/tests/elementary/spec/efl_test_basics.c index 0985adb43c..99a441c059 100644 --- a/src/tests/elementary/spec/efl_test_basics.c +++ b/src/tests/elementary/spec/efl_test_basics.c @@ -66,6 +66,8 @@ EFL_START_TEST(no_leaking_canvas_object) Eina_Iterator *iter = eo_objects_iterator_new(); Eo *obj; + if (efl_isa(widget, EFL_UI_FLIP_CLASS)) return; //FIXME Flip needs more work for this. However, flip should be redone as a spotlight manager, When this is done, we can add these classes to the check here. + EINA_ITERATOR_FOREACH(iter, obj) { if (!efl_alive_get(obj)) continue; @@ -75,6 +77,12 @@ EFL_START_TEST(no_leaking_canvas_object) } eina_iterator_free(iter); + //Just overwrite the widget pointer, and expect errors, if any error is happening here, we are not interested in it, another testcase will take care of them + EXPECT_ERROR_START; + widget = efl_add(widget_klass, win); + expect_error_start = EINA_TRUE; + EXPECT_ERROR_END; + //now try to will those widgets if (efl_isa(widget, EFL_PACK_LINEAR_INTERFACE)) { @@ -105,7 +113,10 @@ EFL_START_TEST(no_leaking_canvas_object) if (!efl_alive_get(obj)) continue; if (!efl_isa(obj, EFL_CANVAS_OBJECT_CLASS)) continue; - ck_assert_ptr_ne(eina_list_data_find(not_invalidate, obj), NULL); + if (eina_list_data_find(not_invalidate, obj) == NULL) + { + ck_abort_msg("Leak detected %s Evas-Parent: %s", efl_debug_name_get(obj), efl_class_name_get(efl_canvas_object_render_parent_get(obj))); + } } eina_iterator_free(iter); From 431800a529fba3ff90c77cfdb3cd76e79c59528a Mon Sep 17 00:00:00 2001 From: Marcel Hollerbach Date: Mon, 9 Dec 2019 19:25:18 +0100 Subject: [PATCH 14/19] efl_datetime_manager: how did that ever work? seriously, it sometimes might be worth at least *reading* what code does, this was initializating a private data struct on one single global boolean flag. How was that ever intended to work ? How could that ever slip through review ? This is not the only madness in these widget arround time and date, you cannot even select hours in 24h mode, you also cannot cannot select the 0 hour, which is kind of normal for the one or another region? the datetimemanager (which is IMO a complete misconcept) is full of FIXMEs and API calls that are defined and never called at all. Again what is this ? And how did that ever get into the codebase ?! With this commit the widget *finally* can be created more than once without exploding and erroring one. Reviewed-by: Cedric BAIL Differential Revision: https://phab.enlightenment.org/D10843 --- src/lib/elementary/efl_datetime_manager.c | 8 +++----- src/tests/elementary/spec/efl_test_basics.c | 8 ++++++++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/lib/elementary/efl_datetime_manager.c b/src/lib/elementary/efl_datetime_manager.c index 24daa34217..7445b8cdee 100644 --- a/src/lib/elementary/efl_datetime_manager.c +++ b/src/lib/elementary/efl_datetime_manager.c @@ -22,10 +22,9 @@ typedef struct { Efl_Time time; char format[MAX_FORMAT_LEN]; + Eina_Bool init; } Efl_Datetime_Manager_Data; -Eina_Bool init = EINA_FALSE; - static void _time_init(Efl_Time *curr_time) { @@ -33,8 +32,6 @@ _time_init(Efl_Time *curr_time) t = time(NULL); localtime_r(&t, curr_time); - - init = EINA_TRUE; } static char * @@ -162,7 +159,8 @@ _efl_datetime_manager_value_set(Eo *obj EINA_UNUSED, Efl_Datetime_Manager_Data * EOLIAN static Efl_Time _efl_datetime_manager_value_get(const Eo *obj EINA_UNUSED, Efl_Datetime_Manager_Data *pd) { - if (!init) _time_init(&pd->time); + if (!pd->init) _time_init(&pd->time); + pd->init = EINA_TRUE; return pd->time; } diff --git a/src/tests/elementary/spec/efl_test_basics.c b/src/tests/elementary/spec/efl_test_basics.c index 99a441c059..b14e18a568 100644 --- a/src/tests/elementary/spec/efl_test_basics.c +++ b/src/tests/elementary/spec/efl_test_basics.c @@ -124,6 +124,13 @@ EFL_START_TEST(no_leaking_canvas_object) } EFL_END_TEST + +EFL_START_TEST(no_err_on_creation) +{ + widget = efl_add(widget_klass, win); +} +EFL_END_TEST + EFL_START_TEST(no_err_on_shutdown) { efl_ref(widget); @@ -204,4 +211,5 @@ efl_ui_widget_behavior_test(TCase *tc) tcase_add_test(tc, no_leaking_canvas_object); tcase_add_test(tc, no_err_on_shutdown); tcase_add_test(tc, correct_visibility_setting); + tcase_add_test(tc, no_err_on_creation); } From 349df856791abf9adb2e3f66c90e476947e3431b Mon Sep 17 00:00:00 2001 From: Marcel Hollerbach Date: Mon, 9 Dec 2019 21:02:26 +0100 Subject: [PATCH 15/19] efl_ui_spotlight_manager_*: do not keep ptr of dead pointer when content is deleted, we should not keep a dangling pointer of it. Setting it to NULL here is enough, as later on a swtich_to reuest will be sent. Reviewed-by: Cedric BAIL Differential Revision: https://phab.enlightenment.org/D10844 --- src/lib/elementary/efl_ui_spotlight_manager_plain.c | 2 ++ src/lib/elementary/efl_ui_spotlight_manager_stack.c | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/src/lib/elementary/efl_ui_spotlight_manager_plain.c b/src/lib/elementary/efl_ui_spotlight_manager_plain.c index 83aab8fcce..d9c52ab3db 100644 --- a/src/lib/elementary/efl_ui_spotlight_manager_plain.c +++ b/src/lib/elementary/efl_ui_spotlight_manager_plain.c @@ -90,6 +90,8 @@ EOLIAN static void _efl_ui_spotlight_manager_plain_efl_ui_spotlight_manager_content_del(Eo *obj, Efl_Ui_Spotlight_Manager_Plain_Data *pd, Efl_Gfx_Entity *subobj, int index EINA_UNUSED) { efl_canvas_group_member_remove(pd->container, subobj); + if (pd->current_content == subobj) + pd->current_content = NULL; _content_changed(obj, pd); } EOLIAN static void diff --git a/src/lib/elementary/efl_ui_spotlight_manager_stack.c b/src/lib/elementary/efl_ui_spotlight_manager_stack.c index b286d75eab..d7d6d94c62 100644 --- a/src/lib/elementary/efl_ui_spotlight_manager_stack.c +++ b/src/lib/elementary/efl_ui_spotlight_manager_stack.c @@ -105,6 +105,11 @@ EOLIAN static void _efl_ui_spotlight_manager_stack_efl_ui_spotlight_manager_content_del(Eo *obj EINA_UNUSED, Efl_Ui_Spotlight_Manager_Stack_Data *pd, Efl_Gfx_Entity *subobj, int index) { efl_canvas_group_member_remove(pd->container, subobj); + for (int i = 0; i < 2; ++i) + { + if (pd->content[i] == subobj) + pd->content[i] = NULL; + } _update_ids(obj, pd, index); } From 4982da63273f60bc3e5a114ee407e9fbd166dd75 Mon Sep 17 00:00:00 2001 From: Marcel Hollerbach Date: Mon, 9 Dec 2019 21:40:10 +0100 Subject: [PATCH 16/19] evas_focus: protect against faulty focus object the problem is that we only remove ourselfs from the focused list in the invalidator. However, we allowed invalidated objects to be part of this hash, which made everything go boom. With this commit you at least only get one error and you should fix up this case. This fixes random errors in enlightenment (That are appearing theire since seats have been introduced to evas, the problem before invalidate was that the object was already destructor called, but not fully destructed yet). Reviewed-by: Cedric BAIL Differential Revision: https://phab.enlightenment.org/D10845 --- src/lib/evas/canvas/evas_focus.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib/evas/canvas/evas_focus.c b/src/lib/evas/canvas/evas_focus.c index e11df7887d..83678fc64a 100644 --- a/src/lib/evas/canvas/evas_focus.c +++ b/src/lib/evas/canvas/evas_focus.c @@ -223,6 +223,8 @@ _efl_canvas_object_seat_focus_add(Eo *eo_obj, return EINA_FALSE; MAGIC_CHECK_END(); + EINA_SAFETY_ON_FALSE_RETURN_VAL(!efl_invalidating_get(eo_obj) && !efl_invalidated_get(eo_obj), EINA_FALSE); + event_id = _evas_event_counter; if (seat) default_seat = _default_seat_get(eo_obj); else default_seat = seat = _default_seat_get(eo_obj); From 7d1463124ac139f3cb99028ff453041a5453ef8f Mon Sep 17 00:00:00 2001 From: Marcel Hollerbach Date: Mon, 9 Dec 2019 21:51:02 +0100 Subject: [PATCH 17/19] efl_ui_widget: do not execute up handler when on destruction otherwise we would cause an error. Reviewed-by: Cedric BAIL Differential Revision: https://phab.enlightenment.org/D10846 --- src/lib/elementary/efl_ui_widget.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/lib/elementary/efl_ui_widget.c b/src/lib/elementary/efl_ui_widget.c index 010c9fa9b6..768d934fae 100644 --- a/src/lib/elementary/efl_ui_widget.c +++ b/src/lib/elementary/efl_ui_widget.c @@ -691,7 +691,8 @@ _obj_mouse_up(void *data, Evas_Event_Mouse_Up *ev = event_info; if (sd->still_in && (ev->flags == EVAS_BUTTON_NONE) && - (sd->focus_move_policy == ELM_FOCUS_MOVE_POLICY_CLICK)) + (sd->focus_move_policy == ELM_FOCUS_MOVE_POLICY_CLICK) && + !efl_invalidated_get(data)) elm_widget_focus_mouse_up_handle(evas_object_widget_parent_find(obj)); sd->still_in = EINA_FALSE; @@ -704,7 +705,8 @@ _obj_mouse_in(void *data, void *event_info EINA_UNUSED) { ELM_WIDGET_DATA_GET(data, sd); - if (sd->focus_move_policy == ELM_FOCUS_MOVE_POLICY_IN) + if (sd->focus_move_policy == ELM_FOCUS_MOVE_POLICY_IN && + !efl_invalidated_get(data)) elm_widget_focus_mouse_up_handle(evas_object_widget_parent_find(obj)); } From 5892292ac8066e5e00fba085990d7190a36404f3 Mon Sep 17 00:00:00 2001 From: Marcel Hollerbach Date: Fri, 13 Dec 2019 18:11:17 +0100 Subject: [PATCH 18/19] efl_ui: docuement code there was the request that this needs to be documented, here we are. Reviewed-by: Cedric BAIL Differential Revision: https://phab.enlightenment.org/D10874 --- src/lib/elementary/efl_ui_collection.c | 1 + src/lib/elementary/efl_ui_collection_view.c | 1 + src/lib/elementary/efl_ui_scroller.c | 1 + 3 files changed, 3 insertions(+) diff --git a/src/lib/elementary/efl_ui_collection.c b/src/lib/elementary/efl_ui_collection.c index f40a366c76..53afb10743 100644 --- a/src/lib/elementary/efl_ui_collection.c +++ b/src/lib/elementary/efl_ui_collection.c @@ -438,6 +438,7 @@ _efl_ui_collection_efl_object_invalidate(Eo *obj, Efl_Ui_Collection_Data *pd EIN while(pd->items) efl_del(pd->items->data); + // pan is given to edje, which reparents it, which forces us to manually deleting it efl_del(pd->pan); efl_invalidate(efl_super(obj, MY_CLASS)); diff --git a/src/lib/elementary/efl_ui_collection_view.c b/src/lib/elementary/efl_ui_collection_view.c index ba18264225..2598849f36 100644 --- a/src/lib/elementary/efl_ui_collection_view.c +++ b/src/lib/elementary/efl_ui_collection_view.c @@ -2072,6 +2072,7 @@ _efl_ui_collection_view_efl_object_invalidate(Eo *obj, _all_cleanup(obj, pd); + //pd pan is given to edje, which reparents it, which forces us to manually deleting it if (pd->pan) efl_del(pd->pan); diff --git a/src/lib/elementary/efl_ui_scroller.c b/src/lib/elementary/efl_ui_scroller.c index 5c79c2eec7..5b0eca2fa5 100644 --- a/src/lib/elementary/efl_ui_scroller.c +++ b/src/lib/elementary/efl_ui_scroller.c @@ -281,6 +281,7 @@ _efl_ui_scroller_efl_object_finalize(Eo *obj, EOLIAN static void _efl_ui_scroller_efl_object_invalidate(Eo *obj, Efl_Ui_Scroller_Data *pd) { + // pan is given to edje, which reparents it, which forces us to manually deleting it efl_event_callback_del(pd->pan_obj, EFL_GFX_ENTITY_EVENT_SIZE_CHANGED, _efl_ui_scroller_pan_resized_cb, obj); efl_del(pd->pan_obj); From c3dbcb2447dcdc01050fdb87533affabe42f154a Mon Sep 17 00:00:00 2001 From: ali Date: Fri, 13 Dec 2019 23:23:15 +0000 Subject: [PATCH 19/19] edje_entry: real part protection check Fix T8524 Reviewed-by: Cedric BAIL Differential Revision: https://phab.enlightenment.org/D10875 --- src/lib/edje/edje_entry.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lib/edje/edje_entry.c b/src/lib/edje/edje_entry.c index 14696182d1..92bc0df031 100644 --- a/src/lib/edje/edje_entry.c +++ b/src/lib/edje/edje_entry.c @@ -4400,7 +4400,10 @@ Eina_Bool _edje_text_cursor_coord_set(Edje_Real_Part *rp, Efl_Text_Cursor_Handle *c, Evas_Coord x, Evas_Coord y) { + if ((rp->type != EDJE_RP_TYPE_TEXT) || + (!rp->typedata.text)) return EINA_FALSE; Entry *en = rp->typedata.text->entry_data; + if (!en) return EINA_FALSE; if ((c == _cursor_get(rp, EDJE_CURSOR_SELECTION_BEGIN)) || (c == _cursor_get(rp, EDJE_CURSOR_SELECTION_END))) {