commit d2eb173ceef986bbd712ee147c1738dde8bb7cad
parent 6e59880af8c043aec21bc53a84e027a92acd876f
Author: Emilio Cobos Álvarez <emilio@crisal.io>
Date: Fri, 17 Oct 2025 21:10:55 +0000
Bug 1995049 - Simplify widget move/resize APIs. r=stransky,mac-reviewers,mstange
We no longer have child windows which means that all widgets use desktop
pixels. Make the type system enforce that.
We want to start storing coordinates in DesktopPixels for GTK, to deal
correctly with fractional scaling, so move mBounds to the relevant
subclasses.
There's no behavior change. Some of the changes uncover coordinate
system confusions in Windows that I plan to fix in followups.
Android / iOS / PuppetWidgets don't care about the coordinate
differences, because their DesktopToLayoutDeviceScale is 1.0. Still I
made puppet widgets go through the coordinate conversion because it
seemed easier than casting or what not.
Differential Revision: https://phabricator.services.mozilla.com/D269091
Diffstat:
21 files changed, 244 insertions(+), 321 deletions(-)
diff --git a/dom/ipc/BrowserChild.cpp b/dom/ipc/BrowserChild.cpp
@@ -1181,11 +1181,10 @@ mozilla::ipc::IPCResult BrowserChild::RecvUpdateDimensions(
baseWin->SetPositionAndSize(0, 0, innerSize.width, innerSize.height,
nsIBaseWindow::eRepaint);
- const LayoutDeviceIntRect outerRect =
- GetOuterRect() + mClientOffset + mChromeOffset;
-
- mPuppetWidget->Resize(outerRect.x, outerRect.y, innerSize.width,
- innerSize.height, true);
+ const LayoutDeviceIntRect widgetRect(
+ GetOuterRect().TopLeft() + mClientOffset + mChromeOffset, innerSize);
+ mPuppetWidget->Resize(widgetRect / mPuppetWidget->GetDesktopToDeviceScale(),
+ true);
RecvSafeAreaInsetsChanged(mPuppetWidget->GetSafeAreaInsets());
@@ -3632,10 +3631,10 @@ mozilla::ipc::IPCResult BrowserChild::RecvUIResolutionChanged(
baseWin->SetPositionAndSize(0, 0, innerSize.width, innerSize.height,
nsIBaseWindow::eRepaint);
- const LayoutDeviceIntRect outerRect =
- GetOuterRect() + mClientOffset + mChromeOffset;
- mPuppetWidget->Resize(outerRect.x, outerRect.y, innerSize.width,
- innerSize.height, true);
+ const LayoutDeviceIntRect widgetRect(
+ GetOuterRect().TopLeft() + mClientOffset + mChromeOffset, innerSize);
+ mPuppetWidget->Resize(widgetRect / mPuppetWidget->GetDesktopToDeviceScale(),
+ true);
}
nsCOMPtr<Document> document(GetTopLevelDocument());
diff --git a/gfx/tests/gtest/MockWidget.h b/gfx/tests/gtest/MockWidget.h
@@ -57,10 +57,9 @@ class MockWidget : public nsIWidget {
}
void Show(bool aState) override {}
bool IsVisible() const override { return true; }
- void Move(double aX, double aY) override {}
- void Resize(double aWidth, double aHeight, bool aRepaint) override {}
- void Resize(double aX, double aY, double aWidth, double aHeight,
- bool aRepaint) override {}
+ void Move(const DesktopPoint&) override {}
+ void Resize(const DesktopSize&, bool aRepaint) override {}
+ void Resize(const DesktopRect&, bool aRepaint) override {}
void Enable(bool aState) override {}
bool IsEnabled() const override { return true; }
diff --git a/layout/base/nsDocumentViewer.cpp b/layout/base/nsDocumentViewer.cpp
@@ -1934,7 +1934,7 @@ nsDocumentViewer::SetBoundsWithFlags(const LayoutDeviceIntRect& aBounds,
if (mWindow && !mAttachedToParent) {
// Resize the widget, but don't trigger repaint. Layout will generate
// repaint requests during reflow.
- mWindow->Resize(aBounds.x, aBounds.y, aBounds.width, aBounds.height, false);
+ mWindow->Resize(aBounds / mWindow->GetDesktopToDeviceScale(), false);
} else if (mPresContext && mViewManager) {
// Ensure presContext's deviceContext is up to date, as we sometimes get
// here before a resolution-change notification has been fully handled
@@ -2002,7 +2002,7 @@ nsDocumentViewer::Move(int32_t aX, int32_t aY) {
NS_ENSURE_TRUE(mDocument, NS_ERROR_NOT_AVAILABLE);
mBounds.MoveTo(aX, aY);
if (mWindow) {
- mWindow->Move(aX, aY);
+ mWindow->Move(mBounds.TopLeft() / mWindow->GetDesktopToDeviceScale());
}
return NS_OK;
}
diff --git a/widget/PuppetWidget.cpp b/widget/PuppetWidget.cpp
@@ -96,13 +96,14 @@ void PuppetWidget::InfallibleCreate(nsIWidget* aParent,
const LayoutDeviceIntRect& aRect,
const widget::InitData& aInitData) {
BaseCreate(aParent, aInitData);
+ MOZ_ASSERT(GetDesktopToDeviceScale().scale == 1.0);
mBounds = aRect;
mEnabled = true;
mNeedIMEStateInit = MightNeedIMEFocus(aInitData);
- Resize(mBounds.X(), mBounds.Y(), mBounds.Width(), mBounds.Height(), false);
+ Resize(aRect.Size() / GetDesktopToDeviceScale(), false);
mMemoryPressureObserver = MemoryPressureObserver::Create(this);
}
@@ -159,15 +160,15 @@ void PuppetWidget::Show(bool aState) {
// of no use anymore (and is actually actively harmful - see
// bug 1323586).
mPreviouslyAttachedWidgetListener = nullptr;
- Resize(mBounds.Width(), mBounds.Height(), false);
+ Resize(mBounds.Size() / GetDesktopToDeviceScale(), false);
Invalidate(mBounds);
}
}
-void PuppetWidget::Resize(double aWidth, double aHeight, bool aRepaint) {
+void PuppetWidget::Resize(const DesktopSize& aSize, bool aRepaint) {
+ MOZ_ASSERT(GetDesktopToDeviceScale().scale == 1.0);
LayoutDeviceIntRect oldBounds = mBounds;
- mBounds.SizeTo(
- LayoutDeviceIntSize(NSToIntRound(aWidth), NSToIntRound(aHeight)));
+ mBounds.SizeTo(LayoutDeviceIntSize::Round(aSize * GetDesktopToDeviceScale()));
// XXX: roc says that |aRepaint| dictates whether or not to
// invalidate the expanded area
@@ -966,6 +967,8 @@ LayoutDeviceIntPoint PuppetWidget::GetWindowPosition() {
GetOwningBrowserChild()->GetClientOffset();
}
+LayoutDeviceIntRect PuppetWidget::GetBounds() { return mBounds; }
+
LayoutDeviceIntRect PuppetWidget::GetScreenBounds() {
return LayoutDeviceIntRect(WidgetToScreenOffset(), mBounds.Size());
}
diff --git a/widget/PuppetWidget.h b/widget/PuppetWidget.h
@@ -85,16 +85,15 @@ class PuppetWidget final : public nsIWidget,
bool IsVisible() const override { return mVisible; }
// Widget position is controlled by the parent process via BrowserChild.
- void Move(double aX, double aY) override {}
-
- void Resize(double aWidth, double aHeight, bool aRepaint) override;
- void Resize(double aX, double aY, double aWidth, double aHeight,
- bool aRepaint) override {
- if (!mBounds.IsEqualXY(aX, aY)) {
- NotifyWindowMoved(aX, aY);
+ void Move(const DesktopPoint&) override {}
+ void Resize(const DesktopSize&, bool aRepaint) override;
+ void Resize(const DesktopRect& aRect, bool aRepaint) override {
+ auto targetRect = gfx::RoundedToInt(aRect * GetDesktopToDeviceScale());
+ if (mBounds.TopLeft() != targetRect.TopLeft()) {
+ NotifyWindowMoved(targetRect.X(), targetRect.Y());
}
- mBounds.MoveTo(aX, aY);
- return Resize(aWidth, aHeight, aRepaint);
+ mBounds.MoveTo(targetRect.TopLeft());
+ return Resize(aRect.Size(), aRepaint);
}
// XXX/cjones: copying gtk behavior here; unclear what disabling a
@@ -220,6 +219,7 @@ class PuppetWidget final : public nsIWidget,
// Get the screen position of the application window.
LayoutDeviceIntPoint GetWindowPosition();
+ LayoutDeviceIntRect GetBounds() override;
LayoutDeviceIntRect GetScreenBounds() override;
nsresult SynthesizeNativeKeyEvent(
@@ -372,6 +372,8 @@ class PuppetWidget final : public nsIWidget,
private:
nsSizeMode mSizeMode;
+ LayoutDeviceIntRect mBounds;
+
bool mNeedIMEStateInit;
// When remote process requests to commit/cancel a composition, the
// composition may have already been committed in the main process. In such
diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp
@@ -1345,7 +1345,7 @@ class LayerViewSupport final
return;
}
- gkWindow->Resize(aLeft, aTop, aWidth, aHeight, /* repaint */ false);
+ gkWindow->DoResize(aLeft, aTop, aWidth, aHeight, /* repaint */ false);
}
void NotifyMemoryPressure() {
@@ -2469,7 +2469,7 @@ void nsWindow::Show(bool aState) {
bool nsWindow::IsVisible() const { return mIsVisible; }
void nsWindow::ConstrainPosition(DesktopIntPoint& aPoint) {
- ALOG("nsWindow[%p]::ConstrainPosition [%d %d]", (void*)this, aPoint.x.value,
+ ALOG("nsWindow[%p]::ConstrainPosition [%d %d]", this, aPoint.x.value,
aPoint.y.value);
// Constrain toplevel windows; children we don't care about
@@ -2478,19 +2478,25 @@ void nsWindow::ConstrainPosition(DesktopIntPoint& aPoint) {
}
}
-void nsWindow::Move(double aX, double aY) {
- if (IsTopLevel()) return;
+void nsWindow::Move(const DesktopPoint& aPoint) {
+ if (IsTopLevel()) {
+ return;
+ }
+
+ DoResize(aPoint.x, aPoint.y, mBounds.width, mBounds.height, true);
+}
- Resize(aX, aY, mBounds.width, mBounds.height, true);
+void nsWindow::Resize(const DesktopSize& aSize, bool aRepaint) {
+ DoResize(mBounds.x, mBounds.y, aSize.width, aSize.height, aRepaint);
}
-void nsWindow::Resize(double aWidth, double aHeight, bool aRepaint) {
- Resize(mBounds.x, mBounds.y, aWidth, aHeight, aRepaint);
+void nsWindow::Resize(const DesktopRect& aRect, bool aRepaint) {
+ DoResize(aRect.x, aRect.y, aRect.width, aRect.height, aRepaint);
}
-void nsWindow::Resize(double aX, double aY, double aWidth, double aHeight,
- bool aRepaint) {
- ALOG("nsWindow[%p]::Resize [%f %f %f %f] (repaint %d)", (void*)this, aX, aY,
+void nsWindow::DoResize(double aX, double aY, double aWidth, double aHeight,
+ bool aRepaint) {
+ ALOG("nsWindow[%p]::DoResize [%f %f %f %f] (repaint %d)", this, aX, aY,
aWidth, aHeight, aRepaint);
LayoutDeviceIntRect oldBounds = mBounds;
diff --git a/widget/android/nsWindow.h b/widget/android/nsWindow.h
@@ -79,6 +79,7 @@ class nsWindow final : public nsIWidget {
mozilla::widget::PlatformCompositorWidgetDelegate* mCompositorWidgetDelegate =
nullptr;
mozilla::Mutex mDestroyMutex{"nsWindow::mDestroyMutex"};
+ LayoutDeviceIntRect mBounds;
// Unique ID given to each widget, used to map Surfaces to widgets
// in the CompositorSurfaceManager.
@@ -165,10 +166,9 @@ class nsWindow final : public nsIWidget {
void Show(bool aState) override;
bool IsVisible() const override;
void ConstrainPosition(DesktopIntPoint&) override;
- void Move(double aX, double aY) override;
- void Resize(double aWidth, double aHeight, bool aRepaint) override;
- void Resize(double aX, double aY, double aWidth, double aHeight,
- bool aRepaint) override;
+ void Move(const DesktopPoint&) override;
+ void Resize(const DesktopSize&, bool aRepaint) override;
+ void Resize(const DesktopRect&, bool aRepaint) override;
nsSizeMode SizeMode() override { return mSizeMode; }
void SetSizeMode(nsSizeMode aMode) override;
void Enable(bool aState) override;
@@ -176,6 +176,7 @@ class nsWindow final : public nsIWidget {
void Invalidate(const LayoutDeviceIntRect& aRect) override;
void SetFocus(Raise, mozilla::dom::CallerType aCallerType) override;
LayoutDeviceIntRect GetScreenBounds() override;
+ LayoutDeviceIntRect GetBounds() override { return mBounds; }
LayoutDeviceIntPoint WidgetToScreenOffset() override;
nsresult DispatchEvent(mozilla::WidgetGUIEvent* aEvent,
nsEventStatus& aStatus) override;
@@ -262,6 +263,9 @@ class nsWindow final : public nsIWidget {
mozilla::jni::NativeWeakPtr<mozilla::widget::NPZCSupport>
GetNPZCSupportWeakPtr();
+ void DoResize(double aX, double aY, double aWidth, double aHeight,
+ bool aRepaint);
+
protected:
void BringToFront();
nsWindow* FindTopLevel();
diff --git a/widget/cocoa/nsCocoaWindow.h b/widget/cocoa/nsCocoaWindow.h
@@ -232,7 +232,7 @@ class nsCocoaWindow final : public nsIWidget {
void ConstrainPosition(DesktopIntPoint&) override;
void SetSizeConstraints(const SizeConstraints& aConstraints) override;
- void Move(double aX, double aY) override;
+ void Move(const DesktopPoint&) override;
nsSizeMode SizeMode() override { return mSizeMode; }
void SetSizeMode(nsSizeMode aMode) override;
void GetWorkspaceID(nsAString& workspaceID) override;
@@ -354,12 +354,12 @@ class nsCocoaWindow final : public nsIWidget {
mFullscreenTransitionAnimation = nil;
}
- void Resize(double aWidth, double aHeight, bool aRepaint) override;
- void Resize(double aX, double aY, double aWidth, double aHeight,
- bool aRepaint) override;
+ void Resize(const DesktopSize&, bool aRepaint) override;
+ void Resize(const DesktopRect&, bool aRepaint) override;
NSRect GetClientCocoaRect();
LayoutDeviceIntRect GetClientBounds() override;
LayoutDeviceIntRect GetScreenBounds() override;
+ LayoutDeviceIntRect GetBounds() override { return mBounds; }
void ReportMoveEvent();
void ReportSizeEvent();
bool WidgetTypeSupportsAcceleration() override { return true; }
@@ -662,6 +662,8 @@ class nsCocoaWindow final : public nsIWidget {
InputContext mInputContext;
NSWindowAnimationBehavior mWindowAnimationBehavior;
+ LayoutDeviceIntRect mBounds;
+
mozilla::widget::PlatformCompositorWidgetDelegate* mCompositorWidgetDelegate =
nullptr;
diff --git a/widget/cocoa/nsCocoaWindow.mm b/widget/cocoa/nsCocoaWindow.mm
@@ -5489,7 +5489,7 @@ void nsCocoaWindow::SetSizeConstraints(const SizeConstraints& aConstraints) {
}
// Coordinates are desktop pixels
-void nsCocoaWindow::Move(double aX, double aY) {
+void nsCocoaWindow::Move(const DesktopPoint& aPoint) {
NS_OBJC_BEGIN_TRY_IGNORE_BLOCK;
if (!mWindow) {
@@ -5499,8 +5499,8 @@ void nsCocoaWindow::Move(double aX, double aY) {
// The point we have is in Gecko coordinates (origin top-left). Convert
// it to Cocoa ones (origin bottom-left).
NSPoint coord = {
- static_cast<float>(aX),
- static_cast<float>(nsCocoaUtils::FlippedScreenY(NSToIntRound(aY)))};
+ static_cast<float>(aPoint.x),
+ static_cast<float>(nsCocoaUtils::FlippedScreenY(NSToIntRound(aPoint.y)))};
NSRect frame = mWindow.frame;
if (frame.origin.x != coord.x ||
@@ -6327,17 +6327,15 @@ void nsCocoaWindow::DoResize(double aX, double aY, double aWidth,
NS_OBJC_END_TRY_IGNORE_BLOCK;
}
-// Coordinates are desktop pixels
-void nsCocoaWindow::Resize(double aX, double aY, double aWidth, double aHeight,
- bool aRepaint) {
- DoResize(aX, aY, aWidth, aHeight, aRepaint, false);
+void nsCocoaWindow::Resize(const DesktopRect& aRect, bool aRepaint) {
+ DoResize(aRect.x, aRect.y, aRect.width, aRect.height, aRepaint, false);
}
// Coordinates are desktop pixels
-void nsCocoaWindow::Resize(double aWidth, double aHeight, bool aRepaint) {
+void nsCocoaWindow::Resize(const DesktopSize& aSize, bool aRepaint) {
double invScale = 1.0 / BackingScaleFactor();
- DoResize(mBounds.x * invScale, mBounds.y * invScale, aWidth, aHeight,
- aRepaint, true);
+ DoResize(mBounds.x * invScale, mBounds.y * invScale, aSize.width,
+ aSize.height, aRepaint, true);
}
// Return the area that the Gecko ChildView in our window should cover, as an
diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp
@@ -1117,29 +1117,23 @@ void nsWindow::ResizeInt(const Maybe<LayoutDeviceIntPoint>& aMove,
NativeMoveResize(moved, resized);
}
-void nsWindow::Resize(double aWidth, double aHeight, bool aRepaint) {
- double scale =
- BoundsUseDesktopPixels() ? GetDesktopToDeviceScale().scale : 1.0;
- LOG("nsWindow::Resize %.2f x %.2f (scaled %.2f x %.2f)", aWidth, aHeight,
- scale * aWidth, scale * aHeight);
-
- auto size = LayoutDeviceIntSize::Round(scale * aWidth, scale * aHeight);
-
+void nsWindow::Resize(const DesktopSize& aSize, bool aRepaint) {
+ auto size = LayoutDeviceIntSize::Round(aSize * GetDesktopToDeviceScale());
+ LOG("nsWindow::Resize %s (scaled %s)", ToString(aSize).c_str(),
+ ToString(size).c_str());
ResizeInt(Nothing(), size);
}
-void nsWindow::Resize(double aX, double aY, double aWidth, double aHeight,
- bool aRepaint) {
- double scale =
- BoundsUseDesktopPixels() ? GetDesktopToDeviceScale().scale : 1.0;
- auto size = LayoutDeviceIntSize::Round(scale * aWidth, scale * aHeight);
- auto topLeft = LayoutDeviceIntPoint::Round(scale * aX, scale * aY);
+void nsWindow::Resize(const DesktopRect& aRect, bool aRepaint) {
+ auto size =
+ LayoutDeviceIntSize::Round(aRect.Size() * GetDesktopToDeviceScale());
+ auto topLeft =
+ LayoutDeviceIntPoint::Round(aRect.TopLeft() * GetDesktopToDeviceScale());
- LOG("nsWindow::Resize [%.2f,%.2f] -> [%.2f x %.2f] scaled [%.2f,%.2f] -> "
- "[%.2f x %.2f] "
- "repaint %d\n",
- aX, aY, aWidth, aHeight, scale * aX, scale * aY, scale * aWidth,
- scale * aHeight, aRepaint);
+ LOG("nsWindow::Resize [%.2f,%.2f] -> [%.2f x %.2f] scaled [%d,%d] -> "
+ "[%d x %d] repaint %d\n",
+ aRect.x, aRect.y, aRect.width, aRect.height, topLeft.x.value,
+ topLeft.y.value, size.width, size.height, aRepaint);
ResizeInt(Some(topLeft), size);
}
@@ -1148,11 +1142,9 @@ void nsWindow::Enable(bool aState) { mEnabled = aState; }
bool nsWindow::IsEnabled() const { return mEnabled; }
-void nsWindow::Move(double aX, double aY) {
- double scale =
- BoundsUseDesktopPixels() ? GetDesktopToDeviceScale().scale : 1.0;
- const LayoutDeviceIntPoint request(NSToIntRound(aX * scale),
- NSToIntRound(aY * scale));
+void nsWindow::Move(const DesktopPoint& aTopLeft) {
+ auto request =
+ LayoutDeviceIntPoint::Round(aTopLeft * GetDesktopToDeviceScale());
LOG("nsWindow::Move to %d x %d\n", request.x.value, request.y.value);
if (mSizeMode != nsSizeMode_Normal && IsTopLevelWidget()) {
diff --git a/widget/gtk/nsWindow.h b/widget/gtk/nsWindow.h
@@ -191,11 +191,10 @@ class nsWindow final : public nsIWidget {
void ConstrainPosition(DesktopIntPoint&) override;
void SetSizeConstraints(const SizeConstraints&) override;
void LockAspectRatio(bool aShouldLock) override;
- void Move(double aX, double aY) override;
+ void Move(const DesktopPoint&) override;
void Show(bool aState) override;
- void Resize(double aWidth, double aHeight, bool aRepaint) override;
- void Resize(double aX, double aY, double aWidth, double aHeight,
- bool aRepaint) override;
+ void Resize(const DesktopSize&, bool aRepaint) override;
+ void Resize(const DesktopRect&, bool aRepaint) override;
bool IsEnabled() const override;
nsSizeMode SizeMode() override { return mSizeMode; }
@@ -206,6 +205,7 @@ class nsWindow final : public nsIWidget {
void SetFocus(Raise, mozilla::dom::CallerType aCallerType) override;
LayoutDeviceIntRect GetScreenBounds() override;
LayoutDeviceIntRect GetClientBounds() override;
+ LayoutDeviceIntRect GetBounds() override { return mBounds; }
LayoutDeviceIntSize GetClientSize() override;
LayoutDeviceIntPoint GetClientOffset() override {
return LayoutDeviceIntPoint(mClientMargin.left, mClientMargin.top);
@@ -624,6 +624,8 @@ class nsWindow final : public nsIWidget {
LayoutDeviceIntPoint mLastMoveRequest;
// Margin from mBounds to the client rect (including CSD decorations).
LayoutDeviceIntMargin mClientMargin;
+ // Bounds of the window, as in GetBounds().
+ LayoutDeviceIntRect mBounds;
// This field omits duplicate scroll events caused by GNOME bug 726878.
guint32 mLastScrollEventTime = GDK_CURRENT_TIME;
diff --git a/widget/headless/HeadlessWidget.cpp b/widget/headless/HeadlessWidget.cpp
@@ -200,20 +200,17 @@ void HeadlessWidget::Enable(bool aState) { mEnabled = aState; }
bool HeadlessWidget::IsEnabled() const { return mEnabled; }
-void HeadlessWidget::Move(double aX, double aY) {
- LOG(("HeadlessWidget::Move [%p] %f %f\n", (void*)this, aX, aY));
-
- double scale =
- BoundsUseDesktopPixels() ? GetDesktopToDeviceScale().scale : 1.0;
- int32_t x = NSToIntRound(aX * scale);
- int32_t y = NSToIntRound(aY * scale);
+void HeadlessWidget::Move(const DesktopPoint& aPoint) {
+ LOG(("HeadlessWidget::Move [%p] %f %f\n", this, aPoint.x.value,
+ aPoint.y.value));
+ auto topLeft =
+ LayoutDeviceIntPoint::Round(aPoint * GetDesktopToDeviceScale());
if (mWindowType == WindowType::TopLevel ||
mWindowType == WindowType::Dialog) {
SetSizeMode(nsSizeMode_Normal);
}
-
- MoveInternal(x, y);
+ MoveInternal(topLeft.x, topLeft.y);
}
void HeadlessWidget::MoveInternal(int32_t aX, int32_t aY) {
@@ -251,9 +248,9 @@ void HeadlessWidget::SetCompositorWidgetDelegate(
}
}
-void HeadlessWidget::Resize(double aWidth, double aHeight, bool aRepaint) {
- int32_t width = NSToIntRound(aWidth);
- int32_t height = NSToIntRound(aHeight);
+void HeadlessWidget::Resize(const DesktopSize& aSize, bool aRepaint) {
+ int32_t width = NSToIntRound(aSize.width);
+ int32_t height = NSToIntRound(aSize.height);
ResizeInternal(width, height, aRepaint);
}
@@ -263,8 +260,7 @@ void HeadlessWidget::ResizeInternal(int32_t aWidth, int32_t aHeight,
mBounds.SizeTo(LayoutDeviceIntSize(aWidth, aHeight));
if (mCompositorWidget) {
- mCompositorWidget->NotifyClientSizeChanged(
- LayoutDeviceIntSize(mBounds.Width(), mBounds.Height()));
+ mCompositorWidget->NotifyClientSizeChanged(mBounds.Size());
}
if (mWidgetListener) {
mWidgetListener->WindowResized(this, mBounds.Width(), mBounds.Height());
@@ -275,10 +271,9 @@ void HeadlessWidget::ResizeInternal(int32_t aWidth, int32_t aHeight,
}
}
-void HeadlessWidget::Resize(double aX, double aY, double aWidth, double aHeight,
- bool aRepaint) {
- MoveInternal(NSToIntRound(aX), NSToIntRound(aY));
- Resize(aWidth, aHeight, aRepaint);
+void HeadlessWidget::Resize(const DesktopRect& aRect, bool aRepaint) {
+ Move(aRect.TopLeft());
+ Resize(aRect.Size(), aRepaint);
}
void HeadlessWidget::SetSizeMode(nsSizeMode aMode) {
diff --git a/widget/headless/HeadlessWidget.h b/widget/headless/HeadlessWidget.h
@@ -60,16 +60,16 @@ class HeadlessWidget final : public nsIWidget {
void Destroy() override;
void Show(bool aState) override;
bool IsVisible() const override;
- void Move(double aX, double aY) override;
- void Resize(double aWidth, double aHeight, bool aRepaint) override;
- void Resize(double aX, double aY, double aWidth, double aHeight,
- bool aRepaint) override;
+ void Move(const DesktopPoint&) override;
+ void Resize(const DesktopSize&, bool aRepaint) override;
+ void Resize(const DesktopRect&, bool aRepaint) override;
nsSizeMode SizeMode() override { return mSizeMode; }
void SetSizeMode(nsSizeMode aMode) override;
nsresult MakeFullScreen(bool aFullScreen) override;
void Enable(bool aState) override;
bool IsEnabled() const override;
void SetFocus(Raise, mozilla::dom::CallerType aCallerType) override;
+ LayoutDeviceIntRect GetBounds() override { return mBounds; }
void Invalidate(const LayoutDeviceIntRect& aRect) override {
// TODO: see if we need to do anything here.
}
@@ -149,6 +149,7 @@ class HeadlessWidget final : public nsIWidget {
// In headless there is no window manager to track window bounds
// across size mode changes, so we must track it to emulate.
LayoutDeviceIntRect mRestoreBounds;
+ LayoutDeviceIntRect mBounds;
void ApplySizeModeSideEffects();
// Move while maintaining size mode.
void MoveInternal(int32_t aX, int32_t aY);
diff --git a/widget/nsIWidget.cpp b/widget/nsIWidget.cpp
@@ -307,7 +307,6 @@ nsIWidget::nsIWidget(BorderStyle aBorderStyle)
mPreviouslyAttachedWidgetListener(nullptr),
mCompositorVsyncDispatcher(nullptr),
mBorderStyle(aBorderStyle),
- mBounds(0, 0, 0, 0),
mIsTiled(false),
mPopupLevel(PopupLevel::Top),
mPopupType(PopupType::Any),
@@ -781,11 +780,6 @@ void nsIWidget::InfallibleMakeFullScreen(bool aFullScreen) {
#define MOZ_SPLAT_RECT(rect) \
(rect).X(), (rect).Y(), (rect).Width(), (rect).Height()
- // Windows which can be made fullscreen are exactly those which are located on
- // the desktop, rather than being a child of some other window.
- MOZ_DIAGNOSTIC_ASSERT(BoundsUseDesktopPixels(),
- "non-desktop windows cannot be made fullscreen");
-
// Ensure that the OS chrome is hidden/shown before we resize and/or exit the
// function.
//
@@ -826,20 +820,16 @@ void nsIWidget::InfallibleMakeFullScreen(bool aFullScreen) {
("window was not resized within InfallibleMakeFullScreen()"));
// Hide chrome and "resize" the window to its current size.
- auto rect = GetBounds();
+ auto rect = GetBounds() / GetDesktopToDeviceScale();
adjustOSChrome();
- Resize(rect.X(), rect.Y(), rect.Width(), rect.Height(), true);
+ Resize(rect, true);
});
// Attempt to resize to `rect`.
//
// Returns the actual rectangle resized to. (This may differ from `rect`, if
// the OS is unhappy with it. See bug 1786226.)
- const auto doReposition = [&](auto rect) -> void {
- static_assert(std::is_base_of_v<DesktopPixel,
- std::remove_reference_t<decltype(rect)>>,
- "doReposition requires a rectangle using desktop pixels");
-
+ const auto doReposition = [&](const DesktopRect& rect) -> void {
if (MOZ_LOG_TEST(sBaseWidgetLog, LogLevel::Debug)) {
const DesktopRect previousSize =
GetScreenBounds() / GetDesktopToDeviceScale();
@@ -849,7 +839,7 @@ void nsIWidget::InfallibleMakeFullScreen(bool aFullScreen) {
}
adjustOSChrome();
- Resize(rect.X(), rect.Y(), rect.Width(), rect.Height(), true);
+ Resize(rect, true);
if (MOZ_LOG_TEST(sBaseWidgetLog, LogLevel::Warning)) {
// `rect` may have any underlying data type; coerce to float to
@@ -903,7 +893,7 @@ void nsIWidget::InfallibleMakeFullScreen(bool aFullScreen) {
}
// Move to fill the screen.
- doReposition(screen->GetRectDisplayPix());
+ doReposition(DesktopRect(screen->GetRectDisplayPix()));
// Save off the new position. (This may differ from GetRectDisplayPix(), if
// the OS was unhappy with it. See bug 1786226.)
mSavedBounds->screenRect = GetScreenBounds() / GetDesktopToDeviceScale();
@@ -1768,18 +1758,10 @@ DesktopIntPoint nsIWidget::ConstrainPositionToBounds(
}
void nsIWidget::MoveClient(const DesktopPoint& aOffset) {
- LayoutDeviceIntPoint clientOffset(GetClientOffset());
-
// GetClientOffset returns device pixels; scale back to desktop pixels
// if that's what this widget uses for the Move/Resize APIs
- if (BoundsUseDesktopPixels()) {
- DesktopPoint desktopOffset = clientOffset / GetDesktopToDeviceScale();
- Move(aOffset.x - desktopOffset.x, aOffset.y - desktopOffset.y);
- } else {
- LayoutDevicePoint layoutOffset = aOffset * GetDesktopToDeviceScale();
- Move(layoutOffset.x - LayoutDeviceCoord(clientOffset.x),
- layoutOffset.y - LayoutDeviceCoord(clientOffset.y));
- }
+ DesktopPoint desktopOffset = GetClientOffset() / GetDesktopToDeviceScale();
+ Move(aOffset - desktopOffset);
}
void nsIWidget::ResizeClient(const DesktopSize& aSize, bool aRepaint) {
@@ -1790,19 +1772,9 @@ void nsIWidget::ResizeClient(const DesktopSize& aSize, bool aRepaint) {
// GetClientBounds and mBounds are device pixels; scale back to desktop pixels
// if that's what this widget uses for the Move/Resize APIs
- if (BoundsUseDesktopPixels()) {
- DesktopSize desktopDelta =
- (LayoutDeviceIntSize(mBounds.Width(), mBounds.Height()) -
- clientBounds.Size()) /
- GetDesktopToDeviceScale();
- Resize(aSize.width + desktopDelta.width, aSize.height + desktopDelta.height,
- aRepaint);
- } else {
- LayoutDeviceSize layoutSize = aSize * GetDesktopToDeviceScale();
- Resize(mBounds.Width() + (layoutSize.width - clientBounds.Width()),
- mBounds.Height() + (layoutSize.height - clientBounds.Height()),
- aRepaint);
- }
+ DesktopSize desktopDelta =
+ (GetBounds().Size() - clientBounds.Size()) / GetDesktopToDeviceScale();
+ Resize(aSize + desktopDelta, aRepaint);
}
void nsIWidget::ResizeClient(const DesktopRect& aRect, bool aRepaint) {
@@ -1813,22 +1785,12 @@ void nsIWidget::ResizeClient(const DesktopRect& aRect, bool aRepaint) {
LayoutDeviceIntPoint clientOffset = GetClientOffset();
DesktopToLayoutDeviceScale scale = GetDesktopToDeviceScale();
- if (BoundsUseDesktopPixels()) {
- DesktopPoint desktopOffset = clientOffset / scale;
- DesktopSize desktopDelta =
- (LayoutDeviceIntSize(mBounds.Width(), mBounds.Height()) -
- clientBounds.Size()) /
- scale;
- Resize(aRect.X() - desktopOffset.x, aRect.Y() - desktopOffset.y,
- aRect.Width() + desktopDelta.width,
- aRect.Height() + desktopDelta.height, aRepaint);
- } else {
- LayoutDeviceRect layoutRect = aRect * scale;
- Resize(layoutRect.X() - clientOffset.x, layoutRect.Y() - clientOffset.y,
- layoutRect.Width() + mBounds.Width() - clientBounds.Width(),
- layoutRect.Height() + mBounds.Height() - clientBounds.Height(),
- aRepaint);
- }
+ DesktopPoint desktopOffset = clientOffset / scale;
+ DesktopSize desktopDelta = (GetBounds().Size() - clientBounds.Size()) / scale;
+ Resize(DesktopRect(aRect.X() - desktopOffset.x, aRect.Y() - desktopOffset.y,
+ aRect.Width() + desktopDelta.width,
+ aRect.Height() + desktopDelta.height),
+ aRepaint);
}
//-------------------------------------------------------------------------
@@ -1837,27 +1799,6 @@ void nsIWidget::ResizeClient(const DesktopRect& aRect, bool aRepaint) {
//
//-------------------------------------------------------------------------
-/**
- * If the implementation of nsWindow supports borders this method MUST be
- * overridden
- *
- **/
-LayoutDeviceIntRect nsIWidget::GetClientBounds() { return GetBounds(); }
-
-/**
- * If the implementation of nsWindow supports borders this method MUST be
- * overridden
- *
- **/
-LayoutDeviceIntRect nsIWidget::GetBounds() { return mBounds; }
-
-/**
- * If the implementation of nsWindow uses a local coordinate system within the
- *window, this method must be overridden
- *
- **/
-LayoutDeviceIntRect nsIWidget::GetScreenBounds() { return GetBounds(); }
-
nsresult nsIWidget::GetRestoredBounds(LayoutDeviceIntRect& aRect) {
if (SizeMode() != nsSizeMode_Normal) {
return NS_ERROR_FAILURE;
@@ -1955,18 +1896,12 @@ void nsIWidget::SetSizeConstraints(const SizeConstraints& aConstraints) {
// the new constraints don't affect the current size, because Resize
// implementation on some platforms may touch other geometry even if
// the size don't need to change.
- LayoutDeviceIntSize curSize = mBounds.Size();
+ LayoutDeviceIntSize curSize = GetBounds().Size();
LayoutDeviceIntSize clampedSize =
Max(aConstraints.mMinSize, Min(aConstraints.mMaxSize, curSize));
if (clampedSize != curSize) {
- gfx::Size size;
- if (BoundsUseDesktopPixels()) {
- DesktopSize desktopSize = clampedSize / GetDesktopToDeviceScale();
- size = desktopSize.ToUnknownSize();
- } else {
- size = gfx::Size(clampedSize.ToUnknownSize());
- }
- Resize(size.width, size.height, true);
+ DesktopSize desktopSize = clampedSize / GetDesktopToDeviceScale();
+ Resize(desktopSize, true);
}
}
diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h
@@ -772,18 +772,7 @@ class nsIWidget : public nsSupportsWeakReference {
* @param aY the new y position expressed in the parent's coordinate system
*
**/
- virtual void Move(double aX, double aY) = 0;
-
- // Return whether this widget interprets parameters to Move and Resize APIs
- // as "desktop pixels" rather than "device pixels", and therefore
- // applies its GetDefaultScale() value to them before using them as mBounds
- // etc (which are always stored in device pixels).
- // Note that APIs that -get- the widget's position/size/bounds, rather than
- // -setting- them (i.e. moving or resizing the widget) will always return
- // values in the widget's device pixels.
- bool BoundsUseDesktopPixels() const {
- return mWindowType <= WindowType::Popup;
- }
+ virtual void Move(const DesktopPoint&) = 0;
/**
* Reposition this widget so that the client area has the given offset.
@@ -793,7 +782,7 @@ class nsIWidget : public nsSupportsWeakReference {
* widget (for root widgets and popup widgets it is in
* screen coordinates)
**/
- virtual void MoveClient(const DesktopPoint& aOffset);
+ void MoveClient(const DesktopPoint& aOffset);
/**
* Resize this widget. Any size constraints set for the window by a
@@ -804,33 +793,23 @@ class nsIWidget : public nsSupportsWeakReference {
* system
* @param aRepaint whether the widget should be repainted
*/
- virtual void Resize(double aWidth, double aHeight, bool aRepaint) = 0;
+ virtual void Resize(const DesktopSize&, bool aRepaint) = 0;
/**
* Lock the aspect ratio of a Window
- *
* @param aShouldLock bool
- *
*/
- virtual void LockAspectRatio(bool aShouldLock) {};
+ virtual void LockAspectRatio(bool aShouldLock) {}
/**
* Move or resize this widget. Any size constraints set for the window by
* a previous call to SetSizeConstraints will be applied.
*
- * @param aX the new x position expressed in the parent's coordinate
- * system
- * @param aY the new y position expressed in the parent's coordinate
- * system
- * @param aWidth the new width expressed in the parent's coordinate system
- * @param aHeight the new height expressed in the parent's coordinate
- * system
* @param aRepaint whether the widget should be repainted if the size
* changes
*
*/
- virtual void Resize(double aX, double aY, double aWidth, double aHeight,
- bool aRepaint) = 0;
+ virtual void Resize(const DesktopRect&, bool aRepaint) = 0;
/**
* Resize the widget so that the inner client area has the given size.
@@ -838,7 +817,7 @@ class nsIWidget : public nsSupportsWeakReference {
* @param aSize the new size of the client area.
* @param aRepaint whether the widget should be repainted
*/
- virtual void ResizeClient(const DesktopSize& aSize, bool aRepaint);
+ void ResizeClient(const DesktopSize& aSize, bool aRepaint);
/**
* Resize and reposition the widget so tht inner client area has the given
@@ -850,7 +829,7 @@ class nsIWidget : public nsSupportsWeakReference {
* is in screen coordinates).
* @param aRepaint whether the widget should be repainted
*/
- virtual void ResizeClient(const DesktopRect& aRect, bool aRepaint);
+ void ResizeClient(const DesktopRect& aRect, bool aRepaint);
/**
* Minimize, maximize or normalize the window size.
@@ -918,7 +897,7 @@ class nsIWidget : public nsSupportsWeakReference {
*
* @return the x, y, width and height of this widget.
*/
- virtual LayoutDeviceIntRect GetBounds();
+ virtual LayoutDeviceIntRect GetBounds() = 0;
/**
* Get this widget's outside dimensions in device coordinates. This
@@ -926,7 +905,7 @@ class nsIWidget : public nsSupportsWeakReference {
*
* @return the x, y, width and height of this widget.
*/
- virtual LayoutDeviceIntRect GetScreenBounds();
+ virtual LayoutDeviceIntRect GetScreenBounds() { return GetBounds(); }
/**
* Similar to GetScreenBounds except that this function will always
@@ -960,7 +939,7 @@ class nsIWidget : public nsSupportsWeakReference {
*
* @return the x, y, width and height of the client area of this widget.
*/
- virtual LayoutDeviceIntRect GetClientBounds();
+ virtual LayoutDeviceIntRect GetClientBounds() { return GetBounds(); }
/** Whether to extend the client area into the titlebar. */
virtual void SetCustomTitlebar(bool) {}
@@ -2430,7 +2409,6 @@ class nsIWidget : public nsSupportsWeakReference {
Cursor mCursor;
bool mCustomCursorAllowed = true;
BorderStyle mBorderStyle;
- LayoutDeviceIntRect mBounds;
bool mIsTiled;
PopupLevel mPopupLevel;
PopupType mPopupType;
diff --git a/widget/tests/gtest/MockWinWidget.h b/widget/tests/gtest/MockWinWidget.h
@@ -45,10 +45,9 @@ class MockWinWidget : public nsIWidget {
}
void Show(bool aState) override {}
bool IsVisible() const override { return true; }
- void Move(double aX, double aY) override {}
- void Resize(double aWidth, double aHeight, bool aRepaint) override {}
- void Resize(double aX, double aY, double aWidth, double aHeight,
- bool aRepaint) override {}
+ void Move(const DesktopPoint&) override {}
+ void Resize(const DesktopSize&, bool aRepaint) override {}
+ void Resize(const DesktopRect&, bool aRepaint) override {}
void Enable(bool aState) override {}
bool IsEnabled() const override { return true; }
@@ -65,6 +64,7 @@ class MockWinWidget : public nsIWidget {
void SetInputContext(const InputContext& aContext,
const InputContextAction& aAction) override {}
InputContext GetInputContext() override { abort(); }
+ LayoutDeviceIntRect GetBounds() override { return mBounds; }
private:
MockWinWidget();
@@ -74,6 +74,7 @@ class MockWinWidget : public nsIWidget {
const LayoutDeviceIntRect& aRect);
HWND mWnd = 0;
+ LayoutDeviceIntRect mBounds;
mozilla::widget::OcclusionState mExpectation =
mozilla::widget::OcclusionState::UNKNOWN;
diff --git a/widget/uikit/nsWindow.h b/widget/uikit/nsWindow.h
@@ -58,14 +58,16 @@ class nsWindow final : public nsIWidget {
void SetBackgroundColor(const nscolor& aColor) override;
void* GetNativeData(uint32_t aDataType) override;
- void Move(double aX, double aY) override;
+ void Move(const DesktopPoint&) override;
nsSizeMode SizeMode() override { return mSizeMode; }
void SetSizeMode(nsSizeMode aMode) override;
void EnteredFullScreen(bool aFullScreen);
- void Resize(double aWidth, double aHeight, bool aRepaint) override;
- void Resize(double aX, double aY, double aWidth, double aHeight,
- bool aRepaint) override;
+ void Resize(const DesktopSize&, bool aRepaint) override;
+ void Resize(const DesktopRect&, bool aRepaint) override;
+ void DoResize(double aX, double aY, double aWidth, double aHeight,
+ bool aRepaint);
LayoutDeviceIntRect GetScreenBounds() override;
+ LayoutDeviceIntRect GetBounds() override { return mBounds; }
void ReportMoveEvent();
void ReportSizeEvent();
void ReportSizeModeEvent(nsSizeMode aMode);
@@ -164,6 +166,7 @@ class nsWindow final : public nsIWidget {
RefPtr<mozilla::layers::NativeLayerRootCA> mNativeLayerRoot;
RefPtr<mozilla::CancelableRunnable> mUnsuspendAsyncCATransactionsRunnable;
+ LayoutDeviceIntRect mBounds;
void OnSizeChanged(const mozilla::gfx::IntSize& aSize);
diff --git a/widget/uikit/nsWindow.mm b/widget/uikit/nsWindow.mm
@@ -346,10 +346,10 @@ class nsAutoRetainUIKitObject {
}
CGFloat scaleFactor = [self contentScaleFactor];
- mGeckoChild->Resize(self.frame.origin.x * scaleFactor,
- self.frame.origin.y * scaleFactor,
- self.frame.size.width * scaleFactor,
- self.frame.size.height * scaleFactor, false);
+ mGeckoChild->DoResize(self.frame.origin.x * scaleFactor,
+ self.frame.origin.y * scaleFactor,
+ self.frame.size.width * scaleFactor,
+ self.frame.size.height * scaleFactor, false);
}
- (BOOL)canBecomeFirstResponder {
@@ -861,14 +861,16 @@ void nsWindow::Show(bool aState) {
}
}
-void nsWindow::Move(double aX, double aY) {
- if (!mNativeView || (mBounds.x == aX && mBounds.y == aY)) return;
+void nsWindow::Move(const DesktopPoint& aPoint) {
+ if (!mNativeView || (mBounds.x == aPoint.x && mBounds.y == aPoint.y)) {
+ return;
+ }
// XXX: handle this
// The point we have is in Gecko coordinates (origin top-left). Convert
// it to Cocoa ones (origin bottom-left).
- mBounds.x = aX;
- mBounds.y = aY;
+ mBounds.x = aPoint.x;
+ mBounds.y = aPoint.y;
if (mWindowType != WindowType::TopLevel) {
mNativeView.frame = DevPixelsToUIKitPoints(mBounds, BackingScaleFactor());
@@ -879,11 +881,19 @@ void nsWindow::Move(double aX, double aY) {
ReportMoveEvent();
}
-void nsWindow::Resize(double aX, double aY, double aWidth, double aHeight,
- bool aRepaint) {
- BOOL isMoving = (mBounds.x != aX || mBounds.y != aY);
- BOOL isResizing = (mBounds.width != aWidth || mBounds.height != aHeight);
- if (!mNativeView || (!isMoving && !isResizing)) return;
+void nsWindow::Resize(const DesktopRect& aRect, bool aRepaint) {
+ DoResize(aRect.x, aRect.y, aRect.width, aRect.height, aRepaint);
+}
+
+void nsWindow::DoResize(double aX, double aY, double aWidth, double aHeight,
+ bool aRepaint) {
+ // FIXME: This code is confused about integers vs. double coords, and desktop
+ // vs. device pixels.
+ BOOL isMoving = mBounds.x != aX || mBounds.y != aY;
+ BOOL isResizing = mBounds.width != aWidth || mBounds.height != aHeight;
+ if (!mNativeView || (!isMoving && !isResizing)) {
+ return;
+ }
if (isMoving) {
mBounds.x = aX;
@@ -906,12 +916,14 @@ void nsWindow::Resize(double aX, double aY, double aWidth, double aHeight,
if (isResizing) ReportSizeEvent();
}
-void nsWindow::Resize(double aWidth, double aHeight, bool aRepaint) {
- if (!mNativeView || (mBounds.width == aWidth && mBounds.height == aHeight))
+void nsWindow::Resize(const DesktopSize& aSize, bool aRepaint) {
+ if (!mNativeView ||
+ (mBounds.width == aSize.width && mBounds.height == aSize.height)) {
return;
+ }
- mBounds.width = aWidth;
- mBounds.height = aHeight;
+ mBounds.width = aSize.width;
+ mBounds.height = aSize.height;
if (mWindowType != WindowType::TopLevel) {
[mNativeView
diff --git a/widget/windows/nsWindow.cpp b/widget/windows/nsWindow.cpp
@@ -966,15 +966,13 @@ void nsWindow::RecreateDirectManipulationIfNeeded() {
mDmOwner = MakeUnique<DirectManipulationOwner>(this);
- LayoutDeviceIntRect bounds(mBounds.X(), mBounds.Y(), mBounds.Width(),
- mBounds.Height());
+ LayoutDeviceIntRect bounds = mBounds;
mDmOwner->Init(bounds);
}
void nsWindow::ResizeDirectManipulationViewport() {
if (mDmOwner) {
- LayoutDeviceIntRect bounds(mBounds.X(), mBounds.Y(), mBounds.Width(),
- mBounds.Height());
+ LayoutDeviceIntRect bounds = mBounds;
mDmOwner->ResizeViewport(bounds);
}
}
@@ -1083,11 +1081,11 @@ nsresult nsWindow::Create(nsIWidget* aParent, const LayoutDeviceIntRect& aRect,
mIsCloaked = mozilla::IsCloaked(mWnd);
mFrameState->ConsumePreXULSkeletonState(WasPreXULSkeletonUIMaximized());
- MOZ_ASSERT(BoundsUseDesktopPixels());
+ // FIXME(emilio): This looks wrong, mBounds and mLastPaintBounds
+ // are LayoutDevice coords...
auto scale = GetDesktopToDeviceScale();
mBounds = mLastPaintBounds = LayoutDeviceIntRect::FromUnknownRect(
- DesktopIntRect::Round(LayoutDeviceRect(GetBounds()) / scale)
- .ToUnknownRect());
+ DesktopIntRect::Round(GetBounds() / scale).ToUnknownRect());
// Reset the WNDPROC for this window and its whole class, as we had
// to use our own WNDPROC when creating the the skeleton UI window.
@@ -1966,7 +1964,7 @@ const SizeConstraints nsWindow::GetSizeConstraints() {
}
// Move this component
-void nsWindow::Move(double aX, double aY) {
+void nsWindow::Move(const DesktopPoint& aTopLeft) {
if (mWindowType == WindowType::TopLevel ||
mWindowType == WindowType::Dialog) {
SetSizeMode(nsSizeMode_Normal);
@@ -1974,10 +1972,8 @@ void nsWindow::Move(double aX, double aY) {
// for top-level windows only, convert coordinates from desktop pixels
// (the "parent" coordinate space) to the window's device pixel space
- double scale =
- BoundsUseDesktopPixels() ? GetDesktopToDeviceScale().scale : 1.0;
- int32_t x = NSToIntRound(aX * scale);
- int32_t y = NSToIntRound(aY * scale);
+ auto topLeft =
+ LayoutDeviceIntPoint::Round(aTopLeft * GetDesktopToDeviceScale());
// Check to see if window needs to be moved first
// to avoid a costly call to SetWindowPos. This check
@@ -1987,7 +1983,7 @@ void nsWindow::Move(double aX, double aY) {
// Only perform this check for non-popup windows, since the positioning can
// in fact change even when the x/y do not. We always need to perform the
// check. See bug #97805 for details.
- if (mWindowType != WindowType::Popup && mBounds.IsEqualXY(x, y)) {
+ if (mWindowType != WindowType::Popup && mBounds.TopLeft() == topLeft) {
// Nothing to do, since it is already positioned correctly.
return;
}
@@ -2012,10 +2008,10 @@ void nsWindow::Move(double aX, double aY) {
MONITORINFO mi = {sizeof(MONITORINFO)};
VERIFY(::GetMonitorInfo(monitor, &mi));
- int32_t deltaX =
- x + mi.rcWork.left - mi.rcMonitor.left - pl.rcNormalPosition.left;
- int32_t deltaY =
- y + mi.rcWork.top - mi.rcMonitor.top - pl.rcNormalPosition.top;
+ int32_t deltaX = topLeft.x.value + mi.rcWork.left - mi.rcMonitor.left -
+ pl.rcNormalPosition.left;
+ int32_t deltaY = topLeft.y.value + mi.rcWork.top - mi.rcMonitor.top -
+ pl.rcNormalPosition.top;
pl.rcNormalPosition.left += deltaX;
pl.rcNormalPosition.right += deltaX;
pl.rcNormalPosition.top += deltaY;
@@ -2024,7 +2020,7 @@ void nsWindow::Move(double aX, double aY) {
return;
}
- mBounds.MoveTo(x, y);
+ mBounds.MoveTo(topLeft);
if (mWnd) {
#ifdef DEBUG
@@ -2039,7 +2035,8 @@ void nsWindow::Move(double aX, double aY) {
RECT workArea;
::SystemParametersInfo(SPI_GETWORKAREA, 0, &workArea, 0);
// no annoying assertions. just mention the issue.
- if (x < 0 || x >= workArea.right || y < 0 || y >= workArea.bottom) {
+ if (topLeft.x < 0 || topLeft.x >= workArea.right || topLeft.y < 0 ||
+ topLeft.y >= workArea.bottom) {
MOZ_LOG(gWindowsLog, LogLevel::Info,
("window moved to offscreen position\n"));
}
@@ -2051,7 +2048,7 @@ void nsWindow::Move(double aX, double aY) {
UINT flags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOSIZE;
double oldScale = mDefaultScale;
mResizeState = IN_SIZEMOVE;
- VERIFY(::SetWindowPos(mWnd, nullptr, x, y, 0, 0, flags));
+ VERIFY(::SetWindowPos(mWnd, nullptr, topLeft.x, topLeft.y, 0, 0, flags));
mResizeState = NOT_RESIZING;
if (WinUtils::LogToPhysFactor(mWnd) != oldScale) {
ChangedDPI();
@@ -2062,25 +2059,21 @@ void nsWindow::Move(double aX, double aY) {
}
// Resize this component
-void nsWindow::Resize(double aWidth, double aHeight, bool aRepaint) {
+void nsWindow::Resize(const DesktopSize& aSize, bool aRepaint) {
// for top-level windows only, convert coordinates from desktop pixels
// (the "parent" coordinate space) to the window's device pixel space
- double scale =
- BoundsUseDesktopPixels() ? GetDesktopToDeviceScale().scale : 1.0;
- int32_t width = NSToIntRound(aWidth * scale);
- int32_t height = NSToIntRound(aHeight * scale);
-
- NS_ASSERTION((width >= 0), "Negative width passed to nsWindow::Resize");
- NS_ASSERTION((height >= 0), "Negative height passed to nsWindow::Resize");
- if (width < 0 || height < 0) {
- gfxCriticalNoteOnce << "Negative passed to Resize(" << width << ", "
- << height << ") repaint: " << aRepaint;
+ auto size = LayoutDeviceIntSize::Round(aSize * GetDesktopToDeviceScale());
+ NS_ASSERTION(size.width >= 0, "Negative width passed to nsWindow::Resize");
+ NS_ASSERTION(size.height >= 0, "Negative height passed to nsWindow::Resize");
+ if (size.width < 0 || size.height < 0) {
+ gfxCriticalNoteOnce << "Negative passed to Resize(" << size.width << ", "
+ << size.height << ") repaint: " << aRepaint;
}
- ConstrainSize(&width, &height);
+ ConstrainSize(&size.width, &size.height);
// Avoid unnecessary resizing calls
- if (mBounds.IsEqualSize(width, height)) {
+ if (mBounds.Size() == size) {
if (aRepaint) {
Invalidate();
}
@@ -2091,8 +2084,8 @@ void nsWindow::Resize(double aWidth, double aHeight, bool aRepaint) {
if (mIsShowingPreXULSkeletonUI && WasPreXULSkeletonUIMaximized()) {
WINDOWPLACEMENT pl = {sizeof(WINDOWPLACEMENT)};
VERIFY(::GetWindowPlacement(mWnd, &pl));
- pl.rcNormalPosition.right = pl.rcNormalPosition.left + width;
- pl.rcNormalPosition.bottom = pl.rcNormalPosition.top + height;
+ pl.rcNormalPosition.right = pl.rcNormalPosition.left + size.width;
+ pl.rcNormalPosition.bottom = pl.rcNormalPosition.top + size.height;
mResizeState = RESIZING;
VERIFY(::SetWindowPlacement(mWnd, &pl));
mResizeState = NOT_RESIZING;
@@ -2101,7 +2094,7 @@ void nsWindow::Resize(double aWidth, double aHeight, bool aRepaint) {
// Set cached value for lightweight and printing
bool wasLocking = mAspectRatio != 0.0;
- mBounds.SizeTo(width, height);
+ mBounds.SizeTo(size);
if (wasLocking) {
LockAspectRatio(true); // This causes us to refresh the mAspectRatio value
}
@@ -2113,7 +2106,7 @@ void nsWindow::Resize(double aWidth, double aHeight, bool aRepaint) {
}
double oldScale = mDefaultScale;
mResizeState = RESIZING;
- VERIFY(::SetWindowPos(mWnd, nullptr, 0, 0, width, height, flags));
+ VERIFY(::SetWindowPos(mWnd, nullptr, 0, 0, size.width, size.height, flags));
mResizeState = NOT_RESIZING;
if (WinUtils::LogToPhysFactor(mWnd) != oldScale) {
ChangedDPI();
@@ -2125,29 +2118,25 @@ void nsWindow::Resize(double aWidth, double aHeight, bool aRepaint) {
}
// Resize this component
-void nsWindow::Resize(double aX, double aY, double aWidth, double aHeight,
- bool aRepaint) {
+void nsWindow::Resize(const DesktopRect& aRect, bool aRepaint) {
// for top-level windows only, convert coordinates from desktop pixels
// (the "parent" coordinate space) to the window's device pixel space
- double scale =
- BoundsUseDesktopPixels() ? GetDesktopToDeviceScale().scale : 1.0;
- int32_t x = NSToIntRound(aX * scale);
- int32_t y = NSToIntRound(aY * scale);
- int32_t width = NSToIntRound(aWidth * scale);
- int32_t height = NSToIntRound(aHeight * scale);
-
- NS_ASSERTION((width >= 0), "Negative width passed to nsWindow::Resize");
- NS_ASSERTION((height >= 0), "Negative height passed to nsWindow::Resize");
- if (width < 0 || height < 0) {
- gfxCriticalNoteOnce << "Negative passed to Resize(" << x << " ," << y
- << ", " << width << ", " << height
+ auto topLeft =
+ LayoutDeviceIntPoint::Round(aRect.TopLeft() * GetDesktopToDeviceScale());
+ auto size =
+ LayoutDeviceIntSize::Round(aRect.Size() * GetDesktopToDeviceScale());
+
+ NS_ASSERTION(size.width >= 0, "Negative width passed to nsWindow::Resize");
+ NS_ASSERTION(size.height >= 0, "Negative height passed to nsWindow::Resize");
+ if (size.width < 0 || size.height < 0) {
+ gfxCriticalNoteOnce << "Negative passed to Resize(" << size
<< ") repaint: " << aRepaint;
}
- ConstrainSize(&width, &height);
+ ConstrainSize(&size.width, &size.height);
// Avoid unnecessary resizing calls
- if (mBounds.IsEqualRect(x, y, width, height)) {
+ if (mBounds.IsEqualRect(topLeft.x, topLeft.y, size.width, size.height)) {
if (aRepaint) {
Invalidate();
}
@@ -2166,20 +2155,20 @@ void nsWindow::Resize(double aX, double aY, double aWidth, double aHeight,
MONITORINFO mi = {sizeof(MONITORINFO)};
VERIFY(::GetMonitorInfo(monitor, &mi));
- int32_t deltaX =
- x + mi.rcWork.left - mi.rcMonitor.left - pl.rcNormalPosition.left;
- int32_t deltaY =
- y + mi.rcWork.top - mi.rcMonitor.top - pl.rcNormalPosition.top;
+ int32_t deltaX = topLeft.x.value + mi.rcWork.left - mi.rcMonitor.left -
+ pl.rcNormalPosition.left;
+ int32_t deltaY = topLeft.y.value + mi.rcWork.top - mi.rcMonitor.top -
+ pl.rcNormalPosition.top;
pl.rcNormalPosition.left += deltaX;
- pl.rcNormalPosition.right = pl.rcNormalPosition.left + width;
+ pl.rcNormalPosition.right = pl.rcNormalPosition.left + size.width;
pl.rcNormalPosition.top += deltaY;
- pl.rcNormalPosition.bottom = pl.rcNormalPosition.top + height;
+ pl.rcNormalPosition.bottom = pl.rcNormalPosition.top + size.height;
VERIFY(::SetWindowPlacement(mWnd, &pl));
return;
}
// Set cached value for lightweight and printing
- mBounds.SetRect(x, y, width, height);
+ mBounds = LayoutDeviceIntRect(topLeft, size);
if (mWnd) {
UINT flags = SWP_NOZORDER | SWP_NOACTIVATE;
@@ -2189,7 +2178,8 @@ void nsWindow::Resize(double aX, double aY, double aWidth, double aHeight,
double oldScale = mDefaultScale;
mResizeState = RESIZING;
- VERIFY(::SetWindowPos(mWnd, nullptr, x, y, width, height, flags));
+ VERIFY(::SetWindowPos(mWnd, nullptr, topLeft.x, topLeft.y, size.width,
+ size.height, flags));
mResizeState = NOT_RESIZING;
if (WinUtils::LogToPhysFactor(mWnd) != oldScale) {
ChangedDPI();
@@ -3276,8 +3266,6 @@ bool nsWindow::PrepareForFullscreenTransition(nsISupports** aData) {
FullscreenTransitionInitData initData;
nsCOMPtr<nsIScreen> screen = GetWidgetScreen();
const DesktopIntRect rect = screen->GetRectDisplayPix();
- MOZ_ASSERT(BoundsUseDesktopPixels(),
- "Should only be called on top-level window");
initData.mBounds =
LayoutDeviceIntRect::Round(rect * GetDesktopToDeviceScale());
@@ -6494,7 +6482,8 @@ void nsWindow::OnWindowPosChanged(WINDOWPOS* wp) {
NS_DispatchToMainThread(NS_NewRunnableFunction(
"EnforceAspectRatio", [self, this, newWidth]() -> void {
if (mWnd) {
- Resize(newWidth, newWidth / mAspectRatio, true);
+ // FIXME: This seems wrong? newWidth is LayoutDevicePixel
+ Resize(DesktopSize(newWidth, newWidth / mAspectRatio), true);
}
}));
}
@@ -7057,7 +7046,9 @@ void nsWindow::OnDPIChanged(int32_t x, int32_t y, int32_t width,
}
}
- Resize(x, y, width, height, true);
+ // FIXME(emilio): This looks wrong, x / y / width / height are
+ // LayoutDevice coords...
+ Resize(DesktopRect(x, y, width, height), true);
}
UpdateNonClientMargins();
ChangedDPI();
diff --git a/widget/windows/nsWindow.h b/widget/windows/nsWindow.h
@@ -211,10 +211,9 @@ class nsWindow final : public nsIWidget {
void LockAspectRatio(bool aShouldLock) override;
const SizeConstraints GetSizeConstraints() override;
void SetInputRegion(const InputRegion&) override;
- void Move(double aX, double aY) override;
- void Resize(double aWidth, double aHeight, bool aRepaint) override;
- void Resize(double aX, double aY, double aWidth, double aHeight,
- bool aRepaint) override;
+ void Move(const DesktopPoint&) override;
+ void Resize(const DesktopSize&, bool aRepaint) override;
+ void Resize(const DesktopRect&, bool aRepaint) override;
void SetSizeMode(nsSizeMode aMode) override;
nsSizeMode SizeMode() override;
void GetWorkspaceID(nsAString& workspaceID) override;
@@ -830,6 +829,8 @@ class nsWindow final : public nsIWidget {
// area).
LayoutDeviceIntRegion mOpaqueRegion;
+ LayoutDeviceIntRect mBounds;
+
// Graphics
LayoutDeviceIntRect mLastPaintBounds;
// The region of the window we know is cleared to transparent already,
diff --git a/xpfe/appshell/AppWindow.cpp b/xpfe/appshell/AppWindow.cpp
@@ -716,15 +716,14 @@ nsresult AppWindow::MoveResize(const Maybe<DesktopPoint>& aPosition,
}
if (aPosition && aSize) {
- mWindow->Resize(aPosition->x, aPosition->y, aSize->width, aSize->height,
- aRepaint);
+ mWindow->Resize(DesktopRect(*aPosition, *aSize), aRepaint);
dirtyAttributes = {PersistentAttribute::Size,
PersistentAttribute::Position};
} else if (aSize) {
- mWindow->Resize(aSize->width, aSize->height, aRepaint);
+ mWindow->Resize(*aSize, aRepaint);
dirtyAttributes = {PersistentAttribute::Size};
} else if (aPosition) {
- mWindow->Move(aPosition->x, aPosition->y);
+ mWindow->Move(*aPosition);
dirtyAttributes = {PersistentAttribute::Position};
}