From 18dfd8f691a8068ab466b2b5c03bc00ef790b736 Mon Sep 17 00:00:00 2001 From: Christian Soffke Date: Wed, 24 Dec 2025 11:38:39 +0100 Subject: [PATCH] Reduce list title glitches when switching between menus Each time viewportmanager_theme_enable (or _undo) is called, the SBS title is reset, even if the theme remains enabled. Thus switching from one menu to another, if do_menu is called again, briefly results in an empty title before the correct one is displayed. Even unchanged titles will unnecessarily flash for a moment. Other theme elements that are drawn using conditions based on the title, may also appear glitchy. This patch adds a way to make the status bar title persist by copying it to a static buffer. Persistent titles are not reset by toggle_theme (although scrolling will be stopped in viewportmanager_theme_undo), so that the theme can immediately display the appropriate title in do_menu, simplelist_show_list, the yesno screen, or plugins that want to keep the theme enabled. Change-Id: I1ec8f233b730321793eb7d3cad51496ee1b35440 --- apps/gui/list.c | 9 +++- apps/gui/statusbar-skinned.c | 20 +++++++++ apps/gui/statusbar-skinned.h | 3 ++ apps/gui/viewport.c | 5 ++- apps/gui/yesno.c | 4 +- apps/menu.c | 64 +++++++++++++++++---------- apps/plugin.c | 1 + apps/plugin.h | 2 + apps/plugins/playing_time.c | 5 ++- apps/plugins/text_viewer/tv_display.c | 4 ++ 10 files changed, 88 insertions(+), 29 deletions(-) diff --git a/apps/gui/list.c b/apps/gui/list.c index f324e538ce..572a7757cc 100644 --- a/apps/gui/list.c +++ b/apps/gui/list.c @@ -882,7 +882,8 @@ bool simplelist_show_list(struct simplelist_info *info) struct gui_synclist lists; int action, old_line_count = simplelist_line_count; list_get_name *getname; - int line_count, ret = false; + int line_count; + bool ret = false; if (info->get_name) { @@ -896,7 +897,10 @@ bool simplelist_show_list(struct simplelist_info *info) } FOR_NB_SCREENS(i) + { + sb_set_persistent_title(info->title, info->title_icon, i); viewportmanager_theme_enable(i, !info->hide_theme, NULL); + } gui_synclist_init(&lists, getname, info->callback_data, info->scroll_all, info->selection_size, NULL); @@ -985,7 +989,10 @@ bool simplelist_show_list(struct simplelist_info *info) #endif FOR_NB_SCREENS(i) + { + sb_set_persistent_title(info->title, info->title_icon, i); viewportmanager_theme_undo(i, false); + } return ret; } diff --git a/apps/gui/statusbar-skinned.c b/apps/gui/statusbar-skinned.c index 52fc17deaf..0242016e1e 100644 --- a/apps/gui/statusbar-skinned.c +++ b/apps/gui/statusbar-skinned.c @@ -39,6 +39,7 @@ #include "icon.h" #include "icons.h" #include "option_select.h" +#include "string-extra.h" #ifdef HAVE_TOUCHSCREEN #include "sound.h" #include "misc.h" @@ -49,6 +50,7 @@ static int update_delay = DEFAULT_UPDATE_DELAY; static bool sbs_has_title[NB_SCREENS]; static const char* sbs_title[NB_SCREENS]; +static char sbs_persistent_title[NB_SCREENS][80]; static enum themable_icons sbs_icon[NB_SCREENS]; static bool sbs_loaded[NB_SCREENS] = { false }; @@ -62,6 +64,15 @@ bool sb_set_title_text(const char* title, enum themable_icons icon, enum screen_ return sbs_has_title[screen]; } +bool sb_set_persistent_title(const char* title, enum themable_icons icon, enum screen_type screen) +{ + if (!title) + return sb_set_title_text(title, icon, screen); + + strlcpy(sbs_persistent_title[screen], title, sizeof(*sbs_persistent_title)); + return sb_set_title_text((const char *) sbs_persistent_title[screen], icon, screen); +} + void sb_skin_has_title(enum screen_type screen) { sbs_has_title[screen] = true; @@ -71,6 +82,15 @@ const char* sb_get_title(enum screen_type screen) { return sbs_has_title[screen] ? sbs_title[screen] : NULL; } + +const char* sb_get_persistent_title(enum screen_type screen) +{ + return (sbs_has_title[screen] && + sbs_title[screen] == sbs_persistent_title[screen]) ? + sbs_title[screen] : NULL; + +} + enum themable_icons sb_get_icon(enum screen_type screen) { return sbs_has_title[screen] ? sbs_icon[screen] : Icon_NOICON + 2; diff --git a/apps/gui/statusbar-skinned.h b/apps/gui/statusbar-skinned.h index 4e7c461f90..905a15b369 100644 --- a/apps/gui/statusbar-skinned.h +++ b/apps/gui/statusbar-skinned.h @@ -39,8 +39,11 @@ void sb_skin_update(enum screen_type screen, bool force); void sb_skin_set_update_delay(int delay); bool sb_set_title_text(const char* title, enum themable_icons icon, enum screen_type screen); +bool sb_set_persistent_title(const char* title, enum themable_icons icon, + enum screen_type screen); void sb_skin_has_title(enum screen_type screen); const char* sb_get_title(enum screen_type screen); +const char* sb_get_persistent_title(enum screen_type screen); enum themable_icons sb_get_icon(enum screen_type screen); #ifdef HAVE_TOUCHSCREEN diff --git a/apps/gui/viewport.c b/apps/gui/viewport.c index cf81f7d009..1d89467682 100644 --- a/apps/gui/viewport.c +++ b/apps/gui/viewport.c @@ -111,7 +111,8 @@ static void toggle_theme(enum screen_type screen, bool force) FOR_NB_SCREENS(i) { enable_event = enable_event || is_theme_enabled(i); - sb_set_title_text(NULL, Icon_NOICON, i); + if (!sb_get_persistent_title(i)) + sb_set_title_text(NULL, Icon_NOICON, i); } toggle_events(enable_event); @@ -195,6 +196,8 @@ void viewportmanager_theme_undo(enum screen_type screen, bool force_redraw) panicf("Stack underflow... viewportmanager"); toggle_theme(screen, force_redraw); + if (sb_get_persistent_title(screen)) + screens[screen].scroll_stop(); } diff --git a/apps/gui/yesno.c b/apps/gui/yesno.c index bb0132e79b..4838366134 100644 --- a/apps/gui/yesno.c +++ b/apps/gui/yesno.c @@ -243,9 +243,8 @@ enum yesno_res gui_syncyesno_run_w_tmo(int ticks, enum yesno_res tmo_default_res yn[i].main_message=main_message; yn[i].display=&screens[i]; screens[i].scroll_stop(); + sb_set_persistent_title(title, Icon_NOICON, i); viewportmanager_theme_enable(i, true, &(yn[i].vp)); - if (sb_set_title_text(title, Icon_NOICON, i)) - send_event(GUI_EVENT_ACTIONUPDATE, (void*)1); yn[i].vp_lines = viewport_get_nb_lines(&(yn[i].vp)); } @@ -355,6 +354,7 @@ exit: FOR_NB_SCREENS(i) { screens[i].scroll_stop_viewport(&(yn[i].vp)); + sb_set_persistent_title(title, Icon_NOICON, i); viewportmanager_theme_undo(i, true); } diff --git a/apps/menu.c b/apps/menu.c index 2a56292ec6..89c29f4cae 100644 --- a/apps/menu.c +++ b/apps/menu.c @@ -53,6 +53,7 @@ #include "viewport.h" #include "quickscreen.h" #include "shortcuts.h" +#include "statusbar-skinned.h" #include "icons.h" @@ -66,6 +67,8 @@ static struct menu_item_ex *current_submenus_menu; static int current_subitems[MAX_MENU_SUBITEMS]; static int current_subitems_count = 0; static int talk_menu_item(int selected_item, void *data); +static char *title_buf; +static size_t title_buf_sz; struct menu_data_t { @@ -197,6 +200,34 @@ static enum themable_icons menu_get_icon(int selected_item, void * data) return menu_icon; } +static char* init_title(const struct menu_item_ex *menu, int *icon) +{ + char *title; + + if (menu->flags&MENU_HAS_DESC) + { + *icon = menu->callback_and_desc->icon_id; + title = P2STR(menu->callback_and_desc->desc); + } + else if (menu->flags&MENU_DYNAMIC_DESC) + { + *icon = menu->menu_get_name_and_icon->icon_id; + title = menu->menu_get_name_and_icon-> + list_get_name(-1, menu->menu_get_name_and_icon-> + list_get_name_data, title_buf, title_buf_sz); + } + else + { + *icon = Icon_NOICON; + title = ""; + } + + if (*icon == Icon_NOICON) + *icon = Icon_Submenu_Entered; + + return title; +} + static int init_menu_lists(const struct menu_item_ex *menu, struct gui_synclist *lists, int selected, bool callback, struct viewport parent[NB_SCREENS]) @@ -236,28 +267,7 @@ static int init_menu_lists(const struct menu_item_ex *menu, current_submenus_menu = (struct menu_item_ex *)menu; gui_synclist_init(lists,get_menu_item_name,(void*)menu,false,1, parent); - - if (menu->flags&MENU_HAS_DESC) - { - icon = menu->callback_and_desc->icon_id; - title = P2STR(menu->callback_and_desc->desc); - } - else if (menu->flags&MENU_DYNAMIC_DESC) - { - char buffer[80]; - icon = menu->menu_get_name_and_icon->icon_id; - title = menu->menu_get_name_and_icon-> - list_get_name(-1, menu->menu_get_name_and_icon-> - list_get_name_data, buffer, sizeof(buffer)); - } - else - { - icon = Icon_NOICON; - title = ""; - } - - if (icon == Icon_NOICON) - icon = Icon_Submenu_Entered; + title = init_title(menu, &icon); gui_synclist_set_title(lists, title, icon); gui_synclist_set_icon_callback(lists, global_settings.show_icons?menu_get_icon:NULL); if(global_settings.talk_menu) @@ -382,6 +392,8 @@ int do_menu(const struct menu_item_ex *start_menu, int *start_selected, int ret = 0; int action; int start_action; + int icon; + char buf[80], *title; struct gui_synclist lists; const struct menu_item_ex *temp = NULL; const struct menu_item_ex *menu = start_menu; @@ -398,9 +410,14 @@ int do_menu(const struct menu_item_ex *start_menu, int *start_selected, touchscreen_set_mode(global_settings.touch_mode); #endif + title_buf = buf; + title_buf_sz = sizeof buf; + title = init_title(menu, &icon); FOR_NB_SCREENS(i) + { + sb_set_persistent_title(title, icon, i); viewportmanager_theme_enable(i, !hide_theme, NULL); - + } struct menu_data_t mstack[MAX_MENUS]; /* menu, selected */ int stack_top = 0; @@ -785,6 +802,7 @@ int do_menu(const struct menu_item_ex *start_menu, int *start_selected, FOR_NB_SCREENS(i) { + sb_set_persistent_title(lists.title, lists.title_icon, i); viewportmanager_theme_undo(i, false); skinlist_set_cfg(i, NULL); /* Bugfix dangling reference in skin_draw() */ } diff --git a/apps/plugin.c b/apps/plugin.c index 113bad7d26..0679d60f23 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -874,6 +874,7 @@ static const struct plugin_api rockbox_api = { /* new stuff at the end, sort into place next time the API gets incompatible */ + sb_set_persistent_title, }; static int plugin_buffer_handle; diff --git a/apps/plugin.h b/apps/plugin.h index 1402a9575c..64ae2c0449 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -1026,6 +1026,8 @@ struct plugin_api { /* new stuff at the end, sort into place next time the API gets incompatible */ + bool (*sb_set_persistent_title)(const char* title, enum themable_icons icon, + enum screen_type screen); }; /* plugin header */ diff --git a/apps/plugins/playing_time.c b/apps/plugins/playing_time.c index 6a63c3dd8d..6504988026 100644 --- a/apps/plugins/playing_time.c +++ b/apps/plugins/playing_time.c @@ -560,10 +560,11 @@ enum plugin_status plugin_start(const void* parameter) return status; } - /* Only relevant if launched using hotkey from the - WPS. Otherwise theme should be enabled already. */ FOR_NB_SCREENS(i) + { + rb->sb_set_persistent_title(rb->str(LANG_PLAYING_TIME), Icon_NOICON, i); rb->viewportmanager_theme_enable(i, true, NULL); + } if (playing_time()) status = PLUGIN_USB_CONNECTED; diff --git a/apps/plugins/text_viewer/tv_display.c b/apps/plugins/text_viewer/tv_display.c index dfce96f3ab..62e811cbb0 100644 --- a/apps/plugins/text_viewer/tv_display.c +++ b/apps/plugins/text_viewer/tv_display.c @@ -300,10 +300,14 @@ static void tv_change_viewport(void) bool show_statusbar = preferences->statusbar; if (is_initialized_vp) + { + rb->sb_set_persistent_title(tv_get_title_text(), Icon_NOICON, SCREEN_MAIN); rb->viewportmanager_theme_undo(SCREEN_MAIN, false); + } else is_initialized_vp = true; + rb->sb_set_persistent_title(tv_get_title_text(), Icon_NOICON, SCREEN_MAIN); rb->viewportmanager_theme_enable(SCREEN_MAIN, show_statusbar, &vp_info); vp_info.flags &= ~VP_FLAG_ALIGNMENT_MASK; display->set_viewport(&vp_info);