diff --git a/driver.h b/driver.h index 4fd4ee0cb6..14bed8b5eb 100644 --- a/driver.h +++ b/driver.h @@ -481,10 +481,9 @@ typedef struct driver #endif bool stdin_claimed; bool block_hotkey; - unsigned block_hotkey_until; bool block_input; bool block_libretro_input; - unsigned block_libretro_input_until; + bool flushing_input; bool nonblock_state; /* Opaque handles to currently running window. diff --git a/frontend/menu/disp/glui.c b/frontend/menu/disp/glui.c index 6de08e7257..eac83fe896 100644 --- a/frontend/menu/disp/glui.c +++ b/frontend/menu/disp/glui.c @@ -344,13 +344,6 @@ static void glui_free(void *data) g_extern.core_info = NULL; } -static int glui_input_postprocess(uint64_t old_state) -{ - (void)old_state; - - return 0; -} - static GLuint glui_png_texture_load(const char * file_name) { struct texture_image ti = {0}; @@ -404,7 +397,7 @@ menu_ctx_driver_t menu_ctx_glui = { NULL, NULL, NULL, - glui_input_postprocess, + NULL, NULL, NULL, NULL, diff --git a/frontend/menu/disp/lakka.c b/frontend/menu/disp/lakka.c index 03d66520d6..c94079728f 100644 --- a/frontend/menu/disp/lakka.c +++ b/frontend/menu/disp/lakka.c @@ -984,10 +984,10 @@ static void lakka_free(void *data) g_extern.core_info = NULL; } -static int lakka_input_postprocess(uint64_t old_state) +static int lakka_input_postprocess(retro_input_t state, retro_input_t old_state) { - if ((driver.menu && driver.menu->trigger_state - & (1ULL << RARCH_MENU_TOGGLE)) && + retro_input_t trigger_state = state & ~old_state; + if ((driver.menu && check_enter_menu_func(trigger_state)) && g_extern.main_is_init && !g_extern.libretro_dummy) global_alpha = 0; diff --git a/frontend/menu/disp/menu_display.h b/frontend/menu/disp/menu_display.h index 4b8904a593..d9c776c368 100644 --- a/frontend/menu/disp/menu_display.h +++ b/frontend/menu/disp/menu_display.h @@ -18,7 +18,7 @@ typedef struct menu_ctx_driver void (*populate_entries)(void*, const char *, const char *, unsigned); void (*iterate)(void*, unsigned); - int (*input_postprocess)(uint64_t); + int (*input_postprocess)(uint64_t, uint64_t); void (*navigation_clear)(void *); void (*navigation_decrement)(void *); void (*navigation_increment)(void *); diff --git a/frontend/menu/disp/rgui.c b/frontend/menu/disp/rgui.c index 0ed3adee7a..89ea90b49c 100644 --- a/frontend/menu/disp/rgui.c +++ b/frontend/menu/disp/rgui.c @@ -447,11 +447,6 @@ static void rgui_free(void *data) free((uint8_t*)menu->font); } -static int rgui_input_postprocess(uint64_t old_state) -{ - return 0; -} - void rgui_set_texture(void *data) { menu_handle_t *menu = (menu_handle_t*)data; @@ -473,7 +468,7 @@ menu_ctx_driver_t menu_ctx_rgui = { NULL, NULL, NULL, - rgui_input_postprocess, + NULL, NULL, NULL, NULL, diff --git a/frontend/menu/menu_common.c b/frontend/menu/menu_common.c index 09e65aceeb..5ac804d69f 100644 --- a/frontend/menu/menu_common.c +++ b/frontend/menu/menu_common.c @@ -103,8 +103,6 @@ bool load_menu_content(void) /* redraw menu frame */ if (driver.menu) { - driver.menu->old_input_state = driver.menu->trigger_state = 0; - driver.menu->do_held = false; driver.menu->msg_force = true; } @@ -172,9 +170,6 @@ void *menu_init(const void *data) menu_entries_push_list(menu, menu->selection_buf, "", "mainmenu", 0); - menu->trigger_state = 0; - menu->old_input_state = 0; - menu->do_held = false; menu->current_pad = 0; update_libretro_info(&g_extern.menu.info); @@ -302,8 +297,14 @@ bool menu_iterate(retro_input_t input, unsigned action = MENU_ACTION_NOOP; static bool initial_held = true; static bool first_held = false; - uint64_t input_state = 0; int32_t ret = 0; + static const retro_input_t input_repeat = + (1ULL << RETRO_DEVICE_ID_JOYPAD_UP) + | (1ULL << RETRO_DEVICE_ID_JOYPAD_DOWN) + | (1ULL << RETRO_DEVICE_ID_JOYPAD_LEFT) + | (1ULL << RETRO_DEVICE_ID_JOYPAD_RIGHT) + | (1ULL << RETRO_DEVICE_ID_JOYPAD_L) + | (1ULL << RETRO_DEVICE_ID_JOYPAD_R); if (!driver.menu) return false; @@ -316,9 +317,7 @@ bool menu_iterate(retro_input_t input, driver.retro_ctx.poll_cb(); - input_state = menu_input(); - - if (driver.menu->do_held) + if (input & input_repeat) { if (!first_held) { @@ -330,7 +329,7 @@ bool menu_iterate(retro_input_t input, if (driver.menu->delay_count >= driver.menu->delay_timer) { first_held = false; - driver.menu->trigger_state = input_state; + trigger_input |= input & input_repeat; driver.menu->scroll_accel = min(driver.menu->scroll_accel + 1, 64); } @@ -344,15 +343,14 @@ bool menu_iterate(retro_input_t input, } driver.menu->delay_count++; - driver.menu->old_input_state = input_state; if (driver.block_input) - driver.menu->trigger_state = 0; + trigger_input = 0; /* don't run anything first frame, only capture held inputs * for old_input_state. */ - action = input_frame(driver.menu->trigger_state); + action = input_frame(trigger_input); if (driver.menu_ctx && driver.menu_ctx->backend && driver.menu_ctx->backend->iterate) @@ -362,7 +360,7 @@ bool menu_iterate(retro_input_t input, draw_frame(false); if (driver.menu_ctx && driver.menu_ctx->input_postprocess) - driver.menu_ctx->input_postprocess(driver.menu->old_input_state); + driver.menu_ctx->input_postprocess(input, old_input); #if 0 /* Go back to Main Menu when exiting */ diff --git a/frontend/menu/menu_driver.h b/frontend/menu/menu_driver.h index 921867b003..a121f1c8ad 100644 --- a/frontend/menu/menu_driver.h +++ b/frontend/menu/menu_driver.h @@ -67,18 +67,6 @@ struct menu_bind_state typedef struct { - /* Keys down last frame. Used for trigger_state */ - uint64_t old_input_state; - - /* New keys pressed down this frame */ - uint64_t trigger_state; - - /* Whether any repeating keys are being held down, */ - /* and key repeat should be handled */ - /* TODO: should be a mask of keys we are repeating, */ - /* instead of repeating all keys being held down. */ - bool do_held; - /* Used for key repeat */ unsigned delay_timer; unsigned delay_count; diff --git a/frontend/menu/menu_input_line_cb.c b/frontend/menu/menu_input_line_cb.c index ca82789a71..c0a14be7c0 100644 --- a/frontend/menu/menu_input_line_cb.c +++ b/frontend/menu/menu_input_line_cb.c @@ -56,7 +56,7 @@ static void menu_key_end_line(void *data) menu->keyboard.label_setting = NULL; /* Avoid triggering states on pressing return. */ - menu->old_input_state = -1ULL; + driver.flushing_input = true; } static void menu_search_callback(void *userdata, const char *str) @@ -298,43 +298,6 @@ bool menu_custom_bind_keyboard_cb(void *data, unsigned code) return menu->binds.begin <= menu->binds.last; } -uint64_t menu_input(void) -{ - unsigned i; - retro_input_t input_state = 0; - static const struct retro_keybind *binds[] = { g_settings.input.binds[0] }; - - if (!driver.menu) - return 0; - - input_push_analog_dpad((struct retro_keybind*)binds[0], - (g_settings.input.analog_dpad_mode[0] == ANALOG_DPAD_NONE) ? - ANALOG_DPAD_LSTICK : g_settings.input.analog_dpad_mode[0]); - - for (i = 0; i < MAX_PLAYERS; i++) - input_push_analog_dpad(g_settings.input.autoconf_binds[i], - g_settings.input.analog_dpad_mode[i]); - - input_state = input_keys_pressed(0, RARCH_FIRST_CUSTOM_BIND, binds); - - input_pop_analog_dpad((struct retro_keybind*)binds[0]); - for (i = 0; i < MAX_PLAYERS; i++) - input_pop_analog_dpad(g_settings.input.autoconf_binds[i]); - - driver.menu->trigger_state = input_state & ~driver.menu->old_input_state; - - driver.menu->do_held = (input_state & ( - (1ULL << RETRO_DEVICE_ID_JOYPAD_UP) - | (1ULL << RETRO_DEVICE_ID_JOYPAD_DOWN) - | (1ULL << RETRO_DEVICE_ID_JOYPAD_LEFT) - | (1ULL << RETRO_DEVICE_ID_JOYPAD_RIGHT) - | (1ULL << RETRO_DEVICE_ID_JOYPAD_L) - | (1ULL << RETRO_DEVICE_ID_JOYPAD_R) - )); - - return input_state; -} - int menu_input_bind_iterate(void *data) { char msg[PATH_MAX]; @@ -358,22 +321,22 @@ int menu_input_bind_iterate(void *data) && driver.menu_ctx->render_messagebox) driver.menu_ctx->render_messagebox(msg); + driver.block_input = true; menu_poll_bind_state(&binds); - driver.block_hotkey_until = g_extern.frame_count + (15); - if ((binds.skip && !menu->binds.skip) || menu_poll_find_trigger(&menu->binds, &binds)) { + driver.block_input = false; + + /* Avoid new binds triggering things right away. */ + driver.flushing_input = true; + binds.begin++; if (binds.begin <= binds.last) binds.target++; else return 1; - - /* Avoid new binds triggering things right away. */ - menu->trigger_state = 0; - menu->old_input_state = -1ULL; } menu->binds = binds; @@ -416,14 +379,11 @@ int menu_input_bind_iterate_keyboard(void *data) timed_out = true; } - driver.block_hotkey_until = g_extern.frame_count + (15); - /* binds.begin is updated in keyboard_press callback. */ if (menu->binds.begin > menu->binds.last) { /* Avoid new binds triggering things right away. */ - menu->trigger_state = 0; - menu->old_input_state = -1ULL; + driver.flushing_input = true; /* We won't be getting any key events, so just cancel early. */ if (timed_out) diff --git a/frontend/menu/menu_input_line_cb.h b/frontend/menu/menu_input_line_cb.h index 66e4a3cf6f..9e46dc0fab 100644 --- a/frontend/menu/menu_input_line_cb.h +++ b/frontend/menu/menu_input_line_cb.h @@ -42,6 +42,4 @@ int menu_input_bind_iterate(void *data); int menu_input_bind_iterate_keyboard(void *data); -uint64_t menu_input(void); - #endif diff --git a/input/android_input.c b/input/android_input.c index 7fa626895f..185633614f 100644 --- a/input/android_input.c +++ b/input/android_input.c @@ -503,9 +503,7 @@ static int android_input_get_id(android_input_t *android, AInputEvent *event) static bool pause_key_pressed(void) { - retro_input_t old_input = 0; - retro_input_t input = meta_input_keys_pressed(RARCH_PAUSE_TOGGLE, RARCH_PAUSE_TOGGLE+1, &old_input); - return BIND_PRESSED(input, RARCH_PAUSE_TOGGLE); + return driver.input->key_pressed(driver.input_data, RARCH_PAUSE_TOGGLE); } /* Handle all events. If our activity is in pause state, diff --git a/input/input_common.c b/input/input_common.c index 9d6767660f..cf0401003c 100644 --- a/input/input_common.c +++ b/input/input_common.c @@ -1625,6 +1625,10 @@ retro_input_t input_keys_pressed(unsigned key, * from the specified key up until the last queryable key * (key_end). * + * Because this function keeps a copy of the old input state, + * it should only be called once per frame (currently in + * rarch_main_iterate); + * * TODO: In case RARCH_BIND_LIST_END starts exceeding 64, * and you need a bitmask of more than 64 entries, don't * use this function. @@ -1634,20 +1638,29 @@ retro_input_t meta_input_keys_pressed(unsigned key, unsigned key_end, retro_input_t *old_state) { static retro_input_t old_ret = 0; + static const struct retro_keybind *binds[] = { g_settings.input.binds[0] }; retro_input_t ret = 0; *old_state = old_ret; + int i; #ifdef RARCH_INTERNAL rarch_check_block_hotkey(driver.input->key_pressed(driver.input_data, RARCH_ENABLE_HOTKEY)); #endif + input_push_analog_dpad((struct retro_keybind*)binds[0], + (g_settings.input.analog_dpad_mode[0] == ANALOG_DPAD_NONE) ? + ANALOG_DPAD_LSTICK : g_settings.input.analog_dpad_mode[0]); + + for (i = 0; i < MAX_PLAYERS; i++) + input_push_analog_dpad(g_settings.input.autoconf_binds[i], + g_settings.input.analog_dpad_mode[i]); + for (; key < key_end; key++) { bool state = false; - if (!driver.block_hotkey - && g_extern.frame_count > driver.block_hotkey_until) + if (!driver.block_hotkey) state = driver.input->key_pressed(driver.input_data, key); #ifdef HAVE_OVERLAY @@ -1663,6 +1676,10 @@ retro_input_t meta_input_keys_pressed(unsigned key, ret |= (1ULL << key); } + input_pop_analog_dpad((struct retro_keybind*)binds[0]); + for (i = 0; i < MAX_PLAYERS; i++) + input_pop_analog_dpad(g_settings.input.autoconf_binds[i]); + old_ret = ret; return ret; diff --git a/libretro_version_1.c b/libretro_version_1.c index 0c9bd373cb..7bcc347aa9 100644 --- a/libretro_version_1.c +++ b/libretro_version_1.c @@ -183,8 +183,7 @@ static int16_t input_state(unsigned port, unsigned device, if (!driver.block_libretro_input && ((id < RARCH_FIRST_META_KEY || - device == RETRO_DEVICE_KEYBOARD) && - (g_extern.frame_count > driver.block_libretro_input_until)) + device == RETRO_DEVICE_KEYBOARD)) ) res = driver.input->input_state(driver.input_data, binds, port, device, index, id); @@ -203,6 +202,35 @@ static int16_t input_state(unsigned port, unsigned device, } #endif + { + /* Last frame input_state was called. */ + static unsigned flush_frame = 0; + /* Last frame which had input. */ + static unsigned flush_frame_input = 0; + + if (driver.flushing_input) + { + if (flush_frame != g_extern.frame_count && + flush_frame != flush_frame_input) + { + /* At least one entire frame has passed with no input. */ + driver.flushing_input = false; + flush_frame = flush_frame_input = 0; + } + else + { + flush_frame = g_extern.frame_count; + if (res) + { + flush_frame_input = g_extern.frame_count; + res = 0; + } + } + } + else + flush_frame = flush_frame_input = 0; + } + /* Don't allow turbo for D-pad. */ if (device == RETRO_DEVICE_JOYPAD && (id < RETRO_DEVICE_ID_JOYPAD_UP || id > RETRO_DEVICE_ID_JOYPAD_RIGHT)) diff --git a/retroarch.c b/retroarch.c index 37fc64dd43..dff810fa95 100644 --- a/retroarch.c +++ b/retroarch.c @@ -2838,7 +2838,9 @@ void rarch_main_set_state(unsigned cmd) rarch_main_command(RARCH_CMD_AUDIO_START); - driver.block_libretro_input_until = g_extern.frame_count + (5); + /* Prevent stray input from going to libretro core */ + driver.flushing_input = true; + /* Restore libretro keyboard callback. */ g_extern.system.key_event = g_extern.frontend_key_event; break; @@ -3226,9 +3228,17 @@ bool rarch_main_iterate(void) { unsigned i; retro_input_t old_input, trigger_input; - retro_input_t input = meta_input_keys_pressed(RARCH_FIRST_META_KEY, + retro_input_t input = meta_input_keys_pressed(0, RARCH_BIND_LIST_END, &old_input); + if (driver.flushing_input) + { + if (input) + input = 0; + else + driver.flushing_input = false; + } + trigger_input = input & ~old_input; /* Time to drop? */