147 lines
4.6 KiB
C#
147 lines
4.6 KiB
C#
|
using System;
|
||
|
using System.Collections;
|
||
|
using System.Collections.Generic;
|
||
|
using System.Runtime.InteropServices;
|
||
|
using UnityEngine.InputSystem.Utilities;
|
||
|
|
||
|
namespace UnityEngine.InputSystem.LowLevel
|
||
|
{
|
||
|
/// <summary>
|
||
|
/// A specialized event that contains the current IME Composition string, if IME is enabled and active.
|
||
|
/// This event contains the entire current string to date, and once a new composition is submitted will send a blank string event.
|
||
|
/// </summary>
|
||
|
[StructLayout(LayoutKind.Explicit, Size = InputEvent.kBaseEventSize + sizeof(int) + (sizeof(char) * kIMECharBufferSize))]
|
||
|
public struct IMECompositionEvent : IInputEventTypeInfo
|
||
|
{
|
||
|
// These needs to match the native ImeCompositionStringInputEventData settings
|
||
|
internal const int kIMECharBufferSize = 64;
|
||
|
public const int Type = 0x494D4553;
|
||
|
|
||
|
[FieldOffset(0)]
|
||
|
public InputEvent baseEvent;
|
||
|
|
||
|
[FieldOffset(InputEvent.kBaseEventSize)]
|
||
|
public IMECompositionString compositionString;
|
||
|
|
||
|
public FourCC typeStatic => Type;
|
||
|
|
||
|
public static IMECompositionEvent Create(int deviceId, string compositionString, double time)
|
||
|
{
|
||
|
var inputEvent = new IMECompositionEvent();
|
||
|
inputEvent.baseEvent = new InputEvent(Type, InputEvent.kBaseEventSize + sizeof(int) + (sizeof(char) * kIMECharBufferSize), deviceId, time);
|
||
|
inputEvent.compositionString = new IMECompositionString(compositionString);
|
||
|
return inputEvent;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// A struct representing an string of characters generated by an IME for text input.
|
||
|
/// </summary>
|
||
|
/// <remarks>
|
||
|
/// This is the internal representation of character strings in the event stream. It is exposed to user content through the
|
||
|
/// <see cref="ITextInputReceiver.OnIMECompositionChanged"/> method. It can easily be converted to a normal C# string using
|
||
|
/// <see cref="ToString"/>, but is exposed as the raw struct to avoid allocating memory by default.
|
||
|
/// </remarks>
|
||
|
[StructLayout(LayoutKind.Explicit, Size = sizeof(int) + sizeof(char) * LowLevel.IMECompositionEvent.kIMECharBufferSize)]
|
||
|
public unsafe struct IMECompositionString : IEnumerable<char>
|
||
|
{
|
||
|
internal struct Enumerator : IEnumerator<char>
|
||
|
{
|
||
|
IMECompositionString m_CompositionString;
|
||
|
char m_CurrentCharacter;
|
||
|
int m_CurrentIndex;
|
||
|
|
||
|
public Enumerator(IMECompositionString compositionString)
|
||
|
{
|
||
|
m_CompositionString = compositionString;
|
||
|
m_CurrentCharacter = '\0';
|
||
|
m_CurrentIndex = -1;
|
||
|
}
|
||
|
|
||
|
public bool MoveNext()
|
||
|
{
|
||
|
int size = m_CompositionString.Count;
|
||
|
|
||
|
m_CurrentIndex++;
|
||
|
|
||
|
if (m_CurrentIndex == size)
|
||
|
return false;
|
||
|
|
||
|
fixed(char* ptr = m_CompositionString.buffer)
|
||
|
{
|
||
|
m_CurrentCharacter = *(ptr + m_CurrentIndex);
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
public void Reset()
|
||
|
{
|
||
|
m_CurrentIndex = -1;
|
||
|
}
|
||
|
|
||
|
public void Dispose()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
public char Current => m_CurrentCharacter;
|
||
|
|
||
|
object IEnumerator.Current => Current;
|
||
|
}
|
||
|
|
||
|
public int Count => size;
|
||
|
|
||
|
public char this[int index]
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
if (index >= Count || index < 0)
|
||
|
throw new ArgumentOutOfRangeException(nameof(index));
|
||
|
|
||
|
fixed(char* ptr = buffer)
|
||
|
{
|
||
|
return *(ptr + index);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[FieldOffset(0)]
|
||
|
int size;
|
||
|
|
||
|
[FieldOffset(sizeof(int))]
|
||
|
fixed char buffer[IMECompositionEvent.kIMECharBufferSize];
|
||
|
|
||
|
public IMECompositionString(string characters)
|
||
|
{
|
||
|
if (string.IsNullOrEmpty(characters))
|
||
|
{
|
||
|
size = 0;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
Debug.Assert(characters.Length < IMECompositionEvent.kIMECharBufferSize);
|
||
|
size = characters.Length;
|
||
|
for (var i = 0; i < size; i++)
|
||
|
buffer[i] = characters[i];
|
||
|
}
|
||
|
|
||
|
public override string ToString()
|
||
|
{
|
||
|
fixed(char* ptr = buffer)
|
||
|
{
|
||
|
return new string(ptr, 0, size);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public IEnumerator<char> GetEnumerator()
|
||
|
{
|
||
|
return new Enumerator(this);
|
||
|
}
|
||
|
|
||
|
IEnumerator IEnumerable.GetEnumerator()
|
||
|
{
|
||
|
return GetEnumerator();
|
||
|
}
|
||
|
}
|
||
|
}
|