aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.HLE/HOS
diff options
context:
space:
mode:
authormageven <62494521+mageven@users.noreply.github.com>2020-08-03 07:00:58 +0530
committerGitHub <noreply@github.com>2020-08-03 03:30:58 +0200
commitc11855565e0ce2bac228610cbaa92c8c7f082c70 (patch)
tree76f4ee1c3c4c15997d27c9cf8d963bac4405c915 /Ryujinx.HLE/HOS
parentf0c91d9efb7eff0b8bbe8fc8d4901af5a9d59005 (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')
-rw-r--r--Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardApplet.cs66
-rw-r--r--Ryujinx.HLE/HOS/Applets/SoftwareKeyboard/SoftwareKeyboardUiArgs.cs13
-rw-r--r--Ryujinx.HLE/HOS/Services/Am/AppletAE/AllSystemAppletProxiesService/SystemAppletProxy/ILibraryAppletCreator.cs18
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;
}