| // 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. | |
| /// @docImport 'package:flutter/widgets.dart'; | |
| /// | |
| /// @docImport 'raw_keyboard.dart'; | |
| library; | |
| import 'package:flutter/foundation.dart'; | |
| export 'package:flutter/foundation.dart' show DiagnosticPropertiesBuilder; | |
| // 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. | |
| // | |
| // Edit the template dev/tools/gen_keycodes/data/keyboard_key.tmpl instead. | |
| // See dev/tools/gen_keycodes/README.md for more information. | |
| /// A base class for all keyboard key types. | |
| /// | |
| /// See also: | |
| /// | |
| /// * [PhysicalKeyboardKey], a class with static values that describe the keys | |
| /// that are returned from [RawKeyEvent.physicalKey]. | |
| /// * [LogicalKeyboardKey], a class with static values that describe the keys | |
| /// that are returned from [RawKeyEvent.logicalKey]. | |
| abstract class KeyboardKey with Diagnosticable { | |
| /// Abstract const constructor. This constructor enables subclasses to provide | |
| /// const constructors so that they can be used in const expressions. | |
| const KeyboardKey(); | |
| } | |
| /// A class with static values that describe the keys that are returned from | |
| /// [RawKeyEvent.logicalKey]. | |
| /// | |
| /// These represent *logical* keys, which are keys which are interpreted in the | |
| /// context of any modifiers, modes, or keyboard layouts which may be in effect. | |
| /// | |
| /// This is contrast to [PhysicalKeyboardKey], which represents a physical key | |
| /// in a particular location on the keyboard, without regard for the modifier | |
| /// state, mode, or keyboard layout. | |
| /// | |
| /// As an example, if you wanted to implement an app where the "Q" key "quit" | |
| /// something, you'd want to look at the logical key to detect this, since you | |
| /// would like to have it match the key with "Q" on it, instead of always | |
| /// looking for "the key next to the TAB key", since on a French keyboard, | |
| /// the key next to the TAB key has an "A" on it. | |
| /// | |
| /// Conversely, if you wanted a game where the key next to the CAPS LOCK (the | |
| /// "A" key on a QWERTY keyboard) moved the player to the left, you'd want to | |
| /// look at the physical key to make sure that regardless of the character the | |
| /// key produces, you got the key that is in that location on the keyboard. | |
| /// | |
| /// {@tool dartpad} | |
| /// This example shows how to detect if the user has selected the logical "Q" | |
| /// key and handle the key if they have. | |
| /// | |
| /// ** See code in examples/api/lib/services/keyboard_key/logical_keyboard_key.0.dart ** | |
| /// {@end-tool} | |
| /// See also: | |
| /// | |
| /// * [RawKeyEvent], the keyboard event object received by widgets that listen | |
| /// to keyboard events. | |
| /// * [Focus.onKey], the handler on a widget that lets you handle key events. | |
| /// * [RawKeyboardListener], a widget used to listen to keyboard events (but | |
| /// not handle them). | |
| @immutable | |
| class LogicalKeyboardKey extends KeyboardKey { | |
| /// Creates a new LogicalKeyboardKey object for a key ID. | |
| const LogicalKeyboardKey(this.keyId); | |
| /// A unique code representing this key. | |
| /// | |
| /// This is an opaque code. It should not be unpacked to derive information | |
| /// from it, as the representation of the code could change at any time. | |
| final int keyId; | |
| // Returns the bits that are not included in [valueMask], shifted to the | |
| // right. | |
| // | |
| // For example, if the input is 0x12abcdabcd, then the result is 0x12. | |
| // | |
| // This is mostly equivalent to a right shift, resolving the problem that | |
| // JavaScript only support 32-bit bitwise operation and needs to use division | |
| // instead. | |
| static int _nonValueBits(int n) { | |
| // `n >> valueMaskWidth` is equivalent to `n / divisorForValueMask`. | |
| const int divisorForValueMask = valueMask + 1; | |
| const int valueMaskWidth = 32; | |
| // Equivalent to assert(divisorForValueMask == (1 << valueMaskWidth)). | |
| const int firstDivisorWidth = 28; | |
| assert(divisorForValueMask == | |
| (1 << firstDivisorWidth) * (1 << (valueMaskWidth - firstDivisorWidth))); | |
| // JS only supports up to 2^53 - 1, therefore non-value bits can only | |
| // contain (maxSafeIntegerWidth - valueMaskWidth) bits. | |
| const int maxSafeIntegerWidth = 52; | |
| const int nonValueMask = (1 << (maxSafeIntegerWidth - valueMaskWidth)) - 1; | |
| if (kIsWeb) { | |
| return (n / divisorForValueMask).floor() & nonValueMask; | |
| } else { | |
| return (n >> valueMaskWidth) & nonValueMask; | |
| } | |
| } | |
| static String? _unicodeKeyLabel(int keyId) { | |
| if (_nonValueBits(keyId) == 0) { | |
| return String.fromCharCode(keyId).toUpperCase(); | |
| } | |
| return null; | |
| } | |
| /// A description representing the character produced by a [RawKeyEvent]. | |
| /// | |
| /// This value is useful for providing readable strings for keys or keyboard | |
| /// shortcuts. Do not use this value to compare equality of keys; compare | |
| /// [keyId] instead. | |
| /// | |
| /// For printable keys, this is usually the printable character in upper case | |
| /// ignoring modifiers or combining keys, such as 'A', '1', or '/'. This | |
| /// might also return accented letters (such as 'Ù') for keys labeled as so, | |
| /// but not if such character is a result from preceding combining keys ('`̀' | |
| /// followed by key U). | |
| /// | |
| /// For other keys, [keyLabel] looks up the full key name from a predefined | |
| /// map, such as 'F1', 'Shift Left', or 'Media Down'. This value is an empty | |
| /// string if there's no key label data for a key. | |
| /// | |
| /// For the printable representation that takes into consideration the | |
| /// modifiers and combining keys, see [RawKeyEvent.character]. | |
| /// | |
| /// {@macro flutter.services.RawKeyEventData.keyLabel} | |
| String get keyLabel { | |
| return _unicodeKeyLabel(keyId) | |
| ?? _keyLabels[keyId] | |
| ?? ''; | |
| } | |
| /// The debug string to print for this keyboard key, which will be null in | |
| /// release mode. | |
| /// | |
| /// For printable keys, this is usually a more descriptive name related to | |
| /// [keyLabel], such as 'Key A', 'Digit 1', 'Backslash'. This might | |
| /// also return accented letters (such as 'Key Ù') for keys labeled as so. | |
| /// | |
| /// For other keys, this looks up the full key name from a predefined map (the | |
| /// same value as [keyLabel]), such as 'F1', 'Shift Left', or 'Media Down'. If | |
| /// there's no key label data for a key, this returns a name that explains the | |
| /// ID (such as 'Key with ID 0x00100012345'). | |
| String? get debugName { | |
| String? result; | |
| assert(() { | |
| result = _keyLabels[keyId]; | |
| if (result == null) { | |
| final String? unicodeKeyLabel = _unicodeKeyLabel(keyId); | |
| if (unicodeKeyLabel != null) { | |
| result = 'Key $unicodeKeyLabel'; | |
| } else { | |
| result = 'Key with ID 0x${keyId.toRadixString(16).padLeft(11, '0')}'; | |
| } | |
| } | |
| return true; | |
| }()); | |
| return result; | |
| } | |
| @override | |
| int get hashCode => keyId.hashCode; | |
| @override | |
| bool operator ==(Object other) { | |
| if (identical(this, other)) { | |
| return true; | |
| } | |
| if (other.runtimeType != runtimeType) { | |
| return false; | |
| } | |
| return other is LogicalKeyboardKey | |
| && other.keyId == keyId; | |
| } | |
| /// Returns the [LogicalKeyboardKey] constant that matches the given ID, or | |
| /// null, if not found. | |
| static LogicalKeyboardKey? findKeyByKeyId(int keyId) => _knownLogicalKeys[keyId]; | |
| /// Returns true if the given label represents a Unicode control character. | |
| /// | |
| /// Examples of control characters are characters like "U+000A LINE FEED (LF)" | |
| /// or "U+001B ESCAPE (ESC)". | |
| /// | |
| /// See <https://en.wikipedia.org/wiki/Unicode_control_characters> for more | |
| /// information. | |
| /// | |
| /// Used by [RawKeyEvent] subclasses to help construct IDs. | |
| static bool isControlCharacter(String label) { | |
| if (label.length != 1) { | |
| return false; | |
| } | |
| final int codeUnit = label.codeUnitAt(0); | |
| return (codeUnit <= 0x1f && codeUnit >= 0x00) || (codeUnit >= 0x7f && codeUnit <= 0x9f); | |
| } | |
| /// Returns true if the [keyId] of this object is one that is auto-generated by | |
| /// Flutter. | |
| /// | |
| /// Auto-generated key IDs are generated in response to platform key codes | |
| /// which Flutter doesn't recognize, and their IDs shouldn't be used in a | |
| /// persistent way. | |
| /// | |
| /// Auto-generated IDs should be a rare occurrence: Flutter supports most keys. | |
| /// | |
| /// Keys that generate Unicode characters (even if unknown to Flutter) will | |
| /// not return true for [isAutogenerated], since they will be assigned a | |
| /// Unicode-based code that will remain stable. | |
| /// | |
| /// If Flutter adds support for a previously unsupported key code, the ID it | |
| /// reports will change, but the ID will remain stable on the platform it is | |
| /// produced on until Flutter adds support for recognizing it. | |
| /// | |
| /// So, hypothetically, if Android added a new key code of 0xffff, | |
| /// representing a new "do what I mean" key, then the auto-generated code | |
| /// would be 0x1020000ffff, but once Flutter added the "doWhatIMean" key to | |
| /// the definitions below, the new code would be 0x0020000ffff for all | |
| /// platforms that had a "do what I mean" key from then on. | |
| bool get isAutogenerated => (keyId & planeMask) >= startOfPlatformPlanes; | |
| /// Returns a set of pseudo-key synonyms for the given `key`. | |
| /// | |
| /// This allows finding the pseudo-keys that also represent a concrete `key` | |
| /// so that a class with a key map can match pseudo-keys as well as the actual | |
| /// generated keys. | |
| /// | |
| /// Pseudo-keys returned in the set are typically used to represent keys which | |
| /// appear in multiple places on the keyboard, such as the [shift], [alt], | |
| /// [control], and [meta] keys. Pseudo-keys in the returned set won't ever be | |
| /// generated directly, but if a more specific key event is received, then | |
| /// this set can be used to find the more general pseudo-key. For example, if | |
| /// this is a [shiftLeft] key, this accessor will return the set | |
| /// `<LogicalKeyboardKey>{ shift }`. | |
| Set<LogicalKeyboardKey> get synonyms => _synonyms[this] ?? <LogicalKeyboardKey>{}; | |
| /// Takes a set of keys, and returns the same set, but with any keys that have | |
| /// synonyms replaced. | |
| /// | |
| /// It is used, for example, to take sets of keys with members like | |
| /// [controlRight] and [controlLeft] and convert that set to contain just | |
| /// [control], so that the question "is any control key down?" can be asked. | |
| static Set<LogicalKeyboardKey> collapseSynonyms(Set<LogicalKeyboardKey> input) { | |
| return input.expand((LogicalKeyboardKey element) { | |
| return _synonyms[element] ?? <LogicalKeyboardKey>{element}; | |
| }).toSet(); | |
| } | |
| /// Returns the given set with any pseudo-keys expanded into their synonyms. | |
| /// | |
| /// It is used, for example, to take sets of keys with members like [control] | |
| /// and [shift] and convert that set to contain [controlLeft], [controlRight], | |
| /// [shiftLeft], and [shiftRight]. | |
| static Set<LogicalKeyboardKey> expandSynonyms(Set<LogicalKeyboardKey> input) { | |
| return input.expand((LogicalKeyboardKey element) { | |
| return _reverseSynonyms[element] ?? <LogicalKeyboardKey>{element}; | |
| }).toSet(); | |
| } | |
| @override | |
| void debugFillProperties(DiagnosticPropertiesBuilder properties) { | |
| super.debugFillProperties(properties); | |
| properties.add(StringProperty('keyId', '0x${keyId.toRadixString(16).padLeft(8, '0')}')); | |
| properties.add(StringProperty('keyLabel', keyLabel)); | |
| properties.add(StringProperty('debugName', debugName, defaultValue: null)); | |
| } | |
| @@@MASK_CONSTANTS@@@ | |
| @@@LOGICAL_KEY_DEFINITIONS@@@ | |
| /// A list of all predefined constant [LogicalKeyboardKey]s. | |
| static Iterable<LogicalKeyboardKey> get knownLogicalKeys => _knownLogicalKeys.values; | |
| // A list of all predefined constant LogicalKeyboardKeys so they can be | |
| // searched. | |
| static const Map<int, LogicalKeyboardKey> _knownLogicalKeys = <int, LogicalKeyboardKey>{ | |
| @@@LOGICAL_KEY_MAP@@@ | |
| }; | |
| // A map of keys to the pseudo-key synonym for that key. | |
| static final Map<LogicalKeyboardKey, Set<LogicalKeyboardKey>> _synonyms = <LogicalKeyboardKey, Set<LogicalKeyboardKey>>{ | |
| @@@LOGICAL_KEY_SYNONYMS@@@ }; | |
| // A map of pseudo-key to the set of keys that are synonyms for that pseudo-key. | |
| static final Map<LogicalKeyboardKey, Set<LogicalKeyboardKey>> _reverseSynonyms = <LogicalKeyboardKey, Set<LogicalKeyboardKey>>{ | |
| @@@LOGICAL_KEY_REVERSE_SYNONYMS@@@ }; | |
| static const Map<int, String> _keyLabels = <int, String>{ | |
| @@@LOGICAL_KEY_KEY_LABELS@@@ | |
| }; | |
| } | |
| /// A class with static values that describe the keys that are returned from | |
| /// [RawKeyEvent.physicalKey]. | |
| /// | |
| /// These represent *physical* keys, which are keys which represent a particular | |
| /// key location on a QWERTY keyboard. It ignores any modifiers, modes, or | |
| /// keyboard layouts which may be in effect. This is contrast to | |
| /// [LogicalKeyboardKey], which represents a logical key interpreted in the | |
| /// context of modifiers, modes, and/or keyboard layouts. | |
| /// | |
| /// As an example, if you wanted a game where the key next to the CAPS LOCK (the | |
| /// "A" key on a QWERTY keyboard) moved the player to the left, you'd want to | |
| /// look at the physical key to make sure that regardless of the character the | |
| /// key produces, you got the key that is in that location on the keyboard. | |
| /// | |
| /// Conversely, if you wanted to implement an app where the "Q" key "quit" | |
| /// something, you'd want to look at the logical key to detect this, since you | |
| /// would like to have it match the key with "Q" on it, instead of always | |
| /// looking for "the key next to the TAB key", since on a French keyboard, | |
| /// the key next to the TAB key has an "A" on it. | |
| /// | |
| /// {@tool dartpad} | |
| /// This example shows how to detect if the user has selected the physical key | |
| /// to the right of the CAPS LOCK key. | |
| /// | |
| /// ** See code in examples/api/lib/services/keyboard_key/physical_keyboard_key.0.dart ** | |
| /// {@end-tool} | |
| /// | |
| /// See also: | |
| /// | |
| /// * [RawKeyEvent], the keyboard event object received by widgets that listen | |
| /// to keyboard events. | |
| /// * [Focus.onKey], the handler on a widget that lets you handle key events. | |
| /// * [RawKeyboardListener], a widget used to listen to keyboard events (but | |
| /// not handle them). | |
| @immutable | |
| class PhysicalKeyboardKey extends KeyboardKey { | |
| /// Creates a new PhysicalKeyboardKey object for a USB HID usage. | |
| const PhysicalKeyboardKey(this.usbHidUsage); | |
| /// The unique USB HID usage ID of this physical key on the keyboard. | |
| /// | |
| /// Due to the variations in platform APIs, this may not be the actual HID | |
| /// usage code from the hardware, but a value derived from available | |
| /// information on the platform. | |
| /// | |
| /// See <https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf> | |
| /// for the HID usage values and their meanings. | |
| final int usbHidUsage; | |
| /// The debug string to print for this keyboard key, which will be null in | |
| /// release mode. | |
| String? get debugName { | |
| String? result; | |
| assert(() { | |
| result = _debugNames[usbHidUsage] ?? | |
| 'Key with ID 0x${usbHidUsage.toRadixString(16).padLeft(8, '0')}'; | |
| return true; | |
| }()); | |
| return result; | |
| } | |
| @override | |
| int get hashCode => usbHidUsage.hashCode; | |
| @override | |
| bool operator ==(Object other) { | |
| if (identical(this, other)) { | |
| return true; | |
| } | |
| if (other.runtimeType != runtimeType) { | |
| return false; | |
| } | |
| return other is PhysicalKeyboardKey | |
| && other.usbHidUsage == usbHidUsage; | |
| } | |
| /// Finds a known [PhysicalKeyboardKey] that matches the given USB HID usage | |
| /// code. | |
| static PhysicalKeyboardKey? findKeyByCode(int usageCode) => _knownPhysicalKeys[usageCode]; | |
| @override | |
| void debugFillProperties(DiagnosticPropertiesBuilder properties) { | |
| super.debugFillProperties(properties); | |
| properties.add(StringProperty('usbHidUsage', '0x${usbHidUsage.toRadixString(16).padLeft(8, '0')}')); | |
| properties.add(StringProperty('debugName', debugName, defaultValue: null)); | |
| } | |
| // Key constants for all keyboard keys in the USB HID specification at the | |
| // time Flutter was built. | |
| @@@PHYSICAL_KEY_DEFINITIONS@@@ | |
| /// A list of all predefined constant [PhysicalKeyboardKey]s. | |
| static Iterable<PhysicalKeyboardKey> get knownPhysicalKeys => _knownPhysicalKeys.values; | |
| // A list of all the predefined constant PhysicalKeyboardKeys so that they | |
| // can be searched. | |
| static const Map<int, PhysicalKeyboardKey> _knownPhysicalKeys = <int, PhysicalKeyboardKey>{ | |
| @@@PHYSICAL_KEY_MAP@@@ | |
| }; | |
| static const Map<int, String> _debugNames = kReleaseMode ? | |
| <int, String>{} : | |
| <int, String>{ | |
| @@@PHYSICAL_KEY_DEBUG_NAMES@@@ | |
| }; | |
| } |