aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--content_scripts/mode.coffee11
-rw-r--r--content_scripts/mode_key_handler.coffee72
-rw-r--r--content_scripts/mode_passkeys.coffee13
-rw-r--r--content_scripts/vimium_frontend.coffee3
-rw-r--r--lib/handler_stack.coffee2
5 files changed, 36 insertions, 65 deletions
diff --git a/content_scripts/mode.coffee b/content_scripts/mode.coffee
index 454a6ed9..efbc9cf4 100644
--- a/content_scripts/mode.coffee
+++ b/content_scripts/mode.coffee
@@ -120,20 +120,13 @@ class Mode
singletons[key] = this
# If @options.trackState is truthy, then the mode mainatins the current state in @enabled and @passKeys,
- # and calls @registerStateChange() (if defined) whenever the state changes. The mode also tracks the
- # current keyQueue in @keyQueue.
+ # and calls @registerStateChange() (if defined) whenever the state changes.
if @options.trackState
@enabled = false
@passKeys = ""
- @keyQueue = ""
@push
_name: "mode-#{@id}/registerStateChange"
- registerStateChange: ({ enabled: enabled, passKeys: passKeys }) => @alwaysContinueBubbling =>
- if enabled != @enabled or passKeys != @passKeys
- @enabled = enabled
- @passKeys = passKeys
- @registerStateChange?()
- registerKeyQueue: ({ keyQueue: keyQueue }) => @alwaysContinueBubbling => @keyQueue = keyQueue
+ registerStateChange: ({ enabled: @enabled, passKeys: @passKeys }) => @alwaysContinueBubbling =>
# If @options.passInitialKeyupEvents is set, then we pass initial non-printable keyup events to the page
# or to other extensions (because the corresponding keydown events were passed). This is used when
diff --git a/content_scripts/mode_key_handler.coffee b/content_scripts/mode_key_handler.coffee
index 9b044923..c9cab244 100644
--- a/content_scripts/mode_key_handler.coffee
+++ b/content_scripts/mode_key_handler.coffee
@@ -1,32 +1,25 @@
class KeyHandlerMode extends Mode
- useCount: true
countPrefix: 0
keydownEvents: {}
keyState: []
constructor: (options) ->
- # A function accepting a command name and a count; required.
@commandHandler = options.commandHandler ? (->)
- @useCount = false if options.noCount
- @reset()
-
- # We don't pass these options on to super().
- options = Utils.copyObjectOmittingProperties options, "commandHandler", "keyMapping", "noCount"
+ @setKeyMapping options.commandHandler ? {}
+ delete options[option] for option in ["commandHandler", "keyMapping"]
super extend options,
keydown: @onKeydown.bind this
keypress: @onKeypress.bind this
keyup: @onKeyup.bind this
# We cannot track matching keydown/keyup events if we lose the focus.
- blur: (event) => @alwaysContinueBubbling =>
- @keydownEvents = {} if event.target == window
+ blur: (event) => @alwaysContinueBubbling => @keydownEvents = {} if event.target == window
setKeyMapping: (@keyMapping) -> @reset()
onKeydown: (event) ->
keyChar = KeyboardUtils.getKeyCharString event
-
if KeyboardUtils.isEscape event
if @isInResetState()
@continueBubbling
@@ -39,16 +32,14 @@ class KeyHandlerMode extends Mode
@handleKeyChar event, keyChar
else
- # We did not handle the event, but we might handle the subsequent keypress event. If we *will* be
- # handling that event, then we need to suppress propagation of this keydown event to prevent triggering
- # page features like Google instant search.
+ # We did not handle the event, but we might handle a subsequent keypress. If we will be handling that
+ # event, then we suppress propagation of this keydown to prevent triggering page events.
keyChar = KeyboardUtils.getKeyChar event
if keyChar and (@mappingForKeyChar(keyChar) or @isCountKey keyChar)
DomUtils.suppressPropagation event
- @keydownEvents[@getEventCode event] = true
+ @keydownEvents[event.keyCode] = true
@stopBubblingAndTrue
else
- @countPrefix = 0 if keyChar
@continueBubbling
onKeypress: (event) ->
@@ -56,50 +47,46 @@ class KeyHandlerMode extends Mode
if keyChar and @mappingForKeyChar keyChar
@handleKeyChar event, keyChar
else if keyChar and @isCountKey keyChar
- @reset @countPrefix * 10 + parseInt keyChar
+ digit = parseInt keyChar
+ @reset if @keyState.length == 1 then @countPrefix * 10 + digit else digit
false # Suppress event.
else
+ @reset()
@continueBubbling
onKeyup: (event) ->
- eventCode = @getEventCode event
- if eventCode of @keydownEvents
- delete @keydownEvents[eventCode]
+ if event.keyCode of @keydownEvents
+ delete @keydownEvents[event.keyCode]
DomUtils.suppressPropagation event
@stopBubblingAndTrue
else
@continueBubbling
handleKeyChar: (event, keyChar) ->
+ bgLog "Handling key #{keyChar}, mode=#{@name}."
@advanceKeyState keyChar
commands = @keyState.filter (entry) -> entry.command
- @invokeCommand commands[0] if 0 < commands.length
+ if 0 < commands.length
+ countPrefix = if 0 < @countPrefix then @countPrefix else 1
+ @reset()
+ bgLog "Calling mode=#{@name}, command=#{commands[0].command}, count=#{countPrefix}."
+ @commandHandler commands[0], countPrefix
false # Suppress event.
- # This returns the first mapping for which keyChar is mapped. The return value is truthy if a match is found
- # and falsy otherwise.
+ # This returns the first key-state entry for which keyChar is mapped. The return value is truthy if a match
+ # is found and falsy otherwise.
mappingForKeyChar: (keyChar) ->
- for mapping in @keyState
- return mapping if keyChar of mapping
- null
+ (mapping for mapping in @keyState when keyChar of mapping)[0]
- # This is called whenever a keyChar is matched. We keep any existing entries matching keyChar, and append a
- # new copy of the global key mappings.
+ # This is called whenever a keyChar is matched. We keep any existing mappings matching keyChar, and append
+ # a new copy of the mode's global key mappings.
advanceKeyState: (keyChar) ->
- newKeyState =
- for mapping in @keyState
- continue unless keyChar of mapping
- mapping[keyChar]
- @keyState = [newKeyState..., @keyMapping]
-
- # This is called to invoke a command and reset the key state.
- invokeCommand: (command) ->
- countPrefix = if 0 < @countPrefix then @countPrefix else 1
- @reset()
- @commandHandler command, countPrefix
+ newMappings = (mapping[keyChar] for mapping in @keyState when keyChar of mapping)
+ @keyState = [newMappings..., @keyMapping]
# Reset the state (as if no keys had been handled), but retaining the count - if one is provided.
reset: (count = 0) ->
+ bgLog "Clearing key queue, set count=#{count}."
@countPrefix = count
@keyState = [@keyMapping]
@@ -110,18 +97,15 @@ class KeyHandlerMode extends Mode
# This tests whether keyChar should be treated as a count key.
isCountKey: (keyChar) ->
- return false unless @useCount and keyChar.length == 1
+ return false unless keyChar.length == 1
if 0 < @countPrefix
'0' <= keyChar <= '9'
else
'1' <= keyChar <= '9'
- # True if keyChar would be the first character of a command mapping. This is used by passKeys to decide
- # whether keyChar is a continuation of a command which the user has already begin entering.
+ # Test whether keyChar would be the very first character of a command mapping.
isFirstKeyChar: (keyChar) ->
- @countPrefix == 0 and @keyMapping == @mappingForKeyChar keyChar
-
- getEventCode: (event) -> event.keyCode
+ keyChar and @countPrefix == 0 and (@mappingForKeyChar(keyChar) == @keyMapping or @isCountKey keyChar)
root = exports ? window
root.KeyHandlerMode = KeyHandlerMode
diff --git a/content_scripts/mode_passkeys.coffee b/content_scripts/mode_passkeys.coffee
index 426e5369..a68fe3be 100644
--- a/content_scripts/mode_passkeys.coffee
+++ b/content_scripts/mode_passkeys.coffee
@@ -3,20 +3,17 @@ class PassKeysMode extends Mode
constructor: (@normalMode) ->
super
name: "passkeys"
- trackState: true # Maintain @enabled, @passKeys and @keyQueue.
+ trackState: true # Maintain @passKeys.
keydown: (event) => @handleKeyChar event, KeyboardUtils.getKeyChar event
keypress: (event) => @handleKeyChar event, String.fromCharCode event.charCode
keyup: (event) => @handleKeyChar event, KeyboardUtils.getKeyChar event
- # Keystrokes are *never* considered passKeys if the user has begin entering a command. So, for example, if
- # 't' is a passKey, then 'gt' and '99t' will neverthless be handled by Vimium.
+ # Keystrokes are *never* considered passKeys if the user has begun entering a command. So, for example, if
+ # 't' is a passKey, then 'gt' and '99t' are neverthless be handled by Vimium.
handleKeyChar: (event, keyChar) ->
return @continueBubbling if event.altKey or event.ctrlKey or event.metaKey
- return @continueBubbling unless keyChar and keyChar.length == 1
- # Test whether the user has already begun entering a command.
- return @continueBubbling unless @normalMode.isFirstKeyChar keyChar
- return @continueBubbling unless 0 <= @passKeys.indexOf keyChar
- # This is a passkey.
+ return @continueBubbling unless keyChar and @normalMode.isFirstKeyChar keyChar
+ return @continueBubbling unless keyChar.length == 1 and 0 <= @passKeys.indexOf keyChar
@stopBubblingAndTrue
root = exports ? window
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index 5c594d1c..3220b084 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -7,7 +7,6 @@
isEnabledForUrl = true
isIncognitoMode = chrome.extension.inIncognitoContext
-passKeys = null
# We track whther the current window has the focus or not.
windowIsFocused = do ->
@@ -162,7 +161,7 @@ initializePreDomReady = ->
return if request.handler and not request.name
shouldHandleRequest = isEnabledForUrl
# We always handle the message if it's one of these listed message types.
- shouldHandleRequest ||= request.name in [ "checkEnabledAfterURLChange" ]
+ shouldHandleRequest ||= request.name in ["checkEnabledAfterURLChange", "openVomnibar"]
sendResponse requestHandlers[request.name](request, sender) if shouldHandleRequest
# Ensure the sendResponse callback is freed.
false
diff --git a/lib/handler_stack.coffee b/lib/handler_stack.coffee
index bb0f19a6..2a44d26b 100644
--- a/lib/handler_stack.coffee
+++ b/lib/handler_stack.coffee
@@ -84,8 +84,6 @@ class HandlerStack
# Debugging.
logResult: (eventNumber, type, event, handler, result) ->
- # Key queue events aren't usually useful for debugging, so we filter them out.
- return if type in [ "registerKeyQueue" ]
label =
switch result
when @stopBubblingAndTrue then "stop/true"