commit 05318948d540d6b873ad1ddd434209a91447be93
parent 89b04cc61065ba39b499ede46e24e99936128725
Author: Emilio Cobos Álvarez <emilio@crisal.io>
Date: Wed, 12 Nov 2025 18:22:35 +0000
Bug 1999623 - Remove more view code. r=tnikkel,layout-reviewers
Remove and simplify some view-using code:
* Add nsIFrame::GetOwnWidget() to get an nsIWidget rather than doing
menupopup-or-view.
* Move widget invalidation to the only place it's used.
* Don't deal with reentrant paints. Assert more strongly.
* Move SetView only to ViewportFrame.
Differential Revision: https://phabricator.services.mozilla.com/D272208
Diffstat:
13 files changed, 59 insertions(+), 209 deletions(-)
diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp
@@ -4799,10 +4799,9 @@ nsresult PresShell::RenderDocument(const nsRect& aRect,
}
if (aFlags & RenderDocumentFlags::UseWidgetLayers) {
// We only support using widget layers on display root's with widgets.
- nsView* view = rootFrame->GetView();
- if (view && view->GetWidget() &&
- nsLayoutUtils::GetDisplayRootFrame(rootFrame) == rootFrame) {
- WindowRenderer* renderer = view->GetWidget()->GetWindowRenderer();
+ nsIWidget* widget = rootFrame->GetOwnWidget();
+ if (widget && nsLayoutUtils::GetDisplayRootFrame(rootFrame) == rootFrame) {
+ WindowRenderer* renderer = widget->GetWindowRenderer();
// WebRenderLayerManagers in content processes
// don't support taking snapshots.
if (renderer &&
@@ -6524,8 +6523,9 @@ void PresShell::PaintAndRequestComposite(nsIFrame* aFrame,
// The fallback renderer doesn't do any retaining, so we just need to
// notify the view and widget that we're invalid, and we'll do a
// paint+composite from the PaintWindow callback.
- if (auto* view = aFrame ? aFrame->GetView() : nullptr) {
- GetViewManager()->InvalidateView(view);
+ if (nsIWidget* widget = aFrame ? aFrame->GetOwnWidget() : nullptr) {
+ auto bounds = widget->GetBounds();
+ widget->Invalidate(LayoutDeviceIntRect({}, bounds.Size()));
}
return;
}
diff --git a/layout/base/ZoomConstraintsClient.cpp b/layout/base/ZoomConstraintsClient.cpp
@@ -64,9 +64,7 @@ static nsIWidget* GetWidget(PresShell* aPresShell) {
// see https://bugzilla.mozilla.org/show_bug.cgi?id=1648427#c7 .
return rootFrame->GetNearestWidget();
#else
- if (nsView* view = rootFrame->GetView()) {
- return view->GetWidget();
- }
+ return rootFrame->GetOwnWidget();
#endif
}
return nullptr;
diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp
@@ -162,8 +162,6 @@
#include "nsTableWrapperFrame.h"
#include "nsTextFrame.h"
#include "nsTransitionManager.h"
-#include "nsView.h"
-#include "nsViewManager.h"
#include "nsXULPopupManager.h"
#include "prenv.h"
@@ -1449,25 +1447,13 @@ nsPoint GetEventCoordinatesRelativeTo(nsIWidget* aWidget,
return nsPoint(NS_UNCONSTRAINEDSIZE, NS_UNCONSTRAINEDSIZE);
}
- nsView* view = frame->GetView();
- if (view || frame->IsMenuPopupFrame()) {
- nsIWidget* frameWidget =
- view ? view->GetWidget()
- : static_cast<const nsMenuPopupFrame*>(frame)->GetWidget();
- if (frameWidget == aWidget) {
- MOZ_ASSERT_IF(!view, frameWidget->GetPopupFrame() ==
- static_cast<const nsMenuPopupFrame*>(frame));
- // Special case this cause it happens a lot.
- // This also fixes bug 664707, events in the extra-special case of select
- // dropdown popups that are transformed.
- nsPresContext* presContext = frame->PresContext();
- nsPoint pt(presContext->DevPixelsToAppUnits(aPoint.x),
- presContext->DevPixelsToAppUnits(aPoint.y));
- if (view) {
- pt -= view->ViewToWidgetOffset();
- }
- return pt;
- }
+ if (frame->GetOwnWidget() == aWidget) {
+ // Special case this cause it happens a lot.
+ // This also fixes bug 664707, events in the extra-special case of select
+ // dropdown popups that are transformed.
+ nsPresContext* presContext = frame->PresContext();
+ return nsPoint(presContext->DevPixelsToAppUnits(aPoint.x),
+ presContext->DevPixelsToAppUnits(aPoint.y));
}
/* If we walk up the frame tree and discover that any of the frames are
diff --git a/layout/generic/FrameClasses.py b/layout/generic/FrameClasses.py
@@ -16,7 +16,6 @@ MATHML = {"MathML"}
SVG = {"SVG"}
BFC = {"BlockFormattingContext"}
LINE_PARTICIPANT = {"LineParticipant"}
-MAY_HAVE_VIEW = {"MayHaveView"}
BLOCK = COMMON | {"CanContainOverflowContainers"}
@@ -172,7 +171,7 @@ FRAME_CLASSES = [
Frame("nsTreeBodyFrame", "SimpleXULLeaf", COMMON | LEAF),
Frame("nsVideoFrame", "HTMLVideo", REPLACED_SIZING),
Frame("nsAudioFrame", "HTMLVideo", REPLACED_SIZING - {"SupportsAspectRatio"}),
- Frame("ViewportFrame", "Viewport", COMMON | MAY_HAVE_VIEW),
+ Frame("ViewportFrame", "Viewport", COMMON),
Frame("WBRFrame", "Wbr", COMMON | LEAF),
# Non-concrete classes (for FrameIID use)
AbstractFrame("ButtonControlFrame"),
diff --git a/layout/generic/ScrollContainerFrame.cpp b/layout/generic/ScrollContainerFrame.cpp
@@ -100,7 +100,6 @@
#include "nsStyleConsts.h"
#include "nsStyleTransformMatrix.h"
#include "nsSubDocumentFrame.h"
-#include "nsView.h"
#include "nsViewportInfo.h"
static mozilla::LazyLogModule sApzPaintSkipLog("apz.paintskip");
diff --git a/layout/generic/ViewportFrame.cpp b/layout/generic/ViewportFrame.cpp
@@ -339,10 +339,18 @@ void ViewportFrame::RemoveFrame(DestroyContext& aContext, ChildListID aListID,
}
#endif
+void ViewportFrame::SetView(nsView* aView) {
+ MOZ_ASSERT(!mView, "Should not swap views");
+ if (aView) {
+ aView->SetFrame(this);
+ }
+ mView = aView;
+}
+
void ViewportFrame::Destroy(DestroyContext& aContext) {
// Prevent event dispatch during destruction.
- if (auto* view = GetView()) {
- view->SetFrame(nullptr);
+ if (mView) {
+ mView->SetFrame(nullptr);
}
if (PresShell()->IsDestroying()) {
PresShell::ClearMouseCapture(this);
@@ -501,9 +509,9 @@ void ViewportFrame::Reflow(nsPresContext* aPresContext,
// so we don't need to change our overflow areas.
FinishAndStoreOverflow(&aDesiredSize);
- if (auto* view = GetView()) {
- view->GetViewManager()->ResizeView(
- view, nsRect(nsPoint(), aDesiredSize.PhysicalSize()));
+ if (mView) {
+ mView->GetViewManager()->ResizeView(
+ mView, nsRect(nsPoint(), aDesiredSize.PhysicalSize()));
}
NS_FRAME_TRACE_REFLOW_OUT("ViewportFrame::Reflow", aStatus);
diff --git a/layout/generic/ViewportFrame.h b/layout/generic/ViewportFrame.h
@@ -94,13 +94,13 @@ class ViewportFrame : public nsContainerFrame {
virtual nsresult GetFrameName(nsAString& aResult) const override;
#endif
+ nsView* GetViewportFrameView() const { return mView; }
+ void SetView(nsView*);
+
protected:
ViewportFrame(ComputedStyle* aStyle, nsPresContext* aPresContext, ClassID aID)
: nsContainerFrame(aStyle, aPresContext, aID), mView(nullptr) {}
- nsView* GetViewInternal() const override { return mView; }
- void SetViewInternal(nsView* aView) override { mView = aView; }
-
private:
nsDisplayWrapList* MaybeWrapTopLayerList(nsDisplayListBuilder*,
uint16_t aIndex, nsDisplayList&);
diff --git a/layout/generic/nsIFrame.cpp b/layout/generic/nsIFrame.cpp
@@ -50,6 +50,7 @@
#include "mozilla/TextControlElement.h"
#include "mozilla/ToString.h"
#include "mozilla/Try.h"
+#include "mozilla/ViewportFrame.h"
#include "mozilla/ViewportUtils.h"
#include "mozilla/WritingModes.h"
#include "mozilla/dom/AncestorIterator.h"
@@ -121,6 +122,7 @@
#include "nsRegion.h"
#include "nsStyleChangeList.h"
#include "nsSubDocumentFrame.h"
+#include "nsViewportInfo.h"
#include "nsWindowSizes.h"
#ifdef ACCESSIBILITY
@@ -7711,19 +7713,19 @@ nsIFrame* nsIFrame::GetTailContinuation() {
return frame;
}
-// Associated view object
-void nsIFrame::SetView(nsView* aView) {
- if (aView) {
- MOZ_ASSERT(MayHaveView(), "Only specific frame types can have an nsView");
- MOZ_ASSERT(!GetParent(), "Only the viewport can have views");
- aView->SetFrame(this);
-
- // Store the view on the frame.
- SetViewInternal(aView);
- } else {
- MOZ_ASSERT_UNREACHABLE("Destroying a view while the frame is alive?");
- SetViewInternal(nullptr);
+nsIWidget* nsIFrame::GetOwnWidget() const {
+ if (auto* view = GetView()) {
+ return view->GetWidget();
}
+ if (IsMenuPopupFrame()) {
+ return static_cast<const nsMenuPopupFrame*>(this)->GetWidget();
+ }
+ return nullptr;
+}
+
+nsView* nsIFrame::DoGetView() const {
+ MOZ_ASSERT(IsViewportFrame());
+ return static_cast<const ViewportFrame*>(this)->GetViewportFrameView();
}
template <nsPoint (nsIFrame::*PositionGetter)() const>
@@ -8496,12 +8498,6 @@ bool nsIFrame::UpdateOverflow() {
UnionChildOverflow(overflowAreas);
if (FinishAndStoreOverflow(overflowAreas, GetSize())) {
- if (nsView* view = GetView()) {
- // Make sure the frame's view is properly sized.
- nsViewManager* vm = view->GetViewManager();
- vm->ResizeView(view, overflowAreas.InkOverflow());
- }
-
return true;
}
diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h
@@ -664,8 +664,6 @@ enum class LayoutFrameClassFlags : uint32_t {
BlockFormattingContext = 1 << 14,
// Whether we're a SVG rendering observer container.
SVGRenderingObserverContainer = 1 << 15,
- // Whether this frame type may store an nsView
- MayHaveView = 1 << 16,
};
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(LayoutFrameClassFlags)
@@ -2277,8 +2275,7 @@ class nsIFrame : public nsQueryFrame {
* Event handling of GUI events.
*
* @param aEvent event structure describing the type of event and rge widget
- * where the event originated. The |point| member of this is in the coordinate
- * system of the view returned by GetOffsetFromView.
+ * where the event originated.
*
* @param aEventStatus a return value indicating whether the event was
* handled and whether default processing should be done
@@ -3317,22 +3314,18 @@ class nsIFrame : public nsQueryFrame {
}
protected:
- virtual nsView* GetViewInternal() const {
- MOZ_ASSERT_UNREACHABLE("method should have been overridden by subclass");
- return nullptr;
- }
- virtual void SetViewInternal(nsView* aView) {
- MOZ_ASSERT_UNREACHABLE("method should have been overridden by subclass");
- }
+ nsView* DoGetView() const;
public:
+ // Gets the widget owned by this frame.
+ nsIWidget* GetOwnWidget() const;
+
nsView* GetView() const {
- if (MOZ_LIKELY(!MayHaveView())) {
+ if (MOZ_LIKELY(!IsViewportFrame())) {
return nullptr;
}
- return GetViewInternal();
+ return DoGetView();
}
- void SetView(nsView* aView);
/**
* Get the offset between the coordinate systems of |this| and aOther.
@@ -3567,7 +3560,6 @@ class nsIFrame : public nsQueryFrame {
CLASS_FLAG_METHOD(IsBidiInlineContainer, BidiInlineContainer);
CLASS_FLAG_METHOD(IsLineParticipant, LineParticipant);
CLASS_FLAG_METHOD(HasReplacedSizing, ReplacedSizing);
- CLASS_FLAG_METHOD(MayHaveView, MayHaveView);
CLASS_FLAG_METHOD(IsTablePart, TablePart);
CLASS_FLAG_METHOD0(CanContainOverflowContainers)
CLASS_FLAG_METHOD0(SupportsCSSTransforms);
diff --git a/layout/tools/layout-debug/src/nsLayoutDebuggingTools.cpp b/layout/tools/layout-debug/src/nsLayoutDebuggingTools.cpp
@@ -6,6 +6,7 @@
#include "nsLayoutDebuggingTools.h"
+#include "ErrorList.h"
#include "RetainedDisplayListBuilder.h"
#include "mozilla/Preferences.h"
#include "mozilla/PresShell.h"
@@ -376,15 +377,7 @@ nsLayoutDebuggingTools::DumpReflowStats() {
}
nsresult nsLayoutDebuggingTools::ForceRefresh() {
- RefPtr<nsViewManager> vm(view_manager(mDocShell));
- if (!vm) {
- return NS_OK;
- }
- nsView* root = vm->GetRootView();
- if (root) {
- vm->InvalidateView(root);
- }
- return NS_OK;
+ return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult nsLayoutDebuggingTools::SetBoolPrefAndRefresh(const char* aPrefName,
diff --git a/layout/xul/tree/nsTreeBodyFrame.cpp b/layout/xul/tree/nsTreeBodyFrame.cpp
@@ -58,8 +58,6 @@
#include "nsTreeImageListener.h"
#include "nsTreeSelection.h"
#include "nsTreeUtils.h"
-#include "nsView.h"
-#include "nsViewManager.h"
#include "nsWidgetsCID.h"
#ifdef ACCESSIBILITY
diff --git a/view/nsViewManager.cpp b/view/nsViewManager.cpp
@@ -57,7 +57,6 @@ nsViewManager::nsViewManager(nsDeviceContext* aContext)
mDelayedResize(NSCOORD_NONE, NSCOORD_NONE),
mRootView(nullptr),
mPainting(false),
- mRecursiveRefreshPending(false),
mHasPendingWidgetGeometryChanges(false) {
MOZ_ASSERT(aContext);
}
@@ -206,9 +205,8 @@ void nsViewManager::Refresh(nsView* aView,
return;
}
- NS_ASSERTION(!IsPainting(), "recursive painting not permitted");
- if (IsPainting()) {
- RootViewManager()->mRecursiveRefreshPending = true;
+ MOZ_ASSERT(!IsPainting(), "recursive painting not permitted");
+ if (NS_WARN_IF(IsPainting())) {
return;
}
@@ -242,11 +240,6 @@ void nsViewManager::Refresh(nsView* aView,
SetPainting(false);
}
-
- if (RootViewManager()->mRecursiveRefreshPending) {
- RootViewManager()->mRecursiveRefreshPending = false;
- InvalidateAllViews();
- }
}
void nsViewManager::ProcessPendingUpdatesForView(nsView* aView,
@@ -279,10 +272,8 @@ void nsViewManager::ProcessPendingUpdatesForView(nsView* aView,
if (aFlushDirtyRegion) {
nsAutoScriptBlocker scriptBlocker;
SetPainting(true);
- for (uint32_t i = 0; i < widgets.Length(); ++i) {
- nsIWidget* widget = widgets[i];
- nsView* view = nsView::GetViewFor(widget);
- if (view) {
+ for (nsIWidget* widget : widgets) {
+ if (nsView* view = nsView::GetViewFor(widget)) {
RefPtr<nsViewManager> viewManager = view->GetViewManager();
viewManager->ProcessPendingUpdatesPaint(MOZ_KnownLive(widget));
}
@@ -297,11 +288,8 @@ void nsViewManager::ProcessPendingUpdatesRecurse(
return;
}
- nsIWidget* widget = aView->GetWidget();
- if (widget) {
+ if (nsIWidget* widget = aView->GetWidget()) {
aWidgets.AppendElement(widget);
- } else {
- FlushDirtyRegionToWidget(aView);
}
}
@@ -347,21 +335,6 @@ void nsViewManager::ProcessPendingUpdatesPaint(nsIWidget* aWidget) {
#endif
}
}
- FlushDirtyRegionToWidget(nsView::GetViewFor(aWidget));
-}
-
-void nsViewManager::FlushDirtyRegionToWidget(nsView* aView) {
- NS_ASSERTION(aView->GetViewManager() == this,
- "FlushDirtyRegionToWidget called on view we don't own");
-
- if (!aView->IsDirty() || !aView->HasWidget()) {
- return;
- }
-
- const nsRect dirtyRegion = aView->GetBounds();
- nsViewManager* widgetVM = aView->GetViewManager();
- widgetVM->InvalidateWidgetArea(aView, dirtyRegion);
- aView->SetIsDirty(false);
}
void nsViewManager::PostPendingUpdate() {
@@ -373,79 +346,6 @@ void nsViewManager::PostPendingUpdate() {
}
}
-/**
- * @param aDamagedRegion this region, relative to aWidgetView, is invalidated in
- * every widget child of aWidgetView, plus aWidgetView's own widget
- */
-void nsViewManager::InvalidateWidgetArea(nsView* aWidgetView,
- const nsRegion& aDamagedRegion) {
- NS_ASSERTION(aWidgetView->GetViewManager() == this,
- "InvalidateWidgetArea called on view we don't own");
- nsIWidget* widget = aWidgetView->GetWidget();
-
-#if 0
- nsRect dbgBounds = aDamagedRegion.GetBounds();
- printf("InvalidateWidgetArea view:%X (%d) widget:%X region: %d, %d, %d, %d\n",
- aWidgetView, aWidgetView->IsAttachedToTopLevel(),
- widget, dbgBounds.x, dbgBounds.y, dbgBounds.width, dbgBounds.height);
-#endif
-
- // If the widget is hidden, it don't cover nothing
- if (widget && !widget->IsVisible()) {
- return;
- }
-
- if (!widget) {
- // The root view or a scrolling view might not have a widget
- // (for example, during printing). We get here when we scroll
- // during printing to show selected options in a listbox, for example.
- return;
- }
-
- if (!aDamagedRegion.IsEmpty()) {
- for (auto iter = aDamagedRegion.RectIter(); !iter.Done(); iter.Next()) {
- LayoutDeviceIntRect bounds = ViewToWidget(aWidgetView, iter.Get());
- widget->Invalidate(bounds);
- }
- }
-}
-
-static bool ShouldIgnoreInvalidation(nsViewManager* aVM) {
- PresShell* presShell = aVM->GetPresShell();
- return !presShell || presShell->ShouldIgnoreInvalidation();
-}
-
-void nsViewManager::InvalidateView(nsView* aView) {
- // If painting is suppressed in the presshell or an ancestor drop all
- // invalidates, it will invalidate everything when it unsuppresses.
- if (ShouldIgnoreInvalidation(this)) {
- return;
- }
-
- NS_ASSERTION(aView->GetViewManager() == this,
- "InvalidateView called on view we don't own");
-
- if (aView->GetBounds().IsEmpty()) {
- return;
- }
- MOZ_ASSERT(!aView->GetFrame() || !aView->GetFrame()->GetParent(),
- "Frame should be a display root");
- aView->SetIsDirty(true);
-}
-
-void nsViewManager::InvalidateAllViews() {
- if (RootViewManager() != this) {
- return RootViewManager()->InvalidateAllViews();
- }
-
- InvalidateViews(mRootView);
-}
-
-void nsViewManager::InvalidateViews(nsView* aView) {
- // Invalidate this view.
- InvalidateView(aView);
-}
-
void nsViewManager::WillPaintWindow(nsIWidget* aWidget) {
if (aWidget) {
nsView* view = nsView::GetViewFor(aWidget);
diff --git a/view/nsViewManager.h b/view/nsViewManager.h
@@ -93,18 +93,6 @@ class nsViewManager final {
void FlushDelayedResize();
/**
- * Called to inform the view manager that the entire area of a view
- * is dirty and needs to be redrawn.
- * @param aView view to paint. should be root view
- */
- void InvalidateView(nsView* aView);
-
- /**
- * Called to inform the view manager that it should invalidate all views.
- */
- void InvalidateAllViews();
-
- /**
* Called to dispatch an event to the appropriate view. Often called
* as a result of receiving a mouse or keyboard event from the widget
* event system.
@@ -187,7 +175,6 @@ class nsViewManager final {
MOZ_CAN_RUN_SCRIPT
void ProcessPendingUpdatesPaint(nsIWidget* aWidget);
- void FlushDirtyRegionToWidget(nsView* aView);
/**
* Call WillPaint() on all view observers under this vm root.
*/
@@ -195,11 +182,6 @@ class nsViewManager final {
static void CollectVMsForWillPaint(nsView* aView, nsViewManager* aParentVM,
nsTArray<RefPtr<nsViewManager>>& aVMs);
- void InvalidateWidgetArea(nsView* aWidgetView,
- const nsRegion& aDamagedRegion);
-
- void InvalidateViews(nsView* aView);
-
// aView is the view for aWidget and aRegion is relative to aWidget.
MOZ_CAN_RUN_SCRIPT
void Refresh(nsView* aView, const LayoutDeviceIntRegion& aRegion);
@@ -246,7 +228,6 @@ class nsViewManager final {
// this, as noted.
// Use IsPainting() and SetPainting() to access mPainting.
bool mPainting;
- bool mRecursiveRefreshPending;
bool mHasPendingWidgetGeometryChanges;
// from here to public should be static and locked... MMP