Event callback functions not being called (solved)

Description

Button callback function not being called

What MCU/Processor/Board and compiler are you using?

iMX6UL running Linux using framebuffer and touchscreen

Solved issue.

I have finally figure out what is happening. I am creating a cursor to check touchscreen positioning and it appears that this object is actually catching the touch event as it is always at the touch point. This might also be an issue when using a mouse or touchpad if you create a cursor.

To fix this you need to make sure that the cursor object is not clickable by calling.

lv_obj_set_click(cursor_obj, false);

I have the framebuffer set up and working correctly. I am using a slightly modified version evdec.c where some of the #if conditional code blocks have been removed or replaced by runtime if statements.

The input driver is registered and for testing purposes I have a simple 10x10 pixel cursor to make sure the touch events are returning the correct values.

   static lv_indev_drv_t indev_drv;
   lv_indev_drv_init(&indev_drv);
   indev_drv.type = LV_INDEV_TYPE_POINTER;
   indev_drv.read_cb = my_input_read;

   lv_indev_t * my_indev = lv_indev_drv_register(&indev_drv);

   lv_obj_t * cursor_obj =  lv_obj_create(lv_scr_act(), NULL);
   lv_obj_add_style(cursor_obj, LV_OBJ_PART_MAIN, &white_bg_style);
   lv_obj_set_size(cursor_obj, 10, 10);
   lv_indev_set_cursor(my_indev, cursor_obj);

my_input_read() is being called as expected and the cursor follows touch events correctly. For debug purposes I have added some output to the end of the function.

   data->state = evdev_button;

   if(data->point.x < 0)
      data->point.x = 0;
   if(data->point.y < 0)
      data->point.y = 0;
   if(data->point.x >= lv_disp_get_hor_res(drv->disp))
      data->point.x = lv_disp_get_hor_res(drv->disp) - 1;
   if(data->point.y >= lv_disp_get_ver_res(drv->disp))
      data->point.y = lv_disp_get_ver_res(drv->disp) - 1;

   std::cout << "x: " << data->point.x << " y: " << data->point.y << " state: " << (int)data->state << "\n";

   return false;

As expected when touching the screen and moving, state = 1, when not touching the screen state = 0 with the last x,y coordinates being returned.

The test is using a simple button example taken from the documentation,

static void event_handler(lv_obj_t * obj, lv_event_t event)
{
   std::cout << "ev handler\n";
    if(event == LV_EVENT_CLICKED) {
        printf("Clicked\n");
    }
}

void lv_ex_btn_1(void)
{
    lv_obj_t * label;

    lv_obj_t * btn1 = lv_btn_create(lv_scr_act(), NULL);
    lv_obj_set_event_cb(btn1, event_handler);
    lv_obj_align(btn1, NULL, LV_ALIGN_CENTER, 0, 0);

    label = lv_label_create(btn1, NULL);
    lv_label_set_text(label, "Button");
}

The LVGL code is running in its own thread with calls being protected by a mutex, however for the purposes of testing there are no other calls to lv_xxx functions from other threads.

   while(threads_run) {
      gui_mutex.lock();
      lv_tick_inc(5);
      lv_task_handler();
      gui_mutex.unlock();

      usleep(5000);
   }

I should add that LVGL is compiled to a static library and then included in my project. I am not sure if this is causing an issue, however as the callback for the pointer is working I would assume that this is fine.

I can see no reason why my button callback is not being called. I have gone over and over the code looking for some error and I suspect it is going to end up being something so obvious I just can’t see it.

Is there any way to turn on some debugging information in LVGL ?

Update.

I have split the main loop, moving the lv_tick_inc() call to another thread. The documentation does not seem to clear on this, with some examples having both calls in the same loop, but a few posts saying it won’t work.
This still doesn’t solve the problem, however it is nice to see the processor usage drop from 99% to 1-2%. Cursor still moves as expected.

Update 2 - found the issue, but not the cause

Ok I have been looking through the LVGL code and have identified the cause, but not sure why.

In lv_indev.c, the function static void indev_proc_press(lv_indev_proc_t * proc) the code looks for an object at the point. It checks first the sys layer, then the top layer and finally the act layer. If I change the order of the check to act first, then my button callback gets called.

    if(indev_obj_act == NULL) {
        indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_sys(disp), &proc->types.pointer.act_point);
        if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_top(disp),
                                                                          &proc->types.pointer.act_point);
        if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_scr_act(disp),
                                                                          &proc->types.pointer.act_point);
        new_obj_searched = true;
    }

chanegd to

    if(indev_obj_act == NULL) {
        indev_obj_act = lv_indev_search_obj(lv_disp_get_scr_act(disp),
                                                                          &proc->types.pointer.act_point);
        if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_sys(disp), &proc->types.pointer.act_point);
        if(indev_obj_act == NULL) indev_obj_act = lv_indev_search_obj(lv_disp_get_layer_top(disp),
                                                                          &proc->types.pointer.act_point);
        new_obj_searched = true;
    }

So something on either the sys or top layer is grabbing the touch event. I have only created a single button on the act layer. So do I need to do something to cause touch events to get propagated down thought the layers even if I have nothing on the sys and top layer ?

I can’t see anything special in the examples or find anything in the docs.