diff --git a/lib/web_ui/lib/src/engine/raw_keyboard.dart b/lib/web_ui/lib/src/engine/raw_keyboard.dart index b2e2edc7cf7df..b299437b21f0e 100644 --- a/lib/web_ui/lib/src/engine/raw_keyboard.dart +++ b/lib/web_ui/lib/src/engine/raw_keyboard.dart @@ -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 eventData = { diff --git a/lib/web_ui/test/engine/raw_keyboard_test.dart b/lib/web_ui/test/engine/raw_keyboard_test.dart index 1cfae7fe706f0..d9f4cd0fe4036 100644 --- a/lib/web_ui/test/engine/raw_keyboard_test.dart +++ b/lib/web_ui/test/engine/raw_keyboard_test.dart @@ -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? dataReceived; + ui.window.onPlatformMessage = (String channel, ByteData? data, + ui.PlatformMessageResponseCallback? callback) { + dataReceived = const JSONMessageCodec().decodeMessage(data) as Map?; + }; + + // 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, { + '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();