aboutsummaryrefslogtreecommitdiffstats
path: root/content_scripts/vimium_frontend.coffee
diff options
context:
space:
mode:
Diffstat (limited to 'content_scripts/vimium_frontend.coffee')
-rw-r--r--content_scripts/vimium_frontend.coffee51
1 files changed, 41 insertions, 10 deletions
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index fde3d167..ec39ccde 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.
@@ -96,6 +103,11 @@ settings =
#
frameId = 1 + Math.floor(Math.random()*999999999)
+# For debugging only. This logs to the console on the background page.
+bgLog = (args...) ->
+ args = (arg.toString() for arg in args)
+ chrome.runtime.sendMessage handler: "log", frameId: frameId, message: args.join " "
+
# If an input grabs the focus before the user has interacted with the page, then grab it back (if the
# grabBackFocus option is set).
class GrabBackFocus extends Mode
@@ -167,7 +179,7 @@ initializePreDomReady = ->
requestHandlers =
showHUDforDuration: (request) -> HUD.showForDuration request.text, request.duration
toggleHelpDialog: (request) -> toggleHelpDialog(request.dialogHtml, request.frameId)
- focusFrame: (request) -> if (frameId == request.frameId) then focusThisFrame(request.highlight)
+ focusFrame: (request) -> if (frameId == request.frameId) then focusThisFrame request
refreshCompletionKeys: refreshCompletionKeys
getScrollPosition: -> scrollX: window.scrollX, scrollY: window.scrollY
setScrollPosition: (request) -> setScrollPosition request.scrollX, request.scrollY
@@ -175,6 +187,8 @@ initializePreDomReady = ->
currentKeyQueue: (request) ->
keyQueue = request.keyQueue
handlerStack.bubbleEvent "registerKeyQueue", { keyQueue: keyQueue }
+ # A frame has received the focus. We don't care, here (the Vomnibar/UI-component handles this).
+ frameFocused: ->
chrome.runtime.onMessage.addListener (request, sender, sendResponse) ->
# In the options page, we will receive requests from both content and background scripts. ignore those
@@ -182,10 +196,11 @@ initializePreDomReady = ->
return if sender.tab and not sender.tab.url.startsWith 'chrome-extension://'
# These requests are delivered to the options page, but there are no handlers there.
return if request.handler in [ "registerFrame", "frameFocused", "unregisterFrame" ]
- shouldHandleRequest = isEnabledForUrl
- # Requests with a frameId of zero are sent to and only received by the tab's main frame. We *always*
- # handle the listed requests in that frame (even if Vimium is otherwise disabled).
- if request.frameId == 0 and request.name in [ "focusFrame" ]
+ # We handle the message if we're enabled, or if it's one of these listed message types.
+ shouldHandleRequest = isEnabledForUrl or request.name in [ "executePageCommand" ]
+ # Requests with a frameId of zero should only be handled in the main/top frame (regardless of whether
+ # Vimium is enabled there).
+ if request.frameId == 0 and DomUtils.isTopFrame()
request.frameId = frameId
shouldHandleRequest = true
sendResponse requestHandlers[request.name](request, sender) if shouldHandleRequest
@@ -238,7 +253,8 @@ initializeOnDomReady = ->
# Tell the background page we're in the dom ready state.
chrome.runtime.connect({ name: "domReady" })
CursorHider.init()
- Vomnibar.init()
+ # We only initialize the vomnibar in the tab's main frame, because it's only ever opened there.
+ Vomnibar.init() if DomUtils.isTopFrame()
registerFrame = ->
# Don't register frameset containers; focusing them is no use.
@@ -252,10 +268,21 @@ unregisterFrame = ->
chrome.runtime.sendMessage
handler: "unregisterFrame"
frameId: frameId
- tab_is_closing: window.top == window.self
+ tab_is_closing: DomUtils.isTopFrame()
executePageCommand = (request) ->
- return unless frameId == request.frameId
+ # Vomnibar commands are handled in the tab's main/top frame. They are handled even if Vimium is otherwise
+ # disabled in the frame.
+ if request.command.split(".")[0] == "Vomnibar"
+ if DomUtils.isTopFrame()
+ # We pass the frameId from request. That's the frame which originated the request, so that's the frame
+ # which should receive the focus when the vomnibar closes.
+ Utils.invokeCommandString request.command, [ request.frameId ]
+ refreshCompletionKeys request
+ return
+
+ # All other commands are handled in their frame (but only if Vimium is enabled).
+ return unless frameId == request.frameId and isEnabledForUrl
if (request.passCountToFunction)
Utils.invokeCommandString(request.command, [request.count])
@@ -271,7 +298,7 @@ setScrollPosition = (scrollX, scrollY) ->
#
# Called from the backend in order to change frame focus.
#
-window.focusThisFrame = (shouldHighlight) ->
+window.focusThisFrame = (request) ->
if window.innerWidth < 3 or window.innerHeight < 3
# This frame is too small to focus. Cancel and tell the background frame to focus the next one instead.
# This affects sites like Google Inbox, which have many tiny iframes. See #1317.
@@ -279,7 +306,9 @@ window.focusThisFrame = (shouldHighlight) ->
chrome.runtime.sendMessage({ handler: "nextFrame", frameId: frameId })
return
window.focus()
- if (document.body && shouldHighlight)
+ shouldHighlight = request.highlight
+ shouldHighlight ||= request.highlightOnlyIfNotTop and not DomUtils.isTopFrame()
+ if document.body and shouldHighlight
borderWas = document.body.style.border
document.body.style.border = '5px solid yellow'
setTimeout((-> document.body.style.border = borderWas), 200)
@@ -1197,3 +1226,5 @@ root.settings = settings
root.HUD = HUD
root.handlerStack = handlerStack
root.frameId = frameId
+root.windowIsFocused = windowIsFocused
+root.bgLog = bgLog