mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-22 09:45:41 +00:00
9790c57933
When we open firefox with pinned tabs, we first paint a window with one tab open, and then that tab gets displaced after the pinned tabs come in. This aims to ensure that our first paint contains the pinned tab, so that we don't have tabs moving around after first paint. MozReview-Commit-ID: GC1y6NlgLTd Differential Revision: https://phabricator.services.mozilla.com/D18742 --HG-- extra : moz-landing-system : lando
196 lines
5.9 KiB
JavaScript
196 lines
5.9 KiB
JavaScript
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
/*
|
|
* This module tracks each browser window and informs network module
|
|
* the current selected tab's content outer window ID.
|
|
*/
|
|
|
|
var EXPORTED_SYMBOLS = ["BrowserWindowTracker"];
|
|
|
|
const {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|
|
|
// Lazy getters
|
|
XPCOMUtils.defineLazyModuleGetters(this, {
|
|
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
|
|
});
|
|
|
|
// Constants
|
|
const TAB_EVENTS = ["TabBrowserInserted", "TabSelect"];
|
|
const WINDOW_EVENTS = ["activate", "unload"];
|
|
const DEBUG = false;
|
|
|
|
// Variables
|
|
var _lastTopLevelWindowID = 0;
|
|
var _trackedWindows = [];
|
|
|
|
// Global methods
|
|
function debug(s) {
|
|
if (DEBUG) {
|
|
dump("-*- UpdateTopLevelContentWindowIDHelper: " + s + "\n");
|
|
}
|
|
}
|
|
|
|
function _updateCurrentContentOuterWindowID(browser) {
|
|
if (!browser.outerWindowID ||
|
|
browser.outerWindowID === _lastTopLevelWindowID ||
|
|
browser.ownerGlobal != _trackedWindows[0]) {
|
|
return;
|
|
}
|
|
|
|
debug("Current window uri=" + (browser.currentURI && browser.currentURI.spec) +
|
|
" id=" + browser.outerWindowID);
|
|
|
|
_lastTopLevelWindowID = browser.outerWindowID;
|
|
let windowIDWrapper = Cc["@mozilla.org/supports-PRUint64;1"]
|
|
.createInstance(Ci.nsISupportsPRUint64);
|
|
windowIDWrapper.data = _lastTopLevelWindowID;
|
|
Services.obs.notifyObservers(windowIDWrapper,
|
|
"net:current-toplevel-outer-content-windowid");
|
|
}
|
|
|
|
function _handleEvent(event) {
|
|
switch (event.type) {
|
|
case "TabBrowserInserted":
|
|
if (event.target.ownerGlobal.gBrowser.selectedBrowser === event.target.linkedBrowser) {
|
|
_updateCurrentContentOuterWindowID(event.target.linkedBrowser);
|
|
}
|
|
break;
|
|
case "TabSelect":
|
|
_updateCurrentContentOuterWindowID(event.target.linkedBrowser);
|
|
break;
|
|
case "activate":
|
|
WindowHelper.onActivate(event.target);
|
|
break;
|
|
case "unload":
|
|
WindowHelper.removeWindow(event.currentTarget);
|
|
break;
|
|
}
|
|
}
|
|
|
|
function _handleMessage(message) {
|
|
let browser = message.target;
|
|
if (message.name === "Browser:Init" &&
|
|
browser === browser.ownerGlobal.gBrowser.selectedBrowser) {
|
|
_updateCurrentContentOuterWindowID(browser);
|
|
}
|
|
}
|
|
|
|
function _trackWindowOrder(window) {
|
|
if (window.windowState == window.STATE_MINIMIZED) {
|
|
let firstMinimizedWindow = _trackedWindows.findIndex(w => w.windowState == w.STATE_MINIMIZED);
|
|
if (firstMinimizedWindow == -1) {
|
|
firstMinimizedWindow = _trackedWindows.length;
|
|
}
|
|
_trackedWindows.splice(firstMinimizedWindow, 0, window);
|
|
} else {
|
|
_trackedWindows.unshift(window);
|
|
}
|
|
}
|
|
|
|
function _untrackWindowOrder(window) {
|
|
let idx = _trackedWindows.indexOf(window);
|
|
if (idx >= 0)
|
|
_trackedWindows.splice(idx, 1);
|
|
}
|
|
|
|
function _trackPinnedTabs(window) {
|
|
Services.prefs.setIntPref("browser.tabs.firstWindowRestore.numPinnedTabs",
|
|
window.gBrowser._numPinnedTabs);
|
|
}
|
|
|
|
// Methods that impact a window. Put into single object for organization.
|
|
var WindowHelper = {
|
|
addWindow(window) {
|
|
// Add event listeners
|
|
TAB_EVENTS.forEach(function(event) {
|
|
window.gBrowser.tabContainer.addEventListener(event, _handleEvent);
|
|
});
|
|
WINDOW_EVENTS.forEach(function(event) {
|
|
window.addEventListener(event, _handleEvent);
|
|
});
|
|
|
|
let messageManager = window.getGroupMessageManager("browsers");
|
|
messageManager.addMessageListener("Browser:Init", _handleMessage);
|
|
|
|
_trackWindowOrder(window);
|
|
|
|
// Update the selected tab's content outer window ID.
|
|
_updateCurrentContentOuterWindowID(window.gBrowser.selectedBrowser);
|
|
},
|
|
|
|
removeWindow(window) {
|
|
_untrackWindowOrder(window);
|
|
|
|
// Remove the event listeners
|
|
TAB_EVENTS.forEach(function(event) {
|
|
window.gBrowser.tabContainer.removeEventListener(event, _handleEvent);
|
|
});
|
|
WINDOW_EVENTS.forEach(function(event) {
|
|
window.removeEventListener(event, _handleEvent);
|
|
});
|
|
|
|
let messageManager = window.getGroupMessageManager("browsers");
|
|
messageManager.removeMessageListener("Browser:Init", _handleMessage);
|
|
},
|
|
|
|
onActivate(window) {
|
|
// If this window was the last focused window, we don't need to do anything
|
|
if (window == _trackedWindows[0])
|
|
return;
|
|
|
|
_untrackWindowOrder(window);
|
|
_trackWindowOrder(window);
|
|
_trackPinnedTabs(window);
|
|
|
|
_updateCurrentContentOuterWindowID(window.gBrowser.selectedBrowser);
|
|
},
|
|
};
|
|
|
|
this.BrowserWindowTracker = {
|
|
/**
|
|
* Get the most recent browser window.
|
|
*
|
|
* @param options an object accepting the arguments for the search.
|
|
* * private: true to restrict the search to private windows
|
|
* only, false to restrict the search to non-private only.
|
|
* Omit the property to search in both groups.
|
|
* * allowPopups: true if popup windows are permissable.
|
|
*/
|
|
getTopWindow(options = {}) {
|
|
for (let win of _trackedWindows) {
|
|
if (!win.closed &&
|
|
(options.allowPopups || win.toolbar.visible) &&
|
|
(!("private" in options) ||
|
|
PrivateBrowsingUtils.permanentPrivateBrowsing ||
|
|
PrivateBrowsingUtils.isWindowPrivate(win) == options.private)) {
|
|
return win;
|
|
}
|
|
}
|
|
return null;
|
|
},
|
|
|
|
/**
|
|
* Number of currently open browser windows.
|
|
*/
|
|
get windowCount() {
|
|
return _trackedWindows.length;
|
|
},
|
|
|
|
/**
|
|
* Array of browser windows ordered by z-index, in reverse order.
|
|
* This means that the top-most browser window will be the first item.
|
|
*/
|
|
get orderedWindows() {
|
|
// Clone the windows array immediately as it may change during iteration,
|
|
// we'd rather have an outdated order than skip/revisit windows.
|
|
return [..._trackedWindows];
|
|
},
|
|
|
|
track(window) {
|
|
return WindowHelper.addWindow(window);
|
|
},
|
|
};
|