Prevent raw Unicode control codes from showing on software keyboard applet. (#3845)
* Revert "Add support for releasing a semaphore to DmaClass (#2926)"
This reverts commit 521a07e612
.
* Revert "Revert "Add support for releasing a semaphore to DmaClass (#2926)""
This reverts commit ec8a5fd05362f04cc77436ee3e45a9188777f75e.
* Strip non-visible control codes from strings before they are sent to the software keyboard to prevent ugly unicode blocks from being shown on the UI.
* remove debugging junk
* Initialize stringbuilder capacity at the start to prevent resizing (a tiny tiny microoptimization)
* Update remarks documentation. Remove unneeded imports.
* Removing a test that's actually just redundant
Co-authored-by: Logan Stromberg <lostromb@microsoft.com>
This commit is contained in:
parent
d536cc8ae6
commit
2c9ab5e45f
3
Ryujinx.HLE/AssemblyInfo.cs
Normal file
3
Ryujinx.HLE/AssemblyInfo.cs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
|
||||||
|
[assembly: InternalsVisibleTo("Ryujinx.Tests")]
|
@ -204,12 +204,11 @@ namespace Ryujinx.HLE.HOS.Applets
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Call the configured GUI handler to get user's input.
|
// Call the configured GUI handler to get user's input.
|
||||||
|
|
||||||
var args = new SoftwareKeyboardUiArgs
|
var args = new SoftwareKeyboardUiArgs
|
||||||
{
|
{
|
||||||
HeaderText = _keyboardForegroundConfig.HeaderText,
|
HeaderText = StripUnicodeControlCodes(_keyboardForegroundConfig.HeaderText),
|
||||||
SubtitleText = _keyboardForegroundConfig.SubtitleText,
|
SubtitleText = StripUnicodeControlCodes(_keyboardForegroundConfig.SubtitleText),
|
||||||
GuideText = _keyboardForegroundConfig.GuideText,
|
GuideText = StripUnicodeControlCodes(_keyboardForegroundConfig.GuideText),
|
||||||
SubmitText = (!string.IsNullOrWhiteSpace(_keyboardForegroundConfig.SubmitText) ?
|
SubmitText = (!string.IsNullOrWhiteSpace(_keyboardForegroundConfig.SubmitText) ?
|
||||||
_keyboardForegroundConfig.SubmitText : "OK"),
|
_keyboardForegroundConfig.SubmitText : "OK"),
|
||||||
StringLengthMin = _keyboardForegroundConfig.StringLengthMin,
|
StringLengthMin = _keyboardForegroundConfig.StringLengthMin,
|
||||||
@ -764,6 +763,41 @@ namespace Ryujinx.HLE.HOS.Applets
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes all Unicode control code characters from the input string.
|
||||||
|
/// This includes CR/LF, tabs, null characters, escape characters,
|
||||||
|
/// and special control codes which are used for formatting by the real keyboard applet.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Some games send special control codes (such as 0x13 "Device Control 3") as part of the string.
|
||||||
|
/// Future implementations of the emulated keyboard applet will need to handle these as well.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="input">The input string to sanitize (may be null).</param>
|
||||||
|
/// <returns>The sanitized string.</returns>
|
||||||
|
internal static string StripUnicodeControlCodes(string input)
|
||||||
|
{
|
||||||
|
if (input is null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (input.Length == 0)
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder(capacity: input.Length);
|
||||||
|
foreach (char c in input)
|
||||||
|
{
|
||||||
|
if (!char.IsControl(c))
|
||||||
|
{
|
||||||
|
sb.Append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
private static T ReadStruct<T>(byte[] data)
|
private static T ReadStruct<T>(byte[] data)
|
||||||
where T : struct
|
where T : struct
|
||||||
{
|
{
|
||||||
|
71
Ryujinx.Tests/HLE/SoftwareKeyboardTests.cs
Normal file
71
Ryujinx.Tests/HLE/SoftwareKeyboardTests.cs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
using NUnit.Framework;
|
||||||
|
using Ryujinx.HLE.HOS.Applets;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Ryujinx.Tests.HLE
|
||||||
|
{
|
||||||
|
public class SoftwareKeyboardTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void StripUnicodeControlCodes_NullInput()
|
||||||
|
{
|
||||||
|
Assert.IsNull(SoftwareKeyboardApplet.StripUnicodeControlCodes(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void StripUnicodeControlCodes_EmptyInput()
|
||||||
|
{
|
||||||
|
Assert.AreEqual(string.Empty, SoftwareKeyboardApplet.StripUnicodeControlCodes(string.Empty));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void StripUnicodeControlCodes_Passthrough()
|
||||||
|
{
|
||||||
|
string[] prompts = new string[]
|
||||||
|
{
|
||||||
|
"Please name him.",
|
||||||
|
"Name her, too.",
|
||||||
|
"Name your friend.",
|
||||||
|
"Name another friend.",
|
||||||
|
"Name your pet.",
|
||||||
|
"Favorite homemade food?",
|
||||||
|
"What’s your favorite thing?",
|
||||||
|
"Are you sure?",
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (string prompt in prompts)
|
||||||
|
{
|
||||||
|
Assert.AreEqual(prompt, SoftwareKeyboardApplet.StripUnicodeControlCodes(prompt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void StripUnicodeControlCodes_StripsNewlines()
|
||||||
|
{
|
||||||
|
Assert.AreEqual("I am very tall", SoftwareKeyboardApplet.StripUnicodeControlCodes("I \r\nam \r\nvery \r\ntall"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void StripUnicodeControlCodes_StripsDeviceControls()
|
||||||
|
{
|
||||||
|
// 0x13 is control code DC3 used by some games
|
||||||
|
string specialInput = Encoding.UTF8.GetString(new byte[] { 0x13, 0x53, 0x68, 0x69, 0x6E, 0x65, 0x13 });
|
||||||
|
Assert.AreEqual("Shine", SoftwareKeyboardApplet.StripUnicodeControlCodes(specialInput));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void StripUnicodeControlCodes_StripsToEmptyString()
|
||||||
|
{
|
||||||
|
string specialInput = Encoding.UTF8.GetString(new byte[] { 17, 18, 19, 20 }); // DC1 - DC4 special codes
|
||||||
|
Assert.AreEqual(string.Empty, SoftwareKeyboardApplet.StripUnicodeControlCodes(specialInput));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void StripUnicodeControlCodes_PreservesMultiCodePoints()
|
||||||
|
{
|
||||||
|
// Turtles are a good example of multi-codepoint Unicode chars
|
||||||
|
string specialInput = "♀ 🐢 🐢 ♂ ";
|
||||||
|
Assert.AreEqual(specialInput, SoftwareKeyboardApplet.StripUnicodeControlCodes(specialInput));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user