diff --git a/shell/platform/darwin/macos/framework/Source/FlutterChannelKeyResponder.mm b/shell/platform/darwin/macos/framework/Source/FlutterChannelKeyResponder.mm index b6aaae1376247..29436dec17ea1 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterChannelKeyResponder.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterChannelKeyResponder.mm @@ -39,6 +39,8 @@ - (nonnull instancetype)initWithChannel:(nonnull FlutterBasicMessageChannel*)cha } - (void)handleEvent:(NSEvent*)event callback:(FlutterAsyncKeyCallback)callback { + // Remove the modifier bits that Flutter is not interested in. + NSEventModifierFlags modifierFlags = event.modifierFlags & ~0x100; NSString* type; switch (event.type) { case NSEventTypeKeyDown: @@ -48,9 +50,9 @@ - (void)handleEvent:(NSEvent*)event callback:(FlutterAsyncKeyCallback)callback { type = @"keyup"; break; case NSEventTypeFlagsChanged: - if (event.modifierFlags < _previouslyPressedFlags) { + if (modifierFlags < _previouslyPressedFlags) { type = @"keyup"; - } else if (event.modifierFlags > _previouslyPressedFlags) { + } else if (modifierFlags > _previouslyPressedFlags) { type = @"keydown"; } else { // ignore duplicate modifiers; This can happen in situations like switching @@ -61,7 +63,7 @@ - (void)handleEvent:(NSEvent*)event callback:(FlutterAsyncKeyCallback)callback { default: NSAssert(false, @"Unexpected key event type (got %lu).", event.type); } - _previouslyPressedFlags = event.modifierFlags; + _previouslyPressedFlags = modifierFlags; NSMutableDictionary* keyMessage = [@{ @"keymap" : @"macos", @"type" : type, diff --git a/shell/platform/darwin/macos/framework/Source/FlutterChannelKeyResponderUnittests.mm b/shell/platform/darwin/macos/framework/Source/FlutterChannelKeyResponderUnittests.mm index 01254d6b7c780..d5629e900bea8 100644 --- a/shell/platform/darwin/macos/framework/Source/FlutterChannelKeyResponderUnittests.mm +++ b/shell/platform/darwin/macos/framework/Source/FlutterChannelKeyResponderUnittests.mm @@ -52,9 +52,20 @@ callback(keyMessage); })); - // Key down FlutterChannelKeyResponder* responder = [[FlutterChannelKeyResponder alloc] initWithChannel:mockKeyEventChannel]; + + // Initial empty modifiers. This can happen when user opens window while modifier key is pressed + // and then releases the modifier. Shouldn't result in an event being sent. + // Regression test for https://github.com/flutter/flutter/issues/87339. + [responder handleEvent:keyEvent(NSEventTypeFlagsChanged, 0x100, @"", @"", FALSE, 60) + callback:^(BOOL handled) { + [responses addObject:@(handled)]; + }]; + + EXPECT_EQ([messages count], 0u); + + // Key down [responder handleEvent:keyEvent(NSEventTypeKeyDown, 0x100, @"a", @"a", FALSE, 0) callback:^(BOOL handled) { [responses addObject:@(handled)];