aboutsummaryrefslogtreecommitdiffstats
path: root/content_scripts/vimium_frontend.coffee
diff options
context:
space:
mode:
Diffstat (limited to 'content_scripts/vimium_frontend.coffee')
-rw-r--r--content_scripts/vimium_frontend.coffee78
1 files changed, 50 insertions, 28 deletions
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index 565c9e61..137b9d1a 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -13,8 +13,11 @@ findModeQueryHasResults = false
findModeAnchorNode = null
isShowingHelpDialog = false
keyPort = null
-# Users can disable Vimium on URL patterns via the settings page.
+# Users can disable Vimium on URL patterns via the settings page. The following two variables
+# (isEnabledForUrl and passKeys) control Vimium's enabled/disabled behaviour.
isEnabledForUrl = true
+passKeys = null
+keyQueue = null
# The user's operating system.
currentCompletionKeys = null
validFirstKeys = null
@@ -115,42 +118,46 @@ initializePreDomReady = ->
getScrollPosition: -> scrollX: window.scrollX, scrollY: window.scrollY
setScrollPosition: (request) -> setScrollPosition request.scrollX, request.scrollY
executePageCommand: executePageCommand
- getActiveState: -> { enabled: isEnabledForUrl }
- disableVimium: disableVimium
+ getActiveState: -> { enabled: isEnabledForUrl, passKeys: passKeys }
+ setState: setState
+ currentKeyQueue: (request) -> keyQueue = request.keyQueue
chrome.runtime.onMessage.addListener (request, sender, sendResponse) ->
- # in the options page, we will receive requests from both content and background scripts. ignore those
+ # In the options page, we will receive requests from both content and background scripts. ignore those
# from the former.
return if sender.tab and not sender.tab.url.startsWith 'chrome-extension://'
- return unless isEnabledForUrl or request.name == 'getActiveState'
+ return unless isEnabledForUrl or request.name == 'getActiveState' or request.name == 'setState'
+ # These requests are delivered to the options page, but there are no handlers there.
+ return if request.handler == "registerFrame" or request.handler == "frameFocused"
sendResponse requestHandlers[request.name](request, sender)
- # Ensure the sendResponse callback is freed.
false
-#
-# This is called once the background page has told us that Vimium should be enabled for the current URL.
-#
-initializeWhenEnabled = ->
- document.addEventListener("keydown", onKeydown, true)
- document.addEventListener("keypress", onKeypress, true)
- document.addEventListener("keyup", onKeyup, true)
- document.addEventListener("focus", onFocusCapturePhase, true)
- document.addEventListener("blur", onBlurCapturePhase, true)
- document.addEventListener("DOMActivate", onDOMActivate, true)
- enterInsertModeIfElementIsFocused()
+# Wrapper to install event listeners. Syntactic sugar.
+installListener = (event, callback) -> document.addEventListener(event, callback, true)
#
-# Used to disable Vimium without needing to reload the page.
-# This is called if the current page's url is blacklisted using the popup UI.
+# This is called once the background page has told us that Vimium should be enabled for the current URL.
+# We enable/disable Vimium by toggling isEnabledForUrl. The alternative, installing or uninstalling
+# listeners, is error prone. It's more difficult to keep track of the state.
#
-disableVimium = ->
- document.removeEventListener("keydown", onKeydown, true)
- document.removeEventListener("keypress", onKeypress, true)
- document.removeEventListener("keyup", onKeyup, true)
- document.removeEventListener("focus", onFocusCapturePhase, true)
- document.removeEventListener("blur", onBlurCapturePhase, true)
- document.removeEventListener("DOMActivate", onDOMActivate, true)
- isEnabledForUrl = false
+installedListeners = false
+initializeWhenEnabled = (newPassKeys=undefined) ->
+ isEnabledForUrl = true
+ passKeys = passKeys if typeof(newPassKeys) != 'undefined'
+ if (!installedListeners)
+ installListener "keydown", (event) -> if isEnabledForUrl then onKeydown(event) else true
+ installListener "keypress", (event) -> if isEnabledForUrl then onKeypress(event) else true
+ installListener "keyup", (event) -> if isEnabledForUrl then onKeyup(event) else true
+ installListener "focus", (event) -> if isEnabledForUrl then onFocusCapturePhase(event) else true
+ installListener "blur", (event) -> if isEnabledForUrl then onBlurCapturePhase(event)
+ installListener "DOMActivate", (event) -> if isEnabledForUrl then onDOMActivate(event)
+ enterInsertModeIfElementIsFocused()
+ installedListeners = true
+
+setState = (request) ->
+ isEnabledForUrl = request.enabled
+ passKeys = request.passKeys
+ initializeWhenEnabled(passKeys) if isEnabledForUrl and !installedListeners
#
# The backend needs to know which frame has focus.
@@ -321,6 +328,15 @@ extend window,
false
+# Should this keyChar be passed to the underlying page?
+# Keystrokes are *never* considered passKeys if the keyQueue is not empty. So, for example, if 't' is a
+# passKey, then 'gt' and '99t' will neverthless be handled by vimium.
+# TODO: This currently only works for unmodified keys (so not for '<c-a>', or the like). It's not clear if
+# this is a problem or not. I don't recall coming across a web page with modifier key bindings. Such
+# bindings might be too likely to conflict with browsers' native bindings.
+isPassKey = ( keyChar ) ->
+ !keyQueue and passKeys and 0 <= passKeys.indexOf keyChar
+
handledKeydownEvents = []
#
@@ -349,6 +365,9 @@ onKeypress = (event) ->
handleKeyCharForFindMode(keyChar)
DomUtils.suppressEvent(event)
else if (!isInsertMode() && !findMode)
+ # Is this keyChar is to be passed to the underlying page?
+ if (isPassKey keyChar)
+ return undefined
if (currentCompletionKeys.indexOf(keyChar) != -1)
DomUtils.suppressEvent(event)
@@ -431,6 +450,9 @@ onKeydown = (event) ->
else if (KeyboardUtils.isEscape(event))
keyPort.postMessage({ keyChar:"<ESC>", frameId:frameId })
+ else if isPassKey KeyboardUtils.getKeyChar(event)
+ return undefined
+
# Added to prevent propagating this event to other listeners if it's one that'll trigger a Vimium command.
# The goal is to avoid the scenario where Google Instant Search uses every keydown event to dump us
# back into the search box. As a side effect, this should also prevent overriding by other sites.
@@ -466,7 +488,7 @@ checkIfEnabledForUrl = ->
chrome.runtime.sendMessage { handler: "isEnabledForUrl", url: url }, (response) ->
isEnabledForUrl = response.isEnabledForUrl
if (isEnabledForUrl)
- initializeWhenEnabled()
+ initializeWhenEnabled(response.passKeys)
else if (HUD.isReady())
# Quickly hide any HUD we might already be showing, e.g. if we entered insert mode on page load.
HUD.hide()