Merge pull request #29464 from bruvzg/macos_fix_non_ime_unicode_input

[macOS] Fixes unicode input with IME input mode inactive.
This commit is contained in:
Rémi Verschelde 2019-06-04 18:49:53 +02:00 committed by GitHub
commit d0dc42f80c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 106 additions and 42 deletions

View File

@ -29,7 +29,7 @@
Key scancode, one of the [enum KeyList] constants.
</member>
<member name="unicode" type="int" setter="set_unicode" getter="get_unicode">
Key unicode identifier when relevant.
Key unicode identifier when relevant. Unicode identifiers for the composite characters and complex scripts may not be available unless IME input mode is active. See [method OS.set_ime_active] for more information.
</member>
</members>
<constants>

View File

@ -221,14 +221,16 @@
<return type="Vector2">
</return>
<description>
Returns IME selection range.
Returns IME cursor position (currently edited portion of the string) relative to the characters in the composition string.
[code]NOTIFICATION_OS_IME_UPDATE[/code] is sent to the application to notify it of changes to the IME cursor position.
</description>
</method>
<method name="get_ime_text" qualifiers="const">
<return type="String">
</return>
<description>
Returns IME intermediate text.
Returns IME intermediate composition string.
[code]NOTIFICATION_OS_IME_UPDATE[/code] is sent to the application to notify it of changes to the IME composition string.
</description>
</method>
<method name="get_latin_keyboard_variant" qualifiers="const">
@ -710,6 +712,9 @@
</argument>
<description>
Sets whether IME input mode should be enabled.
If active IME handles key events before the application and creates an composition string and suggestion list.
Application can retrieve the composition status by using [method get_ime_selection] and [method get_ime_text] functions.
Completed composition string is committed when input is finished.
</description>
</method>
<method name="set_ime_position">

View File

@ -60,6 +60,7 @@ public:
unsigned int osx_state;
bool pressed;
bool echo;
bool raw;
uint32_t scancode;
uint32_t unicode;
};

View File

@ -392,7 +392,7 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt
@interface GodotContentView : NSView <NSTextInputClient> {
NSTrackingArea *trackingArea;
NSMutableAttributedString *markedText;
bool imeMode;
bool imeInputEventInProgress;
}
- (void)cancelComposition;
- (BOOL)wantsUpdateLayer;
@ -418,7 +418,7 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt
- (id)init {
self = [super init];
trackingArea = nil;
imeMode = false;
imeInputEventInProgress = false;
[self updateTrackingAreas];
[self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
markedText = [[NSMutableAttributedString alloc] init];
@ -452,7 +452,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
[markedText initWithString:aString];
}
if (OS_OSX::singleton->im_active) {
imeMode = true;
imeInputEventInProgress = true;
OS_OSX::singleton->im_text.parse_utf8([[markedText mutableString] UTF8String]);
OS_OSX::singleton->im_selection = Point2(selectedRange.location, selectedRange.length);
@ -467,7 +467,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
}
- (void)unmarkText {
imeMode = false;
imeInputEventInProgress = false;
[[markedText mutableString] setString:@""];
if (OS_OSX::singleton->im_active) {
OS_OSX::singleton->im_text = String();
@ -540,6 +540,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
ke.osx_state = [event modifierFlags];
ke.pressed = true;
ke.echo = false;
ke.raw = false; // IME input event
ke.scancode = 0;
ke.unicode = codepoint;
@ -1045,29 +1046,52 @@ static int remapKey(unsigned int key) {
- (void)keyDown:(NSEvent *)event {
//disable raw input in IME mode
if (!imeMode) {
OS_OSX::KeyEvent ke;
// Ignore all input if IME input is in progress
if (!imeInputEventInProgress) {
NSString *characters = [event characters];
NSUInteger length = [characters length];
ke.osx_state = [event modifierFlags];
ke.pressed = true;
ke.echo = [event isARepeat];
ke.scancode = remapKey([event keyCode]);
ke.unicode = 0;
if (!OS_OSX::singleton->im_active && length > 0 && keycode_has_unicode(remapKey([event keyCode]))) {
// Fallback unicode character handler used if IME is not active
for (NSUInteger i = 0; i < length; i++) {
OS_OSX::KeyEvent ke;
push_to_key_event_buffer(ke);
ke.osx_state = [event modifierFlags];
ke.pressed = true;
ke.echo = [event isARepeat];
ke.scancode = remapKey([event keyCode]);
ke.raw = true;
ke.unicode = [characters characterAtIndex:i];
push_to_key_event_buffer(ke);
}
} else {
OS_OSX::KeyEvent ke;
ke.osx_state = [event modifierFlags];
ke.pressed = true;
ke.echo = [event isARepeat];
ke.scancode = remapKey([event keyCode]);
ke.raw = false;
ke.unicode = 0;
push_to_key_event_buffer(ke);
}
}
if (OS_OSX::singleton->im_active == true)
// Pass events to IME handler
if (OS_OSX::singleton->im_active)
[self interpretKeyEvents:[NSArray arrayWithObject:event]];
}
- (void)flagsChanged:(NSEvent *)event {
if (!imeMode) {
// Ignore all input if IME input is in progress
if (!imeInputEventInProgress) {
OS_OSX::KeyEvent ke;
ke.echo = false;
ke.raw = true;
int key = [event keyCode];
int mod = [event modifierFlags];
@ -1114,17 +1138,37 @@ static int remapKey(unsigned int key) {
- (void)keyUp:(NSEvent *)event {
if (!imeMode) {
// Ignore all input if IME input is in progress
if (!imeInputEventInProgress) {
NSString *characters = [event characters];
NSUInteger length = [characters length];
OS_OSX::KeyEvent ke;
// Fallback unicode character handler used if IME is not active
if (!OS_OSX::singleton->im_active && length > 0 && keycode_has_unicode(remapKey([event keyCode]))) {
for (NSUInteger i = 0; i < length; i++) {
OS_OSX::KeyEvent ke;
ke.osx_state = [event modifierFlags];
ke.pressed = false;
ke.echo = false;
ke.scancode = remapKey([event keyCode]);
ke.unicode = 0;
ke.osx_state = [event modifierFlags];
ke.pressed = false;
ke.echo = [event isARepeat];
ke.scancode = remapKey([event keyCode]);
ke.raw = true;
ke.unicode = [characters characterAtIndex:i];
push_to_key_event_buffer(ke);
push_to_key_event_buffer(ke);
}
} else {
OS_OSX::KeyEvent ke;
ke.osx_state = [event modifierFlags];
ke.pressed = false;
ke.echo = [event isARepeat];
ke.scancode = remapKey([event keyCode]);
ke.raw = true;
ke.unicode = 0;
push_to_key_event_buffer(ke);
}
}
}
@ -2612,30 +2656,44 @@ void OS_OSX::process_key_events() {
const KeyEvent &ke = key_event_buffer[i];
if ((i == 0 && ke.scancode == 0) || (i > 0 && key_event_buffer[i - 1].scancode == 0)) {
k.instance();
get_key_modifier_state(ke.osx_state, k);
k->set_pressed(ke.pressed);
k->set_echo(ke.echo);
k->set_scancode(0);
k->set_unicode(ke.unicode);
push_input(k);
}
if (ke.scancode != 0) {
if (ke.raw) {
// Non IME input - no composite characters, pass events as is
k.instance();
get_key_modifier_state(ke.osx_state, k);
k->set_pressed(ke.pressed);
k->set_echo(ke.echo);
k->set_scancode(ke.scancode);
if (i + 1 < key_event_pos && key_event_buffer[i + 1].scancode == 0) {
k->set_unicode(key_event_buffer[i + 1].unicode);
}
k->set_unicode(ke.unicode);
push_input(k);
} else {
// IME input
if ((i == 0 && ke.scancode == 0) || (i > 0 && key_event_buffer[i - 1].scancode == 0)) {
k.instance();
get_key_modifier_state(ke.osx_state, k);
k->set_pressed(ke.pressed);
k->set_echo(ke.echo);
k->set_scancode(0);
k->set_unicode(ke.unicode);
push_input(k);
}
if (ke.scancode != 0) {
k.instance();
get_key_modifier_state(ke.osx_state, k);
k->set_pressed(ke.pressed);
k->set_echo(ke.echo);
k->set_scancode(ke.scancode);
if (i + 1 < key_event_pos && key_event_buffer[i + 1].scancode == 0) {
k->set_unicode(key_event_buffer[i + 1].unicode);
}
push_input(k);
}
}
}