Move code to menu_driver.c and input_driver.c

This commit is contained in:
twinaphex 2021-10-13 15:40:01 +02:00
parent 99b09ce359
commit f070da6dfc
8 changed files with 805 additions and 797 deletions

View File

@ -62,7 +62,31 @@
#define INPUT_REMOTE_KEY_PRESSED(input_st, key, port) (input_st->remote_st_ptr.buttons[(port)] & (UINT64_C(1) << (key)))
/**
* check_input_driver_block_hotkey:
*
* Checks if 'hotkey enable' key is pressed.
*
* If we haven't bound anything to this,
* always allow hotkeys.
* If we hold ENABLE_HOTKEY button, block all libretro input to allow
* hotkeys to be bound to same keys as RetroPad.
**/
#define CHECK_INPUT_DRIVER_BLOCK_HOTKEY(normal_bind, autoconf_bind) \
( \
(((normal_bind)->key != RETROK_UNKNOWN) \
|| ((normal_bind)->mbutton != NO_BTN) \
|| ((normal_bind)->joykey != NO_BTN) \
|| ((normal_bind)->joyaxis != AXIS_NONE) \
|| ((autoconf_bind)->key != RETROK_UNKNOWN) \
|| ((autoconf_bind)->joykey != NO_BTN) \
|| ((autoconf_bind)->joyaxis != AXIS_NONE)) \
)
/**************************************/
/* TODO/FIXME - turn these into static global variable */
uint64_t lifecycle_state = 0;
static void *input_null_init(const char *joypad_driver) { return (void*)-1; }
static void input_null_poll(void *data) { }
@ -3244,7 +3268,7 @@ static void input_overlay_loaded(retro_task_t *task,
bool inp_overlay_auto_rotate = settings->bools.input_overlay_auto_rotate;
bool input_overlay_enable = settings->bools.input_overlay_enable;
video_driver_state_t *video_st = video_state_get_ptr();
input_driver_state_t *input_st = input_state_get_ptr();
input_driver_state_t *input_st = &input_driver_st;
if (err)
return;
@ -3450,6 +3474,139 @@ bool input_keys_pressed_other_sources(
return false;
}
void input_keys_pressed(
unsigned port,
bool is_menu,
int input_hotkey_block_delay,
input_bits_t *p_new_state,
const struct retro_keybind **binds,
const struct retro_keybind *binds_norm,
const struct retro_keybind *binds_auto,
const input_device_driver_t *joypad,
const input_device_driver_t *sec_joypad,
rarch_joypad_info_t *joypad_info)
{
unsigned i;
input_driver_state_t *input_st = &input_driver_st;
if (CHECK_INPUT_DRIVER_BLOCK_HOTKEY(binds_norm, binds_auto))
{
if ( input_state_wrap(
input_st->current_driver,
input_st->current_data,
input_st->primary_joypad,
sec_joypad,
joypad_info,
&binds[port],
input_st->keyboard_mapping_blocked,
port, RETRO_DEVICE_JOYPAD, 0,
RARCH_ENABLE_HOTKEY))
{
if (input_st->input_hotkey_block_counter < input_hotkey_block_delay)
input_st->input_hotkey_block_counter++;
else
input_st->block_libretro_input = true;
}
else
{
input_st->input_hotkey_block_counter = 0;
input_st->block_hotkey = true;
}
}
if ( !is_menu
&& binds[port][RARCH_GAME_FOCUS_TOGGLE].valid)
{
const struct retro_keybind *focus_binds_auto =
&input_autoconf_binds[port][RARCH_GAME_FOCUS_TOGGLE];
const struct retro_keybind *focus_normal =
&binds[port][RARCH_GAME_FOCUS_TOGGLE];
/* Allows rarch_focus_toggle hotkey to still work
* even though every hotkey is blocked */
if (CHECK_INPUT_DRIVER_BLOCK_HOTKEY(
focus_normal, focus_binds_auto))
{
if (input_state_wrap(
input_st->current_driver,
input_st->current_data,
input_st->primary_joypad,
sec_joypad,
joypad_info,
&binds[port],
input_st->keyboard_mapping_blocked,
port,
RETRO_DEVICE_JOYPAD, 0, RARCH_GAME_FOCUS_TOGGLE))
input_st->block_hotkey = false;
}
}
{
int16_t ret = 0;
/* Check the libretro input first */
if (!input_st->block_libretro_input)
ret = input_state_wrap(
input_st->current_driver,
input_st->current_data,
input_st->primary_joypad,
sec_joypad,
joypad_info, &binds[port],
input_st->keyboard_mapping_blocked,
port, RETRO_DEVICE_JOYPAD, 0,
RETRO_DEVICE_ID_JOYPAD_MASK);
for (i = 0; i < RARCH_FIRST_META_KEY; i++)
{
if (
(ret & (UINT64_C(1) << i)) ||
input_keys_pressed_other_sources(input_st,
i, p_new_state))
{
BIT256_SET_PTR(p_new_state, i);
}
}
}
/* Check the hotkeys */
if (input_st->block_hotkey)
{
for (i = RARCH_FIRST_META_KEY; i < RARCH_BIND_LIST_END; i++)
{
if (
BIT64_GET(lifecycle_state, i)
|| input_keys_pressed_other_sources(input_st,
i, p_new_state))
{
BIT256_SET_PTR(p_new_state, i);
}
}
}
else
{
for (i = RARCH_FIRST_META_KEY; i < RARCH_BIND_LIST_END; i++)
{
bool bit_pressed = binds[port][i].valid
&& input_state_wrap(
input_st->current_driver,
input_st->current_data,
input_st->primary_joypad,
sec_joypad,
joypad_info,
&binds[port],
input_st->keyboard_mapping_blocked,
port, RETRO_DEVICE_JOYPAD, 0, i);
if ( bit_pressed
|| BIT64_GET(lifecycle_state, i)
|| input_keys_pressed_other_sources(input_st,
i, p_new_state))
{
BIT256_SET_PTR(p_new_state, i);
}
}
}
}
int16_t input_state_device(
input_driver_state_t *input_st,
settings_t *settings,
@ -4891,4 +5048,3 @@ int16_t input_driver_state_wrapper(unsigned port, unsigned device,
return result;
}

View File

@ -1009,6 +1009,25 @@ void input_driver_poll(void);
int16_t input_driver_state_wrapper(unsigned port, unsigned device,
unsigned idx, unsigned id);
/**
* input_keys_pressed:
*
* Grab an input sample for this frame.
*
* Returns: Input sample containing a mask of all pressed keys.
*/
void input_keys_pressed(
unsigned port,
bool is_menu,
int input_hotkey_block_delay,
input_bits_t *p_new_state,
const struct retro_keybind **binds,
const struct retro_keybind *binds_norm,
const struct retro_keybind *binds_auto,
const input_device_driver_t *joypad,
const input_device_driver_t *sec_joypad,
rarch_joypad_info_t *joypad_info);
extern input_device_driver_t *joypad_drivers[];
extern input_driver_t *input_drivers[];
#ifdef HAVE_HID

View File

@ -5642,7 +5642,7 @@ current_time;
bool menu_input_dialog_get_display_kb(void)
{
struct menu_state *menu_st = menu_state_get_ptr();
struct menu_state *menu_st = &menu_driver_state;
#ifdef HAVE_LIBNX
input_driver_state_t *input_st = input_state_get_ptr();
SwkbdConfig kbd;
@ -5738,7 +5738,7 @@ unsigned menu_event(
unsigned ret = MENU_ACTION_NOOP;
bool set_scroll = false;
size_t new_scroll_accel = 0;
struct menu_state *menu_st = menu_state_get_ptr();
struct menu_state *menu_st = &menu_driver_state;
menu_input_t *menu_input = &menu_st->input_state;
input_driver_state_t *input_st = input_state_get_ptr();
input_driver_t *current_input = input_st->current_driver;
@ -6094,3 +6094,619 @@ unsigned menu_event(
return ret;
}
static int menu_input_pointer_post_iterate(
gfx_display_t *p_disp,
retro_time_t current_time,
menu_file_list_cbs_t *cbs,
menu_entry_t *entry, unsigned action)
{
static retro_time_t start_time = 0;
static int16_t start_x = 0;
static int16_t start_y = 0;
static int16_t last_x = 0;
static int16_t last_y = 0;
static uint16_t dx_start_right_max = 0;
static uint16_t dx_start_left_max = 0;
static uint16_t dy_start_up_max = 0;
static uint16_t dy_start_down_max = 0;
static bool last_select_pressed = false;
static bool last_cancel_pressed = false;
static bool last_left_pressed = false;
static bool last_right_pressed = false;
static retro_time_t last_left_action_time = 0;
static retro_time_t last_right_action_time = 0;
static retro_time_t last_press_direction_time = 0;
bool attenuate_y_accel = true;
bool osk_active = menu_input_dialog_get_display_kb();
bool messagebox_active = false;
int ret = 0;
struct menu_state *menu_st = &menu_driver_state;
menu_input_pointer_hw_state_t *pointer_hw_state = &menu_st->input_pointer_hw_state;
menu_input_t *menu_input = &menu_st->input_state;
menu_handle_t *menu = menu_st->driver_data;
video_driver_state_t *video_st = video_state_get_ptr();
input_driver_state_t *input_st = input_state_get_ptr();
/* Check whether a message box is currently
* being shown
* > Note: This ignores input bind dialogs,
* since input binding overrides normal input
* and must be handled separately... */
if (menu)
messagebox_active = BIT64_GET(
menu->state, MENU_STATE_RENDER_MESSAGEBOX) &&
!string_is_empty(menu->menu_state_msg);
/* If onscreen keyboard is shown and we currently have
* active mouse input, highlight key under mouse cursor */
if (osk_active &&
(menu_input->pointer.type == MENU_POINTER_MOUSE) &&
pointer_hw_state->active)
{
menu_ctx_pointer_t point;
point.x = pointer_hw_state->x;
point.y = pointer_hw_state->y;
point.ptr = 0;
point.cbs = NULL;
point.entry = NULL;
point.action = 0;
point.gesture = MENU_INPUT_GESTURE_NONE;
point.retcode = 0;
menu_driver_ctl(RARCH_MENU_CTL_OSK_PTR_AT_POS, &point);
if (point.retcode > -1)
input_st->osk_ptr = point.retcode;
}
/* Select + X/Y position */
if (!menu_input->select_inhibit)
{
if (pointer_hw_state->select_pressed)
{
int16_t x = pointer_hw_state->x;
int16_t y = pointer_hw_state->y;
static float accel0 = 0.0f;
static float accel1 = 0.0f;
/* Transition from select unpressed to select pressed */
if (!last_select_pressed)
{
menu_ctx_pointer_t point;
/* Initialise variables */
start_time = current_time;
start_x = x;
start_y = y;
last_x = x;
last_y = y;
dx_start_right_max = 0;
dx_start_left_max = 0;
dy_start_up_max = 0;
dy_start_down_max = 0;
accel0 = 0.0f;
accel1 = 0.0f;
last_press_direction_time = 0;
/* If we are not currently showing the onscreen
* keyboard or a message box, trigger a 'pointer
* down' event */
if (!osk_active && !messagebox_active)
{
point.x = x;
point.y = y;
/* Note: menu_input->ptr is meaningless here when
* using a touchscreen... */
point.ptr = menu_input->ptr;
point.cbs = cbs;
point.entry = entry;
point.action = action;
point.gesture = MENU_INPUT_GESTURE_NONE;
menu_driver_ctl(RARCH_MENU_CTL_POINTER_DOWN, &point);
ret = point.retcode;
}
}
else
{
/* Pointer is being held down
* (i.e. for more than one frame) */
float dpi = menu ? menu_input_get_dpi(menu, p_disp,
video_st->width, video_st->height) : 0.0f;
/* > Update deltas + acceleration & detect press direction
* Note: We only do this if the pointer has moved above
* a certain threshold - this requires dpi info */
if (dpi > 0.0f)
{
uint16_t dpi_threshold_drag =
(uint16_t)((dpi * MENU_INPUT_DPI_THRESHOLD_DRAG) + 0.5f);
int16_t dx_start = x - start_x;
int16_t dy_start = y - start_y;
uint16_t dx_start_abs = dx_start < 0 ? dx_start * -1 : dx_start;
uint16_t dy_start_abs = dy_start < 0 ? dy_start * -1 : dy_start;
if ((dx_start_abs > dpi_threshold_drag) ||
(dy_start_abs > dpi_threshold_drag))
{
uint16_t dpi_threshold_press_direction_min =
(uint16_t)((dpi * MENU_INPUT_DPI_THRESHOLD_PRESS_DIRECTION_MIN) + 0.5f);
uint16_t dpi_threshold_press_direction_max =
(uint16_t)((dpi * MENU_INPUT_DPI_THRESHOLD_PRESS_DIRECTION_MAX) + 0.5f);
uint16_t dpi_threshold_press_direction_tangent =
(uint16_t)((dpi * MENU_INPUT_DPI_THRESHOLD_PRESS_DIRECTION_TANGENT) + 0.5f);
enum menu_input_pointer_press_direction
press_direction = MENU_INPUT_PRESS_DIRECTION_NONE;
float press_direction_amplitude = 0.0f;
retro_time_t press_direction_delay = MENU_INPUT_PRESS_DIRECTION_DELAY_MAX;
/* Pointer has moved a sufficient distance to
* trigger a 'dragged' state */
menu_input->pointer.dragged = true;
/* Here we diverge:
* > If onscreen keyboard or a message box is
* active, pointer deltas, acceleration and
* press direction must be inhibited
* > If not, input is processed normally */
if (osk_active || messagebox_active)
{
/* Inhibit normal pointer input */
menu_input->pointer.dx = 0;
menu_input->pointer.dy = 0;
menu_input->pointer.y_accel = 0.0f;
menu_input->pointer.press_direction = MENU_INPUT_PRESS_DIRECTION_NONE;
accel0 = 0.0f;
accel1 = 0.0f;
attenuate_y_accel = false;
}
else
{
/* Assign current deltas */
menu_input->pointer.dx = x - last_x;
menu_input->pointer.dy = y - last_y;
/* Update maximum start->current deltas */
if (dx_start > 0)
dx_start_right_max = (dx_start_abs > dx_start_right_max) ?
dx_start_abs : dx_start_right_max;
else
dx_start_left_max = (dx_start_abs > dx_start_left_max) ?
dx_start_abs : dx_start_left_max;
if (dy_start > 0)
dy_start_down_max = (dy_start_abs > dy_start_down_max) ?
dy_start_abs : dy_start_down_max;
else
dy_start_up_max = (dy_start_abs > dy_start_up_max) ?
dy_start_abs : dy_start_up_max;
/* Magic numbers... */
menu_input->pointer.y_accel = (accel0 + accel1 + (float)menu_input->pointer.dy) / 3.0f;
accel0 = accel1;
accel1 = menu_input->pointer.y_accel;
/* Acceleration decays over time - but if the value
* has been set on this frame, attenuation should
* be skipped */
attenuate_y_accel = false;
/* Check if pointer is being held in a particular
* direction */
menu_input->pointer.press_direction = MENU_INPUT_PRESS_DIRECTION_NONE;
/* > Press directions are actually triggered as a pulse train,
* since a continuous direction prevents fine control in the
* context of menu actions (i.e. it would be the same
* as always holding down a cursor key all the time - too fast
* to control). We therefore apply a low pass filter, with
* a variable frequency based upon the distance the user has
* dragged the pointer */
/* > Horizontal */
if ((dx_start_abs >= dpi_threshold_press_direction_min) &&
(dy_start_abs < dpi_threshold_press_direction_tangent))
{
press_direction = (dx_start > 0) ?
MENU_INPUT_PRESS_DIRECTION_RIGHT : MENU_INPUT_PRESS_DIRECTION_LEFT;
/* Get effective amplitude of press direction offset */
press_direction_amplitude =
(float)(dx_start_abs - dpi_threshold_press_direction_min) /
(float)(dpi_threshold_press_direction_max - dpi_threshold_press_direction_min);
}
/* > Vertical */
else if ((dy_start_abs >= dpi_threshold_press_direction_min) &&
(dx_start_abs < dpi_threshold_press_direction_tangent))
{
press_direction = (dy_start > 0) ?
MENU_INPUT_PRESS_DIRECTION_DOWN : MENU_INPUT_PRESS_DIRECTION_UP;
/* Get effective amplitude of press direction offset */
press_direction_amplitude =
(float)(dy_start_abs - dpi_threshold_press_direction_min) /
(float)(dpi_threshold_press_direction_max - dpi_threshold_press_direction_min);
}
if (press_direction != MENU_INPUT_PRESS_DIRECTION_NONE)
{
/* > Update low pass filter frequency */
if (press_direction_amplitude > 1.0f)
press_direction_delay = MENU_INPUT_PRESS_DIRECTION_DELAY_MIN;
else
press_direction_delay = MENU_INPUT_PRESS_DIRECTION_DELAY_MIN +
((MENU_INPUT_PRESS_DIRECTION_DELAY_MAX - MENU_INPUT_PRESS_DIRECTION_DELAY_MIN)*
(1.0f - press_direction_amplitude));
/* > Apply low pass filter */
if (current_time - last_press_direction_time > press_direction_delay)
{
menu_input->pointer.press_direction = press_direction;
last_press_direction_time = current_time;
}
}
}
}
else
{
/* Pointer is stationary */
menu_input->pointer.dx = 0;
menu_input->pointer.dy = 0;
menu_input->pointer.press_direction = MENU_INPUT_PRESS_DIRECTION_NONE;
/* Standard behaviour (on Android, at least) is to stop
* scrolling when the user touches the screen. We should
* therefore 'reset' y acceleration whenever the pointer
* is stationary - with two caveats:
* - We only disable scrolling if the pointer *remains*
* stationary. If the pointer is held down then
* subsequently moves, normal scrolling should resume
* - Halting the scroll immediately produces a very
* unpleasant 'jerky' user experience. To avoid this,
* we add a small delay between detecting a pointer
* down event and forcing y acceleration to zero
* NOTE: Of course, we must also 'reset' y acceleration
* whenever the onscreen keyboard or a message box is
* shown */
if ((!menu_input->pointer.dragged &&
(menu_input->pointer.press_duration > MENU_INPUT_Y_ACCEL_RESET_DELAY)) ||
(osk_active || messagebox_active))
{
menu_input->pointer.y_accel = 0.0f;
accel0 = 0.0f;
accel1 = 0.0f;
attenuate_y_accel = false;
}
}
}
else
{
/* No dpi info - just fallback to zero... */
menu_input->pointer.dx = 0;
menu_input->pointer.dy = 0;
menu_input->pointer.y_accel = 0.0f;
menu_input->pointer.press_direction = MENU_INPUT_PRESS_DIRECTION_NONE;
accel0 = 0.0f;
accel1 = 0.0f;
attenuate_y_accel = false;
}
/* > Update remaining variables */
menu_input->pointer.press_duration = current_time - start_time;
last_x = x;
last_y = y;
}
}
else if (last_select_pressed)
{
/* Transition from select pressed to select unpressed */
int16_t x;
int16_t y;
menu_ctx_pointer_t point;
if (menu_input->pointer.dragged)
{
/* Pointer has moved.
* When using a touchscreen, releasing a press
* resets the x/y position - so cannot use
* current hardware x/y values. Instead, use
* previous position from last time that a
* press was active */
x = last_x;
y = last_y;
}
else
{
/* Pointer is considered stationary,
* so use start position */
x = start_x;
y = start_y;
}
point.x = x;
point.y = y;
point.ptr = menu_input->ptr;
point.cbs = cbs;
point.entry = entry;
point.action = action;
point.gesture = MENU_INPUT_GESTURE_NONE;
/* On screen keyboard overrides normal menu input... */
if (osk_active)
{
/* If pointer has been 'dragged', then it counts as
* a miss. Only register 'release' event if pointer
* has remained stationary */
if (!menu_input->pointer.dragged)
{
menu_driver_ctl(RARCH_MENU_CTL_OSK_PTR_AT_POS, &point);
if (point.retcode > -1)
{
bool show_osk_symbols = input_event_osk_show_symbol_pages(menu_st->driver_data);
input_st->osk_ptr = point.retcode;
input_event_osk_append(
&input_st->keyboard_line,
&input_st->osk_idx,
&input_st->osk_last_codepoint,
&input_st->osk_last_codepoint_len,
point.retcode,
show_osk_symbols,
input_st->osk_grid[input_st->osk_ptr]);
}
}
}
/* Message boxes override normal menu input...
* > If a message box is shown, any kind of pointer
* gesture should close it */
else if (messagebox_active)
menu_input_pointer_close_messagebox(
menu_st);
/* Normal menu input */
else
{
/* Detect gesture type */
if (!menu_input->pointer.dragged)
{
/* Pointer hasn't moved - check press duration */
if (menu_input->pointer.press_duration
< MENU_INPUT_PRESS_TIME_SHORT)
point.gesture = MENU_INPUT_GESTURE_TAP;
else if (menu_input->pointer.press_duration
< MENU_INPUT_PRESS_TIME_LONG)
point.gesture = MENU_INPUT_GESTURE_SHORT_PRESS;
else
point.gesture = MENU_INPUT_GESTURE_LONG_PRESS;
}
else
{
/* Pointer has moved - check if this is a swipe */
float dpi = menu ? menu_input_get_dpi(menu, p_disp,
video_st->width, video_st->height) : 0.0f;
if ((dpi > 0.0f)
&&
(menu_input->pointer.press_duration <
MENU_INPUT_SWIPE_TIMEOUT))
{
uint16_t dpi_threshold_swipe =
(uint16_t)((dpi * MENU_INPUT_DPI_THRESHOLD_SWIPE) + 0.5f);
uint16_t dpi_threshold_swipe_tangent =
(uint16_t)((dpi * MENU_INPUT_DPI_THRESHOLD_SWIPE_TANGENT) + 0.5f);
int16_t dx_start = x - start_x;
int16_t dy_start = y - start_y;
uint16_t dx_start_right_final = 0;
uint16_t dx_start_left_final = 0;
uint16_t dy_start_up_final = 0;
uint16_t dy_start_down_final = 0;
/* Get final deltas */
if (dx_start > 0)
dx_start_right_final = (uint16_t)dx_start;
else
dx_start_left_final = (uint16_t)
(dx_start * -1);
if (dy_start > 0)
dy_start_down_final = (uint16_t)dy_start;
else
dy_start_up_final = (uint16_t)
(dy_start * -1);
/* Swipe right */
if ( (dx_start_right_final > dpi_threshold_swipe)
&& (dx_start_left_max < dpi_threshold_swipe_tangent)
&& (dy_start_up_max < dpi_threshold_swipe_tangent)
&& (dy_start_down_max < dpi_threshold_swipe_tangent)
)
point.gesture = MENU_INPUT_GESTURE_SWIPE_RIGHT;
/* Swipe left */
else if (
(dx_start_right_max < dpi_threshold_swipe_tangent)
&& (dx_start_left_final > dpi_threshold_swipe)
&& (dy_start_up_max < dpi_threshold_swipe_tangent)
&& (dy_start_down_max < dpi_threshold_swipe_tangent)
)
point.gesture = MENU_INPUT_GESTURE_SWIPE_LEFT;
/* Swipe up */
else if (
(dx_start_right_max < dpi_threshold_swipe_tangent)
&& (dx_start_left_max < dpi_threshold_swipe_tangent)
&& (dy_start_up_final > dpi_threshold_swipe)
&& (dy_start_down_max < dpi_threshold_swipe_tangent)
)
point.gesture = MENU_INPUT_GESTURE_SWIPE_UP;
/* Swipe down */
else if (
(dx_start_right_max < dpi_threshold_swipe_tangent)
&& (dx_start_left_max < dpi_threshold_swipe_tangent)
&& (dy_start_up_max < dpi_threshold_swipe_tangent)
&& (dy_start_down_final > dpi_threshold_swipe)
)
point.gesture = MENU_INPUT_GESTURE_SWIPE_DOWN;
}
}
/* Trigger a 'pointer up' event */
menu_driver_ctl(RARCH_MENU_CTL_POINTER_UP, &point);
ret = point.retcode;
}
/* Reset variables */
start_x = 0;
start_y = 0;
last_x = 0;
last_y = 0;
dx_start_right_max = 0;
dx_start_left_max = 0;
dy_start_up_max = 0;
dy_start_down_max = 0;
last_press_direction_time = 0;
menu_input->pointer.press_duration = 0;
menu_input->pointer.press_direction = MENU_INPUT_PRESS_DIRECTION_NONE;
menu_input->pointer.dx = 0;
menu_input->pointer.dy = 0;
menu_input->pointer.dragged = false;
}
}
/* Adjust acceleration
* > If acceleration has not been set on this frame,
* apply normal attenuation */
if (attenuate_y_accel)
menu_input->pointer.y_accel *= MENU_INPUT_Y_ACCEL_DECAY_FACTOR;
/* If select has been released, disable any existing
* select inhibit */
if (!pointer_hw_state->select_pressed)
menu_input->select_inhibit = false;
/* Cancel */
if ( !menu_input->cancel_inhibit
&& pointer_hw_state->cancel_pressed
&& !last_cancel_pressed)
{
/* If currently showing a message box, close it */
if (messagebox_active)
menu_input_pointer_close_messagebox(menu_st);
/* If onscreen keyboard is shown, send a 'backspace' */
else if (osk_active)
input_keyboard_event(true, '\x7f', '\x7f',
0, RETRO_DEVICE_KEYBOARD);
/* ...otherwise, invoke standard MENU_ACTION_CANCEL
* action */
else
{
size_t selection = menu_st->selection_ptr;
ret = menu_entry_action(entry, selection, MENU_ACTION_CANCEL);
}
}
/* If cancel has been released, disable any existing
* cancel inhibit */
if (!pointer_hw_state->cancel_pressed)
menu_input->cancel_inhibit = false;
if (!messagebox_active)
{
/* Up/Down
* > Note 1: These always correspond to a mouse wheel, which
* handles differently from other inputs - i.e. we don't
* want a 'last pressed' check
* > Note 2: If a message box is currently shown, must
* inhibit input */
/* > Up */
if (pointer_hw_state->up_pressed)
{
size_t selection = menu_st->selection_ptr;
ret = menu_entry_action(
entry, selection, MENU_ACTION_UP);
}
/* > Down */
if (pointer_hw_state->down_pressed)
{
size_t selection = menu_st->selection_ptr;
ret = menu_entry_action(
entry, selection, MENU_ACTION_DOWN);
}
/* Left/Right
* > Note 1: These also always correspond to a mouse wheel...
* In this case, it's a mouse wheel *tilt* operation, which
* is incredibly annoying because holding a tilt direction
* rapidly toggles the input state. The repeat speed is so
* high that any sort of useable control is impossible - so
* we have to apply a 'low pass' filter by ignoring inputs
* that occur below a certain frequency...
* > Note 2: If a message box is currently shown, must
* inhibit input */
/* > Left */
if ( pointer_hw_state->left_pressed
&& !last_left_pressed)
{
if (current_time - last_left_action_time
> MENU_INPUT_HORIZ_WHEEL_DELAY)
{
size_t selection = menu_st->selection_ptr;
last_left_action_time = current_time;
ret = menu_entry_action(
entry, selection, MENU_ACTION_LEFT);
}
}
/* > Right */
if (
pointer_hw_state->right_pressed
&& !last_right_pressed)
{
if (current_time - last_right_action_time
> MENU_INPUT_HORIZ_WHEEL_DELAY)
{
size_t selection = menu_st->selection_ptr;
last_right_action_time = current_time;
ret = menu_entry_action(
entry, selection, MENU_ACTION_RIGHT);
}
}
}
last_select_pressed = pointer_hw_state->select_pressed;
last_cancel_pressed = pointer_hw_state->cancel_pressed;
last_left_pressed = pointer_hw_state->left_pressed;
last_right_pressed = pointer_hw_state->right_pressed;
return ret;
}
int menu_input_post_iterate(
gfx_display_t *p_disp,
struct menu_state *menu_st,
unsigned action,
retro_time_t current_time)
{
menu_entry_t entry;
menu_list_t *menu_list = menu_st->entries.list;
file_list_t *selection_buf = menu_list ? MENU_LIST_GET_SELECTION(menu_list, (unsigned)0) : NULL;
size_t selection = menu_st->selection_ptr;
menu_file_list_cbs_t *cbs = selection_buf ?
(menu_file_list_cbs_t*)selection_buf->list[selection].actiondata
: NULL;
MENU_ENTRY_INIT(entry);
/* Note: If menu_input_pointer_post_iterate() is
* modified, will have to verify that these
* parameters remain unused... */
entry.rich_label_enabled = false;
entry.value_enabled = false;
entry.sublabel_enabled = false;
menu_entry_get(&entry, 0, selection, NULL, false);
return menu_input_pointer_post_iterate(p_disp,
current_time, cbs, &entry, action);
}

View File

@ -891,6 +891,13 @@ unsigned menu_event(
input_bits_t *p_trigger_input,
bool display_kb);
int menu_input_post_iterate(
gfx_display_t *p_disp,
struct menu_state *menu_st,
unsigned action,
retro_time_t current_time);
extern const menu_ctx_driver_t *menu_ctx_drivers[];
RETRO_END_DECLS

View File

@ -27,6 +27,7 @@
#include "menu_defines.h"
#include "../input/input_types.h"
#include "../input/input_driver.h"
#include "../gfx/gfx_display.h"
#include "../performance_counters.h"
RETRO_BEGIN_DECLS

View File

@ -304,7 +304,6 @@ struct aspect_ratio_elem aspectratio_lut[ASPECT_RATIO_END] = {
#ifdef HAVE_DISCORD
bool discord_is_inited = false;
#endif
uint64_t lifecycle_state = 0;
unsigned subsystem_current_count = 0;
struct retro_keybind input_config_binds[MAX_USERS][RARCH_BIND_LIST_END];
struct retro_keybind input_autoconf_binds[MAX_USERS][RARCH_BIND_LIST_END];
@ -837,7 +836,7 @@ static int generic_menu_iterate(
if (menu_input->pointer.type == MENU_POINTER_DISABLED)
ret = 0;
else
ret = menu_input_post_iterate(p_rarch, p_disp, menu_st, action,
ret = menu_input_post_iterate(p_disp, menu_st, action,
current_time);
menu_input_set_pointer_visibility(
&menu_st->input_pointer_hw_state,
@ -858,7 +857,7 @@ int generic_menu_entry_action(
const menu_ctx_driver_t
*menu_driver_ctx = menu_st->driver_ctx;
menu_handle_t *menu = menu_st->driver_data;
settings_t *settings = p_rarch->configuration_settings;
settings_t *settings = config_get_ptr();
void *menu_userdata = menu_st->userdata;
bool wraparound_enable = settings->bools.menu_navigation_wraparound_enable;
size_t scroll_accel = menu_st->scroll.acceleration;
@ -13989,765 +13988,6 @@ const char* config_get_input_driver_options(void)
}
/* MENU INPUT */
#ifdef HAVE_MENU
static int menu_input_pointer_post_iterate(
struct rarch_state *p_rarch,
gfx_display_t *p_disp,
retro_time_t current_time,
menu_file_list_cbs_t *cbs,
menu_entry_t *entry, unsigned action)
{
static retro_time_t start_time = 0;
static int16_t start_x = 0;
static int16_t start_y = 0;
static int16_t last_x = 0;
static int16_t last_y = 0;
static uint16_t dx_start_right_max = 0;
static uint16_t dx_start_left_max = 0;
static uint16_t dy_start_up_max = 0;
static uint16_t dy_start_down_max = 0;
static bool last_select_pressed = false;
static bool last_cancel_pressed = false;
static bool last_left_pressed = false;
static bool last_right_pressed = false;
static retro_time_t last_left_action_time = 0;
static retro_time_t last_right_action_time = 0;
static retro_time_t last_press_direction_time = 0;
bool attenuate_y_accel = true;
bool osk_active = menu_input_dialog_get_display_kb();
bool messagebox_active = false;
int ret = 0;
struct menu_state *menu_st = menu_state_get_ptr();
menu_input_pointer_hw_state_t *pointer_hw_state = &menu_st->input_pointer_hw_state;
menu_input_t *menu_input = &menu_st->input_state;
menu_handle_t *menu = menu_st->driver_data;
video_driver_state_t *video_st = video_state_get_ptr();
input_driver_state_t *input_st = input_state_get_ptr();
/* Check whether a message box is currently
* being shown
* > Note: This ignores input bind dialogs,
* since input binding overrides normal input
* and must be handled separately... */
if (menu)
messagebox_active = BIT64_GET(
menu->state, MENU_STATE_RENDER_MESSAGEBOX) &&
!string_is_empty(menu->menu_state_msg);
/* If onscreen keyboard is shown and we currently have
* active mouse input, highlight key under mouse cursor */
if (osk_active &&
(menu_input->pointer.type == MENU_POINTER_MOUSE) &&
pointer_hw_state->active)
{
menu_ctx_pointer_t point;
point.x = pointer_hw_state->x;
point.y = pointer_hw_state->y;
point.ptr = 0;
point.cbs = NULL;
point.entry = NULL;
point.action = 0;
point.gesture = MENU_INPUT_GESTURE_NONE;
point.retcode = 0;
menu_driver_ctl(RARCH_MENU_CTL_OSK_PTR_AT_POS, &point);
if (point.retcode > -1)
input_st->osk_ptr = point.retcode;
}
/* Select + X/Y position */
if (!menu_input->select_inhibit)
{
if (pointer_hw_state->select_pressed)
{
int16_t x = pointer_hw_state->x;
int16_t y = pointer_hw_state->y;
static float accel0 = 0.0f;
static float accel1 = 0.0f;
/* Transition from select unpressed to select pressed */
if (!last_select_pressed)
{
menu_ctx_pointer_t point;
/* Initialise variables */
start_time = current_time;
start_x = x;
start_y = y;
last_x = x;
last_y = y;
dx_start_right_max = 0;
dx_start_left_max = 0;
dy_start_up_max = 0;
dy_start_down_max = 0;
accel0 = 0.0f;
accel1 = 0.0f;
last_press_direction_time = 0;
/* If we are not currently showing the onscreen
* keyboard or a message box, trigger a 'pointer
* down' event */
if (!osk_active && !messagebox_active)
{
point.x = x;
point.y = y;
/* Note: menu_input->ptr is meaningless here when
* using a touchscreen... */
point.ptr = menu_input->ptr;
point.cbs = cbs;
point.entry = entry;
point.action = action;
point.gesture = MENU_INPUT_GESTURE_NONE;
menu_driver_ctl(RARCH_MENU_CTL_POINTER_DOWN, &point);
ret = point.retcode;
}
}
else
{
/* Pointer is being held down
* (i.e. for more than one frame) */
float dpi = menu ? menu_input_get_dpi(menu, p_disp,
video_st->width, video_st->height) : 0.0f;
/* > Update deltas + acceleration & detect press direction
* Note: We only do this if the pointer has moved above
* a certain threshold - this requires dpi info */
if (dpi > 0.0f)
{
uint16_t dpi_threshold_drag =
(uint16_t)((dpi * MENU_INPUT_DPI_THRESHOLD_DRAG) + 0.5f);
int16_t dx_start = x - start_x;
int16_t dy_start = y - start_y;
uint16_t dx_start_abs = dx_start < 0 ? dx_start * -1 : dx_start;
uint16_t dy_start_abs = dy_start < 0 ? dy_start * -1 : dy_start;
if ((dx_start_abs > dpi_threshold_drag) ||
(dy_start_abs > dpi_threshold_drag))
{
uint16_t dpi_threshold_press_direction_min =
(uint16_t)((dpi * MENU_INPUT_DPI_THRESHOLD_PRESS_DIRECTION_MIN) + 0.5f);
uint16_t dpi_threshold_press_direction_max =
(uint16_t)((dpi * MENU_INPUT_DPI_THRESHOLD_PRESS_DIRECTION_MAX) + 0.5f);
uint16_t dpi_threshold_press_direction_tangent =
(uint16_t)((dpi * MENU_INPUT_DPI_THRESHOLD_PRESS_DIRECTION_TANGENT) + 0.5f);
enum menu_input_pointer_press_direction
press_direction = MENU_INPUT_PRESS_DIRECTION_NONE;
float press_direction_amplitude = 0.0f;
retro_time_t press_direction_delay = MENU_INPUT_PRESS_DIRECTION_DELAY_MAX;
/* Pointer has moved a sufficient distance to
* trigger a 'dragged' state */
menu_input->pointer.dragged = true;
/* Here we diverge:
* > If onscreen keyboard or a message box is
* active, pointer deltas, acceleration and
* press direction must be inhibited
* > If not, input is processed normally */
if (osk_active || messagebox_active)
{
/* Inhibit normal pointer input */
menu_input->pointer.dx = 0;
menu_input->pointer.dy = 0;
menu_input->pointer.y_accel = 0.0f;
menu_input->pointer.press_direction = MENU_INPUT_PRESS_DIRECTION_NONE;
accel0 = 0.0f;
accel1 = 0.0f;
attenuate_y_accel = false;
}
else
{
/* Assign current deltas */
menu_input->pointer.dx = x - last_x;
menu_input->pointer.dy = y - last_y;
/* Update maximum start->current deltas */
if (dx_start > 0)
dx_start_right_max = (dx_start_abs > dx_start_right_max) ?
dx_start_abs : dx_start_right_max;
else
dx_start_left_max = (dx_start_abs > dx_start_left_max) ?
dx_start_abs : dx_start_left_max;
if (dy_start > 0)
dy_start_down_max = (dy_start_abs > dy_start_down_max) ?
dy_start_abs : dy_start_down_max;
else
dy_start_up_max = (dy_start_abs > dy_start_up_max) ?
dy_start_abs : dy_start_up_max;
/* Magic numbers... */
menu_input->pointer.y_accel = (accel0 + accel1 + (float)menu_input->pointer.dy) / 3.0f;
accel0 = accel1;
accel1 = menu_input->pointer.y_accel;
/* Acceleration decays over time - but if the value
* has been set on this frame, attenuation should
* be skipped */
attenuate_y_accel = false;
/* Check if pointer is being held in a particular
* direction */
menu_input->pointer.press_direction = MENU_INPUT_PRESS_DIRECTION_NONE;
/* > Press directions are actually triggered as a pulse train,
* since a continuous direction prevents fine control in the
* context of menu actions (i.e. it would be the same
* as always holding down a cursor key all the time - too fast
* to control). We therefore apply a low pass filter, with
* a variable frequency based upon the distance the user has
* dragged the pointer */
/* > Horizontal */
if ((dx_start_abs >= dpi_threshold_press_direction_min) &&
(dy_start_abs < dpi_threshold_press_direction_tangent))
{
press_direction = (dx_start > 0) ?
MENU_INPUT_PRESS_DIRECTION_RIGHT : MENU_INPUT_PRESS_DIRECTION_LEFT;
/* Get effective amplitude of press direction offset */
press_direction_amplitude =
(float)(dx_start_abs - dpi_threshold_press_direction_min) /
(float)(dpi_threshold_press_direction_max - dpi_threshold_press_direction_min);
}
/* > Vertical */
else if ((dy_start_abs >= dpi_threshold_press_direction_min) &&
(dx_start_abs < dpi_threshold_press_direction_tangent))
{
press_direction = (dy_start > 0) ?
MENU_INPUT_PRESS_DIRECTION_DOWN : MENU_INPUT_PRESS_DIRECTION_UP;
/* Get effective amplitude of press direction offset */
press_direction_amplitude =
(float)(dy_start_abs - dpi_threshold_press_direction_min) /
(float)(dpi_threshold_press_direction_max - dpi_threshold_press_direction_min);
}
if (press_direction != MENU_INPUT_PRESS_DIRECTION_NONE)
{
/* > Update low pass filter frequency */
if (press_direction_amplitude > 1.0f)
press_direction_delay = MENU_INPUT_PRESS_DIRECTION_DELAY_MIN;
else
press_direction_delay = MENU_INPUT_PRESS_DIRECTION_DELAY_MIN +
((MENU_INPUT_PRESS_DIRECTION_DELAY_MAX - MENU_INPUT_PRESS_DIRECTION_DELAY_MIN)*
(1.0f - press_direction_amplitude));
/* > Apply low pass filter */
if (current_time - last_press_direction_time > press_direction_delay)
{
menu_input->pointer.press_direction = press_direction;
last_press_direction_time = current_time;
}
}
}
}
else
{
/* Pointer is stationary */
menu_input->pointer.dx = 0;
menu_input->pointer.dy = 0;
menu_input->pointer.press_direction = MENU_INPUT_PRESS_DIRECTION_NONE;
/* Standard behaviour (on Android, at least) is to stop
* scrolling when the user touches the screen. We should
* therefore 'reset' y acceleration whenever the pointer
* is stationary - with two caveats:
* - We only disable scrolling if the pointer *remains*
* stationary. If the pointer is held down then
* subsequently moves, normal scrolling should resume
* - Halting the scroll immediately produces a very
* unpleasant 'jerky' user experience. To avoid this,
* we add a small delay between detecting a pointer
* down event and forcing y acceleration to zero
* NOTE: Of course, we must also 'reset' y acceleration
* whenever the onscreen keyboard or a message box is
* shown */
if ((!menu_input->pointer.dragged &&
(menu_input->pointer.press_duration > MENU_INPUT_Y_ACCEL_RESET_DELAY)) ||
(osk_active || messagebox_active))
{
menu_input->pointer.y_accel = 0.0f;
accel0 = 0.0f;
accel1 = 0.0f;
attenuate_y_accel = false;
}
}
}
else
{
/* No dpi info - just fallback to zero... */
menu_input->pointer.dx = 0;
menu_input->pointer.dy = 0;
menu_input->pointer.y_accel = 0.0f;
menu_input->pointer.press_direction = MENU_INPUT_PRESS_DIRECTION_NONE;
accel0 = 0.0f;
accel1 = 0.0f;
attenuate_y_accel = false;
}
/* > Update remaining variables */
menu_input->pointer.press_duration = current_time - start_time;
last_x = x;
last_y = y;
}
}
else if (last_select_pressed)
{
/* Transition from select pressed to select unpressed */
int16_t x;
int16_t y;
menu_ctx_pointer_t point;
if (menu_input->pointer.dragged)
{
/* Pointer has moved.
* When using a touchscreen, releasing a press
* resets the x/y position - so cannot use
* current hardware x/y values. Instead, use
* previous position from last time that a
* press was active */
x = last_x;
y = last_y;
}
else
{
/* Pointer is considered stationary,
* so use start position */
x = start_x;
y = start_y;
}
point.x = x;
point.y = y;
point.ptr = menu_input->ptr;
point.cbs = cbs;
point.entry = entry;
point.action = action;
point.gesture = MENU_INPUT_GESTURE_NONE;
/* On screen keyboard overrides normal menu input... */
if (osk_active)
{
/* If pointer has been 'dragged', then it counts as
* a miss. Only register 'release' event if pointer
* has remained stationary */
if (!menu_input->pointer.dragged)
{
menu_driver_ctl(RARCH_MENU_CTL_OSK_PTR_AT_POS, &point);
if (point.retcode > -1)
{
bool show_osk_symbols = input_event_osk_show_symbol_pages(menu_st->driver_data);
input_st->osk_ptr = point.retcode;
input_event_osk_append(
&input_st->keyboard_line,
&input_st->osk_idx,
&input_st->osk_last_codepoint,
&input_st->osk_last_codepoint_len,
point.retcode,
show_osk_symbols,
input_st->osk_grid[input_st->osk_ptr]);
}
}
}
/* Message boxes override normal menu input...
* > If a message box is shown, any kind of pointer
* gesture should close it */
else if (messagebox_active)
menu_input_pointer_close_messagebox(
menu_st);
/* Normal menu input */
else
{
/* Detect gesture type */
if (!menu_input->pointer.dragged)
{
/* Pointer hasn't moved - check press duration */
if (menu_input->pointer.press_duration
< MENU_INPUT_PRESS_TIME_SHORT)
point.gesture = MENU_INPUT_GESTURE_TAP;
else if (menu_input->pointer.press_duration
< MENU_INPUT_PRESS_TIME_LONG)
point.gesture = MENU_INPUT_GESTURE_SHORT_PRESS;
else
point.gesture = MENU_INPUT_GESTURE_LONG_PRESS;
}
else
{
/* Pointer has moved - check if this is a swipe */
float dpi = menu ? menu_input_get_dpi(menu, p_disp,
video_st->width, video_st->height) : 0.0f;
if ((dpi > 0.0f)
&&
(menu_input->pointer.press_duration <
MENU_INPUT_SWIPE_TIMEOUT))
{
uint16_t dpi_threshold_swipe =
(uint16_t)((dpi * MENU_INPUT_DPI_THRESHOLD_SWIPE) + 0.5f);
uint16_t dpi_threshold_swipe_tangent =
(uint16_t)((dpi * MENU_INPUT_DPI_THRESHOLD_SWIPE_TANGENT) + 0.5f);
int16_t dx_start = x - start_x;
int16_t dy_start = y - start_y;
uint16_t dx_start_right_final = 0;
uint16_t dx_start_left_final = 0;
uint16_t dy_start_up_final = 0;
uint16_t dy_start_down_final = 0;
/* Get final deltas */
if (dx_start > 0)
dx_start_right_final = (uint16_t)dx_start;
else
dx_start_left_final = (uint16_t)
(dx_start * -1);
if (dy_start > 0)
dy_start_down_final = (uint16_t)dy_start;
else
dy_start_up_final = (uint16_t)
(dy_start * -1);
/* Swipe right */
if ( (dx_start_right_final > dpi_threshold_swipe)
&& (dx_start_left_max < dpi_threshold_swipe_tangent)
&& (dy_start_up_max < dpi_threshold_swipe_tangent)
&& (dy_start_down_max < dpi_threshold_swipe_tangent)
)
point.gesture = MENU_INPUT_GESTURE_SWIPE_RIGHT;
/* Swipe left */
else if (
(dx_start_right_max < dpi_threshold_swipe_tangent)
&& (dx_start_left_final > dpi_threshold_swipe)
&& (dy_start_up_max < dpi_threshold_swipe_tangent)
&& (dy_start_down_max < dpi_threshold_swipe_tangent)
)
point.gesture = MENU_INPUT_GESTURE_SWIPE_LEFT;
/* Swipe up */
else if (
(dx_start_right_max < dpi_threshold_swipe_tangent)
&& (dx_start_left_max < dpi_threshold_swipe_tangent)
&& (dy_start_up_final > dpi_threshold_swipe)
&& (dy_start_down_max < dpi_threshold_swipe_tangent)
)
point.gesture = MENU_INPUT_GESTURE_SWIPE_UP;
/* Swipe down */
else if (
(dx_start_right_max < dpi_threshold_swipe_tangent)
&& (dx_start_left_max < dpi_threshold_swipe_tangent)
&& (dy_start_up_max < dpi_threshold_swipe_tangent)
&& (dy_start_down_final > dpi_threshold_swipe)
)
point.gesture = MENU_INPUT_GESTURE_SWIPE_DOWN;
}
}
/* Trigger a 'pointer up' event */
menu_driver_ctl(RARCH_MENU_CTL_POINTER_UP, &point);
ret = point.retcode;
}
/* Reset variables */
start_x = 0;
start_y = 0;
last_x = 0;
last_y = 0;
dx_start_right_max = 0;
dx_start_left_max = 0;
dy_start_up_max = 0;
dy_start_down_max = 0;
last_press_direction_time = 0;
menu_input->pointer.press_duration = 0;
menu_input->pointer.press_direction = MENU_INPUT_PRESS_DIRECTION_NONE;
menu_input->pointer.dx = 0;
menu_input->pointer.dy = 0;
menu_input->pointer.dragged = false;
}
}
/* Adjust acceleration
* > If acceleration has not been set on this frame,
* apply normal attenuation */
if (attenuate_y_accel)
menu_input->pointer.y_accel *= MENU_INPUT_Y_ACCEL_DECAY_FACTOR;
/* If select has been released, disable any existing
* select inhibit */
if (!pointer_hw_state->select_pressed)
menu_input->select_inhibit = false;
/* Cancel */
if ( !menu_input->cancel_inhibit
&& pointer_hw_state->cancel_pressed
&& !last_cancel_pressed)
{
/* If currently showing a message box, close it */
if (messagebox_active)
menu_input_pointer_close_messagebox(menu_st);
/* If onscreen keyboard is shown, send a 'backspace' */
else if (osk_active)
input_keyboard_event(true, '\x7f', '\x7f',
0, RETRO_DEVICE_KEYBOARD);
/* ...otherwise, invoke standard MENU_ACTION_CANCEL
* action */
else
{
size_t selection = menu_st->selection_ptr;
ret = menu_entry_action(entry, selection, MENU_ACTION_CANCEL);
}
}
/* If cancel has been released, disable any existing
* cancel inhibit */
if (!pointer_hw_state->cancel_pressed)
menu_input->cancel_inhibit = false;
if (!messagebox_active)
{
/* Up/Down
* > Note 1: These always correspond to a mouse wheel, which
* handles differently from other inputs - i.e. we don't
* want a 'last pressed' check
* > Note 2: If a message box is currently shown, must
* inhibit input */
/* > Up */
if (pointer_hw_state->up_pressed)
{
size_t selection = menu_st->selection_ptr;
ret = menu_entry_action(
entry, selection, MENU_ACTION_UP);
}
/* > Down */
if (pointer_hw_state->down_pressed)
{
size_t selection = menu_st->selection_ptr;
ret = menu_entry_action(
entry, selection, MENU_ACTION_DOWN);
}
/* Left/Right
* > Note 1: These also always correspond to a mouse wheel...
* In this case, it's a mouse wheel *tilt* operation, which
* is incredibly annoying because holding a tilt direction
* rapidly toggles the input state. The repeat speed is so
* high that any sort of useable control is impossible - so
* we have to apply a 'low pass' filter by ignoring inputs
* that occur below a certain frequency...
* > Note 2: If a message box is currently shown, must
* inhibit input */
/* > Left */
if ( pointer_hw_state->left_pressed
&& !last_left_pressed)
{
if (current_time - last_left_action_time
> MENU_INPUT_HORIZ_WHEEL_DELAY)
{
size_t selection = menu_st->selection_ptr;
last_left_action_time = current_time;
ret = menu_entry_action(
entry, selection, MENU_ACTION_LEFT);
}
}
/* > Right */
if (
pointer_hw_state->right_pressed
&& !last_right_pressed)
{
if (current_time - last_right_action_time
> MENU_INPUT_HORIZ_WHEEL_DELAY)
{
size_t selection = menu_st->selection_ptr;
last_right_action_time = current_time;
ret = menu_entry_action(
entry, selection, MENU_ACTION_RIGHT);
}
}
}
last_select_pressed = pointer_hw_state->select_pressed;
last_cancel_pressed = pointer_hw_state->cancel_pressed;
last_left_pressed = pointer_hw_state->left_pressed;
last_right_pressed = pointer_hw_state->right_pressed;
return ret;
}
static int menu_input_post_iterate(
struct rarch_state *p_rarch,
gfx_display_t *p_disp,
struct menu_state *menu_st,
unsigned action,
retro_time_t current_time)
{
menu_entry_t entry;
menu_list_t *menu_list = menu_st->entries.list;
file_list_t *selection_buf = menu_list ? MENU_LIST_GET_SELECTION(menu_list, (unsigned)0) : NULL;
size_t selection = menu_st->selection_ptr;
menu_file_list_cbs_t *cbs = selection_buf ?
(menu_file_list_cbs_t*)selection_buf->list[selection].actiondata
: NULL;
MENU_ENTRY_INIT(entry);
/* Note: If menu_input_pointer_post_iterate() is
* modified, will have to verify that these
* parameters remain unused... */
entry.rich_label_enabled = false;
entry.value_enabled = false;
entry.sublabel_enabled = false;
menu_entry_get(&entry, 0, selection, NULL, false);
return menu_input_pointer_post_iterate(p_rarch, p_disp,
current_time, cbs, &entry, action);
}
#endif
/**
* input_keys_pressed:
*
* Grab an input sample for this frame.
*
* Returns: Input sample containing a mask of all pressed keys.
*/
static void input_keys_pressed(
unsigned port,
bool is_menu,
int input_hotkey_block_delay,
input_bits_t *p_new_state,
const struct retro_keybind **binds,
const struct retro_keybind *binds_norm,
const struct retro_keybind *binds_auto,
const input_device_driver_t *joypad,
const input_device_driver_t *sec_joypad,
rarch_joypad_info_t *joypad_info)
{
unsigned i;
input_driver_state_t *input_st = input_state_get_ptr();
if (CHECK_INPUT_DRIVER_BLOCK_HOTKEY(binds_norm, binds_auto))
{
if ( input_state_wrap(
input_st->current_driver,
input_st->current_data,
input_st->primary_joypad,
sec_joypad,
joypad_info,
&binds[port],
input_st->keyboard_mapping_blocked,
port, RETRO_DEVICE_JOYPAD, 0,
RARCH_ENABLE_HOTKEY))
{
if (input_st->input_hotkey_block_counter < input_hotkey_block_delay)
input_st->input_hotkey_block_counter++;
else
input_st->block_libretro_input = true;
}
else
{
input_st->input_hotkey_block_counter = 0;
input_st->block_hotkey = true;
}
}
if ( !is_menu
&& binds[port][RARCH_GAME_FOCUS_TOGGLE].valid)
{
const struct retro_keybind *focus_binds_auto =
&input_autoconf_binds[port][RARCH_GAME_FOCUS_TOGGLE];
const struct retro_keybind *focus_normal =
&binds[port][RARCH_GAME_FOCUS_TOGGLE];
/* Allows rarch_focus_toggle hotkey to still work
* even though every hotkey is blocked */
if (CHECK_INPUT_DRIVER_BLOCK_HOTKEY(
focus_normal, focus_binds_auto))
{
if (input_state_wrap(
input_st->current_driver,
input_st->current_data,
input_st->primary_joypad,
sec_joypad,
joypad_info,
&binds[port],
input_st->keyboard_mapping_blocked,
port,
RETRO_DEVICE_JOYPAD, 0, RARCH_GAME_FOCUS_TOGGLE))
input_st->block_hotkey = false;
}
}
{
int16_t ret = 0;
/* Check the libretro input first */
if (!input_st->block_libretro_input)
ret = input_state_wrap(
input_st->current_driver,
input_st->current_data,
input_st->primary_joypad,
sec_joypad,
joypad_info, &binds[port],
input_st->keyboard_mapping_blocked,
port, RETRO_DEVICE_JOYPAD, 0,
RETRO_DEVICE_ID_JOYPAD_MASK);
for (i = 0; i < RARCH_FIRST_META_KEY; i++)
{
if (
(ret & (UINT64_C(1) << i)) ||
input_keys_pressed_other_sources(input_st,
i, p_new_state))
{
BIT256_SET_PTR(p_new_state, i);
}
}
}
/* Check the hotkeys */
if (input_st->block_hotkey)
{
for (i = RARCH_FIRST_META_KEY; i < RARCH_BIND_LIST_END; i++)
{
if (
BIT64_GET(lifecycle_state, i)
|| input_keys_pressed_other_sources(input_st,
i, p_new_state))
{
BIT256_SET_PTR(p_new_state, i);
}
}
}
else
{
for (i = RARCH_FIRST_META_KEY; i < RARCH_BIND_LIST_END; i++)
{
bool bit_pressed = binds[port][i].valid
&& input_state_wrap(
input_st->current_driver,
input_st->current_data,
input_st->primary_joypad,
sec_joypad,
joypad_info,
&binds[port],
input_st->keyboard_mapping_blocked,
port, RETRO_DEVICE_JOYPAD, 0, i);
if ( bit_pressed
|| BIT64_GET(lifecycle_state, i)
|| input_keys_pressed_other_sources(input_st,
i, p_new_state))
{
BIT256_SET_PTR(p_new_state, i);
}
}
}
}
/**
* config_get_joypad_driver_options:

View File

@ -122,28 +122,6 @@ input_st->bsv_movie_state.eof_exit)
old_pressed3 = pressed3; \
}
/**
* check_input_driver_block_hotkey:
*
* Checks if 'hotkey enable' key is pressed.
*
* If we haven't bound anything to this,
* always allow hotkeys.
* If we hold ENABLE_HOTKEY button, block all libretro input to allow
* hotkeys to be bound to same keys as RetroPad.
**/
#define CHECK_INPUT_DRIVER_BLOCK_HOTKEY(normal_bind, autoconf_bind) \
( \
(((normal_bind)->key != RETROK_UNKNOWN) \
|| ((normal_bind)->mbutton != NO_BTN) \
|| ((normal_bind)->joykey != NO_BTN) \
|| ((normal_bind)->joyaxis != AXIS_NONE) \
|| ((autoconf_bind)->key != RETROK_UNKNOWN) \
|| ((autoconf_bind)->joykey != NO_BTN) \
|| ((autoconf_bind)->joyaxis != AXIS_NONE)) \
)
#define INHERIT_JOYAXIS(binds) (((binds)[x_plus].joyaxis == (binds)[x_minus].joyaxis) || ( (binds)[y_plus].joyaxis == (binds)[y_minus].joyaxis))
#define CDN_URL "https://cdn.discordapp.com/avatars"

View File

@ -99,15 +99,6 @@ static bool accessibility_speak_priority(
const char* speak_text, int priority);
#endif
#ifdef HAVE_MENU
static int menu_input_post_iterate(
struct rarch_state *p_rarch,
gfx_display_t *p_disp,
struct menu_state *menu_st,
unsigned action,
retro_time_t current_time);
#endif
static bool retroarch_apply_shader(
struct rarch_state *p_rarch,
settings_t *settings,