aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--background_scripts/main.coffee2
-rw-r--r--content_scripts/mode.coffee16
-rw-r--r--content_scripts/mode_passkeys.coffee11
-rw-r--r--content_scripts/vimium_frontend.coffee54
-rw-r--r--lib/handler_stack.coffee10
5 files changed, 71 insertions, 22 deletions
diff --git a/background_scripts/main.coffee b/background_scripts/main.coffee
index 8d36de95..fc0a792f 100644
--- a/background_scripts/main.coffee
+++ b/background_scripts/main.coffee
@@ -352,7 +352,7 @@ setBadge = (request) ->
root.updateActiveState = updateActiveState = (tabId) ->
enabledIcon = "icons/browser_action_enabled.png"
disabledIcon = "icons/browser_action_disabled.png"
- partialIcon = enabledIcon # Let's try diabling that while we're playing with badges... "icons/browser_action_partial.png"
+ partialIcon = "icons/browser_action_partial.png"
chrome.tabs.get tabId, (tab) ->
chrome.tabs.sendMessage tabId, { name: "getActiveState" }, (response) ->
if response
diff --git a/content_scripts/mode.coffee b/content_scripts/mode.coffee
index 7ca818b4..a2a8b8b0 100644
--- a/content_scripts/mode.coffee
+++ b/content_scripts/mode.coffee
@@ -9,11 +9,11 @@ class Mode
@propagate = true
# Default values.
- name: "" # The name of this mode.
- badge: "" # A badge to display on the popup when this mode is active.
- keydown: "suppress" # A function, or "suppress" or "pass"; the latter are replaced with suitable functions.
- keypress: "suppress" # A function, or "suppress" or "pass"; the latter are replaced with suitable functions.
- keyup: "suppress" # A function, or "suppress" or "pass"; the latter are replaced with suitable functions.
+ name: "" # The name of this mode.
+ badge: "" # A badge to display on the popup when this mode is active.
+ keydown: "pass" # A function, or "suppress" or "pass"; the latter are replaced with suitable handlers.
+ keypress: "pass" # A function, or "suppress" or "pass"; the latter are replaced with suitable handlers.
+ keyup: "pass" # A function, or "suppress" or "pass"; the latter are replaced with suitable handlers.
constructor: (options) ->
extend @, options
@@ -73,5 +73,11 @@ class Mode
@sendBadge: (badge) ->
chrome.runtime.sendMessage({ handler: "setBadge", badge: badge })
+ # Install a mode, call a function, and exit the mode again.
+ @runIn: (mode, func) ->
+ mode = new mode()
+ func()
+ mode.exit()
+
root = exports ? window
root.Mode = Mode
diff --git a/content_scripts/mode_passkeys.coffee b/content_scripts/mode_passkeys.coffee
index a953deca..9e922104 100644
--- a/content_scripts/mode_passkeys.coffee
+++ b/content_scripts/mode_passkeys.coffee
@@ -7,9 +7,6 @@ class PassKeysMode extends Mode
# 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.
isPassKey: (keyChar) ->
- # FIXME(smblott). Temporary hack: attach findMode to the window (so passKeysMode can see it). This will be
- # fixed when find mode is rationalized or #1401 is merged.
- return false if window.findMode
not @keyQueue and 0 <= @passKeys.indexOf(keyChar)
handlePassKeyEvent: (event) ->
@@ -24,12 +21,12 @@ class PassKeysMode extends Mode
setState: (request) ->
if request.isEnabledForUrl?
@passKeys = (request.isEnabledForUrl and request.passKeys) or ""
+ Mode.updateBadge()
if request.enabled?
@passKeys = (request.enabled and request.passKeys) or ""
+ Mode.updateBadge()
if request.keyQueue?
@keyQueue = request.keyQueue
- @badge = if @passKeys and not @keyQueue then "P" else ""
- Mode.updateBadge()
constructor: ->
super
@@ -38,5 +35,9 @@ class PassKeysMode extends Mode
keypress: (event) => @handlePassKeyEvent event
keyup: -> Mode.propagate
+ updateBadgeForMode: (badge) ->
+ @badge = if @passKeys and not @keyQueue then "P" else ""
+ super badge
+
root = exports ? window
root.PassKeysMode = PassKeysMode
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index 2df2e226..c0f98d85 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -8,9 +8,7 @@
insertMode = null
passKeysMode = null
insertModeLock = null
-# FIXME(smblott). Temporary hack: attach findMode to the window (so passKeysMode can see it). This will be
-# fixed when find mode is rationalized or #1401 is merged.
-window.findMode = false
+findMode = false
findModeQuery = { rawQuery: "", matchCount: 0 }
findModeQueryHasResults = false
findModeAnchorNode = null
@@ -729,6 +727,42 @@ handleEnterForFindMode = ->
document.body.classList.add("vimiumFindMode")
settings.set("findModeRawQuery", findModeQuery.rawQuery)
+class FindMode extends Mode
+ constructor: ->
+ super
+ name: "find"
+ badge: "F"
+
+ keydown: (event) =>
+ if KeyboardUtils.isEscape event
+ handleEscapeForFindMode()
+ @exit()
+ Mode.suppressPropagation
+ else if (event.keyCode == keyCodes.backspace || event.keyCode == keyCodes.deleteKey)
+ handleDeleteForFindMode()
+ Mode.suppressPropagation
+ else if (event.keyCode == keyCodes.enter)
+ handleEnterForFindMode()
+ @exit()
+ Mode.suppressPropagation
+ else
+ DomUtils.suppressPropagation(event)
+ handlerStack.eventConsumed
+
+ keypress: (event) ->
+ handlerStack.neverPropagate ->
+ if event.keyCode > 31
+ keyChar = String.fromCharCode event.charCode
+ handleKeyCharForFindMode keyChar if keyChar
+
+ keyup: (event) -> handlerStack.neverPropagate -> false
+
+ # Prevent insert mode from detecting a focused editable element.
+ @handlers.push handlerStack.push
+ focus: (event) -> handlerStack.neverPropagate (event) ->
+
+ Mode.updateBadge()
+
performFindInPlace = ->
cachedScrollX = window.scrollX
cachedScrollY = window.scrollY
@@ -747,25 +781,21 @@ performFindInPlace = ->
# :options is an optional dict. valid parameters are 'caseSensitive' and 'backwards'.
executeFind = (query, options) ->
+ result = null
options = options || {}
- # rather hacky, but this is our way of signalling to the insertMode listener not to react to the focus
- # changes that find() induces.
- oldFindMode = findMode
- window.findMode = true # Same hack, see comment at window.findMode definition.
-
document.body.classList.add("vimiumFindMode")
# prevent find from matching its own search query in the HUD
HUD.hide(true)
# ignore the selectionchange event generated by find()
document.removeEventListener("selectionchange",restoreDefaultSelectionHighlight, true)
- result = window.find(query, options.caseSensitive, options.backwards, true, false, true, false)
+ Mode.runIn FindMode, ->
+ result = window.find(query, options.caseSensitive, options.backwards, true, false, true, false)
setTimeout(
-> document.addEventListener("selectionchange", restoreDefaultSelectionHighlight, true)
0)
- window.findMode = oldFindMode # Same hack, see comment at window.findMode definition.
# we need to save the anchor node here because <esc> seems to nullify it, regardless of whether we do
# preventDefault()
findModeAnchorNode = document.getSelection().anchorNode
@@ -839,6 +869,7 @@ findAndFocus = (backwards) ->
if (KeyboardUtils.isEscape(event))
DomUtils.simulateSelect(document.activeElement)
enterInsertModeWithoutShowingIndicator(document.activeElement)
+ insertMode.activate()
return false # we have "consumed" this event, so do not propagate
return true
})
@@ -958,8 +989,9 @@ showFindModeHUDForQuery = ->
window.enterFindMode = ->
findModeQuery = { rawQuery: "" }
- window.findMode = true # Same hack, see comment at window.findMode definition.
+ # window.findMode = true # Same hack, see comment at window.findMode definition.
HUD.show("/")
+ new FindMode()
exitFindMode = ->
window.findMode = false # Same hack, see comment at window.findMode definition.
diff --git a/lib/handler_stack.coffee b/lib/handler_stack.coffee
index f56683f1..764461e7 100644
--- a/lib/handler_stack.coffee
+++ b/lib/handler_stack.coffee
@@ -6,6 +6,7 @@ class HandlerStack
@stack = []
@counter = 0
@passDirectlyToPage = new Object() # Used only as a constant, distinct from any other value.
+ @eventConsumed = new Object() # Used only as a constant, distinct from any other value.
genId: -> @counter = ++@counter
@@ -32,6 +33,10 @@ class HandlerStack
# event through to the underlying page. The event is not suppresssed.
if passThrough == @passDirectlyToPage
return false
+ # If the constant @eventConsumed is returned, then discontinue further bubbling and
+ # return false.
+ if passThrough == @eventConsumed
+ return false
true
remove: (id = @currentId) ->
@@ -51,5 +56,10 @@ class HandlerStack
handler()
true
+ # Convenience wrapper for handlers which never continue propagation.
+ neverPropagate: (handler) ->
+ handler()
+ false
+
root.HandlerStack = HandlerStack
root.handlerStack = new HandlerStack