Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(wayland): Wayland useability improvements #204

Merged
merged 1 commit into from Apr 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -1962,18 +1962,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 @@ -2054,9 +2058,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 @@ -2236,6 +2244,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 @@ -2340,6 +2357,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 @@ -2458,4 +2500,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