Bug 1276537 part 1 - Make resizable window on macOS always show full screen button. r=spohl

Differential Revision: https://phabricator.services.mozilla.com/D74833
This commit is contained in:
Xidorn Quan 2020-05-15 06:19:14 +00:00
Родитель 80d3b6bc61
Коммит 58b03accf4
6 изменённых файлов: 80 добавлений и 97 удалений

Просмотреть файл

@ -30,20 +30,36 @@ var timeoutID;
var eventOffsetX = 2; var eventOffsetX = 2;
var eventOffsetY = 2; var eventOffsetY = 2;
let sizemodeChanged = false;
let fullscreenChanged = false;
let childHasFocused = false;
function openFullscreenWindow() { function openFullscreenWindow() {
win = window.docShell.rootTreeItem.domWindow win = window.docShell.rootTreeItem.domWindow
.openDialog("bug665540_window.xhtml", "_blank", "resizable=yes,chrome", window); .openDialog("bug665540_window.xhtml", "_blank", "resizable=yes,chrome", window);
win.addEventListener("sizemodechange",
function() {
info("sizemodechange. windowState = " + win.windowState + " fullScreen = " + win.fullScreen);
});
win.addEventListener("fullscreen",
function() {
info("fullscreen event. windowState = " + win.windowState + " fullScreen = " + win.fullScreen);
});
info("win.windowState = " + win.windowState); info("win.windowState = " + win.windowState);
info("win.fullScreen = " + win.fullScreen); info("win.fullScreen = " + win.fullScreen);
// size mode and full screen may change asynchronously after child gets focused.
if (win.windowState == win.STATE_FULLSCREEN) {
sizemodeChanged = true;
} else {
win.addEventListener("sizemodechange", () => {
info("sizemodechange. windowState = " + win.windowState + " fullScreen = " + win.fullScreen);
sizemodeChanged = true;
tryStart();
}, { once: true });
}
if (win.fullScreen) {
fullscreenChanged = true;
} else {
win.addEventListener("fullscreen", () => {
info("fullscreen event. windowState = " + win.windowState + " fullScreen = " + win.fullScreen);
fullscreenChanged = true;
tryStart();
}, { once: true });
}
// Close our window if the test times out so that it doesn't interfere // Close our window if the test times out so that it doesn't interfere
// with later tests. // with later tests.
timeoutID = setTimeout(function () { timeoutID = setTimeout(function () {
@ -54,9 +70,15 @@ function openFullscreenWindow() {
} }
function childFocused() { function childFocused() {
ok(win.fullScreen, "window should be fullscreen"); info("child focused. windowState = " + win.windowState + " fullScreen = " + win.fullScreen);
is(win.windowState, win.STATE_FULLSCREEN, childHasFocused = true;
"window state should be fullscreen"); tryStart();
}
function tryStart() {
if (!sizemodeChanged || !fullscreenChanged || !childHasFocused) {
return;
}
// The select doesn't open if the mouse click is fired too soon // The select doesn't open if the mouse click is fired too soon
// (on X11 at least). // (on X11 at least).

Просмотреть файл

@ -27,7 +27,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1104916
}); });
// Chrome test run tests in iframe, and fullscreen is disabled by default. // Chrome test run tests in iframe, and fullscreen is disabled by default.
// So run the test in a separate window. // So run the test in a separate window.
window.open("display_mode.html", "display_mode", "width=500,height=500"); window.open("display_mode.html", "display_mode", "width=500,height=500,resizable");
} }
</script> </script>
</head> </head>

Просмотреть файл

@ -27,7 +27,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1256084
}); });
// Chrome test run tests in iframe, and fullscreen is disabled by default. // Chrome test run tests in iframe, and fullscreen is disabled by default.
// So run the test in a separate window. // So run the test in a separate window.
window.open("display_mode_reflow.html", "display_mode_reflow", "width=500,height=500"); window.open("display_mode_reflow.html", "display_mode_reflow", "width=500,height=500,resizable");
} }
</script> </script>
</head> </head>

Просмотреть файл

@ -302,7 +302,6 @@ class nsCocoaWindow final : public nsBaseWidget, public nsPIWidgetCocoa {
virtual void SetWindowTransform(const mozilla::gfx::Matrix& aTransform) override; virtual void SetWindowTransform(const mozilla::gfx::Matrix& aTransform) override;
virtual void SetWindowMouseTransparent(bool aIsTransparent) override; virtual void SetWindowMouseTransparent(bool aIsTransparent) override;
virtual void SetShowsToolbarButton(bool aShow) override; virtual void SetShowsToolbarButton(bool aShow) override;
virtual void SetShowsFullScreenButton(bool aShow) override;
virtual void SetWindowAnimationType(WindowAnimationType aType) override; virtual void SetWindowAnimationType(WindowAnimationType aType) override;
virtual void SetDrawsTitle(bool aDrawTitle) override; virtual void SetDrawsTitle(bool aDrawTitle) override;
virtual void SetUseBrightTitlebarForeground(bool aBrightForeground) override; virtual void SetUseBrightTitlebarForeground(bool aBrightForeground) override;
@ -387,8 +386,6 @@ class nsCocoaWindow final : public nsBaseWidget, public nsPIWidgetCocoa {
bool mModal; bool mModal;
bool mFakeModal; bool mFakeModal;
// Only true on 10.7+ if SetShowsFullScreenButton(true) is called.
bool mSupportsNativeFullScreen;
// Whether we are currently using native fullscreen. It could be false because // Whether we are currently using native fullscreen. It could be false because
// we are in the DOM fullscreen where we do not use the native fullscreen. // we are in the DOM fullscreen where we do not use the native fullscreen.
bool mInNativeFullScreenMode; bool mInNativeFullScreenMode;

Просмотреть файл

@ -158,7 +158,6 @@ nsCocoaWindow::nsCocoaWindow()
mInFullScreenTransition(false), mInFullScreenTransition(false),
mModal(false), mModal(false),
mFakeModal(false), mFakeModal(false),
mSupportsNativeFullScreen(false),
mInNativeFullScreenMode(false), mInNativeFullScreenMode(false),
mIsAnimationSuppressed(false), mIsAnimationSuppressed(false),
mInReportMoveEvent(false), mInReportMoveEvent(false),
@ -494,12 +493,15 @@ nsresult nsCocoaWindow::CreateNativeWindow(const NSRect& aRect, nsBorderStyle aB
[mWindow setOpaque:YES]; [mWindow setOpaque:YES];
} }
NSWindowCollectionBehavior newBehavior = [mWindow collectionBehavior];
if (mAlwaysOnTop) { if (mAlwaysOnTop) {
[mWindow setLevel:NSFloatingWindowLevel]; [mWindow setLevel:NSFloatingWindowLevel];
NSWindowCollectionBehavior newBehavior = [mWindow collectionBehavior];
newBehavior |= NSWindowCollectionBehaviorCanJoinAllSpaces; newBehavior |= NSWindowCollectionBehaviorCanJoinAllSpaces;
[mWindow setCollectionBehavior:newBehavior];
} }
if ((features & NSResizableWindowMask)) {
newBehavior |= NSWindowCollectionBehaviorFullScreenPrimary;
}
[mWindow setCollectionBehavior:newBehavior];
[mWindow setContentMinSize:NSMakeSize(60, 60)]; [mWindow setContentMinSize:NSMakeSize(60, 60)];
[mWindow disableCursorRects]; [mWindow disableCursorRects];
@ -1578,10 +1580,6 @@ void nsCocoaWindow::UpdateFullscreenState(bool aFullScreen, bool aNativeMode) {
inline bool nsCocoaWindow::ShouldToggleNativeFullscreen(bool aFullScreen, inline bool nsCocoaWindow::ShouldToggleNativeFullscreen(bool aFullScreen,
bool aUseSystemTransition) { bool aUseSystemTransition) {
if (!mSupportsNativeFullScreen) {
// If we cannot use native fullscreen, don't touch it.
return false;
}
if (mInNativeFullScreenMode) { if (mInNativeFullScreenMode) {
// If we are using native fullscreen, go ahead to exit it. // If we are using native fullscreen, go ahead to exit it.
return true; return true;
@ -1621,14 +1619,6 @@ nsresult nsCocoaWindow::DoMakeFullScreen(bool aFullScreen, bool aUseSystemTransi
mInFullScreenTransition = true; mInFullScreenTransition = true;
if (ShouldToggleNativeFullscreen(aFullScreen, aUseSystemTransition)) { if (ShouldToggleNativeFullscreen(aFullScreen, aUseSystemTransition)) {
// If we're using native fullscreen mode and our native window is invisible,
// our attempt to go into fullscreen mode will fail with an assertion in
// system code, without [WindowDelegate windowDidFailToEnterFullScreen:]
// ever getting called. To pre-empt this we bail here. See bug 752294.
if (aFullScreen && ![mWindow isVisible]) {
EnteredFullScreen(false);
return NS_OK;
}
MOZ_ASSERT(mInNativeFullScreenMode != aFullScreen, MOZ_ASSERT(mInNativeFullScreenMode != aFullScreen,
"We shouldn't have been in native fullscreen."); "We shouldn't have been in native fullscreen.");
// Calling toggleFullScreen will result in windowDid(FailTo)?(Enter|Exit)FullScreen // Calling toggleFullScreen will result in windowDid(FailTo)?(Enter|Exit)FullScreen
@ -2307,41 +2297,6 @@ void nsCocoaWindow::SetShowsToolbarButton(bool aShow) {
NS_OBJC_END_TRY_ABORT_BLOCK; NS_OBJC_END_TRY_ABORT_BLOCK;
} }
void nsCocoaWindow::SetShowsFullScreenButton(bool aShow) {
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
if (!mWindow || ![mWindow respondsToSelector:@selector(toggleFullScreen:)] ||
mSupportsNativeFullScreen == aShow) {
return;
}
// If the window is currently in fullscreen mode, then we're going to
// transition out first, then set the collection behavior & toggle
// mSupportsNativeFullScreen, then transtion back into fullscreen mode. This
// prevents us from getting into a conflicting state with MakeFullScreen
// where mSupportsNativeFullScreen would lead us down the wrong path.
bool wasFullScreen = mInFullScreenMode;
if (wasFullScreen) {
MakeFullScreen(false);
}
NSWindowCollectionBehavior newBehavior = [mWindow collectionBehavior];
if (aShow) {
newBehavior |= NSWindowCollectionBehaviorFullScreenPrimary;
} else {
newBehavior &= ~NSWindowCollectionBehaviorFullScreenPrimary;
}
[mWindow setCollectionBehavior:newBehavior];
mSupportsNativeFullScreen = aShow;
if (wasFullScreen) {
MakeFullScreen(true);
}
NS_OBJC_END_TRY_ABORT_BLOCK;
}
void nsCocoaWindow::SetWindowAnimationType(nsIWidget::WindowAnimationType aType) { void nsCocoaWindow::SetWindowAnimationType(nsIWidget::WindowAnimationType aType) {
mAnimationType = aType; mAnimationType = aType;
} }

Просмотреть файл

@ -27,41 +27,50 @@ function isnot(aLeft, aRight, aMessage)
window.arguments[0].SimpleTest.isnot(aLeft, aRight, aMessage); window.arguments[0].SimpleTest.isnot(aLeft, aRight, aMessage);
} }
function executeSoon(aFct) function executeSoon() {
{ return new Promise(resolve => {
window.arguments[0].SimpleTest.executeSoon(aFct); window.arguments[0].SimpleTest.executeSoon(resolve);
});
} }
function start() { function waitForEvent(obj, name) {
window.onfocus = function () { return new Promise(resolve => {
window.onfocus = null; obj.addEventListener(name, resolve, { once: true });
var oldOuterWidth = window.outerWidth, oldOuterHeight = window.outerHeight; });
var oldInnerWidth = window.innerWidth, oldInnerHeight = window.innerHeight; }
document.documentElement.setAttribute("drawintitlebar", "true");
executeSoon(function() { async function start() {
is(window.outerWidth, oldOuterWidth, "drawintitlebar shouldn't change the window's outerWidth"); await waitForEvent(window, "focus");
is(window.outerHeight, oldOuterHeight, "drawintitlebar shouldn't change the window's outerHeight"); var oldOuterWidth = window.outerWidth, oldOuterHeight = window.outerHeight;
is(window.innerWidth, oldOuterWidth, "if drawintitlebar is set, innerWidth and outerWidth should be the same"); var oldInnerWidth = window.innerWidth, oldInnerHeight = window.innerHeight;
is(window.innerHeight, oldOuterHeight, "if drawintitlebar is set, innerHeight and outerHeight should be the same"); document.documentElement.setAttribute("drawintitlebar", "true");
window.fullScreen = true;
window.fullScreen = false;
is(window.outerWidth, oldOuterWidth, "wrong outerWidth after fullscreen mode");
is(window.outerHeight, oldOuterHeight, "wrong outerHeight after fullscreen mode");
is(window.innerWidth, oldOuterWidth, "wrong innerWidth after fullscreen mode");
is(window.innerHeight, oldOuterHeight, "wrong innerHeight after fullscreen mode");
document.documentElement.removeAttribute("drawintitlebar");
executeSoon(function() { await executeSoon();
is(window.outerWidth, oldOuterWidth, "wrong outerWidth after removing drawintitlebar"); is(window.outerWidth, oldOuterWidth, "drawintitlebar shouldn't change the window's outerWidth");
is(window.outerHeight, oldOuterHeight, "wrong outerHeight after removing drawintitlebar"); is(window.outerHeight, oldOuterHeight, "drawintitlebar shouldn't change the window's outerHeight");
is(window.innerWidth, oldInnerWidth, "wrong innerWidth after removing drawintitlebar"); is(window.innerWidth, oldOuterWidth, "if drawintitlebar is set, innerWidth and outerWidth should be the same");
is(window.innerHeight, oldInnerHeight, "wrong innerHeight after removing drawintitlebar"); is(window.innerHeight, oldOuterHeight, "if drawintitlebar is set, innerHeight and outerHeight should be the same");
window.arguments[0].SimpleTest.finish();
window.close(); // Wait for going full screen and back.
}); let sizemodeChange = waitForEvent(window, "sizemodechange");
}); window.fullScreen = true;
} await sizemodeChange;
sizemodeChange = waitForEvent(window, "sizemodechange");
window.fullScreen = false;
await sizemodeChange;
is(window.outerWidth, oldOuterWidth, "wrong outerWidth after fullscreen mode");
is(window.outerHeight, oldOuterHeight, "wrong outerHeight after fullscreen mode");
is(window.innerWidth, oldOuterWidth, "wrong innerWidth after fullscreen mode");
is(window.innerHeight, oldOuterHeight, "wrong innerHeight after fullscreen mode");
document.documentElement.removeAttribute("drawintitlebar");
await executeSoon();
is(window.outerWidth, oldOuterWidth, "wrong outerWidth after removing drawintitlebar");
is(window.outerHeight, oldOuterHeight, "wrong outerHeight after removing drawintitlebar");
is(window.innerWidth, oldInnerWidth, "wrong innerWidth after removing drawintitlebar");
is(window.innerHeight, oldInnerHeight, "wrong innerHeight after removing drawintitlebar");
window.arguments[0].SimpleTest.finish();
window.close();
} }