| // Copyright 2014 The Flutter Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| import 'package:path/path.dart' as path; | |
| import 'base_code_gen.dart'; | |
| import 'constants.dart'; | |
| import 'data.dart'; | |
| import 'logical_key_data.dart'; | |
| import 'physical_key_data.dart'; | |
| import 'utils.dart'; | |
| const List<String> kModifiersOfInterest = <String>[ | |
| 'ShiftLeft', | |
| 'ShiftRight', | |
| 'ControlLeft', | |
| 'ControlRight', | |
| 'AltLeft', | |
| 'AltRight', | |
| 'MetaLeft', | |
| 'MetaRight', | |
| ]; | |
| // The name of keys that require special attention. | |
| const List<String> kSpecialPhysicalKeys = <String>['CapsLock']; | |
| const List<String> kSpecialLogicalKeys = <String>['CapsLock']; | |
| /// Generates the key mapping for iOS, based on the information in the key | |
| /// data structure given to it. | |
| class IOSCodeGenerator extends PlatformCodeGenerator { | |
| IOSCodeGenerator(super.keyData, super.logicalData); | |
| /// This generates the map of iOS key codes to physical keys. | |
| String get _scanCodeMap { | |
| final lines = OutputLines<int>('iOS scancode map'); | |
| for (final PhysicalKeyEntry entry in keyData.entries) { | |
| if (entry.iOSScanCode != null) { | |
| lines.add( | |
| entry.iOSScanCode!, | |
| ' {${toHex(entry.iOSScanCode)}, ${toHex(entry.usbHidCode)}}, // ${entry.constantName}', | |
| ); | |
| } | |
| } | |
| return lines.sortedJoin().trimRight(); | |
| } | |
| Iterable<PhysicalKeyEntry> get _functionKeyData { | |
| final functionKeyRe = RegExp(r'^f[0-9]+$'); | |
| return keyData.entries.where((PhysicalKeyEntry entry) { | |
| return functionKeyRe.hasMatch(entry.constantName); | |
| }); | |
| } | |
| String get _functionKeys { | |
| final result = StringBuffer(); | |
| for (final PhysicalKeyEntry entry in _functionKeyData) { | |
| result.writeln(' ${toHex(entry.iOSScanCode)}, // ${entry.constantName}'); | |
| } | |
| return result.toString().trimRight(); | |
| } | |
| String get _keyCodeToLogicalMap { | |
| final lines = OutputLines<int>('iOS keycode map'); | |
| for (final LogicalKeyEntry entry in logicalData.entries) { | |
| zipStrict(entry.iOSKeyCodeValues, entry.iOSKeyCodeNames, (int iOSValue, String iOSName) { | |
| lines.add( | |
| iOSValue, | |
| ' {${toHex(iOSValue)}, ${toHex(entry.value, digits: 11)}}, // $iOSName', | |
| ); | |
| }); | |
| } | |
| return lines.sortedJoin().trimRight(); | |
| } | |
| /// This generates the mask values for the part of a key code that defines its plane. | |
| String get _maskConstants { | |
| final buffer = StringBuffer(); | |
| const maskConstants = <MaskConstant>[kValueMask, kUnicodePlane, kIosPlane]; | |
| for (final constant in maskConstants) { | |
| buffer.writeln('/**'); | |
| buffer.write(wrapString(constant.description, prefix: ' * ')); | |
| buffer.writeln(' */'); | |
| buffer.writeln( | |
| 'const uint64_t k${constant.upperCamelName} = ${toHex(constant.value, digits: 11)};', | |
| ); | |
| buffer.writeln(); | |
| } | |
| return buffer.toString().trimRight(); | |
| } | |
| /// This generates a map from the key code to a modifier flag. | |
| String get _keyToModifierFlagMap { | |
| final modifierKeyMap = StringBuffer(); | |
| for (final String name in kModifiersOfInterest) { | |
| final line = | |
| '{${toHex(logicalData.entryByName(name).iOSKeyCodeValues[0])}, kModifierFlag${lowerCamelToUpperCamel(name)}},'; | |
| modifierKeyMap.writeln(' ${line.padRight(42)}// $name'); | |
| } | |
| return modifierKeyMap.toString().trimRight(); | |
| } | |
| /// This generates a map from the modifier flag to the key code. | |
| String get _modifierFlagToKeyMap { | |
| final modifierKeyMap = StringBuffer(); | |
| for (final String name in kModifiersOfInterest) { | |
| final line = | |
| '{kModifierFlag${lowerCamelToUpperCamel(name)}, ${toHex(logicalData.entryByName(name).iOSKeyCodeValues[0])}},'; | |
| modifierKeyMap.writeln(' ${line.padRight(42)}// $name'); | |
| } | |
| return modifierKeyMap.toString().trimRight(); | |
| } | |
| String get _specialKeyMapping { | |
| final lines = OutputLines<int>('iOS special key mapping'); | |
| kIosSpecialKeyMapping.forEach((String key, String logicalName) { | |
| final int value = logicalData.entryByName(logicalName).value; | |
| lines.add(value, ' @"$key" : @(${toHex(value)}),'); | |
| }); | |
| return lines.join().trimRight(); | |
| } | |
| /// This generates some keys that needs special attention. | |
| String get _specialKeyConstants { | |
| final specialKeyConstants = StringBuffer(); | |
| for (final String keyName in kSpecialPhysicalKeys) { | |
| specialKeyConstants.writeln( | |
| 'const uint64_t k${keyName}PhysicalKey = ${toHex(keyData.entryByName(keyName).usbHidCode)};', | |
| ); | |
| } | |
| for (final String keyName in kSpecialLogicalKeys) { | |
| specialKeyConstants.writeln( | |
| 'const uint64_t k${lowerCamelToUpperCamel(keyName)}LogicalKey = ${toHex(logicalData.entryByName(keyName).value)};', | |
| ); | |
| } | |
| return specialKeyConstants.toString().trimRight(); | |
| } | |
| @override | |
| String get templatePath => path.join(dataRoot, 'ios_key_code_map_mm.tmpl'); | |
| @override | |
| String outputPath(String platform) => path.join( | |
| PlatformCodeGenerator.engineRoot, | |
| 'shell', | |
| 'platform', | |
| 'darwin', | |
| 'ios', | |
| 'framework', | |
| 'Source', | |
| 'KeyCodeMap.g.mm', | |
| ); | |
| @override | |
| Map<String, String> mappings() { | |
| // There is no iOS keycode map since iOS uses keycode to represent a physical key. | |
| // The LogicalKeyboardKey is generated by raw_keyboard_ios.dart from the unmodified characters | |
| // from NSEvent. | |
| return <String, String>{ | |
| 'MASK_CONSTANTS': _maskConstants, | |
| 'IOS_SCAN_CODE_MAP': _scanCodeMap, | |
| 'IOS_KEYCODE_LOGICAL_MAP': _keyCodeToLogicalMap, | |
| 'IOS_FUNCTION_KEY_SET': _functionKeys, | |
| 'KEYCODE_TO_MODIFIER_FLAG_MAP': _keyToModifierFlagMap, | |
| 'MODIFIER_FLAG_TO_KEYCODE_MAP': _modifierFlagToKeyMap, | |
| 'SPECIAL_KEY_CONSTANTS': _specialKeyConstants, | |
| 'SPECIAL_KEY_MAPPING': _specialKeyMapping, | |
| }; | |
| } | |
| } |