Skip to content
Open
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
20 changes: 19 additions & 1 deletion .github/workflows/micropython_lvgl_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ jobs:
sudo add-apt-repository -y "deb http://archive.ubuntu.com/ubuntu `lsb_release -sc` main universe restricted multiverse"
sudo apt-get update -y -qq
sudo apt-get install libsdl2-dev parallel libfreetype-dev librlottie-dev libavformat-dev libavcodec-dev libswscale-dev libavutil-dev build-essential libc-bin
sudo apt-get install libwayland-dev libwayland-bin wayland-protocols libxkbcommon-dev weston
python3 -m pip install pillow

- name: Clone lv_micropython
Expand Down Expand Up @@ -102,7 +103,24 @@ jobs:
- name: Run MicroPython-LVGL API Tests
if: matrix.port == 'unix'
run: MICROPY_MICROPYTHON=ports/unix/build-lvgl/micropython ./tests/run-tests.py -d user_modules/lv_binding_micropython/tests/api


# Runs the same tests/display suite as the (manual, HIL-oriented) SDL
# path, against the Wayland driver instead, via a headless compositor.
# See README.md's "Wayland driver" section for why this driver exists.
- name: Run MicroPython-LVGL Wayland Display Tests
if: matrix.port == 'unix'
run: |
mkdir -p /tmp/xdg-runtime && chmod 0700 /tmp/xdg-runtime
export XDG_RUNTIME_DIR=/tmp/xdg-runtime
weston --backend=headless --socket=wayland-ci --idle-time=0 &
WESTON_PID=$!
sleep 1

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The sleep 1 before running Wayland tests creates a race condition. On a loaded CI runner, Weston may take more than 1 second to initialize its socket, causing the test command to fail with a connection error. Replace the fixed sleep with a polling loop that waits for the socket file $XDG_RUNTIME_DIR/wayland-ci to appear (with a timeout).

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/micropython_lvgl_ci.yml, line 117:

<comment>The `sleep 1` before running Wayland tests creates a race condition. On a loaded CI runner, Weston may take more than 1 second to initialize its socket, causing the test command to fail with a connection error. Replace the fixed sleep with a polling loop that waits for the socket file `$XDG_RUNTIME_DIR/wayland-ci` to appear (with a timeout).</comment>

<file context>
@@ -102,7 +103,24 @@ jobs:
+        export XDG_RUNTIME_DIR=/tmp/xdg-runtime
+        weston --backend=headless --socket=wayland-ci --idle-time=0 &
+        WESTON_PID=$!
+        sleep 1
+        WAYLAND_DISPLAY=wayland-ci LV_MP_TEST_DRIVER=wayland \
+          MICROPY_MICROPYTHON=ports/unix/build-lvgl/micropython \
</file context>

WAYLAND_DISPLAY=wayland-ci LV_MP_TEST_DRIVER=wayland \
MICROPY_MICROPYTHON=ports/unix/build-lvgl/micropython \
./tests/run-tests.py user_modules/lv_binding_micropython/tests/display/basic*.py -r .
kill $WESTON_PID


- name: Process Tests Artifacts

if: matrix.port == 'unix'
Expand Down
51 changes: 51 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,57 @@ Driver code is under `/driver` directory.
Drivers can also be implemented in pure MicroPython, by providing callbacks (`disp_drv.flush_cb`, `indev_drv.read_cb` etc.)
Currently the supported ILI9341, FT6X36 and XPT2046 are pure micropython drivers.

### Wayland driver

On Linux, LVGL also ships a native Wayland driver (`lvgl/src/drivers/wayland`) as
an alternative to SDL. Usage mirrors the SDL example above:

```python
import lvgl as lv
lv.init()

from lv_utils import event_loop

WIDTH = 480
HEIGHT = 320

event_loop = event_loop()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The Wayland example creates a default event_loop (which calls lv.task_handler = lv_timer_handler() periodically) AND also calls lv.wayland_timer_handler() in the manual while loop. The event_loop source explicitly says lv.wayland_timer_handler() must be used instead of the plain handler since it wraps the same inner call with Wayland event processing. Remove the event_loop line — the manual while loop with lv.wayland_timer_handler() is the complete replacement.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At README.md, line 195:

<comment>The Wayland example creates a default event_loop (which calls lv.task_handler = lv_timer_handler() periodically) AND also calls lv.wayland_timer_handler() in the manual while loop. The event_loop source explicitly says lv.wayland_timer_handler() must be used *instead of* the plain handler since it wraps the same inner call with Wayland event processing. Remove the event_loop line — the manual while loop with lv.wayland_timer_handler() is the complete replacement.</comment>

<file context>
@@ -178,6 +178,57 @@ Driver code is under `/driver` directory.
+WIDTH = 480
+HEIGHT = 320
+
+event_loop = event_loop()
+disp_drv = lv.wayland_window_create_simple(WIDTH, HEIGHT, "MicroPython-LVGL")
+pointer = lv.wayland_pointer_create()
</file context>

disp_drv = lv.wayland_window_create_simple(WIDTH, HEIGHT, "MicroPython-LVGL")
pointer = lv.wayland_pointer_create()
keyboard = lv.wayland_keyboard_create()

while lv.wayland_window_is_open(disp_drv):
lv.wayland_timer_handler()
```

`lv.wayland_window_create_simple` takes only `hor_res, ver_res, title` (no
close-callback - `gen_mpy.py` can't bind `lv_wayland_window_create()`'s C
callback param, see [gen/lv_mpy_drivers.h](gen/lv_mpy_drivers.h)). Poll
`lv.wayland_window_is_open()` to detect the window closing instead.

**Why**: `lv_sdl_window_create()` can segfault deep in the NVIDIA GL/EGL
driver as soon as a real window is presented, on Wayland sessions with the
proprietary NVIDIA driver - a long-standing upstream issue
([#46](https://github.com/lvgl/lv_binding_micropython/issues/46)), caused by
this binding's SDL driver running on MicroPython's own thread rather than a
dedicated one. LVGL's native Wayland driver avoids it entirely: it presents
via `wl_shm` and never touches GL/EGL. It was already upstream in LVGL, just
never wired into this binding's build or exposed to Python.

While wiring it up we also found no LVGL desktop driver (SDL included) has
been reachable from Python at all since
[3f32386](https://github.com/lvgl/lv_binding_micropython/commit/3f32386af5f3ee9ba37d9282b1926e39b74162d7)
(2026-05-02) switched `gen_mpy.py`'s input from `lvgl.h` to
`lvgl_private.h`, which doesn't pull in `src/drivers/lv_drivers.h` - a silent
regression, also breaking `tests/testdisplay.py`'s interactive mode. Fixed
the same way here: gen_mpy now parses
[gen/lv_mpy_drivers.h](gen/lv_mpy_drivers.h) instead, which includes both.

**Build requirements**: autodetected via `pkg-config` in `micropython.mk`
like SDL - left disabled if `wayland-client`/`wayland-cursor`/`xkbcommon`/
`wayland-scanner`/`wayland-protocols` aren't found. `LV_COLOR_DEPTH` must
stay `32`; see the comment above its definition in `lv_conf.h`.

### Where are the drivers?

LVGL C drivers and MicroPython drivers (either C or Python) are **separate and independent** from each other.
Expand Down
6 changes: 6 additions & 0 deletions gen/gen_mpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -1832,7 +1832,13 @@ def register_int_ptr_type(convertor, *types):

unsigned long long val = 0;
bool big_endian = !(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__);
// mp_obj_int_to_bytes() replaced mp_obj_int_to_bytes_impl() in MicroPython
// 1.29 (commit e00daa3a), adding is_signed and overflow_check parameters.
#if MICROPY_VERSION >= MICROPY_MAKE_VERSION(1, 29, 0)
mp_obj_int_to_bytes(obj, sizeof(val), (byte*)&val, big_endian, false, false);
#else
mp_obj_int_to_bytes_impl(obj, big_endian, sizeof(val), (byte*)&val);
#endif
return val;
}

Expand Down
17 changes: 17 additions & 0 deletions gen/lv_mpy_drivers.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* @file lv_mpy_drivers.c
*
* Implementation of the binding-friendly driver wrappers declared for
* gen_mpy.py in lv_mpy_drivers.h. See that file for why this is needed.
*/

#include "lvgl.h"

#if LV_USE_WAYLAND

lv_display_t * lv_wayland_window_create_simple(uint32_t hor_res, uint32_t ver_res, char * title)
{
return lv_wayland_window_create(hor_res, ver_res, title, NULL);
}

#endif
36 changes: 36 additions & 0 deletions gen/lv_mpy_drivers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* @file lv_mpy_drivers.h
*
* gen_mpy.py builds its binding AST from a single preprocessed input file
* (see the LVGL_MPY rule in micropython.mk). lvgl_private.h alone only
* pulls in _private.h counterparts for libinput/evdev, so desktop window
* drivers (sdl/wayland/x11/...) never reach the parser and never get
* Python bindings, regardless of LV_USE_SDL/LV_USE_WAYLAND/etc. This
* wrapper adds the public driver headers to gen_mpy's input so any driver
* enabled in lv_conf.h is bound the same way widgets are.
*/

#include "lvgl_private.h"

#if LV_USE_WAYLAND
/*
* lv_wayland_window_create()'s close_cb parameter has no accompanying
* user_data-carrying struct argument (its first parameter is a plain
* uint32_t, not an lv_obj/lv_display, which is what gen_mpy's
* callback-binding heuristic requires to know where to stash the
* Python callable). gen_mpy silently emits invalid C
* (`hor_res->user_data`) for it instead of erroring, so hide the
* original declaration from the parser here and expose
* lv_wayland_window_create_simple() instead (implemented in
* lv_mpy_drivers.c), which has no callback parameter at all -- window
* close is already observable via lv_wayland_window_is_open().
*/
#define lv_wayland_window_create(...) lv_wayland_window_create_native_unbound
#endif

#include "src/drivers/lv_drivers.h"

#if LV_USE_WAYLAND
#undef lv_wayland_window_create
lv_display_t * lv_wayland_window_create_simple(uint32_t hor_res, uint32_t ver_res, char * title);
#endif
6 changes: 6 additions & 0 deletions gen/lv_mpy_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -778,7 +778,13 @@ STATIC unsigned long long mp_obj_get_ull(mp_obj_t obj)

unsigned long long val = 0;
bool big_endian = !(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__);
// mp_obj_int_to_bytes() replaced mp_obj_int_to_bytes_impl() in MicroPython
// 1.29 (commit e00daa3a), adding is_signed and overflow_check parameters.
#if MICROPY_VERSION >= MICROPY_MAKE_VERSION(1, 29, 0)
mp_obj_int_to_bytes(obj, sizeof(val), (byte*)&val, big_endian, false, false);
#else
mp_obj_int_to_bytes_impl(obj, big_endian, sizeof(val), (byte*)&val);
#endif
return val;
}

Expand Down
13 changes: 11 additions & 2 deletions lib/lv_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ def __init__(
refresh_cb=None,
asynchronous=False,
exception_sink=None,
handler_cb=None,
):
if self.is_running():
raise RuntimeError("Event loop is already running!")
Expand All @@ -91,6 +92,14 @@ def __init__(

self.delay = 1000 // freq
self.refresh_cb = refresh_cb
# Most drivers (e.g. SDL) self-pump via an lv_timer_t they register
# internally, so the plain lv.task_handler() (== lv_timer_handler())
# is all that's needed here. Some (e.g. Wayland) instead require a
# driver-specific wrapper -- lv.wayland_timer_handler() -- to be
# called *instead of* the plain handler, since it does its own
# input/window event handling around the same inner call. Pass that
# wrapper as handler_cb for those.
self.handler_cb = handler_cb if handler_cb else lv.task_handler
self.exception_sink = (
exception_sink if exception_sink else self.default_exception_sink
)
Expand Down Expand Up @@ -145,7 +154,7 @@ def current_instance():
def task_handler(self, _):
try:
if lv._nesting.value == 0:
lv.task_handler()
self.handler_cb()
if self.refresh_cb:
self.refresh_cb()
self.scheduled -= 1
Expand Down Expand Up @@ -178,7 +187,7 @@ async def async_refresh(self):
if lv._nesting.value == 0:
self.refresh_event.clear()
try:
lv.task_handler()
self.handler_cb()
except Exception as e:
if self.exception_sink:
self.exception_sink(e)
Expand Down
32 changes: 29 additions & 3 deletions lv_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,24 @@
COLOR SETTINGS
*====================*/

/** Color depth: 1 (I1), 8 (L8), 16 (RGB565), 24 (RGB888), 32 (XRGB8888) */
#define LV_COLOR_DEPTH 16
/** Color depth: 1 (I1), 8 (L8), 16 (RGB565), 24 (RGB888), 32 (XRGB8888)
* lv_wayland_window_create() takes no color-format argument -- it creates
* its display internally and picks the SHM pixel format from whatever
* LV_COLOR_DEPTH is, with no per-call override available. wl_shm's
* XRGB8888/ARGB8888 are the only formats mandatory per-spec; RGB565
* support is optional and compositor-dependent, and on one that doesn't
* advertise it, lv_wayland_window_create() hangs waiting for a
* wl_shm.format event that never arrives. So this must be 32 whenever the
* Wayland driver is compiled in, and is left at the original 16
* otherwise, unconditionally forcing every other consumer of this build
* (SDL included) to 32bpp too on systems where wayland-client happens to
* be installed even if they don't personally use lv.wayland_window_create_simple.
* See README.md's "Wayland driver" section. */
#ifdef MICROPY_WAYLAND
#define LV_COLOR_DEPTH 32
#else
#define LV_COLOR_DEPTH 16
#endif

/*=========================
STDLIB WRAPPER SETTINGS
Expand Down Expand Up @@ -1341,8 +1357,18 @@ extern void mp_lv_deinit_gc();
#endif

/** Use Wayland to open a window and handle input on Linux or BSD desktops */
#define LV_USE_WAYLAND 0
#ifdef MICROPY_WAYLAND
#define LV_USE_WAYLAND MICROPY_WAYLAND
#else
#define LV_USE_WAYLAND 0
#endif
#if LV_USE_WAYLAND
/* NOTE: =1 (drawn client-side decorations) hits a real, reproducible
* abort ("Too many bits for size_t", a bad size in a wl_shm request)
* in the decoration-surface teardown path on lv_wayland_window_close()
* -- a timing/lifecycle bug in lv_wl_window_decorations.c, unrelated to
* anything in this binding. Left at the upstream default until that's
* fixed; windows are simply undecorated (no title bar) meanwhile. */
#define LV_WAYLAND_WINDOW_DECORATIONS 0 /**< Draw client side window decorations only necessary on Mutter/GNOME */
#define LV_WAYLAND_WL_SHELL 0 /**< Use the legacy wl_shell protocol instead of the default XDG shell */
#endif
Expand Down
35 changes: 32 additions & 3 deletions micropython.mk
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,31 @@ ifeq ($(UNAME_S),Darwin)
CFLAGS_USERMOD:=$(filter-out -I/usr/local/include,$(CFLAGS_USERMOD))
endif

WAYLAND_CFLAGS_USERMOD := $(shell pkg-config --silence-errors --cflags wayland-client wayland-cursor xkbcommon)
WAYLAND_LDFLAGS_USERMOD := $(shell pkg-config --silence-errors --libs wayland-client wayland-cursor xkbcommon)
WAYLAND_SCANNER := $(shell pkg-config --silence-errors --variable=wayland_scanner wayland-scanner)
ifeq ($(WAYLAND_SCANNER),)
WAYLAND_SCANNER := $(shell command -v wayland-scanner)
endif
WAYLAND_PROTOCOLS_DIR := $(shell pkg-config --silence-errors --variable=pkgdatadir wayland-protocols)
ifneq ($(and $(WAYLAND_LDFLAGS_USERMOD),$(WAYLAND_SCANNER),$(WAYLAND_PROTOCOLS_DIR)),)
# lv_wl_xdg_shell.c needs generated xdg-shell client protocol glue that
# isn't shipped by wayland-protocols as source. Generate it eagerly (at
# Makefile-parse time, like the pkg-config detection above) into the
# build dir so it exists before any compilation starts -- a build *rule*
# for this would race lv_wl_xdg_shell.c's compile on a parallel first build,
# since nothing else orders one before the other.
LVGL_WAYLAND_PROTOCOLS_DIR := $(BUILD)/lvgl/wayland_protocols
LVGL_WAYLAND_XDG_SHELL_XML := $(WAYLAND_PROTOCOLS_DIR)/stable/xdg-shell/xdg-shell.xml
$(shell mkdir -p $(LVGL_WAYLAND_PROTOCOLS_DIR))
$(shell $(WAYLAND_SCANNER) client-header $(LVGL_WAYLAND_XDG_SHELL_XML) $(LVGL_WAYLAND_PROTOCOLS_DIR)/wayland_xdg_shell.h)
$(shell $(WAYLAND_SCANNER) private-code $(LVGL_WAYLAND_XDG_SHELL_XML) $(LVGL_WAYLAND_PROTOCOLS_DIR)/wayland_xdg_shell.c)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Incremental Wayland builds recompile generated protocol glue on every make, because this parse-time scanner invocation rewrites a listed C source unconditionally. Model the XML/header/source generation as Make targets with XML/scanner prerequisites so unchanged outputs are retained and compilation is ordered normally.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At micropython.mk, line 41:

<comment>Incremental Wayland builds recompile generated protocol glue on every `make`, because this parse-time scanner invocation rewrites a listed C source unconditionally. Model the XML/header/source generation as Make targets with XML/scanner prerequisites so unchanged outputs are retained and compilation is ordered normally.</comment>

<file context>
@@ -20,6 +20,31 @@ ifeq ($(UNAME_S),Darwin)
+LVGL_WAYLAND_XDG_SHELL_XML := $(WAYLAND_PROTOCOLS_DIR)/stable/xdg-shell/xdg-shell.xml
+$(shell mkdir -p $(LVGL_WAYLAND_PROTOCOLS_DIR))
+$(shell $(WAYLAND_SCANNER) client-header $(LVGL_WAYLAND_XDG_SHELL_XML) $(LVGL_WAYLAND_PROTOCOLS_DIR)/wayland_xdg_shell.h)
+$(shell $(WAYLAND_SCANNER) private-code  $(LVGL_WAYLAND_XDG_SHELL_XML) $(LVGL_WAYLAND_PROTOCOLS_DIR)/wayland_xdg_shell.c)
+
+CFLAGS_USERMOD += $(WAYLAND_CFLAGS_USERMOD) -DMICROPY_WAYLAND=1 -I$(LVGL_WAYLAND_PROTOCOLS_DIR) -I$(USERMOD_DIR)/lvgl
</file context>


CFLAGS_USERMOD += $(WAYLAND_CFLAGS_USERMOD) -DMICROPY_WAYLAND=1 -I$(LVGL_WAYLAND_PROTOCOLS_DIR) -I$(USERMOD_DIR)/lvgl
LDFLAGS_USERMOD += $(WAYLAND_LDFLAGS_USERMOD)
SRC_USERMOD_LIB_C += $(LVGL_WAYLAND_PROTOCOLS_DIR)/wayland_xdg_shell.c
endif

RLOTTIE_CFLAGS_USERMOD := $(shell pkg-config --silence-errors --cflags rlottie)
RLOTTIE_LDFLAGS_USERMOD := $(shell pkg-config --silence-errors --libs rlottie)
ifneq ($(RLOTTIE_LDFLAGS_USERMOD),)
Expand Down Expand Up @@ -76,16 +101,17 @@ CFLAGS_USERMOD += -DLV_CONF_PATH='"$(LV_CONF_PATH)"' -Wno-deprecated-declaration
# CFLAGS DEBUG
$(info CFLAGS_USERMOD is $(CFLAGS_USERMOD))

$(LVGL_MPY): $(ALL_LVGL_SRC) $(LVGL_BINDING_DIR)/gen/gen_mpy.py
$(LVGL_MPY): $(ALL_LVGL_SRC) $(LVGL_BINDING_DIR)/gen/gen_mpy.py $(LVGL_BINDING_DIR)/gen/lv_mpy_drivers.h
$(ECHO) "LVGL-GEN $@"
$(Q)mkdir -p $(dir $@)
$(Q)$(CPP) -DPYCPARSER -x c \
-I $(LVGL_BINDING_DIR)/stubs/include/freetype2 \
-I $(LVGL_BINDING_DIR)/pycparser/utils/fake_libc_include \
-I $(LVGL_BINDING_DIR)/stubs/include \
-I $(LVGL_DIR) \
$(CFLAGS_USERMOD) \
$(LVGL_DIR)/lvgl_private.h > $(LVGL_PP)
$(Q)$(PYTHON) $(LVGL_BINDING_DIR)/gen/gen_mpy.py -M lvgl -MP lv -MD $(LVGL_MPY_METADATA) -E $(LVGL_PP) $(LVGL_DIR)/lvgl.h > $@
$(LVGL_BINDING_DIR)/gen/lv_mpy_drivers.h > $(LVGL_PP)
$(Q)$(PYTHON) $(LVGL_BINDING_DIR)/gen/gen_mpy.py -M lvgl -MP lv -MD $(LVGL_MPY_METADATA) -E $(LVGL_PP) $(LVGL_DIR)/lvgl.h $(LVGL_BINDING_DIR)/gen/lv_mpy_drivers.h > $@

.PHONY: LVGL_MPY
LVGL_MPY: $(LVGL_MPY)
Expand All @@ -96,6 +122,9 @@ CFLAGS_EXTRA += -Wno-unused-function
# LVGL SRC
SRC_USERMOD_LIB_C += $(shell find $(LVGL_DIR)/src -type f -name "*.c")

# Binding-friendly wrappers for driver functions gen_mpy can't bind as-is
SRC_USERMOD_LIB_C += $(LVGL_BINDING_DIR)/gen/lv_mpy_drivers.c

# LVGL GENERIC DRIVER
SRC_USERMOD_LIB_C += $(shell find $(LVGL_GENERIC_DRV_DIR) -type f -name "*.c")

Expand Down
5 changes: 5 additions & 0 deletions tests/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ To run from `micropython/tests`:
```
e.g. in unix port a display will appear to provide visual feedback.

On desktop (unix port), `display/` and `indev/` fall back to a native window
driver, selected via `display_config.DRIVER` ("sdl", the default, or
"wayland") - or the `LV_MP_TEST_DRIVER` env var, so CI can run the same
tests against both without duplicating them. See README.md's "Wayland
driver" section.

- `indev/`: These are to test the `display` + indev (touch) driver. Intended for
interactive HIL testing, e.g. they expect user input to complete the test.
Expand Down
4 changes: 4 additions & 0 deletions tests/display/display_config.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import os
import lvgl as lv

MODE = "interactive"
POINTER = "sim"
# "sdl" (default) or "wayland" -- set via env var so CI can exercise the
# same tests against both desktop drivers without duplicating test files.
DRIVER = os.getenv("LV_MP_TEST_DRIVER", "sdl")
WIDTH = 240
HEIGHT = 320
COLOR_FORMAT = lv.COLOR_FORMAT.RGB888
4 changes: 4 additions & 0 deletions tests/indev/display_config.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import os
import lvgl as lv

MODE = "interactive"
POINTER = "interactive"
# "sdl" (default) or "wayland" -- set via env var so CI can exercise the
# same tests against both desktop drivers without duplicating test files.
DRIVER = os.getenv("LV_MP_TEST_DRIVER", "sdl")
WIDTH = 240
HEIGHT = 320
COLOR_FORMAT = lv.COLOR_FORMAT.RGB888
Loading
Loading