void menu_entries_push(file_list_t *list, const char *path, const char *label, unsigned type, size_t directory_ptr, size_t entry_idx) { size_t idx; const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); menu_file_list_cbs_t *cbs = NULL; if (!list || !label) return; file_list_push(list, path, label, type, directory_ptr, entry_idx); idx = list->size - 1; if (driver->list_insert) driver->list_insert(list, path, label, idx); file_list_free_actiondata(list, idx); cbs = (menu_file_list_cbs_t*) calloc(1, sizeof(menu_file_list_cbs_t)); if (!cbs) return; file_list_set_actiondata(list, idx, cbs); cbs->setting = menu_setting_find(label); menu_cbs_init(list, cbs, path, label, type, idx); }
void menu_driver_frame(void) { const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); if (driver->frame) driver->frame(); }
void menu_driver_free(menu_handle_t *menu) { const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); if (driver->free) driver->free(menu); }
void menu_driver_set_texture(void) { const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); if (driver->set_texture) driver->set_texture(); }
void menu_driver_context_reset(void) { const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); if (driver->context_reset) driver->context_reset(); }
void menu_driver_list_cache(menu_list_type_t type, unsigned action) { const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); if (driver->list_cache) driver->list_cache(type, action); }
void menu_driver_list_set_selection(file_list_t *list) { const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); if (driver && driver->list_set_selection) driver->list_set_selection(list); }
void menu_driver_context_destroy(void) { const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); if (driver && driver->context_destroy) driver->context_destroy(); }
void menu_driver_populate_entries(const char *path, const char *label, unsigned k) { const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); if (driver->populate_entries) driver->populate_entries(path, label, k); }
int menu_driver_iterate(enum menu_action action) { const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); if (driver->iterate) return driver->iterate(action); return -1; }
void menu_driver_list_insert(file_list_t *list, const char *path, const char *label, size_t list_size) { const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); if (driver->list_insert) driver->list_insert(list, path, label, list_size); }
bool menu_driver_list_push(menu_displaylist_info_t *info, unsigned type) { const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); if (driver->list_push) if (driver->list_push(info, type) == 0) return true; return false; }
size_t menu_driver_list_get_selection(void) { const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); menu_handle_t *menu = menu_driver_get_ptr(); if (driver && driver->list_get_selection) return driver->list_get_selection(menu); return 0; }
void menu_driver_render_messagebox(const char *msg) { const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); if (!msg) return; if (driver->render_messagebox && msg[0] != '\0') driver->render_messagebox(msg); }
bool menu_driver_load_background(void *data) { const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); if (driver->load_background) return driver->load_background(data); return false; }
void *menu_driver_list_get_entry(menu_list_type_t type, unsigned i) { menu_handle_t *menu = menu_driver_get_ptr(); const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); if (driver && driver->list_get_entry) return driver->list_get_entry(menu, type, i); return NULL; }
size_t menu_driver_list_get_size(menu_list_type_t type) { menu_handle_t *menu = menu_driver_get_ptr(); const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); if (driver && driver->list_get_size) return driver->list_get_size(menu, type); return 0; }
bool menu_driver_load_image(void *data, menu_image_type_t type) { const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); if (driver->load_image) return driver->load_image(data, type); return false; }
void menu_driver_list_free(file_list_t *list, size_t idx, size_t list_size) { const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); if (driver->list_free) driver->list_free(list, idx, list_size); file_list_free_userdata (list, idx); file_list_free_actiondata(list, idx); }
static void menu_driver_toggle(bool latch) { const menu_ctx_driver_t *menu_driver = menu_ctx_driver_get_ptr(); settings_t *settings = config_get_ptr(); global_t *global = global_get_ptr(); rarch_system_info_t *system = rarch_system_info_get_ptr(); if (menu_driver->toggle) menu_driver->toggle(latch); if (latch) menu_driver_ctl(RARCH_MENU_CTL_SET_ALIVE, NULL); else menu_driver_ctl(RARCH_MENU_CTL_UNSET_ALIVE, NULL); if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL)) { menu_entries_set_refresh(false); /* Menu should always run with vsync on. */ event_command(EVENT_CMD_VIDEO_SET_BLOCKING_STATE); /* Stop all rumbling before entering the menu. */ event_command(EVENT_CMD_RUMBLE_STOP); if (settings->menu.pause_libretro) event_command(EVENT_CMD_AUDIO_STOP); /* Override keyboard callback to redirect to menu instead. * We'll use this later for something ... * FIXME: This should probably be moved to menu_common somehow. */ if (global) { global->frontend_key_event = system->key_event; system->key_event = menu_input_key_event; runloop_ctl(RUNLOOP_CTL_SET_FRAME_TIME_LAST, NULL); } } else { if (!runloop_ctl(RUNLOOP_CTL_IS_SHUTDOWN, NULL)) driver_set_nonblock_state(); if (settings && settings->menu.pause_libretro) event_command(EVENT_CMD_AUDIO_START); /* Prevent stray input from going to libretro core */ input_driver_ctl(RARCH_INPUT_CTL_SET_FLUSHING_INPUT, NULL); /* Restore libretro keyboard callback. */ if (global) system->key_event = global->frontend_key_event; } }
int menu_driver_pointer_tap(unsigned x, unsigned y, unsigned ptr, menu_file_list_cbs_t *cbs, menu_entry_t *entry, unsigned action) { int ret = 0; const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); if (driver->pointer_tap) ret = driver->pointer_tap(x, y, ptr, cbs, entry, action); return ret; }
bool menu_environment_cb(menu_environ_cb_t type, void *data) { const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); if (driver->environ_cb) { int ret = driver->environ_cb(type, data); if (ret == 0) return true; } return false; }
void menu_driver_toggle(bool latch) { driver_t *driver = driver_get_ptr(); const menu_ctx_driver_t *menu_driver = menu_ctx_driver_get_ptr(); settings_t *settings = config_get_ptr(); global_t *global = global_get_ptr(); rarch_system_info_t *system = rarch_system_info_get_ptr(); if (menu_driver->toggle) menu_driver->toggle(latch); menu_alive = latch; if (menu_alive == true) { menu_entries_set_refresh(false); /* Menu should always run with vsync on. */ event_command(EVENT_CMD_VIDEO_SET_BLOCKING_STATE); /* Stop all rumbling before entering the menu. */ event_command(EVENT_CMD_RUMBLE_STOP); if (settings->menu.pause_libretro) event_command(EVENT_CMD_AUDIO_STOP); /* Override keyboard callback to redirect to menu instead. * We'll use this later for something ... * FIXME: This should probably be moved to menu_common somehow. */ if (global) { global->frontend_key_event = system->key_event; system->key_event = menu_input_key_event; system->frame_time_last = 0; } } else { driver_set_nonblock_state(driver->nonblock_state); if (settings && settings->menu.pause_libretro) event_command(EVENT_CMD_AUDIO_START); /* Prevent stray input from going to libretro core */ driver->flushing_input = true; /* Restore libretro keyboard callback. */ if (global) system->key_event = global->frontend_key_event; } }
int menu_driver_bind_init(menu_file_list_cbs_t *cbs, const char *path, const char *label, unsigned type, size_t idx, const char *elem0, const char *elem1, uint32_t label_hash, uint32_t menu_label_hash) { int ret = 0; const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); if (driver && driver->bind_init) ret = driver->bind_init(cbs, path, label, type, idx, elem0, elem1, label_hash, menu_label_hash); return ret; }
void menu_entries_clear(file_list_t *list) { unsigned i; const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); if (driver->list_clear) driver->list_clear(list); for (i = 0; i < list->size; i++) file_list_free_actiondata(list, i); if (list) file_list_clear(list); }
int menu_iterate_render(void) { bool is_idle; const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); menu_handle_t *menu = menu_driver_get_ptr(); if (!menu) return -1; if (BIT64_GET(menu->state, MENU_STATE_RENDER_FRAMEBUFFER) != BIT64_GET(menu->state, MENU_STATE_RENDER_MESSAGEBOX)) BIT64_SET(menu->state, MENU_STATE_RENDER_FRAMEBUFFER); if (BIT64_GET(menu->state, MENU_STATE_RENDER_FRAMEBUFFER)) menu_display_ctl(MENU_DISPLAY_CTL_SET_FRAMEBUFFER_DIRTY_FLAG, NULL); if (BIT64_GET(menu->state, MENU_STATE_RENDER_MESSAGEBOX) && menu->menu_state.msg[0] != '\0') { if (driver->render_messagebox) driver->render_messagebox(menu->menu_state.msg); if (ui_companion_is_on_foreground()) { const ui_companion_driver_t *ui = ui_companion_get_ptr(); if (ui->render_messagebox) ui->render_messagebox(menu->menu_state.msg); } } if (BIT64_GET(menu->state, MENU_STATE_BLIT)) { menu_animation_ctl(MENU_ANIMATION_CTL_UPDATE_TIME, NULL); if (driver->render) driver->render(); } rarch_main_ctl(RARCH_MAIN_CTL_IS_IDLE, &is_idle); if (menu_driver_alive() && !is_idle) menu_display_ctl(MENU_DISPLAY_CTL_LIBRETRO, NULL); menu_driver_set_texture(); menu->state = 0; return 0; }
int menu_iterate_render(void) { const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); menu_handle_t *menu = menu_driver_get_ptr(); if (!menu) return -1; if (menu->state.fb_is_dirty != menu->state.do_messagebox) menu->state.fb_is_dirty = true; if (menu->state.fb_is_dirty) menu_display_fb_set_dirty(); if (menu->state.do_messagebox && menu->state.msg[0] != '\0') { if (driver->render_messagebox) driver->render_messagebox(menu->state.msg); if (ui_companion_is_on_foreground()) { const ui_companion_driver_t *ui = ui_companion_get_ptr(); if (ui->render_messagebox) ui->render_messagebox(menu->state.msg); } } if (menu->state.do_render) { if (driver->render) driver->render(); } if (menu_driver_alive() && !rarch_main_is_idle()) menu_display_fb(); menu_driver_set_texture(); return 0; }
bool menu_navigation_ctl(enum menu_navigation_ctl_state state, void *data) { const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); settings_t *settings = config_get_ptr(); menu_navigation_t *nav = menu_navigation_get_ptr(); size_t menu_list_size = menu_entries_get_size(); size_t selection = nav->selection_ptr; (void)settings; switch (state) { case MENU_NAVIGATION_CTL_CLEAR: { size_t idx = 0; bool scroll = true; bool *pending_push = (bool*)data; if (!pending_push) return false; menu_navigation_ctl(MENU_NAVIGATION_CTL_SET_SELECTION, &idx); menu_navigation_ctl(MENU_NAVIGATION_CTL_SET, &scroll); if (driver->navigation_clear) driver->navigation_clear(*pending_push); } return true; case MENU_NAVIGATION_CTL_INCREMENT: { unsigned *scroll_speed = (unsigned*)data; if (!scroll_speed) return false; if (selection >= menu_list_size - 1 && !settings->menu.navigation.wraparound.enable) return false; if ((selection + (*scroll_speed)) < menu_list_size) { size_t idx = selection + (*scroll_speed); bool scroll = true; menu_navigation_ctl(MENU_NAVIGATION_CTL_SET_SELECTION, &idx); menu_navigation_ctl(MENU_NAVIGATION_CTL_SET, &scroll); menu_navigation_ctl(MENU_NAVIGATION_CTL_INCREMENT, NULL); } else { if (settings->menu.navigation.wraparound.enable) { bool pending_push = false; menu_navigation_ctl(MENU_NAVIGATION_CTL_CLEAR, &pending_push); } else { if (menu_list_size > 0) { menu_navigation_ctl(MENU_NAVIGATION_CTL_SET_LAST, NULL); menu_navigation_ctl(MENU_NAVIGATION_CTL_INCREMENT, NULL); } } } if (driver->navigation_increment) driver->navigation_increment(); } return true; case MENU_NAVIGATION_CTL_DECREMENT: { size_t idx = 0; bool scroll = true; unsigned *scroll_speed = (unsigned*)data; if (!scroll_speed) return false; if (selection == 0 && !settings->menu.navigation.wraparound.enable) return false; if (selection >= *scroll_speed) idx = selection - *scroll_speed; else { idx = menu_list_size - 1; if (!settings->menu.navigation.wraparound.enable) idx = 0; } menu_navigation_ctl(MENU_NAVIGATION_CTL_SET_SELECTION, &idx); menu_navigation_ctl(MENU_NAVIGATION_CTL_SET, &scroll); menu_navigation_ctl(MENU_NAVIGATION_CTL_DECREMENT, NULL); if (driver->navigation_decrement) driver->navigation_decrement(); } return true; case MENU_NAVIGATION_CTL_SET: { bool *scroll = (bool*)data; if (!scroll) return false; if (driver->navigation_set) driver->navigation_set(*scroll); } return true; case MENU_NAVIGATION_CTL_SET_LAST: { size_t new_selection = menu_list_size - 1; menu_navigation_ctl(MENU_NAVIGATION_CTL_SET_SELECTION, &new_selection); if (driver->navigation_set_last) driver->navigation_set_last(); } return true; case MENU_NAVIGATION_CTL_ASCEND_ALPHABET: { size_t i = 0, ptr; size_t *ptr_out = nav ? (size_t*)&nav->selection_ptr : NULL; if (!nav || !nav->scroll.indices.size || !ptr_out) return false; ptr = *ptr_out; if (ptr == nav->scroll.indices.list[nav->scroll.indices.size - 1]) return false; while (i < nav->scroll.indices.size - 1 && nav->scroll.indices.list[i + 1] <= ptr) i++; *ptr_out = nav->scroll.indices.list[i + 1]; if (driver->navigation_ascend_alphabet) driver->navigation_ascend_alphabet(ptr_out); } return true; case MENU_NAVIGATION_CTL_DESCEND_ALPHABET: { size_t i = 0, ptr; size_t *ptr_out = nav ? (size_t*)&nav->selection_ptr : NULL; if (!nav || !nav->scroll.indices.size || !ptr_out) return false; ptr = *ptr_out; if (ptr == 0) return false; i = nav->scroll.indices.size - 1; while (i && nav->scroll.indices.list[i - 1] >= ptr) i--; *ptr_out = nav->scroll.indices.list[i - 1]; if (driver->navigation_descend_alphabet) driver->navigation_descend_alphabet(ptr_out); } return true; case MENU_NAVIGATION_CTL_GET_SELECTION: { size_t *sel = (size_t*)data; if (!nav || !sel) return false; *sel = selection; } return true; case MENU_NAVIGATION_CTL_SET_SELECTION: { size_t *sel = (size_t*)data; if (!nav || !sel) return false; nav->selection_ptr = *sel; } return true; case MENU_NAVIGATION_CTL_CLEAR_SCROLL_INDICES: { if (!nav) return false; nav->scroll.indices.size = 0; } return true; case MENU_NAVIGATION_CTL_ADD_SCROLL_INDEX: { size_t *sel = (size_t*)data; if (!nav || !sel) return false; nav->scroll.indices.list[nav->scroll.indices.size++] = *sel; } return true; case MENU_NAVIGATION_CTL_GET_SCROLL_ACCEL: { size_t *sel = (size_t*)data; if (!nav || !sel) return false; *sel = nav->scroll.acceleration; } return true; case MENU_NAVIGATION_CTL_SET_SCROLL_ACCEL: { size_t *sel = (size_t*)data; if (!nav || !sel) return false; nav->scroll.acceleration = *sel; } return true; } return false; }
unsigned menu_input_frame(retro_input_t input, retro_input_t trigger_input) { unsigned ret = 0; static bool initial_held = true; static bool first_held = false; static const retro_input_t input_repeat = (1ULL << RETRO_DEVICE_ID_JOYPAD_UP) | (1ULL << RETRO_DEVICE_ID_JOYPAD_DOWN) | (1ULL << RETRO_DEVICE_ID_JOYPAD_LEFT) | (1ULL << RETRO_DEVICE_ID_JOYPAD_RIGHT) | (1ULL << RETRO_DEVICE_ID_JOYPAD_L) | (1ULL << RETRO_DEVICE_ID_JOYPAD_R); menu_navigation_t *nav = menu_navigation_get_ptr(); menu_handle_t *menu = menu_driver_get_ptr(); driver_t *driver = driver_get_ptr(); settings_t *settings = config_get_ptr(); if (!menu || !driver || !nav) return 0; driver->retro_ctx.poll_cb(); /* don't run anything first frame, only capture held inputs * for old_input_state. */ if (input & input_repeat) { if (!first_held) { first_held = true; menu->delay.timer = initial_held ? 12 : 6; menu->delay.count = 0; } if (menu->delay.count >= menu->delay.timer) { first_held = false; trigger_input |= input & input_repeat; nav->scroll.acceleration = min(nav->scroll.acceleration + 1, 64); } initial_held = false; } else { first_held = false; initial_held = true; nav->scroll.acceleration = 0; } menu->delay.count += menu->dt / IDEAL_DT; if (driver->block_input) trigger_input = 0; if (trigger_input & (1ULL << RETRO_DEVICE_ID_JOYPAD_UP)) ret = MENU_ACTION_UP; else if (trigger_input & (1ULL << RETRO_DEVICE_ID_JOYPAD_DOWN)) ret = MENU_ACTION_DOWN; else if (trigger_input & (1ULL << RETRO_DEVICE_ID_JOYPAD_LEFT)) ret = MENU_ACTION_LEFT; else if (trigger_input & (1ULL << RETRO_DEVICE_ID_JOYPAD_RIGHT)) ret = MENU_ACTION_RIGHT; else if (trigger_input & (1ULL << settings->menu_scroll_up_btn)) ret = MENU_ACTION_SCROLL_UP; else if (trigger_input & (1ULL << settings->menu_scroll_down_btn)) ret = MENU_ACTION_SCROLL_DOWN; else if (trigger_input & (1ULL << settings->menu_cancel_btn)) ret = MENU_ACTION_CANCEL; else if (trigger_input & (1ULL << settings->menu_ok_btn)) ret = MENU_ACTION_OK; else if (trigger_input & (1ULL << settings->menu_search_btn)) ret = MENU_ACTION_SEARCH; else if (trigger_input & (1ULL << RETRO_DEVICE_ID_JOYPAD_Y)) ret = MENU_ACTION_TEST; else if (trigger_input & (1ULL << settings->menu_default_btn)) ret = MENU_ACTION_START; else if (trigger_input & (1ULL << settings->menu_info_btn)) ret = MENU_ACTION_SELECT; else if (trigger_input & (1ULL << RARCH_MENU_TOGGLE)) ret = MENU_ACTION_TOGGLE; else ret = MENU_ACTION_NOOP; if (settings->menu.mouse.enable) menu_input_mouse(&ret); if (settings->menu.pointer.enable) menu_input_pointer(&ret); if (trigger_input && menu_ctx_driver_get_ptr()->perform_action && menu_ctx_driver_get_ptr()->perform_action(menu->userdata, ret)) { return MENU_ACTION_NOOP; } else { return ret; } }
bool menu_driver_ctl(enum rarch_menu_ctl_state state, void *data) { static bool menu_driver_prevent_populate = false; static bool menu_driver_load_no_content = false; static bool menu_driver_alive = false; static bool menu_driver_data_own = false; const menu_ctx_driver_t *driver = menu_ctx_driver_get_ptr(); switch (state) { case RARCH_MENU_CTL_DESTROY: menu_driver_prevent_populate = false; menu_driver_load_no_content = false; menu_driver_alive = false; menu_driver_data_own = false; menu_driver_ctx = NULL; break; case RARCH_MENU_CTL_FRAME: if (!menu_driver_alive) return false; if (driver->frame) driver->frame(); break; case RARCH_MENU_CTL_SET_PREVENT_POPULATE: menu_driver_prevent_populate = true; break; case RARCH_MENU_CTL_UNSET_PREVENT_POPULATE: menu_driver_prevent_populate = false; break; case RARCH_MENU_CTL_IS_PREVENT_POPULATE: return menu_driver_prevent_populate; case RARCH_MENU_CTL_SET_TOGGLE: menu_driver_toggle(true); break; case RARCH_MENU_CTL_UNSET_TOGGLE: menu_driver_toggle(false); break; case RARCH_MENU_CTL_SET_ALIVE: menu_driver_alive = true; break; case RARCH_MENU_CTL_UNSET_ALIVE: menu_driver_alive = false; break; case RARCH_MENU_CTL_IS_ALIVE: return menu_driver_alive; case RARCH_MENU_CTL_SET_OWN_DRIVER: menu_driver_data_own = true; break; case RARCH_MENU_CTL_UNSET_OWN_DRIVER: menu_driver_data_own = false; break; case RARCH_MENU_CTL_SET_TEXTURE: if (driver->set_texture) driver->set_texture(); break; case RARCH_MENU_CTL_IS_SET_TEXTURE: if (!menu_driver_ctx) return false; return menu_driver_ctx->set_texture; case RARCH_MENU_CTL_OWNS_DRIVER: return menu_driver_data_own; case RARCH_MENU_CTL_DEINIT: menu_free(menu_driver_data); menu_driver_data = NULL; break; case RARCH_MENU_CTL_LOAD_NO_CONTENT_GET: { bool **ptr = (bool**)data; if (!ptr) return false; *ptr = (bool*)&menu_driver_load_no_content; return true; } break; case RARCH_MENU_CTL_HAS_LOAD_NO_CONTENT: return menu_driver_load_no_content; case RARCH_MENU_CTL_SET_LOAD_NO_CONTENT: menu_driver_load_no_content = true; break; case RARCH_MENU_CTL_UNSET_LOAD_NO_CONTENT: menu_driver_load_no_content = false; break; default: case RARCH_MENU_CTL_NONE: break; } return false; }