Merge pull request #15552 from bruvzg/osx_ime_fix
[macOS] Fix IME producing multiple events per key press.
This commit is contained in:
commit
23c464a403
2 changed files with 127 additions and 65 deletions
|
@ -52,6 +52,21 @@
|
||||||
|
|
||||||
class OS_OSX : public OS_Unix {
|
class OS_OSX : public OS_Unix {
|
||||||
public:
|
public:
|
||||||
|
enum {
|
||||||
|
KEY_EVENT_BUFFER_SIZE = 512
|
||||||
|
};
|
||||||
|
|
||||||
|
struct KeyEvent {
|
||||||
|
unsigned int osx_state;
|
||||||
|
bool pressed;
|
||||||
|
bool echo;
|
||||||
|
uint32_t scancode;
|
||||||
|
uint32_t unicode;
|
||||||
|
};
|
||||||
|
|
||||||
|
KeyEvent key_event_buffer[KEY_EVENT_BUFFER_SIZE];
|
||||||
|
int key_event_pos;
|
||||||
|
|
||||||
bool force_quit;
|
bool force_quit;
|
||||||
// rasterizer seems to no longer be given to visual server, its using GLES3 directly?
|
// rasterizer seems to no longer be given to visual server, its using GLES3 directly?
|
||||||
//Rasterizer *rasterizer;
|
//Rasterizer *rasterizer;
|
||||||
|
@ -72,6 +87,7 @@ public:
|
||||||
CGEventSourceRef eventSource;
|
CGEventSourceRef eventSource;
|
||||||
|
|
||||||
void process_events();
|
void process_events();
|
||||||
|
void process_key_events();
|
||||||
|
|
||||||
void *framework;
|
void *framework;
|
||||||
// pthread_key_t current;
|
// pthread_key_t current;
|
||||||
|
|
|
@ -407,13 +407,6 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||||
|
|
||||||
- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange {
|
- (void)insertText:(id)aString replacementRange:(NSRange)replacementRange {
|
||||||
NSEvent *event = [NSApp currentEvent];
|
NSEvent *event = [NSApp currentEvent];
|
||||||
Ref<InputEventKey> k;
|
|
||||||
k.instance();
|
|
||||||
|
|
||||||
get_key_modifier_state([event modifierFlags], k);
|
|
||||||
k->set_pressed(true);
|
|
||||||
k->set_echo(false);
|
|
||||||
k->set_scancode(0);
|
|
||||||
|
|
||||||
NSString *characters;
|
NSString *characters;
|
||||||
if ([aString isKindOfClass:[NSAttributedString class]]) {
|
if ([aString isKindOfClass:[NSAttributedString class]]) {
|
||||||
|
@ -438,8 +431,15 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
||||||
if ((codepoint & 0xFF00) == 0xF700)
|
if ((codepoint & 0xFF00) == 0xF700)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
k->set_unicode(codepoint);
|
OS_OSX::KeyEvent ke;
|
||||||
OS_OSX::singleton->push_input(k);
|
|
||||||
|
ke.osx_state = [event modifierFlags];
|
||||||
|
ke.pressed = true;
|
||||||
|
ke.echo = false;
|
||||||
|
ke.scancode = 0;
|
||||||
|
ke.unicode = codepoint;
|
||||||
|
|
||||||
|
OS_OSX::singleton->key_event_buffer[OS_OSX::singleton->key_event_pos++] = ke;
|
||||||
}
|
}
|
||||||
[self cancelComposition];
|
[self cancelComposition];
|
||||||
}
|
}
|
||||||
|
@ -788,28 +788,29 @@ static int translateKey(unsigned int key) {
|
||||||
|
|
||||||
- (void)keyDown:(NSEvent *)event {
|
- (void)keyDown:(NSEvent *)event {
|
||||||
|
|
||||||
Ref<InputEventKey> k;
|
|
||||||
k.instance();
|
|
||||||
|
|
||||||
get_key_modifier_state([event modifierFlags], k);
|
|
||||||
k->set_pressed(true);
|
|
||||||
k->set_scancode(latin_keyboard_keycode_convert(translateKey([event keyCode])));
|
|
||||||
k->set_echo([event isARepeat]);
|
|
||||||
|
|
||||||
NSString *characters = [event characters];
|
|
||||||
NSUInteger i, length = [characters length];
|
|
||||||
|
|
||||||
//disable raw input in IME mode
|
//disable raw input in IME mode
|
||||||
if (!imeMode)
|
if (!imeMode) {
|
||||||
OS_OSX::singleton->push_input(k);
|
OS_OSX::KeyEvent ke;
|
||||||
|
|
||||||
|
ke.osx_state = [event modifierFlags];
|
||||||
|
ke.pressed = true;
|
||||||
|
ke.echo = [event isARepeat];
|
||||||
|
ke.scancode = latin_keyboard_keycode_convert(translateKey([event keyCode]));
|
||||||
|
ke.unicode = 0;
|
||||||
|
|
||||||
|
OS_OSX::singleton->key_event_buffer[OS_OSX::singleton->key_event_pos++] = ke;
|
||||||
|
}
|
||||||
|
|
||||||
if ((OS_OSX::singleton->im_position.x != 0) && (OS_OSX::singleton->im_position.y != 0))
|
if ((OS_OSX::singleton->im_position.x != 0) && (OS_OSX::singleton->im_position.y != 0))
|
||||||
[self interpretKeyEvents:[NSArray arrayWithObject:event]];
|
[self interpretKeyEvents:[NSArray arrayWithObject:event]];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)flagsChanged:(NSEvent *)event {
|
- (void)flagsChanged:(NSEvent *)event {
|
||||||
Ref<InputEventKey> k;
|
|
||||||
k.instance();
|
if (!imeMode) {
|
||||||
|
OS_OSX::KeyEvent ke;
|
||||||
|
|
||||||
|
ke.echo = false;
|
||||||
|
|
||||||
int key = [event keyCode];
|
int key = [event keyCode];
|
||||||
int mod = [event modifierFlags];
|
int mod = [event modifierFlags];
|
||||||
|
@ -817,51 +818,57 @@ static int translateKey(unsigned int key) {
|
||||||
if (key == 0x36 || key == 0x37) {
|
if (key == 0x36 || key == 0x37) {
|
||||||
if (mod & NSEventModifierFlagCommand) {
|
if (mod & NSEventModifierFlagCommand) {
|
||||||
mod &= ~NSEventModifierFlagCommand;
|
mod &= ~NSEventModifierFlagCommand;
|
||||||
k->set_pressed(true);
|
ke.pressed = true;
|
||||||
} else {
|
} else {
|
||||||
k->set_pressed(false);
|
ke.pressed = false;
|
||||||
}
|
}
|
||||||
} else if (key == 0x38 || key == 0x3c) {
|
} else if (key == 0x38 || key == 0x3c) {
|
||||||
if (mod & NSEventModifierFlagShift) {
|
if (mod & NSEventModifierFlagShift) {
|
||||||
mod &= ~NSEventModifierFlagShift;
|
mod &= ~NSEventModifierFlagShift;
|
||||||
k->set_pressed(true);
|
ke.pressed = true;
|
||||||
} else {
|
} else {
|
||||||
k->set_pressed(false);
|
ke.pressed = false;
|
||||||
}
|
}
|
||||||
} else if (key == 0x3a || key == 0x3d) {
|
} else if (key == 0x3a || key == 0x3d) {
|
||||||
if (mod & NSEventModifierFlagOption) {
|
if (mod & NSEventModifierFlagOption) {
|
||||||
mod &= ~NSEventModifierFlagOption;
|
mod &= ~NSEventModifierFlagOption;
|
||||||
k->set_pressed(true);
|
ke.pressed = true;
|
||||||
} else {
|
} else {
|
||||||
k->set_pressed(false);
|
ke.pressed = false;
|
||||||
}
|
}
|
||||||
} else if (key == 0x3b || key == 0x3e) {
|
} else if (key == 0x3b || key == 0x3e) {
|
||||||
if (mod & NSEventModifierFlagControl) {
|
if (mod & NSEventModifierFlagControl) {
|
||||||
mod &= ~NSEventModifierFlagControl;
|
mod &= ~NSEventModifierFlagControl;
|
||||||
k->set_pressed(true);
|
ke.pressed = true;
|
||||||
} else {
|
} else {
|
||||||
k->set_pressed(false);
|
ke.pressed = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
get_key_modifier_state(mod, k);
|
ke.osx_state = mod;
|
||||||
k->set_scancode(latin_keyboard_keycode_convert(translateKey(key)));
|
ke.scancode = latin_keyboard_keycode_convert(translateKey(key));
|
||||||
|
ke.unicode = 0;
|
||||||
|
|
||||||
OS_OSX::singleton->push_input(k);
|
OS_OSX::singleton->key_event_buffer[OS_OSX::singleton->key_event_pos++] = ke;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)keyUp:(NSEvent *)event {
|
- (void)keyUp:(NSEvent *)event {
|
||||||
|
|
||||||
Ref<InputEventKey> k;
|
if (!imeMode) {
|
||||||
k.instance();
|
|
||||||
|
|
||||||
get_key_modifier_state([event modifierFlags], k);
|
OS_OSX::KeyEvent ke;
|
||||||
k->set_pressed(false);
|
|
||||||
k->set_scancode(latin_keyboard_keycode_convert(translateKey([event keyCode])));
|
|
||||||
|
|
||||||
OS_OSX::singleton->push_input(k);
|
ke.osx_state = [event modifierFlags];
|
||||||
|
ke.pressed = false;
|
||||||
|
ke.echo = false;
|
||||||
|
ke.scancode = latin_keyboard_keycode_convert(translateKey([event keyCode]));
|
||||||
|
ke.unicode = 0;
|
||||||
|
|
||||||
|
OS_OSX::singleton->key_event_buffer[OS_OSX::singleton->key_event_pos++] = ke;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sendScrollEvent(int button, double factor, int modifierFlags) {
|
inline void sendScrollEvent(int button, double factor, int modifierFlags) {
|
||||||
|
@ -2060,11 +2067,49 @@ void OS_OSX::process_events() {
|
||||||
|
|
||||||
[NSApp sendEvent:event];
|
[NSApp sendEvent:event];
|
||||||
}
|
}
|
||||||
|
process_key_events();
|
||||||
|
|
||||||
[autoreleasePool drain];
|
[autoreleasePool drain];
|
||||||
autoreleasePool = [[NSAutoreleasePool alloc] init];
|
autoreleasePool = [[NSAutoreleasePool alloc] init];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OS_OSX::process_key_events() {
|
||||||
|
|
||||||
|
Ref<InputEventKey> k;
|
||||||
|
for (int i = 0; i < key_event_pos; i++) {
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
key_event_pos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void OS_OSX::push_input(const Ref<InputEvent> &p_event) {
|
void OS_OSX::push_input(const Ref<InputEvent> &p_event) {
|
||||||
|
|
||||||
Ref<InputEvent> ev = p_event;
|
Ref<InputEvent> ev = p_event;
|
||||||
|
@ -2184,6 +2229,7 @@ OS_OSX *OS_OSX::singleton = NULL;
|
||||||
|
|
||||||
OS_OSX::OS_OSX() {
|
OS_OSX::OS_OSX() {
|
||||||
|
|
||||||
|
key_event_pos = 0;
|
||||||
mouse_mode = OS::MOUSE_MODE_VISIBLE;
|
mouse_mode = OS::MOUSE_MODE_VISIBLE;
|
||||||
main_loop = NULL;
|
main_loop = NULL;
|
||||||
singleton = this;
|
singleton = this;
|
||||||
|
|
Loading…
Reference in a new issue