diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index dec2c44637..c9135fb2c6 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -1727,6 +1727,15 @@ public:
         ChecksumItuV41
     };
 
+    enum class HighDpiScaleFactorRoundingPolicy {
+        Unset,
+        Round,
+        Ceil,
+        Floor,
+        RoundPreferFloor,
+        PassThrough
+    };
+
 #ifndef Q_QDOC
     // NOTE: Generally, do not add QT_Q_ENUM if a corresponding Q_Q_FLAG exists.
     QT_Q_ENUM(ScrollBarPolicy)
@@ -1812,6 +1821,7 @@ public:
     QT_Q_ENUM(MouseEventSource)
     QT_Q_FLAG(MouseEventFlag)
     QT_Q_ENUM(ChecksumType)
+    QT_Q_ENUM(HighDpiScaleFactorRoundingPolicy)
     QT_Q_ENUM(TabFocusBehavior)
 #endif // Q_DOC
 
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index 5bba8c5fe5..cce67eb376 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -3252,3 +3252,25 @@
 
   \value ChecksumItuV41 Checksum calculation based on ITU-V.41.
 */
+
+/*!
+  \enum Qt::HighDpiScaleFactorRoundingPolicy
+  \since 5.14
+
+  This enum describes the possible High-DPI scale factor rounding policies, which
+  decide how non-integer scale factors (such as Windows 150%) are handled.
+
+  The active policy is set by calling QGuiApplication::setHighDdpiScaleFactorRoundingPolicy() before
+  the application object is created, or by setting the QT_SCALE_FACTOR_ROUNDING_POLICY
+  environment variable.
+
+  \sa QGuiApplication::setHighDdpiScaleFactorRoundingPolicy()
+  \sa AA_EnableHighDpiScaling.
+
+  \omitvalue Unset
+  \value Round Round up for .5 and above.
+  \value Ceil Always round up.
+  \value Floor Always round down.
+  \value RoundPreferFloor Round up for .75 and above.
+  \value PassThrough Don't round.
+*/
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 5014878bd2..1515569785 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -146,6 +146,8 @@ QString QGuiApplicationPrivate::styleOverride;
 
 Qt::ApplicationState QGuiApplicationPrivate::applicationState = Qt::ApplicationInactive;
 
+Qt::HighDpiScaleFactorRoundingPolicy QGuiApplicationPrivate::highDpiScaleFactorRoundingPolicy =
+    Qt::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor;
 bool QGuiApplicationPrivate::highDpiScalingUpdated = false;
 
 QPointer<QWindow> QGuiApplicationPrivate::currentDragWindow;
@@ -685,6 +687,8 @@ QGuiApplication::~QGuiApplication()
     QGuiApplicationPrivate::lastCursorPosition = {qInf(), qInf()};
     QGuiApplicationPrivate::currentMousePressWindow = QGuiApplicationPrivate::currentMouseWindow = nullptr;
     QGuiApplicationPrivate::applicationState = Qt::ApplicationInactive;
+    QGuiApplicationPrivate::highDpiScaleFactorRoundingPolicy =
+        Qt::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor;
     QGuiApplicationPrivate::highDpiScalingUpdated = false;
     QGuiApplicationPrivate::currentDragWindow = nullptr;
     QGuiApplicationPrivate::tabletDevicePoints.clear();
@@ -3456,6 +3460,46 @@ Qt::ApplicationState QGuiApplication::applicationState()
     return QGuiApplicationPrivate::applicationState;
 }
 
+/*!
+    \since 5.14
+
+    Sets the high-DPI scale factor rounding policy for the application. The
+    policy decides how non-integer scale factors (such as Windows 150%) are
+    handled, for applications that have AA_EnableHighDpiScaling enabled.
+
+    The two principal options are whether fractional scale factors should
+    be rounded to an integer or not. Keeping the scale factor as-is will
+    make the user interface size match the OS setting exactly, but may cause
+    painting errors, for example with the Windows style.
+
+    If rounding is wanted, then which type of rounding should be decided
+    next. Mathematically correct rounding is supported but may not give
+    the best visual results: Consider if you want to render 1.5x as 1x
+    ("small UI") or as 2x ("large UI"). See the Qt::HighDpiScaleFactorRoundingPolicy
+    enum for a complete list of all options.
+
+    This function must be called before creating the application object,
+    and can be overridden by setting the QT_SCALE_FACTOR_ROUNDING_POLICY
+    environment variable. The QGuiApplication::highDpiScaleFactorRoundingPolicy()
+    accessor will reflect the environment, if set.
+
+    The default value is Qt::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor.
+*/
+void QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy policy)
+{
+    QGuiApplicationPrivate::highDpiScaleFactorRoundingPolicy = policy;
+}
+
+/*!
+  \since 5.14
+
+  Returns the high-DPI scale factor rounding policy.
+*/
+Qt::HighDpiScaleFactorRoundingPolicy QGuiApplication::highDpiScaleFactorRoundingPolicy()
+{
+    return QGuiApplicationPrivate::highDpiScaleFactorRoundingPolicy;
+}
+
 /*!
     \since 5.2
     \fn void QGuiApplication::applicationStateChanged(Qt::ApplicationState state)
diff --git a/src/gui/kernel/qguiapplication.h b/src/gui/kernel/qguiapplication.h
index 02dffef0fe..2814ba1d1b 100644
--- a/src/gui/kernel/qguiapplication.h
+++ b/src/gui/kernel/qguiapplication.h
@@ -156,6 +156,9 @@ public:
 
     static Qt::ApplicationState applicationState();
 
+    static void setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy policy);
+    static Qt::HighDpiScaleFactorRoundingPolicy highDpiScaleFactorRoundingPolicy();
+
     static int exec();
     bool notify(QObject *, QEvent *) override;
 
diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h
index 482d45e5c3..f7914b0ae8 100644
--- a/src/gui/kernel/qguiapplication_p.h
+++ b/src/gui/kernel/qguiapplication_p.h
@@ -215,6 +215,7 @@ public:
     static QWindow *currentMouseWindow;
     static QWindow *currentMousePressWindow;
     static Qt::ApplicationState applicationState;
+    static Qt::HighDpiScaleFactorRoundingPolicy highDpiScaleFactorRoundingPolicy;
     static bool highDpiScalingUpdated;
     static QPointer<QWindow> currentDragWindow;
 
diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp
index 64f1397771..ee54fd4fa1 100644
--- a/src/gui/kernel/qhighdpiscaling.cpp
+++ b/src/gui/kernel/qhighdpiscaling.cpp
@@ -46,6 +46,9 @@
 #include <private/qguiapplication_p.h>
 
 #include <QtCore/qdebug.h>
+#include <QtCore/qmetaobject.h>
+
+#include <algorithm>
 
 QT_BEGIN_NAMESPACE
 
@@ -53,9 +56,29 @@ Q_LOGGING_CATEGORY(lcScaling, "qt.scaling");
 
 #ifndef QT_NO_HIGHDPISCALING
 static const char legacyDevicePixelEnvVar[] = "QT_DEVICE_PIXEL_RATIO";
+static const char legacyAutoScreenEnvVar[] = "QT_AUTO_SCREEN_SCALE_FACTOR";
+
+static const char enableHighDpiScalingEnvVar[] = "QT_ENABLE_HIGHDPI_SCALING";
 static const char scaleFactorEnvVar[] = "QT_SCALE_FACTOR";
-static const char autoScreenEnvVar[] = "QT_AUTO_SCREEN_SCALE_FACTOR";
 static const char screenFactorsEnvVar[] = "QT_SCREEN_SCALE_FACTORS";
+static const char scaleFactorRoundingPolicyEnvVar[] = "QT_SCALE_FACTOR_ROUNDING_POLICY";
+static const char dpiAdjustmentPolicyEnvVar[] = "QT_DPI_ADJUSTMENT_POLICY";
+static const char usePhysicalDpiEnvVar[] = "QT_USE_PHYSICAL_DPI";
+
+// Per-screen scale factors for named screens set with QT_SCREEN_SCALE_FACTORS
+// are stored here. Use a global hash to keep the factor across screen
+// disconnect/connect cycles where the screen object may be deleted.
+typedef QHash<QString, qreal> QScreenScaleFactorHash;
+Q_GLOBAL_STATIC(QScreenScaleFactorHash, qNamedScreenScaleFactors);
+
+// Reads and interprets the given environment variable as a bool,
+// returns the default value if not set.
+static bool qEnvironmentVariableAsBool(const char *name, bool defaultValue)
+{
+    bool ok = false;
+    int value = qEnvironmentVariableIntValue(name, &ok);
+    return ok ? value > 0 : defaultValue;
+}
 
 static inline qreal initialGlobalScaleFactor()
 {
@@ -63,23 +86,30 @@ static inline qreal initialGlobalScaleFactor()
     qreal result = 1;
     if (qEnvironmentVariableIsSet(scaleFactorEnvVar)) {
         bool ok;
-        const qreal f = qgetenv(scaleFactorEnvVar).toDouble(&ok);
+        const qreal f = qEnvironmentVariable(scaleFactorEnvVar).toDouble(&ok);
         if (ok && f > 0) {
             qCDebug(lcScaling) << "Apply " << scaleFactorEnvVar << f;
             result = f;
         }
     } else {
+        // Check for deprecated environment variables.
         if (qEnvironmentVariableIsSet(legacyDevicePixelEnvVar)) {
             qWarning("Warning: %s is deprecated. Instead use:\n"
                      "   %s to enable platform plugin controlled per-screen factors.\n"
-                     "   %s to set per-screen factors.\n"
+                     "   %s to set per-screen DPI.\n"
                      "   %s to set the application global scale factor.",
-                     legacyDevicePixelEnvVar, autoScreenEnvVar, screenFactorsEnvVar, scaleFactorEnvVar);
+                     legacyDevicePixelEnvVar, legacyAutoScreenEnvVar, screenFactorsEnvVar, scaleFactorEnvVar);
 
             int dpr = qEnvironmentVariableIntValue(legacyDevicePixelEnvVar);
             if (dpr > 0)
                 result = dpr;
         }
+
+        if (qEnvironmentVariableIsSet(legacyAutoScreenEnvVar)) {
+            qWarning("Warning: %s is deprecated. Instead use:\n"
+                     "   %s to enable platform plugin controlled per-screen factors.",
+                     legacyAutoScreenEnvVar, enableHighDpiScalingEnvVar);
+        }
     }
     return result;
 }
@@ -226,7 +256,6 @@ bool QHighDpiScaling::m_usePixelDensity = false; // use scale factor from platfo
 bool QHighDpiScaling::m_pixelDensityScalingActive = false; // pixel density scale factor > 1
 bool QHighDpiScaling::m_globalScalingActive = false; // global scale factor is active
 bool QHighDpiScaling::m_screenFactorSet = false; // QHighDpiScaling::setScreenFactor has been used
-QDpi QHighDpiScaling::m_logicalDpi = QDpi(-1,-1); // The scaled logical DPI of the primary screen
 
 /*
     Initializes the QHighDpiScaling global variables. Called before the
@@ -238,16 +267,215 @@ static inline bool usePixelDensity()
     // Determine if we should set a scale factor based on the pixel density
     // reported by the platform plugin. There are several enablers and several
     // disablers. A single disable may veto all other enablers.
+
+    // First, check of there is an explicit disable.
     if (QCoreApplication::testAttribute(Qt::AA_DisableHighDpiScaling))
         return false;
     bool screenEnvValueOk;
-    const int screenEnvValue = qEnvironmentVariableIntValue(autoScreenEnvVar, &screenEnvValueOk);
+    const int screenEnvValue = qEnvironmentVariableIntValue(legacyAutoScreenEnvVar, &screenEnvValueOk);
     if (screenEnvValueOk && screenEnvValue < 1)
         return false;
+    bool enableEnvValueOk;
+    const int enableEnvValue = qEnvironmentVariableIntValue(enableHighDpiScalingEnvVar, &enableEnvValueOk);
+    if (enableEnvValueOk && enableEnvValue < 1)
+        return false;
+
+    // Then return if there was an enable.
     return QCoreApplication::testAttribute(Qt::AA_EnableHighDpiScaling)
         || (screenEnvValueOk && screenEnvValue > 0)
-        || (qEnvironmentVariableIsSet(legacyDevicePixelEnvVar) &&
-            qgetenv(legacyDevicePixelEnvVar).compare("auto", Qt::CaseInsensitive) == 0);
+        || (enableEnvValueOk && enableEnvValue > 0)
+        || (qEnvironmentVariableIsSet(legacyDevicePixelEnvVar)
+            && qEnvironmentVariable(legacyDevicePixelEnvVar).compare(QLatin1String("auto"), Qt::CaseInsensitive) == 0);
+}
+
+qreal QHighDpiScaling::rawScaleFactor(const QPlatformScreen *screen)
+{
+    // Determine if physical DPI should be used
+    static const bool usePhysicalDpi = qEnvironmentVariableAsBool(usePhysicalDpiEnvVar, false);
+
+    // Calculate scale factor beased on platform screen DPI values
+    qreal factor;
+    QDpi platformBaseDpi = screen->logicalBaseDpi();
+    if (usePhysicalDpi) {
+        qreal platformPhysicalDpi = screen->screen()->physicalDotsPerInch();
+        factor = qreal(platformPhysicalDpi) / qreal(platformBaseDpi.first);
+    } else {
+        const QDpi platformLogicalDpi = QPlatformScreen::overrideDpi(screen->logicalDpi());
+        factor = qreal(platformLogicalDpi.first) / qreal(platformBaseDpi.first);
+    }
+
+    return factor;
+}
+
+template <class EnumType>
+struct EnumLookup
+{
+    const char *name;
+    EnumType value;
+};
+
+template <class EnumType>
+static bool operator==(const EnumLookup<EnumType> &e1, const EnumLookup<EnumType> &e2)
+{
+    return qstricmp(e1.name, e2.name) == 0;
+}
+
+template <class EnumType>
+static QByteArray joinEnumValues(const EnumLookup<EnumType> *i1, const EnumLookup<EnumType> *i2)
+{
+    QByteArray result;
+    for (; i1 < i2; ++i1) {
+        if (!result.isEmpty())
+            result += QByteArrayLiteral(", ");
+        result += i1->name;
+    }
+    return result;
+}
+
+using ScaleFactorRoundingPolicyLookup = EnumLookup<Qt::HighDpiScaleFactorRoundingPolicy>;
+
+static const ScaleFactorRoundingPolicyLookup scaleFactorRoundingPolicyLookup[] =
+{
+    {"Round", Qt::HighDpiScaleFactorRoundingPolicy::Round},
+    {"Ceil", Qt::HighDpiScaleFactorRoundingPolicy::Ceil},
+    {"Floor", Qt::HighDpiScaleFactorRoundingPolicy::Floor},
+    {"RoundPreferFloor", Qt::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor},
+    {"PassThrough", Qt::HighDpiScaleFactorRoundingPolicy::PassThrough}
+};
+
+static Qt::HighDpiScaleFactorRoundingPolicy
+    lookupScaleFactorRoundingPolicy(const QByteArray &v)
+{
+    auto end = std::end(scaleFactorRoundingPolicyLookup);
+    auto it = std::find(std::begin(scaleFactorRoundingPolicyLookup), end,
+                        ScaleFactorRoundingPolicyLookup{v.constData(), Qt::HighDpiScaleFactorRoundingPolicy::Unset});
+    return it != end ? it->value : Qt::HighDpiScaleFactorRoundingPolicy::Unset;
+}
+
+using DpiAdjustmentPolicyLookup = EnumLookup<QHighDpiScaling::DpiAdjustmentPolicy>;
+
+static const DpiAdjustmentPolicyLookup dpiAdjustmentPolicyLookup[] =
+{
+    {"AdjustDpi", QHighDpiScaling::DpiAdjustmentPolicy::Enabled},
+    {"DontAdjustDpi", QHighDpiScaling::DpiAdjustmentPolicy::Disabled},
+    {"AdjustUpOnly", QHighDpiScaling::DpiAdjustmentPolicy::UpOnly}
+};
+
+static QHighDpiScaling::DpiAdjustmentPolicy
+    lookupDpiAdjustmentPolicy(const QByteArray &v)
+{
+    auto end = std::end(dpiAdjustmentPolicyLookup);
+    auto it = std::find(std::begin(dpiAdjustmentPolicyLookup), end,
+                        DpiAdjustmentPolicyLookup{v.constData(), QHighDpiScaling::DpiAdjustmentPolicy::Unset});
+    return it != end ? it->value : QHighDpiScaling::DpiAdjustmentPolicy::Unset;
+}
+
+qreal QHighDpiScaling::roundScaleFactor(qreal rawFactor)
+{
+    // Apply scale factor rounding policy. Using mathematically correct rounding
+    // may not give the most desirable visual results, especially for
+    // critical fractions like .5. In general, rounding down results in visual
+    // sizes that are smaller than the ideal size, and opposite for rounding up.
+    // Rounding down is then preferable since "small UI" is a more acceptable
+    // high-DPI experience than "large UI".
+    static auto scaleFactorRoundingPolicy = Qt::HighDpiScaleFactorRoundingPolicy::Unset;
+
+    // Determine rounding policy
+    if (scaleFactorRoundingPolicy == Qt::HighDpiScaleFactorRoundingPolicy::Unset) {
+        // Check environment
+        if (qEnvironmentVariableIsSet(scaleFactorRoundingPolicyEnvVar)) {
+            QByteArray policyText = qgetenv(scaleFactorRoundingPolicyEnvVar);
+            auto policyEnumValue = lookupScaleFactorRoundingPolicy(policyText);
+            if (policyEnumValue != Qt::HighDpiScaleFactorRoundingPolicy::Unset) {
+                scaleFactorRoundingPolicy = policyEnumValue;
+            } else {
+                auto values = joinEnumValues(std::begin(scaleFactorRoundingPolicyLookup),
+                                             std::end(scaleFactorRoundingPolicyLookup));
+                qWarning("Unknown scale factor rounding policy: %s. Supported values are: %s.",
+                         policyText.constData(), values.constData());
+            }
+        }
+
+        // Check application object if no environment value was set.
+        if (scaleFactorRoundingPolicy == Qt::HighDpiScaleFactorRoundingPolicy::Unset) {
+            scaleFactorRoundingPolicy = QGuiApplication::highDpiScaleFactorRoundingPolicy();
+        } else {
+            // Make application setting reflect environment
+            QGuiApplication::setHighDpiScaleFactorRoundingPolicy(scaleFactorRoundingPolicy);
+        }
+    }
+
+    // Apply rounding policy.
+    qreal roundedFactor = rawFactor;
+    switch (scaleFactorRoundingPolicy) {
+    case Qt::HighDpiScaleFactorRoundingPolicy::Round:
+        roundedFactor = qRound(rawFactor);
+        break;
+    case Qt::HighDpiScaleFactorRoundingPolicy::Ceil:
+        roundedFactor = qCeil(rawFactor);
+        break;
+    case Qt::HighDpiScaleFactorRoundingPolicy::Floor:
+        roundedFactor = qFloor(rawFactor);
+        break;
+    case Qt::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor:
+        // Round up for .75 and higher. This favors "small UI" over "large UI".
+        roundedFactor = rawFactor - qFloor(rawFactor) < 0.75
+            ? qFloor(rawFactor) : qCeil(rawFactor);
+        break;
+    case Qt::HighDpiScaleFactorRoundingPolicy::PassThrough:
+    case Qt::HighDpiScaleFactorRoundingPolicy::Unset:
+        break;
+    }
+
+    // Don't round down to to zero; clamp the minimum (rounded) factor to 1.
+    // This is not a common case but can happen if a display reports a very
+    // low DPI.
+    if (scaleFactorRoundingPolicy != Qt::HighDpiScaleFactorRoundingPolicy::PassThrough)
+        roundedFactor = qMax(roundedFactor, qreal(1));
+
+    return roundedFactor;
+}
+
+QDpi QHighDpiScaling::effectiveLogicalDpi(const QPlatformScreen *screen, qreal rawFactor, qreal roundedFactor)
+{
+    // Apply DPI adjustment policy, if needed. If enabled this will change the
+    // reported logical DPI to account for the difference between the rounded
+    // scale factor and the actual scale factor. The effect is that text size
+    // will be correct for the screen dpi, but may be (slightly) out of sync
+    // with the rest of the UI. The amount of out-of-synch-ness depends on how
+    // well user code handles a non-standard DPI values, but since the
+    // adjustment is small (typically +/- 48 max) this might be OK.
+    static auto dpiAdjustmentPolicy = DpiAdjustmentPolicy::Unset;
+
+    // Determine adjustment policy.
+    if (dpiAdjustmentPolicy == DpiAdjustmentPolicy::Unset) {
+        if (qEnvironmentVariableIsSet(dpiAdjustmentPolicyEnvVar)) {
+            QByteArray policyText = qgetenv(dpiAdjustmentPolicyEnvVar);
+            auto policyEnumValue = lookupDpiAdjustmentPolicy(policyText);
+            if (policyEnumValue != DpiAdjustmentPolicy::Unset) {
+                dpiAdjustmentPolicy = policyEnumValue;
+            } else {
+                auto values = joinEnumValues(std::begin(dpiAdjustmentPolicyLookup),
+                                             std::end(dpiAdjustmentPolicyLookup));
+                qWarning("Unknown DPI adjustment policy: %s. Supported values are: %s.",
+                         policyText.constData(), values.constData());
+            }
+        }
+        if (dpiAdjustmentPolicy == DpiAdjustmentPolicy::Unset)
+            dpiAdjustmentPolicy = DpiAdjustmentPolicy::UpOnly;
+    }
+
+    // Apply adjustment policy.
+    const QDpi baseDpi = screen->logicalBaseDpi();
+    const qreal dpiAdjustmentFactor = rawFactor / roundedFactor;
+
+    // Return the base DPI for cases where there is no adjustment
+    if (dpiAdjustmentPolicy == DpiAdjustmentPolicy::Disabled)
+        return baseDpi;
+    if (dpiAdjustmentPolicy == DpiAdjustmentPolicy::UpOnly && dpiAdjustmentFactor < 1)
+        return baseDpi;
+
+    return QDpi(baseDpi.first * dpiAdjustmentFactor, baseDpi.second * dpiAdjustmentFactor);
 }
 
 void QHighDpiScaling::initHighDpiScaling()
@@ -260,8 +488,6 @@ void QHighDpiScaling::initHighDpiScaling()
 
     m_pixelDensityScalingActive = false; //set in updateHighDpiScaling below
 
-    // we update m_active in updateHighDpiScaling, but while we create the
-    // screens, we have to assume that m_usePixelDensity implies scaling
     m_active = m_globalScalingActive || m_usePixelDensity;
 }
 
@@ -281,22 +507,21 @@ void QHighDpiScaling::updateHighDpiScaling()
     }
     if (qEnvironmentVariableIsSet(screenFactorsEnvVar)) {
         int i = 0;
-        const auto specs = qgetenv(screenFactorsEnvVar).split(';');
-        for (const QByteArray &spec : specs) {
-            QScreen *screen = 0;
-            int equalsPos = spec.lastIndexOf('=');
-            double factor = 0;
+        const QString spec = qEnvironmentVariable(screenFactorsEnvVar);
+        const auto specs = spec.splitRef(QLatin1Char(';'));
+        for (const QStringRef &spec : specs) {
+            int equalsPos = spec.lastIndexOf(QLatin1Char('='));
+            qreal factor = 0;
             if (equalsPos > 0) {
                 // support "name=factor"
-                QByteArray name = spec.mid(0, equalsPos);
-                QByteArray f = spec.mid(equalsPos + 1);
                 bool ok;
-                factor = f.toDouble(&ok);
-                if (ok) {
+                const auto name = spec.left(equalsPos);
+                factor = spec.mid(equalsPos + 1).toDouble(&ok);
+                if (ok && factor > 0 ) {
                     const auto screens = QGuiApplication::screens();
                     for (QScreen *s : screens) {
-                        if (s->name() == QString::fromLocal8Bit(name)) {
-                            screen = s;
+                        if (s->name() == name) {
+                            setScreenFactor(s, factor);
                             break;
                         }
                     }
@@ -305,23 +530,15 @@ void QHighDpiScaling::updateHighDpiScaling()
                 // listing screens in order
                 bool ok;
                 factor = spec.toDouble(&ok);
-                if (ok && i < QGuiApplication::screens().count())
-                    screen = QGuiApplication::screens().at(i);
+                if (ok && factor > 0 && i < QGuiApplication::screens().count()) {
+                    QScreen *screen = QGuiApplication::screens().at(i);
+                    setScreenFactor(screen, factor);
+                }
             }
-            if (screen)
-                setScreenFactor(screen, factor);
             ++i;
         }
     }
-    m_active = m_globalScalingActive || m_screenFactorSet || m_pixelDensityScalingActive;
-
-    QScreen *primaryScreen = QGuiApplication::primaryScreen();
-    if (!primaryScreen)
-        return;
-    QPlatformScreen *platformScreen = primaryScreen->handle();
-    qreal sf = screenSubfactor(platformScreen);
-    QDpi primaryDpi = platformScreen->logicalDpi();
-    m_logicalDpi = QDpi(primaryDpi.first / sf, primaryDpi.second / sf);
+    m_active = m_globalScalingActive || m_screenFactorSet || m_usePixelDensity;
 }
 
 /*
@@ -353,7 +570,14 @@ void QHighDpiScaling::setScreenFactor(QScreen *screen, qreal factor)
         m_screenFactorSet = true;
         m_active = true;
     }
-    screen->setProperty(scaleFactorProperty, QVariant(factor));
+
+    // Prefer associating the factor with screen name over the object
+    // since the screen object may be deleted on screen disconnects.
+    const QString name = screen->name();
+    if (name.isEmpty())
+        screen->setProperty(scaleFactorProperty, QVariant(factor));
+    else
+        qNamedScreenScaleFactors()->insert(name, factor);
 
     // hack to force re-evaluation of screen geometry
     if (screen->handle())
@@ -421,35 +645,50 @@ QPoint QHighDpiScaling::mapPositionFromGlobal(const QPoint &pos, const QPoint &w
 qreal QHighDpiScaling::screenSubfactor(const QPlatformScreen *screen)
 {
     qreal factor = qreal(1.0);
-    if (screen) {
-        if (m_usePixelDensity) {
-            qreal pixelDensity = screen->pixelDensity();
-
-            // Pixel density reported by the screen is sometimes not precise enough,
-            // so recalculate it: divide px (physical pixels) by dp (device-independent pixels)
-            // for both width and height, and then use the average if it is different from
-            // the one initially reported by the screen
-            QRect screenGeometry = screen->geometry();
-            qreal wFactor = qreal(screenGeometry.width()) / qRound(screenGeometry.width() / pixelDensity);
-            qreal hFactor = qreal(screenGeometry.height()) / qRound(screenGeometry.height() / pixelDensity);
-            qreal averageDensity = (wFactor + hFactor) / 2;
-            if (!qFuzzyCompare(pixelDensity, averageDensity))
-                pixelDensity = averageDensity;
-
-            factor *= pixelDensity;
-        }
-        if (m_screenFactorSet) {
-            QVariant screenFactor = screen->screen()->property(scaleFactorProperty);
-            if (screenFactor.isValid())
-                factor *= screenFactor.toReal();
+    if (!screen)
+        return factor;
+
+    // Unlike the other code where factors are combined by multiplication,
+    // factors from QT_SCREEN_SCALE_FACTORS takes precedence over the factor
+    // computed from platform plugin DPI. The rationale is that the user is
+    // setting the factor to override erroneous DPI values.
+    bool screenPropertyUsed = false;
+    if (m_screenFactorSet) {
+        // Check if there is a factor set on the screen object or associated
+        // with the screen name. These are mutually exclusive, so checking
+        // order is not significant.
+        QVariant byIndex = screen->screen()->property(scaleFactorProperty);
+        auto byNameIt = qNamedScreenScaleFactors()->constFind(screen->name());
+        if (byIndex.isValid()) {
+            screenPropertyUsed = true;
+            factor = byIndex.toReal();
+        } else if (byNameIt != qNamedScreenScaleFactors()->cend()) {
+            screenPropertyUsed = true;
+            factor = *byNameIt;
         }
     }
+
+    if (!screenPropertyUsed && m_usePixelDensity)
+        factor = roundScaleFactor(rawScaleFactor(screen));
+
     return factor;
 }
 
-QDpi QHighDpiScaling::logicalDpi()
+QDpi QHighDpiScaling::logicalDpi(const QScreen *screen)
 {
-    return m_logicalDpi;
+    // (Note: m_active test is performed at call site.)
+    if (!screen || !screen->handle())
+        return QDpi(96, 96);
+
+    if (!m_usePixelDensity) {
+        const qreal screenScaleFactor = screenSubfactor(screen->handle());
+        const QDpi dpi = QPlatformScreen::overrideDpi(screen->handle()->logicalDpi());
+        return QDpi{ dpi.first / screenScaleFactor, dpi.second / screenScaleFactor };
+    }
+
+    const qreal scaleFactor = rawScaleFactor(screen->handle());
+    const qreal roundedScaleFactor = roundScaleFactor(scaleFactor);
+    return effectiveLogicalDpi(screen->handle(), scaleFactor, roundedScaleFactor);
 }
 
 QHighDpiScaling::ScaleAndOrigin QHighDpiScaling::scaleAndOrigin(const QPlatformScreen *platformScreen, QPoint *nativePosition)
diff --git a/src/gui/kernel/qhighdpiscaling_p.h b/src/gui/kernel/qhighdpiscaling_p.h
index c43641b8c9..55ad6df5c9 100644
--- a/src/gui/kernel/qhighdpiscaling_p.h
+++ b/src/gui/kernel/qhighdpiscaling_p.h
@@ -72,11 +72,27 @@ typedef QPair<qreal, qreal> QDpi;
 
 #ifndef QT_NO_HIGHDPISCALING
 class Q_GUI_EXPORT QHighDpiScaling {
+    Q_GADGET
 public:
+    enum class DpiAdjustmentPolicy {
+        Unset,
+        Enabled,
+        Disabled,
+        UpOnly
+    };
+    Q_ENUM(DpiAdjustmentPolicy)
+
+    QHighDpiScaling() = delete;
+    ~QHighDpiScaling() = delete;
+    QHighDpiScaling(const QHighDpiScaling &) = delete;
+    QHighDpiScaling &operator=(const QHighDpiScaling &) = delete;
+    QHighDpiScaling(QHighDpiScaling &&) = delete;
+    QHighDpiScaling &operator=(QHighDpiScaling &&) = delete;
+
     static void initHighDpiScaling();
     static void updateHighDpiScaling();
     static void setGlobalFactor(qreal factor);
-    static void setScreenFactor(QScreen *window, qreal factor);
+    static void setScreenFactor(QScreen *screen, qreal factor);
 
     static bool isActive() { return m_active; }
 
@@ -98,9 +114,12 @@ public:
     static QPoint mapPositionToNative(const QPoint &pos, const QPlatformScreen *platformScreen);
     static QPoint mapPositionToGlobal(const QPoint &pos, const QPoint &windowGlobalPosition, const QWindow *window);
     static QPoint mapPositionFromGlobal(const QPoint &pos, const QPoint &windowGlobalPosition, const QWindow *window);
-    static QDpi logicalDpi();
+    static QDpi logicalDpi(const QScreen *screen);
 
 private:
+    static qreal rawScaleFactor(const QPlatformScreen *screen);
+    static qreal roundScaleFactor(qreal rawFactor);
+    static QDpi effectiveLogicalDpi(const QPlatformScreen *screen, qreal rawFactor, qreal roundedFactor);
     static qreal screenSubfactor(const QPlatformScreen *screen);
 
     static qreal m_factor;
diff --git a/src/gui/kernel/qplatformscreen.cpp b/src/gui/kernel/qplatformscreen.cpp
index 21ae75ba8f..9e684c9fbf 100644
--- a/src/gui/kernel/qplatformscreen.cpp
+++ b/src/gui/kernel/qplatformscreen.cpp
@@ -197,6 +197,28 @@ QDpi QPlatformScreen::logicalDpi() const
                 25.4 * s.height() / ps.height());
 }
 
+// Helper function for accessing the platform screen logical dpi
+// which accounts for QT_FONT_DPI.
+QPair<qreal, qreal> QPlatformScreen::overrideDpi(const QPair<qreal, qreal> &in)
+{
+    static const int overrideDpi = qEnvironmentVariableIntValue("QT_FONT_DPI");
+    return overrideDpi > 0 ?  QDpi(overrideDpi, overrideDpi) : in;
+}
+
+/*!
+    Reimplement to return the base logical DPI for the platform. This
+    DPI value should correspond to a standard-DPI (1x) display. The
+    default implementation returns 96.
+
+    QtGui will use this value (together with logicalDpi) to compute
+    the scale factor when high-DPI scaling is enabled:
+        factor = logicalDPI / baseDPI
+*/
+QDpi QPlatformScreen::logicalBaseDpi() const
+{
+    return QDpi(96, 96);
+}
+
 /*!
     Reimplement this function in subclass to return the device pixel ratio
     for the screen. This is the ratio between physical pixels and the
diff --git a/src/gui/kernel/qplatformscreen.h b/src/gui/kernel/qplatformscreen.h
index e9d64c8a29..32e6bf7ec7 100644
--- a/src/gui/kernel/qplatformscreen.h
+++ b/src/gui/kernel/qplatformscreen.h
@@ -113,6 +113,7 @@ public:
 
     virtual QSizeF physicalSize() const;
     virtual QDpi logicalDpi() const;
+    virtual QDpi logicalBaseDpi() const;
     virtual qreal devicePixelRatio() const;
     virtual qreal pixelDensity()  const;
 
@@ -158,6 +159,8 @@ public:
     // The platform screen's geometry in device independent coordinates
     QRect deviceIndependentGeometry() const;
 
+    static QDpi overrideDpi(const QDpi &in);
+
 protected:
     void resizeMaximizedWindows();
 
diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp
index f208eb02be..b856435f67 100644
--- a/src/gui/kernel/qscreen.cpp
+++ b/src/gui/kernel/qscreen.cpp
@@ -84,8 +84,11 @@ void QScreenPrivate::setPlatformScreen(QPlatformScreen *screen)
     platformScreen->d_func()->screen = q;
     orientation = platformScreen->orientation();
     geometry = platformScreen->deviceIndependentGeometry();
-    availableGeometry = QHighDpi::fromNative(platformScreen->availableGeometry(), QHighDpiScaling::factor(platformScreen), geometry.topLeft());
-    logicalDpi = platformScreen->logicalDpi();
+    availableGeometry = QHighDpi::fromNative(platformScreen->availableGeometry(),
+                        QHighDpiScaling::factor(platformScreen), geometry.topLeft());
+
+    logicalDpi = QPlatformScreen::overrideDpi(platformScreen->logicalDpi());
+
     refreshRate = platformScreen->refreshRate();
     // safeguard ourselves against buggy platform behavior...
     if (refreshRate < 1.0)
@@ -279,7 +282,7 @@ qreal QScreen::logicalDotsPerInchX() const
 {
     Q_D(const QScreen);
     if (QHighDpiScaling::isActive())
-        return QHighDpiScaling::logicalDpi().first;
+        return QHighDpiScaling::logicalDpi(this).first;
     return d->logicalDpi.first;
 }
 
@@ -295,7 +298,7 @@ qreal QScreen::logicalDotsPerInchY() const
 {
     Q_D(const QScreen);
     if (QHighDpiScaling::isActive())
-        return QHighDpiScaling::logicalDpi().second;
+        return QHighDpiScaling::logicalDpi(this).second;
     return d->logicalDpi.second;
 }
 
@@ -314,7 +317,7 @@ qreal QScreen::logicalDotsPerInchY() const
 qreal QScreen::logicalDotsPerInch() const
 {
     Q_D(const QScreen);
-    QDpi dpi = QHighDpiScaling::isActive() ? QHighDpiScaling::logicalDpi() : d->logicalDpi;
+    QDpi dpi = QHighDpiScaling::isActive() ? QHighDpiScaling::logicalDpi(this) : d->logicalDpi;
     return (dpi.first + dpi.second) * qreal(0.5);
 }
 
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
index b0f2869128..44d11a43bf 100644
--- a/src/gui/kernel/qwindowsysteminterface.cpp
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
@@ -860,8 +860,8 @@ void QWindowSystemInterface::handleScreenGeometryChange(QScreen *screen, const Q
 
 void QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(QScreen *screen, qreal dpiX, qreal dpiY)
 {
-    QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent *e =
-            new QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent(screen, dpiX, dpiY); // ### tja
+    const QDpi effectiveDpi = QPlatformScreen::overrideDpi(QDpi{dpiX, dpiY});
+    auto e = new QWindowSystemInterfacePrivate::ScreenLogicalDotsPerInchEvent(screen, effectiveDpi.first, effectiveDpi.second);
     QWindowSystemInterfacePrivate::handleWindowSystemEvent(e);
 }
 
diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp
index 7dc8bb8080..80757c2135 100644
--- a/src/plugins/platforms/android/qandroidplatformscreen.cpp
+++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp
@@ -401,15 +401,17 @@ void QAndroidPlatformScreen::doRedraw()
         m_dirtyRect = QRect();
 }
 
+static const int androidLogicalDpi = 72;
+
 QDpi QAndroidPlatformScreen::logicalDpi() const
 {
-    qreal lDpi = QtAndroid::scaledDensity() * 72;
+    qreal lDpi = QtAndroid::scaledDensity() * androidLogicalDpi;
     return QDpi(lDpi, lDpi);
 }
 
-qreal QAndroidPlatformScreen::pixelDensity() const
+QDpi QAndroidPlatformScreen::logicalBaseDpi() const
 {
-    return QtAndroid::pixelDensity();
+    return QDpi(androidLogicalDpi, androidLogicalDpi);
 }
 
 Qt::ScreenOrientation QAndroidPlatformScreen::orientation() const
diff --git a/src/plugins/platforms/android/qandroidplatformscreen.h b/src/plugins/platforms/android/qandroidplatformscreen.h
index f15aeae3fd..5dc158e351 100644
--- a/src/plugins/platforms/android/qandroidplatformscreen.h
+++ b/src/plugins/platforms/android/qandroidplatformscreen.h
@@ -103,7 +103,7 @@ protected:
 
 private:
     QDpi logicalDpi() const override;
-    qreal pixelDensity()  const override;
+    QDpi logicalBaseDpi() const override;
     Qt::ScreenOrientation orientation() const override;
     Qt::ScreenOrientation nativeOrientation() const override;
     void surfaceChanged(JNIEnv *env, jobject surface, int w, int h) override;
diff --git a/src/plugins/platforms/cocoa/qcocoascreen.h b/src/plugins/platforms/cocoa/qcocoascreen.h
index 9ded98df32..a73b97c771 100644
--- a/src/plugins/platforms/cocoa/qcocoascreen.h
+++ b/src/plugins/platforms/cocoa/qcocoascreen.h
@@ -64,6 +64,7 @@ public:
     qreal devicePixelRatio() const override;
     QSizeF physicalSize() const override { return m_physicalSize; }
     QDpi logicalDpi() const override { return m_logicalDpi; }
+    QDpi logicalBaseDpi() const override { return m_logicalDpi; }
     qreal refreshRate() const override { return m_refreshRate; }
     QString name() const override { return m_name; }
     QPlatformCursor *cursor() const override { return m_cursor; }
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index 4137a4bd9a..e9839e9994 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -256,15 +256,6 @@ QWindow *QWindowsScreen::windowAt(const QPoint &screenPoint, unsigned flags)
     return result;
 }
 
-qreal QWindowsScreen::pixelDensity() const
-{
-    // QTBUG-49195: Use logical DPI instead of physical DPI to calculate
-    // the pixel density since it is reflects the Windows UI scaling.
-    // High DPI auto scaling should be disabled when the user chooses
-    // small fonts on a High DPI monitor, resulting in lower logical DPI.
-    return qMax(1, qRound(logicalDpi().first / 96));
-}
-
 /*!
     \brief Determine siblings in a virtual desktop system.
 
diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h
index 8ad012512e..938ca9f865 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.h
+++ b/src/plugins/platforms/windows/qwindowsscreen.h
@@ -87,7 +87,7 @@ public:
     QImage::Format format() const override { return m_data.format; }
     QSizeF physicalSize() const override { return m_data.physicalSizeMM; }
     QDpi logicalDpi() const override { return m_data.dpi; }
-    qreal pixelDensity() const override;
+    QDpi logicalBaseDpi() const override { return QDpi(96, 96); };
     qreal devicePixelRatio() const override { return 1.0; }
     qreal refreshRate() const override { return m_data.refreshRateHz; }
     QString name() const override { return m_data.name; }
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 39e83e0451..ccd1a672bc 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -660,10 +660,6 @@ QImage::Format QXcbScreen::format() const
 
 int QXcbScreen::forcedDpi() const
 {
-    static const int overrideDpi = qEnvironmentVariableIntValue("QT_FONT_DPI");
-    if (overrideDpi)
-        return overrideDpi;
-
     const int forcedDpi = m_virtualDesktop->forcedDpi();
     if (forcedDpi > 0)
         return forcedDpi;
@@ -679,11 +675,6 @@ QDpi QXcbScreen::logicalDpi() const
     return m_virtualDesktop->dpi();
 }
 
-qreal QXcbScreen::pixelDensity() const
-{
-    return m_pixelDensity;
-}
-
 QPlatformCursor *QXcbScreen::cursor() const
 {
     return m_cursor;
@@ -747,14 +738,6 @@ void QXcbScreen::updateGeometry(const QRect &geometry, uint8_t rotation)
     if (m_sizeMillimeters.isEmpty())
         m_sizeMillimeters = sizeInMillimeters(geometry.size(), m_virtualDesktop->dpi());
 
-    qreal dpi = forcedDpi();
-    if (dpi <= 0)
-        dpi = geometry.width() / physicalSize().width() * qreal(25.4);
-
-    // Use 128 as a reference DPI on small screens. This favors "small UI" over "large UI".
-    qreal referenceDpi = physicalSize().width() <= 320 ? 128 : 96;
-
-    m_pixelDensity = qMax(1, qRound(dpi/referenceDpi));
     m_geometry = geometry;
     m_availableGeometry = geometry & m_virtualDesktop->workArea();
     QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), m_geometry, m_availableGeometry);
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
index ec3b07bfb7..62931d2500 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -161,7 +161,7 @@ public:
     QImage::Format format() const override;
     QSizeF physicalSize() const override { return m_sizeMillimeters; }
     QDpi logicalDpi() const override;
-    qreal pixelDensity() const override;
+    QDpi logicalBaseDpi() const override { return QDpi(96, 96); };
     QPlatformCursor *cursor() const override;
     qreal refreshRate() const override { return m_refreshRate; }
     Qt::ScreenOrientation orientation() const override { return m_orientation; }
@@ -227,7 +227,6 @@ private:
     Qt::ScreenOrientation m_orientation = Qt::PrimaryOrientation;
     QXcbCursor *m_cursor;
     int m_refreshRate = 60;
-    int m_pixelDensity = 1;
     QEdidParser m_edid;
 };
 
diff --git a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
index 4b583e13d3..00f50c7933 100644
--- a/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
+++ b/src/plugins/styles/windowsvista/qwindowsxpstyle.cpp
@@ -1485,11 +1485,13 @@ case PE_Frame:
 
                 // Inner white border
                 p->setPen(QPen(option->palette.base().color(), 0));
-                p->drawRect(QRectF(option->rect).adjusted(QStyleHelper::dpiScaled(0.5), QStyleHelper::dpiScaled(0.5),
-                                                          QStyleHelper::dpiScaled(-1), QStyleHelper::dpiScaled(-1)));
+                const auto topLevelAdjustment = QStyleHelper::dpiScaled(0.5);
+                const auto bottomRightAdjustment = QStyleHelper::dpiScaled(-1);
+                p->drawRect(QRectF(option->rect).adjusted(topLevelAdjustment, topLevelAdjustment,
+                                                          bottomRightAdjustment, bottomRightAdjustment));
                 // Outer dark border
                 p->setPen(QPen(bordercolor, 0));
-                p->drawRect(QRectF(option->rect).adjusted(0, 0, QStyleHelper::dpiScaled(-0.5), QStyleHelper::dpiScaled(-0.5)));
+                p->drawRect(QRectF(option->rect).adjusted(0, 0, -topLevelAdjustment, -topLevelAdjustment));
                 p->setPen(oldPen);
                 return;
             } else if (fillType == BT_NONE) {
@@ -3533,9 +3535,12 @@ QRect QWindowsXPStyle::subControlRect(ComplexControl cc, const QStyleOptionCompl
                              qRound(QStyleHelper::dpiScaled(16)), he - qRound(QStyleHelper::dpiScaled(2)));
                 break;
 
-            case SC_ComboBoxEditField:
-                rect = QRect(x + qRound(QStyleHelper::dpiScaled(2)), y + qRound(QStyleHelper::dpiScaled(2)),
-                             wi - qRound(QStyleHelper::dpiScaled(3 + 16)), he - qRound(QStyleHelper::dpiScaled(4)));
+            case SC_ComboBoxEditField: {
+                const int frame = qRound(QStyleHelper::dpiScaled(2));
+                rect = QRect(x + frame, y + frame,
+                             wi - qRound(QStyleHelper::dpiScaled(3 + 16)),
+                             he - qRound(QStyleHelper::dpiScaled(4)));
+            }
                 break;
 
             case SC_ComboBoxListBoxPopup:
diff --git a/src/widgets/accessible/qaccessiblemenu.cpp b/src/widgets/accessible/qaccessiblemenu.cpp
index 507584eb02..7f87288520 100644
--- a/src/widgets/accessible/qaccessiblemenu.cpp
+++ b/src/widgets/accessible/qaccessiblemenu.cpp
@@ -47,6 +47,7 @@
 #endif
 #include <QtWidgets/QAction>
 #include <qstyle.h>
+#include <private/qwidget_p.h>
 
 #ifndef QT_NO_ACCESSIBILITY
 
@@ -241,15 +242,9 @@ QObject *QAccessibleMenuItem::object() const
 /*! \reimp */
 QWindow *QAccessibleMenuItem::window() const
 {
-    QWindow *result = nullptr;
-    if (!m_owner.isNull()) {
-        result = m_owner->windowHandle();
-        if (!result) {
-            if (const QWidget *nativeParent = m_owner->nativeParentWidget())
-                result = nativeParent->windowHandle();
-        }
-    }
-    return result;
+    return m_owner.isNull()
+        ? nullptr
+        : qt_widget_private(m_owner.data())->windowHandle(QWidgetPrivate::WindowHandleMode::Closest);
 }
 
 QRect QAccessibleMenuItem::rect() const
diff --git a/src/widgets/dialogs/qmessagebox.cpp b/src/widgets/dialogs/qmessagebox.cpp
index ac1952a642..e7c67be713 100644
--- a/src/widgets/dialogs/qmessagebox.cpp
+++ b/src/widgets/dialogs/qmessagebox.cpp
@@ -2662,14 +2662,9 @@ QPixmap QMessageBoxPrivate::standardIcon(QMessageBox::Icon icon, QMessageBox *mb
         break;
     }
     if (!tmpIcon.isNull()) {
-        QWindow *window = nullptr;
-        if (mb) {
-            window = mb->windowHandle();
-            if (!window) {
-                if (const QWidget *nativeParent = mb->nativeParentWidget())
-                    window = nativeParent->windowHandle();
-            }
-        }
+        QWindow *window = mb
+            ? qt_widget_private(mb)->windowHandle(QWidgetPrivate::WindowHandleMode::Closest)
+            : nullptr;
         return tmpIcon.pixmap(window, QSize(iconSize, iconSize));
     }
     return QPixmap();
diff --git a/src/widgets/dialogs/qwizard.cpp b/src/widgets/dialogs/qwizard.cpp
index f19a4e99af..60ebed8d25 100644
--- a/src/widgets/dialogs/qwizard.cpp
+++ b/src/widgets/dialogs/qwizard.cpp
@@ -1595,23 +1595,25 @@ bool QWizardPrivate::handleAeroStyleChange()
     bool vistaMargins = false;
 
     if (isVistaThemeEnabled()) {
+        const int topOffset = vistaHelper->topOffset();
+        const int topPadding = vistaHelper->topPadding();
         if (isVistaThemeEnabled(QVistaHelper::VistaAero)) {
             if (isWindow) {
                 vistaHelper->setDWMTitleBar(QVistaHelper::ExtendedTitleBar);
                 q->installEventFilter(vistaHelper);
             }
             q->setMouseTracking(true);
-            antiFlickerWidget->move(0, vistaHelper->titleBarSize() + vistaHelper->topOffset());
+            antiFlickerWidget->move(0, vistaHelper->titleBarSize() + topOffset);
             vistaHelper->backButton()->move(
-                0, vistaHelper->topOffset() // ### should ideally work without the '+ 1'
-                - qMin(vistaHelper->topOffset(), vistaHelper->topPadding() + 1));
+                0, topOffset // ### should ideally work without the '+ 1'
+                - qMin(topOffset, topPadding + 1));
             vistaMargins = true;
             vistaHelper->backButton()->show();
         } else {
             if (isWindow)
                 vistaHelper->setDWMTitleBar(QVistaHelper::NormalTitleBar);
             q->setMouseTracking(true);
-            antiFlickerWidget->move(0, vistaHelper->topOffset());
+            antiFlickerWidget->move(0, topOffset);
             vistaHelper->backButton()->move(0, -1); // ### should ideally work with (0, 0)
         }
         if (isWindow)
diff --git a/src/widgets/dialogs/qwizard_win.cpp b/src/widgets/dialogs/qwizard_win.cpp
index aa9ad7f290..d281b3f143 100644
--- a/src/widgets/dialogs/qwizard_win.cpp
+++ b/src/widgets/dialogs/qwizard_win.cpp
@@ -293,9 +293,9 @@ void QVistaHelper::drawTitleBar(QPainter *painter)
     int glowOffset = 0;
 
     if (vistaState() == VistaAero) {
-        textHeight += 2 * glowSize();
-        textWidth += 2 * glowSize();
         glowOffset = glowSize();
+        textHeight += 2 * glowOffset;
+        textWidth += 2 * glowOffset;
     }
 
     const int titleLeft = (wizard->layoutDirection() == Qt::LeftToRight
diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp
index e1e45143b4..5f723aad79 100644
--- a/src/widgets/itemviews/qabstractitemview.cpp
+++ b/src/widgets/itemviews/qabstractitemview.cpp
@@ -4450,15 +4450,8 @@ QPixmap QAbstractItemViewPrivate::renderToPixmap(const QModelIndexList &indexes,
     if (paintPairs.isEmpty())
         return QPixmap();
 
-    qreal scale = 1.0f;
-
-    Q_Q(const QAbstractItemView);
-    QWidget *window = q->window();
-    if (window) {
-        QWindow *windowHandle = window->windowHandle();
-        if (windowHandle)
-            scale = windowHandle->devicePixelRatio();
-    }
+    QWindow *window = windowHandle(WindowHandleMode::Closest);
+    const qreal scale = window ? window->devicePixelRatio() : qreal(1);
 
     QPixmap pixmap(r->size() * scale);
     pixmap.setDevicePixelRatio(scale);
diff --git a/src/widgets/kernel/qdesktopwidget.cpp b/src/widgets/kernel/qdesktopwidget.cpp
index 5fb7882932..c6596fe833 100644
--- a/src/widgets/kernel/qdesktopwidget.cpp
+++ b/src/widgets/kernel/qdesktopwidget.cpp
@@ -111,7 +111,7 @@ const QRect QDesktopWidgetPrivate::availableGeometry(const QWidget *widget)
 QDesktopScreenWidget *QDesktopWidgetPrivate::widgetForScreen(QScreen *qScreen) const
 {
     foreach (QDesktopScreenWidget *widget, screens) {
-        if (widget->screen() == qScreen)
+        if (widget->assignedScreen() == qScreen)
             return widget;
     }
     return nullptr;
@@ -307,20 +307,12 @@ int QDesktopWidgetPrivate::screenNumber(const QWidget *w)
     if (screens.isEmpty()) // This should never happen
         return primaryScreen();
 
-    const QWindow *winHandle = w->windowHandle();
-    if (!winHandle) {
-        if (const QWidget *nativeParent = w->nativeParentWidget())
-            winHandle = nativeParent->windowHandle();
-    }
-
     // If there is more than one virtual desktop
     if (screens.count() != screens.constFirst()->virtualSiblings().count()) {
         // Find the root widget, get a QScreen from it and use the
         // virtual siblings for checking the window position.
-        if (winHandle) {
-            if (const QScreen *winScreen = winHandle->screen())
-                screens = winScreen->virtualSiblings();
-        }
+        if (const QScreen *winScreen = qt_widget_private(const_cast<QWidget *>(w))->associatedScreen())
+            screens = winScreen->virtualSiblings();
     }
 
     // Get the screen number from window position using screen geometry
diff --git a/src/widgets/kernel/qdesktopwidget_p.h b/src/widgets/kernel/qdesktopwidget_p.h
index 69f87337b3..63949055aa 100644
--- a/src/widgets/kernel/qdesktopwidget_p.h
+++ b/src/widgets/kernel/qdesktopwidget_p.h
@@ -68,7 +68,7 @@ public:
     int screenNumber() const;
     void setScreenGeometry(const QRect &geometry);
 
-    QScreen *screen() const { return m_screen.data(); }
+    QScreen *assignedScreen() const { return m_screen.data(); }
     QRect screenGeometry() const { return m_geometry; }
 
 private:
diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp
index 7aef74c507..cb0a290be9 100644
--- a/src/widgets/kernel/qopenglwidget.cpp
+++ b/src/widgets/kernel/qopenglwidget.cpp
@@ -1333,11 +1333,8 @@ int QOpenGLWidget::metric(QPaintDevice::PaintDeviceMetric metric) const
     if (d->inBackingStorePaint)
         return QWidget::metric(metric);
 
-    QWidget *tlw = window();
-    QWindow *window = tlw ? tlw->windowHandle() : 0;
-    QScreen *screen = tlw && tlw->windowHandle() ? tlw->windowHandle()->screen() : 0;
-    if (!screen && QGuiApplication::primaryScreen())
-        screen = QGuiApplication::primaryScreen();
+    auto window = d->windowHandle(QWidgetPrivate::WindowHandleMode::TopLevel);
+    QScreen *screen = window ? window->screen() : QGuiApplication::primaryScreen();
 
     const float dpmx = qt_defaultDpiX() * 100. / 2.54;
     const float dpmy = qt_defaultDpiY() * 100. / 2.54;
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index bf339ca5c5..72d79c85ee 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -1249,6 +1249,33 @@ void QWidgetPrivate::createRecursively()
     }
 }
 
+QWindow *QWidgetPrivate::windowHandle(WindowHandleMode mode) const
+{
+    if (mode == WindowHandleMode::Direct || mode == WindowHandleMode::Closest) {
+        if (QTLWExtra *x = maybeTopData())
+            return x->window;
+    }
+    if (mode == WindowHandleMode::Closest) {
+        if (auto nativeParent = q_func()->nativeParentWidget()) {
+            if (auto window = nativeParent->windowHandle())
+                return window;
+        }
+    }
+    if (mode == WindowHandleMode::TopLevel || mode == WindowHandleMode::Closest) {
+        if (auto topLevel = q_func()->topLevelWidget()) {
+            if (auto window = topLevel ->windowHandle())
+                return window;
+        }
+    }
+    return nullptr;
+}
+
+QScreen *QWidgetPrivate::associatedScreen() const
+{
+    if (auto window = windowHandle(WindowHandleMode::Closest))
+        return window->screen();
+    return nullptr;
+}
 
 // ### fixme: Qt 6: Remove parameter window from QWidget::create()
 
@@ -2653,7 +2680,7 @@ WId QWidget::effectiveWinId() const
 
     \since 5.0
 
-    \sa winId()
+    \sa winId(), screen()
 */
 QWindow *QWidget::windowHandle() const
 {
@@ -2661,6 +2688,29 @@ QWindow *QWidget::windowHandle() const
     return d->windowHandle();
 }
 
+/*!
+    Returns the screen the widget is on.
+
+    \since 5.14
+
+    \sa windowHandle()
+*/
+QScreen *QWidget::screen() const
+{
+    Q_D(const QWidget);
+    if (auto associatedScreen = d->associatedScreen())
+        return associatedScreen;
+    if (auto topLevel = window()) {
+        if (auto topData = qt_widget_private(topLevel)->topData()) {
+            if (auto initialScreen = QGuiApplicationPrivate::screen_list.value(topData->initialScreenIndex))
+                return initialScreen;
+        }
+        if (auto screenByPos = QGuiApplication::screenAt(topLevel->geometry().center()))
+            return screenByPos;
+    }
+    return QGuiApplication::primaryScreen();
+}
+
 #ifndef QT_NO_STYLE_STYLESHEET
 
 /*!
@@ -8111,7 +8161,7 @@ void QWidgetPrivate::show_sys()
 {
     Q_Q(QWidget);
 
-    QWidgetWindow *window = windowHandle();
+    auto window = qobject_cast<QWidgetWindow *>(windowHandle());
 
     if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
         invalidateBuffer(q->rect());
@@ -8250,7 +8300,7 @@ void QWidgetPrivate::hide_sys()
 {
     Q_Q(QWidget);
 
-    QWidgetWindow *window = windowHandle();
+    auto window = qobject_cast<QWidgetWindow *>(windowHandle());
 
     if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
         q->setAttribute(Qt::WA_Mapped, false);
diff --git a/src/widgets/kernel/qwidget.h b/src/widgets/kernel/qwidget.h
index 9d5fe89c70..da702b34f9 100644
--- a/src/widgets/kernel/qwidget.h
+++ b/src/widgets/kernel/qwidget.h
@@ -85,6 +85,7 @@ class QDragEnterEvent;
 class QDragMoveEvent;
 class QDragLeaveEvent;
 class QDropEvent;
+class QScreen;
 class QShowEvent;
 class QHideEvent;
 class QIcon;
@@ -595,6 +596,7 @@ public:
     QBackingStore *backingStore() const;
 
     QWindow *windowHandle() const;
+    QScreen *screen() const;
 
     static QWidget *createWindowContainer(QWindow *window, QWidget *parent=nullptr, Qt::WindowFlags flags=Qt::WindowFlags());
 
diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h
index 142d5ef9bb..e4a53cf167 100644
--- a/src/widgets/kernel/qwidget_p.h
+++ b/src/widgets/kernel/qwidget_p.h
@@ -343,7 +343,15 @@ public:
     QPainter *sharedPainter() const;
     void setSharedPainter(QPainter *painter);
     QWidgetBackingStore *maybeBackingStore() const;
-    QWidgetWindow *windowHandle() const;
+
+    enum class WindowHandleMode {
+        Direct,
+        Closest,
+        TopLevel
+    };
+    QWindow *windowHandle(WindowHandleMode mode = WindowHandleMode::Direct) const;
+
+    QScreen *associatedScreen() const;
 
     template <typename T>
     void repaint(T t);
@@ -1009,13 +1017,6 @@ inline QWidgetBackingStore *QWidgetPrivate::maybeBackingStore() const
     return x ? x->backingStoreTracker.data() : 0;
 }
 
-inline QWidgetWindow *QWidgetPrivate::windowHandle() const
-{
-    if (QTLWExtra *x = maybeTopData())
-        return x->window;
-    return nullptr;
-}
-
 QT_END_NAMESPACE
 
 #endif // QWIDGET_P_H
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index fbc71cd0ea..40054d5f63 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -586,10 +586,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event)
                         w->window()->raise();
                     }
 
-                    QWindow *win = w->windowHandle();
-                    if (!win)
-                        win = w->nativeParentWidget()->windowHandle();
-                    if (win) {
+                    if (auto win = qt_widget_private(w)->windowHandle(QWidgetPrivate::WindowHandleMode::Closest)) {
                         const QRect globalGeometry = win->isTopLevel()
                             ? win->geometry()
                             : QRect(win->mapToGlobal(QPoint(0, 0)), win->size());
diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp
index 12ca5201c1..2e61bbdd14 100644
--- a/src/widgets/styles/qwindowsstyle.cpp
+++ b/src/widgets/styles/qwindowsstyle.cpp
@@ -380,23 +380,12 @@ int QWindowsStylePrivate::fixedPixelMetric(QStyle::PixelMetric pm)
     return QWindowsStylePrivate::InvalidMetric;
 }
 
-static QWindow *windowOf(const QWidget *w)
+static QScreen *screenOf(const QWidget *w)
 {
-    QWindow *result = nullptr;
     if (w) {
-        result = w->windowHandle();
-        if (!result) {
-            if (const QWidget *np = w->nativeParentWidget())
-                result = np->windowHandle();
-        }
+        if (auto screen = qt_widget_private(const_cast<QWidget *>(w))->associatedScreen())
+            return screen;
     }
-    return result;
-}
-
-static QScreen *screenOf(const QWidget *w)
-{
-    if (const QWindow *window = windowOf(w))
-        return window->screen();
     return QGuiApplication::primaryScreen();
 }
 
@@ -802,8 +791,10 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
         QPen oldPen = p->pen();
         p->setPen(QPen(opt->palette.shadow().color(), 0));
         QRectF rect = opt->rect;
-        rect.adjust(QStyleHelper::dpiScaled(0.5), QStyleHelper::dpiScaled(0.5),
-                    QStyleHelper::dpiScaled(-1.5), QStyleHelper::dpiScaled(-1.5));
+        const qreal topLevelAdjustment = QStyleHelper::dpiScaled(0.5);
+        const qreal bottomRightAdjustment = QStyleHelper::dpiScaled(-1.5);
+        rect.adjust(topLevelAdjustment, topLevelAdjustment,
+                    bottomRightAdjustment, bottomRightAdjustment);
         p->drawRect(rect);
         p->setPen(oldPen);
         break;
diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp
index bdd2462c92..c8367797c8 100644
--- a/src/widgets/widgets/qcombobox.cpp
+++ b/src/widgets/widgets/qcombobox.cpp
@@ -2809,19 +2809,15 @@ void QComboBox::showPopup()
     bool startTimer = !container->isVisible();
     container->raise();
     container->create();
-    QWindow *containerWindow = container->window()->windowHandle();
-    if (containerWindow) {
-        QWindow *win = window()->windowHandle();
-        if (win) {
-            QScreen *currentScreen = win->screen();
-            if (currentScreen && !currentScreen->virtualSiblings().contains(containerWindow->screen())) {
-                containerWindow->setScreen(currentScreen);
-
-                // This seems to workaround an issue in xcb+multi GPU+multiscreen
-                // environment where the window might not always show up when screen
-                // is changed.
-                container->hide();
-            }
+    if (QWindow *containerWindow = qt_widget_private(container)->windowHandle(QWidgetPrivate::WindowHandleMode::TopLevel)) {
+        QScreen *currentScreen = d->associatedScreen();
+        if (currentScreen && !currentScreen->virtualSiblings().contains(containerWindow->screen())) {
+            containerWindow->setScreen(currentScreen);
+
+            // This seems to workaround an issue in xcb+multi GPU+multiscreen
+            // environment where the window might not always show up when screen
+            // is changed.
+            container->hide();
         }
     }
     container->show();
diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp
index 6c871aae2c..adc6167562 100644
--- a/src/widgets/widgets/qdockwidget.cpp
+++ b/src/widgets/widgets/qdockwidget.cpp
@@ -1522,10 +1522,10 @@ bool QDockWidget::event(QEvent *event)
         d->toggleViewAction->setChecked(true);
         QPoint parentTopLeft(0, 0);
         if (isWindow()) {
-            if (const QWindow *window = windowHandle())
-                parentTopLeft = window->screen()->availableVirtualGeometry().topLeft();
-            else
-                parentTopLeft = QGuiApplication::primaryScreen()->availableVirtualGeometry().topLeft();
+            const QScreen *screen = d->associatedScreen();
+            parentTopLeft = screen
+                ? screen->availableVirtualGeometry().topLeft()
+                : QGuiApplication::primaryScreen()->availableVirtualGeometry().topLeft();
         }
         emit visibilityChanged(geometry().right() >= parentTopLeft.x() && geometry().bottom() >= parentTopLeft.y());
 }
diff --git a/src/widgets/widgets/qlineedit_p.cpp b/src/widgets/widgets/qlineedit_p.cpp
index 6dcb2dd693..09667d7462 100644
--- a/src/widgets/widgets/qlineedit_p.cpp
+++ b/src/widgets/widgets/qlineedit_p.cpp
@@ -348,9 +348,7 @@ QLineEditPrivate *QLineEditIconButton::lineEditPrivate() const
 void QLineEditIconButton::paintEvent(QPaintEvent *)
 {
     QPainter painter(this);
-    QWindow *window = nullptr;
-    if (const QWidget *nativeParent = nativeParentWidget())
-        window = nativeParent->windowHandle();
+    QWindow *window = qt_widget_private(this)->windowHandle(QWidgetPrivate::WindowHandleMode::Closest);
     QIcon::Mode state = QIcon::Disabled;
     if (isEnabled())
         state = isDown() ? QIcon::Active : QIcon::Normal;
diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp
index 053bfbf024..244b4ddbdb 100644
--- a/src/widgets/widgets/qmainwindowlayout.cpp
+++ b/src/widgets/widgets/qmainwindowlayout.cpp
@@ -2560,9 +2560,9 @@ void QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos)
             }
         }
         for (QWidget *w : candidates) {
-            QWindow *handle1 = widget->windowHandle();
-            QWindow *handle2 = w->windowHandle();
-            if (handle1 && handle2 && handle1->screen() != handle2->screen())
+            const QScreen *screen1 = qt_widget_private(widget)->associatedScreen();
+            const QScreen *screen2 = qt_widget_private(w)->associatedScreen();
+            if (screen1 && screen2 && screen1 != screen2)
                 continue;
             if (!w->geometry().contains(mousePos))
                 continue;
diff --git a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
index 872e0b62c5..1dcd1cc644 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsitem/tst_qgraphicsitem.cpp
@@ -272,6 +272,9 @@ class tst_QGraphicsItem : public QObject
 {
     Q_OBJECT
 
+public:
+    static void initMain();
+
 private slots:
     void construction();
     void constructionWithParent();
@@ -474,6 +477,14 @@ private:
     QTouchDevice *m_touchDevice = nullptr;
 };
 
+void tst_QGraphicsItem::initMain()
+{
+#ifdef Q_OS_WIN
+    // Ensure minimum size constraints of framed windows on High DPI screens
+    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#endif
+}
+
 void tst_QGraphicsItem::construction()
 {
     for (int i = 0; i < 7; ++i) {
diff --git a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
index 12e458c669..0618f6b9e4 100644
--- a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
+++ b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
@@ -104,6 +104,7 @@ class tst_QHeaderView : public QObject
 
 public:
     tst_QHeaderView();
+    static void initMain();
 
 private slots:
     void initTestCase();
@@ -261,6 +262,14 @@ protected:
     QElapsedTimer timer;
 };
 
+void tst_QHeaderView::initMain()
+{
+#ifdef Q_OS_WIN
+    // Ensure minimum size constraints of framed windows on High DPI screens
+    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
+#endif
+}
+
 class QtTestModel: public QAbstractTableModel
 {
 
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
index 58c61d746a..25b327e96a 100644
--- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -1133,6 +1133,7 @@ void tst_QWidget::visible()
     QVERIFY( !childWidget->isVisible() );
 
     testWidget->show();
+    QVERIFY(testWidget->screen());
     QVERIFY( testWidget->isVisible() );
     QVERIFY( childWidget->isVisible() );
 
diff --git a/tests/auto/widgets/widgets/qframe/tst_qframe.cpp b/tests/auto/widgets/widgets/qframe/tst_qframe.cpp
index 432f4474c5..05f9cd2e4a 100644
--- a/tests/auto/widgets/widgets/qframe/tst_qframe.cpp
+++ b/tests/auto/widgets/widgets/qframe/tst_qframe.cpp
@@ -37,6 +37,10 @@
 class tst_QFrame : public QObject
 {
     Q_OBJECT
+
+public:
+    static void initMain() { QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling); }
+
 private slots:
     void testDefaults();
     void testInitStyleOption_data();
diff --git a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp
index 21c9f41646..76f8ebc804 100644
--- a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp
+++ b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp
@@ -49,6 +49,9 @@ class tst_QOpenGLWidget : public QObject
 {
     Q_OBJECT
 
+public:
+    static void initMain() { QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling); }
+
 private slots:
     void initTestCase();
     void create();
diff --git a/tests/manual/highdpi/highdpi.pro b/tests/manual/highdpi/highdpi.pro
index 9db083cd82..2de8ed3bb5 100644
--- a/tests/manual/highdpi/highdpi.pro
+++ b/tests/manual/highdpi/highdpi.pro
@@ -15,3 +15,4 @@ HEADERS += \
 RESOURCES += \
     highdpi.qrc
 
+DEFINES += HAVE_SCREEN_BASE_DPI
-- 
2.22.0.windows.1

