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
38 changes: 38 additions & 0 deletions Modules/lvgl-module/source/devices/display.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
// SPDX-License-Identifier: Apache-2.0
#define LV_USE_PRIVATE_API 1 // For the lv_theme_t declaration

#include <lvgl/devices/display.h>

#include <lvgl/ppa.h>
Expand All @@ -18,6 +20,38 @@

constexpr auto* TAG = "lvgl_display";

#if LV_USE_THEME_MONO

static lv_style_t mono_button_style;
static bool mono_button_style_initialized = false;
static lv_theme_t mono_theme_extension;

static void mono_theme_extension_apply(lv_theme_t*, lv_obj_t* obj) {
if (lv_obj_check_type(obj, &lv_button_class)) {
lv_obj_add_style(obj, &mono_button_style, LV_PART_MAIN | LV_STATE_DEFAULT);
}
}

// The mono theme draws a border around every button. This removes it in the default state, keeping the pressed border and focus outline.
static void lvgl_display_extend_mono_theme(lv_display_t* disp) {
if (!mono_button_style_initialized) {
lv_style_init(&mono_button_style);
lv_style_set_border_width(&mono_button_style, 0);
mono_button_style_initialized = true;
}
// LVGL prefers the default and simple themes when they are also enabled, so only the mono theme itself is extended
lv_theme_t* mono_theme = lv_display_get_theme(disp);
if (mono_theme == nullptr || mono_theme != lv_theme_mono_get()) {
return;
}
mono_theme_extension = *mono_theme;
lv_theme_set_parent(&mono_theme_extension, mono_theme);
lv_theme_set_apply_cb(&mono_theme_extension, mono_theme_extension_apply);
lv_display_set_theme(disp, &mono_theme_extension);
}

#endif

struct LvglDisplayCtx {
void* buf1;
void* buf2;
Expand Down Expand Up @@ -470,6 +504,10 @@ error_t lvgl_display_add(struct Device* device, const struct LvglDisplayConfig*
return ERROR_OUT_OF_MEMORY;
}

#if LV_USE_THEME_MONO
lvgl_display_extend_mono_theme(disp);
Comment thread
KenVanHoeylandt marked this conversation as resolved.
#endif

ctx->render_mode = render_mode;
lv_display_set_color_format(disp, lv_color_format);
lv_display_set_buffers(disp, ctx->buf1, ctx->buf2, buf_size_bytes, render_mode);
Expand Down
25 changes: 19 additions & 6 deletions Tactility/Source/app/AppGrid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ lv_color_t getIconColor(bool focused, bool highlighted) {
return highlighted ? lv_color_hex(ICON_COLOR_HIGHLIGHTED) : lv_color_white();
}

// Accent colours can't be rendered in 1bpp, so tiles use theme colours and the theme's focus outline instead
bool isMonochrome(lv_obj_t* obj) {
return lv_display_get_color_format(lv_obj_get_display(obj)) == LV_COLOR_FORMAT_I1;
}

const AppGridItem* getTileItem(lv_event_t* e) {
return static_cast<const AppGridItem*>(lv_obj_get_user_data(lv_event_get_target_obj(e)));
}
Expand Down Expand Up @@ -156,6 +161,7 @@ void AppGrid::populate() {
lv_obj_set_flag(lv_obj_get_parent(nextButton), LV_OBJ_FLAG_HIDDEN, page_count <= 1);

lv_obj_t* focusedTile = nullptr;
const bool monochrome = isMonochrome(grid);
const uint32_t first = page * layout.pageSize;
const uint32_t last = std::min(item_count, first + layout.pageSize);
for (uint32_t i = first; i < last; i++) {
Expand All @@ -167,8 +173,10 @@ void AppGrid::populate() {
lv_obj_set_style_pad_row(tile, layout.pad / 2, LV_STATE_DEFAULT);
lv_obj_set_style_shadow_width(tile, 0, LV_STATE_DEFAULT);
lv_obj_set_style_bg_opa(tile, LV_OPA_TRANSP, LV_STATE_DEFAULT);
lv_obj_set_style_outline_width(tile, 0, LV_STATE_FOCUSED);
lv_obj_set_style_outline_width(tile, 0, LV_STATE_FOCUS_KEY);
if (!monochrome) {
lv_obj_set_style_outline_width(tile, 0, LV_STATE_FOCUSED);
lv_obj_set_style_outline_width(tile, 0, LV_STATE_FOCUS_KEY);
}
lv_obj_set_flex_flow(tile, LV_FLEX_FLOW_COLUMN);
lv_obj_set_flex_align(tile, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
lv_obj_set_user_data(tile, const_cast<AppGridItem*>(&item));
Expand All @@ -177,13 +185,16 @@ void AppGrid::populate() {
lv_obj_set_style_text_font(icon, lvgl_get_shared_icon_font_2x(), LV_STATE_DEFAULT);
lv_obj_set_style_text_align(icon, LV_TEXT_ALIGN_CENTER, LV_STATE_DEFAULT);
lv_obj_set_size(icon, layout.iconSize, layout.iconSize);
lv_obj_set_style_text_color(icon, getIconColor(false, item.highlighted), LV_STATE_DEFAULT);
if (!monochrome) {
lv_obj_set_style_text_color(icon, getIconColor(false, item.highlighted), LV_STATE_DEFAULT);
}
lv_label_set_text(icon, item.icon);

lv_obj_t* label = lv_label_create(tile);
lv_obj_set_style_text_font(label, lvgl_get_text_font(FONT_SIZE_SMALL), LV_STATE_DEFAULT);
lv_obj_set_style_text_align(label, LV_TEXT_ALIGN_CENTER, LV_STATE_DEFAULT);
lv_obj_set_width(label, LV_PCT(100));
// Dots mode needs a fixed height, otherwise the label wraps instead of truncating
lv_obj_set_size(label, LV_PCT(100), lv_font_get_line_height(lvgl_get_text_font(FONT_SIZE_SMALL)));
lv_label_set_long_mode(label, LV_LABEL_LONG_MODE_DOTS);
lv_label_set_text(label, item.manifest.name);

Expand All @@ -194,8 +205,10 @@ void AppGrid::populate() {
if (callbacks.onKey != nullptr) {
lv_obj_add_event_cb(tile, onTileKey, LV_EVENT_KEY, this);
}
lv_obj_add_event_cb(tile, onTileFocusChanged, LV_EVENT_FOCUSED, nullptr);
lv_obj_add_event_cb(tile, onTileFocusChanged, LV_EVENT_DEFOCUSED, nullptr);
if (!monochrome) {
lv_obj_add_event_cb(tile, onTileFocusChanged, LV_EVENT_FOCUSED, nullptr);
lv_obj_add_event_cb(tile, onTileFocusChanged, LV_EVENT_DEFOCUSED, nullptr);
}

if (!focusedAppId.empty() && focusedAppId == item.manifest.id) {
focusedTile = tile;
Expand Down
Loading