tor-browser

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

commit 476c551dc522acb523a09d2764bffb62098b96ed
parent 0620775c83fdc4a357330c0f7f63b47b940e35a9
Author: Emilio Cobos Álvarez <emilio@crisal.io>
Date:   Fri, 17 Oct 2025 06:33:35 +0000

Bug 1994893 - Clean up widget / view / nsDocumentViewer initialization. r=tnikkel,layout-reviewers

We always attach to the top-level widget / never create child popups.

On child processes this is already asserted via nsIWidget::CreateChild,
and on the parent nowadays our behavior would be nonsensical (we'd
create a separate nsCocoaWindow etc).

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

Diffstat:
Mlayout/base/PresShell.cpp | 9+--------
Mlayout/base/nsDocumentViewer.cpp | 97++++++++++++++++++-------------------------------------------------------------
Mlayout/printing/nsPrintJob.cpp | 4+---
Mview/nsView.cpp | 66++++++++++--------------------------------------------------------
Mview/nsView.h | 14++------------
Mview/nsViewManager.cpp | 29+++++++++--------------------
Mview/nsViewManager.h | 2+-
Mwidget/nsIWidget.cpp | 10++++------
Mwidget/nsIWidget.h | 2+-
9 files changed, 51 insertions(+), 182 deletions(-)

diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp @@ -11473,12 +11473,9 @@ bool PresShell::VerifyIncrementalReflow() { // Get our scrolling preference nsView* rootView = mViewManager->GetRootView(); NS_ENSURE_TRUE(rootView->HasWidget(), false); - nsIWidget* parentWidget = rootView->GetWidget(); // Create a new view manager. - auto vm = MakeRefPtr<nsViewManager>(); - rv = vm->Init(dc); - NS_ENSURE_SUCCESS(rv, false); + auto vm = MakeRefPtr<nsViewManager>(dc); // Create a child window of the parent that is our "root view/window" // Create a view @@ -11486,10 +11483,6 @@ bool PresShell::VerifyIncrementalReflow() { nsView* view = vm->CreateView(tbounds, nullptr); NS_ENSURE_TRUE(view, false); - // now create the widget for the view - rv = view->CreateWidget(parentWidget, true); - NS_ENSURE_SUCCESS(rv, false); - // Setup hierarchical relationship in view manager vm->SetRootView(view); diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp @@ -342,7 +342,7 @@ class nsDocumentViewer final : public nsIDocumentViewer, * @param aContainerView the container view to hook our root view up * to as a child, or null if this will be the root view manager */ - nsresult MakeWindow(const nsSize& aSize, nsView* aContainerView); + void MakeWindow(const nsSize& aSize, nsView* aContainerView); /** * Create our device context @@ -386,11 +386,6 @@ class nsDocumentViewer final : public nsIDocumentViewer, void InvalidatePotentialSubDocDisplayItem(); - // Whether we should attach to the top level widget. This is true if we - // are sharing/recycling a single base widget and not creating multiple - // child widgets. - bool ShouldAttachToTopLevel(); - std::tuple<const nsIFrame*, int32_t> GetCurrentSheetFrameAndNumber() const; protected: @@ -796,6 +791,7 @@ nsresult nsDocumentViewer::InitInternal( nsAutoScriptBlocker blockScripts; mParentWidget = aParentWidget; // not ref counted + mBounds = aBounds; nsresult rv = NS_OK; @@ -849,10 +845,9 @@ nsresult nsDocumentViewer::InitInternal( // into nsSubDocumentFrame code through reflows caused by // FlushPendingNotifications() calls down the road... - rv = MakeWindow(nsSize(mPresContext->DevPixelsToAppUnits(aBounds.width), - mPresContext->DevPixelsToAppUnits(aBounds.height)), - containerView); - NS_ENSURE_SUCCESS(rv, rv); + MakeWindow(nsSize(mPresContext->DevPixelsToAppUnits(aBounds.width), + mPresContext->DevPixelsToAppUnits(aBounds.height)), + containerView); Hide(); #ifdef NS_PRINT_PREVIEW @@ -1466,8 +1461,7 @@ nsDocumentViewer::Open(nsISupports* aState, nsISHEntry* aSHEntry) { // page B, we detach. So page A's view has no widget. If we then go // back to it, and it is in the bfcache, we will use that view, which // doesn't have a widget. The attach call here will properly attach us. - if (nsIWidget::UsePuppetWidgets() && mPresContext && - ShouldAttachToTopLevel()) { + if (mParentWidget && mPresContext) { // If the old view is already attached to our parent, detach DetachFromTopLevelWidget(); @@ -2097,12 +2091,9 @@ nsDocumentViewer::Show() { return rv; } - rv = MakeWindow(nsSize(mPresContext->DevPixelsToAppUnits(mBounds.width), - mPresContext->DevPixelsToAppUnits(mBounds.height)), - containerView); - if (NS_FAILED(rv)) { - return rv; - } + MakeWindow(nsSize(mPresContext->DevPixelsToAppUnits(mBounds.width), + mPresContext->DevPixelsToAppUnits(mBounds.height)), + containerView); if (mPresContext) { Hide(); @@ -2217,51 +2208,29 @@ nsDocumentViewer::ClearHistoryEntry() { //------------------------------------------------------- -nsresult nsDocumentViewer::MakeWindow(const nsSize& aSize, - nsView* aContainerView) { +void nsDocumentViewer::MakeWindow(const nsSize& aSize, nsView* aContainerView) { if (GetIsPrintPreview()) { - return NS_OK; - } - - const bool shouldAttach = ShouldAttachToTopLevel(); - if (shouldAttach) { - // If the old view is already attached to our parent, detach - DetachFromTopLevelWidget(); + return; } - mViewManager = new nsViewManager(); - - nsDeviceContext* dx = mPresContext->DeviceContext(); - - nsresult rv = mViewManager->Init(dx); - if (NS_FAILED(rv)) { - return rv; - } + mViewManager = new nsViewManager(mPresContext->DeviceContext()); // The root view is always at 0,0. nsRect tbounds(nsPoint(0, 0), aSize); // Create a view nsView* view = mViewManager->CreateView(tbounds, aContainerView); - if (!view) { - return NS_ERROR_OUT_OF_MEMORY; - } + MOZ_ASSERT(view); // Create a widget if we were given a parent widget or don't have a // container view that we can hook up to without a widget. // Don't create widgets for ResourceDocs (external resources & svg images), // because when they're displayed, they're painted into *another* document's // widget. - if (!mDocument->IsResourceDoc() && (mParentWidget || !aContainerView)) { - if (shouldAttach) { - // Reuse the top level parent widget. - rv = view->AttachToTopLevelWidget(mParentWidget); - mAttachedToParent = true; - } else { - rv = view->CreateWidget(mParentWidget, true, false); - } - if (NS_FAILED(rv)) { - return rv; - } + MOZ_ASSERT_IF(!aContainerView, mParentWidget); + if (!mDocument->IsResourceDoc() && mParentWidget) { + // Reuse the top level parent widget. + view->AttachToTopLevelWidget(mParentWidget); + mAttachedToParent = true; } // Setup hierarchical relationship in view manager @@ -2273,8 +2242,6 @@ nsresult nsDocumentViewer::MakeWindow(const nsSize& aSize, // go to the scrolled view as soon as the Window is created instead of going // to the browser window (this enables keyboard scrolling of the document) // mWindow->SetFocus(); - - return rv; } void nsDocumentViewer::DetachFromTopLevelWidget() { @@ -3232,25 +3199,6 @@ nsDocumentViewer::GetPrintPreviewNumPages(int32_t* aPrintPreviewNumPages) { // happening #endif // NS_PRINTING -bool nsDocumentViewer::ShouldAttachToTopLevel() { - if (!mParentWidget) { - return false; - } - - // We always attach when using puppet widgets - if (nsIWidget::UsePuppetWidgets() || mParentWidget->IsPuppetWidget()) { - return true; - } -#ifdef DEBUG - nsIWidgetListener* parentListener = mParentWidget->GetWidgetListener(); - MOZ_ASSERT(!parentListener || !parentListener->GetView(), - "Expect a top level widget"); - MOZ_ASSERT(!parentListener || !parentListener->GetAsMenuPopupFrame(), - "Expect a top level widget"); -#endif - return true; -} - //------------------------------------------------------------ // XXX this always returns false for subdocuments bool nsDocumentViewer::GetIsPrinting() const { @@ -3400,10 +3348,9 @@ NS_IMETHODIMP nsDocumentViewer::SetPrintSettingsForSubdocument( rv = mPresContext->Init(mDeviceContext); NS_ENSURE_SUCCESS(rv, rv); - rv = MakeWindow(nsSize(mPresContext->DevPixelsToAppUnits(mBounds.width), - mPresContext->DevPixelsToAppUnits(mBounds.height)), - FindContainerView()); - NS_ENSURE_SUCCESS(rv, rv); + MakeWindow(nsSize(mPresContext->DevPixelsToAppUnits(mBounds.width), + mPresContext->DevPixelsToAppUnits(mBounds.height)), + FindContainerView()); MOZ_TRY(InitPresentationStuff(true)); } @@ -3535,7 +3482,7 @@ void nsDocumentViewer::SetPrintPreviewPresentation(nsViewManager* aViewManager, mPresContext = aPresContext; mPresShell = aPresShell; - if (ShouldAttachToTopLevel()) { + if (mParentWidget) { DetachFromTopLevelWidget(); nsView* rootView = mViewManager->GetRootView(); rootView->AttachToTopLevelWidget(mParentWidget); diff --git a/layout/printing/nsPrintJob.cpp b/layout/printing/nsPrintJob.cpp @@ -1286,9 +1286,7 @@ nsresult nsPrintJob::ReflowPrintObject(const UniquePtr<nsPrintObject>& aPO) { // init it with the DC MOZ_TRY(aPO->mPresContext->Init(printData->mPrintDC)); - aPO->mViewManager = new nsViewManager(); - - MOZ_TRY(aPO->mViewManager->Init(printData->mPrintDC)); + aPO->mViewManager = new nsViewManager(printData->mPrintDC); bool doReturn = false; bool documentIsTopLevel = false; diff --git a/view/nsView.cpp b/view/nsView.cpp @@ -382,55 +382,6 @@ void nsView::RemoveChild(nsView* child) { } } -struct DefaultWidgetInitData : public widget::InitData { - DefaultWidgetInitData() : widget::InitData() { - mClipChildren = true; - mClipSiblings = true; - } -}; - -nsresult nsView::CreateWidget(nsIWidget* aParent, bool aEnableDragDrop, - bool aResetVisibility) { - AssertNoWindow(); - - DefaultWidgetInitData initData; - LayoutDeviceIntRect trect = - CalcWidgetBounds(initData.mWindowType, initData.mTransparencyMode); - - if (!aParent && GetParent()) { - aParent = GetParent()->GetNearestWidget(nullptr); - } - if (!aParent) { - NS_ERROR("nsView::CreateWidget without suitable parent widget??"); - return NS_ERROR_FAILURE; - } - - mWindow = aParent->CreateChild(trect, initData); - if (!mWindow) { - return NS_ERROR_FAILURE; - } - - InitializeWindow(aEnableDragDrop, aResetVisibility); - - return NS_OK; -} - -void nsView::InitializeWindow(bool aEnableDragDrop, bool aResetVisibility) { - MOZ_ASSERT(mWindow, "Must have a window to initialize"); - - mWindow->SetWidgetListener(this); - - if (aEnableDragDrop) { - mWindow->EnableDragDrop(true); - } - - // make sure visibility state is accurate - - if (aResetVisibility) { - SetVisibility(GetVisibility()); - } -} - void nsView::SetNeedsWindowPropertiesSync() { mNeedsWindowPropertiesSync = true; if (mViewManager) { @@ -439,8 +390,15 @@ void nsView::SetNeedsWindowPropertiesSync() { } // Attach to a top level widget and start receiving mirrored events. -nsresult nsView::AttachToTopLevelWidget(nsIWidget* aWidget) { +void nsView::AttachToTopLevelWidget(nsIWidget* aWidget) { MOZ_ASSERT(aWidget, "null widget ptr"); +#ifdef DEBUG + nsIWidgetListener* parentListener = aWidget->GetWidgetListener(); + MOZ_ASSERT(!parentListener || !parentListener->GetView(), + "Expect a top level widget"); + MOZ_ASSERT(!parentListener || !parentListener->GetAsMenuPopupFrame(), + "Expect a top level widget"); +#endif /// XXXjimm This is a temporary workaround to an issue w/document // viewer (bug 513162). @@ -458,18 +416,16 @@ nsresult nsView::AttachToTopLevelWidget(nsIWidget* aWidget) { mWindow->SetAttachedWidgetListener(this); if (mWindow->GetWindowType() != WindowType::Invisible) { - nsresult rv = mWindow->AsyncEnableDragDrop(true); - NS_ENSURE_SUCCESS(rv, rv); + mWindow->AsyncEnableDragDrop(true); } mWidgetIsTopLevel = true; // Refresh the view bounds RecalcWidgetBounds(); - return NS_OK; } // Detach this view from an attached widget. -nsresult nsView::DetachFromTopLevelWidget() { +void nsView::DetachFromTopLevelWidget() { MOZ_ASSERT(mWidgetIsTopLevel, "Not attached currently!"); MOZ_ASSERT(mWindow, "null mWindow for DetachFromTopLevelWidget!"); @@ -490,8 +446,6 @@ nsresult nsView::DetachFromTopLevelWidget() { mWindow = nullptr; mWidgetIsTopLevel = false; - - return NS_OK; } void nsView::AssertNoWindow() { diff --git a/view/nsView.h b/view/nsView.h @@ -261,16 +261,6 @@ class nsView final : public nsIWidgetListener { nsIWidget* GetNearestWidget(nsPoint* aOffset) const; /** - * Create a widget to associate with this view. This variant of - * CreateWidget*() will look around in the view hierarchy for an - * appropriate parent widget for the view. - * - * @return error status - */ - nsresult CreateWidget(nsIWidget* aParent, bool aEnableDragDrop = true, - bool aResetVisibility = true); - - /** * Destroys the associated widget for this view. If this method is * not called explicitly, the widget when be destroyed when its * view gets destroyed. @@ -288,8 +278,8 @@ class nsView final : public nsIWidgetListener { * * @param aWidget The widget to attach to / detach from. */ - nsresult AttachToTopLevelWidget(nsIWidget* aWidget); - nsresult DetachFromTopLevelWidget(); + void AttachToTopLevelWidget(nsIWidget* aWidget); + void DetachFromTopLevelWidget(); /** * Returns a flag indicating whether the view owns it's widget diff --git a/view/nsViewManager.cpp b/view/nsViewManager.cpp @@ -51,14 +51,17 @@ using namespace mozilla::layers; uint32_t nsViewManager::gLastUserEventTime = 0; -nsViewManager::nsViewManager() - : mPresShell(nullptr), +nsViewManager::nsViewManager(nsDeviceContext* aContext) + : mContext(aContext), + mPresShell(nullptr), mDelayedResize(NSCOORD_NONE, NSCOORD_NONE), mRootView(nullptr), mRefreshDisableCount(0), mPainting(false), mRecursiveRefreshPending(false), - mHasPendingWidgetGeometryChanges(false) {} + mHasPendingWidgetGeometryChanges(false) { + MOZ_ASSERT(aContext); +} nsViewManager::~nsViewManager() { if (mRootView) { @@ -74,22 +77,6 @@ nsViewManager::~nsViewManager() { "the PresShell!"); } -// We don't hold a reference to the presentation context because it -// holds a reference to us. -nsresult nsViewManager::Init(nsDeviceContext* aContext) { - MOZ_ASSERT(nullptr != aContext, "null ptr"); - - if (nullptr == aContext) { - return NS_ERROR_NULL_POINTER; - } - if (nullptr != mContext) { - return NS_ERROR_ALREADY_INITIALIZED; - } - mContext = aContext; - - return NS_OK; -} - nsView* nsViewManager::CreateView(const nsRect& aBounds, nsView* aParent, ViewVisibility aVisibilityFlag) { auto* v = new nsView(this, aVisibilityFlag); @@ -540,7 +527,9 @@ void nsViewManager::WillPaintWindow(nsIWidget* aWidget) { bool nsViewManager::PaintWindow(nsIWidget* aWidget, const LayoutDeviceIntRegion& aRegion) { - if (!aWidget || !mContext) return false; + if (!aWidget) { + return false; + } NS_ASSERTION( IsPaintingAllowed(), diff --git a/view/nsViewManager.h b/view/nsViewManager.h @@ -36,7 +36,7 @@ class nsViewManager final { NS_INLINE_DECL_REFCOUNTING(nsViewManager) - nsViewManager(); + explicit nsViewManager(nsDeviceContext* aContext); /** * Initialize the ViewManager diff --git a/widget/nsIWidget.cpp b/widget/nsIWidget.cpp @@ -2292,12 +2292,10 @@ void nsIWidget::NotifyLiveResizeStopped() { } } -nsresult nsIWidget::AsyncEnableDragDrop(bool aEnable) { - RefPtr<nsIWidget> kungFuDeathGrip = this; - return NS_DispatchToCurrentThreadQueue( - NS_NewRunnableFunction( - "AsyncEnableDragDropFn", - [this, aEnable, kungFuDeathGrip]() { EnableDragDrop(aEnable); }), +void nsIWidget::AsyncEnableDragDrop(bool aEnable) { + NS_DispatchToCurrentThreadQueue( + NewRunnableMethod<bool>("AsyncEnableDragDrop", this, + &nsIWidget::EnableDragDrop, aEnable), kAsyncDragDropTimeout, EventQueuePriority::Idle); } diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h @@ -1566,7 +1566,7 @@ class nsIWidget : public nsSupportsWeakReference { * Enables the dropping of files to a widget. */ virtual void EnableDragDrop(bool aEnable) {} - nsresult AsyncEnableDragDrop(bool aEnable); + void AsyncEnableDragDrop(bool aEnable); /** * Classify the window for the window manager. Mostly for X11.