Skip to content

Commit

Permalink
feat(wayland): Wayland useability improvements (namely a Wayland-spec…
Browse files Browse the repository at this point in the history
…ific lv_timer_handler) (#204)

Adds/stubs out a few functions allowing for a proper event-driven LVGL usage (when using the Wayland backend).

Co-authored-by: simeplejack-src <example@example.com>
  • Loading branch information
simplejack-src and simeplejack-src committed Apr 12, 2022
1 parent c8d483f commit f46cf5a
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 8 deletions.
41 changes: 41 additions & 0 deletions wayland/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,44 @@ or `false` as `fullscreen` argument.
Even when client-side decorations are enabled at compile time, they can be
disabled at runtime setting the `LV_WAYLAND_DISABLE_WINDOWDECORATION`
environment variable to `1`.

### 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));
}
```
102 changes: 94 additions & 8 deletions wayland/wayland.c
Original file line number Diff line number Diff line change
Expand Up @@ -1984,18 +1984,22 @@ static void _lv_wayland_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv
lv_disp_flush_ready(disp_drv);
}

static void _lv_wayland_cycle(lv_timer_t * tmr)
static void _lv_wayland_handle_input(void)
{
struct window *window = NULL;
bool shall_flush = application.cursor_flush_pending;

LV_UNUSED(tmr);

while (wl_display_prepare_read(application.display) != 0)
{
wl_display_dispatch_pending(application.display);
}

wl_display_read_events(application.display);
wl_display_dispatch_pending(application.display);
}

static void _lv_wayland_handle_output(void)
{
struct window *window;
bool shall_flush = application.cursor_flush_pending;

_LV_LL_READ(&application.window_ll, window)
{
if ((window->shall_close) && (window->close_cb != NULL))
Expand Down Expand Up @@ -2076,9 +2080,13 @@ static void _lv_wayland_cycle(lv_timer_t * tmr)
wl_display_flush(application.display);
application.cursor_flush_pending = false;
}
}

wl_display_read_events(application.display);
wl_display_dispatch_pending(application.display);
static void _lv_wayland_cycle(lv_timer_t * tmr)
{
LV_UNUSED(tmr);
_lv_wayland_handle_input();
_lv_wayland_handle_output();
}

static void _lv_wayland_pointer_read(lv_indev_drv_t *drv, lv_indev_data_t *data)
Expand Down Expand Up @@ -2258,6 +2266,15 @@ void lv_wayland_deinit(void)
_lv_ll_clear(&application.window_ll);
}

/**
* Get Wayland display file descriptor
* @return Wayland display file descriptor
*/
int lv_wayland_get_fd(void)
{
return wl_display_get_fd(application.display);
}

/**
* Create wayland window
* @param hor_res initial horizontal window size in pixels
Expand Down Expand Up @@ -2362,6 +2379,31 @@ void lv_wayland_close_window(lv_disp_t * disp)
window->close_cb = NULL;
}

/**
* Check if a Wayland window is open on the specified display. Otherwise (if
* argument is NULL), check if any Wayland window is open.
* @return true if window open, false otherwise
*/
bool lv_wayland_window_is_open(lv_disp_t * disp)
{
struct window *window;
bool open = false;

if (disp == NULL) {
_LV_LL_READ(&application.window_ll, window) {
if (!window->closed) {
open = true;
break;
}
}
} else {
window = disp->driver->user_data;
open = (!window->closed);
}

return open;
}

/**
* Set/unset window fullscreen mode
* @param disp LVGL display using window to be set/unset fullscreen
Expand Down Expand Up @@ -2480,4 +2522,48 @@ lv_indev_t * lv_wayland_get_touchscreen(lv_disp_t * disp)
return window->lv_indev_touch;
}

#ifdef LV_WAYLAND_TIMER_HANDLER
/**
* Wayland specific timer handler (use in place of LVGL lv_timer_handler)
* @return time until next timer expiry in milliseconds
*/
uint32_t lv_wayland_timer_handler(void)
{
int i;
struct window *window;
lv_timer_t *input_timer[4];
uint32_t time_till_next;

/* Remove cycle timer (as this function is doing its work) */
if (application.cycle_timer != NULL) {
lv_timer_del(application.cycle_timer);
application.cycle_timer = NULL;
}

/* Wayland input handling */
_lv_wayland_handle_input();

/* Ready input timers (to probe for any input recieved) */
_LV_LL_READ(&application.window_ll, window) {
input_timer[0] = window->lv_indev_pointer->driver->read_timer;
input_timer[1] = window->lv_indev_pointeraxis->driver->read_timer;
input_timer[2] = window->lv_indev_keyboard->driver->read_timer;
input_timer[3] = window->lv_indev_touch->driver->read_timer;

for (i = 0; i < 4; i++) {
if (input_timer[i]) {
lv_timer_ready(input_timer[i]);
}
}
}

/* LVGL handling */
time_till_next = lv_timer_handler();

/* Wayland output handling */
_lv_wayland_handle_output();

return time_till_next;
}
#endif
#endif // USE_WAYLAND
5 changes: 5 additions & 0 deletions wayland/wayland.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,19 @@ typedef bool (*lv_wayland_display_close_f_t)(lv_disp_t * disp);
**********************/
void lv_wayland_init(void);
void lv_wayland_deinit(void);
int lv_wayland_get_fd(void);
lv_disp_t * lv_wayland_create_window(lv_coord_t hor_res, lv_coord_t ver_res, char *title,
lv_wayland_display_close_f_t close_cb);
void lv_wayland_close_window(lv_disp_t * disp);
bool lv_wayland_window_is_open(lv_disp_t * disp);
void lv_wayland_window_set_fullscreen(lv_disp_t * disp, bool fullscreen);
lv_indev_t * lv_wayland_get_pointer(lv_disp_t * disp);
lv_indev_t * lv_wayland_get_pointeraxis(lv_disp_t * disp);
lv_indev_t * lv_wayland_get_keyboard(lv_disp_t * disp);
lv_indev_t * lv_wayland_get_touchscreen(lv_disp_t * disp);
#ifdef LV_WAYLAND_TIMER_HANDLER
uint32_t lv_wayland_timer_handler(void);
#endif

/**********************
* MACROS
Expand Down

0 comments on commit f46cf5a

Please sign in to comment.