lvgl / lv_drivers

TFT and touch pad drivers for LVGL embedded GUI library
https://docs.lvgl.io/master/porting/index.html
MIT License
291 stars 310 forks source link

wayland on embedded device does not respond to touch events #240

Open gorogoro2 opened 1 year ago

gorogoro2 commented 1 year ago

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.

kisvegabor commented 1 year ago

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

WallaceIT commented 1 year ago

Hi @gorogoro2 ,

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

gorogoro2 commented 1 year ago

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 commented 1 year ago

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.

WallaceIT commented 1 year ago

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:

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().

gorogoro2 commented 1 year ago

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?

WallaceIT commented 1 year ago

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;
}
symfund commented 1 year ago

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

stale[bot] commented 1 year ago

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.