commit 2f5c54b4543ddf1fac145ef6f704cd62af2109fa
parent 305f1022d1e65466b1cd97bcc0c5e69b5e556fc5
Author: Emilio Cobos Álvarez <emilio@crisal.io>
Date: Tue, 4 Nov 2025 21:40:33 +0000
Bug 1998239 - Fix nsIFrame::GetNearestWidget to not use nsView::GetNearestWidget. r=jwatt
This unifies the popup and non-popup cases in preparation for
bug 1994942.
There's one tricky bit here, which is that we need to fix the
app-units-per-dev-px that we return the coordinates to.
nsView::GetNearestWidget returns the offset in its own coordinates, so
match that. That bug went unnoticed because we don't have zoomed
subdocuments inside popups.
Differential Revision: https://phabricator.services.mozilla.com/D271274
Diffstat:
1 file changed, 10 insertions(+), 11 deletions(-)
diff --git a/layout/generic/nsIFrame.cpp b/layout/generic/nsIFrame.cpp
@@ -7907,33 +7907,32 @@ nsIWidget* nsIFrame::GetNearestWidget() const {
nsIWidget* nsIFrame::GetNearestWidget(nsPoint& aOffset) const {
aOffset.MoveTo(0, 0);
nsIFrame* frame = const_cast<nsIFrame*>(this);
+ const auto targetAPD = PresContext()->AppUnitsPerDevPixel();
+ auto curAPD = targetAPD;
do {
if (frame->IsMenuPopupFrame()) {
return static_cast<nsMenuPopupFrame*>(frame)->GetWidget();
}
if (auto* view = frame->GetView()) {
- // NOTE(emilio): NS_FRAME_IN_POPUP gets propagated across documents, so we
- // just need to be careful to not jump to the view hierarchy in this case,
- // since popups are not part of it.
- if (!frame->HasAnyStateBits(NS_FRAME_IN_POPUP)) {
- nsPoint offsetToWidget;
- nsIWidget* widget = view->GetNearestWidget(&offsetToWidget);
- aOffset += offsetToWidget;
+ if (auto* widget = view->GetWidget()) {
+ aOffset += view->ViewToWidgetOffset();
+ aOffset = aOffset.ScaleToOtherAppUnits(curAPD, targetAPD);
return widget;
}
- MOZ_ASSERT(!view->GetWidget(),
- "Shouldn't have a nested widget inside a popup");
}
aOffset += frame->GetPosition();
nsPoint crossDocOffset;
frame =
nsLayoutUtils::GetCrossDocParentFrameInProcess(frame, &crossDocOffset);
- aOffset += crossDocOffset;
- MOZ_ASSERT(frame, "Root frame should have a widget");
if (!frame) {
break;
}
+ auto newAPD = frame->PresContext()->AppUnitsPerDevPixel();
+ aOffset = aOffset.ScaleToOtherAppUnits(curAPD, newAPD);
+ aOffset += crossDocOffset;
+ curAPD = newAPD;
} while (true);
+ aOffset = aOffset.ScaleToOtherAppUnits(curAPD, targetAPD);
return PresContext()->GetRootWidget();
}