diff --git a/menu/drivers_backend/menu_common_backend.c b/menu/drivers_backend/menu_common_backend.c index 31e8664f05..126e98e211 100644 --- a/menu/drivers_backend/menu_common_backend.c +++ b/menu/drivers_backend/menu_common_backend.c @@ -528,7 +528,6 @@ static int menu_common_iterate(unsigned action) const char *label = NULL; const char *label_offset = NULL; const char *path_offset = NULL; - unsigned scroll_speed = 0; menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*) menu_list_get_actiondata_at_offset(driver.menu->menu_list->selection_buf, driver.menu->selection_ptr); @@ -584,27 +583,13 @@ static int menu_common_iterate(unsigned action) if (driver.menu->need_refresh && action != MENU_ACTION_MESSAGE) action = MENU_ACTION_REFRESH; - scroll_speed = (max(driver.menu->scroll_accel, 2) - 2) / 4 + 1; - switch (action) { case MENU_ACTION_UP: - if (driver.menu->selection_ptr >= scroll_speed) - menu_navigation_set(driver.menu, - driver.menu->selection_ptr - scroll_speed, true); - else - menu_navigation_set(driver.menu, - menu_list_get_size(driver.menu->menu_list) - 1, true); - break; - case MENU_ACTION_DOWN: - if (driver.menu->selection_ptr + scroll_speed < (menu_list_get_size(driver.menu->menu_list))) - menu_navigation_set(driver.menu, - driver.menu->selection_ptr + scroll_speed, true); - else - menu_navigation_clear(driver.menu, false); + if (cbs && cbs->action_up_or_down) + ret = cbs->action_up_or_down(type_offset, label_offset, action); break; - case MENU_ACTION_SCROLL_UP: menu_navigation_descend_alphabet(driver.menu, &driver.menu->selection_ptr); break; diff --git a/menu/menu_action.c b/menu/menu_action.c index d8e5cfe830..1c166bf9db 100644 --- a/menu/menu_action.c +++ b/menu/menu_action.c @@ -48,6 +48,11 @@ static void process_setting_handler( switch (action) { + case MENU_ACTION_UP: + case MENU_ACTION_DOWN: + if (setting->action_up_or_down) + setting->action_up_or_down(setting, action); + break; case MENU_ACTION_LEFT: case MENU_ACTION_RIGHT: if (setting->action_toggle) diff --git a/menu/menu_driver.h b/menu/menu_driver.h index 6f95e9b356..136606f934 100644 --- a/menu/menu_driver.h +++ b/menu/menu_driver.h @@ -154,6 +154,7 @@ typedef struct menu_file_list_cbs int (*action_content_list_switch)(void *data, void *userdata, const char *path, const char *label, unsigned type); int (*action_toggle)(unsigned type, const char *label, unsigned action); + int (*action_up_or_down)(unsigned type, const char *label, unsigned action); } menu_file_list_cbs_t; typedef struct menu_ctx_driver_backend diff --git a/menu/menu_entries_cbs.c b/menu/menu_entries_cbs.c index 7f721e1e2f..8b0d7b02e8 100644 --- a/menu/menu_entries_cbs.c +++ b/menu/menu_entries_cbs.c @@ -2546,6 +2546,33 @@ static int deferred_push_default(void *data, void *userdata, return 0; } +static int action_bind_up_or_down_generic(unsigned type, const char *label, + unsigned action) +{ + unsigned scroll_speed = (max(driver.menu->scroll_accel, 2) - 2) / 4 + 1; + + switch (action) + { + case MENU_ACTION_UP: + if (driver.menu->selection_ptr >= scroll_speed) + menu_navigation_set(driver.menu, + driver.menu->selection_ptr - scroll_speed, true); + else + menu_navigation_set(driver.menu, + menu_list_get_size(driver.menu->menu_list) - 1, true); + break; + case MENU_ACTION_DOWN: + if (driver.menu->selection_ptr + scroll_speed < (menu_list_get_size(driver.menu->menu_list))) + menu_navigation_set(driver.menu, + driver.menu->selection_ptr + scroll_speed, true); + else + menu_navigation_clear(driver.menu, false); + break; + } + + return 0; +} + /* Bind the OK callback function */ static int menu_entries_cbs_init_bind_ok_first(menu_file_list_cbs_t *cbs, @@ -2812,6 +2839,16 @@ static void menu_entries_cbs_init_bind_ok(menu_file_list_cbs_t *cbs, cbs->action_ok = action_ok_configurations_list; } + +static void menu_entries_cbs_init_bind_up_or_down(menu_file_list_cbs_t *cbs, + const char *path, const char *label, unsigned type, size_t idx) +{ + if (!cbs) + return; + + cbs->action_up_or_down = action_bind_up_or_down_generic; +} + static void menu_entries_cbs_init_bind_toggle(menu_file_list_cbs_t *cbs, const char *path, const char *label, unsigned type, size_t idx) { @@ -2974,6 +3011,7 @@ void menu_entries_cbs_init(void *data, menu_entries_cbs_init_bind_cancel(cbs, path, label, type, idx); menu_entries_cbs_init_bind_start(cbs, path, label, type, idx); menu_entries_cbs_init_bind_content_list_switch(cbs, path, label, type, idx); + menu_entries_cbs_init_bind_up_or_down(cbs, path, label, type, idx); menu_entries_cbs_init_bind_toggle(cbs, path, label, type, idx); menu_entries_cbs_init_bind_deferred_push(cbs, path, label, type, idx); } diff --git a/settings_list.h b/settings_list.h index f3b363aebd..757f2e40bd 100644 --- a/settings_list.h +++ b/settings_list.h @@ -87,6 +87,7 @@ enum setting_list_flags typedef void (*change_handler_t )(void *data); typedef int (*action_toggle_handler_t )(void *data, unsigned action); +typedef int (*action_up_or_down_handler_t )(void *data, unsigned action); typedef int (*action_start_handler_t )(void *data); typedef int (*action_cancel_handler_t )(void *data, unsigned action); typedef int (*action_ok_handler_t )(void *data, unsigned action); @@ -128,6 +129,7 @@ typedef struct rarch_setting change_handler_t read_handler; action_start_handler_t action_start; action_toggle_handler_t action_toggle; + action_up_or_down_handler_t action_up_or_down; action_cancel_handler_t action_cancel; action_ok_handler_t action_ok; get_string_representation_t get_string_representation;