diff options
Diffstat (limited to 'content_scripts')
| -rw-r--r-- | content_scripts/link_hints.coffee | 1 | ||||
| -rw-r--r-- | content_scripts/mode.coffee | 15 | ||||
| -rw-r--r-- | content_scripts/mode_find.coffee | 21 | ||||
| -rw-r--r-- | content_scripts/mode_insert.coffee | 38 | ||||
| -rw-r--r-- | content_scripts/vimium_frontend.coffee | 27 |
5 files changed, 52 insertions, 50 deletions
diff --git a/content_scripts/link_hints.coffee b/content_scripts/link_hints.coffee index 3c8240c0..5e41cbbb 100644 --- a/content_scripts/link_hints.coffee +++ b/content_scripts/link_hints.coffee @@ -10,7 +10,6 @@ # # The "name" property below is a short-form name to appear in the link-hints mode name. Debugging only. The # key appears in the mode's badge. -# NOTE(smblott) The use of keys in badges is experimental. It may prove too noisy. # OPEN_IN_CURRENT_TAB = { name: "curr-tab", key: "" } OPEN_IN_NEW_BG_TAB = { name: "bg-tab", key: "B" } diff --git a/content_scripts/mode.coffee b/content_scripts/mode.coffee index 2ff71ca8..a74acfed 100644 --- a/content_scripts/mode.coffee +++ b/content_scripts/mode.coffee @@ -24,8 +24,10 @@ # responds to "focus" events, then push an additional handler: # @push # "focus": (event) => .... -# Any such handlers are removed when the mode is deactivated. +# Such handlers are removed when the mode is deactivated. # +# The following events can be handled: +# keydown, keypress, keyup, click, focus and blur # Debug only. count = 0 @@ -85,8 +87,8 @@ class Mode "click": (event) => @alwaysContinueBubbling => @exit event # Some modes are singletons: there may be at most one instance active at any time. A mode is a singleton - # if @options.singleton is truthy. The value of @options.singleton should be the key the which is - # intended to be unique. New instances deactivate existing instances with the same key. + # if @options.singleton is truthy. The value of @options.singleton should be the key which is intended to + # be unique. New instances deactivate existing instances with the same key. if @options.singleton do => singletons = Mode.singletons ||= {} @@ -99,7 +101,7 @@ class Mode # 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. The mode also tracks the - # keyQueue in @keyQueue. + # current keyQueue in @keyQueue. if @options.trackState @enabled = false @passKeys = "" @@ -115,7 +117,7 @@ class Mode Mode.modes.push @ Mode.updateBadge() - @logStack() + @logModes() # End of Mode constructor. push: (handlers) -> @@ -124,7 +126,6 @@ class Mode unshift: (handlers) -> handlers._name ||= "mode-#{@id}" - handlers._name += "/unshifted" @handlers.push handlerStack.unshift handlers onExit: (handler) -> @@ -160,7 +161,7 @@ class Mode badge: badge.badge # Debugging routines. - logStack: -> + logModes: -> if @debug @log "active modes (top to bottom):" @log " ", mode.id for mode in Mode.modes[..].reverse() diff --git a/content_scripts/mode_find.coffee b/content_scripts/mode_find.coffee index 35352277..dff63949 100644 --- a/content_scripts/mode_find.coffee +++ b/content_scripts/mode_find.coffee @@ -33,6 +33,8 @@ class PostFindMode extends SuppressPrintable super name: "post-find" + # We show a "?" badge, but only while an Escape activates insert mode. + badge: "?" singleton: PostFindMode exitOnBlur: element exitOnClick: true @@ -42,20 +44,23 @@ class PostFindMode extends SuppressPrintable # If the very-next keydown is Escape, then exit immediately, thereby passing subsequent keys to the # underlying insert-mode instance. - self = @ @push _name: "mode-#{@id}/handle-escape" - keydown: (event) -> + keydown: (event) => if KeyboardUtils.isEscape event DomUtils.suppressKeyupAfterEscape handlerStack - self.exit() - false # Suppress event. + @exit() + @suppressEvent else - @remove() - true # Continue bubbling. + handlerStack.remove() + @badge = "" + Mode.updateBadge() + @continueBubbling - # If PostFindMode is active, then we suppress the "I" badge from insert mode. - updateBadge: (badge) -> InsertMode.suppressEvent badge # Always truthy. + updateBadge: (badge) -> + badge.badge ||= @badge + # Suppress the "I" badge from insert mode. + InsertMode.suppressEvent badge # Always truthy. root = exports ? window root.PostFindMode = PostFindMode diff --git a/content_scripts/mode_insert.coffee b/content_scripts/mode_insert.coffee index 123c72be..196f910b 100644 --- a/content_scripts/mode_insert.coffee +++ b/content_scripts/mode_insert.coffee @@ -11,11 +11,18 @@ class InsertMode extends Mode # If truthy, then we were activated by the user (with "i"). @global = options.global + handleKeyEvent = (event) => + return @continueBubbling unless @isActive event + return @stopBubblingAndTrue unless event.type == 'keydown' and KeyboardUtils.isEscape event + DomUtils.suppressKeyupAfterEscape handlerStack + @exit event, event.srcElement + @suppressEvent + defaults = name: "insert" - keydown: (event) => @handleKeydownEvent event - keypress: (event) => @handleKeyEvent event - keyup: (event) => @handleKeyEvent event + keypress: handleKeyEvent + keyup: handleKeyEvent + keydown: handleKeyEvent super extend defaults, options @@ -32,11 +39,10 @@ class InsertMode extends Mode # 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 target == @insertModeLock + @exit event, target if @insertModeLock and target == @insertModeLock "focus": (event) => @alwaysContinueBubbling => if @insertModeLock != event.target and DomUtils.isFocusable event.target - @insertModeLock = event.target - Mode.updateBadge() + @activateOnElement event.target isActive: (event) -> return false if event == InsertMode.suppressedEvent @@ -44,24 +50,18 @@ class InsertMode extends Mode # 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. - if @insertModeLock != document.activeElement and document.activeElement?.isContentEditable - @insertModeLock = document.activeElement - Mode.updateBadge() + @activateOnElement document.activeElement if document.activeElement?.isContentEditable @insertModeLock != null - handleKeydownEvent: (event) -> - return @continueBubbling unless @isActive event - return @stopBubblingAndTrue unless KeyboardUtils.isEscape event - DomUtils.suppressKeyupAfterEscape handlerStack - @exit event, event.srcElement - @suppressEvent - - # Handles keypress and keyup events. - handleKeyEvent: (event) -> - if @isActive event then @stopBubblingAndTrue else @continueBubbling + activateOnElement: (element) -> + @log "#{@id}: activating (permanent)" if @debug and @permanent + @insertModeLock = element + Mode.updateBadge() exit: (_, target) -> + # Note: target == undefined, here, is required only for tests. if (target and target == @insertModeLock) or @global or target == undefined + @log "#{@id}: deactivating (permanent)" if @debug and @permanent and @insertModeLock @insertModeLock = null 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. diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 0a034e28..6a26a133 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -117,10 +117,11 @@ initializePreDomReady = -> keypress: (event) => onKeypress.call @, event keyup: (event) => onKeyup.call @, event - # Install the permanent modes and handlers. The permanent insert mode operates only when focusable/editable - # elements are active. + Scroller.init settings + + # Install the permanent modes. The permanently-installed insert mode tracks focus/blur events, and + # activates/deactivates itself accordingly. new NormalMode - Scroller.init settings new PassKeysMode new InsertMode @@ -242,8 +243,6 @@ enterInsertModeIfElementIsFocused = -> enterInsertModeWithoutShowingIndicator(document.activeElement) onDOMActivate = (event) -> handlerStack.bubbleEvent 'DOMActivate', event -onFocus = (event) -> handlerStack.bubbleEvent 'focus', event -onBlur = (event) -> handlerStack.bubbleEvent 'blur', event executePageCommand = (request) -> return unless frameId == request.frameId @@ -326,8 +325,7 @@ extend window, HUD.showForDuration("Yanked URL", 1000) enterInsertMode: -> - new InsertMode - global: true + new InsertMode global: true enterVisualMode: => new VisualMode() @@ -804,17 +802,16 @@ executeFind = (query, options) -> -> document.addEventListener("selectionchange", restoreDefaultSelectionHighlight, true) 0) + # We are either in normal mode ("n"), or find mode ("/"). We are not in insert mode. Nevertheless, if a + # previous find landed in an editable element, then that element may still be activated. In this case, we + # don't want to leave it behind (see #1412). + if document.activeElement and DomUtils.isEditable document.activeElement + if not DomUtils.isSelected document.activeElement + document.activeElement.blur() + # we need to save the anchor node here because <esc> seems to nullify it, regardless of whether we do # preventDefault() findModeAnchorNode = document.getSelection().anchorNode - - # 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 restoreDefaultSelectionHighlight = -> document.body.classList.remove("vimiumFindMode") |
