Add high-DPI scale factor rounding policy C++ API
This API enables tuning of how Qt rounds fractional scale factors, and corresponds to the QT_SCALE_FACTOR_ROUNDING_POLICY environment variable New API: Qt::HighDPiScaleFactorRoundingPolicy QGuiApplication::setHighDpiScaleFactorRoundingPolicy() QGuiApplication::highDpiScaleFactorRoundingPolicy() Done-with: Friedemann Kleint <Friedemann.Kleint@qt.io> Task-number: QTBUG-53022 Change-Id: Ic360f26a173caa757e4ebde35ce08a6b74290b7d Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
This commit is contained in:
parent
1de8b01d2b
commit
f1e40dd6d6
@ -1754,6 +1754,15 @@ public:
|
|||||||
ChecksumItuV41
|
ChecksumItuV41
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class HighDpiScaleFactorRoundingPolicy {
|
||||||
|
Unset,
|
||||||
|
Round,
|
||||||
|
Ceil,
|
||||||
|
Floor,
|
||||||
|
RoundPreferFloor,
|
||||||
|
PassThrough
|
||||||
|
};
|
||||||
|
|
||||||
#ifndef Q_QDOC
|
#ifndef Q_QDOC
|
||||||
// NOTE: Generally, do not add QT_Q_ENUM if a corresponding Q_Q_FLAG exists.
|
// NOTE: Generally, do not add QT_Q_ENUM if a corresponding Q_Q_FLAG exists.
|
||||||
QT_Q_ENUM(ScrollBarPolicy)
|
QT_Q_ENUM(ScrollBarPolicy)
|
||||||
@ -1840,6 +1849,7 @@ public:
|
|||||||
QT_Q_ENUM(MouseEventSource)
|
QT_Q_ENUM(MouseEventSource)
|
||||||
QT_Q_FLAG(MouseEventFlag)
|
QT_Q_FLAG(MouseEventFlag)
|
||||||
QT_Q_ENUM(ChecksumType)
|
QT_Q_ENUM(ChecksumType)
|
||||||
|
QT_Q_ENUM(HighDpiScaleFactorRoundingPolicy)
|
||||||
QT_Q_ENUM(TabFocusBehavior)
|
QT_Q_ENUM(TabFocusBehavior)
|
||||||
#endif // Q_DOC
|
#endif // Q_DOC
|
||||||
|
|
||||||
|
@ -3275,3 +3275,25 @@
|
|||||||
|
|
||||||
\value ChecksumItuV41 Checksum calculation based on ITU-V.41.
|
\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.
|
||||||
|
*/
|
||||||
|
@ -146,6 +146,8 @@ QString QGuiApplicationPrivate::styleOverride;
|
|||||||
|
|
||||||
Qt::ApplicationState QGuiApplicationPrivate::applicationState = Qt::ApplicationInactive;
|
Qt::ApplicationState QGuiApplicationPrivate::applicationState = Qt::ApplicationInactive;
|
||||||
|
|
||||||
|
Qt::HighDpiScaleFactorRoundingPolicy QGuiApplicationPrivate::highDpiScaleFactorRoundingPolicy =
|
||||||
|
Qt::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor;
|
||||||
bool QGuiApplicationPrivate::highDpiScalingUpdated = false;
|
bool QGuiApplicationPrivate::highDpiScalingUpdated = false;
|
||||||
|
|
||||||
QPointer<QWindow> QGuiApplicationPrivate::currentDragWindow;
|
QPointer<QWindow> QGuiApplicationPrivate::currentDragWindow;
|
||||||
@ -687,6 +689,8 @@ QGuiApplication::~QGuiApplication()
|
|||||||
QGuiApplicationPrivate::lastCursorPosition = {qInf(), qInf()};
|
QGuiApplicationPrivate::lastCursorPosition = {qInf(), qInf()};
|
||||||
QGuiApplicationPrivate::currentMousePressWindow = QGuiApplicationPrivate::currentMouseWindow = nullptr;
|
QGuiApplicationPrivate::currentMousePressWindow = QGuiApplicationPrivate::currentMouseWindow = nullptr;
|
||||||
QGuiApplicationPrivate::applicationState = Qt::ApplicationInactive;
|
QGuiApplicationPrivate::applicationState = Qt::ApplicationInactive;
|
||||||
|
QGuiApplicationPrivate::highDpiScaleFactorRoundingPolicy =
|
||||||
|
Qt::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor;
|
||||||
QGuiApplicationPrivate::highDpiScalingUpdated = false;
|
QGuiApplicationPrivate::highDpiScalingUpdated = false;
|
||||||
QGuiApplicationPrivate::currentDragWindow = nullptr;
|
QGuiApplicationPrivate::currentDragWindow = nullptr;
|
||||||
QGuiApplicationPrivate::tabletDevicePoints.clear();
|
QGuiApplicationPrivate::tabletDevicePoints.clear();
|
||||||
@ -3490,6 +3494,46 @@ Qt::ApplicationState QGuiApplication::applicationState()
|
|||||||
return QGuiApplicationPrivate::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
|
\since 5.2
|
||||||
\fn void QGuiApplication::applicationStateChanged(Qt::ApplicationState state)
|
\fn void QGuiApplication::applicationStateChanged(Qt::ApplicationState state)
|
||||||
|
@ -156,6 +156,9 @@ public:
|
|||||||
|
|
||||||
static Qt::ApplicationState applicationState();
|
static Qt::ApplicationState applicationState();
|
||||||
|
|
||||||
|
static void setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy policy);
|
||||||
|
static Qt::HighDpiScaleFactorRoundingPolicy highDpiScaleFactorRoundingPolicy();
|
||||||
|
|
||||||
static int exec();
|
static int exec();
|
||||||
bool notify(QObject *, QEvent *) override;
|
bool notify(QObject *, QEvent *) override;
|
||||||
|
|
||||||
|
@ -223,6 +223,7 @@ public:
|
|||||||
static QWindow *currentMouseWindow;
|
static QWindow *currentMouseWindow;
|
||||||
static QWindow *currentMousePressWindow;
|
static QWindow *currentMousePressWindow;
|
||||||
static Qt::ApplicationState applicationState;
|
static Qt::ApplicationState applicationState;
|
||||||
|
static Qt::HighDpiScaleFactorRoundingPolicy highDpiScaleFactorRoundingPolicy;
|
||||||
static bool highDpiScalingUpdated;
|
static bool highDpiScalingUpdated;
|
||||||
static QPointer<QWindow> currentDragWindow;
|
static QPointer<QWindow> currentDragWindow;
|
||||||
|
|
||||||
|
@ -331,24 +331,24 @@ static QByteArray joinEnumValues(const EnumLookup<EnumType> *i1, const EnumLooku
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
using ScaleFactorRoundingPolicyLookup = EnumLookup<QHighDpiScaling::HighDpiScaleFactorRoundingPolicy>;
|
using ScaleFactorRoundingPolicyLookup = EnumLookup<Qt::HighDpiScaleFactorRoundingPolicy>;
|
||||||
|
|
||||||
static const ScaleFactorRoundingPolicyLookup scaleFactorRoundingPolicyLookup[] =
|
static const ScaleFactorRoundingPolicyLookup scaleFactorRoundingPolicyLookup[] =
|
||||||
{
|
{
|
||||||
{"Round", QHighDpiScaling::HighDpiScaleFactorRoundingPolicy::Round},
|
{"Round", Qt::HighDpiScaleFactorRoundingPolicy::Round},
|
||||||
{"Ceil", QHighDpiScaling::HighDpiScaleFactorRoundingPolicy::Ceil},
|
{"Ceil", Qt::HighDpiScaleFactorRoundingPolicy::Ceil},
|
||||||
{"Floor", QHighDpiScaling::HighDpiScaleFactorRoundingPolicy::Floor},
|
{"Floor", Qt::HighDpiScaleFactorRoundingPolicy::Floor},
|
||||||
{"RoundPreferFloor", QHighDpiScaling::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor},
|
{"RoundPreferFloor", Qt::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor},
|
||||||
{"PassThrough", QHighDpiScaling::HighDpiScaleFactorRoundingPolicy::PassThrough}
|
{"PassThrough", Qt::HighDpiScaleFactorRoundingPolicy::PassThrough}
|
||||||
};
|
};
|
||||||
|
|
||||||
static QHighDpiScaling::HighDpiScaleFactorRoundingPolicy
|
static Qt::HighDpiScaleFactorRoundingPolicy
|
||||||
lookupScaleFactorRoundingPolicy(const QByteArray &v)
|
lookupScaleFactorRoundingPolicy(const QByteArray &v)
|
||||||
{
|
{
|
||||||
auto end = std::end(scaleFactorRoundingPolicyLookup);
|
auto end = std::end(scaleFactorRoundingPolicyLookup);
|
||||||
auto it = std::find(std::begin(scaleFactorRoundingPolicyLookup), end,
|
auto it = std::find(std::begin(scaleFactorRoundingPolicyLookup), end,
|
||||||
ScaleFactorRoundingPolicyLookup{v.constData(), QHighDpiScaling::HighDpiScaleFactorRoundingPolicy::Unset});
|
ScaleFactorRoundingPolicyLookup{v.constData(), Qt::HighDpiScaleFactorRoundingPolicy::Unset});
|
||||||
return it != end ? it->value : QHighDpiScaling::HighDpiScaleFactorRoundingPolicy::Unset;
|
return it != end ? it->value : Qt::HighDpiScaleFactorRoundingPolicy::Unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
using DpiAdjustmentPolicyLookup = EnumLookup<QHighDpiScaling::DpiAdjustmentPolicy>;
|
using DpiAdjustmentPolicyLookup = EnumLookup<QHighDpiScaling::DpiAdjustmentPolicy>;
|
||||||
@ -377,15 +377,15 @@ qreal QHighDpiScaling::roundScaleFactor(qreal rawFactor)
|
|||||||
// sizes that are smaller than the ideal size, and opposite for rounding up.
|
// 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
|
// Rounding down is then preferable since "small UI" is a more acceptable
|
||||||
// high-DPI experience than "large UI".
|
// high-DPI experience than "large UI".
|
||||||
static auto scaleFactorRoundingPolicy = HighDpiScaleFactorRoundingPolicy::Unset;
|
static auto scaleFactorRoundingPolicy = Qt::HighDpiScaleFactorRoundingPolicy::Unset;
|
||||||
|
|
||||||
// Determine rounding policy
|
// Determine rounding policy
|
||||||
if (scaleFactorRoundingPolicy == HighDpiScaleFactorRoundingPolicy::Unset) {
|
if (scaleFactorRoundingPolicy == Qt::HighDpiScaleFactorRoundingPolicy::Unset) {
|
||||||
// Check environment
|
// Check environment
|
||||||
if (qEnvironmentVariableIsSet(scaleFactorRoundingPolicyEnvVar)) {
|
if (qEnvironmentVariableIsSet(scaleFactorRoundingPolicyEnvVar)) {
|
||||||
QByteArray policyText = qgetenv(scaleFactorRoundingPolicyEnvVar);
|
QByteArray policyText = qgetenv(scaleFactorRoundingPolicyEnvVar);
|
||||||
auto policyEnumValue = lookupScaleFactorRoundingPolicy(policyText);
|
auto policyEnumValue = lookupScaleFactorRoundingPolicy(policyText);
|
||||||
if (policyEnumValue != HighDpiScaleFactorRoundingPolicy::Unset) {
|
if (policyEnumValue != Qt::HighDpiScaleFactorRoundingPolicy::Unset) {
|
||||||
scaleFactorRoundingPolicy = policyEnumValue;
|
scaleFactorRoundingPolicy = policyEnumValue;
|
||||||
} else {
|
} else {
|
||||||
auto values = joinEnumValues(std::begin(scaleFactorRoundingPolicyLookup),
|
auto values = joinEnumValues(std::begin(scaleFactorRoundingPolicyLookup),
|
||||||
@ -393,38 +393,43 @@ qreal QHighDpiScaling::roundScaleFactor(qreal rawFactor)
|
|||||||
qWarning("Unknown scale factor rounding policy: %s. Supported values are: %s.",
|
qWarning("Unknown scale factor rounding policy: %s. Supported values are: %s.",
|
||||||
policyText.constData(), values.constData());
|
policyText.constData(), values.constData());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check application object if no environment value was set.
|
||||||
|
if (scaleFactorRoundingPolicy == Qt::HighDpiScaleFactorRoundingPolicy::Unset) {
|
||||||
|
scaleFactorRoundingPolicy = QGuiApplication::highDpiScaleFactorRoundingPolicy();
|
||||||
} else {
|
} else {
|
||||||
// Set default policy if no environment variable is set.
|
// Make application setting reflect environment
|
||||||
scaleFactorRoundingPolicy = HighDpiScaleFactorRoundingPolicy::RoundPreferFloor;
|
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(scaleFactorRoundingPolicy);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply rounding policy.
|
// Apply rounding policy.
|
||||||
qreal roundedFactor = rawFactor;
|
qreal roundedFactor = rawFactor;
|
||||||
switch (scaleFactorRoundingPolicy) {
|
switch (scaleFactorRoundingPolicy) {
|
||||||
case HighDpiScaleFactorRoundingPolicy::Round:
|
case Qt::HighDpiScaleFactorRoundingPolicy::Round:
|
||||||
roundedFactor = qRound(rawFactor);
|
roundedFactor = qRound(rawFactor);
|
||||||
break;
|
break;
|
||||||
case HighDpiScaleFactorRoundingPolicy::Ceil:
|
case Qt::HighDpiScaleFactorRoundingPolicy::Ceil:
|
||||||
roundedFactor = qCeil(rawFactor);
|
roundedFactor = qCeil(rawFactor);
|
||||||
break;
|
break;
|
||||||
case HighDpiScaleFactorRoundingPolicy::Floor:
|
case Qt::HighDpiScaleFactorRoundingPolicy::Floor:
|
||||||
roundedFactor = qFloor(rawFactor);
|
roundedFactor = qFloor(rawFactor);
|
||||||
break;
|
break;
|
||||||
case HighDpiScaleFactorRoundingPolicy::RoundPreferFloor:
|
case Qt::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor:
|
||||||
// Round up for .75 and higher. This favors "small UI" over "large UI".
|
// Round up for .75 and higher. This favors "small UI" over "large UI".
|
||||||
roundedFactor = rawFactor - qFloor(rawFactor) < 0.75
|
roundedFactor = rawFactor - qFloor(rawFactor) < 0.75
|
||||||
? qFloor(rawFactor) : qCeil(rawFactor);
|
? qFloor(rawFactor) : qCeil(rawFactor);
|
||||||
break;
|
break;
|
||||||
case HighDpiScaleFactorRoundingPolicy::PassThrough:
|
case Qt::HighDpiScaleFactorRoundingPolicy::PassThrough:
|
||||||
case HighDpiScaleFactorRoundingPolicy::Unset:
|
case Qt::HighDpiScaleFactorRoundingPolicy::Unset:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't round down to to zero; clamp the minimum (rounded) factor to 1.
|
// 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
|
// This is not a common case but can happen if a display reports a very
|
||||||
// low DPI.
|
// low DPI.
|
||||||
if (scaleFactorRoundingPolicy != HighDpiScaleFactorRoundingPolicy::PassThrough)
|
if (scaleFactorRoundingPolicy != Qt::HighDpiScaleFactorRoundingPolicy::PassThrough)
|
||||||
roundedFactor = qMax(roundedFactor, qreal(1));
|
roundedFactor = qMax(roundedFactor, qreal(1));
|
||||||
|
|
||||||
return roundedFactor;
|
return roundedFactor;
|
||||||
|
@ -74,16 +74,6 @@ typedef QPair<qreal, qreal> QDpi;
|
|||||||
class Q_GUI_EXPORT QHighDpiScaling {
|
class Q_GUI_EXPORT QHighDpiScaling {
|
||||||
Q_GADGET
|
Q_GADGET
|
||||||
public:
|
public:
|
||||||
enum class HighDpiScaleFactorRoundingPolicy {
|
|
||||||
Unset,
|
|
||||||
Round,
|
|
||||||
Ceil,
|
|
||||||
Floor,
|
|
||||||
RoundPreferFloor,
|
|
||||||
PassThrough
|
|
||||||
};
|
|
||||||
Q_ENUM(HighDpiScaleFactorRoundingPolicy)
|
|
||||||
|
|
||||||
enum class DpiAdjustmentPolicy {
|
enum class DpiAdjustmentPolicy {
|
||||||
Unset,
|
Unset,
|
||||||
Enabled,
|
Enabled,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user