commit 0295e6c095d8354ab6004eead9e54ac2187c0016
parent 032216be296baeda24895cf5dcc63dfd2c2fcbd6
Author: Emilio Cobos Álvarez <emilio@crisal.io>
Date: Mon, 20 Oct 2025 20:59:49 +0000
Bug 1994908 - Use nearest pres shell widget in ComputeBackstopColor if there's no frame. r=layout-reviewers,dshin
The problem is that we're painting an about:blank document which hasn't
been laid out yet (there's no root frame).
In that case, we used to get a widget from the view tree, but now we
don't.
Introduce PresShell::GetNearestWidget(), and use it to get the closest
widget if there's no root frame so that we don't paint an opaque
backdrop incorrectly.
Differential Revision: https://phabricator.services.mozilla.com/D269293
Diffstat:
2 files changed, 24 insertions(+), 4 deletions(-)
diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp
@@ -126,6 +126,7 @@
#include "mozilla/gfx/Types.h"
#include "mozilla/glean/GfxMetrics.h"
#include "mozilla/glean/LayoutMetrics.h"
+#include "mozilla/glue/Debug.h"
#include "mozilla/layers/APZPublicUtils.h"
#include "mozilla/layers/CompositorBridgeChild.h"
#include "mozilla/layers/FocusTarget.h"
@@ -5610,7 +5611,8 @@ PresShell::CanvasBackground PresShell::ComputeCanvasBackground() const {
}
nscolor PresShell::ComputeBackstopColor(nsIFrame* aDisplayRoot) {
- nsIWidget* widget = aDisplayRoot ? aDisplayRoot->GetNearestWidget() : nullptr;
+ nsIWidget* widget =
+ aDisplayRoot ? aDisplayRoot->GetNearestWidget() : GetNearestWidget();
if (widget &&
(widget->GetTransparencyMode() != widget::TransparencyMode::Opaque ||
widget->WidgetPaintsBackground())) {
@@ -5630,9 +5632,7 @@ struct PaintParams {
WindowRenderer* PresShell::GetWindowRenderer() {
NS_ASSERTION(mViewManager, "Should have view manager");
-
- nsView* rootView = mViewManager->GetRootView();
- if (rootView) {
+ if (nsView* rootView = mViewManager->GetRootView()) {
if (nsIWidget* widget = rootView->GetWidget()) {
return widget->GetWindowRenderer();
}
@@ -5640,6 +5640,22 @@ WindowRenderer* PresShell::GetWindowRenderer() {
return nullptr;
}
+nsIWidget* PresShell::GetNearestWidget() const {
+ if (mViewManager) {
+ if (auto* root = mViewManager->GetRootView()) {
+ if (nsIWidget* widget = root->GetWidget()) {
+ return widget;
+ }
+ }
+ }
+ if (auto* el = mDocument->GetEmbedderElement()) {
+ if (auto* f = el->GetPrimaryFrame()) {
+ return f->GetNearestWidget();
+ }
+ }
+ return GetRootWidget();
+}
+
bool PresShell::AsyncPanZoomEnabled() {
NS_ASSERTION(mViewManager, "Should have view manager");
nsView* rootView = mViewManager->GetRootView();
diff --git a/layout/base/PresShell.h b/layout/base/PresShell.h
@@ -456,6 +456,10 @@ class PresShell final : public nsStubDocumentObserver,
// Return the closest root widget (widget owned by a root frame).
nsIWidget* GetRootWidget() const;
+ // Return the closest widget (including popups, if our document is inside a
+ // popup).
+ nsIWidget* GetNearestWidget() const;
+
/**
* Get root scroll container frame from the frame constructor.
*/