commit b29a50ebafaf877deaf51650767e8fb2392f6e8f
parent d673d2a47124bbf7f250cb86f6e1b5aafd76b6dd
Author: Serban Stanca <sstanca@mozilla.com>
Date: Wed, 12 Nov 2025 12:14:33 +0200
Revert "Bug 1999623 - Remove view to widget offset. r=tnikkel,layout-reviewers" for causing build bustages in nsLayoutUtils.cpp.
This reverts commit e0b9d3d67032ec26a9ac82dc84dba9e924761de5.
Diffstat:
6 files changed, 78 insertions(+), 3 deletions(-)
diff --git a/layout/base/PresShell.cpp b/layout/base/PresShell.cpp
@@ -5961,7 +5961,9 @@ void PresShell::ProcessSynthMouseOrPointerMoveEvent(
if (rootView->GetFrame()) {
popupFrame = FindPopupFrame(mPresContext, rootView->GetWidget(),
LayoutDeviceIntPoint::FromAppUnitsToNearest(
- aPointerInfo.mLastRefPointInRootDoc, APD));
+ aPointerInfo.mLastRefPointInRootDoc +
+ rootView->ViewToWidgetOffset(),
+ APD));
if (popupFrame) {
pointShell = popupFrame->PresShell();
widget = popupFrame->GetWidget();
@@ -5985,7 +5987,8 @@ void PresShell::ProcessSynthMouseOrPointerMoveEvent(
// pointView can be null in situations related to mouse capture
pointShell = (pointView ? pointView : rootView)->GetPresShell();
bbc = GetChildBrowser(pointView);
- refpoint = aPointerInfo.mLastRefPointInRootDoc;
+ refpoint =
+ aPointerInfo.mLastRefPointInRootDoc + rootView->ViewToWidgetOffset();
}
NS_ASSERTION(widget, "view should have a widget here");
Maybe<WidgetMouseEvent> mouseMoveEvent;
diff --git a/layout/generic/nsIFrame.cpp b/layout/generic/nsIFrame.cpp
@@ -7868,6 +7868,7 @@ nsIWidget* nsIFrame::GetNearestWidget(nsPoint& aOffset) const {
}
if (auto* view = frame->GetView()) {
if (auto* widget = view->GetWidget()) {
+ aOffset += view->ViewToWidgetOffset();
aOffset = aOffset.ScaleToOtherAppUnits(curAPD, targetAPD);
return widget;
}
diff --git a/view/nsView.cpp b/view/nsView.cpp
@@ -181,6 +181,29 @@ static LayoutDeviceIntRect WidgetViewBoundsToDevicePixels(
aViewBounds.mRoundTo);
}
+LayoutDeviceIntRect nsView::CalcWidgetBounds(WindowType aType,
+ TransparencyMode aTransparency) {
+ int32_t p2a = mViewManager->AppUnitsPerDevPixel();
+ auto viewBounds =
+ CalcWidgetViewBounds(mDimBounds, p2a, nullptr, mWindow.get(), aType);
+ auto newBounds =
+ WidgetViewBoundsToDevicePixels(viewBounds, p2a, aType, aTransparency);
+
+ // Compute where the top-left of our widget ended up relative to the parent
+ // widget, in appunits.
+ nsPoint roundedOffset(NSIntPixelsToAppUnits(newBounds.X(), p2a),
+ NSIntPixelsToAppUnits(newBounds.Y(), p2a));
+
+ // mViewToWidgetOffset is added to coordinates relative to the view origin
+ // to get coordinates relative to the widget.
+ // The view origin, relative to the parent widget, is at
+ // mDimBounds.TopLeft() + viewBounds.TopLeft().
+ // Our widget, relative to the parent widget, is roundedOffset.
+ mViewToWidgetOffset =
+ mDimBounds.TopLeft() + viewBounds.mBounds.TopLeft() - roundedOffset;
+ return newBounds;
+}
+
LayoutDeviceIntRect nsView::CalcWidgetBounds(
const nsRect& aBounds, int32_t aAppUnitsPerDevPixel, nsIFrame* aParentFrame,
nsIWidget* aThisWidget, WindowType aType, TransparencyMode aTransparency) {
@@ -190,7 +213,23 @@ LayoutDeviceIntRect nsView::CalcWidgetBounds(
aTransparency);
}
-void nsView::SetDimensions(const nsRect& aRect) { mDimBounds = aRect; }
+LayoutDeviceIntRect nsView::RecalcWidgetBounds() {
+ MOZ_ASSERT(mWindow);
+ return CalcWidgetBounds(mWindow->GetWindowType(),
+ mWindow->GetTransparencyMode());
+}
+
+void nsView::SetDimensions(const nsRect& aRect) {
+ // Don't use nsRect's operator== here, since it returns true when
+ // both rects are empty even if they have different widths and we
+ // have cases where that sort of thing matters to us.
+ if (mDimBounds.TopLeft() == aRect.TopLeft() &&
+ mDimBounds.Size() == aRect.Size()) {
+ return;
+ }
+
+ mDimBounds = aRect;
+}
void nsView::SetNeedsWindowPropertiesSync() {
mNeedsWindowPropertiesSync = true;
@@ -229,6 +268,9 @@ void nsView::AttachToTopLevelWidget(nsIWidget* aWidget) {
mWindow->AsyncEnableDragDrop(true);
}
mWidgetIsTopLevel = true;
+
+ // Refresh the view bounds
+ RecalcWidgetBounds();
}
// Detach this view from an attached widget.
diff --git a/view/nsView.h b/view/nsView.h
@@ -252,6 +252,14 @@ class nsView final : public nsIWidgetListener {
LayoutDeviceIntRect CalcWidgetBounds(mozilla::widget::WindowType,
mozilla::widget::TransparencyMode);
+ LayoutDeviceIntRect RecalcWidgetBounds();
+
+ // This is an app unit offset to add when converting view coordinates to
+ // widget coordinates. It is the offset in view coordinates from widget
+ // origin (unlike views, widgets can't extend above or to the left of their
+ // origin) to view origin expressed in appunits of this.
+ nsPoint ViewToWidgetOffset() const { return mViewToWidgetOffset; }
+
// nsIWidgetListener
mozilla::PresShell* GetPresShell() override;
nsView* GetView() override { return this; }
@@ -313,6 +321,8 @@ class nsView final : public nsIWidgetListener {
nsIFrame* mFrame;
// relative to parent, but in our appunits
nsRect mDimBounds;
+ // in our appunits
+ nsPoint mViewToWidgetOffset;
bool mWidgetIsTopLevel;
bool mForcedRepaint;
bool mNeedsWindowPropertiesSync;
diff --git a/view/nsViewManager.cpp b/view/nsViewManager.cpp
@@ -531,6 +531,18 @@ void nsViewManager::ResizeView(nsView* aView, const nsRect& aRect) {
// because layout will change it back again if necessary.
}
+LayoutDeviceIntRect nsViewManager::ViewToWidget(nsView* aView,
+ const nsRect& aRect) const {
+ NS_ASSERTION(aView->GetViewManager() == this, "wrong view manager");
+
+ // account for the view's origin not lining up with the widget's
+ nsRect rect = aRect + aView->ViewToWidgetOffset();
+
+ // finally, convert to device coordinates.
+ return LayoutDeviceIntRect::FromUnknownRect(
+ rect.ToOutsidePixels(AppUnitsPerDevPixel()));
+}
+
void nsViewManager::IsPainting(bool& aIsPainting) {
aIsPainting = IsPainting();
}
diff --git a/view/nsViewManager.h b/view/nsViewManager.h
@@ -204,6 +204,13 @@ class nsViewManager final {
MOZ_CAN_RUN_SCRIPT
void Refresh(nsView* aView, const LayoutDeviceIntRegion& aRegion);
+ /**
+ * Intersects aRect with aView's bounds and then transforms it from aView's
+ * coordinate system to the coordinate system of the widget attached to
+ * aView.
+ */
+ LayoutDeviceIntRect ViewToWidget(nsView* aView, const nsRect& aRect) const;
+
MOZ_CAN_RUN_SCRIPT_BOUNDARY
void DoSetWindowDimensions(nscoord aWidth, nscoord aHeight);
bool ShouldDelayResize() const;