From 7ab1a81806e831be134da480b4c5b178167380de Mon Sep 17 00:00:00 2001 From: Christian Soffke Date: Tue, 28 Apr 2026 05:36:12 +0200 Subject: [PATCH] simple_viewer: use UI viewport and SBS title Also adjust scrollbar margins and height so it matches the look of normal lists, and hide scrollbars when set to SCROLLBAR_OFF. Change-Id: I27f6de7b16cf5ec72e12c7d6377a8772d84947ac --- apps/plugin.c | 4 ++ apps/plugin.h | 11 +++ apps/plugins/lib/simple_viewer.c | 115 +++++++++++++++++++++---------- apps/plugins/properties.c | 16 ++--- apps/screens.c | 7 +- 5 files changed, 100 insertions(+), 53 deletions(-) diff --git a/apps/plugin.c b/apps/plugin.c index d787149de2..57f0cb3d97 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -872,6 +872,9 @@ static const struct plugin_api rockbox_api = { /* new stuff at the end, sort into place next time the API gets incompatible */ panicf, + gui_synclist_scroll_stop, + add_event_ex, + remove_event_ex, }; static int plugin_buffer_handle; @@ -892,6 +895,7 @@ int plugin_load(const char* plugin, const void* parameter) !strcmp("playing_time.rock", sepch + 1) || !strcmp("main_menu_config.rock", sepch + 1) || !strcmp("text_viewer.rock", sepch + 1) || + !strcmp("view_text.rock", sepch + 1) || !strcmp("disktidy.rock", sepch + 1) || !strcmp("open_plugins.rock", sepch + 1)); diff --git a/apps/plugin.h b/apps/plugin.h index f6c3434692..6abab07cd0 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -1025,6 +1025,17 @@ struct plugin_api { /* new stuff at the end, sort into place next time the API gets incompatible */ void (*panicf)(const char *msg, ...); + void (*gui_synclist_scroll_stop)(struct gui_synclist *lists); + bool (*add_event_ex)(unsigned short id, bool oneshot, + void (*handler)(unsigned short id, + void *event_data, + void *user_data), + void *user_data); + void (*remove_event_ex)(unsigned short id, + void (*handler)(unsigned short id, + void *event_data, + void *user_data), + void *user_data); }; /* plugin header */ diff --git a/apps/plugins/lib/simple_viewer.c b/apps/plugins/lib/simple_viewer.c index e71efce753..bffea2080a 100644 --- a/apps/plugins/lib/simple_viewer.c +++ b/apps/plugins/lib/simple_viewer.c @@ -29,7 +29,9 @@ struct view_info { struct font* pf; struct viewport scrollbar_vp; /* viewport for scrollbar */ + struct viewport title_vp; struct viewport vp; + bool sbs_has_title; /* SBS comes with custom title area */ const char *title; const char *text; /* displayed text */ int display_lines; /* number of lines can be displayed */ @@ -93,17 +95,19 @@ static void calc_line_count(struct view_info *info) { ptr = get_next_line(ptr, info); i++; - if (!scrollbar && i > info->display_lines) + if (!scrollbar && i > info->display_lines && + rb->global_settings->scrollbar != SCROLLBAR_OFF) { ptr = info->text; i = 0; info->scrollbar_vp = info->vp; - info->scrollbar_vp.width = rb->global_settings->scrollbar_width; + info->scrollbar_vp.width = rb->global_settings->scrollbar_width + 1; + info->scrollbar_vp.height = info->display_lines * info->pf->height; info->vp.width -= info->scrollbar_vp.width; - if (rb->global_settings->scrollbar != SCROLLBAR_RIGHT) - info->vp.x = info->scrollbar_vp.width; + if (rb->global_settings->scrollbar == SCROLLBAR_RIGHT) + info->scrollbar_vp.x = info->vp.x + info->vp.width; else - info->scrollbar_vp.x = info->vp.width; + info->vp.x += info->scrollbar_vp.width; scrollbar = true; } } @@ -137,8 +141,14 @@ static void calc_first_line(struct view_info *info, int line) static int init_view(struct view_info *info, const char *title, const char *text) { - rb->viewport_set_defaults(&info->vp, SCREEN_MAIN); - info->pf = rb->font_get(rb->screens[SCREEN_MAIN]->getuifont()); + struct screen* display = rb->screens[SCREEN_MAIN]; + int ui_font = display->getuifont(); + + display->set_viewport(&info->vp); + display->clear_viewport(); + + info->pf = rb->font_get(ui_font); + info->vp.font = ui_font; info->display_lines = info->vp.height / info->pf->height; info->title = title; @@ -147,16 +157,21 @@ static int init_view(struct view_info *info, info->line = 0; info->start = 0; - /* no title for small screens. */ - if (info->display_lines < 4) + if (!info->sbs_has_title) { - info->title = NULL; - } - else - { - info->display_lines--; - info->vp.y += info->pf->height; - info->vp.height -= info->pf->height; + /* no title for small screens. */ + if (info->display_lines < 4) + info->title = NULL; + else + { + info->display_lines--; + + info->title_vp = info->vp; + info->title_vp.height = info->pf->height; + + info->vp.height -= info->title_vp.height; + info->vp.y += info->title_vp.height; + } } calc_line_count(info); @@ -171,20 +186,19 @@ static void draw_text(struct view_info *info) int max_show, line; struct screen* display = rb->screens[SCREEN_MAIN]; - /* clear screen */ - display->clear_display(); - /* display title. */ - if(info->title) + if (info->title && !info->sbs_has_title) { - display->set_viewport(NULL); + display->set_viewport(&info->title_vp); display->puts(0, 0, info->title); } + display->set_viewport(&info->vp); + display->clear_viewport(); + max_show = MIN(info->line_count - info->line, info->display_lines); text = info->text + info->start; - display->set_viewport(&info->vp); for (line = 0; line < max_show; line++) { int len; @@ -197,15 +211,17 @@ static void draw_text(struct view_info *info) display->puts(0, line, output); text = ptr; } - if (info->line_count > info->display_lines) + if (info->line_count > info->display_lines && + rb->global_settings->scrollbar != SCROLLBAR_OFF) { display->set_viewport(&info->scrollbar_vp); - rb->gui_scrollbar_draw(display, (info->scrollbar_vp.width? 0: 1), 0, - info->scrollbar_vp.width - 1, info->scrollbar_vp.height, - info->line_count, info->line, info->line + max_show, - VERTICAL); - } + int margin = info->scrollbar_vp.width > 2 ? 2 : 0; + int x = rb->global_settings->scrollbar == SCROLLBAR_RIGHT ? margin : 0; + rb->gui_scrollbar_draw(display, x, 0, + info->scrollbar_vp.width - margin, info->scrollbar_vp.height, + info->line_count, info->line, info->line + max_show, VERTICAL); + } display->set_viewport(NULL); display->update(); } @@ -248,6 +264,21 @@ static void scroll_to_bottom(struct view_info *info) draw_text(info); } +static void ui_update_cb(unsigned short id, void* param, void* user_data) +{ + (void)id; + (void)param; + struct view_info *info = (struct view_info *) user_data; + draw_text(info); +} + +static void cleanup(void *parameter) +{ + struct view_info *info = (struct view_info *) parameter; + rb->remove_event_ex(GUI_EVENT_NEED_UI_UPDATE, ui_update_cb, info); + rb->viewportmanager_theme_undo(SCREEN_MAIN, false); +} + int view_text(const char *title, const char *text) { struct view_info info; @@ -256,13 +287,24 @@ int view_text(const char *title, const char *text) }; int button; + info.sbs_has_title = rb->sb_set_persistent_title(title, Icon_NOICON, SCREEN_MAIN); + rb->viewportmanager_theme_enable(SCREEN_MAIN, true, &info.vp); init_view(&info, title, text); - draw_text(&info); + + /* handle themes that draw over the UI viewport */ + rb->add_event_ex(GUI_EVENT_NEED_UI_UPDATE, false, ui_update_cb, &info); + + /* skin engine needs to render title and redraw screen */ + if (info.sbs_has_title) + rb->send_event(GUI_EVENT_ACTIONUPDATE, (void*)1); + else + draw_text(&info); /* wait for keypress */ while(1) { - button = pluginlib_getaction(TIMEOUT_BLOCK, view_contexts, + /* don't block, so the skin engine can redraw */ + button = pluginlib_getaction(HZ/4, view_contexts, ARRAYLEN(view_contexts)); switch (button) { @@ -270,7 +312,7 @@ int view_text(const char *title, const char *text) #if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \ || (CONFIG_KEYPAD == IPOD_3G_PAD) \ || (CONFIG_KEYPAD == IPOD_4G_PAD) - return PLUGIN_OK; + goto out; #endif case PLA_UP_REPEAT: #ifdef HAVE_SCROLLWHEEL @@ -291,7 +333,7 @@ int view_text(const char *title, const char *text) #if (CONFIG_KEYPAD == IPOD_1G2G_PAD) \ || (CONFIG_KEYPAD == IPOD_3G_PAD) \ || (CONFIG_KEYPAD == IPOD_4G_PAD) - return PLUGIN_OK; + goto out; #endif scroll_up(&info, info.display_lines); break; @@ -307,13 +349,14 @@ int view_text(const char *title, const char *text) case PLA_SELECT: case PLA_EXIT: case PLA_CANCEL: - return PLUGIN_OK; + goto out; default: - if (rb->default_event_handler(button) == SYS_USB_CONNECTED) + if ((rb->default_event_handler_ex(button, cleanup, + &info) == SYS_USB_CONNECTED)) return PLUGIN_USB_CONNECTED; - break; } } - +out: + cleanup(&info); return PLUGIN_OK; } diff --git a/apps/plugins/properties.c b/apps/plugins/properties.c index 316b33292a..4eb727b7bb 100644 --- a/apps/plugins/properties.c +++ b/apps/plugins/properties.c @@ -187,7 +187,8 @@ static int browse_file_or_dir(struct dir_stats *stats) continue; switch(button) { - case ACTION_STD_OK:; + case ACTION_STD_OK: + rb->gui_synclist_scroll_stop(&properties_lists); int sel_pos = rb->gui_synclist_get_sel_pos(&properties_lists); /* "Show Track Info..." selected? */ @@ -197,17 +198,10 @@ static int browse_file_or_dir(struct dir_stats *stats) return -1; else { + const unsigned char* const *props = (props_type == PROPS_DIR) ? + props_dir : props_file; /* Display field in fullscreen */ - FOR_NB_SCREENS(i) - rb->viewportmanager_theme_enable(i, false, NULL); - if (props_type == PROPS_DIR) - view_text((char *) p2str(props_dir[sel_pos]), - (char *) props_dir[sel_pos + 1]); - else - view_text((char *) p2str(props_file[sel_pos]), - (char *) props_file[sel_pos + 1]); - FOR_NB_SCREENS(i) - rb->viewportmanager_theme_undo(i, false); + view_text((char *) p2str(props[sel_pos]), props[sel_pos + 1]); rb->gui_synclist_set_title(&properties_lists, rb->str(props_type == PROPS_DIR ? diff --git a/apps/screens.c b/apps/screens.c index 6cbd44c3d4..e6031d8f57 100644 --- a/apps/screens.c +++ b/apps/screens.c @@ -827,6 +827,7 @@ refresh_info: { if (key == ACTION_STD_OK) { + gui_synclist_scroll_stop(&id3_lists); int header_id = id3_headers[info.info_id[id3_lists.selected_item/2]]; char* title_and_text[2]; title_and_text[0] = str(header_id); @@ -835,13 +836,7 @@ refresh_info: title_and_text[1] = (char*)id3_get_or_speak_info(id3_lists.selected_item+1,&info, buffer, sizeof(buffer), false); if (view_text) - { - FOR_NB_SCREENS(i) - viewportmanager_theme_enable(i, false, NULL); view_text(title_and_text[0], title_and_text[1]); - FOR_NB_SCREENS(i) - viewportmanager_theme_undo(i, false); - } else plugin_load(VIEWERS_DIR"/view_text.rock", title_and_text); gui_synclist_set_title(&id3_lists, str(LANG_TRACK_INFO), NOICON);