From 5077bb750f94023bded748bd1b0869d7c3d2db38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 16 Jan 2023 23:35:34 +0000 Subject: [PATCH] Bug 1809430 - Clean up ClientToWindowRect. r=cmartin,mstange Make it return a margin from client area to window area, and add an explicit function to get the size difference. No behavior change. Depends on D166428 Differential Revision: https://phabricator.services.mozilla.com/D166431 --- layout/generic/nsContainerFrame.cpp | 23 ++++++++++--------- widget/cocoa/nsCocoaWindow.h | 2 +- widget/cocoa/nsCocoaWindow.mm | 17 ++++++++------- widget/nsBaseWidget.cpp | 9 ++++++++ widget/nsBaseWidget.h | 5 ----- widget/nsIWidget.h | 11 +++++----- widget/windows/nsWindow.cpp | 34 ++++++++++++++++------------- widget/windows/nsWindow.h | 3 +-- xpfe/appshell/AppWindow.cpp | 4 +--- 9 files changed, 59 insertions(+), 49 deletions(-) diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp index e76355d02cfd..a0ed7e5cc12d 100644 --- a/layout/generic/nsContainerFrame.cpp +++ b/layout/generic/nsContainerFrame.cpp @@ -869,16 +869,19 @@ void nsContainerFrame::SetSizeConstraints(nsPresContext* aPresContext, // The sizes are in inner window sizes, so convert them into outer window // sizes. Use a size of (200, 200) as only the difference between the inner // and outer size is needed. - LayoutDeviceIntSize windowSize = - aWidget->ClientToWindowSize(LayoutDeviceIntSize(200, 200)); - if (constraints.mMinSize.width) - constraints.mMinSize.width += windowSize.width - 200; - if (constraints.mMinSize.height) - constraints.mMinSize.height += windowSize.height - 200; - if (constraints.mMaxSize.width != NS_MAXSIZE) - constraints.mMaxSize.width += windowSize.width - 200; - if (constraints.mMaxSize.height != NS_MAXSIZE) - constraints.mMaxSize.height += windowSize.height - 200; + const LayoutDeviceIntSize sizeDiff = aWidget->ClientToWindowSizeDifference(); + if (constraints.mMinSize.width) { + constraints.mMinSize.width += sizeDiff.width; + } + if (constraints.mMinSize.height) { + constraints.mMinSize.height += sizeDiff.height; + } + if (constraints.mMaxSize.width != NS_MAXSIZE) { + constraints.mMaxSize.width += sizeDiff.width; + } + if (constraints.mMaxSize.height != NS_MAXSIZE) { + constraints.mMaxSize.height += sizeDiff.height; + } aWidget->SetSizeConstraints(constraints); } diff --git a/widget/cocoa/nsCocoaWindow.h b/widget/cocoa/nsCocoaWindow.h index 887f9023a2b1..3d54e102f175 100644 --- a/widget/cocoa/nsCocoaWindow.h +++ b/widget/cocoa/nsCocoaWindow.h @@ -249,7 +249,7 @@ class nsCocoaWindow final : public nsBaseWidget, public nsPIWidgetCocoa { virtual void SetFocus(Raise, mozilla::dom::CallerType aCallerType) override; virtual LayoutDeviceIntPoint WidgetToScreenOffset() override; virtual LayoutDeviceIntPoint GetClientOffset() override; - virtual LayoutDeviceIntSize ClientToWindowSize(const LayoutDeviceIntSize& aClientSize) override; + virtual LayoutDeviceIntMargin ClientToWindowMargin() override; virtual void* GetNativeData(uint32_t aDataType) override; diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm index 55a254015550..0a5dc4010064 100644 --- a/widget/cocoa/nsCocoaWindow.mm +++ b/widget/cocoa/nsCocoaWindow.mm @@ -2224,22 +2224,23 @@ LayoutDeviceIntPoint nsCocoaWindow::GetClientOffset() { NS_OBJC_END_TRY_BLOCK_RETURN(LayoutDeviceIntPoint(0, 0)); } -LayoutDeviceIntSize nsCocoaWindow::ClientToWindowSize(const LayoutDeviceIntSize& aClientSize) { +LayoutDeviceIntMargin nsCocoaWindow::ClientToWindowMargin() { NS_OBJC_BEGIN_TRY_BLOCK_RETURN; if (!mWindow) { - return LayoutDeviceIntSize(0, 0); + return {}; } + NSRect clientNSRect = [mWindow contentLayoutRect]; + NSRect frameNSRect = [mWindow frameRectForContentRect:clientNSRect]; + CGFloat backingScale = BackingScaleFactor(); - LayoutDeviceIntRect r(0, 0, aClientSize.width, aClientSize.height); - NSRect rect = nsCocoaUtils::DevPixelsToCocoaPoints(r, backingScale); + const auto clientRect = nsCocoaUtils::CocoaRectToGeckoRectDevPix(clientNSRect, backingScale); + const auto frameRect = nsCocoaUtils::CocoaRectToGeckoRectDevPix(frameNSRect, backingScale); - NSRect maybeInflatedRect = [mWindow frameRectForContentRect:rect]; - r = nsCocoaUtils::CocoaRectToGeckoRectDevPix(maybeInflatedRect, backingScale); - return r.Size(); + return frameRect - clientRect; - NS_OBJC_END_TRY_BLOCK_RETURN(LayoutDeviceIntSize(0, 0)); + NS_OBJC_END_TRY_BLOCK_RETURN({}); } nsMenuBarX* nsCocoaWindow::GetMenuBar() { return mMenuBar; } diff --git a/widget/nsBaseWidget.cpp b/widget/nsBaseWidget.cpp index fcf4467a0642..7fa20b0c2f0e 100644 --- a/widget/nsBaseWidget.cpp +++ b/widget/nsBaseWidget.cpp @@ -567,6 +567,15 @@ nsIntSize nsIWidget::CustomCursorSize(const Cursor& aCursor) { return {width, height}; } +LayoutDeviceIntSize nsIWidget::ClientToWindowSizeDifference() { + auto margin = ClientToWindowMargin(); + MOZ_ASSERT(margin.top >= 0, "Window should be bigger than client area"); + MOZ_ASSERT(margin.left >= 0, "Window should be bigger than client area"); + MOZ_ASSERT(margin.right >= 0, "Window should be bigger than client area"); + MOZ_ASSERT(margin.bottom >= 0, "Window should be bigger than client area"); + return {margin.LeftRight(), margin.TopBottom()}; +} + RefPtr nsIWidget::GetVsyncDispatcher() { return nullptr; } diff --git a/widget/nsBaseWidget.h b/widget/nsBaseWidget.h index 55858bc399d4..790c52734f34 100644 --- a/widget/nsBaseWidget.h +++ b/widget/nsBaseWidget.h @@ -365,11 +365,6 @@ class nsBaseWidget : public nsIWidget, public nsSupportsWeakReference { nsPopupLevel PopupLevel() { return mPopupLevel; } - LayoutDeviceIntSize ClientToWindowSize( - const LayoutDeviceIntSize& aClientSize) override { - return aClientSize; - } - // return true if this is a popup widget with a native titlebar bool IsPopupWithTitleBar() const { return (mWindowType == eWindowType_popup && diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h index c4c5d6488082..d268bc06bdba 100644 --- a/widget/nsIWidget.h +++ b/widget/nsIWidget.h @@ -1329,12 +1329,13 @@ class nsIWidget : public nsISupports { } /** - * Given the specified client size, return the corresponding window size, - * which includes the area for the borders and titlebar. This method - * should work even when the window is not yet visible. + * Returns the margins that are applied to go from client sizes to window + * sizes (which includes window borders and titlebar). + * This method should work even when the window is not yet visible. */ - virtual LayoutDeviceIntSize ClientToWindowSize( - const LayoutDeviceIntSize& aClientSize) = 0; + virtual LayoutDeviceIntMargin ClientToWindowMargin() { return {}; } + + LayoutDeviceIntSize ClientToWindowSizeDifference(); /** * Dispatches an event to the widget diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp index 6f88afd75808..3358b16e79d0 100644 --- a/widget/windows/nsWindow.cpp +++ b/widget/windows/nsWindow.cpp @@ -3871,27 +3871,31 @@ LayoutDeviceIntPoint nsWindow::WidgetToScreenOffset() { return LayoutDeviceIntPoint(point.x, point.y); } -LayoutDeviceIntSize nsWindow::ClientToWindowSize( - const LayoutDeviceIntSize& aClientSize) { +LayoutDeviceIntMargin nsWindow::ClientToWindowMargin() { if (mWindowType == eWindowType_popup && !IsPopupWithTitleBar()) { - return aClientSize; + return {}; } - // Just use (200, 200) as the position - const LayoutDeviceIntPoint point(200, 200); if (mCustomNonClient) { - auto winRect = LayoutDeviceIntRect(point, aClientSize); - winRect.Inflate(NonClientSizeMargin(NormalWindowNonClientOffset())); - return winRect.Size(); + return NonClientSizeMargin(NormalWindowNonClientOffset()); } - RECT r; - r.left = point.x; - r.top = point.y; - r.right = point.x + aClientSize.width; - r.bottom = point.y + aClientSize.height; - ::AdjustWindowRectEx(&r, WindowStyle(), false, WindowExStyle()); - return LayoutDeviceIntSize(r.right - r.left, r.bottom - r.top); + // Just use a dummy 200x200 at (200, 200) client rect as the rect. + RECT clientRect; + clientRect.left = 200; + clientRect.top = 200; + clientRect.right = 400; + clientRect.bottom = 400; + + auto ToRect = [](const RECT& aRect) -> LayoutDeviceIntRect { + return {aRect.left, aRect.top, aRect.right - aRect.left, + aRect.bottom - aRect.top}; + }; + + RECT windowRect = clientRect; + ::AdjustWindowRectEx(&windowRect, WindowStyle(), false, WindowExStyle()); + + return ToRect(windowRect) - ToRect(clientRect); } /************************************************************** diff --git a/widget/windows/nsWindow.h b/widget/windows/nsWindow.h index 508ef5065d4e..3e9bdbccacd8 100644 --- a/widget/windows/nsWindow.h +++ b/widget/windows/nsWindow.h @@ -223,8 +223,7 @@ class nsWindow final : public nsBaseWidget { nsresult SetTitle(const nsAString& aTitle) override; void SetIcon(const nsAString& aIconSpec) override; LayoutDeviceIntPoint WidgetToScreenOffset() override; - LayoutDeviceIntSize ClientToWindowSize( - const LayoutDeviceIntSize& aClientSize) override; + LayoutDeviceIntMargin ClientToWindowMargin() override; nsresult DispatchEvent(mozilla::WidgetGUIEvent* aEvent, nsEventStatus& aStatus) override; void EnableDragDrop(bool aEnable) override; diff --git a/xpfe/appshell/AppWindow.cpp b/xpfe/appshell/AppWindow.cpp index f3652c89d02a..d38fa578aad9 100644 --- a/xpfe/appshell/AppWindow.cpp +++ b/xpfe/appshell/AppWindow.cpp @@ -437,9 +437,7 @@ static LayoutDeviceIntSize GetOuterToInnerSizeDifference(nsIWidget* aWindow) { if (!aWindow) { return LayoutDeviceIntSize(); } - LayoutDeviceIntSize baseSize(200, 200); - LayoutDeviceIntSize windowSize = aWindow->ClientToWindowSize(baseSize); - return windowSize - baseSize; + return aWindow->ClientToWindowSizeDifference(); } static CSSIntSize GetOuterToInnerSizeDifferenceInCSSPixels(