From 3ff80d1fe4c35f68bcebde7dccfde7b0fb03014f Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 5 Mar 2015 16:52:42 +0100 Subject: [PATCH 001/127] Windows printing: Add more error reporting. Task-number: QTCREATORBUG-13742 Change-Id: Ic234c7e86531c0924ddc03c63cd50b442bdcc9e9 Reviewed-by: Andy Shaw --- src/printsupport/kernel/qprintengine_win.cpp | 42 ++++++++++++++++---- src/printsupport/kernel/qprintengine_win_p.h | 5 +-- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/printsupport/kernel/qprintengine_win.cpp b/src/printsupport/kernel/qprintengine_win.cpp index 65af6fadf7..5b3184a20d 100644 --- a/src/printsupport/kernel/qprintengine_win.cpp +++ b/src/printsupport/kernel/qprintengine_win.cpp @@ -89,6 +89,17 @@ QWin32PrintEngine::QWin32PrintEngine(QPrinter::PrinterMode mode) d->initialize(); } +static QByteArray msgBeginFailed(const char *function, const DOCINFO &d) +{ + QString result; + QTextStream str(&result); + str << "QWin32PrintEngine::begin: " << function << " failed, document \"" + << QString::fromWCharArray(d.lpszDocName) << '"'; + if (d.lpszOutput[0]) + str << ", file \"" << QString::fromWCharArray(d.lpszOutput) << '"'; + return result.toLocal8Bit(); +} + bool QWin32PrintEngine::begin(QPaintDevice *pdev) { Q_D(QWin32PrintEngine); @@ -123,12 +134,12 @@ bool QWin32PrintEngine::begin(QPaintDevice *pdev) if (d->printToFile) di.lpszOutput = d->fileName.isEmpty() ? L"FILE:" : reinterpret_cast(d->fileName.utf16()); if (ok && StartDoc(d->hdc, &di) == SP_ERROR) { - qErrnoWarning("QWin32PrintEngine::begin: StartDoc failed"); + qErrnoWarning(msgBeginFailed("StartDoc", di)); ok = false; } if (StartPage(d->hdc) <= 0) { - qErrnoWarning("QWin32PrintEngine::begin: StartPage failed"); + qErrnoWarning(msgBeginFailed("StartPage", di)); ok = false; } @@ -175,8 +186,10 @@ bool QWin32PrintEngine::end() return true; if (d->hdc) { - EndPage(d->hdc); // end; printing done - EndDoc(d->hdc); + if (EndPage(d->hdc) <= 0) // end; printing done + qErrnoWarning("QWin32PrintEngine::end: EndPage failed (%p)", d->hdc); + if (EndDoc(d->hdc) <= 0) + qErrnoWarning("QWin32PrintEngine::end: EndDoc failed"); } d->state = QPrinter::Idle; @@ -201,10 +214,8 @@ bool QWin32PrintEngine::newPage() } if (d->reinit) { - if (!d->resetDC()) { - qErrnoWarning("QWin32PrintEngine::newPage: ResetDC failed"); + if (!d->resetDC()) return false; - } d->reinit = false; } @@ -241,6 +252,8 @@ bool QWin32PrintEngine::newPage() d->reinit = false; } success = (StartPage(d->hdc) > 0); + if (!success) + qErrnoWarning("Win32PrintEngine::newPage: StartPage failed (2)"); } if (!success) { d->state = QPrinter::Aborted; @@ -966,6 +979,21 @@ void QWin32PrintEnginePrivate::doReinit() } } +bool QWin32PrintEnginePrivate::resetDC() +{ + if (!hdc) { + qWarning() << "ResetDC() called with null hdc."; + return false; + } + const HDC oldHdc = hdc; + const HDC hdc = ResetDC(oldHdc, devMode); + if (!hdc) { + const int lastError = GetLastError(); + qErrnoWarning(lastError, "ResetDC() on %p failed (%d)", oldHdc, lastError); + } + return hdc != 0; +} + static int indexOfId(const QList &inputSlots, QPrint::InputSlotId id) { for (int i = 0; i < inputSlots.size(); ++i) { diff --git a/src/printsupport/kernel/qprintengine_win_p.h b/src/printsupport/kernel/qprintengine_win_p.h index 2f2a92f822..98a4cff1a8 100644 --- a/src/printsupport/kernel/qprintengine_win_p.h +++ b/src/printsupport/kernel/qprintengine_win_p.h @@ -152,10 +152,7 @@ public: is handled in the next begin or newpage. */ void doReinit(); - inline bool resetDC() { - hdc = ResetDC(hdc, devMode); - return hdc != 0; - } + bool resetDC(); void strokePath(const QPainterPath &path, const QColor &color); void fillPath(const QPainterPath &path, const QColor &color); From 21a0e3c111b97035a01b6386a4e9ecda2d2febf8 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 6 Mar 2015 13:37:44 +0100 Subject: [PATCH 002/127] Android: don't assume a stationary touchpoint unless all history agrees We need to compare each historical location (not just one of them) against the present location to prove that the touchpoint didn't move. We still don't actually send events for every historical touchpoint location though, because that would multiply the event traffic. Task-number: QTBUG-38379 Change-Id: I4b968ef6877031a157493d0a248564c78195c033 Reviewed-by: BogDan Vatra --- .../jar/src/org/qtproject/qt5/android/QtNative.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java index 8e35840a20..bed9d69782 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java @@ -279,12 +279,14 @@ public class QtNative if (action == MotionEvent.ACTION_MOVE) { int hsz = event.getHistorySize(); if (hsz > 0) { - if (event.getX(index) != event.getHistoricalX(index, hsz-1) - || event.getY(index) != event.getHistoricalY(index, hsz-1)) { - return 1; - } else { - return 2; + float x = event.getX(index); + float y = event.getY(index); + for (int h = 0; h < hsz; ++h) { + if ( event.getHistoricalX(index, h) != x || + event.getHistoricalY(index, h) != y ) + return 1; } + return 2; } return 1; } From 162c116948e8a7705979d1d0f0d5e4f6a2acb389 Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Thu, 5 Mar 2015 16:05:28 +0100 Subject: [PATCH 003/127] Doc: corrected doc QString::operator[] Task-number: QTBUG-43337 Change-Id: I379dfe3f6909de5a63a67261834ea0edff875f9d Reviewed-by: Oswald Buddenhagen Reviewed-by: Martin Smith --- src/corelib/tools/qstring.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index beda0f4919..fb7158c5f2 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -4797,11 +4797,11 @@ QString QString::trimmed_helper(QString &str) \overload operator[]() Returns the character at the specified \a position in the string as a -modifiable reference. Equivalent to \c at(position). +modifiable reference. */ /*! \fn const QChar QString::operator[](uint position) const - + Equivalent to \c at(position). \overload operator[]() */ From 6c099c21283f19c7127f6588a784a3bd68975899 Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Thu, 5 Mar 2015 15:28:50 +0100 Subject: [PATCH 004/127] Doc: added doc QProgressBar about undeterm. state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-43345 Change-Id: Ie8bda9dbe0ca2f713451f3ec2f68467a064f7f2c Reviewed-by: Topi Reiniö --- src/widgets/widgets/qprogressbar.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/widgets/widgets/qprogressbar.cpp b/src/widgets/widgets/qprogressbar.cpp index 6bc44f06fe..8034a0237a 100644 --- a/src/widgets/widgets/qprogressbar.cpp +++ b/src/widgets/widgets/qprogressbar.cpp @@ -347,6 +347,8 @@ int QProgressBar::value() const If the current value falls outside the new range, the progress bar is reset with reset(). + The QProgressBar can be set to undetermined state by using setRange(0, 0). + \sa minimum, maximum */ void QProgressBar::setRange(int minimum, int maximum) From 59495d180bf0538ae777617a2b5ba9a10e79eedf Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Wed, 4 Mar 2015 16:26:56 +0100 Subject: [PATCH 005/127] Doc: removed invalid warning about Qt stylesheets Task-number: QTBUG-44549 Change-Id: I386e75ae5c931f49a0198ae1f24706899bdedd94 Reviewed-by: Martin Smith --- src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc b/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc index b51ab21b25..8dbc716027 100644 --- a/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc +++ b/src/widgets/doc/src/widgets-and-layouts/stylesheet.qdoc @@ -132,8 +132,6 @@ Since Qt 4.5, Qt style sheets fully supports Mac OS X. - \warning Qt style sheets are currently not supported for custom QStyle - subclasses. We plan to address this in some future release. */ /*! From 0fce009f1c72806c349de6892d514ec540b02e44 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Mon, 9 Mar 2015 12:56:40 +0200 Subject: [PATCH 006/127] eglfs_kms: remove deprecated QString uses MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes "warning: ‘QString::QString(const char*)’ is deprecated" While we're here, make the locals const. Change-Id: Iee70253a46f91937b93e06cc08cd361716cd669d Reviewed-by: Laszlo Agocs --- .../eglfs_kms/qeglfskmsintegration.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp index 4598f21d92..7bb932cf00 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsintegration.cpp @@ -223,25 +223,25 @@ void QEglFSKmsIntegration::loadConfig() return; } - QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); + const QJsonDocument doc = QJsonDocument::fromJson(file.readAll()); if (!doc.isObject()) { qCDebug(qLcEglfsKmsDebug) << "Invalid config file" << json << "- no top-level JSON object"; return; } - QJsonObject object = doc.object(); + const QJsonObject object = doc.object(); - m_hwCursor = object.value("hwcursor").toBool(m_hwCursor); - m_pbuffers = object.value("pbuffers").toBool(m_pbuffers); - m_devicePath = object.value("device").toString(); + m_hwCursor = object.value(QStringLiteral("hwcursor")).toBool(m_hwCursor); + m_pbuffers = object.value(QStringLiteral("pbuffers")).toBool(m_pbuffers); + m_devicePath = object.value(QStringLiteral("device")).toString(); - QJsonArray outputs = object.value("outputs").toArray(); + const QJsonArray outputs = object.value(QStringLiteral("outputs")).toArray(); for (int i = 0; i < outputs.size(); i++) { - QVariantMap outputSettings = outputs.at(i).toObject().toVariantMap(); + const QVariantMap outputSettings = outputs.at(i).toObject().toVariantMap(); - if (outputSettings.contains("name")) { - QString name = outputSettings.value("name").toString(); + if (outputSettings.contains(QStringLiteral("name"))) { + const QString name = outputSettings.value(QStringLiteral("name")).toString(); if (m_outputSettings.contains(name)) { qCDebug(qLcEglfsKmsDebug) << "Output" << name << "configured multiple times!"; From 3fea1e53a14775a45e105efaf95066a8f1af5c18 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Sat, 7 Mar 2015 16:06:58 +0100 Subject: [PATCH 007/127] Add joystick/gamepad recognition to device discovery And to keep things readable, migrate to categorized logging. Change-Id: Ie9d82bb4e93d3b96f1a7bf54a37cfde4a941bc7d Reviewed-by: Andy Nichols --- .../devicediscovery/qdevicediscovery_p.h | 3 +- .../qdevicediscovery_static.cpp | 53 ++++++++----------- .../devicediscovery/qdevicediscovery_udev.cpp | 36 +++++-------- 3 files changed, 37 insertions(+), 55 deletions(-) diff --git a/src/platformsupport/devicediscovery/qdevicediscovery_p.h b/src/platformsupport/devicediscovery/qdevicediscovery_p.h index 88b75ee439..637a74cb1f 100644 --- a/src/platformsupport/devicediscovery/qdevicediscovery_p.h +++ b/src/platformsupport/devicediscovery/qdevicediscovery_p.h @@ -74,7 +74,8 @@ public: Device_DRM = 0x10, Device_DRM_PrimaryGPU = 0x20, Device_Tablet = 0x40, - Device_InputMask = Device_Mouse | Device_Touchpad | Device_Touchscreen | Device_Keyboard | Device_Tablet, + Device_Joystick = 0x80, + Device_InputMask = Device_Mouse | Device_Touchpad | Device_Touchscreen | Device_Keyboard | Device_Tablet | Device_Joystick, Device_VideoMask = Device_DRM }; Q_DECLARE_FLAGS(QDeviceTypes, QDeviceType) diff --git a/src/platformsupport/devicediscovery/qdevicediscovery_static.cpp b/src/platformsupport/devicediscovery/qdevicediscovery_static.cpp index 160fb7f5c0..1bc834b5ef 100644 --- a/src/platformsupport/devicediscovery/qdevicediscovery_static.cpp +++ b/src/platformsupport/devicediscovery/qdevicediscovery_static.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -56,13 +57,6 @@ #define ABS_CNT (ABS_MAX+1) #endif - -//#define QT_QPA_DEVICE_DISCOVERY_DEBUG - -#ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG -#include -#endif - #define LONG_BITS (sizeof(long) * 8 ) #define LONG_FIELD_SIZE(bits) ((bits / LONG_BITS) + 1) @@ -73,6 +67,8 @@ static bool testBit(long bit, const long *field) QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcDD, "qt.qpa.input") + QDeviceDiscovery *QDeviceDiscovery::create(QDeviceTypes types, QObject *parent) { return new QDeviceDiscoveryStatic(types, parent); @@ -81,9 +77,7 @@ QDeviceDiscovery *QDeviceDiscovery::create(QDeviceTypes types, QObject *parent) QDeviceDiscoveryStatic::QDeviceDiscoveryStatic(QDeviceTypes types, QObject *parent) : QDeviceDiscovery(types, parent) { -#ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG - qWarning() << "New DeviceDiscovery created for type" << types; -#endif + qCDebug(lcDD) << "static device discovery for type" << types; } QStringList QDeviceDiscoveryStatic::scanConnectedDevices() @@ -112,9 +106,7 @@ QStringList QDeviceDiscoveryStatic::scanConnectedDevices() } } -#ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG - qWarning() << "DeviceDiscovery found matching devices" << devices; -#endif + qCDebug(lcDD) << "Found matching devices" << devices; return devices; } @@ -124,9 +116,7 @@ bool QDeviceDiscoveryStatic::checkDeviceType(const QString &device) bool ret = false; int fd = QT_OPEN(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0); if (!fd) { -#ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG - qWarning() << "DeviceDiscovery cannot open device" << device; -#endif + qWarning() << "Device discovery cannot open device" << device; return false; } @@ -134,9 +124,7 @@ bool QDeviceDiscoveryStatic::checkDeviceType(const QString &device) if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(bitsKey)), bitsKey) >= 0 ) { if (!ret && (m_types & Device_Keyboard)) { if (testBit(KEY_Q, bitsKey)) { -#ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG - qWarning() << "DeviceDiscovery found keyboard at" << device; -#endif + qCDebug(lcDD) << "Found keyboard at" << device; ret = true; } } @@ -145,9 +133,7 @@ bool QDeviceDiscoveryStatic::checkDeviceType(const QString &device) long bitsRel[LONG_FIELD_SIZE(REL_CNT)]; if (ioctl(fd, EVIOCGBIT(EV_REL, sizeof(bitsRel)), bitsRel) >= 0 ) { if (testBit(REL_X, bitsRel) && testBit(REL_Y, bitsRel) && testBit(BTN_MOUSE, bitsKey)) { -#ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG - qWarning() << "DeviceDiscovery found mouse at" << device; -#endif + qCDebug(lcDD) << "Found mouse at" << device; ret = true; } } @@ -158,24 +144,29 @@ bool QDeviceDiscoveryStatic::checkDeviceType(const QString &device) if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(bitsAbs)), bitsAbs) >= 0 ) { if (testBit(ABS_X, bitsAbs) && testBit(ABS_Y, bitsAbs)) { if ((m_types & Device_Touchpad) && testBit(BTN_TOOL_FINGER, bitsKey)) { -#ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG - qWarning() << "DeviceDiscovery found touchpad at" << device; -#endif + qCDebug(lcDD) << "Found touchpad at" << device; ret = true; } else if ((m_types & Device_Touchscreen) && testBit(BTN_TOUCH, bitsKey)) { -#ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG - qWarning() << "DeviceDiscovery found touchscreen at" << device; -#endif + qCDebug(lcDD) << "Found touchscreen at" << device; ret = true; } else if ((m_types & Device_Tablet) && (testBit(BTN_STYLUS, bitsKey) || testBit(BTN_TOOL_PEN, bitsKey))) { -#ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG - qWarning() << "DeviceDiscovery found tablet at" << device; -#endif + qCDebug(lcDD) << "Found tablet at" << device; ret = true; } } } } + + if (!ret && (m_types & Device_Joystick)) { + long bitsAbs[LONG_FIELD_SIZE(ABS_CNT)]; + if (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(bitsAbs)), bitsAbs) >= 0 ) { + if ((m_types & Device_Joystick) + && (testBit(BTN_A, bitsKey) || testBit(BTN_TRIGGER, bitsKey) || testBit(ABS_RX, bitsAbs))) { + qCDebug(lcDD) << "Found joystick/gamepad at" << device; + ret = true; + } + } + } } if (!ret && (m_types & Device_DRM) && device.contains(QString::fromLatin1(QT_DRM_DEVICE_PREFIX))) diff --git a/src/platformsupport/devicediscovery/qdevicediscovery_udev.cpp b/src/platformsupport/devicediscovery/qdevicediscovery_udev.cpp index 358be828fa..8fa82e2ad7 100644 --- a/src/platformsupport/devicediscovery/qdevicediscovery_udev.cpp +++ b/src/platformsupport/devicediscovery/qdevicediscovery_udev.cpp @@ -38,22 +38,17 @@ #include #include #include +#include #include -//#define QT_QPA_DEVICE_DISCOVERY_DEBUG - -#ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG -#include -#endif - QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcDD, "qt.qpa.input") + QDeviceDiscovery *QDeviceDiscovery::create(QDeviceTypes types, QObject *parent) { -#ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG - qWarning() << "Try to create new UDeviceHelper"; -#endif + qCDebug(lcDD) << "udev device discovery for type" << types; QDeviceDiscovery *helper = 0; struct udev *udev; @@ -62,7 +57,7 @@ QDeviceDiscovery *QDeviceDiscovery::create(QDeviceTypes types, QObject *parent) if (udev) { helper = new QDeviceDiscoveryUDev(types, udev, parent); } else { - qWarning("Failed to get udev library context."); + qWarning("Failed to get udev library context"); } return helper; @@ -72,18 +67,12 @@ QDeviceDiscoveryUDev::QDeviceDiscoveryUDev(QDeviceTypes types, struct udev *udev QDeviceDiscovery(types, parent), m_udev(udev), m_udevMonitor(0), m_udevMonitorFileDescriptor(-1), m_udevSocketNotifier(0) { -#ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG - qWarning() << "New UDeviceHelper created for type" << types; -#endif - if (!m_udev) return; m_udevMonitor = udev_monitor_new_from_netlink(m_udev, "udev"); if (!m_udevMonitor) { -#ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG - qWarning("Unable to create an Udev monitor. No devices can be detected."); -#endif + qWarning("Unable to create an udev monitor. No devices can be detected."); return; } @@ -128,11 +117,11 @@ QStringList QDeviceDiscoveryUDev::scanConnectedDevices() } if (m_types & Device_Tablet) udev_enumerate_add_match_property(ue, "ID_INPUT_TABLET", "1"); + if (m_types & Device_Joystick) + udev_enumerate_add_match_property(ue, "ID_INPUT_JOYSTICK", "1"); if (udev_enumerate_scan_devices(ue) != 0) { -#ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG - qWarning() << "UDeviceHelper scan connected devices for enumeration failed"; -#endif + qWarning("Failed to scan devices"); return devices; } @@ -158,9 +147,7 @@ QStringList QDeviceDiscoveryUDev::scanConnectedDevices() } udev_enumerate_unref(ue); -#ifdef QT_QPA_DEVICE_DISCOVERY_DEBUG - qWarning() << "UDeviceHelper found matching devices" << devices; -#endif + qCDebug(lcDD) << "Found matching devices" << devices; return devices; } @@ -251,6 +238,9 @@ bool QDeviceDiscoveryUDev::checkDeviceType(udev_device *dev) if ((m_types & Device_Tablet) && (qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_TABLET"), "1") == 0)) return true; + if ((m_types & Device_Joystick) && (qstrcmp(udev_device_get_property_value(dev, "ID_INPUT_JOYSTICK"), "1") == 0)) + return true; + if ((m_types & Device_DRM) && (qstrcmp(udev_device_get_subsystem(dev), "drm") == 0)) return true; From 1edd16879c238d36d75843be3b54bb20925eeedc Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 9 Mar 2015 10:54:27 +0100 Subject: [PATCH 008/127] Fix building tests on QNX MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use qmath and cmath methods instead of math.h methods. Change-Id: I86ee2465c999822bf00a7cefee1642c4c30590a6 Reviewed-by: Tony Sarajärvi --- tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp | 5 +++-- tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp | 8 +------- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp index 1f5132d369..a192ccde59 100644 --- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp @@ -48,6 +48,7 @@ #include #include +#include #include #include @@ -3376,10 +3377,10 @@ void tst_QVariant::numericalConvert() switch (v.userType()) { case QVariant::Double: - QCOMPARE(v.toString() , QString::number(num, 'g', DBL_MANT_DIG * log10(2.) + 2)); + QCOMPARE(v.toString() , QString::number(num, 'g', DBL_MANT_DIG * std::log10(2.) + 2)); break; case QMetaType::Float: - QCOMPARE(v.toString() , QString::number(float(num), 'g', FLT_MANT_DIG * log10(2.) + 2)); + QCOMPARE(v.toString() , QString::number(float(num), 'g', FLT_MANT_DIG * std::log10(2.) + 2)); break; } } diff --git a/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp b/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp index 4252561001..0a073f5c84 100644 --- a/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp +++ b/tests/auto/gui/painting/qpainterpath/tst_qpainterpath.cpp @@ -895,12 +895,6 @@ void tst_QPainterPath::operators() QCOMPARE(test, expected); } -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif -#define ANGLE(t) ((t) * 2 * M_PI / 360.0) - - static inline bool pathFuzzyCompare(double p1, double p2) { return qAbs(p1 - p2) < 0.001; @@ -931,7 +925,7 @@ void tst_QPainterPath::testArcMoveTo() qreal y_radius = rect.height() / 2.0; QPointF shouldBe = rect.center() - + QPointF(x_radius * cos(ANGLE(angle)), -y_radius * sin(ANGLE(angle))); + + QPointF(x_radius * qCos(qDegreesToRadians(angle)), -y_radius * qSin(qDegreesToRadians(angle))); qreal iw = 1 / rect.width(); qreal ih = 1 / rect.height(); From 72ef272733d9b91c991233d826054cccb926db2d Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Tue, 24 Feb 2015 21:13:06 +0100 Subject: [PATCH 009/127] (Re)introduce loopLevel into QThread MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This function used to reside in QEventLoop in Qt 3 and was deprecated in Qt 4. However this is useful for those who want to know how many event loops are running within the thread so we just make it possible to get at the already available variable. Change-Id: Ia6a7d94ff443a1d1577633363694bc2fa8eca7e4 Reviewed-by: Thiago Macieira Reviewed-by: Jørgen Lind --- src/corelib/thread/qthread.cpp | 13 +++++++++++++ src/corelib/thread/qthread.h | 1 + 2 files changed, 14 insertions(+) diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp index f119828e8e..acee337642 100644 --- a/src/corelib/thread/qthread.cpp +++ b/src/corelib/thread/qthread.cpp @@ -711,6 +711,19 @@ QThread::Priority QThread::priority() const \sa terminate() */ +/*! + Returns the current event loop level for the thread. + + \note This can only be called within the thread itself, i.e. when + it is the current thread. +*/ + +int QThread::loopLevel() const +{ + Q_D(const QThread); + return d->data->eventLoops.size(); +} + #else // QT_NO_THREAD QThread::QThread(QObject *parent) diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h index 72d8f5a5f8..58755b9625 100644 --- a/src/corelib/thread/qthread.h +++ b/src/corelib/thread/qthread.h @@ -90,6 +90,7 @@ public: void setEventDispatcher(QAbstractEventDispatcher *eventDispatcher); bool event(QEvent *event) Q_DECL_OVERRIDE; + int loopLevel() const; public Q_SLOTS: void start(Priority = InheritPriority); From 58073a02fc50cd4cc8402b61f55c9d2cdb2a7c46 Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Sat, 7 Mar 2015 05:45:56 +0400 Subject: [PATCH 010/127] [QFontEngineFT] Use FT_Library associated with a given face Change-Id: I4f9927e2c5cb014523bebbe9c719aca89bb86019 Reviewed-by: Friedemann Kleint Reviewed-by: Simon Hausmann --- src/gui/text/qfontengine_ft.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index b79f971156..10a5719e95 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -891,8 +891,6 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, FT_Matrix_Multiply(&m, &matrix); } - FT_Library library = qt_getFreetype(); - info.xOff = TRUNC(ROUND(slot->advance.x)); info.yOff = 0; @@ -935,7 +933,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, #if defined(QT_USE_FREETYPE_LCDFILTER) bool useFreetypeRenderGlyph = false; if (slot->format == FT_GLYPH_FORMAT_OUTLINE && (hsubpixel || vfactor != 1)) { - err = FT_Library_SetLcdFilter(library, (FT_LcdFilter)lcdFilterType); + err = FT_Library_SetLcdFilter(slot->library, (FT_LcdFilter)lcdFilterType); if (err == FT_Err_Ok) useFreetypeRenderGlyph = true; } @@ -946,7 +944,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, if (err != FT_Err_Ok) qWarning("render glyph failed err=%x face=%p, glyph=%d", err, face, glyph); - FT_Library_SetLcdFilter(library, FT_LCD_FILTER_NONE); + FT_Library_SetLcdFilter(slot->library, FT_LCD_FILTER_NONE); info.height = slot->bitmap.rows / vfactor; info.width = hsubpixel ? slot->bitmap.width / 3 : slot->bitmap.width; @@ -1058,7 +1056,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph, FT_Outline_Transform(&slot->outline, &matrix); FT_Outline_Translate (&slot->outline, (hsubpixel ? -3*left +(4<<6) : -left), -bottom*vfactor); - FT_Outline_Get_Bitmap(library, &slot->outline, &bitmap); + FT_Outline_Get_Bitmap(slot->library, &slot->outline, &bitmap); if (hsubpixel) { Q_ASSERT (bitmap.pixel_mode == FT_PIXEL_MODE_GRAY); Q_ASSERT(antialias); From 17d690952b404d46640115d6c037dacbcf3de0f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 2 Mar 2015 18:22:49 +0100 Subject: [PATCH 011/127] iOS: Use Xcode project to filter out environment variables instead of shell Xcode has a setting for script phases to filter out the environment variables, so we don't need to use grep. Change-Id: Ica1c64321385ab3e3b47cf6f8f4d4191bd963540 Reviewed-by: Oswald Buddenhagen Reviewed-by: Richard Moe Gustavsen --- mkspecs/macx-ios-clang/features/default_post.prf | 3 ++- qmake/generators/mac/pbuilder_pbx.cpp | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/mkspecs/macx-ios-clang/features/default_post.prf b/mkspecs/macx-ios-clang/features/default_post.prf index f9a8921a09..a2c181a55d 100644 --- a/mkspecs/macx-ios-clang/features/default_post.prf +++ b/mkspecs/macx-ios-clang/features/default_post.prf @@ -97,7 +97,8 @@ equals(TEMPLATE, app) { target = $${sdk}-$${cfg}$${action_target_suffix} - $${target}.commands = "@bash -o pipefail -c 'xcodebuild $$action -scheme $(TARGET) -sdk $$sdk -configuration $$title($$cfg) | grep -v setenv'" + $${target}.commands = "xcodebuild $$action -scheme $(TARGET) -sdk $$sdk -configuration $$title($$cfg)" + QMAKE_EXTRA_TARGETS += $$target $${action_target}.depends += $$target diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index e2b5f5f90b..ec18d1f9b3 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -558,6 +558,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) << "\t\t\t" << writeSettings("name", "Qt Qmake") << ";\n" << "\t\t\t" << writeSettings("shellPath", "/bin/sh") << ";\n" << "\t\t\t" << writeSettings("shellScript", "make -C " + IoUtils::shellQuoteUnix(qmake_getpwd()) + " -f " + IoUtils::shellQuoteUnix(mkfile)) << ";\n" + << "\t\t\t" << writeSettings("showEnvVarsInLog", "0") << ";\n" << "\t\t};\n"; } @@ -795,6 +796,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) << "\t\t\t" << writeSettings("name", "Qt Preprocessors") << ";\n" << "\t\t\t" << writeSettings("shellPath", "/bin/sh") << ";\n" << "\t\t\t" << writeSettings("shellScript", "make -C " + IoUtils::shellQuoteUnix(qmake_getpwd()) + " -f " + IoUtils::shellQuoteUnix(mkfile)) << ";\n" + << "\t\t\t" << writeSettings("showEnvVarsInLog", "0") << ";\n" << "\t\t};\n"; } @@ -1070,6 +1072,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) << "\t\t\t" << writeSettings("name", "Qt Postlink") << ";\n" << "\t\t\t" << writeSettings("shellPath", "/bin/sh") << ";\n" << "\t\t\t" << writeSettings("shellScript", project->values("QMAKE_POST_LINK")) << ";\n" + << "\t\t\t" << writeSettings("showEnvVarsInLog", "0") << ";\n" << "\t\t};\n"; } @@ -1088,6 +1091,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) << "\t\t\t" << writeSettings("runOnlyForDeploymentPostprocessing", "0", SettingsNoQuote) << ";\n" << "\t\t\t" << writeSettings("shellPath", "/bin/sh") << ";\n" << "\t\t\t" << writeSettings("shellScript", fixForOutput("cp -r $BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME " + IoUtils::shellQuoteUnix(destDir))) << ";\n" + << "\t\t\t" << writeSettings("showEnvVarsInLog", "0") << ";\n" << "\t\t};\n"; } bool copyBundleResources = project->isActiveConfig("app_bundle") && project->first("TEMPLATE") == "app"; From 3d7a0111e3d72b39c3e5f04ca9d634ed9c151cba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 5 Mar 2015 16:13:57 +0100 Subject: [PATCH 012/127] iOS: Auto-detect available devices when running make check for testing Change-Id: I447d8faf421c31de68dde64211b795eaccec17a4 Reviewed-by: Richard Moe Gustavsen --- .../macx-ios-clang/features/default_post.prf | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/mkspecs/macx-ios-clang/features/default_post.prf b/mkspecs/macx-ios-clang/features/default_post.prf index a2c181a55d..b0f8b14811 100644 --- a/mkspecs/macx-ios-clang/features/default_post.prf +++ b/mkspecs/macx-ios-clang/features/default_post.prf @@ -97,8 +97,24 @@ equals(TEMPLATE, app) { target = $${sdk}-$${cfg}$${action_target_suffix} - $${target}.commands = "xcodebuild $$action -scheme $(TARGET) -sdk $$sdk -configuration $$title($$cfg)" + xcodebuild = "xcodebuild $$action -scheme $(TARGET) -sdk $$sdk -configuration $$title($$cfg)" + equals(action, test):equals(sdk, iphoneos) { + AVAILABLE_DEVICE_IDS = "$(shell system_profiler SPUSBDataType | sed -n -E -e '/(iPhone|iPad|iPod)/,/Serial/s/ *Serial Number: *(.+)/\1/p')" + CUSTOM_DEVICE_IDS = "$(filter $(EXPORT_AVAILABLE_DEVICE_IDS), $(IOS_TEST_DEVICE_IDS))" + TEST_DEVICE_IDS = "$(strip $(if $(EXPORT_CUSTOM_DEVICE_IDS), $(EXPORT_CUSTOM_DEVICE_IDS), $(EXPORT_AVAILABLE_DEVICE_IDS)))" + + QMAKE_EXTRA_VARIABLES += AVAILABLE_DEVICE_IDS CUSTOM_DEVICE_IDS TEST_DEVICE_IDS + + xcodebuild = "@$(if $(EXPORT_TEST_DEVICE_IDS),"\ + "echo Running tests on $(words $(EXPORT_TEST_DEVICE_IDS)) device\\(s\\): && ("\ + "$(foreach deviceid, $(EXPORT_TEST_DEVICE_IDS),"\ + "(echo Testing on device ID '$(deviceid)' ... && $${xcodebuild} -destination 'platform=iOS,id=$(deviceid)' && echo) &&"\ + ") echo Tests completed successfully on all devices"\ + "), $(error No iOS devices connected, please connect at least one device that can be used for testing.))" + } + + $${target}.commands = $$xcodebuild QMAKE_EXTRA_TARGETS += $$target $${action_target}.depends += $$target From afe3e247110dcb790aac1a34f13aa4fe8d5f78c0 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 5 Mar 2015 22:25:45 -0800 Subject: [PATCH 013/127] QPA plugins: Fix const correctness in old style casts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Found with GCC's -Wcast-qual. Change-Id: Ia0aac2f09e9245339951ffff13c946899b4ba15b Reviewed-by: Jørgen Lind Reviewed-by: Shawn Rutledge --- src/platformsupport/input/evdevtouch/qevdevtouch.cpp | 2 +- src/plugins/imageformats/ico/qicohandler.cpp | 2 +- .../compose/qcomposeplatforminputcontext.cpp | 2 +- src/plugins/platforms/xcb/qxcbclipboard.cpp | 4 ++-- src/plugins/platforms/xcb/qxcbscreen.cpp | 2 +- src/plugins/platforms/xcb/qxcbsessionmanager.cpp | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/platformsupport/input/evdevtouch/qevdevtouch.cpp b/src/platformsupport/input/evdevtouch/qevdevtouch.cpp index 5215f7da0a..5c28dfb082 100644 --- a/src/platformsupport/input/evdevtouch/qevdevtouch.cpp +++ b/src/platformsupport/input/evdevtouch/qevdevtouch.cpp @@ -175,7 +175,7 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &specification, setObjectName(QLatin1String("Evdev Touch Handler")); if (qEnvironmentVariableIsSet("QT_QPA_EVDEV_DEBUG")) - ((QLoggingCategory &) qLcEvdevTouch()).setEnabled(QtDebugMsg, true); + const_cast(qLcEvdevTouch()).setEnabled(QtDebugMsg, true); // only the first device argument is used for now QString spec = QString::fromLocal8Bit(qgetenv("QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS")); diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp index 6e5b81ed36..ab03bfeb04 100644 --- a/src/plugins/imageformats/ico/qicohandler.cpp +++ b/src/plugins/imageformats/ico/qicohandler.cpp @@ -524,7 +524,7 @@ QImage ICOReader::iconAt(int index) iod->seek(iconEntry.dwImageOffset); - const QByteArray pngMagic = QByteArray::fromRawData((char*)pngMagicData, sizeof(pngMagicData)); + const QByteArray pngMagic = QByteArray::fromRawData((const char*)pngMagicData, sizeof(pngMagicData)); const bool isPngImage = (iod->read(pngMagic.size()) == pngMagic); if (isPngImage) { diff --git a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp index ad226989a0..49fa32004e 100644 --- a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp +++ b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp @@ -97,7 +97,7 @@ bool QComposeInputContext::filterEvent(const QEvent *event) if ((m_tableState & TableGenerator::NoErrors) != TableGenerator::NoErrors) return false; - QKeyEvent *keyEvent = (QKeyEvent *)event; + const QKeyEvent *keyEvent = (const QKeyEvent *)event; // should pass only the key presses if (keyEvent->type() != QEvent::KeyPress) { return false; diff --git a/src/plugins/platforms/xcb/qxcbclipboard.cpp b/src/plugins/platforms/xcb/qxcbclipboard.cpp index d4f1c6ae48..2c0a7a11cc 100644 --- a/src/plugins/platforms/xcb/qxcbclipboard.cpp +++ b/src/plugins/platforms/xcb/qxcbclipboard.cpp @@ -97,7 +97,7 @@ protected: that->format_atoms = m_clipboard->getDataInFormat(modeAtom, m_clipboard->atom(QXcbAtom::TARGETS)); if (format_atoms.size() > 0) { - xcb_atom_t *targets = (xcb_atom_t *) format_atoms.data(); + const xcb_atom_t *targets = (const xcb_atom_t *) format_atoms.data(); int size = format_atoms.size() / sizeof(xcb_atom_t); for (int i = 0; i < size; ++i) { @@ -128,7 +128,7 @@ protected: (void)formats(); // trigger update of format list QVector atoms; - xcb_atom_t *targets = (xcb_atom_t *) format_atoms.data(); + const xcb_atom_t *targets = (const xcb_atom_t *) format_atoms.data(); int size = format_atoms.size() / sizeof(xcb_atom_t); atoms.reserve(size); for (int i = 0; i < size; ++i) diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 78ced43af8..08108f1e20 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -703,7 +703,7 @@ Q_XCB_EXPORT QDebug operator<<(QDebug debug, const QXcbScreen *screen) { const QDebugStateSaver saver(debug); debug.nospace(); - debug << "QXcbScreen(" << (void *)screen; + debug << "QXcbScreen(" << (const void *)screen; if (screen) { debug << fixed << qSetRealNumberPrecision(1); debug << ", name=" << screen->name(); diff --git a/src/plugins/platforms/xcb/qxcbsessionmanager.cpp b/src/plugins/platforms/xcb/qxcbsessionmanager.cpp index 33e67a14b1..328b72234a 100644 --- a/src/plugins/platforms/xcb/qxcbsessionmanager.cpp +++ b/src/plugins/platforms/xcb/qxcbsessionmanager.cpp @@ -125,7 +125,7 @@ static void sm_setProperty(const QString &name, const QString &value) QByteArray v = value.toUtf8(); SmPropValue prop; prop.length = v.length(); - prop.value = (SmPointer) v.constData(); + prop.value = (SmPointer) const_cast(v.constData()); sm_setProperty(name.toLatin1().data(), SmARRAY8, 1, &prop); } From a31823176af50baaaf78e8ea342b9efbf5c7c4d2 Mon Sep 17 00:00:00 2001 From: Samuli Piippo Date: Thu, 26 Feb 2015 16:37:49 +0200 Subject: [PATCH 014/127] QNX: enable Neon support to be compiled in for QNX Neon detection in configure does not work unless correct flags are passed to compiler. Task-number: QTBUG-44690 Change-Id: If119cc9ed80275aaa8796c1be8853559a7670d6a Reviewed-by: Sean Harmer Reviewed-by: Rafael Roquetto --- mkspecs/common/qcc-base-qnx-armle-v7.conf | 1 + mkspecs/common/qcc-base.conf | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/mkspecs/common/qcc-base-qnx-armle-v7.conf b/mkspecs/common/qcc-base-qnx-armle-v7.conf index 331a65b2bf..12d393f070 100644 --- a/mkspecs/common/qcc-base-qnx-armle-v7.conf +++ b/mkspecs/common/qcc-base-qnx-armle-v7.conf @@ -10,6 +10,7 @@ include(unix.conf) QMAKE_CC = qcc -Vgcc_ntoarmv7le QMAKE_CXX = qcc -Vgcc_ntoarmv7le QNX_CPUDIR = armle-v7 +QMAKE_CFLAGS += -mfpu=neon include(qcc-base-qnx.conf) diff --git a/mkspecs/common/qcc-base.conf b/mkspecs/common/qcc-base.conf index f529d7fc7b..09fdabce43 100644 --- a/mkspecs/common/qcc-base.conf +++ b/mkspecs/common/qcc-base.conf @@ -33,7 +33,6 @@ QMAKE_CFLAGS_SSE4_1 += -msse4.1 QMAKE_CFLAGS_SSE4_2 += -msse4.2 QMAKE_CFLAGS_AVX += -mavx QMAKE_CFLAGS_AVX2 += -mavx2 -QMAKE_CFLAGS_NEON += -mfpu=neon QMAKE_CXXFLAGS += $$QMAKE_CFLAGS -lang-c++ QMAKE_CXXFLAGS_DEPS += $$QMAKE_CFLAGS_DEPS From b0ae0db61afbb93f8087937c8453d78a680bcbeb Mon Sep 17 00:00:00 2001 From: Samuli Piippo Date: Mon, 2 Mar 2015 09:01:36 +0200 Subject: [PATCH 015/127] Remove neon command line options from configureapp Neon support needs to be enabled unconditionally in mkspecs, so removing -neon and -no-neon command line options from configure app. It now has the same functionality as configure script. Task-number: QTBUG-44690 Change-Id: Iaf5bf7ac4e11fcb798f643660e48a4ed3ce1036b Reviewed-by: Oswald Buddenhagen Reviewed-by: Thiago Macieira --- tools/configure/configureapp.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index ed4eb7e09a..ca2a5b1769 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -1269,12 +1269,6 @@ void Configure::parseCmdLine() dictionary["QT_INOTIFY"] = "no"; } - else if (configCmdLine.at(i) == "-neon") { - dictionary["NEON"] = "yes"; - } else if (configCmdLine.at(i) == "-no-neon") { - dictionary["NEON"] = "no"; - } - else if (configCmdLine.at(i) == "-largefile") { dictionary["LARGE_FILE"] = "yes"; } @@ -1846,9 +1840,6 @@ bool Configure::displayHelp() desc("NIS", "no", "-no-nis", "Do not compile NIS support."); desc("NIS", "yes", "-nis", "Compile NIS support.\n"); - desc("NEON", "yes", "-neon", "Enable the use of NEON instructions."); - desc("NEON", "no", "-no-neon", "Do not enable the use of NEON instructions.\n"); - desc("QT_ICONV", "disable", "-no-iconv", "Do not enable support for iconv(3)."); desc("QT_ICONV", "yes", "-iconv", "Enable support for iconv(3)."); desc("QT_ICONV", "yes", "-sun-iconv", "Enable support for iconv(3) using sun-iconv."); From 3e6a14168bfa1a8815baf28eba8eeff5e3a97a80 Mon Sep 17 00:00:00 2001 From: Venugopal Shivashankar Date: Thu, 5 Mar 2015 15:10:03 +0100 Subject: [PATCH 016/127] Example: Removed the code to handle 'num_entries' info. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Google Suggest API doesn't return the 'num_queries' anymore. Had to remove code related to 'num_queries' entry so that the suggestion list shows up. Task-number: QTBUG-42817 Change-Id: Ic918d1c86840fa4c1e18f32a984f5a9dd911261d Reviewed-by: Topi Reiniö --- .../doc/images/googlesuggest-example.png | Bin 9006 -> 21272 bytes examples/network/doc/src/googlesuggest.qdoc | 12 +++------ .../network/googlesuggest/googlesuggest.cpp | 25 ++++-------------- .../network/googlesuggest/googlesuggest.h | 2 +- 4 files changed, 10 insertions(+), 29 deletions(-) diff --git a/examples/network/doc/images/googlesuggest-example.png b/examples/network/doc/images/googlesuggest-example.png index 477d444cbd0474fd23b3f14fef237d60978f9456..c704f5b2b4943d4382ee251dd5c5ebe4c91094bd 100644 GIT binary patch literal 21272 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 literal 9006 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 UY-;#eY5)KL07*qoM6N<$g4_?tqW}N^ diff --git a/examples/network/doc/src/googlesuggest.qdoc b/examples/network/doc/src/googlesuggest.qdoc index 912947dfdf..168515446f 100644 --- a/examples/network/doc/src/googlesuggest.qdoc +++ b/examples/network/doc/src/googlesuggest.qdoc @@ -68,12 +68,8 @@ in the explicit \c editor member variable. We then create a QTreeWidget as a toplevel widget and configure the various - properties to give it the look of a popup widget. - - The popup will be populated by the results returned from Google. We set - the number of columns to be two, since we want to display both the - suggested search term and the number of hits it will trigger in the search - engine. + properties to give it the look of a popup widget. The widget is populated + with the results by Google Suggest API request. Furthermore, we install the GSuggestCompletion instance as an event filter on the QTreeWidget, and connect the \c itemClicked() signal with the \c @@ -110,8 +106,8 @@ \snippet googlesuggest/googlesuggest.cpp 4 The \c showCompletion() function populates the QTreeWidget with the results - returned from the query. It takes two QStringLists, one with the suggested - search terms and the other with the corresponding number of hits. + returned from the query. It takes a QStringList of the suggested search + terms. \snippet googlesuggest/googlesuggest.cpp 5 diff --git a/examples/network/googlesuggest/googlesuggest.cpp b/examples/network/googlesuggest/googlesuggest.cpp index ce727e7675..576629d46b 100644 --- a/examples/network/googlesuggest/googlesuggest.cpp +++ b/examples/network/googlesuggest/googlesuggest.cpp @@ -38,7 +38,6 @@ ** ****************************************************************************/ - //! [1] #include "googlesuggest.h" @@ -54,7 +53,7 @@ GSuggestCompletion::GSuggestCompletion(QLineEdit *parent): QObject(parent), edit popup->setFocusProxy(parent); popup->setMouseTracking(true); - popup->setColumnCount(2); + popup->setColumnCount(1); popup->setUniformRowHeights(true); popup->setRootIsDecorated(false); popup->setEditTriggers(QTreeWidget::NoEditTriggers); @@ -137,10 +136,10 @@ bool GSuggestCompletion::eventFilter(QObject *obj, QEvent *ev) //! [4] //! [5] -void GSuggestCompletion::showCompletion(const QStringList &choices, const QStringList &hits) +void GSuggestCompletion::showCompletion(const QStringList &choices) { - if (choices.isEmpty() || choices.count() != hits.count()) + if (choices.isEmpty()) return; const QPalette &pal = editor->palette(); @@ -152,19 +151,12 @@ void GSuggestCompletion::showCompletion(const QStringList &choices, const QStrin QTreeWidgetItem * item; item = new QTreeWidgetItem(popup); item->setText(0, choices[i]); - item->setText(1, hits[i]); - item->setTextAlignment(1, Qt::AlignRight); - item->setTextColor(1, color); + item->setTextColor(0, color); } popup->setCurrentItem(popup->topLevelItem(0)); popup->resizeColumnToContents(0); - popup->resizeColumnToContents(1); - popup->adjustSize(); popup->setUpdatesEnabled(true); - int h = popup->sizeHintForRow(0) * qMin(7, choices.count()) + 3; - popup->resize(popup->width(), h); - popup->move(editor->mapToGlobal(QPoint(0, editor->height()))); popup->setFocus(); popup->show(); @@ -207,7 +199,6 @@ void GSuggestCompletion::handleNetworkData(QNetworkReply *networkReply) QUrl url = networkReply->url(); if (!networkReply->error()) { QStringList choices; - QStringList hits; QByteArray response(networkReply->readAll()); QXmlStreamReader xml(response); @@ -218,17 +209,11 @@ void GSuggestCompletion::handleNetworkData(QNetworkReply *networkReply) QStringRef str = xml.attributes().value("data"); choices << str.toString(); } - if (xml.tokenType() == QXmlStreamReader::StartElement) - if (xml.name() == "num_queries") { - QStringRef str = xml.attributes().value("int"); - hits << str.toString(); - } } - showCompletion(choices, hits); + showCompletion(choices); } networkReply->deleteLater(); } //! [9] - diff --git a/examples/network/googlesuggest/googlesuggest.h b/examples/network/googlesuggest/googlesuggest.h index dfa04cd009..e53fe996d4 100644 --- a/examples/network/googlesuggest/googlesuggest.h +++ b/examples/network/googlesuggest/googlesuggest.h @@ -61,7 +61,7 @@ public: GSuggestCompletion(QLineEdit *parent = 0); ~GSuggestCompletion(); bool eventFilter(QObject *obj, QEvent *ev) Q_DECL_OVERRIDE; - void showCompletion(const QStringList &choices, const QStringList &hits); + void showCompletion(const QStringList &choices); public slots: From ac3502345f98993c56d6af147c849f7003bb292b Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 4 Mar 2015 13:03:20 +0100 Subject: [PATCH 017/127] Fix design metrics for text on Windows The trick to get design metrics on Windows is to request the font with the design size, however we were passing the em square size in as the cell height instead of the em square size (aka character height in Windows docs). This would give us hinted metrics and thus the design metrics would differ from other platforms. [ChangeLog][Windows][Text] Fixed design metrics for text Task-number: QTBUG-44501 Change-Id: I4cffc3b86359cfdaf2ece07e1259f6fa862132bc Reviewed-by: Konstantin Ritt Reviewed-by: Lars Knoll --- src/plugins/platforms/windows/qwindowsfontengine.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp index ca28b822e4..c25b90e98c 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.cpp +++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp @@ -194,10 +194,10 @@ void QWindowsFontEngine::getCMap() _faceId.index = 0; if(cmap) { OUTLINETEXTMETRIC *otm = getOutlineTextMetric(hdc); - designToDevice = QFixed((int)otm->otmEMSquare)/int(otm->otmTextMetrics.tmHeight); + designToDevice = QFixed((int)otm->otmEMSquare)/QFixed::fromReal(fontDef.pixelSize); unitsPerEm = otm->otmEMSquare; x_height = (int)otm->otmsXHeight; - loadKerningPairs(designToDevice); + loadKerningPairs(QFixed((int)otm->otmEMSquare)/int(otm->otmTextMetrics.tmHeight)); _faceId.filename = QFile::encodeName(QString::fromWCharArray((wchar_t *)((char *)otm + (quintptr)otm->otmpFullName))); lineWidth = otm->otmsUnderscoreSize; fsType = otm->otmfsType; @@ -361,7 +361,7 @@ glyph_t QWindowsFontEngine::glyphIndex(uint ucs4) const HGDIOBJ QWindowsFontEngine::selectDesignFont() const { LOGFONT f = m_logfont; - f.lfHeight = unitsPerEm; + f.lfHeight = -unitsPerEm; f.lfWidth = 0; HFONT designFont = CreateFontIndirect(&f); return SelectObject(m_fontEngineData->hdc, designFont); From 6653e49cf295cd052888ec172f17e088970e4ab4 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 9 Mar 2015 11:57:42 +0100 Subject: [PATCH 018/127] Add missing flush for multisampled QOpenGLWidget MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QOpenGLWidget exhibits the same issue as QQuickWidget in the linked bug. Task-number: QTBUG-39917 Change-Id: Ib231fb88f73c6ef68f12cc3fecf462679e8184a7 Reviewed-by: Jørgen Lind --- src/widgets/kernel/qopenglwidget.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp index f63685c37a..3b33894627 100644 --- a/src/widgets/kernel/qopenglwidget.cpp +++ b/src/widgets/kernel/qopenglwidget.cpp @@ -768,6 +768,7 @@ void QOpenGLWidgetPrivate::resolveSamples() q->makeCurrent(); QRect rect(QPoint(0, 0), fbo->size()); QOpenGLFramebufferObject::blitFramebuffer(resolvedFbo, rect, fbo, rect); + QOpenGLContext::currentContext()->functions()->glFlush(); } } From 1cc8ec1e78cedcf4600b216978b3b08bf08ddf66 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Mon, 9 Mar 2015 13:34:26 +0100 Subject: [PATCH 019/127] Remove cruft Change-Id: I8e0bf5b9befb0e9639da15b07072d046c038ea85 Reviewed-by: Gabriel de Dietrich --- .../widgets/qpushbutton/tst_qpushbutton.cpp | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp b/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp index 1833af7af5..c53a7cc5ca 100644 --- a/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp +++ b/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp @@ -76,11 +76,6 @@ private slots: void sizeHint_data(); void sizeHint(); void taskQTBUG_20191_shortcutWithKeypadModifer(); -/* - void state(); - void group(); - void stateChanged(); -*/ protected slots: void resetCounters(); @@ -419,19 +414,6 @@ void tst_QPushButton::clicked() QCOMPARE( release_count, (uint)10 ); } -/* -void tst_QPushButton::group() -{ -} - -void tst_QPushButton::state() -{ -} - -void tst_QPushButton::stateChanged() -{ -} -*/ QPushButton *pb = 0; void tst_QPushButton::helperSlotDelete() { From 4c0c53742140ef6f35a5258e79f62a202fe9832e Mon Sep 17 00:00:00 2001 From: David Edmundson Date: Mon, 9 Mar 2015 19:18:27 +0100 Subject: [PATCH 020/127] Avoid detaching pixmaps when it has not changed setDevicePixelRatio is often called unconditionally even when the devicePixelRatio matches the pixmap or image. This causes a lot of unncessary detaches wasting some memory. Change-Id: I27535b2b22312ec0edc9bdc00c99d322afb727c1 Reviewed-by: Gunnar Sletta --- src/gui/image/qimage.cpp | 4 ++++ src/gui/image/qpixmap.cpp | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index e33ab24243..dba42d4698 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -1433,6 +1433,10 @@ void QImage::setDevicePixelRatio(qreal scaleFactor) { if (!d) return; + + if (scaleFactor == d->devicePixelRatio) + return; + detach(); d->devicePixelRatio = scaleFactor; } diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index 0a9b55ed24..db6ae54d26 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -682,6 +682,9 @@ void QPixmap::setDevicePixelRatio(qreal scaleFactor) if (isNull()) return; + if (scaleFactor == data->devicePixelRatio()) + return; + detach(); data->setDevicePixelRatio(scaleFactor); } From 971b8413f27f6e317e9e37f518fcc1e6b9eed978 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Mon, 9 Mar 2015 14:29:05 +0100 Subject: [PATCH 021/127] QAbstractButton: emit released on focus out or disable When pressing a button with the mouse and then moving the focus away, the internal and visual state of the button would get updated, but the released signal would not be emitted. The same goes for disabling the button, although in 99% of the cases, disabling the button will also move the focus, so the first case already takes care of emitting the signal. Task-number: QTBUG-42775 Change-Id: Ib6ba8e0a75f0349b66d1e799b02bd8498db85022 Reviewed-by: Gabriel de Dietrich --- src/widgets/widgets/qabstractbutton.cpp | 10 ++++-- .../widgets/qpushbutton/tst_qpushbutton.cpp | 32 +++++++++++++++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/widgets/widgets/qabstractbutton.cpp b/src/widgets/widgets/qabstractbutton.cpp index 965278265a..e413b3b87a 100644 --- a/src/widgets/widgets/qabstractbutton.cpp +++ b/src/widgets/widgets/qabstractbutton.cpp @@ -1293,8 +1293,10 @@ void QAbstractButton::focusInEvent(QFocusEvent *e) void QAbstractButton::focusOutEvent(QFocusEvent *e) { Q_D(QAbstractButton); - if (e->reason() != Qt::PopupFocusReason) + if (e->reason() != Qt::PopupFocusReason && d->down) { d->down = false; + d->emitReleased(); + } QWidget::focusOutEvent(e); } @@ -1304,8 +1306,10 @@ void QAbstractButton::changeEvent(QEvent *e) Q_D(QAbstractButton); switch (e->type()) { case QEvent::EnabledChange: - if (!isEnabled()) - setDown(false); + if (!isEnabled() && d->down) { + d->down = false; + d->emitReleased(); + } break; default: d->sizeHint = QSize(); diff --git a/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp b/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp index c53a7cc5ca..4fd8b99acf 100644 --- a/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp +++ b/tests/auto/widgets/widgets/qpushbutton/tst_qpushbutton.cpp @@ -76,6 +76,7 @@ private slots: void sizeHint_data(); void sizeHint(); void taskQTBUG_20191_shortcutWithKeypadModifer(); + void emitReleasedAfterChange(); protected slots: void resetCounters(); @@ -663,5 +664,36 @@ void tst_QPushButton::taskQTBUG_20191_shortcutWithKeypadModifer() QCOMPARE(spy2.count(), 1); } +void tst_QPushButton::emitReleasedAfterChange() +{ + QPushButton *button1 = new QPushButton("A"); + QPushButton *button2 = new QPushButton("B"); + QVBoxLayout *layout = new QVBoxLayout(); + layout->addWidget(button1); + layout->addWidget(button2); + QDialog dialog; + dialog.setLayout(layout); + dialog.show(); + QTest::qWaitForWindowExposed(&dialog); + QApplication::setActiveWindow(&dialog); + button1->setFocus(); + + QSignalSpy spy(button1, SIGNAL(released())); + QTest::mousePress(button1, Qt::LeftButton); + QVERIFY(button1->isDown()); + QTest::keyClick(&dialog, Qt::Key_Tab); + QVERIFY(!button1->isDown()); + QCOMPARE(spy.count(), 1); + spy.clear(); + + QCOMPARE(spy.count(), 0); + button1->setFocus(); + QTest::mousePress(button1, Qt::LeftButton); + QVERIFY(button1->isDown()); + button1->setEnabled(false); + QVERIFY(!button1->isDown()); + QCOMPARE(spy.count(), 1); +} + QTEST_MAIN(tst_QPushButton) #include "tst_qpushbutton.moc" From 35ee5349f2f549d5fe9d9bd57cef7af0047ee2d4 Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Sun, 1 Mar 2015 09:44:10 +0200 Subject: [PATCH 022/127] QIODevice: Fix some 64-bit issues Change-Id: I77354a3069b256135c5792975a1445bcbe816e20 Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qiodevice.cpp | 76 ++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp index ea7e7b2731..7eb917c71f 100644 --- a/src/corelib/io/qiodevice.cpp +++ b/src/corelib/io/qiodevice.cpp @@ -586,7 +586,7 @@ qint64 QIODevice::pos() const { Q_D(const QIODevice); #if defined QIODEVICE_DEBUG - printf("%p QIODevice::pos() == %d\n", this, int(d->pos)); + printf("%p QIODevice::pos() == %lld\n", this, d->pos); #endif return d->pos; } @@ -629,31 +629,30 @@ bool QIODevice::seek(qint64 pos) return false; } if (pos < 0) { - qWarning("QIODevice::seek: Invalid pos: %d", int(pos)); + qWarning("QIODevice::seek: Invalid pos: %lld", pos); return false; } #if defined QIODEVICE_DEBUG - printf("%p QIODevice::seek(%d), before: d->pos = %d, d->buffer.size() = %d\n", - this, int(pos), int(d->pos), d->buffer.size()); + printf("%p QIODevice::seek(%lld), before: d->pos = %lld, d->buffer.size() = %lld\n", + this, pos, d->pos, d->buffer.size()); #endif qint64 offset = pos - d->pos; d->pos = pos; d->devicePos = pos; - if (offset < 0 - || offset >= qint64(d->buffer.size())) + if (offset < 0 || offset >= d->buffer.size()) // When seeking backwards, an operation that is only allowed for // random-access devices, the buffer is cleared. The next read // operation will then refill the buffer. We can optimize this, if we // find that seeking backwards becomes a significant performance hit. d->buffer.clear(); else if (!d->buffer.isEmpty()) - d->buffer.skip(int(offset)); + d->buffer.skip(offset); #if defined QIODEVICE_DEBUG - printf("%p \tafter: d->pos == %d, d->buffer.size() == %d\n", this, int(d->pos), + printf("%p \tafter: d->pos == %lld, d->buffer.size() == %lld\n", this, d->pos, d->buffer.size()); #endif return true; @@ -675,8 +674,9 @@ bool QIODevice::atEnd() const { Q_D(const QIODevice); #if defined QIODEVICE_DEBUG - printf("%p QIODevice::atEnd() returns %s, d->openMode == %d, d->pos == %d\n", this, (d->openMode == NotOpen || d->pos == size()) ? "true" : "false", - int(d->openMode), int(d->pos)); + printf("%p QIODevice::atEnd() returns %s, d->openMode == %d, d->pos == %lld\n", this, + (d->openMode == NotOpen || d->pos == size()) ? "true" : "false", int(d->openMode), + d->pos); #endif return d->openMode == NotOpen || (d->buffer.isEmpty() && bytesAvailable() == 0); } @@ -749,8 +749,8 @@ qint64 QIODevice::read(char *data, qint64 maxSize) Q_D(QIODevice); #if defined QIODEVICE_DEBUG - printf("%p QIODevice::read(%p, %d), d->pos = %d, d->buffer.size() = %d\n", - this, data, int(maxSize), int(d->pos), int(d->buffer.size())); + printf("%p QIODevice::read(%p, %lld), d->pos = %lld, d->buffer.size() = %lld\n", + this, data, maxSize, d->pos, d->buffer.size()); #endif const bool sequential = d->isSequential(); @@ -791,8 +791,8 @@ qint64 QIODevice::read(char *data, qint64 maxSize) data += bufferReadChunkSize; maxSize -= bufferReadChunkSize; #if defined QIODEVICE_DEBUG - printf("%p \treading %d bytes from buffer into position %d\n", this, - bufferReadChunkSize, int(readSoFar) - bufferReadChunkSize); + printf("%p \treading %lld bytes from buffer into position %lld\n", this, + bufferReadChunkSize, readSoFar - bufferReadChunkSize); #endif } else { if (d->firstRead) { @@ -813,8 +813,8 @@ qint64 QIODevice::read(char *data, qint64 maxSize) readFromDevice = readData(data, maxSize); deviceAtEof = (readFromDevice != maxSize); #if defined QIODEVICE_DEBUG - printf("%p \treading %d bytes from device (total %d)\n", this, - int(readFromDevice), int(readSoFar)); + printf("%p \treading %lld bytes from device (total %lld)\n", this, + readFromDevice, readSoFar); #endif if (readFromDevice > 0) { readSoFar += readFromDevice; @@ -826,17 +826,17 @@ qint64 QIODevice::read(char *data, qint64 maxSize) } } } else { - const int bytesToBuffer = QIODEVICE_BUFFERSIZE; + const qint64 bytesToBuffer = QIODEVICE_BUFFERSIZE; // Try to fill QIODevice buffer by single read readFromDevice = readData(d->buffer.reserve(bytesToBuffer), bytesToBuffer); deviceAtEof = (readFromDevice != bytesToBuffer); - d->buffer.chop(bytesToBuffer - qMax(0, int(readFromDevice))); + d->buffer.chop(bytesToBuffer - qMax(Q_INT64_C(0), readFromDevice)); if (readFromDevice > 0) { if (!sequential) d->devicePos += readFromDevice; #if defined QIODEVICE_DEBUG - printf("%p \treading %d from device into buffer\n", this, - int(readFromDevice)); + printf("%p \treading %lld from device into buffer\n", this, + readFromDevice); #endif continue; } @@ -884,8 +884,8 @@ qint64 QIODevice::read(char *data, qint64 maxSize) } #if defined QIODEVICE_DEBUG - printf("%p \treturning %d, d->pos == %d, d->buffer.size() == %d\n", this, - int(readSoFar), int(d->pos), d->buffer.size()); + printf("%p \treturning %lld, d->pos == %lld, d->buffer.size() == %lld\n", this, + readSoFar, d->pos, d->buffer.size()); debugBinaryString(data - readSoFar, readSoFar); #endif @@ -916,8 +916,8 @@ QByteArray QIODevice::read(qint64 maxSize) CHECK_MAXLEN(read, result); #if defined QIODEVICE_DEBUG - printf("%p QIODevice::read(%d), d->pos = %d, d->buffer.size() = %d\n", - this, int(maxSize), int(d->pos), int(d->buffer.size())); + printf("%p QIODevice::read(%lld), d->pos = %lld, d->buffer.size() = %lld\n", + this, maxSize, d->pos, d->buffer.size()); #else Q_UNUSED(d); #endif @@ -966,8 +966,8 @@ QByteArray QIODevice::readAll() { Q_D(QIODevice); #if defined QIODEVICE_DEBUG - printf("%p QIODevice::readAll(), d->pos = %d, d->buffer.size() = %d\n", - this, int(d->pos), int(d->buffer.size())); + printf("%p QIODevice::readAll(), d->pos = %lld, d->buffer.size() = %lld\n", + this, d->pos, d->buffer.size()); #endif QByteArray result; @@ -1054,8 +1054,8 @@ qint64 QIODevice::readLine(char *data, qint64 maxSize) } #if defined QIODEVICE_DEBUG - printf("%p QIODevice::readLine(%p, %d), d->pos = %d, d->buffer.size() = %d\n", - this, data, int(maxSize), int(d->pos), int(d->buffer.size())); + printf("%p QIODevice::readLine(%p, %lld), d->pos = %lld, d->buffer.size() = %lld\n", + this, data, maxSize, d->pos, d->buffer.size()); #endif // Leave room for a '\0' @@ -1071,8 +1071,8 @@ qint64 QIODevice::readLine(char *data, qint64 maxSize) if (!sequential) d->pos += readSoFar; #if defined QIODEVICE_DEBUG - printf("%p \tread from buffer: %d bytes, last character read: %hhx\n", this, - int(readSoFar), data[int(readSoFar) - 1]); + printf("%p \tread from buffer: %lld bytes, last character read: %hhx\n", this, + readSoFar, data[readSoFar - 1]); if (readSoFar) debugBinaryString(data, int(readSoFar)); #endif @@ -1094,8 +1094,8 @@ qint64 QIODevice::readLine(char *data, qint64 maxSize) d->baseReadLineDataCalled = false; qint64 readBytes = readLineData(data + readSoFar, maxSize - readSoFar); #if defined QIODEVICE_DEBUG - printf("%p \tread from readLineData: %d bytes, readSoFar = %d bytes\n", this, - int(readBytes), int(readSoFar)); + printf("%p \tread from readLineData: %lld bytes, readSoFar = %lld bytes\n", this, + readBytes, readSoFar); if (readBytes > 0) { debugBinaryString(data, int(readSoFar + readBytes)); } @@ -1122,8 +1122,8 @@ qint64 QIODevice::readLine(char *data, qint64 maxSize) } #if defined QIODEVICE_DEBUG - printf("%p \treturning %d, d->pos = %d, d->buffer.size() = %d, size() = %d\n", - this, int(readSoFar), int(d->pos), d->buffer.size(), int(size())); + printf("%p \treturning %lld, d->pos = %lld, d->buffer.size() = %lld, size() = %lld\n", + this, readSoFar, d->pos, d->buffer.size(), size()); debugBinaryString(data, int(readSoFar)); #endif return readSoFar; @@ -1147,8 +1147,8 @@ QByteArray QIODevice::readLine(qint64 maxSize) CHECK_MAXLEN(readLine, result); #if defined QIODEVICE_DEBUG - printf("%p QIODevice::readLine(%d), d->pos = %d, d->buffer.size() = %d\n", - this, int(maxSize), int(d->pos), int(d->buffer.size())); + printf("%p QIODevice::readLine(%lld), d->pos = %lld, d->buffer.size() = %lld\n", + this, maxSize, d->pos, d->buffer.size()); #else Q_UNUSED(d); #endif @@ -1220,8 +1220,8 @@ qint64 QIODevice::readLineData(char *data, qint64 maxSize) } #if defined QIODEVICE_DEBUG - printf("%p QIODevice::readLineData(%p, %d), d->pos = %d, d->buffer.size() = %d, returns %d\n", - this, data, int(maxSize), int(d->pos), int(d->buffer.size()), int(readSoFar)); + printf("%p QIODevice::readLineData(%p, %lld), d->pos = %lld, d->buffer.size() = %lld, " + "returns %lld\n", this, data, maxSize, d->pos, d->buffer.size(), readSoFar); #endif if (lastReadReturn != 1 && readSoFar == 0) return isSequential() ? lastReadReturn : -1; From d96c29a5d14d142e81e5a2fd1b838a85a0fca187 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 9 Mar 2015 14:06:51 +0100 Subject: [PATCH 023/127] Reload QLibraryInfo's settings when QCoreApplication becomes available Some of the paths may only be resolvable if the application path is known. On some platforms we can only figure out the application path if argv[0] is known. Thus, if the paths have been queried before the QCoreApplication is created, the cached settings may be wrong. We have to reload them after creating the QCoreApplication. Task-number: QTBUG-38598 Change-Id: Idf5822be87aa0872b099480040acd7b49939a22c Reviewed-by: Oswald Buddenhagen --- src/corelib/global/qlibraryinfo.cpp | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index 322fc2f651..24afe719c1 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -63,12 +63,16 @@ extern void qDumpCPUFeatures(); // in qsimd.cpp struct QLibrarySettings { QLibrarySettings(); + void load(); + QScopedPointer settings; #ifdef QT_BUILD_QMAKE bool haveDevicePaths; bool haveEffectiveSourcePaths; bool haveEffectivePaths; bool havePaths; +#else + bool reloadOnQAppAvailable; #endif }; Q_GLOBAL_STATIC(QLibrarySettings, qt_library_settings) @@ -93,16 +97,31 @@ public: static QSettings *configuration() { QLibrarySettings *ls = qt_library_settings(); - return ls ? ls->settings.data() : 0; + if (ls) { +#ifndef QT_BUILD_QMAKE + if (ls->reloadOnQAppAvailable && QCoreApplication::instance() != 0) + ls->load(); +#endif + return ls->settings.data(); + } else { + return 0; + } } }; static const char platformsSection[] = "Platforms"; QLibrarySettings::QLibrarySettings() - : settings(QLibraryInfoPrivate::findConfiguration()) { + load(); +} + +void QLibrarySettings::load() +{ + // If we get any settings here, those won't change when the application shows up. + settings.reset(QLibraryInfoPrivate::findConfiguration()); #ifndef QT_BUILD_QMAKE + reloadOnQAppAvailable = (settings.data() == 0 && QCoreApplication::instance() == 0); bool haveDevicePaths; bool haveEffectivePaths; bool havePaths; From 1fc6056ff5526e61419262931de79137bf7c1b4d Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 9 Mar 2015 17:42:19 +0100 Subject: [PATCH 024/127] Detect qt.conf in bundle on OSX without QCoreApplication On OSX we don't need the applicationDirPath to find a qt.conf located in the application bundle. Let's take advantage of this and allow findConfiguration to use it. Task-number: QTBUG-24541 Change-Id: I38c349a3bcd140fcf91352c88c24ca662e6e6f2e Reviewed-by: Oswald Buddenhagen --- src/corelib/global/qlibraryinfo.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index 24afe719c1..484c7869a6 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -162,7 +162,7 @@ QSettings *QLibraryInfoPrivate::findConfiguration() if(!QFile::exists(qtconfig)) qtconfig = qmake_libraryInfoFile(); #else - if (!QFile::exists(qtconfig) && QCoreApplication::instance()) { + if (!QFile::exists(qtconfig)) { #ifdef Q_OS_MAC CFBundleRef bundleRef = CFBundleGetMainBundle(); if (bundleRef) { @@ -177,10 +177,12 @@ QSettings *QLibraryInfoPrivate::findConfiguration() } if (qtconfig.isEmpty()) #endif - { + { + if (QCoreApplication::instance()) { QDir pwd(QCoreApplication::applicationDirPath()); qtconfig = pwd.filePath(QLatin1String("qt.conf")); } + } } #endif if (QFile::exists(qtconfig)) From 3ce88e13b9cc56e00bc3f075e9649c6b291ae01c Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 9 Mar 2015 10:16:18 +0100 Subject: [PATCH 025/127] Add AVX2 autovectorized versions of premultiply Following up on using GCC's autovectorizing for faster SSE4.1 premultiply, this patch adds specialized autovectorized versions of premultiply for AVX2, giving another almost doubling in speed. To make the speed up for AVX2 and also SSE4_1 available to non-GCC compilers, the target-specific methods have been moved to separate files. Change-Id: I97ce05be67f4adeeb9a096eef80fd5fb662099f3 Reviewed-by: Gunnar Sletta --- src/gui/image/image.pri | 2 + src/gui/image/qimage_avx2.cpp | 61 +++++++++++++++++++ src/gui/image/qimage_conversions.cpp | 42 ++++++------- src/gui/image/qimage_sse4.cpp | 70 ++++++++++++++++++++++ src/gui/painting/painting.pri | 2 + src/gui/painting/qdrawhelper.cpp | 85 +++++++-------------------- src/gui/painting/qdrawhelper_avx2.cpp | 54 +++++++++++++++++ src/gui/painting/qdrawhelper_p.h | 16 +++++ src/gui/painting/qdrawhelper_sse4.cpp | 79 +++++++++++++++++++++++++ 9 files changed, 321 insertions(+), 90 deletions(-) create mode 100644 src/gui/image/qimage_avx2.cpp create mode 100644 src/gui/image/qimage_sse4.cpp create mode 100644 src/gui/painting/qdrawhelper_avx2.cpp create mode 100644 src/gui/painting/qdrawhelper_sse4.cpp diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri index 7022a6efd0..8db944e5e3 100644 --- a/src/gui/image/image.pri +++ b/src/gui/image/image.pri @@ -80,6 +80,8 @@ contains(QT_CONFIG, gif):include($$PWD/qgifhandler.pri) # SIMD SSE2_SOURCES += image/qimage_sse2.cpp SSSE3_SOURCES += image/qimage_ssse3.cpp +SSE4_1_SOURCES += image/qimage_sse4.cpp +AVX2_SOURCES += image/qimage_avx2.cpp NEON_SOURCES += image/qimage_neon.cpp MIPS_DSPR2_SOURCES += image/qimage_mips_dspr2.cpp MIPS_DSPR2_ASM += image/qimage_mips_dspr2_asm.S diff --git a/src/gui/image/qimage_avx2.cpp b/src/gui/image/qimage_avx2.cpp new file mode 100644 index 0000000000..c52baec948 --- /dev/null +++ b/src/gui/image/qimage_avx2.cpp @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include + +#ifdef QT_COMPILER_SUPPORTS_AVX2 + +QT_BEGIN_NAMESPACE + +void convert_ARGB_to_ARGB_PM_avx2(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) +{ + Q_ASSERT(src->format == QImage::Format_ARGB32 || src->format == QImage::Format_RGBA8888); + Q_ASSERT(dest->format == QImage::Format_ARGB32_Premultiplied || dest->format == QImage::Format_RGBA8888_Premultiplied); + Q_ASSERT(src->width == dest->width); + Q_ASSERT(src->height == dest->height); + + const uint *src_data = (uint *) src->data; + uint *dest_data = (uint *) dest->data; + for (int i = 0; i < src->height; ++i) { + qt_convertARGB32ToARGB32PM(dest_data, src_data, src->width); + src_data += src->bytes_per_line >> 2; + dest_data += dest->bytes_per_line >> 2; + } +} + +QT_END_NAMESPACE + +#endif // QT_COMPILER_SUPPORTS_AVX2 diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index 5103d820d6..fe76c6d3ba 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -32,7 +32,6 @@ ****************************************************************************/ #include -#include #include #include #include @@ -110,17 +109,6 @@ static const uint *QT_FASTCALL convertRGB32FromARGB32PM(uint *buffer, const uint return buffer; } -#if QT_COMPILER_SUPPORTS_HERE(SSE4_1) -QT_FUNCTION_TARGET(SSE4_1) -static const uint *QT_FASTCALL convertRGB32FromARGB32PM_sse4(uint *buffer, const uint *src, int count, - const QPixelLayout *, const QRgb *) -{ - for (int i = 0; i < count; ++i) - buffer[i] = 0xff000000 | qUnpremultiply_sse4(src[i]); - return buffer; -} -#endif - static const uint *QT_FASTCALL convertRGB32ToARGB32PM(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *) { @@ -129,6 +117,10 @@ static const uint *QT_FASTCALL convertRGB32ToARGB32PM(uint *buffer, const uint * return buffer; } +#ifdef QT_COMPILER_SUPPORTS_SSE4_1 +extern const uint *QT_FASTCALL convertRGB32FromARGB32PM_sse4(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *); +#endif + void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) { // Cannot be used with indexed formats. @@ -152,7 +144,7 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio if (src->format == QImage::Format_RGB32) convertToARGB32PM = convertRGB32ToARGB32PM; if (dest->format == QImage::Format_RGB32) { -#if QT_COMPILER_SUPPORTS_HERE(SSE4_1) +#ifdef QT_COMPILER_SUPPORTS_SSE4_1 if (qCpuHasFeature(SSE4_1)) convertFromARGB32PM = convertRGB32FromARGB32PM_sse4; else @@ -201,7 +193,7 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im if (data->format == QImage::Format_RGB32) convertToARGB32PM = convertRGB32ToARGB32PM; if (dst_format == QImage::Format_RGB32) { -#if QT_COMPILER_SUPPORTS_HERE(SSE4_1) +#ifdef QT_COMPILER_SUPPORTS_SSE4_1 if (qCpuHasFeature(SSE4_1)) convertFromARGB32PM = convertRGB32FromARGB32PM_sse4; else @@ -257,7 +249,7 @@ static bool convert_passthrough_inplace(QImageData *data, Qt::ImageConversionFla return true; } -static inline void convert_ARGB_to_ARGB_PM(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) +static void convert_ARGB_to_ARGB_PM(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) { Q_ASSERT(src->format == QImage::Format_ARGB32 || src->format == QImage::Format_RGBA8888); Q_ASSERT(dest->format == QImage::Format_ARGB32_Premultiplied || dest->format == QImage::Format_RGBA8888_Premultiplied); @@ -281,15 +273,6 @@ static inline void convert_ARGB_to_ARGB_PM(QImageData *dest, const QImageData *s } } -#if QT_COMPILER_SUPPORTS_HERE(SSE4_1) && !defined(__SSE4_1__) -QT_FUNCTION_TARGET(SSE4_1) -static void convert_ARGB_to_ARGB_PM_sse4(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags flags) -{ - // Twice as fast autovectorized due to SSE4.1 PMULLD instructions. - convert_ARGB_to_ARGB_PM(dest, src, flags); -} -#endif - Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32(quint32 *dest_data, const uchar *src_data, int len) { int pixel = 0; @@ -2804,13 +2787,22 @@ void qInitImageConversions() } #endif -#if QT_COMPILER_SUPPORTS_HERE(SSE4_1) && !defined(__SSE4_1__) +#if defined(QT_COMPILER_SUPPORTS_SSE4_1) && !defined(__SSE4_1__) if (qCpuHasFeature(SSE4_1)) { + extern void convert_ARGB_to_ARGB_PM_sse4(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags); qimage_converter_map[QImage::Format_ARGB32][QImage::Format_ARGB32_Premultiplied] = convert_ARGB_to_ARGB_PM_sse4; qimage_converter_map[QImage::Format_RGBA8888][QImage::Format_RGBA8888_Premultiplied] = convert_ARGB_to_ARGB_PM_sse4; } #endif +#if defined(QT_COMPILER_SUPPORTS_AVX2) && !defined(__AVX2__) + if (qCpuHasFeature(AVX2)) { + extern void convert_ARGB_to_ARGB_PM_avx2(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags); + qimage_converter_map[QImage::Format_ARGB32][QImage::Format_ARGB32_Premultiplied] = convert_ARGB_to_ARGB_PM_avx2; + qimage_converter_map[QImage::Format_RGBA8888][QImage::Format_RGBA8888_Premultiplied] = convert_ARGB_to_ARGB_PM_avx2; + } +#endif + #if defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64) extern void convert_RGB888_to_RGB32_neon(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags); qimage_converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_neon; diff --git a/src/gui/image/qimage_sse4.cpp b/src/gui/image/qimage_sse4.cpp new file mode 100644 index 0000000000..5fad4f572a --- /dev/null +++ b/src/gui/image/qimage_sse4.cpp @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include + +#ifdef QT_COMPILER_SUPPORTS_SSE4_1 + +QT_BEGIN_NAMESPACE + +const uint *QT_FASTCALL convertRGB32FromARGB32PM_sse4(uint *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ + for (int i = 0; i < count; ++i) + buffer[i] = 0xff000000 | qUnpremultiply_sse4(src[i]); + return buffer; +} + +void convert_ARGB_to_ARGB_PM_sse4(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) +{ + Q_ASSERT(src->format == QImage::Format_ARGB32 || src->format == QImage::Format_RGBA8888); + Q_ASSERT(dest->format == QImage::Format_ARGB32_Premultiplied || dest->format == QImage::Format_RGBA8888_Premultiplied); + Q_ASSERT(src->width == dest->width); + Q_ASSERT(src->height == dest->height); + + const uint *src_data = (uint *) src->data; + uint *dest_data = (uint *) dest->data; + for (int i = 0; i < src->height; ++i) { + qt_convertARGB32ToARGB32PM(dest_data, src_data, src->width); + src_data += src->bytes_per_line >> 2; + dest_data += dest->bytes_per_line >> 2; + } +} + +QT_END_NAMESPACE + +#endif // QT_COMPILER_SUPPORTS_SSE4_1 diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 6ee1beaa3c..2f2d3daaf8 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -93,6 +93,8 @@ SOURCES += \ SSE2_SOURCES += painting/qdrawhelper_sse2.cpp SSSE3_SOURCES += painting/qdrawhelper_ssse3.cpp +SSE4_1_SOURCES += painting/qdrawhelper_sse4.cpp +AVX2_SOURCES += painting/qdrawhelper_avx2.cpp !ios { CONFIG += no_clang_integrated_as diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 04857fb0d6..0b269cc5a7 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -355,25 +355,12 @@ static const uint *QT_FASTCALL convertPassThrough(uint *, const uint *src, int, return src; } -static inline const uint *QT_FASTCALL convertARGB32ToARGB32PM(uint *buffer, const uint *src, int count, - const QPixelLayout *, const QRgb *) +static const uint *QT_FASTCALL convertARGB32ToARGB32PM(uint *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) { - for (int i = 0; i < count; ++i) - buffer[i] = qPremultiply(src[i]); - return buffer; + return qt_convertARGB32ToARGB32PM(buffer, src, count); } -#if QT_COMPILER_SUPPORTS_HERE(SSE4_1) && !defined(__SSE4_1__) -QT_FUNCTION_TARGET(SSE4_1) -static const uint *QT_FASTCALL convertARGB32ToARGB32PM_sse4(uint *buffer, const uint *src, int count, - const QPixelLayout *layout, const QRgb *clut) -{ - // Twice as fast autovectorized due to SSE4.1 PMULLD instructions. - return convertARGB32ToARGB32PM(buffer, src, count, layout, clut); -} -#endif - - static const uint *QT_FASTCALL convertRGBA8888PMToARGB32PM(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *) { @@ -382,24 +369,12 @@ static const uint *QT_FASTCALL convertRGBA8888PMToARGB32PM(uint *buffer, const u return buffer; } -static inline const uint *QT_FASTCALL convertRGBA8888ToARGB32PM(uint *buffer, const uint *src, int count, +static const uint *QT_FASTCALL convertRGBA8888ToARGB32PM(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *) { - for (int i = 0; i < count; ++i) - buffer[i] = qPremultiply(RGBA2ARGB(src[i])); - return buffer; + return qt_convertRGBA8888ToARGB32PM(buffer, src, count); } -#if QT_COMPILER_SUPPORTS_HERE(SSE4_1) && !defined(__SSE4_1__) -QT_FUNCTION_TARGET(SSE4_1) -static const uint *QT_FASTCALL convertRGBA8888ToARGB32PM_sse4(uint *buffer, const uint *src, int count, - const QPixelLayout *layout, const QRgb *clut) -{ - // Twice as fast autovectorized due to SSE4.1 PMULLD instructions. - return convertRGBA8888ToARGB32PM(buffer, src, count, layout, clut); -} -#endif - static const uint *QT_FASTCALL convertAlpha8ToRGB32(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *) { @@ -424,18 +399,6 @@ static const uint *QT_FASTCALL convertARGB32FromARGB32PM(uint *buffer, const uin return buffer; } -#if QT_COMPILER_SUPPORTS_HERE(SSE4_1) -QT_FUNCTION_TARGET(SSE4_1) -static const uint *QT_FASTCALL convertARGB32FromARGB32PM_sse4(uint *buffer, const uint *src, int count, - const QPixelLayout *, const QRgb *) -{ - for (int i = 0; i < count; ++i) - buffer[i] = qUnpremultiply_sse4(src[i]); - return buffer; -} -#endif - - static const uint *QT_FASTCALL convertRGBA8888PMFromARGB32PM(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *) { @@ -452,17 +415,6 @@ static const uint *QT_FASTCALL convertRGBA8888FromARGB32PM(uint *buffer, const u return buffer; } -#if QT_COMPILER_SUPPORTS_HERE(SSE4_1) -QT_FUNCTION_TARGET(SSE4_1) -static const uint *QT_FASTCALL convertRGBA8888FromARGB32PM_sse4(uint *buffer, const uint *src, int count, - const QPixelLayout *, const QRgb *) -{ - for (int i = 0; i < count; ++i) - buffer[i] = ARGB2RGBA(qUnpremultiply_sse4(src[i])); - return buffer; -} -#endif - static const uint *QT_FASTCALL convertRGBXFromRGB32(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *) { @@ -479,17 +431,6 @@ static const uint *QT_FASTCALL convertRGBXFromARGB32PM(uint *buffer, const uint return buffer; } -#if QT_COMPILER_SUPPORTS_HERE(SSE4_1) -QT_FUNCTION_TARGET(SSE4_1) -static const uint *QT_FASTCALL convertRGBXFromARGB32PM_sse4(uint *buffer, const uint *src, int count, - const QPixelLayout *, const QRgb *) -{ - for (int i = 0; i < count; ++i) - buffer[i] = ARGB2RGBA(0xff000000 | qUnpremultiply_sse4(src[i])); - return buffer; -} -#endif - template static const uint *QT_FASTCALL convertA2RGB30PMToARGB32PM(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *) @@ -6793,18 +6734,32 @@ void qInitDrawhelperAsm() } #endif // SSSE3 -#if QT_COMPILER_SUPPORTS_HERE(SSE4_1) +#if QT_COMPILER_SUPPORTS_SSE4_1 if (qCpuHasFeature(SSE4_1)) { #if !defined(__SSE4_1__) + extern const uint *QT_FASTCALL convertARGB32ToARGB32PM_sse4(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *); + extern const uint *QT_FASTCALL convertRGBA8888ToARGB32PM_sse4(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *); qPixelLayouts[QImage::Format_ARGB32].convertToARGB32PM = convertARGB32ToARGB32PM_sse4; qPixelLayouts[QImage::Format_RGBA8888].convertToARGB32PM = convertRGBA8888ToARGB32PM_sse4; #endif + extern const uint *QT_FASTCALL convertARGB32FromARGB32PM_sse4(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *); + extern const uint *QT_FASTCALL convertRGBA8888FromARGB32PM_sse4(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *); + extern const uint *QT_FASTCALL convertRGBXFromARGB32PM_sse4(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *); qPixelLayouts[QImage::Format_ARGB32].convertFromARGB32PM = convertARGB32FromARGB32PM_sse4; qPixelLayouts[QImage::Format_RGBA8888].convertFromARGB32PM = convertRGBA8888FromARGB32PM_sse4; qPixelLayouts[QImage::Format_RGBX8888].convertFromARGB32PM = convertRGBXFromARGB32PM_sse4; } #endif +#if QT_COMPILER_SUPPORTS_AVX2 && !defined(__AVX2__) + if (qCpuHasFeature(AVX2)) { + extern const uint *QT_FASTCALL convertARGB32ToARGB32PM_avx2(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *); + extern const uint *QT_FASTCALL convertRGBA8888ToARGB32PM_avx2(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *); + qPixelLayouts[QImage::Format_ARGB32].convertToARGB32PM = convertARGB32ToARGB32PM_avx2; + qPixelLayouts[QImage::Format_RGBA8888].convertToARGB32PM = convertRGBA8888ToARGB32PM_avx2; + } +#endif + functionForModeAsm = qt_functionForMode_SSE2; functionForModeSolidAsm = qt_functionForModeSolid_SSE2; #endif // SSE2 diff --git a/src/gui/painting/qdrawhelper_avx2.cpp b/src/gui/painting/qdrawhelper_avx2.cpp new file mode 100644 index 0000000000..5716be682b --- /dev/null +++ b/src/gui/painting/qdrawhelper_avx2.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#if defined(QT_COMPILER_SUPPORTS_AVX2) + +QT_BEGIN_NAMESPACE + +const uint *QT_FASTCALL convertARGB32ToARGB32PM_avx2(uint *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ + return qt_convertARGB32ToARGB32PM(buffer, src, count); +} + +const uint *QT_FASTCALL convertRGBA8888ToARGB32PM_avx2(uint *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ + return qt_convertRGBA8888ToARGB32PM(buffer, src, count); +} + +QT_END_NAMESPACE + +#endif diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h index 08bc0776f7..51e51fd53f 100644 --- a/src/gui/painting/qdrawhelper_p.h +++ b/src/gui/painting/qdrawhelper_p.h @@ -893,6 +893,22 @@ inline int qBlue565(quint16 rgb) { return (b << 3) | (b >> 2); } + +static Q_ALWAYS_INLINE const uint *qt_convertARGB32ToARGB32PM(uint *buffer, const uint *src, int count) +{ + for (int i = 0; i < count; ++i) + buffer[i] = qPremultiply(src[i]); + return buffer; +} + +static Q_ALWAYS_INLINE const uint *qt_convertRGBA8888ToARGB32PM(uint *buffer, const uint *src, int count) +{ + for (int i = 0; i < count; ++i) + buffer[i] = qPremultiply(RGBA2ARGB(src[i])); + return buffer; +} + + const uint qt_bayer_matrix[16][16] = { { 0x1, 0xc0, 0x30, 0xf0, 0xc, 0xcc, 0x3c, 0xfc, 0x3, 0xc3, 0x33, 0xf3, 0xf, 0xcf, 0x3f, 0xff}, diff --git a/src/gui/painting/qdrawhelper_sse4.cpp b/src/gui/painting/qdrawhelper_sse4.cpp new file mode 100644 index 0000000000..43a3958997 --- /dev/null +++ b/src/gui/painting/qdrawhelper_sse4.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#if defined(QT_COMPILER_SUPPORTS_SSE4_1) + +QT_BEGIN_NAMESPACE + +const uint *QT_FASTCALL convertARGB32ToARGB32PM_sse4(uint *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ + return qt_convertARGB32ToARGB32PM(buffer, src, count); +} + +const uint *QT_FASTCALL convertRGBA8888ToARGB32PM_sse4(uint *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ + return qt_convertRGBA8888ToARGB32PM(buffer, src, count); +} + +const uint *QT_FASTCALL convertARGB32FromARGB32PM_sse4(uint *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ + for (int i = 0; i < count; ++i) + buffer[i] = qUnpremultiply_sse4(src[i]); + return buffer; +} + +const uint *QT_FASTCALL convertRGBA8888FromARGB32PM_sse4(uint *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ + for (int i = 0; i < count; ++i) + buffer[i] = ARGB2RGBA(qUnpremultiply_sse4(src[i])); + return buffer; +} + +const uint *QT_FASTCALL convertRGBXFromARGB32PM_sse4(uint *buffer, const uint *src, int count, + const QPixelLayout *, const QRgb *) +{ + for (int i = 0; i < count; ++i) + buffer[i] = ARGB2RGBA(0xff000000 | qUnpremultiply_sse4(src[i])); + return buffer; +} + +QT_END_NAMESPACE + +#endif From 4c542ab592ccd409639aed30f0a5efc965a3c3c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 9 Mar 2015 19:30:10 +0100 Subject: [PATCH 026/127] iOS: Handle an QIOSViewController outliving its related QIOSScreen We release the UIWindow that retains QIOSViewController in the QIOSScreen destructor, but other parts of the OS may have retained the view controller, so the dealloc may not happen until later. In the meantime we may receive calls to shouldAutorotate, so we need to guard this code for the situation that m_screen has been deleted. Change-Id: Iefeb75f4fc698b5e80417ffd3a971b7de625bcd5 Reviewed-by: Richard Moe Gustavsen --- src/plugins/platforms/ios/qiosviewcontroller.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm index 02c3a2d28d..d144b419aa 100644 --- a/src/plugins/platforms/ios/qiosviewcontroller.mm +++ b/src/plugins/platforms/ios/qiosviewcontroller.mm @@ -238,7 +238,7 @@ -(BOOL)shouldAutorotate { - return m_screen->uiScreen() == [UIScreen mainScreen] && !self.lockedOrientation; + return m_screen && m_screen->uiScreen() == [UIScreen mainScreen] && !self.lockedOrientation; } #if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_6_0) From dfd6fc7bce67eaddf4333c65d8d160a6ca4a8e82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 9 Mar 2015 20:37:50 +0100 Subject: [PATCH 027/127] iOS: Only use root level native runloop if at first level of processEvents We used to support calling QEventLoop::exec() from within a processEvent recursion and still jump down to the root native runloop, but this does not work as intended due to how QEventDispatcherCoreFoundation uses flags in its ProcessEventsState for e.g. deferred wake up or timer updates. The logic in QEventDispatcherCoreFoundation assumes that the next recursion to processEvents will be handled by itself, so that it can interpret the flags in ProcessEventsState. The iOS event dispatcher subclass, QIOSEventDispatcher, does neither of these things, and should only be used from a 'clean' state. Change-Id: I44fa156feecc45772806002465c35bef0797ead2 Reviewed-by: Richard Moe Gustavsen --- .../platforms/ios/qioseventdispatcher.h | 2 +- .../platforms/ios/qioseventdispatcher.mm | 20 ++++++++----------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/plugins/platforms/ios/qioseventdispatcher.h b/src/plugins/platforms/ios/qioseventdispatcher.h index 3a6b67f72e..fdaa7e68fe 100644 --- a/src/plugins/platforms/ios/qioseventdispatcher.h +++ b/src/plugins/platforms/ios/qioseventdispatcher.h @@ -52,7 +52,7 @@ public: void interruptEventLoopExec(); private: - uint m_processEventCallsAfterExec; + uint m_processEventLevel; RunLoopObserver m_runLoopExitObserver; }; diff --git a/src/plugins/platforms/ios/qioseventdispatcher.mm b/src/plugins/platforms/ios/qioseventdispatcher.mm index f4567f36f4..fc12e83a81 100644 --- a/src/plugins/platforms/ios/qioseventdispatcher.mm +++ b/src/plugins/platforms/ios/qioseventdispatcher.mm @@ -422,7 +422,7 @@ QT_USE_NAMESPACE QIOSEventDispatcher::QIOSEventDispatcher(QObject *parent) : QEventDispatcherCoreFoundation(parent) - , m_processEventCallsAfterExec(0) + , m_processEventLevel(0) , m_runLoopExitObserver(this, &QIOSEventDispatcher::handleRunLoopExit, kCFRunLoopExit) { } @@ -439,8 +439,8 @@ bool __attribute__((returns_twice)) QIOSEventDispatcher::processEvents(QEventLoo return false; } - if (!m_processEventCallsAfterExec && (flags & QEventLoop::EventLoopExec)) { - ++m_processEventCallsAfterExec; + if (!m_processEventLevel && (flags & QEventLoop::EventLoopExec)) { + ++m_processEventLevel; m_runLoopExitObserver.addToMode(kCFRunLoopCommonModes); @@ -465,13 +465,9 @@ bool __attribute__((returns_twice)) QIOSEventDispatcher::processEvents(QEventLoo Q_UNREACHABLE(); } - if (m_processEventCallsAfterExec) - ++m_processEventCallsAfterExec; - + ++m_processEventLevel; bool processedEvents = QEventDispatcherCoreFoundation::processEvents(flags); - - if (m_processEventCallsAfterExec) - --m_processEventCallsAfterExec; + --m_processEventLevel; return processedEvents; } @@ -481,7 +477,7 @@ void QIOSEventDispatcher::handleRunLoopExit(CFRunLoopActivity activity) Q_UNUSED(activity); Q_ASSERT(activity == kCFRunLoopExit); - if (m_processEventCallsAfterExec == 1 && !QThreadData::current()->eventLoops.top()->isRunning()) { + if (m_processEventLevel == 1 && !QThreadData::current()->eventLoops.top()->isRunning()) { qEventDispatcherDebug() << "Root runloop level exited"; interruptEventLoopExec(); } @@ -489,9 +485,9 @@ void QIOSEventDispatcher::handleRunLoopExit(CFRunLoopActivity activity) void QIOSEventDispatcher::interruptEventLoopExec() { - Q_ASSERT(m_processEventCallsAfterExec == 1); + Q_ASSERT(m_processEventLevel == 1); - --m_processEventCallsAfterExec; + --m_processEventLevel; m_runLoopExitObserver.removeFromMode(kCFRunLoopCommonModes); From de92efd44812640aefa4f02fb8d9f8f6d04de688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 9 Mar 2015 17:39:35 +0100 Subject: [PATCH 028/127] CF event dispatcher: Decide if eventsProcessed before breaking out of loop In the case of calling processEvents with WaitForMoreEvents and ending up processing a Qt timer, we explicitly interrupt the runloop, as CF doesn't normally treat handling timers as having handled a source. That way we can re-evaluate whether processEvents should return. But, we need to compute eventsProcessed before breaking out of the Q_FOREVER loop, otherwise processEvents will return false when waiting for events and processing a timer. Change-Id: Ie5f8905228cce1508b5b2e040cf1186820855191 Reviewed-by: Richard Moe Gustavsen --- .../eventdispatchers/qeventdispatcher_cf.mm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/platformsupport/eventdispatchers/qeventdispatcher_cf.mm b/src/platformsupport/eventdispatchers/qeventdispatcher_cf.mm index bd0f89ba2f..13b7dc4358 100644 --- a/src/platformsupport/eventdispatchers/qeventdispatcher_cf.mm +++ b/src/platformsupport/eventdispatchers/qeventdispatcher_cf.mm @@ -268,6 +268,10 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag qUnIndent(); qEventDispatcherDebug() << "result = " << qPrintableResult(result); + eventsProcessed |= (result == kCFRunLoopRunHandledSource + || m_processEvents.processedPostedEvents + || m_processEvents.processedTimers); + if (result == kCFRunLoopRunFinished) { // This should only happen at application shutdown, as the main runloop // will presumably always have sources registered. @@ -302,10 +306,6 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag } } - eventsProcessed |= (result == kCFRunLoopRunHandledSource - || m_processEvents.processedPostedEvents - || m_processEvents.processedTimers); - if (m_processEvents.flags & QEventLoop::EventLoopExec) { // We were called from QEventLoop's exec(), which blocks until the event // loop is asked to exit by calling processEvents repeatedly. Instead of From a29b7635bd1d58b29fca96bd3e7831d0ee1f6666 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 27 Feb 2015 13:17:16 +0100 Subject: [PATCH 029/127] Simplify calculation of week number This also removes a dependency to 3rd party licensed code. Change-Id: Ia4818a5cf306501bdb7192265edc4bcba8e597d8 Reviewed-by: Simon Hausmann --- src/corelib/tools/qdatetime.cpp | 65 ++++++++------------------------- 1 file changed, 16 insertions(+), 49 deletions(-) diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index e5fbf5af5e..3c8233ade7 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -560,22 +560,6 @@ int QDate::daysInYear() const January 2000 has week number 52 in the year 1999, and 31 December 2002 has week number 1 in the year 2003. - \legalese - Copyright (c) 1989 The Regents of the University of California. - All rights reserved. - - Redistribution and use in source and binary forms are permitted - provided that the above copyright notice and this paragraph are - duplicated in all such forms and that any documentation, - advertising materials, and other materials related to such - distribution and use acknowledge that the software was developed - by the University of California, Berkeley. The name of the - University may not be used to endorse or promote products derived - from this software without specific prior written permission. - THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - \sa isValid() */ @@ -585,46 +569,29 @@ int QDate::weekNumber(int *yearNumber) const return 0; int year = QDate::year(); - int yday = dayOfYear() - 1; + int yday = dayOfYear(); int wday = dayOfWeek(); - if (wday == 7) - wday = 0; - int w; - for (;;) { - int len; - int bot; - int top; + int week = (yday - wday + 10) / 7; - len = isLeapYear(year) ? 366 : 365; - /* - ** What yday (-3 ... 3) does - ** the ISO year begin on? - */ - bot = ((yday + 11 - wday) % 7) - 3; - /* - ** What yday does the NEXT - ** ISO year begin on? - */ - top = bot - (len % 7); - if (top < -3) - top += 7; - top += len; - if (yday >= top) { - ++year; - w = 1; - break; - } - if (yday >= bot) { - w = 1 + ((yday - bot) / 7); - break; - } + if (week == 0) { + // last week of previous year --year; - yday += isLeapYear(year) ? 366 : 365; + week = (yday + 365 + (QDate::isLeapYear(year) ? 1 : 0) - wday + 10) / 7; + Q_ASSERT(week == 52 || week == 53); + } else if (week == 53) { + // maybe first week of next year + int w = (yday - 365 - (QDate::isLeapYear(year + 1) ? 1 : 0) - wday + 10) / 7; + if (w > 0) { + ++year; + week = w; + } + Q_ASSERT(week == 53 || week == 1); } + if (yearNumber != 0) *yearNumber = year; - return w; + return week; } #ifndef QT_NO_TEXTDATE From 3dbb5263290b06b74bb5c0a4e15e86b398a759c2 Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Tue, 10 Mar 2015 13:32:05 +0100 Subject: [PATCH 030/127] Fix regression in time zone handling In QtScript we use the msecs since epoch conversion (JS date is based on the concept). After a8c74ddcf78604c9038ba2a2bea81e445e4b3c58 the date conversion test in qtscript started to fail. Instead of relying on the code working by chance, simply update the date when setting it with setMSecsSinceEpoch. Task-number: QTBUG-44885 Change-Id: I9f95c9cdccea52e7d1f808f3cb9e18570ef0df13 Reviewed-by: Thiago Macieira --- src/corelib/tools/qdatetime.cpp | 1 + tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp | 12 ------------ 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index 3c8233ade7..48cad022a1 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -3436,6 +3436,7 @@ void QDateTime::setMSecsSinceEpoch(qint64 msecs) epochMSecsToLocalTime(msecs, &dt, &tm, &status); d->setDateTime(dt, tm); d->setDaylightStatus(status); + d->refreshDateTime(); break; } } diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp index 446e56e936..e3ea0bbd2c 100644 --- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp @@ -2634,10 +2634,6 @@ void tst_QDateTime::daylightTransitions() const QVERIFY(test.isValid()); QCOMPARE(test.date(), QDate(2012, 10, 28)); QCOMPARE(test.time(), QTime(2, 0, 0)); -#if !defined(Q_OS_MAC) && !defined(Q_OS_QNX) - // Linux mktime bug uses last calculation - QEXPECT_FAIL("", "QDateTime doesn't properly support Daylight Transitions", Continue); -#endif // Q_OS_MAC QCOMPARE(test.toMSecsSinceEpoch(), standard2012 - msecsOneHour); // Add year to get to after tran FirstOccurrence @@ -2676,10 +2672,6 @@ void tst_QDateTime::daylightTransitions() const QVERIFY(test.isValid()); QCOMPARE(test.date(), QDate(2012, 10, 28)); QCOMPARE(test.time(), QTime(2, 0, 0)); -#if !defined(Q_OS_MAC) && !defined(Q_OS_QNX) - // Linux mktime bug uses last calculation - QEXPECT_FAIL("", "QDateTime doesn't properly support Daylight Transitions", Continue); -#endif // Q_OS_MAC QCOMPARE(test.toMSecsSinceEpoch(), standard2012 - msecsOneHour); // Add month to get to after tran FirstOccurrence @@ -2718,10 +2710,6 @@ void tst_QDateTime::daylightTransitions() const QVERIFY(test.isValid()); QCOMPARE(test.date(), QDate(2012, 10, 28)); QCOMPARE(test.time(), QTime(2, 0, 0)); -#if !defined(Q_OS_MAC) && !defined(Q_OS_QNX) - // Linux mktime bug uses last calculation - QEXPECT_FAIL("", "QDateTime doesn't properly support Daylight Transitions", Continue); -#endif // Q_OS_MAC QCOMPARE(test.toMSecsSinceEpoch(), standard2012 - msecsOneHour); // Add day to get to after tran FirstOccurrence From ff807df6c9c08444187bd08c36c1bf34b97cdec8 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 5 Mar 2015 22:25:45 -0800 Subject: [PATCH 031/127] QtDBus: Fix const correctness in old style casts Found with GCC's -Wcast-qual. Change-Id: Ia0aac2f09e9245339951ffff13c9468642b2db83 Reviewed-by: Lorn Potter Reviewed-by: Frederik Gladhorn --- src/dbus/qdbusintegrator.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index a95d96e526..74d6a11dee 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -91,7 +91,7 @@ static inline QString dbusInterfaceString() static inline QDebug operator<<(QDebug dbg, const QThread *th) { - dbg.nospace() << "QThread(ptr=" << (void*)th; + dbg.nospace() << "QThread(ptr=" << (const void*)th; if (th && !th->objectName().isEmpty()) dbg.nospace() << ", name=" << th->objectName(); else if (th) @@ -104,7 +104,7 @@ static inline QDebug operator<<(QDebug dbg, const QThread *th) static inline QDebug operator<<(QDebug dbg, const QDBusConnectionPrivate *conn) { dbg.nospace() << "QDBusConnection(" - << "ptr=" << (void*)conn + << "ptr=" << (const void*)conn << ", name=" << conn->name << ", baseService=" << conn->baseService << ", thread="; From a0e693b1e8a2640bd97ea31da643fa57995ed767 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 5 Mar 2015 22:25:45 -0800 Subject: [PATCH 032/127] QtXml: Fix const correctness in old style casts Found with GCC's -Wcast-qual. Change-Id: Ia0aac2f09e9245339951ffff13c94686ec193958 Reviewed-by: Frederik Gladhorn --- src/xml/dom/qdom.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/xml/dom/qdom.cpp b/src/xml/dom/qdom.cpp index 1194f695f1..943d5c28a4 100644 --- a/src/xml/dom/qdom.cpp +++ b/src/xml/dom/qdom.cpp @@ -514,7 +514,7 @@ public: QDomAttrPrivate* createAttributeNS(const QString& nsURI, const QString& qName); QDomEntityReferencePrivate* createEntityReference(const QString& name); - QDomNodePrivate* importNode(const QDomNodePrivate* importedNode, bool deep); + QDomNodePrivate* importNode(QDomNodePrivate* importedNode, bool deep); // Reimplemented from QDomNodePrivate QDomNodePrivate* cloneNode(bool deep = true) Q_DECL_OVERRIDE; @@ -6371,7 +6371,7 @@ QDomEntityReferencePrivate* QDomDocumentPrivate::createEntityReference(const QSt return e; } -QDomNodePrivate* QDomDocumentPrivate::importNode(const QDomNodePrivate *importedNode, bool deep) +QDomNodePrivate* QDomDocumentPrivate::importNode(QDomNodePrivate *importedNode, bool deep) { QDomNodePrivate *node = 0; switch (importedNode->nodeType()) { From 6b38d9fa77e4639021d504754b8a96088cbbe427 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 5 Mar 2015 22:25:45 -0800 Subject: [PATCH 033/127] qdoc: Fix const correctness in old style casts Found with GCC's -Wcast-qual. Change-Id: Ia0aac2f09e9245339951ffff13c94687a79b3f40 Reviewed-by: Martin Smith --- src/tools/qdoc/config.cpp | 6 +++--- src/tools/qdoc/htmlgenerator.cpp | 36 ++++++++++++++++---------------- src/tools/qdoc/node.cpp | 6 +++--- src/tools/qdoc/node.h | 4 ++-- src/tools/qdoc/tree.cpp | 6 +++--- 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/tools/qdoc/config.cpp b/src/tools/qdoc/config.cpp index 5ab3cb0d7d..606bb1c619 100644 --- a/src/tools/qdoc/config.cpp +++ b/src/tools/qdoc/config.cpp @@ -396,7 +396,7 @@ QString Config::getString(const QString& var) const while (i >= 0) { const ConfigVar& cv = configVars[i]; if (!cv.location_.isEmpty()) - (Location&) lastLocation_ = cv.location_; + const_cast(this)->lastLocation_ = cv.location_; if (!cv.values_.isEmpty()) { if (!cv.plus_) value.clear(); @@ -443,7 +443,7 @@ QStringList Config::getStringList(const QString& var) const int i = configVars.size() - 1; while (i >= 0) { if (!configVars[i].location_.isEmpty()) - (Location&) lastLocation_ = configVars[i].location_; + const_cast(this)->lastLocation_ = configVars[i].location_; if (configVars[i].plus_) values.append(configVars[i].values_); else @@ -478,7 +478,7 @@ QStringList Config::getCanonicalPathList(const QString& var, bool validate) cons while (i >= 0) { const ConfigVar& cv = configVars[i]; if (!cv.location_.isEmpty()) - (Location&) lastLocation_ = cv.location_; + const_cast(this)->lastLocation_ = cv.location_; if (!cv.plus_) t.clear(); const QString d = cv.currentPath_; diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp index 7518b20fa3..f0369c989a 100644 --- a/src/tools/qdoc/htmlgenerator.cpp +++ b/src/tools/qdoc/htmlgenerator.cpp @@ -788,63 +788,63 @@ int HtmlGenerator::generateAtom(const Atom *atom, const Node *relative, CodeMark NodeMultiMap::const_iterator n = nsmap.constBegin(); while (n != nsmap.constEnd()) { - const Node* node = n.value(); + Node* node = n.value(); switch (node->type()) { case Node::QmlType: - sections[QmlClass].appendMember((Node*)node); + sections[QmlClass].appendMember(node); break; case Node::Namespace: - sections[Namespace].appendMember((Node*)node); + sections[Namespace].appendMember(node); break; case Node::Class: - sections[Class].appendMember((Node*)node); + sections[Class].appendMember(node); break; case Node::Enum: - sections[Enum].appendMember((Node*)node); + sections[Enum].appendMember(node); break; case Node::Typedef: - sections[Typedef].appendMember((Node*)node); + sections[Typedef].appendMember(node); break; case Node::Function: { const FunctionNode* fn = static_cast(node); if (fn->isMacro()) - sections[Macro].appendMember((Node*)node); + sections[Macro].appendMember(node); else { Node* p = fn->parent(); if (p) { if (p->type() == Node::Class) - sections[MemberFunction].appendMember((Node*)node); + sections[MemberFunction].appendMember(node); else if (p->type() == Node::Namespace) { if (p->name().isEmpty()) - sections[GlobalFunction].appendMember((Node*)node); + sections[GlobalFunction].appendMember(node); else - sections[NamespaceFunction].appendMember((Node*)node); + sections[NamespaceFunction].appendMember(node); } else - sections[GlobalFunction].appendMember((Node*)node); + sections[GlobalFunction].appendMember(node); } else - sections[GlobalFunction].appendMember((Node*)node); + sections[GlobalFunction].appendMember(node); } break; } case Node::Property: - sections[Property].appendMember((Node*)node); + sections[Property].appendMember(node); break; case Node::Variable: - sections[Variable].appendMember((Node*)node); + sections[Variable].appendMember(node); break; case Node::QmlProperty: - sections[QmlProperty].appendMember((Node*)node); + sections[QmlProperty].appendMember(node); break; case Node::QmlSignal: - sections[QmlSignal].appendMember((Node*)node); + sections[QmlSignal].appendMember(node); break; case Node::QmlSignalHandler: - sections[QmlSignalHandler].appendMember((Node*)node); + sections[QmlSignalHandler].appendMember(node); break; case Node::QmlMethod: - sections[QmlMethod].appendMember((Node*)node); + sections[QmlMethod].appendMember(node); break; default: break; diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp index 25792a7c35..a5b1f466bc 100644 --- a/src/tools/qdoc/node.cpp +++ b/src/tools/qdoc/node.cpp @@ -807,7 +807,7 @@ FunctionNode *InnerNode::findFunctionNode(const QString& name) const that the function has the same name and signature as the \a clone node. */ -FunctionNode *InnerNode::findFunctionNode(const FunctionNode *clone) +FunctionNode *InnerNode::findFunctionNode(const FunctionNode *clone) const { QMap::ConstIterator c = primaryFunctionMap.constFind(clone->name()); if (c != primaryFunctionMap.constEnd()) { @@ -857,7 +857,7 @@ QStringList InnerNode::secondaryKeys() /*! */ -void InnerNode::setOverload(const FunctionNode *func, bool overlode) +void InnerNode::setOverload(FunctionNode *func, bool overlode) { Node *node = (Node *) func; Node *&primary = primaryFunctionMap[func->name()]; @@ -1017,7 +1017,7 @@ const EnumNode *InnerNode::findEnumNodeForValue(const QString &enumValue) const */ int InnerNode::overloadNumber(const FunctionNode *func) const { - Node *node = (Node *) func; + Node *node = const_cast(func); if (primaryFunctionMap[func->name()] == node) { return 1; } diff --git a/src/tools/qdoc/node.h b/src/tools/qdoc/node.h index 73b705dd0f..2c6e703103 100644 --- a/src/tools/qdoc/node.h +++ b/src/tools/qdoc/node.h @@ -376,10 +376,10 @@ public: Node* findChildNode(const QString& name, Type type); virtual void findChildren(const QString& name, NodeList& nodes) const Q_DECL_OVERRIDE; FunctionNode* findFunctionNode(const QString& name) const; - FunctionNode* findFunctionNode(const FunctionNode* clone); + FunctionNode* findFunctionNode(const FunctionNode* clone) const; void addInclude(const QString &include); void setIncludes(const QStringList &includes); - void setOverload(const FunctionNode* func, bool overlode); + void setOverload(FunctionNode* func, bool overlode); void normalizeOverloads(); void makeUndocumentedChildrenInternal(); void deleteChildren(); diff --git a/src/tools/qdoc/tree.cpp b/src/tools/qdoc/tree.cpp index 6393ad4e6f..d36003c665 100644 --- a/src/tools/qdoc/tree.cpp +++ b/src/tools/qdoc/tree.cpp @@ -178,7 +178,7 @@ FunctionNode* Tree::findFunctionNode(const QStringList& parentPath, const Functi parent = findNode(parentPath, 0, 0, Node::DontCare); if (parent == 0 || !parent->isInnerNode()) return 0; - return ((InnerNode*)parent)->findFunctionNode(clone); + return ((const InnerNode*)parent)->findFunctionNode(clone); } @@ -249,9 +249,9 @@ const FunctionNode* Tree::findFunctionNode(const QStringList& path, const Node* next; if (i == path.size() - 1) - next = ((InnerNode*) node)->findFunctionNode(path.at(i)); + next = ((const InnerNode*) node)->findFunctionNode(path.at(i)); else - next = ((InnerNode*) node)->findChildNode(path.at(i), genus); + next = ((const InnerNode*) node)->findChildNode(path.at(i), genus); if (!next && node->isClass() && (findFlags & SearchBaseClasses)) { NodeList baseClasses = allBaseClasses(static_cast(node)); From d6268ea91c519a13e297931f0b5be8c17f56bcd6 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 5 Mar 2015 22:25:45 -0800 Subject: [PATCH 034/127] QtSql: Fix const correctness in old style casts Found with GCC's -Wcast-qual. Change-Id: Ia0aac2f09e9245339951ffff13c94688f5b6ed76 Reviewed-by: Frederik Gladhorn --- src/sql/drivers/odbc/qsql_odbc.cpp | 38 +++++++++++++++--------------- src/sql/drivers/psql/qsql_psql.cpp | 6 ++--- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/sql/drivers/odbc/qsql_odbc.cpp b/src/sql/drivers/odbc/qsql_odbc.cpp index e12764636a..8db06e6831 100644 --- a/src/sql/drivers/odbc/qsql_odbc.cpp +++ b/src/sql/drivers/odbc/qsql_odbc.cpp @@ -506,7 +506,7 @@ static QVariant qGetBinaryData(SQLHANDLE hStmt, int column) r = SQLGetData(hStmt, column+1, SQL_C_BINARY, - (SQLPOINTER)(fieldVal.constData() + read), + const_cast(fieldVal.constData() + read), colSize, &lengthIndicator); if (r != SQL_SUCCESS && r != SQL_SUCCESS_WITH_INFO) @@ -1361,7 +1361,7 @@ bool QODBCResult::exec() case QVariant::Date: { QByteArray &ba = tmpStorage[i]; ba.resize(sizeof(DATE_STRUCT)); - DATE_STRUCT *dt = (DATE_STRUCT *)ba.constData(); + DATE_STRUCT *dt = (DATE_STRUCT *)const_cast(ba.constData()); QDate qdt = val.toDate(); dt->year = qdt.year(); dt->month = qdt.month(); @@ -1380,7 +1380,7 @@ bool QODBCResult::exec() case QVariant::Time: { QByteArray &ba = tmpStorage[i]; ba.resize(sizeof(TIME_STRUCT)); - TIME_STRUCT *dt = (TIME_STRUCT *)ba.constData(); + TIME_STRUCT *dt = (TIME_STRUCT *)const_cast(ba.constData()); QTime qdt = val.toTime(); dt->hour = qdt.hour(); dt->minute = qdt.minute(); @@ -1399,7 +1399,7 @@ bool QODBCResult::exec() case QVariant::DateTime: { QByteArray &ba = tmpStorage[i]; ba.resize(sizeof(TIMESTAMP_STRUCT)); - TIMESTAMP_STRUCT * dt = (TIMESTAMP_STRUCT *)ba.constData(); + TIMESTAMP_STRUCT * dt = (TIMESTAMP_STRUCT *)const_cast(ba.constData()); QDateTime qdt = val.toDateTime(); dt->year = qdt.date().year(); dt->month = qdt.date().month(); @@ -1438,7 +1438,7 @@ bool QODBCResult::exec() SQL_INTEGER, 0, 0, - (void *) val.constData(), + const_cast(val.constData()), 0, *ind == SQL_NULL_DATA ? ind : NULL); break; @@ -1450,7 +1450,7 @@ bool QODBCResult::exec() SQL_NUMERIC, 15, 0, - (void *) val.constData(), + const_cast(val.constData()), 0, *ind == SQL_NULL_DATA ? ind : NULL); break; @@ -1462,7 +1462,7 @@ bool QODBCResult::exec() SQL_DOUBLE, 0, 0, - (void *) val.constData(), + const_cast(val.constData()), 0, *ind == SQL_NULL_DATA ? ind : NULL); break; @@ -1474,7 +1474,7 @@ bool QODBCResult::exec() SQL_BIGINT, 0, 0, - (void *) val.constData(), + const_cast(val.constData()), 0, *ind == SQL_NULL_DATA ? ind : NULL); break; @@ -1486,7 +1486,7 @@ bool QODBCResult::exec() SQL_BIGINT, 0, 0, - (void *) val.constData(), + const_cast(val.constData()), 0, *ind == SQL_NULL_DATA ? ind : NULL); break; @@ -1501,7 +1501,7 @@ bool QODBCResult::exec() SQL_LONGVARBINARY, val.toByteArray().size(), 0, - (void *) val.toByteArray().constData(), + const_cast(val.toByteArray().constData()), val.toByteArray().size(), ind); break; @@ -1513,7 +1513,7 @@ bool QODBCResult::exec() SQL_BIT, 0, 0, - (void *) val.constData(), + const_cast(val.constData()), 0, *ind == SQL_NULL_DATA ? ind : NULL); break; @@ -1535,7 +1535,7 @@ bool QODBCResult::exec() strSize > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR, 0, // god knows... don't change this! 0, - (void *)ba.data(), + ba.data(), ba.size(), ind); break; @@ -1548,7 +1548,7 @@ bool QODBCResult::exec() strSize > 254 ? SQL_WLONGVARCHAR : SQL_WVARCHAR, strSize, 0, - (SQLPOINTER)ba.constData(), + const_cast(ba.constData()), ba.size(), ind); break; @@ -1568,7 +1568,7 @@ bool QODBCResult::exec() strSize > 254 ? SQL_LONGVARCHAR : SQL_VARCHAR, strSize, 0, - (void *)str.constData(), + const_cast(str.constData()), strSize, ind); break; @@ -1585,7 +1585,7 @@ bool QODBCResult::exec() SQL_VARBINARY, ba.length() + 1, 0, - (void *) ba.constData(), + const_cast(ba.constData()), ba.length() + 1, ind); break; } @@ -1631,16 +1631,16 @@ bool QODBCResult::exec() for (i = 0; i < values.count(); ++i) { switch (values.at(i).type()) { case QVariant::Date: { - DATE_STRUCT ds = *((DATE_STRUCT *)tmpStorage.at(i).constData()); + DATE_STRUCT ds = *((DATE_STRUCT *)const_cast(tmpStorage.at(i).constData())); values[i] = QVariant(QDate(ds.year, ds.month, ds.day)); break; } case QVariant::Time: { - TIME_STRUCT dt = *((TIME_STRUCT *)tmpStorage.at(i).constData()); + TIME_STRUCT dt = *((TIME_STRUCT *)const_cast(tmpStorage.at(i).constData())); values[i] = QVariant(QTime(dt.hour, dt.minute, dt.second)); break; } case QVariant::DateTime: { TIMESTAMP_STRUCT dt = *((TIMESTAMP_STRUCT*) - tmpStorage.at(i).constData()); + const_cast(tmpStorage.at(i).constData())); values[i] = QVariant(QDateTime(QDate(dt.year, dt.month, dt.day), QTime(dt.hour, dt.minute, dt.second, dt.fraction / 1000000))); break; } @@ -1658,7 +1658,7 @@ bool QODBCResult::exec() if (bindValueType(i) & QSql::Out) { const QByteArray &first = tmpStorage.at(i); QVarLengthArray array; - array.append((SQLTCHAR *)first.constData(), first.size()); + array.append((const SQLTCHAR *)first.constData(), first.size()); values[i] = fromSQLTCHAR(array, first.size()/sizeof(SQLTCHAR)); } break; diff --git a/src/sql/drivers/psql/qsql_psql.cpp b/src/sql/drivers/psql/qsql_psql.cpp index 3aa2455ff0..5c67652cdb 100644 --- a/src/sql/drivers/psql/qsql_psql.cpp +++ b/src/sql/drivers/psql/qsql_psql.cpp @@ -448,7 +448,7 @@ QVariant QPSQLResult::data(int i) } case QVariant::ByteArray: { size_t len; - unsigned char *data = PQunescapeBytea((unsigned char*)val, &len); + unsigned char *data = PQunescapeBytea((const unsigned char*)val, &len); QByteArray ba((const char*)data, len); qPQfreemem(data); return QVariant(ba); @@ -1312,9 +1312,9 @@ QString QPSQLDriver::formatValue(const QSqlField &field, bool trimStrings) const QByteArray ba(field.value().toByteArray()); size_t len; #if defined PG_VERSION_NUM && PG_VERSION_NUM-0 >= 80200 - unsigned char *data = PQescapeByteaConn(d->connection, (unsigned char*)ba.constData(), ba.size(), &len); + unsigned char *data = PQescapeByteaConn(d->connection, (const unsigned char*)ba.constData(), ba.size(), &len); #else - unsigned char *data = PQescapeBytea((unsigned char*)ba.constData(), ba.size(), &len); + unsigned char *data = PQescapeBytea((const unsigned char*)ba.constData(), ba.size(), &len); #endif r += QLatin1Char('\''); r += QLatin1String((const char*)data); From 7acc7a8eb3da62bde5b278da46d4b7b133c7a952 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 5 Mar 2015 23:16:30 -0800 Subject: [PATCH 035/127] Fix const correctness in Harfbuzz to_tis620 modifies cstr, so it mustn't be const. Change-Id: Ia0aac2f09e9245339951ffff13c8d77c886f767d Reviewed-by: Konstantin Ritt Reviewed-by: Lars Knoll --- src/3rdparty/harfbuzz/src/harfbuzz-thai.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-thai.c b/src/3rdparty/harfbuzz/src/harfbuzz-thai.c index b79e0b6cb7..7438d5994c 100644 --- a/src/3rdparty/harfbuzz/src/harfbuzz-thai.c +++ b/src/3rdparty/harfbuzz/src/harfbuzz-thai.c @@ -68,7 +68,7 @@ static int init_libthai() { return 0; } -static void to_tis620(const HB_UChar16 *string, hb_uint32 len, const char *cstr) +static void to_tis620(const HB_UChar16 *string, hb_uint32 len, char *cstr) { hb_uint32 i; unsigned char *result = (unsigned char *)cstr; @@ -183,7 +183,7 @@ static int thai_contain_glyphs (HB_ShaperItem *shaper_item, const int glyph_map[ for (c = 0; c < 0x80; c++) { if ( glyph_map[c] ) { - if ( !shaper_item->font->klass->canRender (shaper_item->font, (HB_UChar16 *) &glyph_map[c], 1) ) + if ( !shaper_item->font->klass->canRender (shaper_item->font, (const HB_UChar16 *) &glyph_map[c], 1) ) return 0; } } From 78588382938675648b14d1ccaa45be6ba09844df Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 25 Feb 2015 20:55:34 -0800 Subject: [PATCH 036/127] QTest: Print hex instead of octal for QByteArray QCOMPARE failures Change-Id: Ia0aac2f09e9245339951ffff13c65b2234d01ad0 Reviewed-by: Oswald Buddenhagen --- src/testlib/qtestcase.cpp | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index fa2080fe69..6250be5853 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -88,6 +88,7 @@ QT_BEGIN_NAMESPACE using QtMiscUtils::toHexUpper; +using QtMiscUtils::fromHex; /*! \namespace QTest @@ -2184,7 +2185,7 @@ char *toHexRepresentation(const char *ba, int length) /*! \internal Returns the same QByteArray but with only the ASCII characters still shown; - everything else is replaced with \c {\OOO}. + everything else is replaced with \c {\xHH}. */ char *toPrettyCString(const char *p, int length) { @@ -2193,14 +2194,30 @@ char *toPrettyCString(const char *p, int length) const char *end = p + length; char *dst = buffer.data(); + bool lastWasHexEscape = false; *dst++ = '"'; for ( ; p != end; ++p) { + // we can add: + // 1 byte: a single character + // 2 bytes: a simple escape sequence (\n) + // 3 bytes: "" and a character + // 4 bytes: an hex escape sequence (\xHH) if (dst - buffer.data() > 246) { - // plus the the quote, the three dots and NUL, it's 251, 252 or 255 + // plus the the quote, the three dots and NUL, it's 255 in the worst case trimmed = true; break; } + // check if we need to insert "" to break an hex escape sequence + if (Q_UNLIKELY(lastWasHexEscape)) { + if (fromHex(*p) != -1) { + // yes, insert it + *dst++ = '"'; + *dst++ = '"'; + } + lastWasHexEscape = false; + } + if (*p < 0x7f && *p >= 0x20 && *p != '\\' && *p != '"') { *dst++ = *p; continue; @@ -2230,10 +2247,12 @@ char *toPrettyCString(const char *p, int length) *dst++ = 't'; break; default: - // write as octal - *dst++ = '0' + ((uchar(*p) >> 6) & 7); - *dst++ = '0' + ((uchar(*p) >> 3) & 7); - *dst++ = '0' + ((uchar(*p)) & 7); + // print as hex escape + *dst++ = 'x'; + *dst++ = toHexUpper(uchar(*p) >> 4); + *dst++ = toHexUpper(uchar(*p)); + lastWasHexEscape = true; + break; } } From 3b36a550b04fbdfca835002c9c090be8099afa7f Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 11 Mar 2015 03:17:25 +0100 Subject: [PATCH 037/127] QDateTime: ensure we always use the daylight status if known Refactor the code so that the localMSecsToEpochMSecs function always gets the daylight status as input. The calculation can be very wrong if we forget to set it. Change-Id: I39e2a3fa6dc7c4a417f23288f10b303e450b8b98 Reviewed-by: Frederik Gladhorn --- src/corelib/tools/qdatetime.cpp | 47 ++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index 48cad022a1..505a6f863b 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -2440,11 +2440,12 @@ static bool epochMSecsToLocalTime(qint64 msecs, QDate *localDate, QTime *localTi } } -// Convert a LocalTime expressed in local msecs encoding into a UTC epoch msecs -// Optionally populate the returned values from mktime for the adjusted local -// date and time and daylight status. Uses daylightStatus in calculation if populated. -static qint64 localMSecsToEpochMSecs(qint64 localMsecs, QDate *localDate = 0, QTime *localTime = 0, - QDateTimePrivate::DaylightStatus *daylightStatus = 0, +// Convert a LocalTime expressed in local msecs encoding and the corresponding +// daylight status into a UTC epoch msecs. Optionally populate the returned +// values from mktime for the adjusted local date and time. +static qint64 localMSecsToEpochMSecs(qint64 localMsecs, + QDateTimePrivate::DaylightStatus *daylightStatus, + QDate *localDate = 0, QTime *localTime = 0, QString *abbreviation = 0, bool *ok = 0) { QDate dt; @@ -2680,9 +2681,11 @@ qint64 QDateTimePrivate::toMSecsSinceEpoch() const case Qt::UTC: return (m_msecs - (m_offsetFromUtc * 1000)); - case Qt::LocalTime: + case Qt::LocalTime: { // recalculate the local timezone - return localMSecsToEpochMSecs(m_msecs); + DaylightStatus status = daylightStatus(); + return localMSecsToEpochMSecs(m_msecs, &status); + } case Qt::TimeZone: #ifndef QT_BOOTSTRAPPED @@ -2752,7 +2755,7 @@ void QDateTimePrivate::refreshDateTime() qint64 epochMSecs = 0; if (m_spec == Qt::LocalTime) { DaylightStatus status = daylightStatus(); - epochMSecs = localMSecsToEpochMSecs(m_msecs, &testDate, &testTime, &status); + epochMSecs = localMSecsToEpochMSecs(m_msecs, &status, &testDate, &testTime); #ifndef QT_BOOTSTRAPPED } else { epochMSecs = zoneMSecsToEpochMSecs(m_msecs, m_timeZone, &testDate, &testTime); @@ -3190,7 +3193,7 @@ QString QDateTime::timeZoneAbbreviation() const case Qt::LocalTime: { QString abbrev; QDateTimePrivate::DaylightStatus status = d->daylightStatus(); - localMSecsToEpochMSecs(d->m_msecs, 0, 0, &status, &abbrev); + localMSecsToEpochMSecs(d->m_msecs, &status, 0, 0, &abbrev); return abbrev; } } @@ -3221,7 +3224,7 @@ bool QDateTime::isDaylightTime() const case Qt::LocalTime: { QDateTimePrivate::DaylightStatus status = d->daylightStatus(); if (status == QDateTimePrivate::UnknownDaylightTime) - localMSecsToEpochMSecs(d->m_msecs, 0, 0, &status, 0); + localMSecsToEpochMSecs(d->m_msecs, &status); return (status == QDateTimePrivate::DaylightTime); } } @@ -3676,12 +3679,14 @@ QDateTime QDateTime::addDays(qint64 ndays) const date = date.addDays(ndays); // Result might fall into "missing" DaylightTime transition hour, // so call conversion and use the adjusted returned time - if (d->m_spec == Qt::LocalTime) - localMSecsToEpochMSecs(timeToMSecs(date, time), &date, &time); + if (d->m_spec == Qt::LocalTime) { + QDateTimePrivate::DaylightStatus status = d->daylightStatus(); + localMSecsToEpochMSecs(timeToMSecs(date, time), &status, &date, &time); #ifndef QT_BOOTSTRAPPED - else if (d->m_spec == Qt::TimeZone) + } else if (d->m_spec == Qt::TimeZone) { QDateTimePrivate::zoneMSecsToEpochMSecs(timeToMSecs(date, time), d->m_timeZone, &date, &time); #endif // QT_BOOTSTRAPPED + } dt.d->setDateTime(date, time); return dt; } @@ -3710,12 +3715,14 @@ QDateTime QDateTime::addMonths(int nmonths) const date = date.addMonths(nmonths); // Result might fall into "missing" DaylightTime transition hour, // so call conversion and use the adjusted returned time - if (d->m_spec == Qt::LocalTime) - localMSecsToEpochMSecs(timeToMSecs(date, time), &date, &time); + if (d->m_spec == Qt::LocalTime) { + QDateTimePrivate::DaylightStatus status = d->daylightStatus(); + localMSecsToEpochMSecs(timeToMSecs(date, time), &status, &date, &time); #ifndef QT_BOOTSTRAPPED - else if (d->m_spec == Qt::TimeZone) + } else if (d->m_spec == Qt::TimeZone) { QDateTimePrivate::zoneMSecsToEpochMSecs(timeToMSecs(date, time), d->m_timeZone, &date, &time); #endif // QT_BOOTSTRAPPED + } dt.d->setDateTime(date, time); return dt; } @@ -3744,12 +3751,14 @@ QDateTime QDateTime::addYears(int nyears) const date = date.addYears(nyears); // Result might fall into "missing" DaylightTime transition hour, // so call conversion and use the adjusted returned time - if (d->m_spec == Qt::LocalTime) - localMSecsToEpochMSecs(timeToMSecs(date, time), &date, &time); + if (d->m_spec == Qt::LocalTime) { + QDateTimePrivate::DaylightStatus status = d->daylightStatus(); + localMSecsToEpochMSecs(timeToMSecs(date, time), &status, &date, &time); #ifndef QT_BOOTSTRAPPED - else if (d->m_spec == Qt::TimeZone) + } else if (d->m_spec == Qt::TimeZone) { QDateTimePrivate::zoneMSecsToEpochMSecs(timeToMSecs(date, time), d->m_timeZone, &date, &time); #endif // QT_BOOTSTRAPPED + } dt.d->setDateTime(date, time); return dt; } From d3f6249de30ade8e75fe01bd61f5e7416790c032 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 11 Mar 2015 03:20:32 +0100 Subject: [PATCH 038/127] tst_QDateTime: Mark more Windows incorrect transitions The refactoring from a8c74ddcf78604c9038ba2a2bea81e445e4b3c58 commit exposed more issues in the Windows API. There were already quite a few QEXPECT_FAIL for this, so this isn't new. For example, localtime(1351386000) on the Central European Timezone should be "Sun Oct 28 02:00:00 CET 2012" (the second occurrence of 2 am), but the Windows API returns tm_isdst = 1 (i.e., still in the CEST timezone) and that's incorrect. Change-Id: I1bc63ac99b1d67b55d783f9606e5c59b24223b13 Reviewed-by: Frederik Gladhorn --- tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp index e3ea0bbd2c..24453d35b6 100644 --- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp @@ -2634,6 +2634,10 @@ void tst_QDateTime::daylightTransitions() const QVERIFY(test.isValid()); QCOMPARE(test.date(), QDate(2012, 10, 28)); QCOMPARE(test.time(), QTime(2, 0, 0)); +#ifdef Q_OS_WIN + // Windows uses SecondOccurrence + QEXPECT_FAIL("", "QDateTime doesn't properly support Daylight Transitions", Continue); +#endif // Q_OS_WIN QCOMPARE(test.toMSecsSinceEpoch(), standard2012 - msecsOneHour); // Add year to get to after tran FirstOccurrence @@ -2672,6 +2676,10 @@ void tst_QDateTime::daylightTransitions() const QVERIFY(test.isValid()); QCOMPARE(test.date(), QDate(2012, 10, 28)); QCOMPARE(test.time(), QTime(2, 0, 0)); +#ifdef Q_OS_WIN + // Windows uses SecondOccurrence + QEXPECT_FAIL("", "QDateTime doesn't properly support Daylight Transitions", Continue); +#endif // Q_OS_WIN QCOMPARE(test.toMSecsSinceEpoch(), standard2012 - msecsOneHour); // Add month to get to after tran FirstOccurrence @@ -2710,6 +2718,10 @@ void tst_QDateTime::daylightTransitions() const QVERIFY(test.isValid()); QCOMPARE(test.date(), QDate(2012, 10, 28)); QCOMPARE(test.time(), QTime(2, 0, 0)); +#ifdef Q_OS_WIN + // Windows uses SecondOccurrence + QEXPECT_FAIL("", "QDateTime doesn't properly support Daylight Transitions", Continue); +#endif // Q_OS_WIN QCOMPARE(test.toMSecsSinceEpoch(), standard2012 - msecsOneHour); // Add day to get to after tran FirstOccurrence From 3b30a8215e98f6164a1650ce7c7e2a42a3d8746f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Vr=C3=A1til?= Date: Mon, 23 Feb 2015 20:27:37 +0100 Subject: [PATCH 039/127] Improve handling of XRandR events in XCB backend Querying X server for data can be very expensive, especially when there are multiple processes querying it at the same time (which is exactly what happens when screen configuration changes and all Qt applications receive XRandR change notifications). This patch is aiming to reduce the number of queries to X server as much as possible by making use of detailed information available in the RRCrtcChangeNotify and RROutputChangeNotify events. Firstly, the backend now does not rebuild all QXcbScreens on any change (which involved the very expensive xcb_randr_get_screen_resources() call), but only builds the full set of QXcbScreens once in initializeScreens(), and then just incrementally updates it. Secondly, it avoids querying X server for all screens geometry as much as possible, and only does so when CRTC/Output change notification for a particular screen is delivered. As a result, handling of all XRandR events on screen change is reduced from tens of seconds to less then a seconds and applications are better responsive after that, because we don't block the event loop for long. The X server is also more responsive after the screen change, since we are not overloading it with requests. Change-Id: I9b8308341cada71dfc9590030909b1e68a335a1f Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbconnection.cpp | 297 ++++++++++++++----- src/plugins/platforms/xcb/qxcbconnection.h | 13 +- src/plugins/platforms/xcb/qxcbscreen.cpp | 129 ++++---- src/plugins/platforms/xcb/qxcbscreen.h | 21 +- 4 files changed, 322 insertions(+), 138 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index da973b5313..81d8a9b72a 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #include @@ -116,8 +117,29 @@ static int ioErrorHandler(Display *dpy) } #endif -QXcbScreen* QXcbConnection::findOrCreateScreen(QList& newScreens, - int screenNumber, xcb_screen_t* xcbScreen, xcb_randr_get_output_info_reply_t *output) +QXcbScreen* QXcbConnection::findScreenForCrtc(xcb_window_t rootWindow, xcb_randr_crtc_t crtc) +{ + foreach (QXcbScreen *screen, m_screens) { + if (screen->root() == rootWindow && screen->crtc() == crtc) + return screen; + } + + return 0; +} + +QXcbScreen* QXcbConnection::findScreenForOutput(xcb_window_t rootWindow, xcb_randr_output_t output) +{ + foreach (QXcbScreen *screen, m_screens) { + if (screen->root() == rootWindow && screen->output() == output) + return screen; + } + + return 0; +} + +QXcbScreen* QXcbConnection::createScreen(int screenNumber, xcb_screen_t* xcbScreen, + xcb_randr_output_t outputId, + xcb_randr_get_output_info_reply_t *output) { QString name; if (output) @@ -130,23 +152,147 @@ QXcbScreen* QXcbConnection::findOrCreateScreen(QList& newScreens, displayName.truncate(dotPos); name = QString::fromLocal8Bit(displayName) + QLatin1Char('.') + QString::number(screenNumber); } - foreach (QXcbScreen* scr, m_screens) - if (scr->name() == name && scr->root() == xcbScreen->root) - return scr; - QXcbScreen *ret = new QXcbScreen(this, xcbScreen, output, name, screenNumber); - newScreens << ret; - return ret; + + return new QXcbScreen(this, xcbScreen, outputId, output, name, screenNumber); +} + +bool QXcbConnection::checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output) +{ + xcb_generic_error_t *error = 0; + xcb_randr_get_output_primary_cookie_t primaryCookie = + xcb_randr_get_output_primary(xcb_connection(), rootWindow); + QScopedPointer primary ( + xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error)); + if (!primary || error) { + qWarning("failed to get the primary output of the screen"); + free(error); + error = NULL; + } + const bool isPrimary = primary ? (primary->output == output) : false; + + return isPrimary; +} + +xcb_screen_t* QXcbConnection::xcbScreenForRootWindow(xcb_window_t rootWindow, int *xcbScreenNumber) +{ + xcb_screen_iterator_t xcbScreenIter = xcb_setup_roots_iterator(m_setup); + for (; xcbScreenIter.rem; xcb_screen_next(&xcbScreenIter)) { + if (xcbScreenIter.data->root == rootWindow) { + if (xcbScreenNumber) + *xcbScreenNumber = xcb_setup_roots_length(m_setup) - xcbScreenIter.rem; + return xcbScreenIter.data; + } + } + + return 0; } /*! \brief Synchronizes the screen list, adds new screens, removes deleted ones */ -void QXcbConnection::updateScreens() +void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event) +{ + if (event->subCode == XCB_RANDR_NOTIFY_CRTC_CHANGE) { + xcb_randr_crtc_change_t crtc = event->u.cc; + xcb_screen_t *xcbScreen = xcbScreenForRootWindow(crtc.window); + if (!xcbScreen) + // Not for us + return; + + qCDebug(lcQpaScreen) << "QXcbConnection: XCB_RANDR_NOTIFY_CRTC_CHANGE:" << crtc.crtc; + QXcbScreen *screen = findScreenForCrtc(crtc.window, crtc.crtc); + // Only update geometry when there's a valid mode on the CRTC + // CRTC with node mode could mean that output has been disabled, and we'll + // get RRNotifyOutputChange notification for that. + if (screen && crtc.mode) { + screen->updateGeometry(QRect(crtc.x, crtc.y, crtc.width, crtc.height), crtc.rotation); + if (screen->mode() != crtc.mode) + screen->updateRefreshRate(crtc.mode); + } + + } else if (event->subCode == XCB_RANDR_NOTIFY_OUTPUT_CHANGE) { + xcb_randr_output_change_t output = event->u.oc; + int xcbScreenNumber = 0; + xcb_screen_t *xcbScreen = xcbScreenForRootWindow(output.window, &xcbScreenNumber); + if (!xcbScreen) + // Not for us + return; + + QXcbScreen *screen = findScreenForOutput(output.window, output.output); + qCDebug(lcQpaScreen) << "QXcbConnection: XCB_RANDR_NOTIFY_OUTPUT_CHANGE:" << output.output; + + if (screen && output.connection == XCB_RANDR_CONNECTION_DISCONNECTED) { + qCDebug(lcQpaScreen) << "screen" << screen->name() << "has been disconnected"; + + // Known screen removed -> delete it + m_screens.removeOne(screen); + foreach (QXcbScreen *otherScreen, m_screens) + otherScreen->removeVirtualSibling((QPlatformScreen *) screen); + + QXcbIntegration::instance()->destroyScreen(screen); + + // QTBUG-40174, QTBUG-42985: If there are no outputs, then there must be + // no QScreen instances; a Qt application can survive this situation, and + // start rendering again later when there is a screen again. + + } else if (!screen && output.connection == XCB_RANDR_CONNECTION_CONNECTED) { + // New XRandR output is available and it's enabled + if (output.crtc != XCB_NONE && output.mode != XCB_NONE) { + xcb_randr_get_output_info_cookie_t outputInfoCookie = + xcb_randr_get_output_info(xcb_connection(), output.output, output.config_timestamp); + QScopedPointer outputInfo( + xcb_randr_get_output_info_reply(xcb_connection(), outputInfoCookie, NULL)); + + screen = createScreen(xcbScreenNumber, xcbScreen, output.output, outputInfo.data()); + qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled"; + + screen->setPrimary(checkOutputIsPrimary(output.window, output.output)); + foreach (QXcbScreen *otherScreen, m_screens) + if (otherScreen->root() == output.window) + otherScreen->addVirtualSibling(screen); + m_screens << screen; + QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary()); + } + // else ignore disabled screens + } else if (screen) { + // Screen has been disabled -> remove + if (output.crtc == XCB_NONE && output.mode == XCB_NONE) { + qCDebug(lcQpaScreen) << "output" << screen->name() << "has been disabled"; + m_screens.removeOne(screen); + foreach (QXcbScreen *otherScreen, m_screens) + otherScreen->removeVirtualSibling((QPlatformScreen *) screen); + QXcbIntegration::instance()->destroyScreen(screen); + } else { + // Just update existing screen + screen->updateGeometry(output.config_timestamp); + const bool wasPrimary = screen->isPrimary(); + screen->setPrimary(checkOutputIsPrimary(output.window, output.output)); + if (screen->mode() != output.mode) + screen->updateRefreshRate(output.mode); + + // If the screen became primary, reshuffle the order in QGuiApplicationPrivate + // TODO: add a proper mechanism for updating primary screen + if (!wasPrimary && screen->isPrimary()) { + QScreen *realScreen = static_cast(screen)->screen(); + QGuiApplicationPrivate::screen_list.removeOne(realScreen); + QGuiApplicationPrivate::screen_list.prepend(realScreen); + m_screens.removeOne(screen); + m_screens.prepend(screen); + } + qCDebug(lcQpaScreen) << "output has changed" << screen; + } + } + if (!m_screens.isEmpty()) + qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name(); + else + qCDebug(lcQpaScreen) << "no outputs"; + } +} + +void QXcbConnection::initializeScreens() { xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup); int xcbScreenNumber = 0; // screen number in the xcb sense - QList activeScreens; - QList newScreens; QXcbScreen* primaryScreen = NULL; while (it.rem) { // Each "screen" in xcb terminology is a virtual desktop, @@ -161,59 +307,73 @@ void QXcbConnection::updateScreens() xcb_generic_error_t *error = NULL; xcb_randr_get_output_primary_cookie_t primaryCookie = xcb_randr_get_output_primary(xcb_connection(), xcbScreen->root); + // TODO: RRGetScreenResources has to be called on each X display at least once before + // RRGetScreenResourcesCurrent can be used - we can't know if we are the first application + // to do so or not, so we always call the slower version here. Ideally we should share some + // global flag (an atom on root window maybe) that at least other Qt apps would understand + // and could call RRGetScreenResourcesCurrent here, speeding up start. xcb_randr_get_screen_resources_cookie_t resourcesCookie = xcb_randr_get_screen_resources(xcb_connection(), xcbScreen->root); - xcb_randr_get_output_primary_reply_t *primary = - xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error); + QScopedPointer primary( + xcb_randr_get_output_primary_reply(xcb_connection(), primaryCookie, &error)); if (!primary || error) { - qWarning("QXcbConnection: Failed to get the primary output of the screen"); + qWarning("failed to get the primary output of the screen"); free(error); } else { - xcb_randr_get_screen_resources_reply_t *resources = - xcb_randr_get_screen_resources_reply(xcb_connection(), resourcesCookie, &error); + QScopedPointer resources( + xcb_randr_get_screen_resources_reply(xcb_connection(), resourcesCookie, &error)); if (!resources || error) { - qWarning("QXcbConnection: Failed to get the screen resources"); + qWarning("failed to get the screen resources"); free(error); } else { xcb_timestamp_t timestamp = resources->config_timestamp; - outputCount = xcb_randr_get_screen_resources_outputs_length(resources); - xcb_randr_output_t *outputs = xcb_randr_get_screen_resources_outputs(resources); + outputCount = xcb_randr_get_screen_resources_outputs_length(resources.data()); + xcb_randr_output_t *outputs = xcb_randr_get_screen_resources_outputs(resources.data()); for (int i = 0; i < outputCount; i++) { - xcb_randr_get_output_info_reply_t *output = + QScopedPointer output( xcb_randr_get_output_info_reply(xcb_connection(), - xcb_randr_get_output_info_unchecked(xcb_connection(), outputs[i], timestamp), NULL); + xcb_randr_get_output_info_unchecked(xcb_connection(), outputs[i], timestamp), NULL)); + + // Invalid, disconnected or disabled output if (output == NULL) continue; - - if (output->crtc == XCB_NONE) { - qCDebug(lcQpaScreen, "output %s is not connected", qPrintable( - QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output), - xcb_randr_get_output_info_name_length(output)))); + if (output->connection != XCB_RANDR_CONNECTION_CONNECTED) { + qCDebug(lcQpaScreen, "Output %s is not connected", qPrintable( + QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.data()), + xcb_randr_get_output_info_name_length(output.data())))); continue; } - QXcbScreen *screen = findOrCreateScreen(newScreens, xcbScreenNumber, xcbScreen, output); + if (output->crtc == XCB_NONE) { + qCDebug(lcQpaScreen, "Output %s is not enabled", qPrintable( + QString::fromUtf8((const char*)xcb_randr_get_output_info_name(output.data()), + xcb_randr_get_output_info_name_length(output.data())))); + continue; + } + + QXcbScreen *screen = createScreen(xcbScreenNumber, xcbScreen, outputs[i], output.data()); siblings << screen; - activeScreens << screen; ++connectedOutputCount; + m_screens << screen; + // There can be multiple outputs per screen, use either // the first or an exact match. An exact match isn't // always available if primary->output is XCB_NONE // or currently disconnected output. if (m_primaryScreenNumber == xcbScreenNumber) { if (!primaryScreen || (primary && outputs[i] == primary->output)) { + if (primaryScreen) + primaryScreen->setPrimary(false); primaryScreen = screen; + primaryScreen->setPrimary(true); siblings.prepend(siblings.takeLast()); } } - free(output); } } - free(resources); } - free(primary); } foreach (QPlatformScreen* s, siblings) ((QXcbScreen*)s)->setVirtualSiblings(siblings); @@ -221,47 +381,7 @@ void QXcbConnection::updateScreens() ++xcbScreenNumber; } // for each xcb screen - QXcbIntegration *integration = QXcbIntegration::instance(); - - // Rebuild screen list, ensuring primary screen is always in front, - // both in the QXcbConnection::m_screens list as well as in the - // QGuiApplicationPrivate::screen_list list, which gets updated via - // - screen added: integration->screenAdded() - // - screen removed: integration->destroyScreen - - // Gather screens to delete - QList screensToDelete; - for (int i = m_screens.count() - 1; i >= 0; --i) { - if (!activeScreens.contains(m_screens[i])) { - screensToDelete.append(m_screens.takeAt(i)); - } - } - - // If there is a new primary screen, add that one first - if (newScreens.contains(primaryScreen)) { - newScreens.removeOne(primaryScreen); - m_screens.prepend(primaryScreen); - qCDebug(lcQpaScreen) << "adding as primary" << primaryScreen; - integration->screenAdded(primaryScreen, true); - } - - // Add the remaining new screens - foreach (QXcbScreen* screen, newScreens) { - m_screens.append(screen); - qCDebug(lcQpaScreen) << "adding" << screen; - integration->screenAdded(screen); - } - - // Delete the old screens, now that the new ones were added - // and we are sure that there is at least one screen available - foreach (QXcbScreen* screen, screensToDelete) { - qCDebug(lcQpaScreen) << "removing" << screen; - integration->destroyScreen(screen); - } - - // Ensure that the primary screen is first in m_screens too - // (in case the assignment of primary was the only change, - // without adding or removing screens) + // Ensure the primary screen is first in the list if (primaryScreen) { Q_ASSERT(!m_screens.isEmpty()); if (m_screens.first() != primaryScreen) { @@ -270,13 +390,15 @@ void QXcbConnection::updateScreens() } } + // Push the screens to QApplication + QXcbIntegration *integration = QXcbIntegration::instance(); + foreach (QXcbScreen* screen, m_screens) { + qCDebug(lcQpaScreen) << "adding" << screen << "(Primary:" << screen->isPrimary() << ")"; + integration->screenAdded(screen, screen->isPrimary()); + } + if (!m_screens.isEmpty()) qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name(); - else - // QTBUG-40174, QTBUG-42985: If there are no outputs, then there must be - // no QScreen instances; a Qt application can survive this situation, and - // start rendering again later when there is a screen again. - qCDebug(lcQpaScreen) << "xcb connection has no outputs"; } QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, const char *displayName) @@ -343,7 +465,7 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra m_netWmUserTime = XCB_CURRENT_TIME; initializeXRandr(); - updateScreens(); + initializeScreens(); if (m_screens.isEmpty()) qFatal("QXcbConnection: no screens available"); @@ -943,14 +1065,14 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) m_clipboard->handleXFixesSelectionRequest((xcb_xfixes_selection_notify_event_t *)event); #endif handled = true; + } else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_NOTIFY) { + updateScreens((xcb_randr_notify_event_t *)event); + handled = true; } else if (has_randr_extension && response_type == xrandr_first_event + XCB_RANDR_SCREEN_CHANGE_NOTIFY) { - updateScreens(); xcb_randr_screen_change_notify_event_t *change_event = (xcb_randr_screen_change_notify_event_t *)event; foreach (QXcbScreen *s, m_screens) { - if (s->root() == change_event->root ) { + if (s->root() == change_event->root ) s->handleScreenChange(change_event); - s->updateRefreshRate(); - } } handled = true; #ifndef QT_NO_XKB @@ -1653,6 +1775,17 @@ void QXcbConnection::initializeXRandr() has_randr_extension = false; } free(xrandr_query); + + xcb_screen_iterator_t rootIter = xcb_setup_roots_iterator(m_setup); + for (; rootIter.rem; xcb_screen_next(&rootIter)) { + xcb_randr_select_input(xcb_connection(), + rootIter.data->root, + XCB_RANDR_NOTIFY_MASK_SCREEN_CHANGE | + XCB_RANDR_NOTIFY_MASK_OUTPUT_CHANGE | + XCB_RANDR_NOTIFY_MASK_CRTC_CHANGE | + XCB_RANDR_NOTIFY_MASK_OUTPUT_PROPERTY + ); + } } void QXcbConnection::initializeXShape() diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index a3c8c0b95e..de454b5eae 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -35,6 +35,7 @@ #define QXCBCONNECTION_H #include +#include #include "qxcbexport.h" #include @@ -492,9 +493,15 @@ private: void initializeXShape(); void initializeXKB(); void handleClientMessageEvent(const xcb_client_message_event_t *event); - QXcbScreen* findOrCreateScreen(QList& newScreens, int screenNumber, - xcb_screen_t* xcbScreen, xcb_randr_get_output_info_reply_t *output = NULL); - void updateScreens(); + QXcbScreen* createScreen(int screenNumber, xcb_screen_t* xcbScreen, + xcb_randr_output_t outputId = XCB_NONE, + xcb_randr_get_output_info_reply_t *output = 0); + QXcbScreen* findScreenForCrtc(xcb_window_t rootWindow, xcb_randr_crtc_t crtc); + QXcbScreen* findScreenForOutput(xcb_window_t rootWindow, xcb_randr_output_t output); + xcb_screen_t* xcbScreenForRootWindow(xcb_window_t rootWindow, int *xcbScreenNumber = 0); + bool checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output); + void initializeScreens(); + void updateScreens(const xcb_randr_notify_event_t *event); void handleButtonPress(xcb_generic_event_t *event); void handleButtonRelease(xcb_generic_event_t *event); void handleMotionNotify(xcb_generic_event_t *event); diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 08108f1e20..383adf9734 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -48,10 +48,15 @@ QT_BEGIN_NAMESPACE QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr, - xcb_randr_get_output_info_reply_t *output, const QString &outputName, int number) + xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output, + QString outputName, int number) : QXcbObject(connection) , m_screen(scr) + , m_output(outputId) , m_crtc(output ? output->crtc : 0) + , m_mode(XCB_NONE) + , m_primary(false) + , m_rotation(XCB_RANDR_ROTATION_ROTATE_0) , m_outputName(outputName) , m_outputSizeMillimeters(output ? QSize(output->mm_width, output->mm_height) : QSize()) , m_virtualSize(scr->width_in_pixels, scr->height_in_pixels) @@ -67,11 +72,20 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr, , m_antialiasingEnabled(-1) , m_xSettings(0) { - if (connection->hasXRandr()) + if (connection->hasXRandr()) { xcb_randr_select_input(xcb_connection(), screen()->root, true); - - updateGeometry(output ? output->timestamp : 0); - updateRefreshRate(); + xcb_randr_get_crtc_info_cookie_t crtcCookie = + xcb_randr_get_crtc_info_unchecked(xcb_connection(), m_crtc, output ? output->timestamp : 0); + xcb_randr_get_crtc_info_reply_t *crtc = + xcb_randr_get_crtc_info_reply(xcb_connection(), crtcCookie, NULL); + if (crtc) { + updateGeometry(QRect(crtc->x, crtc->y, crtc->width, crtc->height), crtc->rotation); + updateRefreshRate(crtc->mode); + free(crtc); + } + } else { + updateGeometry(output ? output->timestamp : 0); + } const int dpr = int(devicePixelRatio()); // On VNC, it can be that physical size is unknown while @@ -352,9 +366,15 @@ QPlatformCursor *QXcbScreen::cursor() const */ void QXcbScreen::handleScreenChange(xcb_randr_screen_change_notify_event_t *change_event) { - updateGeometry(change_event->config_timestamp); + // No need to do anything when screen rotation did not change - if any + // xcb output geometry has changed, we will get RRCrtcChangeNotify and + // RROutputChangeNotify events next + if (change_event->rotation == m_rotation) + return; - switch (change_event->rotation) { + m_rotation = change_event->rotation; + updateGeometry(change_event->timestamp); + switch (m_rotation) { case XCB_RANDR_ROTATION_ROTATE_0: // xrandr --rotate normal m_orientation = Qt::LandscapeOrientation; m_virtualSize.setWidth(change_event->width); @@ -406,35 +426,37 @@ void QXcbScreen::handleScreenChange(xcb_randr_screen_change_notify_event_t *chan void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp) { - QRect xGeometry; - QRect xAvailableGeometry; + xcb_randr_get_crtc_info_cookie_t crtcCookie = + xcb_randr_get_crtc_info_unchecked(xcb_connection(), m_crtc, timestamp); + xcb_randr_get_crtc_info_reply_t *crtc = + xcb_randr_get_crtc_info_reply(xcb_connection(), crtcCookie, NULL); + if (crtc) { + updateGeometry(QRect(crtc->x, crtc->y, crtc->width, crtc->height), crtc->rotation); + free(crtc); + } +} - if (connection()->hasXRandr()) { - xcb_randr_get_crtc_info_reply_t *crtc = xcb_randr_get_crtc_info_reply(xcb_connection(), - xcb_randr_get_crtc_info_unchecked(xcb_connection(), m_crtc, timestamp), NULL); - if (crtc) { - xGeometry = QRect(crtc->x, crtc->y, crtc->width, crtc->height); - xAvailableGeometry = xGeometry; - switch (crtc->rotation) { - case XCB_RANDR_ROTATION_ROTATE_0: // xrandr --rotate normal - m_orientation = Qt::LandscapeOrientation; - m_sizeMillimeters = m_outputSizeMillimeters; - break; - case XCB_RANDR_ROTATION_ROTATE_90: // xrandr --rotate left - m_orientation = Qt::PortraitOrientation; - m_sizeMillimeters = m_outputSizeMillimeters.transposed(); - break; - case XCB_RANDR_ROTATION_ROTATE_180: // xrandr --rotate inverted - m_orientation = Qt::InvertedLandscapeOrientation; - m_sizeMillimeters = m_outputSizeMillimeters; - break; - case XCB_RANDR_ROTATION_ROTATE_270: // xrandr --rotate right - m_orientation = Qt::InvertedPortraitOrientation; - m_sizeMillimeters = m_outputSizeMillimeters.transposed(); - break; - } - free(crtc); - } +void QXcbScreen::updateGeometry(const QRect &geom, uint8_t rotation) +{ + QRect xGeometry = geom; + QRect xAvailableGeometry = xGeometry; + switch (rotation) { + case XCB_RANDR_ROTATION_ROTATE_0: // xrandr --rotate normal + m_orientation = Qt::LandscapeOrientation; + m_sizeMillimeters = m_outputSizeMillimeters; + break; + case XCB_RANDR_ROTATION_ROTATE_90: // xrandr --rotate left + m_orientation = Qt::PortraitOrientation; + m_sizeMillimeters = m_outputSizeMillimeters.transposed(); + break; + case XCB_RANDR_ROTATION_ROTATE_180: // xrandr --rotate inverted + m_orientation = Qt::InvertedLandscapeOrientation; + m_sizeMillimeters = m_outputSizeMillimeters; + break; + case XCB_RANDR_ROTATION_ROTATE_270: // xrandr --rotate right + m_orientation = Qt::InvertedPortraitOrientation; + m_sizeMillimeters = m_outputSizeMillimeters.transposed(); + break; } xcb_get_property_reply_t * workArea = @@ -463,31 +485,38 @@ void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp) m_geometry = QRect(xGeometry.topLeft()/dpr, xGeometry.size()/dpr); m_nativeGeometry = QRect(xGeometry.topLeft(), xGeometry.size()); m_availableGeometry = QRect(xAvailableGeometry.topLeft()/dpr, xAvailableGeometry.size()/dpr); - QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), m_geometry, m_availableGeometry); } -void QXcbScreen::updateRefreshRate() +void QXcbScreen::updateRefreshRate(xcb_randr_mode_t mode) { if (!connection()->hasXRandr()) return; - int rate = m_refreshRate; - - xcb_randr_get_screen_info_reply_t *screenInfoReply = - xcb_randr_get_screen_info_reply(xcb_connection(), xcb_randr_get_screen_info_unchecked(xcb_connection(), m_screen->root), 0); - - if (screenInfoReply) { - rate = screenInfoReply->rate; - free(screenInfoReply); - } - - if (rate == m_refreshRate) + if (m_mode == mode) return; - m_refreshRate = rate; + // we can safely use get_screen_resources_current here, because in order to + // get here, we must have called get_screen_resources before + xcb_randr_get_screen_resources_current_cookie_t resourcesCookie = + xcb_randr_get_screen_resources_current_unchecked(xcb_connection(), m_screen->root); + xcb_randr_get_screen_resources_current_reply_t *resources = + xcb_randr_get_screen_resources_current_reply(xcb_connection(), resourcesCookie, NULL); + if (resources) { + xcb_randr_mode_info_iterator_t modesIter = + xcb_randr_get_screen_resources_current_modes_iterator(resources); + for (; modesIter.rem; xcb_randr_mode_info_next(&modesIter)) { + xcb_randr_mode_info_t *modeInfo = modesIter.data; + if (modeInfo->id == mode) { + m_refreshRate = modeInfo->dot_clock / (modeInfo->htotal * modeInfo->vtotal); + m_mode = mode; + break; + } + } - QWindowSystemInterface::handleScreenRefreshRateChange(QPlatformScreen::screen(), rate); + free(resources); + QWindowSystemInterface::handleScreenRefreshRateChange(QPlatformScreen::screen(), m_refreshRate); + } } QPixmap QXcbScreen::grabWindow(WId window, int x, int y, int width, int height) const diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h index 53ad413541..3f228465f2 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.h +++ b/src/plugins/platforms/xcb/qxcbscreen.h @@ -58,7 +58,8 @@ class Q_XCB_EXPORT QXcbScreen : public QXcbObject, public QPlatformScreen { public: QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, - xcb_randr_get_output_info_reply_t *output, const QString &outputName, int number); + xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output, + QString outputName, int number); ~QXcbScreen(); QPixmap grabWindow(WId window, int x, int y, int width, int height) const Q_DECL_OVERRIDE; @@ -80,11 +81,19 @@ public: Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE { return m_orientation; } QList virtualSiblings() const Q_DECL_OVERRIDE { return m_siblings; } void setVirtualSiblings(QList sl) { m_siblings = sl; } + void removeVirtualSibling(QPlatformScreen *s) { m_siblings.removeOne(s); } + void addVirtualSibling(QPlatformScreen *s) { ((QXcbScreen *) s)->isPrimary() ? m_siblings.prepend(s) : m_siblings.append(s); } + + void setPrimary(bool primary) { m_primary = primary; } + bool isPrimary() const { return m_primary; } int screenNumber() const { return m_number; } xcb_screen_t *screen() const { return m_screen; } xcb_window_t root() const { return m_screen->root; } + xcb_randr_output_t output() const { return m_output; } + xcb_randr_crtc_t crtc() const { return m_crtc; } + xcb_randr_mode_t mode() const { return m_mode; } xcb_window_t clientLeader() const { return m_clientLeader; } @@ -98,8 +107,9 @@ public: QString name() const Q_DECL_OVERRIDE { return m_outputName; } void handleScreenChange(xcb_randr_screen_change_notify_event_t *change_event); - void updateGeometry(xcb_timestamp_t timestamp); - void updateRefreshRate(); + void updateGeometry(const QRect &geom, uint8_t rotation); + void updateGeometry(xcb_timestamp_t timestamp = XCB_TIME_CURRENT_TIME); + void updateRefreshRate(xcb_randr_mode_t mode); void readXResources(); @@ -117,7 +127,12 @@ private: void sendStartupMessage(const QByteArray &message) const; xcb_screen_t *m_screen; + xcb_randr_output_t m_output; xcb_randr_crtc_t m_crtc; + xcb_randr_mode_t m_mode; + bool m_primary; + uint8_t m_rotation; + QString m_outputName; QSizeF m_outputSizeMillimeters; QSizeF m_sizeMillimeters; From c87f8a379706e2a8099c42c2ffe09f258315bb64 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Wed, 18 Feb 2015 15:19:10 +0100 Subject: [PATCH 040/127] Windows: Only set the touch flags if the window is not already registered It is possible for there to be a HCBT_CREATEWND hook which can set the touch window flags already while the window is being created. Therefore we want to defer to those settings instead as they should take precedence. Change-Id: If8dcbd34db2b3bbbfb1bc36731665fb17fb87c24 Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/qwindowscontext.cpp | 5 +++-- src/plugins/platforms/windows/qwindowscontext.h | 2 ++ src/plugins/platforms/windows/qwindowswindow.cpp | 6 ++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index ebd41d482b..fa355f6201 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -173,7 +173,7 @@ static inline QWindowsSessionManager *platformSessionManager() { QWindowsUser32DLL::QWindowsUser32DLL() : setLayeredWindowAttributes(0), updateLayeredWindow(0), updateLayeredWindowIndirect(0), - isHungAppWindow(0), + isHungAppWindow(0), isTouchWindow(0), registerTouchWindow(0), unregisterTouchWindow(0), getTouchInputInfo(0), closeTouchInputHandle(0), setProcessDPIAware(0), addClipboardFormatListener(0), removeClipboardFormatListener(0) @@ -202,11 +202,12 @@ void QWindowsUser32DLL::init() bool QWindowsUser32DLL::initTouch() { QSystemLibrary library(QStringLiteral("user32")); + isTouchWindow = (IsTouchWindow)(library.resolve("IsTouchWindow")); registerTouchWindow = (RegisterTouchWindow)(library.resolve("RegisterTouchWindow")); unregisterTouchWindow = (UnregisterTouchWindow)(library.resolve("UnregisterTouchWindow")); getTouchInputInfo = (GetTouchInputInfo)(library.resolve("GetTouchInputInfo")); closeTouchInputHandle = (CloseTouchInputHandle)(library.resolve("CloseTouchInputHandle")); - return registerTouchWindow && unregisterTouchWindow && getTouchInputInfo && closeTouchInputHandle; + return isTouchWindow && registerTouchWindow && unregisterTouchWindow && getTouchInputInfo && closeTouchInputHandle; } /*! diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h index 870a42946d..81f4a36433 100644 --- a/src/plugins/platforms/windows/qwindowscontext.h +++ b/src/plugins/platforms/windows/qwindowscontext.h @@ -76,6 +76,7 @@ struct QWindowsUser32DLL inline void init(); inline bool initTouch(); + typedef BOOL (WINAPI *IsTouchWindow)(HWND, PULONG); typedef BOOL (WINAPI *RegisterTouchWindow)(HWND, ULONG); typedef BOOL (WINAPI *UnregisterTouchWindow)(HWND); typedef BOOL (WINAPI *GetTouchInputInfo)(HANDLE, UINT, PVOID, int); @@ -99,6 +100,7 @@ struct QWindowsUser32DLL IsHungAppWindow isHungAppWindow; // Touch functions from Windows 7 onwards (also for use with Q_CC_MSVC). + IsTouchWindow isTouchWindow; RegisterTouchWindow registerTouchWindow; UnregisterTouchWindow unregisterTouchWindow; GetTouchInputInfo getTouchInputInfo; diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 4cf8fcf4da..6b490b9404 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -2294,6 +2294,12 @@ void QWindowsWindow::registerTouchWindow(QWindowsWindowFunctions::TouchWindowTou #ifndef Q_OS_WINCE if ((QWindowsContext::instance()->systemInfo() & QWindowsContext::SI_SupportsTouch) && window()->type() != Qt::ForeignWindow) { + ULONG touchFlags = 0; + const bool ret = QWindowsContext::user32dll.isTouchWindow(m_data.hwnd, &touchFlags); + // Return if it is not a touch window or the flags are already set by a hook + // such as HCBT_CREATEWND + if (!ret || touchFlags != 0) + return; if (QWindowsContext::user32dll.registerTouchWindow(m_data.hwnd, (ULONG)touchTypes)) setFlag(TouchRegistered); else From 6272f01617e596b788ff751082504e6e0d0c7fda Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 10 Mar 2015 17:32:15 -0700 Subject: [PATCH 041/127] tst_QDateTime: remove silly test for timezone date too early Let's not try to to compare our QTimeZone handling with the system one. Our handling goes beyond the range of the POSIX APIs, so that's a recipe for error. Change-Id: Iee8cbc07c4434ce9b560ffff13ca4a4f335bdbae Reviewed-by: Lars Knoll Reviewed-by: Friedemann Kleint --- tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp index 24453d35b6..4ab79909e3 100644 --- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp @@ -611,13 +611,11 @@ void tst_QDateTime::setMSecsSinceEpoch() dt2.setTimeZone(europe); dt2.setMSecsSinceEpoch(msecs); QCOMPARE(dt2.date(), european.date()); -#ifdef Q_OS_MAC - // NSTimeZone doesn't apply DST to high values - if (msecs < (Q_INT64_C(123456) << 32)) -#else - // Linux and Win are OK except when they overflow - if (msecs != std::numeric_limits::max()) -#endif + + // don't compare the time if the date is too early or too late: prior + // to 1916, timezones in Europe were not standardised and some OS APIs + // have hard limits. Let's restrict it to the 32-bit Unix range + if (dt2.date().year() >= 1970 && dt2.date().year() <= 2037) QCOMPARE(dt2.time(), european.time()); QCOMPARE(dt2.timeSpec(), Qt::TimeZone); QCOMPARE(dt2.timeZone(), europe); From cacae82a7000041b5347e4cfa3a7b46e064260b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Klitzing?= Date: Tue, 10 Mar 2015 18:18:23 +0100 Subject: [PATCH 042/127] CMake: Fix regression with quoted OPTIONS parameter If a parameter contains quotes the check for "-binary" fails. Change-Id: I27148b590d85291a93f1992dfd277fb857bec6e2 Reviewed-by: Stephen Kelly --- src/corelib/Qt5CoreMacros.cmake | 2 +- tests/auto/cmake/test_add_resource_options/CMakeLists.txt | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/corelib/Qt5CoreMacros.cmake b/src/corelib/Qt5CoreMacros.cmake index 95102be108..a94caf0d25 100644 --- a/src/corelib/Qt5CoreMacros.cmake +++ b/src/corelib/Qt5CoreMacros.cmake @@ -269,7 +269,7 @@ function(QT5_ADD_RESOURCES outfiles ) set(rcc_files ${_RCC_UNPARSED_ARGUMENTS}) set(rcc_options ${_RCC_OPTIONS}) - if(${rcc_options} MATCHES "-binary") + if("${rcc_options}" MATCHES "-binary") message(WARNING "Use qt5_add_binary_resources for binary option") endif() diff --git a/tests/auto/cmake/test_add_resource_options/CMakeLists.txt b/tests/auto/cmake/test_add_resource_options/CMakeLists.txt index a358094546..5fcae59dfe 100644 --- a/tests/auto/cmake/test_add_resource_options/CMakeLists.txt +++ b/tests/auto/cmake/test_add_resource_options/CMakeLists.txt @@ -20,6 +20,9 @@ qt5_wrap_cpp(moc_files myobject.h) # in the add_executable call. qt5_add_resources(rcc_files "test_macro_options.qrc" OPTIONS -binary) +# Test if OPTIONS can handle a quoted parameter. CMake would fail immediately! +qt5_add_resources(rcc_files_quoted_option "test_macro_options.qrc" OPTIONS -root "/") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}") add_executable(myobject myobject.cpp ${moc_files} ${rcc_files}) From 37b7c5164c830458ea833d3757ca94cb7bebcb3a Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 10 Mar 2015 14:51:19 +0100 Subject: [PATCH 043/127] xcb: another QXcbScreen null pointer check In QXcbWindow::setParent(), the window may not have a screen, and in that case we cannot get the root window in this way. Task-number: QTBUG-44719 Change-Id: I719e5e2f8cad13b1460b4d9df6ffd6c4a48e0d37 Reviewed-by: Laszlo Agocs Reviewed-by: Friedemann Kleint --- src/plugins/platforms/xcb/qxcbwindow.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index e2b104e3f1..41b24e302f 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1371,6 +1371,8 @@ void QXcbWindow::setParent(const QPlatformWindow *parent) xcb_parent_id = qXcbParent->xcb_window(); m_embedded = qXcbParent->window()->type() == Qt::ForeignWindow; } else { + if (!xcbScreen()) + return; xcb_parent_id = xcbScreen()->root(); m_embedded = false; } From 595c91f58a443b746135a8df5b53c82dddfc1efa Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Mon, 9 Mar 2015 15:45:30 +0100 Subject: [PATCH 044/127] QGtkStyle: identify QtQuick.Controls.GroupBox as QAccessible::Grouping This allows QGtkStyle to check the role and do appropriate styling (bold font) for the label. Task-number: QTBUG-43736 Change-Id: I735f5f7ffadd7a435fa9e28fab45b202eec0252e Reviewed-by: Gabriel de Dietrich --- src/widgets/styles/qgtkstyle.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/widgets/styles/qgtkstyle.cpp b/src/widgets/styles/qgtkstyle.cpp index 0b67277a63..a585755ddd 100644 --- a/src/widgets/styles/qgtkstyle.cpp +++ b/src/widgets/styles/qgtkstyle.cpp @@ -3633,6 +3633,13 @@ QRect QGtkStyle::subControlRect(ComplexControl control, const QStyleOptionComple QFont font = widget->font(); font.setBold(true); fontMetrics = QFontMetrics(font); + } else if (QStyleHelper::isInstanceOf(groupBox->styleObject, QAccessible::Grouping)) { + QVariant var = groupBox->styleObject->property("font"); + if (var.isValid() && var.canConvert()) { + QFont font = var.value(); + font.setBold(true); + fontMetrics = QFontMetrics(font); + } } QSize textRect = fontMetrics.boundingRect(groupBox->text).size() + QSize(4, 4); From 3128df99d606eae3f461e96cde75e4c75683e290 Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Mon, 2 Mar 2015 15:38:57 +0100 Subject: [PATCH 045/127] Doc: QDataStream Serializing doc error Task-number: QTBUG-44707 Change-Id: I0ccfb47fe0b2464c5b7331040ea658ace3442366 Reviewed-by: Martin Smith --- src/corelib/doc/src/datastreamformat.qdoc | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/corelib/doc/src/datastreamformat.qdoc b/src/corelib/doc/src/datastreamformat.qdoc index c76cc1a95e..8ebc64ca85 100644 --- a/src/corelib/doc/src/datastreamformat.qdoc +++ b/src/corelib/doc/src/datastreamformat.qdoc @@ -129,7 +129,9 @@ \li \list \li Date (QDate) \li Time (QTime) - \li The \l{Qt::TimeSpec}{time spec} (quint8) + \li The \l{Qt::TimeSpec}{time spec} + offsetFromUtc (qint32) if Qt::TimeSpec is offsetFromUtc + TimeZone(QTimeZone) if Qt::TimeSpec is TimeZone \endlist \row \li QEasingCurve \li \list @@ -145,11 +147,19 @@ \row \li QFont \li \list \li The family (QString) - \li The point size (qint16) + \li The style name (QString) + \li The point size (double) + \li The pixel size (qint32) \li The style hint (quint8) + \li The style strategy (quint16) \li The char set (quint8) \li The weight (quint8) \li The font bits (quint8) + \li The font stretch (quint16) + \li The extended font bits (quint8) + \li The letter spacing (double) + \li The word spacing (double) + \li The hinting preference (quint8) \endlist \row \li QHash \li \list From 8eaddf8343242caa9e9dde562107ece8d0785680 Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Wed, 4 Mar 2015 15:12:04 +0100 Subject: [PATCH 046/127] Doc: corrected snippet issue in Defining Plugins doc Task-number: QTBUG-44629 Change-Id: I70e20209b6b33f7adcbcafc6b7d959660cdc2e87 Reviewed-by: Martin Smith --- src/corelib/doc/qtcore.qdocconf | 3 ++- src/corelib/plugin/qplugin.qdoc | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/corelib/doc/qtcore.qdocconf b/src/corelib/doc/qtcore.qdocconf index f3aff83a8b..df1ee4afea 100644 --- a/src/corelib/doc/qtcore.qdocconf +++ b/src/corelib/doc/qtcore.qdocconf @@ -36,7 +36,8 @@ exampledirs += \ ../ \ snippets \ ../../../examples/corelib \ - ../../../examples/network/dnslookup + ../../../examples/network/dnslookup \ + ../../../examples/widgets/tools imagedirs += images diff --git a/src/corelib/plugin/qplugin.qdoc b/src/corelib/plugin/qplugin.qdoc index 81be1df518..94f5bc8a30 100644 --- a/src/corelib/plugin/qplugin.qdoc +++ b/src/corelib/plugin/qplugin.qdoc @@ -44,7 +44,7 @@ to the interface class called \a ClassName. The \a Identifier must be unique. For example: - \snippet code/doc_src_qplugin.cpp 0 + \snippet plugandpaint/interfaces.h 3 This macro is normally used right after the class definition for \a ClassName, in a header file. See the From aad3c089023652844a3898fa0b7cbf1db966ef3c Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 10 Mar 2015 13:31:57 +0100 Subject: [PATCH 047/127] Clean up QLibraryInfoPrivate::findConfiguration() The QFile::exists() check in the end was redundant if one of the !QFile::exists() had returned false before. By always doing the positive check we can get rid of it and also avoid excessive nesting. Also, on OSX the isEmpty() clause probably never evaluated to true, with the effect that qt.conf in an applicationDirPath was never found. Change-Id: I750735741b707d3e98c4bf6c6b9558618e1fcc59 Reviewed-by: Oswald Buddenhagen --- src/corelib/global/qlibraryinfo.cpp | 46 ++++++++++++++--------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index 484c7869a6..5db2e94602 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -158,35 +158,35 @@ void QLibrarySettings::load() QSettings *QLibraryInfoPrivate::findConfiguration() { QString qtconfig = QStringLiteral(":/qt/etc/qt.conf"); + if (QFile::exists(qtconfig)) + return new QSettings(qtconfig, QSettings::IniFormat); #ifdef QT_BUILD_QMAKE - if(!QFile::exists(qtconfig)) - qtconfig = qmake_libraryInfoFile(); + qtconfig = qmake_libraryInfoFile(); + if (QFile::exists(qtconfig)) + return new QSettings(qtconfig, QSettings::IniFormat); #else - if (!QFile::exists(qtconfig)) { #ifdef Q_OS_MAC - CFBundleRef bundleRef = CFBundleGetMainBundle(); - if (bundleRef) { - QCFType urlRef = CFBundleCopyResourceURL(bundleRef, - QCFString(QLatin1String("qt.conf")), - 0, - 0); - if (urlRef) { - QCFString path = CFURLCopyFileSystemPath(urlRef, kCFURLPOSIXPathStyle); - qtconfig = QDir::cleanPath(path); - } - } - if (qtconfig.isEmpty()) -#endif - { - if (QCoreApplication::instance()) { - QDir pwd(QCoreApplication::applicationDirPath()); - qtconfig = pwd.filePath(QLatin1String("qt.conf")); - } + CFBundleRef bundleRef = CFBundleGetMainBundle(); + if (bundleRef) { + QCFType urlRef = CFBundleCopyResourceURL(bundleRef, + QCFString(QLatin1String("qt.conf")), + 0, + 0); + if (urlRef) { + QCFString path = CFURLCopyFileSystemPath(urlRef, kCFURLPOSIXPathStyle); + qtconfig = QDir::cleanPath(path); + if (QFile::exists(qtconfig)) + return new QSettings(qtconfig, QSettings::IniFormat); } } #endif - if (QFile::exists(qtconfig)) - return new QSettings(qtconfig, QSettings::IniFormat); + if (QCoreApplication::instance()) { + QDir pwd(QCoreApplication::applicationDirPath()); + qtconfig = pwd.filePath(QLatin1String("qt.conf")); + if (QFile::exists(qtconfig)) + return new QSettings(qtconfig, QSettings::IniFormat); + } +#endif return 0; //no luck } From fdb7fa937a58900e3966adc765975785d0a9f0da Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Fri, 20 Feb 2015 11:07:09 +0100 Subject: [PATCH 048/127] Windows: Add -static-runtime configure option Support statically linking the MSVC/mingw runtime libraries without manually tweaking mkspecs. This is helpful for projects like the installer framework. MSVC does not support mixing MT[d]/MD[d] flags in different compilation units. The static_runtime option is therefore added to both QT_CONFIG and CONFIG. Change-Id: Ifd6dc9c362090457de8e2c62477d0445f9479722 Reviewed-by: Oswald Buddenhagen --- mkspecs/features/static_runtime.prf | 7 +++++++ tools/configure/configureapp.cpp | 16 ++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 mkspecs/features/static_runtime.prf diff --git a/mkspecs/features/static_runtime.prf b/mkspecs/features/static_runtime.prf new file mode 100644 index 0000000000..3275e6e2e2 --- /dev/null +++ b/mkspecs/features/static_runtime.prf @@ -0,0 +1,7 @@ +msvc { + # -MD becomes -MT, -MDd becomes -MTd + QMAKE_CFLAGS ~= s,^-MD(d?)$, -MT\1,g + QMAKE_CXXFLAGS ~= s,^-MD(d?)$, -MT\1,g +} else: mingw { + QMAKE_LFLAGS += -static +} diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index ca2a5b1769..a263d44f29 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -245,6 +245,8 @@ Configure::Configure(int& argc, char** argv) dictionary[ "SHARED" ] = "yes"; + dictionary[ "STATIC_RUNTIME" ] = "no"; + dictionary[ "ZLIB" ] = "auto"; dictionary[ "PCRE" ] = "auto"; @@ -464,6 +466,8 @@ void Configure::parseCmdLine() dictionary[ "SHARED" ] = "yes"; else if (configCmdLine.at(i) == "-static") dictionary[ "SHARED" ] = "no"; + else if (configCmdLine.at(i) == "-static-runtime") + dictionary[ "STATIC_RUNTIME" ] = "yes"; else if (configCmdLine.at(i) == "-developer-build") dictionary[ "BUILDDEV" ] = "yes"; else if (configCmdLine.at(i) == "-opensource") { @@ -1775,6 +1779,8 @@ bool Configure::displayHelp() desc("SHARED", "yes", "-shared", "Create and use shared Qt libraries."); desc("SHARED", "no", "-static", "Create and use static Qt libraries.\n"); + desc("STATIC_RUNTIME", "no", "-static-runtime","Statically link the C/C++ runtime library.\n"); + desc("LTCG", "yes", "-ltcg", "Use Link Time Code Generation. (Release builds only)"); desc("LTCG", "no", "-no-ltcg", "Do not use Link Time Code Generation.\n"); @@ -2499,6 +2505,11 @@ bool Configure::verifyConfiguration() dictionary["C++11"] = "auto"; } + if (dictionary["STATIC_RUNTIME"] == "yes" && dictionary["SHARED"] == "yes") { + cout << "ERROR: -static-runtime requires -static" << endl << endl; + dictionary[ "DONE" ] = "error"; + } + if (dictionary["SEPARATE_DEBUG_INFO"] == "yes") { if (dictionary[ "SHARED" ] == "no") { cout << "ERROR: -separate-debug-info is incompatible with -static" << endl << endl; @@ -2644,6 +2655,9 @@ void Configure::generateOutputVars() else qtConfig += "shared"; + if (dictionary[ "STATIC_RUNTIME" ] == "yes") + qtConfig += "static_runtime"; + if (dictionary[ "GUI" ] == "no") { qtConfig += "no-gui"; dictionary [ "WIDGETS" ] = "no"; @@ -3362,6 +3376,8 @@ void Configure::generateQConfigPri() configStream << dictionary[ "BUILD" ]; configStream << (dictionary[ "SHARED" ] == "no" ? " static" : " shared"); + if (dictionary["STATIC_RUNTIME"] == "yes") + configStream << " static_runtime"; if (dictionary[ "LTCG" ] == "yes") configStream << " ltcg"; if (dictionary[ "RTTI" ] == "yes") From f29007b1d51bc6ab82a74e4841a904a51dc4ddce Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Fri, 6 Mar 2015 12:41:10 +0100 Subject: [PATCH 049/127] Gui: Fix compilation with QT_NO_OPENGL Change-Id: I96674b39fd4176cf9d93b7ce00efa2b035128b61 Reviewed-by: Laszlo Agocs --- src/gui/kernel/qplatformgraphicsbufferhelper.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/gui/kernel/qplatformgraphicsbufferhelper.cpp b/src/gui/kernel/qplatformgraphicsbufferhelper.cpp index 7da95ffcec..2749b05691 100644 --- a/src/gui/kernel/qplatformgraphicsbufferhelper.cpp +++ b/src/gui/kernel/qplatformgraphicsbufferhelper.cpp @@ -112,6 +112,7 @@ bool QPlatformGraphicsBufferHelper::bindSWToTexture(const QPlatformGraphicsBuffe bool *swizzleRandB, const QRect &subRect) { +#ifndef QT_NO_OPENGL if (!QOpenGLContext::currentContext()) return false; @@ -172,6 +173,12 @@ bool QPlatformGraphicsBufferHelper::bindSWToTexture(const QPlatformGraphicsBuffe return true; +#else + Q_UNUSED(graphicsBuffer) + Q_UNUSED(swizzleRandB) + Q_UNUSED(subRect) + return false; +#endif // QT_NO_OPENGL } QT_END_NAMESPACE From 367a91d27880408c0924e15c5d1a156fff99a025 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 10 Mar 2015 12:14:03 +0100 Subject: [PATCH 050/127] Enhance EGL_CONTEXT_LOST checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Apparently failures can occur not just when doing eglMakeCurrent() but also when creating window surfaces. Change-Id: Ife1210293d5120fd41352164d9c89e83fb5ce468 Reviewed-by: Michael Brüning Reviewed-by: Friedemann Kleint --- .../platforms/windows/qwindowseglcontext.cpp | 33 ++++++++++++++----- .../platforms/windows/qwindowseglcontext.h | 2 +- .../platforms/windows/qwindowsopenglcontext.h | 2 +- .../platforms/windows/qwindowswindow.cpp | 4 +-- .../platforms/windows/qwindowswindow.h | 2 +- 5 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp index 74efd49217..7db6abd8ef 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.cpp +++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp @@ -416,12 +416,15 @@ QWindowsOpenGLContext *QWindowsEGLStaticContext::createContext(QOpenGLContext *c return new QWindowsEGLContext(this, context->format(), context->shareHandle()); } -void *QWindowsEGLStaticContext::createWindowSurface(void *nativeWindow, void *nativeConfig) +void *QWindowsEGLStaticContext::createWindowSurface(void *nativeWindow, void *nativeConfig, int *err) { + *err = 0; EGLSurface surface = libEGL.eglCreateWindowSurface(m_display, (EGLConfig) nativeConfig, (EGLNativeWindowType) nativeWindow, 0); - if (surface == EGL_NO_SURFACE) - qWarning("%s: Could not create the EGL window surface: 0x%x\n", Q_FUNC_INFO, libEGL.eglGetError()); + if (surface == EGL_NO_SURFACE) { + *err = libEGL.eglGetError(); + qWarning("%s: Could not create the EGL window surface: 0x%x\n", Q_FUNC_INFO, *err); + } return surface; } @@ -578,8 +581,15 @@ bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface) QWindowsWindow *window = static_cast(surface); window->aboutToMakeCurrent(); - EGLSurface eglSurface = static_cast(window->surface(m_eglConfig)); - Q_ASSERT(eglSurface); + int err = 0; + EGLSurface eglSurface = static_cast(window->surface(m_eglConfig, &err)); + if (eglSurface == EGL_NO_SURFACE) { + if (err == EGL_CONTEXT_LOST) { + m_eglContext = EGL_NO_CONTEXT; + qCDebug(lcQpaGl) << "Got EGL context lost in createWindowSurface() for context" << this; + } + return false; + } // shortcut: on some GPUs, eglMakeCurrent is not a cheap operation if (QWindowsEGLStaticContext::libEGL.eglGetCurrentContext() == m_eglContext && @@ -597,7 +607,7 @@ bool QWindowsEGLContext::makeCurrent(QPlatformSurface *surface) QWindowsEGLStaticContext::libEGL.eglSwapInterval(m_staticContext->display(), m_swapInterval); } } else { - int err = QWindowsEGLStaticContext::libEGL.eglGetError(); + err = QWindowsEGLStaticContext::libEGL.eglGetError(); // EGL_CONTEXT_LOST (loss of the D3D device) is not necessarily fatal. // Qt Quick is able to recover for example. if (err == EGL_CONTEXT_LOST) { @@ -625,8 +635,15 @@ void QWindowsEGLContext::swapBuffers(QPlatformSurface *surface) { QWindowsEGLStaticContext::libEGL.eglBindAPI(m_api); QWindowsWindow *window = static_cast(surface); - EGLSurface eglSurface = static_cast(window->surface(m_eglConfig)); - Q_ASSERT(eglSurface); + int err = 0; + EGLSurface eglSurface = static_cast(window->surface(m_eglConfig, &err)); + if (eglSurface == EGL_NO_SURFACE) { + if (err == EGL_CONTEXT_LOST) { + m_eglContext = EGL_NO_CONTEXT; + qCDebug(lcQpaGl) << "Got EGL context lost in createWindowSurface() for context" << this; + } + return; + } bool ok = QWindowsEGLStaticContext::libEGL.eglSwapBuffers(m_eglDisplay, eglSurface); if (!ok) diff --git a/src/plugins/platforms/windows/qwindowseglcontext.h b/src/plugins/platforms/windows/qwindowseglcontext.h index 55f58fac5f..2b249348c3 100644 --- a/src/plugins/platforms/windows/qwindowseglcontext.h +++ b/src/plugins/platforms/windows/qwindowseglcontext.h @@ -260,7 +260,7 @@ public: void *moduleHandle() const { return libGLESv2.moduleHandle(); } QOpenGLContext::OpenGLModuleType moduleType() const { return QOpenGLContext::LibGLES; } - void *createWindowSurface(void *nativeWindow, void *nativeConfig) Q_DECL_OVERRIDE; + void *createWindowSurface(void *nativeWindow, void *nativeConfig, int *err) Q_DECL_OVERRIDE; void destroyWindowSurface(void *nativeSurface) Q_DECL_OVERRIDE; QSurfaceFormat formatFromConfig(EGLDisplay display, EGLConfig config, const QSurfaceFormat &referenceFormat); diff --git a/src/plugins/platforms/windows/qwindowsopenglcontext.h b/src/plugins/platforms/windows/qwindowsopenglcontext.h index 8ebcb83a08..2c52c58829 100644 --- a/src/plugins/platforms/windows/qwindowsopenglcontext.h +++ b/src/plugins/platforms/windows/qwindowsopenglcontext.h @@ -56,7 +56,7 @@ public: // If the windowing system interface needs explicitly created window surfaces (like EGL), // reimplement these. - virtual void *createWindowSurface(void * /*nativeWindow*/, void * /*nativeConfig*/) { return 0; } + virtual void *createWindowSurface(void * /*nativeWindow*/, void * /*nativeConfig*/, int * /*err*/) { return 0; } virtual void destroyWindowSurface(void * /*nativeSurface*/) { } private: diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 6b490b9404..2fd0f12c26 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -2259,14 +2259,14 @@ void QWindowsWindow::setCustomMargins(const QMargins &newCustomMargins) } } -void *QWindowsWindow::surface(void *nativeConfig) +void *QWindowsWindow::surface(void *nativeConfig, int *err) { #ifdef QT_NO_OPENGL return 0; #else if (!m_surface) { if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext()) - m_surface = staticOpenGLContext->createWindowSurface(m_data.hwnd, nativeConfig); + m_surface = staticOpenGLContext->createWindowSurface(m_data.hwnd, nativeConfig, err); } return m_surface; diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index f0b04fbc47..0089ad07a0 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -248,7 +248,7 @@ public: bool isEnabled() const; void setWindowIcon(const QIcon &icon); - void *surface(void *nativeConfig); + void *surface(void *nativeConfig, int *err); void invalidateSurface() Q_DECL_OVERRIDE; void aboutToMakeCurrent(); From 42a8613ffab6d966a88232e1535fbf386f0f96ea Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Wed, 11 Mar 2015 14:23:01 +0100 Subject: [PATCH 051/127] QScreen availableGeometryChanged signal: emit correct value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Need to emit availableGeometry not geometry Task-number: QTBUG-44916 Change-Id: I6eb7eb0b8e46d6d8249fa67f57374b25e21f2ade Reviewed-by: Eskil Abrahamsen Blomfeldt Reviewed-by: Tor Arne Vestbø --- src/gui/kernel/qguiapplication.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 8c49b3a2b5..60b289bacb 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -2554,7 +2554,7 @@ void QGuiApplicationPrivate::reportGeometryChange(QWindowSystemInterfacePrivate: } if (availableGeometryChanged) - emit s->availableGeometryChanged(s->geometry()); + emit s->availableGeometryChanged(s->availableGeometry()); if (geometryChanged || availableGeometryChanged) { foreach (QScreen* sibling, s->virtualSiblings()) From a3aaabc6467ee7e7d993bf09d15f3462e7bd9208 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Mon, 9 Mar 2015 17:25:28 +0100 Subject: [PATCH 052/127] Clarify limitations of QCoreApplication::libraryPaths() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If you call libraryPaths() before constructing a QCoreApplication, intersting things may happen. Task-number: QTBUG-38598 Change-Id: I2861746277e391ede9e921e4a8ad825007e25fa0 Reviewed-by: Topi Reiniö --- src/corelib/kernel/qcoreapplication.cpp | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 0bde57c8b3..dbffa83cee 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -2420,16 +2420,27 @@ Q_GLOBAL_STATIC_WITH_ARGS(QMutex, libraryPathMutex, (QMutex::Recursive)) Returns a list of paths that the application will search when dynamically loading libraries. + The return value of this function may change when a QCoreApplication + is created. It is not recommended to call it before creating a + QCoreApplication. The directory of the application executable (\b not + the working directory) is part of the list if it is known. In order + to make it known a QCoreApplication has to be constructed as it will + use \c {argv[0]} to find it. + Qt provides default library paths, but they can also be set using a \l{Using qt.conf}{qt.conf} file. Paths specified in this file - will override default values. + will override default values. Note that if the qt.conf file is in + the directory of the application executable, it may not be found + until a QCoreApplication is created. If it is not found when calling + this function, the default library paths will be used. - This list will include the installation directory for plugins if + The list will include the installation directory for plugins if it exists (the default installation directory for plugins is \c INSTALL/plugins, where \c INSTALL is the directory where Qt was - installed). The directory of the application executable (NOT the - working directory) is always added, as well as the colon separated - entries of the \c QT_PLUGIN_PATH environment variable. + installed). The colon separated entries of the \c QT_PLUGIN_PATH + environment variable are always added. The plugin installation + directory (and its existence) may change when the directory of + the application executable becomes known. If you want to iterate over the list, you can use the \l foreach pseudo-keyword: From 6ef8387e42790d29ea8218f6c43514b2372e9ec6 Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Wed, 11 Mar 2015 12:15:13 +0100 Subject: [PATCH 053/127] Doc: Json classes added to list of implic.shared classes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-44053 Change-Id: I52a1b6c413aaa594bfee9bf7484c3d0ce7e9c9fa Reviewed-by: Topi Reiniö --- src/corelib/json/qjsonarray.cpp | 1 + src/corelib/json/qjsondocument.cpp | 1 + src/corelib/json/qjsonobject.cpp | 1 + src/corelib/json/qjsonparser.cpp | 1 + src/corelib/json/qjsonvalue.cpp | 1 + 5 files changed, 5 insertions(+) diff --git a/src/corelib/json/qjsonarray.cpp b/src/corelib/json/qjsonarray.cpp index a993fd6ea4..77a3d0a2b8 100644 --- a/src/corelib/json/qjsonarray.cpp +++ b/src/corelib/json/qjsonarray.cpp @@ -47,6 +47,7 @@ QT_BEGIN_NAMESPACE \class QJsonArray \inmodule QtCore \ingroup json + \ingroup shared \reentrant \since 5.0 diff --git a/src/corelib/json/qjsondocument.cpp b/src/corelib/json/qjsondocument.cpp index 7014c146d5..f5bad32233 100644 --- a/src/corelib/json/qjsondocument.cpp +++ b/src/corelib/json/qjsondocument.cpp @@ -47,6 +47,7 @@ QT_BEGIN_NAMESPACE /*! \class QJsonDocument \inmodule QtCore \ingroup json + \ingroup shared \reentrant \since 5.0 diff --git a/src/corelib/json/qjsonobject.cpp b/src/corelib/json/qjsonobject.cpp index 22bad6f8a2..ae44cd9ff9 100644 --- a/src/corelib/json/qjsonobject.cpp +++ b/src/corelib/json/qjsonobject.cpp @@ -46,6 +46,7 @@ QT_BEGIN_NAMESPACE \class QJsonObject \inmodule QtCore \ingroup json + \ingroup shared \reentrant \since 5.0 diff --git a/src/corelib/json/qjsonparser.cpp b/src/corelib/json/qjsonparser.cpp index 371a191d3f..0d62687388 100644 --- a/src/corelib/json/qjsonparser.cpp +++ b/src/corelib/json/qjsonparser.cpp @@ -77,6 +77,7 @@ QT_BEGIN_NAMESPACE \class QJsonParseError \inmodule QtCore \ingroup json + \ingroup shared \reentrant \since 5.0 diff --git a/src/corelib/json/qjsonvalue.cpp b/src/corelib/json/qjsonvalue.cpp index 4845d8c876..c8ddfbc2cc 100644 --- a/src/corelib/json/qjsonvalue.cpp +++ b/src/corelib/json/qjsonvalue.cpp @@ -46,6 +46,7 @@ QT_BEGIN_NAMESPACE \class QJsonValue \inmodule QtCore \ingroup json + \ingroup shared \reentrant \since 5.0 From a4c2e95ce16b3c4f9e0c9c983fb1ce9e70b5ce5a Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Mon, 9 Mar 2015 21:44:37 +0100 Subject: [PATCH 054/127] Use own QIconEngine in QFileIconProvider MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows us to lazily load icons from the platform theme by reimplementing the pixmap(). Otherwise, we would instantiate pixmaps in several sizes even though we would not need them right away. Since, at least on OS X, icon sizes can go up to 128x128 pixels, we can end up saving an order of magnitude of memory on icon pixmaps alone if we only use the smallest sizes in our application. Two side modifications are included. The first allows sub- classing QPixmapIconEngine by exporting this class. The second fixes the q_ptr in QFileIconProviderPrivate which was never set. Change-Id: I91af322ded2823e475703871e607773177ae25d3 Task-number: QTBUG-41796 Reviewed-by: Morten Johan Sørvig --- src/gui/image/qicon_p.h | 2 +- src/widgets/itemviews/qfileiconprovider.cpp | 136 +++++++++++++------- src/widgets/itemviews/qfileiconprovider_p.h | 2 +- 3 files changed, 90 insertions(+), 50 deletions(-) diff --git a/src/gui/image/qicon_p.h b/src/gui/image/qicon_p.h index e0fec112b5..8b42e770fa 100644 --- a/src/gui/image/qicon_p.h +++ b/src/gui/image/qicon_p.h @@ -99,7 +99,7 @@ inline QPixmapIconEngineEntry::QPixmapIconEngineEntry(const QString &file, const pixmap.setDevicePixelRatio(1.0); } -class QPixmapIconEngine : public QIconEngine { +class Q_GUI_EXPORT QPixmapIconEngine : public QIconEngine { public: QPixmapIconEngine(); QPixmapIconEngine(const QPixmapIconEngine &); diff --git a/src/widgets/itemviews/qfileiconprovider.cpp b/src/widgets/itemviews/qfileiconprovider.cpp index d1bd0e657e..740bd853b7 100644 --- a/src/widgets/itemviews/qfileiconprovider.cpp +++ b/src/widgets/itemviews/qfileiconprovider.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -57,6 +58,88 @@ QT_BEGIN_NAMESPACE +static bool isCacheable(const QFileInfo &fi); + +class QFileIconEngine : public QPixmapIconEngine +{ +public: + QFileIconEngine(const QFileIconProvider *fip, const QFileInfo &info) + : QPixmapIconEngine(), m_fileIconProvider(fip), m_fileInfo(info) + { } + + QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state) Q_DECL_OVERRIDE + { + Q_UNUSED(mode); + Q_UNUSED(state); + QPixmap pixmap; + + if (!size.isValid()) + return pixmap; + + const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme(); + if (!theme) + return pixmap; + + const QString &keyBase = QLatin1String("qt_.") + m_fileInfo.suffix().toUpper(); + + bool cacheable = isCacheable(m_fileInfo); + if (cacheable) { + QPixmapCache::find(keyBase + QString::number(size.width()), pixmap); + if (!pixmap.isNull()) + return pixmap; + } + + QPlatformTheme::IconOptions iconOptions; + if (m_fileIconProvider->options() & QFileIconProvider::DontUseCustomDirectoryIcons) + iconOptions |= QPlatformTheme::DontUseCustomDirectoryIcons; + + pixmap = theme->fileIconPixmap(m_fileInfo, size, iconOptions); + if (!pixmap.isNull()) { + if (cacheable) + QPixmapCache::insert(keyBase + QString::number(size.width()), pixmap); + } + + return pixmap; + } + + QList availableSizes(QIcon::Mode mode = QIcon::Normal, QIcon::State state = QIcon::Off) const Q_DECL_OVERRIDE + { + Q_UNUSED(mode); + Q_UNUSED(state); + static QList sizes; + static QPlatformTheme *theme = 0; + if (!theme) { + theme = QGuiApplicationPrivate::platformTheme(); + if (!theme) + return sizes; + + QList themeSizes = theme->themeHint(QPlatformTheme::IconPixmapSizes).value >(); + if (themeSizes.isEmpty()) + return sizes; + + foreach (int size, themeSizes) + sizes << QSize(size, size); + } + return sizes; + } + + QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state) Q_DECL_OVERRIDE + { + const QList &sizes = availableSizes(mode, state); + foreach (const QSize &availableSize, sizes) { + if (availableSize.width() >= size.width()) + return availableSize; + } + + return sizes.last(); + } + +private: + const QFileIconProvider *m_fileIconProvider; + QFileInfo m_fileInfo; +}; + + /*! \class QFileIconProvider @@ -86,8 +169,8 @@ QT_BEGIN_NAMESPACE cause a big performance impact over network or removable drives. */ -QFileIconProviderPrivate::QFileIconProviderPrivate() : - homePath(QDir::home().absolutePath()) +QFileIconProviderPrivate::QFileIconProviderPrivate(QFileIconProvider *q) : + q_ptr(q), homePath(QDir::home().absolutePath()) { } @@ -153,7 +236,7 @@ QIcon QFileIconProviderPrivate::getIcon(QStyle::StandardPixmap name) const */ QFileIconProvider::QFileIconProvider() - : d_ptr(new QFileIconProviderPrivate) + : d_ptr(new QFileIconProviderPrivate(this)) { } @@ -238,53 +321,10 @@ static bool isCacheable(const QFileInfo &fi) QIcon QFileIconProviderPrivate::getIcon(const QFileInfo &fi) const { - QIcon retIcon; - const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme(); - if (!theme) - return retIcon; - - QList sizes = theme->themeHint(QPlatformTheme::IconPixmapSizes).value >(); - if (sizes.isEmpty()) - return retIcon; - - const QString keyBase = QLatin1String("qt_.") + fi.suffix().toUpper(); - - bool cacheable = isCacheable(fi); - if (cacheable) { - QPixmap pixmap; - QPixmapCache::find(keyBase + QString::number(sizes.at(0)), pixmap); - if (!pixmap.isNull()) { - bool iconIsComplete = true; - retIcon.addPixmap(pixmap); - for (int i = 1; i < sizes.count(); i++) - if (QPixmapCache::find(keyBase + QString::number(sizes.at(i)), pixmap)) { - retIcon.addPixmap(pixmap); - } else { - iconIsComplete = false; - break; - } - if (iconIsComplete) - return retIcon; - } - } - - QPlatformTheme::IconOptions iconOptions; - if (options & QFileIconProvider::DontUseCustomDirectoryIcons) - iconOptions |= QPlatformTheme::DontUseCustomDirectoryIcons; - - Q_FOREACH (int size, sizes) { - QPixmap pixmap = theme->fileIconPixmap(fi, QSizeF(size, size), iconOptions); - if (!pixmap.isNull()) { - retIcon.addPixmap(pixmap); - if (cacheable) - QPixmapCache::insert(keyBase + QString::number(size), pixmap); - } - } - - return retIcon; + Q_Q(const QFileIconProvider); + return QIcon(new QFileIconEngine(q, fi)); } - /*! Returns an icon for the file described by \a info. */ diff --git a/src/widgets/itemviews/qfileiconprovider_p.h b/src/widgets/itemviews/qfileiconprovider_p.h index 213535616c..a1fb4acbea 100644 --- a/src/widgets/itemviews/qfileiconprovider_p.h +++ b/src/widgets/itemviews/qfileiconprovider_p.h @@ -60,7 +60,7 @@ class QFileIconProviderPrivate Q_DECLARE_PUBLIC(QFileIconProvider) public: - QFileIconProviderPrivate(); + QFileIconProviderPrivate(QFileIconProvider *q); QIcon getIcon(QStyle::StandardPixmap name) const; QIcon getIcon(const QFileInfo &fi) const; From 22afbc153628348bc6d4ee0655ea6a6584a13322 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Tue, 10 Mar 2015 16:22:58 +0100 Subject: [PATCH 055/127] QShortCut: Check whether the menu is QPA-disabled When climbing the menu hierarchy, it's sounder to check whether the actual QPA menu is enabled. This way we can trigger modifier-less shortcuts even in submenus. Task-number: QTBUG-38256 Task-number: QTBUG-42584 Change-Id: I13a27027306bce0f0732b05bf9469f3b77028f73 Reviewed-by: Liang Qi --- src/gui/kernel/qplatformmenu.h | 1 + src/plugins/platforms/cocoa/qcocoamenu.h | 1 + src/plugins/platforms/cocoa/qcocoamenu.mm | 5 +++++ src/widgets/kernel/qshortcut.cpp | 11 ++++++++--- 4 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/gui/kernel/qplatformmenu.h b/src/gui/kernel/qplatformmenu.h index 0536c3688c..baa1e460d7 100644 --- a/src/gui/kernel/qplatformmenu.h +++ b/src/gui/kernel/qplatformmenu.h @@ -103,6 +103,7 @@ public: virtual void setText(const QString &text) = 0; virtual void setIcon(const QIcon &icon) = 0; virtual void setEnabled(bool enabled) = 0; + virtual bool isEnabled() const { return true; } virtual void setVisible(bool visible) = 0; virtual void setMinimumWidth(int width) { Q_UNUSED(width); } virtual void setFont(const QFont &font) { Q_UNUSED(font); } diff --git a/src/plugins/platforms/cocoa/qcocoamenu.h b/src/plugins/platforms/cocoa/qcocoamenu.h index ad8821ca97..59807deb5a 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.h +++ b/src/plugins/platforms/cocoa/qcocoamenu.h @@ -58,6 +58,7 @@ public: void removeMenuItem(QPlatformMenuItem *menuItem); void syncMenuItem(QPlatformMenuItem *menuItem); void setEnabled(bool enabled); + bool isEnabled() const; void setVisible(bool visible); void showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item); void dismiss(); diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index fb11efb689..4fadc2f60a 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -426,6 +426,11 @@ void QCocoaMenu::setEnabled(bool enabled) syncModalState(!m_enabled); } +bool QCocoaMenu::isEnabled() const +{ + return [m_nativeItem isEnabled]; +} + void QCocoaMenu::setVisible(bool visible) { [m_nativeItem setSubmenu:(visible ? m_nativeMenu : nil)]; diff --git a/src/widgets/kernel/qshortcut.cpp b/src/widgets/kernel/qshortcut.cpp index c4326aaa5a..c08c4eeb32 100644 --- a/src/widgets/kernel/qshortcut.cpp +++ b/src/widgets/kernel/qshortcut.cpp @@ -44,6 +44,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -269,9 +270,13 @@ static bool correctActionContext(Qt::ShortcutContext context, QAction *a, QWidge // On Mac, menu item shortcuts are processed before reaching any window. // That means that if a menu action shortcut has not been already processed // (and reaches this point), then the menu item itself has been disabled. - // This occurs at the QPA level on Mac, were we disable all the Cocoa menus - // when showing a modal window. - if (a->shortcut().count() < 1 || (a->shortcut().count() == 1 && (a->shortcut()[0] & Qt::MODIFIER_MASK) != 0)) + // This occurs at the QPA level on Mac, where we disable all the Cocoa menus + // when showing a modal window. (Notice that only the QPA menu is disabled, + // not the QMenu.) Since we can also reach this code by climbing the menu + // hierarchy (see below), or when the shortcut is not a key-equivalent, we + // need to check whether the QPA menu is actually disabled. + QPlatformMenu *pm = menu->platformMenu(); + if (!pm || !pm->isEnabled()) continue; #endif QAction *a = menu->menuAction(); From 85620bd788d351018e9fa0b0f567b19a773be52b Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 9 Mar 2015 13:54:29 +0100 Subject: [PATCH 056/127] windows: Introduce a built-in GPU blacklist Use a built-in JSON file in case the QT_OPENGL_BUGLIST environment variable is not set. When QT_OPENGL_BUGLIST is set, the built-in list is ignored. To make the implementation simpler and more readable, some of the code in QWindowsOpenGLTester is reshuffled a bit. It also caches the results now, so it is safe and fast to call supportedRenderers() and friends multiple times. The blacklist currently contains the Intel card from QTBUG-43263 (Intel GMA / HD3000 ?) and may also apply to QTBUG-42240. [ChangeLog][QtGui] Qt now contains a built-in GPU driver blacklist for Windows that disables the usage of desktop OpenGL with some older cards that are known to be unstable with opengl32.dll. Task-number: QTBUG-42240 Task-number: QTBUG-43263 Change-Id: I1ecd65b51fca77925317d52048e7ab01d9b8797c Reviewed-by: Friedemann Kleint --- src/gui/opengl/qopengl_p.h | 18 ++++ .../platforms/windows/openglblacklists.qrc | 5 ++ .../windows/openglblacklists/default.json | 18 ++++ .../platforms/windows/qwindowsintegration.cpp | 8 +- .../windows/qwindowsopengltester.cpp | 82 ++++++++++--------- .../platforms/windows/qwindowsopengltester.h | 3 + src/plugins/platforms/windows/windows.pri | 2 + 7 files changed, 96 insertions(+), 40 deletions(-) create mode 100644 src/plugins/platforms/windows/openglblacklists.qrc create mode 100644 src/plugins/platforms/windows/openglblacklists/default.json diff --git a/src/gui/opengl/qopengl_p.h b/src/gui/opengl/qopengl_p.h index 377440455a..e04ae05120 100644 --- a/src/gui/opengl/qopengl_p.h +++ b/src/gui/opengl/qopengl_p.h @@ -77,6 +77,9 @@ public: struct Gpu { Gpu() : vendorId(0), deviceId(0) {} bool isValid() const { return deviceId; } + bool equals(const Gpu &other) const { + return vendorId == other.vendorId && deviceId == other.deviceId && driverVersion == other.driverVersion; + } uint vendorId; uint deviceId; @@ -93,6 +96,21 @@ public: static QSet gpuFeatures(const Gpu &gpu, const QString &fileName); }; +inline bool operator==(const QOpenGLConfig::Gpu &a, const QOpenGLConfig::Gpu &b) +{ + return a.equals(b); +} + +inline bool operator!=(const QOpenGLConfig::Gpu &a, const QOpenGLConfig::Gpu &b) +{ + return !a.equals(b); +} + +inline uint qHash(const QOpenGLConfig::Gpu &gpu) +{ + return qHash(gpu.vendorId) + qHash(gpu.deviceId) + qHash(gpu.driverVersion); +} + QT_END_NAMESPACE #endif // QOPENGL_H diff --git a/src/plugins/platforms/windows/openglblacklists.qrc b/src/plugins/platforms/windows/openglblacklists.qrc new file mode 100644 index 0000000000..9f0c186c21 --- /dev/null +++ b/src/plugins/platforms/windows/openglblacklists.qrc @@ -0,0 +1,5 @@ + + + openglblacklists/default.json + + diff --git a/src/plugins/platforms/windows/openglblacklists/default.json b/src/plugins/platforms/windows/openglblacklists/default.json new file mode 100644 index 0000000000..0217b79ecf --- /dev/null +++ b/src/plugins/platforms/windows/openglblacklists/default.json @@ -0,0 +1,18 @@ +{ + "name": "Qt built-in GPU driver blacklist", + "version": "5.5", + "entries": [ + { + "id": 1, + "description": "Desktop OpenGL is unreliable on Intel HD3000/GMA (QTBUG-43263, QTBUG-42240)", + "vendor_id": "0x8086", + "device_id": [ "0x0A16" ], + "os": { + "type": "win" + }, + "features": [ + "disable_desktopgl" + ] + } + ] +} diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 9fd18a1ef4..1041ecf44d 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -79,9 +79,7 @@ # include "qwindowsglcontext.h" #endif -#ifndef Q_OS_WINCE -# include "qwindowsopengltester.h" -#endif +#include "qwindowsopengltester.h" QT_BEGIN_NAMESPACE @@ -209,6 +207,10 @@ QWindowsIntegrationPrivate::QWindowsIntegrationPrivate(const QStringList ¶mL : m_options(0) , m_fontDatabase(0) { +#ifndef Q_OS_WINCE + Q_INIT_RESOURCE(openglblacklists); +#endif + static bool dpiAwarenessSet = false; int tabletAbsoluteRange = -1; // Default to per-monitor awareness to avoid being scaled when monitors with different DPI diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp index ba4c95544e..67548a0836 100644 --- a/src/plugins/platforms/windows/qwindowsopengltester.cpp +++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp @@ -42,14 +42,16 @@ #include #include #include +#include +#ifndef QT_NO_OPENGL #include +#endif #ifndef Q_OS_WINCE # include # include # include -# include #endif QT_BEGIN_NAMESPACE @@ -206,56 +208,62 @@ static inline QString resolveBugListFile(const QString &fileName) return QStandardPaths::locate(QStandardPaths::ConfigLocation, fileName); } -static void readDriverBugList(const GpuDescription &gpu, - QWindowsOpenGLTester::Renderers *result) +typedef QHash SupportedRenderersCache; +Q_GLOBAL_STATIC(SupportedRenderersCache, supportedRenderersCache) + +#endif // !Q_OS_WINCE + +QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::detectSupportedRenderers(const GpuDescription &gpu, bool glesOnly) { - const char bugListFileVar[] = "QT_OPENGL_BUGLIST"; - if (!qEnvironmentVariableIsSet(bugListFileVar)) - return; - const QString fileName = resolveBugListFile(QFile::decodeName(qgetenv(bugListFileVar))); - if (fileName.isEmpty()) - return; + Q_UNUSED(gpu) +#ifndef Q_OS_WINCE QOpenGLConfig::Gpu qgpu; qgpu.deviceId = gpu.deviceId; qgpu.vendorId = gpu.vendorId; qgpu.driverVersion = gpu.driverVersion; - const QSet features = QOpenGLConfig::gpuFeatures(qgpu, fileName); - if (features.contains(QStringLiteral("disable_desktopgl"))) { // Qt-specific - qCWarning(lcQpaGl) << "Disabling Desktop GL: " << gpu; - *result &= ~QWindowsOpenGLTester::DesktopGl; - } - if (features.contains(QStringLiteral("disable_angle"))) { // Qt-specific keyword - qCWarning(lcQpaGl) << "Disabling ANGLE: " << gpu; - *result &= ~QWindowsOpenGLTester::GlesMask; - } else { - if (features.contains(QStringLiteral("disable_d3d11"))) { // standard keyword - qCWarning(lcQpaGl) << "Disabling D3D11: " << gpu; - *result &= ~QWindowsOpenGLTester::AngleRendererD3d11; - } - if (features.contains(QStringLiteral("disable_d3d9"))) { // Qt-specific - qCWarning(lcQpaGl) << "Disabling D3D9: " << gpu; - *result &= ~QWindowsOpenGLTester::AngleRendererD3d9; - } - } -} -#endif // !Q_OS_WINCE + SupportedRenderersCache *srCache = supportedRenderersCache(); + SupportedRenderersCache::const_iterator it = srCache->find(qgpu); + if (it != srCache->cend()) + return *it; -static inline QWindowsOpenGLTester::Renderers - detectSupportedRenderers(const GpuDescription &gpu, bool glesOnly) -{ - Q_UNUSED(gpu) -#ifndef Q_OS_WINCE - // Add checks for card types with known issues here. QWindowsOpenGLTester::Renderers result(QWindowsOpenGLTester::AngleRendererD3d11 | QWindowsOpenGLTester::AngleRendererD3d9 | QWindowsOpenGLTester::AngleRendererD3d11Warp | QWindowsOpenGLTester::SoftwareRasterizer); - if (!glesOnly && QWindowsOpenGLTester::testDesktopGL()) + if (!glesOnly && testDesktopGL()) result |= QWindowsOpenGLTester::DesktopGl; - readDriverBugList(gpu, &result); + QSet features; + const char bugListFileVar[] = "QT_OPENGL_BUGLIST"; + if (qEnvironmentVariableIsSet(bugListFileVar)) { + const QString fileName = resolveBugListFile(QFile::decodeName(qgetenv(bugListFileVar))); + if (!fileName.isEmpty()) + features = QOpenGLConfig::gpuFeatures(qgpu, fileName); + } else { + features = QOpenGLConfig::gpuFeatures(qgpu, QStringLiteral(":/qt-project.org/windows/openglblacklists/default.json")); + } + qCDebug(lcQpaGl) << "GPU features:" << features; + if (features.contains(QStringLiteral("disable_desktopgl"))) { // Qt-specific + qCWarning(lcQpaGl) << "Disabling Desktop GL: " << gpu; + result &= ~QWindowsOpenGLTester::DesktopGl; + } + if (features.contains(QStringLiteral("disable_angle"))) { // Qt-specific keyword + qCWarning(lcQpaGl) << "Disabling ANGLE: " << gpu; + result &= ~QWindowsOpenGLTester::GlesMask; + } else { + if (features.contains(QStringLiteral("disable_d3d11"))) { // standard keyword + qCWarning(lcQpaGl) << "Disabling D3D11: " << gpu; + result &= ~QWindowsOpenGLTester::AngleRendererD3d11; + } + if (features.contains(QStringLiteral("disable_d3d9"))) { // Qt-specific + qCWarning(lcQpaGl) << "Disabling D3D9: " << gpu; + result &= ~QWindowsOpenGLTester::AngleRendererD3d9; + } + } + + srCache->insert(qgpu, result); return result; #else // !Q_OS_WINCE return QWindowsOpenGLTester::Gles; diff --git a/src/plugins/platforms/windows/qwindowsopengltester.h b/src/plugins/platforms/windows/qwindowsopengltester.h index 7b6164946e..748885542d 100644 --- a/src/plugins/platforms/windows/qwindowsopengltester.h +++ b/src/plugins/platforms/windows/qwindowsopengltester.h @@ -80,9 +80,12 @@ public: static Renderer requestedGlesRenderer(); static Renderer requestedRenderer(); + static Renderers supportedGlesRenderers(); static Renderers supportedRenderers(); +private: + static QWindowsOpenGLTester::Renderers detectSupportedRenderers(const GpuDescription &gpu, bool glesOnly); static bool testDesktopGL(); }; diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri index 246598677f..77393033c7 100644 --- a/src/plugins/platforms/windows/windows.pri +++ b/src/plugins/platforms/windows/windows.pri @@ -118,6 +118,8 @@ contains(QT_CONFIG,dynamicgl) { RESOURCES += $$PWD/cursors.qrc } +!wince*: RESOURCES += $$PWD/openglblacklists.qrc + contains(QT_CONFIG, freetype) { DEFINES *= QT_NO_FONTCONFIG QT_FREETYPE_DIR = $$QT_SOURCE_TREE/src/3rdparty/freetype From cc9ca2becea6814b14c87615f67bb8db17968bc1 Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Sat, 14 Feb 2015 20:51:28 +0400 Subject: [PATCH 057/127] Micro optimization to QPainterPrivate::drawGlyphs Re-use font engine obtained in the first place Change-Id: Icdc2ad404ba9b2aadf2732e95c43a47aa957a6fb Reviewed-by: Friedemann Kleint Reviewed-by: Lars Knoll --- src/gui/painting/qpainter.cpp | 9 +++------ src/gui/painting/qpainter_p.h | 2 +- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index bdbb49ff51..995d15581c 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -5565,22 +5565,19 @@ void QPainter::drawGlyphRun(const QPointF &position, const QGlyphRun &glyphRun) fixedPointPositions[i] = QFixedPoint::fromPointF(processedPosition); } - d->drawGlyphs(glyphIndexes, fixedPointPositions.data(), count, font, glyphRun.overline(), - glyphRun.underline(), glyphRun.strikeOut()); + d->drawGlyphs(glyphIndexes, fixedPointPositions.data(), count, fontD->fontEngine, + glyphRun.overline(), glyphRun.underline(), glyphRun.strikeOut()); } void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, QFixedPoint *positions, int glyphCount, - const QRawFont &font, bool overline, bool underline, + QFontEngine *fontEngine, bool overline, bool underline, bool strikeOut) { Q_Q(QPainter); updateState(state); - QRawFontPrivate *fontD = QRawFontPrivate::get(font); - QFontEngine *fontEngine = fontD->fontEngine; - QFixed leftMost; QFixed rightMost; QFixed baseLine; diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h index dde01d32fa..5ac5cac2ff 100644 --- a/src/gui/painting/qpainter_p.h +++ b/src/gui/painting/qpainter_p.h @@ -226,7 +226,7 @@ public: #if !defined(QT_NO_RAWFONT) void drawGlyphs(const quint32 *glyphArray, QFixedPoint *positionArray, int glyphCount, - const QRawFont &font, bool overline = false, bool underline = false, + QFontEngine *fontEngine, bool overline = false, bool underline = false, bool strikeOut = false); #endif From 6ca406d43d63d4c6503f2213b6c8cf0f25f6af5e Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Wed, 11 Mar 2015 13:09:48 +0400 Subject: [PATCH 058/127] Bring harfbuzzng.pri naming in par with the other .pri-s in src/3rdparty Change-Id: I59bf922e3085a03a4c2c370f42418cb005456d3e Reviewed-by: Oswald Buddenhagen --- src/3rdparty/{harfbuzzng.pri => harfbuzz_dependency.pri} | 0 src/gui/text/text.pri | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/3rdparty/{harfbuzzng.pri => harfbuzz_dependency.pri} (100%) diff --git a/src/3rdparty/harfbuzzng.pri b/src/3rdparty/harfbuzz_dependency.pri similarity index 100% rename from src/3rdparty/harfbuzzng.pri rename to src/3rdparty/harfbuzz_dependency.pri diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri index 091129f5be..61e239f678 100644 --- a/src/gui/text/text.pri +++ b/src/gui/text/text.pri @@ -86,7 +86,7 @@ HEADERS += \ contains(QT_CONFIG, harfbuzz)|contains(QT_CONFIG, system-harfbuzz) { DEFINES += QT_ENABLE_HARFBUZZ_NG - include($$PWD/../../3rdparty/harfbuzzng.pri) + include($$PWD/../../3rdparty/harfbuzz_dependency.pri) SOURCES += text/qharfbuzzng.cpp HEADERS += text/qharfbuzzng_p.h From b50e52ed162edbd857b8bb6f4d7d7639f6df119c Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Fri, 6 Mar 2015 20:09:52 +0400 Subject: [PATCH 059/127] Update bundled HarfBuzz copy to 0.9.39 Change-Id: I48d130a1639fef3b8ec2de5622848eb56fadc1c7 Reviewed-by: Lars Knoll --- src/3rdparty/harfbuzz-ng/NEWS | 10 + src/3rdparty/harfbuzz-ng/src/hb-buffer.cc | 2 +- .../harfbuzz-ng/src/hb-open-file-private.hh | 15 +- .../harfbuzz-ng/src/hb-open-type-private.hh | 96 ++--- .../harfbuzz-ng/src/hb-ot-cmap-table.hh | 35 +- .../harfbuzz-ng/src/hb-ot-head-table.hh | 6 +- .../harfbuzz-ng/src/hb-ot-hhea-table.hh | 3 +- .../harfbuzz-ng/src/hb-ot-hmtx-table.hh | 3 +- .../src/hb-ot-layout-common-private.hh | 97 +++-- .../src/hb-ot-layout-gdef-table.hh | 30 +- .../src/hb-ot-layout-gpos-table.hh | 246 +++++------- .../src/hb-ot-layout-gsub-table.hh | 171 +++----- .../src/hb-ot-layout-gsubgpos-private.hh | 378 ++++++++---------- .../src/hb-ot-layout-jstf-table.hh | 12 +- .../harfbuzz-ng/src/hb-ot-layout-private.hh | 5 + src/3rdparty/harfbuzz-ng/src/hb-ot-layout.cc | 105 +++-- .../harfbuzz-ng/src/hb-ot-maxp-table.hh | 6 +- .../harfbuzz-ng/src/hb-ot-name-table.hh | 8 +- .../harfbuzz-ng/src/hb-ot-shape-fallback.cc | 4 +- src/3rdparty/harfbuzz-ng/src/hb-private.hh | 48 ++- .../harfbuzz-ng/src/hb-set-private.hh | 57 ++- src/3rdparty/harfbuzz-ng/src/hb-version.h | 4 +- 22 files changed, 703 insertions(+), 638 deletions(-) diff --git a/src/3rdparty/harfbuzz-ng/NEWS b/src/3rdparty/harfbuzz-ng/NEWS index 3a33bdf5cb..dbbfbba195 100644 --- a/src/3rdparty/harfbuzz-ng/NEWS +++ b/src/3rdparty/harfbuzz-ng/NEWS @@ -1,3 +1,13 @@ +Overview of changes leading to 0.9.39 +Wednesday, March 4, 2015 +===================================== + +- Critical hb-coretext fixes. +- Optimizations and refactoring; no functional change + expected. +- Misc build fixes. + + Overview of changes leading to 0.9.38 Friday, January 23, 2015 ===================================== diff --git a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc index 0500aa23ce..942177cbd0 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc +++ b/src/3rdparty/harfbuzz-ng/src/hb-buffer.cc @@ -454,7 +454,7 @@ hb_buffer_t::reverse_range (unsigned int start, info[j] = t; } - if (pos) { + if (have_positions) { for (i = start, j = end - 1; i < j; i++, j--) { hb_glyph_position_t t; diff --git a/src/3rdparty/harfbuzz-ng/src/hb-open-file-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-open-file-private.hh index 7500c32f15..178bc7ccb8 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-open-file-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-open-file-private.hh @@ -53,7 +53,8 @@ struct TTCHeader; typedef struct TableRecord { - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); return TRACE_RETURN (c->check_struct (this)); } @@ -102,7 +103,8 @@ typedef struct OffsetTable } public: - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); return TRACE_RETURN (c->check_struct (this) && c->check_array (tables, TableRecord::static_size, numTables)); } @@ -130,7 +132,8 @@ struct TTCHeaderVersion1 inline unsigned int get_face_count (void) const { return table.len; } inline const OpenTypeFontFace& get_face (unsigned int i) const { return this+table[i]; } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); return TRACE_RETURN (table.sanitize (c, this)); } @@ -169,7 +172,8 @@ struct TTCHeader } } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); if (unlikely (!u.header.version.sanitize (c))) return TRACE_RETURN (false); switch (u.header.version.major) { @@ -233,7 +237,8 @@ struct OpenTypeFontFile } } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); if (unlikely (!u.tag.sanitize (c))) return TRACE_RETURN (false); switch (u.tag) { diff --git a/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh index 477d9e28b2..75a0f568d1 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-open-type-private.hh @@ -179,10 +179,13 @@ struct hb_sanitize_context_t inline const char *get_name (void) { return "SANITIZE"; } static const unsigned int max_debug_depth = HB_DEBUG_SANITIZE; typedef bool return_t; + template + inline bool may_dispatch (const T *obj, const F *format) + { return format->sanitize (this); } template inline return_t dispatch (const T &obj) { return obj.sanitize (this); } static return_t default_return_value (void) { return true; } - bool stop_sublookup_iteration (const return_t r HB_UNUSED) const { return false; } + bool stop_sublookup_iteration (const return_t r) const { return !r; } inline void init (hb_blob_t *b) { @@ -270,9 +273,9 @@ struct hb_sanitize_context_t } template - inline bool try_set (Type *obj, const ValueType &v) { + inline bool try_set (const Type *obj, const ValueType &v) { if (this->may_edit (obj, obj->static_size)) { - obj->set (v); + const_cast (obj)->set (v); return true; } return false; @@ -546,12 +549,6 @@ struct BEInt return (v[0] << 8) + (v[1] ); } - inline bool operator == (const BEInt& o) const - { - return v[0] == o.v[0] - && v[1] == o.v[1]; - } - inline bool operator != (const BEInt& o) const { return !(*this == o); } private: uint8_t v[2]; }; template @@ -570,13 +567,6 @@ struct BEInt + (v[1] << 8) + (v[2] ); } - inline bool operator == (const BEInt& o) const - { - return v[0] == o.v[0] - && v[1] == o.v[1] - && v[2] == o.v[2]; - } - inline bool operator != (const BEInt& o) const { return !(*this == o); } private: uint8_t v[3]; }; template @@ -597,14 +587,6 @@ struct BEInt + (v[2] << 8) + (v[3] ); } - inline bool operator == (const BEInt& o) const - { - return v[0] == o.v[0] - && v[1] == o.v[1] - && v[2] == o.v[2] - && v[3] == o.v[3]; - } - inline bool operator != (const BEInt& o) const { return !(*this == o); } private: uint8_t v[4]; }; @@ -614,12 +596,19 @@ struct IntType { inline void set (Type i) { v.set (i); } inline operator Type(void) const { return v; } - inline bool operator == (const IntType &o) const { return v == o.v; } - inline bool operator != (const IntType &o) const { return v != o.v; } + inline bool operator == (const IntType &o) const { return (Type) v == (Type) o.v; } + inline bool operator != (const IntType &o) const { return !(*this == o); } static inline int cmp (const IntType *a, const IntType *b) { return b->cmp (*a); } - inline int cmp (IntType va) const { Type a = va; Type b = v; return a < b ? -1 : a == b ? 0 : +1; } - inline int cmp (Type a) const { Type b = v; return a < b ? -1 : a == b ? 0 : +1; } - inline bool sanitize (hb_sanitize_context_t *c) { + inline int cmp (Type a) const + { + Type b = v; + if (sizeof (Type) < sizeof (int)) + return (int) a - (int) b; + else + return a < b ? -1 : a == b ? 0 : +1; + } + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); return TRACE_RETURN (likely (c->check_struct (this))); } @@ -646,7 +635,8 @@ typedef USHORT UFWORD; * 1904. The value is represented as a signed 64-bit integer. */ struct LONGDATETIME { - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); return TRACE_RETURN (likely (c->check_struct (this))); } @@ -670,7 +660,10 @@ struct Tag : ULONG DEFINE_NULL_DATA (Tag, " "); /* Glyph index number, same as uint16 (length = 16 bits) */ -typedef USHORT GlyphID; +struct GlyphID : USHORT { + static inline int cmp (const GlyphID *a, const GlyphID *b) { return b->USHORT::cmp (*a); } + inline int cmp (hb_codepoint_t a) const { return (int) a - (int) *this; } +}; /* Script/language-system/feature index */ struct Index : USHORT { @@ -719,7 +712,8 @@ struct FixedVersion { inline uint32_t to_int (void) const { return (major << 16) + minor; } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); return TRACE_RETURN (c->check_struct (this)); } @@ -747,33 +741,35 @@ struct OffsetTo : Offset return StructAtOffset (base, offset); } - inline Type& serialize (hb_serialize_context_t *c, void *base) + inline Type& serialize (hb_serialize_context_t *c, const void *base) { Type *t = c->start_embed (); this->set ((char *) t - (char *) base); /* TODO(serialize) Overflow? */ return *t; } - inline bool sanitize (hb_sanitize_context_t *c, void *base) { + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { TRACE_SANITIZE (this); if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); unsigned int offset = *this; if (unlikely (!offset)) return TRACE_RETURN (true); - Type &obj = StructAtOffset (base, offset); + const Type &obj = StructAtOffset (base, offset); return TRACE_RETURN (likely (obj.sanitize (c)) || neuter (c)); } template - inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { + inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const + { TRACE_SANITIZE (this); if (unlikely (!c->check_struct (this))) return TRACE_RETURN (false); unsigned int offset = *this; if (unlikely (!offset)) return TRACE_RETURN (true); - Type &obj = StructAtOffset (base, offset); + const Type &obj = StructAtOffset (base, offset); return TRACE_RETURN (likely (obj.sanitize (c, user_data)) || neuter (c)); } /* Set the offset to Null */ - inline bool neuter (hb_sanitize_context_t *c) { + inline bool neuter (hb_sanitize_context_t *c) const { return c->try_set (this, 0); } DEFINE_SIZE_STATIC (sizeof(OffsetType)); @@ -838,7 +834,8 @@ struct ArrayOf return TRACE_RETURN (true); } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); @@ -853,7 +850,8 @@ struct ArrayOf return TRACE_RETURN (true); } - inline bool sanitize (hb_sanitize_context_t *c, void *base) { + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { TRACE_SANITIZE (this); if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); unsigned int count = len; @@ -863,7 +861,8 @@ struct ArrayOf return TRACE_RETURN (true); } template - inline bool sanitize (hb_sanitize_context_t *c, void *base, T user_data) { + inline bool sanitize (hb_sanitize_context_t *c, const void *base, T user_data) const + { TRACE_SANITIZE (this); if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); unsigned int count = len; @@ -884,7 +883,8 @@ struct ArrayOf } private: - inline bool sanitize_shallow (hb_sanitize_context_t *c) { + inline bool sanitize_shallow (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); return TRACE_RETURN (c->check_struct (this) && c->check_array (this, Type::static_size, len)); } @@ -910,12 +910,14 @@ struct OffsetListOf : OffsetArrayOf return this+this->array[i]; } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); return TRACE_RETURN (OffsetArrayOf::sanitize (c, this)); } template - inline bool sanitize (hb_sanitize_context_t *c, T user_data) { + inline bool sanitize (hb_sanitize_context_t *c, T user_data) const + { TRACE_SANITIZE (this); return TRACE_RETURN (OffsetArrayOf::sanitize (c, this, user_data)); } @@ -949,12 +951,14 @@ struct HeadlessArrayOf return TRACE_RETURN (true); } - inline bool sanitize_shallow (hb_sanitize_context_t *c) { + inline bool sanitize_shallow (hb_sanitize_context_t *c) const + { return c->check_struct (this) && c->check_array (this, Type::static_size, len); } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); if (unlikely (!sanitize_shallow (c))) return TRACE_RETURN (false); diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh index d53141157d..0482312553 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-cmap-table.hh @@ -51,7 +51,8 @@ struct CmapSubtableFormat0 return true; } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); return TRACE_RETURN (c->check_struct (this)); } @@ -125,7 +126,7 @@ struct CmapSubtableFormat4 return true; } - inline bool sanitize (hb_sanitize_context_t *c) + inline bool sanitize (hb_sanitize_context_t *c) const { TRACE_SANITIZE (this); if (unlikely (!c->check_struct (this))) @@ -183,7 +184,8 @@ struct CmapSubtableLongGroup return 0; } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); return TRACE_RETURN (c->check_struct (this)); } @@ -210,7 +212,8 @@ struct CmapSubtableTrimmed return true; } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); return TRACE_RETURN (c->check_struct (this) && glyphIdArray.sanitize (c)); } @@ -242,7 +245,8 @@ struct CmapSubtableLongSegmented return true; } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); return TRACE_RETURN (c->check_struct (this) && groups.sanitize (c)); } @@ -288,7 +292,8 @@ struct UnicodeValueRange return 0; } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); return TRACE_RETURN (c->check_struct (this)); } @@ -309,7 +314,8 @@ struct UVSMapping return unicodeValue.cmp (codepoint); } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); return TRACE_RETURN (c->check_struct (this)); } @@ -348,7 +354,8 @@ struct VariationSelectorRecord return varSelector.cmp (variation_selector); } - inline bool sanitize (hb_sanitize_context_t *c, void *base) { + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { TRACE_SANITIZE (this); return TRACE_RETURN (c->check_struct (this) && defaultUVS.sanitize (c, base) && @@ -373,7 +380,8 @@ struct CmapSubtableFormat14 return record[record.bsearch(variation_selector)].get_glyph (codepoint, glyph, this); } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); return TRACE_RETURN (c->check_struct (this) && record.sanitize (c, this)); @@ -418,7 +426,8 @@ struct CmapSubtable } } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); if (!u.format.sanitize (c)) return TRACE_RETURN (false); switch (u.format) { @@ -461,7 +470,8 @@ struct EncodingRecord return 0; } - inline bool sanitize (hb_sanitize_context_t *c, void *base) { + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { TRACE_SANITIZE (this); return TRACE_RETURN (c->check_struct (this) && subtable.sanitize (c, base)); @@ -496,7 +506,8 @@ struct cmap return &(this+encodingRecord[result].subtable); } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); return TRACE_RETURN (c->check_struct (this) && likely (version == 0) && diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh index ec4e8c9d45..268f133408 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-head-table.hh @@ -45,13 +45,15 @@ struct head { static const hb_tag_t tableTag = HB_OT_TAG_head; - inline unsigned int get_upem (void) const { + inline unsigned int get_upem (void) const + { unsigned int upem = unitsPerEm; /* If no valid head table found, assume 1000, which matches typical Type1 usage. */ return 16 <= upem && upem <= 16384 ? upem : 1000; } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); return TRACE_RETURN (c->check_struct (this) && likely (version.major == 1)); } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-hhea-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-hhea-table.hh index edc0e29cbf..992fe55202 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-hhea-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-hhea-table.hh @@ -49,7 +49,8 @@ struct _hea static const hb_tag_t hheaTag = HB_OT_TAG_hhea; static const hb_tag_t vheaTag = HB_OT_TAG_vhea; - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); return TRACE_RETURN (c->check_struct (this) && likely (version.major == 1)); } diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh index 317854ce7f..a0e3855a84 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-hmtx-table.hh @@ -57,7 +57,8 @@ struct _mtx static const hb_tag_t hmtxTag = HB_OT_TAG_hmtx; static const hb_tag_t vmtxTag = HB_OT_TAG_vmtx; - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); /* We don't check for anything specific here. The users of the * struct do all the hard work... */ diff --git a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common-private.hh b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common-private.hh index abd063c896..3db7f57ab4 100644 --- a/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common-private.hh +++ b/src/3rdparty/harfbuzz-ng/src/hb-ot-layout-common-private.hh @@ -37,6 +37,12 @@ namespace OT { +#define TRACE_DISPATCH(this, format) \ + hb_auto_trace_t trace \ + (&c->debug_depth, c->get_name (), this, HB_FUNC, \ + "format %d", (int) format); + + #define NOT_COVERED ((unsigned int) -1) #define MAX_NESTING_LEVEL 8 #define MAX_CONTEXT_LENGTH 64 @@ -63,9 +69,10 @@ struct Record struct sanitize_closure_t { hb_tag_t tag; - void *list_base; + const void *list_base; }; - inline bool sanitize (hb_sanitize_context_t *c, void *base) { + inline bool sanitize (hb_sanitize_context_t *c, const void *base) const + { TRACE_SANITIZE (this); const sanitize_closure_t closure = {tag, base}; return TRACE_RETURN (c->check_struct (this) && offset.sanitize (c, base, &closure)); @@ -121,7 +128,8 @@ struct RecordListOf : RecordArrayOf inline const Type& operator [] (unsigned int i) const { return this+RecordArrayOf::operator [](i).offset; } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); return TRACE_RETURN (RecordArrayOf::sanitize (c, this)); } @@ -134,7 +142,8 @@ struct RangeRecord return g < start ? -1 : g <= end ? 0 : +1 ; } - inline bool sanitize (hb_sanitize_context_t *c) { + inline bool sanitize (hb_sanitize_context_t *c) const + { TRACE_SANITIZE (this); return TRACE_RETURN (c->check_struct (this)); } @@ -199,7 +208,8 @@ struct LangSys } inline bool sanitize (hb_sanitize_context_t *c, - const Record::sanitize_closure_t * = NULL) { + const Record::sanitize_closure_t * = NULL) const + { TRACE_SANITIZE (this); return TRACE_RETURN (c->check_struct (this) && featureIndex.sanitize (c)); } @@ -238,7 +248,8 @@ struct Script inline const LangSys& get_default_lang_sys (void) const { return this+defaultLangSys; } inline bool sanitize (hb_sanitize_context_t *c, - const Record