Fix the character
field of the RawKeyEvent
to hold correct data on non-Android platforms. (#65667)
This fixes a problem where the character field of the RawKeyEvent was not being set at all for non-Android platforms. I also updated the key maps, and corrected a problem with the Windows key map where the backquote character wasn't correctly mapped.
This commit is contained in:
parent
b8a39c15f8
commit
199a7c1964
@ -79,6 +79,7 @@ class _HardwareKeyDemoState extends State<RawKeyboardDemo> {
|
||||
final String modifierList = data.modifiersPressed.keys.map<String>(_getEnumName).join(', ').replaceAll('Modifier', '');
|
||||
final List<Widget> dataText = <Widget>[
|
||||
Text('${_event.runtimeType}'),
|
||||
if (_event.character?.isNotEmpty ?? false) Text('character produced: "${_event.character}"'),
|
||||
Text('modifiers set: $modifierList'),
|
||||
];
|
||||
if (data is RawKeyEventDataAndroid) {
|
||||
@ -114,6 +115,10 @@ class _HardwareKeyDemoState extends State<RawKeyboardDemo> {
|
||||
dataText.add(Text('scanCode: ${data.scanCode}'));
|
||||
dataText.add(Text('characterCodePoint: ${data.characterCodePoint}'));
|
||||
dataText.add(Text('modifiers: ${data.modifiers} (${_asHex(data.modifiers)})'));
|
||||
} else if (data is RawKeyEventDataWeb) {
|
||||
dataText.add(Text('key: ${data.key}'));
|
||||
dataText.add(Text('code: ${data.code}'));
|
||||
dataText.add(Text('metaState: ${data.metaState} (${_asHex(data.metaState)})'));
|
||||
}
|
||||
dataText.add(Text('logical: ${_event.logicalKey}'));
|
||||
dataText.add(Text('physical: ${_event.physicalKey}'));
|
||||
|
@ -2472,7 +2472,9 @@
|
||||
"gtk": [
|
||||
"quoteleft"
|
||||
],
|
||||
"windows": null
|
||||
"windows": [
|
||||
"OEM_3"
|
||||
]
|
||||
},
|
||||
"scanCodes": {
|
||||
"android": [
|
||||
@ -2494,7 +2496,9 @@
|
||||
"gtk": [
|
||||
96
|
||||
],
|
||||
"windows": null
|
||||
"windows": [
|
||||
192
|
||||
]
|
||||
}
|
||||
},
|
||||
"comma": {
|
||||
@ -6565,7 +6569,9 @@
|
||||
"windows": null
|
||||
},
|
||||
"scanCodes": {
|
||||
"android": null,
|
||||
"android": [
|
||||
370
|
||||
],
|
||||
"usb": 786529,
|
||||
"linux": 370,
|
||||
"xkb": 378,
|
||||
@ -6822,7 +6828,9 @@
|
||||
"windows": null
|
||||
},
|
||||
"scanCodes": {
|
||||
"android": null,
|
||||
"android": [
|
||||
405
|
||||
],
|
||||
"usb": 786563,
|
||||
"linux": 405,
|
||||
"xkb": 413,
|
||||
@ -7891,7 +7899,9 @@
|
||||
"windows": null
|
||||
},
|
||||
"scanCodes": {
|
||||
"android": null,
|
||||
"android": [
|
||||
583
|
||||
],
|
||||
"usb": 786891,
|
||||
"linux": 583,
|
||||
"xkb": 591,
|
||||
|
@ -132,7 +132,7 @@
|
||||
"minus": ["OEM_MINUS"],
|
||||
"period": ["OEM_PERIOD"],
|
||||
"slash": ["OEM_2"],
|
||||
"backQuote": ["OEM_3"],
|
||||
"backquote": ["OEM_3"],
|
||||
"gamepadA": ["GAMEPAD_A"],
|
||||
"gamepadB": ["GAMEPAD_B"],
|
||||
"gamepadX": ["GAMEPAD_X"],
|
||||
|
@ -2,8 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// @dart = 2.8
|
||||
|
||||
// DO NOT EDIT -- DO NOT EDIT -- DO NOT EDIT
|
||||
// This file is generated by dev/tools/gen_keycodes/bin/gen_keycodes.dart and
|
||||
// should not be edited directly.
|
||||
|
@ -2,7 +2,6 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
|
||||
// DO NOT EDIT -- DO NOT EDIT -- DO NOT EDIT
|
||||
// This file is generated by dev/tools/gen_keycodes/bin/gen_keycodes.dart and
|
||||
// should not be edited directly.
|
||||
@ -349,8 +348,10 @@ const Map<int, PhysicalKeyboardKey> kAndroidToPhysicalKey = <int, PhysicalKeyboa
|
||||
100: PhysicalKeyboardKey.altRight,
|
||||
126: PhysicalKeyboardKey.metaRight,
|
||||
358: PhysicalKeyboardKey.info,
|
||||
370: PhysicalKeyboardKey.closedCaptionToggle,
|
||||
225: PhysicalKeyboardKey.brightnessUp,
|
||||
224: PhysicalKeyboardKey.brightnessDown,
|
||||
405: PhysicalKeyboardKey.mediaLast,
|
||||
174: PhysicalKeyboardKey.exit,
|
||||
402: PhysicalKeyboardKey.channelUp,
|
||||
403: PhysicalKeyboardKey.channelDown,
|
||||
@ -372,6 +373,7 @@ const Map<int, PhysicalKeyboardKey> kAndroidToPhysicalKey = <int, PhysicalKeyboa
|
||||
215: PhysicalKeyboardKey.launchMail,
|
||||
429: PhysicalKeyboardKey.launchContacts,
|
||||
397: PhysicalKeyboardKey.launchCalendar,
|
||||
583: PhysicalKeyboardKey.launchAssistant,
|
||||
181: PhysicalKeyboardKey.newKey,
|
||||
160: PhysicalKeyboardKey.close,
|
||||
206: PhysicalKeyboardKey.close,
|
||||
@ -2290,6 +2292,7 @@ const Map<int, LogicalKeyboardKey> kWindowsToLogicalKey = <int, LogicalKeyboardK
|
||||
220: LogicalKeyboardKey.backslash,
|
||||
186: LogicalKeyboardKey.semicolon,
|
||||
222: LogicalKeyboardKey.quote,
|
||||
192: LogicalKeyboardKey.backquote,
|
||||
188: LogicalKeyboardKey.comma,
|
||||
190: LogicalKeyboardKey.period,
|
||||
191: LogicalKeyboardKey.slash,
|
||||
|
@ -267,6 +267,7 @@ abstract class RawKeyEvent with Diagnosticable {
|
||||
/// on the [SystemChannels.keyEvent] channel.
|
||||
factory RawKeyEvent.fromMessage(Map<String, dynamic> message) {
|
||||
RawKeyEventData data;
|
||||
String? character;
|
||||
|
||||
final String keymap = message['keymap'] as String;
|
||||
switch (keymap) {
|
||||
@ -284,13 +285,20 @@ abstract class RawKeyEvent with Diagnosticable {
|
||||
deviceId: message['deviceId'] as int? ?? 0,
|
||||
repeatCount: message['repeatCount'] as int? ?? 0,
|
||||
);
|
||||
if (message.containsKey('character')) {
|
||||
character = message['character'] as String?;
|
||||
}
|
||||
break;
|
||||
case 'fuchsia':
|
||||
final int codePoint = message['codePoint'] as int? ?? 0;
|
||||
data = RawKeyEventDataFuchsia(
|
||||
hidUsage: message['hidUsage'] as int? ?? 0,
|
||||
codePoint: message['codePoint'] as int? ?? 0,
|
||||
codePoint: codePoint,
|
||||
modifiers: message['modifiers'] as int? ?? 0,
|
||||
);
|
||||
if (codePoint != 0) {
|
||||
character = String.fromCharCode(codePoint);
|
||||
}
|
||||
break;
|
||||
case 'macos':
|
||||
data = RawKeyEventDataMacOs(
|
||||
@ -298,15 +306,20 @@ abstract class RawKeyEvent with Diagnosticable {
|
||||
charactersIgnoringModifiers: message['charactersIgnoringModifiers'] as String? ?? '',
|
||||
keyCode: message['keyCode'] as int? ?? 0,
|
||||
modifiers: message['modifiers'] as int? ?? 0);
|
||||
character = message['characters'] as String?;
|
||||
break;
|
||||
case 'linux':
|
||||
final int unicodeScalarValues = message['unicodeScalarValues'] as int? ?? 0;
|
||||
data = RawKeyEventDataLinux(
|
||||
keyHelper: KeyHelper(message['toolkit'] as String? ?? ''),
|
||||
unicodeScalarValues: message['unicodeScalarValues'] as int? ?? 0,
|
||||
unicodeScalarValues: unicodeScalarValues,
|
||||
keyCode: message['keyCode'] as int? ?? 0,
|
||||
scanCode: message['scanCode'] as int? ?? 0,
|
||||
modifiers: message['modifiers'] as int? ?? 0,
|
||||
isDown: message['type'] == 'keydown');
|
||||
if (unicodeScalarValues != 0) {
|
||||
character = String.fromCharCode(unicodeScalarValues);
|
||||
}
|
||||
break;
|
||||
case 'web':
|
||||
data = RawKeyEventDataWeb(
|
||||
@ -314,14 +327,19 @@ abstract class RawKeyEvent with Diagnosticable {
|
||||
key: message['key'] as String? ?? '',
|
||||
metaState: message['metaState'] as int? ?? 0,
|
||||
);
|
||||
character = message['key'] as String?;
|
||||
break;
|
||||
case 'windows':
|
||||
final int characterCodePoint = message['characterCodePoint'] as int? ?? 0;
|
||||
data = RawKeyEventDataWindows(
|
||||
keyCode: message['keyCode'] as int? ?? 0,
|
||||
scanCode: message['scanCode'] as int? ?? 0,
|
||||
characterCodePoint: message['characterCodePoint'] as int? ?? 0,
|
||||
characterCodePoint: characterCodePoint,
|
||||
modifiers: message['modifiers'] as int? ?? 0,
|
||||
);
|
||||
if (characterCodePoint != 0) {
|
||||
character = String.fromCharCode(characterCodePoint);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Raw key events are not yet implemented on iOS or other platforms,
|
||||
@ -333,7 +351,7 @@ abstract class RawKeyEvent with Diagnosticable {
|
||||
final String type = message['type'] as String;
|
||||
switch (type) {
|
||||
case 'keydown':
|
||||
return RawKeyDownEvent(data: data, character: message['character'] as String);
|
||||
return RawKeyDownEvent(data: data, character: character);
|
||||
case 'keyup':
|
||||
return RawKeyUpEvent(data: data);
|
||||
default:
|
||||
|
@ -17,6 +17,30 @@ class _ModifierCheck {
|
||||
|
||||
void main() {
|
||||
group('RawKeyboard', () {
|
||||
testWidgets('The correct character is produced', (WidgetTester tester) async {
|
||||
for (final String platform in <String>['linux', 'android', 'macos', 'fuchsia', 'windows']) {
|
||||
String character = '';
|
||||
void handleKey(RawKeyEvent event) {
|
||||
expect(event.character, equals(character), reason: 'on $platform');
|
||||
}
|
||||
RawKeyboard.instance.addListener(handleKey);
|
||||
character = 'a';
|
||||
await simulateKeyDownEvent(LogicalKeyboardKey.keyA, platform: platform);
|
||||
character = '`';
|
||||
await simulateKeyDownEvent(LogicalKeyboardKey.backquote, platform: platform);
|
||||
RawKeyboard.instance.removeListener(handleKey);
|
||||
}
|
||||
});
|
||||
testWidgets('No character is produced for non-printables', (WidgetTester tester) async {
|
||||
for (final String platform in <String>['linux', 'android', 'macos', 'fuchsia', 'windows']) {
|
||||
void handleKey(RawKeyEvent event) {
|
||||
expect(event.character, isNull, reason: 'on $platform');
|
||||
}
|
||||
RawKeyboard.instance.addListener(handleKey);
|
||||
await simulateKeyDownEvent(LogicalKeyboardKey.shiftLeft, platform: platform);
|
||||
RawKeyboard.instance.removeListener(handleKey);
|
||||
}
|
||||
});
|
||||
testWidgets('keysPressed is maintained', (WidgetTester tester) async {
|
||||
for (final String platform in <String>['linux', 'android', 'macos', 'fuchsia', 'windows']) {
|
||||
RawKeyboard.instance.clearKeysPressed();
|
||||
|
@ -174,7 +174,6 @@ class KeyEventSimulator {
|
||||
final Map<String, dynamic> result = <String, dynamic>{
|
||||
'type': isDown ? 'keydown' : 'keyup',
|
||||
'keymap': platform,
|
||||
'character': key.keyLabel,
|
||||
};
|
||||
|
||||
switch (platform) {
|
||||
@ -182,6 +181,7 @@ class KeyEventSimulator {
|
||||
result['keyCode'] = keyCode;
|
||||
if (key.keyLabel.isNotEmpty) {
|
||||
result['codePoint'] = key.keyLabel.codeUnitAt(0);
|
||||
result['character'] = key.keyLabel;
|
||||
}
|
||||
result['scanCode'] = scanCode;
|
||||
result['metaState'] = _getAndroidModifierFlags(key, isDown);
|
||||
@ -198,16 +198,19 @@ class KeyEventSimulator {
|
||||
result['keyCode'] = keyCode;
|
||||
result['scanCode'] = scanCode;
|
||||
result['modifiers'] = _getGlfwModifierFlags(key, isDown);
|
||||
result['unicodeScalarValues'] = key.keyLabel.isNotEmpty ? key.keyLabel.codeUnitAt(0) : 0;
|
||||
break;
|
||||
case 'macos':
|
||||
result['keyCode'] = scanCode;
|
||||
result['characters'] = key.keyLabel;
|
||||
result['charactersIgnoringModifiers'] = key.keyLabel;
|
||||
if (key.keyLabel.isNotEmpty) {
|
||||
result['characters'] = key.keyLabel;
|
||||
result['charactersIgnoringModifiers'] = key.keyLabel;
|
||||
}
|
||||
result['modifiers'] = _getMacOsModifierFlags(key, isDown);
|
||||
break;
|
||||
case 'web':
|
||||
result['code'] = _getWebKeyCode(key);
|
||||
result['key'] = '';
|
||||
result['key'] = key.keyLabel;
|
||||
result['metaState'] = _getWebModifierFlags(key, isDown);
|
||||
break;
|
||||
case 'windows':
|
||||
|
Loading…
x
Reference in New Issue
Block a user