瀏覽代碼

Translate text input to keyboard event

xuty 3 年之前
父節點
當前提交
4cc85ca7fe
共有 3 個文件被更改,包括 339 次插入243 次删除
  1. 49 0
      lib/src/core/input/handler.dart
  2. 12 2
      lib/src/terminal_view.dart
  3. 278 241
      lib/src/ui/input_map.dart

+ 49 - 0
lib/src/core/input/handler.dart

@@ -3,6 +3,13 @@ import 'package:xterm/src/core/input/keytab/keytab.dart';
 import 'package:xterm/src/utils/platform.dart';
 import 'package:xterm/src/core/state.dart';
 
+/// The key event received from the keyboard, along with the state of the
+/// modifier keys and state of the terminal. Typically consumed by the
+/// [TerminalInputHandler] to produce a escape sequence that can be recognized
+/// by the terminal.
+///
+/// See also:
+/// - [TerminalInputHandler]
 class TerminalInputEvent {
   final TerminalKey key;
 
@@ -27,12 +34,39 @@ class TerminalInputEvent {
     required this.altBuffer,
     required this.platform,
   });
+
+  TerminalInputEvent copyWith({
+    TerminalKey? key,
+    bool? shift,
+    bool? ctrl,
+    bool? alt,
+    TerminalState? state,
+    bool? altBuffer,
+    TerminalTargetPlatform? platform,
+  }) {
+    return TerminalInputEvent(
+      key: key ?? this.key,
+      shift: shift ?? this.shift,
+      ctrl: ctrl ?? this.ctrl,
+      alt: alt ?? this.alt,
+      state: state ?? this.state,
+      altBuffer: altBuffer ?? this.altBuffer,
+      platform: platform ?? this.platform,
+    );
+  }
 }
 
+/// TerminalInputHandler contains the logic for translating a [TerminalInputEvent]
+/// into escape sequences that can be recognized by the terminal.
 abstract class TerminalInputHandler {
+  /// Translates a [TerminalInputEvent] into an escape sequence. If the event
+  /// cannot be translated, null is returned.
   String? call(TerminalInputEvent event);
 }
 
+/// A [TerminalInputHandler] that chains multiple handlers together. If any
+/// handler returns a non-null value, it is returned. Otherwise, null is
+/// returned.
 class CascadeInputHandler implements TerminalInputHandler {
   final List<TerminalInputHandler> _handlers;
 
@@ -50,6 +84,15 @@ class CascadeInputHandler implements TerminalInputHandler {
   }
 }
 
+/// The default input handler for the terminal. That is composed of a
+/// [KeytabInputHandler], a [CtrlInputHandler], and a [AltInputHandler].
+///
+/// It's possible to override the default input handler behavior by chaining
+/// another input handler before or after the default input handler using
+/// [CascadeInputHandler].
+///
+/// See also:
+///  * [CascadeInputHandler]
 const defaultInputHandler = CascadeInputHandler([
   KeytabInputHandler(),
   CtrlInputHandler(),
@@ -58,6 +101,8 @@ const defaultInputHandler = CascadeInputHandler([
 
 final _keytab = Keytab.defaultKeytab();
 
+/// A [TerminalInputHandler] that translates key events according to a keytab
+/// file.
 class KeytabInputHandler implements TerminalInputHandler {
   const KeytabInputHandler();
 
@@ -83,6 +128,8 @@ class KeytabInputHandler implements TerminalInputHandler {
   }
 }
 
+/// A [TerminalInputHandler] that translates ctrl + key events into escape
+/// sequences. For example, ctrl + a becomes ^A.
 class CtrlInputHandler implements TerminalInputHandler {
   const CtrlInputHandler();
 
@@ -104,6 +151,8 @@ class CtrlInputHandler implements TerminalInputHandler {
   }
 }
 
+/// A [TerminalInputHandler] that translates alt + key events into escape
+/// sequences. For example, alt + a becomes ^[a.
 class AltInputHandler implements TerminalInputHandler {
   const AltInputHandler();
 

+ 12 - 2
lib/src/terminal_view.dart

@@ -345,8 +345,18 @@ class TerminalViewState extends State<TerminalView> {
   }
 
   void _onInsert(String text) {
+    final key = charToTerminalKey(text.trim());
+
+    // On mobile platforms there is no guarantee that virtual keyboard will
+    // generate hardware key events. So we need first try to send the key
+    // as a hardware key event. If it fails, then we send it as a text input.
+    final consumed = key == null ? false : widget.terminal.keyInput(key);
+
+    if (!consumed) {
+      widget.terminal.textInput(text);
+    }
+
     _scrollToBottom();
-    widget.terminal.textInput(text);
   }
 
   void _onComposing(String? text) {
@@ -368,7 +378,7 @@ class TerminalViewState extends State<TerminalView> {
       return KeyEventResult.ignored;
     }
 
-    final key = inputMap(event.logicalKey);
+    final key = keyToTerminalKey(event.logicalKey);
 
     if (key == null) {
       return KeyEventResult.ignored;

+ 278 - 241
lib/src/ui/input_map.dart

@@ -1,247 +1,284 @@
 import 'package:flutter/services.dart';
 import 'package:xterm/src/core/input/keys.dart';
 
-final _idKeyMap = {
-  LogicalKeyboardKey.hyper.keyId: TerminalKey.hyper,
-  LogicalKeyboardKey.superKey.keyId: TerminalKey.superKey,
-  LogicalKeyboardKey.fnLock.keyId: TerminalKey.fnLock,
-  LogicalKeyboardKey.suspend.keyId: TerminalKey.suspend,
-  LogicalKeyboardKey.resume.keyId: TerminalKey.resume,
-  LogicalKeyboardKey.sleep.keyId: TerminalKey.sleep,
-  LogicalKeyboardKey.wakeUp.keyId: TerminalKey.wakeUp,
-  LogicalKeyboardKey.keyA.keyId: TerminalKey.keyA,
-  LogicalKeyboardKey.keyB.keyId: TerminalKey.keyB,
-  LogicalKeyboardKey.keyC.keyId: TerminalKey.keyC,
-  LogicalKeyboardKey.keyD.keyId: TerminalKey.keyD,
-  LogicalKeyboardKey.keyE.keyId: TerminalKey.keyE,
-  LogicalKeyboardKey.keyF.keyId: TerminalKey.keyF,
-  LogicalKeyboardKey.keyG.keyId: TerminalKey.keyG,
-  LogicalKeyboardKey.keyH.keyId: TerminalKey.keyH,
-  LogicalKeyboardKey.keyI.keyId: TerminalKey.keyI,
-  LogicalKeyboardKey.keyJ.keyId: TerminalKey.keyJ,
-  LogicalKeyboardKey.keyK.keyId: TerminalKey.keyK,
-  LogicalKeyboardKey.keyL.keyId: TerminalKey.keyL,
-  LogicalKeyboardKey.keyM.keyId: TerminalKey.keyM,
-  LogicalKeyboardKey.keyN.keyId: TerminalKey.keyN,
-  LogicalKeyboardKey.keyO.keyId: TerminalKey.keyO,
-  LogicalKeyboardKey.keyP.keyId: TerminalKey.keyP,
-  LogicalKeyboardKey.keyQ.keyId: TerminalKey.keyQ,
-  LogicalKeyboardKey.keyR.keyId: TerminalKey.keyR,
-  LogicalKeyboardKey.keyS.keyId: TerminalKey.keyS,
-  LogicalKeyboardKey.keyT.keyId: TerminalKey.keyT,
-  LogicalKeyboardKey.keyU.keyId: TerminalKey.keyU,
-  LogicalKeyboardKey.keyV.keyId: TerminalKey.keyV,
-  LogicalKeyboardKey.keyW.keyId: TerminalKey.keyW,
-  LogicalKeyboardKey.keyX.keyId: TerminalKey.keyX,
-  LogicalKeyboardKey.keyY.keyId: TerminalKey.keyY,
-  LogicalKeyboardKey.keyZ.keyId: TerminalKey.keyZ,
-  LogicalKeyboardKey.digit1.keyId: TerminalKey.digit1,
-  LogicalKeyboardKey.digit2.keyId: TerminalKey.digit2,
-  LogicalKeyboardKey.digit3.keyId: TerminalKey.digit3,
-  LogicalKeyboardKey.digit4.keyId: TerminalKey.digit4,
-  LogicalKeyboardKey.digit5.keyId: TerminalKey.digit5,
-  LogicalKeyboardKey.digit6.keyId: TerminalKey.digit6,
-  LogicalKeyboardKey.digit7.keyId: TerminalKey.digit7,
-  LogicalKeyboardKey.digit8.keyId: TerminalKey.digit8,
-  LogicalKeyboardKey.digit9.keyId: TerminalKey.digit9,
-  LogicalKeyboardKey.digit0.keyId: TerminalKey.digit0,
-  LogicalKeyboardKey.enter.keyId: TerminalKey.enter,
-  LogicalKeyboardKey.escape.keyId: TerminalKey.escape,
-  LogicalKeyboardKey.backspace.keyId: TerminalKey.backspace,
-  LogicalKeyboardKey.tab.keyId: TerminalKey.tab,
-  LogicalKeyboardKey.space.keyId: TerminalKey.space,
-  LogicalKeyboardKey.minus.keyId: TerminalKey.minus,
-  LogicalKeyboardKey.equal.keyId: TerminalKey.equal,
-  LogicalKeyboardKey.bracketLeft.keyId: TerminalKey.bracketLeft,
-  LogicalKeyboardKey.bracketRight.keyId: TerminalKey.bracketRight,
-  LogicalKeyboardKey.backslash.keyId: TerminalKey.backslash,
-  LogicalKeyboardKey.semicolon.keyId: TerminalKey.semicolon,
-  LogicalKeyboardKey.quote.keyId: TerminalKey.quote,
-  LogicalKeyboardKey.backquote.keyId: TerminalKey.backquote,
-  LogicalKeyboardKey.comma.keyId: TerminalKey.comma,
-  LogicalKeyboardKey.period.keyId: TerminalKey.period,
-  LogicalKeyboardKey.slash.keyId: TerminalKey.slash,
-  LogicalKeyboardKey.capsLock.keyId: TerminalKey.capsLock,
-  LogicalKeyboardKey.f1.keyId: TerminalKey.f1,
-  LogicalKeyboardKey.f2.keyId: TerminalKey.f2,
-  LogicalKeyboardKey.f3.keyId: TerminalKey.f3,
-  LogicalKeyboardKey.f4.keyId: TerminalKey.f4,
-  LogicalKeyboardKey.f5.keyId: TerminalKey.f5,
-  LogicalKeyboardKey.f6.keyId: TerminalKey.f6,
-  LogicalKeyboardKey.f7.keyId: TerminalKey.f7,
-  LogicalKeyboardKey.f8.keyId: TerminalKey.f8,
-  LogicalKeyboardKey.f9.keyId: TerminalKey.f9,
-  LogicalKeyboardKey.f10.keyId: TerminalKey.f10,
-  LogicalKeyboardKey.f11.keyId: TerminalKey.f11,
-  LogicalKeyboardKey.f12.keyId: TerminalKey.f12,
-  LogicalKeyboardKey.printScreen.keyId: TerminalKey.printScreen,
-  LogicalKeyboardKey.scrollLock.keyId: TerminalKey.scrollLock,
-  LogicalKeyboardKey.pause.keyId: TerminalKey.pause,
-  LogicalKeyboardKey.insert.keyId: TerminalKey.insert,
-  LogicalKeyboardKey.home.keyId: TerminalKey.home,
-  LogicalKeyboardKey.pageUp.keyId: TerminalKey.pageUp,
-  LogicalKeyboardKey.delete.keyId: TerminalKey.delete,
-  LogicalKeyboardKey.end.keyId: TerminalKey.end,
-  LogicalKeyboardKey.pageDown.keyId: TerminalKey.pageDown,
-  LogicalKeyboardKey.arrowRight.keyId: TerminalKey.arrowRight,
-  LogicalKeyboardKey.arrowLeft.keyId: TerminalKey.arrowLeft,
-  LogicalKeyboardKey.arrowDown.keyId: TerminalKey.arrowDown,
-  LogicalKeyboardKey.arrowUp.keyId: TerminalKey.arrowUp,
-  LogicalKeyboardKey.numLock.keyId: TerminalKey.numLock,
-  LogicalKeyboardKey.numpadDivide.keyId: TerminalKey.numpadDivide,
-  LogicalKeyboardKey.numpadMultiply.keyId: TerminalKey.numpadMultiply,
-  LogicalKeyboardKey.numpadSubtract.keyId: TerminalKey.numpadSubtract,
-  LogicalKeyboardKey.numpadAdd.keyId: TerminalKey.numpadAdd,
-  LogicalKeyboardKey.numpadEnter.keyId: TerminalKey.numpadEnter,
-  LogicalKeyboardKey.numpad1.keyId: TerminalKey.numpad1,
-  LogicalKeyboardKey.numpad2.keyId: TerminalKey.numpad2,
-  LogicalKeyboardKey.numpad3.keyId: TerminalKey.numpad3,
-  LogicalKeyboardKey.numpad4.keyId: TerminalKey.numpad4,
-  LogicalKeyboardKey.numpad5.keyId: TerminalKey.numpad5,
-  LogicalKeyboardKey.numpad6.keyId: TerminalKey.numpad6,
-  LogicalKeyboardKey.numpad7.keyId: TerminalKey.numpad7,
-  LogicalKeyboardKey.numpad8.keyId: TerminalKey.numpad8,
-  LogicalKeyboardKey.numpad9.keyId: TerminalKey.numpad9,
-  LogicalKeyboardKey.numpad0.keyId: TerminalKey.numpad0,
-  LogicalKeyboardKey.numpadDecimal.keyId: TerminalKey.numpadDecimal,
-  LogicalKeyboardKey.intlBackslash.keyId: TerminalKey.intlBackslash,
-  LogicalKeyboardKey.contextMenu.keyId: TerminalKey.contextMenu,
-  LogicalKeyboardKey.power.keyId: TerminalKey.power,
-  LogicalKeyboardKey.numpadEqual.keyId: TerminalKey.numpadEqual,
-  LogicalKeyboardKey.f13.keyId: TerminalKey.f13,
-  LogicalKeyboardKey.f14.keyId: TerminalKey.f14,
-  LogicalKeyboardKey.f15.keyId: TerminalKey.f15,
-  LogicalKeyboardKey.f16.keyId: TerminalKey.f16,
-  LogicalKeyboardKey.f17.keyId: TerminalKey.f17,
-  LogicalKeyboardKey.f18.keyId: TerminalKey.f18,
-  LogicalKeyboardKey.f19.keyId: TerminalKey.f19,
-  LogicalKeyboardKey.f20.keyId: TerminalKey.f20,
-  LogicalKeyboardKey.f21.keyId: TerminalKey.f21,
-  LogicalKeyboardKey.f22.keyId: TerminalKey.f22,
-  LogicalKeyboardKey.f23.keyId: TerminalKey.f23,
-  LogicalKeyboardKey.f24.keyId: TerminalKey.f24,
-  LogicalKeyboardKey.open.keyId: TerminalKey.open,
-  LogicalKeyboardKey.help.keyId: TerminalKey.help,
-  LogicalKeyboardKey.select.keyId: TerminalKey.select,
-  LogicalKeyboardKey.again.keyId: TerminalKey.again,
-  LogicalKeyboardKey.undo.keyId: TerminalKey.undo,
-  LogicalKeyboardKey.cut.keyId: TerminalKey.cut,
-  LogicalKeyboardKey.copy.keyId: TerminalKey.copy,
-  LogicalKeyboardKey.paste.keyId: TerminalKey.paste,
-  LogicalKeyboardKey.find.keyId: TerminalKey.find,
-  LogicalKeyboardKey.audioVolumeMute.keyId: TerminalKey.audioVolumeMute,
-  LogicalKeyboardKey.audioVolumeUp.keyId: TerminalKey.audioVolumeUp,
-  LogicalKeyboardKey.audioVolumeDown.keyId: TerminalKey.audioVolumeDown,
-  LogicalKeyboardKey.numpadComma.keyId: TerminalKey.numpadComma,
-  LogicalKeyboardKey.intlRo.keyId: TerminalKey.intlRo,
-  LogicalKeyboardKey.kanaMode.keyId: TerminalKey.kanaMode,
-  LogicalKeyboardKey.intlYen.keyId: TerminalKey.intlYen,
-  LogicalKeyboardKey.convert.keyId: TerminalKey.convert,
-  LogicalKeyboardKey.nonConvert.keyId: TerminalKey.nonConvert,
-  LogicalKeyboardKey.lang1.keyId: TerminalKey.lang1,
-  LogicalKeyboardKey.lang2.keyId: TerminalKey.lang2,
-  LogicalKeyboardKey.lang3.keyId: TerminalKey.lang3,
-  LogicalKeyboardKey.lang4.keyId: TerminalKey.lang4,
-  LogicalKeyboardKey.lang5.keyId: TerminalKey.lang5,
-  LogicalKeyboardKey.abort.keyId: TerminalKey.abort,
-  LogicalKeyboardKey.props.keyId: TerminalKey.props,
-  LogicalKeyboardKey.numpadParenLeft.keyId: TerminalKey.numpadParenLeft,
-  LogicalKeyboardKey.numpadParenRight.keyId: TerminalKey.numpadParenRight,
-  LogicalKeyboardKey.controlLeft.keyId: TerminalKey.controlLeft,
-  LogicalKeyboardKey.shiftLeft.keyId: TerminalKey.shiftLeft,
-  LogicalKeyboardKey.altLeft.keyId: TerminalKey.altLeft,
-  LogicalKeyboardKey.metaLeft.keyId: TerminalKey.metaLeft,
-  LogicalKeyboardKey.controlRight.keyId: TerminalKey.controlRight,
-  LogicalKeyboardKey.shiftRight.keyId: TerminalKey.shiftRight,
-  LogicalKeyboardKey.altRight.keyId: TerminalKey.altRight,
-  LogicalKeyboardKey.metaRight.keyId: TerminalKey.metaRight,
-  LogicalKeyboardKey.info.keyId: TerminalKey.info,
-  LogicalKeyboardKey.closedCaptionToggle.keyId: TerminalKey.closedCaptionToggle,
-  LogicalKeyboardKey.brightnessUp.keyId: TerminalKey.brightnessUp,
-  LogicalKeyboardKey.brightnessDown.keyId: TerminalKey.brightnessDown,
-  LogicalKeyboardKey.mediaLast.keyId: TerminalKey.mediaLast,
-  LogicalKeyboardKey.launchPhone.keyId: TerminalKey.launchPhone,
-  LogicalKeyboardKey.exit.keyId: TerminalKey.exit,
-  LogicalKeyboardKey.channelUp.keyId: TerminalKey.channelUp,
-  LogicalKeyboardKey.channelDown.keyId: TerminalKey.channelDown,
-  LogicalKeyboardKey.mediaPlay.keyId: TerminalKey.mediaPlay,
-  LogicalKeyboardKey.mediaPause.keyId: TerminalKey.mediaPause,
-  LogicalKeyboardKey.mediaRecord.keyId: TerminalKey.mediaRecord,
-  LogicalKeyboardKey.mediaFastForward.keyId: TerminalKey.mediaFastForward,
-  LogicalKeyboardKey.mediaRewind.keyId: TerminalKey.mediaRewind,
-  LogicalKeyboardKey.mediaTrackNext.keyId: TerminalKey.mediaTrackNext,
-  LogicalKeyboardKey.mediaTrackPrevious.keyId: TerminalKey.mediaTrackPrevious,
-  LogicalKeyboardKey.mediaStop.keyId: TerminalKey.mediaStop,
-  LogicalKeyboardKey.eject.keyId: TerminalKey.eject,
-  LogicalKeyboardKey.mediaPlayPause.keyId: TerminalKey.mediaPlayPause,
-  LogicalKeyboardKey.speechInputToggle.keyId: TerminalKey.speechInputToggle,
-  LogicalKeyboardKey.launchWordProcessor.keyId: TerminalKey.launchWordProcessor,
-  LogicalKeyboardKey.launchSpreadsheet.keyId: TerminalKey.launchSpreadsheet,
-  LogicalKeyboardKey.launchMail.keyId: TerminalKey.launchMail,
-  LogicalKeyboardKey.launchContacts.keyId: TerminalKey.launchContacts,
-  LogicalKeyboardKey.launchCalendar.keyId: TerminalKey.launchCalendar,
-  LogicalKeyboardKey.logOff.keyId: TerminalKey.logOff,
-  LogicalKeyboardKey.launchControlPanel.keyId: TerminalKey.launchControlPanel,
-  LogicalKeyboardKey.spellCheck.keyId: TerminalKey.spellCheck,
-  LogicalKeyboardKey.launchScreenSaver.keyId: TerminalKey.launchScreenSaver,
-  LogicalKeyboardKey.launchAssistant.keyId: TerminalKey.launchAssistant,
-  LogicalKeyboardKey.newKey.keyId: TerminalKey.newKey,
-  LogicalKeyboardKey.close.keyId: TerminalKey.close,
-  LogicalKeyboardKey.save.keyId: TerminalKey.save,
-  LogicalKeyboardKey.print.keyId: TerminalKey.print,
-  LogicalKeyboardKey.browserSearch.keyId: TerminalKey.browserSearch,
-  LogicalKeyboardKey.browserHome.keyId: TerminalKey.browserHome,
-  LogicalKeyboardKey.browserBack.keyId: TerminalKey.browserBack,
-  LogicalKeyboardKey.browserForward.keyId: TerminalKey.browserForward,
-  LogicalKeyboardKey.browserStop.keyId: TerminalKey.browserStop,
-  LogicalKeyboardKey.browserRefresh.keyId: TerminalKey.browserRefresh,
-  LogicalKeyboardKey.browserFavorites.keyId: TerminalKey.browserFavorites,
-  LogicalKeyboardKey.zoomIn.keyId: TerminalKey.zoomIn,
-  LogicalKeyboardKey.zoomOut.keyId: TerminalKey.zoomOut,
-  LogicalKeyboardKey.zoomToggle.keyId: TerminalKey.zoomToggle,
-  LogicalKeyboardKey.redo.keyId: TerminalKey.redo,
-  LogicalKeyboardKey.mailReply.keyId: TerminalKey.mailReply,
-  LogicalKeyboardKey.mailForward.keyId: TerminalKey.mailForward,
-  LogicalKeyboardKey.mailSend.keyId: TerminalKey.mailSend,
-  LogicalKeyboardKey.gameButton1.keyId: TerminalKey.gameButton1,
-  LogicalKeyboardKey.gameButton2.keyId: TerminalKey.gameButton2,
-  LogicalKeyboardKey.gameButton3.keyId: TerminalKey.gameButton3,
-  LogicalKeyboardKey.gameButton4.keyId: TerminalKey.gameButton4,
-  LogicalKeyboardKey.gameButton5.keyId: TerminalKey.gameButton5,
-  LogicalKeyboardKey.gameButton6.keyId: TerminalKey.gameButton6,
-  LogicalKeyboardKey.gameButton7.keyId: TerminalKey.gameButton7,
-  LogicalKeyboardKey.gameButton8.keyId: TerminalKey.gameButton8,
-  LogicalKeyboardKey.gameButton9.keyId: TerminalKey.gameButton9,
-  LogicalKeyboardKey.gameButton10.keyId: TerminalKey.gameButton10,
-  LogicalKeyboardKey.gameButton11.keyId: TerminalKey.gameButton11,
-  LogicalKeyboardKey.gameButton12.keyId: TerminalKey.gameButton12,
-  LogicalKeyboardKey.gameButton13.keyId: TerminalKey.gameButton13,
-  LogicalKeyboardKey.gameButton14.keyId: TerminalKey.gameButton14,
-  LogicalKeyboardKey.gameButton15.keyId: TerminalKey.gameButton15,
-  LogicalKeyboardKey.gameButton16.keyId: TerminalKey.gameButton16,
-  LogicalKeyboardKey.gameButtonA.keyId: TerminalKey.gameButtonA,
-  LogicalKeyboardKey.gameButtonB.keyId: TerminalKey.gameButtonB,
-  LogicalKeyboardKey.gameButtonC.keyId: TerminalKey.gameButtonC,
-  LogicalKeyboardKey.gameButtonLeft1.keyId: TerminalKey.gameButtonLeft1,
-  LogicalKeyboardKey.gameButtonLeft2.keyId: TerminalKey.gameButtonLeft2,
-  LogicalKeyboardKey.gameButtonMode.keyId: TerminalKey.gameButtonMode,
-  LogicalKeyboardKey.gameButtonRight1.keyId: TerminalKey.gameButtonRight1,
-  LogicalKeyboardKey.gameButtonRight2.keyId: TerminalKey.gameButtonRight2,
-  LogicalKeyboardKey.gameButtonSelect.keyId: TerminalKey.gameButtonSelect,
-  LogicalKeyboardKey.gameButtonStart.keyId: TerminalKey.gameButtonStart,
-  LogicalKeyboardKey.gameButtonThumbLeft.keyId: TerminalKey.gameButtonThumbLeft,
-  LogicalKeyboardKey.gameButtonThumbRight.keyId:
-      TerminalKey.gameButtonThumbRight,
-  LogicalKeyboardKey.gameButtonX.keyId: TerminalKey.gameButtonX,
-  LogicalKeyboardKey.gameButtonY.keyId: TerminalKey.gameButtonY,
-  LogicalKeyboardKey.gameButtonZ.keyId: TerminalKey.gameButtonZ,
-  LogicalKeyboardKey.fn.keyId: TerminalKey.fn,
-  LogicalKeyboardKey.shift.keyId: TerminalKey.shift,
-  LogicalKeyboardKey.meta.keyId: TerminalKey.meta,
-  LogicalKeyboardKey.alt.keyId: TerminalKey.alt,
-  LogicalKeyboardKey.control.keyId: TerminalKey.control,
+final _keyToTerminalKey = {
+  LogicalKeyboardKey.hyper: TerminalKey.hyper,
+  LogicalKeyboardKey.superKey: TerminalKey.superKey,
+  LogicalKeyboardKey.fnLock: TerminalKey.fnLock,
+  LogicalKeyboardKey.suspend: TerminalKey.suspend,
+  LogicalKeyboardKey.resume: TerminalKey.resume,
+  LogicalKeyboardKey.sleep: TerminalKey.sleep,
+  LogicalKeyboardKey.wakeUp: TerminalKey.wakeUp,
+  LogicalKeyboardKey.keyA: TerminalKey.keyA,
+  LogicalKeyboardKey.keyB: TerminalKey.keyB,
+  LogicalKeyboardKey.keyC: TerminalKey.keyC,
+  LogicalKeyboardKey.keyD: TerminalKey.keyD,
+  LogicalKeyboardKey.keyE: TerminalKey.keyE,
+  LogicalKeyboardKey.keyF: TerminalKey.keyF,
+  LogicalKeyboardKey.keyG: TerminalKey.keyG,
+  LogicalKeyboardKey.keyH: TerminalKey.keyH,
+  LogicalKeyboardKey.keyI: TerminalKey.keyI,
+  LogicalKeyboardKey.keyJ: TerminalKey.keyJ,
+  LogicalKeyboardKey.keyK: TerminalKey.keyK,
+  LogicalKeyboardKey.keyL: TerminalKey.keyL,
+  LogicalKeyboardKey.keyM: TerminalKey.keyM,
+  LogicalKeyboardKey.keyN: TerminalKey.keyN,
+  LogicalKeyboardKey.keyO: TerminalKey.keyO,
+  LogicalKeyboardKey.keyP: TerminalKey.keyP,
+  LogicalKeyboardKey.keyQ: TerminalKey.keyQ,
+  LogicalKeyboardKey.keyR: TerminalKey.keyR,
+  LogicalKeyboardKey.keyS: TerminalKey.keyS,
+  LogicalKeyboardKey.keyT: TerminalKey.keyT,
+  LogicalKeyboardKey.keyU: TerminalKey.keyU,
+  LogicalKeyboardKey.keyV: TerminalKey.keyV,
+  LogicalKeyboardKey.keyW: TerminalKey.keyW,
+  LogicalKeyboardKey.keyX: TerminalKey.keyX,
+  LogicalKeyboardKey.keyY: TerminalKey.keyY,
+  LogicalKeyboardKey.keyZ: TerminalKey.keyZ,
+  LogicalKeyboardKey.digit1: TerminalKey.digit1,
+  LogicalKeyboardKey.digit2: TerminalKey.digit2,
+  LogicalKeyboardKey.digit3: TerminalKey.digit3,
+  LogicalKeyboardKey.digit4: TerminalKey.digit4,
+  LogicalKeyboardKey.digit5: TerminalKey.digit5,
+  LogicalKeyboardKey.digit6: TerminalKey.digit6,
+  LogicalKeyboardKey.digit7: TerminalKey.digit7,
+  LogicalKeyboardKey.digit8: TerminalKey.digit8,
+  LogicalKeyboardKey.digit9: TerminalKey.digit9,
+  LogicalKeyboardKey.digit0: TerminalKey.digit0,
+  LogicalKeyboardKey.enter: TerminalKey.enter,
+  LogicalKeyboardKey.escape: TerminalKey.escape,
+  LogicalKeyboardKey.backspace: TerminalKey.backspace,
+  LogicalKeyboardKey.tab: TerminalKey.tab,
+  LogicalKeyboardKey.space: TerminalKey.space,
+  LogicalKeyboardKey.minus: TerminalKey.minus,
+  LogicalKeyboardKey.equal: TerminalKey.equal,
+  LogicalKeyboardKey.bracketLeft: TerminalKey.bracketLeft,
+  LogicalKeyboardKey.bracketRight: TerminalKey.bracketRight,
+  LogicalKeyboardKey.backslash: TerminalKey.backslash,
+  LogicalKeyboardKey.semicolon: TerminalKey.semicolon,
+  LogicalKeyboardKey.quote: TerminalKey.quote,
+  LogicalKeyboardKey.backquote: TerminalKey.backquote,
+  LogicalKeyboardKey.comma: TerminalKey.comma,
+  LogicalKeyboardKey.period: TerminalKey.period,
+  LogicalKeyboardKey.slash: TerminalKey.slash,
+  LogicalKeyboardKey.capsLock: TerminalKey.capsLock,
+  LogicalKeyboardKey.f1: TerminalKey.f1,
+  LogicalKeyboardKey.f2: TerminalKey.f2,
+  LogicalKeyboardKey.f3: TerminalKey.f3,
+  LogicalKeyboardKey.f4: TerminalKey.f4,
+  LogicalKeyboardKey.f5: TerminalKey.f5,
+  LogicalKeyboardKey.f6: TerminalKey.f6,
+  LogicalKeyboardKey.f7: TerminalKey.f7,
+  LogicalKeyboardKey.f8: TerminalKey.f8,
+  LogicalKeyboardKey.f9: TerminalKey.f9,
+  LogicalKeyboardKey.f10: TerminalKey.f10,
+  LogicalKeyboardKey.f11: TerminalKey.f11,
+  LogicalKeyboardKey.f12: TerminalKey.f12,
+  LogicalKeyboardKey.printScreen: TerminalKey.printScreen,
+  LogicalKeyboardKey.scrollLock: TerminalKey.scrollLock,
+  LogicalKeyboardKey.pause: TerminalKey.pause,
+  LogicalKeyboardKey.insert: TerminalKey.insert,
+  LogicalKeyboardKey.home: TerminalKey.home,
+  LogicalKeyboardKey.pageUp: TerminalKey.pageUp,
+  LogicalKeyboardKey.delete: TerminalKey.delete,
+  LogicalKeyboardKey.end: TerminalKey.end,
+  LogicalKeyboardKey.pageDown: TerminalKey.pageDown,
+  LogicalKeyboardKey.arrowRight: TerminalKey.arrowRight,
+  LogicalKeyboardKey.arrowLeft: TerminalKey.arrowLeft,
+  LogicalKeyboardKey.arrowDown: TerminalKey.arrowDown,
+  LogicalKeyboardKey.arrowUp: TerminalKey.arrowUp,
+  LogicalKeyboardKey.numLock: TerminalKey.numLock,
+  LogicalKeyboardKey.numpadDivide: TerminalKey.numpadDivide,
+  LogicalKeyboardKey.numpadMultiply: TerminalKey.numpadMultiply,
+  LogicalKeyboardKey.numpadSubtract: TerminalKey.numpadSubtract,
+  LogicalKeyboardKey.numpadAdd: TerminalKey.numpadAdd,
+  LogicalKeyboardKey.numpadEnter: TerminalKey.numpadEnter,
+  LogicalKeyboardKey.numpad1: TerminalKey.numpad1,
+  LogicalKeyboardKey.numpad2: TerminalKey.numpad2,
+  LogicalKeyboardKey.numpad3: TerminalKey.numpad3,
+  LogicalKeyboardKey.numpad4: TerminalKey.numpad4,
+  LogicalKeyboardKey.numpad5: TerminalKey.numpad5,
+  LogicalKeyboardKey.numpad6: TerminalKey.numpad6,
+  LogicalKeyboardKey.numpad7: TerminalKey.numpad7,
+  LogicalKeyboardKey.numpad8: TerminalKey.numpad8,
+  LogicalKeyboardKey.numpad9: TerminalKey.numpad9,
+  LogicalKeyboardKey.numpad0: TerminalKey.numpad0,
+  LogicalKeyboardKey.numpadDecimal: TerminalKey.numpadDecimal,
+  LogicalKeyboardKey.intlBackslash: TerminalKey.intlBackslash,
+  LogicalKeyboardKey.contextMenu: TerminalKey.contextMenu,
+  LogicalKeyboardKey.power: TerminalKey.power,
+  LogicalKeyboardKey.numpadEqual: TerminalKey.numpadEqual,
+  LogicalKeyboardKey.f13: TerminalKey.f13,
+  LogicalKeyboardKey.f14: TerminalKey.f14,
+  LogicalKeyboardKey.f15: TerminalKey.f15,
+  LogicalKeyboardKey.f16: TerminalKey.f16,
+  LogicalKeyboardKey.f17: TerminalKey.f17,
+  LogicalKeyboardKey.f18: TerminalKey.f18,
+  LogicalKeyboardKey.f19: TerminalKey.f19,
+  LogicalKeyboardKey.f20: TerminalKey.f20,
+  LogicalKeyboardKey.f21: TerminalKey.f21,
+  LogicalKeyboardKey.f22: TerminalKey.f22,
+  LogicalKeyboardKey.f23: TerminalKey.f23,
+  LogicalKeyboardKey.f24: TerminalKey.f24,
+  LogicalKeyboardKey.open: TerminalKey.open,
+  LogicalKeyboardKey.help: TerminalKey.help,
+  LogicalKeyboardKey.select: TerminalKey.select,
+  LogicalKeyboardKey.again: TerminalKey.again,
+  LogicalKeyboardKey.undo: TerminalKey.undo,
+  LogicalKeyboardKey.cut: TerminalKey.cut,
+  LogicalKeyboardKey.copy: TerminalKey.copy,
+  LogicalKeyboardKey.paste: TerminalKey.paste,
+  LogicalKeyboardKey.find: TerminalKey.find,
+  LogicalKeyboardKey.audioVolumeMute: TerminalKey.audioVolumeMute,
+  LogicalKeyboardKey.audioVolumeUp: TerminalKey.audioVolumeUp,
+  LogicalKeyboardKey.audioVolumeDown: TerminalKey.audioVolumeDown,
+  LogicalKeyboardKey.numpadComma: TerminalKey.numpadComma,
+  LogicalKeyboardKey.intlRo: TerminalKey.intlRo,
+  LogicalKeyboardKey.kanaMode: TerminalKey.kanaMode,
+  LogicalKeyboardKey.intlYen: TerminalKey.intlYen,
+  LogicalKeyboardKey.convert: TerminalKey.convert,
+  LogicalKeyboardKey.nonConvert: TerminalKey.nonConvert,
+  LogicalKeyboardKey.lang1: TerminalKey.lang1,
+  LogicalKeyboardKey.lang2: TerminalKey.lang2,
+  LogicalKeyboardKey.lang3: TerminalKey.lang3,
+  LogicalKeyboardKey.lang4: TerminalKey.lang4,
+  LogicalKeyboardKey.lang5: TerminalKey.lang5,
+  LogicalKeyboardKey.abort: TerminalKey.abort,
+  LogicalKeyboardKey.props: TerminalKey.props,
+  LogicalKeyboardKey.numpadParenLeft: TerminalKey.numpadParenLeft,
+  LogicalKeyboardKey.numpadParenRight: TerminalKey.numpadParenRight,
+  LogicalKeyboardKey.controlLeft: TerminalKey.controlLeft,
+  LogicalKeyboardKey.shiftLeft: TerminalKey.shiftLeft,
+  LogicalKeyboardKey.altLeft: TerminalKey.altLeft,
+  LogicalKeyboardKey.metaLeft: TerminalKey.metaLeft,
+  LogicalKeyboardKey.controlRight: TerminalKey.controlRight,
+  LogicalKeyboardKey.shiftRight: TerminalKey.shiftRight,
+  LogicalKeyboardKey.altRight: TerminalKey.altRight,
+  LogicalKeyboardKey.metaRight: TerminalKey.metaRight,
+  LogicalKeyboardKey.info: TerminalKey.info,
+  LogicalKeyboardKey.closedCaptionToggle: TerminalKey.closedCaptionToggle,
+  LogicalKeyboardKey.brightnessUp: TerminalKey.brightnessUp,
+  LogicalKeyboardKey.brightnessDown: TerminalKey.brightnessDown,
+  LogicalKeyboardKey.mediaLast: TerminalKey.mediaLast,
+  LogicalKeyboardKey.launchPhone: TerminalKey.launchPhone,
+  LogicalKeyboardKey.exit: TerminalKey.exit,
+  LogicalKeyboardKey.channelUp: TerminalKey.channelUp,
+  LogicalKeyboardKey.channelDown: TerminalKey.channelDown,
+  LogicalKeyboardKey.mediaPlay: TerminalKey.mediaPlay,
+  LogicalKeyboardKey.mediaPause: TerminalKey.mediaPause,
+  LogicalKeyboardKey.mediaRecord: TerminalKey.mediaRecord,
+  LogicalKeyboardKey.mediaFastForward: TerminalKey.mediaFastForward,
+  LogicalKeyboardKey.mediaRewind: TerminalKey.mediaRewind,
+  LogicalKeyboardKey.mediaTrackNext: TerminalKey.mediaTrackNext,
+  LogicalKeyboardKey.mediaTrackPrevious: TerminalKey.mediaTrackPrevious,
+  LogicalKeyboardKey.mediaStop: TerminalKey.mediaStop,
+  LogicalKeyboardKey.eject: TerminalKey.eject,
+  LogicalKeyboardKey.mediaPlayPause: TerminalKey.mediaPlayPause,
+  LogicalKeyboardKey.speechInputToggle: TerminalKey.speechInputToggle,
+  LogicalKeyboardKey.launchWordProcessor: TerminalKey.launchWordProcessor,
+  LogicalKeyboardKey.launchSpreadsheet: TerminalKey.launchSpreadsheet,
+  LogicalKeyboardKey.launchMail: TerminalKey.launchMail,
+  LogicalKeyboardKey.launchContacts: TerminalKey.launchContacts,
+  LogicalKeyboardKey.launchCalendar: TerminalKey.launchCalendar,
+  LogicalKeyboardKey.logOff: TerminalKey.logOff,
+  LogicalKeyboardKey.launchControlPanel: TerminalKey.launchControlPanel,
+  LogicalKeyboardKey.spellCheck: TerminalKey.spellCheck,
+  LogicalKeyboardKey.launchScreenSaver: TerminalKey.launchScreenSaver,
+  LogicalKeyboardKey.launchAssistant: TerminalKey.launchAssistant,
+  LogicalKeyboardKey.newKey: TerminalKey.newKey,
+  LogicalKeyboardKey.close: TerminalKey.close,
+  LogicalKeyboardKey.save: TerminalKey.save,
+  LogicalKeyboardKey.print: TerminalKey.print,
+  LogicalKeyboardKey.browserSearch: TerminalKey.browserSearch,
+  LogicalKeyboardKey.browserHome: TerminalKey.browserHome,
+  LogicalKeyboardKey.browserBack: TerminalKey.browserBack,
+  LogicalKeyboardKey.browserForward: TerminalKey.browserForward,
+  LogicalKeyboardKey.browserStop: TerminalKey.browserStop,
+  LogicalKeyboardKey.browserRefresh: TerminalKey.browserRefresh,
+  LogicalKeyboardKey.browserFavorites: TerminalKey.browserFavorites,
+  LogicalKeyboardKey.zoomIn: TerminalKey.zoomIn,
+  LogicalKeyboardKey.zoomOut: TerminalKey.zoomOut,
+  LogicalKeyboardKey.zoomToggle: TerminalKey.zoomToggle,
+  LogicalKeyboardKey.redo: TerminalKey.redo,
+  LogicalKeyboardKey.mailReply: TerminalKey.mailReply,
+  LogicalKeyboardKey.mailForward: TerminalKey.mailForward,
+  LogicalKeyboardKey.mailSend: TerminalKey.mailSend,
+  LogicalKeyboardKey.gameButton1: TerminalKey.gameButton1,
+  LogicalKeyboardKey.gameButton2: TerminalKey.gameButton2,
+  LogicalKeyboardKey.gameButton3: TerminalKey.gameButton3,
+  LogicalKeyboardKey.gameButton4: TerminalKey.gameButton4,
+  LogicalKeyboardKey.gameButton5: TerminalKey.gameButton5,
+  LogicalKeyboardKey.gameButton6: TerminalKey.gameButton6,
+  LogicalKeyboardKey.gameButton7: TerminalKey.gameButton7,
+  LogicalKeyboardKey.gameButton8: TerminalKey.gameButton8,
+  LogicalKeyboardKey.gameButton9: TerminalKey.gameButton9,
+  LogicalKeyboardKey.gameButton10: TerminalKey.gameButton10,
+  LogicalKeyboardKey.gameButton11: TerminalKey.gameButton11,
+  LogicalKeyboardKey.gameButton12: TerminalKey.gameButton12,
+  LogicalKeyboardKey.gameButton13: TerminalKey.gameButton13,
+  LogicalKeyboardKey.gameButton14: TerminalKey.gameButton14,
+  LogicalKeyboardKey.gameButton15: TerminalKey.gameButton15,
+  LogicalKeyboardKey.gameButton16: TerminalKey.gameButton16,
+  LogicalKeyboardKey.gameButtonA: TerminalKey.gameButtonA,
+  LogicalKeyboardKey.gameButtonB: TerminalKey.gameButtonB,
+  LogicalKeyboardKey.gameButtonC: TerminalKey.gameButtonC,
+  LogicalKeyboardKey.gameButtonLeft1: TerminalKey.gameButtonLeft1,
+  LogicalKeyboardKey.gameButtonLeft2: TerminalKey.gameButtonLeft2,
+  LogicalKeyboardKey.gameButtonMode: TerminalKey.gameButtonMode,
+  LogicalKeyboardKey.gameButtonRight1: TerminalKey.gameButtonRight1,
+  LogicalKeyboardKey.gameButtonRight2: TerminalKey.gameButtonRight2,
+  LogicalKeyboardKey.gameButtonSelect: TerminalKey.gameButtonSelect,
+  LogicalKeyboardKey.gameButtonStart: TerminalKey.gameButtonStart,
+  LogicalKeyboardKey.gameButtonThumbLeft: TerminalKey.gameButtonThumbLeft,
+  LogicalKeyboardKey.gameButtonThumbRight: TerminalKey.gameButtonThumbRight,
+  LogicalKeyboardKey.gameButtonX: TerminalKey.gameButtonX,
+  LogicalKeyboardKey.gameButtonY: TerminalKey.gameButtonY,
+  LogicalKeyboardKey.gameButtonZ: TerminalKey.gameButtonZ,
+  LogicalKeyboardKey.fn: TerminalKey.fn,
+  LogicalKeyboardKey.shift: TerminalKey.shift,
+  LogicalKeyboardKey.meta: TerminalKey.meta,
+  LogicalKeyboardKey.alt: TerminalKey.alt,
+  LogicalKeyboardKey.control: TerminalKey.control,
 };
 
-TerminalKey? inputMap(LogicalKeyboardKey key) {
-  return _idKeyMap[key.keyId];
+final _keyById = () {
+  final map = <int, TerminalKey>{};
+  for (final entry in _keyToTerminalKey.entries) {
+    map[entry.key.keyId] = entry.value;
+  }
+  return map;
+}();
+
+final _keyByChar = () {
+  final map = <String, TerminalKey>{};
+  for (final entry in _keyToTerminalKey.entries) {
+    final label = entry.key.keyLabel;
+
+    if (label.isEmpty || label.length > 1) {
+      continue;
+    }
+
+    map[label] = entry.value;
+    map[label.toUpperCase()] = entry.value;
+    map[label.toLowerCase()] = entry.value;
+  }
+  return map;
+}();
+
+/// Converts a [LogicalKeyboardKey] to a [TerminalKey]. Returns `null` if the
+/// key does not have a corresponding [TerminalKey].
+///
+/// For example, `LogicalKeyboardKey.keyA` will be converted to
+/// `TerminalKey.keyA`.
+TerminalKey? keyToTerminalKey(LogicalKeyboardKey key) {
+  return _keyById[key.keyId];
+}
+
+/// Converts a character to a [TerminalKey]. Returns `null` if the character
+/// does not have a corresponding [TerminalKey].
+///
+/// For example, `charToTerminalKey('a')` or `charToTerminalKey('A')` will both
+/// return [TerminalKey.a].
+TerminalKey? charToTerminalKey(String char) {
+  return _keyByChar[char];
 }