Merge pull request #9485 from jdgleaver/input-update

Overhaul menu mouse/touchscreen input handling
This commit is contained in:
Twinaphex 2019-09-19 20:44:35 +02:00 committed by GitHub
commit 36e5909057
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 1116 additions and 833 deletions

View File

@ -143,6 +143,7 @@ enum
typedef struct materialui_handle
{
bool need_compute;
bool need_scroll;
bool mouse_show;
int cursor_size;
@ -645,6 +646,40 @@ static void materialui_compute_entries_box(materialui_handle_t* mui, int width,
mui->content_height = sum;
}
/* Compute the scroll value depending on the highlighted entry */
static float materialui_get_scroll(materialui_handle_t *mui)
{
unsigned i, width, height = 0;
float half, sum = 0;
size_t selection = menu_navigation_get_selection();
file_list_t *list = menu_entries_get_selection_buf_ptr(0);
if (!mui)
return 0;
/* Whenever we perform a 'manual' scroll, scroll
* acceleration must be reset */
menu_input_set_pointer_y_accel(0.0f);
video_driver_get_size(&width, &height);
half = height / 2;
for (i = 0; i < selection; i++)
{
materialui_node_t *node = (materialui_node_t*)
file_list_get_userdata_at_offset(list, i);
if (node)
sum += node->line_height;
}
if (sum < half)
return 0;
return sum - half;
}
/* Called on each frame. We use this callback to implement the touch scroll
with acceleration */
static void materialui_render(void *data,
@ -652,6 +687,7 @@ static void materialui_render(void *data,
bool is_idle)
{
unsigned bottom, header_height;
menu_input_pointer_t pointer;
size_t i = 0;
materialui_handle_t *mui = (materialui_handle_t*)data;
settings_t *settings = config_get_ptr();
@ -660,61 +696,63 @@ static void materialui_render(void *data,
if (!mui)
return;
/* Here's a nasty issue:
* After calling populate_entries(), we need to call
* materialui_get_scroll() so the last selected item
* is correctly displayed on screen.
* But we can't do this until materialui_compute_entries_box()
* has been called, so we should delegate it until mui->need_compute
* is acted upon.
* *But* we can't do this in the same frame that mui->need_compute
* is acted upon, because of the order in which materialui_frame()
* and materialui_render() are called. Since mui->tabs_height is
* set by materialui_frame(), the first time materialui_render() is
* called after populate_entries() it has the wrong mui->tabs_height
* value...
* We therefore have to delegate the scroll until the frame after
* mui->need_compute is handled... */
if (mui->need_scroll)
{
mui->scroll_y = materialui_get_scroll(mui);
mui->need_scroll = false;
}
if (mui->need_compute)
{
if (mui->font)
materialui_compute_entries_box(mui, width, height);
mui->need_compute = false;
mui->need_scroll = true;
}
menu_display_set_width(width);
menu_display_set_height(height);
header_height = menu_display_get_header_height();
if (settings->bools.menu_pointer_enable)
menu_input_get_pointer_state(&pointer);
if (pointer.type != MENU_POINTER_DISABLED)
{
size_t ii;
int16_t pointer_y = menu_input_pointer_state(MENU_POINTER_Y_AXIS);
float old_accel_val = 0.0f;
float new_accel_val = 0.0f;
size_t entries_end = menu_entries_get_size();
int16_t pointer_y = pointer.y;
float old_accel_val = 0.0f;
float new_accel_val = 0.0f;
size_t entries_end = menu_entries_get_size();
for (ii = 0; ii < entries_end; ii++)
{
materialui_node_t *node = (materialui_node_t*)
file_list_get_userdata_at_offset(list, ii);
if (pointer_y > (-mui->scroll_y + header_height + node->y)
&& pointer_y < (-mui->scroll_y + header_height + node->y + node->line_height)
)
menu_input_ctl(MENU_INPUT_CTL_POINTER_PTR, &ii);
if ((pointer_y > (-mui->scroll_y + header_height + node->y)) &&
(pointer_y < (-mui->scroll_y + header_height + node->y + node->line_height)))
{
menu_input_set_pointer_selection(ii);
break;
}
}
menu_input_ctl(MENU_INPUT_CTL_POINTER_ACCEL_READ, &old_accel_val);
mui->scroll_y -= old_accel_val;
new_accel_val = old_accel_val * 0.96;
menu_input_ctl(MENU_INPUT_CTL_POINTER_ACCEL_WRITE, &new_accel_val);
}
if (settings->bools.menu_mouse_enable)
{
size_t ii;
int16_t mouse_y = menu_input_mouse_state(MENU_MOUSE_Y_AXIS);
size_t entries_end = menu_entries_get_size();
for (ii = 0; ii < entries_end; ii++)
{
materialui_node_t *node = (materialui_node_t*)
file_list_get_userdata_at_offset(list, ii);
if (mouse_y > (-mui->scroll_y + header_height + node->y)
&& mouse_y < (-mui->scroll_y + header_height + node->y + node->line_height)
)
menu_input_ctl(MENU_INPUT_CTL_MOUSE_PTR, &ii);
}
mui->scroll_y -= pointer.y_accel;
}
if (mui->scroll_y < 0)
@ -1664,15 +1702,20 @@ static void materialui_frame(void *data, video_frame_info_t *video_info)
}
if (mui->mouse_show)
{
menu_input_pointer_t pointer;
menu_input_get_pointer_state(&pointer);
menu_display_draw_cursor(
video_info,
&white_bg[0],
mui->cursor_size,
mui->textures.list[MUI_TEXTURE_POINTER],
menu_input_mouse_state(MENU_MOUSE_X_AXIS),
menu_input_mouse_state(MENU_MOUSE_Y_AXIS),
pointer.x,
pointer.y,
width,
height);
}
menu_display_restore_clear_color();
menu_display_unset_viewport(video_info->width, video_info->height);
@ -1766,6 +1809,7 @@ static void *materialui_init(void **userdata, bool video_is_threaded)
*userdata = mui;
mui->cursor_size = scale_factor / 3;
mui->need_compute = false;
mui->need_scroll = false;
mui->menu_title[0] = '\0';
@ -1840,36 +1884,6 @@ static bool materialui_load_image(void *userdata, void *data, enum menu_image_ty
return true;
}
/* Compute the scroll value depending on the highlighted entry */
static float materialui_get_scroll(materialui_handle_t *mui)
{
unsigned i, width, height = 0;
float half, sum = 0;
size_t selection = menu_navigation_get_selection();
file_list_t *list = menu_entries_get_selection_buf_ptr(0);
if (!mui)
return 0;
video_driver_get_size(&width, &height);
half = height / 2;
for (i = 0; i < selection; i++)
{
materialui_node_t *node = (materialui_node_t*)
file_list_get_userdata_at_offset(list, i);
if (node)
sum += node->line_height;
}
if (sum < half)
return 0;
return sum - half;
}
/* The navigation pointer has been updated (for example by pressing up or down
on the keyboard). We use this function to animate the scroll. */
static void materialui_navigation_set(void *data, bool scroll)
@ -1881,6 +1895,11 @@ static void materialui_navigation_set(void *data, bool scroll)
if (!mui || !scroll)
return;
/* mui->scroll_y will be modified by the animation
* - Set scroll acceleration to zero to minimise
* potential conflicts */
menu_input_set_pointer_y_accel(0.0f);
entry.duration = 166;
entry.target_value = scroll_pos;
entry.subject = &mui->scroll_y;
@ -1895,7 +1914,11 @@ static void materialui_navigation_set(void *data, bool scroll)
static void materialui_list_set_selection(void *data, file_list_t *list)
{
materialui_navigation_set(data, true);
/* This is called upon MENU_ACTION_CANCEL
* Have to set 'scroll' to false, otherwise
* navigating backwards in the menu is absolutely
* horrendous... */
materialui_navigation_set(data, false);
}
/* The navigation pointer is set back to zero */
@ -1908,6 +1931,7 @@ static void materialui_navigation_clear(void *data, bool pending_push)
menu_entries_ctl(MENU_ENTRIES_CTL_SET_START, &i);
mui->scroll_y = 0;
menu_input_set_pointer_y_accel(0.0f);
}
static void materialui_navigation_set_last(void *data)
@ -1925,13 +1949,18 @@ static void materialui_populate_entries(
void *data, const char *path,
const char *label, unsigned i)
{
materialui_handle_t *mui = (materialui_handle_t*)data;
materialui_handle_t *mui = (materialui_handle_t*)data;
if (!mui)
return;
menu_entries_get_title(mui->menu_title, sizeof(mui->menu_title));
mui->need_compute = true;
mui->scroll_y = materialui_get_scroll(mui);
/* Note: mui->scroll_y position needs to be set here,
* but we can't do this until materialui_compute_entries_box()
* has been called. We therefore delegate it until mui->need_compute
* is acted upon */
}
/* Context reset is called on launch or when a core is launched */
@ -2902,7 +2931,6 @@ menu_ctx_driver_t menu_ctx_mui = {
NULL,
NULL,
NULL,
NULL,
menu_display_osk_ptr_at_pos,
NULL, /* update_savestate_thumbnail_path */
NULL, /* update_savestate_thumbnail_image */

View File

@ -88,7 +88,6 @@ menu_ctx_driver_t menu_ctx_null = {
NULL, /* load_image */
"null",
NULL, /* environ */
NULL, /* pointer_tap */
NULL, /* update_thumbnail_path */
NULL, /* update_thumbnail_image */
NULL, /* refresh_thumbnail_image */

View File

@ -1529,8 +1529,11 @@ static void ozone_frame(void *data, video_frame_info_t *video_info)
if (ozone->first_frame)
{
ozone->cursor_x_old = menu_input_mouse_state(MENU_MOUSE_X_AXIS);
ozone->cursor_y_old = menu_input_mouse_state(MENU_MOUSE_Y_AXIS);
menu_input_pointer_t pointer;
menu_input_get_pointer_state(&pointer);
ozone->cursor_x_old = pointer.x;
ozone->cursor_y_old = pointer.y;
ozone->first_frame = false;
}
@ -1699,14 +1702,17 @@ static void ozone_frame(void *data, video_frame_info_t *video_info)
/* Cursor */
if (ozone->show_cursor)
{
menu_input_pointer_t pointer;
menu_input_get_pointer_state(&pointer);
menu_display_set_alpha(ozone_pure_white, 1.0f);
menu_display_draw_cursor(
video_info,
ozone_pure_white,
ozone->dimensions.cursor_size,
ozone->icons_textures[OZONE_ENTRIES_ICONS_TEXTURE_POINTER],
menu_input_mouse_state(MENU_MOUSE_X_AXIS),
menu_input_mouse_state(MENU_MOUSE_Y_AXIS),
pointer.x,
pointer.y,
video_info->width,
video_info->height
);
@ -2269,13 +2275,13 @@ static bool ozone_get_load_content_animation_data(void *userdata, menu_texture_i
}
#endif
static int ozone_pointer_tap(void *userdata,
static int ozone_pointer_up(void *userdata,
unsigned x, unsigned y, unsigned ptr,
menu_file_list_cbs_t *cbs,
menu_entry_t *entry, unsigned action)
{
size_t selection = menu_navigation_get_selection();
if (ptr == selection && cbs && cbs->action_select)
if (ptr == selection)
return (unsigned)menu_entry_action(entry, (unsigned)selection, MENU_ACTION_SELECT);
menu_navigation_set_selection(ptr);
@ -2435,7 +2441,6 @@ menu_ctx_driver_t menu_ctx_ozone = {
ozone_load_image,
"ozone",
ozone_environ_cb,
ozone_pointer_tap,
ozone_update_thumbnail_path,
ozone_update_thumbnail_image,
ozone_refresh_thumbnail_image,
@ -2446,7 +2451,7 @@ menu_ctx_driver_t menu_ctx_ozone = {
NULL, /* update_savestate_thumbnail_path */
NULL, /* update_savestate_thumbnail_image */
NULL, /* pointer_down */
NULL, /* pointer_up */
ozone_pointer_up,
#ifdef HAVE_MENU_WIDGETS
ozone_get_load_content_animation_data
#else

View File

@ -351,6 +351,7 @@ void ozone_draw_entries(ozone_handle_t *ozone, video_frame_info_t *video_info,
size_t i, y, entries_end;
float sidebar_offset, bottom_boundary, invert, alpha_anim;
unsigned video_info_height, video_info_width, entry_width, button_height;
menu_input_pointer_t pointer;
settings_t *settings = config_get_ptr();
bool old_list = selection_buf == ozone->selection_buf_old;
@ -359,13 +360,24 @@ void ozone_draw_entries(ozone_handle_t *ozone, video_frame_info_t *video_info,
size_t old_selection_y = 0;
int entry_padding = ozone_get_entries_padding(ozone, old_list);
int16_t cursor_x = menu_input_mouse_state(MENU_MOUSE_X_AXIS);
int16_t cursor_y = menu_input_mouse_state(MENU_MOUSE_Y_AXIS);
int16_t cursor_x = 0;
int16_t cursor_y = 0;
if (settings->bools.menu_mouse_enable && !ozone->cursor_mode && (cursor_x != ozone->cursor_x_old || cursor_y != ozone->cursor_y_old))
ozone->cursor_mode = true;
else if (!settings->bools.menu_mouse_enable)
ozone->cursor_mode = false; /* we need to disable it on the fly */
menu_input_get_pointer_state(&pointer);
if (pointer.type != MENU_POINTER_DISABLED)
{
cursor_x = pointer.x;
cursor_y = pointer.y;
/* Not sure why it's done like this - best to leave well alone for now... */
if (settings->bools.menu_mouse_enable && !ozone->cursor_mode && (cursor_x != ozone->cursor_x_old || cursor_y != ozone->cursor_y_old))
ozone->cursor_mode = true;
else if (!settings->bools.menu_mouse_enable)
ozone->cursor_mode = false; /* we need to disable it on the fly */
}
else
ozone->cursor_mode = false;
ozone->cursor_x_old = cursor_x;
ozone->cursor_y_old = cursor_y;
@ -438,15 +450,9 @@ void ozone_draw_entries(ozone_handle_t *ozone, video_frame_info_t *video_info,
/* Cursor */
if (!old_list && ozone->cursor_mode)
{
if ( cursor_x >= border_start_x && (cursor_x <= border_start_x + (int)entry_width) &&
cursor_y >= border_start_y && (cursor_y <= border_start_y + (int)button_height))
{
selection_y = y;
menu_navigation_set_selection(i);
menu_input_ctl(MENU_INPUT_CTL_MOUSE_PTR, &i);
}
}
menu_input_set_pointer_selection(i);
border_iterate:
if (node)

View File

@ -531,7 +531,7 @@ typedef struct
bool shadow_enable;
unsigned particle_effect;
bool extended_ascii_enable;
float scroll_y;
int16_t scroll_y;
char msgbox[1024];
unsigned color_theme;
rgui_colors_t colors;
@ -2824,23 +2824,80 @@ end:
string_list_free(list);
}
static void rgui_blit_cursor(void)
static void rgui_blit_cursor(rgui_t *rgui)
{
size_t fb_pitch;
unsigned fb_width, fb_height;
int16_t x = menu_input_mouse_state(MENU_MOUSE_X_AXIS);
int16_t y = menu_input_mouse_state(MENU_MOUSE_Y_AXIS);
menu_input_pointer_t pointer;
menu_display_get_fb_size(&fb_width, &fb_height,
&fb_pitch);
menu_input_get_pointer_state(&pointer);
if (rgui_frame_buf.data)
{
rgui_color_rect(rgui_frame_buf.data, fb_width, fb_height, x, y - 5, 1, 11, 0xFFFF);
rgui_color_rect(rgui_frame_buf.data, fb_width, fb_height, x - 5, y, 11, 1, 0xFFFF);
rgui_color_rect(rgui_frame_buf.data, fb_width, fb_height, pointer.x, pointer.y - 5, 1, 11, rgui->colors.normal_color);
rgui_color_rect(rgui_frame_buf.data, fb_width, fb_height, pointer.x - 5, pointer.y, 11, 1, rgui->colors.normal_color);
}
}
int rgui_osk_ptr_at_pos(void *data, int x, int y,
unsigned width, unsigned height)
{
/* This is a lazy copy/paste from rgui_render_osk(),
* but it will do for now... */
size_t fb_pitch;
unsigned fb_width, fb_height;
size_t key_index;
unsigned key_width, key_height;
unsigned key_text_offset_x, key_text_offset_y;
unsigned ptr_width, ptr_height;
unsigned ptr_offset_x, ptr_offset_y;
unsigned keyboard_width, keyboard_height;
unsigned keyboard_offset_x, keyboard_offset_y;
unsigned osk_width, osk_height;
unsigned osk_x, osk_y;
/* Get dimensions/layout */
menu_display_get_fb_size(&fb_width, &fb_height, &fb_pitch);
key_text_offset_x = 8;
key_text_offset_y = 6;
key_width = FONT_WIDTH + (key_text_offset_x * 2);
key_height = FONT_HEIGHT + (key_text_offset_y * 2);
ptr_offset_x = 2;
ptr_offset_y = 2;
ptr_width = key_width - (ptr_offset_x * 2);
ptr_height = key_height - (ptr_offset_y * 2);
keyboard_width = key_width * OSK_CHARS_PER_LINE;
keyboard_height = key_height * 4;
keyboard_offset_x = 10;
keyboard_offset_y = 10 + 15 + (2 * FONT_HEIGHT_STRIDE);
osk_width = keyboard_width + 20;
osk_height = keyboard_offset_y + keyboard_height + 10;
osk_x = (fb_width - osk_width) / 2;
osk_y = (fb_height - osk_height) / 2;
for (key_index = 0; key_index < 44; key_index++)
{
unsigned key_row = (unsigned)(key_index / OSK_CHARS_PER_LINE);
unsigned key_column = (unsigned)(key_index - (key_row * OSK_CHARS_PER_LINE));
unsigned osk_ptr_x = osk_x + keyboard_offset_x + ptr_offset_x + (key_column * key_width);
unsigned osk_ptr_y = osk_y + keyboard_offset_y + ptr_offset_y + (key_row * key_height);
if (x > osk_ptr_x && x < osk_ptr_x + ptr_width &&
y > osk_ptr_y && y < osk_ptr_y + ptr_height)
return (int)key_index;
}
return -1;
}
static void rgui_render_osk(
rgui_t *rgui,
menu_animation_ctx_ticker_t *ticker, menu_animation_ctx_ticker_smooth_t *ticker_smooth,
@ -3134,8 +3191,9 @@ static void rgui_render(void *data,
size_t i, end, fb_pitch, old_start, new_start;
unsigned fb_width, fb_height;
int bottom;
menu_input_pointer_t pointer;
unsigned ticker_x_offset = 0;
size_t entries_end = 0;
size_t entries_end = menu_entries_get_size();
bool msg_force = false;
bool fb_size_changed = false;
settings_t *settings = config_get_ptr();
@ -3144,6 +3202,11 @@ static void rgui_render(void *data,
static bool display_kb = false;
bool current_display_cb = false;
bool show_fs_thumbnail =
rgui->show_fs_thumbnail &&
rgui->entry_has_thumbnail &&
(fs_thumbnail.is_valid || (rgui->thumbnail_queue_size > 0));
/* Sanity check */
if (!rgui || !rgui_frame_buf.data || !settings)
return;
@ -3207,64 +3270,73 @@ static void rgui_render(void *data,
rgui->force_redraw = false;
if (settings->bools.menu_pointer_enable)
/* Get offset of bottommost entry */
bottom = (int)(entries_end - rgui_term_layout.height);
menu_entries_ctl(MENU_ENTRIES_CTL_START_GET, &old_start);
if (old_start > (unsigned)bottom)
{
unsigned new_val;
/* MENU_ENTRIES_CTL_SET_START requires a pointer of
* type size_t, so have to create a copy of 'bottom'
* here to avoid memory errors... */
size_t bottom_cpy = (size_t)bottom;
menu_entries_ctl(MENU_ENTRIES_CTL_SET_START, &bottom_cpy);
}
menu_entries_ctl(MENU_ENTRIES_CTL_START_GET, &old_start);
/* Handle pointer input
* Note: We'd normally just check pointer.type here but
* RGUI focuses on performance - so skip all of this
* if both mouse and touchscreen input are disabled by
* the user (only saves a dozen or so clock cycles, but
* might as well...) */
if (settings->bools.menu_mouse_enable || settings->bools.menu_pointer_enable)
{
menu_input_get_pointer_state(&pointer);
new_val = (unsigned)(menu_input_pointer_state(MENU_POINTER_Y_AXIS)
/ (11 - 2 + old_start));
menu_input_ctl(MENU_INPUT_CTL_POINTER_PTR, &new_val);
if (menu_input_ctl(MENU_INPUT_CTL_IS_POINTER_DRAGGED, NULL))
/* Ignore input when showing a fullscreen thumbnail */
if ((pointer.type != MENU_POINTER_DISABLED) && !show_fs_thumbnail)
{
size_t start;
int16_t delta_y = menu_input_pointer_state(MENU_POINTER_DELTA_Y_AXIS);
rgui->scroll_y += delta_y;
/* Update currently 'highlighted' item */
if (pointer.y > rgui_term_layout.start_y)
{
unsigned new_ptr;
menu_entries_ctl(MENU_ENTRIES_CTL_START_GET, &old_start);
start = -rgui->scroll_y / 11 + 2;
/* Note: It's okay for this to go out of range
* (limits are checked in rgui_pointer_up()) */
new_ptr = (unsigned)((pointer.y - rgui_term_layout.start_y) / FONT_HEIGHT_STRIDE) + old_start;
menu_entries_ctl(MENU_ENTRIES_CTL_SET_START, &start);
menu_input_set_pointer_selection(new_ptr);
}
if (rgui->scroll_y > 0)
rgui->scroll_y = 0;
/* Allow drag-scrolling if items are currently off-screen */
if (pointer.dragged && (bottom > 0))
{
size_t start;
int16_t scroll_y_max = bottom * FONT_HEIGHT_STRIDE;
rgui->scroll_y += -1 * pointer.dy;
rgui->scroll_y = (rgui->scroll_y < 0) ? 0 : rgui->scroll_y;
rgui->scroll_y = (rgui->scroll_y > scroll_y_max) ? scroll_y_max : rgui->scroll_y;
start = rgui->scroll_y / FONT_HEIGHT_STRIDE;
menu_entries_ctl(MENU_ENTRIES_CTL_SET_START, &start);
}
}
}
if (settings->bools.menu_mouse_enable)
{
unsigned new_mouse_ptr;
int16_t mouse_y = menu_input_mouse_state(MENU_MOUSE_Y_AXIS);
menu_entries_ctl(MENU_ENTRIES_CTL_START_GET, &old_start);
new_mouse_ptr = (unsigned)(mouse_y / 11 - 2 + old_start);
menu_input_ctl(MENU_INPUT_CTL_MOUSE_PTR, &new_mouse_ptr);
}
/* Start position may have changed - get current
* value and determine index of last displayed entry */
menu_entries_ctl(MENU_ENTRIES_CTL_START_GET, &old_start);
end = ((old_start + rgui_term_layout.height) <= entries_end) ?
old_start + rgui_term_layout.height : entries_end;
/* Do not scroll if all items are visible. */
if (menu_entries_get_size() <= rgui_term_layout.height)
if (entries_end <= rgui_term_layout.height)
{
size_t start = 0;
menu_entries_ctl(MENU_ENTRIES_CTL_SET_START, &start);
}
bottom = (int)(menu_entries_get_size() - rgui_term_layout.height);
menu_entries_ctl(MENU_ENTRIES_CTL_START_GET, &old_start);
if (old_start > (unsigned)bottom)
menu_entries_ctl(MENU_ENTRIES_CTL_SET_START, &bottom);
menu_entries_ctl(MENU_ENTRIES_CTL_START_GET, &old_start);
entries_end = menu_entries_get_size();
end = ((old_start + rgui_term_layout.height) <= (entries_end)) ?
old_start + rgui_term_layout.height : entries_end;
/* Render background */
rgui_render_background();
@ -3295,7 +3367,7 @@ static void rgui_render(void *data,
* normal menu thumbnail/text list display modes */
if (current_display_cb)
rgui_render_osk(rgui, &ticker, &ticker_smooth, use_smooth_ticker);
else if (rgui->show_fs_thumbnail && rgui->entry_has_thumbnail && (fs_thumbnail.is_valid || (rgui->thumbnail_queue_size > 0)))
else if (show_fs_thumbnail)
{
/* If fullscreen thumbnails are enabled and we are viewing a playlist,
* switch to fullscreen thumbnail view mode if either current thumbnail
@ -3787,7 +3859,7 @@ static void rgui_render(void *data,
!video_driver_has_windowed();
if (settings->bools.menu_mouse_enable && cursor_visible)
rgui_blit_cursor();
rgui_blit_cursor(rgui);
}
}
@ -4226,6 +4298,7 @@ static void *rgui_init(void **userdata, bool video_is_threaded)
start = 0;
menu_entries_ctl(MENU_ENTRIES_CTL_SET_START, &start);
rgui->scroll_y = 0;
rgui_init_font_lut();
@ -4692,7 +4765,10 @@ static void rgui_navigation_set(void *data, bool scroll)
}
if (do_set_start)
{
menu_entries_ctl(MENU_ENTRIES_CTL_SET_START, &start);
rgui->scroll_y = start * FONT_HEIGHT_STRIDE;
}
}
static void rgui_navigation_set_last(void *data)
@ -4782,27 +4858,51 @@ static int rgui_environ(enum menu_environ_cb type,
return -1;
}
static int rgui_pointer_tap(void *data,
static int rgui_pointer_up(void *data,
unsigned x, unsigned y,
unsigned ptr, menu_file_list_cbs_t *cbs,
menu_entry_t *entry, unsigned action)
{
rgui_t *rgui = (rgui_t*)data;
unsigned header_height = menu_display_get_header_height();
size_t selection = menu_navigation_get_selection();
bool show_fs_thumbnail = false;
if (y < header_height)
{
size_t selection = menu_navigation_get_selection();
return menu_entry_action(entry, (unsigned)selection, MENU_ACTION_CANCEL);
}
else if (ptr <= (menu_entries_get_size() - 1))
{
size_t selection = menu_navigation_get_selection();
if (!rgui)
return -1;
if (ptr == selection && cbs && cbs->action_select)
show_fs_thumbnail =
rgui->show_fs_thumbnail &&
rgui->entry_has_thumbnail &&
(fs_thumbnail.is_valid || (rgui->thumbnail_queue_size > 0));
if (show_fs_thumbnail)
{
/* If we are currently showing a fullscreen thumbnail:
* - Must provide a mechanism for toggling it off
* - A normal mouse press should just select the current
* entry (for which the thumbnail is being shown) */
if (y < header_height)
rgui_update_thumbnail_image(rgui);
else
return menu_entry_action(entry, (unsigned)selection, MENU_ACTION_SELECT);
}
else
{
if (y < header_height)
return menu_entry_action(entry, (unsigned)selection, MENU_ACTION_CANCEL);
else if (ptr <= (menu_entries_get_size() - 1))
{
/* If currently selected item matches 'pointer' value,
* perform a MENU_ACTION_SELECT on it */
if (ptr == selection)
return menu_entry_action(entry, (unsigned)selection, MENU_ACTION_SELECT);
menu_navigation_set_selection(ptr);
menu_driver_navigation_set(false);
/* Otherwise, just move the current selection to the
* 'pointer' value */
menu_navigation_set_selection(ptr);
menu_driver_navigation_set(false);
}
}
return 0;
@ -5065,17 +5165,16 @@ menu_ctx_driver_t menu_ctx_rgui = {
rgui_load_image,
"rgui",
rgui_environ,
rgui_pointer_tap,
NULL, /* update_thumbnail_path */
rgui_update_thumbnail_image,
rgui_refresh_thumbnail_image,
rgui_set_thumbnail_system,
rgui_get_thumbnail_system,
NULL, /* set_thumbnail_content */
NULL, /* osk_ptr_at_pos */
rgui_osk_ptr_at_pos,
NULL, /* update_savestate_thumbnail_path */
NULL, /* update_savestate_thumbnail_image */
NULL, /* pointer_down */
NULL, /* pointer_up */
rgui_pointer_up, /* pointer_up */
NULL, /* get_load_content_animation_data */
};

View File

@ -2655,23 +2655,25 @@ static void stripes_render(void *data,
bool is_idle)
{
size_t i;
menu_input_pointer_t pointer;
settings_t *settings = config_get_ptr();
stripes_handle_t *stripes = (stripes_handle_t*)data;
unsigned end = (unsigned)menu_entries_get_size();
bool mouse_enable = settings->bools.menu_mouse_enable;
bool pointer_enable = settings->bools.menu_pointer_enable;
if (!stripes)
return;
if (pointer_enable || mouse_enable)
menu_input_get_pointer_state(&pointer);
if (pointer.type != MENU_POINTER_DISABLED)
{
size_t selection = menu_navigation_get_selection();
int16_t pointer_y = menu_input_pointer_state(MENU_POINTER_Y_AXIS);
int16_t mouse_y = menu_input_mouse_state(MENU_MOUSE_Y_AXIS)
+ (stripes->cursor_size/2);
int16_t pointer_y = pointer.y;
unsigned first = 0, last = end;
pointer_y = (pointer.type == MENU_POINTER_MOUSE) ?
pointer_y + (stripes->cursor_size/2) : pointer_y;
if (height)
stripes_calculate_visible_range(stripes, height,
end, selection, &first, &last);
@ -2682,17 +2684,8 @@ static void stripes_render(void *data,
+ stripes_item_y(stripes, (int)i, selection);
float item_y2 = item_y1 + stripes->icon_size;
if (pointer_enable)
{
if (pointer_y > item_y1 && pointer_y < item_y2)
menu_input_ctl(MENU_INPUT_CTL_POINTER_PTR, &i);
}
if (mouse_enable)
{
if (mouse_y > item_y1 && mouse_y < item_y2)
menu_input_ctl(MENU_INPUT_CTL_MOUSE_PTR, &i);
}
if (pointer_y > item_y1 && pointer_y < item_y2)
menu_input_set_pointer_selection(i);
}
}
@ -3005,14 +2998,17 @@ static void stripes_frame(void *data, video_frame_info_t *video_info)
/* Cursor image */
if (stripes->mouse_show)
{
menu_input_pointer_t pointer;
menu_input_get_pointer_state(&pointer);
menu_display_set_alpha(stripes_coord_white, MIN(stripes->alpha, 1.00f));
menu_display_draw_cursor(
video_info,
&stripes_coord_white[0],
stripes->cursor_size,
stripes->textures.list[STRIPES_TEXTURE_POINTER],
menu_input_mouse_state(MENU_MOUSE_X_AXIS),
menu_input_mouse_state(MENU_MOUSE_Y_AXIS),
pointer.x,
pointer.y,
width,
height);
}
@ -4390,7 +4386,7 @@ error:
return false;
}
static int stripes_pointer_tap(void *userdata,
static int stripes_pointer_up(void *userdata,
unsigned x, unsigned y, unsigned ptr,
menu_file_list_cbs_t *cbs,
menu_entry_t *entry, unsigned action)
@ -4449,7 +4445,6 @@ menu_ctx_driver_t menu_ctx_stripes = {
stripes_load_image,
"stripes",
stripes_environ,
stripes_pointer_tap,
stripes_update_thumbnail_path,
stripes_update_thumbnail_image,
stripes_refresh_thumbnail_image,
@ -4460,6 +4455,6 @@ menu_ctx_driver_t menu_ctx_stripes = {
stripes_update_savestate_thumbnail_path,
stripes_update_savestate_thumbnail_image,
NULL, /* pointer_down */
NULL, /* pointer_up */
stripes_pointer_up, /* pointer_up */
NULL /* get_load_content_animation_data */
};

View File

@ -3328,8 +3328,8 @@ static void xmb_render(void *data,
unsigned end = (unsigned)menu_entries_get_size();
bool mouse_enable = settings->bools.menu_mouse_enable;
bool pointer_enable = settings->bools.menu_pointer_enable;
float scale_factor;
menu_input_pointer_t pointer;
if (!xmb)
return;
@ -3342,14 +3342,17 @@ static void xmb_render(void *data,
xmb->previous_scale_factor = scale_factor;
if (pointer_enable || mouse_enable)
menu_input_get_pointer_state(&pointer);
if (pointer.type != MENU_POINTER_DISABLED)
{
size_t selection = menu_navigation_get_selection();
int16_t pointer_y = menu_input_pointer_state(MENU_POINTER_Y_AXIS);
int16_t mouse_y = menu_input_mouse_state(MENU_MOUSE_Y_AXIS)
+ (xmb->cursor_size/2);
int16_t pointer_y = pointer.y;
unsigned first = 0, last = end;
pointer_y = (pointer.type == MENU_POINTER_MOUSE) ?
pointer_y + (xmb->cursor_size/2) : pointer_y;
if (height)
xmb_calculate_visible_range(xmb, height,
end, (unsigned)selection, &first, &last);
@ -3360,17 +3363,8 @@ static void xmb_render(void *data,
+ xmb_item_y(xmb, (int)i, selection);
float item_y2 = item_y1 + xmb->icon_size;
if (pointer_enable)
{
if (pointer_y > item_y1 && pointer_y < item_y2)
menu_input_ctl(MENU_INPUT_CTL_POINTER_PTR, &i);
}
if (mouse_enable)
{
if (mouse_y > item_y1 && mouse_y < item_y2)
menu_input_ctl(MENU_INPUT_CTL_MOUSE_PTR, &i);
}
if (pointer_y > item_y1 && pointer_y < item_y2)
menu_input_set_pointer_selection(i);
}
}
@ -4324,14 +4318,17 @@ static void xmb_frame(void *data, video_frame_info_t *video_info)
/* Cursor image */
if (xmb->mouse_show)
{
menu_input_pointer_t pointer;
menu_input_get_pointer_state(&pointer);
menu_display_set_alpha(coord_white, MIN(xmb->alpha, 1.00f));
menu_display_draw_cursor(
video_info,
&coord_white[0],
xmb->cursor_size,
xmb->textures.list[XMB_TEXTURE_POINTER],
menu_input_mouse_state(MENU_MOUSE_X_AXIS),
menu_input_mouse_state(MENU_MOUSE_Y_AXIS),
pointer.x,
pointer.y,
width,
height);
}
@ -5979,7 +5976,7 @@ error:
return false;
}
static int xmb_pointer_tap(void *userdata,
static int xmb_pointer_up(void *userdata,
unsigned x, unsigned y, unsigned ptr,
menu_file_list_cbs_t *cbs,
menu_entry_t *entry, unsigned action)
@ -5994,7 +5991,7 @@ static int xmb_pointer_tap(void *userdata,
else if (ptr <= (menu_entries_get_size() - 1))
{
size_t selection = menu_navigation_get_selection();
if (ptr == selection && cbs && cbs->action_select)
if (ptr == selection)
return (unsigned)menu_entry_action(entry, (unsigned)selection, MENU_ACTION_SELECT);
menu_navigation_set_selection(ptr);
@ -6060,7 +6057,6 @@ menu_ctx_driver_t menu_ctx_xmb = {
xmb_load_image,
"xmb",
xmb_environ,
xmb_pointer_tap,
xmb_update_thumbnail_path,
xmb_update_thumbnail_image,
xmb_refresh_thumbnail_image,
@ -6071,7 +6067,7 @@ menu_ctx_driver_t menu_ctx_xmb = {
xmb_update_savestate_thumbnail_path,
xmb_update_savestate_thumbnail_image,
NULL, /* pointer_down */
NULL, /* pointer_up */
xmb_pointer_up,
#ifdef HAVE_MENU_WIDGETS
xmb_get_load_content_animation_data
#else

View File

@ -721,7 +721,6 @@ menu_ctx_driver_t menu_ctx_xui = {
NULL, /* load_image */
"xui",
xui_environ,
NULL, /* pointer_tap */
NULL, /* update_thumbnail_path */
NULL, /* update_thumbnail_image */
NULL, /* refresh_thumbnail_image */

View File

@ -66,7 +66,6 @@ enum rarch_menu_ctl_state
RARCH_MENU_CTL_FIND_DRIVER,
RARCH_MENU_CTL_LIST_FREE,
RARCH_MENU_CTL_ENVIRONMENT,
RARCH_MENU_CTL_POINTER_TAP,
RARCH_MENU_CTL_POINTER_DOWN,
RARCH_MENU_CTL_POINTER_UP,
RARCH_MENU_CTL_OSK_PTR_AT_POS,
@ -305,38 +304,6 @@ enum menu_action
MENU_ACTION_POINTER_PRESSED
};
enum menu_input_pointer_state
{
MENU_POINTER_X_AXIS = 0,
MENU_POINTER_Y_AXIS,
MENU_POINTER_DELTA_X_AXIS,
MENU_POINTER_DELTA_Y_AXIS,
MENU_POINTER_PRESSED
};
enum menu_input_mouse_state
{
MENU_MOUSE_X_AXIS = 0,
MENU_MOUSE_Y_AXIS,
MENU_MOUSE_LEFT_BUTTON,
MENU_MOUSE_RIGHT_BUTTON,
MENU_MOUSE_WHEEL_UP,
MENU_MOUSE_WHEEL_DOWN,
MENU_MOUSE_HORIZ_WHEEL_UP,
MENU_MOUSE_HORIZ_WHEEL_DOWN
};
enum menu_input_ctl_state
{
MENU_INPUT_CTL_NONE = 0,
MENU_INPUT_CTL_MOUSE_PTR,
MENU_INPUT_CTL_POINTER_PTR,
MENU_INPUT_CTL_POINTER_ACCEL_READ,
MENU_INPUT_CTL_POINTER_ACCEL_WRITE,
MENU_INPUT_CTL_IS_POINTER_DRAGGED,
MENU_INPUT_CTL_DEINIT
};
enum playlist_sublabel_runtime
{
PLAYLIST_RUNTIME_PER_CORE = 0,

View File

@ -2810,12 +2810,12 @@ void menu_display_snow(int width, int height)
if (p->alive)
{
int16_t mouse_x = menu_input_mouse_state(
MENU_MOUSE_X_AXIS);
menu_input_pointer_t pointer;
menu_input_get_pointer_state(&pointer);
p->y += p->yspeed;
p->x += menu_display_scalef(
mouse_x, 0, width, -0.3, 0.3);
pointer.x, 0, width, -0.3, 0.3);
p->x += p->xspeed;
p->alive = p->y >= 0 && p->y < height
@ -3097,6 +3097,10 @@ static bool menu_init(menu_handle_t *menu_data)
{
settings_t *settings = config_get_ptr();
/* Ensure that menu pointer input is correctly
* initialised */
menu_input_reset();
if (!menu_entries_init())
return false;
@ -3463,7 +3467,7 @@ bool menu_driver_ctl(enum rarch_menu_ctl_state state, void *data)
for (i = 0; i < SCROLL_INDEX_SIZE; i++)
scroll_index_list[i] = 0;
menu_input_ctl(MENU_INPUT_CTL_DEINIT, NULL);
menu_input_reset();
if (menu_driver_ctx && menu_driver_ctx->free)
menu_driver_ctx->free(menu_userdata);
@ -3538,19 +3542,6 @@ bool menu_driver_ctl(enum rarch_menu_ctl_state state, void *data)
}
}
return false;
case RARCH_MENU_CTL_POINTER_TAP:
{
menu_ctx_pointer_t *point = (menu_ctx_pointer_t*)data;
if (!menu_driver_ctx || !menu_driver_ctx->pointer_tap)
{
point->retcode = 0;
return false;
}
point->retcode = menu_driver_ctx->pointer_tap(menu_userdata,
point->x, point->y, point->ptr,
point->cbs, point->entry, point->action);
}
break;
case RARCH_MENU_CTL_POINTER_DOWN:
{
menu_ctx_pointer_t *point = (menu_ctx_pointer_t*)data;

View File

@ -305,9 +305,6 @@ typedef struct menu_ctx_driver
bool (*load_image)(void *userdata, void *data, enum menu_image_type type);
const char *ident;
int (*environ_cb)(enum menu_environ_cb type, void *data, void *userdata);
int (*pointer_tap)(void *data, unsigned x, unsigned y, unsigned ptr,
menu_file_list_cbs_t *cbs,
menu_entry_t *entry, unsigned action);
void (*update_thumbnail_path)(void *data, unsigned i, char pos);
void (*update_thumbnail_image)(void *data);
void (*refresh_thumbnail_image)(void *data);

View File

@ -29,25 +29,66 @@
RETRO_BEGIN_DECLS
#define MENU_INPUT_HIDE_CURSOR_DELAY 4000000 /* 4 seconds */
#define MENU_INPUT_PRESS_TIME_SHORT 250000 /* 250 ms */
#define MENU_INPUT_PRESS_TIME_LONG 1500000 /* 1.5 second */
/* (Anthing less than 'short' is considered a tap) */
#define MENU_INPUT_Y_ACCEL_DECAY_FACTOR 0.96f
enum menu_pointer_type
{
MENU_POINTER_DISABLED = 0,
MENU_POINTER_MOUSE,
MENU_POINTER_TOUCHSCREEN
};
enum menu_input_mouse_hw_id
{
MENU_MOUSE_X_AXIS = 0,
MENU_MOUSE_Y_AXIS,
MENU_MOUSE_LEFT_BUTTON,
MENU_MOUSE_RIGHT_BUTTON,
MENU_MOUSE_WHEEL_UP,
MENU_MOUSE_WHEEL_DOWN,
MENU_MOUSE_HORIZ_WHEEL_UP,
MENU_MOUSE_HORIZ_WHEEL_DOWN
};
/* Defines set of (abstracted) inputs/states
* common to mouse + touchscreen hardware */
typedef struct menu_input_pointer_hw_state
{
bool active;
int16_t x;
int16_t y;
bool select_pressed;
bool cancel_pressed;
bool up_pressed;
bool down_pressed;
bool left_pressed;
bool right_pressed;
} menu_input_pointer_hw_state_t;
typedef struct menu_input_pointer
{
enum menu_pointer_type type;
bool pressed;
bool dragged;
retro_time_t press_duration;
int16_t x;
int16_t y;
int16_t dx;
int16_t dy;
float y_accel;
} menu_input_pointer_t;
typedef struct menu_input
{
struct
{
unsigned ptr;
} mouse;
struct
{
bool back;
bool pressed[2];
int16_t x;
int16_t y;
int16_t dx;
int16_t dy;
unsigned ptr;
unsigned counter;
float accel;
} pointer;
menu_input_pointer_t pointer;
unsigned ptr;
bool select_inhibit;
} menu_input_t;
typedef struct menu_input_ctx_hitbox
@ -58,16 +99,32 @@ typedef struct menu_input_ctx_hitbox
int32_t y2;
} menu_input_ctx_hitbox_t;
/* Must be called inside menu_driver_toggle()
* Prevents phantom input when using an overlay to
* toggle menu ON if overlays are disabled in-menu */
void menu_input_driver_toggle(bool on);
/* Provides access to all pointer device parameters */
void menu_input_get_pointer_state(menu_input_pointer_t *pointer);
/* Getters/setters for menu item (index) currently
* selected/highlighted (hovered over) by the pointer
* device
* Note: Each menu driver is responsible for setting this */
unsigned menu_input_get_pointer_selection(void);
void menu_input_set_pointer_selection(unsigned selection);
/* Allows pointer y acceleration to be overridden
* (typically want to set acceleration to zero when
* calling populate entries) */
void menu_input_set_pointer_y_accel(float y_accel);
void menu_input_reset(void);
bool menu_input_pointer_check_vector_inside_hitbox(menu_input_ctx_hitbox_t *hitbox);
void menu_input_post_iterate(int *ret, unsigned action);
int16_t menu_input_pointer_state(enum menu_input_pointer_state state);
int16_t menu_input_mouse_state(enum menu_input_mouse_state state);
bool menu_input_mouse_check_vector_inside_hitbox(menu_input_ctx_hitbox_t *hitbox);
bool menu_input_ctl(enum menu_input_ctl_state state, void *data);
RETRO_END_DECLS
#endif

File diff suppressed because it is too large Load Diff