简体   繁体   中英

Firefox add-on: how to tell if a window is in the background

In a Firefox Add-on SDK add-on, how do I tell whether a window is in the background, ie. visible but not focused?

For example, if I bring a different application to the foreground, the Firefox window becomes unfocused but is still visible.

The reason why I want to do this is because I have a CPU-intensive content script running in the active window, and I'd like to pause it to avoid unnecessary overhead whenever the user isn't actively engaged with the window - meaning it's in the background or minimized.

require("sdk/windows").activeWindow keeps returning the last clicked window even if it's in the background or minimized. There doesn't seem to be any property for the window's focus state.

I can also get use the following code to get an nsIDocShell:

var mostRecentWindow = require("sdk/window/utils").getMostRecentBrowserWindow();
var docShell = require("sdk/window/utils").getWindowDocShell(mostRecentWindow);

Now when I query the docShell.isActive property, it returns true even if the window is in the background.

The one advantage of docShell.isActive is that it returns false when the window is minimized, while activeWindow returns true even in this case. But it's still missing information about whether the window is in the background or not.

Based on the suggestion by @willlma, this code seems to do the trick:

const windows = require('sdk/windows').browserWindows;
const tabs = require("sdk/tabs");
var anyWindowActive = true;
var refreshTimeoutId;

windows.on('deactivate', function(window) {
    if (window == windows.activeWindow) {
        anyWindowActive = false;
    }
    clearTimeout(refreshTimeoutId);
    refreshTimeoutId = setTimeout(refreshTabStates, 50);
});

windows.on('activate', function(window) {
    anyWindowActive = true;
    clearTimeout(refreshTimeoutId);
    refreshTimeoutId = setTimeout(refreshTabStates, 50);
});

tabs.on('activate', function(tab) {
    clearTimeout(refreshTimeoutId);
    refreshTimeoutId = setTimeout(refreshTabStates, 50);
});

function refreshTabStates() {
    refreshTimeoutId = null;
    for (let win of windows) {
        for (let tab of win.tabs) {
            var shouldBeActive = anyWindowActive
                                 && tab == tabs.activeTab
                                 && win == windows.activeWindow;
            notifyTab(tab, shouldBeActive);
        }
    }
}

where notifyTab() is a function that posts a message to that tab's content script (if any) about whether it should be running or not.

setTimeout is used to avoid multiple calls to refreshTabStates in quick succession. For example, if you click on an inactive tab in a window that's not the current one, that one click results in window.deactivate , window.activate and tab.activate events.

Also, the initial state is a problem. What if the user launches Firefox and puts it in the background before any script has managed to run?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM