tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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:
Mlayout/base/PresShell.cpp | 12++++++------
Mlayout/base/ZoomConstraintsClient.cpp | 4+---
Mlayout/base/nsLayoutUtils.cpp | 28+++++++---------------------
Mlayout/generic/FrameClasses.py | 3+--
Mlayout/generic/ScrollContainerFrame.cpp | 1-
Mlayout/generic/ViewportFrame.cpp | 18+++++++++++++-----
Mlayout/generic/ViewportFrame.h | 6+++---
Mlayout/generic/nsIFrame.cpp | 32++++++++++++++------------------
Mlayout/generic/nsIFrame.h | 22+++++++---------------
Mlayout/tools/layout-debug/src/nsLayoutDebuggingTools.cpp | 11++---------
Mlayout/xul/tree/nsTreeBodyFrame.cpp | 2--
Mview/nsViewManager.cpp | 110++++---------------------------------------------------------------------------
Mview/nsViewManager.h | 19-------------------
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