// 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:flutter/foundation.dart'; // 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 --template=stateful_widget_scaffold} /// This example shows how to detect if the user has selected the logical "Q" /// key. /// /// ```dart imports /// import 'package:flutter/foundation.dart'; /// import 'package:flutter/services.dart'; /// ``` /// /// ```dart /// // The node used to request the keyboard focus. /// final FocusNode _focusNode = FocusNode(); /// // The message to display. /// String? _message; /// /// // Focus nodes need to be disposed. /// @override /// void dispose() { /// _focusNode.dispose(); /// super.dispose(); /// } /// /// // Handles the key events from the RawKeyboardListener and update the /// // _message. /// void _handleKeyEvent(RawKeyEvent event) { /// setState(() { /// if (event.logicalKey == LogicalKeyboardKey.keyQ) { /// _message = 'Pressed the "Q" key!'; /// } else { /// if (kReleaseMode) { /// _message = 'Not a Q: Pressed 0x${event.logicalKey.keyId.toRadixString(16)}'; /// } else { /// // The debugName will only print useful information in debug mode. /// _message = 'Not a Q: Pressed ${event.logicalKey.debugName}'; /// } /// } /// }); /// } /// /// @override /// Widget build(BuildContext context) { /// final TextTheme textTheme = Theme.of(context).textTheme; /// return Container( /// color: Colors.white, /// alignment: Alignment.center, /// child: DefaultTextStyle( /// style: textTheme.headline4!, /// child: RawKeyboardListener( /// focusNode: _focusNode, /// onKey: _handleKeyEvent, /// child: AnimatedBuilder( /// animation: _focusNode, /// builder: (BuildContext context, Widget? child) { /// if (!_focusNode.hasFocus) { /// return GestureDetector( /// onTap: () { /// FocusScope.of(context).requestFocus(_focusNode); /// }, /// child: const Text('Tap to focus'), /// ); /// } /// return Text(_message ?? 'Press a key'); /// }, /// ), /// ), /// ), /// ); /// } /// ``` /// {@end-tool} /// See also: /// /// * [RawKeyEvent], the keyboard event object received by widgets that listen /// to keyboard events. /// * [RawKeyboardListener], a widget used to listen to and supply handlers for /// keyboard events. @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 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 & autogeneratedMask) != 0; /// Returns a set of pseudo-key synonyms for the given `key`. /// /// This allows finding the pseudo-keys that also represents a concrete /// `key` so that a class with a key map can match pseudo-keys as well as the /// actual generated keys. /// /// The 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. The 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 /// `{ shift }`. Set get synonyms { final LogicalKeyboardKey? result = _synonyms[this]; return result == null ? {} : {result}; } /// Takes a set of keys, and returns the same set, but with any keys that have /// synonyms replaced. /// /// It is used, for example, to make 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 collapseSynonyms(Set input) { final Set result = {}; for (final LogicalKeyboardKey key in input) { final LogicalKeyboardKey? synonym = _synonyms[key]; result.add(synonym ?? key); } return result; } @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); properties.add(StringProperty('keyId', '0x${keyId.toRadixString(16).padLeft(8, '0')}', showName: true)); properties.add(StringProperty('keyLabel', keyLabel, showName: true)); properties.add(StringProperty('debugName', debugName, showName: true, defaultValue: null)); } /// Mask for the 32-bit value portion of the key code. /// /// This is used by platform-specific code to generate Flutter key codes. static const int valueMask = 0x000FFFFFFFF; /// Mask for the platform prefix portion of the key code. /// /// This is used by platform-specific code to generate Flutter key codes. static const int platformMask = 0x0FF00000000; /// Mask for the auto-generated bit portion of the key code. /// /// This is used by platform-specific code to generate new Flutter key codes /// for keys which are not recognized. static const int autogeneratedMask = 0x10000000000; /// Mask for the synonym pseudo-keys generated for keys which appear in more /// than one place on the keyboard. /// /// IDs in this range are used to represent keys which appear in multiple /// places on the keyboard, such as the SHIFT, ALT, CTRL, and numeric keypad /// keys. These key codes will never be generated by the key event system, but /// may be used in key maps to represent the union of all the keys of each /// type in order to match them. /// /// To look up the synonyms that are defined, look in the [synonyms] map. static const int synonymMask = 0x20000000000; /// The code prefix for keys which have a Unicode representation. /// /// This is used by platform-specific code to generate Flutter key codes. static const int unicodePlane = 0x00000000000; /// The code prefix for keys which do not have a Unicode representation. /// /// This is used by platform-specific code to generate Flutter key codes using /// HID Usage codes. static const int hidPlane = 0x00100000000; @@@LOGICAL_KEY_DEFINITIONS@@@ // A list of all predefined constant LogicalKeyboardKeys so they can be // searched. static const Map _knownLogicalKeys = { @@@LOGICAL_KEY_MAP@@@ }; // A map of keys to the pseudo-key synonym for that key. Used by getSynonyms. static final Map _synonyms = { @@@LOGICAL_KEY_SYNONYMS@@@ }; static const Map _keyLabels = { @@@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 --template=stateful_widget_scaffold} /// This example shows how to detect if the user has selected the physical key /// to the right of the CAPS LOCK key. /// /// ```dart imports /// import 'package:flutter/services.dart'; /// ``` /// /// ```dart /// // The node used to request the keyboard focus. /// final FocusNode _focusNode = FocusNode(); /// // The message to display. /// String? _message; /// /// // Focus nodes need to be disposed. /// @override /// void dispose() { /// _focusNode.dispose(); /// super.dispose(); /// } /// /// // Handles the key events from the RawKeyboardListener and update the /// // _message. /// void _handleKeyEvent(RawKeyEvent event) { /// setState(() { /// if (event.physicalKey == PhysicalKeyboardKey.keyA) { /// _message = 'Pressed the key next to CAPS LOCK!'; /// } else { /// _message = 'Wrong key.'; /// } /// }); /// } /// /// @override /// Widget build(BuildContext context) { /// final TextTheme textTheme = Theme.of(context).textTheme; /// return Container( /// color: Colors.white, /// alignment: Alignment.center, /// child: DefaultTextStyle( /// style: textTheme.headline4!, /// child: RawKeyboardListener( /// focusNode: _focusNode, /// onKey: _handleKeyEvent, /// child: AnimatedBuilder( /// animation: _focusNode, /// builder: (BuildContext context, Widget? child) { /// if (!_focusNode.hasFocus) { /// return GestureDetector( /// onTap: () { /// FocusScope.of(context).requestFocus(_focusNode); /// }, /// child: const Text('Tap to focus'), /// ); /// } /// return Text(_message ?? 'Press a key'); /// }, /// ), /// ), /// ), /// ); /// } /// ``` /// {@end-tool} /// /// See also: /// /// * [RawKeyEvent], the keyboard event object received by widgets that listen /// to keyboard events. /// * [RawKeyboardListener], a widget used to listen to and supply handlers for /// keyboard events. @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 /// 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')}', showName: true)); properties.add(StringProperty('debugName', debugName, showName: true, 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 the predefined constant PhysicalKeyboardKeys so that they // can be searched. static const Map _knownPhysicalKeys = { @@@PHYSICAL_KEY_MAP@@@ }; static const Map _debugNames = kReleaseMode ? {} : { @@@PHYSICAL_KEY_DEBUG_NAMES@@@ }; }