diff options
| -rw-r--r-- | content_scripts/mode.coffee | 9 | ||||
| -rw-r--r-- | content_scripts/mode_find.coffee | 78 | ||||
| -rw-r--r-- | content_scripts/vimium_frontend.coffee | 15 |
3 files changed, 39 insertions, 63 deletions
diff --git a/content_scripts/mode.coffee b/content_scripts/mode.coffee index 9f820469..cc1250b4 100644 --- a/content_scripts/mode.coffee +++ b/content_scripts/mode.coffee @@ -177,14 +177,6 @@ class Mode @top: -> @modes[@modes.length-1] -# InputController is a super-class for modes which control insert mode: PostFindMode and FocusSelector. It's -# a singleton, so no two instances may be active at the same time. -class InputController extends Mode - constructor: (options) -> - defaults = - singleton: InputController - super extend defaults, options - # BadgeMode is a pseudo mode for triggering badge updates on focus changes and state updates. It sits at the # bottom of the handler stack, and so it receives state changes *after* all other modes, and can override the # badge choice of the other modes. We create the the one-and-only instance here. @@ -212,4 +204,3 @@ new class BadgeMode extends Mode root = exports ? window root.Mode = Mode -root.InputController = InputController diff --git a/content_scripts/mode_find.coffee b/content_scripts/mode_find.coffee index f151b8cd..cfcd18b5 100644 --- a/content_scripts/mode_find.coffee +++ b/content_scripts/mode_find.coffee @@ -1,45 +1,42 @@ # NOTE(smblott). Ultimately, all of the FindMode-related code should be moved to this file. +# This is Used as a sub-class to PostFindMode. It prevents printable characters from being passed through to +# underlying input element; see #1415. Note, also, that the "Range" condition in the keyup handler +# implmements option 5c from #1415. +class SuppressPrintable extends Mode + constructor: (options) -> + super options + handler = (event) => if KeyboardUtils.isPrintable event then @suppressEvent else @continueBubbling + + # Note: we use unshift here. We see events *after* normal mode, so we only see unmapped keys. + @unshift + _name: "mode-#{@id}/suppressPrintableEvents" + keydown: handler + keypress: handler + keyup: (event) => + if document.getSelection().type.toLowerCase() != "range" then @exit() else handler event + # When we use find mode, the selection/focus can land in a focusable/editable element. In this situation, # special considerations apply. We implement three special cases: -# 1. Disable keyboard events in insert mode, because the user hasn't asked to enter insert mode. -# 2. Prevent printable keyboard events from propagating to the page; see #1415. +# 1. Disable insert mode, because the user hasn't asked to enter insert mode. We do this by using +# InsertMode.suppressEvent. +# 2. Prevent printable keyboard events from propagating to the page; see #1415. We do this by inheriting +# from SuppressPrintable. # 3. If the very-next keystroke is Escape, then drop immediately into insert mode. # -class PostFindMode extends InputController +class PostFindMode extends SuppressPrintable constructor: (findModeAnchorNode) -> - # Locate the element we need to protect. In most cases, it's just the active element. - element = - if document.activeElement and DomUtils.isEditable document.activeElement - document.activeElement - else - # For contentEditable elements, chrome does not focus them, although they are activated by keystrokes. - # We need to find the element ourselves. - element = findModeAnchorNode - element = element.parentElement while element.parentElement?.isContentEditable - if element.isContentEditable - if DomUtils.isDOMDescendant element, findModeAnchorNode - # TODO(smblott). We shouldn't really need to focus the element, here. Need to look into why this - # is necessary. - element.focus() - element - - return unless element + element = document.activeElement + return unless element and DomUtils.isEditable element super name: "post-find" + singleton: PostFindMode exitOnBlur: element exitOnClick: true - keydown: (event) -> InsertMode.suppressEvent event # Truthy. - keypress: (event) -> InsertMode.suppressEvent event # Truthy. - keyup: (event) => - @alwaysContinueBubbling => - if document.getSelection().type != "Range" - # If the selection is no longer a range, then the user is interacting with the element, so get out - # of the way. See Option 5c from #1415. - @exit() - else - InsertMode.suppressEvent event + keydown: (event) -> InsertMode.suppressEvent event # Always truthy, so always continues bubbling. + keypress: (event) -> InsertMode.suppressEvent event + keyup: (event) -> InsertMode.suppressEvent event # If the very-next keydown is Esc, drop immediately into insert mode. self = @ @@ -54,25 +51,8 @@ class PostFindMode extends InputController @remove() true # Continue bubbling. - # Prevent printable keyboard events from propagating to the page; see #1415. - do => - handler = (event) => - if event.srcElement == element and KeyboardUtils.isPrintable event - @suppressEvent - else - @continueBubbling - - # 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" - keydown: handler - keypress: handler - keyup: handler - - chooseBadge: (badge) -> - # If PostFindMode is active, then we don't want the "I" badge from insert mode. - InsertMode.suppressEvent badge + # If PostFindMode is active, then we suppress the "I" badge from insert mode. + chooseBadge: (badge) -> InsertMode.suppressEvent badge root = exports ? window root.PostFindMode = PostFindMode diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 7d24e714..3049784e 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -364,11 +364,14 @@ extend window, id: "vimiumInputMarkerContainer" className: "vimiumReset" - new class FocusSelector extends InputController + new class FocusSelector extends Mode constructor: -> super name: "focus-selector" badge: "?" + # We share a singleton with PostFindMode. That way, a new FocusSelector displaces any existing + # PostFindMode. + singleton: PostFindMode exitOnClick: true keydown: (event) => if event.keyCode == KeyboardUtils.keyCodes.tab @@ -805,10 +808,12 @@ executeFind = (query, options) -> # preventDefault() findModeAnchorNode = document.getSelection().anchorNode - # If the anchor node is outside of the active element, then blur the active element. We don't want to leave - # behind an inappropriate active element. This fixes #1412. - if document.activeElement and not DomUtils.isDOMDescendant findModeAnchorNode, document.activeElement - document.activeElement.blur() + # TODO(smblott). Disabled. This is the wrong test. Should be reinstated when we have the right test, which + # looks like it should be "isSelected" from #1431. + # # If the anchor node not a descendent of the active element, then blur the active element. We don't want to + # # leave behind an inappropriate active element. This fixes #1412. + # if document.activeElement and not DomUtils.isDOMDescendant document.activeElement, findModeAnchorNode + # document.activeElement.blur() result |
