aboutsummaryrefslogtreecommitdiffstats
path: root/content_scripts/mode_insert.coffee
diff options
context:
space:
mode:
authorStephen Blott2015-01-10 15:05:58 +0000
committerStephen Blott2015-01-10 15:05:58 +0000
commitc554d1fd5b6d81506864516b6f86a14f8672bec5 (patch)
tree5e2d15e17a0344a0882cd57dda1d4d2665a1b9f1 /content_scripts/mode_insert.coffee
parent35cb54fec7242fac5c68503a32ef9dd4fea5d9b6 (diff)
downloadvimium-c554d1fd5b6d81506864516b6f86a14f8672bec5.tar.bz2
Modes; reinstate key blockers:
- when the selection is contentEditable - in PostFindMode Restricted to printable characters.
Diffstat (limited to 'content_scripts/mode_insert.coffee')
-rw-r--r--content_scripts/mode_insert.coffee28
1 files changed, 28 insertions, 0 deletions
diff --git a/content_scripts/mode_insert.coffee b/content_scripts/mode_insert.coffee
index 5720c901..b907f22e 100644
--- a/content_scripts/mode_insert.coffee
+++ b/content_scripts/mode_insert.coffee
@@ -96,6 +96,34 @@ class InsertModeBlocker extends Mode
new @options.onClickMode
targetElement: document.activeElement
+# There's an unfortunate feature interaction between chrome's contentEditable handling and our insert mode.
+# If the selection is contentEditable and a descendant of the active element, then chrome focuses it on any
+# unsuppressed printable keypress. This drops us unintentally into insert mode. See #1415. A single
+# instance of this mode sits near the bottom of the handler stack and suppresses each keypress event if:
+# - it hasn't been handled by any other mode (so not by normal mode, passkeys, insert, ...),
+# - it represents a printable character,
+# - the selection is content editable, and
+# - the selection is a descendant of the active element.
+# This should rarely fire, typically only on fudged keypresses in normal mode. And, even then, only in the
+# circumstances outlined above. So, we shouldn't usually be blocking keyboard events for other extensions or
+# the page itself.
+# There's some controversy as to whether this is the right thing to do. See discussion in #1415. This
+# implements Option 2 from there.
+new class ContentEditableTrap extends Mode
+ constructor: ->
+ super
+ name: "content-editable-trap"
+ keypress: (event) =>
+ if @wouldTriggerInsert event then @suppressEvent else @continueBubbling
+
+ # True if the selection is content editable and a descendant of the active element.
+ wouldTriggerInsert: (event) ->
+ element = document.getSelection()?.anchorNode?.parentElement
+ return element?.isContentEditable and
+ document.activeElement and
+ DomUtils. isPrintable event and
+ DomUtils.isDOMDescendant document.activeElement, element
+
root = exports ? window
root.InsertMode = InsertMode
root.InsertModeTrigger = InsertModeTrigger