87 lines
3.3 KiB
JavaScript
87 lines
3.3 KiB
JavaScript
// Keep track of how many fullscreenChange enters we've received, so that
|
|
// we can balance them with the number of exits we receive. We reset this
|
|
// to 0 when we load a test.
|
|
var fullscreenChangeEnters = 0;
|
|
|
|
addLoadEvent(function () {
|
|
info(`Resetting fullscreen enter count.`);
|
|
fullscreenChangeEnters = 0;
|
|
});
|
|
|
|
// This can be used to force a certain value for fullscreenChangeEnters
|
|
// to handle unusual conditions -- such as exiting multiple levels of
|
|
// fullscreen forcibly.
|
|
function setFullscreenChangeEnters(enters) {
|
|
info(`Setting fullscreen enter count to ${enters}.`);
|
|
fullscreenChangeEnters = enters;
|
|
}
|
|
|
|
// Returns true if the window believes it is in fullscreen. This may be true even
|
|
// before an asynchronous fullscreen transition is complete.
|
|
function inFullscreenMode(win) {
|
|
return win.document.fullscreenElement;
|
|
}
|
|
|
|
// Adds a listener that will be called once a fullscreen transition
|
|
// is complete. When type==='enter', callback is called when we've
|
|
// received a fullscreenchange event, and the fullscreen transition is
|
|
// complete. When type==='exit', callback is called when we've
|
|
// received a fullscreenchange event and the window is out of
|
|
// fullscreen. inDoc is the document which the listeners are added on,
|
|
// if absent, the listeners are added to the current document.
|
|
// the current document.
|
|
function addFullscreenChangeContinuation(type, callback, inDoc) {
|
|
var doc = inDoc || document;
|
|
var topWin = doc.defaultView.top;
|
|
function checkCondition() {
|
|
if (type == "enter") {
|
|
fullscreenChangeEnters++;
|
|
return inFullscreenMode(topWin);
|
|
} else if (type == "exit") {
|
|
fullscreenChangeEnters--;
|
|
return fullscreenChangeEnters
|
|
? inFullscreenMode(topWin)
|
|
: !inFullscreenMode(topWin);
|
|
}
|
|
throw new Error("'type' must be either 'enter', or 'exit'.");
|
|
}
|
|
function onFullscreenChange(event) {
|
|
doc.removeEventListener("fullscreenchange", onFullscreenChange);
|
|
ok(checkCondition(), `Should ${type} fullscreen.`);
|
|
// Delay invocation so other listeners have a chance to respond before
|
|
// we continue.
|
|
requestAnimationFrame(() => setTimeout(() => callback(event), 0), 0);
|
|
}
|
|
doc.addEventListener("fullscreenchange", onFullscreenChange);
|
|
}
|
|
|
|
// Calls |callback| when the next fullscreenerror is dispatched to inDoc||document.
|
|
function addFullscreenErrorContinuation(callback, inDoc) {
|
|
let doc = inDoc || document;
|
|
let listener = function (event) {
|
|
doc.removeEventListener("fullscreenerror", listener);
|
|
// Delay invocation so other listeners have a chance to respond before
|
|
// we continue.
|
|
requestAnimationFrame(() => setTimeout(() => callback(event), 0), 0);
|
|
};
|
|
doc.addEventListener("fullscreenerror", listener);
|
|
}
|
|
|
|
// Waits until the window has both the load event and a MozAfterPaint called on
|
|
// it, and then invokes the callback
|
|
function waitForLoadAndPaint(win, callback) {
|
|
win.addEventListener(
|
|
"MozAfterPaint",
|
|
function () {
|
|
// The load event may have fired before the MozAfterPaint, in which case
|
|
// listening for it now will hang. Instead we check the readyState to see if
|
|
// it already fired, and if so, invoke the callback right away.
|
|
if (win.document.readyState == "complete") {
|
|
callback();
|
|
} else {
|
|
win.addEventListener("load", callback, { once: true });
|
|
}
|
|
},
|
|
{ once: true }
|
|
);
|
|
}
|