lv_drivers icon indicating copy to clipboard operation
lv_drivers copied to clipboard

wayland on embedded device does not respond to touch events

Open gorogoro2 opened this issue 2 years ago • 9 comments

Hi all,

I have an application writen with lvgl using the wayland driver that is working fine when I use the performance monitoring on (mem and fps). However when I remove it (the monitoring stuff) the application does not respond to the touch events properly:

#define LV_USE_PERF_MONITOR 0
#define LV_USE_MEM_MONITOR 0

I did an experiment and on the main loop I added the following line: lv_obj_invalidate(lv_scr_act()); and with this the input events are working fine.

Of course this is not a solution.

Is there any way to handle this?

Thank you.

gorogoro2 avatar Oct 28 '22 09:10 gorogoro2

@simplejack-src @WallaceIT could you take a look at this issue?

kisvegabor avatar Oct 30 '22 07:10 kisvegabor

Hi @gorogoro2 ,

how are you calling the wayland cycle function? I.e, are you using or not the lv_wayland_timer_handler function? If yes, have you set up the poll functionality to catch Wayland events in real time?

WallaceIT avatar Oct 31 '22 21:10 WallaceIT

Hi @WallaceIT

Yes, I am using the lv_wayland_timer_handler(); instead of lv_task_handler(); on my loop.

Regarding this statment:

If yes, have you set up the poll functionality to catch Wayland events in real time?

I don't know what are you talking about, probably not. What poll functionality should I setup?

Are you talking about this README.md sleep/wait thing?

Event-driven timer handler
Set LV_WAYLAND_TIMER_HANDLER in lv_drv_conf.h and call lv_wayland_timer_handler() in your timer loop (in place of lv_timer_handler()).

You can now sleep/wait until the next timer/event is ready, e.g.:

/* [After initialization and display creation] */
#include <limits.h>
#include <errno.h>
#include <poll.h>

struct pollfd pfd;
uint32_t time_till_next;
int sleep;

pfd.fd = lv_wayland_get_fd();
pfd.events = POLLIN;

while (1) {
    /* Handle any Wayland/LVGL timers/events */
    time_till_next = lv_wayland_timer_handler();

    /* Run until the last window closes */
    if (!lv_wayland_window_is_open(NULL)) {
        break;
    }

    /* Wait for something interesting to happen */
    if (time_till_next == LV_NO_TIMER_READY) {
        sleep = -1;
    } else if (time_till_next > INT_MAX) {
        sleep = INT_MAX;
    } else {
       sleep = time_till_next;
    }

    while ((poll(&pfd, 1, sleep) < 0) && (errno == EINTR));
}

gorogoro2 avatar Nov 02 '22 10:11 gorogoro2

Update,

I have added the following code to my loop:

    auto time_till_next = lv_wayland_timer_handler();
    auto sleep = time_till_next;
    /* Wait for something interesting to happen */
    if (time_till_next == LV_NO_TIMER_READY) {
        sleep = -1;
    } else if (time_till_next > INT_MAX) {
        sleep = INT_MAX;
    }

    while ((poll(&pfd, 1, sleep) < 0) && (errno == EINTR));

Before I only had:

    lv_wayland_timer_handler();

And this way things work a little better, however far from perfect. Sometimes it just doesn't get the touch event. But when I turn on monitoring:

#define LV_USE_PERF_MONITOR 0

Everything is fine again.

gorogoro2 avatar Nov 02 '22 17:11 gorogoro2

Hi,

please consider that the Wayland input events are received as part of the lv_wayland_timer_handler() function; if this is not called at the right moment, some events might get lost.

Referring to the example in the README, the right moment is detected using the poll function in conjuntion with time_till_next, that is:

  • if no input events are received, next call will be performed when the LVGL core will need to execute something (as the value returned by lv_wayland_timer_handler() is derived from LVGL core, not the Wayland driver)
  • if an input event is received, the poll() function will return as soon as this happens (and in the example reported in the README, this causes an immediate call to lv_wayland_timer_handler()).

After the snippet you posted, what's in your event loop? Ideally, you should have nothing more than that. In particular, no call to lv_timer_handler() shall be performed, as this function is already called as part of lv_wayland_timer_handler().

WallaceIT avatar Nov 03 '22 21:11 WallaceIT

Hi Thank you for your reply.

That's my event loop. I have nothing more there. It runs every 15ms and I'm not calling lv_timer_handler(). could it be the buffer thing being discussed on other issues?

gorogoro2 avatar Nov 08 '22 14:11 gorogoro2

Hi @gorogoro2,

I don't think it's related, as the input events are processed regardless of the status of the input events.

Here is an example main.c, please check if anything rings a bell while I investigate:

#include "lvgl/lvgl.h"
#include "lvgl/demos/lv_demos.h"
#include "lv_drivers/wayland/wayland.h"
#include <unistd.h>
#include <pthread.h>
#include <time.h>
#include <sys/time.h>

#include <limits.h>
#include <errno.h>
#include <poll.h>

int main(void)
{
    struct pollfd pfd;
    uint32_t time_till_next;
    int sleep;

    /*LittlevGL init*/
    lv_init();

    /*Wayland init*/
    lv_wayland_init();

    lv_disp_t * disp = lv_wayland_create_window(1280, 800, "Window Title", NULL);
    lv_disp_set_default(disp);

    /*Create a Demo*/
    lv_demo_widgets();

    pfd.fd = lv_wayland_get_fd();
    pfd.events = POLLIN;

    /*Handle LitlevGL tasks (tickless mode)*/
    while (lv_wayland_window_is_open(NULL)) {

        /* Handle any Wayland/LVGL timers/events */
        time_till_next = lv_wayland_timer_handler();

        /* Wait for something interesting to happen */
        if (time_till_next == LV_NO_TIMER_READY) {
            sleep = -1;
        } else if (time_till_next > INT_MAX) {
            sleep = INT_MAX;
        } else {
           sleep = time_till_next;
        }

        while ((poll(&pfd, 1, sleep) < 0) && (errno == EINTR));
    }

    return 0;
}

/*Set in lv_conf.h as `LV_TICK_CUSTOM_SYS_TIME_EXPR`*/
uint32_t custom_tick_get(void)
{
    static uint64_t start_ms = 0;
    if(start_ms == 0) {
        struct timeval tv_start;
        gettimeofday(&tv_start, NULL);
        start_ms = (tv_start.tv_sec * 1000000 + tv_start.tv_usec) / 1000;
    }

    struct timeval tv_now;
    gettimeofday(&tv_now, NULL);
    uint64_t now_ms;
    now_ms = (tv_now.tv_sec * 1000000 + tv_now.tv_usec) / 1000;

    uint32_t time_ms = now_ms - start_ms;
    return time_ms;
}

WallaceIT avatar Nov 08 '22 18:11 WallaceIT

Probably, #240 is related with my earlier reported ticket #225

symfund avatar Nov 22 '22 06:11 symfund

This issue or pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Apr 20 '23 03:04 stale[bot]