Skip to content

Commit a3e835d

Browse files
authored
Improves IME ESC key handling
1 parent 88185ee commit a3e835d

File tree

1 file changed

+37
-8
lines changed

1 file changed

+37
-8
lines changed

src/TSMapEditor/UI/IME/IMEHandler.cs

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,11 @@ protected set
4242

4343
public bool CompositionEmpty => string.IsNullOrEmpty(_composition);
4444

45+
/// <summary>
46+
/// Indicates whether an IME event has been received ever. Used to distinguish IME users from non-IME users.
47+
/// </summary>
4548
protected bool IMEEventReceived = false;
49+
4650
protected bool LastActionIMEChatInput = true;
4751

4852
private void OnCompositionChanged(string oldValue, string newValue)
@@ -73,22 +77,35 @@ protected virtual void OnIMETextInput(char character)
7377
{
7478
//Debug.WriteLine($"IME: OnIMETextInput: {character} {(short)character}; IMEFocus is null? {IMEFocus == null}");
7579

76-
IMEEventReceived = true;
7780
LastActionIMEChatInput = true;
7881

79-
if (IMEFocus != null)
82+
// Handle ESC. The IME reports ESC key as a text input.
83+
if (character == 27)
8084
{
81-
// Handle ESC
82-
if (character == 27 && CompositionEmpty)
85+
LastActionIMEChatInput = false;
86+
if (HandleEscapeKey())
8387
{
84-
IMEFocus.Text = string.Empty;
88+
// Do not return this ESC key back to the textbox if HandleEscapeKey returns true.
89+
return;
8590
}
8691
else
8792
{
88-
TextBoxHandleChatInputCallbacks.TryGetValue(IMEFocus, out var handleChatInput);
89-
handleChatInput?.Invoke(character);
93+
// handleChatInput() method rejects the ESC message. Therefore, we need to manually clear the TextBox here.
94+
if (IMEFocus != null)
95+
{
96+
// TODO: wrap this logic as a new action in RegisterXNATextBox(). This requires an API breaking change on XNAUI, and therefore left as a TODO.
97+
IMEFocus.Text = string.Empty;
98+
}
99+
100+
return;
90101
}
91102
}
103+
104+
if (IMEFocus != null)
105+
{
106+
TextBoxHandleChatInputCallbacks.TryGetValue(IMEFocus, out var handleChatInput);
107+
handleChatInput?.Invoke(character);
108+
}
92109
}
93110

94111
public void SetIMETextInputRectangle(WindowManager manager)
@@ -211,9 +228,21 @@ bool IIMEHandler.HandleEnterKey(XNATextBox sender)
211228
=> false;
212229

213230
bool IIMEHandler.HandleEscapeKey(XNATextBox sender)
231+
{
232+
return HandleEscapeKey();
233+
}
234+
235+
private bool HandleEscapeKey()
214236
{
215237
//Debug.WriteLine($"IME: HandleEscapeKey: handled: {IMEEventReceived}");
216-
return IMEEventReceived;
238+
239+
// This method disables the ESC handling of the TextBox as long as the user has used IME.
240+
// This is because IME users often use ESC to cancel composition, and even if currently the composition is empty,
241+
// the user still expects ESC to cancel composition rather than deleting the whole sentence.
242+
// For example, the user might mistakenly hit ESC key twice to cancel composition -- deleting the whole sentence is definitely a heavy punishment for such a small mistake.
243+
244+
// Note: "!string.IsNullOrEmpty(Composition) =>IMEEventReceived" should hold, but just in case
245+
return IMEEventReceived || !string.IsNullOrEmpty(Composition);
217246
}
218247

219248
void IIMEHandler.OnTextChanged(XNATextBox sender) { }

0 commit comments

Comments
 (0)