Bug 1184443 - Make async ExitFullscreen call ask the window to exit fullscreen first. r=smaug

--HG--
extra : source : 237250013b141f622112c0284e0db8a65fc28c3d
This commit is contained in:
Xidorn Quan 2015-07-19 10:30:52 +10:00
parent b7a55dbc9b
commit e5ea6fe8a3
8 changed files with 62 additions and 74 deletions

View File

@ -1680,7 +1680,7 @@ Element::UnbindFromTree(bool aDeep, bool aNullParent)
nsContentUtils::eDOM_PROPERTIES,
"RemovedFullScreenElement");
// Fully exit full-screen.
nsIDocument::ExitFullscreen(OwnerDoc(), /* async */ false);
nsIDocument::ExitFullscreenInDocTree(OwnerDoc());
}
if (HasPointerLock()) {
nsIDocument::UnlockPointer();

View File

@ -3212,7 +3212,7 @@ nsDOMWindowUtils::ExitFullscreen()
nsCOMPtr<nsIDocument> doc = GetDocument();
NS_ENSURE_STATE(doc);
nsIDocument::ExitFullscreen(doc, /* async */ false);
nsIDocument::ExitFullscreenInDocTree(doc);
return NS_OK;
}

View File

@ -9358,7 +9358,7 @@ nsDocument::OnPageHide(bool aPersisted,
// doctree by the time OnPageHide() is called, so we must store a
// reference to the root (in nsDocument::mFullscreenRoot) since we can't
// just traverse the doctree to get the root.
nsIDocument::ExitFullscreen(this, /* async */ false);
nsIDocument::ExitFullscreenInDocTree(this);
// Since the document is removed from the doctree before OnPageHide() is
// called, ExitFullscreen() can't traverse from the root down to *this*
@ -11122,31 +11122,43 @@ SetWindowFullScreen(nsIDocument* aDoc, bool aValue, gfx::VRHMDInfo *aVRHMD = nul
nsContentUtils::AddScriptRunner(new nsSetWindowFullScreen(aDoc, aValue, aVRHMD));
}
class nsCallExitFullscreen : public nsRunnable {
static void
AskWindowToExitFullscreen(nsIDocument* aDoc)
{
if (XRE_GetProcessType() == GeckoProcessType_Content) {
nsContentUtils::DispatchEventOnlyToChrome(
aDoc, ToSupports(aDoc), NS_LITERAL_STRING("MozDOMFullscreen:Exit"),
/* Bubbles */ true, /* Cancelable */ false,
/* DefaultAction */ nullptr);
} else {
SetWindowFullScreen(aDoc, false);
}
}
class nsCallExitFullscreen : public nsRunnable
{
public:
explicit nsCallExitFullscreen(nsIDocument* aDoc)
: mDoc(aDoc) {}
NS_IMETHOD Run()
NS_IMETHOD Run() override final
{
nsDocument::ExitFullscreen(mDoc);
if (!mDoc) {
FullscreenRoots::ForEach(&AskWindowToExitFullscreen);
} else {
AskWindowToExitFullscreen(mDoc);
}
return NS_OK;
}
private:
nsCOMPtr<nsIDocument> mDoc;
};
/* static */
void
nsIDocument::ExitFullscreen(nsIDocument* aDoc, bool aRunAsync)
/* static */ void
nsIDocument::AsyncExitFullscreen(nsIDocument* aDoc)
{
if (aDoc && !aDoc->IsFullScreenDoc()) {
return;
}
if (aRunAsync) {
NS_DispatchToCurrentThread(new nsCallExitFullscreen(aDoc));
return;
}
nsDocument::ExitFullscreen(aDoc);
NS_DispatchToCurrentThread(new nsCallExitFullscreen(aDoc));
}
static bool
@ -11193,16 +11205,16 @@ ResetFullScreen(nsIDocument* aDocument, void* aData)
return true;
}
static void
ExitFullscreenInDocTree(nsIDocument* aMaybeNotARootDoc)
/* static */ void
nsIDocument::ExitFullscreenInDocTree(nsIDocument* aMaybeNotARootDoc)
{
MOZ_ASSERT(aMaybeNotARootDoc);
// Unlock the pointer
UnlockPointer();
nsCOMPtr<nsIDocument> root = aMaybeNotARootDoc->GetFullscreenRoot();
NS_ASSERTION(root, "Should have root when in fullscreen!");
if (!root) {
return;
}
if (!root->IsFullScreenDoc()) {
if (!root || !root->IsFullScreenDoc()) {
// If a document was detached before exiting from fullscreen, it is
// possible that the root had left fullscreen state. In this case,
// we would not get anything from the ResetFullScreen() call. Root's
@ -11246,24 +11258,6 @@ ExitFullscreenInDocTree(nsIDocument* aMaybeNotARootDoc)
SetWindowFullScreen(root, false);
}
/* static */
void
nsDocument::ExitFullscreen(nsIDocument* aDoc)
{
// Unlock the pointer
UnlockPointer();
if (aDoc) {
ExitFullscreenInDocTree(aDoc);
return;
}
// Clear fullscreen stacks in all fullscreen roots' descendant documents.
FullscreenRoots::ForEach(&ExitFullscreenInDocTree);
NS_ASSERTION(FullscreenRoots::IsEmpty(),
"Should have exited all fullscreen roots from fullscreen");
}
bool
GetFullscreenLeaf(nsIDocument* aDoc, void* aData)
{
@ -11318,14 +11312,7 @@ nsDocument::RestorePreviousFullScreenState()
if (exitingFullscreen) {
// If we are fully exiting fullscreen, don't touch anything here,
// just wait for the window to get out from fullscreen first.
if (XRE_GetProcessType() == GeckoProcessType_Content) {
nsContentUtils::DispatchEventOnlyToChrome(
this, ToSupports(this), NS_LITERAL_STRING("MozDOMFullscreen:Exit"),
/* Bubbles */ true, /* Cancelable */ false,
/* DefaultAction */ nullptr);
} else {
SetWindowFullScreen(this, false);
}
AskWindowToExitFullscreen(this);
return;
}

View File

@ -1242,8 +1242,6 @@ public:
//
already_AddRefed<nsSimpleContentList> BlockedTrackingNodes() const;
static void ExitFullscreen(nsIDocument* aDoc);
// Do the "fullscreen element ready check" from the fullscreen spec.
// It returns true if the given element is allowed to go into fullscreen.
bool FullscreenElementReadyCheck(Element* aElement, bool aWasCallerChrome);

View File

@ -1249,7 +1249,7 @@ nsFocusManager::SetFocusInner(nsIContent* aNewContent, int32_t aFlags,
contentToFocus->OwnerDoc(),
nsContentUtils::eDOM_PROPERTIES,
"FocusedWindowedPluginWhileFullScreen");
nsIDocument::ExitFullscreen(contentToFocus->OwnerDoc(), /* async */ true);
nsIDocument::AsyncExitFullscreen(contentToFocus->OwnerDoc());
}
#endif

View File

@ -6308,11 +6308,9 @@ FinishDOMFullscreenChange(nsIDocument* aDoc, bool aInDOMFullscreen)
// Ask the document to handle any pending DOM fullscreen change.
nsIDocument::HandlePendingFullscreenRequests(aDoc);
} else {
// Force exit from DOM full-screen mode. This is so that if we're in
// DOM full-screen mode and the user exits full-screen mode with
// the browser full-screen mode toggle keyboard-shortcut, we'll detect
// that and leave DOM API full-screen mode too.
nsIDocument::ExitFullscreen(aDoc, /* async */ false);
// If the window is leaving fullscreen state, also ask the document
// to exit from DOM Fullscreen.
nsIDocument::ExitFullscreenInDocTree(aDoc);
}
}

View File

@ -1165,24 +1165,29 @@ public:
virtual void SetApprovedForFullscreen(bool aIsApproved) = 0;
/**
* Exits documents out of DOM fullscreen mode.
* Synchronously cleans up the fullscreen state on the given document.
*
* If aDocument is null, all fullscreen documents in all browser windows
* exit fullscreen.
* Calling this without performing fullscreen transition could lead
* to undesired effect (the transition happens after document state
* flips), hence it should only be called either by nsGlobalWindow
* when we have performed the transition, or when it is necessary to
* clean up the state immediately. Otherwise, AsyncExitFullscreen()
* should be called instead.
*
* If aDocument is non null, all documents from aDocument's fullscreen root
* to the fullscreen leaf exit fullscreen.
*
* Note that the fullscreen leaf is the bottom-most document which is
* fullscreen, it may have non-fullscreen child documents. The fullscreen
* root is normally the chrome document.
*
* If aRunAsync is true, fullscreen is executed asynchronously.
*
* Note if aDocument is not fullscreen this function has no effect, even if
* aDocument has fullscreen ancestors.
* aDocument must not be null.
*/
static void ExitFullscreen(nsIDocument* aDocument, bool aRunAsync);
static void ExitFullscreenInDocTree(nsIDocument* aDocument);
/**
* Ask the document to exit fullscreen state asynchronously.
*
* Different from ExitFullscreenInDocTree(), this allows the window
* to perform fullscreen transition first if any.
*
* If aDocument is null, it will exit fullscreen from all documents
* in all windows.
*/
static void AsyncExitFullscreen(nsIDocument* aDocument);
/**
* Handles one single fullscreen request, updates `aHandled` if the request

View File

@ -7809,7 +7809,7 @@ PresShell::HandleEventInternal(WidgetEvent* aEvent, nsEventStatus* aStatus)
// ESC key released while in DOM fullscreen mode.
// Fully exit all browser windows and documents from
// fullscreen mode.
nsIDocument::ExitFullscreen(nullptr, /* async */ true);
nsIDocument::AsyncExitFullscreen(nullptr);
}
}
nsCOMPtr<nsIDocument> pointerLockedDoc =