mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-08 08:10:30 -10:00
input: one hold for what is held, in the input frontend; the menu's flag is gone
What is held when the menu opens or closes, a bind or a text entry ends, or the mouse clicks is meant to do nothing more until it is let go. Two things did that. The core's buttons and keys had a hold in the input frontend (input_driver_hold_core_input()). The menu and the hotkeys had input_driver_flushing_input, an unsigned in the menu's state with values 0, 1 and 2, which the menu set, the run loop counted through, and the core's input path read to block the core outright. There is one now, in the input frontend: - input_driver_hold_held_input() holds back whatever is down, control by control, until each is let go - from the core (its buttons, keys, mouse and lightgun buttons and the pointer press) and from what the run loop and the menu see (the RetroPad bits and the hotkeys). Everything else gets through at once. The menu calls it where it set the flag; input_driver_hold_clear() where it cleared it; - the run loop hands its bits to input_driver_hold_bits(), which takes out what is held back, and keeps the pause as it was while something is - the same pause handling as before; - the core's input path is no longer blocked by the menu: it reads no menu state, and what the menu left held is the hold's to keep back. input_driver_flushing_input is removed from the menu's state, with every use of it, and the comments that named it. The menu pause lane closes the menu with the mouse's left button held and with the pointer pressed, as it does with B and Return: the core does not see the click or the touch while it is held, nor after it is let go, and does see it made again. Built with overlays and networking off, and in a tree configured as the frontend-overhead CI job is, where all harness lanes pass.
This commit is contained in:
1 parent
796108188d
commit
039bb981cb
7 files changed
+246
-87
No files matched your search
+131
-15
@@ -3049,9 +3049,25 @@ static int16_t input_state_device(
|
||||
}
|
||||
|
||||
|
||||
/* Set while the poll reads what the core's ports have down for the core
|
||||
* hold: that read is not to be held back itself. */
|
||||
static bool input_core_hold_reading;
|
||||
/* What the core hold holds back of a mouse and a lightgun: their
|
||||
* buttons, not their positions and not a wheel's notches, which are
|
||||
* over as they come. */
|
||||
#define CORE_HOLD_MOUSE_IDS ( (1u << RETRO_DEVICE_ID_MOUSE_LEFT) \
|
||||
| (1u << RETRO_DEVICE_ID_MOUSE_RIGHT) \
|
||||
| (1u << RETRO_DEVICE_ID_MOUSE_MIDDLE) \
|
||||
| (1u << RETRO_DEVICE_ID_MOUSE_BUTTON_4) \
|
||||
| (1u << RETRO_DEVICE_ID_MOUSE_BUTTON_5))
|
||||
#define CORE_HOLD_GUN_IDS ( (1u << RETRO_DEVICE_ID_LIGHTGUN_TRIGGER) \
|
||||
| (1u << RETRO_DEVICE_ID_LIGHTGUN_AUX_A) \
|
||||
| (1u << RETRO_DEVICE_ID_LIGHTGUN_AUX_B) \
|
||||
| (1u << RETRO_DEVICE_ID_LIGHTGUN_START) \
|
||||
| (1u << RETRO_DEVICE_ID_LIGHTGUN_SELECT) \
|
||||
| (1u << RETRO_DEVICE_ID_LIGHTGUN_AUX_C) \
|
||||
| (1u << RETRO_DEVICE_ID_LIGHTGUN_DPAD_UP) \
|
||||
| (1u << RETRO_DEVICE_ID_LIGHTGUN_DPAD_DOWN) \
|
||||
| (1u << RETRO_DEVICE_ID_LIGHTGUN_DPAD_LEFT) \
|
||||
| (1u << RETRO_DEVICE_ID_LIGHTGUN_DPAD_RIGHT) \
|
||||
| (1u << RETRO_DEVICE_ID_LIGHTGUN_RELOAD))
|
||||
|
||||
static int16_t input_state_internal(
|
||||
input_driver_state_t *input_st,
|
||||
@@ -3078,14 +3094,9 @@ static int16_t input_state_internal(
|
||||
#endif
|
||||
uint8_t mapped_port = 0;
|
||||
int16_t result = 0;
|
||||
#ifdef HAVE_MENU
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
bool input_blocked = ( (menu_st->input_driver_flushing_input > 0)
|
||||
&& !input_core_hold_reading)
|
||||
|| (input_st->flags & INP_FLAG_BLOCK_LIBRETRO_INPUT);
|
||||
#else
|
||||
/* What the menu leaves held as it closes is the core hold's to keep
|
||||
* back, control by control; the core's input is not blocked for it. */
|
||||
bool input_blocked = (input_st->flags & INP_FLAG_BLOCK_LIBRETRO_INPUT) ? true : false;
|
||||
#endif
|
||||
bool input_driver_analog_requested = input_st->analog_requested[port];
|
||||
bool bitmask_enabled = false;
|
||||
|
||||
@@ -9167,7 +9178,7 @@ static void input_keys_pressed(
|
||||
#ifdef HAVE_MENU
|
||||
/* Prevent triggering menu actions after binding */
|
||||
if ( !(input_st->flags & INP_FLAG_MENU_PRESS_PENDING)
|
||||
&& menu_state_get_ptr()->input_driver_flushing_input)
|
||||
&& input_st->held_bits_phase)
|
||||
input_st->flags |= INP_FLAG_WAIT_INPUT_RELEASE;
|
||||
#endif
|
||||
|
||||
@@ -10035,15 +10046,75 @@ bool input_driver_game_focus_core_requested(void)
|
||||
* until each is let go. They are found at the next poll: until then
|
||||
* every button is held back, which is at most the frame the menu
|
||||
* closed in. */
|
||||
void input_driver_hold_core_input(void)
|
||||
static void input_driver_hold_core_input(void)
|
||||
{
|
||||
memset(input_driver_st.core_hold_mask, 0xff,
|
||||
sizeof(input_driver_st.core_hold_mask));
|
||||
memset(input_driver_st.core_hold_keys, 0xff,
|
||||
sizeof(input_driver_st.core_hold_keys));
|
||||
{
|
||||
unsigned port;
|
||||
for (port = 0; port < MAX_USERS; port++)
|
||||
{
|
||||
input_driver_st.core_hold_mouse[port] = CORE_HOLD_MOUSE_IDS;
|
||||
input_driver_st.core_hold_gun[port] = CORE_HOLD_GUN_IDS;
|
||||
input_driver_st.core_hold_pointer[port] = 1;
|
||||
}
|
||||
}
|
||||
input_driver_st.core_hold_armed = true;
|
||||
}
|
||||
|
||||
void input_driver_hold_held_input(void)
|
||||
{
|
||||
input_driver_hold_core_input();
|
||||
input_driver_st.held_bits_phase = 1;
|
||||
}
|
||||
|
||||
void input_driver_hold_clear(void)
|
||||
{
|
||||
memset(input_driver_st.core_hold_mask, 0,
|
||||
sizeof(input_driver_st.core_hold_mask));
|
||||
memset(input_driver_st.core_hold_keys, 0,
|
||||
sizeof(input_driver_st.core_hold_keys));
|
||||
memset(input_driver_st.core_hold_mouse, 0,
|
||||
sizeof(input_driver_st.core_hold_mouse));
|
||||
memset(input_driver_st.core_hold_gun, 0,
|
||||
sizeof(input_driver_st.core_hold_gun));
|
||||
memset(input_driver_st.core_hold_pointer, 0,
|
||||
sizeof(input_driver_st.core_hold_pointer));
|
||||
input_driver_st.core_hold_armed = false;
|
||||
input_driver_st.held_bits_phase = 0;
|
||||
}
|
||||
|
||||
/* The first frame takes what is down; after that each bit drops out of
|
||||
* the hold as it is let go. The hotkey-enable button is never held
|
||||
* back: holding it is how other hotkeys are reached. */
|
||||
bool input_driver_hold_bits(input_bits_t *bits)
|
||||
{
|
||||
input_driver_state_t *input_st = &input_driver_st;
|
||||
bool held = false;
|
||||
unsigned w;
|
||||
|
||||
if (!input_st->held_bits_phase)
|
||||
return false;
|
||||
if (input_st->held_bits_phase == 1)
|
||||
{
|
||||
input_st->held_bits = *bits;
|
||||
BIT256_CLEAR(input_st->held_bits, RARCH_ENABLE_HOTKEY);
|
||||
input_st->held_bits_phase = 2;
|
||||
}
|
||||
for (w = 0; w < ARRAY_SIZE(bits->data); w++)
|
||||
{
|
||||
input_st->held_bits.data[w] &= bits->data[w];
|
||||
bits->data[w] &= ~input_st->held_bits.data[w];
|
||||
if (input_st->held_bits.data[w])
|
||||
held = true;
|
||||
}
|
||||
if (!held)
|
||||
input_st->held_bits_phase = 0;
|
||||
return held;
|
||||
}
|
||||
|
||||
/* Input polled without blocking, for netplay catching up. */
|
||||
void input_driver_set_nonblocking(bool on)
|
||||
{
|
||||
@@ -11239,9 +11310,29 @@ void input_driver_poll(void)
|
||||
{
|
||||
unsigned port;
|
||||
uint16_t any = 0;
|
||||
input_core_hold_reading = true;
|
||||
for (port = 0; port < max_users; port++)
|
||||
{
|
||||
unsigned id;
|
||||
/* the mouse's buttons, the lightgun's, the pointer pressed */
|
||||
for (id = 0; id < 32 && input_st->core_hold_mouse[port]; id++)
|
||||
if ( (input_st->core_hold_mouse[port] & (1u << id))
|
||||
&& !input_state_internal(input_st, settings, port,
|
||||
RETRO_DEVICE_MOUSE, 0, id))
|
||||
input_st->core_hold_mouse[port] &= (uint16_t)~(1u << id);
|
||||
for (id = 0; id < 32 && input_st->core_hold_gun[port]; id++)
|
||||
if ( (input_st->core_hold_gun[port] & (1u << id))
|
||||
&& !input_state_internal(input_st, settings, port,
|
||||
RETRO_DEVICE_LIGHTGUN, 0, id))
|
||||
input_st->core_hold_gun[port] &= ~(1u << id);
|
||||
if ( input_st->core_hold_pointer[port]
|
||||
&& !input_state_internal(input_st, settings, port,
|
||||
RETRO_DEVICE_POINTER, 0, RETRO_DEVICE_ID_POINTER_PRESSED))
|
||||
input_st->core_hold_pointer[port] = 0;
|
||||
if ( input_st->core_hold_mouse[port]
|
||||
|| input_st->core_hold_gun[port]
|
||||
|| input_st->core_hold_pointer[port])
|
||||
any |= 1;
|
||||
|
||||
if (!input_st->core_hold_mask[port])
|
||||
continue;
|
||||
input_st->core_hold_mask[port] &= (uint16_t)input_state_internal(
|
||||
@@ -11250,7 +11341,12 @@ void input_driver_poll(void)
|
||||
any |= input_st->core_hold_mask[port];
|
||||
}
|
||||
for (; port < MAX_USERS; port++)
|
||||
input_st->core_hold_mask[port] = 0;
|
||||
{
|
||||
input_st->core_hold_mask[port] = 0;
|
||||
input_st->core_hold_mouse[port] = 0;
|
||||
input_st->core_hold_gun[port] = 0;
|
||||
input_st->core_hold_pointer[port] = 0;
|
||||
}
|
||||
/* the keys: each one still held back is read, a word of them
|
||||
* skipped at a time once it is clear */
|
||||
{
|
||||
@@ -11275,7 +11371,6 @@ void input_driver_poll(void)
|
||||
any |= (word != 0);
|
||||
}
|
||||
}
|
||||
input_core_hold_reading = false;
|
||||
if (!any)
|
||||
input_st->core_hold_armed = false;
|
||||
}
|
||||
@@ -11509,6 +11604,27 @@ int16_t input_driver_state_wrapper(unsigned port, unsigned device,
|
||||
&& id < RETROK_LAST
|
||||
&& (input_st->core_hold_keys[id >> 5] & (1u << (id & 31))))
|
||||
result = 0;
|
||||
else if (port < MAX_USERS)
|
||||
{
|
||||
switch (device & RETRO_DEVICE_MASK)
|
||||
{
|
||||
case RETRO_DEVICE_MOUSE:
|
||||
if (id < 16 && (input_st->core_hold_mouse[port] & (1u << id)))
|
||||
result = 0;
|
||||
break;
|
||||
case RETRO_DEVICE_LIGHTGUN:
|
||||
if (id < 32 && (input_st->core_hold_gun[port] & (1u << id)))
|
||||
result = 0;
|
||||
break;
|
||||
case RETRO_DEVICE_POINTER:
|
||||
if ( id == RETRO_DEVICE_ID_POINTER_PRESSED
|
||||
&& input_st->core_hold_pointer[port])
|
||||
result = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Register any analog stick input requests for
|
||||
|
||||
+23
-5
@@ -764,13 +764,23 @@ typedef struct
|
||||
* frame's held set. */
|
||||
uint16_t wait_release_mask[MAX_USERS];
|
||||
/* The core's buttons held back after the menu closes: those that
|
||||
* were down, each until it is let go (input_driver_hold_core_input()).
|
||||
* were down, each until it is let go (input_driver_hold_held_input()).
|
||||
* One bit per RetroPad button, per port; core_hold_armed while any
|
||||
* is set. */
|
||||
uint16_t core_hold_mask[MAX_USERS];
|
||||
/* and the keyboard's keys, one bit per RETROK_ code */
|
||||
uint32_t core_hold_keys[(RETROK_LAST + 31) / 32];
|
||||
/* and per port, the mouse's buttons and the lightgun's, one bit per
|
||||
* RETRO_DEVICE_ID_, and the pointer being pressed (bit 0) */
|
||||
uint16_t core_hold_mouse[MAX_USERS];
|
||||
uint32_t core_hold_gun[MAX_USERS];
|
||||
uint8_t core_hold_pointer[MAX_USERS];
|
||||
bool core_hold_armed;
|
||||
/* The same for what the run loop and the menu see - the RetroPad
|
||||
* bits and the hotkeys: 1 takes what is down at the next frame, 2
|
||||
* holds it back, 0 is no hold. */
|
||||
input_bits_t held_bits;
|
||||
uint8_t held_bits_phase;
|
||||
|
||||
/* The frame's view of each port's RetroPad buttons, as a core is
|
||||
* given them: after port mapping, remaps, turbo, hold, overlays and
|
||||
@@ -1110,10 +1120,18 @@ bool input_driver_game_focus_core_requested(void);
|
||||
bool input_driver_overlay_alive(void);
|
||||
bool input_driver_overlay_takes_input(void);
|
||||
bool input_driver_overlay_active_page(void);
|
||||
/* The buttons the core's ports have down now are kept from the core
|
||||
* until each is let go: for the menu as it closes, so that the press
|
||||
* that closed it does nothing in the content. */
|
||||
void input_driver_hold_core_input(void);
|
||||
/* Whatever is down now is held back, control by control, until each is
|
||||
* let go: from the core (its buttons, keys, mouse and lightgun buttons
|
||||
* and the pointer press) and from what the run loop and the menu see
|
||||
* (the RetroPad bits and the hotkeys). Everything else gets through at
|
||||
* once. For the menu as it opens and closes, a bind or a text entry
|
||||
* ends, or the mouse clicks: the press that did it does nothing more. */
|
||||
void input_driver_hold_held_input(void);
|
||||
/* Nothing is held back any more: for the menu going away. */
|
||||
void input_driver_hold_clear(void);
|
||||
/* The run loop's bits for the frame: what the hold holds back is taken
|
||||
* out. True while it is holding something back. */
|
||||
bool input_driver_hold_bits(input_bits_t *bits);
|
||||
void input_driver_set_nonblocking(bool on);
|
||||
void input_driver_set_remapping_cache_active(void);
|
||||
void input_driver_device_info_save(input_device_info_t *dst);
|
||||
|
||||
+9
-11
@@ -4698,7 +4698,7 @@ void menu_driver_destroy(
|
||||
| MENU_ST_FLAG_ALIVE);
|
||||
menu_st->driver_ctx = NULL;
|
||||
menu_st->userdata = NULL;
|
||||
menu_st->input_driver_flushing_input = 0;
|
||||
input_driver_hold_clear();
|
||||
}
|
||||
|
||||
void menu_input_get_pointer_state(menu_input_pointer_t *copy_target)
|
||||
@@ -4769,7 +4769,7 @@ void menu_input_dialog_end(void)
|
||||
|
||||
/* Avoid triggering states on pressing return. */
|
||||
/* Held back until everything held now is let go. */
|
||||
menu_st->input_driver_flushing_input = 1;
|
||||
input_driver_hold_held_input();
|
||||
|
||||
#ifdef HAVE_COCOATOUCH
|
||||
/* Dismiss iOS/tvOS native keyboard if it's currently open */
|
||||
@@ -5151,7 +5151,7 @@ MENU_NOINLINE static bool menu_input_key_bind_iterate(
|
||||
{
|
||||
/* Avoid new binds triggering things right away. */
|
||||
/* Held back until everything held now is let go. */
|
||||
menu_st->input_driver_flushing_input = 1;
|
||||
input_driver_hold_held_input();
|
||||
|
||||
/* We won't be getting any key events, so just cancel early. */
|
||||
if (timed_out)
|
||||
@@ -5283,7 +5283,7 @@ MENU_NOINLINE static bool menu_input_key_bind_iterate(
|
||||
|
||||
/* Avoid new binds triggering things right away. */
|
||||
/* Held back until everything held now is let go. */
|
||||
menu_st->input_driver_flushing_input = 1;
|
||||
input_driver_hold_held_input();
|
||||
|
||||
/* Use human readable order instead */
|
||||
new_binds.order++;
|
||||
@@ -5644,7 +5644,7 @@ unsigned menu_event(
|
||||
{
|
||||
menu_st->input_last_time_us = menu_st->current_time_us;
|
||||
/* Prevent double trigger when OK/Cancel has mouse binds */
|
||||
menu_st->input_driver_flushing_input = 1;
|
||||
input_driver_hold_held_input();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7040,7 +7040,7 @@ void retroarch_menu_running(void)
|
||||
}
|
||||
|
||||
/* Prevent stray input */
|
||||
menu_st->input_driver_flushing_input = 1;
|
||||
input_driver_hold_held_input();
|
||||
|
||||
#ifdef HAVE_AUDIOMIXER
|
||||
if (audio_enable_menu && audio_enable_menu_bgm)
|
||||
@@ -7117,11 +7117,9 @@ void retroarch_menu_running_finished(bool quit)
|
||||
false);
|
||||
}
|
||||
|
||||
/* Prevent stray input */
|
||||
menu_st->input_driver_flushing_input = 1;
|
||||
/* and the core's buttons held as the menu closes stay out of the
|
||||
* content until each is let go */
|
||||
input_driver_hold_core_input();
|
||||
/* What is held as the menu closes does nothing more, in the menu or
|
||||
* in the content, until it is let go */
|
||||
input_driver_hold_held_input();
|
||||
|
||||
if (!quit)
|
||||
{
|
||||
|
||||
@@ -543,14 +543,6 @@ struct menu_state
|
||||
|
||||
/* unsigned alignment */
|
||||
unsigned input_dialog_kb_idx;
|
||||
/* The menu's hold. Set to 1 when the menu opens or closes, a bind or
|
||||
* a text entry ends, or the mouse clicks: the run loop then takes
|
||||
* what is down and holds it back from the menu and the hotkeys, each
|
||||
* button until it is let go (2), and clears this when nothing of it
|
||||
* is down. The core's buttons and keys have a hold of their own
|
||||
* (input_driver_hold_core_input()); while this is set the core's
|
||||
* other input - pointer, mouse, sticks - is kept from it as well. */
|
||||
unsigned input_driver_flushing_input;
|
||||
menu_dialog_t dialog_st;
|
||||
enum menu_action prev_action;
|
||||
enum menu_input_dialog_kb_text_type input_dialog_kb_text_type;
|
||||
|
||||
@@ -7350,51 +7350,25 @@ static enum runloop_state_enum runloop_check_state(
|
||||
&last_input))
|
||||
BIT256_SET(current_bits, RARCH_MENU_TOGGLE);
|
||||
|
||||
/* The menu's hold: what was down when the menu opened or closed, a
|
||||
* bind or a text entry ended or the mouse clicked is held back, each
|
||||
* button and hotkey until it is let go; everything else gets through
|
||||
* at once. 1 asks for what is down to be taken this frame; 2 is the
|
||||
* hold, which ends when nothing of it is down. The hotkey-enable
|
||||
* button is never held back: holding it is how other hotkeys are
|
||||
* reached. */
|
||||
if (menu_st->input_driver_flushing_input > 0)
|
||||
/* What was down when the menu opened or closed, a bind or a text
|
||||
* entry ended or the mouse clicked is held back, each control until
|
||||
* it is let go (input_driver_hold_held_input()). While it is, the
|
||||
* pause is kept as it was. */
|
||||
if (input_driver_hold_bits(¤t_bits))
|
||||
{
|
||||
static input_bits_t held_back;
|
||||
unsigned w;
|
||||
bool input_active = false;
|
||||
|
||||
if (menu_st->input_driver_flushing_input == 1)
|
||||
if ( runloop_paused
|
||||
&& !runloop_st->paused_hotkey
|
||||
&& menu_pause_libretro)
|
||||
BIT256_SET(current_bits, RARCH_PAUSE_TOGGLE);
|
||||
else if (runloop_st->paused_hotkey)
|
||||
{
|
||||
held_back = current_bits;
|
||||
BIT256_CLEAR(held_back, RARCH_ENABLE_HOTKEY);
|
||||
menu_st->input_driver_flushing_input = 2;
|
||||
}
|
||||
for (w = 0; w < ARRAY_SIZE(current_bits.data); w++)
|
||||
{
|
||||
held_back.data[w] &= current_bits.data[w];
|
||||
current_bits.data[w] &= ~held_back.data[w];
|
||||
if (held_back.data[w])
|
||||
input_active = true;
|
||||
}
|
||||
|
||||
if (!input_active)
|
||||
menu_st->input_driver_flushing_input = 0;
|
||||
else
|
||||
{
|
||||
if ( runloop_paused
|
||||
&& !runloop_st->paused_hotkey
|
||||
&& menu_pause_libretro)
|
||||
BIT256_SET(current_bits, RARCH_PAUSE_TOGGLE);
|
||||
else if (runloop_st->paused_hotkey)
|
||||
{
|
||||
/* Restore pause if pause is triggered with both hotkey and menu,
|
||||
* and restore cached video frame to continue properly to
|
||||
* paused state from non-paused menu */
|
||||
if (menu_pause_libretro)
|
||||
command_event(CMD_EVENT_PAUSE, NULL);
|
||||
else
|
||||
video_driver_cached_frame();
|
||||
}
|
||||
/* Restore pause if pause is triggered with both hotkey and menu,
|
||||
* and restore cached video frame to continue properly to
|
||||
* paused state from non-paused menu */
|
||||
if (menu_pause_libretro)
|
||||
command_event(CMD_EVENT_PAUSE, NULL);
|
||||
else
|
||||
video_driver_cached_frame();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2746,9 +2746,12 @@ static bool pm_menu_settled(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
/* an input driver that has one key down, RETROK_RETURN, when told to */
|
||||
/* an input driver that has one key down, RETROK_RETURN, the mouse's
|
||||
* left button down, or the pointer pressed, when told to */
|
||||
static input_driver_t pm_input;
|
||||
static bool pm_return_down;
|
||||
static bool pm_click_down;
|
||||
static bool pm_touch_down;
|
||||
static int16_t pm_input_state(void *data,
|
||||
const input_device_driver_t *joypad,
|
||||
const input_device_driver_t *sec_joypad,
|
||||
@@ -2758,9 +2761,37 @@ static int16_t pm_input_state(void *data,
|
||||
unsigned port, unsigned device, unsigned idx, unsigned id)
|
||||
{
|
||||
(void)data; (void)joypad; (void)sec_joypad; (void)joypad_info;
|
||||
(void)binds; (void)keyboard_mapping_blocked; (void)idx;
|
||||
return ( pm_return_down && port == 0
|
||||
&& device == RETRO_DEVICE_KEYBOARD && id == RETROK_RETURN) ? 1 : 0;
|
||||
(void)binds; (void)keyboard_mapping_blocked;
|
||||
if (port != 0)
|
||||
return 0;
|
||||
switch (device & RETRO_DEVICE_MASK)
|
||||
{
|
||||
case RETRO_DEVICE_KEYBOARD:
|
||||
return (pm_return_down && id == RETROK_RETURN) ? 1 : 0;
|
||||
case RETRO_DEVICE_MOUSE:
|
||||
return (pm_click_down && id == RETRO_DEVICE_ID_MOUSE_LEFT) ? 1 : 0;
|
||||
case RETRO_DEVICE_POINTER:
|
||||
return (pm_touch_down && idx == 0
|
||||
&& id == RETRO_DEVICE_ID_POINTER_PRESSED) ? 1 : 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* frames run one at a time; whether a control reached the core's view
|
||||
* in any of them, read as the core reads it */
|
||||
static bool pm_frames_saw(unsigned n, unsigned device, unsigned id)
|
||||
{
|
||||
bool saw = false;
|
||||
unsigned i;
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
run_loop_frames(1);
|
||||
if (input_driver_state_wrapper(0, device, 0, id))
|
||||
saw = true;
|
||||
}
|
||||
return saw;
|
||||
}
|
||||
|
||||
/* frames run one at a time; whether Return reached the core's view in
|
||||
@@ -2867,6 +2898,34 @@ static void lane_menu_pause(void)
|
||||
pm_return_down = false;
|
||||
run_loop_frames(3);
|
||||
|
||||
/* closed with the mouse's left button held, and with the pointer
|
||||
* pressed: the same, for a click and a touch */
|
||||
{
|
||||
static const struct { const char *what; unsigned device, id; bool *flag; } c[2] = {
|
||||
{ "the left click", RETRO_DEVICE_MOUSE, RETRO_DEVICE_ID_MOUSE_LEFT, &pm_click_down },
|
||||
{ "the touch", RETRO_DEVICE_POINTER, RETRO_DEVICE_ID_POINTER_PRESSED, &pm_touch_down }
|
||||
};
|
||||
unsigned k;
|
||||
for (k = 0; k < 2; k++)
|
||||
{
|
||||
snprintf(msg, sizeof(msg), "menu pause, %s: the menu would not stay open", with);
|
||||
CHECK(pm_menu_settled(), msg);
|
||||
*c[k].flag = true;
|
||||
run_loop_frames(2);
|
||||
pm_set_menu(false);
|
||||
snprintf(msg, sizeof(msg), "menu pause, %s: the core saw %s that closed the menu, while it was held", with, c[k].what);
|
||||
CHECK(!pm_frames_saw(10, c[k].device, c[k].id), msg);
|
||||
*c[k].flag = false;
|
||||
snprintf(msg, sizeof(msg), "menu pause, %s: the core saw %s after it was let go", with, c[k].what);
|
||||
CHECK(!pm_frames_saw(4, c[k].device, c[k].id), msg);
|
||||
*c[k].flag = true;
|
||||
snprintf(msg, sizeof(msg), "menu pause, %s: the core did not see %s made again after the menu", with, c[k].what);
|
||||
CHECK(pm_frames_saw(4, c[k].device, c[k].id), msg);
|
||||
*c[k].flag = false;
|
||||
run_loop_frames(3);
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(msg, sizeof(msg), "menu pause, %s: the menu would not stay open", with);
|
||||
CHECK(pm_menu_settled(), msg);
|
||||
/* closed with B held: the core runs, and does not see that B */
|
||||
@@ -2989,6 +3048,8 @@ static void lane_menu_pause(void)
|
||||
input_config_binds[0][RARCH_MENU_TOGGLE] = saved_toggle;
|
||||
input_st->current_driver = saved_input;
|
||||
pm_return_down = false;
|
||||
pm_click_down = false;
|
||||
pm_touch_down = false;
|
||||
input_st->primary_joypad = joypad_real;
|
||||
run_loop_frames(3);
|
||||
if (failures == had)
|
||||
|
||||
@@ -625,7 +625,7 @@ static ui_application_t ui_application_cocoa = {
|
||||
* a panel. Every key that is down right now will be released into that
|
||||
* window, so this window never sees the key-up: the key stays "held" in
|
||||
* apple_key_state, and a held key is exactly what the menu's flush-and-
|
||||
* wait-for-release (menu_st->input_driver_flushing_input) waits on -
|
||||
* wait-for-release (input_driver_hold_held_input()) waits on -
|
||||
* for ever, since the release never arrives. That was the desktop
|
||||
* companion's "keyboard does not come back after closing it": the hotkey
|
||||
* that opened it was still down when the companion took the keyboard.
|
||||
|
||||
Reference in new issue
Block a user