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
This commit is contained in:
Christian Soffke 2025-12-24 11:38:39 +01:00 committed by Solomon Peachy
parent 399230e9ec
commit 18dfd8f691
10 changed files with 88 additions and 29 deletions

View file

@ -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;
}

View file

@ -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;

View file

@ -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

View file

@ -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();
}

View file

@ -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);
}

View file

@ -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() */
}

View file

@ -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;

View file

@ -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 */

View file

@ -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;

View file

@ -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);