Unverified Commit 199a7c19 authored by Greg Spencer's avatar Greg Spencer Committed by GitHub

Fix the `character` field of the `RawKeyEvent` to hold correct data on...

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