From 32dc2bf3bf5c28ff44fff89d2436a76bb7bba925 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Sat, 15 Oct 2016 12:01:15 +0100 Subject: enterNormalMode; new command - implementation Here's the problem... Many sites define their own keyboard shortcuts, for example Google Play Music defines `gh` for "go home". On such sites, it's natural to set up pass keys for `g` and `h`. But that makes any Vimium key bindings which begin with `g` inaccessible. Here, we add a new command `enterNormalMode` which installs a new normal-mode instance (without any pass keys). This executes a single normal-mode command then exits. Example: map \ enterNormalMode map | enterNormalMode count=999999 Assuming `g` and `o` are pass keys: - `gh` or `o` - use the page's binding - `\gg` - scroll to top - `2\ggo` - scroll to the top and open the Vomnibar - `\go` - open the Vomnibar - `\o` - use the page's bindings - `\\\\\\o` - use the page's bindings (new normal-mode instances displace previous ones) This required some changes to the scroller. Previously, we only ever had one normal-mode instance, and could arrange statically that the scroller's key listeners were above normal-mode's key listeners in the handler stack. Here, we fix this by adding and removing the scroller's listeners dynamically, so they're always at the top of the handler stack. --- content_scripts/mode_key_handler.coffee | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'content_scripts/mode_key_handler.coffee') diff --git a/content_scripts/mode_key_handler.coffee b/content_scripts/mode_key_handler.coffee index 480a79af..9b5a1fef 100644 --- a/content_scripts/mode_key_handler.coffee +++ b/content_scripts/mode_key_handler.coffee @@ -36,6 +36,18 @@ class KeyHandlerMode extends Mode @mapKeyRegistry = {} Utils.monitorChromeStorage "mapKeyRegistry", (value) => @mapKeyRegistry = value + if options.exitOnEscape + # If we're part way through a command's key sequence, then a first Escape should reset the key state, + # and only a second Escape should actually exit this mode. + @push + _name: "key-handler-escape-listener" + keydown: (event) => + if KeyboardUtils.isEscape(event) and not @isInResetState() + @reset() + DomUtils.suppressKeyupAfterEscape handlerStack + else + @continueBubbling + onKeydown: (event) -> keyChar = KeyboardUtils.getKeyCharString event keyChar = @mapKeyRegistry[keyChar] ? keyChar @@ -92,7 +104,10 @@ class KeyHandlerMode extends Mode # Keystrokes are *never* considered pass keys if the user has begun entering a command. So, for example, if # 't' is a passKey, then the "t"-s of 'gt' and '99t' are neverthless handled as regular keys. isPassKey: (keyChar) -> - @countPrefix == 0 and @keyState.length == 1 and keyChar in (@passKeys ? "") + @isInResetState() and keyChar in (@passKeys ? "") + + isInResetState: -> + @countPrefix == 0 and @keyState.length == 1 handleKeyChar: (keyChar) -> bgLog "handle key #{keyChar} (#{@name})" @@ -106,6 +121,7 @@ class KeyHandlerMode extends Mode bgLog " invoke #{command.command} count=#{count} " @reset() @commandHandler {command, count} + @exit() if @options.count? and --@options.count <= 0 @suppressEvent root = exports ? window -- cgit v1.2.3