aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Blott2016-02-18 10:29:51 +0000
committerStephen Blott2016-02-18 10:29:51 +0000
commitf91fb7b9e11095cbb59174601096f0239501f6a0 (patch)
treed0ac44c1ee050c256e3e03de244a3b0efb50d02f
parent8e3ac1867b7577814865bf1cb40d0b865de30b1a (diff)
parent38509ce26afd1df7288255bfbcae1705f7bf9d86 (diff)
downloadvimium-f91fb7b9e11095cbb59174601096f0239501f6a0.tar.bz2
Merge pull request #1985 from smblott-github/pass-next-key
New command: Pass next key
-rw-r--r--background_scripts/commands.coffee12
-rw-r--r--content_scripts/mode_insert.coffee33
-rw-r--r--content_scripts/vimium_frontend.coffee51
-rw-r--r--lib/keyboard_utils.coffee28
-rw-r--r--lib/settings.coffee1
5 files changed, 85 insertions, 40 deletions
diff --git a/background_scripts/commands.coffee b/background_scripts/commands.coffee
index db8cc60f..80ca0f96 100644
--- a/background_scripts/commands.coffee
+++ b/background_scripts/commands.coffee
@@ -67,6 +67,13 @@ Commands =
when "unmapAll"
@keyToCommandRegistry = {}
+ # Push the key mapping for passNextKey into Settings so that it's available in the front end for insert
+ # mode. We exclude single-key mappings (that is, printable keys) because when users press printable keys
+ # in insert mode they expect the character to be input, not to be droppped into some special Vimium
+ # mode.
+ Settings.set "passNextKeyKeys",
+ (key for own key of @keyToCommandRegistry when @keyToCommandRegistry[key].command == "passNextKey" and 1 < key.length)
+
clearKeyMappingsAndSetDefaults: ->
@keyToCommandRegistry = {}
@mapKeyToCommand { key, command } for own key, command of defaultKeyMappings
@@ -96,6 +103,7 @@ Commands =
"goUp",
"goToRoot",
"enterInsertMode",
+ "passNextKey",
"enterVisualMode",
"enterVisualLineMode",
"focusInput",
@@ -164,7 +172,8 @@ Commands =
"moveTabRight",
"closeTabsOnLeft",
"closeTabsOnRight",
- "closeOtherTabs"]
+ "closeOtherTabs",
+ "passNextKey"]
defaultKeyMappings =
"?": "showHelp"
@@ -277,6 +286,7 @@ commandDescriptions =
openCopiedUrlInNewTab: ["Open the clipboard's URL in a new tab", { background: true, repeatLimit: 20 }]
enterInsertMode: ["Enter insert mode", { noRepeat: true }]
+ passNextKey: ["Pass the next key to Chrome", { passCountToFunction: true }]
enterVisualMode: ["Enter visual mode", { noRepeat: true }]
enterVisualLineMode: ["Enter visual line mode", { noRepeat: true }]
diff --git a/content_scripts/mode_insert.coffee b/content_scripts/mode_insert.coffee
index 0b040e5d..a35633ac 100644
--- a/content_scripts/mode_insert.coffee
+++ b/content_scripts/mode_insert.coffee
@@ -10,6 +10,12 @@ class InsertMode extends Mode
handleKeyEvent = (event) =>
return @continueBubbling unless @isActive event
+
+ # Check for a pass-next-key key.
+ if KeyboardUtils.getKeyCharString(event) in Settings.get "passNextKeyKeys"
+ new PassNextKeyMode
+ return false
+
return @stopBubblingAndTrue unless event.type == 'keydown' and KeyboardUtils.isEscape event
DomUtils.suppressKeyupAfterEscape handlerStack
target = event.srcElement
@@ -98,5 +104,32 @@ class InsertMode extends Mode
@suppressedEvent: null
@suppressEvent: (event) -> @suppressedEvent = event
+# This implements the pasNexKey command.
+class PassNextKeyMode extends Mode
+ constructor: (count = 1) ->
+ seenKeyDown = false
+ keyDownCount = 0
+
+ super
+ name: "pass-next-key"
+ indicator: "Pass next key."
+ # We exit on blur because, once we lose the focus, we can no longer track key events.
+ exitOnBlur: window
+ keypress: =>
+ @stopBubblingAndTrue
+
+ keydown: =>
+ seenKeyDown = true
+ keyDownCount += 1
+ @stopBubblingAndTrue
+
+ keyup: =>
+ if seenKeyDown
+ unless 0 < --keyDownCount
+ unless 0 < --count
+ @exit()
+ @stopBubblingAndTrue
+
root = exports ? window
root.InsertMode = InsertMode
+root.PassNextKeyMode = PassNextKeyMode
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index f78b79b0..eb52e4ee 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -368,6 +368,9 @@ extend window,
enterVisualLineMode: ->
new VisualLineMode
+ passNextKey: (count) ->
+ new PassNextKeyMode count
+
focusInput: do ->
# Track the most recently focused input element.
recentlyFocusedElement = null
@@ -486,50 +489,20 @@ handlerStack.push
#
# @/this, here, is the the normal-mode Mode object.
onKeypress = (event) ->
- keyChar = ""
-
- # Ignore modifier keys by themselves.
- if (event.keyCode > 31)
- keyChar = String.fromCharCode(event.charCode)
+ keyChar = KeyboardUtils.getKeyCharString event
+ if keyChar
+ if currentCompletionKeys.indexOf(keyChar) != -1 or isValidFirstKey keyChar
+ DomUtils.suppressEvent(event)
+ keyPort.postMessage keyChar:keyChar, frameId:frameId
+ return @stopBubblingAndTrue
- if (keyChar)
- if currentCompletionKeys.indexOf(keyChar) != -1 or isValidFirstKey(keyChar)
- DomUtils.suppressEvent(event)
- keyPort.postMessage({ keyChar:keyChar, frameId:frameId })
- return @stopBubblingAndTrue
-
- keyPort.postMessage({ keyChar:keyChar, frameId:frameId })
+ keyPort.postMessage keyChar:keyChar, frameId:frameId
return @continueBubbling
# @/this, here, is the the normal-mode Mode object.
onKeydown = (event) ->
- keyChar = ""
-
- # handle special keys, and normal input keys with modifiers being pressed. don't handle shiftKey alone (to
- # avoid / being interpreted as ?
- if (((event.metaKey || event.ctrlKey || event.altKey) && event.keyCode > 31) || (
- # TODO(philc): some events don't have a keyidentifier. How is that possible?
- event.keyIdentifier && event.keyIdentifier.slice(0, 2) != "U+"))
- keyChar = KeyboardUtils.getKeyChar(event)
- # Again, ignore just modifiers. Maybe this should replace the keyCode>31 condition.
- if (keyChar != "")
- modifiers = []
-
- if (event.shiftKey)
- keyChar = keyChar.toUpperCase()
- if (event.metaKey)
- modifiers.push("m")
- if (event.ctrlKey)
- modifiers.push("c")
- if (event.altKey)
- modifiers.push("a")
-
- for own i of modifiers
- keyChar = modifiers[i] + "-" + keyChar
-
- if (modifiers.length > 0 || keyChar.length > 1)
- keyChar = "<" + keyChar + ">"
+ keyChar = KeyboardUtils.getKeyCharString event
if (HelpDialog.showing && KeyboardUtils.isEscape(event))
HelpDialog.hide()
@@ -557,7 +530,7 @@ onKeydown = (event) ->
# Subject to internationalization issues since we're using keyIdentifier instead of charCode (in keypress).
#
# TOOD(ilya): Revisit this. Not sure it's the absolute best approach.
- if keyChar == "" &&
+ if not keyChar &&
(currentCompletionKeys.indexOf(KeyboardUtils.getKeyChar(event)) != -1 ||
isValidFirstKey(KeyboardUtils.getKeyChar(event)))
DomUtils.suppressPropagation(event)
diff --git a/lib/keyboard_utils.coffee b/lib/keyboard_utils.coffee
index f123f75a..10b5f46e 100644
--- a/lib/keyboard_utils.coffee
+++ b/lib/keyboard_utils.coffee
@@ -66,6 +66,34 @@ KeyboardUtils =
@getKeyChar event
keyChar.length == 1
+ # Return the Vimium key representation for this keyboard event. Return a falsy value (the empty string or
+ # undefined) when no Vimium representation is appropriate.
+ getKeyCharString: (event) ->
+ switch event.type
+ when "keypress"
+ # Ignore modifier keys by themselves.
+ if 31 < event.keyCode
+ String.fromCharCode event.charCode
+
+ when "keydown"
+ # handle special keys, and normal input keys with modifiers being pressed. don't handle shiftKey alone (to
+ # avoid / being interpreted as ?
+ if (((event.metaKey || event.ctrlKey || event.altKey) && event.keyCode > 31) || (
+ # TODO(philc): some events don't have a keyidentifier. How is that possible?
+ event.keyIdentifier && event.keyIdentifier.slice(0, 2) != "U+"))
+ keyChar = @getKeyChar event
+ # Again, ignore just modifiers. Maybe this should replace the keyCode>31 condition.
+ if 0 < keyChar.length
+ modifiers = []
+
+ keyChar = keyChar.toUpperCase() if event.shiftKey
+ modifiers.push "m" if event.metaKey
+ modifiers.push "c" if event.ctrlKey
+ modifiers.push "a" if event.altKey
+
+ keyChar = [modifiers..., keyChar].join "-"
+ if 1 < keyChar.length then "<#{keyChar}>" else keyChar
+
KeyboardUtils.init()
root = exports ? window
diff --git a/lib/settings.coffee b/lib/settings.coffee
index 31aad7ad..79ee04a9 100644
--- a/lib/settings.coffee
+++ b/lib/settings.coffee
@@ -174,6 +174,7 @@ Settings =
settingsVersion: Utils.getCurrentVersion()
helpDialog_showAdvancedCommands: false
optionsPage_showAdvancedOptions: false
+ passNextKeyKeys: []
Settings.init()