[5.14.1] UI adjustments

* OS native check of screen resolution (Qt free, experimental)
* changed rounding
* use string for scale factor so we can use fractions as 2/3
* utility functions to clean numbers, parse fractions

It looks like:

* my WIN10 scaling is 250%
* obviously swift rounds that to 3 (device ratio)
* now using FLOOR policy down-rounding to 2
* rational: scaling up (scale factor) is better as down-scaling as the factors would be clearer
* 2->3 1.5, but 3->2 means 0.66667
This commit is contained in:
Klaus Basan
2020-02-08 00:13:54 +01:00
committed by Mat Sutcliffe
parent 52de67a72f
commit 8f4c4a249c
13 changed files with 232 additions and 23 deletions

View File

@@ -25,6 +25,9 @@ else {
QMAKE_CXXFLAGS += -idirafter $$EXTERNALSROOT/common/include/qwt
}
# needed for "ShellScalingApi.h" only
# win32 { LIBS *= -lSHCore }
DEPENDPATH += . ..
PRECOMPILED_HEADER = pch/pch.h

View File

@@ -66,6 +66,7 @@
#include <QMessageBox>
#include <QtGlobal>
#include <QWhatsThis>
#include <Qt>
using namespace BlackConfig;
using namespace BlackMisc;
@@ -351,21 +352,27 @@ namespace BlackGui
CApplication::exit(retcode);
}
void CGuiApplication::highDpiScreenSupport(double scaleFactor)
void CGuiApplication::highDpiScreenSupport(const QString &scaleFactor)
{
// https://lists.qt-project.org/pipermail/development/2019-September/037434.html
if (scaleFactor < 0)
// QSize s = CGuiUtility::physicalScreenSizeOs();
QString sf = scaleFactor.trimmed().isEmpty() ? defaultScaleFactorString() : scaleFactor;
if (sf.contains('/'))
{
// qputenv("QT_AUTO_SCREEN_SCALE_FACTOR", "1"); // until 5.14
qputenv("QT_ENABLE_HIGHDPI_SCALING", "1");
}
else
{
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // DPI support
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); // HiDPI pixmaps
const QString sf = QString::number(scaleFactor, 'f', 2);
qputenv("QT_SCALE_FACTOR", sf.toLatin1());
const double sfd = parseFraction(scaleFactor, -1);
sf = sfd < 0 ? "1.0" : QString::number(sfd, 'f', 8);
}
sf = cleanNumber(sf);
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // DPI support
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); // HiDPI pixmaps
// qputenv("QT_ENABLE_HIGHDPI_SCALING", "1");
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Floor);
const QByteArray sfa = sf.toLatin1();
qputenv("QT_SCALE_FACTOR", sfa);
}
bool CGuiApplication::isUsingHighDpiScreenSupport()
@@ -375,7 +382,7 @@ namespace BlackGui
QScreen *CGuiApplication::currentScreen()
{
QWidget *w = CGuiApplication::mainApplicationWidget();
const QWidget *w = CGuiApplication::mainApplicationWidget();
const int s = QApplication::desktop()->screenNumber(w);
if (s < QGuiApplication::screens().size()) { return QGuiApplication::screens()[s]; }
return QGuiApplication::primaryScreen();
@@ -552,6 +559,37 @@ namespace BlackGui
return -1.0;
}
QString CGuiApplication::scaleFactor(int argc, char *argv[])
{
for (int i = 1; i < argc; ++i)
{
if (qstrcmp(argv[i], "--scale") == 0 || qstrcmp(argv[i], "-scale") == 0)
{
if (i + 1 >= argc) { return QString(); } // no value
const QString factor(argv[i + 1]);
return factor.trimmed();
}
}
return QString();
}
QString CGuiApplication::defaultScaleFactorString()
{
if (!CBuildConfig::isRunningOnWindowsNtPlatform()) { return "1.0"; }
// On windows
// Qt 5.14.1 default is device ratio 3
// Qt 5.14.0 default device ratio was 2
// 2/3 (0.66667) => device ratio 3
// 0.75 => device ratio 2.25
// 0.8 => device ratio 2.4
// 1.00 => device ratio 3
// currently NOT used
return "1.0";
}
bool CGuiApplication::cmdLineErrorMessage(const QString &errorMessage, bool retry) const
{
const QString helpText(beautifyHelpMessage(m_parser.helpText()));

View File

@@ -284,7 +284,7 @@ namespace BlackGui
//! Support for high DPI screens
//! \note Needs to be at the beginning of main
static void highDpiScreenSupport(double scaleFactor = -1);
static void highDpiScreenSupport(const QString &scaleFactor = {});
//! Uses the high DPI support?
static bool isUsingHighDpiScreenSupport();
@@ -300,8 +300,15 @@ namespace BlackGui
static void modalWindowToFront();
//! Parse scale factor if any
//! \deprecated using scaleFactor now
static double parseScaleFactor(int argc, char *argv[]);
//! Get the scale factor
static QString scaleFactor(int argc, char *argv[]);
//! Get a default scale factor
static QString defaultScaleFactorString();
signals:
//! Style sheet changed
void styleSheetsChanged();

View File

@@ -43,6 +43,14 @@
#include <QPropertyAnimation>
#include <QDesktopWidget>
// for the screen size
#ifdef Q_OS_WINDOWS
#include "wtypes.h"
#include "ShellScalingApi.h"
#include <iostream>
#endif
using namespace BlackMisc;
namespace BlackGui
@@ -114,6 +122,79 @@ namespace BlackGui
return QApplication::desktop()->screenGeometry(QApplication::desktop()).size();
}
QSizeF CGuiUtility::physicalScreenSize(QWidget *currentWidget)
{
QScreen *s = QGuiApplication::screens().front();
if (currentWidget)
{
const int sn = QApplication::desktop()->screenNumber(currentWidget);
s = QGuiApplication::screens().at(sn);
}
if (!s) { return QSizeF(); }
const QSizeF ps1 = s->physicalSize();
return ps1;
}
namespace Private
{
#ifdef Q_OS_WINDOWS
QSize windowsGetDesktopResolution()
{
/**
// https://stackoverflow.com/questions/8690619/how-to-get-screen-resolution-in-c
RECT desktop;
// Get a handle to the desktop window
const HWND hDesktop = GetDesktopWindow();
// Get the size of screen to the variable desktop
GetWindowRect(hDesktop, &desktop);
// The top left corner will have coordinates (0,0)
// and the bottom right corner will have coordinates
// (horizontal, vertical)
const int horizontal = desktop.right;
const int vertical = desktop.bottom;
return QSize(vertical, horizontal);
**/
// https://stackoverflow.com/questions/2156212/how-to-get-the-monitor-screen-resolution-from-a-hwnd
const HWND hDesktop = GetDesktopWindow();
HMONITOR monitor = MonitorFromWindow(hDesktop, MONITOR_DEFAULTTONEAREST);
MONITORINFO info;
info.cbSize = sizeof(MONITORINFO);
GetMonitorInfo(monitor, &info);
/**
DEVICE_SCALE_FACTOR pScale;
GetScaleFactorForMonitor(monitor, &pScale);
**/
const int monitor_width = info.rcMonitor.right - info.rcMonitor.left;
const int monitor_height = info.rcMonitor.bottom - info.rcMonitor.top;
return QSize(monitor_height, monitor_width);
/**
// https://stackoverflow.com/a/50205813/356726
const int width = static_cast<int>(GetSystemMetrics(SM_CXSCREEN));
const int height = static_cast<int>(GetSystemMetrics(SM_CYSCREEN));
return QSize(width, height);
**/
}
#endif
} // namespace Private
QSize CGuiUtility::physicalScreenSizeOs()
{
#ifdef Q_OS_WINDOWS
return Private::windowsGetDesktopResolution();
#elif defined(Q_OS_MAC)
return QSize();
#elif defined(Q_OS_LINUX)
return QSize();
#else
return QSize();
#endif
}
bool CGuiUtility::isMainWindowFrameless()
{
const CEnableForFramelessWindow *mw = CGuiUtility::mainFramelessEnabledWindow();
@@ -122,8 +203,15 @@ namespace BlackGui
QString CGuiUtility::screenInformation(const QString &separator)
{
const QSize ps = physicalScreenSizeOs();
QString i = u"Number of screens: " % QString::number(QGuiApplication::screens().size()) % separator %
u"Primary screen: " % QGuiApplication::primaryScreen()->name();
u"Primary screen: " % QGuiApplication::primaryScreen()->name() % separator %
u"QT_AUTO_SCREEN_SCALE_FACTOR: " % qgetenv("QT_AUTO_SCREEN_SCALE_FACTOR") % separator %
u"QT_SCALE_FACTOR: " % qgetenv("QT_SCALE_FACTOR") % separator %
u"QT_ENABLE_HIGHDPI_SCALING: " % qgetenv("QT_ENABLE_HIGHDPI_SCALING") % separator %
u"QT_SCALE_FACTOR_ROUNDING_POLICY: " % qgetenv("QT_SCALE_FACTOR_ROUNDING_POLICY") % separator %
u"QT_SCREEN_SCALE_FACTORS: " % qgetenv("QT_SCREEN_SCALE_FACTORS") % separator %
u"OS screen res." % QString::number(ps.width()) % u"/" % QString::number(ps.height()) % separator;
for (const QScreen *screen : QGuiApplication::screens())
{
@@ -509,7 +597,7 @@ namespace BlackGui
else
{
flags &= ~Qt::WindowStaysOnBottomHint;
flags |= Qt::WindowStaysOnTopHint;
flags |= Qt::WindowStaysOnTopHint;
}
widget->setWindowFlags(flags);
widget->show(); // without that the window sometimes just disappears
@@ -523,7 +611,7 @@ namespace BlackGui
if (onTop)
{
flags &= ~Qt::WindowStaysOnBottomHint;
flags |= Qt::WindowStaysOnTopHint;
flags |= Qt::WindowStaysOnTopHint;
}
else
{

View File

@@ -66,6 +66,14 @@ namespace BlackGui
//! \remark might be scaled depending on CGuiUtility::mainApplicationWidgetPixelRatio
static QSize desktopSize();
//! Pysical screen resolution
//! \remark unscaled
static QSizeF physicalScreenSize(QWidget *currentWidget = nullptr);
//! Qt independent implementation
//! \remark allows to return values before QGuiApplication is initialized
static QSize physicalScreenSizeOs();
//! Is main window frameless?
static bool isMainWindowFrameless();

View File

@@ -491,6 +491,64 @@ namespace BlackMisc
return (c % 2) == 0;
}
double parseFraction(const QString &fraction, double failDefault)
{
if (fraction.isEmpty()) { return failDefault; }
bool ok;
double r = failDefault;
if (fraction.contains('/'))
{
const QStringList parts = fraction.split('/');
if (parts.size() != 2) { return failDefault; }
const double c = parts.front().trimmed().toDouble(&ok);
if (!ok) { return failDefault; }
const double d = parts.last().trimmed().toDouble(&ok);
if (!ok) { return failDefault; }
if (qFuzzyCompare(0.0, d)) { return failDefault; }
r = c / d;
}
else
{
r = fraction.trimmed().toDouble(&ok);
if (!ok) { return failDefault; }
}
return r;
}
QString cleanNumber(const QString &number)
{
QString n = number.trimmed();
if (n.isEmpty()) { return QString(); }
int dp = n.indexOf('.');
if (dp < 0) { dp = n.indexOf(','); }
// clean all trailing stuff
while (dp >= 0 && !n.isEmpty())
{
const QChar l = n.at(n.size() - 1);
if (l == '0')
{
n.chop(1);
continue;
}
else if (l == '.' || l == ',')
{
n.chop(1);
}
break;
}
while (n.startsWith("00"))
{
n.remove(0, 1);
}
return n;
}
} // ns
//! \endcond

View File

@@ -308,6 +308,12 @@ namespace BlackMisc
//! Contains any string of the list?
BLACKMISC_EXPORT bool containsAny(const QString &testString, const QStringList &any, Qt::CaseSensitivity cs);
//! Parse a fraction like 2/3
BLACKMISC_EXPORT double parseFraction(const QString &fraction, double failDefault = std::numeric_limits<double>::quiet_NaN());
//! Remove leading 0, trailing 0, " ", and "." from a number
BLACKMISC_EXPORT QString cleanNumber(const QString &number);
namespace Mixin
{
/*!

View File

@@ -27,7 +27,7 @@ using namespace BlackGui;
int main(int argc, char *argv[])
{
//! [SwiftApplicationDemo]
CGuiApplication::highDpiScreenSupport(CGuiApplication::parseScaleFactor(argc, argv));
CGuiApplication::highDpiScreenSupport(CGuiApplication::scaleFactor(argc, argv));
QApplication qa(argc, argv);
Q_UNUSED(qa) // init of qa is required, but qa not used

View File

@@ -25,9 +25,9 @@ using namespace BlackGui;
int main(int argc, char *argv[])
{
CGuiApplication::highDpiScreenSupport(CGuiApplication::parseScaleFactor(argc, argv));
CGuiApplication::highDpiScreenSupport(CGuiApplication::scaleFactor(argc, argv));
QApplication qa(argc, argv);
Q_UNUSED(qa);
Q_UNUSED(qa)
CCrashHandler::instance()->init();
CGuiApplication a(CApplicationInfo::swiftMappingTool(), CApplicationInfo::MappingTool, CIcons::swiftDatabase48());

View File

@@ -24,7 +24,7 @@ using namespace BlackCore;
int main(int argc, char *argv[])
{
//! [SwiftApplicationDemo]
CGuiApplication::highDpiScreenSupport(CGuiApplication::parseScaleFactor(argc, argv));
CGuiApplication::highDpiScreenSupport(CGuiApplication::scaleFactor(argc, argv));
QApplication qa(argc, argv);
Q_UNUSED(qa) // application init needed

View File

@@ -76,7 +76,8 @@ void SwiftGuiStd::init()
sGui->initMainApplicationWidget(this);
// experimental: avoid mic flickering
if (CBuildConfig::isLocalDeveloperDebugBuild()) { BlackSound::occupyAudioInputDevice(); }
// disabled for 5.14.1
// if (CBuildConfig::isLocalDeveloperDebugBuild()) { BlackSound::occupyAudioInputDevice(); }
// log messages
m_logSubscriber.changeSubscription(CLogPattern().withSeverityAtOrAbove(CStatusMessage::SeverityInfo));

View File

@@ -29,7 +29,7 @@ using namespace BlackCore::Db;
int main(int argc, char *argv[])
{
//! [SwiftApplicationDemo]
CGuiApplication::highDpiScreenSupport(CGuiApplication::parseScaleFactor(argc, argv));
CGuiApplication::highDpiScreenSupport(CGuiApplication::scaleFactor(argc, argv));
QApplication qa(argc, argv); // needed
Q_UNUSED(qa)
CGuiApplication a(CApplicationInfo::swiftLauncher(), CApplicationInfo::Laucher, CIcons::swiftLauncher1024());

View File

@@ -483,7 +483,7 @@ void CSwiftLauncher::startButtonPressed()
{
const QObject *sender = QObject::sender();
const qreal scaleFactor = ui->comp_Scale->getScaleFactor();
CGuiApplication::highDpiScreenSupport(scaleFactor);
CGuiApplication::highDpiScreenSupport(QString::number(scaleFactor, 'f', 4));
const Qt::KeyboardModifiers km = QGuiApplication::queryKeyboardModifiers();
const bool shift = km.testFlag(Qt::ShiftModifier);