aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Blott2014-08-23 11:40:25 +0100
committerStephen Blott2014-08-23 14:52:26 +0100
commitf037e83763b1b62e048e1fc433d52b9564ce3ba0 (patch)
tree033ce9610bbfdc7aa65df1dda6bfd259c37cad26
parent43caeb82d91e7cb88b085cb6e33a61a108322875 (diff)
downloadvimium-f037e83763b1b62e048e1fc433d52b9564ce3ba0.tar.bz2
Allow passing of keys to the underlying page.
-rw-r--r--background_scripts/main.coffee37
-rw-r--r--background_scripts/settings.coffee4
-rw-r--r--content_scripts/vimium_frontend.coffee19
-rw-r--r--pages/options.html25
4 files changed, 71 insertions, 14 deletions
diff --git a/background_scripts/main.coffee b/background_scripts/main.coffee
index 431d9a31..e32027b6 100644
--- a/background_scripts/main.coffee
+++ b/background_scripts/main.coffee
@@ -69,17 +69,29 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) ->
getCurrentTabUrl = (request, sender) -> sender.tab.url
#
-# Checks the user's preferences in local storage to determine if Vimium is enabled for the given URL.
+# Checks the user's preferences in local storage to determine if Vimium is enabled for the given URL, and
+# whether any keys should be passed through to the underlying page.
#
isEnabledForUrl = (request) ->
- # excludedUrls are stored as a series of URL expressions separated by newlines.
- excludedUrls = Settings.get("excludedUrls").split("\n")
- isEnabled = true
- for url in excludedUrls
- # The user can add "*" to the URL which means ".*"
- regexp = new RegExp("^" + url.replace(/\*/g, ".*") + "$")
- isEnabled = false if request.url.match(regexp)
- { isEnabledForUrl: isEnabled }
+ # Excluded URLs are stored as a series of URL expressions and optional passKeys, separated by newlines.
+ # Lines for which the first non-blank character is "#" are comments.
+ excludedLines = (line.trim() for line in Settings.get("excludedUrls").split("\n"))
+ excludedUrls = (line for line in excludedLines when line and line.indexOf("#") != 0)
+ for spec in excludedUrls
+ parse = spec.split(/\s+/)
+ if parse.length
+ url = parse[0]
+ # The user can add "*" to the URL which means ".*"
+ regexp = new RegExp("^" + url.replace(/\*/g, ".*") + "$")
+ if request.url.match(regexp)
+ passKeys = parse[1..].join("")
+ if passKeys
+ # Enabled, but only for these keys.
+ return { isEnabledForUrl: true, passKeys: passKeys }
+ # Disabled.
+ return { isEnabledForUrl: false }
+ # Enabled (the default).
+ { isEnabledForUrl: true }
# Called by the popup UI. Strips leading/trailing whitespace and ignores empty strings.
root.addExcludedUrl = (url) ->
@@ -500,6 +512,13 @@ handleKeyDown = (request, port) ->
console.log("checking keyQueue: [", keyQueue + key, "]")
keyQueue = checkKeyQueue(keyQueue + key, port.sender.tab.id, request.frameId)
console.log("new KeyQueue: " + keyQueue)
+ # Tell the front end whether there are keys in the queue. If there are, then subsequent keys in passKeys will be
+ # handled by vimium.
+ # FIXME: There is a race condition here. The behaviour depends upon whether this message gets back
+ # to the front end before the next keystroke or not.
+ chrome.tabs.sendMessage(port.sender.tab.id,
+ name: "currentKeyQueue",
+ keyQueue: keyQueue)
checkKeyQueue = (keysToCheck, tabId, frameId) ->
refreshedCompletionKeys = false
diff --git a/background_scripts/settings.coffee b/background_scripts/settings.coffee
index 175f3262..34d6e879 100644
--- a/background_scripts/settings.coffee
+++ b/background_scripts/settings.coffee
@@ -83,7 +83,11 @@ root.Settings = Settings =
"""
excludedUrls:
"""
+ # Disable Vimium on Gmail:
http*://mail.google.com/*
+
+ # Use Facebook's own j/k bindings:
+ http*://www.facebook.com/* jk
"""
# NOTE: If a page contains both a single angle-bracket link and a double angle-bracket link, then in
# most cases the single bracket link will be "prev/next page" and the double bracket link will be
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index 565c9e61..70cc5cbb 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -15,6 +15,8 @@ isShowingHelpDialog = false
keyPort = null
# Users can disable Vimium on URL patterns via the settings page.
isEnabledForUrl = true
+passKeys = null
+keyQueue = null
# The user's operating system.
currentCompletionKeys = null
validFirstKeys = null
@@ -115,6 +117,7 @@ initializePreDomReady = ->
getScrollPosition: -> scrollX: window.scrollX, scrollY: window.scrollY
setScrollPosition: (request) -> setScrollPosition request.scrollX, request.scrollY
executePageCommand: executePageCommand
+ currentKeyQueue: (request) -> keyQueue = request.keyQueue
getActiveState: -> { enabled: isEnabledForUrl }
disableVimium: disableVimium
@@ -321,6 +324,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 browser bindings.
+isPassKey = ( keyChar ) ->
+ !keyQueue and passKeys and 0 <= passKeys.indexOf keyChar
+
handledKeydownEvents = []
#
@@ -349,6 +361,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 +446,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.
@@ -467,6 +485,7 @@ checkIfEnabledForUrl = ->
isEnabledForUrl = response.isEnabledForUrl
if (isEnabledForUrl)
initializeWhenEnabled()
+ passKeys = 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()
diff --git a/pages/options.html b/pages/options.html
index b71625e8..fc0f189d 100644
--- a/pages/options.html
+++ b/pages/options.html
@@ -197,15 +197,30 @@
</tr>
<tr>
<td colspan="3">
- Excluded URLs<br/>
+ Excluded URLs and keys<br/>
<div class="help">
<div class="example">
- e.g. http*://mail.google.com/*<br/>
- This will disable Vimium on Gmail.<br/><br/>
- Enter one URL per line.<br/>
+ <p>
+ To disable Vimium on a site, use:<br/>
+ <tt>http*://mail.google.com/*</tt><br/>
+ This will <i>wholly disable</i> Vimium on Gmail.<br/><br/>
+ To use Vimium together with a website's own<br/>
+ key bindings, use:<br/>
+ <tt>http*://mail.google.com/* jknpc</tt><br/>
+ This will <i>enable</i> Vimium on Gmail, but pass<br/>
+ the five listed keys through to Gmail itself.<br/><br/>
+ One entry per line.<br/>
+ </p>
</div>
</div>
- <textarea id="excludedUrls"></textarea>
+ <!-- Hack: fix a minimum size for the text area (below) so that it is
+ not too much smaller than its help text (above). -->
+ <!-- FIXME:
+ This text area should really be broken out into an array
+ separate inputs. However, the whole options page really
+ needs a workover, so I'm leaving it like this, for now
+ (Steve, 23 Aug, 14). -->
+ <textarea id="excludedUrls" style="min-height:180px"></textarea>
</td>
</tr>
<tbody id='advancedOptions'>