macOS: support Chinese and Korean input for text buttons

This patch extends D11695 to provide full support for Chinese and Korean
input on macOS.

Chinese input notes:

You can input symbolic characters (such as '! , '$') during Chinese input.

The difference from Japanese input is that multiple `insertText` may be
called with a single key down (`keyDown` method). This happens when you input
a symbolic character (such as '! , '$') during conversion.

The conversion is confirmed (`insertText`) and the symbolic character is
entered (`insertText`). To solve this problem, I have `result_text` to
concatenate the strings and store them in `result`.

Korean input notes:

Korean does not display a conversion suggestion window.

Like Chinese, Korean input may call multiple `insertText` methods. Also,
in Korean, the previous confirmation (`setMarkedText` and `insertText`) and
the next conversion is processed (`setMarkedText`) may be called
simultaneously with a single key down (`keyDown` method).

For example:
1. press g ㅎ (`setMarkedText`)
2. press k 하 (`setMarkedText`)
3. press t 앗 (`setMarkedText`)
4. press k 하세 (`setMarkedText`, `insertText`, `setMarkedText`)

Fixed so that the `insertText` and the last `setMarkedText` are processed.

Also, if a control character (such as Arrow, Enter) is input during Korean
input, the conversion will be confirmed (`setMarkedText`, `insertText`) and
the original control character will be processed.

In other words, if you press the left arrow key while typing in Korean, the
cursor will move to the left after the character is confirmed. Therefore, I
modified the `keyDown` method so that the `handleKeyEvent` is called again
after the `insertText` is processed in the `interpretKeyEvents` method.

Differential Revision: https://developer.blender.org/D11699
This commit is contained in:
Yuki Hashimoto 2021-07-05 13:17:33 +02:00 committed by Brecht Van Lommel
parent 83e2f8c993
commit 0ef794b553
2 changed files with 50 additions and 5 deletions

View File

@ -356,6 +356,8 @@ enum {
GHOST_IME_INPUT_FOCUSED = (1 << 0),
GHOST_IME_ENABLED = (1 << 1),
GHOST_IME_COMPOSING = (1 << 2),
GHOST_IME_KEY_CONTROL_CHAR = (1 << 3)
GHOST_IME_KEY_CONTROL_CHAR = (1 << 3),
GHOST_IME_COMPOSITION_EVENT = (1 << 4), // For Korean input
GHOST_IME_RESULT_EVENT = (1 << 5) // For Korean input
};
#endif /* WITH_INPUT_IME */

View File

@ -47,6 +47,7 @@
GHOST_TEventImeData event;
std::string result;
std::string composite;
std::string combined_result;
} ime;
#endif
}
@ -123,6 +124,20 @@
// interpret event to call insertText
[self interpretKeyEvents:[NSArray arrayWithObject:event]]; // calls insertText
#ifdef WITH_INPUT_IME
// For Korean input, control characters are also processed by handleKeyEvent.
const int controlCharForKorean = (GHOST_IME_COMPOSITION_EVENT | GHOST_IME_RESULT_EVENT |
GHOST_IME_KEY_CONTROL_CHAR);
if (((ime.state_flag & controlCharForKorean) == controlCharForKorean)) {
systemCocoa->handleKeyEvent(event);
}
ime.state_flag &= ~(GHOST_IME_COMPOSITION_EVENT | GHOST_IME_RESULT_EVENT);
ime.combined_result.clear();
#endif
return;
}
}
@ -261,9 +276,23 @@
[self processImeEvent:GHOST_kEventImeCompositionStart];
}
[self setImeResult:[self convertNSString:chars]];
// For Chinese and Korean input, insertText may be executed twice with a single keyDown.
if (ime.state_flag & GHOST_IME_RESULT_EVENT) {
ime.combined_result += [self convertNSString:chars];
}
else {
ime.combined_result = [self convertNSString:chars];
}
[self setImeResult:ime.combined_result];
/* For Korean input, both "Result Event" and "Composition Event"
* can occur in a single keyDown. */
if (![self ime_did_composition]) {
[self processImeEvent:GHOST_kEventImeComposition];
}
ime.state_flag |= GHOST_IME_RESULT_EVENT;
[self processImeEvent:GHOST_kEventImeComposition];
[self processImeEvent:GHOST_kEventImeCompositionEnd];
ime.state_flag &= ~GHOST_IME_COMPOSING;
}
@ -313,7 +342,11 @@
[self setImeComposition:composing_text selectedRange:range];
[self processImeEvent:GHOST_kEventImeComposition];
// For Korean input, setMarkedText may be executed twice with a single keyDown.
if (![self ime_did_composition]) {
ime.state_flag |= GHOST_IME_COMPOSITION_EVENT;
[self processImeEvent:GHOST_kEventImeComposition];
}
}
#endif
}
@ -457,7 +490,11 @@
- (void)setImeComposition:(NSString *)inString selectedRange:(NSRange)range
{
ime.composite = [self convertNSString:inString];
ime.result.clear();
// For Korean input, both "Result Event" and "Composition Event" can occur in a single keyDown.
if (!(ime.state_flag & GHOST_IME_RESULT_EVENT)) {
ime.result.clear();
}
/* The target string is equivalent to the string in selectedRange of setMarkedText.
* The cursor is displayed at the beginning of the target string. */
@ -525,6 +562,12 @@
}
}
- (bool)ime_did_composition
{
return (ime.state_flag & GHOST_IME_COMPOSITION_EVENT) ||
(ime.state_flag & GHOST_IME_RESULT_EVENT);
}
/* Even if IME is enabled, when not composing, control characters
* (such as arrow, enter, delete) are handled by handleKeyEvent. */
- (bool)isProcessedByIme