[linux] Receives the unmodified characters obtained from GLFW (#34752)
diff --git a/dev/manual_tests/lib/raw_keyboard.dart b/dev/manual_tests/lib/raw_keyboard.dart
index 8507bf2..9499b0f 100644
--- a/dev/manual_tests/lib/raw_keyboard.dart
+++ b/dev/manual_tests/lib/raw_keyboard.dart
@@ -105,7 +105,7 @@
} else if (data is RawKeyEventDataLinux) {
dataText.add(Text('keyCode: ${data.keyCode} (${_asHex(data.keyCode)})'));
dataText.add(Text('scanCode: ${data.scanCode}'));
- dataText.add(Text('codePoint: ${data.codePoint}'));
+ dataText.add(Text('unicodeScalarValues: ${data.unicodeScalarValues}'));
dataText.add(Text('modifiers: ${data.modifiers} (${_asHex(data.modifiers)})'));
}
dataText.add(Text('logical: ${_event.logicalKey}'));
diff --git a/packages/flutter/lib/src/services/raw_keyboard.dart b/packages/flutter/lib/src/services/raw_keyboard.dart
index 3522db4..8427a69 100644
--- a/packages/flutter/lib/src/services/raw_keyboard.dart
+++ b/packages/flutter/lib/src/services/raw_keyboard.dart
@@ -279,7 +279,7 @@
case 'linux':
data = RawKeyEventDataLinux(
keyHelper: KeyHelper(message['toolkit'] ?? ''),
- codePoint: message['codePoint'] ?? 0,
+ unicodeScalarValues: message['unicodeScalarValues'] ?? 0,
keyCode: message['keyCode'] ?? 0,
scanCode: message['scanCode'] ?? 0,
modifiers: message['modifiers'] ?? 0);
diff --git a/packages/flutter/lib/src/services/raw_keyboard_linux.dart b/packages/flutter/lib/src/services/raw_keyboard_linux.dart
index 3f4ea2c..fd09600 100644
--- a/packages/flutter/lib/src/services/raw_keyboard_linux.dart
+++ b/packages/flutter/lib/src/services/raw_keyboard_linux.dart
@@ -19,16 +19,17 @@
class RawKeyEventDataLinux extends RawKeyEventData {
/// Creates a key event data structure specific for macOS.
///
- /// The [toolkit], [scanCode], [codePoint], [keyCode], and [modifiers], arguments
- /// must not be null.
+ /// The [toolkit], [scanCode], [unicodeScalarValues], [keyCode], and [modifiers],
+ /// arguments must not be null.
const RawKeyEventDataLinux({
@required this.keyHelper,
+ this.unicodeScalarValues = 0,
this.scanCode = 0,
- this.codePoint = 0,
this.keyCode = 0,
this.modifiers = 0,
}) : assert(scanCode != null),
- assert(codePoint != null),
+ assert(unicodeScalarValues != null),
+ assert((unicodeScalarValues & ~LogicalKeyboardKey.valueMask) == 0),
assert(keyCode != null),
assert(modifiers != null),
assert(keyHelper != null);
@@ -39,32 +40,32 @@
/// (GLFW, GTK, QT, etc) may have a different key code mapping.
final KeyHelper keyHelper;
+ /// An int with up to two Unicode scalar values generated by a single keystroke. An assertion
+ /// will fire if more than two values are encoded in a single keystroke.
+ ///
+ /// This is typically the character that [keyCode] would produce without any modifier keys.
+ /// For dead keys, it is typically the diacritic it would add to a character. Defaults to 0,
+ /// asserted to be not null.
+ final int unicodeScalarValues;
+
/// The hardware scan code id corresponding to this key event.
///
/// These values are not reliable and vary from device to device, so this
/// information is mainly useful for debugging.
final int scanCode;
- /// The Unicode code point represented by the key event, if any.
- ///
- /// If there is no Unicode code point, this value is zero.
- ///
- /// Dead keys are represented as Unicode combining characters.
- final int codePoint;
-
/// The hardware key code corresponding to this key event.
///
/// This is the physical key that was pressed, not the Unicode character.
- /// See [codePoint] for the Unicode character. This value may be different depending
- /// on the window toolkit used (See [toolkit]).
+ /// This value may be different depending on the window toolkit used. See [KeyHelper].
final int keyCode;
/// A mask of the current modifiers using the values in Modifier Flags.
- /// This value may be different depending on the window toolkit used (See [toolkit]).
+ /// This value may be different depending on the window toolkit used. See [KeyHelper].
final int modifiers;
@override
- String get keyLabel => codePoint == 0 ? null : String.fromCharCode(codePoint);
+ String get keyLabel => unicodeScalarValues == 0 ? null : String.fromCharCode(unicodeScalarValues);
@override
PhysicalKeyboardKey get physicalKey => kLinuxToPhysicalKey[scanCode] ?? PhysicalKeyboardKey.none;
@@ -85,7 +86,7 @@
// plane.
if (keyLabel != null &&
!LogicalKeyboardKey.isControlCharacter(keyLabel)) {
- final int keyId = LogicalKeyboardKey.unicodePlane | (codePoint & LogicalKeyboardKey.valueMask);
+ final int keyId = LogicalKeyboardKey.unicodePlane | (unicodeScalarValues & LogicalKeyboardKey.valueMask);
return LogicalKeyboardKey.findKeyByKeyId(keyId) ?? LogicalKeyboardKey(
keyId,
keyLabel: keyLabel,
@@ -123,7 +124,7 @@
@override
String toString() {
return '$runtimeType(keyLabel: $keyLabel, keyCode: $keyCode, scanCode: $scanCode,'
- ' codePoint: $codePoint, modifiers: $modifiers, '
+ ' unicodeScalarValues: $unicodeScalarValues, modifiers: $modifiers, '
'modifiers down: $modifiersPressed)';
}
}
diff --git a/packages/flutter/test/services/raw_keyboard_test.dart b/packages/flutter/test/services/raw_keyboard_test.dart
index 0cb5cce..1643957 100644
--- a/packages/flutter/test/services/raw_keyboard_test.dart
+++ b/packages/flutter/test/services/raw_keyboard_test.dart
@@ -467,9 +467,9 @@
'type': 'keydown',
'keymap': 'linux',
'toolkit': 'glfw',
- 'keyCode': 0x04,
- 'scanCode': 0x01,
- 'codePoint': 0x10,
+ 'keyCode': 65,
+ 'scanCode': 0x00000026,
+ 'unicodeScalarValues': 97,
'modifiers': modifier,
});
final RawKeyEventDataLinux data = event.data;
@@ -501,9 +501,9 @@
'type': 'keydown',
'keymap': 'linux',
'toolkit': 'glfw',
- 'keyCode': 0x04,
- 'scanCode': 0x64,
- 'codePoint': 0x1,
+ 'keyCode': 65,
+ 'scanCode': 0x00000026,
+ 'unicodeScalarValues': 97,
'modifiers': modifier | GLFWKeyHelper.modifierControl,
});
final RawKeyEventDataLinux data = event.data;
@@ -538,13 +538,44 @@
'toolkit': 'glfw',
'keyCode': 65,
'scanCode': 0x00000026,
- 'codePoint': 97,
+ 'unicodeScalarValues': 113,
'modifiers': 0x0,
});
final RawKeyEventDataLinux data = keyAEvent.data;
expect(data.physicalKey, equals(PhysicalKeyboardKey.keyA));
- expect(data.logicalKey, equals(LogicalKeyboardKey.keyA));
- expect(data.keyLabel, equals('a'));
+ expect(data.logicalKey, equals(LogicalKeyboardKey.keyQ));
+ expect(data.keyLabel, equals('q'));
+ });
+ test('Code points with two Unicode scalar values are allowed', () {
+ final RawKeyEvent keyAEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'linux',
+ 'toolkit': 'glfw',
+ 'keyCode': 65,
+ 'scanCode': 0x00000026,
+ 'unicodeScalarValues': 0x10FFFF,
+ 'modifiers': 0x0,
+ });
+ final RawKeyEventDataLinux data = keyAEvent.data;
+ expect(data.physicalKey, equals(PhysicalKeyboardKey.keyA));
+ expect(data.logicalKey.keyId, equals(0x10FFFF));
+ expect(data.keyLabel, equals(''));
+ });
+
+ test('Code points with more than three Unicode scalar values are not allowed', () {
+ // |keyCode| and |scanCode| are arbitrary values. This test should fail due to an invalid |unicodeScalarValues|.
+ void _createFailingKey() {
+ RawKeyEvent.fromMessage(const <String, dynamic>{
+ 'type': 'keydown',
+ 'keymap': 'linux',
+ 'toolkit': 'glfw',
+ 'keyCode': 65,
+ 'scanCode': 0x00000026,
+ 'unicodeScalarValues': 0x1F00000000,
+ 'modifiers': 0x0,
+ });
+ }
+ expect(() => _createFailingKey(), throwsAssertionError);
});
test('Control keyboard keys are correctly translated', () {
final RawKeyEvent escapeKeyEvent = RawKeyEvent.fromMessage(const <String, dynamic>{
@@ -553,7 +584,7 @@
'toolkit': 'glfw',
'keyCode': 256,
'scanCode': 0x00000009,
- 'codePoint': 0,
+ 'unicodeScalarValues': 0,
'modifiers': 0x0,
});
final RawKeyEventDataLinux data = escapeKeyEvent.data;
@@ -568,7 +599,7 @@
'toolkit': 'glfw',
'keyCode': 340,
'scanCode': 0x00000032,
- 'codePoint': 0,
+ 'unicodeScalarValues': 0,
});
final RawKeyEventDataLinux data = shiftLeftKeyEvent.data;
expect(data.physicalKey, equals(PhysicalKeyboardKey.shiftLeft));