--- a/browser/base/content/browser-fullScreen.js
+++ b/browser/base/content/browser-fullScreen.js
@@ -3,16 +3,17 @@
# 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/.
var FullScreen = {
_MESSAGES: [
"DOMFullscreen:Request",
"DOMFullscreen:NewOrigin",
"DOMFullscreen:Exit",
+ "DOMFullscreen:Painted",
],
init: function() {
// called when we go into full screen, even if initiated by a web page script
window.addEventListener("fullscreen", this, true);
window.addEventListener("MozDOMFullscreen:Entered", this,
/* useCapture */ true,
/* wantsUntrusted */ false);
@@ -161,16 +162,20 @@ var FullScreen = {
case "DOMFullscreen:NewOrigin": {
this.showWarning(aMessage.data.originNoSuffix);
break;
}
case "DOMFullscreen:Exit": {
this._windowUtils.remoteFrameFullscreenReverted();
break;
}
+ case "DOMFullscreen:Painted": {
+ Services.obs.notifyObservers(window, "fullscreen-painted", "");
+ break;
+ }
}
},
enterDomFullscreen : function(aBrowser) {
if (!document.mozFullScreen)
return false;
// If we've received a fullscreen notification, we have to ensure that the
--- a/browser/base/content/tab-content.js
+++ b/browser/base/content/tab-content.js
@@ -619,18 +619,20 @@ if (Services.appinfo.processType == Serv
let DOMFullscreenHandler = {
_fullscreenDoc: null,
init: function() {
addMessageListener("DOMFullscreen:Entered", this);
addMessageListener("DOMFullscreen:Approved", this);
addMessageListener("DOMFullscreen:CleanUp", this);
addEventListener("MozDOMFullscreen:Request", this);
+ addEventListener("MozDOMFullscreen:Entered", this);
addEventListener("MozDOMFullscreen:NewOrigin", this);
addEventListener("MozDOMFullscreen:Exit", this);
+ addEventListener("MozDOMFullscreen:Exited", this);
},
get _windowUtils() {
return content.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
},
receiveMessage: function(aMessage) {
@@ -673,12 +675,22 @@ let DOMFullscreenHandler = {
originNoSuffix: this._fullscreenDoc.nodePrincipal.originNoSuffix,
});
break;
}
case "MozDOMFullscreen:Exit": {
sendAsyncMessage("DOMFullscreen:Exit");
break;
}
+ case "MozDOMFullscreen:Entered":
+ case "MozDOMFullscreen:Exited": {
+ addEventListener("MozAfterPaint", this);
+ break;
+ }
+ case "MozAfterPaint": {
+ removeEventListener("MozAfterPaint", this);
+ sendAsyncMessage("DOMFullscreen:Painted");
+ break;
+ }
}
}
};
DOMFullscreenHandler.init();
--- a/browser/base/content/test/general/browser_domFullscreen_fullscreenMode.js
+++ b/browser/base/content/test/general/browser_domFullscreen_fullscreenMode.js
@@ -116,16 +116,20 @@ let gTests = [
affectsFullscreenMode: true,
exitFunc: function () {
executeSoon(() => EventUtils.synthesizeKey("VK_F11", {}));
}
}
];
add_task(function* () {
+ yield pushPrefs(
+ ["full-screen-api.transition-duration.enter", "0 0"],
+ ["full-screen-api.transition-duration.leave", "0 0"]);
+
let tab = gBrowser.addTab("about:robots");
let browser = tab.linkedBrowser;
gBrowser.selectedTab = tab;
yield waitForDocLoadComplete();
registerCleanupFunction(() => {
if (browser.contentWindow.fullScreen) {
BrowserFullScreen();
--- a/browser/base/content/test/general/test_contextmenu.html
+++ b/browser/base/content/test/general/test_contextmenu.html
@@ -502,16 +502,18 @@ function runTest(testNum) {
var full_screen_element = subwindow.document.getElementById("test-dom-full-screen");
var openDomFullScreen = function() {
subwindow.removeEventListener("mozfullscreenchange", openDomFullScreen, false);
openContextMenuFor(dom_full_screen, true); // Invoke context menu for next test.
}
subwindow.addEventListener("mozfullscreenchange", openDomFullScreen, false);
SpecialPowers.setBoolPref("full-screen-api.approval-required", false);
SpecialPowers.setBoolPref("full-screen-api.allow-trusted-requests-only", false);
+ SpecialPowers.setCharPref("full-screen-api.transition-duration.enter", "0 0");
+ SpecialPowers.setCharPref("full-screen-api.transition-duration.leave", "0 0");
full_screen_element.mozRequestFullScreen();
},
function () {
// Context menu for DOM Fullscreen mode (NOTE: this is *NOT* on an img)
checkContextMenu(["context-navigation", null,
["context-back", false,
"context-forward", false,
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -6025,29 +6025,227 @@ FinishDOMFullscreenChange(nsIDocument* a
// 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);
}
}
+struct FullscreenTransitionDuration
+{
+ // The unit of the durations is millisecond
+ uint16_t mFadeIn = 0;
+ uint16_t mFadeOut = 0;
+ bool IsSuppressed() const
+ {
+ return mFadeIn == 0 && mFadeOut == 0;
+ }
+};
+
+static void
+GetFullscreenTransitionDuration(bool aEnterFullscreen,
+ FullscreenTransitionDuration* aDuration)
+{
+ const char* pref = aEnterFullscreen ?
+ "full-screen-api.transition-duration.enter" :
+ "full-screen-api.transition-duration.leave";
+ nsAdoptingCString prefValue = Preferences::GetCString(pref);
+ if (!prefValue.IsEmpty()) {
+ sscanf(prefValue.get(), "%hu%hu",
+ &aDuration->mFadeIn, &aDuration->mFadeOut);
+ }
+}
+
+class FullscreenTransitionTask : public nsRunnable
+{
+public:
+ FullscreenTransitionTask(const FullscreenTransitionDuration& aDuration,
+ nsGlobalWindow* aWindow, bool aFullscreen,
+ nsIWidget* aWidget, nsIScreen* aScreen,
+ nsISupports* aTransitionData)
+ : mWindow(aWindow)
+ , mWidget(aWidget)
+ , mScreen(aScreen)
+ , mTransitionData(aTransitionData)
+ , mDuration(aDuration)
+ , mStage(eBeforeToggle)
+ , mFullscreen(aFullscreen)
+ {}
+
+ NS_IMETHOD Run() override;
+
+private:
+ enum Stage {
+ // BeforeToggle stage happens before we enter or leave fullscreen
+ // state. In this stage, the task triggers the pre-toggle fullscreen
+ // transition on the widget.
+ eBeforeToggle,
+ // ToggleFullscreen stage actually executes the fullscreen toggle,
+ // and wait for the next paint on the content to continue.
+ eToggleFullscreen,
+ // AfterToggle stage happens after we toggle the fullscreen state.
+ // In this stage, the task triggers the post-toggle fullscreen
+ // transition on the widget.
+ eAfterToggle
+ };
+
+ class Observer final : public nsIObserver
+ {
+ public:
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIOBSERVER
+
+ explicit Observer(FullscreenTransitionTask* aTask)
+ : mTask(aTask) { }
+
+ private:
+ ~Observer() {}
+
+ nsRefPtr<FullscreenTransitionTask> mTask;
+ };
+
+ static const uint32_t kNextPaintTimeout = 1000; // ms
+ static const char* const kPaintedTopic;
+
+ nsRefPtr<nsGlobalWindow> mWindow;
+ nsCOMPtr<nsIWidget> mWidget;
+ nsCOMPtr<nsIScreen> mScreen;
+ nsCOMPtr<nsITimer> mTimer;
+ nsCOMPtr<nsISupports> mTransitionData;
+
+ FullscreenTransitionDuration mDuration;
+ Stage mStage;
+ bool mFullscreen;
+};
+
+const char* const
+FullscreenTransitionTask::kPaintedTopic = "fullscreen-painted";
+
+NS_IMETHODIMP
+FullscreenTransitionTask::Run()
+{
+ Stage stage = mStage;
+ mStage = Stage(mStage + 1);
+ if (stage == eBeforeToggle) {
+ mWidget->PerformFullscreenTransition(nsIWidget::eBeforeFullscreenToggle,
+ mDuration.mFadeIn, mTransitionData,
+ this);
+ } else if (stage == eToggleFullscreen) {
+ if (MOZ_UNLIKELY(mWindow->mFullScreen != mFullscreen)) {
+ // This could happen in theory if several fullscreen requests in
+ // 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
+ mWidget->MakeFullScreen(mFullscreen, mScreen);
+ // 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.
+ // Completely fixing those cases seems to be tricky, and since they
+ // should rarely happen, it probably isn't worth to fix. Hence we
+ // simply add a timeout here to ensure we never hang forever.
+ mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
+ mTimer->Init(observer, kNextPaintTimeout, nsITimer::TYPE_ONE_SHOT);
+ } else if (stage == eAfterToggle) {
+ mWidget->PerformFullscreenTransition(nsIWidget::eAfterFullscreenToggle,
+ mDuration.mFadeOut, mTransitionData,
+ this);
+ }
+ return NS_OK;
+}
+
+NS_IMPL_ISUPPORTS(FullscreenTransitionTask::Observer, nsIObserver)
+
+NS_IMETHODIMP
+FullscreenTransitionTask::Observer::Observe(nsISupports* aSubject,
+ const char* aTopic,
+ const char16_t* aData)
+{
+ bool shouldContinue = false;
+ if (strcmp(aTopic, FullscreenTransitionTask::kPaintedTopic) == 0) {
+ nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(aSubject));
+ nsCOMPtr<nsIWidget> widget = win ?
+ static_cast<nsGlobalWindow*>(win.get())->GetMainWidget() : nullptr;
+ if (widget == mTask->mWidget) {
+ // The paint notification arrives first. Cancel the timer.
+ mTask->mTimer->Cancel();
+ shouldContinue = true;
+ }
+ } else {
+#ifdef DEBUG
+ MOZ_ASSERT(strcmp(aTopic, NS_TIMER_CALLBACK_TOPIC) == 0,
+ "Should only get fullscreen-painted or timer-callback");
+ nsCOMPtr<nsITimer> timer(do_QueryInterface(aSubject));
+ MOZ_ASSERT(timer && timer == mTask->mTimer,
+ "Should only trigger this with the timer the task created");
+#endif
+ shouldContinue = true;
+ }
+ if (shouldContinue) {
+ nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+ obs->RemoveObserver(this, kPaintedTopic);
+ mTask->mTimer = nullptr;
+ mTask->Run();
+ }
+ return NS_OK;
+}
+
+static bool
+MakeWidgetFullscreen(nsGlobalWindow* aWindow, gfx::VRHMDInfo* aHMD,
+ nsPIDOMWindow::FullscreenReason aReason, bool aFullscreen)
+{
+ nsCOMPtr<nsIWidget> widget = aWindow->GetMainWidget();
+ if (!widget) {
+ return false;
+ }
+
+ FullscreenTransitionDuration duration;
+ bool performTransition = false;
+ nsCOMPtr<nsISupports> transitionData;
+ if (aReason == nsPIDOMWindow::eForFullscreenAPI) {
+ GetFullscreenTransitionDuration(aFullscreen, &duration);
+ if (!duration.IsSuppressed()) {
+ performTransition = widget->
+ PrepareForFullscreenTransition(getter_AddRefs(transitionData));
+ }
+ }
+ nsCOMPtr<nsIScreen> screen = aHMD ? aHMD->GetScreen() : nullptr;
+ if (!performTransition) {
+ widget->MakeFullScreen(aFullscreen, screen);
+ } else {
+ nsCOMPtr<nsIRunnable> task =
+ new FullscreenTransitionTask(duration, aWindow, aFullscreen,
+ widget, screen, transitionData);
+ task->Run();
+ }
+ return true;
+}
+
nsresult
nsGlobalWindow::SetFullscreenInternal(FullscreenReason aReason,
bool aFullScreen,
gfx::VRHMDInfo* aHMD)
{
MOZ_ASSERT(IsOuterWindow());
NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
// Only chrome can change our fullscreen mode. Otherwise, the state
// can only be changed for DOM fullscreen.
- if (aFullScreen == FullScreen() ||
- (aReason == eForFullscreenMode && !nsContentUtils::IsCallerChrome())) {
+ if (aReason == eForFullscreenMode && !nsContentUtils::IsCallerChrome()) {
return NS_OK;
}
// SetFullScreen needs to be called on the root window, so get that
// via the DocShell tree, and if we are not already the root,
// call SetFullScreen on that window instead.
nsCOMPtr<nsIDocShellTreeItem> rootItem;
mDocShell->GetRootTreeItem(getter_AddRefs(rootItem));
@@ -6093,26 +6291,17 @@ nsGlobalWindow::SetFullscreenInternal(Fu
// gone full screen, the state trap above works.
mFullScreen = aFullScreen;
// Sometimes we don't want the top-level widget to actually go fullscreen,
// for example in the B2G desktop client, we don't want the emulated screen
// dimensions to appear to increase when entering fullscreen mode; we just
// want the content to fill the entire client area of the emulator window.
if (!Preferences::GetBool("full-screen-api.ignore-widgets", false)) {
- nsCOMPtr<nsIWidget> widget = GetMainWidget();
- if (widget) {
- nsCOMPtr<nsIScreen> screen;
- if (aHMD) {
- screen = aHMD->GetScreen();
- }
- if (aReason == eForFullscreenAPI) {
- widget->PrepareForDOMFullscreenTransition();
- }
- widget->MakeFullScreen(aFullScreen, screen);
+ if (MakeWidgetFullscreen(this, aHMD, aReason, aFullScreen)) {
// The rest of code for switching fullscreen is in nsGlobalWindow::
// FinishFullscreenChange() which will be called after sizemodechange
// event is dispatched.
return NS_OK;
}
}
FinishFullscreenChange(aFullScreen);
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -479,16 +479,19 @@ public:
// Outer windows only.
virtual bool DispatchCustomEvent(const nsAString& aEventName) override;
bool DispatchResizeEvent(const mozilla::CSSIntSize& aSize);
// Inner windows only.
virtual void RefreshCompartmentPrincipal() override;
+ // For accessing protected field mFullScreen
+ friend class FullscreenTransitionTask;
+
// Outer windows only.
virtual nsresult SetFullscreenInternal(
FullscreenReason aReason, bool aIsFullscreen,
mozilla::gfx::VRHMDInfo *aHMD = nullptr) override final;
virtual void FinishFullscreenChange(bool aIsFullscreen) override final;
bool FullScreen() const;
// Inner windows only.
--- a/dom/html/test/test_fullscreen-api.html
+++ b/dom/html/test/test_fullscreen-api.html
@@ -81,16 +81,20 @@ try {
} catch (e) {
}
is(window.fullScreen, false, "Shouldn't be able to set window fullscreen from content");
// Ensure the full-screen api is enabled, and will be disabled on test exit.
// Disable the requirement for trusted contexts only, so the tests are easier
// to write
addLoadEvent(function() {
SpecialPowers.pushPrefEnv({
- "set":[["full-screen-api.enabled", true],
- ["full-screen-api.allow-trusted-requests-only", false]]}, nextTest);
+ "set": [
+ ["full-screen-api.enabled", true],
+ ["full-screen-api.allow-trusted-requests-only", false],
+ ["full-screen-api.transition-duration.enter", "0 0"],
+ ["full-screen-api.transition-duration.leave", "0 0"]
+ ]}, nextTest);
});
SimpleTest.waitForExplicitFinish();
</script>
</pre>
</body>
</html>
--- a/dom/tests/mochitest/chrome/test_MozDomFullscreen_event.xul
+++ b/dom/tests/mochitest/chrome/test_MozDomFullscreen_event.xul
@@ -27,18 +27,22 @@ function make_uri(url) {
// Ensure "fullscreen" permissions are not present on the test URI.
var pm = Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager);
var uri = make_uri("http://mochi.test:8888");
var principal = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
.getService(Ci.nsIScriptSecurityManager)
.getNoAppCodebasePrincipal(uri);
pm.removeFromPrincipal(principal, "fullscreen");
-SpecialPowers.pushPrefEnv({"set": [['full-screen-api.enabled', true],
- ['full-screen-api.allow-trusted-requests-only', false]]}, setup);
+SpecialPowers.pushPrefEnv({"set": [
+ ['full-screen-api.enabled', true],
+ ['full-screen-api.allow-trusted-requests-only', false],
+ ['full-screen-api.transition-duration.enter', '0 0'],
+ ['full-screen-api.transition-duration.leave', '0 0']
+]}, setup);
function setup() {
newwindow = window.open("MozDomFullscreen_chrome.xul", "_blank","chrome,resizable=yes,width=400,height=400");
}
function done()
{
newwindow.close();
--- a/dom/tests/mochitest/pointerlock/test_pointerlock-api.html
+++ b/dom/tests/mochitest/pointerlock/test_pointerlock-api.html
@@ -23,26 +23,27 @@ https://bugzilla.mozilla.org/show_bug.cg
* which doesn't work when run in the mochitests' iframe, since the
* mochitests' iframe doesn't have an allowfullscreen attribute. To get
* around this, all tests are run in a child window, which can go fullscreen.
* This method is borrowed from dom/html/test/test_fullscreen-api.html.
**/
SimpleTest.waitForExplicitFinish();
- // Ensure the full-screen api is enabled, and will be disabled on test exit.
- SpecialPowers.setBoolPref("full-screen-api.enabled", true);
-
- // Disable the requirement for trusted contexts only, so the tests are easier to write.
- SpecialPowers.setBoolPref("full-screen-api.allow-trusted-requests-only", false);
-
// Grant "fullscreen" permission on the test domain. This means fullscreen will be
// automatically approved, so pointer lock in the tests will be too.
SpecialPowers.setFullscreenAllowed(document);
+ SpecialPowers.pushPrefEnv({"set": [
+ ["full-screen-api.enabled", true],
+ ["full-screen-api.allow-trusted-requests-only", false],
+ ["full-screen-api.transition-duration.enter", "0 0"],
+ ["full-screen-api.transition-duration.leave", "0 0"]
+ ]}, nextTest);
+
// Run the tests which go full-screen in new window, as Mochitests
// normally run in an iframe, which by default will not have the
// allowfullscreen attribute set, so full-screen won't work.
var gTestFiles = [
"file_approval.html",
"file_screenClientXYConst.html",
"file_childIframe.html",
"file_doubleLock.html",
@@ -67,18 +68,16 @@ https://bugzilla.mozilla.org/show_bug.cg
{ file: "file_screenClientXYConst.html",
platform: "MacIntel" }
];
var gTestWindow = null;
var gTestIndex = 0;
function finish() {
- SpecialPowers.clearUserPref("full-screen-api.enabled");
- SpecialPowers.clearUserPref("full-screen-api.allow-trusted-requests-only");
SpecialPowers.removeFullscreenAllowed(document)
SimpleTest.finish();
}
function nextTest() {
if (gTestWindow) {
gTestWindow.close();
}
@@ -102,14 +101,12 @@ https://bugzilla.mozilla.org/show_bug.cg
gTestWindow = window.open(file, "", "width=500,height=500");
} else {
nextTest();
}
} else {
finish();
}
}
-
- addLoadEvent(nextTest);
</script>
</pre>
</body>
</html>
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -4337,16 +4337,19 @@ pref("dom.webnotifications.enabled", tru
// Alert animation effect, name is disableSlidingEffect for backwards-compat.
pref("alerts.disableSlidingEffect", false);
// DOM full-screen API.
pref("full-screen-api.enabled", false);
pref("full-screen-api.allow-trusted-requests-only", true);
pref("full-screen-api.pointer-lock.enabled", true);
+// transition duration of fade-to-black and fade-from-black, unit: ms
+pref("full-screen-api.transition-duration.enter", "400 400");
+pref("full-screen-api.transition-duration.leave", "400 400");
// DOM idle observers API
pref("dom.idle-observers-api.enabled", true);
// Time limit, in milliseconds, for EventStateManager::IsHandlingUserInput().
// Used to detect long running handlers of user-generated events.
pref("dom.event.handling-user-input-time-limit", 1000);
--- a/widget/cocoa/nsCocoaWindow.h
+++ b/widget/cocoa/nsCocoaWindow.h
@@ -280,17 +280,17 @@ public:
NS_IMETHOD ConstrainPosition(bool aAllowSlop,
int32_t *aX, int32_t *aY) override;
virtual void SetSizeConstraints(const SizeConstraints& aConstraints) override;
NS_IMETHOD Move(double aX, double aY) override;
NS_IMETHOD PlaceBehind(nsTopLevelWidgetZPlacement aPlacement,
nsIWidget *aWidget, bool aActivate) override;
NS_IMETHOD SetSizeMode(int32_t aMode) override;
NS_IMETHOD HideWindowChrome(bool aShouldHide) override;
- virtual void PrepareForDOMFullscreenTransition() override;
+ virtual bool PrepareForFullscreenTransition(nsISupports** aData) override;
void EnteredFullScreen(bool aFullScreen, bool aNativeMode = true);
inline bool ShouldToggleNativeFullscreen(bool aFullScreen);
NS_IMETHOD MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen = nullptr) override;
NS_IMETHOD Resize(double aWidth, double aHeight, bool aRepaint) override;
NS_IMETHOD Resize(double aX, double aY, double aWidth, double aHeight, bool aRepaint) override;
NS_IMETHOD GetClientBounds(nsIntRect &aRect) override;
NS_IMETHOD GetScreenBounds(nsIntRect &aRect) override;
void ReportMoveEvent();
--- a/widget/cocoa/nsCocoaWindow.mm
+++ b/widget/cocoa/nsCocoaWindow.mm
@@ -1261,19 +1261,21 @@ NS_IMETHODIMP nsCocoaWindow::HideWindowC
NS_ENSURE_SUCCESS(rv, rv);
}
return NS_OK;
NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
}
-void nsCocoaWindow::PrepareForDOMFullscreenTransition()
+/* virtual */ bool
+nsCocoaWindow::PrepareForFullscreenTransition(nsISupports** aData)
{
mInDOMFullscreenTransition = true;
+ return false;
}
void nsCocoaWindow::EnteredFullScreen(bool aFullScreen, bool aNativeMode)
{
mInFullScreenTransition = false;
mInFullScreenMode = aFullScreen;
if (aNativeMode || mInNativeFullScreenMode) {
mInNativeFullScreenMode = aFullScreen;
--- a/widget/nsBaseWidget.cpp
+++ b/widget/nsBaseWidget.cpp
@@ -765,16 +765,26 @@ NS_IMETHODIMP nsBaseWidget::SetWindowSha
// Hide window borders/decorations for this widget
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsBaseWidget::HideWindowChrome(bool aShouldHide)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
+/* virtual */ void
+nsBaseWidget::PerformFullscreenTransition(FullscreenTransitionStage aStage,
+ uint16_t aDuration,
+ nsISupports* aData,
+ nsIRunnable* aCallback)
+{
+ MOZ_ASSERT_UNREACHABLE(
+ "Should never call PerformFullscreenTransition on nsBaseWidget");
+}
+
//-------------------------------------------------------------------------
//
// Put the window into full-screen mode
//
//-------------------------------------------------------------------------
NS_IMETHODIMP nsBaseWidget::MakeFullScreen(bool aFullScreen, nsIScreen* aScreen)
{
HideWindowChrome(aFullScreen);
--- a/widget/nsBaseWidget.h
+++ b/widget/nsBaseWidget.h
@@ -138,17 +138,21 @@ public:
virtual void SetTransparencyMode(nsTransparencyMode aMode) override;
virtual nsTransparencyMode GetTransparencyMode() override;
virtual void GetWindowClipRegion(nsTArray<nsIntRect>* aRects) override;
NS_IMETHOD SetWindowShadowStyle(int32_t aStyle) override;
virtual void SetShowsToolbarButton(bool aShow) override {}
virtual void SetShowsFullScreenButton(bool aShow) override {}
virtual void SetWindowAnimationType(WindowAnimationType aType) override {}
NS_IMETHOD HideWindowChrome(bool aShouldHide) override;
- virtual void PrepareForDOMFullscreenTransition() override {}
+ virtual bool PrepareForFullscreenTransition(nsISupports** aData) override { return false; }
+ virtual void PerformFullscreenTransition(FullscreenTransitionStage aStage,
+ uint16_t aDuration,
+ nsISupports* aData,
+ nsIRunnable* aCallback) override;
NS_IMETHOD MakeFullScreen(bool aFullScreen, nsIScreen* aScreen = nullptr) override;
virtual LayerManager* GetLayerManager(PLayerTransactionChild* aShadowManager = nullptr,
LayersBackend aBackendHint = mozilla::layers::LayersBackend::LAYERS_NONE,
LayerManagerPersistence aPersistence = LAYER_MANAGER_CURRENT,
bool* aAllowRetaining = nullptr) override;
CompositorVsyncDispatcher* GetCompositorVsyncDispatcher() override;
void CreateCompositorVsyncDispatcher();
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -32,16 +32,17 @@
// forward declarations
class nsIRollupListener;
class imgIContainer;
class nsIContent;
class ViewWrapper;
class nsIWidgetListener;
class nsIntRegion;
class nsIScreen;
+class nsIRunnable;
namespace mozilla {
class CompositorVsyncDispatcher;
class WritingMode;
namespace dom {
class TabChild;
}
namespace plugins {
@@ -114,18 +115,18 @@ typedef void* nsNativeWidget;
#if defined(MOZ_WIDGET_GTK)
// set/get nsPluginNativeWindowGtk, e10s specific
#define NS_NATIVE_PLUGIN_OBJECT_PTR 104
#endif
// See RegisterPluginWindowForRemoteUpdates
#define NS_NATIVE_PLUGIN_ID 105
#define NS_IWIDGET_IID \
-{ 0x53376F57, 0xF081, 0x4949, \
- { 0xB5, 0x5E, 0x87, 0xEF, 0x6A, 0xE9, 0xE3, 0x5A } };
+{ 0x22b4504e, 0xddba, 0x4211, \
+ { 0xa1, 0x49, 0x6e, 0x11, 0x73, 0xc4, 0x11, 0x45 } };
/*
* Window shadow styles
* Also used for the -moz-window-shadow CSS property
*/
#define NS_STYLE_WINDOW_SHADOW_NONE 0
#define NS_STYLE_WINDOW_SHADOW_DEFAULT 1
@@ -1580,28 +1581,43 @@ class nsIWidget : public nsISupports {
virtual void SetUseBrightTitlebarForeground(bool aBrightForeground) {}
/**
* Hide window chrome (borders, buttons) for this widget.
*
*/
NS_IMETHOD HideWindowChrome(bool aShouldHide) = 0;
+ enum FullscreenTransitionStage
+ {
+ eBeforeFullscreenToggle,
+ eAfterFullscreenToggle
+ };
+
/**
- * Ask the widget to start the transition for entering or exiting
- * DOM Fullscreen.
- *
- * XXX This method is currently not actually implemented by any
- * widget. The only function of this method is to notify cocoa
- * window that it should not use the native fullscreen mode. This
- * method is reserved for bug 1160014 where a transition will be
- * added for DOM fullscreen. Hence, this function is likely to
- * be further changed then.
+ * Prepares for fullscreen transition and returns whether the widget
+ * supports fullscreen transition. If this method returns false,
+ * PerformFullscreenTransition() must never be called. Otherwise,
+ * caller should call that method twice with "before" and "after"
+ * stages respectively in order. In the latter case, this method may
+ * return some data via aData pointer. Caller must pass that data to
+ * PerformFullscreenTransition() if any, and caller is responsible
+ * for releasing that data.
*/
- virtual void PrepareForDOMFullscreenTransition() = 0;
+ virtual bool PrepareForFullscreenTransition(nsISupports** aData) = 0;
+
+ /**
+ * Performs fullscreen transition. This method returns immediately,
+ * and will post aCallback to the main thread when the transition
+ * finishes.
+ */
+ virtual void PerformFullscreenTransition(FullscreenTransitionStage aStage,
+ uint16_t aDuration,
+ nsISupports* aData,
+ 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.
*/