diff options
Diffstat (limited to 'content_scripts')
| -rw-r--r-- | content_scripts/hud.coffee | 14 | ||||
| -rw-r--r-- | content_scripts/mode_key_handler.coffee | 4 | ||||
| -rw-r--r-- | content_scripts/ui_component.coffee | 107 | ||||
| -rw-r--r-- | content_scripts/vimium_frontend.coffee | 36 | ||||
| -rw-r--r-- | content_scripts/vomnibar.coffee | 6 |
5 files changed, 67 insertions, 100 deletions
diff --git a/content_scripts/hud.coffee b/content_scripts/hud.coffee index bbf7c5e9..fb1fd657 100644 --- a/content_scripts/hud.coffee +++ b/content_scripts/hud.coffee @@ -25,12 +25,12 @@ HUD = show: (text) -> return unless @isReady() clearTimeout(@_showForDurationTimerId) - @hudUI.show {name: "show", text} + @hudUI.activate {name: "show", text} @tween.fade 1.0, 150 showFindMode: (@findMode = null) -> return unless @isReady() - @hudUI.show {name: "showFindMode", text: ""} + @hudUI.activate name: "showFindMode", text: "" @tween.fade 1.0, 150 search: (data) -> @@ -50,9 +50,7 @@ HUD = clearTimeout(@_showForDurationTimerId) @tween.stop() if immediate - unless updateIndicator - @hudUI.hide() - @hudUI.postMessage {name: "hide"} + @hudUI.hide() Mode.setIndicator() if updateIndicator else @tween.fade 0, 150, => @hide true, updateIndicator @@ -60,9 +58,9 @@ HUD = hideFindMode: (data) -> @findMode.checkReturnToViewPort() - # An element element won't receive a focus event if the search landed on it while we were in the HUD - # iframe. To end up with the correct modes active, we create a focus/blur event manually after refocusing - # this window. + # An element won't receive a focus event if the search landed on it while we were in the HUD iframe. To + # end up with the correct modes active, we create a focus/blur event manually after refocusing this + # window. window.focus() focusNode = DomUtils.getSelectionFocusElement() diff --git a/content_scripts/mode_key_handler.coffee b/content_scripts/mode_key_handler.coffee index 08222d98..0b8145fc 100644 --- a/content_scripts/mode_key_handler.coffee +++ b/content_scripts/mode_key_handler.coffee @@ -42,9 +42,9 @@ class KeyHandlerMode extends Mode @reset() @suppressEvent # If the help dialog loses the focus, then Escape should hide it; see point 2 in #2045. - else if isEscape and HelpDialog?.showing + else if isEscape and HelpDialog?.isShowing() @keydownEvents[event.keyCode] = true - HelpDialog.hide() + HelpDialog.toggle() @suppressEvent else if isEscape @continueBubbling diff --git a/content_scripts/ui_component.coffee b/content_scripts/ui_component.coffee index d7bdf2a1..bb350ccc 100644 --- a/content_scripts/ui_component.coffee +++ b/content_scripts/ui_component.coffee @@ -2,7 +2,8 @@ class UIComponent uiComponentIsReady: false iframeElement: null iframePort: null - showing: null + iframeFrameId: null + showing: false options: null shadowDOM: null styleSheetGetter: null @@ -27,10 +28,8 @@ class UIComponent @shadowDOM = shadowWrapper.createShadowRoot?() ? shadowWrapper @shadowDOM.appendChild styleSheet @shadowDOM.appendChild @iframeElement - - @showing = true # The iframe is visible now. - # Hide the iframe, but don't interfere with the focus. - @hide false + @iframeElement.classList.remove "vimiumUIComponentVisible" + @iframeElement.classList.add "vimiumUIComponentHidden" # Open a port and pass it to the iframe via window.postMessage. We use an AsyncDataFetcher to handle # requests which arrive before the iframe (and its message handlers) have completed initialization. See @@ -45,74 +44,59 @@ class UIComponent # Get vimiumSecret so the iframe can determine that our message isn't the page impersonating us. chrome.storage.local.get "vimiumSecret", ({ vimiumSecret }) => { port1, port2 } = new MessageChannel - port1.onmessage = (event) => - if event?.data == "uiComponentIsReady" then @uiComponentIsReady = true else @handleMessage event @iframeElement.contentWindow.postMessage vimiumSecret, chrome.runtime.getURL(""), [ port2 ] - setIframePort port1 - - chrome.runtime.onMessage.addListener (request) => - if @showing and request.name == "frameFocused" and request.focusFrameId != frameId - @postMessage name: "frameFocused", focusFrameId: request.focusFrameId - false # Free up the sendResponse handler. - # Posts a message (if one is provided), then calls continuation (if provided). The continuation is only - # ever called *after* the message has been posted. + port1.onmessage = (event) => + switch event?.data?.name ? event?.data + when "uiComponentIsReady" + # If any other frame receives the focus, then hide the UI component. + chrome.runtime.onMessage.addListener ({name, focusFrameId}) => + if name == "frameFocused" and @options?.focus and focusFrameId not in [frameId, @iframeFrameId] + @hide false + false # We will not be calling sendResponse. + + # If this frame receives the focus, then hide the UI component. + window.addEventListener "focus", (event) => + if event.target == window and @options?.focus and not @options?.allowBlur + @hide false + true # Continue propagating the event. + + @uiComponentIsReady = true + setIframePort port1 + + when "setIframeFrameId" then @iframeFrameId = event.data.iframeFrameId + when "hide" then @hide() + else @handleMessage event + + # Post a message (if provided), then call continuation (if provided). postMessage: (message = null, continuation = null) -> @iframePort.use (port) => port.postMessage message if message? continuation?() - activate: (@options) -> + activate: (@options = null) -> @postMessage @options, => - @show() unless @showing - @iframeElement.focus() - - show: (message) -> - @postMessage message, => @iframeElement.classList.remove "vimiumUIComponentHidden" @iframeElement.classList.add "vimiumUIComponentVisible" - # The window may not have the focus. We focus it now, to prevent the "focus" listener below from firing - # immediately. - window.focus() - window.addEventListener "focus", @onFocus = (event) => - if event.target == window - window.removeEventListener "focus", @onFocus - @onFocus = null - @postMessage "frameFocused" + @iframeElement.focus() if @options?.focus @showing = true - hide: (focusWindow = true)-> - @refocusSourceFrame @options?.sourceFrameId if focusWindow - window.removeEventListener "focus", @onFocus if @onFocus - @onFocus = null - @iframeElement.classList.remove "vimiumUIComponentVisible" - @iframeElement.classList.add "vimiumUIComponentHidden" - @iframeElement.blur() - @options = null - @showing = false - - # Refocus the frame from which the UI component was opened. This may be different from the current frame. - # After hiding the UI component, Chrome refocuses the containing frame. To avoid a race condition, we need - # to wait until that frame first receives the focus, before then focusing the frame which should now have - # the focus. - refocusSourceFrame: (sourceFrameId) -> - if @showing and sourceFrameId? and sourceFrameId != frameId - refocusSourceFrame = -> - chrome.runtime.sendMessage - handler: "sendMessageToFrames" - message: - name: "focusFrame" - frameId: sourceFrameId - - if windowIsFocused() - # We already have the focus. - refocusSourceFrame() - else - # We don't yet have the focus (but we'll be getting it soon). - window.addEventListener "focus", handler = (event) -> - if event.target == window - window.removeEventListener "focus", handler - refocusSourceFrame() + hide: (shouldRefocusOriginalFrame = true) -> + if @showing + @showing = false + @iframeElement.classList.remove "vimiumUIComponentVisible" + @iframeElement.classList.add "vimiumUIComponentHidden" + if @options?.focus and shouldRefocusOriginalFrame + @iframeElement.blur() + if @options?.sourceFrameId? + chrome.runtime.sendMessage + handler: "sendMessageToFrames", + message: name: "focusFrame", frameId: @options.sourceFrameId, forceFocusThisFrame: true + else + window.focus() + @options = null + # Inform the UI component that it is hidden. + Utils.nextTick => @postMessage "hidden" # Fetch a Vimium file/resource (such as "content_scripts/vimium.css"). # We try making an XMLHttpRequest request. That can fail (see #1817), in which case we fetch the @@ -135,6 +119,5 @@ class UIComponent request.open "GET", (chrome.runtime.getURL file), true request.send() - root = exports ? window root.UIComponent = UIComponent diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 4dcdfe7d..537dbaa9 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -119,7 +119,10 @@ class NormalMode extends KeyHandlerMode You have asked Vimium to perform #{count} repetitions of the command: #{registryEntry.description}.\n Are you sure you want to continue?""" - if registryEntry.topFrame + if registryEntry.topFrame and window.isVimiumUIComponent? and window.isVimiumUIComponent + # We cannot use "topFrame" commands, most notably the Vomnibar, from within a UI component. + HUD.showForDuration "#{registryEntry.command} cannot be used here.", 2000 + else if registryEntry.topFrame chrome.runtime.sendMessage handler: "sendMessageToFrames", message: {name: "runInTopFrame", sourceFrameId: frameId, registryEntry} else if registryEntry.background @@ -156,7 +159,7 @@ initializePreDomReady = -> getScrollPosition: (ignoredA, ignoredB, sendResponse) -> sendResponse scrollX: window.scrollX, scrollY: window.scrollY if frameId == 0 setScrollPosition: setScrollPosition - # A frame has received the focus. We don't care here (the Vomnibar/UI-component handles this). + # A frame has received the focus. We don't care here (UI components handle this). frameFocused: -> checkEnabledAfterURLChange: checkEnabledAfterURLChange runInTopFrame: ({sourceFrameId, registryEntry}) -> @@ -626,29 +629,16 @@ enterFindMode = -> # If we are in the help dialog iframe, HelpDialog is already defined with the necessary functions. window.HelpDialog ?= helpUI: null - container: null - showing: false - - init: -> - return if @helpUI? - - @helpUI = new UIComponent "pages/help_dialog.html", "vimiumHelpDialogFrame", (event) => - @hide() if event.data == "hide" - - isReady: -> @helpUI - - show: (html) -> - @init() - return if @showing or !@isReady() - @showing = true - @helpUI.activate html - - hide: -> - @showing = false - @helpUI.hide() + isShowing: -> @helpUI?.showing toggle: (html) -> - if @showing then @hide() else @show html + @helpUI ?= new UIComponent "pages/help_dialog.html", "vimiumHelpDialogFrame", -> + if @isShowing() + @helpUI.hide() + else + # On the options page, we allow the help dialog to lose the focus, elsewhere we do not. This allows + # users to view the help dialog while typing in the key-mappings input. + @helpUI.activate {name: "activate", html, focus: true, allowBlur: window.isVimiumOptionsPage ? false} initializePreDomReady() DomUtils.documentReady initializeOnDomReady diff --git a/content_scripts/vomnibar.coffee b/content_scripts/vomnibar.coffee index c23a4e6f..646fda43 100644 --- a/content_scripts/vomnibar.coffee +++ b/content_scripts/vomnibar.coffee @@ -51,10 +51,6 @@ Vomnibar = unless @vomnibarUI? @vomnibarUI = new UIComponent "pages/vomnibar.html", "vomnibarFrame", (event) => @vomnibarUI.hide() if event.data == "hide" - # Whenever the window receives the focus, we tell the Vomnibar UI that it has been hidden (regardless of - # whether it was previously visible). - window.addEventListener "focus", (event) => - @vomnibarUI.postMessage "hidden" if event.target == window; true # This function opens the vomnibar. It accepts options, a map with the values: @@ -65,7 +61,7 @@ Vomnibar = open: (sourceFrameId, options) -> @init() if @vomnibarUI?.uiComponentIsReady - @vomnibarUI.activate extend options, { sourceFrameId } + @vomnibarUI.activate extend options, { name: "activate", sourceFrameId, focus: true } root = exports ? window root.Vomnibar = Vomnibar |
