aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Blott2016-12-21 05:09:42 +0000
committerGitHub2016-12-21 05:09:42 +0000
commit320f433afb53cc774b175dab0f6a1ad7a47d60f9 (patch)
tree2bb28d6c6afc7ceeb7f463c6aff23d201b43587b
parentcaa63d6642141d2fe4cd6941ec1e84dd2d3e8225 (diff)
parentedfb7ba3ca148f7b00bd683d1979330f395f2e7e (diff)
downloadvimium-320f433afb53cc774b175dab0f6a1ad7a47d60f9.tar.bz2
Merge pull request #2311 from smblott-github/enterNormalMode
New command option to enter normal mode
-rw-r--r--content_scripts/mode.coffee3
-rw-r--r--content_scripts/mode_find.coffee3
-rw-r--r--content_scripts/mode_insert.coffee3
-rw-r--r--content_scripts/mode_key_handler.coffee18
-rw-r--r--content_scripts/scroller.coffee18
-rw-r--r--content_scripts/vimium_frontend.coffee27
-rw-r--r--lib/dom_utils.coffee1
7 files changed, 53 insertions, 20 deletions
diff --git a/content_scripts/mode.coffee b/content_scripts/mode.coffee
index 6508627e..c1dea59a 100644
--- a/content_scripts/mode.coffee
+++ b/content_scripts/mode.coffee
@@ -81,9 +81,8 @@ class Mode
_name: "mode-#{@id}/exitOnEscape"
"keydown": (event) =>
return @continueBubbling unless KeyboardUtils.isEscape event
- DomUtils.suppressKeyupAfterEscape handlerStack
@exit event, event.srcElement
- @suppressEvent
+ DomUtils.suppressKeyupAfterEscape handlerStack
# If @options.exitOnBlur is truthy, then it should be an element. The mode will exit when that element
# loses the focus.
diff --git a/content_scripts/mode_find.coffee b/content_scripts/mode_find.coffee
index 8621edf8..0178527b 100644
--- a/content_scripts/mode_find.coffee
+++ b/content_scripts/mode_find.coffee
@@ -47,9 +47,8 @@ class PostFindMode extends SuppressPrintable
_name: "mode-#{@id}/handle-escape"
keydown: (event) =>
if KeyboardUtils.isEscape event
- DomUtils.suppressKeyupAfterEscape handlerStack
@exit()
- @suppressEvent
+ DomUtils.suppressKeyupAfterEscape handlerStack
else
handlerStack.remove()
@continueBubbling
diff --git a/content_scripts/mode_insert.coffee b/content_scripts/mode_insert.coffee
index 4cb0a39e..d5d98297 100644
--- a/content_scripts/mode_insert.coffee
+++ b/content_scripts/mode_insert.coffee
@@ -17,7 +17,6 @@ class InsertMode extends Mode
return @suppressEvent
return @passEventToPage unless event.type == 'keydown' and KeyboardUtils.isEscape event
- DomUtils.suppressKeyupAfterEscape handlerStack
target = event.srcElement
if target and DomUtils.isFocusable target
# Remove the focus, so the user can't just get back into insert mode by typing in the same input box.
@@ -26,7 +25,7 @@ class InsertMode extends Mode
# An editable element in a shadow DOM is focused; blur it.
@insertModeLock.blur()
@exit event, event.srcElement
- @suppressEvent
+ DomUtils.suppressKeyupAfterEscape handlerStack
defaults =
name: "insert"
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
diff --git a/content_scripts/scroller.coffee b/content_scripts/scroller.coffee
index 3a1b3772..a533c161 100644
--- a/content_scripts/scroller.coffee
+++ b/content_scripts/scroller.coffee
@@ -128,13 +128,15 @@ checkVisibility = (element) ->
CoreScroller =
init: ->
@time = 0
- @lastEvent = null
- @keyIsDown = false
+ @lastEvent = @keyIsDown = @cancelEventListenerId = null
+ # This installs listeners for events which should cancel smooth scrolling.
+ installCanceEventListener: ->
+ @removeCancelEventListener()
# NOTE(smblott) With extreme keyboard configurations, Chrome sometimes does not get a keyup event for
# every keydown, in which case tapping "j" scrolls indefinitely. This appears to be a Chrome/OS/XOrg bug
# of some kind. See #1549.
- handlerStack.push
+ @cancelEventListenerId = handlerStack.push
_name: 'scroller/track-key-status'
keydown: (event) =>
handlerStack.alwaysContinueBubbling =>
@@ -149,6 +151,10 @@ CoreScroller =
handlerStack.alwaysContinueBubbling =>
@time += 1 if event.target == window
+ removeCancelEventListener: ->
+ handlerStack.remove @cancelEventListenerId if @cancelEventListenerId?
+ @cancelEventListenerId = @lastEvent = @keyIsDown = null
+
# Return true if CoreScroller would not initiate a new scroll right now.
wouldNotInitiateScroll: -> @lastEvent?.repeat and Settings.get "smoothScroll"
@@ -175,7 +181,7 @@ CoreScroller =
return if @lastEvent?.repeat
activationTime = ++@time
- myKeyIsStillDown = => @time == activationTime and @keyIsDown
+ myKeyIsStillDown = => @time == activationTime and @keyIsDown ? true
# Store amount's sign and make amount positive; the arithmetic is clearer when amount is positive.
sign = getSign amount
@@ -215,13 +221,15 @@ CoreScroller =
requestAnimationFrame animate
else
# We're done.
+ @removeCancelEventListener()
checkVisibility element
# If we've been asked not to be continuous, then we advance time, so the myKeyIsStillDown test always
# fails.
++@time unless continuous
- # Launch animator.
+ # Start scrolling.
+ @installCanceEventListener()
requestAnimationFrame animate
# Scroller contains the two main scroll functions which are used by clients.
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index 21826944..6447092b 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -111,11 +111,13 @@ handlerStack.push
class NormalMode extends KeyHandlerMode
constructor: (options = {}) ->
- super extend options,
+ defaults =
name: "normal"
- indicator: false # There is no mode indicator in normal mode.
+ indicator: false # There is normally no mode indicator in normal mode.
commandHandler: @commandHandler.bind this
+ super extend defaults, options
+
chrome.storage.local.get "normalModeKeyStateMapping", (items) =>
@setKeyMapping items.normalModeKeyStateMapping
@@ -123,10 +125,6 @@ class NormalMode extends KeyHandlerMode
if area == "local" and changes.normalModeKeyStateMapping?.newValue
@setKeyMapping changes.normalModeKeyStateMapping.newValue
- # Initialize components which normal mode depends upon.
- Scroller.init()
- FindModeHistory.init()
-
commandHandler: ({command: registryEntry, count}) ->
count *= registryEntry.options.count ? 1
count = 1 if registryEntry.noRepeat
@@ -150,6 +148,9 @@ installModes = ->
# Install the permanent modes. The permanently-installed insert mode tracks focus/blur events, and
# activates/deactivates itself accordingly.
normalMode = new NormalMode
+ # Initialize components upon which normal mode depends.
+ Scroller.init()
+ FindModeHistory.init()
new InsertMode permanent: true
new GrabBackFocus if isEnabledForUrl
normalMode # Return the normalMode object (for the tests).
@@ -383,8 +384,18 @@ extend window,
enterVisualLineMode: ->
new VisualLineMode userLaunchedMode: true
- passNextKey: (count) ->
- new PassNextKeyMode count
+ passNextKey: (count, options) ->
+ if options.registryEntry.options.normal
+ enterNormalMode count
+ else
+ new PassNextKeyMode count
+
+ enterNormalMode: (count) ->
+ new NormalMode
+ indicator: "Normal mode (pass keys disabled)"
+ exitOnEscape: true
+ singleton: "enterNormalMode"
+ count: count
focusInput: do ->
# Track the most recently focused input element.
diff --git a/lib/dom_utils.coffee b/lib/dom_utils.coffee
index 82c13287..fad5ffbf 100644
--- a/lib/dom_utils.coffee
+++ b/lib/dom_utils.coffee
@@ -310,6 +310,7 @@ DomUtils =
return true unless KeyboardUtils.isEscape event
@remove()
false
+ handlerStack.suppressEvent
# Adapted from: http://roysharon.com/blog/37.
# This finds the element containing the selection focus.