Skip to content

Commit

Permalink
Bug 1742421 - Part 3: [widget/windows] Exit fullscreen when changing …
Browse files Browse the repository at this point in the history
…sizemode; r=mhowell,edgar

Differential Revision: https://phabricator.services.mozilla.com/D135606
  • Loading branch information
Chris Martin committed Jan 19, 2022
1 parent 1238a22 commit b7b7c16
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 64 deletions.
138 changes: 74 additions & 64 deletions widget/windows/nsWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2294,57 +2294,107 @@ static UINT GetCurrentShowCmd(HWND aWnd) {
return pl.showCmd;
}

// Maximize, minimize or restore the window.
void nsWindow::SetSizeMode(nsSizeMode aMode) {
void nsWindow::SetSizeModeInternal(nsSizeMode aMode, nsIScreen* aFullscreenTarget) {
// 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;
const bool currentlyFullscreen = mSizeMode == nsSizeMode_Fullscreen;
const bool requestedFullscreen = aMode == nsSizeMode_Fullscreen;
const bool fullscreenChanging = currentlyFullscreen || requestedFullscreen;

MOZ_DIAGNOSTIC_ASSERT(currentlyFullscreen == mFullscreenMode);

if (fullscreenChanging) {
if (mWidgetListener) {
mWidgetListener->FullscreenWillChange(requestedFullscreen);
}

mFullscreenMode = requestedFullscreen;
}

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

if (mIsVisible) {
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;
MOZ_ASSERT(aMode == nsSizeMode_Normal);

// 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);
if (fullscreenChanging) {
// taskbarInfo will be nullptr pre Windows 7 until Bug 680227 is resolved.
nsCOMPtr<nsIWinTaskbar> taskbarInfo = do_GetService(NS_TASKBAR_CONTRACTID);

if (requestedFullscreen && taskbarInfo) {
// Notify the taskbar that we will be entering full screen mode.
taskbarInfo->PrepareFullScreenHWND(mWnd, TRUE);
}
// we activate here to ensure that the right child window is focused
if (mode == SW_MAXIMIZE || mode == SW_SHOW)

// If we are going fullscreen, the window size continues to change
// and the window will be reflow again then.
UpdateNonClientMargins(mSizeMode, /* Reflow */ !requestedFullscreen);

// Will call hide chrome, reposition window. Note this will
// also cache dimensions for restoration, so it should only
// be called once per fullscreen request.
nsBaseWidget::InfallibleMakeFullScreen(requestedFullscreen, aFullscreenTarget);

if (mIsVisible && aMode != nsSizeMode_Minimized) {
DispatchFocusToTopLevelWindow(true);
}

if (!requestedFullscreen && taskbarInfo) {
// Notify the taskbar that we have exited full screen mode.
taskbarInfo->PrepareFullScreenHWND(mWnd, FALSE);
}

OnSizeModeChange(mSizeMode);

if (mWidgetListener) {
mWidgetListener->FullscreenChanged(requestedFullscreen);
}
} else if(mIsVisible && aMode != nsSizeMode_Minimized) {
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;
}

SetSizeModeInternal(aMode, nullptr);
}

void DoGetWorkspaceID(HWND aWnd, nsAString* aWorkspaceID) {
RefPtr<IVirtualDesktopManager> desktopManager = gVirtualDesktopManager;
if (!desktopManager || !aWnd) {
Expand Down Expand Up @@ -3667,51 +3717,11 @@ 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 (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, aTargetScreen);
} else {
SetSizeMode(mOldSizeMode);
}

// If we are going fullscreen, the window size continues to change
// and the window will be reflow again then.
UpdateNonClientMargins(mSizeMode, /* Reflow */ !aFullScreen);

// Will call hide chrome, reposition window. Note this will
// also cache dimensions for restoration, so it should only
// be called once per fullscreen request.
nsBaseWidget::InfallibleMakeFullScreen(aFullScreen, aTargetScreen);

if (mIsVisible && !aFullScreen && mOldSizeMode == nsSizeMode_Normal) {
// Ensure the window exiting fullscreen get activated. Window
// activation might be bypassed in SetSizeMode.
DispatchFocusToTopLevelWindow(true);
}

// Notify the taskbar that we have exited full screen mode.
if (!aFullScreen && taskbarInfo) {
taskbarInfo->PrepareFullScreenHWND(mWnd, FALSE);
}

OnSizeModeChange(mSizeMode);

if (mWidgetListener) {
mWidgetListener->FullscreenChanged(aFullScreen);
SetSizeModeInternal(mOldSizeMode, aTargetScreen);
}

return NS_OK;
Expand Down
1 change: 1 addition & 0 deletions widget/windows/nsWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,7 @@ class nsWindow final : public nsWindowBase {
bool DispatchTouchEventFromWMPointer(UINT msg, LPARAM aLParam,
const WinPointerInfo& aPointerInfo,
mozilla::MouseButton aButton);
void SetSizeModeInternal(nsSizeMode aMode, nsIScreen* aFullscreenTarget);

protected:
static bool IsAsyncResponseEvent(UINT aMsg, LRESULT& aResult);
Expand Down

0 comments on commit b7b7c16

Please sign in to comment.