From d9b7c25a4b7e8cc151e8c200b07d4eabbcf63a97 Mon Sep 17 00:00:00 2001 From: Rene Damm Date: Tue, 2 Oct 2018 17:51:20 -0700 Subject: [PATCH] NEW: Support full UTF-32 text input. --- .../InputSystem/Devices/ITextInputReceiver.cs | 4 ++-- .../InputSystem/Events/TextEvent.cs | 19 ++++++++++++++--- .../InputSystem/InputManager.cs | 20 ++++++++++++------ .../Tests/InputSystem/CoreTests_Devices.cs | 21 +++++++++++++++++++ 4 files changed, 53 insertions(+), 11 deletions(-) diff --git a/Packages/com.unity.inputsystem/InputSystem/Devices/ITextInputReceiver.cs b/Packages/com.unity.inputsystem/InputSystem/Devices/ITextInputReceiver.cs index 3b560d230a..6eba0300a3 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Devices/ITextInputReceiver.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Devices/ITextInputReceiver.cs @@ -13,8 +13,8 @@ public interface ITextInputReceiver /// A single, fully-formed Unicode character has been typed on the device. /// /// Character that was typed. Note that in case the character is part of - /// a surrogate pair, this method is called first with the low surrogate and then with the - /// high surrogate character. + /// a surrogate pair, this method is called first with the high surrogate and then with the + /// low surrogate character. void OnTextInput(char character); /// diff --git a/Packages/com.unity.inputsystem/InputSystem/Events/TextEvent.cs b/Packages/com.unity.inputsystem/InputSystem/Events/TextEvent.cs index a21182d25d..3a6aee81fd 100644 --- a/Packages/com.unity.inputsystem/InputSystem/Events/TextEvent.cs +++ b/Packages/com.unity.inputsystem/InputSystem/Events/TextEvent.cs @@ -39,9 +39,22 @@ public FourCC GetTypeStatic() public static TextEvent Create(int deviceId, char character, double time) { - var inputEvent = new TextEvent(); - inputEvent.baseEvent = new InputEvent(Type, InputEvent.kBaseEventSize + 4, deviceId, time); - inputEvent.character = character; + ////TODO: detect and throw when if character is surrogate + var inputEvent = new TextEvent + { + baseEvent = new InputEvent(Type, InputEvent.kBaseEventSize + 4, deviceId, time), + character = character + }; + return inputEvent; + } + + public static TextEvent Create(int deviceId, int character, double time) + { + var inputEvent = new TextEvent + { + baseEvent = new InputEvent(Type, InputEvent.kBaseEventSize + 4, deviceId, time), + character = character + }; return inputEvent; } } diff --git a/Packages/com.unity.inputsystem/InputSystem/InputManager.cs b/Packages/com.unity.inputsystem/InputSystem/InputManager.cs index eab795d648..d0c62276e6 100644 --- a/Packages/com.unity.inputsystem/InputSystem/InputManager.cs +++ b/Packages/com.unity.inputsystem/InputSystem/InputManager.cs @@ -2216,13 +2216,21 @@ internal unsafe void OnUpdate(InputUpdateType updateType, int eventCount, IntPtr var textInputReceiver = device as ITextInputReceiver; if (textInputReceiver != null) { - var ch = (char)textEventPtr->character; - textInputReceiver.OnTextInput(ch); - if (char.IsSurrogate(ch)) + var utf32Char = textEventPtr->character; + if (utf32Char >= 0x10000) { - // Get high-surrogate char of pair. - ch = (char)(textEventPtr->character >> 16); - textInputReceiver.OnTextInput(ch); + // Send surrogate pair. + utf32Char -= 0x10000; + var highSurrogate = 0xD800 + ((utf32Char >> 10) & 0x3FF); + var lowSurrogate = 0xDC00 + (utf32Char & 0x3FF); + + textInputReceiver.OnTextInput((char)highSurrogate); + textInputReceiver.OnTextInput((char)lowSurrogate); + } + else + { + // Send single, plain character. + textInputReceiver.OnTextInput((char)utf32Char); } } break; diff --git a/Packages/com.unity.inputsystem/Tests/InputSystem/CoreTests_Devices.cs b/Packages/com.unity.inputsystem/Tests/InputSystem/CoreTests_Devices.cs index 050d98a8a1..49f102885a 100644 --- a/Packages/com.unity.inputsystem/Tests/InputSystem/CoreTests_Devices.cs +++ b/Packages/com.unity.inputsystem/Tests/InputSystem/CoreTests_Devices.cs @@ -1790,6 +1790,27 @@ public void Devices_CanGetTextInputFromKeyboard() Assert.That(textReceived, Is.EqualTo("abc")); } + [Test] + [Category("Devices")] + public void Devices_CanHandleUTF32CharactersInTextInputOnKeyboard() + { + var keyboard = InputSystem.AddDevice(); + + var charsReceived = new List(); + keyboard.onTextInput += ch => charsReceived.Add(ch); + + const int highBits = 0x12; + const int lowBits = 0x21; + + var inputEvent = TextEvent.Create(keyboard.id, 0x10000 + (highBits << 10 | lowBits), 123); + InputSystem.QueueEvent(ref inputEvent); + InputSystem.Update(); + + Assert.That(charsReceived, Has.Count.EqualTo(2)); + Assert.That(charsReceived[0], Is.EqualTo(0xD800 + highBits)); + Assert.That(charsReceived[1], Is.EqualTo(0xDC00 + lowBits)); + } + [Test] [Category("Devices")] public void Devices_CanGetDisplayNameFromKeyboardKey()