       name: "hint/#{mode.name}"
       indicator: false
       passInitialKeyupEvents: true
-      keydown: @onKeyDownInMode.bind this, hintMarkers
-      # Trap all other key events.
-      keypress: -> false
-      keyup: -> false
+      suppressAllKeyboardEvents: true
+      exitOnEscape: true
+      keypress: @onKeyDownInMode.bind this, hintMarkers
+
+    @hintMode.onExit =>
+      @deactivateMode() if @isActive
 
     @setOpenLinkMode mode
 


  matchHintsByKey: (hintMarkers, event) ->
    # If a shifted-character is typed, treat it as lowerase for the purposes of matching hints.
    keyChar = KeyboardUtils.getKeyChar(event).toLowerCase()

    if (event.keyCode == keyCodes.backspace || event.keyCode == keyCodes.deleteKey)
      if (!@hintKeystrokeQueue.pop())

      if (LinkHints.hintMarkerContainingDiv)
        DomUtils.removeElement LinkHints.hintMarkerContainingDiv
      LinkHints.hintMarkerContainingDiv = null
      @isActive = false
      @hintMode.exit()
      @onExit?()
      @onExit = null

    if delay
      Utils.setTimeout delay, ->
        deactivate()
        callback?()
    else
      # We invoke deactivate() directly (instead of setting a timeout of 0) so that deactivateMode() can be
      # tested synchronously.
      deactivate()
      callback?()

alphabetHints =
  hintKeystrokeQueue: []
