Bug 1189622 part 2 - Allow widget's MakeFullScreen to fail, and call FinishFullscreenChange directly if that happens.
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -5909,18 +5909,22 @@ FullscreenTransitionTask::Run()
// different direction happen continuously in a short time. We
// need to ensure the fullscreen state matches our target here,
// otherwise the widget would change the window state as if we
// toggle for Fullscreen Mode instead of Fullscreen API.
NS_WARNING("The fullscreen state of the window does not match");
mWindow->mFullScreen = mFullscreen;
}
// Toggle the fullscreen state on the widget
- mWindow->SetWidgetFullscreen(nsPIDOMWindow::eForFullscreenAPI,
- mFullscreen, mWidget, mScreen);
+ if (!mWindow->SetWidgetFullscreen(nsPIDOMWindow::eForFullscreenAPI,
+ mFullscreen, mWidget, mScreen)) {
+ // Fail to setup the widget, call FinishFullscreenChange to
+ // complete fullscreen change directly.
+ mWindow->FinishFullscreenChange(mFullscreen);
+ }
// Set observer for the next content paint.
nsCOMPtr<nsIObserver> observer = new Observer(this);
nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
obs->AddObserver(observer, kPaintedTopic, false);
// There are several edge cases where we may never get the paint
// notification, including:
// 1. the window/tab is closed before the next paint;
// 2. the user has switched to another tab before we get here.
@@ -5989,24 +5993,24 @@ MakeWidgetFullscreen(nsGlobalWindow* aWi
GetFullscreenTransitionDuration(aFullscreen, &duration);
if (!duration.IsSuppressed()) {
performTransition = widget->
PrepareForFullscreenTransition(getter_AddRefs(transitionData));
}
}
nsCOMPtr<nsIScreen> screen = aHMD ? aHMD->GetScreen() : nullptr;
if (!performTransition) {
- aWindow->SetWidgetFullscreen(aReason, aFullscreen, widget, screen);
+ return aWindow->SetWidgetFullscreen(aReason, aFullscreen, widget, screen);
} else {
nsCOMPtr<nsIRunnable> task =
new FullscreenTransitionTask(duration, aWindow, aFullscreen,
widget, screen, transitionData);
task->Run();
- }
- return true;
+ return true;
+ }
}
nsresult
nsGlobalWindow::SetFullscreenInternal(FullscreenReason aReason,
bool aFullScreen,
gfx::VRDeviceProxy* aHMD)
{
MOZ_ASSERT(IsOuterWindow());
@@ -6100,35 +6104,34 @@ nsGlobalWindow::SetFullscreenInternal(Fu
if (!presShell->IsInFullscreenChange()) {
presShell->SetIsInFullscreenChange(true);
}
}
FinishFullscreenChange(aFullScreen);
return NS_OK;
}
-void
+bool
nsGlobalWindow::SetWidgetFullscreen(FullscreenReason aReason, bool aIsFullscreen,
nsIWidget* aWidget, nsIScreen* aScreen)
{
MOZ_ASSERT(IsOuterWindow());
MOZ_ASSERT(this == GetTopInternal(), "Only topmost window should call this");
MOZ_ASSERT(!GetFrameElementInternal(), "Content window should not call this");
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
if (nsCOMPtr<nsIPresShell> presShell = mDocShell->GetPresShell()) {
presShell->SetIsInFullscreenChange(true);
}
- if (aReason == nsPIDOMWindow::eForFullscreenMode) {
+ nsresult rv = aReason == nsPIDOMWindow::eForFullscreenMode ?
// If we enter fullscreen for fullscreen mode, we want
// the native system behavior.
- aWidget->MakeFullScreenWithNativeTransition(aIsFullscreen, aScreen);
- } else {
+ aWidget->MakeFullScreenWithNativeTransition(aIsFullscreen, aScreen) :
aWidget->MakeFullScreen(aIsFullscreen, aScreen);
- }
+ return NS_SUCCEEDED(rv);
}
/* virtual */ void
nsGlobalWindow::FinishFullscreenChange(bool aIsFullscreen)
{
MOZ_ASSERT(IsOuterWindow());
if (aIsFullscreen != mFullScreen) {
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -468,17 +468,17 @@ public:
// For accessing protected field mFullScreen
friend class FullscreenTransitionTask;
// Outer windows only.
virtual nsresult SetFullscreenInternal(
FullscreenReason aReason, bool aIsFullscreen,
mozilla::gfx::VRDeviceProxy *aHMD = nullptr) override final;
virtual void FinishFullscreenChange(bool aIsFullscreen) override final;
- void SetWidgetFullscreen(FullscreenReason aReason, bool aIsFullscreen,
+ bool SetWidgetFullscreen(FullscreenReason aReason, bool aIsFullscreen,
nsIWidget* aWidget, nsIScreen* aScreen);
bool FullScreen() const;
// Inner windows only.
virtual void SetHasGamepadEventListener(bool aHasGamepad = true) override;
// nsIInterfaceRequestor
NS_DECL_NSIINTERFACEREQUESTOR
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -1137,16 +1137,20 @@ class nsIWidget : public nsISupports {
nsIRunnable* aCallback) = 0;
/**
* Put the toplevel window into or out of fullscreen mode.
* If aTargetScreen is given, attempt to go fullscreen on that screen,
* if possible. (If not, it behaves as if aTargetScreen is null.)
* If !aFullScreen, aTargetScreen is ignored.
* aTargetScreen support is currently only implemented on Windows.
+ *
+ * @return NS_OK if the widget is setup properly for fullscreen and
+ * FullscreenChanged callback has been or will be called. If other
+ * value is returned, the caller should continue the change itself.
*/
NS_IMETHOD MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen = nullptr) = 0;
/**
* Same as MakeFullScreen, except that, on systems which natively
* support fullscreen transition, calling this method explicitly
* requests that behavior.
* It is currently only supported on OS X 10.7+.