Bug 1878037 - Fix some regressions on alert windows. r=saschanaz,win-reviewers,rkraesig

Bug 1870512 removed top level windows with WindowType::Popup, instead
replacing it with an "alert" feature for the only use of them that we
had.

Turns out that on Windows they need a bit more special handling than I
thought, so this patch uses the alert boolean to fix two regressions
(that alerts now create taskbar icons, and that they steal focus).

Remove mIsForMenuPopupFrame since that is now a synonym with
WindowType::Popup.

Remove also the dialog vs. toplevel difference of using
WS_EX_DLGMODALFRAME, since that doesn't seem to have an effect at all on
windows 10+.

Differential Revision: https://phabricator.services.mozilla.com/D200508
This commit is contained in:
Emilio Cobos Álvarez 2024-02-12 19:45:48 +00:00
parent 0a93c03ada
commit f56dca9254
5 changed files with 40 additions and 30 deletions

View file

@ -268,7 +268,6 @@ nsresult nsMenuPopupFrame::CreateWidgetForView(nsView* aView) {
widget::InitData widgetData;
widgetData.mWindowType = widget::WindowType::Popup;
widgetData.mBorderStyle = widget::BorderStyle::Default;
widgetData.mForMenupopupFrame = true;
widgetData.mClipSiblings = true;
widgetData.mPopupHint = mPopupType;
widgetData.mNoAutoHide = IsNoAutoHide();

View file

@ -91,7 +91,6 @@ struct InitData {
// when painting exclude area occupied by child windows and sibling windows
bool mClipChildren = false;
bool mClipSiblings = false;
bool mForMenupopupFrame = false;
bool mRTL = false;
bool mNoAutoHide = false; // true for noautohide panels
bool mIsDragPopup = false; // true for drag feedback panels

View file

@ -868,9 +868,9 @@ nsresult nsWindow::Create(nsIWidget* aParent, nsNativeWidget aNativeParent,
}
mIsRTL = aInitData->mRTL;
mForMenupopupFrame = aInitData->mForMenupopupFrame;
mOpeningAnimationSuppressed = aInitData->mIsAnimationSuppressed;
mAlwaysOnTop = aInitData->mAlwaysOnTop;
mIsAlert = aInitData->mIsAlert;
mResizable = aInitData->mResizable;
DWORD style = WindowStyle();
@ -895,7 +895,7 @@ nsresult nsWindow::Create(nsIWidget* aParent, nsNativeWidget aNativeParent,
}
}
const wchar_t* className = ChooseWindowClass(mWindowType, mForMenupopupFrame);
const wchar_t* className = ChooseWindowClass(mWindowType);
// Take specific actions when creating the first top-level window
static bool sFirstTopLevelWindowCreated = false;
@ -1220,20 +1220,15 @@ const wchar_t* nsWindow::RegisterWindowClass(const wchar_t* aClassName,
static LPWSTR const gStockApplicationIcon = MAKEINTRESOURCEW(32512);
/* static */
const wchar_t* nsWindow::ChooseWindowClass(WindowType aWindowType,
bool aForMenupopupFrame) {
MOZ_ASSERT_IF(aForMenupopupFrame, aWindowType == WindowType::Popup);
const wchar_t* nsWindow::ChooseWindowClass(WindowType aWindowType) {
switch (aWindowType) {
case WindowType::Invisible:
return RegisterWindowClass(kClassNameHidden, 0, gStockApplicationIcon);
case WindowType::Dialog:
return RegisterWindowClass(kClassNameDialog, 0, 0);
case WindowType::Popup:
if (aForMenupopupFrame) {
return RegisterWindowClass(kClassNameDropShadow, CS_DROPSHADOW,
gStockApplicationIcon);
}
[[fallthrough]];
return RegisterWindowClass(kClassNameDropShadow, CS_DROPSHADOW,
gStockApplicationIcon);
default:
return RegisterWindowClass(GetMainWindowClass(), 0,
gStockApplicationIcon);
@ -1341,22 +1336,27 @@ DWORD nsWindow::WindowExStyle() {
case WindowType::Child:
return 0;
case WindowType::Dialog:
return WS_EX_WINDOWEDGE | WS_EX_DLGMODALFRAME;
case WindowType::Popup: {
DWORD extendedStyle = WS_EX_TOOLWINDOW;
if (mPopupLevel == PopupLevel::Top) extendedStyle |= WS_EX_TOPMOST;
if (mPopupLevel == PopupLevel::Top) {
extendedStyle |= WS_EX_TOPMOST;
}
return extendedStyle;
}
default:
NS_ERROR("unknown border style");
[[fallthrough]];
case WindowType::Sheet:
MOZ_FALLTHROUGH_ASSERT("Sheets are macOS specific");
case WindowType::Dialog:
case WindowType::TopLevel:
case WindowType::Invisible:
return WS_EX_WINDOWEDGE;
break;
}
if (mIsAlert) {
MOZ_ASSERT(mWindowType == WindowType::Dialog,
"Expect alert windows to have type=dialog");
return WS_EX_TOOLWINDOW;
}
return WS_EX_WINDOWEDGE;
}
/**************************************************************
@ -1575,9 +1575,8 @@ void nsWindow::Show(bool bState) {
#endif // defined(ACCESSIBILITY)
}
if (mForMenupopupFrame) {
MOZ_ASSERT(ChooseWindowClass(mWindowType, mForMenupopupFrame) ==
kClassNameDropShadow);
if (mWindowType == WindowType::Popup) {
MOZ_ASSERT(ChooseWindowClass(mWindowType) == kClassNameDropShadow);
const bool shouldUseDropShadow =
mTransparencyMode != TransparencyMode::Transparent;
@ -1644,8 +1643,12 @@ void nsWindow::Show(bool bState) {
}
} else {
DWORD flags = SWP_NOSIZE | SWP_NOMOVE | SWP_SHOWWINDOW;
if (wasVisible) flags |= SWP_NOZORDER;
if (mAlwaysOnTop) flags |= SWP_NOACTIVATE;
if (wasVisible) {
flags |= SWP_NOZORDER;
}
if (mAlwaysOnTop || mIsAlert) {
flags |= SWP_NOACTIVATE;
}
if (mWindowType == WindowType::Popup) {
// ensure popups are the topmost of the TOPMOST
@ -7858,7 +7861,7 @@ bool nsWindow::DealWithPopups(HWND aWnd, UINT aMessage, WPARAM aWParam,
// because we cannot distinguish it's caused by mouse or not.
if (LOWORD(aWParam) == WA_ACTIVE && aLParam) {
nsWindow* window = WinUtils::GetNSWindowPtr(aWnd);
if (window && window->IsPopup()) {
if (window && (window->IsPopup() || window->mIsAlert)) {
// Cancel notifying widget listeners of deactivating the previous
// active window (see WM_KILLFOCUS case in ProcessMessage()).
sJustGotDeactivate = false;

View file

@ -593,7 +593,7 @@ class nsWindow final : public nsBaseWidget {
DWORD WindowStyle();
DWORD WindowExStyle();
static const wchar_t* ChooseWindowClass(WindowType, bool aForMenupopupFrame);
static const wchar_t* ChooseWindowClass(WindowType);
// This method registers the given window class, and returns the class name.
static const wchar_t* RegisterWindowClass(const wchar_t* aClassName,
UINT aExtraStyle, LPWSTR aIconID);
@ -754,7 +754,10 @@ class nsWindow final : public nsBaseWidget {
bool mIsEarlyBlankWindow = false;
bool mIsShowingPreXULSkeletonUI = false;
bool mResizable = false;
bool mForMenupopupFrame = false;
// Whether we're an alert window. Alert windows don't have taskbar icons and
// don't steal focus from other windows when opened. They're also expected to
// be of type WindowType::Dialog.
bool mIsAlert = false;
bool mIsPerformingDwmFlushHack = false;
bool mDraggingWindowWithMouse = false;
DWORD_PTR mOldStyle = 0;
@ -835,7 +838,7 @@ class nsWindow final : public nsBaseWidget {
// Whether we're in the process of sending a WM_SETTEXT ourselves
bool mSendingSetText = false;
// Whether we we're created as a child window (aka ChildWindow) or not.
// Whether we were created as a child window (aka ChildWindow) or not.
bool mIsChildWindow : 1;
int32_t mCachedHitTestResult = 0;

View file

@ -571,7 +571,13 @@ nsresult nsAppShellService::JustCreateTopWindow(
}
#endif
widgetInitData.mIsAlert = !!(aChromeMask & nsIWebBrowserChrome::CHROME_ALERT);
// alert=yes is expected to be used along with dialogs, not other window
// types.
MOZ_ASSERT_IF(aChromeMask & nsIWebBrowserChrome::CHROME_ALERT,
widgetInitData.mWindowType == widget::WindowType::Dialog);
widgetInitData.mIsAlert =
!!(aChromeMask & nsIWebBrowserChrome::CHROME_ALERT) &&
widgetInitData.mWindowType == widget::WindowType::Dialog;
#ifdef XP_MACOSX
// Mac OS X sheet support