commit 3b9fd7d6dbf2f8bc0a428887a0611a66ebcbf0bd
parent e787eae82043d0ad011ca6b5f1691ebe4faf5158
Author: Emilio Cobos Álvarez <emilio@crisal.io>
Date: Fri, 14 Nov 2025 01:48:16 +0000
Bug 1999868 - Simplify PresShell's / nsViewManager resize APIs. r=tnikkel,layout-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D272384
Diffstat:
8 files changed, 86 insertions(+), 123 deletions(-)
diff --git a/layout/base/GeckoMVMContext.cpp b/layout/base/GeckoMVMContext.cpp
@@ -204,8 +204,7 @@ void GeckoMVMContext::Reflow(const CSSSize& aNewSize) {
MOZ_ASSERT(doc);
MOZ_ASSERT(ps);
- if (ps->ResizeReflowIgnoreOverride(CSSPixel::ToAppUnits(aNewSize.width),
- CSSPixel::ToAppUnits(aNewSize.height))) {
+ if (ps->ResizeReflowIgnoreOverride(CSSPixel::ToAppUnits(aNewSize))) {
doc->FlushPendingNotifications(FlushType::InterruptibleLayout);
}
}
diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp
@@ -1792,13 +1792,10 @@ void PresShell::RefreshZoomConstraintsForScreenSizeChange() {
}
void PresShell::ForceResizeReflowWithCurrentDimensions() {
- nscoord currentWidth = 0;
- nscoord currentHeight = 0;
- mViewManager->GetWindowDimensions(¤tWidth, ¤tHeight);
- ResizeReflow(currentWidth, currentHeight);
+ ResizeReflow(mViewManager->GetWindowDimensions());
}
-void PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight,
+void PresShell::ResizeReflow(const nsSize& aSize,
ResizeReflowOptions aOptions) {
if (mZoomConstraintsClient) {
// If we have a ZoomConstraintsClient and the available screen area
@@ -1816,21 +1813,21 @@ void PresShell::ResizeReflow(nscoord aWidth, nscoord aHeight,
mMobileViewportManager->RequestReflow(false);
return;
}
- ResizeReflowIgnoreOverride(aWidth, aHeight, aOptions);
+ ResizeReflowIgnoreOverride(aSize, aOptions);
}
-bool PresShell::SimpleResizeReflow(nscoord aWidth, nscoord aHeight) {
- MOZ_ASSERT(aWidth != NS_UNCONSTRAINEDSIZE);
- MOZ_ASSERT(aHeight != NS_UNCONSTRAINEDSIZE);
+bool PresShell::SimpleResizeReflow(const nsSize& aSize) {
+ MOZ_ASSERT(aSize.width != NS_UNCONSTRAINEDSIZE);
+ MOZ_ASSERT(aSize.height != NS_UNCONSTRAINEDSIZE);
nsSize oldSize = mPresContext->GetVisibleArea().Size();
- mPresContext->SetVisibleArea(nsRect(0, 0, aWidth, aHeight));
+ mPresContext->SetVisibleArea(nsRect(nsPoint(), aSize));
nsIFrame* rootFrame = GetRootFrame();
if (!rootFrame) {
return false;
}
WritingMode wm = rootFrame->GetWritingMode();
- bool isBSizeChanging =
- wm.IsVertical() ? oldSize.width != aWidth : oldSize.height != aHeight;
+ bool isBSizeChanging = wm.IsVertical() ? oldSize.width != aSize.width
+ : oldSize.height != aSize.height;
if (isBSizeChanging) {
nsLayoutUtils::MarkIntrinsicISizesDirtyIfDependentOnBSize(rootFrame);
rootFrame->SetHasBSizeChange(true);
@@ -1898,7 +1895,7 @@ void PresShell::ScheduleResizeEventIfNeeded(ResizeEventKind aKind) {
RenderingPhase::ResizeSteps);
}
-bool PresShell::ResizeReflowIgnoreOverride(nscoord aWidth, nscoord aHeight,
+bool PresShell::ResizeReflowIgnoreOverride(const nsSize& aSize,
ResizeReflowOptions aOptions) {
MOZ_ASSERT(!mIsReflowing, "Shouldn't be in reflow here!");
@@ -1922,11 +1919,11 @@ bool PresShell::ResizeReflowIgnoreOverride(nscoord aWidth, nscoord aHeight,
if (!(aOptions & ResizeReflowOptions::BSizeLimit)) {
nsSize oldSize = mPresContext->GetVisibleArea().Size();
- if (oldSize == nsSize(aWidth, aHeight)) {
+ if (oldSize == aSize) {
return false;
}
- bool changed = SimpleResizeReflow(aWidth, aHeight);
+ bool changed = SimpleResizeReflow(aSize);
postResizeEventIfNeeded();
return changed;
}
@@ -1944,31 +1941,32 @@ bool PresShell::ResizeReflowIgnoreOverride(nscoord aWidth, nscoord aHeight,
// If we don't have a root frame yet, that means we haven't had our initial
// reflow... If that's the case, and aWidth or aHeight is unconstrained,
// ignore them altogether.
- if (aHeight == NS_UNCONSTRAINEDSIZE || aWidth == NS_UNCONSTRAINEDSIZE) {
+ if (aSize.height == NS_UNCONSTRAINEDSIZE ||
+ aSize.width == NS_UNCONSTRAINEDSIZE) {
// We can't do the work needed for SizeToContent without a root
// frame, and we want to return before setting the visible area.
return false;
}
- mPresContext->SetVisibleArea(nsRect(0, 0, aWidth, aHeight));
+ mPresContext->SetVisibleArea(nsRect(nsPoint(), aSize));
// There isn't anything useful we can do if the initial reflow hasn't
// happened.
return true;
}
WritingMode wm = rootFrame->GetWritingMode();
- MOZ_ASSERT((wm.IsVertical() ? aHeight : aWidth) != NS_UNCONSTRAINEDSIZE,
- "unconstrained isize not allowed");
+ MOZ_ASSERT(
+ (wm.IsVertical() ? aSize.height : aSize.width) != NS_UNCONSTRAINEDSIZE,
+ "unconstrained isize not allowed");
- nscoord targetWidth = aWidth;
- nscoord targetHeight = aHeight;
+ nsSize targetSize = aSize;
if (wm.IsVertical()) {
- targetWidth = NS_UNCONSTRAINEDSIZE;
+ targetSize.width = NS_UNCONSTRAINEDSIZE;
} else {
- targetHeight = NS_UNCONSTRAINEDSIZE;
+ targetSize.height = NS_UNCONSTRAINEDSIZE;
}
- mPresContext->SetVisibleArea(nsRect(0, 0, targetWidth, targetHeight));
+ mPresContext->SetVisibleArea(nsRect(nsPoint(), targetSize));
// XXX Do a full invalidate at the beginning so that invalidates along
// the way don't have region accumulation issues?
@@ -1991,11 +1989,11 @@ bool PresShell::ResizeReflowIgnoreOverride(nscoord aWidth, nscoord aHeight,
DoReflow(rootFrame, true, nullptr);
const bool reflowAgain =
- wm.IsVertical() ? mPresContext->GetVisibleArea().width > aWidth
- : mPresContext->GetVisibleArea().height > aHeight;
+ wm.IsVertical() ? mPresContext->GetVisibleArea().width > aSize.width
+ : mPresContext->GetVisibleArea().height > aSize.height;
if (reflowAgain) {
- mPresContext->SetVisibleArea(nsRect(0, 0, aWidth, aHeight));
+ mPresContext->SetVisibleArea(nsRect(nsPoint(), aSize));
rootFrame->SetHasBSizeChange(true);
DoReflow(rootFrame, true, nullptr);
}
diff --git a/layout/base/PresShell.h b/layout/base/PresShell.h
@@ -359,17 +359,12 @@ class PresShell final : public nsStubDocumentObserver,
MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult Initialize();
/**
- * Schedule a reflow for the frame model into a new width and height. The
- * coordinates for aWidth and aHeight must be in standard nscoord's.
- *
- * Returns whether layout might have changed.
+ * Schedule a reflow for the frame model into a new size, in app units.
*/
MOZ_CAN_RUN_SCRIPT void ResizeReflow(
- nscoord aWidth, nscoord aHeight,
- ResizeReflowOptions = ResizeReflowOptions::NoOption);
+ const nsSize&, ResizeReflowOptions = ResizeReflowOptions::NoOption);
MOZ_CAN_RUN_SCRIPT bool ResizeReflowIgnoreOverride(
- nscoord aWidth, nscoord aHeight,
- ResizeReflowOptions = ResizeReflowOptions::NoOption);
+ const nsSize&, ResizeReflowOptions = ResizeReflowOptions::NoOption);
MOZ_CAN_RUN_SCRIPT void ForceResizeReflowWithCurrentDimensions();
/** Schedule a resize event if applicable. */
@@ -398,7 +393,7 @@ class PresShell final : public nsStubDocumentObserver,
* This is what ResizeReflowIgnoreOverride does when not shrink-wrapping (that
* is, when ResizeReflowOptions::BSizeLimit is not specified).
*/
- bool SimpleResizeReflow(nscoord aWidth, nscoord aHeight);
+ bool SimpleResizeReflow(const nsSize&);
bool CanHandleUserInputEvents(WidgetGUIEvent* aGUIEvent);
diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp
@@ -714,8 +714,7 @@ nsresult nsDocumentViewer::InitPresentationStuff(bool aDoInitialReflow) {
mPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom());
const nsSize size = LayoutDevicePixel::ToAppUnits(mBounds.Size(), p2a);
-
- mViewManager->SetWindowDimensions(size.width, size.height);
+ mViewManager->SetWindowDimensions(size);
mPresContext->SetInitialVisibleArea(nsRect(nsPoint(), size));
// We rely on the default zoom not being initialized until here.
mPresContext->RecomputeBrowsingContextDependentData();
@@ -1915,8 +1914,7 @@ nsDocumentViewer::SetBoundsWithFlags(const LayoutDeviceIntRect& aBounds,
}
int32_t p2a = mPresContext->AppUnitsPerDevPixel();
- nscoord width = NSIntPixelsToAppUnits(mBounds.width, p2a);
- nscoord height = NSIntPixelsToAppUnits(mBounds.height, p2a);
+ const nsSize size = LayoutDeviceSize::ToAppUnits(mBounds.Size(), p2a);
nsView* rootView = mViewManager->GetRootView();
if (boundsChanged && rootView) {
nsRect viewDims = rootView->GetBounds();
@@ -1929,7 +1927,7 @@ nsDocumentViewer::SetBoundsWithFlags(const LayoutDeviceIntRect& aBounds,
// if they are the same as the new size it won't do anything, but we still
// need to invalidate because what we want to draw to the screen has
// changed.
- if (viewDims.width == width && viewDims.height == height) {
+ if (viewDims.Size() == size) {
if (nsIFrame* f = rootView->GetFrame()) {
f->InvalidateFrame();
@@ -1943,7 +1941,7 @@ nsDocumentViewer::SetBoundsWithFlags(const LayoutDeviceIntRect& aBounds,
}
mViewManager->SetWindowDimensions(
- width, height, !!(aFlags & nsIDocumentViewer::eDelayResize));
+ size, !!(aFlags & nsIDocumentViewer::eDelayResize));
}
// If there's a previous viewer, it's the one that's actually showing,
@@ -2569,10 +2567,9 @@ MOZ_CAN_RUN_SCRIPT_BOUNDARY NS_IMETHODIMP nsDocumentViewer::GetContentSize(
// Just bail if that happens.
NS_ENSURE_TRUE(prefISize != NS_UNCONSTRAINEDSIZE, NS_ERROR_FAILURE);
- nscoord height = wm.IsVertical() ? prefISize : aMaxHeight;
- nscoord width = wm.IsVertical() ? aMaxWidth : prefISize;
-
- presShell->ResizeReflow(width, height, ResizeReflowOptions::BSizeLimit);
+ const nsSize size(wm.IsVertical() ? aMaxWidth : prefISize,
+ wm.IsVertical() ? prefISize : aMaxHeight);
+ presShell->ResizeReflow(size, ResizeReflowOptions::BSizeLimit);
RefPtr<nsPresContext> presContext = GetPresContext();
NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
diff --git a/layout/base/nsPresContext.cpp b/layout/base/nsPresContext.cpp
@@ -544,20 +544,16 @@ void nsPresContext::PreferenceChanged(const char* aPrefName) {
OwningNonNull<mozilla::PresShell> presShell(*mPresShell);
// Re-fetch the view manager's window dimensions in case there's a
// deferred resize which hasn't affected our mVisibleArea yet
- nscoord oldWidthAppUnits, oldHeightAppUnits;
RefPtr<nsViewManager> vm = presShell->GetViewManager();
if (!vm) {
return;
}
- vm->GetWindowDimensions(&oldWidthAppUnits, &oldHeightAppUnits);
- float oldWidthDevPixels = oldWidthAppUnits / oldAppUnitsPerDevPixel;
- float oldHeightDevPixels = oldHeightAppUnits / oldAppUnitsPerDevPixel;
+ auto oldSizeDevPixels = LayoutDeviceSize::FromAppUnits(
+ vm->GetWindowDimensions(), oldAppUnitsPerDevPixel);
UIResolutionChangedInternal();
-
- nscoord width = NSToCoordRound(oldWidthDevPixels * AppUnitsPerDevPixel());
- nscoord height = NSToCoordRound(oldHeightDevPixels * AppUnitsPerDevPixel());
- vm->SetWindowDimensions(width, height);
+ vm->SetWindowDimensions(
+ LayoutDeviceSize::ToAppUnits(oldSizeDevPixels, AppUnitsPerDevPixel()));
return;
}
@@ -1402,11 +1398,9 @@ void nsPresContext::SetFullZoom(float aZoom) {
// Re-fetch the view manager's window dimensions in case there's a deferred
// resize which hasn't affected our mVisibleArea yet
- nscoord oldWidthAppUnits, oldHeightAppUnits;
- mPresShell->GetViewManager()->GetWindowDimensions(&oldWidthAppUnits,
- &oldHeightAppUnits);
- float oldWidthDevPixels = oldWidthAppUnits / float(mCurAppUnitsPerDevPixel);
- float oldHeightDevPixels = oldHeightAppUnits / float(mCurAppUnitsPerDevPixel);
+ const auto oldSizeDevPixels = LayoutDeviceSize::FromAppUnits(
+ mPresShell->GetViewManager()->GetWindowDimensions(),
+ mCurAppUnitsPerDevPixel);
mDeviceContext->SetFullZoom(aZoom);
mFullZoom = aZoom;
@@ -1414,8 +1408,7 @@ void nsPresContext::SetFullZoom(float aZoom) {
AppUnitsPerDevPixelChanged();
mPresShell->GetViewManager()->SetWindowDimensions(
- NSToCoordRound(oldWidthDevPixels * AppUnitsPerDevPixel()),
- NSToCoordRound(oldHeightDevPixels * AppUnitsPerDevPixel()));
+ LayoutDeviceSize::ToAppUnits(oldSizeDevPixels, AppUnitsPerDevPixel()));
}
void nsPresContext::SetOverrideDPPX(float aDPPX) {
diff --git a/view/nsView.cpp b/view/nsView.cpp
@@ -341,9 +341,8 @@ bool nsView::WindowResized(nsIWidget* aWidget, int32_t aWidth,
// due to a call to e.g. nsDocumentViewer::GetContentSize or so.
frame->InvalidateFrame();
}
-
- mViewManager->SetWindowDimensions(NSIntPixelsToAppUnits(aWidth, p2a),
- NSIntPixelsToAppUnits(aHeight, p2a));
+ const LayoutDeviceIntSize size(aWidth, aHeight);
+ mViewManager->SetWindowDimensions(LayoutDeviceIntSize::ToAppUnits(size, p2a));
if (nsXULPopupManager* pm = nsXULPopupManager::GetInstance()) {
pm->AdjustPopupsOnWindowChange(ps);
diff --git a/view/nsViewManager.cpp b/view/nsViewManager.cpp
@@ -85,33 +85,24 @@ void nsViewManager::SetRootView(nsView* aView) {
mRootView = aView;
}
-void nsViewManager::GetWindowDimensions(nscoord* aWidth, nscoord* aHeight) {
- if (nullptr != mRootView) {
- if (mDelayedResize == nsSize(NSCOORD_NONE, NSCOORD_NONE)) {
- nsRect dim = mRootView->GetBounds();
- *aWidth = dim.Width();
- *aHeight = dim.Height();
- } else {
- *aWidth = mDelayedResize.width;
- *aHeight = mDelayedResize.height;
- }
- } else {
- *aWidth = 0;
- *aHeight = 0;
+nsSize nsViewManager::GetWindowDimensions() const {
+ if (!mRootView) {
+ return {};
+ }
+ if (mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE)) {
+ return mDelayedResize;
}
+ return mRootView->GetBounds().Size();
}
-void nsViewManager::DoSetWindowDimensions(nscoord aWidth, nscoord aHeight) {
- nsRect oldDim = mRootView->GetBounds();
- nsRect newDim(0, 0, aWidth, aHeight);
- // We care about resizes even when one dimension is already zero.
- if (oldDim.IsEqualEdges(newDim)) {
+void nsViewManager::DoSetWindowDimensions(const nsSize& aSize) {
+ if (mRootView->GetBounds().Size() == aSize) {
return;
}
// Don't resize the widget. It is already being set elsewhere.
- mRootView->SetDimensions(newDim);
+ mRootView->SetDimensions(nsRect(nsPoint(), aSize));
if (RefPtr<PresShell> presShell = mPresShell) {
- presShell->ResizeReflow(aWidth, aHeight);
+ presShell->ResizeReflow(aSize);
}
}
@@ -128,35 +119,36 @@ bool nsViewManager::ShouldDelayResize() const {
return false;
}
-void nsViewManager::SetWindowDimensions(nscoord aWidth, nscoord aHeight,
+void nsViewManager::SetWindowDimensions(const nsSize& aSize,
bool aDelayResize) {
- if (mRootView) {
- if (!ShouldDelayResize() && !aDelayResize) {
- if (mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) &&
- mDelayedResize != nsSize(aWidth, aHeight)) {
- // We have a delayed resize; that now obsolete size may already have
- // been flushed to the PresContext so we need to update the PresContext
- // with the new size because if the new size is exactly the same as the
- // root view's current size then DoSetWindowDimensions will not
- // request a resize reflow (which would correct it). See bug 617076.
- mDelayedResize = nsSize(aWidth, aHeight);
- FlushDelayedResize();
- }
- mDelayedResize.SizeTo(NSCOORD_NONE, NSCOORD_NONE);
- DoSetWindowDimensions(aWidth, aHeight);
- } else {
- mDelayedResize.SizeTo(aWidth, aHeight);
- if (mPresShell) {
- mPresShell->SetNeedStyleFlush();
- mPresShell->SetNeedLayoutFlush();
- }
+ if (!mRootView) {
+ return;
+ }
+ if (!ShouldDelayResize() && !aDelayResize) {
+ if (mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) &&
+ mDelayedResize != aSize) {
+ // We have a delayed resize; that now obsolete size may already have
+ // been flushed to the PresContext so we need to update the PresContext
+ // with the new size because if the new size is exactly the same as the
+ // root view's current size then DoSetWindowDimensions will not
+ // request a resize reflow (which would correct it). See bug 617076.
+ mDelayedResize = aSize;
+ FlushDelayedResize();
+ }
+ mDelayedResize.SizeTo(NSCOORD_NONE, NSCOORD_NONE);
+ DoSetWindowDimensions(aSize);
+ } else {
+ mDelayedResize = aSize;
+ if (mPresShell) {
+ mPresShell->SetNeedStyleFlush();
+ mPresShell->SetNeedLayoutFlush();
}
}
}
void nsViewManager::FlushDelayedResize() {
if (mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE)) {
- DoSetWindowDimensions(mDelayedResize.width, mDelayedResize.height);
+ DoSetWindowDimensions(mDelayedResize);
mDelayedResize.SizeTo(NSCOORD_NONE, NSCOORD_NONE);
}
}
diff --git a/view/nsViewManager.h b/view/nsViewManager.h
@@ -67,23 +67,14 @@ class nsViewManager final {
*/
void SetRootView(nsView* aView);
- /**
- * Get the dimensions of the root window. The dimensions are in
- * twips
- * @param aWidth out parameter for width of window in twips
- * @param aHeight out parameter for height of window in twips
- */
- void GetWindowDimensions(nscoord* aWidth, nscoord* aHeight);
+ /** Get the dimensions of the root view. */
+ nsSize GetWindowDimensions() const;
/**
* Set the dimensions of the root window.
- * Called if the root window is resized. The dimensions are in
- * twips
- * @param aWidth of window in twips
- * @param aHeight of window in twips
+ * Called if the root window is resized.
*/
- void SetWindowDimensions(nscoord aWidth, nscoord aHeight,
- bool aDelayResize = false);
+ void SetWindowDimensions(const nsSize& aSize, bool aDelayResize = false);
/**
* Do any resizes that are pending.
@@ -175,8 +166,7 @@ class nsViewManager final {
MOZ_CAN_RUN_SCRIPT
void Refresh(nsView* aView, const LayoutDeviceIntRegion& aRegion);
- MOZ_CAN_RUN_SCRIPT_BOUNDARY
- void DoSetWindowDimensions(nscoord aWidth, nscoord aHeight);
+ MOZ_CAN_RUN_SCRIPT_BOUNDARY void DoSetWindowDimensions(const nsSize&);
bool ShouldDelayResize() const;
bool IsPainting() const { return RootViewManager()->mPainting; }