diff --git a/legacy/edje/src/lib/edje_calc.c b/legacy/edje/src/lib/edje_calc.c index f62f26ab9d..37a41edd77 100644 --- a/legacy/edje/src/lib/edje_calc.c +++ b/legacy/edje/src/lib/edje_calc.c @@ -135,6 +135,14 @@ _edje_part_description_apply(Edje *ed, Edje_Real_Part *ep, const char *d1, doubl void _edje_recalc(Edje *ed) +{ + if (ed->postponed) return ; + evas_object_smart_changed(ed->obj); + ed->postponed = 1; +} + +void +_edje_recalc_do(Edje *ed) { int i; @@ -142,7 +150,8 @@ _edje_recalc(Edje *ed) if (ed->freeze) { ed->recalc = 1; - if (!ed->calc_only) return; + if (!ed->calc_only && + !ed->postponed) return; } for (i = 0; i < ed->table_parts_size; i++) { @@ -161,6 +170,7 @@ _edje_recalc(Edje *ed) _edje_part_recalc(ed, ep, (~ep->calculated) & FLAG_XY); } ed->dirty = 0; + ed->postponed = 0; if (!ed->calc_only) ed->recalc = 0; } diff --git a/legacy/edje/src/lib/edje_private.h b/legacy/edje/src/lib/edje_private.h index 4bc95ccfea..603ab3ef5e 100644 --- a/legacy/edje/src/lib/edje_private.h +++ b/legacy/edje/src/lib/edje_private.h @@ -681,6 +681,7 @@ struct _Edje unsigned short walking_actions : 1; unsigned short block_break : 1; unsigned short delete_me : 1; + unsigned short postponed : 1; }; struct _Edje_Real_Part @@ -1007,6 +1008,7 @@ void _edje_part_pos_set(Edje *ed, Edje_Real_Part *ep, int mode, double pos); Edje_Part_Description *_edje_part_description_find(Edje *ed, Edje_Real_Part *rp, const char *name, double val); void _edje_part_description_apply(Edje *ed, Edje_Real_Part *ep, const char *d1, double v1, const char *d2, double v2); void _edje_recalc(Edje *ed); +void _edje_recalc_do(Edje *ed); int _edje_part_dragable_calc(Edje *ed, Edje_Real_Part *ep, double *x, double *y); void _edje_dragable_pos_set(Edje *ed, Edje_Real_Part *ep, double x, double y); diff --git a/legacy/edje/src/lib/edje_smart.c b/legacy/edje/src/lib/edje_smart.c index b4f027ff5e..a3b23abc53 100644 --- a/legacy/edje/src/lib/edje_smart.c +++ b/legacy/edje/src/lib/edje_smart.c @@ -13,6 +13,7 @@ static void _edje_smart_hide(Evas_Object * obj); static void _edje_smart_color_set(Evas_Object * obj, int r, int g, int b, int a); static void _edje_smart_clip_set(Evas_Object * obj, Evas_Object * clip); static void _edje_smart_clip_unset(Evas_Object * obj); +static void _edje_smart_calculate(Evas_Object * obj); static Evas_Smart *_edje_smart = NULL; @@ -45,6 +46,7 @@ edje_object_add(Evas *evas) _edje_smart_color_set, _edje_smart_clip_set, _edje_smart_clip_unset, + _edje_smart_calculate, NULL }; _edje_smart = evas_smart_class_new(&sc); @@ -237,3 +239,13 @@ _edje_smart_clip_unset(Evas_Object * obj) evas_object_clip_unset(ed->clipper); // _edje_emit(ed, "clip_unset", NULL); } + +static void +_edje_smart_calculate(Evas_Object *obj) +{ + Edje *ed; + + ed = evas_object_smart_data_get(obj); + if (!ed) return; + _edje_recalc_do(ed); +} diff --git a/legacy/edje/src/lib/edje_util.c b/legacy/edje/src/lib/edje_util.c index 4d91bd62ee..ec3eb3f924 100644 --- a/legacy/edje/src/lib/edje_util.c +++ b/legacy/edje/src/lib/edje_util.c @@ -715,6 +715,10 @@ edje_object_part_object_get(const Evas_Object *obj, const char *part) ed = _edje_fetch(obj); if ((!ed) || (!part)) return NULL; + + /* Need to recalc before providing the object. */ + _edje_recalc_do(ed); + rp = _edje_real_part_recursive_get(ed, (char *)part); if (!rp) return NULL; return rp->object; @@ -748,6 +752,10 @@ edje_object_part_geometry_get(const Evas_Object *obj, const char *part, Evas_Coo if (h) *h = 0; return; } + + /* Need to recalc before providing the object. */ + _edje_recalc_do(ed); + rp = _edje_real_part_recursive_get(ed, (char *)part); if (!rp) { @@ -828,6 +836,10 @@ edje_object_part_text_get(const Evas_Object *obj, const char *part) ed = _edje_fetch(obj); if ((!ed) || (!part)) return NULL; + + /* Need to recalc before providing the object. */ + _edje_recalc_do(ed); + rp = _edje_real_part_recursive_get(ed, (char *)part); if (!rp) return NULL; if (rp->part->type == EDJE_PART_TYPE_TEXT) @@ -855,6 +867,10 @@ edje_object_part_swallow(Evas_Object *obj, const char *part, Evas_Object *obj_sw ed = _edje_fetch(obj); if ((!ed) || (!part)) return; + + /* Need to recalc before providing the object. */ + _edje_recalc_do(ed); + rp = _edje_real_part_recursive_get(ed, (char *)part); if (!rp) return; if (rp->part->type != EDJE_PART_TYPE_SWALLOW) return; @@ -1021,7 +1037,7 @@ edje_object_part_unswallow(Evas_Object *obj, Evas_Object *obj_swallow) rp->swallow_params.max.w = 0; rp->swallow_params.max.h = 0; rp->edje->dirty = 1; - _edje_recalc(rp->edje); + _edje_recalc_do(rp->edje); return; } } @@ -1039,6 +1055,10 @@ edje_object_part_swallow_get(const Evas_Object *obj, const char *part) ed = _edje_fetch(obj); if ((!ed) || (!part)) return NULL; + + /* Need to recalc before providing the object. */ + _edje_recalc_do(ed); + rp = _edje_real_part_recursive_get(ed, (char *)part); if (!rp) return NULL; return rp->swallowed_object; @@ -1088,6 +1108,10 @@ edje_object_size_max_get(const Evas_Object *obj, Evas_Coord *maxw, Evas_Coord *m if (maxh) *maxh = 0; return; } + + /* Need to recalc before providing the object. */ + _edje_recalc_do(ed); + if (ed->collection->prop.max.w == 0) { /* XXX TODO: convert maxw to 0, fix things that break. */ @@ -1125,7 +1149,7 @@ edje_object_calc_force(Evas_Object *obj) ed->dirty = 1; pf = ed->freeze; ed->freeze = 0; - _edje_recalc(ed); + _edje_recalc_do(ed); ed->freeze = pf; } @@ -1187,7 +1211,7 @@ edje_object_size_min_restricted_calc(Evas_Object *obj, Evas_Coord *minw, Evas_Co ok = 0; ed->dirty = 1; - _edje_recalc(ed); + _edje_recalc_do(ed); if (reset_maxwh) { maxw = 0; @@ -1291,6 +1315,10 @@ edje_object_part_state_get(const Evas_Object *obj, const char *part, double *val if (val_ret) *val_ret = 0; return ""; } + + /* Need to recalc before providing the object. */ + _edje_recalc_do(ed); + rp = _edje_real_part_recursive_get(ed, (char *)part); if (!rp) { @@ -1335,6 +1363,10 @@ edje_object_part_drag_dir_get(const Evas_Object *obj, const char *part) ed = _edje_fetch(obj); if ((!ed) || (!part)) return EDJE_DRAG_DIR_NONE; + + /* Need to recalc before providing the object. */ + _edje_recalc_do(ed); + rp = _edje_real_part_recursive_get(ed, (char *)part); if (!rp) return EDJE_DRAG_DIR_NONE; if ((rp->part->dragable.x) && (rp->part->dragable.y)) return EDJE_DRAG_DIR_XY; @@ -1399,6 +1431,10 @@ edje_object_part_drag_value_get(const Evas_Object *obj, const char *part, double if (dy) *dy = 0; return; } + + /* Need to recalc before providing the object. */ + _edje_recalc_do(ed); + rp = _edje_real_part_recursive_get(ed, (char *)part); if (!rp) { @@ -1464,6 +1500,10 @@ edje_object_part_drag_size_get(const Evas_Object *obj, const char *part, double if (dh) *dh = 0; return; } + + /* Need to recalc before providing the object. */ + _edje_recalc_do(ed); + rp = _edje_real_part_recursive_get(ed, (char *)part); if (!rp) { @@ -1522,6 +1562,10 @@ edje_object_part_drag_step_get(const Evas_Object *obj, const char *part, double if (dy) *dy = 0; return; } + + /* Need to recalc before providing the object. */ + _edje_recalc_do(ed); + rp = _edje_real_part_recursive_get(ed, (char *)part); if (!rp) { @@ -1580,6 +1624,10 @@ edje_object_part_drag_page_get(const Evas_Object *obj, const char *part, double if (dy) *dy = 0; return; } + + /* Need to recalc before providing the object. */ + _edje_recalc_do(ed); + rp = _edje_real_part_recursive_get(ed, (char *)part); if (!rp) { @@ -2097,5 +2145,5 @@ _edje_real_part_swallow(Edje_Real_Part *rp, Evas_Object *obj_swallow) evas_object_precise_is_inside_set(obj_swallow, 1); rp->edje->dirty = 1; - _edje_recalc(rp->edje); + _edje_recalc_do(rp->edje); } diff --git a/legacy/emotion/src/lib/emotion_smart.c b/legacy/emotion/src/lib/emotion_smart.c index 5943820564..848bc2ea29 100644 --- a/legacy/emotion/src/lib/emotion_smart.c +++ b/legacy/emotion/src/lib/emotion_smart.c @@ -1164,6 +1164,7 @@ _smart_init(void) _smart_color_set, _smart_clip_set, _smart_clip_unset, + NULL, NULL }; smart = evas_smart_class_new(&sc); diff --git a/legacy/evas/src/lib/Evas.h b/legacy/evas/src/lib/Evas.h index 73156d6cf9..e5c1e44428 100644 --- a/legacy/evas/src/lib/Evas.h +++ b/legacy/evas/src/lib/Evas.h @@ -137,7 +137,7 @@ typedef enum _Evas_Aspect_Control } Evas_Aspect_Control; -#define EVAS_SMART_CLASS_VERSION 1 /** the version you have to put into the version field in the smart class struct */ +#define EVAS_SMART_CLASS_VERSION 2 /** the version you have to put into the version field in the smart class struct */ struct _Evas_Smart_Class /** a smart object class */ { const char *name; /** the string name of the class */ @@ -153,6 +153,7 @@ struct _Evas_Smart_Class /** a smart object class */ void (*color_set) (Evas_Object *o, int r, int g, int b, int a); // FIXME: DELETE ME void (*clip_set) (Evas_Object *o, Evas_Object *clip); // FIXME: DELETE ME void (*clip_unset) (Evas_Object *o); // FIXME: DELETE ME + void (*calculate) (Evas_Object *o); const void *data; }; @@ -767,6 +768,11 @@ extern "C" { EAPI void evas_object_smart_callback_add (Evas_Object *obj, const char *event, void (*func) (void *data, Evas_Object *obj, void *event_info), const void *data); EAPI void *evas_object_smart_callback_del (Evas_Object *obj, const char *event, void (*func) (void *data, Evas_Object *obj, void *event_info)); EAPI void evas_object_smart_callback_call (Evas_Object *obj, const char *event, void *event_info); + EAPI void evas_object_smart_changed (Evas_Object *obj); + EAPI void evas_object_smart_need_recalculate_set(Evas_Object *obj, Evas_Bool value); + EAPI Evas_Bool evas_object_smart_need_recalculate_get(Evas_Object *obj); + EAPI void evas_object_smart_calculate (Evas_Object *obj); + /* events */ EAPI void evas_event_freeze (Evas *e); diff --git a/legacy/evas/src/lib/canvas/evas_main.c b/legacy/evas/src/lib/canvas/evas_main.c index 27b3ce6ed8..1a9b34c8bb 100644 --- a/legacy/evas/src/lib/canvas/evas_main.c +++ b/legacy/evas/src/lib/canvas/evas_main.c @@ -70,6 +70,7 @@ evas_new(void) evas_array_setup(&e->pending_objects, 16); evas_array_setup(&e->obscuring_objects, 16); evas_array_setup(&e->temporary_objects, 16); + evas_array_setup(&e->calculate_objects, 16); return e; } diff --git a/legacy/evas/src/lib/canvas/evas_object_smart.c b/legacy/evas/src/lib/canvas/evas_object_smart.c index 811cb813a7..608a8282c7 100644 --- a/legacy/evas/src/lib/canvas/evas_object_smart.c +++ b/legacy/evas/src/lib/canvas/evas_object_smart.c @@ -13,6 +13,7 @@ struct _Evas_Object_Smart Evas_Object_List *contained; int walking_list; Evas_Bool deletions_waiting : 1; + Evas_Bool need_recalculate : 1; }; struct _Evas_Smart_Callback @@ -436,6 +437,163 @@ evas_object_smart_callback_call(Evas_Object *obj, const char *event, void *event evas_object_smart_callbacks_clear(obj); } +/** + * Set the need_recalculate flag of given smart object. + * + * If this flag is set then calculate() callback (method) of the given + * smart object will be called, if one is provided, during render phase + * usually evas_render(). After this step, this flag will be automatically + * unset. + * + * If no calculate() is provided, this flag will be left unchanged. + * + * @note just setting this flag will not make scene dirty and evas_render() + * will have no effect. To do that, use evas_object_smart_changed(), + * that will automatically call this function with 1 as parameter. + * + * @param obj the smart object + * @param value if one want to set or unset the need_recalculate flag. + * + * @ingroup Evas_Smart_Object_Group + */ +EAPI void +evas_object_smart_need_recalculate_set(Evas_Object *obj, Evas_Bool value) +{ + Evas_Object_Smart *o; + MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ); + return; + MAGIC_CHECK_END(); + o = obj->object_data; + MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART); + return; + MAGIC_CHECK_END(); + + value = !!value; + if (o->need_recalculate == value) + return; + o->need_recalculate = value; + + if (!obj->smart.smart->smart_class->calculate) + return; + + /* XXX: objects can be present multiple times in calculate_objects() + * XXX: after a set-unset-set cycle, but it's not a problem since + * XXX: on _evas_render_call_smart_calculate() will check for the flag + * XXX: and it will be unset after the first. + */ + if (o->need_recalculate) + { + Evas *e; + e = obj->layer->evas; + _evas_array_append(&e->calculate_objects, obj); + } + /* TODO: else, remove from array */ +} + +/** + * Get the current value of need_recalculate flag. + * + * @note this flag will be unset during the render phase, after calculate() + * is called if one is provided. If no calculate() is provided, then + * the flag will be left unchanged after render phase. + * + * @param obj the smart object + * @return if flag is set or not. + * + * @ingroup Evas_Smart_Object_Group + */ +EAPI Evas_Bool +evas_object_smart_need_recalculate_get(Evas_Object *obj) +{ + Evas_Object_Smart *o; + MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ); + return; + MAGIC_CHECK_END(); + o = obj->object_data; + MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART); + return; + MAGIC_CHECK_END(); + + return o->need_recalculate; +} + +/** + * Call user provided calculate() and unset need_calculate. + * + * @param obj the smart object + * @return if flag is set or not. + * + * @ingroup Evas_Smart_Object_Group + */ +EAPI void +evas_object_smart_calculate(Evas_Object *obj) +{ + Evas_Object_Smart *o; + MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ); + return; + MAGIC_CHECK_END(); + o = obj->object_data; + MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART); + return; + MAGIC_CHECK_END(); + + if (obj->smart.smart->smart_class->calculate) + obj->smart.smart->smart_class->calculate(obj); + o->need_recalculate = 0; +} + +/** + * Call calculate() on all smart objects that need_recalculate. + * + * @internal + */ +void +evas_call_smarts_calculate(Evas *e) +{ + Evas_Array *calculate; + unsigned int i; + + calculate = &e->calculate_objects; + for (i = 0; i < calculate->count; ++i) + { + Evas_Object *obj; + Evas_Object_Smart *o; + + obj = _evas_array_get(calculate, i); + if (obj->delete_me) + continue; + + o = obj->object_data; + if (o->need_recalculate) + { + obj->smart.smart->smart_class->calculate(obj); + o->need_recalculate = 0; + } + } + + evas_array_flush(calculate); +} + +/** + * Mark smart object as changed, dirty. + * + * This will inform the scene that it changed and needs to be redraw, also + * setting need_recalculate on the given object. + * + * @see evas_object_smart_need_recalculate_set(). + * + * @ingroup Evas_Smart_Object_Group + */ +EAPI void +evas_object_smart_changed(Evas_Object *obj) +{ + MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ); + return; + MAGIC_CHECK_END(); + evas_object_change(obj); + evas_object_smart_need_recalculate_set(obj, 1); +} + /* internal calls */ static void evas_object_smart_callbacks_clear(Evas_Object *obj) diff --git a/legacy/evas/src/lib/canvas/evas_render.c b/legacy/evas/src/lib/canvas/evas_render.c index 8eb6a9670c..c36d4389b4 100644 --- a/legacy/evas/src/lib/canvas/evas_render.c +++ b/legacy/evas/src/lib/canvas/evas_render.c @@ -341,6 +341,8 @@ evas_render_updates_internal(Evas *e, unsigned char make_updates, unsigned char MAGIC_CHECK_END(); if (!e->changed) return NULL; + evas_call_smarts_calculate(e); + /* Check if the modified object mean recalculating every thing */ if (!e->invalidate) _evas_render_check_pending_objects(&e->pending_objects, e); diff --git a/legacy/evas/src/lib/include/evas_private.h b/legacy/evas/src/lib/include/evas_private.h index d2d56710ba..2f6a790a1b 100644 --- a/legacy/evas/src/lib/include/evas_private.h +++ b/legacy/evas/src/lib/include/evas_private.h @@ -288,6 +288,7 @@ struct _Evas Evas_Array pending_objects; Evas_Array obscuring_objects; Evas_Array temporary_objects; + Evas_Array calculate_objects; int delete_grabs; int walking_grabs; @@ -713,6 +714,7 @@ void evas_object_smart_member_lower(Evas_Object *member); void evas_object_smart_member_stack_above(Evas_Object *member, Evas_Object *other); void evas_object_smart_member_stack_below(Evas_Object *member, Evas_Object *other); const Evas_Object_List *evas_object_smart_members_get_direct(const Evas_Object *obj); +void evas_call_smarts_calculate(Evas *e); void *evas_mem_calloc(int size); void evas_object_event_callback_all_del(Evas_Object *obj); void evas_object_event_callback_cleanup(Evas_Object *obj);