зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1708324 - [Fission] Full screen button for YouTube video embedded on Reddit doesn't work r=spohl
During fullscreen transitions on Mac, ignore occlusion events caused by the widget DOM fullscreen transition effect which uses a temporary window. Add a test that attempts to enter fullscreen from a non-focused window. This test is to ensure the fix (and future fixes) do not regress the focus requirement for fullscreen. Differential Revision: https://phabricator.services.mozilla.com/D115046
This commit is contained in:
Родитель
30aa92212a
Коммит
e84c0b8236
|
@ -0,0 +1,24 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Focus test - child window</title>
|
||||||
|
<script type="application/javascript" src="file_fullscreen-utils.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<script type="application/javascript">
|
||||||
|
|
||||||
|
function enterFullscreen() {
|
||||||
|
addFullscreenErrorContinuation(() => { opener.enteredFullscreen(false); });
|
||||||
|
|
||||||
|
addFullscreenChangeContinuation("enter", () => {
|
||||||
|
opener.enteredFullscreen(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.body.requestFullscreen();
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,67 @@
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Test that a fullscreen request fails if the window is not focused.
|
||||||
|
|
||||||
|
Open window1, open window2, focus window2, and then attempt to fullscreen
|
||||||
|
window1 while it is not focused. The fullscreen attempt should be rejected
|
||||||
|
because the window is not focused.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<title>Test fullscreen request is blocked when window is not focused</title>
|
||||||
|
<script src="/tests/SimpleTest/EventUtils.js"></script>
|
||||||
|
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||||
|
<script type="application/javascript" src="file_fullscreen-utils.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<script type="application/javascript">
|
||||||
|
|
||||||
|
function ok(condition, msg) {
|
||||||
|
opener.ok(condition, "[focus] " + msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
var window1, window2;
|
||||||
|
|
||||||
|
function openWindow() {
|
||||||
|
var w = window.open("file_fullscreen-focus-inner.html", "",
|
||||||
|
"width=500,height=500");
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
function begin() {
|
||||||
|
window1 = openWindow();
|
||||||
|
window1.focus();
|
||||||
|
|
||||||
|
SimpleTest.waitForFocus(function(){
|
||||||
|
window2 = openWindow();
|
||||||
|
window2.focus();
|
||||||
|
|
||||||
|
SimpleTest.waitForFocus(function(){
|
||||||
|
// Now that window2 is focused, attempt to fullscreen window1.
|
||||||
|
// This should fail.
|
||||||
|
window1.enterFullscreen("one");
|
||||||
|
}, window2);
|
||||||
|
|
||||||
|
}, window1);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function enteredFullscreen(enteredSuccessfully) {
|
||||||
|
ok(!enteredSuccessfully, "window1 did not enter fullscreen");
|
||||||
|
|
||||||
|
if (enteredSuccessfully) {
|
||||||
|
await window1.document.exitFullscreen()
|
||||||
|
}
|
||||||
|
|
||||||
|
window1.close();
|
||||||
|
window2.close();
|
||||||
|
opener.nextTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</pre>
|
||||||
|
<div id="full-screen-element"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -451,6 +451,8 @@ support-files =
|
||||||
file_fullscreen-event-order.html
|
file_fullscreen-event-order.html
|
||||||
file_fullscreen-featurePolicy.html
|
file_fullscreen-featurePolicy.html
|
||||||
file_fullscreen-featurePolicy-inner.html
|
file_fullscreen-featurePolicy-inner.html
|
||||||
|
file_fullscreen-focus.html
|
||||||
|
file_fullscreen-focus-inner.html
|
||||||
file_fullscreen-hidden.html
|
file_fullscreen-hidden.html
|
||||||
file_fullscreen-lenient-setters.html
|
file_fullscreen-lenient-setters.html
|
||||||
file_fullscreen-multiple-inner.html
|
file_fullscreen-multiple-inner.html
|
||||||
|
|
|
@ -36,6 +36,7 @@ var gTestWindows = [
|
||||||
{ test: "file_fullscreen-denied.html" },
|
{ test: "file_fullscreen-denied.html" },
|
||||||
{ test: "file_fullscreen-api.html" },
|
{ test: "file_fullscreen-api.html" },
|
||||||
{ test: "file_fullscreen-hidden.html" },
|
{ test: "file_fullscreen-hidden.html" },
|
||||||
|
{ test: "file_fullscreen-focus.html" },
|
||||||
{ test: "file_fullscreen-svg-element.html" },
|
{ test: "file_fullscreen-svg-element.html" },
|
||||||
{ test: "file_fullscreen-navigation.html" },
|
{ test: "file_fullscreen-navigation.html" },
|
||||||
{ test: "file_fullscreen-scrollbar.html" },
|
{ test: "file_fullscreen-scrollbar.html" },
|
||||||
|
|
|
@ -265,6 +265,7 @@ class nsCocoaWindow final : public nsBaseWidget, public nsPIWidgetCocoa {
|
||||||
virtual bool PrepareForFullscreenTransition(nsISupports** aData) override;
|
virtual bool PrepareForFullscreenTransition(nsISupports** aData) override;
|
||||||
virtual void PerformFullscreenTransition(FullscreenTransitionStage aStage, uint16_t aDuration,
|
virtual void PerformFullscreenTransition(FullscreenTransitionStage aStage, uint16_t aDuration,
|
||||||
nsISupports* aData, nsIRunnable* aCallback) override;
|
nsISupports* aData, nsIRunnable* aCallback) override;
|
||||||
|
virtual void CleanupFullscreenTransition() override;
|
||||||
nsresult MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen = nullptr) final;
|
nsresult MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen = nullptr) final;
|
||||||
nsresult MakeFullScreenWithNativeTransition(bool aFullScreen,
|
nsresult MakeFullScreenWithNativeTransition(bool aFullScreen,
|
||||||
nsIScreen* aTargetScreen = nullptr) final;
|
nsIScreen* aTargetScreen = nullptr) final;
|
||||||
|
@ -409,6 +410,12 @@ class nsCocoaWindow final : public nsBaseWidget, public nsPIWidgetCocoa {
|
||||||
bool mInFullScreenMode;
|
bool mInFullScreenMode;
|
||||||
bool mInFullScreenTransition; // true from the request to enter/exit fullscreen
|
bool mInFullScreenTransition; // true from the request to enter/exit fullscreen
|
||||||
// (MakeFullScreen() call) to EnteredFullScreen()
|
// (MakeFullScreen() call) to EnteredFullScreen()
|
||||||
|
|
||||||
|
// Ignore occlusion events caused by displaying the temporary fullscreen
|
||||||
|
// window during the fullscreen transition animation because only focused
|
||||||
|
// contexts are permitted to enter DOM fullscreen.
|
||||||
|
int mIgnoreOcclusionCount;
|
||||||
|
|
||||||
bool mModal;
|
bool mModal;
|
||||||
bool mFakeModal;
|
bool mFakeModal;
|
||||||
|
|
||||||
|
|
|
@ -136,6 +136,7 @@ nsCocoaWindow::nsCocoaWindow()
|
||||||
mSheetNeedsShow(false),
|
mSheetNeedsShow(false),
|
||||||
mInFullScreenMode(false),
|
mInFullScreenMode(false),
|
||||||
mInFullScreenTransition(false),
|
mInFullScreenTransition(false),
|
||||||
|
mIgnoreOcclusionCount(0),
|
||||||
mModal(false),
|
mModal(false),
|
||||||
mFakeModal(false),
|
mFakeModal(false),
|
||||||
mInNativeFullScreenMode(false),
|
mInNativeFullScreenMode(false),
|
||||||
|
@ -1516,6 +1517,17 @@ static bool AlwaysUsesNativeFullScreen() {
|
||||||
if (AlwaysUsesNativeFullScreen()) {
|
if (AlwaysUsesNativeFullScreen()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Our fullscreen transition creates a new window occluding this window.
|
||||||
|
// That triggers an occlusion event which can cause DOM fullscreen requests
|
||||||
|
// to fail due to the context not being focused at the time the focus check
|
||||||
|
// is performed in the child process. Until the transition is cleaned up in
|
||||||
|
// CleanupFullscreenTransition(), ignore occlusion events for this window.
|
||||||
|
// If this method is changed to return false, the transition will not be
|
||||||
|
// performed and mIgnoreOcclusionCount should not be incremented.
|
||||||
|
MOZ_ASSERT(mIgnoreOcclusionCount >= 0);
|
||||||
|
mIgnoreOcclusionCount++;
|
||||||
|
|
||||||
nsCOMPtr<nsIScreen> widgetScreen = GetWidgetScreen();
|
nsCOMPtr<nsIScreen> widgetScreen = GetWidgetScreen();
|
||||||
NSScreen* cocoaScreen = ScreenHelperCocoa::CocoaScreenForScreen(widgetScreen);
|
NSScreen* cocoaScreen = ScreenHelperCocoa::CocoaScreenForScreen(widgetScreen);
|
||||||
|
|
||||||
|
@ -1535,6 +1547,11 @@ static bool AlwaysUsesNativeFullScreen() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* virtual */ void nsCocoaWindow::CleanupFullscreenTransition() {
|
||||||
|
MOZ_ASSERT(mIgnoreOcclusionCount > 0);
|
||||||
|
mIgnoreOcclusionCount--;
|
||||||
|
}
|
||||||
|
|
||||||
/* virtual */ void nsCocoaWindow::PerformFullscreenTransition(FullscreenTransitionStage aStage,
|
/* virtual */ void nsCocoaWindow::PerformFullscreenTransition(FullscreenTransitionStage aStage,
|
||||||
uint16_t aDuration,
|
uint16_t aDuration,
|
||||||
nsISupports* aData,
|
nsISupports* aData,
|
||||||
|
@ -2048,6 +2065,11 @@ void nsCocoaWindow::DispatchOcclusionEvent() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MOZ_ASSERT(mIgnoreOcclusionCount >= 0);
|
||||||
|
if (newOcclusionState && mIgnoreOcclusionCount > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mIsFullyOccluded = newOcclusionState;
|
mIsFullyOccluded = newOcclusionState;
|
||||||
if (mWidgetListener) {
|
if (mWidgetListener) {
|
||||||
mWidgetListener->OcclusionStateChanged(mIsFullyOccluded);
|
mWidgetListener->OcclusionStateChanged(mIsFullyOccluded);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче