Improve compact UI, improve DisplayApi, cleanup (#660)

This commit is contained in:
Ken Van Hoeylandt 2026-09-25 20:18:23 +02:00 committed by GitHub
parent c2082b3f46
commit e42545d284
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 90 additions and 182 deletions

View File

@ -315,17 +315,6 @@ static uint16_t papers3_display_get_resolution_y(Device*) {
return static_cast<uint16_t>(epd_rotated_display_height()); return static_cast<uint16_t>(epd_rotated_display_height());
} }
static void papers3_display_get_frame_buffer(Device*, uint8_t, void** out_buffer) {
// Not exposed via the generic fb-direct path: EPDiy's framebuffer is its own 4bpp packed
// format, not the DISPLAY_COLOR_FORMAT_GRAYSCALE8 (1 byte/pixel) this driver reports.
// See get_frame_buffer_count() and draw_bitmap()'s conversion.
*out_buffer = nullptr;
}
static uint8_t papers3_display_get_frame_buffer_count(Device*) {
return 0;
}
// endregion // endregion
static const DisplayApi papers3_display_api = { static const DisplayApi papers3_display_api = {
@ -352,8 +341,9 @@ static const DisplayApi papers3_display_api = {
.get_color_format = papers3_display_get_color_format, .get_color_format = papers3_display_get_color_format,
.get_resolution_x = papers3_display_get_resolution_x, .get_resolution_x = papers3_display_get_resolution_x,
.get_resolution_y = papers3_display_get_resolution_y, .get_resolution_y = papers3_display_get_resolution_y,
.get_frame_buffer = papers3_display_get_frame_buffer, // EPDiy's frame buffer is 4bpp packed, not the GRAYSCALE8 format this driver reports, so it is not exposed
.get_frame_buffer_count = papers3_display_get_frame_buffer_count, .get_frame_buffer = nullptr,
.get_frame_buffer_count = nullptr,
.get_backlight = nullptr, .get_backlight = nullptr,
.has_capability = nullptr, .has_capability = nullptr,
}; };

View File

@ -191,14 +191,6 @@ static uint16_t sdl_display_get_resolution_y(Device* device) {
return GET_CONFIG(device)->vertical_resolution; return GET_CONFIG(device)->vertical_resolution;
} }
static void sdl_display_get_frame_buffer(Device*, uint8_t, void** out_buffer) {
*out_buffer = nullptr;
}
static uint8_t sdl_display_get_frame_buffer_count(Device*) {
return 0;
}
// endregion // endregion
static const DisplayApi sdl_display_api = { static const DisplayApi sdl_display_api = {
@ -220,8 +212,8 @@ static const DisplayApi sdl_display_api = {
.get_color_format = sdl_display_get_color_format, .get_color_format = sdl_display_get_color_format,
.get_resolution_x = sdl_display_get_resolution_x, .get_resolution_x = sdl_display_get_resolution_x,
.get_resolution_y = sdl_display_get_resolution_y, .get_resolution_y = sdl_display_get_resolution_y,
.get_frame_buffer = sdl_display_get_frame_buffer, .get_frame_buffer = nullptr,
.get_frame_buffer_count = sdl_display_get_frame_buffer_count, .get_frame_buffer_count = nullptr,
.get_backlight = nullptr, .get_backlight = nullptr,
.has_capability = nullptr, .has_capability = nullptr,
}; };

View File

@ -10,23 +10,13 @@
## Higher Priority ## Higher Priority
- coreutils apps: Only emit colour escapes when stdout is the terminal (command_support.h color() function) - coreutils apps: Only emit colour escapes when stdout is the terminal (command_support.h color() function)
- DisplayApi::get_frame_buffer should be nullable and have a default behaviour of assigning NULL to the output pointer.
get_frame_buffer_count should be NULLable too, document it explicitly
- Shell interpreter works recursive-descent algorithm, which requires a big stack size. Can we optimize this?
- CrashDiagnostics shouldn't show a QR when there's no callstack - CrashDiagnostics shouldn't show a QR when there's no callstack
- stopAppFromToolbar() in Tactility.cpp stops the top-most app. Change it so the toolbar knows for which app id it is created, so it can rely on that.
- Warn if file operations are done from prohibited tasks (e.g. lvgl task)
- Move USB host task stacks to SPIRAM when available: esp32_usbhost*.cpp - Move USB host task stacks to SPIRAM when available: esp32_usbhost*.cpp
- Get rid of WiFi service (Wifi.cpp/h) in Tactility.cpp - Get rid of WiFi service (Wifi.cpp/h) in Tactility.cpp
- Make it more clear to end-users that an SD card is required to run Tactility
- Add bold fonts for e-ink readability improvement - Add bold fonts for e-ink readability improvement
- Improve Setup: Show "Step done" screen
- Improve Setup: Add keyboard/keypad navigation explanation - Improve Setup: Add keyboard/keypad navigation explanation
- Improve kernel_init.cpp (and other modules): create driver_ensure_added() and driver_ensure_destructed()
- Drivers/audio-codec-module is not a module. Move it somewhere else. Or make it an actual module. - Drivers/audio-codec-module is not a module. Move it somewhere else. Or make it an actual module.
- LilyGO T-Dongle S3: 1 button control, stop auto-launching web server - LilyGO T-Dongle S3: 1 button control, stop auto-launching web server
- Core2: support power off via software
- Create `#define` for empty module (for modules that fully rely on device.properties and don't define drivers or have start/stop logic)
- Improve SPI kernel driver (implement read, write, transactions) - Improve SPI kernel driver (implement read, write, transactions)
- Add font design tokens such as "regular", "title" and "smaller". Perhaps via the LVGL kernel module. - Add font design tokens such as "regular", "title" and "smaller". Perhaps via the LVGL kernel module.
- TCA9534 keyboards should use interrupts - TCA9534 keyboards should use interrupts
@ -42,6 +32,13 @@
## Medium Priority ## Medium Priority
- Core2: support power off via software
- Improve Setup: Show "Step done" screen
- Make it more clear to end-users that an SD card is required to run Tactility
- Warn if file operations are done from prohibited tasks (e.g. lvgl task)
- Shell interpreter works recursive-descent algorithm, which requires a big stack size. Can we optimize this?
- stopAppFromToolbar() in Tactility.cpp stops the top-most app. Change it so the toolbar knows for which app id it is created, so it can rely on that.
- Consider not unpacking `.app` files and executing them directly. Might want to cache file offsets. Cache file must be pinned to app version.
- lvgl-module's spinner relies on hard-coded spinner asset from Tactility main project. - lvgl-module's spinner relies on hard-coded spinner asset from Tactility main project.
- esp_lvgl_port settings has a large stack size (~9kB) to fix stackoverflow when LVGL events (e.g. button click) do actions like file operations do actions like file operations. Can we reduce the callstack? - esp_lvgl_port settings has a large stack size (~9kB) to fix stackoverflow when LVGL events (e.g. button click) do actions like file operations do actions like file operations. Can we reduce the callstack?
- `struct Driver` has an `.owner`, but it's not always set. Either validate on Module construct that it matches, or otherwise set it during module start. The problem: NULL parent currently means that driver is not removable. This clashes with setting it dynamically. Consider some kind of flag to determine removability. - `struct Driver` has an `.owner`, but it's not always set. Either validate on Module construct that it matches, or otherwise set it during module start. The problem: NULL parent currently means that driver is not removable. This clashes with setting it dynamically. Consider some kind of flag to determine removability.

View File

@ -251,14 +251,6 @@ static uint16_t esp_epaper_get_resolution_y(Device* device) {
return esp_epaper_get_display_height(internal, GET_CONFIG(device)->rotation); return esp_epaper_get_display_height(internal, GET_CONFIG(device)->rotation);
} }
static void esp_epaper_get_frame_buffer(Device*, uint8_t, void** out_buffer) {
*out_buffer = nullptr;
}
static uint8_t esp_epaper_get_frame_buffer_count(Device*) {
return 0;
}
static const DisplayApi esp_epaper_display_api = { static const DisplayApi esp_epaper_display_api = {
.capabilities = DISPLAY_CAPABILITY_ON_OFF | DISPLAY_CAPABILITY_SLOW_REFRESH | DISPLAY_CAPABILITY_REQUIRES_FULL_FRAME, .capabilities = DISPLAY_CAPABILITY_ON_OFF | DISPLAY_CAPABILITY_SLOW_REFRESH | DISPLAY_CAPABILITY_REQUIRES_FULL_FRAME,
.reset = esp_epaper_reset, .reset = esp_epaper_reset,
@ -280,8 +272,8 @@ static const DisplayApi esp_epaper_display_api = {
.get_color_format = esp_epaper_get_color_format, .get_color_format = esp_epaper_get_color_format,
.get_resolution_x = esp_epaper_get_resolution_x, .get_resolution_x = esp_epaper_get_resolution_x,
.get_resolution_y = esp_epaper_get_resolution_y, .get_resolution_y = esp_epaper_get_resolution_y,
.get_frame_buffer = esp_epaper_get_frame_buffer, .get_frame_buffer = nullptr,
.get_frame_buffer_count = esp_epaper_get_frame_buffer_count, .get_frame_buffer_count = nullptr,
.get_backlight = nullptr, .get_backlight = nullptr,
.has_capability = nullptr, .has_capability = nullptr,
}; };

View File

@ -305,14 +305,6 @@ static uint16_t gc9a01_get_resolution_y(Device* device) {
return GET_CONFIG(device)->vertical_resolution; return GET_CONFIG(device)->vertical_resolution;
} }
static void gc9a01_get_frame_buffer(Device*, uint8_t, void** out_buffer) {
*out_buffer = nullptr;
}
static uint8_t gc9a01_get_frame_buffer_count(Device*) {
return 0;
}
static error_t gc9a01_get_backlight(Device* device, Device** backlight) { static error_t gc9a01_get_backlight(Device* device, Device** backlight) {
auto* configured_backlight = GET_CONFIG(device)->backlight; auto* configured_backlight = GET_CONFIG(device)->backlight;
if (configured_backlight == nullptr) { if (configured_backlight == nullptr) {
@ -347,8 +339,8 @@ static const DisplayApi gc9a01_display_api = {
.get_color_format = gc9a01_get_color_format, .get_color_format = gc9a01_get_color_format,
.get_resolution_x = gc9a01_get_resolution_x, .get_resolution_x = gc9a01_get_resolution_x,
.get_resolution_y = gc9a01_get_resolution_y, .get_resolution_y = gc9a01_get_resolution_y,
.get_frame_buffer = gc9a01_get_frame_buffer, .get_frame_buffer = nullptr,
.get_frame_buffer_count = gc9a01_get_frame_buffer_count, .get_frame_buffer_count = nullptr,
.get_backlight = gc9a01_get_backlight, .get_backlight = gc9a01_get_backlight,
.has_capability = nullptr, .has_capability = nullptr,
}; };

View File

@ -525,14 +525,6 @@ static uint16_t gdeq031t10_get_resolution_y(Device*) {
return HEIGHT; return HEIGHT;
} }
static void gdeq031t10_get_frame_buffer(Device*, uint8_t, void** out_buffer) {
*out_buffer = nullptr;
}
static uint8_t gdeq031t10_get_frame_buffer_count(Device*) {
return 0;
}
// endregion // endregion
static error_t gdeq031t10_get_backlight(Device* device, Device** backlight) { static error_t gdeq031t10_get_backlight(Device* device, Device** backlight) {
@ -575,8 +567,8 @@ static const DisplayApi gdeq031t10_display_api = {
.get_color_format = gdeq031t10_get_color_format, .get_color_format = gdeq031t10_get_color_format,
.get_resolution_x = gdeq031t10_get_resolution_x, .get_resolution_x = gdeq031t10_get_resolution_x,
.get_resolution_y = gdeq031t10_get_resolution_y, .get_resolution_y = gdeq031t10_get_resolution_y,
.get_frame_buffer = gdeq031t10_get_frame_buffer, .get_frame_buffer = nullptr,
.get_frame_buffer_count = gdeq031t10_get_frame_buffer_count, .get_frame_buffer_count = nullptr,
.get_backlight = gdeq031t10_get_backlight, .get_backlight = gdeq031t10_get_backlight,
.has_capability = gdeq031t10_has_capability, .has_capability = gdeq031t10_has_capability,
}; };

View File

@ -417,14 +417,6 @@ static uint16_t hx8357_get_resolution_y(Device* device) {
return GET_CONFIG(device)->vertical_resolution; return GET_CONFIG(device)->vertical_resolution;
} }
static void hx8357_get_frame_buffer(Device*, uint8_t, void** out_buffer) {
*out_buffer = nullptr;
}
static uint8_t hx8357_get_frame_buffer_count(Device*) {
return 0;
}
static error_t hx8357_get_backlight(Device* device, Device** backlight) { static error_t hx8357_get_backlight(Device* device, Device** backlight) {
auto* configured_backlight = GET_CONFIG(device)->backlight; auto* configured_backlight = GET_CONFIG(device)->backlight;
if (configured_backlight == nullptr) { if (configured_backlight == nullptr) {
@ -462,8 +454,8 @@ static const DisplayApi hx8357_display_api = {
.get_color_format = hx8357_get_color_format, .get_color_format = hx8357_get_color_format,
.get_resolution_x = hx8357_get_resolution_x, .get_resolution_x = hx8357_get_resolution_x,
.get_resolution_y = hx8357_get_resolution_y, .get_resolution_y = hx8357_get_resolution_y,
.get_frame_buffer = hx8357_get_frame_buffer, .get_frame_buffer = nullptr,
.get_frame_buffer_count = hx8357_get_frame_buffer_count, .get_frame_buffer_count = nullptr,
.get_backlight = hx8357_get_backlight, .get_backlight = hx8357_get_backlight,
.has_capability = nullptr, .has_capability = nullptr,
}; };

View File

@ -410,14 +410,6 @@ static uint16_t ili9341_get_resolution_y(Device* device) {
return GET_CONFIG(device)->vertical_resolution; return GET_CONFIG(device)->vertical_resolution;
} }
static void ili9341_get_frame_buffer(Device*, uint8_t, void** out_buffer) {
*out_buffer = nullptr;
}
static uint8_t ili9341_get_frame_buffer_count(Device*) {
return 0;
}
static error_t ili9341_get_backlight(Device* device, Device** backlight) { static error_t ili9341_get_backlight(Device* device, Device** backlight) {
auto* configured_backlight = GET_CONFIG(device)->backlight; auto* configured_backlight = GET_CONFIG(device)->backlight;
if (configured_backlight == nullptr) { if (configured_backlight == nullptr) {
@ -452,8 +444,8 @@ static const DisplayApi ili9341_display_api = {
.get_color_format = ili9341_get_color_format, .get_color_format = ili9341_get_color_format,
.get_resolution_x = ili9341_get_resolution_x, .get_resolution_x = ili9341_get_resolution_x,
.get_resolution_y = ili9341_get_resolution_y, .get_resolution_y = ili9341_get_resolution_y,
.get_frame_buffer = ili9341_get_frame_buffer, .get_frame_buffer = nullptr,
.get_frame_buffer_count = ili9341_get_frame_buffer_count, .get_frame_buffer_count = nullptr,
.get_backlight = ili9341_get_backlight, .get_backlight = ili9341_get_backlight,
.has_capability = nullptr, .has_capability = nullptr,
}; };

View File

@ -335,14 +335,6 @@ static uint16_t ili9488_get_resolution_y(Device* device) {
return GET_CONFIG(device)->vertical_resolution; return GET_CONFIG(device)->vertical_resolution;
} }
static void ili9488_get_frame_buffer(Device*, uint8_t, void** out_buffer) {
*out_buffer = nullptr;
}
static uint8_t ili9488_get_frame_buffer_count(Device*) {
return 0;
}
static error_t ili9488_get_backlight(Device* device, Device** backlight) { static error_t ili9488_get_backlight(Device* device, Device** backlight) {
auto* configured_backlight = GET_CONFIG(device)->backlight; auto* configured_backlight = GET_CONFIG(device)->backlight;
if (configured_backlight == nullptr) { if (configured_backlight == nullptr) {
@ -377,8 +369,8 @@ static const DisplayApi ili9488_display_api = {
.get_color_format = ili9488_get_color_format, .get_color_format = ili9488_get_color_format,
.get_resolution_x = ili9488_get_resolution_x, .get_resolution_x = ili9488_get_resolution_x,
.get_resolution_y = ili9488_get_resolution_y, .get_resolution_y = ili9488_get_resolution_y,
.get_frame_buffer = ili9488_get_frame_buffer, .get_frame_buffer = nullptr,
.get_frame_buffer_count = ili9488_get_frame_buffer_count, .get_frame_buffer_count = nullptr,
.get_backlight = ili9488_get_backlight, .get_backlight = ili9488_get_backlight,
.has_capability = nullptr, .has_capability = nullptr,
}; };

View File

@ -318,14 +318,6 @@ static uint16_t jd9853_get_resolution_y(Device* device) {
return GET_CONFIG(device)->vertical_resolution; return GET_CONFIG(device)->vertical_resolution;
} }
static void jd9853_get_frame_buffer(Device*, uint8_t, void** out_buffer) {
*out_buffer = nullptr;
}
static uint8_t jd9853_get_frame_buffer_count(Device*) {
return 0;
}
static error_t jd9853_get_backlight(Device* device, Device** backlight) { static error_t jd9853_get_backlight(Device* device, Device** backlight) {
auto* configured_backlight = GET_CONFIG(device)->backlight; auto* configured_backlight = GET_CONFIG(device)->backlight;
if (configured_backlight == nullptr) { if (configured_backlight == nullptr) {
@ -360,8 +352,8 @@ static const DisplayApi jd9853_display_api = {
.get_color_format = jd9853_get_color_format, .get_color_format = jd9853_get_color_format,
.get_resolution_x = jd9853_get_resolution_x, .get_resolution_x = jd9853_get_resolution_x,
.get_resolution_y = jd9853_get_resolution_y, .get_resolution_y = jd9853_get_resolution_y,
.get_frame_buffer = jd9853_get_frame_buffer, .get_frame_buffer = nullptr,
.get_frame_buffer_count = jd9853_get_frame_buffer_count, .get_frame_buffer_count = nullptr,
.get_backlight = jd9853_get_backlight, .get_backlight = jd9853_get_backlight,
.has_capability = nullptr, .has_capability = nullptr,
}; };

View File

@ -308,14 +308,6 @@ static uint16_t ssd1306_get_resolution_y(Device* device) {
return GET_CONFIG(device)->vertical_resolution; return GET_CONFIG(device)->vertical_resolution;
} }
static void ssd1306_get_frame_buffer(Device*, uint8_t, void** out_buffer) {
*out_buffer = nullptr;
}
static uint8_t ssd1306_get_frame_buffer_count(Device*) {
return 0;
}
// get_backlight is not exposed: SSD1306 is a self-emitting OLED panel with no backlight. // get_backlight is not exposed: SSD1306 is a self-emitting OLED panel with no backlight.
// endregion // endregion
@ -341,8 +333,8 @@ static const DisplayApi ssd1306_display_api = {
.get_color_format = ssd1306_get_color_format, .get_color_format = ssd1306_get_color_format,
.get_resolution_x = ssd1306_get_resolution_x, .get_resolution_x = ssd1306_get_resolution_x,
.get_resolution_y = ssd1306_get_resolution_y, .get_resolution_y = ssd1306_get_resolution_y,
.get_frame_buffer = ssd1306_get_frame_buffer, .get_frame_buffer = nullptr,
.get_frame_buffer_count = ssd1306_get_frame_buffer_count, .get_frame_buffer_count = nullptr,
.get_backlight = nullptr, .get_backlight = nullptr,
.has_capability = nullptr, .has_capability = nullptr,
}; };

View File

@ -337,14 +337,6 @@ static uint16_t st7735_get_resolution_y(Device* device) {
return GET_CONFIG(device)->vertical_resolution; return GET_CONFIG(device)->vertical_resolution;
} }
static void st7735_get_frame_buffer(Device*, uint8_t, void** out_buffer) {
*out_buffer = nullptr;
}
static uint8_t st7735_get_frame_buffer_count(Device*) {
return 0;
}
static error_t st7735_get_backlight(Device* device, Device** backlight) { static error_t st7735_get_backlight(Device* device, Device** backlight) {
auto* configured_backlight = GET_CONFIG(device)->backlight; auto* configured_backlight = GET_CONFIG(device)->backlight;
if (configured_backlight == nullptr) { if (configured_backlight == nullptr) {
@ -379,8 +371,8 @@ static const DisplayApi st7735_display_api = {
.get_color_format = st7735_get_color_format, .get_color_format = st7735_get_color_format,
.get_resolution_x = st7735_get_resolution_x, .get_resolution_x = st7735_get_resolution_x,
.get_resolution_y = st7735_get_resolution_y, .get_resolution_y = st7735_get_resolution_y,
.get_frame_buffer = st7735_get_frame_buffer, .get_frame_buffer = nullptr,
.get_frame_buffer_count = st7735_get_frame_buffer_count, .get_frame_buffer_count = nullptr,
.get_backlight = st7735_get_backlight, .get_backlight = st7735_get_backlight,
.has_capability = nullptr, .has_capability = nullptr,
}; };

View File

@ -326,14 +326,6 @@ static uint16_t st7789_i8080_get_resolution_y(Device* device) {
return GET_CONFIG(device)->vertical_resolution; return GET_CONFIG(device)->vertical_resolution;
} }
static void st7789_i8080_get_frame_buffer(Device*, uint8_t, void** out_buffer) {
*out_buffer = nullptr;
}
static uint8_t st7789_i8080_get_frame_buffer_count(Device*) {
return 0;
}
static error_t st7789_i8080_get_backlight(Device* device, Device** backlight) { static error_t st7789_i8080_get_backlight(Device* device, Device** backlight) {
auto* configured_backlight = GET_CONFIG(device)->backlight; auto* configured_backlight = GET_CONFIG(device)->backlight;
if (configured_backlight == nullptr) { if (configured_backlight == nullptr) {
@ -368,8 +360,8 @@ static const DisplayApi st7789_i8080_display_api = {
.get_color_format = st7789_i8080_get_color_format, .get_color_format = st7789_i8080_get_color_format,
.get_resolution_x = st7789_i8080_get_resolution_x, .get_resolution_x = st7789_i8080_get_resolution_x,
.get_resolution_y = st7789_i8080_get_resolution_y, .get_resolution_y = st7789_i8080_get_resolution_y,
.get_frame_buffer = st7789_i8080_get_frame_buffer, .get_frame_buffer = nullptr,
.get_frame_buffer_count = st7789_i8080_get_frame_buffer_count, .get_frame_buffer_count = nullptr,
.get_backlight = st7789_i8080_get_backlight, .get_backlight = st7789_i8080_get_backlight,
.has_capability = nullptr, .has_capability = nullptr,
}; };

View File

@ -337,14 +337,6 @@ static uint16_t st7789_get_resolution_y(Device* device) {
return GET_CONFIG(device)->vertical_resolution; return GET_CONFIG(device)->vertical_resolution;
} }
static void st7789_get_frame_buffer(Device*, uint8_t, void** out_buffer) {
*out_buffer = nullptr;
}
static uint8_t st7789_get_frame_buffer_count(Device*) {
return 0;
}
static error_t st7789_get_backlight(Device* device, Device** backlight) { static error_t st7789_get_backlight(Device* device, Device** backlight) {
auto* configured_backlight = GET_CONFIG(device)->backlight; auto* configured_backlight = GET_CONFIG(device)->backlight;
if (configured_backlight == nullptr) { if (configured_backlight == nullptr) {
@ -379,8 +371,8 @@ static const DisplayApi st7789_display_api = {
.get_color_format = st7789_get_color_format, .get_color_format = st7789_get_color_format,
.get_resolution_x = st7789_get_resolution_x, .get_resolution_x = st7789_get_resolution_x,
.get_resolution_y = st7789_get_resolution_y, .get_resolution_y = st7789_get_resolution_y,
.get_frame_buffer = st7789_get_frame_buffer, .get_frame_buffer = nullptr,
.get_frame_buffer_count = st7789_get_frame_buffer_count, .get_frame_buffer_count = nullptr,
.get_backlight = st7789_get_backlight, .get_backlight = st7789_get_backlight,
.has_capability = nullptr, .has_capability = nullptr,
}; };

View File

@ -281,14 +281,6 @@ static uint16_t st7796_i8080_get_resolution_y(Device* device) {
return GET_CONFIG(device)->vertical_resolution; return GET_CONFIG(device)->vertical_resolution;
} }
static void st7796_i8080_get_frame_buffer(Device*, uint8_t, void** out_buffer) {
*out_buffer = nullptr;
}
static uint8_t st7796_i8080_get_frame_buffer_count(Device*) {
return 0;
}
static error_t st7796_i8080_get_backlight(Device* device, Device** backlight) { static error_t st7796_i8080_get_backlight(Device* device, Device** backlight) {
auto* configured_backlight = GET_CONFIG(device)->backlight; auto* configured_backlight = GET_CONFIG(device)->backlight;
if (configured_backlight == nullptr) { if (configured_backlight == nullptr) {
@ -323,8 +315,8 @@ static const DisplayApi st7796_i8080_display_api = {
.get_color_format = st7796_i8080_get_color_format, .get_color_format = st7796_i8080_get_color_format,
.get_resolution_x = st7796_i8080_get_resolution_x, .get_resolution_x = st7796_i8080_get_resolution_x,
.get_resolution_y = st7796_i8080_get_resolution_y, .get_resolution_y = st7796_i8080_get_resolution_y,
.get_frame_buffer = st7796_i8080_get_frame_buffer, .get_frame_buffer = nullptr,
.get_frame_buffer_count = st7796_i8080_get_frame_buffer_count, .get_frame_buffer_count = nullptr,
.get_backlight = st7796_i8080_get_backlight, .get_backlight = st7796_i8080_get_backlight,
.has_capability = nullptr, .has_capability = nullptr,
}; };

View File

@ -337,14 +337,6 @@ static uint16_t st7796_get_resolution_y(Device* device) {
return GET_CONFIG(device)->vertical_resolution; return GET_CONFIG(device)->vertical_resolution;
} }
static void st7796_get_frame_buffer(Device*, uint8_t, void** out_buffer) {
*out_buffer = nullptr;
}
static uint8_t st7796_get_frame_buffer_count(Device*) {
return 0;
}
static error_t st7796_get_backlight(Device* device, Device** backlight) { static error_t st7796_get_backlight(Device* device, Device** backlight) {
auto* configured_backlight = GET_CONFIG(device)->backlight; auto* configured_backlight = GET_CONFIG(device)->backlight;
if (configured_backlight == nullptr) { if (configured_backlight == nullptr) {
@ -379,8 +371,8 @@ static const DisplayApi st7796_display_api = {
.get_color_format = st7796_get_color_format, .get_color_format = st7796_get_color_format,
.get_resolution_x = st7796_get_resolution_x, .get_resolution_x = st7796_get_resolution_x,
.get_resolution_y = st7796_get_resolution_y, .get_resolution_y = st7796_get_resolution_y,
.get_frame_buffer = st7796_get_frame_buffer, .get_frame_buffer = nullptr,
.get_frame_buffer_count = st7796_get_frame_buffer_count, .get_frame_buffer_count = nullptr,
.get_backlight = st7796_get_backlight, .get_backlight = st7796_get_backlight,
.has_capability = nullptr, .has_capability = nullptr,
}; };

View File

@ -108,6 +108,8 @@ error_t parse_app_manifest(const std::map<std::string, std::string>& properties,
out_manifest.stack.depth = static_cast<uint16_t>(stack_size); out_manifest.stack.depth = static_cast<uint16_t>(stack_size);
} }
out_manifest.flags = 0;
// <index>.hidden (optional; defaults to false) // <index>.hidden (optional; defaults to false)
auto hidden_iterator = properties.find(prefix + "hidden"); auto hidden_iterator = properties.find(prefix + "hidden");
if (hidden_iterator != properties.end()) { if (hidden_iterator != properties.end()) {
@ -115,7 +117,21 @@ error_t parse_app_manifest(const std::map<std::string, std::string>& properties,
LOG_E(TAG, "Invalid %shidden", prefix.c_str()); LOG_E(TAG, "Invalid %shidden", prefix.c_str());
return ERROR_INVALID_ARGUMENT; return ERROR_INVALID_ARGUMENT;
} }
out_manifest.flags = hidden_iterator->second == "true" ? APP_MANIFEST_FLAG_HIDDEN : 0; if (hidden_iterator->second == "true") {
out_manifest.flags |= APP_MANIFEST_FLAG_HIDDEN;
}
}
// <index>.headless (optional; defaults to false)
auto headless_iterator = properties.find(prefix + "headless");
if (headless_iterator != properties.end()) {
if (!app_package_manifest_is_valid_bool(headless_iterator->second)) {
LOG_E(TAG, "Invalid %sheadless", prefix.c_str());
return ERROR_INVALID_ARGUMENT;
}
if (headless_iterator->second == "true") {
out_manifest.flags |= APP_MANIFEST_FLAG_HEADLESS;
}
} }
out_manifest.category = APP_CATEGORY_USER; out_manifest.category = APP_CATEGORY_USER;

View File

@ -12,7 +12,7 @@
static uint32_t getToolbarHeight(UiDensity uiDensity) { static uint32_t getToolbarHeight(UiDensity uiDensity) {
if (uiDensity == LVGL_UI_DENSITY_COMPACT) { if (uiDensity == LVGL_UI_DENSITY_COMPACT) {
return lvgl_get_text_font_height(FONT_SIZE_DEFAULT) * 1.4f; return lvgl_get_text_font_height(FONT_SIZE_DEFAULT) * 1.6f;
} else { } else {
return lvgl_get_text_font_height(FONT_SIZE_LARGE) * 2.2f; return lvgl_get_text_font_height(FONT_SIZE_LARGE) * 2.2f;
} }
@ -29,7 +29,7 @@ static const _lv_font_t* getToolbarFont(UiDensity uiDensity) {
static uint32_t getActionIconPadding(UiDensity uiDensity) { static uint32_t getActionIconPadding(UiDensity uiDensity) {
auto toolbar_height = getToolbarHeight(uiDensity); auto toolbar_height = getToolbarHeight(uiDensity);
// Minimal 8 pixels total padding for selection/animation (4+4 pixels) // Minimal 8 pixels total padding for selection/animation (4+4 pixels)
return (uiDensity != LVGL_UI_DENSITY_COMPACT) ? (uint32_t)(toolbar_height * 0.2f) : 8; return (uiDensity != LVGL_UI_DENSITY_COMPACT) ? (uint32_t)(toolbar_height * 0.2f) : 10;
} }
/** /**

View File

@ -1,7 +0,0 @@
#pragma once
#include <lvgl/widgets/toolbar.h>
namespace tt::lvgl {
} // namespace

View File

@ -84,10 +84,13 @@ void createWidgets(lv_obj_t* parent, void* userData) {
lv_obj_t* button_wrapper = lv_obj_create(parent); lv_obj_t* button_wrapper = lv_obj_create(parent);
lv_obj_set_flex_flow(button_wrapper, LV_FLEX_FLOW_ROW); lv_obj_set_flex_flow(button_wrapper, LV_FLEX_FLOW_ROW);
lv_obj_set_size(button_wrapper, LV_PCT(100), LV_SIZE_CONTENT); lv_obj_set_size(button_wrapper, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_set_style_pad_all(button_wrapper, 0, 0);
lv_obj_set_flex_align(button_wrapper, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); lv_obj_set_flex_align(button_wrapper, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_set_style_border_width(button_wrapper, 0, 0); lv_obj_set_style_border_width(button_wrapper, 0, 0);
lv_obj_align(button_wrapper, LV_ALIGN_BOTTOM_MID, 0, -4); lv_obj_align(button_wrapper, LV_ALIGN_BOTTOM_MID, 0, -4);
// Ensures showing selection state for keyboard/encoder devices
lv_obj_set_style_pad_all(button_wrapper, 0, LV_ALIGN_DEFAULT);
lv_obj_set_style_pad_column(button_wrapper, 12, LV_STATE_DEFAULT);
lv_obj_set_style_pad_ver(button_wrapper, 4, LV_STATE_DEFAULT);
for (int32_t index = 0; index < argc - 2; index++) { for (int32_t index = 0; index < argc - 2; index++) {
createButton(ctx, button_wrapper, argv[2 + index], index); createButton(ctx, button_wrapper, argv[2 + index], index);

View File

@ -6,8 +6,6 @@
#include <Tactility/app/btmanage/View.h> #include <Tactility/app/btmanage/View.h>
#include <Tactility/app/btmanage/BtManagePrivate.h> #include <Tactility/app/btmanage/BtManagePrivate.h>
#include <Tactility/app/btpeersettings/BtPeerSettings.h> #include <Tactility/app/btpeersettings/BtPeerSettings.h>
#include <Tactility/lvgl/Style.h>
#include <Tactility/lvgl/Toolbar.h>
#include <Tactility/bluetooth/Bluetooth.h> #include <Tactility/bluetooth/Bluetooth.h>
#include <Tactility/bluetooth/BluetoothSettings.h> #include <Tactility/bluetooth/BluetoothSettings.h>
#include <Tactility/bluetooth/BluetoothPairedDevice.h> #include <Tactility/bluetooth/BluetoothPairedDevice.h>

View File

@ -325,8 +325,9 @@ void createWidgets(lv_obj_t* parent, void* userData) {
auto* wrapper = lv_obj_create(main_wrapper); auto* wrapper = lv_obj_create(main_wrapper);
lv_obj_set_width(wrapper, LV_PCT(100)); lv_obj_set_width(wrapper, LV_PCT(100));
lv_obj_set_height(wrapper, LV_SIZE_CONTENT); lv_obj_set_height(wrapper, LV_SIZE_CONTENT);
lv_obj_set_style_pad_all(wrapper, 0, 0);
lv_obj_set_style_border_width(wrapper, 0, 0); lv_obj_set_style_border_width(wrapper, 0, 0);
// Ensures showing selection state for keyboard/encoder devices
lv_obj_set_style_pad_all(wrapper, 6, LV_ALIGN_DEFAULT);
auto* scan_button = lv_button_create(wrapper); auto* scan_button = lv_button_create(wrapper);
lv_obj_set_width(scan_button, LV_PCT(48)); lv_obj_set_width(scan_button, LV_PCT(48));

View File

@ -10,7 +10,9 @@
#include <lvgl_window_manager/window_manager.h> #include <lvgl_window_manager/window_manager.h>
#include <lvgl/widgets/toolbar.h> #include <lvgl/widgets/toolbar.h>
#include <tactility/check.h> #include <tactility/check.h>
#include <tactility/error.h>
#include <tactility/log.h> #include <tactility/log.h>
#include <lvgl.h> #include <lvgl.h>
@ -86,6 +88,9 @@ void createWidgets(lv_obj_t* parent, void* userData) {
lv_label_set_long_mode(message_label, LV_LABEL_LONG_WRAP); lv_label_set_long_mode(message_label, LV_LABEL_LONG_WRAP);
auto* textarea = lv_textarea_create(parent); auto* textarea = lv_textarea_create(parent);
// Ensures showing selection state for keyboard/encoder devices
lv_obj_set_style_margin_hor(textarea, 4, LV_STATE_DEFAULT);
lv_obj_set_width(textarea, LV_PCT(80));
lv_obj_align_to(textarea, message_label, LV_ALIGN_OUT_BOTTOM_MID, 0, 4); lv_obj_align_to(textarea, message_label, LV_ALIGN_OUT_BOTTOM_MID, 0, 4);
lv_textarea_set_one_line(textarea, true); lv_textarea_set_one_line(textarea, true);
if (argv[2][0] != '\0') { if (argv[2][0] != '\0') {
@ -99,6 +104,9 @@ void createWidgets(lv_obj_t* parent, void* userData) {
lv_obj_set_flex_align(button_wrapper, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); lv_obj_set_flex_align(button_wrapper, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_set_style_border_width(button_wrapper, 0, 0); lv_obj_set_style_border_width(button_wrapper, 0, 0);
lv_obj_align(button_wrapper, LV_ALIGN_BOTTOM_MID, 0, -4); lv_obj_align(button_wrapper, LV_ALIGN_BOTTOM_MID, 0, -4);
// Ensures showing selection state for keyboard/encoder devices
lv_obj_set_style_pad_column(button_wrapper, 12, LV_STATE_DEFAULT);
lv_obj_set_style_pad_ver(button_wrapper, 6, LV_STATE_DEFAULT);
createButton(ctx, button_wrapper, "OK", textarea); createButton(ctx, button_wrapper, "OK", textarea);
createButton(ctx, button_wrapper, "Cancel", nullptr); createButton(ctx, button_wrapper, "Cancel", nullptr);
@ -106,7 +114,7 @@ void createWidgets(lv_obj_t* parent, void* userData) {
int32_t appMain(int argc, char* argv[]) { int32_t appMain(int argc, char* argv[]) {
uint32_t appInstanceId = app_scheduler_current_app_id(); uint32_t appInstanceId = app_scheduler_current_app_id();
Context ctx { appInstanceId }; Context ctx { .appInstanceId = appInstanceId };
ctx.argc = argc; ctx.argc = argc;
ctx.argv = argv; ctx.argv = argv;

View File

@ -53,6 +53,8 @@ void createWidgets(lv_obj_t* parent, void* userData) {
lv_obj_set_flex_align(wrapper, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); lv_obj_set_flex_align(wrapper, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_set_size(wrapper, lv_pct(100), LV_SIZE_CONTENT); lv_obj_set_size(wrapper, lv_pct(100), LV_SIZE_CONTENT);
lv_obj_align(wrapper, LV_ALIGN_CENTER, 0, 0); lv_obj_align(wrapper, LV_ALIGN_CENTER, 0, 0);
// Ensures showing selection state for keyboard/encoder devices
lv_obj_set_style_pad_all(wrapper, 6, LV_ALIGN_DEFAULT);
bool hasSd = hal::usb::canRebootIntoMassStorageSdmmc(); bool hasSd = hal::usb::canRebootIntoMassStorageSdmmc();
bool hasFlash = hal::usb::canRebootIntoMassStorageFlash(); bool hasFlash = hal::usb::canRebootIntoMassStorageFlash();

View File

@ -1 +0,0 @@
#include <Tactility/lvgl/Toolbar.h>

View File

@ -12,7 +12,7 @@ lv_obj_t* __wrap_lv_button_create(lv_obj_t* parent) {
auto button = __real_lv_button_create(parent); auto button = __real_lv_button_create(parent);
if (lvgl_get_ui_density() == LVGL_UI_DENSITY_COMPACT) { if (lvgl_get_ui_density() == LVGL_UI_DENSITY_COMPACT) {
lv_obj_set_style_pad_all(button, 2, LV_STATE_DEFAULT); lv_obj_set_style_pad_all(button, 3, LV_STATE_DEFAULT);
lv_obj_set_style_radius(button, 3, LV_STATE_DEFAULT); lv_obj_set_style_radius(button, 3, LV_STATE_DEFAULT);
} }

View File

@ -218,6 +218,7 @@ struct DisplayApi {
/** /**
* @brief Gets a pointer to one of the panel's frame buffers, for panels that expose direct frame buffer access. * @brief Gets a pointer to one of the panel's frame buffers, for panels that expose direct frame buffer access.
* @warning Nullable. When null, display_get_frame_buffer() sets *out_buffer to NULL.
* @param[in] device the display device * @param[in] device the display device
* @param[in] index the frame buffer index (see get_frame_buffer_count()) * @param[in] index the frame buffer index (see get_frame_buffer_count())
* @param[out] out_buffer the buffer pointer * @param[out] out_buffer the buffer pointer
@ -226,6 +227,7 @@ struct DisplayApi {
/** /**
* @brief Gets the number of frame buffers exposed by the panel via get_frame_buffer(). 0 when unsupported. * @brief Gets the number of frame buffers exposed by the panel via get_frame_buffer(). 0 when unsupported.
* @warning Nullable. When null, display_get_frame_buffer_count() returns 0.
* @param[in] device the display device * @param[in] device the display device
* @return the frame buffer count * @return the frame buffer count
*/ */
@ -366,11 +368,13 @@ uint16_t display_get_resolution_y(struct Device* device);
/** /**
* @brief Gets a pointer to one of the panel's frame buffers using the specified display. * @brief Gets a pointer to one of the panel's frame buffers using the specified display.
* @param[out] out_buffer set to NULL when the display doesn't expose frame buffers
*/ */
void display_get_frame_buffer(struct Device* device, uint8_t index, void** out_buffer); void display_get_frame_buffer(struct Device* device, uint8_t index, void** out_buffer);
/** /**
* @brief Gets the number of frame buffers exposed by the panel using the specified display. * @brief Gets the number of frame buffers exposed by the panel using the specified display.
* @return the frame buffer count, or 0 when the display doesn't expose frame buffers
*/ */
uint8_t display_get_frame_buffer_count(struct Device* device); uint8_t display_get_frame_buffer_count(struct Device* device);

View File

@ -122,12 +122,21 @@ uint16_t display_get_resolution_y(Device* device) {
void display_get_frame_buffer(Device* device, uint8_t index, void** out_buffer) { void display_get_frame_buffer(Device* device, uint8_t index, void** out_buffer) {
const auto* driver = device_get_driver(device); const auto* driver = device_get_driver(device);
DISPLAY_DRIVER_API(driver)->get_frame_buffer(device, index, out_buffer); const auto* api = DISPLAY_DRIVER_API(driver);
if (api->get_frame_buffer == nullptr) {
*out_buffer = nullptr;
return;
}
api->get_frame_buffer(device, index, out_buffer);
} }
uint8_t display_get_frame_buffer_count(Device* device) { uint8_t display_get_frame_buffer_count(Device* device) {
const auto* driver = device_get_driver(device); const auto* driver = device_get_driver(device);
return DISPLAY_DRIVER_API(driver)->get_frame_buffer_count(device); const auto* api = DISPLAY_DRIVER_API(driver);
if (api->get_frame_buffer_count == nullptr) {
return 0;
}
return api->get_frame_buffer_count(device);
} }
error_t display_get_backlight(Device* device, Device** backlight) { error_t display_get_backlight(Device* device, Device** backlight) {