private void HandleNpadButtonUpEvent(int npadIndex, NpadButton button) { lock (_lock) { KeyboardResult result = KeyboardResult.NotSet; switch (button) { case NpadButton.A: result = KeyboardResult.Accept; _keyboardRenderer.UpdateCommandState(false, null, null); break; case NpadButton.B: result = KeyboardResult.Cancel; _keyboardRenderer.UpdateCommandState(null, false, null); break; } if (IsKeyboardActive()) { if (!_canAcceptController) { _canAcceptController = true; } else if (InputModeControllerEnabled()) { PushUpdatedState(_textValue, _cursorBegin, result); } } } }
private void PushUpdatedState(string text, int cursorBegin, KeyboardResult result) { _lastResult = result; _textValue = text; bool cancel = result == KeyboardResult.Cancel; bool accept = result == KeyboardResult.Accept; if (!IsKeyboardActive()) { // Keyboard is not active. return; } if (accept == false && cancel == false) { Logger.Debug?.Print(LogClass.ServiceAm, $"Updating keyboard text to {text} and cursor position to {cursorBegin}"); PushChangedString(text, (uint)cursorBegin, _backgroundState); } else { // Disable the frontend. DeactivateFrontend(); // The 'Complete' state indicates the Calc request has been fulfilled by the applet. _backgroundState = InlineKeyboardState.Disappearing; if (accept) { Logger.Debug?.Print(LogClass.ServiceAm, $"Sending keyboard OK with text {text}"); DecidedEnter(text, _backgroundState); } else if (cancel) { Logger.Debug?.Print(LogClass.ServiceAm, "Sending keyboard Cancel"); DecidedCancel(_backgroundState); } _interactiveSession.Push(InlineResponses.Default(_backgroundState)); Logger.Debug?.Print(LogClass.ServiceAm, $"Resetting state of the keyboard to {_backgroundState}"); // Set the state of the applet to 'Initialized' as it is the only known state so far // that does not soft-lock the keyboard after use. _backgroundState = InlineKeyboardState.Initialized; _interactiveSession.Push(InlineResponses.Default(_backgroundState)); } }
private void ExecuteForegroundKeyboard() { string initialText = null; // Initial Text is always encoded as a UTF-16 string in the work buffer (passed as transfer memory) // InitialStringOffset points to the memory offset and InitialStringLength is the number of UTF-16 characters if (_transferMemory != null && _keyboardForegroundConfig.InitialStringLength > 0) { initialText = Encoding.Unicode.GetString(_transferMemory, _keyboardForegroundConfig.InitialStringOffset, 2 * _keyboardForegroundConfig.InitialStringLength); } // If the max string length is 0, we set it to a large default // length. if (_keyboardForegroundConfig.StringLengthMax == 0) { _keyboardForegroundConfig.StringLengthMax = 100; } if (_device.UiHandler == null) { Logger.Warning?.Print(LogClass.Application, "GUI Handler is not set. Falling back to default"); _textValue = DefaultInputText; _lastResult = KeyboardResult.Accept; } else { // Call the configured GUI handler to get user's input. var args = new SoftwareKeyboardUiArgs { HeaderText = _keyboardForegroundConfig.HeaderText, SubtitleText = _keyboardForegroundConfig.SubtitleText, GuideText = _keyboardForegroundConfig.GuideText, SubmitText = (!string.IsNullOrWhiteSpace(_keyboardForegroundConfig.SubmitText) ? _keyboardForegroundConfig.SubmitText : "OK"), StringLengthMin = _keyboardForegroundConfig.StringLengthMin, StringLengthMax = _keyboardForegroundConfig.StringLengthMax, InitialText = initialText }; _lastResult = _device.UiHandler.DisplayInputDialog(args, out _textValue) ? KeyboardResult.Accept : KeyboardResult.Cancel; _textValue ??= initialText ?? DefaultInputText; } // If the game requests a string with a minimum length less // than our default text, repeat our default text until we meet // the minimum length requirement. // This should always be done before the text truncation step. while (_textValue.Length < _keyboardForegroundConfig.StringLengthMin) { _textValue = String.Join(" ", _textValue, _textValue); } // If our default text is longer than the allowed length, // we truncate it. if (_textValue.Length > _keyboardForegroundConfig.StringLengthMax) { _textValue = _textValue.Substring(0, _keyboardForegroundConfig.StringLengthMax); } // Does the application want to validate the text itself? if (_keyboardForegroundConfig.CheckText) { // The application needs to validate the response, so we // submit it to the interactive output buffer, and poll it // for validation. Once validated, the application will submit // back a validation status, which is handled in OnInteractiveDataPushIn. _foregroundState = SoftwareKeyboardState.ValidationPending; PushForegroundResponse(true); } else { // If the application doesn't need to validate the response, // we push the data to the non-interactive output buffer // and poll it for completion. _foregroundState = SoftwareKeyboardState.Complete; PushForegroundResponse(false); AppletStateChanged?.Invoke(this, null); } }