From 9e59174b49b8d4c6ebe0cab2b8df9e93f1090211 Mon Sep 17 00:00:00 2001 From: Anton Kudryavtsev Date: Sat, 20 Feb 2016 15:48:40 +0300 Subject: QPixmap: check data ptr in isQBitmap() Task-number: QTBUG-51271 Change-Id: I670e074ced1217d2614fa334eb365e40ef80b8b1 Reviewed-by: Edward Welbourne Reviewed-by: Marc Mutz --- src/gui/image/qpixmap.cpp | 2 +- tests/auto/gui/image/qpixmap/tst_qpixmap.cpp | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index fb62889e40..0c8ab527b2 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -481,7 +481,7 @@ QMatrix QPixmap::trueMatrix(const QMatrix &m, int w, int h) bool QPixmap::isQBitmap() const { - return data->type == QPlatformPixmap::BitmapType; + return data && data->type == QPlatformPixmap::BitmapType; } /*! diff --git a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp index 67d7e57fd4..4ffe357d09 100644 --- a/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp +++ b/tests/auto/gui/image/qpixmap/tst_qpixmap.cpp @@ -105,6 +105,7 @@ private slots: void drawBitmap(); void isNull(); void task_246446(); + void task_51271(); void convertFromImageNoDetach(); void convertFromImageDetach(); @@ -1441,6 +1442,14 @@ void tst_QPixmap::task_246446() QVERIFY(pm.mask().isNull()); } +void tst_QPixmap::task_51271() +{ + QPixmap pm; + QBitmap bm; + QVERIFY(!pm.isQBitmap()); // Should not crash ! + QVERIFY(bm.isQBitmap()); +} + void tst_QPixmap::preserveDepth() { QPixmap target(64, 64); -- cgit v1.2.3 From 479167cd4e7102b4cff654a13cc43298bbb638d0 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Wed, 24 Feb 2016 12:22:46 +0100 Subject: tst_QProcess: Transform loop into additional test rows Do not use a loop to execute similar but separate tests in tst_QProcess::softExitInSlots. Use separate test rows with distinguishable data tags instead. This way we can deduce from CI output which part of this test failed. Change-Id: Ic9bc996f2ced11b2bb1c33c1970e64937d860976 Reviewed-by: Friedemann Kleint --- tests/auto/corelib/io/qprocess/tst_qprocess.cpp | 27 ++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp index 712e3440d8..b7dd58870c 100644 --- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp +++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp @@ -1050,24 +1050,33 @@ private: void tst_QProcess::softExitInSlots_data() { QTest::addColumn("appName"); + QTest::addColumn("signalToConnect"); + QByteArray dataTagPrefix("gui app "); #ifndef QT_NO_WIDGETS - QTest::newRow("gui app") << "testGuiProcess/testGuiProcess"; + for (int i = 0; i < 5; ++i) { + QTest::newRow(dataTagPrefix + QByteArray::number(i)) + << "testGuiProcess/testGuiProcess" << i; + } #endif - QTest::newRow("console app") << "testProcessEcho2/testProcessEcho2"; + + dataTagPrefix = "console app "; + for (int i = 0; i < 5; ++i) { + QTest::newRow(dataTagPrefix + QByteArray::number(i)) + << "testProcessEcho2/testProcessEcho2" << i; + } } void tst_QProcess::softExitInSlots() { QFETCH(QString, appName); + QFETCH(int, signalToConnect); - for (int i = 0; i < 5; ++i) { - SoftExitProcess proc(i); - proc.writeAfterStart("OLEBOLE", 8); // include the \0 - proc.start(appName); - QTRY_VERIFY_WITH_TIMEOUT(proc.waitedForFinished, 10000); - QCOMPARE(proc.state(), QProcess::NotRunning); - } + SoftExitProcess proc(signalToConnect); + proc.writeAfterStart("OLEBOLE", 8); // include the \0 + proc.start(appName); + QTRY_VERIFY_WITH_TIMEOUT(proc.waitedForFinished, 10000); + QCOMPARE(proc.state(), QProcess::NotRunning); } #endif -- cgit v1.2.3 From 696a4bc2f96fb84c38ff40507608e834d2cd79c7 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Wed, 24 Feb 2016 14:12:44 +0100 Subject: Remove legacy from tst_qprocess.cpp The windows.h include is not needed, the enums are properly known to the metaobject system nowadays, and qprocess_p.h already has a QT_NO_PROCESS guard. Change-Id: I6bbdce19f097feb8260c51a29425279049aa0192 Reviewed-by: Friedemann Kleint --- tests/auto/corelib/io/qprocess/tst_qprocess.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp index b7dd58870c..8b311921e2 100644 --- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp +++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp @@ -45,15 +45,7 @@ #include #include -#ifndef QT_NO_PROCESS # include // only so we get QPROCESS_USE_SPAWN -# if defined(Q_OS_WIN) -# include -# endif - -Q_DECLARE_METATYPE(QProcess::ExitStatus); -Q_DECLARE_METATYPE(QProcess::ProcessState); -#endif typedef void (QProcess::*QProcessFinishedSignal1)(int); typedef void (QProcess::*QProcessFinishedSignal2)(int, QProcess::ExitStatus); -- cgit v1.2.3 From 1db9962cef140971d18110bb76486c40db373b8f Mon Sep 17 00:00:00 2001 From: Mark Brand Date: Thu, 18 Feb 2016 14:38:39 +0100 Subject: QSqlDriver::sqlStatement: documentation fix Change-Id: I12bd612c48020594b5377b04aeccc51f7c4be53d Reviewed-by: Andy Shaw Reviewed-by: Vyacheslav Grigoryev --- src/sql/kernel/qsqldriver.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/sql/kernel/qsqldriver.cpp b/src/sql/kernel/qsqldriver.cpp index 9ee8d67f56..adaeb8c846 100644 --- a/src/sql/kernel/qsqldriver.cpp +++ b/src/sql/kernel/qsqldriver.cpp @@ -457,6 +457,17 @@ QString QSqlDriver::stripDelimiters(const QString &identifier, IdentifierType ty This method can be used to manipulate tables without having to worry about database-dependent SQL dialects. For non-prepared statements, the values will be properly escaped. + + In the WHERE statement, each non-null field of \a rec specifies a + filter condition of equality to the field value, or if prepared, a + placeholder. However, prepared or not, a null field specifies the + condition IS NULL and never introduces a placeholder. The + application must not attempt to bind data for the null field during + execution. The field must be set to some non-null value if a + placeholder is desired. Furthermore, since non-null fields specify + equality conditions and SQL NULL is not equal to anything, even + itself, it is generally not useful to bind a null to a placeholder. + */ QString QSqlDriver::sqlStatement(StatementType type, const QString &tableName, const QSqlRecord &rec, bool preparedStatement) const -- cgit v1.2.3 From e695b92464f886bb9026bb20877f0ea3ea57d2c8 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 7 Jan 2016 12:18:26 +0100 Subject: QWindow: Use scaling when calling QPlatformWindow::mapTo/FromGlobal(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The platform window API uses native pixels. Task-number: QTBUG-50206 Change-Id: I1385d34bb0eacd61d77cad483e2a863d129ed129 Reviewed-by: Morten Johan Sørvig --- src/gui/kernel/qwindow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index e0d991aaf8..68bcbdec71 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -2298,7 +2298,7 @@ QPoint QWindow::mapToGlobal(const QPoint &pos) const // QTBUG-43252, prefer platform implementation for foreign windows. if (d->platformWindow && (type() == Qt::ForeignWindow || d->platformWindow->isEmbedded())) { - return d->platformWindow->mapToGlobal(pos); + return QHighDpi::fromNativeLocalPosition(d->platformWindow->mapToGlobal(QHighDpi::toNativeLocalPosition(pos, this)), this); } return pos + d->globalPosition(); } @@ -2318,7 +2318,7 @@ QPoint QWindow::mapFromGlobal(const QPoint &pos) const // QTBUG-43252, prefer platform implementation for foreign windows. if (d->platformWindow && (type() == Qt::ForeignWindow || d->platformWindow->isEmbedded())) { - return d->platformWindow->mapFromGlobal(pos); + return QHighDpi::fromNativeLocalPosition(d->platformWindow->mapFromGlobal(QHighDpi::toNativeLocalPosition(pos, this)), this); } return pos - d->globalPosition(); } -- cgit v1.2.3 From 45feee5f93fad5396af2653ed904a535bc5b7938 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Thu, 25 Feb 2016 10:12:50 +0100 Subject: Fix QDBusPlatformMenu::menuItemAt() Other platform menu implementations check that the index is not out of bounds, so make QDBusPlatformMenu::menuItemAt() do the same. Change-Id: I1d2e42681f2dbfff8b80044141d620bddbc3b6aa Task-number: QTBUG-51372 Reviewed-by: Simon Hausmann Reviewed-by: Dmitry Shachnev --- src/platformsupport/dbusmenu/qdbusplatformmenu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/platformsupport/dbusmenu/qdbusplatformmenu.cpp b/src/platformsupport/dbusmenu/qdbusplatformmenu.cpp index 9f99ef97e5..5c259d5b67 100644 --- a/src/platformsupport/dbusmenu/qdbusplatformmenu.cpp +++ b/src/platformsupport/dbusmenu/qdbusplatformmenu.cpp @@ -262,7 +262,7 @@ void QDBusPlatformMenu::setContainingMenuItem(QDBusPlatformMenuItem *item) QPlatformMenuItem *QDBusPlatformMenu::menuItemAt(int position) const { - return m_items.at(position); + return m_items.value(position); } QPlatformMenuItem *QDBusPlatformMenu::menuItemForTag(quintptr tag) const -- cgit v1.2.3 From debc44cf1106fb20065aab7848759eace3211c65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Arve=20S=C3=A6ther?= Date: Thu, 25 Feb 2016 15:54:40 +0100 Subject: Add missing initializations in QWheelEvent Change-Id: I77f014934b97aa6729d568996f0e6c03feb44588 Reviewed-by: Shawn Rutledge --- src/gui/kernel/qevent.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index b0f7adf43a..4f368e1db3 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -726,7 +726,8 @@ QHoverEvent::~QHoverEvent() QWheelEvent::QWheelEvent(const QPointF &pos, int delta, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::Orientation orient) - : QInputEvent(Wheel, modifiers), p(pos), qt4D(delta), qt4O(orient), mouseState(buttons) + : QInputEvent(Wheel, modifiers), p(pos), qt4D(delta), qt4O(orient), mouseState(buttons), + ph(Qt::ScrollUpdate), src(Qt::MouseEventNotSynthesized) { g = QCursor::pos(); if (orient == Qt::Vertical) @@ -760,7 +761,8 @@ QWheelEvent::~QWheelEvent() QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, int delta, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::Orientation orient) - : QInputEvent(Wheel, modifiers), p(pos), g(globalPos), qt4D(delta), qt4O(orient), mouseState(buttons) + : QInputEvent(Wheel, modifiers), p(pos), g(globalPos), qt4D(delta), qt4O(orient), mouseState(buttons), + ph(Qt::ScrollUpdate), src(Qt::MouseEventNotSynthesized) { if (orient == Qt::Vertical) angleD = QPoint(0, delta); @@ -796,7 +798,8 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, QPoint pixelDelta, QPoint angleDelta, int qt4Delta, Qt::Orientation qt4Orientation, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers) : QInputEvent(Wheel, modifiers), p(pos), g(globalPos), pixelD(pixelDelta), - angleD(angleDelta), qt4D(qt4Delta), qt4O(qt4Orientation), mouseState(buttons), ph(Qt::ScrollUpdate) + angleD(angleDelta), qt4D(qt4Delta), qt4O(qt4Orientation), mouseState(buttons), ph(Qt::ScrollUpdate), + src(Qt::MouseEventNotSynthesized) {} /*! -- cgit v1.2.3 From 44357dbe423d430246504d977f4422ed0e2e7a5a Mon Sep 17 00:00:00 2001 From: Kai Pastor Date: Fri, 11 Sep 2015 01:22:14 +0200 Subject: QMacPrintEngine: Really set the printer resolution As already reported in 2009 (Qt 4.6) QPrinter never actually set the printer resolution. This change adds the necessary call to PMPrinterSetOutputResolution (available since OS X 10.5). [ChangeLog][QtPrintSupport][OS X] QMacPrintEngine now really sets the printer resolution. Task-number: QTBUG-7000 Change-Id: I3e851b62e1a7ed78564a8a6fd576b0a18d7eff63 Reviewed-by: Andy Shaw --- src/plugins/platforms/cocoa/qprintengine_mac.mm | 13 +++++++++++-- .../printsupport/kernel/qprinter/tst_qprinter.cpp | 19 ++++++++++++++++++- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm index edd1d656f0..000a9c46c8 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm @@ -470,7 +470,6 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va d->embedFonts = value.toBool(); break; case PPK_Resolution: { - // TODO It appears the old code didn't actually set the resolution??? Can we delete all this??? int bestResolution = 0; int dpi = value.toInt(); int bestDistance = INT_MAX; @@ -486,7 +485,17 @@ void QMacPrintEngine::setProperty(PrintEnginePropertyKey key, const QVariant &va } } } - PMSessionValidatePageFormat(d->session(), d->format(), kPMDontWantBoolean); + PMResolution resolution; + resolution.hRes = resolution.vRes = bestResolution; + if (PMPrinterSetOutputResolution(d->m_printDevice->macPrinter(), d->settings(), &resolution) == noErr) { + // Setting the resolution succeeded. + // Now try to read the actual resolution selected by the OS. + if (PMPrinterGetOutputResolution(d->m_printDevice->macPrinter(), d->settings(), &d->resolution) != noErr) { + // Reading the resolution somehow failed; d->resolution is in undefined state. + // So use the value which was acceptable to PMPrinterSetOutputResolution. + d->resolution = resolution; + } + } break; } case PPK_CollateCopies: diff --git a/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp b/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp index aa72be3ea8..5e7a40d3b5 100644 --- a/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp +++ b/tests/auto/printsupport/kernel/qprinter/tst_qprinter.cpp @@ -1628,7 +1628,24 @@ void tst_QPrinter::resolution() // Test set/get int expected = 333; #ifdef Q_OS_MAC - // Set resolution does nothing on OSX, see QTBUG-7000 + // QMacPrintEngine chooses the closest supported resolution. + const QList all_supported = native.supportedResolutions(); + foreach (int supported, all_supported) { + // Test setting a supported resolution + int requested = supported; + native.setResolution(requested); + QCOMPARE(native.resolution(), requested); + + // Test setting an unsupported resolution + do { + requested += 5; + } while (all_supported.contains(requested)); + native.setResolution(requested); + int result = native.resolution(); + QVERIFY(all_supported.contains(result)); + QVERIFY(qAbs(result - requested) <= qAbs(supported - requested)); + } + expected = native.resolution(); #endif // Q_OS_MAC native.setResolution(expected); -- cgit v1.2.3 From c0963486ce689e778d59dafd26d36d8ef9e3ee74 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 24 Feb 2016 13:13:36 +0100 Subject: QScreen::grabWindow(): Scale the coordinates. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The coordinates need to be scaled before calling QPlatformScreen::grabWindow() On return, set a devicePixelRatio on the pixmap. Adapt the QWidget test to scale the grabbed pixmaps. Fixes pixeltool displaying the wrong part of the screen when High DPI scaling is in effect. Task-number: QTBUG-46615 Change-Id: I12de7df0da669230cf0fae74f4a42d43f061d5ff Reviewed-by: Morten Johan Sørvig --- src/gui/kernel/qscreen.cpp | 15 ++++++++++++++- tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp | 6 ++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/gui/kernel/qscreen.cpp b/src/gui/kernel/qscreen.cpp index 52e7686439..e87f58d735 100644 --- a/src/gui/kernel/qscreen.cpp +++ b/src/gui/kernel/qscreen.cpp @@ -40,6 +40,7 @@ #include #include +#include "qhighdpiscaling_p.h" QT_BEGIN_NAMESPACE @@ -683,7 +684,19 @@ QPixmap QScreen::grabWindow(WId window, int x, int y, int width, int height) qWarning("invoked with handle==0"); return QPixmap(); } - return platformScreen->grabWindow(window, x, y, width, height); + const qreal factor = QHighDpiScaling::factor(this); + if (qFuzzyCompare(factor, 1)) + return platformScreen->grabWindow(window, x, y, width, height); + + const QPoint nativePos = QHighDpi::toNative(QPoint(x, y), factor); + QSize nativeSize(width, height); + if (nativeSize.isValid()) + nativeSize = QHighDpi::toNative(nativeSize, factor); + QPixmap result = + platformScreen->grabWindow(window, nativePos.x(), nativePos.y(), + nativeSize.width(), nativeSize.height()); + result.setDevicePixelRatio(factor); + return result; } #ifndef QT_NO_DEBUG_STREAM diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 8a5250aad4..293689bff3 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -4979,7 +4979,9 @@ static inline QByteArray msgRgbMismatch(unsigned actual, unsigned expected) static QPixmap grabWindow(QWindow *window, int x, int y, int width, int height) { QScreen *screen = window->screen(); - return screen ? screen->grabWindow(window->winId(), x, y, width, height) : QPixmap(); + Q_ASSERT(screen); + QPixmap result = screen->grabWindow(window->winId(), x, y, width, height); + return result.devicePixelRatio() > 1 ? result.scaled(width, height) : result; } #define VERIFY_COLOR(child, region, color) verifyColor(child, region, color, __LINE__) @@ -8505,7 +8507,7 @@ void tst_QWidget::translucentWidget() #ifdef Q_OS_WIN QWidget *desktopWidget = QApplication::desktop()->screen(0); if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA) - widgetSnapshot = qApp->primaryScreen()->grabWindow(desktopWidget->winId(), labelPos.x(), labelPos.y(), label.width(), label.height()); + widgetSnapshot = grabWindow(desktopWidget->windowHandle(), labelPos.x(), labelPos.y(), label.width(), label.height()); else #endif widgetSnapshot = label.grab(QRect(QPoint(0, 0), label.size())); -- cgit v1.2.3 From ea757da43697787cfcd1c01f11bd2b0288c679fe Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 22 Feb 2016 09:42:39 +0100 Subject: QWindowsTheme: Run SHGetFileInfo() in a thread. Windows 10: SHGetFileInfo() (as called by item views on file system models has been observed to trigger a WM_PAINT on the mainwindow for totally obscure reasons, causing a recursive repaint. Suppress this by running it via QThreadPool. Task-number: QTBUG-45298 Task-number: QTBUG-48823 Task-number: QTCREATORBUG-14888 Change-Id: I7479102b9b8fb0771681260298c3d735e66f220f Reviewed-by: Joerg Bornemann --- src/plugins/platforms/windows/qwindowstheme.cpp | 56 ++++++++-- src/plugins/platforms/windows/qwindowstheme.h | 2 + .../platforms/windows/qwindowsthreadpoolrunner.h | 116 +++++++++++++++++++++ src/plugins/platforms/windows/windows.pri | 3 +- 4 files changed, 165 insertions(+), 12 deletions(-) create mode 100644 src/plugins/platforms/windows/qwindowsthreadpoolrunner.h diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp index 887a217b06..ef652e6f98 100644 --- a/src/plugins/platforms/windows/qwindowstheme.cpp +++ b/src/plugins/platforms/windows/qwindowstheme.cpp @@ -122,6 +122,41 @@ static inline QColor getSysColor(int index) return COLORREFToQColor(GetSysColor(index)); } +#ifndef QT_NO_WINCE_SHELLSDK +// QTBUG-48823/Windows 10: SHGetFileInfo() (as called by item views on file system +// models has been observed to trigger a WM_PAINT on the mainwindow. Suppress the +// behavior by running it in a thread. +class ShGetFileInfoFunction +{ +public: + explicit ShGetFileInfoFunction(const wchar_t *fn, DWORD a, SHFILEINFO *i, UINT f, bool *r) : + m_fileName(fn), m_attributes(a), m_flags(f), m_info(i), m_result(r) {} + + void operator()() const { *m_result = SHGetFileInfo(m_fileName, m_attributes, m_info, sizeof(SHFILEINFO), m_flags); } + +private: + const wchar_t *m_fileName; + const DWORD m_attributes; + const UINT m_flags; + SHFILEINFO *const m_info; + bool *m_result; +}; + +static bool shGetFileInfoBackground(QWindowsThreadPoolRunner &r, + const wchar_t *fileName, DWORD attributes, + SHFILEINFO *info, UINT flags, + unsigned long timeOutMSecs = 5000) +{ + bool result = false; + if (!r.run(ShGetFileInfoFunction(fileName, attributes, info, flags, &result), timeOutMSecs)) { + qWarning().noquote() << "ShGetFileInfoBackground() timed out for " + << QString::fromWCharArray(fileName); + return false; + } + return result; +} +#endif // !QT_NO_WINCE_SHELLSDK + // from QStyle::standardPalette static inline QPalette standardPalette() { @@ -690,23 +725,22 @@ QPixmap QWindowsTheme::fileIconPixmap(const QFileInfo &fileInfo, const QSizeF &s } SHFILEINFO info; - unsigned int flags = + const unsigned int flags = #ifndef Q_OS_WINCE SHGFI_ICON|iconSize|SHGFI_SYSICONINDEX|SHGFI_ADDOVERLAYS|SHGFI_OVERLAYINDEX; #else iconSize|SHGFI_SYSICONINDEX; #endif // Q_OS_WINCE - unsigned long val = 0; + + #if !defined(QT_NO_WINCE_SHELLSDK) - if (cacheableDirIcon && useDefaultFolderIcon) { - flags |= SHGFI_USEFILEATTRIBUTES; - val = SHGetFileInfo(L"dummy", - FILE_ATTRIBUTE_DIRECTORY, - &info, sizeof(SHFILEINFO), flags); - } else { - val = SHGetFileInfo(reinterpret_cast(filePath.utf16()), 0, - &info, sizeof(SHFILEINFO), flags); - } + const bool val = cacheableDirIcon && useDefaultFolderIcon + ? shGetFileInfoBackground(m_threadPoolRunner, L"dummy", FILE_ATTRIBUTE_DIRECTORY, + &info, flags | SHGFI_USEFILEATTRIBUTES) + : shGetFileInfoBackground(m_threadPoolRunner, reinterpret_cast(filePath.utf16()), 0, + &info, flags); +#else + const bool val = false; #endif // !QT_NO_WINCE_SHELLSDK // Even if GetFileInfo returns a valid result, hIcon can be empty in some cases diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h index fc004b68c8..cacde98601 100644 --- a/src/plugins/platforms/windows/qwindowstheme.h +++ b/src/plugins/platforms/windows/qwindowstheme.h @@ -34,6 +34,7 @@ #ifndef QWINDOWSTHEME_H #define QWINDOWSTHEME_H +#include "qwindowsthreadpoolrunner.h" #include QT_BEGIN_NAMESPACE @@ -74,6 +75,7 @@ private: static QWindowsTheme *m_instance; QPalette *m_palettes[NPalettes]; QFont *m_fonts[NFonts]; + mutable QWindowsThreadPoolRunner m_threadPoolRunner; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h b/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h new file mode 100644 index 0000000000..0361aa90f5 --- /dev/null +++ b/src/plugins/platforms/windows/qwindowsthreadpoolrunner.h @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSTHREADPOOLRUNNER_H +#define QWINDOWSTHREADPOOLRUNNER_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +/*! + \class QWindowsThreadPoolRunner + \brief Runs a task in the global instance of QThreadPool + + QThreadPool does not provide a method to wait on a single task, so this needs + to be done by using QWaitCondition/QMutex. + + \internal + \ingroup qt-lighthouse-win +*/ +class QWindowsThreadPoolRunner +{ + Q_DISABLE_COPY(QWindowsThreadPoolRunner) + +#ifndef QT_NO_THREAD + template // nested class implementing QRunnable to execute a function. + class Runnable : public QRunnable + { + public: + explicit Runnable(QMutex *m, QWaitCondition *c, RunnableFunction f) + : m_mutex(m), m_condition(c), m_function(f) {} + + void run() Q_DECL_OVERRIDE + { + m_function(); + m_mutex->lock(); + m_condition->wakeAll(); + m_mutex->unlock(); + } + + private: + QMutex *m_mutex; + QWaitCondition *m_condition; + RunnableFunction m_function; + }; // class Runnable + +public: + QWindowsThreadPoolRunner() {} + + template + bool run(Function f, unsigned long timeOutMSecs = 5000) + { + QThreadPool *pool = QThreadPool::globalInstance(); + Q_ASSERT(pool); + Runnable *runnable = new Runnable(&m_mutex, &m_condition, f); + m_mutex.lock(); + pool->start(runnable); + const bool ok = m_condition.wait(&m_mutex, timeOutMSecs); + m_mutex.unlock(); + if (!ok) + pool->cancel(runnable); + return ok; + } + +private: + QMutex m_mutex; + QWaitCondition m_condition; +#else // !QT_NO_THREAD +public: + QWindowsThreadPoolRunner() {} + + template + bool run(Function f, unsigned long /* timeOutMSecs */ = 5000) + { + f(); + return true; + } +#endif // QT_NO_THREAD +}; + +QT_END_NAMESPACE + +#endif // QWINDOWSTHREADPOOLRUNNER_H diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri index 67af5c03ef..eba0593d75 100644 --- a/src/plugins/platforms/windows/windows.pri +++ b/src/plugins/platforms/windows/windows.pri @@ -63,7 +63,8 @@ HEADERS += \ $$PWD/qplatformfunctions_wince.h \ $$PWD/qwindowsnativeimage.h \ $$PWD/qwindowsnativeinterface.h \ - $$PWD/qwindowsopengltester.h + $$PWD/qwindowsopengltester.h \ + $$PWD/qwindowsthreadpoolrunner.h INCLUDEPATH += $$PWD -- cgit v1.2.3 From 827420c4c6d015431fb5207855896d863624ea12 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 25 Feb 2016 12:32:26 +0100 Subject: Windows QPA: Fix scrolling down with mouse wheel. Use GET_WHEEL_DELTA_WPARAM() instead of HIWORD and casting. Fix breakage introduced by b20548f9999d8c111268f3f2287c0801c6c5cbb0 . Change-Id: I11bd97d73c12d72e824e3f769e9c402975f27d48 Reviewed-by: Joerg Bornemann --- src/plugins/platforms/windows/qwindowsmousehandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index 32f8285954..4ed708540c 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -422,7 +422,7 @@ bool QWindowsMouseHandler::translateMouseWheelEvent(QWindow *window, HWND, int delta; if (msg.message == WM_MOUSEWHEEL || msg.message == WM_MOUSEHWHEEL) - delta = HIWORD (msg.wParam); + delta = GET_WHEEL_DELTA_WPARAM(msg.wParam); else delta = int(msg.wParam); -- cgit v1.2.3 From cf846d6a8a0df0f0935f7f1306ab8439309cf6e5 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 25 Feb 2016 10:15:22 +0100 Subject: Fix QHighDpi::fromNative(QRect, QScreen *, QPoint). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Call fromNative() instead of toNative(). Task-number: QTBUG-46615 Change-Id: I1e648a2680126d1f560e71573f7346b053fe676b Reviewed-by: Morten Johan Sørvig --- src/gui/kernel/qhighdpiscaling_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/kernel/qhighdpiscaling_p.h b/src/gui/kernel/qhighdpiscaling_p.h index fac3ae420d..a7b80982af 100644 --- a/src/gui/kernel/qhighdpiscaling_p.h +++ b/src/gui/kernel/qhighdpiscaling_p.h @@ -162,7 +162,7 @@ inline QRect toNative(const QRect &rect, qreal scaleFactor, const QPoint &origin inline QRect fromNative(const QRect &rect, const QScreen *screen, const QPoint &screenOrigin) { - return toNative(rect, QHighDpiScaling::factor(screen), screenOrigin); + return fromNative(rect, QHighDpiScaling::factor(screen), screenOrigin); } inline QRect fromNativeScreenGeometry(const QRect &nativeScreenGeometry, const QScreen *screen) -- cgit v1.2.3 From d1dfcc776fd3bf738d0c6e7125f5bb2c9aecc57e Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 25 Feb 2016 10:01:21 +0100 Subject: Windows QPA: Apply scaling when fixing maximized/frameless geometry. Task-number: QTBUG-8361 Task-number: QTBUG-51327 Change-Id: I590702df8f6313701fe69d0873657c6af53fee16 Reviewed-by: Andy Shaw --- src/plugins/platforms/windows/qwindowswindow.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index e2f5885047..c0892feabe 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -2089,14 +2089,15 @@ void QWindowsWindow::getSizeHints(MINMAXINFO *mmi) const // Documentation of MINMAXINFO states that it will only work for the primary screen if (screen && screen == QGuiApplication::primaryScreen()) { - mmi->ptMaxSize.y = screen->availableGeometry().height(); + const QRect availableGeometry = QHighDpi::toNativePixels(screen->availableGeometry(), screen); + mmi->ptMaxSize.y = availableGeometry.height(); // Width, because you can have the taskbar on the sides too. - mmi->ptMaxSize.x = screen->availableGeometry().width(); + mmi->ptMaxSize.x = availableGeometry.width(); // If you have the taskbar on top, or on the left you don't want it at (0,0): - mmi->ptMaxPosition.x = screen->availableGeometry().x(); - mmi->ptMaxPosition.y = screen->availableGeometry().y(); + mmi->ptMaxPosition.x = availableGeometry.x(); + mmi->ptMaxPosition.y = availableGeometry.y(); } else if (!screen){ qWarning() << "window()->screen() returned a null screen"; } -- cgit v1.2.3 From 7984f24b1fcb9cc2785d4659d877ae2aaf377ac1 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 22 Feb 2016 16:46:21 +0100 Subject: Fix potential crash in QWindowsIA2Accessible::QueryInterface(). QWindowsIA2Accessible does not implement IAccessibleRelation (found when replacing the C-style casts by static_cast<>). Remove the corresponding branch. Task-number: QTBUG-50804 Change-Id: I80901634044f85e413666f34b91be2e6ad70da91 Reviewed-by: Joerg Bornemann --- src/plugins/platforms/windows/accessible/iaccessible2.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp index 9531272a07..e34c86158d 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp +++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp @@ -249,8 +249,6 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryInterface(REFIID id, LPVOI //*iface = (IAccessibleHypertext*)this; } else if (id == IID_IAccessibleImage) { //*iface = (IAccessibleImage*)this; - } else if (id == IID_IAccessibleRelation) { - *iface = (IAccessibleRelation*)this; } else if (id == IID_IAccessibleTable) { //*iface = (IAccessibleTable*)this; // not supported } else if (id == IID_IAccessibleTable2) { -- cgit v1.2.3 From 403b7d4a21bba14bc059ad0c84a7614f221255e9 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 22 Feb 2016 16:56:07 +0100 Subject: Windows Accessibility: Refactor code creating COM arrays. Introduce a convenience function for allocating arrays and use algorithms. Task-number: QTBUG-50804 Change-Id: Iead75f8297923fd13efcfc7987f76262777d074b Reviewed-by: Joerg Bornemann --- .../platforms/windows/accessible/iaccessible2.cpp | 47 +++++++++++++--------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp index e34c86158d..abca91a7db 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp +++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp @@ -41,8 +41,16 @@ #include #include +#include + QT_BEGIN_NAMESPACE +template +static inline T *coTaskMemAllocArray(int size) +{ + return static_cast(::CoTaskMemAlloc(sizeof(T) * size_t(size))); +} + /**************************************************************\ * AccessibleApplication * **************************************************************/ @@ -591,9 +599,9 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_keyBinding(long actionIndex numBindings = keyBindings.count(); if (numBindings > 0) { // The IDL documents that the client must free with CoTaskMemFree - arrayOfBindingsToReturn = (BSTR*)::CoTaskMemAlloc(sizeof(BSTR) * numBindings); - for (int i = 0; i < numBindings; ++i) - arrayOfBindingsToReturn[i] = QStringToBSTR(keyBindings.at(i)); + arrayOfBindingsToReturn = coTaskMemAllocArray(numBindings); + std::transform(keyBindings.constBegin(), keyBindings.constEnd(), + arrayOfBindingsToReturn, QStringToBSTR); } } *keyBindings = arrayOfBindingsToReturn; @@ -970,12 +978,13 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedColumns(long **sele if (QAccessibleTableInterface *tableIface = tableInterface()) { const QList selectedIndices = tableIface->selectedColumns(); - const int &count = selectedIndices.count(); - long *selected = (count ? (long*)::CoTaskMemAlloc(sizeof(long) * count) : (long*)0); - for (int i = 0; i < count; ++i) - selected[i] = selectedIndices.at(i); - *selectedColumns = selected; + const int count = selectedIndices.count(); *nColumns = count; + *selectedColumns = Q_NULLPTR; + if (count) { + *selectedColumns = coTaskMemAllocArray(count); + std::copy(selectedIndices.constBegin(), selectedIndices.constEnd(), *selectedColumns); + } return count ? S_OK : S_FALSE; } return E_FAIL; @@ -991,12 +1000,13 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedRows(long **selecte if (QAccessibleTableInterface *tableIface = tableInterface()) { const QList selectedIndices = tableIface->selectedRows(); - const int &count = selectedIndices.count(); - long *selected = (count ? (long*)::CoTaskMemAlloc(sizeof(long) * count) : (long*)0); - for (int i = 0; i < count; ++i) - selected[i] = selectedIndices.at(i); - *selectedRows = selected; + const int count = selectedIndices.count(); *nRows = count; + *selectedRows = Q_NULLPTR; + if (count) { + *selectedRows = coTaskMemAllocArray(count); + std::copy(selectedIndices.constBegin(), selectedIndices.constEnd(), *selectedRows); + } return count ? S_OK : S_FALSE; } return E_FAIL; @@ -1648,12 +1658,13 @@ HRESULT QWindowsIA2Accessible::wrapListOfCells(const QList(count); + std::transform(inputCells.constBegin(), inputCells.constEnd(), + *outputAccessibles, QWindowsAccessibility::wrap); + } return count > 0 ? S_OK : S_FALSE; } -- cgit v1.2.3 From 4905bf06549ce33250b13e837d192e92bffffcdb Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 22 Feb 2016 16:58:38 +0100 Subject: Windows Accessibility: Fix warnings as shown by Qt Creator's Clang based code model. Introduce C++ casts and add some conversions. Where possible, increase const-correctness. Remove trivial conversion function BSTRToQString(). Task-number: QTBUG-50804 Change-Id: I1820d4693db8bc0dfa6c4a5fecd768cf64a4405c Reviewed-by: Joerg Bornemann --- .../platforms/windows/accessible/comutils.cpp | 18 +++--- .../platforms/windows/accessible/comutils.h | 7 +-- .../platforms/windows/accessible/iaccessible2.cpp | 71 +++++++++++++--------- .../windows/accessible/qwindowsaccessibility.cpp | 8 +-- .../windows/accessible/qwindowsmsaaaccessible.cpp | 20 +++--- 5 files changed, 65 insertions(+), 59 deletions(-) diff --git a/src/plugins/platforms/windows/accessible/comutils.cpp b/src/plugins/platforms/windows/accessible/comutils.cpp index 94e56e8b73..acfab97899 100644 --- a/src/plugins/platforms/windows/accessible/comutils.cpp +++ b/src/plugins/platforms/windows/accessible/comutils.cpp @@ -58,15 +58,15 @@ static DATE QDateTimeToDATE(const QDateTime &dt) QDate date = dt.date(); QTime time = dt.time(); if (date.isValid() && !date.isNull()) { - stime.wDay = date.day(); - stime.wMonth = date.month(); - stime.wYear = date.year(); + stime.wDay = WORD(date.day()); + stime.wMonth = WORD(date.month()); + stime.wYear = WORD(date.year()); } if (time.isValid() && !time.isNull()) { - stime.wMilliseconds = time.msec(); - stime.wSecond = time.second(); - stime.wMinute = time.minute(); - stime.wHour = time.hour(); + stime.wMilliseconds = WORD(time.msec()); + stime.wSecond = WORD(time.second()); + stime.wMinute = WORD(time.minute()); + stime.wHour = WORD(time.hour()); } double vtime; @@ -92,8 +92,8 @@ bool QVariant2VARIANT(const QVariant &var, VARIANT &arg, const QByteArray &typeN proptype = QVariant::Double; } if (proptype != QVariant::Invalid && proptype != QVariant::UserType && proptype != qvar.type()) { - if (qvar.canConvert(proptype)) - qvar.convert(proptype); + if (qvar.canConvert(int(proptype))) + qvar.convert(int(proptype)); else qvar = QVariant(proptype); } diff --git a/src/plugins/platforms/windows/accessible/comutils.h b/src/plugins/platforms/windows/accessible/comutils.h index 113d79d473..d5476aa6e8 100644 --- a/src/plugins/platforms/windows/accessible/comutils.h +++ b/src/plugins/platforms/windows/accessible/comutils.h @@ -47,14 +47,9 @@ class QVariant; // Originally QVariantToVARIANT copied from ActiveQt - renamed to avoid conflicts in static builds. bool QVariant2VARIANT(const QVariant &var, VARIANT &arg, const QByteArray &typeName, bool out); -inline QString BSTRToQString(const BSTR &bstr) -{ - return QString((QChar*)bstr); -} - inline BSTR QStringToBSTR(const QString &str) { - return SysAllocStringLen((OLECHAR*)str.unicode(), str.length()); + return SysAllocStringLen(reinterpret_cast(str.unicode()), UINT(str.length())); } QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp index abca91a7db..7c0b0370b3 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp +++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp @@ -60,7 +60,7 @@ HRESULT STDMETHODCALLTYPE AccessibleApplication::QueryInterface(REFIID id, LPVOI *iface = 0; if (id == IID_IUnknown) { qCDebug(lcQpaAccessibility) << "AccessibleApplication::QI(): IID_IUnknown"; - *iface = (IUnknown*)this; + *iface = static_cast(this); } else if (id == IID_IAccessibleApplication) { qCDebug(lcQpaAccessibility) << "AccessibleApplication::QI(): IID_IAccessibleApplication"; *iface = static_cast(this); @@ -130,7 +130,7 @@ HRESULT STDMETHODCALLTYPE AccessibleRelation::QueryInterface(REFIID id, LPVOID * { *iface = 0; if (id == IID_IUnknown || id == IID_IAccessibleRelation) - *iface = (IUnknown*)this; + *iface = static_cast(this); if (*iface) { AddRef(); @@ -208,7 +208,7 @@ HRESULT STDMETHODCALLTYPE AccessibleRelation::get_targets( /* [retval][out] */ long *nTargets) { - const int numTargets = qMin((int)maxTargets, m_targets.count()); + const int numTargets = qMin(int(maxTargets), m_targets.count()); for (int i = 0; i < numTargets; ++i) { QAccessibleInterface *iface = m_targets.at(i); IAccessible *iacc = QWindowsAccessibility::wrap(iface); @@ -237,40 +237,40 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryInterface(REFIID id, LPVOI HRESULT hr = QWindowsMsaaAccessible::QueryInterface(id, iface); if (!SUCCEEDED(hr)) { if (id == IID_IServiceProvider) { - *iface = (IServiceProvider*)this; + *iface = static_cast(this); } else if (id == IID_IAccessible2) { - *iface = (IAccessible2*)this; + *iface = static_cast(this); } else if (id == IID_IAccessibleAction) { if (accessible->actionInterface()) - *iface = (IAccessibleAction*)this; + *iface = static_cast(this); } else if (id == IID_IAccessibleComponent) { - *iface = (IAccessibleComponent*)this; + *iface = static_cast(this); } else if (id == IID_IAccessibleEditableText) { if (accessible->editableTextInterface() || accessible->role() == QAccessible::EditableText) { - *iface = (IAccessibleEditableText*)this; + *iface = static_cast(this); } } else if (id == IID_IAccessibleHyperlink) { - //*iface = (IAccessibleHyperlink*)this; + //*iface = static_cast(this); } else if (id == IID_IAccessibleHypertext) { - //*iface = (IAccessibleHypertext*)this; + //*iface = static_cast(this); } else if (id == IID_IAccessibleImage) { - //*iface = (IAccessibleImage*)this; + //*iface = static_cast(this); } else if (id == IID_IAccessibleTable) { - //*iface = (IAccessibleTable*)this; // not supported + //*iface = static_cast(this); // not supported } else if (id == IID_IAccessibleTable2) { if (accessible->tableInterface()) - *iface = (IAccessibleTable2*)this; + *iface = static_cast(this); } else if (id == IID_IAccessibleTableCell) { if (accessible->tableCellInterface()) - *iface = (IAccessibleTableCell*)this; + *iface = static_cast(this); } else if (id == IID_IAccessibleText) { if (accessible->textInterface()) - *iface = (IAccessibleText*)this; + *iface = static_cast(this); } else if (id == IID_IAccessibleValue) { if (accessible->valueInterface()) - *iface = (IAccessibleValue*)this; + *iface = static_cast(this); } if (*iface) { AddRef(); @@ -674,7 +674,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_foreground(IA2Color *foregr return E_FAIL; // IA2Color is a typedef for long - *foreground = (IA2Color)accessible->foregroundColor().rgb(); + *foreground = static_cast(accessible->foregroundColor().rgb()); return S_OK; } @@ -686,7 +686,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_background(IA2Color *backgr return E_FAIL; // IA2Color is a typedef for long - *background = (IA2Color)accessible->backgroundColor().rgb(); + *background = static_cast(accessible->backgroundColor().rgb()); return S_OK; } @@ -760,7 +760,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::insertText(long offset, BSTR *t { QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - const QString txt(BSTRToQString(*text)); + const QString txt = QString::fromWCharArray(*text); if (QAccessibleEditableTextInterface *editableTextIface = accessible->editableTextInterface()) editableTextIface->insertText(offset, txt); else @@ -805,7 +805,7 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::replaceText(long startOffset, l { QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); - const QString txt(BSTRToQString(*text)); + const QString txt = QString::fromWCharArray(*text); if (QAccessibleEditableTextInterface *editableTextIface = accessible->editableTextInterface()) editableTextIface->replaceText(startOffset, endOffset, txt); else @@ -1206,10 +1206,10 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_rowColumnExtents(long *row, if (!accessible || !tableCellInterface()) return E_FAIL; - *row = (long)tableCellInterface()->rowIndex(); - *column = (long)tableCellInterface()->columnIndex(); - *rowExtents = (long)tableCellInterface()->rowExtent(); - *columnExtents = (long)tableCellInterface()->columnExtent(); + *row = tableCellInterface()->rowIndex(); + *column = tableCellInterface()->columnIndex(); + *rowExtents = tableCellInterface()->rowExtent(); + *columnExtents = tableCellInterface()->columnExtent(); *isSelected = tableCellInterface()->isSelected(); return S_OK; } @@ -1250,7 +1250,8 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_attributes(long offset, QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleTextInterface *text = textInterface()) { - const QString attrs = text->attributes(offset, (int*)startOffset, (int*)endOffset); + const QString attrs = text->attributes(offset, reinterpret_cast(startOffset), + reinterpret_cast(endOffset)); *textAttributes = QStringToBSTR(attrs); return S_OK; } @@ -1322,7 +1323,8 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selection(long selectionInd QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleTextInterface *text = textInterface()) { - text->selection(selectionIndex, (int*)startOffset, (int*)endOffset); + text->selection(selectionIndex, reinterpret_cast(startOffset), + reinterpret_cast(endOffset)); return S_OK; } return E_FAIL; @@ -1354,7 +1356,10 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textBeforeOffset(long offse QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleTextInterface *textIface = textInterface()) { - const QString txt = textIface->textBeforeOffset(offset, (QAccessible::TextBoundaryType)boundaryType, (int*)startOffset, (int*)endOffset); + const QString txt = + textIface->textBeforeOffset(offset, static_cast(boundaryType), + reinterpret_cast(startOffset), + reinterpret_cast(endOffset)); if (!txt.isEmpty()) { *text = QStringToBSTR(txt); return S_OK; @@ -1374,7 +1379,10 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textAfterOffset( QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleTextInterface *textIface = textInterface()) { - const QString txt = textIface->textAfterOffset(offset, (QAccessible::TextBoundaryType)boundaryType, (int*)startOffset, (int*)endOffset); + const QString txt = + textIface->textAfterOffset(offset, static_cast(boundaryType), + reinterpret_cast(startOffset), + reinterpret_cast(endOffset)); if (!txt.isEmpty()) { *text = QStringToBSTR(txt); return S_OK; @@ -1393,7 +1401,10 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_textAtOffset(long offset, QAccessibleInterface *accessible = accessibleInterface(); accessibleDebugClientCalls(accessible); if (QAccessibleTextInterface *textIface = textInterface()) { - const QString txt = textIface->textAtOffset(offset, (QAccessible::TextBoundaryType)boundaryType, (int*)startOffset, (int*)endOffset); + const QString txt = + textIface->textAtOffset(offset, static_cast(boundaryType), + reinterpret_cast(startOffset), + reinterpret_cast(endOffset)); if (!txt.isEmpty()) { *text = QStringToBSTR(txt); return S_OK; @@ -1632,7 +1643,7 @@ HRESULT QWindowsIA2Accessible::getRelationsHelper(IAccessibleRelation **relation QList keys = relationMap.keys(); const int numRelations = keys.count(); if (relations) { - for (int i = startIndex; i < qMin(startIndex + (int)maxRelations, numRelations); ++i) { + for (int i = startIndex; i < qMin(startIndex + int(maxRelations), numRelations); ++i) { QAccessible::Relation relation = keys.at(i); QList targets = relationMap.values(relation); AccessibleRelation *rel = new AccessibleRelation(targets, relation); diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp index cdadb070a5..3e96895bf9 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp +++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp @@ -167,7 +167,7 @@ void QWindowsAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event) QPlatformNativeInterface *platform = QGuiApplication::platformNativeInterface(); if (!window->handle()) // Called before show(), no native window yet. return; - HWND hWnd = (HWND)platform->nativeResourceForWindow("handle", window); + const HWND hWnd = reinterpret_cast(platform->nativeResourceForWindow("handle", window)); if (event->type() != QAccessible::MenuCommand && // MenuCommand is faked event->type() != QAccessible::ObjectDestroyed) { @@ -214,7 +214,7 @@ IAccessible *QWindowsAccessibility::wrap(QAccessibleInterface *acc) QWindowsIA2Accessible *wacc = new QWindowsIA2Accessible(acc); # endif IAccessible *iacc = 0; - wacc->QueryInterface(IID_IAccessible, (void**)&iacc); + wacc->QueryInterface(IID_IAccessible, reinterpret_cast(&iacc)); return iacc; #endif // defined(Q_OS_WINCE) } @@ -224,7 +224,7 @@ bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, W #if !defined(Q_OS_WINCE) if (static_cast(lParam) == static_cast(UiaRootObjectId)) { /* For UI Automation */ - } else if ((DWORD)lParam == DWORD(OBJID_CLIENT)) { + } else if (DWORD(lParam) == DWORD(OBJID_CLIENT)) { // Start handling accessibility internally QGuiApplicationPrivate::platformIntegration()->accessibility()->setActive(true); // Ignoring all requests while starting up @@ -238,7 +238,7 @@ bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, W if (!oleaccChecked) { oleaccChecked = true; - ptrLresultFromObject = (PtrLresultFromObject)QSystemLibrary::resolve(QLatin1String("oleacc"), "LresultFromObject"); + ptrLresultFromObject = reinterpret_cast(QSystemLibrary::resolve(QLatin1String("oleacc"), "LresultFromObject")); } if (ptrLresultFromObject) { diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp index 2189938248..4ecf78dbf6 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp +++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp @@ -94,9 +94,9 @@ HRESULT STDMETHODCALLTYPE QWindowsEnumerate::QueryInterface(REFIID id, LPVOID *i { *iface = 0; if (id == IID_IUnknown) - *iface = (IUnknown*)this; + *iface = static_cast(this); else if (id == IID_IEnumVARIANT) - *iface = (IEnumVARIANT*)this; + *iface = static_cast(this); if (*iface) { AddRef(); @@ -144,13 +144,13 @@ HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Next(unsigned long celt, VARIANT F ULONG l; for (l = 0; l < celt; l++) { VariantInit(&rgVar[l]); - if ((current+1) > (ULONG)array.size()) { + if (current + 1 > ULONG(array.size())) { *pCeltFetched = l; return S_FALSE; } rgVar[l].vt = VT_I4; - rgVar[l].lVal = array[(int)current]; + rgVar[l].lVal = array[int(current)]; ++current; } *pCeltFetched = l; @@ -166,8 +166,8 @@ HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Reset() HRESULT STDMETHODCALLTYPE QWindowsEnumerate::Skip(unsigned long celt) { current += celt; - if (current > (ULONG)array.size()) { - current = array.size(); + if (current > ULONG(array.size())) { + current = ULONG(array.size()); return S_FALSE; } return S_OK; @@ -195,13 +195,13 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::QueryInterface(REFIID id, LPVO << strIID << ", iface:" << accessibleInterface(); } if (id == IID_IUnknown) { - *iface = (IUnknown*)(IDispatch*)this; + *iface = static_cast(static_cast(this)); } else if (id == IID_IDispatch) { - *iface = (IDispatch*)this; + *iface = static_cast(this); } else if (id == IID_IAccessible) { - *iface = (IAccessible*)this; + *iface = static_cast(this); } else if (id == IID_IOleWindow) { - *iface = (IOleWindow*)this; + *iface = static_cast(this); } if (*iface) { -- cgit v1.2.3 From c320d5221f166d3657771ae55585cba051f8caef Mon Sep 17 00:00:00 2001 From: Kai Koehne Date: Thu, 18 Feb 2016 13:20:24 +0100 Subject: Win: Prevent crash in qt_message_fatal() The source argument can be nullptr, e.g. if debug information has been stripped out. Task-number: QTBUG-51195 Change-Id: Ie229c82278c420200cad33c19e8c3f52ab7f12c3 Reviewed-by: Marc Mutz --- src/corelib/global/qlogging.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index 20c31f7ef8..e629e16e8d 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -250,10 +250,11 @@ static inline void convert_to_wchar_t_elided(wchar_t *d, size_t space, const cha if (len + 1 > space) { const size_t skip = len - space + 4; // 4 for "..." + '\0' s += skip; + len -= skip; for (int i = 0; i < 3; ++i) *d++ = L'.'; } - while (*s) + while (len--) *d++ = *s++; *d++ = 0; } -- cgit v1.2.3 From 0a8fd9c620adfc5dd38f41fcd14537296fde13b6 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Fri, 26 Feb 2016 01:25:29 +0100 Subject: tst_qguimetatype::flags(): port to QTypeInfoQuery QTypeInfoQuery was introduced for 5.6 to decouple isStatic and isRelocatable so old code continues to work. But since this test still uses !isStatic to mean trivially-relocatable, it will fail as soon as one of the checked types is marked as Q_RELOCATABLE_TYPE instead of Q_MOVABLE_TYPE. Incidentally, such a change is in the pipeline for Qt 5.7/5.8, so fix the test by porting to QTypeInfoQuery. Do this in 5.6, because that's when QTypeInfoQuery was introduced. Change-Id: I06f815f26ca9b430e124c4a2f8de2a729999762b Reviewed-by: Olivier Goffart (Woboq GmbH) --- tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp b/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp index d8709baa18..73a2f83bac 100644 --- a/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp +++ b/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp @@ -346,11 +346,11 @@ struct TypeAlignment void tst_QGuiMetaType::flags_data() { QTest::addColumn("type"); - QTest::addColumn("isMovable"); + QTest::addColumn("isRelocatable"); QTest::addColumn("isComplex"); #define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \ - QTest::newRow(#RealType) << MetaTypeId << bool(!QTypeInfo::isStatic) << bool(QTypeInfo::isComplex); + QTest::newRow(#RealType) << MetaTypeId << bool(QTypeInfoQuery::isRelocatable) << bool(QTypeInfoQuery::isComplex); QT_FOR_EACH_STATIC_GUI_CLASS(ADD_METATYPE_TEST_ROW) #undef ADD_METATYPE_TEST_ROW } @@ -358,12 +358,12 @@ QT_FOR_EACH_STATIC_GUI_CLASS(ADD_METATYPE_TEST_ROW) void tst_QGuiMetaType::flags() { QFETCH(int, type); - QFETCH(bool, isMovable); + QFETCH(bool, isRelocatable); QFETCH(bool, isComplex); QCOMPARE(bool(QMetaType::typeFlags(type) & QMetaType::NeedsConstruction), isComplex); QCOMPARE(bool(QMetaType::typeFlags(type) & QMetaType::NeedsDestruction), isComplex); - QCOMPARE(bool(QMetaType::typeFlags(type) & QMetaType::MovableType), isMovable); + QCOMPARE(bool(QMetaType::typeFlags(type) & QMetaType::MovableType), isRelocatable); } -- cgit v1.2.3 From 45ae0cb780c1c11eddc3adb5d09c1d95b188b238 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 12 Jan 2016 15:43:22 +0100 Subject: Remove a mis-placed QSKIP(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It made us skip the rest of the test, not just the small set of sub-tests that were conditioned by the if () in whose else it sat. Change-Id: I5e914e0aeb9d5ba44b21966d071aaccbc590365d Reviewed-by: Jędrzej Nowacki --- tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp index f6f1c05814..35c278da0e 100644 --- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp @@ -718,8 +718,6 @@ void tst_QDateTime::fromMSecsSinceEpoch() QCOMPARE(dtLocal.toLocalTime(), cet); QCOMPARE(dtUtc.toLocalTime(), cet); QCOMPARE(dtOffset.toLocalTime(), cet); - } else { - QSKIP("You must test using Central European (CET/CEST) time zone, e.g. TZ=Europe/Oslo"); } // LocalTime will overflow for max -- cgit v1.2.3 From 9f134750a1ab677cfba4f42fbf72208405e04b84 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 23 Feb 2016 15:26:49 +0100 Subject: QPlatformWindow::screenForGeometry(): Do not call mapToGlobal() on top level geometry. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use mapToGlobal() only for foreign windows passing relative coordinates. Amend change 9915630d0886434e8984904b1cadedc81dc78ca0. Task-number: QTBUG-50206 Task-number: QTBUG-51320 Change-Id: Idee60cc8ea8004c0355ce78a00f807798836b49c Reviewed-by: Morten Johan Sørvig --- src/gui/kernel/qplatformwindow.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp index 04532e82aa..9f2c6af51f 100644 --- a/src/gui/kernel/qplatformwindow.cpp +++ b/src/gui/kernel/qplatformwindow.cpp @@ -486,8 +486,9 @@ QPlatformScreen *QPlatformWindow::screenForGeometry(const QRect &newGeometry) co QPlatformScreen *fallback = currentScreen; // QRect::center can return a value outside the rectangle if it's empty. // Apply mapToGlobal() in case it is a foreign/embedded window. - const QPoint center = - mapToGlobal(newGeometry.isEmpty() ? newGeometry.topLeft() : newGeometry.center()); + QPoint center = newGeometry.isEmpty() ? newGeometry.topLeft() : newGeometry.center(); + if (window()->type() == Qt::ForeignWindow) + center = mapToGlobal(center - newGeometry.topLeft()); if (!parent() && currentScreen && !currentScreen->geometry().contains(center)) { Q_FOREACH (QPlatformScreen* screen, currentScreen->virtualSiblings()) { -- cgit v1.2.3 From c3761bf6a74a7ed0dee0e256794672fb73d3276d Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 26 Feb 2016 15:58:09 +0100 Subject: tst_QDialog::snapToDefaultButton(): Do not check on exact cursor position unless hint is set. Given the flakyness of cursor positioning, loosen the check to only verify that the cursor is outside the window. The hint is only active on Windows depending on a system setting. Task-number: QTBUG-51516 Change-Id: I474d251cc41e68f182baf8dba84eaf38d914d7ee Reviewed-by: Simon Hausmann --- tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp | 26 ++++++++++++---------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp index 37afa7f0a5..438884df33 100644 --- a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp +++ b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp @@ -560,6 +560,11 @@ void tst_QDialog::reject() QCOMPARE(dialog.called, 4); } +static QByteArray formatPoint(QPoint p) +{ + return QByteArray::number(p.x()) + ", " + QByteArray::number(p.y()); +} + void tst_QDialog::snapToDefaultButton() { #ifdef QT_NO_CURSOR @@ -568,9 +573,9 @@ void tst_QDialog::snapToDefaultButton() if (!QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive)) QSKIP("Wayland: Wayland does not support setting the cursor position."); - QPoint topLeftPos = QApplication::desktop()->availableGeometry().topLeft(); - topLeftPos = QPoint(topLeftPos.x() + 100, topLeftPos.y() + 100); - QPoint startingPos(topLeftPos.x() + 250, topLeftPos.y() + 250); + const QRect dialogGeometry(QApplication::desktop()->availableGeometry().topLeft() + + QPoint(100, 100), QSize(200, 200)); + const QPoint startingPos = dialogGeometry.bottomRight() + QPoint(100, 100); QCursor::setPos(startingPos); #ifdef Q_OS_OSX // On OS X we use CGEventPost to move the cursor, it needs at least @@ -581,17 +586,14 @@ void tst_QDialog::snapToDefaultButton() QDialog dialog; QPushButton *button = new QPushButton(&dialog); button->setDefault(true); - dialog.setGeometry(QRect(topLeftPos, QSize(200, 200))); + dialog.setGeometry(dialogGeometry); dialog.show(); QVERIFY(QTest::qWaitForWindowExposed(&dialog)); - if (const QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme()) { - if (theme->themeHint(QPlatformTheme::DialogSnapToDefaultButton).toBool()) { - QPoint localPos = button->mapFromGlobal(QCursor::pos()); - QVERIFY(button->rect().contains(localPos)); - } else { - QCOMPARE(startingPos, QCursor::pos()); - } - } + const QPoint localPos = button->mapFromGlobal(QCursor::pos()); + if (QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::DialogSnapToDefaultButton).toBool()) + QVERIFY2(button->rect().contains(localPos), formatPoint(localPos).constData()); + else + QVERIFY2(!button->rect().contains(localPos), formatPoint(localPos).constData()); #endif // !QT_NO_CURSOR } -- cgit v1.2.3 From a17a7d37c2d9a77446911a1836b9f511be7c9934 Mon Sep 17 00:00:00 2001 From: Boris Pek Date: Thu, 25 Feb 2016 01:01:37 +0300 Subject: Update QMAKE_LIB in win32-g++ mkspec `ar' tool from latest binutils shows warning: ar error: `u' modifier ignored since `D' is the default (see `U') Warning message includes word "error" so QtCreator processes it as error in UI. `ar' command-line option `u' might be dropped safely because it is unnecessary. Option `c' is added to suppress extra `ar' warnings. Other build systems are also affected. For example, automake: https://bugzilla.redhat.com/1155273 Change-Id: Ia378b720503d93b0c0c12ae7a5f38f4d7c32eee5 Reviewed-by: Oswald Buddenhagen --- mkspecs/win32-g++/qmake.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkspecs/win32-g++/qmake.conf b/mkspecs/win32-g++/qmake.conf index 2b9eab3e3d..f6828f68ea 100644 --- a/mkspecs/win32-g++/qmake.conf +++ b/mkspecs/win32-g++/qmake.conf @@ -105,7 +105,7 @@ QMAKE_LIBS_COMPAT = -ladvapi32 -lshell32 -lcomdlg32 -luser32 -lgdi32 -lws2 QMAKE_LIBS_QT_ENTRY = -lmingw32 -lqtmain QMAKE_IDL = midl -QMAKE_LIB = $${CROSS_COMPILE}ar -ru +QMAKE_LIB = $${CROSS_COMPILE}ar -rc QMAKE_RC = $${CROSS_COMPILE}windres QMAKE_STRIP = $${CROSS_COMPILE}strip -- cgit v1.2.3 From f253f4c3310655933266f62e90f46fd12b5c49e4 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Wed, 10 Feb 2016 11:30:33 -0800 Subject: Track target widget when wheel events are received This issue is reproducible on OS X when using a Magic Mouse or a combination of Magic Trackpad and regular mouse. In these cases it's possible to start a scrolling gesture on one widget and move the mouse cursor over another widget. Although we send the wheel event phase information, we never made any use of it. This means that a widget would start scrolling even though it never received a ScrollBegin event. In this patch, we make sure the scrolling cycle is respected and that once a widget starts scrolling, it'll be recieving all the wheel events until a ScrollEnd event reaches the application. For those input devices not supporting a proper phase cycle, we introduce a new (undocumented) phase value, NoScrollPhase. If the wheel event phase is NoScrollPhase, then we ignore the current scroll widget and proceed as usual. This value is the default for wheel events. It's up to the platform plugin to set the proper phase value according to the data received from the OS. Finally, we fix a few of QWheelEvent constructors to properly initialize the phase and source properties. Task-number: QTBUG-50199 Change-Id: I3773729a9c757e2d2fcc5100dcd79f0ed26cb808 Reviewed-by: Shawn Rutledge --- src/corelib/global/qnamespace.h | 3 +- src/corelib/global/qnamespace.qdoc | 2 + src/gui/kernel/qevent.cpp | 6 +-- src/gui/kernel/qevent.h | 2 + src/gui/kernel/qwindowsysteminterface.h | 12 +++++- src/gui/kernel/qwindowsysteminterface_p.h | 2 +- src/plugins/platforms/cocoa/qnsview.mm | 2 + src/widgets/kernel/qapplication.cpp | 68 +++++++++++++++++++++++-------- src/widgets/kernel/qapplication_p.h | 1 + 9 files changed, 74 insertions(+), 24 deletions(-) diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index c4f5415a01..4d0bd6903d 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -1626,7 +1626,8 @@ public: }; enum ScrollPhase { - ScrollBegin = 1, + NoScrollPhase = 0, // Make public in 5.7 or asap + ScrollBegin, ScrollUpdate, ScrollEnd }; diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 7c5263ddbd..527bded3c2 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -3070,6 +3070,8 @@ This enum describes the phase of scrolling. + \omitvalue NoScrollPhase The input device doesn't support scroll phase. + \value ScrollBegin Scrolling is about to begin, but the scrolling distance did not yet change. diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 4f368e1db3..8abec2b05e 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -727,7 +727,7 @@ QWheelEvent::QWheelEvent(const QPointF &pos, int delta, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::Orientation orient) : QInputEvent(Wheel, modifiers), p(pos), qt4D(delta), qt4O(orient), mouseState(buttons), - ph(Qt::ScrollUpdate), src(Qt::MouseEventNotSynthesized) + ph(Qt::NoScrollPhase), src(Qt::MouseEventNotSynthesized) { g = QCursor::pos(); if (orient == Qt::Vertical) @@ -762,7 +762,7 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, int delta Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, Qt::Orientation orient) : QInputEvent(Wheel, modifiers), p(pos), g(globalPos), qt4D(delta), qt4O(orient), mouseState(buttons), - ph(Qt::ScrollUpdate), src(Qt::MouseEventNotSynthesized) + ph(Qt::NoScrollPhase), src(Qt::MouseEventNotSynthesized) { if (orient == Qt::Vertical) angleD = QPoint(0, delta); @@ -798,7 +798,7 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos, QPoint pixelDelta, QPoint angleDelta, int qt4Delta, Qt::Orientation qt4Orientation, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers) : QInputEvent(Wheel, modifiers), p(pos), g(globalPos), pixelD(pixelDelta), - angleD(angleDelta), qt4D(qt4Delta), qt4O(qt4Orientation), mouseState(buttons), ph(Qt::ScrollUpdate), + angleD(angleDelta), qt4D(qt4Delta), qt4O(qt4Orientation), mouseState(buttons), ph(Qt::NoScrollPhase), src(Qt::MouseEventNotSynthesized) {} diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index ed2deda9a0..b407663338 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -219,6 +219,8 @@ protected: uint ph : 2; uint src: 2; int reserved : 28; + + friend class QApplication; }; #endif diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h index a27c68649e..20d560f82e 100644 --- a/src/gui/kernel/qwindowsysteminterface.h +++ b/src/gui/kernel/qwindowsysteminterface.h @@ -94,8 +94,16 @@ public: quint32 nativeModifiers, const QString& text = QString(), bool autorep = false, ushort count = 1, bool tryShortcutOverride = true); - static void handleWheelEvent(QWindow *w, const QPointF & local, const QPointF & global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods = Qt::NoModifier, Qt::ScrollPhase phase = Qt::ScrollUpdate, Qt::MouseEventSource source = Qt::MouseEventNotSynthesized); - static void handleWheelEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, QPoint pixelDelta, QPoint angleDelta, Qt::KeyboardModifiers mods = Qt::NoModifier, Qt::ScrollPhase phase = Qt::ScrollUpdate, Qt::MouseEventSource source = Qt::MouseEventNotSynthesized); + static void handleWheelEvent(QWindow *w, const QPointF & local, const QPointF & global, + QPoint pixelDelta, QPoint angleDelta, + Qt::KeyboardModifiers mods = Qt::NoModifier, + Qt::ScrollPhase phase = Qt::NoScrollPhase, + Qt::MouseEventSource source = Qt::MouseEventNotSynthesized); + static void handleWheelEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, + QPoint pixelDelta, QPoint angleDelta, + Qt::KeyboardModifiers mods = Qt::NoModifier, + Qt::ScrollPhase phase = Qt::NoScrollPhase, + Qt::MouseEventSource source = Qt::MouseEventNotSynthesized); // Wheel event compatibility functions. Will be removed: do not use. static void handleWheelEvent(QWindow *w, const QPointF & local, const QPointF & global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods = Qt::NoModifier); diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h index e48d1e965b..c2569f29cd 100644 --- a/src/gui/kernel/qwindowsysteminterface_p.h +++ b/src/gui/kernel/qwindowsysteminterface_p.h @@ -236,7 +236,7 @@ public: class WheelEvent : public InputEvent { public: WheelEvent(QWindow *w, ulong time, const QPointF & local, const QPointF & global, QPoint pixelD, QPoint angleD, int qt4D, Qt::Orientation qt4O, - Qt::KeyboardModifiers mods, Qt::ScrollPhase phase = Qt::ScrollUpdate, Qt::MouseEventSource src = Qt::MouseEventNotSynthesized) + Qt::KeyboardModifiers mods, Qt::ScrollPhase phase = Qt::NoScrollPhase, Qt::MouseEventSource src = Qt::MouseEventNotSynthesized) : InputEvent(w, time, Wheel, mods), pixelDelta(pixelD), angleDelta(angleD), qt4Delta(qt4D), qt4Orientation(qt4O), localPos(local), globalPos(global), phase(phase), source(src) { } QPoint pixelDelta; QPoint angleDelta; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 0d80333e65..05dcbd33ad 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -1405,6 +1405,8 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) momentumPhase == NSEventPhaseEnded || momentumPhase == NSEventPhaseCancelled) { ph = Qt::ScrollEnd; m_scrolling = false; + } else if (phase == NSEventPhaseNone && momentumPhase == NSEventPhaseNone) { + ph = Qt::NoScrollPhase; } QWindowSystemInterface::handleWheelEvent(m_window, qt_timestamp, qt_windowPoint, qt_screenPoint, pixelDelta, angleDelta, currentWheelModifiers, ph, source); diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 3ab477ccfb..7c5a0da0c1 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -417,6 +417,7 @@ QWidget *QApplicationPrivate::hidden_focus_widget = 0; // will get keyboard inpu QWidget *QApplicationPrivate::active_window = 0; // toplevel with keyboard focus #ifndef QT_NO_WHEELEVENT int QApplicationPrivate::wheel_scroll_lines; // number of lines to scroll +QWidget *QApplicationPrivate::wheel_widget = Q_NULLPTR; #endif bool qt_in_tab_key_event = false; int qt_antialiasing_threshold = -1; @@ -3309,7 +3310,6 @@ bool QApplication::notify(QObject *receiver, QEvent *e) case QEvent::Wheel: { QWidget* w = static_cast(receiver); - QWheelEvent* wheel = static_cast(e); // QTBUG-40656, QTBUG-42731: ignore wheel events when a popup (QComboBox) is open. if (const QWidget *popup = QApplication::activePopupWidget()) { @@ -3317,27 +3317,61 @@ bool QApplication::notify(QObject *receiver, QEvent *e) return true; } - QPoint relpos = wheel->pos(); - bool eventAccepted = wheel->isAccepted(); + QWheelEvent* wheel = static_cast(e); + const bool spontaneous = wheel->spontaneous(); + const Qt::ScrollPhase phase = wheel->phase(); - if (e->spontaneous() && wheel->phase() == Qt::ScrollUpdate) - QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, e, relpos); + if (phase == Qt::NoScrollPhase || phase == Qt::ScrollBegin + || (phase == Qt::ScrollUpdate && !QApplicationPrivate::wheel_widget)) { + + if (spontaneous && phase == Qt::ScrollBegin) + QApplicationPrivate::wheel_widget = Q_NULLPTR; + + const QPoint &relpos = wheel->pos(); + + if (spontaneous && (phase == Qt::NoScrollPhase || phase == Qt::ScrollUpdate)) + QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, e, relpos); - while (w) { QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(), - wheel->modifiers(), wheel->phase(), wheel->source()); - we.spont = wheel->spontaneous(); - res = d->notify_helper(w, w == receiver ? wheel : &we); - eventAccepted = ((w == receiver) ? wheel : &we)->isAccepted(); - e->spont = false; - if ((res && eventAccepted) - || w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation)) - break; + wheel->modifiers(), phase, wheel->source()); + bool eventAccepted; + while (w) { + we.spont = spontaneous && w == receiver; + we.ignore(); + res = d->notify_helper(w, &we); + eventAccepted = we.isAccepted(); + if (res && eventAccepted) { + if (spontaneous && phase != Qt::NoScrollPhase) + QApplicationPrivate::wheel_widget = w; + break; + } + if (w->isWindow() || w->testAttribute(Qt::WA_NoMousePropagation)) + break; - relpos += w->pos(); - w = w->parentWidget(); + we.p += w->pos(); + w = w->parentWidget(); + } + wheel->setAccepted(eventAccepted); + } else if (QApplicationPrivate::wheel_widget) { + if (!spontaneous) { + // wheel_widget may forward the wheel event to a delegate widget, + // either directly or indirectly (e.g. QAbstractScrollArea will + // forward to its QScrollBars through viewportEvent()). In that + // case, the event will not be spontaneous but synthesized, so + // we can send it straigth to the receiver. + d->notify_helper(w, wheel); + } else { + const QPoint &relpos = QApplicationPrivate::wheel_widget->mapFromGlobal(wheel->globalPos()); + QWheelEvent we(relpos, wheel->globalPos(), wheel->pixelDelta(), wheel->angleDelta(), wheel->delta(), wheel->orientation(), wheel->buttons(), + wheel->modifiers(), wheel->phase(), wheel->source()); + we.spont = true; + we.ignore(); + d->notify_helper(QApplicationPrivate::wheel_widget, &we); + wheel->setAccepted(we.isAccepted()); + if (phase == Qt::ScrollEnd) + QApplicationPrivate::wheel_widget = Q_NULLPTR; + } } - wheel->setAccepted(eventAccepted); } break; #endif diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h index 75d86a5eba..4cce2d84e8 100644 --- a/src/widgets/kernel/qapplication_p.h +++ b/src/widgets/kernel/qapplication_p.h @@ -202,6 +202,7 @@ public: static QWidget *active_window; #ifndef QT_NO_WHEELEVENT static int wheel_scroll_lines; + static QWidget *wheel_widget; #endif static int enabledAnimations; // Combination of QPlatformTheme::UiEffect -- cgit v1.2.3