tor-browser

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

commit 403aa6265d08c81a7b10bad851313cd01f3277d4
parent c56c1bde649fdf2dcad428e5eeae25b9d87eb505
Author: Emilio Cobos Álvarez <emilio@crisal.io>
Date:   Thu,  9 Oct 2025 21:14:38 +0000

Bug 1993570 - Make painting code not use views directly. r=layout-reviewers,dshin

The idea is that by passing (frame, renderer) we'll accommodate popups
not having views (and eventually kill views directly).

Differential Revision: https://phabricator.services.mozilla.com/D268208

Diffstat:
Mdom/base/nsDOMWindowUtils.cpp | 5+++--
Mdom/ipc/BrowserChild.cpp | 4+++-
Mdom/view-transitions/ViewTransition.cpp | 11+++++++----
Mlayout/base/PresShell.cpp | 75+++++++++++++++++++++++++++++++++++++--------------------------------------
Mlayout/base/PresShell.h | 10++++++----
Mlayout/base/nsLayoutUtils.cpp | 11++++-------
Mlayout/base/nsLayoutUtils.h | 4++--
Mview/nsViewManager.cpp | 5+++--
8 files changed, 65 insertions(+), 60 deletions(-)

diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp @@ -426,8 +426,9 @@ nsDOMWindowUtils::UpdateLayerTree() { RefPtr<nsViewManager> vm = presShell->GetViewManager(); if (nsView* view = vm->GetRootView()) { nsAutoScriptBlocker scriptBlocker; - presShell->PaintAndRequestComposite(view, - PaintFlags::PaintSyncDecodeImages); + presShell->PaintAndRequestComposite( + view->GetFrame(), view->GetWidget()->GetWindowRenderer(), + PaintFlags::PaintSyncDecodeImages); presShell->GetWindowRenderer()->WaitOnTransactionProcessed(); } } diff --git a/dom/ipc/BrowserChild.cpp b/dom/ipc/BrowserChild.cpp @@ -3070,7 +3070,9 @@ mozilla::ipc::IPCResult BrowserChild::RecvRenderLayers(const bool& aEnabled) { } else { RefPtr<nsViewManager> vm = presShell->GetViewManager(); if (nsView* view = vm->GetRootView()) { - presShell->PaintAndRequestComposite(view, PaintFlags::None); + presShell->PaintAndRequestComposite( + view->GetFrame(), view->GetWidget()->GetWindowRenderer(), + PaintFlags::None); } } presShell->SuppressDisplayport(false); diff --git a/dom/view-transitions/ViewTransition.cpp b/dom/view-transitions/ViewTransition.cpp @@ -1352,13 +1352,16 @@ Maybe<SkipTransitionReason> ViewTransition::CaptureOldState() { if (RefPtr<PresShell> ps = nsContentUtils::GetInProcessSubtreeRootDocument(mDocument) ->GetPresShell()) { - VT_LOG("ViewTransitions::CaptureOldState(), requesting composite"); // Build a display list and send it to WR in order to perform the // capturing of old content. RefPtr<nsViewManager> vm = ps->GetViewManager(); - ps->PaintAndRequestComposite(vm->GetRootView(), - PaintFlags::PaintCompositeOffscreen); - VT_LOG("ViewTransitions::CaptureOldState(), requesting composite end"); + if (RefPtr widget = vm->GetRootWidget()) { + VT_LOG("ViewTransitions::CaptureOldState(), requesting composite"); + ps->PaintAndRequestComposite(ps->GetRootFrame(), + widget->GetWindowRenderer(), + PaintFlags::PaintCompositeOffscreen); + VT_LOG("ViewTransitions::CaptureOldState(), requesting composite end"); + } } } diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp @@ -5763,8 +5763,8 @@ PresShell::CanvasBackground PresShell::ComputeCanvasBackground() const { return {viewportBg, pageBg}; } -nscolor PresShell::ComputeBackstopColor(nsView* aDisplayRoot) { - nsIWidget* widget = aDisplayRoot->GetWidget(); +nscolor PresShell::ComputeBackstopColor(nsIFrame* aDisplayRoot) { + nsIWidget* widget = aDisplayRoot ? aDisplayRoot->GetNearestWidget() : nullptr; if (widget && (widget->GetTransparencyMode() != widget::TransparencyMode::Opaque || widget->WidgetPaintsBackground())) { @@ -6703,18 +6703,21 @@ void PresShell::RemoveFrameFromApproximatelyVisibleList(nsIFrame* aFrame) { } } -void PresShell::PaintAndRequestComposite(nsView* aView, PaintFlags aFlags) { +void PresShell::PaintAndRequestComposite(nsIFrame* aFrame, + WindowRenderer* aRenderer, + PaintFlags aFlags) { if (!mIsActive) { return; } - WindowRenderer* renderer = aView->GetWidget()->GetWindowRenderer(); - NS_ASSERTION(renderer, "Must be in paint event"); - if (renderer->AsFallback()) { - // 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. - GetViewManager()->InvalidateView(aView); + NS_ASSERTION(aRenderer, "Must be in paint event"); + if (aRenderer->AsFallback()) { + // 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); + } return; } @@ -6727,26 +6730,28 @@ void PresShell::PaintAndRequestComposite(nsView* aView, PaintFlags aFlags) { if (aFlags & PaintFlags::PaintCompositeOffscreen) { flags |= PaintInternalFlags::PaintCompositeOffscreen; } - PaintInternal(aView, flags); + PaintInternal(aFrame, aRenderer, flags); } -void PresShell::SyncPaintFallback(nsView* aView) { +void PresShell::SyncPaintFallback(nsIFrame* aFrame, WindowRenderer* aRenderer) { if (!mIsActive) { return; } - WindowRenderer* renderer = aView->GetWidget()->GetWindowRenderer(); - NS_ASSERTION(renderer->AsFallback(), + NS_ASSERTION(aRenderer->AsFallback(), "Can't do Sync paint for remote renderers"); - if (!renderer->AsFallback()) { + if (!aRenderer->AsFallback()) { return; } - PaintInternal(aView, PaintInternalFlags::PaintComposite); + PaintInternal(aFrame, aRenderer, PaintInternalFlags::PaintComposite); GetPresContext()->NotifyDidPaintForSubtree(); } -void PresShell::PaintInternal(nsView* aViewToPaint, PaintInternalFlags aFlags) { +void PresShell::PaintInternal(nsIFrame* aFrame, WindowRenderer* aRenderer, + PaintInternalFlags aFlags) { + MOZ_ASSERT_IF(aFrame, + aFrame->IsViewportFrame() || aFrame->IsMenuPopupFrame()); nsCString url; nsIURI* uri = mDocument->GetDocumentURI(); Document* contentRoot = GetPrimaryContentDocument(); @@ -6771,7 +6776,7 @@ void PresShell::PaintInternal(nsView* aViewToPaint, PaintInternalFlags aFlags) { #endif NS_ASSERTION(!mIsDestroying, "painting a destroyed PresShell"); - NS_ASSERTION(aViewToPaint, "null view"); + NS_ASSERTION(aRenderer, "null renderer"); MOZ_ASSERT(!mApproximateFrameVisibilityVisited, "Should have been cleared"); @@ -6779,19 +6784,15 @@ void PresShell::PaintInternal(nsView* aViewToPaint, PaintInternalFlags aFlags) { return; } - nsIFrame* frame = aViewToPaint->GetFrame(); - FocusTarget focusTarget; if (StaticPrefs::apz_keyboard_enabled_AtStartup()) { // Update the focus target for async keyboard scrolling. This will be // forwarded to APZ by nsDisplayList::PaintRoot. We need to to do this // before we enter the paint phase because dispatching eVoid events can // cause layout to happen. - uint64_t focusSequenceNumber; - if (nsMenuPopupFrame* popup = do_QueryFrame(frame)) { + uint64_t focusSequenceNumber = mAPZFocusSequenceNumber; + if (nsMenuPopupFrame* popup = do_QueryFrame(aFrame)) { focusSequenceNumber = popup->GetAPZFocusSequenceNumber(); - } else { - focusSequenceNumber = mAPZFocusSequenceNumber; } focusTarget = FocusTarget(this, focusSequenceNumber); } @@ -6799,9 +6800,7 @@ void PresShell::PaintInternal(nsView* aViewToPaint, PaintInternalFlags aFlags) { nsPresContext* presContext = GetPresContext(); AUTO_LAYOUT_PHASE_ENTRY_POINT(presContext, Paint); - WindowRenderer* renderer = aViewToPaint->GetWidget()->GetWindowRenderer(); - NS_ASSERTION(renderer, "Must be in paint event"); - WebRenderLayerManager* layerManager = renderer->AsWebRender(); + WebRenderLayerManager* layerManager = aRenderer->AsWebRender(); // Whether or not we should set first paint when painting is suppressed // is debatable. For now we'll do it because B2G relied on first paint @@ -6820,7 +6819,7 @@ void PresShell::PaintInternal(nsView* aViewToPaint, PaintInternalFlags aFlags) { const bool offscreen = bool(aFlags & PaintInternalFlags::PaintCompositeOffscreen); - if (!renderer->BeginTransaction(url)) { + if (!aRenderer->BeginTransaction(url)) { return; } @@ -6830,24 +6829,24 @@ void PresShell::PaintInternal(nsView* aViewToPaint, PaintInternalFlags aFlags) { layerManager->SetFocusTarget(focusTarget); } - if (frame) { + if (aFrame) { if (!(aFlags & PaintInternalFlags::PaintSyncDecodeImages) && - !frame->HasAnyStateBits(NS_FRAME_UPDATE_LAYER_TREE)) { + !aFrame->HasAnyStateBits(NS_FRAME_UPDATE_LAYER_TREE)) { if (layerManager) { layerManager->SetTransactionIdAllocator(presContext->RefreshDriver()); } - if (renderer->EndEmptyTransaction( + if (aRenderer->EndEmptyTransaction( (aFlags & PaintInternalFlags::PaintComposite) ? WindowRenderer::END_DEFAULT : WindowRenderer::END_NO_COMPOSITE)) { return; } } - frame->RemoveStateBits(NS_FRAME_UPDATE_LAYER_TREE); + aFrame->RemoveStateBits(NS_FRAME_UPDATE_LAYER_TREE); } - nscolor bgcolor = ComputeBackstopColor(aViewToPaint); + nscolor bgcolor = ComputeBackstopColor(aFrame); PaintFrameFlags flags = PaintFrameFlags::WidgetLayers | PaintFrameFlags::ExistingTransaction; @@ -6862,21 +6861,21 @@ void PresShell::PaintInternal(nsView* aViewToPaint, PaintInternalFlags aFlags) { if (aFlags & PaintInternalFlags::PaintCompositeOffscreen) { flags |= PaintFrameFlags::CompositeOffscreen; } - if (renderer->GetBackendType() == layers::LayersBackend::LAYERS_WR) { + if (aRenderer->GetBackendType() == layers::LayersBackend::LAYERS_WR) { flags |= PaintFrameFlags::ForWebRender; } - if (frame) { + if (aFrame) { // We can paint directly into the widget using its layer manager. SelectionNodeCache cache(*this); - nsLayoutUtils::PaintFrame(nullptr, frame, nsRegion(), bgcolor, + nsLayoutUtils::PaintFrame(nullptr, aFrame, nsRegion(), bgcolor, nsDisplayListBuilderMode::Painting, flags); return; } bgcolor = NS_ComposeColors(bgcolor, mCanvasBackground.mViewport.mColor); - if (renderer->GetBackendType() == layers::LayersBackend::LAYERS_WR) { + if (aRenderer->GetBackendType() == layers::LayersBackend::LAYERS_WR) { LayoutDeviceRect bounds = LayoutDeviceRect::FromAppUnits( presContext->GetVisibleArea(), presContext->AppUnitsPerDevPixel()); WebRenderBackgroundData data(wr::ToLayoutRect(bounds), @@ -6889,7 +6888,7 @@ void PresShell::PaintInternal(nsView* aViewToPaint, PaintInternalFlags aFlags) { return; } - FallbackRenderer* fallback = renderer->AsFallback(); + FallbackRenderer* fallback = aRenderer->AsFallback(); MOZ_ASSERT(fallback); if (aFlags & PaintInternalFlags::PaintComposite) { diff --git a/layout/base/PresShell.h b/layout/base/PresShell.h @@ -965,7 +965,7 @@ class PresShell final : public nsStubDocumentObserver, * widget, otherwise the PresContext default background color. This color is * only visible if the contents of the view as a whole are translucent. */ - nscolor ComputeBackstopColor(nsView* aDisplayRoot); + nscolor ComputeBackstopColor(nsIFrame* aDisplayRoot); void ObserveNativeAnonMutationsForPrint(bool aObserve) { mObservesMutationsForPrint = aObserve; @@ -1367,14 +1367,15 @@ class PresShell final : public nsStubDocumentObserver, * SyncPaintFallback from the widget paint event. */ MOZ_CAN_RUN_SCRIPT - void PaintAndRequestComposite(nsView* aView, PaintFlags aFlags); + void PaintAndRequestComposite(nsIFrame* aFrame, WindowRenderer* aRenderer, + PaintFlags aFlags); /** * Does an immediate paint+composite using the FallbackRenderer (which must * be the current WindowRenderer for the root frame's widget). */ MOZ_CAN_RUN_SCRIPT - void SyncPaintFallback(nsView* aView); + void SyncPaintFallback(nsIFrame* aFrame, WindowRenderer* aRenderer); /** * Notify that we're going to call Paint with PaintFlags::PaintLayers @@ -1868,7 +1869,8 @@ class PresShell final : public nsStubDocumentObserver, bool ComputeActiveness() const; MOZ_CAN_RUN_SCRIPT - void PaintInternal(nsView* aViewToPaint, PaintInternalFlags aFlags); + void PaintInternal(nsIFrame* aFrame, WindowRenderer* aRenderer, + PaintInternalFlags aFlags); // Refresh observer management. void ScheduleFlush(); diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp @@ -2860,12 +2860,9 @@ void nsLayoutUtils::PaintFrame(gfxContext* aRenderingContext, nsIFrame* aFrame, nsIFrame* displayRoot = GetDisplayRootFrame(aFrame); - if (aFlags & PaintFrameFlags::WidgetLayers) { - nsView* view = aFrame->GetView(); - if (!(view && view->GetWidget() && displayRoot == aFrame)) { - aFlags &= ~PaintFrameFlags::WidgetLayers; - NS_ASSERTION(aRenderingContext, "need a rendering context"); - } + if ((aFlags & PaintFrameFlags::WidgetLayers) && displayRoot != aFrame) { + aFlags &= ~PaintFrameFlags::WidgetLayers; + NS_ASSERTION(aRenderingContext, "need a rendering context"); } nsPresContext* presContext = aFrame->PresContext(); @@ -6690,7 +6687,7 @@ bool nsLayoutUtils::HasNonZeroCornerOnSide(const BorderRadius& aCorners, /* static */ widget::TransparencyMode nsLayoutUtils::GetFrameTransparency( - nsIFrame* aBackgroundFrame, nsIFrame* aCSSRootFrame) { + const nsIFrame* aBackgroundFrame, const nsIFrame* aCSSRootFrame) { if (!aCSSRootFrame->StyleEffects()->IsOpaque()) { return TransparencyMode::Transparent; } diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h @@ -2166,8 +2166,8 @@ class nsLayoutUtils { * @return a value suitable for passing to SetWindowTranslucency. */ using TransparencyMode = mozilla::widget::TransparencyMode; - static TransparencyMode GetFrameTransparency(nsIFrame* aBackgroundFrame, - nsIFrame* aCSSRootFrame); + static TransparencyMode GetFrameTransparency(const nsIFrame* aBackgroundFrame, + const nsIFrame* aCSSRootFrame); /** * A frame is a popup if it has its own floating window. Menus, panels diff --git a/view/nsViewManager.cpp b/view/nsViewManager.cpp @@ -273,7 +273,7 @@ void nsViewManager::Refresh(nsView* aView, if (!renderer->NeedsWidgetInvalidation()) { renderer->FlushRendering(wr::RenderReasons::WIDGET); } else { - presShell->SyncPaintFallback(aView); + presShell->SyncPaintFallback(aView->GetFrame(), renderer); } #ifdef MOZ_DUMP_PAINTING if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { @@ -396,7 +396,8 @@ void nsViewManager::ProcessPendingUpdatesPaint(nsIWidget* aWidget) { } #endif - presShell->PaintAndRequestComposite(view, PaintFlags::None); + presShell->PaintAndRequestComposite( + view->GetFrame(), aWidget->GetWindowRenderer(), PaintFlags::None); view->SetForcedRepaint(false); #ifdef MOZ_DUMP_PAINTING