Page MenuHomePhabricator

genlist callbacks are hostile
Open, Showstopper IssuesPublic

Description

Consider the following code which does something when a given genlist item is realized:

void
item_realize(void *data, ..., void *event_info)
{
   if (data == event_info)
     something();
}

genlist = elm_genlist_add(win);
evas_object_resize(genlist, 100, 100);
evas_object_show(genlist);
it = elm_genlist_item_append(genlist, itc,
                           NULL/* item data */, NULL/* parent */,
                           0, NULL/* func */,
                           NULL/* func data */);
evas_object_smart_callback_add(genlist, "realized", item_realize, it);

Except I lied, this code will actually do nothing. The reason it will do nothing is that the "realized" callback will be emitted during the elm_genlist_item_append call, meaning that it's impossible to use the created item in this callback. This is caused by the genlist region that the item will occupy being visible; were the genlist shown/resized later, the callback will work as expected.

Genlist (and other widget) items should never be directly created from the add() method, as this creates different behaviors which are extremely difficult to document and test for.

As this behavior has been in place for many years now I don't think it can be changed, but for 2.0 it must be removed in order to achieve consistency.

Related Objects

StatusAssignedTask
OpenNone
OpenNone
zmike created this task.Aug 3 2018, 11:38 AM
zmike triaged this task as Showstopper Issues priority.
raster added a subscriber: raster.Aug 3 2018, 10:17 PM

eh? why do this. you just made buggy code by registering a callback after the event has happened. this can happen anywhere and the idea is to set up callbacks early on before the events happen like

genlist = elm_genlist_add(win);
evas_object_smart_callback_add(genlist, "realized", item_realize, it);
evas_object_resize(genlist, 100, 100);
evas_object_show(genlist);
it = elm_genlist_item_append(genlist, itc,
                           NULL/* item data */, NULL/* parent */,
                           0, NULL/* func */,
                           NULL/* func data */);

so that solves the "nothing happens". but then i'm using the it variable before it's assigned - and that is the fatal bit of this piece of code. it wants to rely on data that has not been created yet (the item handle has not been returned yet from elm_genlist_item_append()). that is why you have idem data (NULL there in your example) and the idea always has been that the idem data points to some data struct that contains the relevant backing data for your item and any necessary state/values needed to do your work, so your design of using the item handle itself is the mistake here. use the item data ptr that is not being used. :)