summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/kernel/qguiapplication.cpp3
-rw-r--r--src/gui/kernel/qhighdpiscaling.cpp80
-rw-r--r--src/gui/kernel/qhighdpiscaling_p.h12
-rw-r--r--src/gui/kernel/qplatformscreen.cpp18
-rw-r--r--src/gui/kernel/qwindow.cpp16
-rw-r--r--src/plugins/platforms/android/androidjnimain.cpp2
-rw-r--r--tests/manual/highdpi/highdpi.pro3
-rw-r--r--tests/manual/highdpi/main.cpp127
8 files changed, 153 insertions, 108 deletions
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 8e4290b8e8..fe0bbbc15a 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -1118,6 +1118,9 @@ void QGuiApplicationPrivate::createPlatformIntegration()
// this flag.
QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuBar, true);
+
+ QHighDpiScaling::initHighDPiScaling();
+
// Load the platform integration
QString platformPluginPath = QLatin1String(qgetenv("QT_QPA_PLATFORM_PLUGIN_PATH"));
diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp
index 54d06a8572..a1387f781b 100644
--- a/src/gui/kernel/qhighdpiscaling.cpp
+++ b/src/gui/kernel/qhighdpiscaling.cpp
@@ -43,6 +43,7 @@
#include "qwindow_p.h" // for QWINDOWSIZE_MAX
#include "qguiapplication.h"
#include "qscreen.h"
+#include "qplatformintegration.h"
#include "private/qscreen_p.h"
#include <QtCore/qdebug.h>
@@ -68,7 +69,7 @@ static inline qreal initialScaleFactor()
/*!
\class QHighDpiScaling
- \since 5.4
+ \since 5.6
\internal
\preliminary
\ingroup qpa
@@ -76,12 +77,26 @@ static inline qreal initialScaleFactor()
\brief Collection of utility functions for UI scaling.
*/
-qreal QHighDpiScaling::m_factor = initialScaleFactor();
-bool QHighDpiScaling::m_autoFactor = qgetenv("QT_SCALE_FACTOR").toLower() == "auto";
-bool QHighDpiScaling::m_active = m_autoFactor || !qFuzzyCompare(QHighDpiScaling::m_factor, qreal(1));
-bool QHighDpiScaling::m_perWindowActive = false;
-void QHighDpiScaling::setFactor(qreal factor)
+qreal QHighDpiScaling::m_factor;
+
+bool QHighDpiScaling::m_active; //"overall active" - is there any scale factor set.
+bool QHighDpiScaling::m_perScreenActive;
+
+void QHighDpiScaling::initHighDPiScaling()
+{
+ QHighDpiScaling::m_factor = initialScaleFactor();
+ bool usePlatformPluginPixelDensity = qEnvironmentVariableIsSet("QT_AUTO_SCREEN_SCALE_FACTOR");
+
+ // m_active below is "overall active" - is there any scale factor set.
+ QHighDpiScaling::m_active = !qFuzzyCompare(m_factor, qreal(1)) || usePlatformPluginPixelDensity;
+ QHighDpiScaling::m_perScreenActive = usePlatformPluginPixelDensity;
+}
+
+/*
+ Sets the global scale factor which is applied to all windows.
+*/
+void QHighDpiScaling::setGlobalFactor(qreal factor)
{
if (qFuzzyCompare(factor, QHighDpiScaling::m_factor))
return;
@@ -97,14 +112,16 @@ void QHighDpiScaling::setFactor(qreal factor)
static const char *scaleFactorProperty = "_q_scaleFactor";
-void QHighDpiScaling::setWindowFactor(QWindow *window, qreal factor)
+/*
+ Sets a per-screen scale factor.
+*/
+void QHighDpiScaling::setScreenFactor(QScreen *screen, qreal factor)
{
m_active = true;
- m_perWindowActive = true;
- window->setProperty(scaleFactorProperty, QVariant(factor));
+ m_perScreenActive = true;
+ screen->setProperty(scaleFactorProperty, QVariant(factor));
}
-
/*
QPoint QXcbScreen::mapToNative(const QPoint &pos) const
@@ -141,31 +158,46 @@ QPoint QHighDpiScaling::mapPositionFromNative(const QPoint &pos, const QPlatform
return (pos - topLeft) / scaleFactor + topLeft;
}
+qreal QHighDpiScaling::screenSubfactor(const QPlatformScreen *screen)
+{
+ qreal factor = qreal(1.0);
+ if (m_perScreenActive && screen) {
+ factor *= screen->pixelDensity();
+ QVariant screenFactor = screen->screen()->property(scaleFactorProperty);
+ if (screenFactor.isValid())
+ factor *= screenFactor.toReal();
+ }
+ return factor;
+}
qreal QHighDpiScaling::factor(const QScreen *screen)
{
- if (m_autoFactor && screen && screen->handle())
- return screen->handle()->pixelDensity();
- return m_factor;
+ // Fast path for when scaling in Qt is not used at all.
+ if (!m_active)
+ return qreal(1.0);
+
+ // The effective factor for a given screen is the product of the
+ // screen and global sub-factors
+ qreal factor = m_factor;
+ if (screen)
+ factor *= screenSubfactor(screen->handle());
+ return factor;
}
qreal QHighDpiScaling::factor(const QPlatformScreen *platformScreen)
{
- if (m_autoFactor && platformScreen)
- return platformScreen->pixelDensity();
- return m_factor;
+ if (!m_active)
+ return qreal(1.0);
+
+ return m_factor * screenSubfactor(platformScreen);
}
qreal QHighDpiScaling::factor(const QWindow *window)
{
- qreal f = m_factor;
- if (m_autoFactor && window && window->screen() && window->screen()->handle())
- f = window->screen()->handle()->pixelDensity();
- if (!m_perWindowActive || window == 0)
- return f;
-
- QVariant windowFactor = window->property(scaleFactorProperty);
- return f * (windowFactor.isValid() ? windowFactor.toReal() : 1);
+ if (!m_active || !window)
+ return qreal(1.0);
+
+ return factor(window->screen());
}
QPoint QHighDpiScaling::origin(const QScreen *screen)
diff --git a/src/gui/kernel/qhighdpiscaling_p.h b/src/gui/kernel/qhighdpiscaling_p.h
index 2350ca6fdb..a5d4c40a07 100644
--- a/src/gui/kernel/qhighdpiscaling_p.h
+++ b/src/gui/kernel/qhighdpiscaling_p.h
@@ -83,6 +83,10 @@ class QPlatformScreen;
class Q_GUI_EXPORT QHighDpiScaling {
public:
+ static void initHighDPiScaling();
+ static void setGlobalFactor(qreal factor);
+ static void setScreenFactor(QScreen *window, qreal factor);
+
static bool isActive() { return m_active; }
static qreal factor(const QWindow *window);
static qreal factor(const QScreen *screen);
@@ -91,13 +95,12 @@ public:
static QPoint origin(const QPlatformScreen *platformScreen);
static QPoint mapPositionFromNative(const QPoint &pos, const QPlatformScreen *platformScreen);
static QPoint mapPositionToNative(const QPoint &pos, const QPlatformScreen *platformScreen);
- static void setFactor(qreal factor);
- static void setWindowFactor(QWindow *window, qreal factor);
private:
+ static qreal screenSubfactor(const QPlatformScreen *screen);
+
static qreal m_factor;
- static bool m_autoFactor;
static bool m_active;
- static bool m_perWindowActive;
+ static bool m_perScreenActive;
};
// Coordinate system conversion functions:
@@ -157,7 +160,6 @@ inline QRect toNative(const QRect &rect, qreal scaleFactor, const QPoint &origin
}
-
inline QRect fromNative(const QRect &rect, const QScreen *screen, const QPoint &screenOrigin)
{
return toNative(rect, QHighDpiScaling::factor(screen), screenOrigin);
diff --git a/src/gui/kernel/qplatformscreen.cpp b/src/gui/kernel/qplatformscreen.cpp
index bda7280e81..ccb0452629 100644
--- a/src/gui/kernel/qplatformscreen.cpp
+++ b/src/gui/kernel/qplatformscreen.cpp
@@ -159,9 +159,11 @@ QDpi QPlatformScreen::logicalDpi() const
/*!
Reimplement this function in subclass to return the device pixel ratio
for the screen. This is the ratio between physical pixels and the
- device-independent pixels of the windowing system.
+ device-independent pixels of the windowing system. The default
+ implementation returns 1.0.
- \sa QPlatformWindow::devicePixelRatio();
+ \sa QPlatformWindow::devicePixelRatio()
+ \sa QPlatformScreen::pixelDensity()
*/
qreal QPlatformScreen::devicePixelRatio() const
{
@@ -171,7 +173,17 @@ qreal QPlatformScreen::devicePixelRatio() const
/*!
Reimplement this function in subclass to return the pixel density of the
screen. This is the scale factor needed to make a low-dpi application
- usable on this screen. The default implementation returns 1.0.
+ usable on this screen. The default implementation returns 1.0. In
+ addition the platform integration must return true for the PlatformScreenPixelDensity
+ Capability for this value to have an effect.
+
+ Returning something else than 1 from this function causes Qt to
+ apply the scale factor to the application's coordinate system.
+ This is different from devicePixelRatio, which reports a scale
+ factor already applied by the windowing system. A platform plugin
+ typically implements one (or none) of these two functions.
+
+ \sa QPlatformWindow::devicePixelRatio()
*/
qreal QPlatformScreen::pixelDensity() const
{
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index d84035e29c..4465a9aeb4 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -1086,17 +1086,13 @@ qreal QWindow::devicePixelRatio() const
{
Q_D(const QWindow);
- // Get the platform scale factor. If there is no platform window
- // use the app global devicePixelRatio, which is the the highest
- // devicePixelRatio found on the system screens, and will be
- // correct for single-display systems (a very common case).
- qreal ratio = d->platformWindow ? d->platformWindow->devicePixelRatio()
- : qApp->devicePixelRatio();
-
- //
- ratio *= QHighDpiScaling::factor(this);
+ // If there is no platform window use the app global devicePixelRatio,
+ // which is the the highest devicePixelRatio found on the system
+ // screens, and will be correct for single-display systems (a very common case).
+ if (!d->platformWindow)
+ return qApp->devicePixelRatio();
- return ratio;
+ return d->platformWindow->devicePixelRatio() * QHighDpiScaling::factor(this);
}
/*!
diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp
index cf9a96b993..184fc58cf0 100644
--- a/src/plugins/platforms/android/androidjnimain.cpp
+++ b/src/plugins/platforms/android/androidjnimain.cpp
@@ -574,7 +574,7 @@ static void setDisplayMetrics(JNIEnv */*env*/, jclass /*clazz*/,
m_density = density;
if (m_highDpiScalingEnabled)
- QHighDpiScaling::setFactor(density);
+ QHighDpiScaling::setGlobalFactor(density);
if (!m_androidPlatformIntegration) {
QAndroidPlatformIntegration::setDefaultDisplayMetrics(desktopWidthPixels,
diff --git a/tests/manual/highdpi/highdpi.pro b/tests/manual/highdpi/highdpi.pro
index f6d49033ce..842d98f110 100644
--- a/tests/manual/highdpi/highdpi.pro
+++ b/tests/manual/highdpi/highdpi.pro
@@ -2,8 +2,9 @@ TEMPLATE = app
TARGET = highdpi
INCLUDEPATH += .
QT += widgets gui-private
-CONFIG+=console
+CONFIG +=console
CONFIG -= app_bundle
+CONFIG += c++11
# Input
SOURCES += main.cpp
diff --git a/tests/manual/highdpi/main.cpp b/tests/manual/highdpi/main.cpp
index b6305ba1d4..fb5ff33232 100644
--- a/tests/manual/highdpi/main.cpp
+++ b/tests/manual/highdpi/main.cpp
@@ -56,69 +56,64 @@
#include <QDebug>
#include <private/qhighdpiscaling_p.h>
-class ScaleFactorSetter : public QWidget
+class ScreenScaleFactorSetter : public QWidget
{
Q_OBJECT
public:
- ScaleFactorSetter();
- QLabel *label;
- QSlider *slider;
- QLabel *scaleFactorLabel;
- QHBoxLayout *layout;
-private Q_SLOTS:
- void scaleFactorChanged(int scaleFactor);
+ ScreenScaleFactorSetter();
};
-// Shows a slider which sets the scale factor for all windows.
-ScaleFactorSetter::ScaleFactorSetter()
+ScreenScaleFactorSetter::ScreenScaleFactorSetter()
{
- label = new QLabel("Scale Factor");
- slider = new QSlider();
- slider->setOrientation(Qt::Horizontal);
- slider->setMinimum(1);
- slider->setMaximum(40);
- slider->setValue(10);
- slider->setTracking(true);
- slider->setTickInterval(5);
- slider->setTickPosition(QSlider::TicksBelow);
- scaleFactorLabel = new QLabel("1.0");
-
- layout = new QHBoxLayout();
- layout->addWidget(label);
- layout->addWidget(slider);
- layout->addWidget(scaleFactorLabel);
- setLayout(layout);
+ setWindowTitle("screen scale factors");
+ setObjectName("controller"); // make WindowScaleFactorSetter skip this window
- connect(slider, SIGNAL(valueChanged(int)), this, SLOT(scaleFactorChanged(int)));
-}
+ QVBoxLayout *layout = new QVBoxLayout;
+ setLayout(layout);
-void ScaleFactorSetter::scaleFactorChanged(int scaleFactor)
-{
- // slider value is scale factor times ten;
- qreal scalefactorF = qreal(scaleFactor) / 10.0;
-
- // update label, add ".0" if needed.
- QString number = QString::number(scalefactorF);
- if (!number.contains("."))
- number.append(".0");
- scaleFactorLabel->setText(number);
-
- // set scale factor on all top-level windows
- QWindowList windows = QGuiApplication::topLevelWindows();
- foreach (QWindow *window, windows) {
-
- // skip this controller window
- if (window == this->windowHandle())
- continue;
-
- qDebug() << "set scale factor on" << window;
- qreal oldFactor = QHighDpiScaling::factor(window);
- QHighDpiScaling::setWindowFactor(window, scalefactorF);
- qreal newFactor = QHighDpiScaling::factor(window);
- qDebug() << "factor was / is" << oldFactor << newFactor;
-
- // resize window to keep showing the same amount of content.
- window->resize(window->size() / oldFactor * newFactor);
+ // set up one scale control line per screen
+ QList<QScreen *> screens = QGuiApplication::screens();
+ foreach (QScreen *screen, screens) {
+ // create scale control line
+ QHBoxLayout *row = new QHBoxLayout;
+ QSize screenSize = screen->geometry().size();
+ QString screenId = screen->name() + " " + QString::number(screenSize.width())
+ + " " + QString::number(screenSize.height());
+ QLabel *label = new QLabel(screenId);
+ QSlider *slider = new QSlider();
+ slider->setOrientation(Qt::Horizontal);
+ slider->setMinimum(1);
+ slider->setMaximum(40);
+ slider->setValue(10);
+ slider->setTracking(true);
+ slider->setTickInterval(5);
+ slider->setTickPosition(QSlider::TicksBelow);
+ QLabel *scaleFactorLabel = new QLabel("1.0");
+
+ // set up layouts
+ row->addWidget(label);
+ row->addWidget(slider);
+ row->addWidget(scaleFactorLabel);
+ layout->addLayout(row);
+
+ // handle slider value change
+ connect(slider, &QSlider::valueChanged, [scaleFactorLabel, screen](int scaleFactor){
+ // slider value is scale factor times ten;
+ qreal scalefactorF = qreal(scaleFactor) / 10.0;
+
+ // update label, add ".0" if needed.
+ QString number = QString::number(scalefactorF);
+ if (!number.contains("."))
+ number.append(".0");
+ scaleFactorLabel->setText(number);
+
+ // set scale factor for screen
+ qreal oldFactor = QHighDpiScaling::factor(screen);
+ QHighDpiScaling::setScreenFactor(screen, scalefactorF);
+ qreal newFactor = QHighDpiScaling::factor(screen);
+
+ qDebug() << "factor was / is" << oldFactor << newFactor;
+ });
}
}
@@ -272,7 +267,7 @@ public:
int dy = 50;
int maxX = 500;
- for (int iconIndex = QStyle::SP_TitleBarMenuButton; iconIndex < QStyle::SP_MediaVolumeMuted; ++iconIndex) {
+ for (uint iconIndex = QStyle::SP_TitleBarMenuButton; iconIndex < QStyle::SP_MediaVolumeMuted; ++iconIndex) {
QIcon icon = qApp->style()->standardIcon(QStyle::StandardPixmap(iconIndex));
QPainter p(this);
p.drawPixmap(x, y, icon.pixmap(dx - 5, dy - 5));
@@ -607,11 +602,15 @@ int main(int argc, char **argv)
QCoreApplication::setApplicationVersion(QT_VERSION_STR);
QCommandLineParser parser;
- parser.setApplicationDescription("High DPI tester");
+ parser.setApplicationDescription("High DPI tester. Pass one or more of the options to\n"
+ "test various high-dpi aspects. \n"
+ "--sceen-scale-factor is a special option and opens a configuration"
+ " window for setting window and screen scale factors.");
parser.addHelpOption();
parser.addVersionOption();
- QCommandLineOption scaleFactorOption("window-scale-factor", "Show Scale Factor Slider");
- parser.addOption(scaleFactorOption);
+ QCommandLineOption screenScaleFactorOption("screen-scale-factor", "Show screen scale factor setter.");
+ parser.addOption(screenScaleFactorOption);
+
QCommandLineOption pixmapPainterOption("pixmap", "Test pixmap painter");
parser.addOption(pixmapPainterOption);
QCommandLineOption labelOption("label", "Test Labels");
@@ -633,13 +632,13 @@ int main(int argc, char **argv)
QCommandLineOption linePainterOption("linepainter", "Test line painting");
parser.addOption(linePainterOption);
-
parser.process(app);
- QScopedPointer<ScaleFactorSetter> scaleFactorSetter;
- if (parser.isSet(scaleFactorOption)) {
- scaleFactorSetter.reset(new ScaleFactorSetter);
- scaleFactorSetter->show();
+ // special screen scale factor controller
+ QScopedPointer<ScreenScaleFactorSetter> screeScaleFactorSetter;
+ if (parser.isSet(screenScaleFactorOption)) {
+ screeScaleFactorSetter.reset(new ScreenScaleFactorSetter);
+ screeScaleFactorSetter->show();
}
QScopedPointer<PixmapPainter> pixmapPainter;