Bug 1446264 part 4 - Delay handling of WM_SETFOCUS after we explicit show the window. r?jimm
With the previous patch, we now may activate a window which we still
consider invisible, that brings the focus to the new window. This leads
to extra reflow in window open path because focus manager now dispatches
event which it didn't when the window doesn't have focus.
This patch delays WM_SETFOCUS until nsWindow::Show is invoked, so that
focus would not be set on an "invisible" window.
MozReview-Commit-ID: 2a7zPUWm9DA
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -610,16 +610,17 @@ nsWindow::nsWindow(bool aIsChildWindow)
mFutureMarginsToUse = false;
mCustomNonClient = false;
mHideChrome = false;
mFullscreenMode = false;
mMousePresent = false;
mDestroyCalled = false;
mHasTaskbarIconBeenCreated = false;
mMouseTransparent = false;
+ mDelayedFocus = false;
mPickerDisplayCount = 0;
mWindowType = eWindowType_child;
mBorderStyle = eBorderStyle_default;
mOldSizeMode = nsSizeMode_Normal;
mLastSizeMode = nsSizeMode_Normal;
mLastSize.width = 0;
mLastSize.height = 0;
mOldStyle = 0;
@@ -1616,16 +1617,20 @@ nsWindow::Show(bool bState)
::SetWindowPos(mWnd, HWND_TOP, 0, 0, 0, 0, flags);
}
}
if (!wasVisible && (mWindowType == eWindowType_toplevel || mWindowType == eWindowType_dialog)) {
// when a toplevel window or dialog is shown, initialize the UI state
::SendMessageW(mWnd, WM_CHANGEUISTATE, MAKEWPARAM(UIS_INITIALIZE, UISF_HIDEFOCUS | UISF_HIDEACCEL), 0);
}
+ if (mDelayedFocus) {
+ mDelayedFocus = false;
+ ::SendMessageW(mWnd, WM_SETFOCUS, 0, 0);
+ }
} else {
// Clear contents to avoid ghosting of old content if we display
// this window again.
if (wasVisible && mTransparencyMode == eTransparencyTransparent) {
if (mCompositorWidgetDelegate) {
mCompositorWidgetDelegate->ClearTransparentWindow();
}
}
@@ -5992,16 +5997,20 @@ nsWindow::ProcessMessage(UINT msg, WPARA
std::min((int32_t)mmi->ptMaxTrackSize.y,
std::max((int32_t)mmi->ptMinTrackSize.y, mSizeConstraints.mMinSize.height));
mmi->ptMaxTrackSize.x = std::min((int32_t)mmi->ptMaxTrackSize.x, mSizeConstraints.mMaxSize.width);
mmi->ptMaxTrackSize.y = std::min((int32_t)mmi->ptMaxTrackSize.y, mSizeConstraints.mMaxSize.height);
}
break;
case WM_SETFOCUS:
+ if (!mIsVisible) {
+ mDelayedFocus = true;
+ break;
+ }
// If previous focused window isn't ours, it must have received the
// redirected message. So, we should forget it.
if (!WinUtils::IsOurProcessWindow(HWND(wParam))) {
RedirectedKeyDownMessageManager::Forget();
}
if (sJustGotActivate) {
DispatchFocusToTopLevelWindow(true);
}
--- a/widget/windows/nsWindow.h
+++ b/widget/windows/nsWindow.h
@@ -541,16 +541,17 @@ protected:
bool mTouchWindow;
bool mDisplayPanFeedback;
bool mHideChrome;
bool mIsRTL;
bool mFullscreenMode;
bool mMousePresent;
bool mDestroyCalled;
bool mOpeningAnimationSuppressed;
+ bool mDelayedFocus;
uint32_t mBlurSuppressLevel;
DWORD_PTR mOldStyle;
DWORD_PTR mOldExStyle;
nsNativeDragTarget* mNativeDragTarget;
HKL mLastKeyboardLayout;
nsSizeMode mOldSizeMode;
nsSizeMode mLastSizeMode;
WindowHook mWindowHook;