diff options
author | mageven <62494521+mageven@users.noreply.github.com> | 2020-08-03 07:00:58 +0530 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-03 03:30:58 +0200 |
commit | c11855565e0ce2bac228610cbaa92c8c7f082c70 (patch) | |
tree | 76f4ee1c3c4c15997d27c9cf8d963bac4405c915 /Ryujinx.HLE/HOS | |
parent | f0c91d9efb7eff0b8bbe8fc8d4901af5a9d59005 (diff) |
Implement Software Keyboard GTK frontend (#1434)
* Implement SwKbd GUI
* Relocate UI handler to Emu Context from Config
Also create a common interface for UI handlers in the context and specialize for Gtk
Add basic input length validation in InputDialog
* Add Transfer Memory support to AppletCreator
Read Initial Text for SwKbd using Transfer Memory
* Improve InputDialog widget
Improve length validation
Has extra label to show validition info
Handle potential errors and log them
* Misc improvements
* Improve string validation
* Improve error handling
* Remove tuple in struct
* Address formatting nits
* Add proper Cancel functionality
Also handle GUI errors in UI handler
* Address jD's comments
* Fix _uiHandler init
* Address AcK's comments
Diffstat (limited to 'Ryujinx.HLE/HOS')
3 files changed, 83 insertions, 14 deletions
diff --git a/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardApplet.cs b/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardApplet.cs index e142838c..000d1193 100644 --- a/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardApplet.cs +++ b/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardApplet.cs @@ -1,4 +1,5 @@ -using Ryujinx.HLE.HOS.Applets.SoftwareKeyboard; +using Ryujinx.Common.Logging; +using Ryujinx.HLE.HOS.Applets.SoftwareKeyboard; using Ryujinx.HLE.HOS.Services.Am.AppletAE; using System; using System.IO; @@ -9,9 +10,10 @@ namespace Ryujinx.HLE.HOS.Applets { internal class SoftwareKeyboardApplet : IApplet { - private const string DefaultNumb = "1"; private const string DefaultText = "Ryujinx"; + private readonly Switch _device; + private const int StandardBufferSize = 0x7D8; private const int InteractiveBufferSize = 0x7D4; @@ -21,13 +23,18 @@ namespace Ryujinx.HLE.HOS.Applets private AppletSession _interactiveSession; private SoftwareKeyboardConfig _keyboardConfig; + private byte[] _transferMemory; - private string _textValue = DefaultText; + private string _textValue = null; + private bool _okPressed = false; private Encoding _encoding = Encoding.Unicode; public event EventHandler AppletStateChanged; - public SoftwareKeyboardApplet(Horizon system) { } + public SoftwareKeyboardApplet(Horizon system) + { + _device = system.Device; + } public ResultCode Start(AppletSession normalSession, AppletSession interactiveSession) @@ -39,9 +46,20 @@ namespace Ryujinx.HLE.HOS.Applets var launchParams = _normalSession.Pop(); var keyboardConfig = _normalSession.Pop(); - var transferMemory = _normalSession.Pop(); - _keyboardConfig = ReadStruct<SoftwareKeyboardConfig>(keyboardConfig); + if (keyboardConfig.Length < Marshal.SizeOf<SoftwareKeyboardConfig>()) + { + Logger.PrintError(LogClass.ServiceAm, $"SoftwareKeyboardConfig size mismatch. Expected {Marshal.SizeOf<SoftwareKeyboardConfig>():x}. Got {keyboardConfig.Length:x}"); + } + else + { + _keyboardConfig = ReadStruct<SoftwareKeyboardConfig>(keyboardConfig); + } + + if (!_normalSession.TryPop(out _transferMemory)) + { + Logger.PrintError(LogClass.ServiceAm, "SwKbd Transfer Memory is null"); + } if (_keyboardConfig.UseUtf8) { @@ -62,11 +80,13 @@ namespace Ryujinx.HLE.HOS.Applets private void Execute() { - // If the keyboard type is numbers only, we swap to a default - // text that only contains numbers. - if (_keyboardConfig.Mode == KeyboardMode.NumbersOnly) + 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 && _keyboardConfig.InitialStringLength > 0) { - _textValue = DefaultNumb; + initialText = Encoding.Unicode.GetString(_transferMemory, _keyboardConfig.InitialStringOffset, 2 * _keyboardConfig.InitialStringLength); } // If the max string length is 0, we set it to a large default @@ -76,6 +96,30 @@ namespace Ryujinx.HLE.HOS.Applets _keyboardConfig.StringLengthMax = 100; } + var args = new SoftwareKeyboardUiArgs + { + HeaderText = _keyboardConfig.HeaderText, + SubtitleText = _keyboardConfig.SubtitleText, + GuideText = _keyboardConfig.GuideText, + SubmitText = (!string.IsNullOrWhiteSpace(_keyboardConfig.SubmitText) ? _keyboardConfig.SubmitText : "OK"), + StringLengthMin = _keyboardConfig.StringLengthMin, + StringLengthMax = _keyboardConfig.StringLengthMax, + InitialText = initialText + }; + + // Call the configured GUI handler to get user's input + if (_device.UiHandler == null) + { + Logger.PrintWarning(LogClass.Application, $"GUI Handler is not set. Falling back to default"); + _okPressed = true; + } + else + { + _okPressed = _device.UiHandler.DisplayInputDialog(args, out _textValue); + } + + _textValue ??= initialText ?? DefaultText; + // 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. @@ -162,7 +206,7 @@ namespace Ryujinx.HLE.HOS.Applets if (!interactive) { // Result Code - writer.Write((uint)0); + writer.Write(_okPressed ? 0U : 1U); } else { diff --git a/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardUiArgs.cs b/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardUiArgs.cs new file mode 100644 index 00000000..d24adec3 --- /dev/null +++ b/Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardUiArgs.cs @@ -0,0 +1,13 @@ +namespace Ryujinx.HLE.HOS.Applets +{ + public struct SoftwareKeyboardUiArgs + { + public string HeaderText; + public string SubtitleText; + public string InitialText; + public string GuideText; + public string SubmitText; + public int StringLengthMin; + public int StringLengthMax; + } +}
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs index 564bde09..bc0e4d8a 100644 --- a/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs +++ b/Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs @@ -1,4 +1,5 @@ -using Ryujinx.HLE.HOS.Applets; +using Ryujinx.Common.Logging; +using Ryujinx.HLE.HOS.Kernel.Memory; using Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.LibraryAppletCreator; namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.SystemAppletProxy @@ -36,10 +37,21 @@ namespace Ryujinx.HLE.HOS.Services.Am.AppletAE.AllSystemAppletProxiesService.Sys { bool unknown = context.RequestData.ReadBoolean(); long size = context.RequestData.ReadInt64(); + int handle = context.Request.HandleDesc.ToCopy[0]; - // NOTE: We don't support TransferMemory for now. + KTransferMemory transferMem = context.Process.HandleTable.GetObject<KTransferMemory>(handle); - MakeObject(context, new IStorage(new byte[size])); + if (transferMem == null) + { + Logger.PrintWarning(LogClass.ServiceAm, $"Invalid TransferMemory Handle: {handle:X}"); + + return ResultCode.Success; // TODO: Find correct error code + } + + var data = new byte[transferMem.Size]; + context.Memory.Read(transferMem.Address, data); + + MakeObject(context, new IStorage(data)); return ResultCode.Success; } |