commit ee81313552142c076e7421c8a3949ee9d3c9788f
parent 5c7b1adb9c3f08f3402dc3402cd4ddc959984e5e
Author: Emilio Cobos Álvarez <emilio@crisal.io>
Date: Sat, 22 Nov 2025 19:52:21 +0000
Bug 2000998 - Move widget bounds to nsMenuPopupFrame. r=tnikkel,layout-reviewers
Differential Revision: https://phabricator.services.mozilla.com/D273138
Diffstat:
3 files changed, 23 insertions(+), 90 deletions(-)
diff --git a/layout/xul/nsMenuPopupFrame.cpp b/layout/xul/nsMenuPopupFrame.cpp
@@ -68,6 +68,7 @@
#include "nsXULPopupManager.h"
using namespace mozilla;
+using namespace mozilla::widget;
using mozilla::dom::Document;
using mozilla::dom::Element;
using mozilla::dom::Event;
@@ -339,10 +340,28 @@ void nsMenuPopupFrame::CreateWidget() {
}
LayoutDeviceIntRect nsMenuPopupFrame::CalcWidgetBounds() const {
- return nsView::CalcWidgetBounds(
- GetRect(), PresContext()->AppUnitsPerDevPixel(),
- PresShell()->GetRootFrame(), nullptr, widget::WindowType::Popup,
- nsLayoutUtils::GetFrameTransparency(this, this));
+ auto a2d = PresContext()->AppUnitsPerDevPixel();
+ nsPoint offset;
+ nsIWidget* parentWidget =
+ PresShell()->GetRootFrame()->GetNearestWidget(offset);
+ // We want the bounds be relative to the parent widget, in appunits
+ if (parentWidget) {
+ // put offset into screen coordinates. (based on client area origin)
+ offset += LayoutDeviceIntPoint::ToAppUnits(
+ parentWidget->WidgetToScreenOffset(), a2d);
+ }
+ int32_t roundTo =
+ parentWidget ? parentWidget->RoundsWidgetCoordinatesTo() : 1;
+ auto bounds = GetRect() + offset;
+ // We use outside pixels for transparent windows if possible, so that we
+ // don't truncate the contents. For opaque popups, we use nearest pixels
+ // which prevents having pixels not drawn by the frame.
+ const auto transparency = nsLayoutUtils::GetFrameTransparency(this, this);
+ const bool opaque = transparency == TransparencyMode::Opaque;
+ const auto idealBounds = LayoutDeviceIntRect::FromUnknownRect(
+ opaque ? bounds.ToNearestPixels(a2d) : bounds.ToOutsidePixels(a2d));
+ return nsIWidget::MaybeRoundToDisplayPixels(idealBounds, transparency,
+ roundTo);
}
void nsMenuPopupFrame::DestroyWidget() {
diff --git a/view/nsView.cpp b/view/nsView.cpp
@@ -91,69 +91,6 @@ void nsView::Destroy() {
nsView::operator delete(this);
}
-struct WidgetViewBounds {
- nsRect mBounds;
- int32_t mRoundTo = 1;
-};
-
-static WidgetViewBounds CalcWidgetViewBounds(const nsRect& aBounds,
- int32_t aAppUnitsPerDevPixel,
- nsIFrame* aParentFrame,
- nsIWidget* aThisWidget,
- WindowType aType) {
- nsRect viewBounds(aBounds);
- nsIWidget* parentWidget = nullptr;
- if (aParentFrame) {
- nsPoint offset;
- parentWidget = aParentFrame->GetNearestWidget(offset);
- // make viewBounds be relative to the parent widget, in appunits
- viewBounds += offset;
-
- if (parentWidget && aType == WindowType::Popup) {
- // put offset into screen coordinates. (based on client area origin)
- LayoutDeviceIntPoint screenPoint = parentWidget->WidgetToScreenOffset();
- viewBounds +=
- nsPoint(NSIntPixelsToAppUnits(screenPoint.x, aAppUnitsPerDevPixel),
- NSIntPixelsToAppUnits(screenPoint.y, aAppUnitsPerDevPixel));
- }
- }
-
- nsIWidget* widget = parentWidget ? parentWidget : aThisWidget;
- int32_t roundTo = widget ? widget->RoundsWidgetCoordinatesTo() : 1;
- return {viewBounds, roundTo};
-}
-
-static LayoutDeviceIntRect WidgetViewBoundsToDevicePixels(
- const WidgetViewBounds& aViewBounds, int32_t aAppUnitsPerDevPixel,
- WindowType aType, TransparencyMode aTransparency) {
- // Compute widget bounds in device pixels
- // TODO(emilio): We should probably use outside pixels for transparent
- // windows (not just popups) as well.
- if (aType != WindowType::Popup) {
- return LayoutDeviceIntRect::FromUnknownRect(
- aViewBounds.mBounds.ToNearestPixels(aAppUnitsPerDevPixel));
- }
- // We use outside pixels for transparent windows if possible, so that we
- // don't truncate the contents. For opaque popups, we use nearest pixels
- // which prevents having pixels not drawn by the frame.
- const bool opaque = aTransparency == TransparencyMode::Opaque;
- const auto idealBounds = LayoutDeviceIntRect::FromUnknownRect(
- opaque ? aViewBounds.mBounds.ToNearestPixels(aAppUnitsPerDevPixel)
- : aViewBounds.mBounds.ToOutsidePixels(aAppUnitsPerDevPixel));
-
- return nsIWidget::MaybeRoundToDisplayPixels(idealBounds, aTransparency,
- aViewBounds.mRoundTo);
-}
-
-LayoutDeviceIntRect nsView::CalcWidgetBounds(
- const nsRect& aBounds, int32_t aAppUnitsPerDevPixel, nsIFrame* aParentFrame,
- nsIWidget* aThisWidget, WindowType aType, TransparencyMode aTransparency) {
- auto viewBounds = CalcWidgetViewBounds(aBounds, aAppUnitsPerDevPixel,
- aParentFrame, aThisWidget, aType);
- return WidgetViewBoundsToDevicePixels(viewBounds, aAppUnitsPerDevPixel, aType,
- aTransparency);
-}
-
// Attach to a top level widget and start receiving mirrored events.
void nsView::AttachToTopLevelWidget(nsIWidget* aWidget) {
MOZ_ASSERT(aWidget, "null widget ptr");
@@ -219,12 +156,6 @@ void nsView::List(FILE* out, int32_t aIndent) const {
}
#endif // DEBUG
-bool nsView::IsRoot() const {
- NS_ASSERTION(mViewManager != nullptr,
- " View manager is null in nsView::IsRoot()");
- return mViewManager->GetRootView() == this;
-}
-
PresShell* nsView::GetPresShell() { return GetViewManager()->GetPresShell(); }
bool nsView::WindowResized(nsIWidget* aWidget, int32_t aWidth,
@@ -378,10 +309,6 @@ nsEventStatus nsView::HandleEvent(WidgetGUIEvent* aEvent) {
void nsView::SafeAreaInsetsChanged(
const LayoutDeviceIntMargin& aSafeAreaInsets) {
- if (!IsRoot()) {
- return;
- }
-
PresShell* presShell = mViewManager->GetPresShell();
if (!presShell) {
return;
diff --git a/view/nsView.h b/view/nsView.h
@@ -192,19 +192,6 @@ class nsView final : public nsIWidgetListener {
virtual void List(FILE* out, int32_t aIndent = 0) const;
#endif // DEBUG
- /**
- * @result true iff this is the root view for its view manager
- */
- bool IsRoot() const;
-
- static LayoutDeviceIntRect CalcWidgetBounds(
- const nsRect& aBounds, int32_t aAppUnitsPerDevPixel,
- nsIFrame* aParentFrame, nsIWidget* aThisWidget,
- mozilla::widget::WindowType, mozilla::widget::TransparencyMode);
-
- LayoutDeviceIntRect CalcWidgetBounds(mozilla::widget::WindowType,
- mozilla::widget::TransparencyMode);
-
// nsIWidgetListener
mozilla::PresShell* GetPresShell() override;
nsView* GetView() override { return this; }