Listen to keyUp event on meta modified keys (#13984)

This commit is contained in:
Francisco Magdaleno 2019-12-02 16:17:19 -08:00 committed by GitHub
parent ea721ebf1a
commit a68805bcf8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -100,6 +100,11 @@ struct KeyboardState {
*/
@property(nonatomic) KeyboardState keyboardState;
/**
* Event monitor for keyUp events.
*/
@property(nonatomic) id keyUpMonitor;
/**
* Starts running |engine|, including any initial setup.
*/
@ -241,6 +246,14 @@ static void CommonInit(FlutterViewController* controller) {
if (!_engine.running) {
[self launchEngine];
}
[self listenForMetaModifiedKeyUpEvents];
}
- (void)viewWillDisappear {
// Per Apple's documentation, it is discouraged to call removeMonitor: in dealloc, and it's
// recommended to be called earlier in the lifecycle.
[NSEvent removeMonitor:_keyUpMonitor];
_keyUpMonitor = nil;
}
- (void)dealloc {
@ -268,7 +281,6 @@ static void CommonInit(FlutterViewController* controller) {
}
- (void)removeKeyResponder:(NSResponder*)responder {
[self.additionalKeyResponders removeObject:responder];
}
#pragma mark - Private methods
@ -287,6 +299,27 @@ static void CommonInit(FlutterViewController* controller) {
return YES;
}
// macOS does not call keyUp: on a key while the command key is pressed. This results in a loss
// of a key event once the modified key is released. This method registers the
// ViewController as a listener for a keyUp event before it's handled by NSApplication, and should
// NOT modify the event to avoid any unexpected behavior.
- (void)listenForMetaModifiedKeyUpEvents {
NSAssert(_keyUpMonitor == nil, @"_keyUpMonitor was already created");
FlutterViewController* __weak weakSelf = self;
_keyUpMonitor = [NSEvent
addLocalMonitorForEventsMatchingMask:NSEventMaskKeyUp
handler:^NSEvent*(NSEvent* event) {
// Intercept keyUp only for events triggered on the current
// view.
if (weakSelf.view &&
([[event window] firstResponder] == weakSelf.view) &&
([event modifierFlags] & NSEventModifierFlagCommand) &&
([event type] == NSEventTypeKeyUp))
[weakSelf keyUp:event];
return event;
}];
}
- (void)configureTrackingArea {
if (_mouseTrackingMode != FlutterMouseTrackingModeNone && self.view) {
NSTrackingAreaOptions options =