aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--background_scripts/main.coffee2
-rw-r--r--content_scripts/ui_component.coffee23
-rw-r--r--content_scripts/vimium_frontend.coffee10
-rw-r--r--content_scripts/vomnibar.coffee8
-rw-r--r--pages/vomnibar.coffee9
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()