File size: 4,719 Bytes
18a519f | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | 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();
}
}
}
|