aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--content_scripts/mode.coffee4
-rw-r--r--content_scripts/mode_find.coffee36
-rw-r--r--content_scripts/mode_insert.coffee13
-rw-r--r--content_scripts/vimium_frontend.coffee18
4 files changed, 36 insertions, 35 deletions
diff --git a/content_scripts/mode.coffee b/content_scripts/mode.coffee
index ebb3e8bc..2b35f0de 100644
--- a/content_scripts/mode.coffee
+++ b/content_scripts/mode.coffee
@@ -101,9 +101,7 @@ class Mode
if @options.exitOnClick
@push
_name: "mode-#{@id}/exitOnClick"
- "click": (event) => @alwaysContinueBubbling =>
- @clickEvent = event
- @exit()
+ "click": (event) => @alwaysContinueBubbling => @exit event
# If @options.trackState is truthy, then the mode mainatins the current state in @enabled and @passKeys,
# and calls @registerStateChange() (if defined) whenever the state changes.
diff --git a/content_scripts/mode_find.coffee b/content_scripts/mode_find.coffee
index 08bc9e5d..4906d363 100644
--- a/content_scripts/mode_find.coffee
+++ b/content_scripts/mode_find.coffee
@@ -9,18 +9,28 @@
#
class PostFindMode extends Mode
constructor: (findModeAnchorNode) ->
- element = document.activeElement
+ # Locate the element we need to protect and focus it. Usually, we can just rely on insert mode to have
+ # picked it up (when it received the focus).
+ element = InsertMode.permanentInstance.insertModeLock
+ unless element?
+ # If insert mode hasn't picked up the element, then it could be content editable. As a heuristic, we
+ # start at findModeAnchorNode and walk up the DOM, stopping at the last node encountered which is
+ # contentEditable. If that node is a descendent of the active element, then we use it.
+ element = findModeAnchorNode
+ element = element.parentElement while element?.parentElement?.isContentEditable
+ return unless element?.isContentEditable
+ return unless document.activeElement and DomUtils.isDOMDescendant document.activeElement, element
+ element.focus()
super
name: "post-find"
badge: "N" # Pretend to be normal mode (because we don't want the insert-mode badge).
- # Be a singleton. That way, we don't have to keep track of any currently-active instance. Any active
- # instance is automatically deactivated when a new instance is activated.
+ # Be a singleton. That way, we don't have to keep track of any currently-active instance.
singleton: PostFindMode
exitOnBlur: element
exitOnClick: true
- keydown: (event) -> InsertMode.suppressEvent event
- keypress: (event) -> InsertMode.suppressEvent event
+ keydown: (event) -> InsertMode.suppressEvent event # Truthy.
+ keypress: (event) -> InsertMode.suppressEvent event # Truthy.
keyup: (event) =>
@alwaysContinueBubbling =>
if document.getSelection().type != "Range"
@@ -30,15 +40,6 @@ class PostFindMode extends Mode
else
InsertMode.suppressEvent event
- return @exit() unless element and findModeAnchorNode
-
- # Special considerations only arise if the active element can take input. So, exit immediately if it
- # cannot.
- canTakeInput = DomUtils.isSelectable(element) and DomUtils.isDOMDescendant findModeAnchorNode, element
- canTakeInput ||= element.isContentEditable
- canTakeInput ||= findModeAnchorNode.parentElement?.isContentEditable # FIXME(smblott) This is too specific.
- return @exit() unless canTakeInput
-
# If the very-next keydown is Esc, drop immediately into insert mode.
self = @
@push
@@ -60,7 +61,7 @@ class PostFindMode extends Mode
else
@continueBubbling
- # Note. We use unshift here, instead of push; therefore we see events *after* normal mode, and so only
+ # Note. We use unshift here, instead of push. We see events *after* normal mode, so we only see
# unmapped keys.
@unshift
_name: "mode-#{@id}/suppressPrintableEvents"
@@ -68,5 +69,10 @@ class PostFindMode extends Mode
keypress: handler
keyup: handler
+# NOTE. There's a problem with this approach when a find/search lands in a contentEditable element. Chrome
+# generates a focus event triggering insert mode (good), then immediately generates a "blur" event, disabling
+# insert mode again. Nevertheless, unmapped keys *do* result in the element being focused again.
+# So, asking insert mode whether it's active is giving us the wrong answer.
+
root = exports ? window
root.PostFindMode = PostFindMode
diff --git a/content_scripts/mode_insert.coffee b/content_scripts/mode_insert.coffee
index 4be9c589..89077c6a 100644
--- a/content_scripts/mode_insert.coffee
+++ b/content_scripts/mode_insert.coffee
@@ -1,6 +1,11 @@
class InsertMode extends Mode
+ # There is one permanently-installed instance of InsertMode. This allows PostFindMode to query its state.
+ @permanentInstance: null
+
constructor: (options = {}) ->
+ InsertMode.permanentInstance ||= @
+
defaults =
name: "insert"
keydown: (event) => @handleKeydownEvent event
@@ -51,12 +56,8 @@ class InsertMode extends Mode
exit: (target) ->
if target == undefined or target == @insertModeLock
- if @options.targetElement?
- super()
- else
- # If @options.targetElement isn't set, then this is the permanently-installed instance from the front
- # end. So, we don't actually exit; instead, we just reset ourselves.
- @insertModeLock = null
+ # If this is the permanently-installed instance, then we don't actually exit; instead, we just reset.
+ if @ == InsertMode.permanentInstance then @insertModeLock = null else super()
chooseBadge: (badge) ->
badge.badge ||= "I" if @isActive()
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index 00d90e81..e14813f7 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -389,7 +389,6 @@ extend window,
visibleInputs[selectedInputIndex].element.focus()
return @exit() if visibleInputs.length == 1
-
hints[selectedInputIndex].classList.add 'internalVimiumSelectedInputHint'
exit: ->
@@ -747,6 +746,7 @@ class FindMode extends Mode
name: "find"
badge: "/"
exitOnEscape: true
+ exitOnClick: true
keydown: (event) =>
if event.keyCode == keyCodes.backspace || event.keyCode == keyCodes.deleteKey
@@ -772,8 +772,8 @@ class FindMode extends Mode
super()
handleEscapeForFindMode() if event?.type == "keydown" and KeyboardUtils.isEscape event
handleEscapeForFindMode() if event?.type == "click"
- # If event?.type == "click", then the InsertModeBlocker super-class will be dropping us into insert mode.
- new PostFindMode findModeAnchorNode unless event?.type == "click"
+ if findModeQueryHasResults and event?.type != "click"
+ new PostFindMode findModeAnchorNode
performFindInPlace = ->
cachedScrollX = window.scrollX
@@ -863,15 +863,11 @@ findAndFocus = (backwards) ->
findModeQueryHasResults =
executeFind(query, { backwards: backwards, caseSensitive: !findModeQuery.ignoreCase })
- if (!findModeQueryHasResults)
+ if findModeQueryHasResults
+ focusFoundLink()
+ new PostFindMode findModeAnchorNode if findModeQueryHasResults
+ else
HUD.showForDuration("No matches for '" + findModeQuery.rawQuery + "'", 1000)
- return
-
- # if we have found an input element via 'n', pressing <esc> immediately afterwards sends us into insert
- # mode
- new PostFindMode findModeAnchorNode
-
- focusFoundLink()
window.performFind = -> findAndFocus()