Bug 1689682 - Include the desktop-to-device scaling factor in SizeConstraints r=mac-reviewers,mstange

Include the scaling factor in the SizeConstraints struct so that widgets can
correctly constrain their width and height when the widget's scaling factor
differs from the nsPresContext.

Differential Revision: https://phabricator.services.mozilla.com/D109265
This commit is contained in:
Haik Aftandilian 2021-03-26 02:23:46 +00:00
Родитель 31b7df19ba
Коммит c45e8b4f76
3 изменённых файлов: 52 добавлений и 37 удалений

Просмотреть файл

@ -830,7 +830,13 @@ void nsContainerFrame::SetSizeConstraints(nsPresContext* aPresContext,
if (devMinSize.height > devMaxSize.height)
devMaxSize.height = devMinSize.height;
widget::SizeConstraints constraints(devMinSize, devMaxSize);
nsIWidget* rootWidget = aPresContext->GetNearestWidget();
DesktopToLayoutDeviceScale constraintsScale(MOZ_WIDGET_INVALID_SCALE);
if (rootWidget) {
constraintsScale = rootWidget->GetDesktopToDeviceScale();
}
widget::SizeConstraints constraints(devMinSize, devMaxSize, constraintsScale);
// 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

Просмотреть файл

@ -1140,29 +1140,32 @@ void nsCocoaWindow::SetSizeConstraints(const SizeConstraints& aConstraints) {
NSRect rect = (mWindowType == eWindowType_popup) ? NSZeroRect : NSMakeRect(0.0, 0.0, 32, 32);
rect = [mWindow frameRectForChildViewRect:rect];
CGFloat scaleFactor = BackingScaleFactor();
SizeConstraints c = aConstraints;
c.mMinSize.width = std::max(nsCocoaUtils::CocoaPointsToDevPixels(rect.size.width, scaleFactor),
c.mMinSize.width);
c.mMinSize.height = std::max(nsCocoaUtils::CocoaPointsToDevPixels(rect.size.height, scaleFactor),
c.mMinSize.height);
NSSize minSize = {nsCocoaUtils::DevPixelsToCocoaPoints(c.mMinSize.width, scaleFactor),
nsCocoaUtils::DevPixelsToCocoaPoints(c.mMinSize.height, scaleFactor)};
if (c.mScale.scale == MOZ_WIDGET_INVALID_SCALE) {
c.mScale.scale = BackingScaleFactor();
}
c.mMinSize.width = std::max(nsCocoaUtils::CocoaPointsToDevPixels(rect.size.width, c.mScale.scale),
c.mMinSize.width);
c.mMinSize.height = std::max(
nsCocoaUtils::CocoaPointsToDevPixels(rect.size.height, c.mScale.scale), c.mMinSize.height);
NSSize minSize = {nsCocoaUtils::DevPixelsToCocoaPoints(c.mMinSize.width, c.mScale.scale),
nsCocoaUtils::DevPixelsToCocoaPoints(c.mMinSize.height, c.mScale.scale)};
[mWindow setMinSize:minSize];
c.mMaxSize.width = std::max(nsCocoaUtils::CocoaPointsToDevPixels(c.mMaxSize.width, scaleFactor),
c.mMaxSize.width);
c.mMaxSize.height = std::max(nsCocoaUtils::CocoaPointsToDevPixels(c.mMaxSize.height, scaleFactor),
c.mMaxSize.height);
c.mMaxSize.width = std::max(
nsCocoaUtils::CocoaPointsToDevPixels(c.mMaxSize.width, c.mScale.scale), c.mMaxSize.width);
c.mMaxSize.height = std::max(
nsCocoaUtils::CocoaPointsToDevPixels(c.mMaxSize.height, c.mScale.scale), c.mMaxSize.height);
NSSize maxSize = {c.mMaxSize.width == NS_MAXSIZE
? FLT_MAX
: nsCocoaUtils::DevPixelsToCocoaPoints(c.mMaxSize.width, scaleFactor),
: nsCocoaUtils::DevPixelsToCocoaPoints(c.mMaxSize.width, c.mScale.scale),
c.mMaxSize.height == NS_MAXSIZE
? FLT_MAX
: nsCocoaUtils::DevPixelsToCocoaPoints(c.mMaxSize.height, scaleFactor)};
: nsCocoaUtils::DevPixelsToCocoaPoints(c.mMaxSize.height, c.mScale.scale)};
[mWindow setMaxSize:maxSize];
nsBaseWidget::SetSizeConstraints(c);
@ -1677,12 +1680,19 @@ void nsCocoaWindow::DoResize(double aX, double aY, double aWidth, double aHeight
AutoRestore<bool> reentrantResizeGuard(mInResize);
mInResize = true;
// ConstrainSize operates in device pixels, so we need to convert using
// the backing scale factor here
CGFloat scale = BackingScaleFactor();
CGFloat scale = mSizeConstraints.mScale.scale;
if (scale == MOZ_WIDGET_INVALID_SCALE) {
scale = BackingScaleFactor();
}
// mSizeConstraints is in device pixels.
int32_t width = NSToIntRound(aWidth * scale);
int32_t height = NSToIntRound(aHeight * scale);
ConstrainSize(&width, &height);
width =
std::max(mSizeConstraints.mMinSize.width, std::min(mSizeConstraints.mMaxSize.width, width));
height = std::max(mSizeConstraints.mMinSize.height,
std::min(mSizeConstraints.mMaxSize.height, height));
DesktopIntRect newBounds(NSToIntRound(aX), NSToIntRound(aY), NSToIntRound(width / scale),
NSToIntRound(height / scale));
@ -1831,21 +1841,6 @@ void nsCocoaWindow::BackingScaleFactorChanged() {
return;
}
if (mBackingScaleFactor > 0.0) {
// convert size constraints to the new device pixel coordinate space
double scaleFactor = newScale / mBackingScaleFactor;
mSizeConstraints.mMinSize.width = NSToIntRound(mSizeConstraints.mMinSize.width * scaleFactor);
mSizeConstraints.mMinSize.height = NSToIntRound(mSizeConstraints.mMinSize.height * scaleFactor);
if (mSizeConstraints.mMaxSize.width < NS_MAXSIZE) {
mSizeConstraints.mMaxSize.width =
std::min(NS_MAXSIZE, NSToIntRound(mSizeConstraints.mMaxSize.width * scaleFactor));
}
if (mSizeConstraints.mMaxSize.height < NS_MAXSIZE) {
mSizeConstraints.mMaxSize.height =
std::min(NS_MAXSIZE, NSToIntRound(mSizeConstraints.mMaxSize.height * scaleFactor));
}
}
mBackingScaleFactor = newScale;
if (!mWidgetListener || mWidgetListener->GetAppWindow()) {

Просмотреть файл

@ -172,6 +172,7 @@ typedef void* nsNativeWidget;
#endif
#define MOZ_WIDGET_MAX_SIZE 16384
#define MOZ_WIDGET_INVALID_SCALE 0.0
// Must be kept in sync with xpcom/rust/xpcom/src/interfaces/nonidl.rs
#define NS_IWIDGET_IID \
@ -293,11 +294,14 @@ namespace widget {
* Values are in device pixels.
*/
struct SizeConstraints {
SizeConstraints() : mMaxSize(MOZ_WIDGET_MAX_SIZE, MOZ_WIDGET_MAX_SIZE) {}
SizeConstraints()
: mMaxSize(MOZ_WIDGET_MAX_SIZE, MOZ_WIDGET_MAX_SIZE),
mScale(MOZ_WIDGET_INVALID_SCALE) {}
SizeConstraints(mozilla::LayoutDeviceIntSize aMinSize,
mozilla::LayoutDeviceIntSize aMaxSize)
: mMinSize(aMinSize), mMaxSize(aMaxSize) {
mozilla::LayoutDeviceIntSize aMaxSize,
mozilla::DesktopToLayoutDeviceScale aScale)
: mMinSize(aMinSize), mMaxSize(aMaxSize), mScale(aScale) {
if (mMaxSize.width > MOZ_WIDGET_MAX_SIZE) {
mMaxSize.width = MOZ_WIDGET_MAX_SIZE;
}
@ -308,6 +312,16 @@ struct SizeConstraints {
mozilla::LayoutDeviceIntSize mMinSize;
mozilla::LayoutDeviceIntSize mMaxSize;
/*
* The scale used to convert from desktop to device dimensions.
* MOZ_WIDGET_INVALID_SCALE if the value is not known.
*
* Bug 1701109 is filed to revisit adding of 'mScale' and deal
* with multi-monitor scaling issues in more complete way across
* all widget implementations.
*/
mozilla::DesktopToLayoutDeviceScale mScale;
};
struct AutoObserverNotifier {