diff --git a/toolkit/content/widgets/dialog.js b/toolkit/content/widgets/dialog.js index 862f891154e9..6a32efc7f6c2 100644 --- a/toolkit/content/widgets/dialog.js +++ b/toolkit/content/widgets/dialog.js @@ -196,6 +196,8 @@ return this.shadowRoot.querySelector(".dialog-button-box"); } + // NOTE(emilio): This has to match AppWindow::IntrinsicallySizeShell, to + // prevent flickering, see bug 1799394. _sizeToPreferredSize() { const docEl = document.documentElement; const prefWidth = (() => { diff --git a/xpcom/ds/StaticAtoms.py b/xpcom/ds/StaticAtoms.py index b680e87ea4fd..af190caa7682 100644 --- a/xpcom/ds/StaticAtoms.py +++ b/xpcom/ds/StaticAtoms.py @@ -1012,9 +1012,10 @@ STATIC_ATOMS = [ Atom("prefersReducedMotion", "prefers-reduced-motion"), Atom("prefersColorScheme", "prefers-color-scheme"), Atom("prefersContrast", "prefers-contrast"), + Atom("prefix", "prefix"), + Atom("prefwidth", "prefwidth"), Atom("dynamicRange", "dynamic-range"), Atom("videoDynamicRange", "video-dynamic-range"), - Atom("prefix", "prefix"), Atom("preload", "preload"), Atom("preserve", "preserve"), Atom("preserveSpace", "preserve-space"), diff --git a/xpfe/appshell/AppWindow.cpp b/xpfe/appshell/AppWindow.cpp index 116c23d01d58..4e1331fdb443 100644 --- a/xpfe/appshell/AppWindow.cpp +++ b/xpfe/appshell/AppWindow.cpp @@ -2598,6 +2598,55 @@ void AppWindow::LoadPersistentWindowState() { loadValue(nsGkAtoms::sizemode); } +void AppWindow::IntrinsicallySizeShell(const CSSIntSize& aWindowDiff, + int32_t& aSpecWidth, + int32_t& aSpecHeight) { + nsCOMPtr cv; + mDocShell->GetContentViewer(getter_AddRefs(cv)); + if (!cv) { + return; + } + RefPtr docShell = mDocShell; + nsCOMPtr treeOwner; + docShell->GetTreeOwner(getter_AddRefs(treeOwner)); + if (!treeOwner) { + return; + } + + CSSIntCoord maxWidth = 0; + CSSIntCoord maxHeight = 0; + CSSIntCoord prefWidth = 0; + if (RefPtr element = GetWindowDOMElement()) { + nsAutoString prefWidthAttr; + if (element->GetAttr(nsGkAtoms::prefwidth, prefWidthAttr)) { + // TODO: Make this more generic perhaps? + if (prefWidthAttr.EqualsLiteral("min-width")) { + if (auto* f = element->GetPrimaryFrame(FlushType::Frames)) { + const auto& coord = f->StylePosition()->mMinWidth; + if (coord.ConvertsToLength()) { + prefWidth = CSSPixel::FromAppUnitsRounded(coord.ToLength()); + } + } + } + } + } + + Maybe size = cv->GetContentSize(maxWidth, maxHeight, prefWidth); + if (!size) { + return; + } + nsPresContext* pc = cv->GetPresContext(); + MOZ_ASSERT(pc, "Should have pres context"); + + int32_t width = pc->CSSPixelsToDevPixels(size->width); + int32_t height = pc->CSSPixelsToDevPixels(size->height); + treeOwner->SizeShellTo(docShell, width, height); + + // Update specified size for the final LoadPositionFromXUL call. + aSpecWidth = size->width + aWindowDiff.width; + aSpecHeight = size->height + aWindowDiff.height; +} + void AppWindow::SizeShell() { AutoRestore sizingShellFromXUL(mSizingShellFromXUL); mSizingShellFromXUL = true; @@ -2610,7 +2659,7 @@ void AppWindow::SizeShell() { windowElement->GetAttr(nsGkAtoms::windowtype, windowType); } - CSSIntSize windowDiff = GetOuterToInnerSizeDifferenceInCSSPixels( + const CSSIntSize windowDiff = GetOuterToInnerSizeDifferenceInCSSPixels( mWindow, UnscaledDevicePixelsPerCSSPixel()); // If we're using fingerprint resistance, we're going to resize the window @@ -2652,28 +2701,9 @@ void AppWindow::SizeShell() { SetSpecifiedSize(specWidth, specHeight); } + // If LoadSizeFromXUL set the size, mIntrinsicallySized will be false. if (mIntrinsicallySized) { - // (if LoadSizeFromXUL set the size, mIntrinsicallySized will be false) - nsCOMPtr cv; - mDocShell->GetContentViewer(getter_AddRefs(cv)); - if (cv) { - RefPtr docShell = mDocShell; - nsCOMPtr treeOwner; - docShell->GetTreeOwner(getter_AddRefs(treeOwner)); - if (treeOwner) { - if (Maybe size = cv->GetContentSize()) { - nsPresContext* pc = cv->GetPresContext(); - MOZ_ASSERT(pc, "Should have pres context"); - int32_t width = pc->CSSPixelsToDevPixels(size->width); - int32_t height = pc->CSSPixelsToDevPixels(size->height); - - treeOwner->SizeShellTo(docShell, width, height); - // Update specified size for the final LoadPositionFromXUL call. - specWidth = width + windowDiff.width; - specHeight = height + windowDiff.height; - } - } - } + IntrinsicallySizeShell(windowDiff, specWidth, specHeight); } // Now that we have set the window's final size, we can re-do its diff --git a/xpfe/appshell/AppWindow.h b/xpfe/appshell/AppWindow.h index 9f4eecb9294a..b0d30f3499d5 100644 --- a/xpfe/appshell/AppWindow.h +++ b/xpfe/appshell/AppWindow.h @@ -374,6 +374,10 @@ class AppWindow final : public nsIBaseWindow, WidgetListenerDelegate mWidgetListenerDelegate; private: + MOZ_CAN_RUN_SCRIPT void IntrinsicallySizeShell(const CSSIntSize& aWindowDiff, + int32_t& aSpecWidth, + int32_t& aSpecHeight); + // GetPrimaryBrowserParentSize is called from xpidl methods and we don't have // a good way to annotate those with MOZ_CAN_RUN_SCRIPT yet. It takes no // refcounted args other than "this", and the "this" uses seem ok.