diff options
| -rw-r--r-- | background_scripts/main.coffee | 2 | ||||
| -rw-r--r-- | content_scripts/ui_component.coffee | 23 | ||||
| -rw-r--r-- | content_scripts/vimium_frontend.coffee | 10 | ||||
| -rw-r--r-- | content_scripts/vomnibar.coffee | 8 | ||||
| -rw-r--r-- | pages/vomnibar.coffee | 9 |
5 files changed, 36 insertions, 16 deletions
diff --git a/background_scripts/main.coffee b/background_scripts/main.coffee index a64c7e37..0c7d9343 100644 --- a/background_scripts/main.coffee +++ b/background_scripts/main.coffee @@ -658,7 +658,7 @@ handleFrameFocused = (request, sender) -> frameIdsForTab[tabId] = [request.frameId, (frameIdsForTab[tabId].filter (id) -> id != request.frameId)...] # Inform all frames that a frame has received the focus. - chrome.tabs.sendMessage sender.tab.id, + chrome.tabs.sendMessage sender.tab.id, name: "frameFocused" focusFrameId: request.frameId diff --git a/content_scripts/ui_component.coffee b/content_scripts/ui_component.coffee index ee74c3a8..ea0bf776 100644 --- a/content_scripts/ui_component.coffee +++ b/content_scripts/ui_component.coffee @@ -55,7 +55,7 @@ class UIComponent @showing = true hide: (focusWindow = true)-> - @refocusSourceFrame @options?.sourceFrameId if focusWindow and @options?.sourceFrameId? + @refocusSourceFrame @options?.sourceFrameId if focusWindow window.removeEventListener "focus", @onFocus if @onFocus @onFocus = null @iframeElement.classList.remove "vimiumUIComponentShowing" @@ -63,14 +63,13 @@ class UIComponent @options = null @showing = false - # Refocus the frame from which the UI component was opened. + # 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 receives the focus, before then focusing the frame which should now have the - # focus. + # to wait until that frame first receives the focus, before then focusing the frame which should now have + # the focus. refocusSourceFrame: (sourceFrameId) -> - window.addEventListener "focus", handler = (event) -> - if event.target == window - window.removeEventListener "focus", handler + if @showing and sourceFrameId? and sourceFrameId != frameId + refocusSourceFrame = -> chrome.runtime.sendMessage handler: "sendMessageToFrames" message: @@ -79,5 +78,15 @@ class UIComponent highlight: false highlightOnlyIfNotTop: true + if windowIsFocused() and false + # 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() + root = exports ? window root.UIComponent = UIComponent diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index c5bc185f..931b8edf 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -19,6 +19,13 @@ keyQueue = null currentCompletionKeys = "" validFirstKeys = "" +# We track whther the current window has the focus or not. +windowIsFocused = do -> + windowHasFocus = document.hasFocus() + window.addEventListener "focus", (event) -> windowHasFocus = true if event.target == window; true + window.addEventListener "blur", (event) -> windowHasFocus = false if event.target == window; true + -> windowHasFocus + # The types in <input type="..."> that we consider for focusInput command. Right now this is recalculated in # each content script. Alternatively we could calculate it once in the background page and use a request to # fetch it each time. @@ -192,7 +199,7 @@ initializePreDomReady = -> # We handle the message if we're enabled, or if it's one of these listed message types. return unless isEnabledForUrl or request.name in [ "getActiveState", "setState", "executePageCommand" ] # These requests are delivered to the options page, but there are no handlers there. - return if request.handler in [ "registerFrame", "frameFocused", "unregisterFrame" ] + return if request.handler in [ "registerFrame", "unregisterFrame" ] # We don't handle these here. They're handled elsewhere (e.g. in the vomnibar/UI component). return if request.name in [ "frameFocused" ] # Handle the request. @@ -1245,4 +1252,5 @@ root.settings = settings root.HUD = HUD root.handlerStack = handlerStack root.frameId = frameId +root.windowIsFocused = windowIsFocused root.bgLog = bgLog diff --git a/content_scripts/vomnibar.coffee b/content_scripts/vomnibar.coffee index 3d54e643..2529c077 100644 --- a/content_scripts/vomnibar.coffee +++ b/content_scripts/vomnibar.coffee @@ -40,9 +40,11 @@ Vomnibar = init: -> unless @vomnibarUI? @vomnibarUI = new UIComponent "pages/vomnibar.html", "vomnibarFrame", (event) => - if event.data == "hide" - @vomnibarUI.hide() - @vomnibarUI.postMessage "hidden" + @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: diff --git a/pages/vomnibar.coffee b/pages/vomnibar.coffee index dbb37ebf..b133b126 100644 --- a/pages/vomnibar.coffee +++ b/pages/vomnibar.coffee @@ -63,10 +63,11 @@ class VomnibarUI # The sequence of events when the vomnibar is hidden is as follows: # 1. Post a "hide" message to the host page. - # 2. The host page hides the vomnibar and posts back a "hidden" message. - # 3. Only once "hidden" message is received here is any required action (callback) invoked (in onHidden). - # This ensures that the vomnibar is actually hidden, and avoids flicker after opening a link in a new tab - # (see #1485). + # 2. The host page hides the vomnibar. + # 3. When that page receives the focus, and it posts back a "hidden" message. + # 3. Only once the "hidden" message is received here is any required action invoked (in onHidden). + # This ensures that the vomnibar is actually hidden before any new tab is created, and avoids flicker after + # opening a link in a new tab then returning to the original tab (see #1485). hide: (@postHideCallback = null) -> UIComponentServer.postMessage "hide" @reset() |
