Feat/wayland driver binding

O-
3mo ago
+262-26

Summary

Adds LVGL's native Wayland driver as a working alternative to the SDL
driver, and fixes a regression that's been silently keeping every LVGL
desktop window driver (SDL included) out of the Python bindings entirely.

lv_sdl_window_create() can segfault deep inside the proprietary NVIDIA
driver as soon as a real window is presented, on Wayland sessions with an
NVIDIA GPU. This is #46, filed in 2019 and auto-closed stale in 2020
without a fix - I hit it firsthand and confirmed it's still present today,
5+ years later. The maintainers' own diagnosis at the time: this binding's
SDL driver deliberately runs SDL on MicroPython's own thread (for LVGL
binding thread-safety), unlike the standalone lv_drivers SDL simulator,
which refreshes on its own dedicated thread and doesn't hit the bug.
LVGL's native Wayland driver (lvgl/src/drivers/wayland) sidesteps the
whole crash class: it presents via wl_shm and never creates a GL/EGL
context at all. It's already upstream in LVGL, just never wired into this
binding's build or exposed to Python - both are fixed here.

While wiring Wayland up, I found gen_mpy.py hasn't been able to see any
desktop window driver - SDL included - since 3f32386 (2026-05-02) switched
its input from lvgl.h (which pulls in src/drivers/lv_drivers.h) to
lvgl_private.h (which only pulls in _private.h counterparts for the
libinput/evdev drivers). lv.sdl_window_create etc. have simply not
existed as Python attributes since then, regardless of LV_USE_SDL - this
also silently broke this repo's own tests/testdisplay.py's interactive
mode. Fixed by gen/lv_mpy_drivers.h, which gen_mpy now parses instead: it
pulls in lvgl_private.h and src/drivers/lv_drivers.h, so any driver
enabled in lv_conf.h gets bound the same way widgets already are.
gen/lv_mpy_drivers.c adds a binding-friendly
lv_wayland_window_create_simple() wrapper, since gen_mpy can't bind
lv_wayland_window_create()'s close-callback parameter (no
user_data-carrying struct argument for it to hook into).

micropython.mk autodetects wayland-client/wayland-cursor/xkbcommon
via pkg-config, the same pattern SDL already uses, and generates the
xdg-shell protocol glue at build time via wayland-scanner into
$(BUILD) - nothing checked into the lvgl submodule. LV_COLOR_DEPTH is
forced to 32 only when Wayland is actually compiled in, since
lv_wayland_window_create() hangs rather than failing fast on a
compositor that doesn't advertise wl_shm RGB565 support (optional
per-spec, unlike XRGB8888/ARGB8888).

This is based on #411, which this build needed to even link against a
current MicroPython. Expecting that one to land first.

Testing

Rather than duplicating tests/display/tests/indev per driver,
testdisplay.py/testrunner.py/lv_utils.py gain a DRIVER selector
("sdl"/"wayland", or the LV_MP_TEST_DRIVER env var), so the existing
suites run against either driver unchanged. Verified
tests/display/basic.py against Wayland via a headless weston
compositor - output matches the existing .exp byte for byte, no new
expected-output file needed. CI installs the Wayland build deps and
weston, and runs tests/display against Wayland in a new job step.

Doesn't attempt to fix the underlying NVIDIA/SDL bug itself (#46) - a
proprietary-driver issue outside this repo's control - or the window
decorations abort (lv_wl_window_decorations.c, unrelated, left at
upstream's own default of off).

Generative AI

I used generative AI tools when creating this PR, but a human has checked
the code and is responsible for the code and the description above.


Summary by cubic

Adds LVGL’s Wayland window driver as a safe alternative to SDL on Linux, restores desktop driver APIs to the Python bindings, and ensures compatibility with MicroPython 1.29.

  • New Features

    • Wayland driver binding: lv.wayland_window_create_simple(...), lv.wayland_pointer_create(), lv.wayland_keyboard_create(), lv.wayland_timer_handler(), lv.wayland_window_is_open().
    • Auto-enable when wayland-client, wayland-cursor, xkbcommon, wayland-scanner, and wayland-protocols are found via pkg-config; generates xdg-shell glue at build time.
    • Event loop supports a driver-specific timer via handler_cb for Wayland.
    • Tests/CI can run against wayland via LV_MP_TEST_DRIVER; CI uses headless weston.
    • Sets LV_COLOR_DEPTH=32 when Wayland is compiled to ensure a supported wl_shm format.
  • Bug Fixes

    • Restores SDL/desktop driver bindings by feeding gen_mpy gen/lv_mpy_drivers.h (includes src/drivers/lv_drivers.h) and adds a lv_wayland_window_create_simple() wrapper to avoid an unbindable close-callback.
    • Builds with MicroPython 1.29 by using mp_obj_int_to_bytes() with version guards.