Improve heuristic for showing the keyboard (#2066)

This commit is contained in:
Caian Benedicto 2021-02-28 07:26:00 -03:00 committed by GitHub
parent f556c80d02
commit 8b4e4fc076
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -50,6 +50,7 @@ namespace Ryujinx.HLE.HOS.Applets
private bool _okPressed = false; private bool _okPressed = false;
private Encoding _encoding = Encoding.Unicode; private Encoding _encoding = Encoding.Unicode;
private long _lastTextSetMillis = 0; private long _lastTextSetMillis = 0;
private bool _lastWasHidden = false;
public event EventHandler AppletStateChanged; public event EventHandler AppletStateChanged;
@ -350,12 +351,12 @@ namespace Ryujinx.HLE.HOS.Applets
// The Calc request tells the Applet to enter the main input handling loop, which will end // The Calc request tells the Applet to enter the main input handling loop, which will end
// with either a text being submitted or a cancel request from the user. // with either a text being submitted or a cancel request from the user.
// NOTE: Some Calc requests happen early in the process and are not meant to be shown. This possibly // NOTE: Some Calc requests happen early in the application and are not meant to be shown. This possibly
// happens because the game has complete control over when the inline keyboard is drawn, but here it // happens because the game has complete control over when the inline keyboard is drawn, but here it
// would cause a dialog to pop in the emulator, which is inconvenient. An algorithm is applied to // would cause a dialog to pop in the emulator, which is inconvenient. An algorithm is applied to
// decide whether it is a dummy Calc or not, but regardless of the result, the dummy Calc appears to // decide whether it is a dummy Calc or not, but regardless of the result, the dummy Calc appears to
// never happen twice, so the keyboard will always show if it has already been shown before. // never happen twice, so the keyboard will always show if it has already been shown before.
bool forceShowKeyboard = _alreadyShown; bool shouldShowKeyboard = _alreadyShown;
_alreadyShown = true; _alreadyShown = true;
// Read the Calc data. // Read the Calc data.
@ -379,7 +380,7 @@ namespace Ryujinx.HLE.HOS.Applets
// input dialog may show, but it is better than a soft lock. // input dialog may show, but it is better than a soft lock.
if (_keyboardBackgroundCalc.Appear.ShouldBeHidden == 0) if (_keyboardBackgroundCalc.Appear.ShouldBeHidden == 0)
{ {
forceShowKeyboard = true; shouldShowKeyboard = true;
} }
} }
// Send an initialization finished signal. // Send an initialization finished signal.
@ -387,10 +388,10 @@ namespace Ryujinx.HLE.HOS.Applets
SetInlineState(state); SetInlineState(state);
_interactiveSession.Push(InlineResponses.FinishedInitialize(state)); _interactiveSession.Push(InlineResponses.FinishedInitialize(state));
// Start a task with the GUI handler to get user's input. // Start a task with the GUI handler to get user's input.
new Task(() => { GetInputTextAndSend(forceShowKeyboard, state); }).Start(); new Task(() => { GetInputTextAndSend(shouldShowKeyboard, state); }).Start();
break; break;
case InlineKeyboardRequest.Finalize: case InlineKeyboardRequest.Finalize:
// The calling process wants to close the keyboard applet and will wait for a state change. // The calling application wants to close the keyboard applet and will wait for a state change.
_backgroundState = InlineKeyboardState.Uninitialized; _backgroundState = InlineKeyboardState.Uninitialized;
AppletStateChanged?.Invoke(this, null); AppletStateChanged?.Invoke(this, null);
break; break;
@ -403,7 +404,7 @@ namespace Ryujinx.HLE.HOS.Applets
} }
} }
private void GetInputTextAndSend(bool forceShowKeyboard, InlineKeyboardState oldState) private void GetInputTextAndSend(bool shouldShowKeyboard, InlineKeyboardState oldState)
{ {
bool submit = true; bool submit = true;
@ -422,27 +423,32 @@ namespace Ryujinx.HLE.HOS.Applets
SetInlineState(newState); SetInlineState(newState);
ChangedString("", newState); ChangedString("", newState);
if (inputElapsedMillis < DebounceTimeMillis) if (!_lastWasHidden && (inputElapsedMillis < DebounceTimeMillis))
{ {
// A repeated Calc request has been received without player interaction, after the input has been // A repeated Calc request has been received without player interaction, after the input has been
// sent. This behavior happens in some games, so instead of showing another dialog, just apply a // sent. This behavior happens in some games, so instead of showing another dialog, just apply a
// time-based debouncing algorithm and repeat the last submission, either a value or a cancel. // time-based debouncing algorithm and repeat the last submission, either a value or a cancel.
// It is also possible that the first Calc request was hidden by accident, in this case use the
// debouncing as an oportunity to properly ask for input.
inputText = _textValue; inputText = _textValue;
submit = _textValue != null; submit = _textValue != null;
_lastWasHidden = false;
Logger.Warning?.Print(LogClass.Application, "Debouncing repeated keyboard request"); Logger.Warning?.Print(LogClass.Application, "Debouncing repeated keyboard request");
} }
else if (!forceShowKeyboard) else if (!shouldShowKeyboard)
{ {
// Submit the default text to avoid soft locking if the keyboard was ignored by // Submit the default text to avoid soft locking if the keyboard was ignored by
// accident. It's better to change the name than being locked out of the game. // accident. It's better to change the name than being locked out of the game.
inputText = DefaultText; inputText = DefaultText;
_lastWasHidden = true;
Logger.Debug?.Print(LogClass.Application, "Received a dummy Calc, keyboard will not be shown"); Logger.Debug?.Print(LogClass.Application, "Received a dummy Calc, keyboard will not be shown");
} }
else if (_device.UiHandler == null) else if (_device.UiHandler == null)
{ {
Logger.Warning?.Print(LogClass.Application, "GUI Handler is not set. Falling back to default"); Logger.Warning?.Print(LogClass.Application, "GUI Handler is not set. Falling back to default");
_lastWasHidden = false;
} }
else else
{ {
@ -461,6 +467,7 @@ namespace Ryujinx.HLE.HOS.Applets
submit = _device.UiHandler.DisplayInputDialog(args, out inputText); submit = _device.UiHandler.DisplayInputDialog(args, out inputText);
inputText = submit ? inputText : null; inputText = submit ? inputText : null;
_lastWasHidden = false;
} }
// The 'Complete' state indicates the Calc request has been fulfilled by the applet. // The 'Complete' state indicates the Calc request has been fulfilled by the applet.