using System; using System.Collections.Generic; using System.Linq; using Unity.UIWidgets.foundation; namespace Unity.UIWidgets.services { public abstract class KeyboardKey : Diagnosticable { protected KeyboardKey() { } } public class LogicalKeyboardKey : KeyboardKey, IEquatable { public bool Equals(LogicalKeyboardKey other) { if (ReferenceEquals(null, other)) { return false; } if (ReferenceEquals(this, other)) { return true; } return keyId == other.keyId; } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) { return false; } if (ReferenceEquals(this, obj)) { return true; } if (obj.GetType() != GetType()) { return false; } return Equals((LogicalKeyboardKey) obj); } public override int GetHashCode() { unchecked { int hashCode = (int)keyId; hashCode = (hashCode * 397) ^ (debugName != null ? debugName.GetHashCode() : 0); hashCode = (hashCode * 397) ^ (keyLabel != null ? keyLabel.GetHashCode() : 0); return hashCode; } } protected LogicalKeyboardKey(long keyId, string debugName = null, string keyLabel = null) : base() { D.assert(keyId != null); this.keyId = keyId; this.debugName = debugName; this.keyLabel = keyLabel; } public readonly long keyId; public readonly string debugName; public readonly string keyLabel; public static LogicalKeyboardKey findKeyByKeyId(int keyId) => _knownLogicalKeys[keyId]; public static bool isControlCharacter(string label) { if (label.Length > 1) { return false; } int codeUnit = label[0]; return (codeUnit <= 0x1f && codeUnit >= 0x00) || (codeUnit >= 0x7f && codeUnit <= 0x9f); } public bool isAutogenerated { get { return (keyId & autogeneratedMask) != 0; } } public HashSet synonyms { get { HashSet result = new HashSet(); LogicalKeyboardKey item = _synonyms[this]; if (item == null) { return result; } result.Add(item: item); return result; } } public static HashSet collapseSynonyms(HashSet input) { HashSet result = new HashSet(); foreach (LogicalKeyboardKey key in input) { LogicalKeyboardKey synonym = _synonyms[key]; result.Add(synonym ?? key); } return result; } public override void debugFillProperties(DiagnosticPropertiesBuilder properties) { base.debugFillProperties(properties); properties.add(new StringProperty("keyId", keyId.ToString().PadLeft(8,'\0'), showName: true)); properties.add(new StringProperty("keyLabel", keyLabel, showName: true)); properties.add(new 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. public static readonly long valueMask = 0x000FFFFFFFF; /// Mask for the platform prefix portion of the key code. /// /// This is used by platform-specific code to generate Flutter key codes. public static readonly long 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. public static readonly long 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. public static readonly long synonymMask = 0x20000000000; /// The code prefix for keys which have a Unicode representation. /// /// This is used by platform-specific code to generate Flutter key codes. public static readonly long 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. public static readonly long hidPlane = 0x00100000000; /// Represents the logical "None" key on the keyboard. /// /// See the function [RawKeyEvent.logicalKey] for more information. public static readonly LogicalKeyboardKey none = new LogicalKeyboardKey(0x00100000000, debugName: foundation_.kReleaseMode ? null : "None"); /// Represents the logical "Control Left" key on the keyboard. /// /// See the function [RawKeyEvent.logicalKey] for more information. public static readonly LogicalKeyboardKey controlLeft = new LogicalKeyboardKey(0x001000700e0, debugName: foundation_.kReleaseMode ? null : "Control Left"); /// Represents the logical "Shift Left" key on the keyboard. /// /// See the function [RawKeyEvent.logicalKey] for more information. public static readonly LogicalKeyboardKey shiftLeft = new LogicalKeyboardKey(0x001000700e1, debugName: foundation_.kReleaseMode ? null : "Shift Left"); /// Represents the logical "Alt Left" key on the keyboard. /// /// See the function [RawKeyEvent.logicalKey] for more information. public static readonly LogicalKeyboardKey altLeft = new LogicalKeyboardKey(0x001000700e2, debugName: foundation_.kReleaseMode ? null : "Alt Left"); /// Represents the logical "Meta Left" key on the keyboard. /// /// See the function [RawKeyEvent.logicalKey] for more information. public static readonly LogicalKeyboardKey metaLeft = new LogicalKeyboardKey(0x001000700e3, debugName: foundation_.kReleaseMode ? null : "Meta Left"); /// Represents the logical "Control Right" key on the keyboard. /// /// See the function [RawKeyEvent.logicalKey] for more information. public static readonly LogicalKeyboardKey controlRight = new LogicalKeyboardKey(0x001000700e4, debugName: foundation_.kReleaseMode ? null : "Control Right"); /// Represents the logical "Shift Right" key on the keyboard. /// /// See the function [RawKeyEvent.logicalKey] for more information. public static readonly LogicalKeyboardKey shiftRight = new LogicalKeyboardKey(0x001000700e5, debugName: foundation_.kReleaseMode ? null : "Shift Right"); /// Represents the logical "Alt Right" key on the keyboard. /// /// See the function [RawKeyEvent.logicalKey] for more information. public static readonly LogicalKeyboardKey altRight = new LogicalKeyboardKey(0x001000700e6, debugName: foundation_.kReleaseMode ? null : "Alt Right"); /// Represents the logical "Meta Right" key on the keyboard. /// /// See the function [RawKeyEvent.logicalKey] for more information. public static readonly LogicalKeyboardKey metaRight = new LogicalKeyboardKey(0x001000700e7, debugName: foundation_.kReleaseMode ? null : "Meta Right"); /// Represents the logical "Shift" key on the keyboard. /// /// This key represents the union of the keys {shiftLeft, shiftRight} when /// comparing keys. This key will never be generated directly, its main use is /// in defining key maps. public static readonly LogicalKeyboardKey shift = new LogicalKeyboardKey(0x201000700e1, debugName: foundation_.kReleaseMode ? null : "Shift"); /// Represents the logical "Meta" key on the keyboard. /// /// This key represents the union of the keys {metaLeft, metaRight} when /// comparing keys. This key will never be generated directly, its main use is /// in defining key maps. public static readonly LogicalKeyboardKey meta = new LogicalKeyboardKey(0x201000700e3, debugName: foundation_.kReleaseMode ? null : "Meta"); /// Represents the logical "Alt" key on the keyboard. /// /// This key represents the union of the keys {altLeft, altRight} when /// comparing keys. This key will never be generated directly, its main use is /// in defining key maps. public static readonly LogicalKeyboardKey alt = new LogicalKeyboardKey(0x201000700e2, debugName: foundation_.kReleaseMode ? null : "Alt"); /// Represents the logical "Control" key on the keyboard. /// /// This key represents the union of the keys {controlLeft, controlRight} when /// comparing keys. This key will never be generated directly, its main use is /// in defining key maps. public static readonly LogicalKeyboardKey control = new LogicalKeyboardKey(0x201000700e0, debugName: foundation_.kReleaseMode ? null : "Control"); // A list of all predefined constant LogicalKeyboardKeys so they can be // searched. public static readonly Dictionary _knownLogicalKeys = new Dictionary{ {0x0100000000, none}, {0x201000700e1, shift}, {0x201000700e3, meta}, {0x201000700e2, alt}, {0x201000700e0, control}, }; // A map of keys to the pseudo-key synonym for that key. Used by getSynonyms. public static readonly Dictionary _synonyms = new Dictionary{ {shiftLeft, shift}, {shiftRight, shift}, {metaLeft, meta}, {metaRight, meta}, {altLeft, alt}, {altRight, alt}, {controlLeft, control}, {controlRight, control}, }; } public class PhysicalKeyboardKey : KeyboardKey, IEquatable { protected PhysicalKeyboardKey(int usbHidUsage, string debugName = null) { D.assert(usbHidUsage != null); this.usbHidUsage = usbHidUsage; this.debugName = debugName; } /// 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. public readonly int usbHidUsage; /// The debug string to print for this keyboard key, which will be null in /// release mode. public readonly string debugName; /// Finds a known [PhysicalKeyboardKey] that matches the given USB HID usage /// code. public static PhysicalKeyboardKey findKeyByCode(int usageCode) => _knownPhysicalKeys[usageCode]; public override void debugFillProperties(DiagnosticPropertiesBuilder properties) { base.debugFillProperties(properties); properties.add(new StringProperty("usbHidUsage", usbHidUsage.ToString().PadLeft(8,'0'), showName: true)); properties.add(new StringProperty("debugName", debugName, showName: true, defaultValue: null)); } public bool Equals(PhysicalKeyboardKey other) { if (ReferenceEquals(null, other)) { return false; } if (ReferenceEquals(this, other)) { return true; } return usbHidUsage == other.usbHidUsage; } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) { return false; } if (ReferenceEquals(this, obj)) { return true; } if (obj.GetType() != GetType()) { return false; } return Equals((PhysicalKeyboardKey) obj); } public override int GetHashCode() { unchecked { return (usbHidUsage * 397) ^ (debugName != null ? debugName.GetHashCode() : 0); } } // Key constants for all keyboard keys in the USB HID specification at the // time Flutter was built. /// Represents the location of the "None" key on a generalized keyboard. /// /// See the function [RawKeyEvent.physicalKey] for more information. public static readonly PhysicalKeyboardKey none = new PhysicalKeyboardKey(0x00000000, debugName: foundation_.kReleaseMode ? null : "None"); /// Represents the location of the "Control Left" key on a generalized /// keyboard. /// /// See the function [RawKeyEvent.physicalKey] for more information. public static readonly PhysicalKeyboardKey controlLeft = new PhysicalKeyboardKey(0x000700e0, debugName: foundation_.kReleaseMode ? null : "Control Left"); /// Represents the location of the "Shift Left" key on a generalized keyboard. /// /// See the function [RawKeyEvent.physicalKey] for more information. public static readonly PhysicalKeyboardKey shiftLeft = new PhysicalKeyboardKey(0x000700e1, debugName: foundation_.kReleaseMode ? null : "Shift Left"); /// Represents the location of the "Alt Left" key on a generalized keyboard. /// /// See the function [RawKeyEvent.physicalKey] for more information. public static readonly PhysicalKeyboardKey altLeft = new PhysicalKeyboardKey(0x000700e2, debugName: foundation_.kReleaseMode ? null : "Alt Left"); /// Represents the location of the "Meta Left" key on a generalized keyboard. /// /// See the function [RawKeyEvent.physicalKey] for more information. public static readonly PhysicalKeyboardKey metaLeft = new PhysicalKeyboardKey(0x000700e3, debugName: foundation_.kReleaseMode ? null : "Meta Left"); /// Represents the location of the "Control Right" key on a generalized /// keyboard. /// /// See the function [RawKeyEvent.physicalKey] for more information. public static readonly PhysicalKeyboardKey controlRight = new PhysicalKeyboardKey(0x000700e4, debugName: foundation_.kReleaseMode ? null : "Control Right"); /// Represents the location of the "Shift Right" key on a generalized /// keyboard. /// /// See the function [RawKeyEvent.physicalKey] for more information. public static readonly PhysicalKeyboardKey shiftRight = new PhysicalKeyboardKey(0x000700e5, debugName: foundation_.kReleaseMode ? null : "Shift Right"); /// Represents the location of the "Alt Right" key on a generalized keyboard. /// /// See the function [RawKeyEvent.physicalKey] for more information. public static readonly PhysicalKeyboardKey altRight = new PhysicalKeyboardKey(0x000700e6, debugName: foundation_.kReleaseMode ? null : "Alt Right"); /// Represents the location of the "Meta Right" key on a generalized keyboard. /// /// See the function [RawKeyEvent.physicalKey] for more information. public static readonly PhysicalKeyboardKey metaRight = new PhysicalKeyboardKey(0x000700e7, debugName: foundation_.kReleaseMode ? null : "Meta Right"); public static readonly Dictionary _knownPhysicalKeys = new Dictionary() { {0x00000000, none}, {0x000700e0, controlLeft}, {0x000700e1, shiftLeft}, {0x000700e2, altLeft}, {0x000700e3, metaLeft}, {0x000700e4, controlRight}, {0x000700e5, shiftRight}, {0x000700e6, altRight}, {0x000700e7, metaRight}, }; } }