From 4c2b7d4b29fa4991280a79de61c37689acd386b6 Mon Sep 17 00:00:00 2001 From: niklascfw Date: Tue, 11 Nov 2025 20:41:39 +0100 Subject: [PATCH] feat(nyx): support per-tab backgrounds with shared fallback --- nyx/README_RES.md | 12 +++- nyx/nyx_gui/frontend/gui.c | 103 ++++++++++++++++++++++++----- nyx/nyx_gui/frontend/gui.h | 14 ++++ nyx/nyx_gui/frontend/gui_info.c | 6 +- nyx/nyx_gui/frontend/gui_options.c | 4 +- nyx/nyx_gui/frontend/gui_tools.c | 8 +-- nyx/nyx_gui/nyx.c | 36 ++++++++++ 7 files changed, 155 insertions(+), 28 deletions(-) diff --git a/nyx/README_RES.md b/nyx/README_RES.md index f4f54e3..eb874f9 100644 --- a/nyx/README_RES.md +++ b/nyx/README_RES.md @@ -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. diff --git a/nyx/nyx_gui/frontend/gui.c b/nyx/nyx_gui/frontend/gui.c index 47bef3b..ef072b3 100644 --- a/nyx/nyx_gui/frontend/gui.c +++ b/nyx/nyx_gui/frontend/gui.c @@ -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); diff --git a/nyx/nyx_gui/frontend/gui.h b/nyx/nyx_gui/frontend/gui.h index 3f13444..4ca7d4b 100644 --- a/nyx/nyx_gui/frontend/gui.h +++ b/nyx/nyx_gui/frontend/gui.h @@ -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; diff --git a/nyx/nyx_gui/frontend/gui_info.c b/nyx/nyx_gui/frontend/gui_info.c index d7351ab..924fc32 100644 --- a/nyx/nyx_gui/frontend/gui_info.c +++ b/nyx/nyx_gui/frontend/gui_info.c @@ -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); diff --git a/nyx/nyx_gui/frontend/gui_options.c b/nyx/nyx_gui/frontend/gui_options.c index 15feeac..4f04796 100644 --- a/nyx/nyx_gui/frontend/gui_options.c +++ b/nyx/nyx_gui/frontend/gui_options.c @@ -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); diff --git a/nyx/nyx_gui/frontend/gui_tools.c b/nyx/nyx_gui/frontend/gui_tools.c index 3229814..df06b80 100644 --- a/nyx/nyx_gui/frontend/gui_tools.c +++ b/nyx/nyx_gui/frontend/gui_tools.c @@ -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); diff --git a/nyx/nyx_gui/nyx.c b/nyx/nyx_gui/nyx.c index 05275a2..e45ba74 100644 --- a/nyx/nyx_gui/nyx.c +++ b/nyx/nyx_gui/nyx.c @@ -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