[macOS, Keyboard] Duplicate down events are no longer ignored, but kept and preceded by up events (flutter/engine#31800)
This commit is contained in:
@@ -680,12 +680,23 @@ const char* getEventString(NSString* characters) {
|
||||
bool isARepeat = event.isARepeat;
|
||||
NSNumber* pressedLogicalKey = _pressingRecords[@(physicalKey)];
|
||||
if (pressedLogicalKey != nil && !isARepeat) {
|
||||
// Normally the key up events won't be missed since macOS always sends the
|
||||
// key up event to the window where the corresponding key down occurred.
|
||||
// However this might happen in add-to-app scenarios if the focus is changed
|
||||
// This might happen in add-to-app scenarios if the focus is changed
|
||||
// from the native view to the Flutter view amid the key tap.
|
||||
[callback resolveTo:TRUE];
|
||||
return;
|
||||
//
|
||||
// This might also happen when a key event is forged (such as by an
|
||||
// IME) using the same keyCode as an unreleased key. See
|
||||
// https://github.com/flutter/flutter/issues/82673#issuecomment-988661079
|
||||
FlutterKeyEvent flutterEvent = {
|
||||
.struct_size = sizeof(FlutterKeyEvent),
|
||||
.timestamp = GetFlutterTimestampFrom(event.timestamp),
|
||||
.type = kFlutterKeyEventTypeUp,
|
||||
.physical = physicalKey,
|
||||
.logical = [pressedLogicalKey unsignedLongLongValue],
|
||||
.character = nil,
|
||||
.synthesized = true,
|
||||
};
|
||||
[self sendSynthesizedFlutterEvent:flutterEvent guard:callback];
|
||||
pressedLogicalKey = nil;
|
||||
}
|
||||
|
||||
if (pressedLogicalKey == nil) {
|
||||
|
||||
@@ -306,7 +306,7 @@ TEST(FlutterEmbedderKeyResponderUnittests, MultipleCharacters) {
|
||||
[events removeAllObjects];
|
||||
}
|
||||
|
||||
TEST(FlutterEmbedderKeyResponderUnittests, IgnoreDuplicateDownEvent) {
|
||||
TEST(FlutterEmbedderKeyResponderUnittests, SynthesizeForDuplicateDownEvent) {
|
||||
__block NSMutableArray<TestKeyEvent*>* events = [[NSMutableArray<TestKeyEvent*> alloc] init];
|
||||
__block BOOL last_handled = TRUE;
|
||||
FlutterKeyEvent* event;
|
||||
@@ -319,7 +319,7 @@ TEST(FlutterEmbedderKeyResponderUnittests, IgnoreDuplicateDownEvent) {
|
||||
userData:user_data]];
|
||||
}];
|
||||
|
||||
last_handled = FALSE;
|
||||
last_handled = TRUE;
|
||||
[responder handleEvent:keyEvent(NSEventTypeKeyDown, 0x100, @"a", @"a", FALSE, kKeyCodeKeyA)
|
||||
callback:^(BOOL handled) {
|
||||
last_handled = handled;
|
||||
@@ -332,44 +332,35 @@ TEST(FlutterEmbedderKeyResponderUnittests, IgnoreDuplicateDownEvent) {
|
||||
EXPECT_EQ(event->logical, kLogicalKeyA);
|
||||
EXPECT_STREQ(event->character, "a");
|
||||
EXPECT_EQ(event->synthesized, false);
|
||||
EXPECT_EQ(last_handled, TRUE);
|
||||
[[events lastObject] respond:FALSE];
|
||||
EXPECT_EQ(last_handled, FALSE);
|
||||
[[events lastObject] respond:TRUE];
|
||||
EXPECT_EQ(last_handled, TRUE);
|
||||
|
||||
[events removeAllObjects];
|
||||
|
||||
last_handled = FALSE;
|
||||
[responder handleEvent:keyEvent(NSEventTypeKeyDown, 0x100, @"a", @"a", FALSE, kKeyCodeKeyA)
|
||||
last_handled = TRUE;
|
||||
[responder handleEvent:keyEvent(NSEventTypeKeyDown, 0x100, @"à", @"à", FALSE, kKeyCodeKeyA)
|
||||
callback:^(BOOL handled) {
|
||||
last_handled = handled;
|
||||
}];
|
||||
|
||||
EXPECT_EQ([events count], 1u);
|
||||
EXPECT_EQ(last_handled, TRUE);
|
||||
event = [events lastObject].data;
|
||||
EXPECT_EQ(event->physical, 0ull);
|
||||
EXPECT_EQ(event->logical, 0ull);
|
||||
EXPECT_FALSE([[events lastObject] hasCallback]);
|
||||
EXPECT_EQ(last_handled, TRUE);
|
||||
EXPECT_EQ([events count], 2u);
|
||||
|
||||
[events removeAllObjects];
|
||||
|
||||
last_handled = FALSE;
|
||||
[responder handleEvent:keyEvent(NSEventTypeKeyUp, 0x100, @"a", @"a", FALSE, kKeyCodeKeyA)
|
||||
callback:^(BOOL handled) {
|
||||
last_handled = handled;
|
||||
}];
|
||||
|
||||
EXPECT_EQ([events count], 1u);
|
||||
event = [events lastObject].data;
|
||||
event = [events firstObject].data;
|
||||
EXPECT_EQ(event->type, kFlutterKeyEventTypeUp);
|
||||
EXPECT_EQ(event->physical, kPhysicalKeyA);
|
||||
EXPECT_EQ(event->logical, kLogicalKeyA);
|
||||
EXPECT_STREQ(event->character, nullptr);
|
||||
EXPECT_STREQ(event->character, NULL);
|
||||
EXPECT_EQ(event->synthesized, true);
|
||||
|
||||
event = [events lastObject].data;
|
||||
EXPECT_EQ(event->type, kFlutterKeyEventTypeDown);
|
||||
EXPECT_EQ(event->physical, kPhysicalKeyA);
|
||||
EXPECT_EQ(event->logical, 0xE0ull /* à */);
|
||||
EXPECT_STREQ(event->character, "à");
|
||||
EXPECT_EQ(event->synthesized, false);
|
||||
[[events lastObject] respond:FALSE];
|
||||
EXPECT_EQ(last_handled, FALSE);
|
||||
[[events lastObject] respond:TRUE];
|
||||
EXPECT_EQ(last_handled, TRUE);
|
||||
|
||||
[events removeAllObjects];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user