Merge lp:~dandrader/qtubuntu/logicalDpi into lp:qtubuntu

Proposed by Daniel d'Andrada
Status: Merged
Approved by: Gerry Boland
Approved revision: 386
Merged at revision: 390
Proposed branch: lp:~dandrader/qtubuntu/logicalDpi
Merge into: lp:qtubuntu
Diff against target: 137 lines (+40/-13)
2 files modified
src/ubuntumirclient/qmirclientscreen.cpp (+34/-11)
src/ubuntumirclient/qmirclientscreen.h (+6/-2)
To merge this branch: bzr merge lp:~dandrader/qtubuntu/logicalDpi
Reviewer Review Type Date Requested Status
Lukáš Tinkl (community) Approve
Gerry Boland (community) Approve
Unity8 CI Bot continuous-integration Approve
Review via email: mp+320940@code.launchpad.net

Commit message

Proper implementation of QPlatformScreen::logicalDpi

It's *not* the physical DPI.
It's just a value used for scaling point sized UI elements (mainly QWidget text)

You can view it as the value used to convert pt (point) to pixels

Description of the change

To test. Run kate or QtCreator without any arguments. Then run it with different GRID_UNIT_PX values.

A good reference is that when a QWidget-based application have the same grid unit value as unity8 itself, the text size in its buttons etc should be roughly the same as the size of the text in its window decorations.

To post a comment you must log in.
Revision history for this message
Lukáš Tinkl (lukas-kde) wrote :

if (mGridUnitPxEnv != 0) {
        mLogicalDpi.first = mGridUnitPxEnv * mGridUnitToLogicalDpiMultiplier;
        mLogicalDpi.second = mGridUnitPxEnv * mGridUnitToLogicalDpiMultiplier;
    } else {
        mLogicalDpi.first = mScale * mMirScaleToGridUnitMultiplier * mGridUnitToLogicalDpiMultiplier;
        mLogicalDpi.second = mScale * mMirScaleToGridUnitMultiplier * mGridUnitToLogicalDpiMultiplier;
    }

I think this could be simplified; if mScale is by default 1.0 and you'd initialize mGridUnitPxEnv to the default value of mMirScaleToGridUnitMultiplier (8.0), this could become one branch.

review: Needs Information
Revision history for this message
Lukáš Tinkl (lukas-kde) wrote :

And btw, looks like all other platform QPAs use roughly this code for logicalDpi():

458 QDpi QXcbScreen::virtualDpi() const
459 {
460 return QDpi(Q_MM_PER_INCH * m_virtualSize.width() / m_virtualSizeMillimeters.width(),
461 Q_MM_PER_INCH * m_virtualSize.height() / m_virtualSizeMillimeters.height());
462 }

https://code.woboq.org/qt5/qtbase/src/plugins/platforms/xcb/qxcbscreen.cpp.html#_ZNK10QXcbScreen10virtualDpiEv

Revision history for this message
Unity8 CI Bot (unity8-ci-bot) wrote :

PASSED: Continuous integration, rev:385
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/212/
Executed test runs:
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build/4683
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-0-fetch/4711
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/4534
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=xenial+overlay/4534/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/4534
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=amd64,release=zesty/4534/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/4534
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=xenial+overlay/4534/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/4534
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=armhf,release=zesty/4534/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/4534
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=xenial+overlay/4534/artifact/output/*zip*/output.zip
    SUCCESS: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/4534
        deb: https://unity8-jenkins.ubuntu.com/job/build-2-binpkg/arch=i386,release=zesty/4534/artifact/output/*zip*/output.zip

Click here to trigger a rebuild:
https://unity8-jenkins.ubuntu.com/job/lp-qtubuntu-ci/212/rebuild

review: Approve (continuous-integration)
Revision history for this message
Daniel d'Andrada (dandrader) wrote :

On 24/03/2017 12:24, Lukáš Tinkl wrote:
> Review: Needs Information
>
> if (mGridUnitPxEnv != 0) {
> mLogicalDpi.first = mGridUnitPxEnv * mGridUnitToLogicalDpiMultiplier;
> mLogicalDpi.second = mGridUnitPxEnv * mGridUnitToLogicalDpiMultiplier;
> } else {
> mLogicalDpi.first = mScale * mMirScaleToGridUnitMultiplier * mGridUnitToLogicalDpiMultiplier;
> mLogicalDpi.second = mScale * mMirScaleToGridUnitMultiplier * mGridUnitToLogicalDpiMultiplier;
> }
>
> I think this could be simplified; if mScale is by default 1.0 and you'd initialize mGridUnitPxEnv to the default value of mMirScaleToGridUnitMultiplier (8.0), this could become one branch.

Then I wouldn't know whether the environment variable GRID_UNIT_PX is
defined or not. This is important since the environment var has a higher
precedence than what the server says (through the scale info).
Specifying a GRID_UNIT_PX when launching an app is a way of overriding
the default behavior (which is getting the scale from the server).

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

On 24/03/2017 12:35, Lukáš Tinkl wrote:
> And btw, looks like all other platform QPAs use roughly this code for logicalDpi():
>
> 458 QDpi QXcbScreen::virtualDpi() const
> 459 {
> 460 return QDpi(Q_MM_PER_INCH * m_virtualSize.width() / m_virtualSizeMillimeters.width(),
> 461 Q_MM_PER_INCH * m_virtualSize.height() / m_virtualSizeMillimeters.height());
> 462 }
>
> https://code.woboq.org/qt5/qtbase/src/plugins/platforms/xcb/qxcbscreen.cpp.html#_ZNK10QXcbScreen10virtualDpiEv

Yes, I've seem it. logicalDpi() returning the physical DPI in xcb. Not
what we want.

Revision history for this message
Gerry Boland (gerboland) wrote :

TBH, I am not keen on introducing more dependency on the GRID_UNIT_PX env var, and this usage does not really match up with GRID_UNIT_PX really was intended for.

I also expect that this code will be removed when we implement QPlatformSCreen::pixelDensity(), as that does proper UI scaling of all components of the UI, not just fonts. So I wonder if introducing this as a "transition" to full UI scaling has any real value. Say this breaks fonts in some apps, then we land full UI scaling - will those fonts break again?

Also do we have any existing apps which use fonts with point sizes? Did you test this with them to ensure we don't break them (too badly)?

I do agree that this should be user adjustable, IMO it would be logical for Mir to have an api for this.

+const float QMirClientScreen::mGridUnitToLogicalDpiMultiplier = 14.0; // by experimentation
IMO should be 12, as on desktop 8*12=96 which is the typical value.

+ mLogicalDpi.first = 0;
+ mLogicalDpi.second = 0;
think unnecessary, as QPair claims to default construct the values.

Not a full review, want to ensure we're on the right track with this first.

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

On 27/03/2017 10:54, Gerry Boland wrote:
> Also do we have any existing apps which use fonts with point sizes? Did you test this with them to ensure we don't break them (too badly)?
What do you mean by "existing apps"? All existing QWidged-based apps
which are exactly the topic of this patch or do you mean some other
class of applications?

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

On 27/03/2017 10:54, Gerry Boland wrote:
> I also expect that this code will be removed when we implement QPlatformSCreen::pixelDensity(), as that does proper UI scaling of all components of the UI, not just fonts. So I wonder if introducing this as a "transition" to full UI scaling has any real value. Say this breaks fonts in some apps, then we land full UI scaling - will those fonts break again?

I don't think so. QPlatformSCreen::pixelDensity() is orthogonal to that. As I said, logicalDPI() is a conversion from point size to pixel (probably device independent ones). Those scaling factors act at pixel level, after the conversion from point size has been done.

That said, tested multiple values of QPlatformScreen::pixelDensity() and it had not impact whatsoever on QWidget apps (with or without this logicalDpi) patch. devicePixelRatio() seriously brake QWidget-based apps with or without this logicalDpi patch.

Revision history for this message
Gerry Boland (gerboland) wrote :

> On 27/03/2017 10:54, Gerry Boland wrote:
> > Also do we have any existing apps which use fonts with point sizes? Did you
> test this with them to ensure we don't break them (too badly)?
> What do you mean by "existing apps"? All existing QWidged-based apps
> which are exactly the topic of this patch or do you mean some other
> class of applications?

Well this impacts not just QWidget apps, it is anything Qt that draws fonts at point sizes. So in QML, people might be using Text & point sizes instead of Label (that is app bug though, should be using Label so I don't care about that case), and people can be using Canvas and drawing text.

OFC since the current code is wrong, us fixing this means the apps that we break need to be fixed too.

But realistically the battery usage image in System Settings is the only one I really care about. If we break that, we should fix it.

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

> But realistically the battery usage image in System Settings is the only one I
> really care about. If we break that, we should fix it.

Didn't spot any visual differences in this application with and without this patch.

Revision history for this message
Daniel d'Andrada (dandrader) wrote :

> But realistically the battery usage image in System Settings is the only one I
> really care about. If we break that, we should fix it.

Didn't spot any visual differences in this application with and without this patch.

Revision history for this message
Gerry Boland (gerboland) wrote :

> On 27/03/2017 10:54, Gerry Boland wrote:
> > I also expect that this code will be removed when we implement
> QPlatformSCreen::pixelDensity(), as that does proper UI scaling of all
> components of the UI, not just fonts. So I wonder if introducing this as a
> "transition" to full UI scaling has any real value. Say this breaks fonts in
> some apps, then we land full UI scaling - will those fonts break again?
>
> I don't think so. QPlatformSCreen::pixelDensity() is orthogonal to that. As I
> said, logicalDPI() is a conversion from point size to pixel (probably device
> independent ones). Those scaling factors act at pixel level, after the
> conversion from point size has been done.

pixelDensity is intended for full UI scaling. You are scaling fonts with this. Full UI scaling will also scale fonts, so I don't think they are orthogonal. And the Grid Unit concept is for scaling whole UIs, not just the fonts.

If you used a different env var, and made the default 96, I'd be happier, as the ability to scale fonts alone is still something we want.

But this is combining full UI scaling with just-font scaling, which is incorrect. They are 2 different scaling mechanisms.

> That said, tested multiple values of QPlatformScreen::pixelDensity() and it
> had not impact whatsoever on QWidget apps (with or without this logicalDpi)
> patch. devicePixelRatio() seriously brake QWidget-based apps with or without
> this logicalDpi patch.

Sadly you can't just set pixelDensity to 2 and test apps - it requires a bit more work in the QPA to make pixelDensity actually scale the UI (c.f. QHighDpi).

Note: DevicePixelRatio is not what we need any more, that is for platforms like iOS and OSX that (for backward compatibility) tell clients they are on low dpi screens, and add extra api for newer clients to get the 2x/3x multiplier and draw at higher detail. It was enough to get the UI to scale back in Qt5.4, but now pixelDensity is considered the proper solution for full UI scaling that we want.

lp:~dandrader/qtubuntu/logicalDpi updated
386. By Daniel d'Andrada

Forget about GRID_UNIT_PX

Revision history for this message
Gerry Boland (gerboland) wrote :

lgtm

review: Approve
Revision history for this message
Lukáš Tinkl (lukas-kde) wrote :

Tested as well, worked fine

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/ubuntumirclient/qmirclientscreen.cpp'
--- src/ubuntumirclient/qmirclientscreen.cpp 2017-02-07 15:37:20 +0000
+++ src/ubuntumirclient/qmirclientscreen.cpp 2017-03-28 12:14:55 +0000
@@ -1,6 +1,6 @@
1/****************************************************************************1/****************************************************************************
2**2**
3** Copyright (C) 2014-2016 Canonical, Ltd.3** Copyright (C) 2014-2017 Canonical, Ltd.
4** Contact: https://www.qt.io/licensing/4** Contact: https://www.qt.io/licensing/
5**5**
6** This file is part of the plugins of the Qt Toolkit.6** This file is part of the plugins of the Qt Toolkit.
@@ -56,8 +56,12 @@
5656
57#include <memory>57#include <memory>
5858
59#define ENV_LOGICAL_DPI "QT_LOGICAL_DPI"
60
59static const int overrideDevicePixelRatio = qgetenv("QT_DEVICE_PIXEL_RATIO").toInt();61static const int overrideDevicePixelRatio = qgetenv("QT_DEVICE_PIXEL_RATIO").toInt();
6062
63const float QMirClientScreen::mMirScaleToLogicalDpiMultiplier = 96.0; // by definition in qtmir
64
61static const char *orientationToStr(Qt::ScreenOrientation orientation) {65static const char *orientationToStr(Qt::ScreenOrientation orientation) {
62 switch (orientation) {66 switch (orientation) {
63 case Qt::PrimaryOrientation:67 case Qt::PrimaryOrientation:
@@ -82,12 +86,23 @@
82 : mDevicePixelRatio(1.0)86 : mDevicePixelRatio(1.0)
83 , mFormat(QImage::Format_RGB32)87 , mFormat(QImage::Format_RGB32)
84 , mDepth(32)88 , mDepth(32)
85 , mDpi{0}
86 , mFormFactor{mir_form_factor_unknown}89 , mFormFactor{mir_form_factor_unknown}
87 , mScale{1.0}90 , mScale{1.0}
88 , mOutputId(0)91 , mOutputId(0)
89 , mCursor(connection)92 , mCursor(connection)
90{93{
94
95 if (qEnvironmentVariableIsSet(ENV_LOGICAL_DPI)) {
96 QByteArray stringValue = qgetenv(ENV_LOGICAL_DPI);
97 bool ok;
98 float value = stringValue.toFloat(&ok);
99 if (ok && value > 0) {
100 mLogicalDpiEnv = value;
101 }
102 }
103
104 updateLogicalDpi();
105
91 setMirOutput(output);106 setMirOutput(output);
92}107}
93108
@@ -183,6 +198,7 @@
183198
184 // UI scale & DPR199 // UI scale & DPR
185 mScale = mir_output_get_scale_factor(output);200 mScale = mir_output_get_scale_factor(output);
201 updateLogicalDpi();
186 if (overrideDevicePixelRatio > 0) {202 if (overrideDevicePixelRatio > 0) {
187 mDevicePixelRatio = overrideDevicePixelRatio;203 mDevicePixelRatio = overrideDevicePixelRatio;
188 } else {204 } else {
@@ -234,16 +250,12 @@
234 }250 }
235}251}
236252
237void QMirClientScreen::setAdditionalMirDisplayProperties(float scale, MirFormFactor formFactor, int dpi)253void QMirClientScreen::setAdditionalMirDisplayProperties(float scale, MirFormFactor formFactor, int /*dpi*/)
238{254{
239 if (mDpi != dpi) {
240 mDpi = dpi;
241 QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen(), dpi, dpi);
242 }
243
244 auto nativeInterface = static_cast<QMirClientNativeInterface *>(qGuiApp->platformNativeInterface());255 auto nativeInterface = static_cast<QMirClientNativeInterface *>(qGuiApp->platformNativeInterface());
245 if (!qFuzzyCompare(mScale, scale)) {256 if (!qFuzzyCompare(mScale, scale)) {
246 mScale = scale;257 mScale = scale;
258 updateLogicalDpi();
247 nativeInterface->screenPropertyChanged(this, QStringLiteral("scale"));259 nativeInterface->screenPropertyChanged(this, QStringLiteral("scale"));
248 }260 }
249 if (mFormFactor != formFactor) {261 if (mFormFactor != formFactor) {
@@ -254,9 +266,20 @@
254266
255QDpi QMirClientScreen::logicalDpi() const267QDpi QMirClientScreen::logicalDpi() const
256{268{
257 if (mDpi > 0) {269 return mLogicalDpi;
258 return QDpi(mDpi, mDpi);270}
271
272void QMirClientScreen::updateLogicalDpi()
273{
274 auto oldDpi = mLogicalDpi;
275
276 if (mLogicalDpiEnv != 0) {
277 mLogicalDpi.first = mLogicalDpi.second = mLogicalDpiEnv;
259 } else {278 } else {
260 return QPlatformScreen::logicalDpi();279 mLogicalDpi.first = mLogicalDpi.second = mScale * mMirScaleToLogicalDpiMultiplier;
280 }
281
282 if (oldDpi.first != 0 && oldDpi.second != 0 && oldDpi != mLogicalDpi) {
283 QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen(), mLogicalDpi.first, mLogicalDpi.second);
261 }284 }
262}285}
263286
=== modified file 'src/ubuntumirclient/qmirclientscreen.h'
--- src/ubuntumirclient/qmirclientscreen.h 2017-02-07 15:37:20 +0000
+++ src/ubuntumirclient/qmirclientscreen.h 2017-03-28 12:14:55 +0000
@@ -1,6 +1,6 @@
1/****************************************************************************1/****************************************************************************
2**2**
3** Copyright (C) 2014-2016 Canonical, Ltd.3** Copyright (C) 2014-2017 Canonical, Ltd.
4** Contact: https://www.qt.io/licensing/4** Contact: https://www.qt.io/licensing/
5**5**
6** This file is part of the plugins of the Qt Toolkit.6** This file is part of the plugins of the Qt Toolkit.
@@ -85,6 +85,7 @@
8585
86private:86private:
87 void setMirOutput(const MirOutput *output);87 void setMirOutput(const MirOutput *output);
88 void updateLogicalDpi();
8889
89 QRect mGeometry, mNativeGeometry;90 QRect mGeometry, mNativeGeometry;
90 QSizeF mPhysicalSize;91 QSizeF mPhysicalSize;
@@ -93,12 +94,15 @@
93 Qt::ScreenOrientation mCurrentOrientation;94 Qt::ScreenOrientation mCurrentOrientation;
94 QImage::Format mFormat;95 QImage::Format mFormat;
95 int mDepth;96 int mDepth;
96 int mDpi;
97 qreal mRefreshRate;97 qreal mRefreshRate;
98 MirFormFactor mFormFactor;98 MirFormFactor mFormFactor;
99 float mScale;99 float mScale;
100 int mOutputId;100 int mOutputId;
101 QMirClientCursor mCursor;101 QMirClientCursor mCursor;
102 float mLogicalDpiEnv{0};
103 QDpi mLogicalDpi;
104
105 static const float mMirScaleToLogicalDpiMultiplier;
102106
103 friend class QMirClientNativeInterface;107 friend class QMirClientNativeInterface;
104};108};

Subscribers

People subscribed via source and target branches