[Genlist] Improved performance by adding lots of freezes and thaws.
authorDaniel Juyung Seo <juyung.seo@samsung.com>
Wed, 1 Jun 2011 13:42:49 +0000 (22:42 +0900)
committerDaniel Juyung Seo <juyung.seo@samsung.com>
Wed, 1 Jun 2011 13:42:49 +0000 (22:42 +0900)
Applied some other patches from upstream.
Upstream merge with r58951, r59147, r59729, r59866, r59867.

src/lib/elm_genlist.c

index 83c4d8c..a319095 100644 (file)
@@ -279,8 +279,8 @@ struct _Widget_Data
    Pan              *pan;
    Evas_Coord        pan_x, pan_y, w, h, minw, minh, realminw, prev_viewport_w;
    Ecore_Job        *calc_job, *update_job;
-   Ecore_Idler      *queue_idler;
-   Ecore_Idler      *must_recalc_idler;
+   Ecore_Idle_Enterer *queue_idle_enterer;
+   Ecore_Idler        *must_recalc_idler;
    Eina_List        *queue, *selected;
    Elm_Genlist_Item *show_item;
    Elm_Genlist_Item *last_selected_item;
@@ -759,6 +759,7 @@ _del_hook(Evas_Object *obj)
    _item_cache_zero(wd);
    if (wd->calc_job) ecore_job_del(wd->calc_job);
    if (wd->update_job) ecore_job_del(wd->update_job);
+   if (wd->queue_idle_enterer) ecore_idle_enterer_del(wd->queue_idle_enterer);
    if (wd->changed_job) ecore_job_del(wd->changed_job);
    if (wd->must_recalc_idler) ecore_idler_del(wd->must_recalc_idler);
    if (wd->multi_timer) ecore_timer_del(wd->multi_timer);
@@ -795,6 +796,7 @@ _theme_hook(Evas_Object *obj)
    Widget_Data *wd = elm_widget_data_get(obj);
    Item_Block *itb;
    if (!wd) return;
+   evas_event_freeze(evas_object_evas_get(wd->obj));
    _item_cache_zero(wd);
    _elm_widget_mirrored_reload(obj);
    _mirrored_set(obj, elm_widget_mirrored_get(obj));
@@ -818,6 +820,8 @@ _theme_hook(Evas_Object *obj)
    if (wd->calc_job) ecore_job_del(wd->calc_job);
    wd->calc_job = ecore_job_add(_calc_job, wd);
    _sizing_eval(obj);
+   evas_event_thaw(evas_object_evas_get(wd->obj));
+   evas_event_thaw_eval(evas_object_evas_get(wd->obj));
 }
 
 static void
@@ -1002,6 +1006,9 @@ _item_subitems_clear(Elm_Genlist_Item *it)
 static void
 _item_del(Elm_Genlist_Item *it)
 {
+   Evas_Object *tob = it->wd->obj;
+
+   evas_event_freeze(evas_object_evas_get(tob));
    elm_widget_item_pre_notify_del(it);
    elm_genlist_item_subitems_clear(it);
    it->wd->walking -= it->walking;
@@ -1034,6 +1041,9 @@ _item_del(Elm_Genlist_Item *it)
    if (it->tooltip.del_cb)
      it->tooltip.del_cb((void *)it->tooltip.data, it->base.widget, it);
 
+   evas_event_thaw(evas_object_evas_get(tob));
+   evas_event_thaw_eval(evas_object_evas_get(tob));
+
    elm_widget_item_del(it);
    it->wd->total_num--;  // todo : remove
 }
@@ -1696,16 +1706,21 @@ _mode_finished_signal_cb(void        *data,
    Elm_Genlist_Item *it = data;
    if ((it->delete_me) || (!it->realized) || (!it->mode_view)) return;
    char buf[1024];
+   Evas *te = evas_object_evas_get(obj);
 
+   evas_event_freeze(te);
    it->nocache = EINA_FALSE;
    _mode_item_unrealize(it);
    snprintf(buf, sizeof(buf), "elm,state,%s,passive,finished", it->wd->mode_type);
    edje_object_signal_callback_del_full(obj, buf, "elm", _mode_finished_signal_cb, it);
+   evas_event_thaw(te);
+   evas_event_thaw_eval(te);
 }
 
 static void
 _item_cache_clean(Widget_Data *wd)
 {
+   evas_event_freeze(evas_object_evas_get(wd->obj));
    while ((wd->item_cache) && (wd->item_cache_count > wd->item_cache_max))
      {
         Item_Cache *itc;
@@ -1719,6 +1734,8 @@ _item_cache_clean(Widget_Data *wd)
         if (itc->item_style) eina_stringshare_del(itc->item_style);
         free(itc);
      }
+   evas_event_thaw(evas_object_evas_get(wd->obj));
+   evas_event_thaw_eval(evas_object_evas_get(wd->obj));
 }
 
 static void
@@ -1735,18 +1752,26 @@ _item_cache_add(Elm_Genlist_Item *it)
 {
    Item_Cache *itc;
 
+   evas_event_freeze(evas_object_evas_get(it->wd->obj));
    if (it->wd->item_cache_max <= 0)
      {
         evas_object_del(it->base.view);
         it->base.view = NULL;
         evas_object_del(it->spacer);
         it->spacer = NULL;
+        evas_event_thaw(evas_object_evas_get(it->wd->obj));
+        evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
         return;
      }
 
    it->wd->item_cache_count++;
    itc = calloc(1, sizeof(Item_Cache));
-   if (!itc) return;
+   if (!itc)
+     {
+        evas_event_thaw(evas_object_evas_get(it->wd->obj));
+        evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
+        return;
+     }
    it->wd->item_cache = eina_inlist_prepend(it->wd->item_cache,
                                             EINA_INLIST_GET(itc));
    itc->spacer = it->spacer;
@@ -1794,6 +1819,8 @@ _item_cache_add(Elm_Genlist_Item *it)
    evas_object_event_callback_del_full(itc->base_view, EVAS_CALLBACK_MULTI_MOVE,
                                        _multi_move, it);
    _item_cache_clean(it->wd);
+   evas_event_thaw(evas_object_evas_get(it->wd->obj));
+   evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
 }
 
 static Item_Cache *
@@ -1844,6 +1871,7 @@ _item_realize(Elm_Genlist_Item *it,
    Item_Cache *itc = NULL;
 
    if ((it->realized) || (it->delete_me)) return;
+   evas_event_freeze(evas_object_evas_get(it->wd->obj));
    it->order_num_in = in;
    if (it->wd->move_effect_mode == ELM_GENLIST_ITEM_MOVE_EFFECT_DELETE)        calc = EINA_FALSE;
    if ((it->nocache) && (!it->renamed))
@@ -2113,6 +2141,8 @@ _item_realize(Elm_Genlist_Item *it,
    it->want_unrealize = EINA_FALSE;
 
    if (itc) _item_cache_free(itc);
+   evas_event_thaw(evas_object_evas_get(it->wd->obj));
+   evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
    if (!calc) evas_object_smart_callback_call(it->base.widget, "realized", it);
    if ((!calc) && (it->wd->edit_mode) && (it->flags != ELM_GENLIST_ITEM_GROUP))
      {
@@ -2131,6 +2161,7 @@ _item_unrealize(Elm_Genlist_Item *it, Eina_Bool calc)
 
    if (!it->realized) return;
    if (it->wd->reorder_it && it->wd->reorder_it == it) return;
+   evas_event_freeze(evas_object_evas_get(it->wd->obj));
    if (!calc) evas_object_smart_callback_call(it->base.widget, "unrealized", it);
    if (it->long_timer)
      {
@@ -2162,6 +2193,8 @@ _item_unrealize(Elm_Genlist_Item *it, Eina_Bool calc)
    it->states = NULL;
    it->realized = EINA_FALSE;
    it->want_unrealize = EINA_FALSE;
+   evas_event_thaw(evas_object_evas_get(it->wd->obj));
+   evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
    if (it->wd->edit_mode) _effect_item_unrealize(it);
 }
 
@@ -2177,6 +2210,7 @@ _item_block_recalc(Item_Block *itb,
    Eina_Bool showme = EINA_FALSE, changed = EINA_FALSE;
    Evas_Coord y = 0;
 
+   evas_event_freeze(evas_object_evas_get(itb->wd->obj));
    itb->num = in;
    EINA_LIST_FOREACH(itb->items, l, it)
      {
@@ -2212,7 +2246,9 @@ _item_block_recalc(Item_Block *itb,
    itb->minh = minh;
    itb->changed = EINA_FALSE;
    /* force an evas norender to garbage collect deleted objects */
-   if (norender) evas_norender(evas_object_evas_get(itb->wd->obj));
+   //if (norender) evas_norender(evas_object_evas_get(itb->wd->obj));
+   evas_event_thaw(evas_object_evas_get(itb->wd->obj));
+   evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
    return showme;
 }
 
@@ -2225,6 +2261,7 @@ _item_block_realize(Item_Block *itb,
    Elm_Genlist_Item *it;
 
    if (itb->realized) return;
+   evas_event_freeze(evas_object_evas_get(itb->wd->obj));
    EINA_LIST_FOREACH(itb->items, l, it)
      {
         if (it->delete_me) continue;
@@ -2233,6 +2270,8 @@ _item_block_realize(Item_Block *itb,
      }
    itb->realized = EINA_TRUE;
    itb->want_unrealize = EINA_FALSE;
+   evas_event_thaw(evas_object_evas_get(itb->wd->obj));
+   evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
 }
 
 static void
@@ -2243,6 +2282,7 @@ _item_block_unrealize(Item_Block *itb)
    Eina_Bool dragging = EINA_FALSE;
 
    if (!itb->realized) return;
+   evas_event_freeze(evas_object_evas_get(itb->wd->obj));
    EINA_LIST_FOREACH(itb->items, l, it)
      {
         if (it->flags != ELM_GENLIST_ITEM_GROUP)
@@ -2263,6 +2303,8 @@ _item_block_unrealize(Item_Block *itb)
      }
    else
      itb->want_unrealize = EINA_FALSE;
+   evas_event_thaw(evas_object_evas_get(itb->wd->obj));
+   evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
 }
 
 static int
@@ -2355,9 +2397,12 @@ _item_position(Elm_Genlist_Item *it, Evas_Object *view)
    if (!it) return;
    if (!view) return;
 
+   evas_event_freeze(evas_object_evas_get(it->wd->obj));
    evas_object_resize(view, it->w, it->h);
    evas_object_move(view, it->scrl_x, it->scrl_y);
    evas_object_show(view);
+   evas_event_thaw(evas_object_evas_get(it->wd->obj));
+   evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
 }
 
 static void
@@ -2370,6 +2415,7 @@ _item_block_position(Item_Block *itb,
    Evas_Coord y = 0, ox, oy, ow, oh, cvx, cvy, cvw, cvh;
    int vis = 0;
 
+   evas_event_freeze(evas_object_evas_get(itb->wd->obj));
    evas_object_geometry_get(itb->wd->pan_smart, &ox, &oy, &ow, &oh);
    evas_output_viewport_get(evas_object_evas_get(itb->wd->obj), &cvx, &cvy,
                             &cvw, &cvh);
@@ -2465,6 +2511,8 @@ _item_block_position(Item_Block *itb,
           }
         y += it->h;
      }
+   evas_event_thaw(evas_object_evas_get(itb->wd->obj));
+   evas_event_thaw_eval(evas_object_evas_get(itb->wd->obj));
 }
 
 static void
@@ -2485,6 +2533,7 @@ _group_items_recalc(void *data)
    Eina_List *l;
    Elm_Genlist_Item *git;
 
+   evas_event_freeze(evas_object_evas_get(wd->obj));
    EINA_LIST_FOREACH(wd->group_items, l, git)
      {
         if (git->want_realize)
@@ -2502,6 +2551,8 @@ _group_items_recalc(void *data)
                _item_unrealize(git, EINA_FALSE);
           }
      }
+   evas_event_thaw(evas_object_evas_get(wd->obj));
+   evas_event_thaw_eval(evas_object_evas_get(wd->obj));
 }
 
 static Eina_Bool
@@ -2535,6 +2586,7 @@ _calc_job(void *data)
 //        if (wd->height_for_width) changed = EINA_TRUE;
      }
 
+   evas_event_freeze(evas_object_evas_get(wd->obj));
    EINA_INLIST_FOREACH(wd->blocks, itb)
      {
         Eina_Bool showme = EINA_FALSE;
@@ -2645,6 +2697,8 @@ _calc_job(void *data)
      }
    wd->calc_job = NULL;
    evas_object_smart_changed(wd->pan_smart);
+   evas_event_thaw(evas_object_evas_get(wd->obj));
+   evas_event_thaw_eval(evas_object_evas_get(wd->obj));
 }
 
 static void
@@ -2657,6 +2711,8 @@ _update_job(void *data)
    if (!wd) return;
    wd->update_job = NULL;
    num = 0;
+
+   evas_event_freeze(evas_object_evas_get(wd->obj));
    EINA_INLIST_FOREACH(wd->blocks, itb)
      {
         Evas_Coord itminw, itminh;
@@ -2709,6 +2765,8 @@ _update_job(void *data)
         if (wd->calc_job) ecore_job_del(wd->calc_job);
         wd->calc_job = ecore_job_add(_calc_job, wd);
      }
+   evas_event_thaw(evas_object_evas_get(wd->obj));
+   evas_event_thaw_eval(evas_object_evas_get(wd->obj));
 }
 
 static void
@@ -2938,6 +2996,7 @@ _pan_calculate(Evas_Object *obj)
    Elm_Genlist_Item *git;
    Eina_List *l;
 
+   evas_event_freeze(evas_object_evas_get(obj));
    evas_object_geometry_get(obj, &ox, &oy, &ow, &oh);
    evas_output_viewport_get(evas_object_evas_get(obj), &cvx, &cvy, &cvw, &cvh);
    EINA_LIST_FOREACH(sd->wd->group_items, l, git)
@@ -2992,6 +3051,8 @@ _pan_calculate(Evas_Object *obj)
         }
       else _item_auto_scroll(sd->wd);
    sd->wd->contracting = EINA_FALSE;
+   evas_event_thaw(evas_object_evas_get(obj));
+   evas_event_thaw_eval(evas_object_evas_get(obj));
  }
 
 static void
@@ -3088,6 +3149,7 @@ _mode_item_realize(Elm_Genlist_Item *it)
 
    if ((it->mode_view) || (it->delete_me)) return;
 
+   evas_event_freeze(evas_object_evas_get(it->wd->obj));
    it->mode_view = edje_object_add(evas_object_evas_get(it->base.widget));
    edje_object_scale_set(it->mode_view,
                          elm_widget_scale_get(it->base.widget) *
@@ -3187,6 +3249,8 @@ _mode_item_realize(Elm_Genlist_Item *it)
                             it->base.view);
 
    it->want_unrealize = EINA_FALSE;
+   evas_event_thaw(evas_object_evas_get(it->wd->obj));
+   evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
 }
 
 static void
@@ -3196,6 +3260,7 @@ _mode_item_unrealize(Elm_Genlist_Item *it)
    Evas_Object *icon;
    if (!it->mode_view) return;
 
+   evas_event_freeze(evas_object_evas_get(it->wd->obj));
    elm_widget_stringlist_free(it->mode_labels);
    it->mode_labels = NULL;
    elm_widget_stringlist_free(it->mode_icons);
@@ -3212,6 +3277,8 @@ _mode_item_unrealize(Elm_Genlist_Item *it)
 
    if (wd->mode_item == it)
      wd->mode_item = NULL;
+   evas_event_thaw(evas_object_evas_get(it->wd->obj));
+   evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
 }
 
 static void
@@ -3233,8 +3300,11 @@ _item_mode_set(Elm_Genlist_Item *it)
    elm_smart_scroller_hold_set(wd->scr, EINA_TRUE);
    wd->scr_hold_timer = ecore_timer_add(0.1, _scr_hold_timer_cb, wd);
 
+   evas_event_freeze(evas_object_evas_get(it->wd->obj));
    _mode_item_realize(it);
    _item_position(it, it->mode_view);
+   evas_event_thaw(evas_object_evas_get(it->wd->obj));
+   evas_event_thaw_eval(evas_object_evas_get(it->wd->obj));
 
    snprintf(buf, sizeof(buf), "elm,state,%s,active", wd->mode_type);
    edje_object_signal_emit(it->mode_view, buf, "elm");
@@ -3533,6 +3603,7 @@ _queue_process(Widget_Data *wd,
    double t0, t;
 
    t0 = ecore_time_get();
+   evas_event_freeze(evas_object_evas_get(wd->obj));
    for (n = 0; (wd->queue) && (n < 128); n++)
      {
         Elm_Genlist_Item *it;
@@ -3554,11 +3625,13 @@ _queue_process(Widget_Data *wd,
              if ((t - t0) > (ecore_animator_frametime_get())) break;
           }
      }
+   evas_event_thaw(evas_object_evas_get(wd->obj));
+   evas_event_thaw_eval(evas_object_evas_get(wd->obj));
    return n;
 }
 
 static Eina_Bool
-_item_idler(void *data)
+_idle_process(void *data, Eina_Bool *wakeup)
 {
    Widget_Data *wd = data;
 
@@ -3566,23 +3639,34 @@ _item_idler(void *data)
    //static double q_start = 0.0;
    //if (q_start == 0.0) q_start = ecore_time_get();
    //xxx
-
-   if (_queue_process(wd, 1) > 0)
-     {
-        if (wd->calc_job) ecore_job_del(wd->calc_job);
-        wd->calc_job = ecore_job_add(_calc_job, wd);
-     }
+   if (_queue_process(wd, 1) > 0) *wakeup = EINA_TRUE;
    if (!wd->queue)
      {
         //xxx
         //printf("PROCESS TIME: %3.3f\n", ecore_time_get() - q_start);
         //xxx
-        wd->queue_idler = NULL;
         return ECORE_CALLBACK_CANCEL;
      }
    return ECORE_CALLBACK_RENEW;
 }
 
+static Eina_Bool
+_item_idle_enterer(void *data)
+{
+   Widget_Data *wd = data;
+   Eina_Bool wakeup = EINA_FALSE;
+   Eina_Bool ok = _idle_process(data, &wakeup);
+
+   if (wakeup)
+     {
+        // wake up mainloop
+        if (wd->calc_job) ecore_job_del(wd->calc_job);
+        wd->calc_job = ecore_job_add(_calc_job, wd);
+     }
+   if (ok == ECORE_CALLBACK_CANCEL) wd->queue_idle_enterer = NULL;
+   return ok;
+}
+
 static void
 _item_queue(Widget_Data      *wd,
             Elm_Genlist_Item *it)
@@ -3590,16 +3674,22 @@ _item_queue(Widget_Data      *wd,
    if (it->queued) return;
    it->queued = EINA_TRUE;
    wd->queue = eina_list_append(wd->queue, it);
+// FIXME: why does a freeze then thaw here cause some genlist
+// elm_genlist_item_append() to be much much slower?
+//   evas_event_freeze(evas_object_evas_get(wd->obj));
    while ((wd->queue) && ((!wd->blocks) || (!wd->blocks->next)))
      {
-        if (wd->queue_idler)
+        if (wd->queue_idle_enterer)
           {
-             ecore_idler_del(wd->queue_idler);
-             wd->queue_idler = NULL;
+             ecore_idle_enterer_del(wd->queue_idle_enterer);
+             wd->queue_idle_enterer = NULL;
           }
         _queue_process(wd, 0);
      }
-   if (!wd->queue_idler) wd->queue_idler = ecore_idler_add(_item_idler, wd);
+//   evas_event_thaw(evas_object_evas_get(wd->obj));
+//   evas_event_thaw_eval(evas_object_evas_get(wd->obj));
+   if (!wd->queue_idle_enterer)
+      wd->queue_idle_enterer = ecore_idle_enterer_add(_item_idle_enterer, wd);
 }
 
 /**
@@ -3847,6 +3937,7 @@ elm_genlist_clear(Evas_Object *obj)
           }
         return;
      }
+   evas_event_freeze(evas_object_evas_get(wd->obj));
    while (wd->items)
      {
         Elm_Genlist_Item *it = ELM_GENLIST_ITEM_FROM_INLIST(wd->items);
@@ -3887,10 +3978,10 @@ elm_genlist_clear(Evas_Object *obj)
         ecore_job_del(wd->calc_job);
         wd->calc_job = NULL;
      }
-   if (wd->queue_idler)
+   if (wd->queue_idle_enterer)
      {
-        ecore_idler_del(wd->queue_idler);
-        wd->queue_idler = NULL;
+        ecore_idle_enterer_del(wd->queue_idle_enterer);
+        wd->queue_idle_enterer = NULL;
      }
    if (wd->must_recalc_idler)
      {
@@ -3928,6 +4019,8 @@ elm_genlist_clear(Evas_Object *obj)
         evas_object_smart_callback_call(wd->pan_smart, "changed", NULL);
      }
    _sizing_eval(obj);
+   evas_event_thaw(evas_object_evas_get(wd->obj));
+   evas_event_thaw_eval(evas_object_evas_get(wd->obj));
 }
 
 /**