[Web+Linux] Fix pressing Meta keys throws (flutter/engine#41694)

## Description

This PR fixes Meta keys throwing exception on Chrome Linux.

The assertions throws because the DOM event sent when Meta keys is pressed is not coherent when Meta is the only pressed key.

## Related Issue

Fixes https://github.com/flutter/flutter/issues/125672

## Tests

Adds 1 test.
This commit is contained in:
Bruno Leroux 2023-05-12 23:46:17 +02:00 committed by GitHub
parent 015608f15e
commit fea415faa0
2 changed files with 34 additions and 0 deletions

View File

@ -6,6 +6,7 @@ import 'dart:async';
import 'dart:typed_data';
import '../engine.dart' show registerHotRestartListener;
import 'browser_detection.dart';
import 'dom.dart';
import 'keyboard_binding.dart';
import 'platform_dispatcher.dart';
@ -133,6 +134,9 @@ class RawKeyboard {
_lastMetaState |= modifierNumLock;
} else if (event.key == 'ScrollLock') {
_lastMetaState |= modifierScrollLock;
} else if (event.key == 'Meta' && operatingSystem == OperatingSystem.linux) {
// On Chrome Linux, metaState can be wrong when a Meta key is pressed.
_lastMetaState |= _modifierMeta;
}
}
final Map<String, dynamic> eventData = <String, dynamic>{

View File

@ -7,6 +7,7 @@ import 'dart:typed_data';
import 'package:quiver/testing/async.dart';
import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';
import 'package:ui/src/engine/browser_detection.dart';
import 'package:ui/src/engine/dom.dart';
import 'package:ui/src/engine/raw_keyboard.dart';
import 'package:ui/src/engine/services.dart';
@ -151,6 +152,35 @@ void testMain() {
RawKeyboard.instance!.dispose();
});
// Regression test for https://github.com/flutter/flutter/issues/125672.
test('updates meta state for Meta key and wrong DOM event metaKey value', () {
RawKeyboard.initialize();
Map<String, dynamic>? dataReceived;
ui.window.onPlatformMessage = (String channel, ByteData? data,
ui.PlatformMessageResponseCallback? callback) {
dataReceived = const JSONMessageCodec().decodeMessage(data) as Map<String, dynamic>?;
};
// Purposely send an incoherent DOM event where Meta key is pressed but event.metaKey is not set to true.
final DomKeyboardEvent event = dispatchKeyboardEvent(
'keydown',
key: 'Meta',
code: 'MetaLeft',
);
expect(event.defaultPrevented, isFalse);
expect(dataReceived, <String, dynamic>{
'type': 'keydown',
'keymap': 'web',
'code': 'MetaLeft',
'key': 'Meta',
'location': 0,
'metaState': 0x8,
'keyCode': 0,
});
RawKeyboard.instance!.dispose();
}, skip: operatingSystem != OperatingSystem.linux);
test('dispatches repeat events', () {
RawKeyboard.initialize();