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:
commit
d0dc42f80c
|
@ -29,7 +29,7 @@
|
||||||
Key scancode, one of the [enum KeyList] constants.
|
Key scancode, one of the [enum KeyList] constants.
|
||||||
</member>
|
</member>
|
||||||
<member name="unicode" type="int" setter="set_unicode" getter="get_unicode">
|
<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>
|
</member>
|
||||||
</members>
|
</members>
|
||||||
<constants>
|
<constants>
|
||||||
|
|
|
@ -221,14 +221,16 @@
|
||||||
<return type="Vector2">
|
<return type="Vector2">
|
||||||
</return>
|
</return>
|
||||||
<description>
|
<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>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="get_ime_text" qualifiers="const">
|
<method name="get_ime_text" qualifiers="const">
|
||||||
<return type="String">
|
<return type="String">
|
||||||
</return>
|
</return>
|
||||||
<description>
|
<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>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="get_latin_keyboard_variant" qualifiers="const">
|
<method name="get_latin_keyboard_variant" qualifiers="const">
|
||||||
|
@ -710,6 +712,9 @@
|
||||||
</argument>
|
</argument>
|
||||||
<description>
|
<description>
|
||||||
Sets whether IME input mode should be enabled.
|
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>
|
</description>
|
||||||
</method>
|
</method>
|
||||||
<method name="set_ime_position">
|
<method name="set_ime_position">
|
||||||
|
|
|
@ -60,6 +60,7 @@ public:
|
||||||
unsigned int osx_state;
|
unsigned int osx_state;
|
||||||
bool pressed;
|
bool pressed;
|
||||||
bool echo;
|
bool echo;
|
||||||
|
bool raw;
|
||||||
uint32_t scancode;
|
uint32_t scancode;
|
||||||
uint32_t unicode;
|
uint32_t unicode;
|
||||||
};
|
};
|
||||||
|
|
|
@ -392,7 +392,7 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt
|
||||||
@interface GodotContentView : NSView <NSTextInputClient> {
|
@interface GodotContentView : NSView <NSTextInputClient> {
|
||||||
NSTrackingArea *trackingArea;
|
NSTrackingArea *trackingArea;
|
||||||
NSMutableAttributedString *markedText;
|
NSMutableAttributedString *markedText;
|
||||||
bool imeMode;
|
bool imeInputEventInProgress;
|
||||||
}
|
}
|
||||||
- (void)cancelComposition;
|
- (void)cancelComposition;
|
||||||
- (BOOL)wantsUpdateLayer;
|
- (BOOL)wantsUpdateLayer;
|
||||||
|
@ -418,7 +418,7 @@ static CVReturn DisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeSt
|
||||||
- (id)init {
|
- (id)init {
|
||||||
self = [super init];
|
self = [super init];
|
||||||
trackingArea = nil;
|
trackingArea = nil;
|
||||||
imeMode = false;
|
imeInputEventInProgress = false;
|
||||||
[self updateTrackingAreas];
|
[self updateTrackingAreas];
|
||||||
[self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
|
[self registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
|
||||||
markedText = [[NSMutableAttributedString alloc] init];
|
markedText = [[NSMutableAttributedString alloc] init];
|
||||||
|
@ -452,7 +452,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||||
[markedText initWithString:aString];
|
[markedText initWithString:aString];
|
||||||
}
|
}
|
||||||
if (OS_OSX::singleton->im_active) {
|
if (OS_OSX::singleton->im_active) {
|
||||||
imeMode = true;
|
imeInputEventInProgress = true;
|
||||||
OS_OSX::singleton->im_text.parse_utf8([[markedText mutableString] UTF8String]);
|
OS_OSX::singleton->im_text.parse_utf8([[markedText mutableString] UTF8String]);
|
||||||
OS_OSX::singleton->im_selection = Point2(selectedRange.location, selectedRange.length);
|
OS_OSX::singleton->im_selection = Point2(selectedRange.location, selectedRange.length);
|
||||||
|
|
||||||
|
@ -467,7 +467,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)unmarkText {
|
- (void)unmarkText {
|
||||||
imeMode = false;
|
imeInputEventInProgress = false;
|
||||||
[[markedText mutableString] setString:@""];
|
[[markedText mutableString] setString:@""];
|
||||||
if (OS_OSX::singleton->im_active) {
|
if (OS_OSX::singleton->im_active) {
|
||||||
OS_OSX::singleton->im_text = String();
|
OS_OSX::singleton->im_text = String();
|
||||||
|
@ -540,6 +540,7 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||||
ke.osx_state = [event modifierFlags];
|
ke.osx_state = [event modifierFlags];
|
||||||
ke.pressed = true;
|
ke.pressed = true;
|
||||||
ke.echo = false;
|
ke.echo = false;
|
||||||
|
ke.raw = false; // IME input event
|
||||||
ke.scancode = 0;
|
ke.scancode = 0;
|
||||||
ke.unicode = codepoint;
|
ke.unicode = codepoint;
|
||||||
|
|
||||||
|
@ -1045,29 +1046,52 @@ static int remapKey(unsigned int key) {
|
||||||
|
|
||||||
- (void)keyDown:(NSEvent *)event {
|
- (void)keyDown:(NSEvent *)event {
|
||||||
|
|
||||||
//disable raw input in IME mode
|
// Ignore all input if IME input is in progress
|
||||||
if (!imeMode) {
|
if (!imeInputEventInProgress) {
|
||||||
OS_OSX::KeyEvent ke;
|
NSString *characters = [event characters];
|
||||||
|
NSUInteger length = [characters length];
|
||||||
|
|
||||||
ke.osx_state = [event modifierFlags];
|
if (!OS_OSX::singleton->im_active && length > 0 && keycode_has_unicode(remapKey([event keyCode]))) {
|
||||||
ke.pressed = true;
|
// Fallback unicode character handler used if IME is not active
|
||||||
ke.echo = [event isARepeat];
|
for (NSUInteger i = 0; i < length; i++) {
|
||||||
ke.scancode = remapKey([event keyCode]);
|
OS_OSX::KeyEvent ke;
|
||||||
ke.unicode = 0;
|
|
||||||
|
|
||||||
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]];
|
[self interpretKeyEvents:[NSArray arrayWithObject:event]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)flagsChanged:(NSEvent *)event {
|
- (void)flagsChanged:(NSEvent *)event {
|
||||||
|
|
||||||
if (!imeMode) {
|
// Ignore all input if IME input is in progress
|
||||||
|
if (!imeInputEventInProgress) {
|
||||||
OS_OSX::KeyEvent ke;
|
OS_OSX::KeyEvent ke;
|
||||||
|
|
||||||
ke.echo = false;
|
ke.echo = false;
|
||||||
|
ke.raw = true;
|
||||||
|
|
||||||
int key = [event keyCode];
|
int key = [event keyCode];
|
||||||
int mod = [event modifierFlags];
|
int mod = [event modifierFlags];
|
||||||
|
@ -1114,17 +1138,37 @@ static int remapKey(unsigned int key) {
|
||||||
|
|
||||||
- (void)keyUp:(NSEvent *)event {
|
- (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.osx_state = [event modifierFlags];
|
||||||
ke.pressed = false;
|
ke.pressed = false;
|
||||||
ke.echo = false;
|
ke.echo = [event isARepeat];
|
||||||
ke.scancode = remapKey([event keyCode]);
|
ke.scancode = remapKey([event keyCode]);
|
||||||
ke.unicode = 0;
|
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];
|
const KeyEvent &ke = key_event_buffer[i];
|
||||||
|
|
||||||
if ((i == 0 && ke.scancode == 0) || (i > 0 && key_event_buffer[i - 1].scancode == 0)) {
|
if (ke.raw) {
|
||||||
k.instance();
|
// Non IME input - no composite characters, pass events as is
|
||||||
|
|
||||||
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();
|
k.instance();
|
||||||
|
|
||||||
get_key_modifier_state(ke.osx_state, k);
|
get_key_modifier_state(ke.osx_state, k);
|
||||||
k->set_pressed(ke.pressed);
|
k->set_pressed(ke.pressed);
|
||||||
k->set_echo(ke.echo);
|
k->set_echo(ke.echo);
|
||||||
k->set_scancode(ke.scancode);
|
k->set_scancode(ke.scancode);
|
||||||
|
k->set_unicode(ke.unicode);
|
||||||
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);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue