RawKeyEventData classes support diagnostic and equality (#86679)
This PR changes RawKeyEventData so that they use Diagnosticable to construct toString, and use operator== and hashCode to compare.
diff --git a/packages/flutter/lib/src/services/raw_keyboard.dart b/packages/flutter/lib/src/services/raw_keyboard.dart
index 512ed64..ba67416 100644
--- a/packages/flutter/lib/src/services/raw_keyboard.dart
+++ b/packages/flutter/lib/src/services/raw_keyboard.dart
@@ -115,7 +115,7 @@
/// reference to [RawKeyEventData] subclasses.
/// * [RawKeyboard], which uses these interfaces to expose key data.
@immutable
-abstract class RawKeyEventData {
+abstract class RawKeyEventData with Diagnosticable {
/// Abstract const constructor. This constructor enables subclasses to provide
/// const constructors so that they can be used in const expressions.
const RawKeyEventData();
diff --git a/packages/flutter/lib/src/services/raw_keyboard_android.dart b/packages/flutter/lib/src/services/raw_keyboard_android.dart
index 8a68645..ddcd604 100644
--- a/packages/flutter/lib/src/services/raw_keyboard_android.dart
+++ b/packages/flutter/lib/src/services/raw_keyboard_android.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 'dart:ui' show hashValues;
import 'package:flutter/foundation.dart';
@@ -286,6 +287,42 @@
}
}
+ @override
+ void debugFillProperties(DiagnosticPropertiesBuilder properties) {
+ super.debugFillProperties(properties);
+ properties.add(DiagnosticsProperty<int>('flags', flags));
+ properties.add(DiagnosticsProperty<int>('codePoint', codePoint));
+ properties.add(DiagnosticsProperty<int>('plainCodePoint', plainCodePoint));
+ properties.add(DiagnosticsProperty<int>('keyCode', keyCode));
+ properties.add(DiagnosticsProperty<int>('scanCode', scanCode));
+ properties.add(DiagnosticsProperty<int>('metaState', metaState));
+ }
+
+ @override
+ bool operator==(Object other) {
+ if (identical(this, other))
+ return true;
+ if (other.runtimeType != runtimeType)
+ return false;
+ return other is RawKeyEventDataAndroid
+ && other.flags == flags
+ && other.codePoint == codePoint
+ && other.plainCodePoint == plainCodePoint
+ && other.keyCode == keyCode
+ && other.scanCode == scanCode
+ && other.metaState == metaState;
+ }
+
+ @override
+ int get hashCode => hashValues(
+ flags,
+ codePoint,
+ plainCodePoint,
+ keyCode,
+ scanCode,
+ metaState,
+ );
+
// Modifier key masks.
/// No modifier keys are pressed in the [metaState] field.
@@ -430,11 +467,4 @@
/// it's much easier to use [isModifierPressed] if you just want to know if
/// a modifier is pressed.
static const int modifierScrollLock = 0x400000;
-
- @override
- String toString() {
- return '${objectRuntimeType(this, 'RawKeyEventDataAndroid')}(keyLabel: $keyLabel flags: $flags, codePoint: $codePoint, '
- 'keyCode: $keyCode, scanCode: $scanCode, metaState: $metaState, '
- 'modifiers down: $modifiersPressed)';
- }
}
diff --git a/packages/flutter/lib/src/services/raw_keyboard_fuchsia.dart b/packages/flutter/lib/src/services/raw_keyboard_fuchsia.dart
index 55059cc..ad6e6a8 100644
--- a/packages/flutter/lib/src/services/raw_keyboard_fuchsia.dart
+++ b/packages/flutter/lib/src/services/raw_keyboard_fuchsia.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 'dart:ui' show hashValues;
import 'package:flutter/foundation.dart';
@@ -159,6 +160,33 @@
}
}
+ @override
+ void debugFillProperties(DiagnosticPropertiesBuilder properties) {
+ super.debugFillProperties(properties);
+ properties.add(DiagnosticsProperty<int>('hidUsage', hidUsage));
+ properties.add(DiagnosticsProperty<int>('codePoint', codePoint));
+ properties.add(DiagnosticsProperty<int>('modifiers', modifiers));
+ }
+
+ @override
+ bool operator==(Object other) {
+ if (identical(this, other))
+ return true;
+ if (other.runtimeType != runtimeType)
+ return false;
+ return other is RawKeyEventDataFuchsia
+ && other.hidUsage == hidUsage
+ && other.codePoint == codePoint
+ && other.modifiers == modifiers;
+ }
+
+ @override
+ int get hashCode => hashValues(
+ hidUsage,
+ codePoint,
+ modifiers,
+ );
+
// Keyboard modifier masks for Fuchsia modifiers.
/// The [modifiers] field indicates that no modifier keys are pressed if it
@@ -272,10 +300,4 @@
/// it's much easier to use [isModifierPressed] if you just want to know if
/// a modifier is pressed.
static const int modifierMeta = modifierLeftMeta | modifierRightMeta;
-
- @override
- String toString() {
- return '${objectRuntimeType(this, 'RawKeyEventDataFuchsia')}(hidUsage: $hidUsage, codePoint: $codePoint, modifiers: $modifiers, '
- 'modifiers down: $modifiersPressed)';
- }
}
diff --git a/packages/flutter/lib/src/services/raw_keyboard_ios.dart b/packages/flutter/lib/src/services/raw_keyboard_ios.dart
index 8d5735c..f356843 100644
--- a/packages/flutter/lib/src/services/raw_keyboard_ios.dart
+++ b/packages/flutter/lib/src/services/raw_keyboard_ios.dart
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+import 'dart:ui' show hashValues;
+
import 'package:flutter/foundation.dart';
import 'keyboard_key.dart';
@@ -253,6 +255,36 @@
}
}
+ @override
+ void debugFillProperties(DiagnosticPropertiesBuilder properties) {
+ super.debugFillProperties(properties);
+ properties.add(DiagnosticsProperty<String>('characters', characters));
+ properties.add(DiagnosticsProperty<String>('charactersIgnoringModifiers', charactersIgnoringModifiers));
+ properties.add(DiagnosticsProperty<int>('keyCode', keyCode));
+ properties.add(DiagnosticsProperty<int>('modifiers', modifiers));
+ }
+
+ @override
+ bool operator==(Object other) {
+ if (identical(this, other))
+ return true;
+ if (other.runtimeType != runtimeType)
+ return false;
+ return other is RawKeyEventDataIos
+ && other.characters == characters
+ && other.charactersIgnoringModifiers == charactersIgnoringModifiers
+ && other.keyCode == keyCode
+ && other.modifiers == modifiers;
+ }
+
+ @override
+ int get hashCode => hashValues(
+ characters,
+ charactersIgnoringModifiers,
+ keyCode,
+ modifiers,
+ );
+
// Modifier key masks. See Apple's UIKey documentation
// https://developer.apple.com/documentation/uikit/uikeymodifierflags?language=objc
// https://opensource.apple.com/source/IOHIDFamily/IOHIDFamily-86/IOHIDSystem/IOKit/hidsystem/IOLLEvent.h.auto.html
@@ -361,11 +393,4 @@
/// applications to mask off the device-dependent modifier flags, including
/// event coalescing information.
static const int deviceIndependentMask = 0xffff0000;
-
- @override
- String toString() {
- return '${objectRuntimeType(this, 'RawKeyEventDataIos')}(keyLabel: $keyLabel, keyCode: $keyCode, characters: $characters,'
- ' unmodifiedCharacters: $charactersIgnoringModifiers, modifiers: $modifiers, '
- 'modifiers down: $modifiersPressed)';
- }
}
diff --git a/packages/flutter/lib/src/services/raw_keyboard_linux.dart b/packages/flutter/lib/src/services/raw_keyboard_linux.dart
index f0f2510..e0af412 100644
--- a/packages/flutter/lib/src/services/raw_keyboard_linux.dart
+++ b/packages/flutter/lib/src/services/raw_keyboard_linux.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 'dart:ui' show hashValues;
import 'package:flutter/foundation.dart';
@@ -117,11 +118,40 @@
}
@override
- String toString() {
- return '${objectRuntimeType(this, 'RawKeyEventDataLinux')}(keyLabel: $keyLabel, keyCode: $keyCode, scanCode: $scanCode,'
- ' unicodeScalarValues: $unicodeScalarValues, modifiers: $modifiers, '
- 'modifiers down: $modifiersPressed)';
+ void debugFillProperties(DiagnosticPropertiesBuilder properties) {
+ super.debugFillProperties(properties);
+ properties.add(DiagnosticsProperty<String>('toolkit', keyHelper.debugToolkit));
+ properties.add(DiagnosticsProperty<int>('unicodeScalarValues', unicodeScalarValues));
+ properties.add(DiagnosticsProperty<int>('scanCode', scanCode));
+ properties.add(DiagnosticsProperty<int>('keyCode', keyCode));
+ properties.add(DiagnosticsProperty<int>('modifiers', modifiers));
+ properties.add(DiagnosticsProperty<bool>('isDown', isDown));
}
+
+ @override
+ bool operator==(Object other) {
+ if (identical(this, other))
+ return true;
+ if (other.runtimeType != runtimeType)
+ return false;
+ return other is RawKeyEventDataLinux
+ && other.keyHelper.runtimeType == keyHelper.runtimeType
+ && other.unicodeScalarValues == unicodeScalarValues
+ && other.scanCode == scanCode
+ && other.keyCode == keyCode
+ && other.modifiers == modifiers
+ && other.isDown == isDown;
+ }
+
+ @override
+ int get hashCode => hashValues(
+ keyHelper.runtimeType,
+ unicodeScalarValues,
+ scanCode,
+ keyCode,
+ modifiers,
+ isDown,
+ );
}
/// Abstract class for window-specific key mappings.
@@ -141,6 +171,11 @@
}
}
+ /// Returns the name for the toolkit.
+ ///
+ /// This is used in debug mode to generate readable string.
+ String get debugToolkit;
+
/// Returns a [KeyboardSide] enum value that describes which side or sides of
/// the given keyboard modifier key were pressed at the time of this event.
KeyboardSide getModifierSide(ModifierKey key);
@@ -204,6 +239,9 @@
/// {@macro flutter.services.GLFWKeyHelper.modifierCapsLock}
static const int modifierNumericPad = 0x0020;
+ @override
+ String get debugToolkit => 'GLFW';
+
int _mergeModifiers({required int modifiers, required int keyCode, required bool isDown}) {
// GLFW Key codes for modifier keys.
const int shiftLeftKeyCode = 340;
@@ -343,6 +381,9 @@
/// {@macro flutter.services.GtkKeyHelper.modifierShift}
static const int modifierMeta = 1 << 26;
+ @override
+ String get debugToolkit => 'GTK';
+
int _mergeModifiers({required int modifiers, required int keyCode, required bool isDown}) {
// GTK Key codes for modifier keys.
const int shiftLeftKeyCode = 0xffe1;
diff --git a/packages/flutter/lib/src/services/raw_keyboard_macos.dart b/packages/flutter/lib/src/services/raw_keyboard_macos.dart
index bbc3ee8..63eab78 100644
--- a/packages/flutter/lib/src/services/raw_keyboard_macos.dart
+++ b/packages/flutter/lib/src/services/raw_keyboard_macos.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 'dart:ui' show hashValues;
import 'package:flutter/foundation.dart';
@@ -216,6 +217,36 @@
return logicalKey != LogicalKeyboardKey.fn;
}
+ @override
+ void debugFillProperties(DiagnosticPropertiesBuilder properties) {
+ super.debugFillProperties(properties);
+ properties.add(DiagnosticsProperty<String>('characters', characters));
+ properties.add(DiagnosticsProperty<String>('charactersIgnoringModifiers', charactersIgnoringModifiers));
+ properties.add(DiagnosticsProperty<int>('keyCode', keyCode));
+ properties.add(DiagnosticsProperty<int>('modifiers', modifiers));
+ }
+
+ @override
+ bool operator==(Object other) {
+ if (identical(this, other))
+ return true;
+ if (other.runtimeType != runtimeType)
+ return false;
+ return other is RawKeyEventDataMacOs
+ && other.characters == characters
+ && other.charactersIgnoringModifiers == charactersIgnoringModifiers
+ && other.keyCode == keyCode
+ && other.modifiers == modifiers;
+ }
+
+ @override
+ int get hashCode => hashValues(
+ characters,
+ charactersIgnoringModifiers,
+ keyCode,
+ modifiers,
+ );
+
/// Returns true if the given label represents an unprintable key.
///
/// Examples of unprintable keys are "NSUpArrowFunctionKey = 0xF700"
@@ -341,11 +372,4 @@
/// applications to mask off the device-dependent modifier flags, including
/// event coalescing information.
static const int deviceIndependentMask = 0xffff0000;
-
- @override
- String toString() {
- return '${objectRuntimeType(this, 'RawKeyEventDataMacOs')}(keyLabel: $keyLabel, keyCode: $keyCode, characters: $characters,'
- ' unmodifiedCharacters: $charactersIgnoringModifiers, modifiers: $modifiers, '
- 'modifiers down: $modifiersPressed)';
- }
}
diff --git a/packages/flutter/lib/src/services/raw_keyboard_web.dart b/packages/flutter/lib/src/services/raw_keyboard_web.dart
index 232bfc8..70e2b94 100644
--- a/packages/flutter/lib/src/services/raw_keyboard_web.dart
+++ b/packages/flutter/lib/src/services/raw_keyboard_web.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 'dart:ui' show hashValues;
import 'package:flutter/foundation.dart';
@@ -29,18 +30,28 @@
/// The `KeyboardEvent.code` corresponding to this event.
///
+ /// The [code] represents a physical key on the keyboard, a value that isn't
+ /// altered by keyboard layout or the state of the modifier keys.
+ ///
/// See <https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code>
/// for more information.
final String code;
/// The `KeyboardEvent.key` corresponding to this event.
///
+ /// The [key] represents the key pressed by the user, taking into
+ /// consideration the state of modifier keys such as Shift as well as the
+ /// keyboard locale and layout.
+ ///
/// See <https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key>
/// for more information.
final String key;
/// The `KeyboardEvent.location` corresponding to this event.
///
+ /// The [location] represents the location of the key on the keyboard or other
+ /// input device, such as left or right modifier keys, or Numpad keys.
+ ///
/// See <https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/location>
/// for more information.
final int location;
@@ -126,6 +137,36 @@
return KeyboardSide.any;
}
+ @override
+ void debugFillProperties(DiagnosticPropertiesBuilder properties) {
+ super.debugFillProperties(properties);
+ properties.add(DiagnosticsProperty<String>('code', code));
+ properties.add(DiagnosticsProperty<String>('key', key));
+ properties.add(DiagnosticsProperty<int>('location', location));
+ properties.add(DiagnosticsProperty<int>('metaState', metaState));
+ }
+
+ @override
+ bool operator==(Object other) {
+ if (identical(this, other))
+ return true;
+ if (other.runtimeType != runtimeType)
+ return false;
+ return other is RawKeyEventDataWeb
+ && other.code == code
+ && other.key == key
+ && other.location == location
+ && other.metaState == metaState;
+ }
+
+ @override
+ int get hashCode => hashValues(
+ code,
+ key,
+ location,
+ metaState,
+ );
+
// Modifier key masks.
/// No modifier keys are pressed in the [metaState] field.
@@ -190,10 +231,4 @@
/// it's much easier to use [isModifierPressed] if you just want to know if
/// a modifier is pressed.
static const int modifierScrollLock = 0x40;
-
- @override
- String toString() {
- return '${objectRuntimeType(this, 'RawKeyEventDataWeb')}(keyLabel: $keyLabel, code: $code, '
- 'location: $location, metaState: $metaState, modifiers down: $modifiersPressed)';
- }
}
diff --git a/packages/flutter/lib/src/services/raw_keyboard_windows.dart b/packages/flutter/lib/src/services/raw_keyboard_windows.dart
index 7e57090..4fb2c7f 100644
--- a/packages/flutter/lib/src/services/raw_keyboard_windows.dart
+++ b/packages/flutter/lib/src/services/raw_keyboard_windows.dart
@@ -2,6 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+import 'dart:ui' show hashValues;
+
+import 'package:flutter/foundation.dart';
import 'keyboard_key.dart';
import 'keyboard_maps.dart';
@@ -197,6 +200,36 @@
return keyCode != _vkProcessKey;
}
+ @override
+ void debugFillProperties(DiagnosticPropertiesBuilder properties) {
+ super.debugFillProperties(properties);
+ properties.add(DiagnosticsProperty<int>('keyCode', keyCode));
+ properties.add(DiagnosticsProperty<int>('scanCode', scanCode));
+ properties.add(DiagnosticsProperty<int>('characterCodePoint', characterCodePoint));
+ properties.add(DiagnosticsProperty<int>('modifiers', modifiers));
+ }
+
+ @override
+ bool operator==(Object other) {
+ if (identical(this, other))
+ return true;
+ if (other.runtimeType != runtimeType)
+ return false;
+ return other is RawKeyEventDataWindows
+ && other.keyCode == keyCode
+ && other.scanCode == scanCode
+ && other.characterCodePoint == characterCodePoint
+ && other.modifiers == modifiers;
+ }
+
+ @override
+ int get hashCode => hashValues(
+ keyCode,
+ scanCode,
+ characterCodePoint,
+ modifiers,
+ );
+
// These are not the values defined by the Windows header for each modifier. Since they
// can't be packaged into a single int, we are re-defining them here to reduce the size
// of the message from the embedder. Embedders should map these values to the native key codes.
diff --git a/packages/flutter/test/services/raw_keyboard_test.dart b/packages/flutter/test/services/raw_keyboard_test.dart
index b11860e..5db4e25 100644
--- a/packages/flutter/test/services/raw_keyboard_test.dart
+++ b/packages/flutter/test/services/raw_keyboard_test.dart
@@ -1045,6 +1045,59 @@
expect(message, equals(<String, dynamic>{ 'handled': true }));
tester.binding.defaultBinaryMessenger.setMockMessageHandler(SystemChannels.keyEvent.name, null);
});
+
+ test('data.toString', () {
+ expect(RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'android',
+ 'keyCode': 29,
+ 'plainCodePoint': 97,
+ 'codePoint': 65,
+ 'character': 'A',
+ 'scanCode': 30,
+ 'metaState': 0x0,
+ 'source': 0x101, // Keyboard source.
+ 'repeatCount': 42,
+ }).data.toString(), equalsIgnoringHashCodes(
+ 'RawKeyEventDataAndroid#00000('
+ 'flags: 0, codePoint: 65, plainCodePoint: 97, keyCode: 29, '
+ 'scanCode: 30, metaState: 0)'));
+ });
+
+ test('data.equality', () {
+ expect(RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'android',
+ 'keyCode': 29,
+ 'plainCodePoint': 97,
+ 'codePoint': 65,
+ 'character': 'A',
+ 'scanCode': 30,
+ 'metaState': 0x0,
+ 'source': 0x101, // Keyboard source.
+ 'repeatCount': 42,
+ }).data, const RawKeyEventDataAndroid(
+ flags: 0,
+ codePoint: 65,
+ plainCodePoint: 97,
+ keyCode: 29,
+ scanCode: 30,
+ metaState: 0,
+ ));
+
+ expect(RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'android',
+ 'keyCode': 29,
+ 'plainCodePoint': 97,
+ 'codePoint': 65,
+ 'character': 'A',
+ 'scanCode': 30,
+ 'metaState': 0x0,
+ 'source': 0x101, // Keyboard source.
+ 'repeatCount': 42,
+ }).data, isNot(equals(const RawKeyEventDataAndroid())));
+ });
}, skip: isBrowser); // This is an Android-specific group.
group('RawKeyEventDataFuchsia', () {
@@ -1163,6 +1216,42 @@
expect(data.logicalKey, equals(LogicalKeyboardKey.shiftLeft));
expect(data.keyLabel, isEmpty);
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/35347
+
+ test('data.toString', () {
+ expect(RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'fuchsia',
+ 'hidUsage': 0x00070004,
+ 'codePoint': 97,
+ 'character': 'a',
+ 'modifiers': 0x10,
+ }).data.toString(), equalsIgnoringHashCodes(
+ 'RawKeyEventDataFuchsia#00000(hidUsage: 458756, codePoint: 97, modifiers: 16)'));
+ });
+
+ test('data.equality', () {
+ expect(RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'fuchsia',
+ 'hidUsage': 0x00070004,
+ 'codePoint': 97,
+ 'character': 'a',
+ 'modifiers': 0x10,
+ }).data, const RawKeyEventDataFuchsia(
+ hidUsage: 0x00070004,
+ codePoint: 97,
+ modifiers: 0x10,
+ ));
+
+ expect(RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'fuchsia',
+ 'hidUsage': 0x00070004,
+ 'codePoint': 97,
+ 'character': 'a',
+ 'modifiers': 0x10,
+ }).data, isNot(equals(const RawKeyEventDataFuchsia())));
+ });
}, skip: isBrowser); // This is a Fuchsia-specific group.
group('RawKeyEventDataMacOs', () {
@@ -1311,6 +1400,43 @@
expect(data.physicalKey, equals(PhysicalKeyboardKey.arrowLeft));
expect(data.logicalKey, equals(LogicalKeyboardKey.arrowLeft));
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/35347
+
+ test('data.toString', () {
+ expect(RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'macos',
+ 'keyCode': 0x00000060,
+ 'characters': 'A',
+ 'charactersIgnoringModifiers': 'a',
+ 'modifiers': 0x10,
+ }).data.toString(), equalsIgnoringHashCodes(
+ 'RawKeyEventDataMacOs#00000(characters: A, charactersIgnoringModifiers: a, keyCode: 96, modifiers: 16)'));
+ });
+
+ test('data.equality', () {
+ expect(RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'macos',
+ 'keyCode': 0x00000060,
+ 'characters': 'A',
+ 'charactersIgnoringModifiers': 'a',
+ 'modifiers': 0x10,
+ }).data, const RawKeyEventDataMacOs(
+ keyCode: 0x00000060,
+ characters: 'A',
+ charactersIgnoringModifiers: 'a',
+ modifiers: 0x10,
+ ));
+
+ expect(RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'macos',
+ 'keyCode': 0x00000060,
+ 'characters': 'A',
+ 'charactersIgnoringModifiers': 'a',
+ 'modifiers': 0x10,
+ }).data, isNot(equals(const RawKeyEventDataMacOs())));
+ });
}, skip: isBrowser); // This is a macOS-specific group.
group('RawKeyEventDataIos', () {
@@ -1459,6 +1585,43 @@
expect(data.physicalKey, equals(PhysicalKeyboardKey.arrowLeft));
expect(data.logicalKey, equals(LogicalKeyboardKey.arrowLeft));
}, skip: isBrowser); // https://github.com/flutter/flutter/issues/35347
+
+ test('data.toString', () {
+ expect(RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'ios',
+ 'keyCode': 0x00000004,
+ 'characters': 'A',
+ 'charactersIgnoringModifiers': 'a',
+ 'modifiers': 0x10,
+ }).data.toString(), equalsIgnoringHashCodes(
+ 'RawKeyEventDataIos#00000(characters: A, charactersIgnoringModifiers: a, keyCode: 4, modifiers: 16)'));
+ });
+
+ test('data.equality', () {
+ expect(RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'ios',
+ 'keyCode': 0x00000004,
+ 'characters': 'A',
+ 'charactersIgnoringModifiers': 'a',
+ 'modifiers': 0x10,
+ }).data, const RawKeyEventDataIos(
+ keyCode: 0x00000004,
+ characters: 'A',
+ charactersIgnoringModifiers: 'a',
+ modifiers: 0x10,
+ ));
+
+ expect(RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'ios',
+ 'keyCode': 0x00000004,
+ 'characters': 'A',
+ 'charactersIgnoringModifiers': 'a',
+ 'modifiers': 0x10,
+ }).data, isNot(equals(const RawKeyEventDataIos())));
+ });
}, skip: isBrowser); // This is an iOS-specific group.
group('RawKeyEventDataWindows', () {
@@ -1640,9 +1803,46 @@
expect(lastHandled, true);
expect(RawKeyboard.instance.keysPressed, isEmpty);
});
+
+ test('data.toString', () {
+ expect(RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'windows',
+ 'keyCode': 0x00000010,
+ 'characterCodePoint': 10,
+ 'scanCode': 0x0000001e,
+ 'modifiers': 0x20,
+ }).data.toString(), equalsIgnoringHashCodes(
+ 'RawKeyEventDataWindows#00000(keyCode: 16, scanCode: 30, characterCodePoint: 10, modifiers: 32)'));
+ });
+
+ test('data.equality', () {
+ expect(RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'windows',
+ 'keyCode': 0x00000010,
+ 'characterCodePoint': 10,
+ 'scanCode': 0x0000001e,
+ 'modifiers': 0x20,
+ }).data, const RawKeyEventDataWindows(
+ keyCode: 0x00000010,
+ scanCode: 0x1e,
+ modifiers: 0x20,
+ characterCodePoint: 10,
+ ));
+
+ expect(RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'windows',
+ 'keyCode': 0x00000010,
+ 'characterCodePoint': 10,
+ 'scanCode': 0x0000001e,
+ 'modifiers': 0x20,
+ }).data, isNot(equals(const RawKeyEventDataWindows())));
+ });
}, skip: isBrowser); // This is a Windows-specific group.
- group('RawKeyEventDataLinux-GFLW', () {
+ group('RawKeyEventDataLinux-GLFW', () {
const Map<int, _ModifierCheck> modifierTests = <int, _ModifierCheck>{
GLFWKeyHelper.modifierAlt: _ModifierCheck(ModifierKey.altModifier, KeyboardSide.all),
GLFWKeyHelper.modifierShift: _ModifierCheck(ModifierKey.shiftModifier, KeyboardSide.all),
@@ -1828,6 +2028,50 @@
expect(data.logicalKey, equals(LogicalKeyboardKey.shiftLeft));
expect(data.keyLabel, isEmpty);
});
+
+ test('data.toString', () {
+ expect(RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'linux',
+ 'toolkit': 'glfw',
+ 'keyCode': 65,
+ 'scanCode': 0x00000026,
+ 'unicodeScalarValues': 0x10FFFF,
+ 'modifiers': 0x10,
+ }).data.toString(), equalsIgnoringHashCodes(
+ 'RawKeyEventDataLinux#00000(toolkit: GLFW, unicodeScalarValues: 1114111, scanCode: 38, keyCode: 65, modifiers: 16, isDown: true)'));
+ });
+
+ test('data.equality', () {
+ expect(RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'linux',
+ 'toolkit': 'glfw',
+ 'keyCode': 65,
+ 'scanCode': 0x00000026,
+ 'unicodeScalarValues': 0x10FFFF,
+ 'modifiers': 0x10,
+ }).data, RawKeyEventDataLinux(
+ keyHelper: KeyHelper('glfw'),
+ unicodeScalarValues: 0x10FFFF,
+ keyCode: 65,
+ scanCode: 0x26,
+ modifiers: 0x10,
+ isDown: true,
+ ));
+
+ expect(RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'linux',
+ 'toolkit': 'glfw',
+ 'keyCode': 65,
+ 'scanCode': 0x00000026,
+ 'unicodeScalarValues': 0x10FFFF,
+ 'modifiers': 0x10,
+ }).data, isNot(equals(RawKeyEventDataLinux(
+ keyHelper: KeyHelper('glfw'), isDown: true)),
+ ));
+ });
}, skip: isBrowser); // This is a GLFW-specific group.
group('RawKeyEventDataLinux-GTK', () {
@@ -2016,6 +2260,67 @@
expect(data.logicalKey, equals(LogicalKeyboardKey.shiftLeft));
expect(data.keyLabel, isEmpty);
});
+
+ test('data.toString', () {
+ expect(RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'linux',
+ 'toolkit': 'gtk',
+ 'keyCode': 65,
+ 'scanCode': 0x00000026,
+ 'unicodeScalarValues': 113,
+ 'modifiers': 0x10,
+ }).data.toString(), equalsIgnoringHashCodes(
+ 'RawKeyEventDataLinux#00000(toolkit: GTK, unicodeScalarValues: 113, scanCode: 38, keyCode: 65, modifiers: 16, isDown: true)'));
+ });
+
+ test('data.equality', () {
+ expect(RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'linux',
+ 'toolkit': 'gtk',
+ 'keyCode': 65,
+ 'scanCode': 0x00000026,
+ 'unicodeScalarValues': 113,
+ 'modifiers': 0x10,
+ }).data, RawKeyEventDataLinux(
+ keyHelper: KeyHelper('gtk'),
+ unicodeScalarValues: 113,
+ keyCode: 65,
+ scanCode: 0x26,
+ modifiers: 0x10,
+ isDown: true,
+ ));
+
+ expect(RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'linux',
+ 'toolkit': 'gtk',
+ 'keyCode': 65,
+ 'scanCode': 0x00000026,
+ 'unicodeScalarValues': 113,
+ 'modifiers': 0x10,
+ }).data, isNot(equals(RawKeyEventDataLinux(
+ keyHelper: KeyHelper('glfw'),
+ unicodeScalarValues: 113,
+ keyCode: 65,
+ scanCode: 0x26,
+ modifiers: 0x10,
+ isDown: true,
+ ))));
+
+ expect(RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'linux',
+ 'toolkit': 'gtk',
+ 'keyCode': 65,
+ 'scanCode': 0x00000026,
+ 'unicodeScalarValues': 113,
+ 'modifiers': 0x10,
+ }).data, isNot(equals(RawKeyEventDataLinux(
+ keyHelper: KeyHelper('gtk'), isDown: true)),
+ ));
+ });
}, skip: isBrowser); // This is a GTK-specific group.
group('RawKeyEventDataWeb', () {
@@ -2141,5 +2446,52 @@
expect(data.logicalKey, equals(LogicalKeyboardKey.arrowDown));
expect(data.keyLabel, isEmpty);
});
+
+ test('data.toString', () {
+ expect(RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'web',
+ 'code': 'KeyA',
+ 'key': 'a',
+ 'location': 2,
+ 'metaState': 0x10,
+ }).data.toString(), equalsIgnoringHashCodes(
+ 'RawKeyEventDataWeb#00000(code: KeyA, key: a, location: 2, metaState: 16)'));
+
+ // Without location
+ expect(RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'web',
+ 'code': 'KeyA',
+ 'key': 'a',
+ 'metaState': 0x10,
+ }).data.toString(), equalsIgnoringHashCodes(
+ 'RawKeyEventDataWeb#00000(code: KeyA, key: a, location: 0, metaState: 16)'));
+ });
+
+ test('data.equality', () {
+ expect(RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'web',
+ 'code': 'KeyA',
+ 'key': 'a',
+ 'location': 2,
+ 'metaState': 0x10,
+ }).data, const RawKeyEventDataWeb(
+ key: 'a',
+ code: 'KeyA',
+ location: 2,
+ metaState: 0x10,
+ ));
+
+ expect(RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'web',
+ 'code': 'KeyA',
+ 'key': 'a',
+ 'location': 2,
+ 'metaState': 0x10,
+ }).data, isNot(equals(const RawKeyEventDataWeb(code: 'KeyA', key: 'a'))));
+ });
});
}