aboutsummaryrefslogtreecommitdiffstats
path: root/content_scripts
diff options
context:
space:
mode:
authorStephen Blott2017-11-30 10:39:15 +0000
committerStephen Blott2017-11-30 10:39:15 +0000
commitcbc3d21046f35c05bd3138cb0b8ac1309c718fe6 (patch)
tree1658df541fd5567d5245b34abf0dcaf45420d421 /content_scripts
parent971d067f99ddc09b9ca388c2cffeadd32302c35a (diff)
downloadvimium-cbc3d21046f35c05bd3138cb0b8ac1309c718fe6.tar.bz2
Rework insert mode (check status dynamically).
This removes @insertModeLock and instead always checks whether we are in insert mode dynamically (as we previously did only for contentEditable). @mrmr1993... Would you be able to check this, please? It is intended to be mostly a no-op. Fixes #2841.
Diffstat (limited to 'content_scripts')
-rw-r--r--content_scripts/mode_insert.coffee87
1 files changed, 18 insertions, 69 deletions
diff --git a/content_scripts/mode_insert.coffee b/content_scripts/mode_insert.coffee
index d2a33091..3b6edf1e 100644
--- a/content_scripts/mode_insert.coffee
+++ b/content_scripts/mode_insert.coffee
@@ -10,23 +10,23 @@ class InsertMode extends Mode
handleKeyEvent = (event) =>
return @continueBubbling unless @isActive event
- return @passEventToPage if @insertModeLock is document.body
+
+ # See comment here: https://github.com/philc/vimium/commit/48c169bd5a61685bb4e67b1e76c939dbf360a658.
+ activeElement = @getActiveElement()
+ return @passEventToPage if activeElement == document.body and activeElement.isContentEditable
# Check for a pass-next-key key.
if KeyboardUtils.getKeyCharString(event) in Settings.get "passNextKeyKeys"
new PassNextKeyMode
- return @suppressEvent
-
- return @passEventToPage unless event.type == 'keydown' and KeyboardUtils.isEscape event
- target = event.target
- 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.
- target.blur()
- else if target?.shadowRoot and @insertModeLock
- # An editable element in a shadow DOM is focused; blur it.
- @insertModeLock.blur()
- @exit event, event.target
- @suppressEvent
+
+ else if event.type == 'keydown' and KeyboardUtils.isEscape(event)
+ activeElement.blur() if DomUtils.isFocusable activeElement
+ @exit() unless @permanent
+
+ else
+ return @passEventToPage
+
+ return @suppressEvent
defaults =
name: "insert"
@@ -36,67 +36,16 @@ class InsertMode extends Mode
super extend defaults, options
- @insertModeLock =
- if options.targetElement and DomUtils.isEditable options.targetElement
- # The caller has told us which element to activate on.
- options.targetElement
- else if document.activeElement and DomUtils.isEditable document.activeElement
- # An input element is already active, so use it.
- document.activeElement
- else
- null
-
- @push
- _name: "mode-#{@id}-focus"
- "blur": (event) => @alwaysContinueBubbling =>
- target = event.target
- # We can't rely on focus and blur events arriving in the expected order. When the active element
- # changes, we might get "focus" before "blur". We track the active element in @insertModeLock, and
- # exit only when that element blurs.
- @exit event, target if @insertModeLock and target == @insertModeLock
- "focus": (event) => @alwaysContinueBubbling =>
- if @insertModeLock != event.target and DomUtils.isFocusable event.target
- @activateOnElement event.target
- else if event.target.shadowRoot
- # A focusable element inside the shadow DOM might have been selected. If so, we can catch the focus
- # event inside the shadow DOM. This fixes #853.
- shadowRoot = event.target.shadowRoot
- eventListeners = {}
- for type in [ "focus", "blur" ]
- eventListeners[type] = do (type) ->
- forTrusted (event) -> handlerStack.bubbleEvent type, event
- shadowRoot.addEventListener type, eventListeners[type], true
-
- handlerStack.push
- _name: "shadow-DOM-input-mode"
- blur: (event) ->
- if event.target.shadowRoot == shadowRoot
- handlerStack.remove()
- for own type, listener of eventListeners
- shadowRoot.removeEventListener type, listener, true
-
# Only for tests. This gives us a hook to test the status of the permanently-installed instance.
InsertMode.permanentInstance = this if @permanent
isActive: (event) ->
return false if event == InsertMode.suppressedEvent
- return true if @insertModeLock or @global
- # Some sites (e.g. inbox.google.com) change the contentEditable property on the fly (see #1245); and
- # unfortunately, the focus event fires *before* the change. Therefore, we need to re-check whether the
- # active element is contentEditable.
- @activateOnElement document.activeElement if document.activeElement?.isContentEditable
- @insertModeLock != null
-
- activateOnElement: (element) ->
- @log "#{@id}: activating (permanent)" if @debug and @permanent
- @insertModeLock = element
-
- exit: (_, target) ->
- if (target and target == @insertModeLock) or @global or target == undefined
- @log "#{@id}: deactivating (permanent)" if @debug and @permanent and @insertModeLock
- @insertModeLock = null
- # Exit, but only if this isn't the permanently-installed instance.
- super() unless @permanent
+ return true if @global
+ DomUtils.isFocusable @getActiveElement()
+
+ getActiveElement: ->
+ document.activeElement?.shadowRoot?.activeElement ? document.activeElement
# Static stuff. This allows PostFindMode to suppress the permanently-installed InsertMode instance.
@suppressedEvent: null