From d0349e17acc4b0bc2b4a100d2dc786525f36837f Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Mon, 5 Mar 2018 10:18:35 +0100 Subject: [PATCH 01/29] tst_QGuiApplication check WindowActivate capability instead of platform MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-66849 Change-Id: I31dfe6d38435b043eb21d2de02d44551649444c9 Reviewed-by: Tor Arne Vestbø --- .../kernel/qguiapplication/tst_qguiapplication.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp index 4f27aeb8990..b5a69d920aa 100644 --- a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp +++ b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp @@ -35,9 +35,12 @@ #include #include #include +#include #include #include +#include + #if defined(Q_OS_QNX) #include #endif @@ -203,8 +206,8 @@ void tst_QGuiApplication::focusObject() int argc = 0; QGuiApplication app(argc, 0); - if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive)) - QSKIP("Wayland: This fails. Figure out why."); + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); QObject obj1, obj2, obj3; const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry(); @@ -374,8 +377,8 @@ void tst_QGuiApplication::changeFocusWindow() int argc = 0; QGuiApplication app(argc, 0); - if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive)) - QSKIP("Wayland: This fails. Figure out why."); + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry(); From 17b65edad11987f67b97aa9171be426dbfa8a668 Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Mon, 5 Mar 2018 10:33:59 +0100 Subject: [PATCH 02/29] tst_QInputMethod check WindowActivation capability instead of platform MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-66849 Change-Id: I72a8751f1fc0df7ff5a371c854cb975b3cee8fd2 Reviewed-by: Tor Arne Vestbø --- tests/auto/gui/kernel/qinputmethod/tst_qinputmethod.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/auto/gui/kernel/qinputmethod/tst_qinputmethod.cpp b/tests/auto/gui/kernel/qinputmethod/tst_qinputmethod.cpp index 509f8bd45fa..15c905f943e 100644 --- a/tests/auto/gui/kernel/qinputmethod/tst_qinputmethod.cpp +++ b/tests/auto/gui/kernel/qinputmethod/tst_qinputmethod.cpp @@ -186,8 +186,8 @@ void tst_qinputmethod::cursorRectangle() { QCOMPARE(qApp->inputMethod()->cursorRectangle(), QRectF()); - if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive)) - QSKIP("Wayland: This fails. Figure out why."); + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); DummyWindow window; window.show(); @@ -284,8 +284,8 @@ void tst_qinputmethod::inputDirection() void tst_qinputmethod::inputMethodAccepted() { - if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive)) - QSKIP("Wayland: This fails. Figure out why."); + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); if (!QGuiApplication::platformName().compare(QLatin1String("minimal"), Qt::CaseInsensitive) || !QGuiApplication::platformName().compare(QLatin1String("offscreen"), Qt::CaseInsensitive)) { From 951e204b29bf42459e8cfdf42eadec5fa250226b Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Mon, 5 Mar 2018 11:24:55 +0100 Subject: [PATCH 03/29] Skip failing tests in tst_QPixmap on Wayland Task-number: QTBUG-66846 Change-Id: I61bd3e59e51fd1d988a30b6454a6a90650a3069b Reviewed-by: Eirik Aavitsland --- tests/auto/gui/image/qpixmap/tst_qpixmap.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp index e3bda6c2dfb..de6713596d4 100644 --- a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp +++ b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp @@ -527,8 +527,16 @@ void tst_QPixmap::fill_transparent() QVERIFY(pixmap.hasAlphaChannel()); } +static bool isPlatformWayland() +{ + return QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive); +} + void tst_QPixmap::mask() { + if (isPlatformWayland()) + QSKIP("Wayland: This fails. See QTBUG-66983."); + QPixmap pm(100, 100); QBitmap bm(100, 100); @@ -770,6 +778,9 @@ void tst_QPixmap::convertFromImageNoDetach() void tst_QPixmap::convertFromImageNoDetach2() { + if (isPlatformWayland()) + QSKIP("Wayland: This fails. See QTBUG-66984."); + QPixmap randomPixmap(10, 10); if (randomPixmap.handle()->classId() != QPlatformPixmap::RasterClass) QSKIP("Test only valid for raster pixmaps"); @@ -1444,6 +1455,9 @@ void tst_QPixmap::fromImageReaderAnimatedGif() void tst_QPixmap::task_246446() { + if (isPlatformWayland()) + QSKIP("Wayland: This fails. See QTBUG-66985."); + // This crashed without the bugfix in 246446 QPixmap pm(10, 10); pm.fill(Qt::transparent); // force 32-bit depth From 5473535344e7abe12c9a02559020b37480d30d21 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 12 Dec 2017 12:07:38 +0100 Subject: [PATCH 04/29] Fix scaling precision with large zooms Avoid using the two fast-scaling paths, while they might not overflow in this case, they do not have enough precision in their fixed point math to render accurately. Task-number: QTBUG-53582 Change-Id: I2e063ee90defbecd79a12a6ce02a74c60d1805df Reviewed-by: Eirik Aavitsland --- src/gui/painting/qpaintengine_raster.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index f7578a3c575..33fde8c61ab 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -2341,8 +2341,12 @@ void QRasterPaintEngine::drawImage(const QRectF &r, const QImage &img, const QRe if (s->matrix.type() > QTransform::TxTranslate || stretch_sr) { QRectF targetBounds = s->matrix.mapRect(r); - bool exceedsPrecision = targetBounds.width() > 0x7fff - || targetBounds.height() > 0x7fff; + bool exceedsPrecision = r.width() > 0x7fff + || r.height() > 0x7fff + || targetBounds.width() > 0x7fff + || targetBounds.height() > 0x7fff + || s->matrix.m11() >= 512 + || s->matrix.m22() >= 512; if (!exceedsPrecision && d->canUseFastImageBlending(d->rasterBuffer->compositionMode, img)) { if (s->matrix.type() > QTransform::TxScale) { @@ -4639,9 +4643,13 @@ void QSpanData::setupMatrix(const QTransform &matrix, int bilin) bilinear = bilin; const bool affine = inv.isAffine(); + const qreal f1 = m11 * m11 + m21 * m21; + const qreal f2 = m12 * m12 + m22 * m22; fast_matrix = affine - && m11 * m11 + m21 * m21 < 1e4 - && m12 * m12 + m22 * m22 < 1e4 + && f1 < 1e4 + && f2 < 1e4 + && f1 > (1.0 / 65536) + && f2 > (1.0 / 65536) && qAbs(dx) < 1e4 && qAbs(dy) < 1e4; From 3ae03c3585df7247f5699eeaa70e1bedf47f6d5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 9 Mar 2018 12:03:01 +0100 Subject: [PATCH 05/29] testlib: Silence all Qt logging in selftests Otherwise random debug messages from Qt might mess up the expected vs actual results. The setting of QT_LOGGING_RULES in initTestcase has been removed, as the selftest overrides that for each invocation of a subtests, via the processEnvironment() function. Task-number: QTQAINFRA-1631 Change-Id: I855d31274f8261f8b125df23409353f7101be0e4 Reviewed-by: Friedemann Kleint --- tests/auto/testlib/selftests/generate_expected_output.py | 2 +- tests/auto/testlib/selftests/tst_selftests.cpp | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/auto/testlib/selftests/generate_expected_output.py b/tests/auto/testlib/selftests/generate_expected_output.py index 6c14d75ea6a..aa11ca4fe77 100755 --- a/tests/auto/testlib/selftests/generate_expected_output.py +++ b/tests/auto/testlib/selftests/generate_expected_output.py @@ -257,7 +257,7 @@ def main(name, *args): # Avoid interference from any qtlogging.ini files, e.g. in # /etc/xdg/QtProject/, (must match tst_selftests.cpp's # processEnvironment()'s value): - QT_LOGGING_RULES = '*.debug=true;qt.qpa.screen=false') + QT_LOGGING_RULES = '*.debug=true;qt.*=false') herePath = os.getcwd() cleaner = Cleaner(herePath, name) diff --git a/tests/auto/testlib/selftests/tst_selftests.cpp b/tests/auto/testlib/selftests/tst_selftests.cpp index 93d5daa160f..63e5721e7e4 100644 --- a/tests/auto/testlib/selftests/tst_selftests.cpp +++ b/tests/auto/testlib/selftests/tst_selftests.cpp @@ -404,7 +404,6 @@ tst_Selftests::tst_Selftests() void tst_Selftests::initTestCase() { QVERIFY2(tempDir.isValid(), qPrintable(tempDir.errorString())); - qputenv("QT_LOGGING_RULES", QByteArrayLiteral("*.debug=false")); // Silence any debug output //Detect the location of the sub programs QString subProgram = QLatin1String("float/float"); #if defined(Q_OS_WIN) @@ -644,7 +643,7 @@ static QProcessEnvironment processEnvironment() // Avoid interference from any qtlogging.ini files, e.g. in /etc/xdg/QtProject/: result.insert(QStringLiteral("QT_LOGGING_RULES"), // Must match generate_expected_output.py's main()'s value: - QStringLiteral("*.debug=true;qt.qpa.screen=false")); + QStringLiteral("*.debug=true;qt.*=false")); } return result; } From 54190595efe55bdbb647c69fa7b0a43d3f84dd68 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 28 Jul 2017 13:25:50 +0200 Subject: [PATCH 06/29] Make sure QDir::absoluteFilePath("/dir") includes a drive on MS QDir::isAbsolutePath(name) thinks any path starting with a slash is absolute; however, to return a valid absolute path, we need to put a drive prefix onto such a name. So use QFileSystemEntry::isAbsolute() for that check (it believes in the need for a drive, or UNC prefix) and handle the absolute-but-for-drive case when it arises. Add a regression test and make related changes to existing tests. Task-number: QTBUG-50839 Change-Id: Id5d2b2586bb1423fa2d9375a298a4bb5241cffe0 Reviewed-by: Oswald Buddenhagen Reviewed-by: Thiago Macieira --- src/corelib/io/qdir.cpp | 36 ++++++++++++++++++++++++- tests/auto/corelib/io/qdir/tst_qdir.cpp | 18 ++++++++----- 2 files changed, 47 insertions(+), 7 deletions(-) diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp index 520f98b18fe..e4d384e4ca5 100644 --- a/src/corelib/io/qdir.cpp +++ b/src/corelib/io/qdir.cpp @@ -750,13 +750,47 @@ QString QDir::filePath(const QString &fileName) const QString QDir::absoluteFilePath(const QString &fileName) const { const QDirPrivate* d = d_ptr.constData(); - if (isAbsolutePath(fileName)) + // Don't trust our own isAbsolutePath(); Q_OS_WIN needs a drive. + if (QFileSystemEntry(fileName).isAbsolute()) return fileName; d->resolveAbsoluteEntry(); const QString absoluteDirPath = d->absoluteDirEntry.filePath(); if (fileName.isEmpty()) return absoluteDirPath; +#ifdef Q_OS_WIN + // Handle the "absolute except for drive" case (i.e. \blah not c:\blah): + int size = absoluteDirPath.length(); + if ((fileName.startsWith(QLatin1Char('/')) + || fileName.startsWith(QLatin1Char('\\'))) + && size > 1) { + // Combine absoluteDirPath's drive with fileName + int drive = 2; // length of drive prefix + if (Q_UNLIKELY(absoluteDirPath.at(1).unicode() != ':')) { + // Presumably, absoluteDirPath is an UNC path; use its //server/share + // part as "drive" - it's as sane a thing as we can do. + for (int i = 2; i-- > 0; ) { // Scan two "path fragments": + while (drive < size && absoluteDirPath.at(drive).unicode() == '/') + drive++; + if (drive >= size) { + qWarning("Base directory starts with neither a drive nor a UNC share: %s", + qPrintable(QDir::toNativeSeparators(absoluteDirPath))); + return QString(); + } + while (drive < size && absoluteDirPath.at(drive).unicode() != '/') + drive++; + } + // We'll append fileName, which starts with a slash; so omit trailing slash: + if (absoluteDirPath.at(drive).unicode() == '/') + drive--; + } else if (!absoluteDirPath.at(0).isLetter()) { + qWarning("Base directory's drive is not a letter: %s", + qPrintable(QDir::toNativeSeparators(absoluteDirPath))); + return QString(); + } + return absoluteDirPath.leftRef(drive) % fileName; + } +#endif // Q_OS_WIN if (!absoluteDirPath.endsWith(QLatin1Char('/'))) return absoluteDirPath % QLatin1Char('/') % fileName; return absoluteDirPath % fileName; diff --git a/tests/auto/corelib/io/qdir/tst_qdir.cpp b/tests/auto/corelib/io/qdir/tst_qdir.cpp index 9d47bb28845..734b26cd65d 100644 --- a/tests/auto/corelib/io/qdir/tst_qdir.cpp +++ b/tests/auto/corelib/io/qdir/tst_qdir.cpp @@ -1384,16 +1384,22 @@ void tst_QDir::absoluteFilePath_data() QTest::addColumn("fileName"); QTest::addColumn("expectedFilePath"); - QTest::newRow("0") << "/etc" << "/passwd" << "/passwd"; - QTest::newRow("1") << "/etc" << "passwd" << "/etc/passwd"; - QTest::newRow("2") << "/" << "passwd" << "/passwd"; - QTest::newRow("3") << "relative" << "path" << QDir::currentPath() + "/relative/path"; - QTest::newRow("4") << "" << "" << QDir::currentPath(); #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) - QTest::newRow("5") << "//machine" << "share" << "//machine/share"; + QTest::newRow("UNC") << "//machine" << "share" << "//machine/share"; + QTest::newRow("Drive") << "c:/side/town" << "/my/way/home" << "c:/my/way/home"; +#define DRIVE "Q:" +#else +#define DRIVE #endif + QTest::newRow("0") << DRIVE "/etc" << "/passwd" << DRIVE "/passwd"; + QTest::newRow("1") << DRIVE "/etc" << "passwd" << DRIVE "/etc/passwd"; + QTest::newRow("2") << DRIVE "/" << "passwd" << DRIVE "/passwd"; + QTest::newRow("3") << "relative" << "path" << QDir::currentPath() + "/relative/path"; + QTest::newRow("4") << "" << "" << QDir::currentPath(); + QTest::newRow("resource") << ":/prefix" << "foo.bar" << ":/prefix/foo.bar"; +#undef DRIVE } void tst_QDir::absoluteFilePath() From c6ea77f59d493e16f03cd82e532fe4f8cda5eaf1 Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Tue, 6 Mar 2018 10:02:21 +0100 Subject: [PATCH 07/29] Use QWindow::windowStates() for WindowStateChangedEvent::oldState MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit WindowStateChangedEvent::oldState is of type Qt::WindowStates and should therefore be set to QWindow::windowStates() instead of QWindow::windowState() Change-Id: I6710624dd303642a31bfbb25bc07bf05b921d84c Reviewed-by: Tor Arne Vestbø Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/gui/kernel/qwindowsysteminterface.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 318a280a40e..5243ae66a2c 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -251,7 +251,7 @@ QT_DEFINE_QPA_EVENT_HANDLER(void, handleWindowStateChanged, QWindow *window, Qt: { Q_ASSERT(window); if (oldState < Qt::WindowNoState) - oldState = window->windowState(); + oldState = window->windowStates(); QWindowSystemInterfacePrivate::WindowStateChangedEvent *e = new QWindowSystemInterfacePrivate::WindowStateChangedEvent(window, newState, Qt::WindowStates(oldState)); From 0e37558b6edd0cbdfa2a3bc8d67d9170c7917d7f Mon Sep 17 00:00:00 2001 From: Johan Klokkhammer Helsing Date: Mon, 5 Mar 2018 10:44:03 +0100 Subject: [PATCH 08/29] Don't skip tests in tst_QTouchEvent on Wayland They seem to be running just fine Task-number: QTBUG-66849 Change-Id: Ia48d47c0fff173eb1d6eba38bdba752a91bd2b56 Reviewed-by: Shawn Rutledge --- .../kernel/qtouchevent/tst_qtouchevent.cpp | 21 ------------------- 1 file changed, 21 deletions(-) diff --git a/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp b/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp index 706c66ef146..d16d95500b6 100644 --- a/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp +++ b/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp @@ -317,9 +317,6 @@ void tst_QTouchEvent::touchDisabledByDefault() void tst_QTouchEvent::touchEventAcceptedByDefault() { - if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive)) - QSKIP("Wayland: This fails. Figure out why."); - // QWidget { // enabling touch events should automatically accept touch events @@ -606,9 +603,6 @@ QPointF normalized(const QPointF &pos, const QRectF &rect) void tst_QTouchEvent::basicRawEventTranslation() { - if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive)) - QSKIP("Wayland: This fails. Figure out why."); - tst_QTouchEventWidget touchWidget; touchWidget.setWindowTitle(QTest::currentTestFunction()); touchWidget.setAttribute(Qt::WA_AcceptTouchEvents); @@ -733,9 +727,6 @@ void tst_QTouchEvent::basicRawEventTranslation() void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen() { - if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive)) - QSKIP("Wayland: This fails. Figure out why."); - tst_QTouchEventWidget touchWidget; touchWidget.setWindowTitle(QTest::currentTestFunction()); touchWidget.setAttribute(Qt::WA_AcceptTouchEvents); @@ -962,9 +953,6 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen() void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad() { - if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive)) - QSKIP("Wayland: This fails. Figure out why."); - tst_QTouchEventWidget touchWidget; touchWidget.setWindowTitle(QTest::currentTestFunction()); touchWidget.setAttribute(Qt::WA_AcceptTouchEvents); @@ -1191,9 +1179,6 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad() void tst_QTouchEvent::basicRawEventTranslationOfIds() { - if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive)) - QSKIP("Wayland: This fails. Figure out why."); - tst_QTouchEventWidget touchWidget; touchWidget.setWindowTitle(QTest::currentTestFunction()); touchWidget.setAttribute(Qt::WA_AcceptTouchEvents); @@ -1311,9 +1296,6 @@ void tst_QTouchEvent::basicRawEventTranslationOfIds() void tst_QTouchEvent::deleteInEventHandler() { - if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive)) - QSKIP("Wayland: This fails. Figure out why."); - // QWidget { QWidget window; @@ -1463,9 +1445,6 @@ void tst_QTouchEvent::deleteInEventHandler() void tst_QTouchEvent::deleteInRawEventTranslation() { - if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive)) - QSKIP("Wayland: This fails. Figure out why."); - tst_QTouchEventWidget touchWidget; touchWidget.setWindowTitle(QTest::currentTestFunction()); touchWidget.setAttribute(Qt::WA_AcceptTouchEvents); From 910cc08f6b45241b80bdf50732fa9c1283499d49 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 13 Mar 2018 10:08:25 +0100 Subject: [PATCH 09/29] Windows QPA: Improve the event logging Add more message codes and fix the whitespaces in the output: EVENT: hwd= 0x280484 WM_WINDOWPOSCHANGED msg=0x 47 et=0x 21e wp= 0 at -2208 -31887 handled= false -> EVENT: hwd=0x2204d6 WM_WINDOWPOSCHANGED msg=0x47 et=0x21e wp=0 at -3280,-19633 handled=false Change-Id: I89a7b3bd328748ef39fe2dcd789497f43e9d4a2a Reviewed-by: Andre de la Rocha Reviewed-by: Joerg Bornemann --- .../eventdispatchers/qwindowsguieventdispatcher.cpp | 6 +++++- src/plugins/platforms/windows/qwindowscontext.cpp | 7 ++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/platformsupport/eventdispatchers/qwindowsguieventdispatcher.cpp b/src/platformsupport/eventdispatchers/qwindowsguieventdispatcher.cpp index de369e0b00d..aa7bb102c6f 100644 --- a/src/platformsupport/eventdispatchers/qwindowsguieventdispatcher.cpp +++ b/src/platformsupport/eventdispatchers/qwindowsguieventdispatcher.cpp @@ -134,6 +134,7 @@ messageDebugEntries[] = { {WM_XBUTTONUP, "WM_XBUTTONUP", true}, {WM_XBUTTONDBLCLK, "WM_XBUTTONDBLCLK", true}, {WM_MOUSEHWHEEL, "WM_MOUSEHWHEEL", true}, + {WM_GETOBJECT, "WM_GETOBJECT", true}, {WM_IME_SETCONTEXT, "WM_IME_SETCONTEXT", true}, {WM_INPUTLANGCHANGE, "WM_INPUTLANGCHANGE", true}, {WM_IME_NOTIFY, "WM_IME_NOTIFY", true}, @@ -162,6 +163,7 @@ messageDebugEntries[] = { {WM_GETMINMAXINFO, "WM_GETMINMAXINFO", true}, {WM_WINDOWPOSCHANGING, "WM_WINDOWPOSCHANGING", true}, {WM_NCCREATE, "WM_NCCREATE", true}, + {WM_NCDESTROY, "WM_NCDESTROY", true}, {WM_NCCALCSIZE, "WM_NCCALCSIZE", true}, {WM_NCACTIVATE, "WM_NCACTIVATE", true}, {WM_NCMOUSEMOVE, "WM_NCMOUSEMOVE", true}, @@ -180,7 +182,9 @@ messageDebugEntries[] = { {WM_CHANGECBCHAIN, "WM_CHANGECBCHAIN", true}, {WM_DISPLAYCHANGE, "WM_DISPLAYCHANGE", true}, {WM_DRAWCLIPBOARD, "WM_DRAWCLIPBOARD", true}, - {WM_THEMECHANGED, "WM_THEMECHANGED", true} + {WM_THEMECHANGED, "WM_THEMECHANGED", true}, + {0x90, "WM_UAHDESTROYWINDOW", true}, + {0x272, "WM_UNREGISTER_WINDOW_SERVICES", true} }; static inline const MessageDebugEntry *messageDebugEntry(UINT msg) diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 3d0dbd7b1a3..20d6e6e8d49 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -1364,9 +1364,10 @@ extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPAR const bool handled = QWindowsContext::instance()->windowsProc(hwnd, message, et, wParam, lParam, &result, &platformWindow); if (QWindowsContext::verbose > 1 && lcQpaEvents().isDebugEnabled()) { if (const char *eventName = QWindowsGuiEventDispatcher::windowsMessageName(message)) { - qCDebug(lcQpaEvents) << "EVENT: hwd=" << hwnd << eventName << hex << "msg=0x" << message - << "et=0x" << et << dec << "wp=" << int(wParam) << "at" - << GET_X_LPARAM(lParam) << GET_Y_LPARAM(lParam) << "handled=" << handled; + qCDebug(lcQpaEvents).nospace() << "EVENT: hwd=" << hwnd << ' ' << eventName + << " msg=0x" << hex << message << " et=0x" << et << dec << " wp=" + << int(wParam) << " at " << GET_X_LPARAM(lParam) << ',' + << GET_Y_LPARAM(lParam) << " handled=" << handled; } } if (!handled) From 43918feb4adbcd2e7035b5985309eefe2e2f28c6 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 13 Mar 2018 10:50:41 +0100 Subject: [PATCH 10/29] Windows QPA: Fix QWindowsWindowFunctions::SetHasBorderInFullScreen() to work in all cases - Directly apply the flag in case the platform window exists and is in full screen. - Store as a dynamic property in case the platform window is not created yet. Amends 69839e55c13000ee9bf8d8e9d74b70096a92ae51. Task-number: QTBUG-41309 Task-number: QTBUG-66557 Change-Id: I162baecfae4d07a5d5b59c5401bdb605faa7ab68 Reviewed-by: Laszlo Agocs Reviewed-by: Andy Shaw --- src/plugins/platforms/windows/qwindowswindow.cpp | 16 +++++++++++++++- src/plugins/platforms/windows/qwindowswindow.h | 1 + 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 159e1250d0b..d639f27c1a6 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1077,6 +1077,7 @@ QWindowCreationContext::QWindowCreationContext(const QWindow *w, */ const char *QWindowsWindow::embeddedNativeParentHandleProperty = "_q_embedded_native_parent_handle"; +const char *QWindowsWindow::hasBorderInFullScreenProperty = "_q_has_border_in_fullscreen"; QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) : QWindowsBaseWindow(aWindow), @@ -1115,6 +1116,8 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) if (aWindow->isTopLevel()) setWindowIcon(aWindow->icon()); + if (aWindow->property(hasBorderInFullScreenProperty).toBool()) + setFlag(HasBorderInFullScreen); clearFlag(WithinCreate); } @@ -2662,15 +2665,26 @@ void QWindowsWindow::setHasBorderInFullScreenStatic(QWindow *window, bool border if (QPlatformWindow *handle = window->handle()) static_cast(handle)->setHasBorderInFullScreen(border); else - qWarning("%s invoked without window handle; call has no effect.", Q_FUNC_INFO); + window->setProperty(hasBorderInFullScreenProperty, QVariant(border)); } void QWindowsWindow::setHasBorderInFullScreen(bool border) { + if (testFlag(HasBorderInFullScreen) == border) + return; if (border) setFlag(HasBorderInFullScreen); else clearFlag(HasBorderInFullScreen); + // Directly apply the flag in case we are fullscreen. + if (m_windowState == Qt::WindowFullScreen) { + LONG_PTR style = GetWindowLongPtr(handle(), GWL_STYLE); + if (border) + style |= WS_BORDER; + else + style &= ~WS_BORDER; + SetWindowLongPtr(handle(), GWL_STYLE, style); + } } QString QWindowsWindow::formatWindowTitle(const QString &title) diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 8d29b871bf7..fe2518e3297 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -340,6 +340,7 @@ public: static QString formatWindowTitle(const QString &title); static const char *embeddedNativeParentHandleProperty; + static const char *hasBorderInFullScreenProperty; private: inline void show_sys() const; From e9dc2f1783d2e4914b156eabafc50f1156f1d1c5 Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Thu, 19 Oct 2017 15:38:09 +0200 Subject: [PATCH 11/29] Doc: Add doc to Graphics View Flow Layout example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Id3965d099222607cee4252bbb33c6a1e9c17765a Reviewed-by: Topi Reiniö --- .../widgets/doc/src/graphicsview-flowlayout.qdoc | 14 +++++++++++++- .../widgets/graphicsview/flowlayout/main.cpp | 3 ++- examples/widgets/layouts/flowlayout/main.cpp | 3 ++- src/widgets/doc/images/graphicsflowlayout.png | Bin 0 -> 6064 bytes 4 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 src/widgets/doc/images/graphicsflowlayout.png diff --git a/examples/widgets/doc/src/graphicsview-flowlayout.qdoc b/examples/widgets/doc/src/graphicsview-flowlayout.qdoc index e5080c672d4..13819f5499a 100644 --- a/examples/widgets/doc/src/graphicsview-flowlayout.qdoc +++ b/examples/widgets/doc/src/graphicsview-flowlayout.qdoc @@ -36,5 +36,17 @@ \image graphicsflowlayout-example.png - See the \l{Flow Layout Example} for a corresponding widget-based example. + This example uses a Graphics View to display the widget, which is a more + customizable approach than displaying the flow layout in the application + window (See \l {Flow Layout Example}). + + Graphics View Flow Layout snippet: + + \snippet graphicsview/flowlayout/main.cpp 1 + + Flow Layout Example snippet: + + \snippet layouts/flowlayout/main.cpp 1 + + */ diff --git a/examples/widgets/graphicsview/flowlayout/main.cpp b/examples/widgets/graphicsview/flowlayout/main.cpp index 850302e175b..74c03b9bce3 100644 --- a/examples/widgets/graphicsview/flowlayout/main.cpp +++ b/examples/widgets/graphicsview/flowlayout/main.cpp @@ -47,7 +47,7 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ - +//! [1] #include "window.h" #include @@ -68,3 +68,4 @@ int main(int argc, char *argv[]) return app.exec(); } +//! [1] diff --git a/examples/widgets/layouts/flowlayout/main.cpp b/examples/widgets/layouts/flowlayout/main.cpp index 99725195e5f..bbc78ccda3c 100644 --- a/examples/widgets/layouts/flowlayout/main.cpp +++ b/examples/widgets/layouts/flowlayout/main.cpp @@ -47,7 +47,7 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ - +//! [1] #include #include "window.h" @@ -59,3 +59,4 @@ int main(int argc, char *argv[]) window.show(); return app.exec(); } +//! [1] diff --git a/src/widgets/doc/images/graphicsflowlayout.png b/src/widgets/doc/images/graphicsflowlayout.png new file mode 100644 index 0000000000000000000000000000000000000000..ea70e102c3de35c218729789c02bf551bf0d3f29 GIT binary patch literal 6064 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 literal 0 HcmV?d00001 From 0daa14e1912b07c40833f3dc3e34f8e6c579eedb Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Tue, 12 Dec 2017 13:30:32 +0100 Subject: [PATCH 12/29] Doc: complete Dir View Example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - add updated screenshot - add basic doc to example code Change-Id: Iad616b285ee1470571adc38b868fcf8a0ed64840 Reviewed-by: Topi Reiniö --- doc/src/images/dirview-example.png | Bin 22348 -> 25348 bytes examples/widgets/doc/src/dirview.qdoc | 36 +++++++++++++++++++++++--- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/doc/src/images/dirview-example.png b/doc/src/images/dirview-example.png index 6412ead5b2b4bcfe0a8a1eff1ac9dcd5d781e60a..deb06267f6afc48970e002043576c32c59478b54 100644 GIT binary patch literal 25348 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 Jywa0^{{w+LPYD13 literal 22348 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 Date: Tue, 13 Mar 2018 09:22:06 +0100 Subject: [PATCH 13/29] widgets: Add a QT_CONFIG(messagebox) guard for initResources in QApplication Change-Id: Id083edbcba4b348ef78e55c788ea94f85b6f572b Reviewed-by: Richard Moe Gustavsen --- src/widgets/kernel/qapplication.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index b855e32f2da..0d434c70972 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -113,8 +113,10 @@ static void initResources() { Q_INIT_RESOURCE(qstyle); - Q_INIT_RESOURCE(qmessagebox); +#if QT_CONFIG(messagebox) + Q_INIT_RESOURCE(qmessagebox); +#endif } QT_BEGIN_NAMESPACE From a060ee2802c72d8ce22f42635d1740bf2f84bed7 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 13 Mar 2018 10:17:10 +0100 Subject: [PATCH 14/29] QWindowWindow: Avoid resize events from the ctor When calling showFullScreen(), the setwindowStates call in the QWindowsWindow constructor led to generating a resize event. This is pretty bad for example when QOpenGLWindow is involved since the QWindow's platformWindow member is not even set yet (handle() == nullptr) so everything related to OpenGL contexts starts failing (as there is no underlying platform window yet as far as the QWindow is concerned). In short, generating geometry changes from the platformwindow ctor is a bad idea. Use initialize() instead for that. Task-number: QTBUG-67027 Change-Id: I35d11949213eb21f81b2ff2d4f2282cb36510210 Reviewed-by: Friedemann Kleint --- src/gui/kernel/qopenglwindow.cpp | 3 +++ src/plugins/platforms/windows/qwindowswindow.cpp | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qopenglwindow.cpp b/src/gui/kernel/qopenglwindow.cpp index cf3d712421e..c3a264f1e89 100644 --- a/src/gui/kernel/qopenglwindow.cpp +++ b/src/gui/kernel/qopenglwindow.cpp @@ -222,6 +222,9 @@ void QOpenGLWindowPrivate::initialize() if (context) return; + if (!q->handle()) + qWarning("Attempted to initialize QOpenGLWindow without a platform window"); + context.reset(new QOpenGLContext); context->setShareContext(shareContext); context->setFormat(q->requestedFormat()); diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index d639f27c1a6..9fff4b5e429 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1107,7 +1107,6 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) updateDropSite(window()->isTopLevel()); registerTouchWindow(); - setWindowState(aWindow->windowStates()); const qreal opacity = qt_window_private(aWindow)->opacity; if (!qFuzzyCompare(opacity, qreal(1.0))) setOpacity(opacity); @@ -1136,9 +1135,11 @@ void QWindowsWindow::initialize() QWindowCreationContextPtr creationContext = QWindowsContext::instance()->setWindowCreationContext(QWindowCreationContextPtr()); + QWindow *w = window(); + setWindowState(w->windowStates()); + // Trigger geometry change (unless it has a special state in which case setWindowState() // will send the message) and screen change signals of QWindow. - QWindow *w = window(); if (w->type() != Qt::Desktop) { const Qt::WindowState state = w->windowState(); if (state != Qt::WindowMaximized && state != Qt::WindowFullScreen From 4d4c63acbafee9e6c46bd1e4b401a807a7692706 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 2 Mar 2018 11:38:20 +0100 Subject: [PATCH 15/29] Remove needless #include from qrandom.cpp Tripped over by Alexei Fedotov and brought to light on the developer list; Thiago says it's a left-over from before reworking to actually use getentropy() instead of getrandom(); it should no longer be needed. Change-Id: Id09b0628e58fa62170a0f0da35b2b121f3fb0172 Reviewed-by: Thiago Macieira Reviewed-by: Oswald Buddenhagen --- src/corelib/global/qrandom.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp index 9143e04d459..ebf9864b153 100644 --- a/src/corelib/global/qrandom.cpp +++ b/src/corelib/global/qrandom.cpp @@ -48,9 +48,7 @@ #include -#if QT_CONFIG(getentropy) -# include -#elif !defined(Q_OS_BSD4) && !defined(Q_OS_WIN) +#if !QT_CONFIG(getentropy) && !defined(Q_OS_BSD4) && !defined(Q_OS_WIN) # include "qdeadlinetimer.h" # include "qhashfunctions.h" From f9131b0e171cc53eb48d57934bba3458bc2482bc Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Tue, 13 Mar 2018 12:10:24 +0100 Subject: [PATCH 16/29] Fix Darwin OS (but not macOS) build - mark unusued parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ... with Q_UNUSED. Change-Id: I3736c179381deb08cec9c2c399aaf8a24d8d7f0b Reviewed-by: Tor Arne Vestbø --- src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index 5eb5cd8a306..f31f58945b5 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -521,6 +521,8 @@ static void addExtraFallbacks(QStringList *fallbackList) // add Apple Symbols to cover those too. if (!fallbackList->contains(QStringLiteral("Apple Symbols"))) fallbackList->append(QStringLiteral("Apple Symbols")); +#else + Q_UNUSED(fallbackList) #endif } From c0272f98df87afde411e14358f65caa79991a9be Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Thu, 8 Mar 2018 15:56:10 +0100 Subject: [PATCH 17/29] Expand Config to Configuration in method names Commit f55c73ede28d4455f555a28e401407326ac9b954 added various backendConfig methods; API review for 5.11 pointed out that Config should not be abbreviated. Change-Id: I3b294b44a030b2a6e4cdd034fa27583c228dfe42 Reviewed-by: Timur Pocheptsov --- src/network/ssl/qsslconfiguration.cpp | 18 +++++++++--------- src/network/ssl/qsslconfiguration.h | 6 +++--- src/network/ssl/qsslcontext_openssl.cpp | 4 ++-- src/network/ssl/qsslsocket.cpp | 2 +- .../network/ssl/qsslsocket/tst_qsslsocket.cpp | 4 ++-- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/network/ssl/qsslconfiguration.cpp b/src/network/ssl/qsslconfiguration.cpp index e0c705f97e5..116a6693c43 100644 --- a/src/network/ssl/qsslconfiguration.cpp +++ b/src/network/ssl/qsslconfiguration.cpp @@ -876,12 +876,12 @@ void QSslConfiguration::setDiffieHellmanParameters(const QSslDiffieHellmanParame Returns the backend-specific configuration. - Only options set by addBackendConfig() or setBackendConfig() will be + Only options set by addBackendConfiguration() or setBackendConfiguration() will be returned. The internal standard configuration of the backend is not reported. - \sa setBackendConfigOption(), setBackendConfig() + \sa setBackendConfigurationOption(), setBackendConfiguration() */ -QMap QSslConfiguration::backendConfig() const +QMap QSslConfiguration::backendConfiguration() const { return d->backendConfig; } @@ -902,9 +902,9 @@ QMap QSslConfiguration::backendConfig() const configuration. Using the backend-specific configuration to set a general configuration option again will overwrite the general configuration option. - \sa backendConfig(), setBackendConfig() + \sa backendConfiguration(), setBackendConfiguration() */ -void QSslConfiguration::setBackendConfigOption(const QByteArray &name, const QVariant &value) +void QSslConfiguration::setBackendConfigurationOption(const QByteArray &name, const QVariant &value) { d->backendConfig[name] = value; } @@ -914,13 +914,13 @@ void QSslConfiguration::setBackendConfigOption(const QByteArray &name, const QVa Sets or clears the backend-specific configuration. - Without a \a backendConfig parameter this function will clear the + Without a \a backendConfiguration parameter this function will clear the backend-specific configuration. More information about the supported - options is available in the documentation of addBackendConfig(). + options is available in the documentation of addBackendConfiguration(). - \sa backendConfig(), setBackendConfigOption() + \sa backendConfiguration(), setBackendConfigurationOption() */ -void QSslConfiguration::setBackendConfig(const QMap &backendConfig) +void QSslConfiguration::setBackendConfiguration(const QMap &backendConfig) { d->backendConfig = backendConfig; } diff --git a/src/network/ssl/qsslconfiguration.h b/src/network/ssl/qsslconfiguration.h index b3264126ddf..a5561d98286 100644 --- a/src/network/ssl/qsslconfiguration.h +++ b/src/network/ssl/qsslconfiguration.h @@ -150,9 +150,9 @@ public: QSslDiffieHellmanParameters diffieHellmanParameters() const; void setDiffieHellmanParameters(const QSslDiffieHellmanParameters &dhparams); - QMap backendConfig() const; - void setBackendConfigOption(const QByteArray &name, const QVariant &value); - void setBackendConfig(const QMap &backendConfig = QMap()); + QMap backendConfiguration() const; + void setBackendConfigurationOption(const QByteArray &name, const QVariant &value); + void setBackendConfiguration(const QMap &backendConfig = QMap()); static QSslConfiguration defaultConfiguration(); static void setDefaultConfiguration(const QSslConfiguration &configuration); diff --git a/src/network/ssl/qsslcontext_openssl.cpp b/src/network/ssl/qsslcontext_openssl.cpp index 386c2806594..41b759364b1 100644 --- a/src/network/ssl/qsslcontext_openssl.cpp +++ b/src/network/ssl/qsslcontext_openssl.cpp @@ -245,7 +245,7 @@ QString QSslContext::errorString() const // static void QSslContext::applyBackendConfig(QSslContext *sslContext) { - if (sslContext->sslConfiguration.backendConfig().isEmpty()) + if (sslContext->sslConfiguration.backendConfiguration().isEmpty()) return; #if OPENSSL_VERSION_NUMBER >= 0x10002000L @@ -255,7 +255,7 @@ void QSslContext::applyBackendConfig(QSslContext *sslContext) q_SSL_CONF_CTX_set_ssl_ctx(cctx.data(), sslContext->ctx); q_SSL_CONF_CTX_set_flags(cctx.data(), SSL_CONF_FLAG_FILE); - const auto &backendConfig = sslContext->sslConfiguration.backendConfig(); + const auto &backendConfig = sslContext->sslConfiguration.backendConfiguration(); for (auto i = backendConfig.constBegin(); i != backendConfig.constEnd(); ++i) { if (!i.value().canConvert(QMetaType::QByteArray)) { sslContext->errorCode = QSslError::UnspecifiedError; diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index 833d6761925..4273904c129 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -922,7 +922,7 @@ void QSslSocket::setSslConfiguration(const QSslConfiguration &configuration) d->configuration.peerVerifyDepth = configuration.peerVerifyDepth(); d->configuration.peerVerifyMode = configuration.peerVerifyMode(); d->configuration.protocol = configuration.protocol(); - d->configuration.backendConfig = configuration.backendConfig(); + d->configuration.backendConfig = configuration.backendConfiguration(); d->configuration.sslOptions = configuration.d->sslOptions; d->configuration.sslSession = configuration.sessionTicket(); d->configuration.sslSessionTicketLifeTimeHint = configuration.sessionTicketLifeTimeHint(); diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp index f77afd23649..1332b369e76 100644 --- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp @@ -4016,12 +4016,12 @@ void tst_QSslSocket::signatureAlgorithm() SslServer server; server.protocol = serverProtocol; server.config.setCiphers({QSslCipher("ECDHE-RSA-AES256-SHA")}); - server.config.setBackendConfigOption(QByteArrayLiteral("SignatureAlgorithms"), serverSigAlgPairs.join(':')); + server.config.setBackendConfigurationOption(QByteArrayLiteral("SignatureAlgorithms"), serverSigAlgPairs.join(':')); QVERIFY(server.listen()); QSslConfiguration clientConfig = QSslConfiguration::defaultConfiguration(); clientConfig.setProtocol(clientProtocol); - clientConfig.setBackendConfigOption(QByteArrayLiteral("SignatureAlgorithms"), clientSigAlgPairs.join(':')); + clientConfig.setBackendConfigurationOption(QByteArrayLiteral("SignatureAlgorithms"), clientSigAlgPairs.join(':')); QSslSocket client; client.setSslConfiguration(clientConfig); socket = &client; From 39d2a11a86669aa975860b7a074d338d4da0d7fc Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 14 Mar 2018 10:16:00 +0100 Subject: [PATCH 18/29] Item views: Fix 5.11 API review findings Rename getter QHeaderView::firstSectionMovable() to QHeaderView::isFirstSectionMovable(), turn into a property and fix \since. Change-Id: Ica2ca43d22f3fd78ff63178ba75014807fc9b823 Reviewed-by: David Faure --- src/widgets/itemviews/qheaderview.cpp | 18 ++++++++---------- src/widgets/itemviews/qheaderview.h | 3 ++- .../itemviews/qheaderview/tst_qheaderview.cpp | 6 +++--- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp index b7048d16164..00e9ff7400d 100644 --- a/src/widgets/itemviews/qheaderview.cpp +++ b/src/widgets/itemviews/qheaderview.cpp @@ -1175,9 +1175,10 @@ bool QHeaderView::sectionsMovable() const */ /*! - \since 5.10 + \property QHeaderView::firstSectionMovable + \brief Whether the first column can be moved by the user - If \a movable is true, the first column can be moved by the user. + This property controls whether the first column can be moved by the user. In a QTreeView, the first column holds the tree structure and is therefore non-movable by default, even after setSectionsMovable(true). @@ -1186,8 +1187,11 @@ bool QHeaderView::sectionsMovable() const In such a scenario, it is recommended to call QTreeView::setRootIsDecorated(false) as well. - This method has no effect unless setSectionsMovable(true) is called as well. + Setting it to true has no effect unless setSectionsMovable(true) is called + as well. + \sa setSectionsMovable() + \since 5.11 */ void QHeaderView::setFirstSectionMovable(bool movable) { @@ -1195,13 +1199,7 @@ void QHeaderView::setFirstSectionMovable(bool movable) d->allowUserMoveOfSection0 = movable; } -/*! - \since 5.10 - - Returns \c true if the first column can be moved by the user, - when this header is used in a QTreeView. -*/ -bool QHeaderView::firstSectionMovable() const +bool QHeaderView::isFirstSectionMovable() const { Q_D(const QHeaderView); return d->allowUserMoveOfSection0; diff --git a/src/widgets/itemviews/qheaderview.h b/src/widgets/itemviews/qheaderview.h index c09081cd80e..7e950add1f3 100644 --- a/src/widgets/itemviews/qheaderview.h +++ b/src/widgets/itemviews/qheaderview.h @@ -53,6 +53,7 @@ class QStyleOptionHeader; class Q_WIDGETS_EXPORT QHeaderView : public QAbstractItemView { Q_OBJECT + Q_PROPERTY(bool firstSectionMovable READ isFirstSectionMovable WRITE setFirstSectionMovable) Q_PROPERTY(bool showSortIndicator READ isSortIndicatorShown WRITE setSortIndicatorShown) Q_PROPERTY(bool highlightSections READ highlightSections WRITE setHighlightSections) Q_PROPERTY(bool stretchLastSection READ stretchLastSection WRITE setStretchLastSection) @@ -119,7 +120,7 @@ public: inline QT_DEPRECATED bool isMovable() const { return sectionsMovable(); } #endif void setFirstSectionMovable(bool movable); - bool firstSectionMovable() const; + bool isFirstSectionMovable() const; void setSectionsClickable(bool clickable); bool sectionsClickable() const; diff --git a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp index 812ca4b223f..74a2f7f2b67 100644 --- a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp +++ b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp @@ -544,11 +544,11 @@ void tst_QHeaderView::movable() view->setSectionsMovable(true); QCOMPARE(view->sectionsMovable(), true); - QCOMPARE(view->firstSectionMovable(), true); + QCOMPARE(view->isFirstSectionMovable(), true); view->setFirstSectionMovable(false); - QCOMPARE(view->firstSectionMovable(), false); + QCOMPARE(view->isFirstSectionMovable(), false); view->setFirstSectionMovable(true); - QCOMPARE(view->firstSectionMovable(), true); + QCOMPARE(view->isFirstSectionMovable(), true); } void tst_QHeaderView::clickable() From 00304eac7b1ddd22b971da78aa84c86fe2919359 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 14 Mar 2018 12:52:10 +0100 Subject: [PATCH 19/29] Revert "Set sharedPainter correctly for QGraphicsEffect" This reverts commit 7257862fb2edfab0219d6cd45c83677049404f7d. It has been reported that this patch causes widgets with certain effects become invisible. Task-number: QTBUG-60231 Task-number: QTBUG-66803 Task-number: QTBUG-66387 Change-Id: I9c3c4cf2f17ac639d1aee5489b665aa1e165af16 Reviewed-by: Friedemann Kleint --- src/widgets/kernel/qwidget.cpp | 4 ++-- .../qgraphicseffect/tst_qgraphicseffect.cpp | 21 ------------------- 2 files changed, 2 insertions(+), 23 deletions(-) diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 74f2dc0c419..0a46d2a8eba 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -5482,11 +5482,11 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP setSystemClip(pdev->paintEngine(), pdev->devicePixelRatioF(), rgn.translated(offset)); QPainter p(pdev); p.translate(offset); - context.painter = context.sharedPainter = &p; + context.painter = &p; graphicsEffect->draw(&p); setSystemClip(pdev->paintEngine(), 1, QRegion()); } else { - context.painter = context.sharedPainter = sharedPainter; + context.painter = sharedPainter; if (sharedPainter->worldTransform() != sourced->lastEffectTransform) { sourced->invalidateCache(); sourced->lastEffectTransform = sharedPainter->worldTransform(); diff --git a/tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp b/tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp index dfe5baba719..a1cb7298496 100644 --- a/tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp +++ b/tests/auto/widgets/effects/qgraphicseffect/tst_qgraphicseffect.cpp @@ -52,7 +52,6 @@ private slots: void boundingRect2(); void draw(); void opacity(); - void nestedOpaqueOpacity(); void grayscale(); void colorize(); void drawPixmapItem(); @@ -408,26 +407,6 @@ void tst_QGraphicsEffect::opacity() QCOMPARE(effect->m_opacity, qreal(0.5)); } -void tst_QGraphicsEffect::nestedOpaqueOpacity() -{ - // QTBUG-60231: Nesting widgets with a QGraphicsEffect on a toplevel with - // QGraphicsOpacityEffect caused crashes due to constructing several - // QPainter instances on a device in the fast path for - // QGraphicsOpacityEffect::opacity=1 - QWidget topLevel; - topLevel.setWindowTitle(QTest::currentTestFunction()); - topLevel.resize(320, 200); - QGraphicsOpacityEffect *opacityEffect = new QGraphicsOpacityEffect; - opacityEffect->setOpacity(1); - topLevel.setGraphicsEffect(opacityEffect); - QWidget *child = new QWidget(&topLevel); - child->resize(topLevel.size() / 2); - QGraphicsDropShadowEffect *childEffect = new QGraphicsDropShadowEffect; - child->setGraphicsEffect(childEffect); - topLevel.show(); - QVERIFY(QTest::qWaitForWindowExposed(&topLevel)); -} - void tst_QGraphicsEffect::grayscale() { if (qApp->desktop()->depth() < 24) From 421cfd9492ec04f5432c81b6cad93ebe45601974 Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Mon, 4 Dec 2017 16:07:23 +0100 Subject: [PATCH 20/29] Doc: Complete Dynamic Layouts Example MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - add doc to code - replace old signal/slot syntax - more up-to-date screenshot Task-number: QTBUG-60635 Change-Id: Iec3d2c3d0d8b9c07ccd4446d74d5eca2d88e7e08 Reviewed-by: Paul Wicking Reviewed-by: Topi Reiniö --- doc/src/images/dynamiclayouts-example.png | Bin 0 -> 22858 bytes examples/widgets/doc/src/dynamiclayouts.qdoc | 75 ++++++++++++++++++ .../widgets/layouts/dynamiclayouts/dialog.cpp | 54 +++++++------ .../widgets/layouts/dynamiclayouts/dialog.h | 8 +- 4 files changed, 108 insertions(+), 29 deletions(-) create mode 100644 doc/src/images/dynamiclayouts-example.png diff --git a/doc/src/images/dynamiclayouts-example.png b/doc/src/images/dynamiclayouts-example.png new file mode 100644 index 0000000000000000000000000000000000000000..b26d3725cc884a553f0ff0e0ba284df6d20f51b8 GIT binary patch literal 22858 zcmagG1yEc~7%eyif(Q5Dkl^m_?hxGFgF6fmECdhk?(Pl=?(Xh`yM%#(o&UYvw^F;c zRr8JAJ6%`0zdqkNrzcWXS>_Wm5i$S(_#`JQsSW_Z&_lxx@dNZ5N-0k;p_3ATIypyd3kxUEaA}_sbmgqb#9ZD z59p22s`~=rY<@4Nre;2k^J#B&<4oVhBTx*S_9FgB;>D4wf8INM8M^a-o2I4s(e>%Z z^?{?zQk9v3;q3VibaHZH*Q{4MpDy>4TvqNR)jrRt7UYw&-xeAgN~4kkeQs-OLxlU# zKacpMOA5VNuiB`#*JVH4fEgVbdGGE|fmnQNjj^)w6y)XU;|DPl6BA%xB>9Ly(A30) zqP+a=-QB!h^D*gS4 z_HMm;oH}v66A&=^wj%VkalP2u!wNBB?JOT5MEB-yFWN85M3c0dOvT|y#SruCUUvKS z2n%c7!*->0mpQ|R7mQBN=nm5dl-!GKxjlD>AYl3ZoI<r23 zi&&YVhU~ z_46<~o{a?wKa7RvYQOoNPHB8$@w~2HC+K`@nty!ZVpiHorzJKlOKc=V*{<$@Qaqzu?FH7I_0-MdP*tSZ9P8IPR*v5=7%YwDGs*2yIhovZwVZKVEh1BLqK@?65OU-N-IMI zAb(ycr(XYgM3SLpW^AA*;&xNaC?0iTp?vuHF^kp5ecSG}*$|~y2RAi0_e(DSgAVCz zm*%I^Xg@zKmhImM7>fml4tc^S_ouo7Icex|GaD}+=PO};SCJK-M1p23*46ZU^5>3e zW+n4WXcDUb)@L^jIXowR2;F$jZbk$yRb<^xI2ohAyh&y}XbH$;&H5Q!$+7_qYsP=d zVGpTXkPHn~zu6ro2q;>V3I}v>A>KWrI^+3wt^RJj`;mL(?c=)c;ScasU)DCqCo@zARcqMSs|c@ z7e$EJb3o)bCM^OydUurjrHLq2rCeWEy4F*jijEn)2|S5s?p_E<1k=v-Yz>DM zkIk6mA2GW*?ue+=2rU9nEnjUd4Gr! z_wDADE9x^8db71pW3ZKvk1s=Zez7y%z9Gl+y;bdsKFc<94ZjEgoL-V204A2C`5r`4 z;8hgi+jbndDpBgOPnY8Ps&)JMCbw24T7g><4E1-@o*pwJq3^*U?IR_Wb$SU~AwW+`=ai~(w%yxI*wH0sa{ z5F>9+WY=~MV&MXiCcrejJAcLZBv{%;ONE>l!~ZG#9hdY0fWaG)k_b~Iq{!fzTTff| z^hA{zUUZ)GG8m-g2(M`9#df%V;iN35L?Uc;4*3UXOh#r*mMbGCM>QOyBB#_`Lneky zQ;TdFG!ArjSmo&z`XJZM%tb;cj(E0Or2mN`&}aV*TL4W2A=h&eB5-- z>&r>guYlfXm%qQrUJwW!EgFOfwqc{HgD~_?kLW*myI*?3YrpRE{3*rtCD7VNWAbpr zgc0lplV{R|Vi?|D_{jrgj1kJK2>{>9b;HeB7dSt$h^ql4RsL-(7deQpMeEn!@gr5b~yE6?}jq zCsSe8PR^<=3Eh71Svo!r;GNpF=AZ6`99a9$X$cU9aXR~9k-K(7qh?k09tD*barFMv z_4=6e#m)DF(*WZ*Y~b7s$IDzw;AKca<8+4iSRzAv-$R6b&+DZW@59b(c`6{BF{=5g z0YO%{+5NHsUYL<&p>1Q;DTTUC3y}ddQCjf;;NFXCeRzcCTe09^kvG=<*}pJ=qv>>^ z?|TP+PgmySptBZ#ECAr`W|b-qCRAM@UF8t3y2IU8V^Tu#5I?ibfB5ljUHeN=o%FDt zGA9Lft*l$2@>bTMDBWpv`kd9$@9fVA@WM1fEY%KI~6znqI- z$!97K&(G8>p7+&rZN9NNBRclOf&X0o%G5aU9-Q@|^@G=8Ohw~#-5h{MH`BY#D2*Ru zVYvJPIohm0@ky-$`Ri3)-du{X zoc-yxtTbWkA%T1FOD((l{`>?ZYO;PLEbcEbVlM`Hy_?P!@Pf|r7|}q)A7G0AVnhbj zvy%!@S_DoEf&usU09$M<95^~Us)K=e3%nNy0CVEO{pdn~AW}H$asGt@1TS>%ZgRxa z2=X$rAOA%jw5k8%e>V5uhX1#Xx_!ktx@@53#uOA>Ym&3Gt94uBqfSAB#q`yzfohX2)XN(uCY&j? z?TrOIhZHwc14+?!rMTKD2fdn`tj|P(F!6Jk5FM%YkA9C=YpoYo$r^g=Bxx%h(`#^s zv+{!Ph2>tyMdPPlH^Rhr9u;K*ofmeVZw5J%G*(iI>uJt<~*g-ak2L%8wm3b1pxzbsdI#{&=S8)G3 zp(<{?lu&6Gt`08=a273APNPn`n&EiQz!_>v6>xM} zA(VQG|2UY}9elZ$s>NP{l3@L?Pzfy`W2*5FCJ|6=PW-LsBXLLpK`O${U$(k+qfzab~yKy6Z0RUmh-fez0C9DuGaFHl(TR&doEaxI~wozH~r;4-Wpzoypv-WY|1crWl zQ)AQ%XVv-9`Jr~<_yS2BC$*ynLv9(_-a~6|_0evPa}CE?OYFghAy1E?l(AP>W2te> zcM&74-PQ1}dSDj+^JT)9MEoyF??vgU0MU2vfOq&@r^E*X@12cZ5ovI4`btNCgLk#k zWEei$8^+%@_xC%!jR(Kd63v8}7GN_!D&+C0I|A)ZnE&5BI;6KV%}-w4Q?o^k5<;1Yshw{bjrA}*}bYNn|_hBx@_AoB`_-6i)cwQ-VOG(f7%LRW{5iG!C z<59ysyJQ!$+U$_$O(<0vAPYW>X+0<6yul}YPkDUXQ+Dj_(6F2%Ltr^K;;+{Xno*^u zz8e`x>3)J!+4j5mdvW&yYR0U%Z`Tsmd66qEUQ`koZ1zm{%)F^uYVAL?9{22Q?#9{-Ic3^9lz!|HQ->ULeML^~epUjcx3*Y~(HkL=|*+XH4eKx!WO@J4~U zv2p!BtA{J*Prp1%V1!BDpMS4-_>rO$?-j?hC;gG$JwB!e0GjEUKA$s4@|5Y$ru;zG zy!j@vRdzC%57~prJYMC@4=7`>c_01L(Z&OaW_yG4X&ZdX951c*c80jla}4DtT2e$R zuv;gIX6ah2WMw7KUuCkC`*jts8JNiQb?;yIAdHFD3pX-Xwlyl{C+Fui&YoV;1a4}n z4+gedI`n9^i?XDxHx3y`qX{G|{cAE~00(-{Xv)$SgXyWrbr*T_{XCYs`H-WT4N<2=`zOJr-WFlz|mlgAiH7w@8F?>ZP;;26Y% z=Ctw>QQg|;Ew~uZW9N&>4!BM$;|>*)uaQFS4u6V@`u~> z+r_%YK;n{dOfKJ&ME)Azzj+d^UJM;fl+b;p`+Yu=pF~V+59X7CWVFE>lYO6T!_a06 zj6P3qPj9`kUMCVg;s91OPjr-oJjR=OJ0%Er_vzQui3xV^1?#!Td3NuKOGlS<1SPyl zhIs=!T-V!Xx~Nm|Ry%cT`WbIu+!s&MV9rwCc)fHcx8JjGo*KkV)eRU(d>T8*&Ne-c z5Vy_eOGssRVMNdI4~yHoc$it%Z1>Q!wSAYFtzkvk#NoZWg`aSy+Pe=q7xywxLi84E zHNSBFQL}k4SP<&0j}2&Z{NI-%0s^SnV&sM zfG(}-4t@QNz8uB@bAioo#}6-FEM%MYPtxJZp|K5>OZj$7`I?}MOz!K63#|O?Q%}Yx zn|))iZv7=56?VFaG`0Ytnt)aNIhF|K?KWStv!n6wU7l#av+_+`nc+`qJtwc5GB@~W z#PTyl0}bWeb=oF*!n46o4v;AezKB`@3>|p4#o{9e4B==Cnq; zyT1yp%p~hx2R%beQd4^;;a%-O(b0mTX`4*Q__1Z{!XIC+_rsmO6>E_|qgFe`r{~BA z{BxbzwRCtuycUU2G06jzEpUXN5&{2U7BO4A?`Z9@*DbZ}%{AsGBEE=UKARjPnO}OS z-8GjT6p=+FMIixJ&vm`b8LG!8MR*g3*^L=u;2s$ zzSIhspJnv?Cc$1?Dw}iPsjz0xa(>+N1 z7xC=ho;1q8jnb8)_Oqh4h>(v22JiF6?q?B`6sez_ojl!IHYk2glpVlP(*LXyLoTa^ zA&xj*xtNhUO4lP?TTaG+AzO?UEE;t9ll-0VSHU+vzFNa4a{_qQV~UZ_FV+SDg~kd7 zj6!fe{m0h+`1-<_2i?I?O!$8Xid|e|8y{tEA|vH3wd~}Pfse9CdppNAG^x+e;2s`G z3URyFi_cPfD8A^HF`KID=63OqOn;MZz&K4@4sU*)wxm{hY$=NRopB{$)YE4EsLSHY_`(=)h4p)nz+M^n|)yc=sDHeegR@$}g^VM@k%@;JoYe}&! z_)kP!!fk=mFOk63T$H<62B`C2Wq)N%P?tG5^W>>HiXr8IQh+D!9kb@r zpG9IRu;}iBW?H- z$Z?WT|LKzf&1sL#UCEbj2OfV?4wG?|9_n+d(D>v^Eg|n~a-Jznzz1|vL7lg|X=?OW zn*?@)Cv3Q??532f?z>#F3|d+njqN8(*}HQ4URyq9o$DbmjA(C9z{|sh{z_vRnR-bf z*@gQ1mA&UActJ}Q07xqE%sqN+<<3zA-u;u2t^bawZuNleqv<2sRrzulr;7Qa^+X}3 zoolnbBAkT&_n^^+ATj{Wa-V!McOkOgB}tu+@RTPOI4H-+_AEKp1T;|YU>a4{bn#*N zTduB2UY|O1B`NZ1lF*RlZhpP`hV|jViZlB4tMk3%6Si6 za+S^_0swL%-B#Mt-XMPEFPIP`BydF1$pNJ!aToRLz;#rf{j zQLQzBV!%H50W_VPE_8T#iK&+_{>F`{uJr)BRloYX-<~>G>9uOGHOuXxrxI<_=|~6b zZwdwg5d}rV(wd<$=^1_8!7@KTzr8wV<^D&KBLqNeYg1cH-UTdDT4@87s;%)uA>3>Gu$G%#9 zB;bfVpwpl*`Im-IKl~-ZYF9RpUNg%S92kR7pXdZUdQab&%~F&#PmCpgzZ1Rv>L~_Y zn`KlSojE*LdOjk*jwG~3gcR;WdpYjL0g7i1*=)gDzq`u;;EW<0r{7yXE*EfgN9`V!c-RHtzwBx?e9E}HZ*X1Y`(0`kI|x~tD3))p2fVpRW^jQ1Z+tqLt`p+SdIrvrxwu&De-NJv;t zXL~|OsJp65c#=*yHgSLN9;u@^AHAXcohEhskUhP6VoUkEwUaeXt2seN$<5j42Z=WZ zbW-6i*Tc2u&pa0gt_eDO7yE}tr$_i07PWP$qX+8ca6xl6oVvQYgoGz_qjW4rg1sJ~ z%fbls2jA?tI2E0+TTD|^9HmCo5c&e3Y<-&t!{u1>nRe|aA{w&8T9r?0PPddeg{mm( z9f$hYd7LOo%65ax-Cffz1o4smBAMY>5;6{;nWUs-*o-S~e}6GI_c6t3gpN$HgY!jo?cm6d#0MWc1>;8aw5kM&5@Z@B%*?#%^W@oSe&EENH zh)t@ljR9CQBRfIZ@q|@_iwKH(7=>!5s&!f%2$ie74;mbqKQ4cmplPsrC|| z>;1nHCjAIBlBG%&ksOduEbPu*33cgh0SO!X4DbD+j|~=BQSyKnjaLXGe%#VHfQyOl zWcF!$5)lc>ZnZ02k`fa+EG@PGXqhmsUHg5btyrou#eS*kBl11Jq1YyqmlEJZD0>PE z%N@1WIYXOy0H##Vev@xJq1_iUCXU zl>1thlm;hiR%NqAM5>i~OAg4Jx4Y+eoGc^KtoTOA?rk!iBlP3LYZzsMD)}FD#KLWv z@u*Z5nV9VBL453fD$09)CMO-|{x-T|Q9?5;*iT-!-v>AWNA}iD2*1g|x1Qh4s3;^W z7wZ_i!KqvbXr%ler_s{YOE#QsV7k+%1g*y!1N|oN=i1(ydhL}n54}cs#X?yt2XeM* zkZwC6gbQq0_^3(+^Ou+VLy%GFqMd6`=1qw7wBuTXX7y5DaM`xZ$O#9C*`TY*W)w@@ zTe+44D=zJ$=-s1&IO1sSu5Me}6HlN56;jNp|8rbg%PIgSb{=G5`FOh6sddpYu3fEe z&uQ130rGhrsk?kia6Y|X4MjkwQOqjR1Yw9PX0YBd1i%Hc+pSU$lyUt|`^Z_TDbH$K z&4vpCbeen7I%-p$#5CB^+e&I1PRxV^hygR6=xG zNVCO?pI``vFZ`8=@cT!Z_0QjMKW!fp(ptxK4!YpTY4mlA<(pHg_22KNrDL=zwJOKG z@qU2=P#u{*^EeW|58`JKC(Hd~=ZVL$$d?wvpw?#IA4+*mNfT6L_%&cBBUtZ%`K4r( z4iH4IPl%~jZXnxUI2>!+w8n0PE(ww635~z%$>nl-^Y7Nm{QRUiCx(qVNu(TYG5$2; z+*pPDyDJaj`BPB|$xX_nKnnW75@}=d2?@W4&%f)N>daP7qUstGR={aQ61^3)h`QWp z2ZZk5<7sl5Eku3)PR{122XmGzY{r;l%h`Nh!9sbTekCZt0SVM7{l3{k#l@vrIBPRr z5nN_WXLUgq_;@_K`S-6{?R+v4{Yp zR*K=1=F_Za6ntib2F1$xlcu$XRg7QYYbrVQe{I_s@mw6D5UI*U_w zskw*m1GIUV_ONv^YbJ_*2b1g?+0sfd>4GkEM@;(7{MlNSQjmD{{-GFs;fpoR+Id10 z(W<9X>?p|vcZbqZ5{5_IZ*PCx0g7TYd2;R?SE!th$)oSug<8odpOlo8ROEfD7Ei}a zkfDbmA4@E>R3(LyulmQux3L7>Y&G}$7fh}(hWxsE=4V_fsvAZ4KWQD-b7kg2C?BJ4 z?Cdm`%Ge5@E=BU@ZO8v-6WorgO9ehC+0u?ioei9IKZCQSN%4Rj_W5*({_)%9rnebi zZA+!B^O6C_d*`R;=dLf8hS^5OOL}5zy>r8l*`4s{q>6~Ud{Yjh?z`|A;bKuROJUnT zrQAN%E4oL@(R8_3=eg*>jsGnG#1|`GE!S@MKqBt>vz1F3G+;0u7%Y$7JGx)c7Agz{ zS_cP51kHIAB@)|1k4W)68o6)hi?ZkYgaA=aaQ68uS8-oyWayKnr54+~Pa1Oe$G!oe zoy++6#qRW5x3UbP6L-NNBS#Y+{N1`LGXGLktp7lfMhg_u%j+fD{ z!9i*ZSeO}GE>T&V=b5&3FKEfXe5NLH5VF5i-IkUHFRB)L{gE%*M>{9kpg!KcNk?bJ z-XO7w7*1m1G(c-!d4I;*TeNaje$^TQ|_4C?p;|5}Lmk<05z6`J*t6wWMA3 zVr#hP%UM68Z2$SzRe69{~3z1mnjS1^APy>55!D|A!aAvDiv>Vvy?NBW{_r zBLDs*KWxm0Jh?U7S8|wUJ>2y&wTKxtUtbR_ke$dnofA+WNhn0&EDGr<2yep#uR5#Zl zaZ;*64Pqk-(qi2tuaBPgxztq_^>R+-MhbEy0=D9Fq;6c%&4%`EH2GpEenz(&aM~b1G+0^9v6y0DM9AQ8pVNO)oU0z4jjq7ty;mj6BxLanMd+R(s7xt zgPC^mxeR{p^&xd7wsvyLO|CxhF`K#C&q4n5z(7)DZPC`=hS>+2qR=5Hp#Y>{9YM?) zjkhGO*WPf!xyfqF&(az019!y3E?qtiw)|utVRm?@w7yP{jd8<4VTZ`&Vgl$%;-cxd7^Nobg^$ zw-=DUa*52B(;{M!XXRi=4(g6Eepp&&m4L)QCHT{GSh5pN-+er*#b=^O)6Do8rnJCd z?-!+VP6`PKC{QN&-;*(% zYV*hc927;QFsSh?c~6%|JW`OzToD(;q@$%%SGY5=_;P%RVzn@Aa$=+wc+X!QRoSRj z$$&D8o@pdM3X@{h!Xw1T*f);VonF?-GKu&F!!$0^=fWDU0j@i(rKDgxrC#5tR>c z|29@Bku4bdgv{3NKL9xUuLXx$QKdA>pdIrhH77@T76*q7esC>JN_rEq$b=5}tiLLT zn=Q9^&Htb@-TN7dX4s|3L{BA=FZJi4q~h029MK?F&dOPv19p9h^;wzTR|4qS*Cmdt zYpBy@P=qOJDIq_^>x>Jde716|Pfpf7VybZ(L-!3$LltKrK$id6EH}g0Y(elyW? ztLHBx7-jsZF8ZnFhOkUTTDB^RQR6r|X4|K7LZe=%~W2kkj>-hs)-xf;w zM3}8?Z7|QF#B01RL@wIsAnhBzAT16f1@n=t6G#A&m%FufN=>@|SwKrJSvn8%5mjlP zGZ7z-30^NmPBwJe!LPo9+wo09aN30!T{@YkvT;g(qV)y&2@qtOc93L|Ud^O5k0Zs# z83U#u6W^RxE}h4gSSKGQlvZ;kM#n+a2~O}Df*q&zF8t2Xc!CV$T1)UDY892~OH++O zKK#*PwORea)}~(#vofdBEa%tUkqDUnnVz04bZqP}%1B!V#MwhrE_-Sz&RQLNd$ub$ zPI>k_B5g&M1}-}TijQ|J>F=uE*fwG@36?s)tdz5OFVD^-Kv1TL><>tCe%BN?HkTKg zfhJglc*s!Ja0v<3w(rDRGjrdIkn3W;$cu`;ry99zZ(UU(@+B;G&@-Q@-cJG z$7D;Lk-z7d7F6mai~c%11)*xL7xKB4R5bxee5P+fJ&o|ERplhX)7m{rq@k=IIE9m4 zB4The&y0*;8cB}P;Y`P}-<|p8)_yby2*ko2hmFftxRJ7;_@<*I;j59f!G(oF3Sv4#o?bE83P8~^Mag8QXYJRsPMcH<8iKEe^ z;0f%y?b?OI+~&f96h>WsM=%e)CilT(0*40&BId*JI zd3SG*h=70`3+X{GX7p$Y$ew96I_9o$#PAujQbgxr`tRVw>uMv~<6}!pOZbkq^nL%a z_Smh8h=_4QyprtC*5uW0{ULi_9YxC2bt%NylkBJpjf|6XsN<|qHb|3RTUlPd!|kO-lr~tr zfDDHNoIrUBT;fov*ZCj{>2#5Zv0MCD6=bR#EUJpf%q0$yuMe))Z^?q}JCrY^l%!J< z8H9@8T4uvUrsUhE)aVu8hN0lQ`!YGMVVQp?3A$+j zrtAfeCSNZFvYy#{xqEJ2Ux9sRJ#=9hFzP;};3C3VmT?DLyV)+NP$n!?>VuAFskqsF z@;ChfqH2+m=mv&{y5Ux~8K$-&uBiR&oZ~a7P`X2k1LxxMDCge}rUVDx*x@jLp~rCa zRR;Q-zveyF*TRXpIrXU=5o0<^L6vTH958h3{!*oNSfloQsxi#UX{=AipW6|)$&gb} zX>3f@;B-75wXzAf(oOmAR0uMxP(v8#1O$BS#uR>)OeS&s@)$VBq%{z{%d^&79q(+4 zbMd&->2dIB9IA(6BHTLh{5-`l;e}cpo?zs#J|m&d7-BAUJ97q{UyKrDQXJ{&gjn^G zj5xD65*nOR9H#VJ*En)rS zPojt1-gDt+!?rs}s(_?jW+|BBv9X5wgxi6t>Oo1VMod=KHgCL|^mWk5MXS@*_ip9S zy7j+R$#D?FpcX80TDObqGGp7Y0@{340%8IT-SWNDWRcDeKYb&M0k^EaEnx-)IW^|6Cw>xoUfM|O1;qlJIoq;K?NR*X|cX6n+NZJbMd@m>7`ThEDKik6@QkZzK zDmfN%n7FC#gxR$qb2lq06;7nx@~^Q8SrOoCSz=}9YLI;n$Y665N=3(5_f6$G&Um*! zMxz!-RaWNAXKKCzs`Q_bZ;)ev14g@L`}d93(;~S)#SY@=>*jV3~CCT=_ zYCp|2TSEyy1e#w3!!abwoz`CYvNnjm;t4-3$B(bkp}71rEzU2=zF=4|8K3LHY4Z4Y zBVlPI+R;(1!6EK;=bHlc^kji_=G;;|^goGE(h^DvF4{|$H*la>B?cyY)XED~ON!8F z^W>G)n-8NMZ!d3cDO<3rP-CUkFDWlvnODL=DaZuXmFhE^m#3?DFUa=R+uslQBhE`_ z?si(Dtv0i_;FwHwEbO_txqIK(Ysu_FV8ZL|+#v%|b&1^k(bzp_AGUetua-+q+ftwV zyZalz+kZFzZuVd9FKx}KaHAx}^JS^&3pIQEohLxU=HvkXx#IaJ5AR!rQdDGxb$_B@;_Qq>x4t0XiN#p>wF}xD2THN+ z+UV#_U}En|lh55%Z!HO%Yf))jpxqdXW)3hbKM=iY&6;bMaY)2R1SRwXjWzUk_P&Gf zHo{OQiH3cBe2_nei+nI${SGxo2?JrnpkM(yYVBtd5)2GPoU(?b z)m7baZ=L8F>sxdxjFq)92M0^6$otX6VGtBLc|At=8O@THkV0p&C5%%z@%&wR%GUw} zz>J%Lo?b_0rNXF8@4o@ba8q+4?ysQ;h0WiPc6~mGwlSo#4AW4<=LKI0qBihn$C}zL zlo=JfT5Mbh=yN+ocLwlqHu?95$Bd<-C(BZ&r=I}wmd|**jcS+O_@U3^t+7zJgG=xg zV4(vu$qJPKtkMQTL$jf*^h!MyEh{T6ZJpFz3G^y4_9MeF_8%Gk(bhsp>YhK~prN6m zqT*SLboyMfqzkpmzv;?bN`o7d zl9D=~F0*-ED0yjld1+1d{?&6zG%9Wt-=mH+{`>(1ifotE#~6L35%Isj-rDROW3<%LN@3Se&Q31=M!#venYEeav>9zqAZ=xD z4^?H7*JK@w+4c2#@JrbW!{<3CXZ}-gB{&$zXPS29jbO$LyvYpaQKUo*XU+0^jiLEF zUzB|2j4ua->h0^>*53YKUEX)+56q^37J-$E%?@ix1$3+vc=BpE2S((%y=V!hS_b_G zS(X;SDfM!)+h9?(B+)+~>OwKL>a-kTLTLm67~<4eazM==^g52&1+?@kLK#*BEe=(~ zL12n6SEj%b_Juj09FSXx@#SIgv;NVWf*Pul22R*mK2TP!;-`A|SqA_Q=0_3|1o0zd zl%^XToh_sYE3#W$?cV;RNw3|2dC&*}j!qXsjTPB9b=mjKG1QDiYr|CN;d=ocF4@`H z_4DXrs7V&{QMtKJ;(H-Noh_x*r8>fA=jR7IJ3CjPsIXY_FSTTVe=pAkCWyB+i7Nj? z`1#M%_+R`_4g5bv=)aH;0ZJ#fkt5z3vnH0cfnA6ZpgzW~`at60!)=DkJdSRo+{D7K zp{krQjmJ=({HI?i$jx=Zw{SHksxr4R(cD$Of}REeG$$7S9&T#JU~OHxyre>(43;g{ z`GKhZ!(^Q1|JMvC2a;AwFZs*<_<=;iiQg|iO4o|yD%Fn*#$d^?QoNzi<8R5_|Y z$6Tmgxg30->jZX|Bb4hwKvgeipc|&m?@X8awHG|r?8X$oZ%y#8@^T^?QJ-idtq(gq z==~I~3y|RGj^gbN`!aU1(Y#}~+kMPD_&xztdo4jNTz*`HTssj~rB(}dbeCspEeTY3 zOn+Qu;>~14CbOFrSooiE`Pi3*po?cdy1xL$52AWO*(2mo``+1(UC5BfFJu?zN3@DX z%iASME|`bp+P)7RR~pt%SHx9Ni`4Ud5c`?V_MiB-;RYCh?9`@`#`r1{Zj3vId4V%7{*kY+u;|0RJYUM9}SVE-Rt!AVr>Zf_vaaL=Os= z;}qKc56bm3nK7-zly}w}tUpc`_ai|U4pfBl>b6Q{s*wDHjCas6fLlqu7&UMn2XF2a zPEiKyE2lPMI!Rj#avc9UosrdEZSUMUHsqk7X9>Ix%f549>wD?o)p8YeOsnKh#r|`c z0#ga3x-Y$PTt<;h`>1B;zMUi`1{Z3b3pWLxb>&xA@}peCN(zGy5;cUi)sc-6qGAZs zOR*Cl7&XuVq70P!oRy^XVKebp+V(XI8G`o9?=Aj&MDQnx z3GQxg7D60L6acVMYdF`gZtqDSQW_2bd|q(dI~F!V6~!(6JFW$BzDy{QkoA=3KGSLk zLdr}qLnC%0B9bDHhgbMlnHvuojPWh{OMysYr9g{J7r`f!oN5BOT~_p z_+GmJ4|=EeoqRFF9#6;~ZB9aqwPX0fO>x|>PD8q#XjG@GnGA(~zUMns>tnM(O29A7 zxvbd6pPFX9v@DZ{-7Y?}%GiO&U2~nD?FFCJ=pvm$VBA`Bgdid}z4NI?qkmN}o>$I* zfFC>4sSxj){*@u6nmEF_{FdJ9lf%tQ(5q|r#_@ykQUX+{4AR~bZo0|}D58W+RE%oW zCg(Pl_5ApN!5_g}8TjHgEj6uLZ>Ug}T4 zC%slP3pXcIAbYvehJf|XFZ;Nk+Q}uxPPuHXl869u#^v`)Qa|ZWPEF&rCrR5&?o8gc zSC_rS7Nv2Jle><@hVu`0?mBhmdiK^GKjHJN<+NMgy1kF~QL|^7?DB0=y|w$)An1L5FX7BlY5E( zl>j|9Rf^TWloqk0hM+`Kj0E=A{YgtK4B>RDuiHEQUsj;DuCG5{5m3kNEB>E0AOMTA zRQx-dlv+hr)^g1Y8!9ZpJ;p%{grlZsw)P8i3Us-d={-kJ6jLtZ?Uv~OOu+wp^8HVe z-y&kfgHh*%`hawGSLvW;a~v%fch}$RYvAW+s6Ia0DKoFA7^1`Yi?Yr8%|Uz*_I;TL zBT=P@wjoIuYG$Dkz1AA2c5ObDFUBe)Q|~J(D#FN`?DhT_2BvU=xxcE0(n+-q=%4(* zynFC+o<`u%yygR?)}D+5F*A*}a63w0QYK!gm`mN)o^Cc=nWLXlmy94f#(jQo<#KAcoo`^#_Zm3we+sE%YS_~j-IE$zcYAx6 z&Eo>?K0ex)*APvQzZ_uemy}6;{8S0~+yLoomZinS=UCxdb|2QmT=*7JSQV>;W%9e@ zYt~%6@%`q5Z1cw)d7IoTLlMWm4B<}#{sBKLRs$cM&QfCRFY#K70u>{!rYvrkxbZte zmuob*L?6M!e|mM6H(30~a3Aa)hgRUfRcg>|JTujd_lazCTOLuAiUpDg2ik)AU?>WB z)-rErN`VyJaR-5h$Ct0)rmMGpdvCtXvph*QdP?^m@i94<;~0w2%SxxF!EDTPc~}C? z6?=)0u@C!aYT?d+;DKhU9^PZN?=M40iwB$l(Qdr#wT1I_|NA^$rPx6IezRR+Qgqcra3#s_n&?TI%2>H?MF>XUG%!m2a-Va{5- zy#qX~Ro^}1)<&eDBXBfPa)(O#N-J=XoQCIWN4oI6tv0x79}-d--BuLXQc;|mnX0i8 z+Q{d>R?ZioHyrBg$LABVeA#&|NpEe*p}BU{0+U=~I1d0^r!ND^7F)j8rKb9Y`8v`# zb`??r0IQ|&T2;@h+WP`a<;S~6heq`m2P7)haG!s>Io&Oj6jBLo_55vh5XoscexAOL_$9uLmen@l5gLEbq-5BKpmc83zpk~Xx}RBTi{FdbrNI?x6OLBha-k0{QxCGIrth6l?T%TPK|Mn@%wEqJFJ*cEg zGEl46Kh0>Y8l28L3EN_vnA6~n3sH4W@c*u2c_m4@JsvJL;sY;Kdw`r9$!V?~XAApU z-D0Wjh+bgT2FZXckjz6^i}Z{<6E!iJFYm6yKU=mfP<5J~LC&tgOY0E7NrpggdD@`M z=k)ms3Wzm&_4&2;=CSEM%~BMk^5M1drBK+BpU3Q?hi(^3+JPoN(s=SQq!RtX16NQ4 zJU?Tb8(@6bSCxU6X`6dcI{K92W%JhEFpq9;wOk+AQ00PvXmYySh2 z3Qw_|yr$T(B%TiEXDk-Qp5G`UFacWQ7gvuBck`VO~4w29E59TP+R&x(ud zk;P>ny8|M-tsue!%n~F9%4u2p2-xA#0yoY-a{%!Z=KJOyxfjCC`6Lt_MIM`{sBK%v z5xB#8zNI8N9NymjTBmmi(r}m`)~soiEn-O9oE0^Pi<(1TVu=^)MwieOoU+O{OCGC6 zJ`I=1$P-3phf=`lM!I2nOIm15VJ9GuV?>d~UV|aj9piZ)L$LyGg3*=2(jT&!8 zw2?AF)`IETV$*(5T838@gY`R|Tcz~&U?!Odk%RFF4V5PE3X-ifwU@Jd(?? zp@Ca*4d}_5na+eM9eN6Pl1o;tNjsiw`4arH<#+zqW9i7l!$QNuk~-p&>aIJTY}IL2^oS*2Ij8HlF9|Vui7V{jEH|X!Y#8l>F5uAk z=0=}N>czL%{yjSIyL-VoWoAUZ9R6?4qhhM&RCT@NrTZ^#q**>tbgcE4n??2GpjM+F zkWTG^Ur5UHgMsf906;MH-~R$6D2=N{f=KP&+#>OxSdqsjx$W);eC6IN^{Yp(zr2uD zMESrUa#tQ~0%+?MWCzC*5}sQ}5CaK6i6WLIG7pqPGM7B8Q9sWsbLqp~J+TOCNf^zr zttQXrEH2}t>L$(F{#~AR1&A-)(2)JCY(j0E+!Q5VU>v(VdG^*cD#?7|W%7tuU32(E zcbqk`O_Ph=>oWv$ETDP~_;5PuGjg&3-k3BhR4^S&8g*@-xNbCH&SbZAjr0&mDgwqP zpSB6E_B^-f4yU}0_Vj*7qAY;?vV%L|WBN(Nyb`!OF}kt73d>=S34ejZ zNpu4_^$2_y-ssg~%VzJ@IL}83O?zrm7wtZhbjG2wpzFis9DtO*wJi&v$`f%P#A)Ea z5#hesNGu=J89k+cvc5;%{#yl2#?Jk1xDD7|Y3zt*za>WAkaf^StX5ygnb zR8D#hXZ3B;oQ@+#$}+&|^>1<*l*Bit|4*AwpO_-v@XfL-ImL;77L5#rHoXYkE0+@` z?mO{Zm)jSRa&GrMQCLkcVeT&){VEjnR_Gr6J!;yGn%~WA=bG0KA@Zx~t-iGTdR|{* z&i(yols$R*b zS~!2v!uf?ayuAN@KSA(ki)S@{`d!mz17@$=as1T2f0mAI+i1wafKe-^)Rs|2H$wLq zP&swoXWgg$bL{&4yH}3w+;=mBFX9}MdIs3OJhJu3jXT$Fr|N~S6ldCdx8IcYr|&(CJNC=SVH*UWOl;>-yyYtd0iO=7oB8X|QLB!} zJ-mPV&;Nb4G_C2Rp5ZUC z%}Zv?+4)qT-!U5EtiHHm@1@%}Za&ozU=;oy%!A!qPQ~54em{eL?ZZ&t{_Dque{4N| z_2$JRyH7sl<<2q&w0D+wuGM_v(F{`j;8)0lKqz_LQN7(xPw4&4hV%CmuI`@w+315_ zL%(dGC^$bYL#F=u)(Ml3`H!5|Or}grPfN?lRB=QQ)NN$_%$5CzEIV>D@$SjB<9jbi zYd*DKIibY?^87_TIbmMjrx4OeEa2Ou88fWRYy*0Oa0L!w%yB{e(D-syWx=Eb2_iwHKVq?xY;A?-EGyr`Hh~f98|wXqh1RW z>(AS^yp{8-i&Eg=d~ad<$N-P>&A&JqG=0<34sHy9AgJ%W=?#*X^ljT>;M{}SD($K& zat~h^-1p1wuKPwdZt?lIJ09tPQq=$Ai|ChgyEJP*X7%MP<~0w4%X;?s>edCLySAv; zV$kxGW^+~y3=sm+Wv8cQD773Zy7pIavwWn$Ey_0Py91lXxgMC3nfe>w#{~O%`}%qN`bJK^r~<~P*B^(MGxSf z{r<^adw;j@nVwjCFaPcKU!ayRU*4rdn^$i4?D-3Y!k)$Djmj8@4j*aWq9xDsSQJGC zF`C}Bb4P=iSC8q?b6i?lx|^#@33ogoA1iOttz34B=soxQAs_L{h1dHPqY)bQL*B-z zh1dHPqli#H1d~rpJ`qelG5JLOkT*x6Q1CpVC>k3-3xlR00`)^m7`aS#^VW^f z&Nanx-fm`-dQ}9rp;&=j5pMI^ApQ=j`N|oRX@_$zgE1 z7XT&qass z#6443!uT*BGBq!rZ^WSiEacgDe~p|lZy}E9U2pCd2&z`9n&BdEqW6!o7%gTHqQ%O zAQ@ePUvSx{hkDsI_|x<&^>9vapMYUpLIC z$GFCH3Co(j>6WTN4JiOX=7oQ*`Fz?@yYb&cPe%s(umGTca(LV0fUfmi8Ihphk~JS; zol14_yRKi|ZTC;y!dC8ryayY#1^@u%hkMw?JzIDvvFJxEqn~kr<&{@g4QyP&)n4Wr z9y{WXn^~OM2FgRd{X)7A|FpKRoxR*6vhk2#uPM2b3V=}DuV<4-XsKLG(=-Ky5W=Nj zS~;jugu6^C^QzQj)StJqc*3Xr+sHn0`d$64|Aot?VoAmCZfbOow@&C#FU&(GmN@v- z?6>4nCU0#s!Yi+={JegMi&)|k++g@`Hgwqe8dW>orToN8IfM|RPd)il*P4O$5}9jwi-}tj)kJ%Lel>@f)i3p@`*_=k zCDJ;-KH<2G^Nae`@mGi?QkhrPZp-he-+J^@o}Rz)ExfKaBe|Bf4K*1rVaXJ-(u z-*Us<17rM|poxd?B|dz3cx14Eu@7t5b=<n}$3wOD@!vVK zF_xJjlFN)OYlu>4A#F-Ui`KW&;ug83-s+|G*1heUR4R4rwij(GQ6UkMqO92ped=mK z7Y$}P&-;gw!Q4`fZudIh&-wVn`8o4@zUO?;^IM*IG_*CNyt*`d*otQ^+hd+Qx%I1A ztj~l^>F-;*Ow)B8!+n0`R+#`H#LtVkiw|(?VdXwl_3_!1N&+FGDlI&lHP}_3j-;8a zO<7RA03p#I7iK&8Wey5Sd;YQ{J9?utyl*5|@bvK5(LsXA zhm!L%ulTc1&X~HtfZ)!(m49)H8pSp^{aIOQ>9vWP{Ck08mnC*zdLlL@IVxnaM{f;k zN6W9FEGgr?p=&P=hGeU+`RNrtKRvbI%nK@BhZ3{W!v1TRve;$Rp27x%YGt}z_jrTr zlymC7=N{&#pPX8=Yto$XuPp%noxvwU0JwSJ#gHNF<{E6nlReWH6eB=L@a){?IGvTL zOGoHY0ki{`g`D0Po)@?ZYmVLl0RW@>$kC1#ssP4j$7p%hUfWI;xh*lK%fY=*mF6Ul zfbhv`EB0y$iTZA9FYlk+4F~l8(Z1kx-tx2{FAD~MiQnPFkIg-HT`V2vr?19gQZTBL zn!0)y8UP?r&>J>R4*&qn^;V4DJ1Q=_CcsR+rJ1lebW<#Mbz0y^Jt~0Cisiv4H=NB| zVQZ@>@lxx?ZO9|zEMjB6}W8T|sF;ikvJe?R*!XDPR55*o|d_W(t$Xv0xwvP}| zer@f+*CT$5UE!{Q1DI$G(4`**gg{VoZc7x$@9x6BYE%H_Zru%3DF6r%KWqQ4oIcxg z7C33(0Ml0b>~=hH{kiW#19g@H1*55`sdrJw0HC_|EuX4o>oUl}SOF|8+uKtAntx#} zs(o7vO6p1!nOA7aTmT^u6rJ39i#hv7sGp+>0O$vuD7xD(l)cDHJxXBX@n2cL2*y--xR7S@*5%|{OtO$G)CA)>A@p|CzDz*>vV z>cVDen)+o3Ys#y|ABtC!0toR*l=rJT_sYE?@4+pBrI=y=4NC#5`U4t=a{}hWF zL_}+|`oj2v`mE)as>&)%WfkS_z7K`fJE97m*~i8)vN~F>ZW+)ICeg5*Q7)~1km38lV zZM+vxRfVan!c?>SrASy)UM*@Cjl^ErAz;;@vgNiW1HE@fm+*;pwH;c~`YpZ;D%iSNC`(Q$7`gUk{qf)_U#8m)FYZ6CsyH{Qn+j7|g{j=t<;ZJ6 z_3LV}+!`;`_U;-eui3AOXX%SIm)*o-0Wb!I#BH%}+SUo9scI>rJSiVqm0=J93}_4r z$Zd9R$Lt4yD{7foSQya^gO{Fl2wZb(c&Mv7-jq2?@r(d43<7XALoL~_k0I^5_3PTRY1vx5xAcUo**xFBK4^Jn?l(5vI+RLRz)B3Uj z5U_epva1WY{3wSNTV)ks%WC4jiE0sn5J5EaDfvkVg(6`?o#;csP~s0E7KkYt(~d_6 z^k6i-yBVBr3JCE5Nw>{0rscv5S!3dU-?44ic@uB zUn^N;EF%PxzA1=602q?G(Fg+!!vM*0TU#s;;|BiMF3jRKg^9R=h7RRx76^Pivj7i2j3>Rzr63YnCpL%jI#oJg%-bn)~RgAjihY zU%WV4C?LV(jKAQp-m z$4k6>csa9+*Os+2M>zHEY06{MFv%;Wg&AGPMyozE=?#a=)8p~HizCeQ&Q^b zX%8t!4jp@<>)uZjM+hO{^qFK`6?y2l3opBmb5zHgT}OZrL&sJhD~L>eBW{(?GV~qw zMUO6~RS{Cz3PK2HbvIUilagMq+2jdNx0@;zAp|&`0%Czssw4yoJeT>wQI8+|tPr*) zIGx{$xKGgg`C#^1;BB0@an81+w<6j3mgF&G=-KPmXGCY$N>0=j$E4P9`x`6DbepEx zgGVh*%)zvqhRox3W#V6z`Julz_(U@MeiBL2ji>zBtMcUZ>1)m;WEB=<#9zOW^-hd1 zMRg@naa2T1O7>d;0)U3H_~@kElBXG0x6bvCQ=hZSLmTVp;8S)q1EAbDaI1TD=;FOO z^$02UoHx&^c*}p5oled#&5b|k^W!<%lr`hEDF{(H20GMdkr$J4voj0diJ3a4tQS|0 zTzF8FlX&LmB}ZQf8!y<>jA}B&r+3BiX%kkSiO(#|PmjMEmHkfKHm1Q;dr$0L8*?a) zGu%ao+W1RMqrazV+4)n2x}%-CQd@?YfNOgMj#G$PFn!hOgpBO;nDY?@0t5hvW;|=P zoA|u9*Y>FN;?gH6Hxgco001GSUcR#opY9ktZPWRr+``hMY?gvG?-d;YL#zIaME?<9pyvZb@PC@ntiEt46GuZA=GQZewcB z{u9+6F7x;?=vrD{VNPUA3@Xi4!gE}EJUrEI;gMfjFpG3 zroRy)DsTM4aqRfj)8=iCc_l;$;MJY|%iQf8M=igp>U-w;T3cqvFFKQiZfy@t!*$(y zho{??o-P$4hS}oCn;Uv&ZW`amdcfS@>n5L!+16hbLjb^WS+&CH)i(Emqx=q}*C^Vr zJG#OsZlO!>AwPxTp1#&9lE|c`8P&+={O#T2A##OBf4c!w14FJncq5YG2Cim5(FUN4 z(?~-`(=Tx?=W*r$I>U$X=pQVb#)5N(?TJ1(g>vzyvHQl< z9`hb(V>5I~SP@?`cBakBn~}dbRi66E&Czz)?4OU`%B~UtAgYeX`h^yc0$c}9Sbn_V zeQkN!qf6WU#yQ&$_6m9Hw)?oBDMQ-T&!xAW2g7Xsne^-1X7I`)b}pXaHgv@F<)Imb z27^F~J?1YSOq}^?f_KpUYMeXcRD8&=@&jHDRt}SQJsT7fbHrT(2a!y-F}8D1{J8-0 zf_-y`+Vvehf6J*m#kIuOx+=8@v_9Xe}SNm@#mv`zwh)5 zX>2u(c3QrxeA6DYhVqp2JA$LLU)3|UES$X0#rQk3K`vweMCJ2KKjPyIv~$$oG<5r1 z`F%&Rfl~jy`K8b?n_v7Bqob;d*Iz$6X)sK@kKXbAf0eY-_>11Upo5{onf~n z0uf~J`OQKvGWcwl{A{@DVglh9CjM8~rYJZrCXfwRz3nLuheHqu!|={n{FD=L9483G z;cz-Fy=@t2m;8EYvv);j`46|GP$>V}{Wvfn2(;@)mX!{>?MarZYHnVRnVC6;W1rZv zgv4LG_6bDf<>s+itj_!mDQHe7Wp9k%ZvW0_|Qi;AnO ztE;N2NF{w4I2;a(#WFH9=(O~h6IU@1eTwl&*$^`e12VBT|+~IP$(3MLaddWidget(rotatableWidgets[i] + \printuntil } + \printuntil } + \include examples-run.qdocinc */ + diff --git a/examples/widgets/layouts/dynamiclayouts/dialog.cpp b/examples/widgets/layouts/dynamiclayouts/dialog.cpp index 080d69204bb..f46053372a4 100644 --- a/examples/widgets/layouts/dynamiclayouts/dialog.cpp +++ b/examples/widgets/layouts/dynamiclayouts/dialog.cpp @@ -55,12 +55,12 @@ Dialog::Dialog(QWidget *parent) : QDialog(parent) { - createRotableGroupBox(); + createRotatableGroupBox(); createOptionsGroupBox(); createButtonBox(); mainLayout = new QGridLayout; - mainLayout->addWidget(rotableGroupBox, 0, 0); + mainLayout->addWidget(rotatableGroupBox, 0, 0); mainLayout->addWidget(optionsGroupBox, 1, 0); mainLayout->addWidget(buttonBox, 2, 0); setLayout(mainLayout); @@ -102,17 +102,17 @@ void Dialog::buttonsOrientationChanged(int index) void Dialog::rotateWidgets() { - Q_ASSERT(rotableWidgets.count() % 2 == 0); + Q_ASSERT(rotatableWidgets.count() % 2 == 0); - foreach (QWidget *widget, rotableWidgets) - rotableLayout->removeWidget(widget); + foreach (QWidget *widget, rotatableWidgets) + rotatableLayout->removeWidget(widget); - rotableWidgets.enqueue(rotableWidgets.dequeue()); + rotatableWidgets.enqueue(rotatableWidgets.dequeue()); - const int n = rotableWidgets.count(); + const int n = rotatableWidgets.count(); for (int i = 0; i < n / 2; ++i) { - rotableLayout->addWidget(rotableWidgets[n - i - 1], 0, i); - rotableLayout->addWidget(rotableWidgets[i], 1, i); + rotatableLayout->addWidget(rotatableWidgets[n - i - 1], 0, i); + rotatableLayout->addWidget(rotatableWidgets[i], 1, i); } } @@ -123,23 +123,23 @@ void Dialog::help() "dynamically.")); } -void Dialog::createRotableGroupBox() +void Dialog::createRotatableGroupBox() { - rotableGroupBox = new QGroupBox(tr("Rotable Widgets")); + rotatableGroupBox = new QGroupBox(tr("Rotatable Widgets")); - rotableWidgets.enqueue(new QSpinBox); - rotableWidgets.enqueue(new QSlider); - rotableWidgets.enqueue(new QDial); - rotableWidgets.enqueue(new QProgressBar); + rotatableWidgets.enqueue(new QSpinBox); + rotatableWidgets.enqueue(new QSlider); + rotatableWidgets.enqueue(new QDial); + rotatableWidgets.enqueue(new QProgressBar); - int n = rotableWidgets.count(); + int n = rotatableWidgets.count(); for (int i = 0; i < n; ++i) { - connect(rotableWidgets[i], SIGNAL(valueChanged(int)), - rotableWidgets[(i + 1) % n], SLOT(setValue(int))); + connect(rotatableWidgets[i], SIGNAL(valueChanged(int)), + rotatableWidgets[(i + 1) % n], SLOT(setValue(int))); } - rotableLayout = new QGridLayout; - rotableGroupBox->setLayout(rotableLayout); + rotatableLayout = new QGridLayout; + rotatableGroupBox->setLayout(rotatableLayout); rotateWidgets(); } @@ -154,8 +154,10 @@ void Dialog::createOptionsGroupBox() buttonsOrientationComboBox->addItem(tr("Horizontal"), Qt::Horizontal); buttonsOrientationComboBox->addItem(tr("Vertical"), Qt::Vertical); - connect(buttonsOrientationComboBox, SIGNAL(currentIndexChanged(int)), - this, SLOT(buttonsOrientationChanged(int))); + connect(buttonsOrientationComboBox, + QOverload::of(&QComboBox::currentIndexChanged), + this, + &Dialog::buttonsOrientationChanged); optionsLayout = new QGridLayout; optionsLayout->addWidget(buttonsOrientationLabel, 0, 0); @@ -173,7 +175,9 @@ void Dialog::createButtonBox() rotateWidgetsButton = buttonBox->addButton(tr("Rotate &Widgets"), QDialogButtonBox::ActionRole); - connect(rotateWidgetsButton, SIGNAL(clicked()), this, SLOT(rotateWidgets())); - connect(closeButton, SIGNAL(clicked()), this, SLOT(close())); - connect(helpButton, SIGNAL(clicked()), this, SLOT(help())); + connect(rotateWidgetsButton, &QPushButton::clicked, this, &Dialog::rotateWidgets); + connect(closeButton, &QPushButton::clicked, this, &Dialog::close); + connect(helpButton, &QPushButton::clicked, this, &Dialog::help); } + + diff --git a/examples/widgets/layouts/dynamiclayouts/dialog.h b/examples/widgets/layouts/dynamiclayouts/dialog.h index 0ff0c12b385..923a6fe01bf 100644 --- a/examples/widgets/layouts/dynamiclayouts/dialog.h +++ b/examples/widgets/layouts/dynamiclayouts/dialog.h @@ -76,12 +76,12 @@ private slots: void help(); private: - void createRotableGroupBox(); + void createRotatableGroupBox(); void createOptionsGroupBox(); void createButtonBox(); - QGroupBox *rotableGroupBox; - QQueue rotableWidgets; + QGroupBox *rotatableGroupBox; + QQueue rotatableWidgets; QGroupBox *optionsGroupBox; QLabel *buttonsOrientationLabel; @@ -93,7 +93,7 @@ private: QPushButton *rotateWidgetsButton; QGridLayout *mainLayout; - QGridLayout *rotableLayout; + QGridLayout *rotatableLayout; QGridLayout *optionsLayout; }; From a62f1d03560937a306c7586669a46cd9575e9464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Sat, 3 Mar 2018 16:23:33 +0100 Subject: [PATCH 21/29] xcb: Prevent shared memory allocation on every window resize Allocate new shared memory only when window size grows or when window size is 2 times smaller than allocated memory size. This improves window resizing performance and also allows to free some memory if window becames much smaller. Change-Id: I3454cd3c6023eede8242d6b29038f4dd6638f9f1 Reviewed-by: Shawn Rutledge Reviewed-by: Alexander Volkov --- .../platforms/xcb/qxcbbackingstore.cpp | 118 ++++++++++++------ 1 file changed, 83 insertions(+), 35 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index 6ae52d9fd34..70d1757af46 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -74,7 +74,9 @@ class QXcbShmImage : public QXcbObject { public: QXcbShmImage(QXcbScreen *connection, const QSize &size, uint depth, QImage::Format format); - ~QXcbShmImage() { destroy(); } + ~QXcbShmImage() { destroy(true); } + + void resize(const QSize &size); void flushScrolledRegion(bool clientSideScroll); @@ -95,14 +97,18 @@ private: void createShmSegment(size_t segmentSize); void destroyShmSegment(size_t segmentSize); - void destroy(); + void create(const QSize &size, const xcb_format_t *fmt, QImage::Format format); + void destroy(bool destroyShm); void ensureGC(xcb_drawable_t dst); void shmPutImage(xcb_drawable_t drawable, const QRegion ®ion, const QPoint &offset = QPoint()); void flushPixmap(const QRegion ®ion, bool fullRegion = false); void setClip(const QRegion ®ion); + xcb_window_t m_screen_root; + xcb_shm_segment_info_t m_shm_info; + size_t m_segmentSize; xcb_image_t *m_xcb_image; @@ -171,6 +177,8 @@ static inline size_t imageDataSize(const xcb_image_t *image) QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QImage::Format format) : QXcbObject(screen->connection()) + , m_screen_root(screen->screen()->root) + , m_segmentSize(0) , m_graphics_buffer(nullptr) , m_gc(0) , m_gc_drawable(0) @@ -180,6 +188,27 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI const xcb_format_t *fmt = connection()->formatForDepth(depth); Q_ASSERT(fmt); + m_hasAlpha = QImage::toPixelFormat(format).alphaUsage() == QPixelFormat::UsesAlpha; + if (!m_hasAlpha) + format = qt_maybeAlphaVersionWithSameDepth(format); + + memset(&m_shm_info, 0, sizeof m_shm_info); + create(size, fmt, format); +} + +void QXcbShmImage::resize(const QSize &size) +{ + xcb_format_t fmt; + fmt.depth = m_xcb_image->depth; + fmt.bits_per_pixel = m_xcb_image->bpp; + fmt.scanline_pad = m_xcb_image->scanline_pad; + memset(fmt.pad0, 0, sizeof(fmt.pad0)); + destroy(false); + create(size, &fmt, m_qimage.format()); +} + +void QXcbShmImage::create(const QSize &size, const xcb_format_t *fmt, QImage::Format format) +{ m_xcb_image = xcb_image_create(size.width(), size.height(), XCB_IMAGE_FORMAT_Z_PIXMAP, fmt->scanline_pad, @@ -192,14 +221,16 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI if (!segmentSize) return; - createShmSegment(segmentSize); + if (hasShm() && m_segmentSize > 0 && (m_segmentSize < segmentSize || m_segmentSize / 2 >= segmentSize)) + destroyShmSegment(m_segmentSize); + if (!hasShm() && connection()->hasShm()) + { + qCDebug(lcQpaXcb) << "creating shared memory" << segmentSize << "for" << size << "depth" << fmt->depth << "bits" << fmt->bits_per_pixel; + createShmSegment(segmentSize); + } m_xcb_image->data = m_shm_info.shmaddr ? m_shm_info.shmaddr : (uint8_t *)malloc(segmentSize); - m_hasAlpha = QImage::toPixelFormat(format).alphaUsage() == QPixelFormat::UsesAlpha; - if (!m_hasAlpha) - format = qt_maybeAlphaVersionWithSameDepth(format); - m_qimage = QImage( (uchar*) m_xcb_image->data, m_xcb_image->width, m_xcb_image->height, m_xcb_image->stride, format); m_graphics_buffer = new QXcbShmGraphicsBuffer(&m_qimage); @@ -207,10 +238,36 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI xcb_create_pixmap(xcb_connection(), m_xcb_image->depth, m_xcb_pixmap, - screen->screen()->root, + m_screen_root, m_xcb_image->width, m_xcb_image->height); } +void QXcbShmImage::destroy(bool destroyShm) +{ + if (m_xcb_image->data) { + if (m_shm_info.shmaddr) { + if (destroyShm) + destroyShmSegment(m_segmentSize); + } else { + free(m_xcb_image->data); + } + } + + xcb_image_destroy(m_xcb_image); + + if (m_gc) { + xcb_free_gc(xcb_connection(), m_gc); + m_gc = 0; + } + m_gc_drawable = 0; + + delete m_graphics_buffer; + m_graphics_buffer = nullptr; + + xcb_free_pixmap(xcb_connection(), m_xcb_pixmap); + m_xcb_pixmap = 0; +} + void QXcbShmImage::flushScrolledRegion(bool clientSideScroll) { if (m_clientSideScroll == clientSideScroll) @@ -261,10 +318,8 @@ void QXcbShmImage::flushScrolledRegion(bool clientSideScroll) void QXcbShmImage::createShmSegment(size_t segmentSize) { - m_shm_info.shmaddr = nullptr; - - if (!connection()->hasShm()) - return; + Q_ASSERT(connection()->hasShm()); + Q_ASSERT(m_segmentSize == 0); #ifdef XCB_USE_SHM_FD if (connection()->hasShmFd()) { @@ -302,6 +357,8 @@ void QXcbShmImage::createShmSegment(size_t segmentSize) close(fds[0]); m_shm_info.shmseg = seg; m_shm_info.shmaddr = static_cast(addr); + + m_segmentSize = segmentSize; } else #endif { @@ -338,6 +395,8 @@ void QXcbShmImage::createShmSegment(size_t segmentSize) m_shm_info.shmseg = seg; m_shm_info.shmid = id; // unused m_shm_info.shmaddr = static_cast(addr); + + m_segmentSize = segmentSize; } } @@ -350,6 +409,7 @@ void QXcbShmImage::destroyShmSegment(size_t segmentSize) xcb_generic_error_t *error = xcb_request_check(xcb_connection(), cookie); if (error) connection()->printXcbError("QXcbShmImage: xcb_shm_detach() failed with error", error); + m_shm_info.shmseg = 0; #ifdef XCB_USE_SHM_FD if (connection()->hasShmFd()) { @@ -364,7 +424,11 @@ void QXcbShmImage::destroyShmSegment(size_t segmentSize) qWarning("QXcbShmImage: shmdt() failed (%d: %s) for %p", errno, strerror(errno), m_shm_info.shmaddr); } + m_shm_info.shmid = 0; // unused } + m_shm_info.shmaddr = nullptr; + + m_segmentSize = 0; } extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset); @@ -413,26 +477,6 @@ bool QXcbShmImage::scroll(const QRegion &area, int dx, int dy) return true; } -void QXcbShmImage::destroy() -{ - if (m_xcb_image->data) { - if (m_shm_info.shmaddr) - destroyShmSegment(imageDataSize(m_xcb_image)); - else - free(m_xcb_image->data); - } - - xcb_image_destroy(m_xcb_image); - - if (m_gc) - xcb_free_gc(xcb_connection(), m_gc); - delete m_graphics_buffer; - m_graphics_buffer = nullptr; - - xcb_free_pixmap(xcb_connection(), m_xcb_pixmap); - m_xcb_pixmap = 0; -} - void QXcbShmImage::ensureGC(xcb_drawable_t dst) { if (m_gc_drawable != dst) { @@ -805,7 +849,6 @@ void QXcbBackingStore::resize(const QSize &size, const QRegion &) if (m_image && size == m_image->size()) return; - QXcbScreen *screen = static_cast(window()->screen()->handle()); QPlatformWindow *pw = window()->handle(); if (!pw) { window()->create(); @@ -813,8 +856,13 @@ void QXcbBackingStore::resize(const QSize &size, const QRegion &) } QXcbWindow* win = static_cast(pw); - delete m_image; - m_image = new QXcbShmImage(screen, size, win->depth(), win->imageFormat()); + if (m_image) { + m_image->resize(size); + } else { + QXcbScreen *screen = static_cast(window()->screen()->handle()); + m_image = new QXcbShmImage(screen, size, win->depth(), win->imageFormat()); + } + // Slow path for bgr888 VNC: Create an additional image, paint into that and // swap R and B while copying to m_image after each paint. if (win->imageNeedsRgbSwap()) { From 91b35011f52c092360314e4a625e1f806402af5e Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Mon, 12 Mar 2018 14:26:42 +0100 Subject: [PATCH 22/29] doc: Make fromStdVariant() appear in the QVariant docs This function was not appearing in the QVariant docs because the \fn command was wrong and because clang was not seeing the declaration in qvariant.h in the first place. With this update, the function does appear in the docs, but it's signature is not correct because clang can't find a definition for std::variant, which probably means it doesn't have the most recent declarations in the std namespace. Change-Id: I7912ff333e5d4a8619461dd3ab7ee34bcd8f2289 Reviewed-by: Allan Sandfeld Jensen --- src/corelib/kernel/qvariant.cpp | 2 +- src/corelib/kernel/qvariant.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 96299b9eafd..f77831c703a 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -3896,7 +3896,7 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) \sa setValue(), value() */ -/*! \fn static inline QVariant fromStdVariant(const std::variant &value) +/*! \fn template QVariant QVariant::fromStdVariant(const std::variant &value) \since 5.11 Returns a QVariant with the type and value of the active variant of \a value. If diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index fe1ef1bdfcd..7ce4e1a4d81 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -359,7 +359,7 @@ class Q_CORE_EXPORT QVariant static inline QVariant fromValue(const T &value) { return qVariantFromValue(value); } -#if QT_HAS_INCLUDE() && __cplusplus >= 201703L +#if defined(Q_CLANG_QDOC) || (QT_HAS_INCLUDE() && __cplusplus >= 201703L) template static inline QVariant fromStdVariant(const std::variant &value) { From 59343eef7dce58b1c167250b59b5f0a68428aa14 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 14 Mar 2018 13:34:13 +0100 Subject: [PATCH 23/29] sub-attaq example: Fix crash with software Open GL Check whether an Open GL context could be created, else fall back to raster. Task-number: QTBUG-64797 Change-Id: I91bba41b0efca85293a1a4af054842b9f309b126 Reviewed-by: Laszlo Agocs --- examples/widgets/animation/sub-attaq/mainwindow.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/examples/widgets/animation/sub-attaq/mainwindow.cpp b/examples/widgets/animation/sub-attaq/mainwindow.cpp index 106404682d0..b08a7d9f985 100644 --- a/examples/widgets/animation/sub-attaq/mainwindow.cpp +++ b/examples/widgets/animation/sub-attaq/mainwindow.cpp @@ -84,8 +84,13 @@ MainWindow::MainWindow() : QMainWindow(0) view->setAlignment(Qt::AlignLeft | Qt::AlignTop); scene->setupScene(newAction, quitAction); #ifndef QT_NO_OPENGL - view->setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers))); + QGLWidget *glWidget = new QGLWidget(QGLFormat(QGL::SampleBuffers)); + if (glWidget->context()->isValid()) { + view->setViewport(glWidget); + } else { + qWarning("Unable to create an Open GL context with sample buffers, not using Open GL."); + delete glWidget; + } #endif - setCentralWidget(view); } From b30b957552c8f9df2cc6e600a0bc71649bf0bb07 Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Tue, 13 Mar 2018 10:31:19 +0200 Subject: [PATCH 24/29] Android: Fix possible crash Change-Id: I3362dffe0f30196a2a1eabcffe6cb3b2d52a7785 Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/corelib/kernel/qjnihelpers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/kernel/qjnihelpers.cpp b/src/corelib/kernel/qjnihelpers.cpp index 04c9a9bcba5..712e8bbcab1 100644 --- a/src/corelib/kernel/qjnihelpers.cpp +++ b/src/corelib/kernel/qjnihelpers.cpp @@ -599,7 +599,7 @@ void QtAndroidPrivate::setOnBindListener(QtAndroidPrivate::OnBindListener *liste jobject QtAndroidPrivate::callOnBindListener(jobject intent) { QMutexLocker lock(g_onBindListenerMutex); - if (g_onBindListener) + if (*g_onBindListener) return (*g_onBindListener)->onBind(intent); return nullptr; } From ed245f3e70661a1e02467393918feef4b5af8197 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 12 Mar 2018 17:09:18 +0100 Subject: [PATCH 25/29] Manual tablet test: Draw crosshairs when tablet pen is close Crosshairs provide better visual feedback for coordinate conversions. Change-Id: I20f67733d7a5e6b1455507a39a8b9535202a92c4 Reviewed-by: Shawn Rutledge --- .../qtabletevent/regular_widgets/main.cpp | 60 ++++++++++++++----- 1 file changed, 44 insertions(+), 16 deletions(-) diff --git a/tests/manual/qtabletevent/regular_widgets/main.cpp b/tests/manual/qtabletevent/regular_widgets/main.cpp index caf8c70c6f4..c0366dea63d 100644 --- a/tests/manual/qtabletevent/regular_widgets/main.cpp +++ b/tests/manual/qtabletevent/regular_widgets/main.cpp @@ -61,23 +61,38 @@ struct TabletPoint class ProximityEventFilter : public QObject { + Q_OBJECT public: explicit ProximityEventFilter(QObject *parent) : QObject(parent) { } - bool eventFilter(QObject *, QEvent *event) override - { - switch (event->type()) { - case QEvent::TabletEnterProximity: - case QEvent::TabletLeaveProximity: - qDebug() << event; - break; - default: - break; - } - return false; - } + bool eventFilter(QObject *, QEvent *event) override; + + static bool tabletPenProximity() { return m_tabletPenProximity; } + +signals: + void proximityChanged(); + +private: + static bool m_tabletPenProximity; }; +bool ProximityEventFilter::eventFilter(QObject *, QEvent *event) +{ + switch (event->type()) { + case QEvent::TabletEnterProximity: + case QEvent::TabletLeaveProximity: + ProximityEventFilter::m_tabletPenProximity = event->type() == QEvent::TabletEnterProximity; + emit proximityChanged(); + qDebug() << event; + break; + default: + break; + } + return false; +} + +bool ProximityEventFilter::m_tabletPenProximity = false; + class EventReportWidget : public QWidget { Q_OBJECT @@ -111,6 +126,7 @@ private: Qt::MouseButton m_lastButton = Qt::NoButton; QVector m_points; QVector m_touchPoints; + QPointF m_tabletPos; int m_tabletMoveCount = 0; int m_paintEventCount = 0; }; @@ -169,6 +185,13 @@ void EventReportWidget::paintEvent(QPaintEvent *) } } } + + // Draw haircross when tablet pen is in proximity + if (ProximityEventFilter::tabletPenProximity() && geom.contains(m_tabletPos)) { + p.setPen(Qt::black); + p.drawLine(QPointF(0, m_tabletPos.y()), QPointF(geom.width(), m_tabletPos.y())); + p.drawLine(QPointF(m_tabletPos.x(), 0), QPointF(m_tabletPos.x(), geom.height())); + } p.setPen(Qt::blue); for (QPointF t : m_touchPoints) { p.drawLine(t.x() - 40, t.y(), t.x() + 40, t.y()); @@ -181,20 +204,21 @@ void EventReportWidget::tabletEvent(QTabletEvent *event) { QWidget::tabletEvent(event); bool isMove = false; + m_tabletPos = event->posF(); switch (event->type()) { case QEvent::TabletMove: - m_points.push_back(TabletPoint(event->pos(), TabletMove, m_lastButton, event->pointerType(), event->pressure(), event->rotation())); + m_points.push_back(TabletPoint(m_tabletPos, TabletMove, m_lastButton, event->pointerType(), event->pressure(), event->rotation())); update(); isMove = true; ++m_tabletMoveCount; break; case QEvent::TabletPress: - m_points.push_back(TabletPoint(event->pos(), TabletButtonPress, event->button(), event->pointerType(), event->rotation())); + m_points.push_back(TabletPoint(m_tabletPos, TabletButtonPress, event->button(), event->pointerType(), event->rotation())); m_lastButton = event->button(); update(); break; case QEvent::TabletRelease: - m_points.push_back(TabletPoint(event->pos(), TabletButtonRelease, event->button(), event->pointerType(), event->rotation())); + m_points.push_back(TabletPoint(m_tabletPos, TabletButtonRelease, event->button(), event->pointerType(), event->rotation())); update(); break; default: @@ -253,10 +277,14 @@ void EventReportWidget::timerEvent(QTimerEvent *) int main(int argc, char *argv[]) { QApplication app(argc, argv); - app.installEventFilter(new ProximityEventFilter(&app)); + + ProximityEventFilter *proximityEventFilter = new ProximityEventFilter(&app); + app.installEventFilter(proximityEventFilter); QMainWindow mainWindow; mainWindow.setWindowTitle(QString::fromLatin1("Tablet Test %1").arg(QT_VERSION_STR)); EventReportWidget *widget = new EventReportWidget; + QObject::connect(proximityEventFilter, &ProximityEventFilter::proximityChanged, + widget, QOverload::of(&QWidget::update)); widget->setMinimumSize(640, 480); QMenu *fileMenu = mainWindow.menuBar()->addMenu("File"); fileMenu->addAction("Clear", widget, &EventReportWidget::clearPoints); From a93096a77030b3ffa810265fdf2e9616e2929092 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Wed, 14 Mar 2018 15:55:48 +0100 Subject: [PATCH 26/29] Fix performance regression in simple a8 non-gamma corrected Avoid doing the conversion over QRgba64 when we don't need it. Change-Id: Ic2f82bef0a80b17ef7803eedcdb0600eeac96489 Reviewed-by: Lars Knoll --- src/gui/painting/qdrawhelper.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 23c8e42ded7..f08038e34b8 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -5670,6 +5670,8 @@ static inline void alphamapblend_argb32(quint32 *dst, int coverage, QRgba64 srcL // nothing } else if (coverage == 255) { *dst = src; + } else if (!colorProfile) { + *dst = INTERPOLATE_PIXEL_255(src, coverage, *dst, 255 - coverage); } else { if (*dst >= 0xff000000) { grayBlendPixel(dst, coverage, srcLinear, colorProfile); From 1718efe8fab245ef2a5a3dd11dc038cdcd0957bc Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Mon, 14 Aug 2017 14:02:56 +0200 Subject: [PATCH 27/29] QByteArray::setRawData(): don't null-terminate initialization from nullptr it's antithetical to do that, as raw data is documented to be not null- terminated. QString doesn't, either. Change-Id: I7ded83a09f64e747a248f9bdac2a364032aae4c0 Reviewed-by: Thiago Macieira --- src/corelib/tools/qbytearray.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index adfa939cc6d..421e716d141 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -4337,7 +4337,6 @@ QByteArray &QByteArray::setRawData(const char *data, uint size) } else { d->offset = sizeof(QByteArrayData); d->size = 0; - *d->data() = 0; } } return *this; From 96ba39b1ee095e814587c760dc83add03ee67232 Mon Sep 17 00:00:00 2001 From: Alexander Akulich Date: Tue, 13 Mar 2018 21:56:17 +0300 Subject: [PATCH 28/29] QFlatpakTheme: Cleanup the code There is no codepath that can result in d->baseTheme being nullptr. Remove the checks and get rid unneeded and sometimes dangerous fallbacks (createPlatformMenuBar(), showPlatformMenuBar() and three more methods could overflow the stack because of infinity recursion). Change-Id: Ib03adadf56c169286de42671e2da506502df7aea Reviewed-by: Jan Grulich Reviewed-by: Thiago Macieira --- .../platformthemes/flatpak/qflatpaktheme.cpp | 88 ++++--------------- 1 file changed, 15 insertions(+), 73 deletions(-) diff --git a/src/plugins/platformthemes/flatpak/qflatpaktheme.cpp b/src/plugins/platformthemes/flatpak/qflatpaktheme.cpp index 04abd707e10..6c5e1389cfc 100644 --- a/src/plugins/platformthemes/flatpak/qflatpaktheme.cpp +++ b/src/plugins/platformthemes/flatpak/qflatpaktheme.cpp @@ -95,41 +95,25 @@ QFlatpakTheme::QFlatpakTheme() QPlatformMenuItem* QFlatpakTheme::createPlatformMenuItem() const { Q_D(const QFlatpakTheme); - - if (d->baseTheme) - return d->baseTheme->createPlatformMenuItem(); - - return QPlatformTheme::createPlatformMenuItem(); + return d->baseTheme->createPlatformMenuItem(); } QPlatformMenu* QFlatpakTheme::createPlatformMenu() const { Q_D(const QFlatpakTheme); - - if (d->baseTheme) - return d->baseTheme->createPlatformMenu(); - - return QPlatformTheme::createPlatformMenu(); + return d->baseTheme->createPlatformMenu(); } QPlatformMenuBar* QFlatpakTheme::createPlatformMenuBar() const { Q_D(const QFlatpakTheme); - - if (d->baseTheme) - return d->baseTheme->createPlatformMenuBar(); - - return QFlatpakTheme::createPlatformMenuBar(); + return d->baseTheme->createPlatformMenuBar(); } void QFlatpakTheme::showPlatformMenuBar() { Q_D(const QFlatpakTheme); - - if (d->baseTheme) - return d->baseTheme->showPlatformMenuBar(); - - return QFlatpakTheme::showPlatformMenuBar(); + return d->baseTheme->showPlatformMenuBar(); } bool QFlatpakTheme::usePlatformNativeDialog(DialogType type) const @@ -139,10 +123,7 @@ bool QFlatpakTheme::usePlatformNativeDialog(DialogType type) const if (type == FileDialog) return true; - if (d->baseTheme) - return d->baseTheme->usePlatformNativeDialog(type); - - return QFlatpakTheme::usePlatformNativeDialog(type); + return d->baseTheme->usePlatformNativeDialog(type); } QPlatformDialogHelper* QFlatpakTheme::createPlatformDialogHelper(DialogType type) const @@ -152,103 +133,64 @@ QPlatformDialogHelper* QFlatpakTheme::createPlatformDialogHelper(DialogType type if (type == FileDialog) return new QFlatpakFileDialog; - if (d->baseTheme) - return d->baseTheme->createPlatformDialogHelper(type); - - return QFlatpakTheme::createPlatformDialogHelper(type); + return d->baseTheme->createPlatformDialogHelper(type); } #ifndef QT_NO_SYSTEMTRAYICON QPlatformSystemTrayIcon* QFlatpakTheme::createPlatformSystemTrayIcon() const { Q_D(const QFlatpakTheme); - - if (d->baseTheme) - return d->baseTheme->createPlatformSystemTrayIcon(); - - return QPlatformTheme::createPlatformSystemTrayIcon(); + return d->baseTheme->createPlatformSystemTrayIcon(); } #endif const QPalette *QFlatpakTheme::palette(Palette type) const { Q_D(const QFlatpakTheme); - - if (d->baseTheme) - return d->baseTheme->palette(type); - - return QPlatformTheme::palette(type); + return d->baseTheme->palette(type); } const QFont* QFlatpakTheme::font(Font type) const { Q_D(const QFlatpakTheme); - - if (d->baseTheme) - return d->baseTheme->font(type); - - return QPlatformTheme::font(type); + return d->baseTheme->font(type); } QVariant QFlatpakTheme::themeHint(ThemeHint hint) const { Q_D(const QFlatpakTheme); - - if (d->baseTheme) - return d->baseTheme->themeHint(hint); - - return QPlatformTheme::themeHint(hint); + return d->baseTheme->themeHint(hint); } QPixmap QFlatpakTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const { Q_D(const QFlatpakTheme); - - if (d->baseTheme) - return d->baseTheme->standardPixmap(sp, size); - - return QPlatformTheme::standardPixmap(sp, size); + return d->baseTheme->standardPixmap(sp, size); } QIcon QFlatpakTheme::fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions iconOptions) const { Q_D(const QFlatpakTheme); - - if (d->baseTheme) - return d->baseTheme->fileIcon(fileInfo, iconOptions); - - return QPlatformTheme::fileIcon(fileInfo, iconOptions); + return d->baseTheme->fileIcon(fileInfo, iconOptions); } QIconEngine * QFlatpakTheme::createIconEngine(const QString &iconName) const { Q_D(const QFlatpakTheme); - - if (d->baseTheme) - return d->baseTheme->createIconEngine(iconName); - - return QPlatformTheme::createIconEngine(iconName); + return d->baseTheme->createIconEngine(iconName); } QList QFlatpakTheme::keyBindings(QKeySequence::StandardKey key) const { Q_D(const QFlatpakTheme); - - if (d->baseTheme) - return d->baseTheme->keyBindings(key); - - return QPlatformTheme::keyBindings(key); + return d->baseTheme->keyBindings(key); } QString QFlatpakTheme::standardButtonText(int button) const { Q_D(const QFlatpakTheme); - - if (d->baseTheme) - return d->baseTheme->standardButtonText(button); - - return QPlatformTheme::standardButtonText(button); + return d->baseTheme->standardButtonText(button); } QT_END_NAMESPACE From 8eb3944dac81b8c51d7bac7784204d457551b50c Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 7 Jan 2018 15:32:35 -0600 Subject: [PATCH 29/29] Disable statx(2) and renameat2(2) system calls on Android Many Android systems come with a locked down system call list, causing the statx(2) system call to fail with an unexpected error code or by delivering a signal to the application. Because of the signal, we can't do runtime detection... This is not our bug: it's obviously a mistake in the SECCOMP rules in Android. But we work around the issue. Unfortunately, because of a few manufacturers who can't configure their rules properly, everyone will suffer. Task-number: QTBUG-64490 Change-Id: I39332e0a867442d58082fffd1507a49415917384 Reviewed-by: BogDan Vatra --- src/corelib/io/qfilesystemengine_unix.cpp | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index b974af80dcf..b8cf42a2e90 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -91,26 +91,35 @@ extern "C" NSString *NSTemporaryDirectory(); # include # include # include +# include // in case linux/fs.h is too old and doesn't define it: #ifndef FICLONE # define FICLONE _IOW(0x94, 9, int) #endif -# if !QT_CONFIG(renameat2) && defined(SYS_renameat2) +# if defined(Q_OS_ANDROID) +// renameat2() and statx() are disabled on Android because quite a few systems +// come with sandboxes that kill applications that make system calls outside a +// whitelist and several Android vendors can't be bothered to update the list. +# undef SYS_renameat2 +# undef SYS_statx +# undef STATX_BASIC_STATS +# else +# if !QT_CONFIG(renameat2) && defined(SYS_renameat2) static int renameat2(int oldfd, const char *oldpath, int newfd, const char *newpath, unsigned flags) { return syscall(SYS_renameat2, oldfd, oldpath, newfd, newpath, flags); } -# endif +# endif -# if !QT_CONFIG(statx) && defined(SYS_statx) && QT_HAS_INCLUDE() -# include +# if !QT_CONFIG(statx) && defined(SYS_statx) static int statx(int dirfd, const char *pathname, int flag, unsigned mask, struct statx *statxbuf) { return syscall(SYS_statx, dirfd, pathname, flag, mask, statxbuf); } -# endif +# endif +# endif // !Q_OS_ANDROID #endif -#ifndef STATX_BASIC_STATS -struct statx { mode_t stx_mode; }; +#ifndef STATX_ALL +struct statx { mode_t stx_mode; }; // dummy #endif QT_BEGIN_NAMESPACE