| // 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'; |
| |
| import 'keyboard_key.dart'; |
| import 'keyboard_maps.dart'; |
| import 'raw_keyboard.dart'; |
| |
| /// Platform-specific key event data for Web. |
| /// |
| /// See also: |
| /// |
| /// * [RawKeyboard], which uses this interface to expose key data. |
| @immutable |
| class RawKeyEventDataWeb extends RawKeyEventData { |
| /// Creates a key event data structure specific for Web. |
| /// |
| /// The [keyCode] and [metaState] arguments must not be null. |
| const RawKeyEventDataWeb({ |
| @required this.code, |
| @required this.key, |
| this.metaState = modifierNone, |
| }) : assert(code != null), |
| assert(metaState != null); |
| |
| /// The `KeyboardEvent.code` corresponding to this event. |
| /// |
| /// See <https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/code> |
| /// for more information. |
| final String code; |
| |
| /// The `KeyboardEvent.key` corresponding to this event. |
| /// |
| /// See <https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key> |
| /// for more information. |
| final String key; |
| |
| /// The modifiers that were present when the key event occurred. |
| /// |
| /// See `lib/src/engine/keyboard.dart` in the web engine for the numerical |
| /// values of the `metaState`. These constants are also replicated as static |
| /// constants in this class. |
| /// |
| /// See also: |
| /// |
| /// * [modifiersPressed], which returns a Map of currently pressed modifiers |
| /// and their keyboard side. |
| /// * [isModifierPressed], to see if a specific modifier is pressed. |
| /// * [isControlPressed], to see if a CTRL key is pressed. |
| /// * [isShiftPressed], to see if a SHIFT key is pressed. |
| /// * [isAltPressed], to see if an ALT key is pressed. |
| /// * [isMetaPressed], to see if a META key is pressed. |
| final int metaState; |
| |
| @override |
| String get keyLabel => key; |
| |
| @override |
| PhysicalKeyboardKey get physicalKey { |
| return kWebToPhysicalKey[code] ?? PhysicalKeyboardKey.none; |
| } |
| |
| @override |
| LogicalKeyboardKey get logicalKey { |
| // Look to see if the keyCode is a printable number pad key, so that a |
| // difference between regular keys (e.g. ".") and the number pad version |
| // (e.g. the "." on the number pad) can be determined. |
| final LogicalKeyboardKey numPadKey = kWebNumPadMap[code]; |
| if (numPadKey != null) { |
| return numPadKey; |
| } |
| |
| // Look to see if the [code] is one we know about and have a mapping for. |
| final LogicalKeyboardKey newKey = kWebToLogicalKey[code]; |
| if (newKey != null) { |
| return newKey; |
| } |
| |
| // This is a non-printable key that we don't know about, so we mint a new |
| // code with the autogenerated bit set. |
| const int webKeyIdPlane = 0x00800000000; |
| return LogicalKeyboardKey( |
| webKeyIdPlane | code.hashCode | LogicalKeyboardKey.autogeneratedMask, |
| debugName: kReleaseMode ? null : 'Unknown Web code "$code"', |
| ); |
| } |
| |
| @override |
| bool isModifierPressed( |
| ModifierKey key, { |
| KeyboardSide side = KeyboardSide.any, |
| }) { |
| switch (key) { |
| case ModifierKey.controlModifier: |
| return metaState & modifierControl != 0; |
| case ModifierKey.shiftModifier: |
| return metaState & modifierShift != 0; |
| case ModifierKey.altModifier: |
| return metaState & modifierAlt != 0; |
| case ModifierKey.metaModifier: |
| return metaState & modifierMeta != 0; |
| case ModifierKey.numLockModifier: |
| return metaState & modifierNumLock != 0; |
| case ModifierKey.capsLockModifier: |
| return metaState & modifierCapsLock != 0; |
| case ModifierKey.scrollLockModifier: |
| return metaState & modifierScrollLock != 0; |
| case ModifierKey.functionModifier: |
| case ModifierKey.symbolModifier: |
| default: |
| // On Web, the browser doesn't report the state of the FN and SYM modifiers. |
| return false; |
| } |
| } |
| |
| @override |
| KeyboardSide getModifierSide(ModifierKey key) { |
| // On Web, we don't distinguish the sides of modifier keys. Both left shift |
| // and right shift, for example, are reported as the "Shift" modifier. |
| // |
| // See <https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/getModifierState> |
| // for more information. |
| return KeyboardSide.all; |
| } |
| |
| // Modifier key masks. |
| |
| /// No modifier keys are pressed in the [metaState] field. |
| /// |
| /// Use this value if you need to decode the [metaState] field yourself, but |
| /// it's much easier to use [isModifierPressed] if you just want to know if |
| /// a modifier is pressed. |
| static const int modifierNone = 0; |
| |
| /// This mask is used to check the [metaState] field to test whether one of |
| /// the SHIFT modifier keys is pressed. |
| /// |
| /// Use this value if you need to decode the [metaState] field yourself, but |
| /// it's much easier to use [isModifierPressed] if you just want to know if |
| /// a modifier is pressed. |
| static const int modifierShift = 0x01; |
| |
| /// This mask is used to check the [metaState] field to test whether one of |
| /// the ALT modifier keys is pressed. |
| /// |
| /// Use this value if you need to decode the [metaState] field yourself, but |
| /// it's much easier to use [isModifierPressed] if you just want to know if |
| /// a modifier is pressed. |
| static const int modifierAlt = 0x02; |
| |
| /// This mask is used to check the [metaState] field to test whether one of |
| /// the CTRL modifier keys is pressed. |
| /// |
| /// Use this value if you need to decode the [metaState] field yourself, but |
| /// it's much easier to use [isModifierPressed] if you just want to know if |
| /// a modifier is pressed. |
| static const int modifierControl = 0x04; |
| |
| /// This mask is used to check the [metaState] field to test whether one of |
| /// the META modifier keys is pressed. |
| /// |
| /// Use this value if you need to decode the [metaState] field yourself, but |
| /// it's much easier to use [isModifierPressed] if you just want to know if |
| /// a modifier is pressed. |
| static const int modifierMeta = 0x08; |
| |
| /// This mask is used to check the [metaState] field to test whether the NUM |
| /// LOCK modifier key is on. |
| /// |
| /// Use this value if you need to decode the [metaState] field yourself, but |
| /// it's much easier to use [isModifierPressed] if you just want to know if |
| /// a modifier is pressed. |
| static const int modifierNumLock = 0x10; |
| |
| /// This mask is used to check the [metaState] field to test whether the CAPS |
| /// LOCK modifier key is on. |
| /// |
| /// Use this value if you need to decode the [metaState] field yourself, but |
| /// it's much easier to use [isModifierPressed] if you just want to know if |
| /// a modifier is pressed. |
| static const int modifierCapsLock = 0x20; |
| |
| /// This mask is used to check the [metaState] field to test whether the |
| /// SCROLL LOCK modifier key is on. |
| /// |
| /// Use this value if you need to decode the [metaState] field yourself, but |
| /// it's much easier to use [isModifierPressed] if you just want to know if |
| /// a modifier is pressed. |
| static const int modifierScrollLock = 0x40; |
| |
| @override |
| String toString() { |
| return '${objectRuntimeType(this, 'RawKeyEventDataWeb')}(keyLabel: $keyLabel, code: $code, ' |
| 'metaState: $metaState, modifiers down: $modifiersPressed)'; |
| } |
| } |