menu: the media viewer's title follows the image shown

In Ozone, opening an image from the file browser with OK and pressing
Up/Down to step to the next image changed the picture but kept the
first image's name as the title.

The title was refreshed by each menu driver on a selection change, and
Ozone only did that when the fullscreen view had been asked for with
START. The viewer opened by OK sets the "shown" flag but not the
"wanted" one, so its title was never refreshed while stepping.

Every step through the viewer - the OK that opens it, Up/Down/Left/
Right, continuous playback - goes through
menu_media_open_selected_file, so the title now belongs there: it takes
the driver's title buffer and rewrites it for the file it opens. Ozone
and XMB pass theirs; no driver can open a file in the viewer and leave
the old name up. A row the viewer cannot show leaves the title alone.

samples/gfx/media_controls: viewer_title drives the real
menu_media_browser.c through OK, Down, a row the viewer cannot show,
Down past it and Up, checking the title each time, plus truncation to
the buffer and no buffer. It fails on the old code.
This commit is contained in:
LibretroAdmin authored and libretroadmin committed 2026-11-07 16:29:11 +01:00
1 parent 1838427ffe
commit 2443ac01fe
5 files changed
+125 -13

No files matched your search

+9 -3
View File
@@ -9177,7 +9177,9 @@ static enum menu_action ozone_parse_menu_entry_action(
&& menu_media_selected_in_history(menu_st)))
&& !(ozone->flags2 & OZONE_FLAG2_SHOW_FULLSCREEN_THUMBNAILS)
&& (action == MENU_ACTION_OK || action == MENU_ACTION_SELECT || action == MENU_ACTION_START)
&& menu_media_open_selected_file(menu_st, &ozone->thumbnails.left, &ozone->thumbnails.right))
&& menu_media_open_selected_file(menu_st, &ozone->thumbnails.left, &ozone->thumbnails.right,
ozone->fullscreen_thumbnail_label,
sizeof(ozone->fullscreen_thumbnail_label)))
{
ozone->thumbnails.pending = OZONE_PENDING_THUMBNAIL_NONE;
ozone->flags |= OZONE_FLAG_FULLSCREEN_THUMBNAILS_AVAILABLE;
@@ -10837,7 +10839,9 @@ static void ozone_context_reset(void *data, bool is_threaded)
&& ((ozone->flags & OZONE_FLAG_IS_FILE_LIST)
|| menu_media_selected_in_history(menu_state_get_ptr()))
&& menu_media_open_selected_file(menu_state_get_ptr(),
&ozone->thumbnails.left, &ozone->thumbnails.right))
&ozone->thumbnails.left, &ozone->thumbnails.right,
ozone->fullscreen_thumbnail_label,
sizeof(ozone->fullscreen_thumbnail_label)))
ozone->thumbnails.pending = OZONE_PENDING_THUMBNAIL_NONE;
ozone_update_savestate_thumbnail_image(ozone);
@@ -12993,7 +12997,9 @@ static void ozone_navigation_set(void *data, bool scroll)
&& ((ozone->flags & OZONE_FLAG_IS_FILE_LIST)
|| menu_media_selected_in_history(menu_state_get_ptr()))
&& menu_media_open_selected_file(menu_state_get_ptr(),
&ozone->thumbnails.left, &ozone->thumbnails.right))
&ozone->thumbnails.left, &ozone->thumbnails.right,
ozone->fullscreen_thumbnail_label,
sizeof(ozone->fullscreen_thumbnail_label)))
ozone->thumbnails.pending = OZONE_PENDING_THUMBNAIL_NONE;
}
+9 -3
View File
@@ -6222,7 +6222,9 @@ static enum menu_action xmb_parse_menu_entry_action(
&& menu_media_selected_in_history(menu_st)))
&& !xmb->show_fullscreen_thumbnails
&& (action == MENU_ACTION_OK || action == MENU_ACTION_SELECT || action == MENU_ACTION_START)
&& menu_media_open_selected_file(menu_st, &xmb->thumbnails.left, &xmb->thumbnails.right))
&& menu_media_open_selected_file(menu_st, &xmb->thumbnails.left, &xmb->thumbnails.right,
xmb->fullscreen_thumbnail_label,
sizeof(xmb->fullscreen_thumbnail_label)))
{
xmb->thumbnails.pending = XMB_PENDING_THUMBNAIL_NONE;
xmb->fullscreen_thumbnails_available = true;
@@ -7369,7 +7371,9 @@ static void xmb_context_reset_internal(xmb_handle_t *xmb,
&& (xmb->is_file_list
|| (xmb->is_playlist && menu_media_selected_in_history(menu_st)))
&& menu_media_open_selected_file(menu_st,
&xmb->thumbnails.left, &xmb->thumbnails.right))
&xmb->thumbnails.left, &xmb->thumbnails.right,
xmb->fullscreen_thumbnail_label,
sizeof(xmb->fullscreen_thumbnail_label)))
xmb->thumbnails.pending = XMB_PENDING_THUMBNAIL_NONE;
/* Have to reset this, otherwise savestate
@@ -10070,7 +10074,9 @@ static void xmb_navigation_set(void *data, bool scroll)
&& (xmb->is_file_list || (xmb->is_playlist
&& menu_media_selected_in_history(menu_state_get_ptr())))
&& menu_media_open_selected_file(menu_state_get_ptr(),
&xmb->thumbnails.left, &xmb->thumbnails.right))
&xmb->thumbnails.left, &xmb->thumbnails.right,
xmb->fullscreen_thumbnail_label,
sizeof(xmb->fullscreen_thumbnail_label)))
xmb->thumbnails.pending = XMB_PENDING_THUMBNAIL_NONE;
}
+10 -1
View File
@@ -261,7 +261,8 @@ bool menu_media_selected_in_history(struct menu_state *menu_st)
}
bool menu_media_open_selected_file(struct menu_state *menu_st,
gfx_thumbnail_t *primary, gfx_thumbnail_t *secondary)
gfx_thumbnail_t *primary, gfx_thumbnail_t *secondary,
char *title, size_t title_len)
{
#if defined(HAVE_IMAGEVIEWER) || defined(HAVE_MENU)
char history_dir[DIR_MAX_LENGTH];
@@ -302,5 +303,13 @@ bool menu_media_open_selected_file(struct menu_state *menu_st,
gfx_thumbnail_request_file(paths->content_path, primary,
config_get_ptr()->uints.gfx_thumbnail_upscale_threshold);
}
/* The title goes with the file shown. Left to the menu drivers, it
* was only refreshed when the fullscreen view had been asked for
* with START: Ozone's viewer opened by OK kept the first file's
* title through every Up/Down to the next image. */
if (title && title_len
&& !menu_update_fullscreen_thumbnail_label(title, title_len,
false, NULL))
*title = '\0';
return true;
}
+6 -2
View File
@@ -23,8 +23,12 @@ const char *menu_media_selected_history_image(struct menu_state *menu_st);
bool menu_media_selected_in_history(struct menu_state *menu_st);
/* Main-thread image/movie activation, independent of playlist thumbnail settings.
* Retains a matching preview and removes a duplicate/obsolete second one. */
* Retains a matching preview and removes a duplicate/obsolete second one.
* @title (@title_len bytes) is the viewer's title: it is rewritten for the
* file opened, so the title follows every step to another file - the OK
* that opens the viewer, Up/Down/Left/Right, and continuous playback. */
bool menu_media_open_selected_file(struct menu_state *menu_st,
gfx_thumbnail_t *primary, gfx_thumbnail_t *secondary);
gfx_thumbnail_t *primary, gfx_thumbnail_t *secondary,
char *title, size_t title_len);
RETRO_END_DECLS
#endif
@@ -141,14 +141,34 @@ bool gfx_thumbnail_set_repeat(gfx_thumbnail_t *t, bool repeat)
{ (void)t; (void)repeat; return false; }
bool gfx_thumbnail_take_completed(gfx_thumbnail_t *t)
{ (void)t; return false; }
/* Thumbnail loads are tested in gfx_thumbnail_anim; only viewer_title
* opens files here, and every other lane must not reach them. */
static bool viewer_opening;
static unsigned viewer_requests;
bool gfx_thumbnail_has_file(const gfx_thumbnail_t *t, const char *path)
{ (void)t; (void)path; abort(); return false; }
void gfx_thumbnail_reset(gfx_thumbnail_t *t) { (void)t; abort(); }
{ (void)t; (void)path; if (!viewer_opening) abort(); return false; }
void gfx_thumbnail_reset(gfx_thumbnail_t *t)
{ (void)t; if (!viewer_opening) abort(); }
void gfx_thumbnail_request_file(const char *path, gfx_thumbnail_t *t, unsigned n)
{ (void)path; (void)t; (void)n; abort(); }
{ (void)path; (void)t; (void)n; if (!viewer_opening) abort(); viewer_requests++; }
bool gfx_thumbnail_set_content_image(gfx_thumbnail_path_data_t *p,
const char *dir, const char *name)
{ (void)p; (void)dir; (void)name; abort(); return false; }
{
if (!viewer_opening) abort();
snprintf(p->content_path, sizeof(p->content_path), "%s/%s", dir, name);
return true;
}
/* What menu_driver.c gives a file browser row: its rich label, else its
* name. */
size_t menu_update_fullscreen_thumbnail_label(char *s, size_t len,
bool is_quick_menu, const char *title)
{
file_list_t *list = MENU_LIST_GET_SELECTION(test_menu.entries.list, 0);
const char *name = list->list[test_menu.selection_ptr].path;
(void)title;
if (!viewer_opening || is_quick_menu) abort();
return *name ? strlcpy(s, name, len) : 0;
}
task_subtitle_catalog_t *task_subtitle_discover(const char *path)
{ (void)path; abort(); return NULL; }
int task_subtitle_catalog_status(const task_subtitle_catalog_t *catalog)
@@ -227,6 +247,72 @@ static void folder_queue(void)
test_menu.driver_ctx = NULL;
}
/* The viewer's title follows the file shown. Ozone's viewer opened with
* OK refreshed its title only when the fullscreen view had been asked for
* with START, so Up/Down to the next image kept the first one's name;
* the title now belongs to menu_media_open_selected_file, which every
* step through the viewer goes through, in Ozone and XMB alike. */
static void viewer_title(void)
{
static menu_list_t lists;
static gfx_thumbnail_path_data_t paths;
gfx_thumbnail_t left, right;
file_list_t *selection[1], *stack[1];
char title[64];
memset(&left, 0, sizeof(left));
memset(&right, 0, sizeof(right));
selection[0] = (file_list_t*)calloc(1, sizeof(file_list_t));
stack[0] = (file_list_t*)calloc(1, sizeof(file_list_t));
CHECK(selection[0] && stack[0]);
lists.selection_buf = selection; lists.selection_buf_size = 1;
lists.menu_stack = stack; lists.menu_stack_size = 1;
test_menu.entries.list = &lists;
test_menu.thumbnail_path_data = &paths;
CHECK(file_list_append(stack[0], "/pics", "", FILE_TYPE_DIRECTORY, 0, 0));
CHECK(file_list_append(selection[0], "first.png", "", FILE_TYPE_IMAGEVIEWER, 0, 0));
CHECK(file_list_append(selection[0], "second.jpg", "", FILE_TYPE_IMAGEVIEWER, 0, 0));
CHECK(file_list_append(selection[0], "folder", "", FILE_TYPE_DIRECTORY, 0, 0));
CHECK(file_list_append(selection[0], "third.gif", "", FILE_TYPE_IMAGEVIEWER, 0, 0));
viewer_opening = true;
/* OK opens the viewer on the first image */
test_menu.selection_ptr = 0;
strlcpy(title, "stale", sizeof(title));
CHECK(menu_media_open_selected_file(&test_menu, &left, &right,
title, sizeof(title)));
CHECK(!strcmp(title, "first.png"));
/* Down: the next image, and its name */
test_menu.selection_ptr = 1;
CHECK(menu_media_open_selected_file(&test_menu, &left, &right,
title, sizeof(title)));
CHECK(!strcmp(title, "second.jpg"));
CHECK(!strcmp(paths.content_path, "/pics/second.jpg"));
/* a row the viewer cannot show leaves the title of the one shown */
test_menu.selection_ptr = 2;
CHECK(!menu_media_open_selected_file(&test_menu, &left, &right,
title, sizeof(title)));
CHECK(!strcmp(title, "second.jpg"));
/* Down again, past it */
test_menu.selection_ptr = 3;
CHECK(menu_media_open_selected_file(&test_menu, &left, &right,
title, sizeof(title)));
CHECK(!strcmp(title, "third.gif"));
/* Up: back to the first */
test_menu.selection_ptr = 0;
CHECK(menu_media_open_selected_file(&test_menu, &left, &right,
title, sizeof(title)));
CHECK(!strcmp(title, "first.png"));
/* truncated to the buffer, never past it */
CHECK(menu_media_open_selected_file(&test_menu, &left, &right, title, 4));
CHECK(!strcmp(title, "fir"));
/* no title buffer: the file still opens */
CHECK(menu_media_open_selected_file(&test_menu, &left, &right, NULL, 0));
CHECK(viewer_requests == 6);
viewer_opening = false;
file_list_free(selection[0]); file_list_free(stack[0]);
test_menu.entries.list = NULL;
test_menu.thumbnail_path_data = NULL;
}
/* Loading is tested separately; this drawing oracle publishes cue views. */
task_subtitle_request_t *task_subtitle_load(const char *path)
{ (void)path; abort(); return NULL; }
@@ -1274,6 +1360,7 @@ int main(void)
display_races();
#endif
folder_queue();
viewer_title();
combined_subtitle_toolbar();
subtitle_button();
subtitles_without_transport();