diff --git a/apps/menu.c b/apps/menu.c index 830bc67a11..802a16bbb8 100644 --- a/apps/menu.c +++ b/apps/menu.c @@ -187,17 +187,18 @@ static enum themable_icons menu_get_icon(int selected_item, void * data) return menu_icon; } -static void init_menu_lists(const struct menu_item_ex *menu, +static int init_menu_lists(const struct menu_item_ex *menu, struct gui_synclist *lists, int selected, bool callback, struct viewport parent[NB_SCREENS]) { if (!menu || !lists) { panicf("init_menu_lists, NULL pointer"); - return; + return 0; } int i; + int start_action = ACTION_ENTER_MENUITEM; int count = MIN(MENU_GET_COUNT(menu->flags), MAX_MENU_SUBITEMS); int type = (menu->flags&MENU_TYPE_MASK); menu_callback_type menu_callback = NULL; @@ -264,7 +265,9 @@ static void init_menu_lists(const struct menu_item_ex *menu, get_menu_callback(menu,&menu_callback); if (callback && menu_callback) - menu_callback(ACTION_ENTER_MENUITEM, menu, lists); + start_action = menu_callback(start_action, menu, lists); + + return start_action; } static int talk_menu_item(int selected_item, void *data) @@ -381,6 +384,7 @@ int do_menu(const struct menu_item_ex *start_menu, int *start_selected, int selected = start_selected? *start_selected : 0; int ret = 0; int action; + int start_action; struct gui_synclist lists; const struct menu_item_ex *temp = NULL; const struct menu_item_ex *menu = start_menu; @@ -407,8 +411,10 @@ int do_menu(const struct menu_item_ex *start_menu, int *start_selected, menu_callback_type menu_callback = NULL; /* if hide_theme is true, assume parent has been fixed before passed into - * this function, e.g. with viewport_set_defaults(parent, screen) */ - init_menu_lists(menu, &lists, selected, true, parent); + * this function, e.g. with viewport_set_defaults(parent, screen) + * start_action allows an action to be processed + * by menu logic by bypassing get_action on the initial run */ + start_action = init_menu_lists(menu, &lists, selected, true, parent); vps = *(lists.parent); in_stringlist = ((menu->flags&MENU_TYPE_MASK) == MT_RETURN_ID); /* load the callback, and only reload it if menu changes */ @@ -421,7 +427,13 @@ int do_menu(const struct menu_item_ex *start_menu, int *start_selected, { keyclick_set_callback(gui_synclist_keyclick_callback, &lists); - action = get_action(CONTEXT_MAINMENU|ALLOW_SOFTLOCK, + if (UNLIKELY(start_action != ACTION_ENTER_MENUITEM)) + { + action = start_action; + start_action = ACTION_ENTER_MENUITEM; + } + else + action = get_action(CONTEXT_MAINMENU|ALLOW_SOFTLOCK, list_do_action_timeout(&lists, HZ)); /* HZ so the status bar redraws corectly */ @@ -639,7 +651,8 @@ int do_menu(const struct menu_item_ex *start_menu, int *start_selected, if (!(menu->flags&MENU_EXITAFTERTHISMENU) || (temp->flags&MENU_EXITAFTERTHISMENU)) { - init_menu_lists(menu, &lists, selected, true, vps); + /* Reload menu but don't run the calback again FS#8117 */ + init_menu_lists(menu, &lists, selected, false, vps); } if (temp->flags&MENU_FUNC_CHECK_RETVAL) { diff --git a/apps/menus/plugin_menu.c b/apps/menus/plugin_menu.c index 055cfce140..7f29e61af4 100644 --- a/apps/menus/plugin_menu.c +++ b/apps/menus/plugin_menu.c @@ -24,11 +24,12 @@ #include "config.h" #include "lang.h" #include "menu.h" +#include "action.h" #include "settings.h" #include "rbpaths.h" #include "root_menu.h" #include "tree.h" - +static int reenter = 0; enum { GAMES, @@ -53,13 +54,36 @@ static int plugins_menu(void* param) browse_context_init(&browse, SHOW_PLUGINS, 0, str(items[item].id), Icon_Plugin, items[item].path, NULL); - + ret = rockbox_browse(&browse); + if (ret == GO_TO_PREVIOUS) return 0; + if (ret == GO_TO_PLUGIN) + reenter = 1; return ret; } +static int menu_callback(int action, + const struct menu_item_ex *this_item, + struct gui_synclist *this_list) +{ + (void)this_item; + static int selected = 0; + + if (action == ACTION_ENTER_MENUITEM) + { + this_list->selected_item = selected; + if (reenter-- > 0) + action = ACTION_STD_OK; + } + else if (action == ACTION_STD_OK) + { + selected = gui_synclist_get_sel_pos(this_list); + } + return action; +} + #define ITEM_FLAG (MENU_FUNC_USEPARAM|MENU_FUNC_CHECK_RETVAL) MENUITEM_FUNCTION(games_item, ITEM_FLAG, ID2P(LANG_PLUGIN_GAMES), @@ -69,6 +93,6 @@ MENUITEM_FUNCTION(apps_item, ITEM_FLAG, ID2P(LANG_PLUGIN_APPS), MENUITEM_FUNCTION(demos_item, ITEM_FLAG, ID2P(LANG_PLUGIN_DEMOS), plugins_menu, (void*)DEMOS, NULL, Icon_Folder); -MAKE_MENU(plugin_menu, ID2P(LANG_PLUGINS), NULL, +MAKE_MENU(plugin_menu, ID2P(LANG_PLUGINS), &menu_callback, Icon_Plugin, &games_item, &apps_item, &demos_item); diff --git a/apps/root_menu.c b/apps/root_menu.c index 15d03a7cda..ed6bdfdcca 100644 --- a/apps/root_menu.c +++ b/apps/root_menu.c @@ -634,6 +634,7 @@ static int item_callback(int action, } return action; } + static int get_selection(int last_screen) { int i; @@ -683,6 +684,7 @@ static inline int load_screen(int screen) last_screen = old_previous; return ret_val; } + static int load_context_screen(int selection) { const struct menu_item_ex *context_menu = NULL; @@ -709,13 +711,12 @@ static int load_plugin_screen(char *key) { int ret_val; int old_previous = last_screen; + int old_global = global_status.last_screen; last_screen = next_screen; global_status.last_screen = (char)next_screen; status_save(); - int opret = open_plugin_get_entry(key, &open_plugin_entry); - bool flush = (opret == OPEN_PLUGIN_NEEDS_FLUSHED); char *path = open_plugin_entry.path; char *param = open_plugin_entry.param; if (param[0] == '\0') @@ -723,6 +724,9 @@ static int load_plugin_screen(char *key) switch (plugin_load(path, param)) { + case PLUGIN_USB_CONNECTED: + ret_val = GO_TO_ROOT; + break; case PLUGIN_GOTO_WPS: ret_val = GO_TO_WPS; break; @@ -730,18 +734,30 @@ static int load_plugin_screen(char *key) ret_val = GO_TO_PLUGIN; break; case PLUGIN_OK: - ret_val = audio_status() ? GO_TO_PREVIOUS : GO_TO_ROOT; - break; + /* Prevents infinite loop with WPS & Plugins*/ + if (old_global == GO_TO_WPS && !audio_status()) + { + ret_val = GO_TO_ROOT; + break; + } + /*fallthrough*/ default: ret_val = GO_TO_PREVIOUS; + last_screen = (old_previous == next_screen) ? GO_TO_ROOT : old_previous; break; + } - if (!flush && ret_val != GO_TO_PLUGIN) - open_plugin_add_path(NULL, NULL, NULL); - - if (ret_val == GO_TO_PREVIOUS) - last_screen = (old_previous == next_screen) ? GO_TO_ROOT : old_previous; + if (ret_val != GO_TO_PLUGIN) + { + if (opret != OPEN_PLUGIN_NEEDS_FLUSHED || last_screen != GO_TO_WPS) + { + /* Keep the entry in case of GO_TO_PREVIOUS */ + open_plugin_entry.hash = 0; /*remove hash -- prevents flush to disk */ + open_plugin_entry.lang_id = LANG_PREVIOUS_SCREEN; + /*open_plugin_add_path(NULL, NULL, NULL);// clear entry */ + } + } return ret_val; } @@ -858,8 +874,12 @@ void root_menu(void) #endif /* With !CONFIG_TUNER previous_music is always GO_TO_WPS */ case GO_TO_PREVIOUS: + { next_screen = last_screen; + if (last_screen == GO_TO_PLUGIN)/* for WPS */ + last_screen = GO_TO_PREVIOUS; break; + } case GO_TO_PREVIOUS_BROWSER: next_screen = previous_browser; @@ -874,7 +894,8 @@ void root_menu(void) case GO_TO_PLUGIN: { char *key; - if (global_status.last_screen == GO_TO_SHORTCUTMENU) + if (global_status.last_screen == GO_TO_SHORTCUTMENU && + last_screen != GO_TO_ROOT) { shortcut_origin = last_screen; key = ID2P(LANG_SHORTCUTS); @@ -892,6 +913,9 @@ void root_menu(void) case GO_TO_SHORTCUTMENU: key = ID2P(LANG_SHORTCUTS); break; + case GO_TO_PREVIOUS: + key = ID2P(LANG_PREVIOUS_SCREEN); + break; default: key = ID2P(LANG_OPEN_PLUGIN); break; @@ -900,15 +924,23 @@ void root_menu(void) next_screen = load_plugin_screen(key); - /* shortcuts may take several trips through the GO_TO_PLUGIN case - make sure we preserve and restore the origin */ - if (next_screen == GO_TO_PREVIOUS && shortcut_origin != GO_TO_ROOT) + if (next_screen == GO_TO_PREVIOUS) { - if (shortcut_origin != GO_TO_WPS) - next_screen = shortcut_origin; - shortcut_origin = GO_TO_ROOT; + /* shortcuts may take several trips through the GO_TO_PLUGIN + case make sure we preserve and restore the origin */ + if (shortcut_origin != GO_TO_ROOT) + { + if (shortcut_origin != GO_TO_WPS) + next_screen = shortcut_origin; + shortcut_origin = GO_TO_ROOT; + } + /* skip GO_TO_PREVIOUS */ + if (last_screen == GO_TO_BROWSEPLUGINS) + { + next_screen = last_screen; + last_screen = GO_TO_PLUGIN; + } } - previous_browser = (next_screen != GO_TO_WPS) ? GO_TO_FILEBROWSER : GO_TO_PLUGIN; break; } diff --git a/apps/tree.c b/apps/tree.c index 7fcced92c8..e35f769a14 100644 --- a/apps/tree.c +++ b/apps/tree.c @@ -967,11 +967,17 @@ int rockbox_browse(struct browse_context *browse) if (*tc.dirfilter >= NUM_FILTER_MODES) { int last_context; + /* don't reset if its the same browse already loaded */ + if (tc.browse != browse || + !(tc.currdir[1] && strcmp(tc.currdir, browse->root) == 0)) + { + tc.browse = browse; + tc.selected_item = 0; + tc.dirlevel = 0; + + strlcpy(tc.currdir, browse->root, sizeof(tc.currdir)); + } - tc.browse = browse; - tc.selected_item = 0; - tc.dirlevel = 0; - strlcpy(tc.currdir, browse->root, sizeof(tc.currdir)); start_wps = false; last_context = curr_context;