static int menu_input_pointer_post_iterate( menu_file_list_cbs_t *cbs, menu_entry_t *entry, unsigned action) { static bool pointer_oldpressed[2]; static bool pointer_oldback = false; static int16_t start_x = 0; static int16_t start_y = 0; static int16_t pointer_old_x = 0; static int16_t pointer_old_y = 0; int ret = 0; menu_input_t *menu_input = menu_input_get_ptr(); settings_t *settings = config_get_ptr(); bool check_overlay = settings ? !settings->menu.pointer.enable : false; if (!menu_input || !settings) return -1; #ifdef HAVE_OVERLAY check_overlay = check_overlay || (settings->input.overlay_enable && input_overlay_is_alive(NULL)); #endif if (check_overlay) return 0; if (menu_input->pointer.pressed[0]) { gfx_ctx_metrics_t metrics; float dpi; static float accel0 = 0.0f; static float accel1 = 0.0f; int16_t pointer_x = menu_input_pointer_state(MENU_POINTER_X_AXIS); int16_t pointer_y = menu_input_pointer_state(MENU_POINTER_Y_AXIS); metrics.type = DISPLAY_METRIC_DPI; metrics.value = &dpi; video_context_driver_get_metrics(&metrics); if (!pointer_oldpressed[0]) { menu_input->pointer.accel = 0; accel0 = 0; accel1 = 0; start_x = pointer_x; start_y = pointer_y; pointer_old_x = pointer_x; pointer_old_y = pointer_y; pointer_oldpressed[0] = true; } else if (abs(pointer_x - start_x) > (dpi / 10) || abs(pointer_y - start_y) > (dpi / 10)) { float s, delta_time; menu_input_ctl(MENU_INPUT_CTL_SET_POINTER_DRAGGED, NULL); menu_input->pointer.dx = pointer_x - pointer_old_x; menu_input->pointer.dy = pointer_y - pointer_old_y; pointer_old_x = pointer_x; pointer_old_y = pointer_y; menu_animation_ctl(MENU_ANIMATION_CTL_DELTA_TIME, &delta_time); s = (menu_input->pointer.dy * 550000000.0 ) / ( dpi * delta_time ); menu_input->pointer.accel = (accel0 + accel1 + s) / 3; accel0 = accel1; accel1 = menu_input->pointer.accel; } } else { if (pointer_oldpressed[0]) { if (!menu_input_ctl(MENU_INPUT_CTL_IS_POINTER_DRAGGED, NULL)) { menu_ctx_pointer_t point; point.x = start_x; point.y = start_y; point.ptr = menu_input->pointer.ptr; point.cbs = cbs; point.entry = entry; point.action = action; menu_driver_ctl(RARCH_MENU_CTL_POINTER_TAP, &point); ret = point.retcode; } pointer_oldpressed[0] = false; start_x = 0; start_y = 0; pointer_old_x = 0; pointer_old_y = 0; menu_input->pointer.dx = 0; menu_input->pointer.dy = 0; menu_input_ctl(MENU_INPUT_CTL_UNSET_POINTER_DRAGGED, NULL); } } if (menu_input->pointer.back) { if (!pointer_oldback) { size_t selection; pointer_oldback = true; menu_navigation_ctl(MENU_NAVIGATION_CTL_GET_SELECTION, &selection); menu_entry_action(entry, selection, MENU_ACTION_CANCEL); } } pointer_oldback = menu_input->pointer.back; return ret; }
static int action_select_default(const char *path, const char *label, unsigned type, size_t idx) { menu_entry_t entry; int ret = 0; enum menu_action action = MENU_ACTION_NOOP; menu_file_list_cbs_t *cbs = NULL; file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0); menu_entry_init(&entry); menu_entry_get(&entry, 0, idx, NULL, false); if (selection_buf) cbs = (menu_file_list_cbs_t*) file_list_get_actiondata_at_offset(selection_buf, idx); if (!cbs) { menu_entry_free(&entry); return -1; } if (cbs->setting) { switch (setting_get_type(cbs->setting)) { case ST_BOOL: case ST_INT: case ST_UINT: case ST_FLOAT: action = MENU_ACTION_RIGHT; break; case ST_PATH: case ST_DIR: case ST_ACTION: case ST_STRING: case ST_HEX: case ST_BIND: action = MENU_ACTION_OK; break; default: break; } } if (action == MENU_ACTION_NOOP) { if (cbs->action_ok) action = MENU_ACTION_OK; else { if (cbs->action_start) action = MENU_ACTION_START; if (cbs->action_right) action = MENU_ACTION_RIGHT; } } if (action != MENU_ACTION_NOOP) ret = menu_entry_action(&entry, (unsigned)idx, action); menu_entry_free(&entry); task_queue_check(); return ret; }
/** * menu_iterate: * @input : input sample for this frame * @old_input : input sample of the previous frame * @trigger_input : difference' input sample - difference * between 'input' and 'old_input' * * Runs RetroArch menu for one frame. * * Returns: 0 on success, -1 if we need to quit out of the loop. **/ int generic_menu_iterate(enum menu_action action) { size_t selection; menu_entry_t entry; enum action_iterate_type iterate_type; const char *label = NULL; int ret = 0; uint32_t label_hash = 0; uint32_t hash = 0; menu_handle_t *menu = menu_driver_get_ptr(); file_list_t *menu_stack = menu_entries_get_menu_stack_ptr(); file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(); menu_entries_get_last_stack(NULL, &label, NULL, NULL); if (!menu) return 0; if (!menu_navigation_ctl(MENU_NAVIGATION_CTL_GET_SELECTION, &selection)) return 0; menu->menu_state.msg[0] = '\0'; hash = menu_hash_calculate(label); iterate_type = action_iterate_type(hash); if (action != MENU_ACTION_NOOP || menu_entries_needs_refresh() || menu_display_ctl(MENU_DISPLAY_CTL_UPDATE_PENDING, NULL)) { BIT64_SET(menu->state, MENU_STATE_RENDER_FRAMEBUFFER); } switch (iterate_type) { case ITERATE_TYPE_HELP: ret = action_iterate_help(menu->menu_state.msg, sizeof(menu->menu_state.msg), label); BIT64_SET(menu->state, MENU_STATE_RENDER_MESSAGEBOX); BIT64_SET(menu->state, MENU_STATE_POST_ITERATE); if (ret == 1 || action == MENU_ACTION_OK) BIT64_SET(menu->state, MENU_STATE_POP_STACK); break; case ITERATE_TYPE_BIND: if (menu_input_key_bind_iterate(menu->menu_state.msg, sizeof(menu->menu_state.msg))) { menu_entries_pop_stack(&selection); menu_navigation_ctl(MENU_NAVIGATION_CTL_SET_SELECTION, &selection); } else BIT64_SET(menu->state, MENU_STATE_RENDER_MESSAGEBOX); break; case ITERATE_TYPE_INFO: { menu_file_list_cbs_t *cbs = menu_entries_get_actiondata_at_offset(selection_buf, selection); rarch_setting_t *setting = cbs->setting; if (setting) { char needle[PATH_MAX_LENGTH]; strlcpy(needle, menu_setting_get_name(setting), sizeof(needle)); label_hash = menu_hash_calculate(needle); } ret = menu_hash_get_help(label_hash, menu->menu_state.msg, sizeof(menu->menu_state.msg)); } BIT64_SET(menu->state, MENU_STATE_RENDER_MESSAGEBOX); BIT64_SET(menu->state, MENU_STATE_POST_ITERATE); if (action == MENU_ACTION_OK) BIT64_SET(menu->state, MENU_STATE_POP_STACK); break; case ITERATE_TYPE_DEFAULT: /* FIXME: Crappy hack, needed for mouse controls to not be completely broken * in case we press back. * * We need to fix this entire mess, mouse controls should not rely on a * hack like this in order to work. */ selection = max(min(selection, (menu_entries_get_size() - 1)), 0); menu_entry_get(&entry, selection, NULL, false); ret = menu_entry_action(&entry, selection, (enum menu_action)action); if (ret) goto end; BIT64_SET(menu->state, MENU_STATE_POST_ITERATE); /* Have to defer it so we let settings refresh. */ if (menu->push_help_screen) { menu_displaylist_info_t info = {0}; info.list = menu_stack; strlcpy(info.label, menu_hash_to_str(MENU_LABEL_HELP), sizeof(info.label)); menu_displaylist_push_list(&info, DISPLAYLIST_HELP); } break; } BIT64_SET(menu->state, MENU_STATE_BLIT); if (BIT64_GET(menu->state, MENU_STATE_POP_STACK)) { size_t new_selection_ptr = selection; menu_entries_pop_stack(&new_selection_ptr); menu_navigation_ctl(MENU_NAVIGATION_CTL_SET_SELECTION, &selection); } if (BIT64_GET(menu->state, MENU_STATE_POST_ITERATE)) menu_input_post_iterate(&ret, action); end: if (ret) return -1; return 0; }