     @hintMarkerContainingDiv = DomUtils.addElementList(hintMarkers,
       { id: "vimiumHintMarkerContainer", className: "vimiumReset" })
 
-    # handlerStack is declared by vimiumFrontend.js
-    @handlerId = handlerStack.push({
-      keydown: @onKeyDownInMode.bind(this, hintMarkers),
-      # trap all key events
-      keypress: -> false
-      keyup: -> false
-    })
+    @handlerMode =
+      new class HintMode extends Mode
+        constructor: ->
+          super
+            name: "hint/#{mode.name}"
+            badge: "?#{mode.key}"
+            exitOnEscape: true
+            keydown: (event) -> LinkHints.onKeyDownInMode hintMarkers, event
+            # trap all key events
+            keypress: => @stopBubblingAndFalse
+            keyup: => @stopBubblingAndFalse
+
+        exit: (delay, callback) =>
+          super()
+          LinkHints.deactivateMode delay, callback
 
   setOpenLinkMode: (@mode) ->
     if @mode is OPEN_IN_NEW_BG_TAB or @mode is OPEN_IN_NEW_FG_TAB or @mode is OPEN_WITH_QUEUE

      if (LinkHints.hintMarkerContainingDiv)
        DomUtils.removeElement LinkHints.hintMarkerContainingDiv
      LinkHints.hintMarkerContainingDiv = null
      handlerStack.remove @handlerId
      HUD.hide()
      @isActive = false



    # TODO(philc): Ignore keys that have modifiers.
    if (KeyboardUtils.isEscape(event))
      # TODO(smblott). Now unreachable.  Clean up.  Left like this for now to keep the diff clean.
      @handlerMode.exit()
    else
      keyResult = @getMarkerMatcher().matchHintsByKey(hintMarkers, event)
      linksMatched = keyResult.linksMatched
      delay = keyResult.delay ? 0
      if (linksMatched.length == 0)
        @handlerMode.exit()
      else if (linksMatched.length == 1)
        @activateLink(linksMatched[0], delay)
      else
