tor-browser

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

commit ae9c84efa945f0fbbae86b5a91a36772cbe3e646
parent 3b9fd7d6dbf2f8bc0a428887a0611a66ebcbf0bd
Author: Emilio Cobos Álvarez <emilio@crisal.io>
Date:   Fri, 14 Nov 2025 02:11:08 +0000

Bug 1999867 - Remove some more nsView usage outside of view. r=tnikkel,layout-reviewers

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

Diffstat:
Mgfx/layers/ipc/SharedSurfacesChild.cpp | 3+--
Mlayout/base/PresShell.cpp | 200++++++++++++++++---------------------------------------------------------------
Mlayout/base/PresShell.h | 6+++++-
Mlayout/base/nsCSSFrameConstructor.cpp | 2+-
Mlayout/generic/nsIFrame.cpp | 2+-
Mview/nsView.cpp | 66+++++++++++++++++++++++-------------------------------------------
Mview/nsView.h | 13++++---------
Mview/nsViewManager.cpp | 140++++++++++++++++++++++++++++---------------------------------------------------
Mview/nsViewManager.h | 21+++++----------------
Mwidget/PuppetWidget.cpp | 2+-
Mwidget/gtk/nsWindow.cpp | 23++++++++---------------
Mwidget/nsIWidget.cpp | 18++++++++++++++++--
Mwidget/nsIWidget.h | 3+++
Mwidget/nsIWidgetListener.h | 17+++++------------
14 files changed, 161 insertions(+), 355 deletions(-)

diff --git a/gfx/layers/ipc/SharedSurfacesChild.cpp b/gfx/layers/ipc/SharedSurfacesChild.cpp @@ -480,8 +480,7 @@ void SharedSurfacesAnimation::HoldSurfaceForRecycling( // in nsIWidget that does this for us but there isn't yet. static nsIWidgetListener* GetPaintWidgetListener(nsIWidget* aWidget) { if (auto* attached = aWidget->GetAttachedWidgetListener()) { - if (attached->GetView() && - attached->GetView()->IsPrimaryFramePaintSuppressed()) { + if (attached->IsPaintSuppressed()) { if (auto* previouslyAttached = aWidget->GetPreviouslyAttachedWidgetListener()) { return previouslyAttached; diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp @@ -5748,97 +5748,6 @@ static nsMenuPopupFrame* FindPopupFrame(nsPresContext* aRootPresContext, nsLayoutUtils::GetPopupFrameForPointFlags::OnlyReturnFramesWithWidgets); } -/* - * This finds the first view with a frame that contains the given point in a - * postorder traversal of the view tree, assuming that the point is not in a - * floating view. It assumes that only floating views extend outside the bounds - * of their parents. - * - * This methods should only be called if FindPopupFrame returns null. - * - * aPt is relative aRelativeToView with the viewport type - * aRelativeToViewportType. aRelativeToView will always have a frame. If aView - * has a frame then aRelativeToView will be aView. (The reason aRelativeToView - * and aView are separate is because we need to traverse into views without - * frames (ie the inner view of a subdocument frame) but we can only easily - * transform between views using TransformPoint which takes frames.) - */ -static nsView* FindViewContaining(nsView* aRelativeToView, - ViewportType aRelativeToViewportType, - nsView* aView, nsPoint aPt) { - MOZ_ASSERT(aRelativeToView->GetFrame()); - - nsIFrame* frame = aView->GetFrame(); - if (frame) { - if (!frame->PresShell()->IsActive() || - !frame->IsVisibleConsideringAncestors( - nsIFrame::VISIBILITY_CROSS_CHROME_CONTENT_BOUNDARY)) { - return nullptr; - } - - // We start out in visual coords and then if we cross the zoom boundary we - // become in layout coords. The zoom boundary always occurs in a document - // with IsRootContentDocumentCrossProcess. The root view of such a document - // is outside the zoom boundary and any child view must be inside the zoom - // boundary because we only create views for certain kinds of frames and - // none of them can be between the root frame and the zoom boundary. - bool crossingZoomBoundary = false; - if (aRelativeToViewportType == ViewportType::Visual) { - if (nsIFrame* f = aRelativeToView->GetFrame(); - f && f->PresContext()->IsRootContentDocumentCrossProcess()) { - crossingZoomBoundary = true; - } - } - - ViewportType nextRelativeToViewportType = aRelativeToViewportType; - if (crossingZoomBoundary) { - nextRelativeToViewportType = ViewportType::Layout; - } - - nsLayoutUtils::TransformResult result = nsLayoutUtils::TransformPoint( - RelativeTo{aRelativeToView->GetFrame(), aRelativeToViewportType}, - RelativeTo{frame, nextRelativeToViewportType}, aPt); - if (result != nsLayoutUtils::TRANSFORM_SUCCEEDED) { - return nullptr; - } - - // Even though aPt is in visual coordinates until we cross the zoom boundary - // it is valid to compare it to view coords (which are in layout coords) - // because visual coords are the same as layout coords for every view - // outside of the zoom boundary except for the root view of the root content - // document. - // For the root view of the root content document, its bounds don't - // actually correspond to what is visible when we have a - // MobileViewportManager. So we skip the hit test. This is okay because the - // point has already been hit test: 1) if we are the root view in the - // process then the point comes from a real mouse event so it must have been - // over our widget, or 2) if we are the root of a subdocument then - // hittesting against the view of the subdocument frame that contains us - // already happened and succeeded before getting here. - if (!crossingZoomBoundary) { - if (!aView->GetBounds().Contains(aPt)) { - return nullptr; - } - } - - aRelativeToView = aView; - aRelativeToViewportType = nextRelativeToViewportType; - } - - return frame ? aView : nullptr; -} - -static BrowserBridgeChild* GetChildBrowser(nsView* aView) { - if (!aView) { - return nullptr; - } - nsIFrame* frame = aView->GetFrame(); - if (!frame || !frame->GetContent()) { - return nullptr; - } - return BrowserBridgeChild::GetFrom(frame->GetContent()); -} - void PresShell::ProcessSynthMouseMoveEvent(bool aFromScroll) { auto forgetMouseMove = MakeScopeExit([&]() { // Must be safe to refer `this` without grabbing it with a RefPtr since this @@ -5954,34 +5863,25 @@ void PresShell::ProcessSynthMouseOrPointerMoveEvent( RefPtr<BrowserBridgeChild> bbc; // We either dispatch the event to a popup, or a view. - nsMenuPopupFrame* popupFrame = nullptr; - if (rootView->GetFrame()) { - popupFrame = FindPopupFrame(mPresContext, rootView->GetWidget(), - LayoutDeviceIntPoint::FromAppUnitsToNearest( - aPointerInfo.mLastRefPointInRootDoc, APD)); - if (popupFrame) { - pointShell = popupFrame->PresShell(); - widget = popupFrame->GetWidget(); - widgetAPD = popupFrame->PresContext()->AppUnitsPerDevPixel(); - refpoint = aPointerInfo.mLastRefPointInRootDoc; - DebugOnly<nsLayoutUtils::TransformResult> result = - nsLayoutUtils::TransformPoint( - RelativeTo{rootView->GetFrame(), ViewportType::Visual}, - RelativeTo{popupFrame, ViewportType::Layout}, refpoint); - MOZ_ASSERT(result == nsLayoutUtils::TRANSFORM_SUCCEEDED); - } + nsMenuPopupFrame* popupFrame = + FindPopupFrame(mPresContext, rootView->GetWidget(), + LayoutDeviceIntPoint::FromAppUnitsToNearest( + aPointerInfo.mLastRefPointInRootDoc, APD)); + if (popupFrame) { + pointShell = popupFrame->PresShell(); + widget = popupFrame->GetWidget(); + widgetAPD = popupFrame->PresContext()->AppUnitsPerDevPixel(); + refpoint = aPointerInfo.mLastRefPointInRootDoc; + DebugOnly<nsLayoutUtils::TransformResult> result = + nsLayoutUtils::TransformPoint( + RelativeTo{rootView->GetFrame(), ViewportType::Visual}, + RelativeTo{popupFrame, ViewportType::Layout}, refpoint); + MOZ_ASSERT(result == nsLayoutUtils::TRANSFORM_SUCCEEDED); } if (!widget) { widget = rootView->GetWidget(); widgetAPD = APD; - nsView* pointView = rootView; - if (rootView->GetFrame()) { - pointView = FindViewContaining(rootView, ViewportType::Visual, rootView, - aPointerInfo.mLastRefPointInRootDoc); - } - // pointView can be null in situations related to mouse capture - pointShell = (pointView ? pointView : rootView)->GetPresShell(); - bbc = GetChildBrowser(pointView); + pointShell = this; refpoint = aPointerInfo.mLastRefPointInRootDoc; } NS_ASSERTION(widget, "view should have a widget here"); @@ -6018,41 +5918,20 @@ void PresShell::ProcessSynthMouseOrPointerMoveEvent( event.pointerId = aPointerId; event.mModifiers = PresShell::GetCurrentModifiers(); - if (bbc) { - // If we have a BrowserBridgeChild, we're going to be dispatching this - // mouse event into an OOP iframe of the current document if and only if - // we're synthesizing a mouse move. - // FIXME: We may need to dispatch ePointerMove in the OOP iframe too. - // However, it may require to change the active pointer state in both this - // process and the OOP iframe process too. Therefore, we will fire - // ePointerMove as a preceding pointer event of the synthesized eMouseMove - // in PointerEventHandler::DispatchPointerFromMouseOrTouch(). - if (aMoveMessage == eMouseMove) { - event.mLayersId = bbc->GetLayersId(); - event.convertToPointer = true; - bbc->SendDispatchSynthesizedMouseEvent(event); - } - return; - } - - if (pointShell) { - // Since this gets run in a refresh tick there isn't an InputAPZContext on - // the stack from the nsIWidget. We need to simulate one with at least - // the correct target guid, so that the correct callback transform gets - // applied if this event goes to a child process. The input block id is set - // to 0 because this is a synthetic event which doesn't really belong to any - // input block. Same for the APZ response field. - InputAPZContext apzContext(aPointerInfo.mLastTargetGuid, 0, - nsEventStatus_eIgnore); - AUTO_PROFILER_MARKER_DOCSHELL("DispatchSynthMouseOrPointerMove", GRAPHICS, - pointShell->GetPresContext()->GetDocShell()); - nsEventStatus status = nsEventStatus_eIgnore; - if (popupFrame) { - pointShell->HandleEvent(popupFrame, &event, false, &status); - } else { - RefPtr<nsViewManager> viewManager = rootView->GetViewManager(); - viewManager->DispatchEvent(&event, rootView, &status); - } + MOZ_ASSERT(pointShell); + // Since this gets run in a refresh tick there isn't an InputAPZContext on + // the stack from the nsIWidget. We need to simulate one with at least + // the correct target guid, so that the correct callback transform gets + // applied if this event goes to a child process. The input block id is set + // to 0 because this is a synthetic event which doesn't really belong to any + // input block. Same for the APZ response field. + InputAPZContext apzContext(aPointerInfo.mLastTargetGuid, 0, + nsEventStatus_eIgnore); + AUTO_PROFILER_MARKER_DOCSHELL("DispatchSynthMouseOrPointerMove", GRAPHICS, + pointShell->GetPresContext()->GetDocShell()); + nsEventStatus status = nsEventStatus_eIgnore; + if (auto* eventFrame = popupFrame ? popupFrame : GetRootFrame()) { + pointShell->HandleEvent(eventFrame, &event, false, &status); } } @@ -12328,6 +12207,13 @@ void PresShell::ResetVisualViewportSize() { } } +void PresShell::SetNeedsWindowPropertiesSync() { + mNeedsWindowPropertiesSync = true; + if (mViewManager) { + mViewManager->PostPendingUpdate(); + } +} + bool PresShell::SetVisualViewportOffset(const nsPoint& aScrollOffset, const nsPoint& aPrevLayoutScrollPos) { nsPoint newOffset = aScrollOffset; @@ -12603,15 +12489,12 @@ PresShell::WindowSizeConstraints PresShell::GetWindowSizeConstraints() { return {minSize, maxSize}; } -void PresShell::SyncWindowProperties(bool aSync) { - if (XRE_IsContentProcess()) { +void PresShell::SyncWindowProperties() { + if (!mNeedsWindowPropertiesSync || XRE_IsContentProcess()) { return; } - nsView* view = mViewManager->GetRootView(); - if (!view || !view->HasWidget()) { - return; - } + mNeedsWindowPropertiesSync = false; RefPtr pc = mPresContext; if (!pc) { @@ -12623,11 +12506,6 @@ void PresShell::SyncWindowProperties(bool aSync) { return; } - if (!aSync) { - view->SetNeedsWindowPropertiesSync(); - return; - } - nsIFrame* rootFrame = FrameConstructor()->GetRootElementStyleFrame(); if (!rootFrame) { return; diff --git a/layout/base/PresShell.h b/layout/base/PresShell.h @@ -1276,7 +1276,7 @@ class PresShell final : public nsStubDocumentObserver, return mNeedLayoutFlush || mNeedStyleFlush; } - void SyncWindowProperties(bool aSync); + void SyncWindowProperties(); struct WindowSizeConstraints { nsSize mMinSize; nsSize mMaxSize; @@ -1550,6 +1550,7 @@ class PresShell final : public nsStubDocumentObserver, void SetVisualViewportSize(nscoord aWidth, nscoord aHeight); void ResetVisualViewportSize(); bool IsVisualViewportSizeSet() { return mVisualViewportSizeSet; } + void SetNeedsWindowPropertiesSync(); nsSize GetVisualViewportSize() { NS_ASSERTION(mVisualViewportSizeSet, "asking for visual viewport size when its not set?"); @@ -3390,6 +3391,9 @@ class PresShell final : public nsStubDocumentObserver, // True if a style flush might not be a no-op bool mNeedStyleFlush : 1; + // Whether we need to sync window properties. + bool mNeedsWindowPropertiesSync : 1 = false; + // True if there are throttled animations that would be processed when // performing a flush with mFlushAnimations == true. bool mNeedThrottledAnimationFlush : 1; diff --git a/layout/base/nsCSSFrameConstructor.cpp b/layout/base/nsCSSFrameConstructor.cpp @@ -2670,7 +2670,7 @@ ViewportFrame* nsCSSFrameConstructor::ConstructRootFrame() { // Bind the viewport frame to the root view if (nsView* rootView = mPresShell->GetViewManager()->GetRootView()) { viewportFrame->SetView(rootView); - rootView->SetNeedsWindowPropertiesSync(); + mPresShell->SetNeedsWindowPropertiesSync(); } // Make it an absolute container for fixed-pos elements diff --git a/layout/generic/nsIFrame.cpp b/layout/generic/nsIFrame.cpp @@ -1260,7 +1260,7 @@ void nsIFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle) { const bool isRootElementStyle = Style()->IsRootElementStyle(); if (isRootElementStyle) { - PresShell()->SyncWindowProperties(/* aSync = */ false); + PresShell()->SetNeedsWindowPropertiesSync(); } const nsStyleImageLayers* oldLayers = diff --git a/view/nsView.cpp b/view/nsView.cpp @@ -33,8 +33,7 @@ nsView::nsView(nsViewManager* aViewManager) : mViewManager(aViewManager), mFrame(nullptr), mWidgetIsTopLevel(false), - mForcedRepaint(false), - mNeedsWindowPropertiesSync(false) { + mForcedRepaint(false) { MOZ_COUNT_CTOR(nsView); // Views should be transparent by default. Not being transparent is @@ -108,20 +107,6 @@ void nsView::DestroyWidget() { } } -nsView* nsView::GetViewFor(const nsIWidget* aWidget) { - MOZ_ASSERT(aWidget, "null widget ptr"); - - nsIWidgetListener* listener = aWidget->GetWidgetListener(); - if (listener) { - if (nsView* view = listener->GetView()) { - return view; - } - } - - listener = aWidget->GetAttachedWidgetListener(); - return listener ? listener->GetView() : nullptr; -} - void nsView::Destroy() { this->~nsView(); mozWritePoison(this, sizeof(*this)); @@ -193,19 +178,12 @@ LayoutDeviceIntRect nsView::CalcWidgetBounds( void nsView::SetDimensions(const nsRect& aRect) { mDimBounds = aRect; } -void nsView::SetNeedsWindowPropertiesSync() { - mNeedsWindowPropertiesSync = true; - if (mViewManager) { - mViewManager->PostPendingUpdate(); - } -} - // Attach to a top level widget and start receiving mirrored events. void nsView::AttachToTopLevelWidget(nsIWidget* aWidget) { MOZ_ASSERT(aWidget, "null widget ptr"); #ifdef DEBUG nsIWidgetListener* parentListener = aWidget->GetWidgetListener(); - MOZ_ASSERT(!parentListener || !parentListener->GetView(), + MOZ_ASSERT(!parentListener || parentListener->GetAppWindow(), "Expect a top level widget"); MOZ_ASSERT(!parentListener || !parentListener->GetAsMenuPopupFrame(), "Expect a top level widget"); @@ -278,9 +256,9 @@ void nsView::AttachWidgetEventHandler(nsIWidget* aWidget) { } void nsView::DetachWidgetEventHandler(nsIWidget* aWidget) { - NS_ASSERTION(!aWidget->GetWidgetListener() || - aWidget->GetWidgetListener()->GetView() == this, - "Wrong view"); + NS_ASSERTION( + !aWidget->GetWidgetListener() || aWidget->GetWidgetListener() == this, + "Wrong view"); aWidget->SetWidgetListener(nullptr); } @@ -418,11 +396,9 @@ void nsView::WillPaintWindow(nsIWidget* aWidget) { } bool nsView::PaintWindow(nsIWidget* aWidget, LayoutDeviceIntRegion aRegion) { - NS_ASSERTION(this == nsView::GetViewFor(aWidget), "wrong view for widget?"); - RefPtr<nsViewManager> vm = mViewManager; - bool result = vm->PaintWindow(aWidget, aRegion); - return result; + vm->Refresh(this, aRegion); + return true; } void nsView::DidPaintWindow() { @@ -461,19 +437,23 @@ nsEventStatus nsView::HandleEvent(WidgetGUIEvent* aEvent, MOZ_ASSERT(aEvent->mWidget, "null widget ptr"); nsEventStatus result = nsEventStatus_eIgnore; - nsView* view; - if (aUseAttachedEvents) { - nsIWidgetListener* listener = aEvent->mWidget->GetAttachedWidgetListener(); - view = listener ? listener->GetView() : nullptr; - } else { - view = GetViewFor(aEvent->mWidget); + auto* listener = [&]() -> nsIWidgetListener* { + if (!aUseAttachedEvents) { + if (auto* l = aEvent->mWidget->GetWidgetListener()) { + return l; + } + } + return aEvent->mWidget->GetAttachedWidgetListener(); + }(); + if (NS_WARN_IF(!listener)) { + return result; } - - if (view) { - RefPtr<nsViewManager> vm = view->GetViewManager(); - vm->DispatchEvent(aEvent, view, &result); + nsViewManager::MaybeUpdateLastUserEventTime(aEvent); + if (RefPtr<PresShell> ps = listener->GetPresShell()) { + if (nsIFrame* root = ps->GetRootFrame()) { + ps->HandleEvent(root, aEvent, false, &result); + } } - return result; } @@ -507,7 +487,7 @@ void nsView::SafeAreaInsetsChanged( }); } -bool nsView::IsPrimaryFramePaintSuppressed() { +bool nsView::IsPrimaryFramePaintSuppressed() const { return StaticPrefs::layout_show_previous_page() && mFrame && mFrame->PresShell()->IsPaintingSuppressed(); } diff --git a/view/nsView.h b/view/nsView.h @@ -126,13 +126,6 @@ class nsView final : public nsIWidgetListener { nsViewManager* GetViewManager() const { return mViewManager; } /** - * Find the view for the given widget, if there is one. - * @return the view the widget belongs to, or null if the widget doesn't - * belong to any view. - */ - static nsView* GetViewFor(const nsIWidget* aWidget); - - /** * Destroy the view. * * The view destroys its child views, and destroys and releases its @@ -255,6 +248,9 @@ class nsView final : public nsIWidgetListener { // nsIWidgetListener mozilla::PresShell* GetPresShell() override; nsView* GetView() override { return this; } + bool IsPaintSuppressed() const override { + return IsPrimaryFramePaintSuppressed(); + } bool WindowResized(nsIWidget* aWidget, int32_t aWidth, int32_t aHeight) override; #ifdef MOZ_WIDGET_ANDROID @@ -280,7 +276,7 @@ class nsView final : public nsIWidgetListener { virtual ~nsView(); - bool IsPrimaryFramePaintSuppressed(); + bool IsPrimaryFramePaintSuppressed() const; private: explicit nsView(nsViewManager* = nullptr); @@ -314,7 +310,6 @@ class nsView final : public nsIWidgetListener { nsRect mDimBounds; bool mWidgetIsTopLevel; bool mForcedRepaint; - bool mNeedsWindowPropertiesSync; bool mIsDirty = false; }; diff --git a/view/nsViewManager.cpp b/view/nsViewManager.cpp @@ -241,18 +241,10 @@ void nsViewManager::ProcessPendingUpdatesForView(nsView* aView, RefPtr<PresShell> rootPresShell = mPresShell; AutoTArray<nsCOMPtr<nsIWidget>, 1> widgets; aView->GetViewManager()->ProcessPendingUpdatesRecurse(aView, widgets); - for (uint32_t i = 0; i < widgets.Length(); ++i) { - nsView* view = nsView::GetViewFor(widgets[i]); - if (!view) { - continue; - } - if (view->mNeedsWindowPropertiesSync) { - view->mNeedsWindowPropertiesSync = false; - if (nsViewManager* vm = view->GetViewManager()) { - if (PresShell* presShell = vm->GetPresShell()) { - presShell->SyncWindowProperties(/* aSync */ true); - } - } + for (nsIWidget* widget : widgets) { + MOZ_ASSERT(widget->IsTopLevelWidget()); + if (RefPtr ps = widget->GetPresShell()) { + ps->SyncWindowProperties(); } } if (rootPresShell->GetViewManager() != this) { @@ -262,9 +254,9 @@ void nsViewManager::ProcessPendingUpdatesForView(nsView* aView, nsAutoScriptBlocker scriptBlocker; SetPainting(true); for (nsIWidget* widget : widgets) { - if (nsView* view = nsView::GetViewFor(widget)) { - RefPtr<nsViewManager> viewManager = view->GetViewManager(); - viewManager->ProcessPendingUpdatesPaint(MOZ_KnownLive(widget)); + if (RefPtr ps = widget->GetPresShell()) { + RefPtr vm = ps->GetViewManager(); + vm->ProcessPendingUpdatesPaint(MOZ_KnownLive(widget)); } } SetPainting(false); @@ -283,47 +275,46 @@ void nsViewManager::ProcessPendingUpdatesRecurse( } void nsViewManager::ProcessPendingUpdatesPaint(nsIWidget* aWidget) { - if (aWidget->NeedsPaint()) { - // If an ancestor widget was hidden and then shown, we could - // have a delayed resize to handle. - if (mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) && mPresShell && - mPresShell->IsVisible()) { - FlushDelayedResize(); - } - nsView* view = nsView::GetViewFor(aWidget); - if (!view) { - NS_ERROR("FlushDelayedResize destroyed the nsView?"); - return; - } + if (!aWidget->NeedsPaint()) { + return; + } + // If an ancestor widget was hidden and then shown, we could + // have a delayed resize to handle. + if (mDelayedResize != nsSize(NSCOORD_NONE, NSCOORD_NONE) && mPresShell && + mPresShell->IsVisible()) { + FlushDelayedResize(); + } + + if (!mRootView || !mPresShell) { + NS_ERROR("FlushDelayedResize destroyed the view?"); + return; + } - nsIWidgetListener* previousListener = - aWidget->GetPreviouslyAttachedWidgetListener(); + nsIWidgetListener* previousListener = + aWidget->GetPreviouslyAttachedWidgetListener(); - if (previousListener && previousListener != view && - view->IsPrimaryFramePaintSuppressed()) { - return; - } + if (previousListener && previousListener != mRootView && + mRootView->IsPrimaryFramePaintSuppressed()) { + return; + } - if (RefPtr<PresShell> presShell = mPresShell) { + RefPtr ps = mPresShell; #ifdef MOZ_DUMP_PAINTING - if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { - printf_stderr( - "---- PAINT START ----PresShell(%p), nsView(%p), nsIWidget(%p)\n", - presShell.get(), view, aWidget); - } + if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { + printf_stderr("---- PAINT START ----PresShell(%p), nsIWidget(%p)\n", + ps.get(), aWidget); + } #endif - presShell->PaintAndRequestComposite( - view->GetFrame(), aWidget->GetWindowRenderer(), PaintFlags::None); - view->SetForcedRepaint(false); + ps->PaintAndRequestComposite(ps->GetRootFrame(), aWidget->GetWindowRenderer(), + PaintFlags::None); + mRootView->SetForcedRepaint(false); #ifdef MOZ_DUMP_PAINTING - if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { - printf_stderr("---- PAINT END ----\n"); - } -#endif - } + if (nsLayoutUtils::InvalidationDebuggingIsEnabled()) { + printf_stderr("---- PAINT END ----\n"); } +#endif } void nsViewManager::PostPendingUpdate() { @@ -336,35 +327,19 @@ void nsViewManager::PostPendingUpdate() { } void nsViewManager::WillPaintWindow(nsIWidget* aWidget) { - if (aWidget) { - nsView* view = nsView::GetViewFor(aWidget); - WindowRenderer* renderer = aWidget->GetWindowRenderer(); - if (view && - (view->ForcedRepaint() || !renderer->NeedsWidgetInvalidation())) { - ProcessPendingUpdates(); - // Re-get the view pointer here since the ProcessPendingUpdates might have - // destroyed it during CallWillPaintOnObservers. - view = nsView::GetViewFor(aWidget); - if (view) { - view->SetForcedRepaint(false); - } - } - } -} - -bool nsViewManager::PaintWindow(nsIWidget* aWidget, - const LayoutDeviceIntRegion& aRegion) { if (!aWidget) { - return false; + return; } - // Get the view pointer here since NS_WILL_PAINT might have - // destroyed it during CallWillPaintOnObservers (bug 378273). - nsView* view = nsView::GetViewFor(aWidget); - if (view && !aRegion.IsEmpty()) { - Refresh(view, aRegion); + WindowRenderer* renderer = aWidget->GetWindowRenderer(); + if (mRootView && + (mRootView->ForcedRepaint() || !renderer->NeedsWidgetInvalidation())) { + ProcessPendingUpdates(); + // Re-get the view pointer here since the ProcessPendingUpdates might have + // destroyed it during CallWillPaintOnObservers. + if (mRootView) { + mRootView->SetForcedRepaint(false); + } } - - return true; } void nsViewManager::DidPaintWindow() { @@ -373,10 +348,7 @@ void nsViewManager::DidPaintWindow() { } } -void nsViewManager::DispatchEvent(WidgetGUIEvent* aEvent, nsView* aView, - nsEventStatus* aStatus) { - AUTO_PROFILER_LABEL("nsViewManager::DispatchEvent", OTHER); - +void nsViewManager::MaybeUpdateLastUserEventTime(WidgetGUIEvent* aEvent) { WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent(); if ((mouseEvent && // Ignore mouse events that we synthesize. @@ -389,20 +361,6 @@ void nsViewManager::DispatchEvent(WidgetGUIEvent* aEvent, nsView* aView, aEvent->HasKeyEventMessage() || aEvent->HasIMEEventMessage()) { gLastUserEventTime = PR_IntervalToMicroseconds(PR_IntervalNow()); } - - // Find the view whose coordinates system we're in. - // If the view has no frame, look for a view that does. - if (nsIFrame* frame = aView->GetFrame()) { - // Hold a refcount to the presshell. The continued existence of the - // presshell will delay deletion of this view hierarchy should the event - // want to cause its destruction in, say, some JavaScript event handler. - if (RefPtr<PresShell> presShell = aView->GetViewManager()->GetPresShell()) { - presShell->HandleEvent(frame, aEvent, false, aStatus); - return; - } - } - - *aStatus = nsEventStatus_eIgnore; } void nsViewManager::ResizeView(nsView* aView, const nsRect& aRect) { diff --git a/view/nsViewManager.h b/view/nsViewManager.h @@ -82,18 +82,6 @@ class nsViewManager final { void FlushDelayedResize(); /** - * 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. - * @param aEvent event to dispatch - * @param aViewTarget dispatch the event to this view - * @param aStatus event handling status - */ - MOZ_CAN_RUN_SCRIPT - void DispatchEvent(mozilla::WidgetGUIEvent* aEvent, nsView* aViewTarget, - nsEventStatus* aStatus); - - /** * Resize a view. In addition to setting the width and height, you can * set the x and y of its bounds relative to its position. Negative x and y * will let the view extend above and to the left of the (0,0) point in its @@ -130,6 +118,7 @@ class nsViewManager final { * saves the time of the last user event. */ static uint32_t GetLastUserEventTime() { return gLastUserEventTime; } + static void MaybeUpdateLastUserEventTime(mozilla::WidgetGUIEvent*); /** * Flush the accumulated dirty region to the widget and update widget @@ -142,6 +131,10 @@ class nsViewManager final { */ MOZ_CAN_RUN_SCRIPT void UpdateWidgetGeometry(); + // Call this when you need to let the viewmanager know that it now has + // pending updates. + void PostPendingUpdate(); + private: static uint32_t gLastUserEventTime; @@ -182,10 +175,6 @@ class nsViewManager final { bool PaintWindow(nsIWidget* aWidget, const LayoutDeviceIntRegion& aRegion); MOZ_CAN_RUN_SCRIPT void DidPaintWindow(); - // Call this when you need to let the viewmanager know that it now has - // pending updates. - void PostPendingUpdate(); - mozilla::PresShell* mPresShell; // The size for a resize that we delayed until the root view becomes diff --git a/widget/PuppetWidget.cpp b/widget/PuppetWidget.cpp @@ -995,7 +995,7 @@ nsIWidgetListener* PuppetWidget::GetCurrentWidgetListener() { return mAttachedWidgetListener; } - if (mAttachedWidgetListener->GetView()->IsPrimaryFramePaintSuppressed()) { + if (mAttachedWidgetListener->IsPaintSuppressed()) { return mPreviouslyAttachedWidgetListener; } diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp @@ -569,7 +569,9 @@ void nsWindow::DispatchActivateEvent(void) { DispatchActivateEventAccessible(); #endif // ACCESSIBILITY - if (mWidgetListener) mWidgetListener->WindowActivated(); + if (mWidgetListener) { + mWidgetListener->WindowActivated(); + } } void nsWindow::DispatchDeactivateEvent() { @@ -5721,10 +5723,8 @@ void nsWindow::OnWindowStateEvent(GtkWidget* aWidget, void nsWindow::OnDPIChanged() { // Update menu's font size etc. // This affects style / layout because it affects system font sizes. - if (mWidgetListener) { - if (PresShell* presShell = mWidgetListener->GetPresShell()) { - presShell->BackingScaleFactorChanged(); - } + if (PresShell* presShell = GetPresShell()) { + presShell->BackingScaleFactorChanged(); } NotifyAPZOfDPIChange(); } @@ -5800,10 +5800,8 @@ void nsWindow::RefreshScale(bool aRefreshScreen, bool aForceRefresh) { RecomputeBounds(/* MayChangeCsdMargin */ true, /* ScaleChanged*/ true); - if (mWidgetListener) { - if (PresShell* presShell = mWidgetListener->GetPresShell()) { - presShell->BackingScaleFactorChanged(); - } + if (PresShell* presShell = GetPresShell()) { + presShell->BackingScaleFactorChanged(); } if (mCursor.IsCustom()) { @@ -9920,11 +9918,7 @@ void nsWindow::UpdateMozWindowActive() { void nsWindow::ForceTitlebarRedraw() { MOZ_ASSERT(mDrawInTitlebar, "We should not redraw invisible titlebar."); - - if (!mWidgetListener) { - return; - } - PresShell* ps = mWidgetListener->GetPresShell(); + PresShell* ps = GetPresShell(); if (!ps) { return; } @@ -9932,7 +9926,6 @@ void nsWindow::ForceTitlebarRedraw() { if (!frame) { return; } - frame = FindTitlebarFrame(frame); if (frame) { nsIContent* content = frame->GetContent(); diff --git a/widget/nsIWidget.cpp b/widget/nsIWidget.cpp @@ -491,8 +491,8 @@ nsIFrame* nsIWidget::GetFrame() const { if (auto* popup = GetPopupFrame()) { return popup; } - if (nsView* view = nsView::GetViewFor(this)) { - return view->GetFrame(); + if (auto* ps = GetPresShell()) { + return ps->GetRootFrame(); } return nullptr; } @@ -2017,6 +2017,20 @@ nsIWidget::TextEventDispatcher* nsIWidget::GetTextEventDispatcher() { return mTextEventDispatcher; } +PresShell* nsIWidget::GetPresShell() const { + if (mWidgetListener) { + if (auto* ps = mWidgetListener->GetPresShell()) { + return ps; + } + } + if (mAttachedWidgetListener) { + if (auto* ps = mAttachedWidgetListener->GetPresShell()) { + return ps; + } + } + return nullptr; +} + void* nsIWidget::GetPseudoIMEContext() { TextEventDispatcher* dispatcher = GetTextEventDispatcher(); if (!dispatcher) { diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h @@ -2269,6 +2269,9 @@ class nsIWidget : public nsSupportsWeakReference { */ TextEventDispatcher* GetTextEventDispatcher(); + // Gets the pres shell this widget is managed by. + mozilla::PresShell* GetPresShell() const; + /** * GetNativeTextEventDispatcherListener() returns a * TextEventDispatcherListener instance which is used when the widget diff --git a/widget/nsIWidgetListener.h b/widget/nsIWidgetListener.h @@ -34,25 +34,15 @@ enum nsSizeMode { nsSizeMode_Invalid }; -/** - * different types of (top-level) window z-level positioning - */ -enum nsWindowZ { - nsWindowZTop = 0, // on top - nsWindowZBottom, // on bottom - nsWindowZRelative // just below some specified widget -}; - class nsIWidgetListener { public: /** * If this listener is for an nsIAppWindow, return it. If this is null, then - * this is likely a listener for a view, which can be determined using - * GetView. If both methods return null, this will be an nsWebBrowser. + * this is likely a listener for a popup or a pres shell. */ virtual nsIAppWindow* GetAppWindow() { return nullptr; } - /** If this listener is for an nsView, return it. */ + /** If this listener is for a view, return it. */ virtual nsView* GetView() { return nullptr; } /** If this listener is for an nsMenuPopupFrame, return it. */ @@ -163,6 +153,9 @@ class nsIWidgetListener { */ virtual bool ShouldNotBeVisible() { return false; } + /** Returns true if painting should be suppressed for this listener */ + virtual bool IsPaintSuppressed() const { return false; } + /** Handle an event. */ virtual nsEventStatus HandleEvent(mozilla::WidgetGUIEvent* aEvent, bool aUseAttachedEvents) {