Skip to content

Commit

Permalink
Bug 1751360 - Fix broken fullscreen behavior on Windows r=mhowell,han…
Browse files Browse the repository at this point in the history
…dyman

Differential Revision: https://phabricator.services.mozilla.com/D137089
  • Loading branch information
Chris Martin committed Jan 28, 2022
1 parent 73da862 commit f3b4019
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 42 deletions.
105 changes: 63 additions & 42 deletions widget/windows/nsWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2294,54 +2294,66 @@ static UINT GetCurrentShowCmd(HWND aWnd) {
return pl.showCmd;
}

// Maximize, minimize or restore the window.
void nsWindow::SetSizeMode(nsSizeMode aMode) {
// Let's not try and do anything if we're already in that state.
// (This is needed to prevent problems when calling window.minimize(), which
// calls us directly, and then the OS triggers another call to us.)
if (aMode == mSizeMode) return;

// If we are still displaying a maximized pre-XUL skeleton UI, ignore the
// noise of sizemode changes. Once we have "shown" the window for the first
// time (called nsWindow::Show(true), even though the window is already
// technically displayed), we will again accept sizemode changes.
if (mIsShowingPreXULSkeletonUI && WasPreXULSkeletonUIMaximized()) {
return;
}

void nsWindow::SetSizeModeInternal(nsSizeMode aMode) {
// save the requested state
mLastSizeMode = mSizeMode;
nsBaseWidget::SetSizeMode(aMode);
if (mIsVisible) {
int mode;

switch (aMode) {
case nsSizeMode_Fullscreen:
mode = SW_SHOW;
::ShowWindow(mWnd, SW_SHOW);
break;

case nsSizeMode_Maximized:
mode = SW_MAXIMIZE;
::ShowWindow(mWnd, SW_MAXIMIZE);
break;

case nsSizeMode_Minimized:
mode = SW_MINIMIZE;
::ShowWindow(mWnd, SW_MINIMIZE);
break;

default:
mode = SW_RESTORE;
// Don't call ::ShowWindow if we're trying to "restore" a window that is
// already in a normal state. Prevents a bug where snapping to one side
// of the screen and then minimizing would cause Windows to forget our
// window's correct restored position/size.
if (GetCurrentShowCmd(mWnd) != SW_SHOWNORMAL) {
::ShowWindow(mWnd, SW_RESTORE);
}
}
}

// Don't call ::ShowWindow if we're trying to "restore" a window that is
// already in a normal state. Prevents a bug where snapping to one side
// of the screen and then minimizing would cause Windows to forget our
// window's correct restored position/size.
if (!(GetCurrentShowCmd(mWnd) == SW_SHOWNORMAL && mode == SW_RESTORE)) {
::ShowWindow(mWnd, mode);
}
// we activate here to ensure that the right child window is focused
if (mode == SW_MAXIMIZE || mode == SW_SHOW)
DispatchFocusToTopLevelWindow(true);
// we activate here to ensure that the right child window is focused
if (mIsVisible && (aMode == nsSizeMode_Maximized || aMode == nsSizeMode_Fullscreen)) {
DispatchFocusToTopLevelWindow(true);
}
}

// Maximize, minimize or restore the window.
void nsWindow::SetSizeMode(nsSizeMode aMode) {
// If we are still displaying a maximized pre-XUL skeleton UI, ignore the
// noise of sizemode changes. Once we have "shown" the window for the first
// time (called nsWindow::Show(true), even though the window is already
// technically displayed), we will again accept sizemode changes.
if (mIsShowingPreXULSkeletonUI && WasPreXULSkeletonUIMaximized()) {
return;
}

// Let's not try and do anything if we're already in that state.
// (This is needed to prevent problems when calling window.minimize(), which
// calls us directly, and then the OS triggers another call to us.)
if (aMode == mSizeMode) return;

if (aMode == nsSizeMode_Fullscreen) {
MakeFullScreen(true, nullptr);
} else if ((mSizeMode == nsSizeMode_Fullscreen) && (aMode == nsSizeMode_Normal)) {
// If we are in fullscreen mode, minimize should work like normal and
// return us to fullscreen mode when unminimized. Maximize isn't really
// available and won't do anything. "Restore" should do the same thing as
// requesting to end fullscreen.
MakeFullScreen(false, nullptr);
} else {
SetSizeModeInternal(aMode);
}
}

Expand Down Expand Up @@ -3667,25 +3679,32 @@ void nsWindow::CleanupFullscreenTransition() {
}

nsresult nsWindow::MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen) {
// taskbarInfo will be nullptr pre Windows 7 until Bug 680227 is resolved.
nsCOMPtr<nsIWinTaskbar> taskbarInfo = do_GetService(NS_TASKBAR_CONTRACTID);
if (mFullscreenMode == aFullScreen) {
return NS_OK;
}

if (mWidgetListener) {
mWidgetListener->FullscreenWillChange(aFullScreen);
}

mFullscreenMode = aFullScreen;
if (aFullScreen) {
if (mSizeMode == nsSizeMode_Fullscreen) return NS_OK;
mOldSizeMode = mSizeMode;
SetSizeMode(nsSizeMode_Fullscreen);

// Notify the taskbar that we will be entering full screen mode.
if (taskbarInfo) {
taskbarInfo->PrepareFullScreenHWND(mWnd, TRUE);
}
SetSizeModeInternal(nsSizeMode_Fullscreen);
} else {
SetSizeMode(mOldSizeMode);
if (mSizeMode != mOldSizeMode) {
SetSizeModeInternal(mOldSizeMode);
}

MOZ_ASSERT(mSizeMode == mOldSizeMode);
}

// taskbarInfo will be nullptr pre Windows 7 until Bug 680227 is resolved.
nsCOMPtr<nsIWinTaskbar> taskbarInfo = do_GetService(NS_TASKBAR_CONTRACTID);

// Notify the taskbar that we will be entering full screen mode.
if (aFullScreen && taskbarInfo) {
taskbarInfo->PrepareFullScreenHWND(mWnd, TRUE);
}

// If we are going fullscreen, the window size continues to change
Expand All @@ -3697,7 +3716,9 @@ nsresult nsWindow::MakeFullScreen(bool aFullScreen, nsIScreen* aTargetScreen) {
// be called once per fullscreen request.
nsBaseWidget::InfallibleMakeFullScreen(aFullScreen, aTargetScreen);

if (mIsVisible && !aFullScreen && mOldSizeMode == nsSizeMode_Normal) {
if (mIsVisible && !aFullScreen && mSizeMode == nsSizeMode_Normal) {
MOZ_ASSERT(mSizeMode == mOldSizeMode);

// Ensure the window exiting fullscreen get activated. Window
// activation might be bypassed in SetSizeMode.
DispatchFocusToTopLevelWindow(true);
Expand Down
2 changes: 2 additions & 0 deletions widget/windows/nsWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,8 @@ class nsWindow final : public nsWindowBase {
const WinPointerInfo& aPointerInfo,
mozilla::MouseButton aButton);

void SetSizeModeInternal(nsSizeMode aMode);

protected:
static bool IsAsyncResponseEvent(UINT aMsg, LRESULT& aResult);
void IPCWindowProcHandler(UINT& msg, WPARAM& wParam, LPARAM& lParam);
Expand Down

0 comments on commit f3b4019

Please sign in to comment.