void ozone_change_tab(ozone_handle_t *ozone, enum msg_hash_enums tab, enum menu_settings_type type) { file_list_t *menu_stack = menu_entries_get_menu_stack_ptr(0); size_t stack_size; menu_ctx_list_t list_info; file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0); size_t selection = menu_navigation_get_selection(); menu_file_list_cbs_t *cbs = selection_buf ? (menu_file_list_cbs_t*)file_list_get_actiondata_at_offset(selection_buf, selection) : NULL; list_info.type = MENU_LIST_HORIZONTAL; list_info.action = MENU_ACTION_LEFT; stack_size = menu_stack->size; if (menu_stack->list[stack_size - 1].label) free(menu_stack->list[stack_size - 1].label); menu_stack->list[stack_size - 1].label = NULL; menu_stack->list[stack_size - 1].label = strdup(msg_hash_to_str(tab)); menu_stack->list[stack_size - 1].type = type; menu_driver_list_cache(&list_info); if (cbs && cbs->action_content_list_switch) cbs->action_content_list_switch(selection_buf, menu_stack, "", "", 0); }
static int action_right_scroll(unsigned type, const char *label, bool wraparound) { size_t scroll_accel = 0; unsigned scroll_speed = 0, fast_scroll_speed = 0; size_t selection = menu_navigation_get_selection(); if (!menu_driver_ctl(MENU_NAVIGATION_CTL_GET_SCROLL_ACCEL, &scroll_accel)) return false; scroll_speed = (unsigned)((MAX(scroll_accel, 2) - 2) / 4 + 1); fast_scroll_speed = 4 + 4 * scroll_speed; if (selection + fast_scroll_speed < (menu_entries_get_size())) { size_t idx = selection + fast_scroll_speed; menu_navigation_set_selection(idx); menu_driver_navigation_set(true); } else { if ((menu_entries_get_size() > 0)) menu_driver_ctl(MENU_NAVIGATION_CTL_SET_LAST, NULL); } return 0; }
static void menu_list_flush_stack(menu_list_t *list, size_t idx, const char *needle, unsigned final_type) { bool refresh = false; const char *path = NULL; const char *label = NULL; unsigned type = 0; size_t entry_idx = 0; file_list_t *menu_list = menu_list_get(list, (unsigned)idx); if (!list) return; menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh); file_list_get_last(menu_list, &path, &label, &type, &entry_idx); while (menu_list_flush_stack_type( needle, label, type, final_type) != 0) { size_t new_selection_ptr = menu_navigation_get_selection(); if (!menu_list_pop_stack(list, idx, &new_selection_ptr, 1)) break; menu_navigation_set_selection(new_selection_ptr); menu_list = menu_list_get(list, (unsigned)idx); file_list_get_last(menu_list, &path, &label, &type, &entry_idx); } }
static int action_left_mainmenu(unsigned type, const char *label, bool wraparound) { menu_ctx_list_t list_info; unsigned push_list = 0; menu_handle_t *menu = NULL; if (!menu_driver_ctl(RARCH_MENU_CTL_DRIVER_DATA_GET, &menu)) return menu_cbs_exit(); menu_driver_ctl(RARCH_MENU_CTL_LIST_GET_SELECTION, &list_info); list_info.type = MENU_LIST_PLAIN; menu_driver_ctl(RARCH_MENU_CTL_LIST_GET_SIZE, &list_info); if (list_info.size == 1) { settings_t *settings = config_get_ptr(); if ((list_info.selection != 0) || settings->bools.menu_navigation_wraparound_enable) push_list = 1; } else push_list = 2; switch (push_list) { case 1: { menu_ctx_list_t list_info; file_list_t *menu_stack = menu_entries_get_menu_stack_ptr(0); file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0); size_t selection = menu_navigation_get_selection(); menu_file_list_cbs_t *cbs = selection_buf ? (menu_file_list_cbs_t*)file_list_get_actiondata_at_offset(selection_buf, selection) : NULL; list_info.type = MENU_LIST_HORIZONTAL; list_info.action = MENU_ACTION_LEFT; menu_driver_ctl(RARCH_MENU_CTL_LIST_CACHE, &list_info); if (cbs && cbs->action_content_list_switch) return cbs->action_content_list_switch( selection_buf, menu_stack, "", "", 0); } break; case 2: action_left_scroll(0, "", false); break; case 0: default: break; } return 0; }
static int action_left_scroll(unsigned type, const char *label, bool wraparound) { size_t scroll_accel = 0; unsigned scroll_speed = 0, fast_scroll_speed = 0; size_t selection = menu_navigation_get_selection(); if (!menu_driver_ctl(MENU_NAVIGATION_CTL_GET_SCROLL_ACCEL, &scroll_accel)) return false; scroll_speed = (unsigned)((MAX(scroll_accel, 2) - 2) / 4 + 1); fast_scroll_speed = 4 + 4 * scroll_speed; if (selection > fast_scroll_speed) { size_t idx = selection - fast_scroll_speed; menu_navigation_set_selection(idx); menu_driver_navigation_set(true); } else { bool pending_push = false; menu_driver_ctl(MENU_NAVIGATION_CTL_CLEAR, &pending_push); } return 0; }
static void xui_populate_entries(void *data, const char *path, const char *label, unsigned i) { size_t selection = menu_navigation_get_selection(); XuiListSetCurSelVisible(m_menulist, selection); }
static int menu_input_key_bind_set_mode_common( enum menu_input_binds_ctl_state state, rarch_setting_t *setting) { unsigned bind_type = 0; menu_displaylist_info_t info = {0}; struct retro_keybind *keybind = NULL; unsigned index_offset = setting->index_offset; file_list_t *menu_stack = menu_entries_get_menu_stack_ptr(0); size_t selection = menu_navigation_get_selection(); switch (state) { case MENU_INPUT_BINDS_CTL_BIND_SINGLE: keybind = (struct retro_keybind*)setting_get_ptr(setting); if (!keybind) return -1; bind_type = setting_get_bind_type(setting); menu_input_binds.begin = bind_type; menu_input_binds.last = bind_type; menu_input_binds.target = keybind; menu_input_binds.user = index_offset; info.list = menu_stack; info.type = MENU_SETTINGS_CUSTOM_BIND_KEYBOARD; info.directory_ptr = selection; info.enum_idx = MENU_ENUM_LABEL_CUSTOM_BIND; strlcpy(info.label, msg_hash_to_str(MENU_ENUM_LABEL_CUSTOM_BIND), sizeof(info.label)); if (menu_displaylist_ctl(DISPLAYLIST_INFO, &info)) menu_displaylist_process(&info); break; case MENU_INPUT_BINDS_CTL_BIND_ALL: menu_input_binds.target = &input_config_binds[index_offset][0]; menu_input_binds.begin = MENU_SETTINGS_BIND_BEGIN; menu_input_binds.last = MENU_SETTINGS_BIND_LAST; info.list = menu_stack; info.type = MENU_SETTINGS_CUSTOM_BIND_KEYBOARD; info.directory_ptr = selection; info.enum_idx = MENU_ENUM_LABEL_CUSTOM_BIND_ALL; strlcpy(info.label, msg_hash_to_str(MENU_ENUM_LABEL_CUSTOM_BIND_ALL), sizeof(info.label)); if (menu_displaylist_ctl(DISPLAYLIST_INFO, &info)) menu_displaylist_process(&info); break; default: case MENU_INPUT_BINDS_CTL_BIND_NONE: break; } return 0; }
void menu_input_post_iterate(int *ret, unsigned action) { menu_entry_t entry; settings_t *settings = config_get_ptr(); file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0); size_t selection = menu_navigation_get_selection(); menu_file_list_cbs_t *cbs = selection_buf ? (menu_file_list_cbs_t*)file_list_get_actiondata_at_offset(selection_buf, selection) : NULL; menu_entry_init(&entry); menu_entry_get(&entry, 0, selection, NULL, false); *ret = menu_input_mouse_frame(cbs, &entry, action); if (settings->bools.menu_pointer_enable) *ret |= menu_input_pointer_post_iterate(cbs, &entry, action); menu_entry_free(&entry); }
static int action_right_goto_tab(void) { menu_ctx_list_t list_info; file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0); file_list_t *menu_stack = menu_entries_get_menu_stack_ptr(0); size_t selection = menu_navigation_get_selection(); menu_file_list_cbs_t *cbs = selection_buf ? (menu_file_list_cbs_t*) file_list_get_actiondata_at_offset(selection_buf, selection) : NULL; list_info.type = MENU_LIST_HORIZONTAL; list_info.action = MENU_ACTION_RIGHT; menu_driver_list_cache(&list_info); if (cbs && cbs->action_content_list_switch) return cbs->action_content_list_switch(selection_buf, menu_stack, "", "", 0); return 0; }
void menu_input_post_iterate(int *ret, unsigned action) { menu_entry_t entry = {{0}}; menu_input_t *menu_input = menu_input_get_ptr(); menu_list_t *menu_list = menu_list_get_ptr(); menu_navigation_t *nav = menu_navigation_get_ptr(); settings_t *settings = config_get_ptr(); size_t selected = menu_navigation_get_selection(nav); menu_file_list_cbs_t *cbs = menu_list_get_actiondata_at_offset (menu_list->selection_buf, selected); menu_entry_get(&entry, selected, NULL, false); if (settings->menu.mouse.enable) *ret = menu_input_mouse_post_iterate (&menu_input->mouse.state, cbs, action); *ret = menu_input_mouse_frame(cbs, &entry, menu_input->mouse.state); if (settings->menu.pointer.enable) *ret |= menu_input_pointer_post_iterate(cbs, &entry, action); }
static float glui_get_scroll(void) { int half = 0; unsigned width, height; glui_handle_t *glui = NULL; menu_handle_t *menu = menu_driver_get_ptr(); menu_navigation_t *nav = menu_navigation_get_ptr(); size_t selection = menu_navigation_get_selection(nav); if (!menu || !menu->userdata) return 0; video_driver_get_size(&width, &height); glui = (glui_handle_t*)menu->userdata; if (glui->line_height) half = (height / glui->line_height) / 2; if (selection < (unsigned)half) return 0; return ((selection + 2 - half) * glui->line_height); }
static int action_iterate_info(char *s, size_t len, const char *label) { uint32_t label_hash = 0; menu_file_list_cbs_t *cbs = NULL; menu_list_t *menu_list = menu_list_get_ptr(); menu_navigation_t *nav = menu_navigation_get_ptr(); size_t i = menu_navigation_get_selection(nav); if (!menu_list) return 0; cbs = menu_list_get_actiondata_at_offset(menu_list->selection_buf, i); if (cbs->setting) { char needle[PATH_MAX_LENGTH]; strlcpy(needle, cbs->setting->name, sizeof(needle)); label_hash = menu_hash_calculate(needle); } return menu_hash_get_help(label_hash, s, len); }
/** * Before a refresh, we could have deleted a * file on disk, causing selection_ptr to * suddendly be out of range. * * Ensure it doesn't overflow. **/ static bool menu_entries_refresh(void *data) { size_t list_size; file_list_t *list = (file_list_t*)data; size_t selection = menu_navigation_get_selection(); menu_entries_build_scroll_indices(list); list_size = menu_entries_get_size(); if ((selection >= list_size) && list_size) { size_t idx = list_size - 1; menu_navigation_set_selection(idx); menu_driver_navigation_set(true); } else if (!list_size) { bool pending_push = true; menu_driver_ctl(MENU_NAVIGATION_CTL_CLEAR, &pending_push); } return true; }
static void glui_render_menu_list(glui_handle_t *glui, unsigned width, unsigned height, menu_handle_t *menu, uint32_t normal_color, uint32_t hover_color) { size_t i = 0; uint64_t *frame_count = video_driver_get_frame_count(); size_t end = menu_entries_get_end(); menu_display_t *disp = menu_display_get_ptr(); menu_navigation_t *nav = menu_navigation_get_ptr(); if (!menu_display_update_pending()) return; glui->list_block.carr.coords.vertices = 0; for (i = menu_entries_get_start(); i < end; i++) { bool entry_selected; menu_entry_t entry; int y = disp->header_height - menu->scroll_y + (glui->line_height * i); if (y > (int)height || ((y + (int)glui->line_height) < 0)) continue; menu_entries_get(i, &entry); entry_selected = (menu_navigation_get_selection(nav) == i); glui_render_label_value(glui, y, width, height, *frame_count / 40, entry_selected ? hover_color : normal_color, entry_selected, entry.path, entry.value); } }
static void rmenu_render(void) { size_t begin, end, i, j; struct font_params font_parms = {0}; char title[256] = {0}; char title_buf[256] = {0}; char title_msg[64] = {0}; menu_handle_t *menu = menu_driver_get_ptr(); menu_display_t *disp = menu_display_get_ptr(); menu_animation_t *anim = menu_animation_get_ptr(); menu_list_t *menu_list = menu_list_get_ptr(); menu_navigation_t *nav = menu_navigation_get_ptr(); uint64_t *frame_count = video_driver_get_frame_count(); size_t entries_end = menu_entries_get_end(); size_t selection = menu_navigation_get_selection(nav); if (!menu) return; if (!render_normal) { render_normal = true; return; } if (menu_entries_needs_refresh() && menu_driver_alive() && !disp->msg_force) return; menu_display_fb_unset_dirty(); menu_animation_clear_active(anim); if (!menu_list->selection_buf) return; begin = (selection >= (ENTRIES_HEIGHT / 2)) ? (selection - (ENTRIES_HEIGHT / 2)) : 0; end = ((selection + ENTRIES_HEIGHT) <= entries_end) ? selection + ENTRIES_HEIGHT : entries_end; if (entries_end <= ENTRIES_HEIGHT) begin = 0; if (end - begin > ENTRIES_HEIGHT) end = begin + ENTRIES_HEIGHT; rmenu_render_background(); menu_entries_get_title(title, sizeof(title)); menu_animation_ticker_str(title_buf, RMENU_TERM_WIDTH, *frame_count / 15, title, true); font_parms.x = POSITION_EDGE_MIN + POSITION_OFFSET; font_parms.y = POSITION_EDGE_MIN + POSITION_RENDER_OFFSET - (POSITION_OFFSET*2); font_parms.scale = FONT_SIZE_NORMAL; font_parms.color = WHITE; video_driver_set_osd_msg(title_buf, &font_parms, NULL); font_parms.x = POSITION_EDGE_MIN + POSITION_OFFSET; font_parms.y = POSITION_EDGE_MAX - (POSITION_OFFSET*2); font_parms.scale = FONT_SIZE_NORMAL; font_parms.color = WHITE; menu_entries_get_core_title(title_msg, sizeof(title_msg)); video_driver_set_osd_msg(title_msg, &font_parms, NULL); j = 0; for (i = begin; i < end; i++, j++) { char entry_path[PATH_MAX_LENGTH] = {0}; char entry_value[PATH_MAX_LENGTH] = {0}; char message[PATH_MAX_LENGTH] = {0}; char entry_title_buf[PATH_MAX_LENGTH] = {0}; char type_str_buf[PATH_MAX_LENGTH] = {0}; unsigned entry_spacing = menu_entry_get_spacing(i); bool entry_selected = menu_entry_is_currently_selected(i); menu_entry_get_value(i, entry_value, sizeof(entry_value)); menu_entry_get_path(i, entry_path, sizeof(entry_path)); menu_animation_ticker_str(entry_title_buf, RMENU_TERM_WIDTH - (entry_spacing + 1 + 2), *frame_count / 15, entry_path, entry_selected); menu_animation_ticker_str(type_str_buf, entry_spacing, *frame_count / 15, entry_value, entry_selected); snprintf(message, sizeof(message), "%c %s", entry_selected ? '>' : ' ', entry_title_buf); font_parms.x = POSITION_EDGE_MIN + POSITION_OFFSET; font_parms.y = POSITION_EDGE_MIN + POSITION_RENDER_OFFSET + (POSITION_OFFSET * j); font_parms.scale = FONT_SIZE_NORMAL; font_parms.color = WHITE; video_driver_set_osd_msg(message, &font_parms, NULL); font_parms.x = POSITION_EDGE_CENTER + POSITION_OFFSET; video_driver_set_osd_msg(type_str_buf, &font_parms, NULL); } }
/** * 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 menu_iterate(bool render_this_frame, unsigned action) { menu_entry_t entry; enum action_iterate_type iterate_type; size_t selected; const char *label = NULL; int ret = 0; uint32_t hash = 0; menu_handle_t *menu = menu_driver_get_ptr(); menu_navigation_t *nav = menu_navigation_get_ptr(); menu_display_t *disp = menu_display_get_ptr(); menu_list_t *menu_list = menu_list_get_ptr(); if (render_this_frame) menu_animation_update_time(); menu_list_get_last_stack(menu_list, NULL, &label, NULL, NULL); if (!menu || !menu_list) return 0; menu->state.fb_is_dirty = false; menu->state.do_messagebox = false; menu->state.do_render = false; menu->state.do_pop_stack = false; menu->state.do_post_iterate = false; menu->state.pop_selected = NULL; 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_update_pending()) { if (render_this_frame) menu->state.fb_is_dirty = true; } switch (iterate_type) { case ITERATE_TYPE_HELP: ret = action_iterate_help(menu->state.msg, sizeof(menu->state.msg), label); if (render_this_frame) menu->state.do_render = true; menu->state.pop_selected = NULL; menu->state.do_messagebox = true; menu->state.do_pop_stack = true; menu->state.do_post_iterate = true; if (ret == 1) action = MENU_ACTION_OK; break; case ITERATE_TYPE_BIND: if (menu_input_bind_iterate(menu->state.msg, sizeof(menu->state.msg))) menu_list_pop_stack(menu_list, &nav->selection_ptr); else menu->state.do_messagebox = true; if (render_this_frame) menu->state.do_render = true; break; case ITERATE_TYPE_VIEWPORT: ret = action_iterate_menu_viewport(menu->state.msg, sizeof(menu->state.msg), label, action, hash); if (render_this_frame) menu->state.do_render = true; menu->state.do_messagebox = true; break; case ITERATE_TYPE_INFO: ret = action_iterate_info(menu->state.msg, sizeof(menu->state.msg), label); menu->state.pop_selected = &nav->selection_ptr; if (render_this_frame) menu->state.do_render = true; menu->state.do_messagebox = true; menu->state.do_pop_stack = true; menu->state.do_post_iterate = true; break; case ITERATE_TYPE_MESSAGE: strlcpy(menu->state.msg, disp->message_contents, sizeof(menu->state.msg)); menu->state.pop_selected = &nav->selection_ptr; menu->state.do_messagebox = true; menu->state.do_pop_stack = true; break; case ITERATE_TYPE_DEFAULT: selected = menu_navigation_get_selection(nav); /* FIXME: selected > selection_buf->list->size, i don't know why. */ selected = max(min(selected, menu_list_get_size(menu_list)-1), 0); menu_entry_get(&entry, selected, NULL, false); ret = menu_entry_action(&entry, selected, (enum menu_action)action); if (ret) goto end; menu->state.do_post_iterate = true; if (render_this_frame) menu->state.do_render = true; /* Have to defer it so we let settings refresh. */ if (menu->push_help_screen) { menu_displaylist_info_t info = {0}; info.list = menu_list->menu_stack; strlcpy(info.label, menu_hash_to_str(MENU_LABEL_HELP), sizeof(info.label)); menu_displaylist_push_list(&info, DISPLAYLIST_HELP); } break; } if (menu->state.do_pop_stack && action == MENU_ACTION_OK) menu_list_pop_stack(menu_list, menu->state.pop_selected); if (menu->state.do_post_iterate) menu_input_post_iterate(&ret, action); end: if (ret) return -1; return 0; }
static void glui_frame(void) { unsigned i; GRfloat coord_color[16]; GRfloat coord_color2[16]; GRfloat black_bg[16]; GRfloat bar_bg[16]; GRfloat highlight_bg[16]; GRfloat white_bg[16]; unsigned width, height, ticker_limit; char title[PATH_MAX_LENGTH]; char title_buf[PATH_MAX_LENGTH]; char title_msg[PATH_MAX_LENGTH]; char timedate[PATH_MAX_LENGTH]; gl_t *gl = NULL; glui_handle_t *glui = NULL; const struct font_renderer *font_driver = NULL; driver_t *driver = driver_get_ptr(); menu_handle_t *menu = menu_driver_get_ptr(); menu_animation_t *anim = menu_animation_get_ptr(); menu_navigation_t *nav = menu_navigation_get_ptr(); menu_display_t *disp = menu_display_get_ptr(); settings_t *settings = config_get_ptr(); menu_input_t *menu_input = menu_input_get_ptr(); uint64_t *frame_count = video_driver_get_frame_count(); const uint32_t normal_color = FONT_COLOR_ARGB_TO_RGBA( settings->menu.entry_normal_color); const uint32_t hover_color = FONT_COLOR_ARGB_TO_RGBA( settings->menu.entry_hover_color); const uint32_t title_color = FONT_COLOR_ARGB_TO_RGBA( settings->menu.title_color); if (!menu || !menu->userdata) return; gl = (gl_t*)video_driver_get_ptr(NULL); if (!gl) return; glui = (glui_handle_t*)menu->userdata; title[0] = '\0'; title_buf[0] = '\0'; title_msg[0] = '\0'; timedate[0] = '\0'; video_driver_get_size(&width, &height); menu_display_set_viewport(); for (i = 0; i < 16; i++) { coord_color[i] = 0; coord_color2[i] = 1.0f; black_bg[i] = 0; bar_bg[i] = 0.2; highlight_bg[i] = 1; white_bg[i] = 1; if (i == 3 || i == 7 || i == 11 || i == 15) { black_bg[i] = 0.75f; coord_color[i] = 0.75f; coord_color2[i] = 0.75f; bar_bg[i] = 1.00f; highlight_bg[i] = 0.1f; } } menu_video_frame_background(menu, settings, gl, glui->textures.bg.id, 0.75f, false, &coord_color[0], &coord_color2[0], &glui_vertexes[0], &glui_tex_coords[0]); menu_entries_get_title(title, sizeof(title)); font_driver = driver->font_osd_driver; menu_display_font_bind_block(menu, font_driver, &glui->list_block); glui_render_menu_list(glui, width, height, menu, normal_color, hover_color); menu_display_font_flush_block(menu, font_driver); glui_render_quad(gl, 0, disp->header_height - menu->scroll_y + glui->line_height * menu_navigation_get_selection(nav), width, glui->line_height, width, height, &highlight_bg[0]); menu_animation_set_active(anim); glui_render_quad(gl, 0, 0, width, disp->header_height, width, height, &bar_bg[0]); ticker_limit = (width - glui->margin*2) / glui->glyph_width - strlen(menu_hash_to_str(MENU_VALUE_BACK)) * 2; menu_animation_ticker_str(title_buf, ticker_limit, *frame_count / 100, title, true); glui_blit_line(width / 2, 0, width, height, title_buf, title_color, TEXT_ALIGN_CENTER); if (menu_entries_show_back()) glui_blit_line(glui->margin, 0, width, height, menu_hash_to_str(MENU_VALUE_BACK), title_color, TEXT_ALIGN_LEFT); glui_render_quad(gl, 0, height - disp->header_height, width, disp->header_height, width, height, &bar_bg[0]); glui_draw_scrollbar(gl, width, height, &white_bg[0]); if (menu_entries_get_core_title(title_msg, sizeof(title_msg)) == 0) glui_blit_line( glui->margin, height - glui->line_height, width, height, title_msg, title_color, TEXT_ALIGN_LEFT); if (settings->menu.timedate_enable) { menu_display_timedate(timedate, sizeof(timedate), 0); glui_blit_line( width - glui->margin, height - glui->line_height, width, height, timedate, hover_color, TEXT_ALIGN_RIGHT); } if (menu_input->keyboard.display) { char msg[PATH_MAX_LENGTH]; const char *str = *menu_input->keyboard.buffer; msg[0] = '\0'; if (!str) str = ""; glui_render_quad(gl, 0, 0, width, height, width, height, &black_bg[0]); snprintf(msg, sizeof(msg), "%s\n%s", menu_input->keyboard.label, str); glui_render_messagebox(msg); } if (glui->box_message[0] != '\0') { glui_render_quad(gl, 0, 0, width, height, width, height, &black_bg[0]); glui_render_messagebox(glui->box_message); glui->box_message[0] = '\0'; } if (settings->menu.mouse.enable) glui_render_quad(gl, menu_input->mouse.x - 5, menu_input->mouse.y - 5, 10, 10, width, height, &white_bg[0]); gl->shader->use(gl, GL_SHADER_STOCK_BLEND); menu_display_unset_viewport(); }
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_state; settings_t *settings = config_get_ptr(); if (!menu_input || !settings) return -1; #ifdef HAVE_OVERLAY /* If we have overlays enabled, overlay controls take * precedence and we don't want regular menu * pointer controls to be handled */ if (( settings->bools.input_overlay_enable && input_overlay_is_alive(overlay_ptr))) return 0; #endif 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; menu_input->pointer.counter++; if (menu_input->pointer.counter == 1 && !menu_input_ctl(MENU_INPUT_CTL_IS_POINTER_DRAGGED, NULL)) { menu_ctx_pointer_t point; point.x = pointer_x; point.y = pointer_y; point.ptr = menu_input->pointer.ptr; point.cbs = cbs; point.entry = entry; point.action = action; menu_driver_ctl(RARCH_MENU_CTL_POINTER_DOWN, &point); } 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 (video_context_driver_get_metrics(&metrics)) { if (abs(pointer_x - start_x) > (dpi / 10) || abs(pointer_y - start_y) > (dpi / 10)) { float s; 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; s = menu_input->pointer.dy; 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; if (menu_input_dialog_get_display_kb()) { menu_driver_ctl(RARCH_MENU_CTL_OSK_PTR_AT_POS, &point); if (point.retcode > -1) { menu_event_set_osk_ptr(point.retcode); menu_event_osk_append(point.retcode); } } else { if (menu_input->pointer.counter > 32) { size_t selection = menu_navigation_get_selection(); if (cbs && cbs->action_start) return menu_entry_action(entry, (unsigned)selection, MENU_ACTION_START); } else { menu_driver_ctl(RARCH_MENU_CTL_POINTER_UP, &point); 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->pointer.counter = 0; menu_input_ctl(MENU_INPUT_CTL_UNSET_POINTER_DRAGGED, NULL); } } if (menu_input->pointer.back) { if (!pointer_oldback) { pointer_oldback = true; menu_entry_action(entry, (unsigned)menu_navigation_get_selection(), MENU_ACTION_CANCEL); } } pointer_oldback = menu_input->pointer.back; return ret; }
static void xui_render(void *data, bool is_idle) { size_t end, i, selection, fb_pitch; unsigned fb_width, fb_height; char title[PATH_MAX_LENGTH] = {0}; const char *dir = NULL; const char *label = NULL; unsigned menu_type = 0; uint64_t frame_count = xui_frame_count; bool msg_force = menu_display_get_msg_force(); menu_display_get_fb_size(&fb_width, &fb_height, &fb_pitch); if ( menu_entries_ctl(MENU_ENTRIES_CTL_NEEDS_REFRESH, NULL) && menu_driver_is_alive() && !msg_force ) return; menu_display_unset_framebuffer_dirty_flag(); menu_animation_ctl(MENU_ANIMATION_CTL_CLEAR_ACTIVE, NULL); xui_render_background(); if (XuiHandleIsValid(m_menutitle)) { menu_animation_ctx_ticker_t ticker; menu_entries_get_title(title, sizeof(title)); mbstowcs(strw_buffer, title, sizeof(strw_buffer) / sizeof(wchar_t)); XuiTextElementSetText(m_menutitle, strw_buffer); ticker.s = title; ticker.len = RXUI_TERM_WIDTH(fb_width) - 3; ticker.idx = (unsigned int)frame_count / 15; ticker.str = title; ticker.selected = true; menu_animation_ticker(&ticker); } if (XuiHandleIsValid(m_menutitle)) { if ( menu_entries_get_core_title(title, sizeof(title)) == 0) { mbstowcs(strw_buffer, title, sizeof(strw_buffer) / sizeof(wchar_t)); XuiTextElementSetText(m_menutitlebottom, strw_buffer); } } end = menu_entries_get_size(); for (i = 0; i < end; i++) { menu_entry_t entry; char *entry_path = NULL; char entry_value[PATH_MAX_LENGTH] = {0}; wchar_t msg_right[PATH_MAX_LENGTH] = {0}; wchar_t msg_left[PATH_MAX_LENGTH] = {0}; menu_entry_init(&entry); menu_entry_get(&entry, 0, i, NULL, true); menu_entry_get_value(&entry, entry_value, sizeof(entry_value)); entry_path = menu_entry_get_path(&entry); mbstowcs(msg_left, entry_path, sizeof(msg_left) / sizeof(wchar_t)); mbstowcs(msg_right, entry_value, sizeof(msg_right) / sizeof(wchar_t)); xui_set_list_text(i, msg_left, msg_right); menu_entry_free(&entry); if (!string_is_empty(entry_path)) free(entry_path); } selection = menu_navigation_get_selection(); XuiListSetCurSelVisible(m_menulist, selection); if (menu_input_dialog_get_display_kb()) { char msg[1024] = {0}; const char *str = menu_input_dialog_get_buffer(); const char *label = menu_input_dialog_get_label_buffer(); snprintf(msg, sizeof(msg), "%s\n%s", label, str); xui_render_messagebox(NULL, msg); } }
static void xui_navigation_clear(void *data, bool pending_push) { size_t selection = menu_navigation_get_selection(); XuiListSetCurSelVisible(m_menulist, selection); }
static int menu_input_mouse_post_iterate(uint64_t *input_mouse, menu_file_list_cbs_t *cbs, unsigned action, bool *mouse_activity) { settings_t *settings = config_get_ptr(); static bool mouse_oldleft = false; static bool mouse_oldright = false; if ( !settings->bools.menu_mouse_enable #ifdef HAVE_OVERLAY || (settings->bools.input_overlay_enable && input_overlay_is_alive(overlay_ptr)) #endif ) { /* HACK: Need to lie to avoid false hits if mouse is held * when entering the RetroArch window. */ /* This happens if, for example, someone double clicks the * window border to maximize it. * * The proper fix is, of course, triggering on WM_LBUTTONDOWN * rather than this state change. */ mouse_oldleft = true; mouse_oldright = true; return 0; } if (menu_input_mouse_state(MENU_MOUSE_LEFT_BUTTON)) { if (!mouse_oldleft) { menu_input_t *menu_input = &menu_input_state; size_t selection = menu_navigation_get_selection(); BIT64_SET(*input_mouse, MENU_MOUSE_ACTION_BUTTON_L); mouse_oldleft = true; if ((menu_input->mouse.ptr == selection) && cbs && cbs->action_select) { BIT64_SET(*input_mouse, MENU_MOUSE_ACTION_BUTTON_L_TOGGLE); } else if (menu_input->mouse.ptr <= (menu_entries_get_size() - 1)) { BIT64_SET(*input_mouse, MENU_MOUSE_ACTION_BUTTON_L_SET_NAVIGATION); } *mouse_activity = true; } } else mouse_oldleft = false; if (menu_input_mouse_state(MENU_MOUSE_RIGHT_BUTTON)) { if (!mouse_oldright) { mouse_oldright = true; BIT64_SET(*input_mouse, MENU_MOUSE_ACTION_BUTTON_R); *mouse_activity = true; } } else mouse_oldright = false; if (menu_input_mouse_state(MENU_MOUSE_WHEEL_DOWN)) { BIT64_SET(*input_mouse, MENU_MOUSE_ACTION_WHEEL_DOWN); *mouse_activity = true; } if (menu_input_mouse_state(MENU_MOUSE_WHEEL_UP)) { BIT64_SET(*input_mouse, MENU_MOUSE_ACTION_WHEEL_UP); *mouse_activity = true; } if (menu_input_mouse_state(MENU_MOUSE_HORIZ_WHEEL_DOWN)) { BIT64_SET(*input_mouse, MENU_MOUSE_ACTION_HORIZ_WHEEL_DOWN); *mouse_activity = true; } if (menu_input_mouse_state(MENU_MOUSE_HORIZ_WHEEL_UP)) { BIT64_SET(*input_mouse, MENU_MOUSE_ACTION_HORIZ_WHEEL_UP); *mouse_activity = true; } return 0; }
static int menu_input_mouse_frame( menu_file_list_cbs_t *cbs, menu_entry_t *entry, unsigned action) { bool mouse_activity = false; bool no_mouse_activity = false; uint64_t mouse_state = MENU_MOUSE_ACTION_NONE; int ret = 0; settings_t *settings = config_get_ptr(); menu_input_t *menu_input = &menu_input_state; bool mouse_enable = settings->bools.menu_mouse_enable; if (mouse_enable) ret = menu_input_mouse_post_iterate(&mouse_state, cbs, action, &mouse_activity); if ((settings->bools.menu_pointer_enable || mouse_enable)) { menu_ctx_pointer_t point; point.x = menu_input_mouse_state(MENU_MOUSE_X_AXIS); point.y = menu_input_mouse_state(MENU_MOUSE_Y_AXIS); point.ptr = 0; point.cbs = NULL; point.entry = NULL; point.action = 0; point.retcode = 0; if (menu_input_dialog_get_display_kb()) menu_driver_ctl(RARCH_MENU_CTL_OSK_PTR_AT_POS, &point); if (rarch_timer_is_running(&mouse_activity_timer)) rarch_timer_tick(&mouse_activity_timer); if (mouse_old_x != point.x || mouse_old_y != point.y) { if (!rarch_timer_is_running(&mouse_activity_timer)) mouse_activity = true; menu_event_set_osk_ptr(point.retcode); } else { if (rarch_timer_has_expired(&mouse_activity_timer)) no_mouse_activity = true; } mouse_old_x = point.x; mouse_old_y = point.y; } if (BIT64_GET(mouse_state, MENU_MOUSE_ACTION_BUTTON_L)) { menu_ctx_pointer_t point; point.x = menu_input_mouse_state(MENU_MOUSE_X_AXIS); point.y = menu_input_mouse_state(MENU_MOUSE_Y_AXIS); point.ptr = menu_input->mouse.ptr; point.cbs = cbs; point.entry = entry; point.action = action; if (menu_input_dialog_get_display_kb()) { menu_driver_ctl(RARCH_MENU_CTL_OSK_PTR_AT_POS, &point); if (point.retcode > -1) { menu_event_set_osk_ptr(point.retcode); menu_event_osk_append(point.retcode); } } else { menu_driver_ctl(RARCH_MENU_CTL_POINTER_UP, &point); menu_driver_ctl(RARCH_MENU_CTL_POINTER_TAP, &point); ret = point.retcode; } } if (BIT64_GET(mouse_state, MENU_MOUSE_ACTION_BUTTON_R)) { size_t selection = menu_navigation_get_selection(); menu_entry_action(entry, (unsigned)selection, MENU_ACTION_CANCEL); } if (BIT64_GET(mouse_state, MENU_MOUSE_ACTION_WHEEL_DOWN)) { unsigned increment_by = 1; menu_driver_ctl(MENU_NAVIGATION_CTL_INCREMENT, &increment_by); } if (BIT64_GET(mouse_state, MENU_MOUSE_ACTION_WHEEL_UP)) { unsigned decrement_by = 1; menu_driver_ctl(MENU_NAVIGATION_CTL_DECREMENT, &decrement_by); } if (BIT64_GET(mouse_state, MENU_MOUSE_ACTION_HORIZ_WHEEL_UP)) { /* stub */ } if (BIT64_GET(mouse_state, MENU_MOUSE_ACTION_HORIZ_WHEEL_DOWN)) { /* stub */ } if (mouse_activity) { menu_ctx_environment_t menu_environ; rarch_timer_begin(&mouse_activity_timer, 4); menu_environ.type = MENU_ENVIRON_ENABLE_MOUSE_CURSOR; menu_environ.data = NULL; menu_driver_ctl(RARCH_MENU_CTL_ENVIRONMENT, &menu_environ); } if (no_mouse_activity) { menu_ctx_environment_t menu_environ; rarch_timer_end(&mouse_activity_timer); menu_environ.type = MENU_ENVIRON_DISABLE_MOUSE_CURSOR; menu_environ.data = NULL; menu_driver_ctl(RARCH_MENU_CTL_ENVIRONMENT, &menu_environ); } return ret; }
static void xui_navigation_set_visible(void *data) { size_t selection = menu_navigation_get_selection(); XuiListSetCurSelVisible(m_menulist, selection); }
bool menu_entry_is_currently_selected(unsigned id) { return (id == menu_navigation_get_selection()); }