Modal message box

I’m working on a modal message box example for version 6.1.

The way I have it set up, it would be simplest to delete the message box’s parent inside the message box’s LV_EVENT_DELETE handler. The problem is that deleting a parent object inside its child’s event handler currently doesn’t work.

Is there an easy way to do this?

It’s working for me:


void event_handler(lv_obj_t * obj, lv_event_t e)
{
    if(e == LV_EVENT_CLICKED) {
        lv_obj_del(lv_obj_get_parent(obj));
    }
}

...


    lv_obj_t * par = lv_obj_create(lv_scr_act(), NULL);
    lv_obj_set_size(par, 300, 200);

    const char * btns[] = {"Ok", "Cancel", ""};
    lv_obj_t * mbox = lv_mbox_create(par, NULL);
    lv_mbox_add_btns(mbox, btns);
    lv_obj_set_event_cb(mbox, event_handler);

@kisvegabor Thanks!

I could do it that way, but I would like to maintain the existing functionality whereby the message box animates to minimal size and then closes. To avoid duplicating the code, I wanted to delete the parent inside the LV_EVENT_DELETE handler (not LV_EVENT_CLICKED), but that doesn’t work, understandably.

Possibly, a better option is to introduce a new LV_EVENT_BEFORE_DELETE that is called before any of the deletion logic starts running? Then lv_obj_del can check if the object passed to it is still valid after the event call.

EDIT: I just realized the above won’t work due to recursion. When the parent gets deleted, it’s going to try to delete its children, which will result in LV_EVENT_BEFORE_DELETE being sent to the message box again, causing an infinite loop.

Maybe a simpler method is to add a new feature to LittlevGL: asynchronous callbacks.

It would look something like this:

static void my_async_callback(void *user_data)
{
   /* Delete the modal object */
   lv_obj_del((lv_obj_t *)user_data); /* Parent is passed in `user_data` */
}
static void mbox_event_handler(lv_obj_t *obj, lv_event_t evt)
{
    if(evt == LV_EVENT_DELETE) {
        /* We cannot delete an object's parent inside an `LV_EVENT_DELETE` handler. */
        /* Therefore, have the deletion be performed by an async callback. */
        /* This will occur at the beginning of the next `lv_task_handler()`. */
        lv_async_call(my_async_callback, lv_obj_get_parent(obj));
    }
}

If you like the general concept I am working on a PR for 6.1.

It’s a wonderful idea!

I’ve tried to make possible to enable deleting in LV_EVENT_DELETE but it didn’t work due to recursion as you mentioned. I’m still thinking about it but the async API would be very nice anyway!

1 Like

@kisvegabor When will the async lv_event_send function be provided?

@zhwxChaos Did you look at the documentation? This feature has been available since 6.1: https://docs.lvgl.io/latest/en/html/overview/task.html#asynchronous-calls

I read this post and learned about this function.
It is best to provide a API that sends events asynchronously

Like PostMessage and SendMessage in MFC :grin:

Technically you could call lv_event_send inside lv_async_call. Is there a specific thing you’re trying to do that needs asynchronous events?

I did that like this . Inspiration from you :upside_down_face:
static void SendMessage(void* pData)
{
lv_event_t* t_pEvent = (lv_event_t*)pData;

if(m_testMode_ext.m_obj != NULL)
{
	lv_event_send(m_testMode_ext.m_obj, *t_pEvent, NULL);
}

lv_mem_free(pData);

}