From 041a3eaa849c2d1370846475f03b62bfa6921214 Mon Sep 17 00:00:00 2001 From: Greg Spencer Date: Wed, 19 Aug 2020 15:03:17 -0700 Subject: [PATCH] Standardize the nullability of arguments to raw key data constructors. (#63523) This standardizes the handling of nullability for the LogicalKeyboardKey.keyLabel and RawKeyEventData.keyLabel accessors so that they are non-nullable, but can be empty. Before this change, the keyLabel could be either null or an empty string to indicate that there wasn't a label, which makes it harder to test for, since both need to be checked for. Since an empty string is sufficient, there is no need for it to be nullable. Also, in raw_keyboard.dart, the web and Windows implementations wouldn't accept null values for parameters in the Map coming from the message, but tests were supplying null for some of them. This makes web and Windows creation of events match the other platforms, and makes the migration of tests to non-nullability easier. --- dev/tools/gen_keycodes/data/keyboard_key.tmpl | 12 ++-- .../lib/src/services/keyboard_key.dart | 11 ++-- .../lib/src/services/raw_keyboard.dart | 18 +++--- .../src/services/raw_keyboard_android.dart | 6 +- .../src/services/raw_keyboard_fuchsia.dart | 2 +- .../lib/src/services/raw_keyboard_linux.dart | 8 +-- .../lib/src/services/raw_keyboard_macos.dart | 46 ++++++++------- .../lib/src/services/raw_keyboard_web.dart | 4 +- .../src/services/raw_keyboard_windows.dart | 13 ++--- .../test/services/raw_keyboard_test.dart | 58 +++++++------------ .../lib/src/event_simulation.dart | 12 +++- 11 files changed, 89 insertions(+), 101 deletions(-) diff --git a/dev/tools/gen_keycodes/data/keyboard_key.tmpl b/dev/tools/gen_keycodes/data/keyboard_key.tmpl index 80cf3b4d00..37da2944bf 100644 --- a/dev/tools/gen_keycodes/data/keyboard_key.tmpl +++ b/dev/tools/gen_keycodes/data/keyboard_key.tmpl @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -// @dart = 2.8 +import 'package:flutter/foundation.dart'; // DO NOT EDIT -- DO NOT EDIT -- DO NOT EDIT // This file is generated by dev/tools/gen_keycodes/bin/gen_keycodes.dart and @@ -11,8 +11,6 @@ // Edit the template dev/tools/gen_keycodes/data/keyboard_key.tmpl instead. // See dev/tools/gen_keycodes/README.md for more information. -import 'package:flutter/foundation.dart'; - /// A base class for all keyboard key types. /// /// See also: @@ -138,7 +136,7 @@ class LogicalKeyboardKey extends KeyboardKey { /// const LogicalKeyboardKey(0x0010000000a, debugName: kReleaseMode ? null : 'Special Key') /// ``` /// {@end-tool} - const LogicalKeyboardKey(this.keyId, {this.debugName, this.keyLabel}) + const LogicalKeyboardKey(this.keyId, {this.debugName, this.keyLabel = ''}) : assert(keyId != null); /// A unique code representing this key. @@ -156,7 +154,7 @@ class LogicalKeyboardKey extends KeyboardKey { /// This value is useful for describing or matching mnemonic keyboard /// shortcuts. /// - /// This value can be null if there's no key label data for a key. + /// This value is an empty string if there's no key label data for a key. /// /// On most platforms this is a single code point, but it could contain any /// Unicode string. The `keyLabel` differs from [RawKeyEvent.character] @@ -166,7 +164,7 @@ class LogicalKeyboardKey extends KeyboardKey { /// “o” for [keyLabel], but would return “ö” for [RawKeyEvent.character]. /// /// {@macro flutter.services.RawKeyEventData.keyLabel} - final String? keyLabel; + final String keyLabel; @override int get hashCode => keyId.hashCode; @@ -194,7 +192,7 @@ class LogicalKeyboardKey extends KeyboardKey { /// /// Used by [RawKeyEvent] subclasses to help construct IDs. static bool isControlCharacter(String label) { - if (label.length > 1) { + if (label.length != 1) { return false; } final int codeUnit = label.codeUnitAt(0); diff --git a/packages/flutter/lib/src/services/keyboard_key.dart b/packages/flutter/lib/src/services/keyboard_key.dart index 63e560f8d6..e80f5e674b 100644 --- a/packages/flutter/lib/src/services/keyboard_key.dart +++ b/packages/flutter/lib/src/services/keyboard_key.dart @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:flutter/foundation.dart'; // DO NOT EDIT -- DO NOT EDIT -- DO NOT EDIT // This file is generated by dev/tools/gen_keycodes/bin/gen_keycodes.dart and @@ -10,8 +11,6 @@ // Edit the template dev/tools/gen_keycodes/data/keyboard_key.tmpl instead. // See dev/tools/gen_keycodes/README.md for more information. -import 'package:flutter/foundation.dart'; - /// A base class for all keyboard key types. /// /// See also: @@ -137,7 +136,7 @@ class LogicalKeyboardKey extends KeyboardKey { /// const LogicalKeyboardKey(0x0010000000a, debugName: kReleaseMode ? null : 'Special Key') /// ``` /// {@end-tool} - const LogicalKeyboardKey(this.keyId, {this.debugName, this.keyLabel}) + const LogicalKeyboardKey(this.keyId, {this.debugName, this.keyLabel = ''}) : assert(keyId != null); /// A unique code representing this key. @@ -155,7 +154,7 @@ class LogicalKeyboardKey extends KeyboardKey { /// This value is useful for describing or matching mnemonic keyboard /// shortcuts. /// - /// This value can be null if there's no key label data for a key. + /// This value is an empty string if there's no key label data for a key. /// /// On most platforms this is a single code point, but it could contain any /// Unicode string. The `keyLabel` differs from [RawKeyEvent.character] @@ -165,7 +164,7 @@ class LogicalKeyboardKey extends KeyboardKey { /// “o” for [keyLabel], but would return “ö” for [RawKeyEvent.character]. /// /// {@macro flutter.services.RawKeyEventData.keyLabel} - final String? keyLabel; + final String keyLabel; @override int get hashCode => keyId.hashCode; @@ -193,7 +192,7 @@ class LogicalKeyboardKey extends KeyboardKey { /// /// Used by [RawKeyEvent] subclasses to help construct IDs. static bool isControlCharacter(String label) { - if (label.length > 1) { + if (label.length != 1) { return false; } final int codeUnit = label.codeUnitAt(0); diff --git a/packages/flutter/lib/src/services/raw_keyboard.dart b/packages/flutter/lib/src/services/raw_keyboard.dart index 7a12ea58e7..46e49dd405 100644 --- a/packages/flutter/lib/src/services/raw_keyboard.dart +++ b/packages/flutter/lib/src/services/raw_keyboard.dart @@ -213,6 +213,8 @@ abstract class RawKeyEventData { /// Returns the Unicode string representing the label on this key. /// + /// This value is an empty string if there's no key label data for a key. + /// /// {@template flutter.services.RawKeyEventData.keyLabel} /// Do not use the [keyLabel] to compose a text string: it will be missing /// special processing for Unicode strings for combining characters and other @@ -226,7 +228,7 @@ abstract class RawKeyEventData { /// complexities of managing keyboard input, like showing a soft keyboard or /// interacting with an input method editor (IME). /// {@endtemplate} - String? get keyLabel; + String get keyLabel; } /// Defines the interface for raw key events. @@ -308,17 +310,17 @@ abstract class RawKeyEvent with Diagnosticable { break; case 'web': data = RawKeyEventDataWeb( - code: message['code'] as String, - key: message['key'] as String, - metaState: message['metaState'] as int, + code: message['code'] as String? ?? '', + key: message['key'] as String? ?? '', + metaState: message['metaState'] as int? ?? 0, ); break; case 'windows': data = RawKeyEventDataWindows( - keyCode: message['keyCode'] as int, - scanCode: message['scanCode'] as int, - characterCodePoint: message['characterCodePoint'] as int, - modifiers: message['modifiers'] as int, + keyCode: message['keyCode'] as int? ?? 0, + scanCode: message['scanCode'] as int? ?? 0, + characterCodePoint: message['characterCodePoint'] as int? ?? 0, + modifiers: message['modifiers'] as int? ?? 0, ); break; default: diff --git a/packages/flutter/lib/src/services/raw_keyboard_android.dart b/packages/flutter/lib/src/services/raw_keyboard_android.dart index 12a972bf08..4d92b4485a 100644 --- a/packages/flutter/lib/src/services/raw_keyboard_android.dart +++ b/packages/flutter/lib/src/services/raw_keyboard_android.dart @@ -147,7 +147,7 @@ class RawKeyEventDataAndroid extends RawKeyEventData { // Android only reports a single code point for the key label. @override - String? get keyLabel => plainCodePoint == 0 ? null : String.fromCharCode(plainCodePoint & _kCombiningCharacterMask); + String get keyLabel => plainCodePoint == 0 ? '' : String.fromCharCode(plainCodePoint & _kCombiningCharacterMask); @override PhysicalKeyboardKey get physicalKey { @@ -191,13 +191,13 @@ class RawKeyEventDataAndroid extends RawKeyEventData { // constant, or construct a new Unicode-based key from it. Don't mark it as // autogenerated, since the label uniquely identifies an ID from the Unicode // plane. - if (keyLabel != null && keyLabel!.isNotEmpty && !LogicalKeyboardKey.isControlCharacter(keyLabel!)) { + if (keyLabel.isNotEmpty && !LogicalKeyboardKey.isControlCharacter(keyLabel)) { final int combinedCodePoint = plainCodePoint & _kCombiningCharacterMask; final int keyId = LogicalKeyboardKey.unicodePlane | (combinedCodePoint & LogicalKeyboardKey.valueMask); return LogicalKeyboardKey.findKeyByKeyId(keyId) ?? LogicalKeyboardKey( keyId, keyLabel: keyLabel, - debugName: kReleaseMode ? null : 'Key ${keyLabel!.toUpperCase()}', + debugName: kReleaseMode ? null : 'Key ${keyLabel.toUpperCase()}', ); } diff --git a/packages/flutter/lib/src/services/raw_keyboard_fuchsia.dart b/packages/flutter/lib/src/services/raw_keyboard_fuchsia.dart index f8b53dcaae..fff0e91451 100644 --- a/packages/flutter/lib/src/services/raw_keyboard_fuchsia.dart +++ b/packages/flutter/lib/src/services/raw_keyboard_fuchsia.dart @@ -61,7 +61,7 @@ class RawKeyEventDataFuchsia extends RawKeyEventData { // Fuchsia only reports a single code point for the key label. @override - String? get keyLabel => codePoint == 0 ? null : String.fromCharCode(codePoint); + String get keyLabel => codePoint == 0 ? '' : String.fromCharCode(codePoint); @override LogicalKeyboardKey get logicalKey { diff --git a/packages/flutter/lib/src/services/raw_keyboard_linux.dart b/packages/flutter/lib/src/services/raw_keyboard_linux.dart index 990712cf83..7ea87d88c3 100644 --- a/packages/flutter/lib/src/services/raw_keyboard_linux.dart +++ b/packages/flutter/lib/src/services/raw_keyboard_linux.dart @@ -70,7 +70,7 @@ class RawKeyEventDataLinux extends RawKeyEventData { final bool isDown; @override - String? get keyLabel => unicodeScalarValues == 0 ? null : String.fromCharCode(unicodeScalarValues); + String get keyLabel => unicodeScalarValues == 0 ? '' : String.fromCharCode(unicodeScalarValues); @override PhysicalKeyboardKey get physicalKey => kLinuxToPhysicalKey[scanCode] ?? PhysicalKeyboardKey.none; @@ -89,13 +89,13 @@ class RawKeyEventDataLinux extends RawKeyEventData { // constant, or construct a new Unicode-based key from it. Don't mark it as // autogenerated, since the label uniquely identifies an ID from the Unicode // plane. - if (keyLabel != null && - !LogicalKeyboardKey.isControlCharacter(keyLabel!)) { + if (keyLabel.isNotEmpty && + !LogicalKeyboardKey.isControlCharacter(keyLabel)) { final int keyId = LogicalKeyboardKey.unicodePlane | (unicodeScalarValues & LogicalKeyboardKey.valueMask); return LogicalKeyboardKey.findKeyByKeyId(keyId) ?? LogicalKeyboardKey( keyId, keyLabel: keyLabel, - debugName: kReleaseMode ? null : 'Key ${keyLabel!.toUpperCase()}', + debugName: kReleaseMode ? null : 'Key ${keyLabel.toUpperCase()}', ); } diff --git a/packages/flutter/lib/src/services/raw_keyboard_macos.dart b/packages/flutter/lib/src/services/raw_keyboard_macos.dart index 60797b92a6..45148ed7aa 100644 --- a/packages/flutter/lib/src/services/raw_keyboard_macos.dart +++ b/packages/flutter/lib/src/services/raw_keyboard_macos.dart @@ -62,7 +62,7 @@ class RawKeyEventDataMacOs extends RawKeyEventData { final int modifiers; @override - String? get keyLabel => charactersIgnoringModifiers.isEmpty ? null : charactersIgnoringModifiers; + String get keyLabel => charactersIgnoringModifiers; @override PhysicalKeyboardKey get physicalKey => kMacOsToPhysicalKey[keyCode] ?? PhysicalKeyboardKey.none; @@ -76,15 +76,17 @@ class RawKeyEventDataMacOs extends RawKeyEventData { if (numPadKey != null) { return numPadKey; } - // If this key is printable, generate the LogicalKeyboardKey from its Unicode value. - // Control keys such as ESC, CRTL, and SHIFT are not printable. HOME, DEL, arrow keys, and function - // keys are considered modifier function keys, which generate invalid Unicode scalar values. - if (keyLabel != null && - !LogicalKeyboardKey.isControlCharacter(keyLabel!) && - !_isUnprintableKey(keyLabel!)) { - // Given that charactersIgnoringModifiers can contain a String of arbitrary length, - // limit to a maximum of two Unicode scalar values. It is unlikely that a keyboard would produce a code point - // bigger than 32 bits, but it is still worth defending against this case. + // If this key is printable, generate the LogicalKeyboardKey from its + // Unicode value. Control keys such as ESC, CRTL, and SHIFT are not + // printable. HOME, DEL, arrow keys, and function keys are considered + // modifier function keys, which generate invalid Unicode scalar values. + if (keyLabel.isNotEmpty && + !LogicalKeyboardKey.isControlCharacter(keyLabel) && + !_isUnprintableKey(keyLabel)) { + // Given that charactersIgnoringModifiers can contain a String of + // arbitrary length, limit to a maximum of two Unicode scalar values. It + // is unlikely that a keyboard would produce a code point bigger than 32 + // bits, but it is still worth defending against this case. assert(charactersIgnoringModifiers.length <= 2); int codeUnit = charactersIgnoringModifiers.codeUnitAt(0); if (charactersIgnoringModifiers.length == 2) { @@ -96,20 +98,21 @@ class RawKeyEventDataMacOs extends RawKeyEventData { return LogicalKeyboardKey.findKeyByKeyId(keyId) ?? LogicalKeyboardKey( keyId, keyLabel: keyLabel, - debugName: kReleaseMode ? null : 'Key ${keyLabel!.toUpperCase()}', + debugName: kReleaseMode ? null : 'Key ${keyLabel.toUpperCase()}', ); } - // Control keys like "backspace" and movement keys like arrow keys don't have a printable representation, - // but are present on the physical keyboard. Since there is no logical keycode map for macOS - // (macOS uses the keycode to reference physical keys), a LogicalKeyboardKey is created with - // the physical key's HID usage and debugName. This avoids duplicating the physical - // key map. + // Control keys like "backspace" and movement keys like arrow keys don't + // have a printable representation, but are present on the physical + // keyboard. Since there is no logical keycode map for macOS (macOS uses the + // keycode to reference physical keys), a LogicalKeyboardKey is created with + // the physical key's HID usage and debugName. This avoids duplicating the + // physical key map. if (physicalKey != PhysicalKeyboardKey.none) { final int keyId = physicalKey.usbHidUsage | LogicalKeyboardKey.hidPlane; return LogicalKeyboardKey.findKeyByKeyId(keyId) ?? LogicalKeyboardKey( keyId, - keyLabel: physicalKey.debugName, + keyLabel: physicalKey.debugName ?? '', debugName: physicalKey.debugName, ); } @@ -129,10 +132,9 @@ class RawKeyEventDataMacOs extends RawKeyEventData { return false; } // If only the "anyMask" bit is set, then we respond true for requests of - // whether either left or right is pressed. - // Handles the case where macOS supplies just the "either" modifier flag, - // but not the left/right flag. (e.g. modifierShift but not - // modifierLeftShift). + // whether either left or right is pressed. Handles the case where macOS + // supplies just the "either" modifier flag, but not the left/right flag. + // (e.g. modifierShift but not modifierLeftShift). final bool anyOnly = modifiers & (leftMask | rightMask | anyMask) == anyMask; switch (side) { case KeyboardSide.any: @@ -229,7 +231,7 @@ class RawKeyEventDataMacOs extends RawKeyEventData { /// /// Used by [RawKeyEvent] subclasses to help construct IDs. static bool _isUnprintableKey(String label) { - if (label.length > 1) { + if (label.length != 1) { return false; } final int codeUnit = label.codeUnitAt(0); diff --git a/packages/flutter/lib/src/services/raw_keyboard_web.dart b/packages/flutter/lib/src/services/raw_keyboard_web.dart index 77b399efcd..3e0edde068 100644 --- a/packages/flutter/lib/src/services/raw_keyboard_web.dart +++ b/packages/flutter/lib/src/services/raw_keyboard_web.dart @@ -36,7 +36,7 @@ class RawKeyEventDataWeb extends RawKeyEventData { /// /// See /// for more information. - final String? key; + final String key; /// The modifiers that were present when the key event occurred. /// @@ -56,7 +56,7 @@ class RawKeyEventDataWeb extends RawKeyEventData { final int metaState; @override - String? get keyLabel => key; + String get keyLabel => key == 'Unidentified' ? '' : key; @override PhysicalKeyboardKey get physicalKey { diff --git a/packages/flutter/lib/src/services/raw_keyboard_windows.dart b/packages/flutter/lib/src/services/raw_keyboard_windows.dart index 1d81eddbea..a88ee17081 100644 --- a/packages/flutter/lib/src/services/raw_keyboard_windows.dart +++ b/packages/flutter/lib/src/services/raw_keyboard_windows.dart @@ -54,7 +54,7 @@ class RawKeyEventDataWindows extends RawKeyEventData { final int modifiers; @override - String? get keyLabel => characterCodePoint == 0 ? null : String.fromCharCode(characterCodePoint); + String get keyLabel => characterCodePoint == 0 ? '' : String.fromCharCode(characterCodePoint); @override PhysicalKeyboardKey get physicalKey => kWindowsToPhysicalKey[scanCode] ?? PhysicalKeyboardKey.none; @@ -73,12 +73,12 @@ class RawKeyEventDataWindows extends RawKeyEventData { // constant, or construct a new Unicode-based key from it. Don't mark it as // autogenerated, since the label uniquely identifies an ID from the Unicode // plane. - if (keyLabel != null && keyLabel!.isNotEmpty && !LogicalKeyboardKey.isControlCharacter(keyLabel!)) { + if (keyLabel.isNotEmpty && !LogicalKeyboardKey.isControlCharacter(keyLabel)) { final int keyId = LogicalKeyboardKey.unicodePlane | (characterCodePoint & LogicalKeyboardKey.valueMask); return LogicalKeyboardKey.findKeyByKeyId(keyId) ?? LogicalKeyboardKey( keyId, keyLabel: keyLabel, - debugName: kReleaseMode ? null : 'Key ${keyLabel!.toUpperCase()}', + debugName: kReleaseMode ? null : 'Key ${keyLabel.toUpperCase()}', ); } // Look to see if the keyCode is one we know about and have a mapping for. @@ -104,10 +104,9 @@ class RawKeyEventDataWindows extends RawKeyEventData { return false; } // If only the "anyMask" bit is set, then we respond true for requests of - // whether either left or right is pressed. - // Handles the case where Windows supplies just the "either" modifier flag, - // but not the left/right flag. (e.g. modifierShift but not - // modifierLeftShift). + // whether either left or right is pressed. Handles the case where Windows + // supplies just the "either" modifier flag, but not the left/right flag. + // (e.g. modifierShift but not modifierLeftShift). final bool anyOnly = modifiers & (leftMask | rightMask | anyMask) == anyMask; switch (side) { case KeyboardSide.any: diff --git a/packages/flutter/test/services/raw_keyboard_test.dart b/packages/flutter/test/services/raw_keyboard_test.dart index 5b28d13ab3..a19c5bb2c6 100644 --- a/packages/flutter/test/services/raw_keyboard_test.dart +++ b/packages/flutter/test/services/raw_keyboard_test.dart @@ -601,7 +601,6 @@ void main() { 'keymap': 'android', 'keyCode': 111, 'codePoint': 0, - 'character': null, 'scanCode': 1, 'metaState': 0x0, 'source': 0x101, // Keyboard source. @@ -610,7 +609,7 @@ void main() { final RawKeyEventDataAndroid data = escapeKeyEvent.data as RawKeyEventDataAndroid; expect(data.physicalKey, equals(PhysicalKeyboardKey.escape)); expect(data.logicalKey, equals(LogicalKeyboardKey.escape)); - expect(data.keyLabel, isNull); + expect(data.keyLabel, isEmpty); }); test('Modifier keyboard keys are correctly translated', () { final RawKeyEvent shiftLeftKeyEvent = RawKeyEvent.fromMessage(const { @@ -619,7 +618,6 @@ void main() { 'keyCode': 59, 'plainCodePoint': 0, 'codePoint': 0, - 'character': null, 'scanCode': 42, 'metaState': RawKeyEventDataAndroid.modifierLeftShift, 'source': 0x101, // Keyboard source. @@ -628,7 +626,7 @@ void main() { final RawKeyEventDataAndroid data = shiftLeftKeyEvent.data as RawKeyEventDataAndroid; expect(data.physicalKey, equals(PhysicalKeyboardKey.shiftLeft)); expect(data.logicalKey, equals(LogicalKeyboardKey.shiftLeft)); - expect(data.keyLabel, isNull); + expect(data.keyLabel, isEmpty); }); test('DPAD keys from a joystick give physical key mappings', () { final RawKeyEvent joystickDpadDown = RawKeyEvent.fromMessage(const { @@ -637,7 +635,6 @@ void main() { 'keyCode': 20, 'plainCodePoint': 0, 'codePoint': 0, - 'character': null, 'scanCode': 0, 'metaState': 0, 'source': 0x1000010, // Joystick source. @@ -646,7 +643,7 @@ void main() { final RawKeyEventDataAndroid data = joystickDpadDown.data as RawKeyEventDataAndroid; expect(data.physicalKey, equals(PhysicalKeyboardKey.arrowDown)); expect(data.logicalKey, equals(LogicalKeyboardKey.arrowDown)); - expect(data.keyLabel, isNull); + expect(data.keyLabel, isEmpty); }); test('Arrow keys from a keyboard give correct physical key mappings', () { final RawKeyEvent joystickDpadDown = RawKeyEvent.fromMessage(const { @@ -655,7 +652,6 @@ void main() { 'keyCode': 20, 'plainCodePoint': 0, 'codePoint': 0, - 'character': null, 'scanCode': 108, 'metaState': 0, 'source': 0x101, // Keyboard source. @@ -663,7 +659,7 @@ void main() { final RawKeyEventDataAndroid data = joystickDpadDown.data as RawKeyEventDataAndroid; expect(data.physicalKey, equals(PhysicalKeyboardKey.arrowDown)); expect(data.logicalKey, equals(LogicalKeyboardKey.arrowDown)); - expect(data.keyLabel, isNull); + expect(data.keyLabel, isEmpty); }); test('DPAD center from a game pad gives physical key mappings', () { final RawKeyEvent joystickDpadCenter = RawKeyEvent.fromMessage(const { @@ -672,7 +668,6 @@ void main() { 'keyCode': 23, // DPAD_CENTER code. 'plainCodePoint': 0, 'codePoint': 0, - 'character': null, 'scanCode': 317, // Left side thumb joystick center click button. 'metaState': 0, 'source': 0x501, // Gamepad and keyboard source. @@ -681,7 +676,7 @@ void main() { final RawKeyEventDataAndroid data = joystickDpadCenter.data as RawKeyEventDataAndroid; expect(data.physicalKey, equals(PhysicalKeyboardKey.gameButtonThumbLeft)); expect(data.logicalKey, equals(LogicalKeyboardKey.select)); - expect(data.keyLabel, isNull); + expect(data.keyLabel, isEmpty); }); test('Device id is read from message', () { final RawKeyEvent joystickDpadCenter = RawKeyEvent.fromMessage(const { @@ -690,7 +685,6 @@ void main() { 'keyCode': 23, // DPAD_CENTER code. 'plainCodePoint': 0, 'codePoint': 0, - 'character': null, 'scanCode': 317, // Left side thumb joystick center click button. 'metaState': 0, 'source': 0x501, // Gamepad and keyboard source. @@ -853,13 +847,11 @@ void main() { 'type': 'keydown', 'keymap': 'fuchsia', 'hidUsage': 0x00070029, - 'codePoint': null, - 'character': null, }); final RawKeyEventDataFuchsia data = escapeKeyEvent.data as RawKeyEventDataFuchsia; expect(data.physicalKey, equals(PhysicalKeyboardKey.escape)); expect(data.logicalKey, equals(LogicalKeyboardKey.escape)); - expect(data.keyLabel, isNull); + expect(data.keyLabel, isEmpty); }, skip: isBrowser); // https://github.com/flutter/flutter/issues/35347 test('Modifier keyboard keys are correctly translated', () { @@ -867,13 +859,11 @@ void main() { 'type': 'keydown', 'keymap': 'fuchsia', 'hidUsage': 0x000700e1, - 'codePoint': null, - 'character': null, }); final RawKeyEventDataFuchsia data = shiftLeftKeyEvent.data as RawKeyEventDataFuchsia; expect(data.physicalKey, equals(PhysicalKeyboardKey.shiftLeft)); expect(data.logicalKey, equals(LogicalKeyboardKey.shiftLeft)); - expect(data.keyLabel, isNull); + expect(data.keyLabel, isEmpty); }, skip: isBrowser); // https://github.com/flutter/flutter/issues/35347 }); @@ -985,13 +975,12 @@ void main() { 'keyCode': 0x00000035, 'characters': '', 'charactersIgnoringModifiers': '', - 'character': null, 'modifiers': 0x0, }); final RawKeyEventDataMacOs data = escapeKeyEvent.data as RawKeyEventDataMacOs; expect(data.physicalKey, equals(PhysicalKeyboardKey.escape)); expect(data.logicalKey, equals(LogicalKeyboardKey.escape)); - expect(data.keyLabel, isNull); + expect(data.keyLabel, isEmpty); }, skip: isBrowser); // https://github.com/flutter/flutter/issues/35347 test('Modifier keyboard keys are correctly translated', () { @@ -1001,13 +990,12 @@ void main() { 'keyCode': 0x00000038, 'characters': '', 'charactersIgnoringModifiers': '', - 'character': null, 'modifiers': RawKeyEventDataMacOs.modifierLeftShift, }); final RawKeyEventDataMacOs data = shiftLeftKeyEvent.data as RawKeyEventDataMacOs; expect(data.physicalKey, equals(PhysicalKeyboardKey.shiftLeft)); expect(data.logicalKey, equals(LogicalKeyboardKey.shiftLeft)); - expect(data.keyLabel, isNull); + expect(data.keyLabel, isEmpty); }, skip: isBrowser); // https://github.com/flutter/flutter/issues/35347 test('Unprintable keyboard keys are correctly translated', () { @@ -1017,13 +1005,12 @@ void main() { 'keyCode': 0x0000007B, 'characters': '', 'charactersIgnoringModifiers': '', // NSLeftArrowFunctionKey = 0xF702 - 'character': null, 'modifiers': RawKeyEventDataMacOs.modifierFunction, }); final RawKeyEventDataMacOs data = leftArrowKey.data as RawKeyEventDataMacOs; expect(data.physicalKey, equals(PhysicalKeyboardKey.arrowLeft)); expect(data.logicalKey, equals(LogicalKeyboardKey.arrowLeft)); - expect(data.logicalKey.keyLabel, isNull); + expect(data.logicalKey.keyLabel, isEmpty); }, skip: isBrowser); // https://github.com/flutter/flutter/issues/35347 }); @@ -1140,7 +1127,7 @@ void main() { final RawKeyEventDataWindows data = escapeKeyEvent.data as RawKeyEventDataWindows; expect(data.physicalKey, equals(PhysicalKeyboardKey.escape)); expect(data.logicalKey, equals(LogicalKeyboardKey.escape)); - expect(data.keyLabel, isNull); + expect(data.keyLabel, isEmpty); }); test('Modifier keyboard keys are correctly translated', () { final RawKeyEvent shiftLeftKeyEvent = RawKeyEvent.fromMessage(const { @@ -1154,7 +1141,7 @@ void main() { final RawKeyEventDataWindows data = shiftLeftKeyEvent.data as RawKeyEventDataWindows; expect(data.physicalKey, equals(PhysicalKeyboardKey.shiftLeft)); expect(data.logicalKey, equals(LogicalKeyboardKey.shiftLeft)); - expect(data.keyLabel, isNull); + expect(data.keyLabel, isEmpty); }); test('Unprintable keyboard keys are correctly translated', () { final RawKeyEvent leftArrowKey = RawKeyEvent.fromMessage(const { @@ -1168,7 +1155,7 @@ void main() { final RawKeyEventDataWindows data = leftArrowKey.data as RawKeyEventDataWindows; expect(data.physicalKey, equals(PhysicalKeyboardKey.arrowLeft)); expect(data.logicalKey, equals(LogicalKeyboardKey.arrowLeft)); - expect(data.logicalKey.keyLabel, isNull); + expect(data.logicalKey.keyLabel, isEmpty); }); }); @@ -1338,7 +1325,7 @@ void main() { final RawKeyEventDataLinux data = escapeKeyEvent.data as RawKeyEventDataLinux; expect(data.physicalKey, equals(PhysicalKeyboardKey.escape)); expect(data.logicalKey, equals(LogicalKeyboardKey.escape)); - expect(data.keyLabel, isNull); + expect(data.keyLabel, isEmpty); }); test('Modifier keyboard keys are correctly translated', () { final RawKeyEvent shiftLeftKeyEvent = RawKeyEvent.fromMessage(const { @@ -1352,7 +1339,7 @@ void main() { final RawKeyEventDataLinux data = shiftLeftKeyEvent.data as RawKeyEventDataLinux; expect(data.physicalKey, equals(PhysicalKeyboardKey.shiftLeft)); expect(data.logicalKey, equals(LogicalKeyboardKey.shiftLeft)); - expect(data.keyLabel, isNull); + expect(data.keyLabel, isEmpty); }); }); @@ -1522,7 +1509,7 @@ void main() { final RawKeyEventDataLinux data = escapeKeyEvent.data as RawKeyEventDataLinux; expect(data.physicalKey, equals(PhysicalKeyboardKey.escape)); expect(data.logicalKey, equals(LogicalKeyboardKey.escape)); - expect(data.keyLabel, isNull); + expect(data.keyLabel, isEmpty); }); test('Modifier keyboard keys are correctly translated', () { final RawKeyEvent shiftLeftKeyEvent = RawKeyEvent.fromMessage(const { @@ -1536,7 +1523,7 @@ void main() { final RawKeyEventDataLinux data = shiftLeftKeyEvent.data as RawKeyEventDataLinux; expect(data.physicalKey, equals(PhysicalKeyboardKey.shiftLeft)); expect(data.logicalKey, equals(LogicalKeyboardKey.shiftLeft)); - expect(data.keyLabel, isNull); + expect(data.keyLabel, isEmpty); }); }); @@ -1557,7 +1544,6 @@ void main() { 'type': 'keydown', 'keymap': 'web', 'code': 'RandomCode', - 'key': null, 'metaState': modifier, }); final RawKeyEventDataWeb data = event.data as RawKeyEventDataWeb; @@ -1588,7 +1574,6 @@ void main() { 'type': 'keydown', 'keymap': 'web', 'code': 'RandomCode', - 'key': null, 'metaState': modifier | RawKeyEventDataWeb.modifierMeta, }); final RawKeyEventDataWeb data = event.data as RawKeyEventDataWeb; @@ -1629,39 +1614,36 @@ void main() { 'type': 'keydown', 'keymap': 'web', 'code': 'Escape', - 'key': null, 'metaState': 0x0, }); final RawKeyEventDataWeb data = escapeKeyEvent.data as RawKeyEventDataWeb; expect(data.physicalKey, equals(PhysicalKeyboardKey.escape)); expect(data.logicalKey, equals(LogicalKeyboardKey.escape)); - expect(data.keyLabel, isNull); + expect(data.keyLabel, isEmpty); }); test('Modifier keyboard keys are correctly translated', () { final RawKeyEvent shiftKeyEvent = RawKeyEvent.fromMessage(const { 'type': 'keydown', 'keymap': 'web', 'code': 'ShiftLeft', - 'keyLabel': null, 'metaState': RawKeyEventDataWeb.modifierShift, }); final RawKeyEventDataWeb data = shiftKeyEvent.data as RawKeyEventDataWeb; expect(data.physicalKey, equals(PhysicalKeyboardKey.shiftLeft)); expect(data.logicalKey, equals(LogicalKeyboardKey.shiftLeft)); - expect(data.keyLabel, isNull); + expect(data.keyLabel, isEmpty); }); test('Arrow keys from a keyboard give correct physical key mappings', () { final RawKeyEvent arrowKeyDown = RawKeyEvent.fromMessage(const { 'type': 'keydown', 'keymap': 'web', 'code': 'ArrowDown', - 'key': null, 'metaState': 0x0, }); final RawKeyEventDataWeb data = arrowKeyDown.data as RawKeyEventDataWeb; expect(data.physicalKey, equals(PhysicalKeyboardKey.arrowDown)); expect(data.logicalKey, equals(LogicalKeyboardKey.arrowDown)); - expect(data.keyLabel, isNull); + expect(data.keyLabel, isEmpty); }); }); } diff --git a/packages/flutter_test/lib/src/event_simulation.dart b/packages/flutter_test/lib/src/event_simulation.dart index a38c87f048..f7a65f22a0 100644 --- a/packages/flutter_test/lib/src/event_simulation.dart +++ b/packages/flutter_test/lib/src/event_simulation.dart @@ -180,13 +180,17 @@ class KeyEventSimulator { switch (platform) { case 'android': result['keyCode'] = keyCode; - result['codePoint'] = key.keyLabel?.codeUnitAt(0); + if (key.keyLabel.isNotEmpty) { + result['codePoint'] = key.keyLabel.codeUnitAt(0); + } result['scanCode'] = scanCode; result['metaState'] = _getAndroidModifierFlags(key, isDown); break; case 'fuchsia': result['hidUsage'] = physicalKey?.usbHidUsage ?? (key.keyId & LogicalKeyboardKey.hidPlane != 0 ? key.keyId & LogicalKeyboardKey.valueMask : null); - result['codePoint'] = key.keyLabel?.codeUnitAt(0); + if (key.keyLabel.isNotEmpty) { + result['codePoint'] = key.keyLabel.codeUnitAt(0); + } result['modifiers'] = _getFuchsiaModifierFlags(key, isDown); break; case 'linux': @@ -209,7 +213,9 @@ class KeyEventSimulator { case 'windows': result['keyCode'] = keyCode; result['scanCode'] = scanCode; - result['characterCodePoint'] = key.keyLabel?.codeUnitAt(0) ?? 0; + if (key.keyLabel.isNotEmpty) { + result['characterCodePoint'] = key.keyLabel.codeUnitAt(0); + } result['modifiers'] = _getWindowsModifierFlags(key, isDown); } return result;