feat(nyx): support per-tab backgrounds with shared fallback

This commit is contained in:
2025-11-11 20:41:39 +01:00
parent 5e8b01f727
commit 4c2b7d4b29
7 changed files with 155 additions and 28 deletions

View File

@@ -1,6 +1,16 @@
# Nyx - Background - Icons
The background for Nyx, must be a 1280 x 720 32-bit BMP. Alpha blending is taken into account. For that reason, if a solid background is required, that value must be 0xFF. There are sites that can produce the correct bmp.
The background for Nyx must be a 1280 x 720 32-bit BMP. Alpha blending is taken into account. For that reason, if a solid background is required, that value must be 0xFF. There are sites that can produce the correct bmp.
You can now provide section-specific backgrounds by placing any of the following files in `bootloader/res/`:
- `background_about.bmp`
- `background_home.bmp`
- `background_tools.bmp`
- `background_info.bmp`
- `background_options.bmp`
If a section-specific file is missing, Nyx will first try `background_etc.bmp` (shared across every non-Home tab) and then fall back to `background.bmp` when available.
The icons supported are 192 x 192 32-bit BMP. You can utilize transparency at will and make nice mixes with the button background.

View File

@@ -53,6 +53,48 @@ lv_img_dsc_t *icon_payload;
lv_img_dsc_t *icon_lakka;
lv_img_dsc_t *hekate_bg;
lv_img_dsc_t *hekate_bg_generic;
lv_img_dsc_t *hekate_bg_tabs[NYX_BG_TAB_MAX];
static lv_obj_t *nyx_bg_container;
static lv_obj_t *nyx_bg_img;
static lv_img_dsc_t *_nyx_get_tab_background(uint16_t tab_idx);
bool nyx_tab_has_background(enum nyx_bg_tab tab)
{
return _nyx_get_tab_background((uint16_t)tab) != NULL;
}
static bool _nyx_any_background(void)
{
if (hekate_bg || hekate_bg_generic)
return true;
for (int i = 0; i < NYX_BG_TAB_MAX; i++)
{
if (hekate_bg_tabs[i])
return true;
}
return false;
}
static lv_img_dsc_t *_nyx_get_tab_background(uint16_t tab_idx)
{
if (tab_idx < NYX_BG_TAB_MAX && hekate_bg_tabs[tab_idx])
return hekate_bg_tabs[tab_idx];
if (tab_idx == NYX_BG_TAB_HOME)
return hekate_bg ? hekate_bg : hekate_bg_generic;
if (hekate_bg_generic)
return hekate_bg_generic;
return hekate_bg;
}
static void _nyx_apply_tab_background(uint16_t tab_idx);
lv_style_t btn_transp_rel, btn_transp_pr, btn_transp_tgl_rel, btn_transp_tgl_pr;
lv_style_t ddlist_transp_bg, ddlist_transp_sel;
@@ -1217,7 +1259,7 @@ static void _create_text_button(lv_theme_t *th, lv_obj_t *parent, lv_obj_t *btn,
btn_onoff_rel_hos_style.body.empty = 1;
lv_style_copy(&btn_onoff_pr_hos_style, &btn_onoff_rel_hos_style);
if (hekate_bg)
if (nyx_tab_has_background(NYX_BG_TAB_OPTIONS))
{
btn_onoff_pr_hos_style.body.main_color = LV_COLOR_HEX(0xFFFFFF);
btn_onoff_pr_hos_style.body.opa = 35;
@@ -1448,7 +1490,6 @@ typedef struct _launch_menu_entries_t
static launch_menu_entries_t launch_ctxt;
static lv_obj_t *launch_bg = NULL;
static bool launch_bg_done = false;
static lv_res_t _launch_more_cfg_action(lv_obj_t *btn)
{
@@ -1484,13 +1525,12 @@ static lv_res_t _win_launch_close_action(lv_obj_t * btn)
lv_obj_del(win);
if (n_cfg.home_screen && !launch_bg_done && hekate_bg)
if (n_cfg.home_screen && launch_bg && nyx_tab_has_background(NYX_BG_TAB_HOME))
{
lv_obj_set_opa_scale_enable(launch_bg, true);
lv_obj_set_opa_scale(launch_bg, LV_OPA_TRANSP);
//if (launch_bg)
// lv_obj_del(launch_bg); //! TODO: Find why it hangs.
launch_bg_done = true;
}
close_btn = NULL;
@@ -1506,12 +1546,16 @@ static lv_obj_t *create_window_launch(const char *win_title)
win_bg_style.body.main_color = lv_theme_get_current()->bg->body.main_color;
win_bg_style.body.grad_color = win_bg_style.body.main_color;
if (n_cfg.home_screen && !launch_bg_done && hekate_bg)
if (n_cfg.home_screen && nyx_tab_has_background(NYX_BG_TAB_HOME))
{
lv_obj_t *img = lv_img_create(lv_scr_act(), NULL);
lv_img_set_src(img, hekate_bg);
launch_bg = img;
lv_img_dsc_t *bg = _nyx_get_tab_background(NYX_BG_TAB_HOME);
if (!launch_bg)
launch_bg = lv_img_create(lv_scr_act(), NULL);
else
lv_obj_set_parent(launch_bg, lv_scr_act());
lv_img_set_src(launch_bg, bg);
lv_obj_set_opa_scale_enable(launch_bg, false);
lv_obj_set_opa_scale(launch_bg, LV_OPA_COVER);
}
lv_obj_t *win = lv_win_create(lv_scr_act(), NULL);
@@ -1519,7 +1563,7 @@ static lv_obj_t *create_window_launch(const char *win_title)
lv_obj_set_size(win, LV_HOR_RES, LV_VER_RES);
if (n_cfg.home_screen && !launch_bg_done && hekate_bg)
if (n_cfg.home_screen && nyx_tab_has_background(NYX_BG_TAB_HOME))
{
lv_style_copy(&win_header, lv_theme_get_current()->win.header);
win_header.body.opa = LV_OPA_TRANSP;
@@ -1974,7 +2018,7 @@ static void _create_tab_home(lv_theme_t *th, lv_obj_t *parent)
// Launch button.
lv_obj_t *btn_launch = lv_btn_create(parent, NULL);
if (hekate_bg)
if (nyx_tab_has_background(NYX_BG_TAB_HOME))
{
lv_btn_set_style(btn_launch, LV_BTN_STYLE_REL, &btn_transp_rel);
lv_btn_set_style(btn_launch, LV_BTN_STYLE_PR, &btn_transp_pr);
@@ -2200,6 +2244,8 @@ void nyx_check_ini_changes()
static lv_res_t _show_hide_save_button(lv_obj_t *tv, uint16_t tab_idx)
{
_nyx_apply_tab_background(tab_idx);
if (tab_idx == 4) // Options.
{
lv_btn_set_action(status_bar.mid, LV_BTN_ACTION_CLICK, _save_options_action);
@@ -2217,6 +2263,29 @@ static lv_res_t _show_hide_save_button(lv_obj_t *tv, uint16_t tab_idx)
return LV_RES_OK;
}
static void _nyx_apply_tab_background(uint16_t tab_idx)
{
if (!nyx_bg_container)
return;
lv_img_dsc_t *bg = _nyx_get_tab_background(tab_idx);
if (!bg)
{
if (nyx_bg_img)
{
lv_obj_del(nyx_bg_img);
nyx_bg_img = NULL;
}
return;
}
if (!nyx_bg_img)
nyx_bg_img = lv_img_create(nyx_bg_container, NULL);
lv_img_set_src(nyx_bg_img, bg);
}
static void _nyx_set_default_styles(lv_theme_t * th)
{
lv_style_copy(&mbox_darken, &lv_style_plain);
@@ -2321,16 +2390,11 @@ static void _nyx_main_menu(lv_theme_t * th)
base_bg_style.body.grad_color = base_bg_style.body.main_color;
lv_cont_set_style(cnr, &base_bg_style);
lv_obj_set_size(cnr, LV_HOR_RES, LV_VER_RES);
if (hekate_bg)
{
lv_obj_t *img = lv_img_create(cnr, NULL);
lv_img_set_src(img, hekate_bg);
}
nyx_bg_container = cnr;
// Add tabview page to screen.
lv_obj_t *tv = lv_tabview_create(scr, NULL);
if (hekate_bg)
if (_nyx_any_background())
{
lv_tabview_set_style(tv, LV_TABVIEW_STYLE_BTN_PR, &tabview_btn_pr);
lv_tabview_set_style(tv, LV_TABVIEW_STYLE_BTN_TGL_PR, &tabview_btn_tgl_pr);
@@ -2356,6 +2420,8 @@ static void _nyx_main_menu(lv_theme_t * th)
lv_page_set_style(tab_info, LV_PAGE_STYLE_SCRL, &no_padding);
lv_obj_t *tab_options = lv_tabview_add_tab(tv, SYMBOL_SETTINGS" Options");
lv_page_set_style(tab_options, LV_PAGE_STYLE_BG, &no_padding);
lv_page_set_style(tab_options, LV_PAGE_STYLE_SCRL, &no_padding);
_create_tab_about(th, tab_about);
_create_tab_home(th, tab_home);
@@ -2364,6 +2430,7 @@ static void _nyx_main_menu(lv_theme_t * th)
create_tab_options(th, tab_options);
lv_tabview_set_tab_act(tv, 1, false);
_nyx_apply_tab_background(lv_tabview_get_tab_act(tv));
// Create status bar.
_create_status_bar(th);

View File

@@ -58,6 +58,20 @@ extern lv_img_dsc_t *icon_payload;
extern lv_img_dsc_t *icon_lakka;
extern lv_img_dsc_t *hekate_bg;
extern lv_img_dsc_t *hekate_bg_generic;
enum nyx_bg_tab {
NYX_BG_TAB_ABOUT = 0,
NYX_BG_TAB_HOME,
NYX_BG_TAB_TOOLS,
NYX_BG_TAB_INFO,
NYX_BG_TAB_OPTIONS,
NYX_BG_TAB_MAX
};
extern lv_img_dsc_t *hekate_bg_tabs[NYX_BG_TAB_MAX];
bool nyx_tab_has_background(enum nyx_bg_tab tab);
extern lv_style_t btn_transp_rel, btn_transp_pr, btn_transp_tgl_rel, btn_transp_tgl_pr;
extern lv_style_t ddlist_transp_bg, ddlist_transp_sel;

View File

@@ -2659,7 +2659,7 @@ void create_tab_info(lv_theme_t *th, lv_obj_t *parent)
// Create Bootrom button.
lv_obj_t *btn = lv_btn_create(h1, NULL);
if (hekate_bg)
if (nyx_tab_has_background(NYX_BG_TAB_INFO))
{
lv_btn_set_style(btn, LV_BTN_STYLE_REL, &btn_transp_rel);
lv_btn_set_style(btn, LV_BTN_STYLE_PR, &btn_transp_pr);
@@ -2755,7 +2755,7 @@ void create_tab_info(lv_theme_t *th, lv_obj_t *parent)
// Create eMMC button.
lv_obj_t *btn5 = lv_btn_create(h2, NULL);
if (hekate_bg)
if (nyx_tab_has_background(NYX_BG_TAB_INFO))
{
lv_btn_set_style(btn5, LV_BTN_STYLE_REL, &btn_transp_rel);
lv_btn_set_style(btn5, LV_BTN_STYLE_PR, &btn_transp_pr);
@@ -2787,7 +2787,7 @@ void create_tab_info(lv_theme_t *th, lv_obj_t *parent)
// Create Battery button.
lv_obj_t *btn7 = lv_btn_create(h2, NULL);
if (hekate_bg)
if (nyx_tab_has_background(NYX_BG_TAB_INFO))
{
lv_btn_set_style(btn7, LV_BTN_STYLE_REL, &btn_transp_rel);
lv_btn_set_style(btn7, LV_BTN_STYLE_PR, &btn_transp_pr);

View File

@@ -1397,7 +1397,7 @@ void create_tab_options(lv_theme_t *th, lv_obj_t *parent)
// Create Auto Boot button.
lv_obj_t *btn = lv_btn_create(sw_h2, NULL);
if (hekate_bg)
if (nyx_tab_has_background(NYX_BG_TAB_OPTIONS))
{
lv_btn_set_style(btn, LV_BTN_STYLE_REL, &btn_transp_rel);
lv_btn_set_style(btn, LV_BTN_STYLE_PR, &btn_transp_pr);
@@ -1448,7 +1448,7 @@ void create_tab_options(lv_theme_t *th, lv_obj_t *parent)
lv_ddlist_set_action(ddlist, _autoboot_delay_action);
lv_ddlist_set_selected(ddlist, h_cfg.bootwait);
if (hekate_bg)
if (nyx_tab_has_background(NYX_BG_TAB_OPTIONS))
{
lv_ddlist_set_style(ddlist, LV_DDLIST_STYLE_BG, &ddlist_transp_bg);
lv_ddlist_set_style(ddlist, LV_DDLIST_STYLE_BGO, &ddlist_transp_bg);

View File

@@ -1462,7 +1462,7 @@ static void _create_tab_tools_emmc_pkg12(lv_theme_t *th, lv_obj_t *parent)
// Create Backup eMMC button.
lv_obj_t *btn = lv_btn_create(h1, NULL);
if (hekate_bg)
if (nyx_tab_has_background(NYX_BG_TAB_TOOLS))
{
lv_btn_set_style(btn, LV_BTN_STYLE_REL, &btn_transp_rel);
lv_btn_set_style(btn, LV_BTN_STYLE_PR, &btn_transp_pr);
@@ -1517,7 +1517,7 @@ static void _create_tab_tools_emmc_pkg12(lv_theme_t *th, lv_obj_t *parent)
// Create Partition SD Card button.
lv_obj_t *btn3 = lv_btn_create(h2, NULL);
if (hekate_bg)
if (nyx_tab_has_background(NYX_BG_TAB_TOOLS))
{
lv_btn_set_style(btn3, LV_BTN_STYLE_REL, &btn_transp_rel);
lv_btn_set_style(btn3, LV_BTN_STYLE_PR, &btn_transp_pr);
@@ -1580,7 +1580,7 @@ static void _create_tab_tools_arc_autorcm(lv_theme_t *th, lv_obj_t *parent)
// Create fix archive bit button.
lv_obj_t *btn = lv_btn_create(h1, NULL);
if (hekate_bg)
if (nyx_tab_has_background(NYX_BG_TAB_TOOLS))
{
lv_btn_set_style(btn, LV_BTN_STYLE_REL, &btn_transp_rel);
lv_btn_set_style(btn, LV_BTN_STYLE_PR, &btn_transp_pr);
@@ -1633,7 +1633,7 @@ static void _create_tab_tools_arc_autorcm(lv_theme_t *th, lv_obj_t *parent)
// Create AutoRCM On/Off button.
lv_obj_t *btn3 = lv_btn_create(h2, NULL);
if (hekate_bg)
if (nyx_tab_has_background(NYX_BG_TAB_TOOLS))
{
lv_btn_set_style(btn3, LV_BTN_STYLE_REL, &btn_transp_rel);
lv_btn_set_style(btn3, LV_BTN_STYLE_PR, &btn_transp_pr);

View File

@@ -326,6 +326,42 @@ static void nyx_load_bg_icons()
// Load background resource if any.
hekate_bg = bmp_to_lvimg_obj("bootloader/res/background.bmp");
hekate_bg_generic = bmp_to_lvimg_obj("bootloader/res/background_etc.bmp");
memset(hekate_bg_tabs, 0, sizeof(hekate_bg_tabs));
static const struct {
const char *path;
enum nyx_bg_tab tab;
} bg_sources[] = {
{ "bootloader/res/background_about.bmp", NYX_BG_TAB_ABOUT },
{ "bootloader/res/background_home.bmp", NYX_BG_TAB_HOME },
{ "bootloader/res/background_tools.bmp", NYX_BG_TAB_TOOLS },
{ "bootloader/res/background_info.bmp", NYX_BG_TAB_INFO },
{ "bootloader/res/background_options.bmp", NYX_BG_TAB_OPTIONS },
};
for (size_t i = 0; i < sizeof(bg_sources) / sizeof(bg_sources[0]); i++)
{
lv_img_dsc_t *img = bmp_to_lvimg_obj(bg_sources[i].path);
if (img)
hekate_bg_tabs[bg_sources[i].tab] = img;
}
if (!hekate_bg && hekate_bg_generic)
hekate_bg = hekate_bg_generic;
if (!hekate_bg)
{
for (int i = 0; i < NYX_BG_TAB_MAX; i++)
{
if (hekate_bg_tabs[i])
{
hekate_bg = hekate_bg_tabs[i];
break;
}
}
}
}
#define EXCP_EN_ADDR 0x4003FFFC