From 86b061b234b2dbe0225c602a36ba1595e2a6388c Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Thu, 29 Oct 2015 11:55:16 +0100 Subject: [PATCH 01/50] Mirclient: Avoid hardcoding the platform api choice When built in by the debian scripts, a symbol PLATFORM_API_TOUCH would be defined for relevant target platforms. Here in Qt, this does not apply. On a correctly installed system, the UBUNTU_PLATFORM_API_BACKEND variable is not required at runtime, since the system's value will be read from a settings file under /etc. Also, the previous hardcoding would mean that it could not be overridden at runtime. Change-Id: I24ddfaa254005b4113f3328b66edb1c6bbc509e2 Reviewed-by: Christian Stromme --- src/plugins/platforms/mirclient/qmirclientplugin.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/plugins/platforms/mirclient/qmirclientplugin.cpp b/src/plugins/platforms/mirclient/qmirclientplugin.cpp index 43d913f8d2..203a1cbfd8 100644 --- a/src/plugins/platforms/mirclient/qmirclientplugin.cpp +++ b/src/plugins/platforms/mirclient/qmirclientplugin.cpp @@ -49,11 +49,6 @@ QPlatformIntegration* QMirClientIntegrationPlugin::create(const QString &system, const QStringList &) { if (system.toLower() == "mirclient") { -#ifdef PLATFORM_API_TOUCH - setenv("UBUNTU_PLATFORM_API_BACKEND", "touch_mirclient", 1); -#else - setenv("UBUNTU_PLATFORM_API_BACKEND", "desktop_mirclient", 1); -#endif return new QMirClientClientIntegration; } else { return 0; From 9599ee5ab7236130e3c375b56b6c0f00094e3a36 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 19 Nov 2015 20:33:45 +0100 Subject: [PATCH 02/50] Fix no-opengl build for texture backed widgets The recent changes added a widgetTexturesFor() helper function. There has to be a dummy version of this for -no-opengl builds because QPlatformTextureList is not available in such builds at all, meaning the real function is not suitable outside !QT_NO_OPENGL. Change-Id: Ib108b1804f539796631b1927de89937236781d2a Reviewed-by: Paul Olav Tvete --- src/widgets/kernel/qwidgetbackingstore.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index 55b8513072..9036c28b9a 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -1000,6 +1000,16 @@ void QPlatformTextureListWatcher::onLockStatusChanged(bool locked) if (!isLocked()) m_backingStore->sync(); } + +#else + +static QPlatformTextureList *widgetTexturesFor(QWidget *tlw, QWidget *widget) +{ + Q_UNUSED(tlw); + Q_UNUSED(widget); + return Q_NULLPTR; +} + #endif // QT_NO_OPENGL static inline bool discardSyncRequest(QWidget *tlw, QTLWExtra *tlwExtra) From 39c0d16a8e11ba7523a7dbeb3b1d6ee3ddfc09e8 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 19 Nov 2015 10:31:34 +0100 Subject: [PATCH 03/50] Send a paint after resize correctly from QOpenGLWidget Due to recreating the underlying framebuffer we absolutely need a re-render. However, going directly through paintGL() is wrong since application code may override paintEvent() instead. Such code would then miss these repaint requests. To overcome this, simply rely on paint events, like the normal code path does. Task-number: QTBUG-49466 Change-Id: I6ddb9eb53bedb1655a9714b9b77faa1c439766a2 Reviewed-by: Paul Olav Tvete --- src/widgets/kernel/qopenglwidget.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp index 3a4a3a0d63..a80db3f60b 100644 --- a/src/widgets/kernel/qopenglwidget.cpp +++ b/src/widgets/kernel/qopenglwidget.cpp @@ -1172,8 +1172,7 @@ void QOpenGLWidget::resizeEvent(QResizeEvent *e) d->recreateFbo(); resizeGL(width(), height()); - d->invokeUserPaint(); - d->resolveSamples(); + d->sendPaintEvent(QRect(QPoint(0, 0), size())); } /*! From 436ad32f9f47787d0262c25e669b808c195c6565 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Fri, 20 Nov 2015 15:44:30 +0100 Subject: [PATCH 04/50] xcb: Fix windows opened from keyboard are not active on Marco or Xfwm4 Windows opened from keyboard (e.g. keyboard shortcut) are not active on Marco or Xfwm4. These windows are under the window which received the key event. This patch fixes the problem by updating XCB timestamp on every key press like Qt4 does. Task-number: QTBUG-49567 Change-Id: I9ea483784ac361d0b645d0f11f643868b367ac2c Reviewed-by: Laszlo Agocs --- src/plugins/platforms/xcb/qxcbconnection.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 901764bbf8..50d49ca798 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -1086,8 +1086,12 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) case XCB_FOCUS_OUT: HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent); case XCB_KEY_PRESS: - m_keyboard->updateXKBStateFromCore(((xcb_key_press_event_t *)event)->state); + { + xcb_key_press_event_t *kp = (xcb_key_press_event_t *)event; + m_keyboard->updateXKBStateFromCore(kp->state); + setTime(kp->time); HANDLE_KEYBOARD_EVENT(xcb_key_press_event_t, handleKeyPressEvent); + } case XCB_KEY_RELEASE: m_keyboard->updateXKBStateFromCore(((xcb_key_release_event_t *)event)->state); HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent); From f39db6c3f8bc8dd3e38da40b5baf87da383bcc4a Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 18 Nov 2015 13:36:02 +0100 Subject: [PATCH 05/50] Windows: Create one QPlatformCursor per screen. The pixmap-based cursors and some of the standard cursors we create from resource pixmaps need to be separated per screen. Use a QScopedPointer containing the per-screen cursor instead of the previously used QSharedPointer containing the cursor shared by all screens. Task-number: QTBUG-49511 Change-Id: I5203fcc4ecf5a7ff3fea833a4eaeb5300a6e6d54 Reviewed-by: Oliver Wolff Reviewed-by: Joerg Bornemann --- src/plugins/platforms/windows/qwindowscursor.cpp | 9 ++++++--- src/plugins/platforms/windows/qwindowscursor.h | 3 ++- src/plugins/platforms/windows/qwindowsscreen.cpp | 12 +----------- src/plugins/platforms/windows/qwindowsscreen.h | 4 ++-- 4 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp index 800b79347c..da121944c1 100644 --- a/src/plugins/platforms/windows/qwindowscursor.cpp +++ b/src/plugins/platforms/windows/qwindowscursor.cpp @@ -47,11 +47,12 @@ #include #include -static void initResources() +static bool initResources() { #if !defined (Q_OS_WINCE) && !defined (QT_NO_IMAGEFORMAT_PNG) Q_INIT_RESOURCE(cursors); #endif + return true; } QT_BEGIN_NAMESPACE @@ -590,9 +591,11 @@ CursorHandlePtr QWindowsCursor::pixmapWindowCursor(const QCursor &c) return it.value(); } -QWindowsCursor::QWindowsCursor() +QWindowsCursor::QWindowsCursor(const QPlatformScreen *screen) + : m_screen(screen) { - initResources(); + static const bool dummy = initResources(); + Q_UNUSED(dummy) } /*! diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h index ac9e87d1fb..f1de5379d8 100644 --- a/src/plugins/platforms/windows/qwindowscursor.h +++ b/src/plugins/platforms/windows/qwindowscursor.h @@ -96,7 +96,7 @@ public: QPoint hotSpot; }; - QWindowsCursor(); + explicit QWindowsCursor(const QPlatformScreen *screen); void changeCursor(QCursor * widgetCursor, QWindow * widget) Q_DECL_OVERRIDE; QPoint pos() const Q_DECL_OVERRIDE; @@ -117,6 +117,7 @@ private: typedef QHash StandardCursorCache; typedef QHash PixmapCursorCache; + const QPlatformScreen *const m_screen; StandardCursorCache m_standardCursorCache; PixmapCursorCache m_pixmapCursorCache; }; diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index de4ef79b81..e69665e4a9 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -195,16 +195,6 @@ static QDebug operator<<(QDebug dbg, const QWindowsScreenData &d) } #endif // !QT_NO_DEBUG_STREAM -// Return the cursor to be shared by all screens (virtual desktop). -static inline QSharedPointer sharedCursor() -{ -#ifndef QT_NO_CURSOR - if (const QScreen *primaryScreen = QGuiApplication::primaryScreen()) - return static_cast(primaryScreen->handle())->cursorPtr(); -#endif - return QSharedPointer(new QWindowsCursor); -} - /*! \class QWindowsScreen \brief Windows screen. @@ -216,7 +206,7 @@ static inline QSharedPointer sharedCursor() QWindowsScreen::QWindowsScreen(const QWindowsScreenData &data) : m_data(data) #ifndef QT_NO_CURSOR - ,m_cursor(sharedCursor()) + , m_cursor(new QWindowsCursor(this)) #endif { } diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h index bc8fbf553b..879cda047e 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.h +++ b/src/plugins/platforms/windows/qwindowsscreen.h @@ -42,7 +42,7 @@ #include #include #include -#include +#include #include QT_BEGIN_NAMESPACE @@ -74,7 +74,7 @@ class QWindowsScreen : public QPlatformScreen { public: #ifndef QT_NO_CURSOR - typedef QSharedPointer CursorPtr; + typedef QScopedPointer CursorPtr; #endif explicit QWindowsScreen(const QWindowsScreenData &data); From 36bb6d266e08ff4ae3c45d2ad428f7f787746b8a Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 19 Nov 2015 13:32:25 +0100 Subject: [PATCH 06/50] Windows: Scale pixmap/bitmap cursors when High DPI scaling is active. Apply a per screen scale factor, also taking the device pixel ratios of the pixmaps into account. Task-number: QTBUG-49511 Change-Id: If46b6eeb37635c2c4046992c1ba06711ccf54eae Reviewed-by: Oliver Wolff --- .../platforms/windows/qwindowscursor.cpp | 26 +++++++++++++++---- .../platforms/windows/qwindowscursor.h | 4 +-- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp index da121944c1..7dfaf201cd 100644 --- a/src/plugins/platforms/windows/qwindowscursor.cpp +++ b/src/plugins/platforms/windows/qwindowscursor.cpp @@ -43,6 +43,7 @@ #include #include #include // getPixmapCursor() +#include #include #include @@ -93,9 +94,14 @@ QWindowsPixmapCursorCacheKey::QWindowsPixmapCursorCacheKey(const QCursor &c) \sa QWindowsWindowCursor */ -HCURSOR QWindowsCursor::createPixmapCursor(const QPixmap &pixmap, const QPoint &hotSpot) +HCURSOR QWindowsCursor::createPixmapCursor(QPixmap pixmap, const QPoint &hotSpot, qreal scaleFactor) { HCURSOR cur = 0; + scaleFactor /= pixmap.devicePixelRatioF(); + if (!qFuzzyCompare(scaleFactor, 1)) { + pixmap = pixmap.scaled((scaleFactor * QSizeF(pixmap.size())).toSize(), + Qt::KeepAspectRatio, Qt::SmoothTransformation); + } QBitmap mask = pixmap.mask(); if (mask.isNull()) { mask = QBitmap(pixmap.size()); @@ -203,11 +209,19 @@ static HCURSOR createBitmapCursor(const QImage &bbits, const QImage &mbits, } // Create a cursor from image and mask of the format QImage::Format_Mono. -static HCURSOR createBitmapCursor(const QCursor &cursor) +static HCURSOR createBitmapCursor(const QCursor &cursor, qreal scaleFactor = 1) { Q_ASSERT(cursor.shape() == Qt::BitmapCursor && cursor.bitmap()); - const QImage bbits = cursor.bitmap()->toImage().convertToFormat(QImage::Format_Mono); - const QImage mbits = cursor.mask()->toImage().convertToFormat(QImage::Format_Mono); + QImage bbits = cursor.bitmap()->toImage(); + QImage mbits = cursor.mask()->toImage(); + scaleFactor /= bbits.devicePixelRatioF(); + if (!qFuzzyCompare(scaleFactor, 1)) { + const QSize scaledSize = (QSizeF(bbits.size()) * scaleFactor).toSize(); + bbits = bbits.scaled(scaledSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); + mbits = mbits.scaled(scaledSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); + } + bbits = bbits.convertToFormat(QImage::Format_Mono); + mbits = mbits.convertToFormat(QImage::Format_Mono); const bool invb = bbits.colorCount() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1)); const bool invm = mbits.colorCount() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1)); return createBitmapCursor(bbits, mbits, cursor.hotSpot(), invb, invm); @@ -583,9 +597,11 @@ CursorHandlePtr QWindowsCursor::pixmapWindowCursor(const QCursor &c) ++it; } } + const qreal scaleFactor = QHighDpiScaling::factor(m_screen); const QPixmap pixmap = c.pixmap(); const HCURSOR hc = pixmap.isNull() - ? createBitmapCursor(c) : QWindowsCursor::createPixmapCursor(pixmap, c.hotSpot()); + ? createBitmapCursor(c, scaleFactor) + : QWindowsCursor::createPixmapCursor(pixmap, c.hotSpot(), scaleFactor); it = m_pixmapCursorCache.insert(cacheKey, CursorHandlePtr(new CursorHandle(hc))); } return it.value(); diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h index f1de5379d8..ac4462f131 100644 --- a/src/plugins/platforms/windows/qwindowscursor.h +++ b/src/plugins/platforms/windows/qwindowscursor.h @@ -102,8 +102,8 @@ public: QPoint pos() const Q_DECL_OVERRIDE; void setPos(const QPoint &pos) Q_DECL_OVERRIDE; - static HCURSOR createPixmapCursor(const QPixmap &pixmap, const QPoint &hotSpot); - static HCURSOR createPixmapCursor(const PixmapCursor &pc) { return createPixmapCursor(pc.pixmap, pc.hotSpot); } + static HCURSOR createPixmapCursor(QPixmap pixmap, const QPoint &hotSpot, qreal scaleFactor = 1); + static HCURSOR createPixmapCursor(const PixmapCursor &pc, qreal scaleFactor = 1) { return createPixmapCursor(pc.pixmap, pc.hotSpot, scaleFactor); } static PixmapCursor customCursor(Qt::CursorShape cursorShape); static HCURSOR createCursorFromShape(Qt::CursorShape cursorShape); From 05c8e51d884d7130e3f26701a7955ebc2026bb12 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 19 Nov 2015 13:39:52 +0100 Subject: [PATCH 07/50] Windows: Scale cursors from resource pixmaps according to screen. QWindowsCursor::customCursor() uses a best match algorithm to find the most suitable pixmap for the cursor size obtained from GetSystemMetrics(). This size is correct for the primary screen only; in High DPI + normal monitor multiscreen-environments, the cursors will be too large on the secondary monitor. Pass the platform screen to apply a correction factor based on logical DPI to obtain the correct size. Task-number: QTBUG-49511 Change-Id: I8a64a969e3ade7ab5029e3ae904a0bcbb4704f90 Reviewed-by: Oliver Wolff --- .../platforms/windows/qwindowscursor.cpp | 45 +++++++++++++------ .../platforms/windows/qwindowscursor.h | 4 +- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp index 7dfaf201cd..c138335b4b 100644 --- a/src/plugins/platforms/windows/qwindowscursor.cpp +++ b/src/plugins/platforms/windows/qwindowscursor.cpp @@ -227,7 +227,25 @@ static HCURSOR createBitmapCursor(const QCursor &cursor, qreal scaleFactor = 1) return createBitmapCursor(bbits, mbits, cursor.hotSpot(), invb, invm); } -static inline QSize systemCursorSize() { return QSize(GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR)); } +static QSize systemCursorSize(const QPlatformScreen *screen = Q_NULLPTR) +{ + const QSize primaryScreenCursorSize(GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR)); + if (screen) { + // Correct the size if the DPI value of the screen differs from + // that of the primary screen. + if (const QScreen *primaryQScreen = QGuiApplication::primaryScreen()) { + const QPlatformScreen *primaryScreen = primaryQScreen->handle(); + if (screen != primaryScreen) { + const qreal logicalDpi = screen->logicalDpi().first; + const qreal primaryScreenLogicalDpi = primaryScreen->logicalDpi().first; + if (!qFuzzyCompare(logicalDpi, primaryScreenLogicalDpi)) + return (QSizeF(primaryScreenCursorSize) * logicalDpi / primaryScreenLogicalDpi).toSize(); + } + } + } + return primaryScreenCursorSize; +} + static inline QSize standardCursorSize() { return QSize(32, 32); } #if defined (Q_OS_WINCE) || defined (QT_NO_IMAGEFORMAT_PNG) @@ -257,7 +275,8 @@ static QWindowsCursor::PixmapCursor createPixmapCursorFromData(const QSize &syst return QWindowsCursor::PixmapCursor(rawImage, hotSpot); } -QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape) +QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape, + const QPlatformScreen *screen) { // Non-standard Windows cursors are created from bitmaps static const uchar vsplit_bits[] = { @@ -425,13 +444,13 @@ QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursor switch (cursorShape) { case Qt::SplitVCursor: - return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 32, vsplit_bits, vsplitm_bits); + return createPixmapCursorFromData(systemCursorSize(screen), standardCursorSize(), 32, vsplit_bits, vsplitm_bits); case Qt::SplitHCursor: - return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 32, hsplit_bits, hsplitm_bits); + return createPixmapCursorFromData(systemCursorSize(screen), standardCursorSize(), 32, hsplit_bits, hsplitm_bits); case Qt::OpenHandCursor: - return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 16, openhand_bits, openhandm_bits); + return createPixmapCursorFromData(systemCursorSize(screen), standardCursorSize(), 16, openhand_bits, openhandm_bits); case Qt::ClosedHandCursor: - return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 16, closedhand_bits, closedhandm_bits); + return createPixmapCursorFromData(systemCursorSize(screen), standardCursorSize(), 16, closedhand_bits, closedhandm_bits); case Qt::DragCopyCursor: return QWindowsCursor::PixmapCursor(QPixmap(copyDragCursorXpmC), QPoint(0, 0)); case Qt::DragMoveCursor: @@ -451,7 +470,7 @@ struct QWindowsCustomPngCursor { int hotSpotY; }; -QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape) +QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape, const QPlatformScreen *screen) { static const QWindowsCustomPngCursor pngCursors[] = { { Qt::SplitVCursor, 32, "splitvcursor_32.png", 11, 11 }, @@ -477,14 +496,14 @@ QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursor { Qt::DragLinkCursor, 64, "draglinkcursor_64.png", 0, 0 } }; - const int cursorSize = GetSystemMetrics(SM_CXCURSOR); + const QSize cursorSize = systemCursorSize(screen); const QWindowsCustomPngCursor *sEnd = pngCursors + sizeof(pngCursors) / sizeof(pngCursors[0]); const QWindowsCustomPngCursor *bestFit = 0; int sizeDelta = INT_MAX; for (const QWindowsCustomPngCursor *s = pngCursors; s < sEnd; ++s) { if (s->shape != cursorShape) continue; - const int currentSizeDelta = qMax(s->size, cursorSize) - qMin(s->size, cursorSize); + const int currentSizeDelta = qMax(s->size, cursorSize.width()) - qMin(s->size, cursorSize.width()); if (currentSizeDelta < sizeDelta) { bestFit = s; if (currentSizeDelta == 0) @@ -507,7 +526,7 @@ struct QWindowsStandardCursorMapping { LPCWSTR resource; }; -HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape) +HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape, const QPlatformScreen *screen) { Q_ASSERT(cursorShape != Qt::BitmapCursor); @@ -530,7 +549,7 @@ HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape) switch (cursorShape) { case Qt::BlankCursor: { - QImage blank = QImage(systemCursorSize(), QImage::Format_Mono); + QImage blank = QImage(systemCursorSize(screen), QImage::Format_Mono); blank.fill(0); // ignore color table return createBitmapCursor(blank, blank); } @@ -541,7 +560,7 @@ HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape) case Qt::DragCopyCursor: case Qt::DragMoveCursor: case Qt::DragLinkCursor: - return QWindowsCursor::createPixmapCursor(customCursor(cursorShape)); + return QWindowsCursor::createPixmapCursor(customCursor(cursorShape, screen)); default: break; } @@ -570,7 +589,7 @@ CursorHandlePtr QWindowsCursor::standardWindowCursor(Qt::CursorShape shape) { StandardCursorCache::Iterator it = m_standardCursorCache.find(shape); if (it == m_standardCursorCache.end()) { - if (const HCURSOR hc = QWindowsCursor::createCursorFromShape(shape)) + if (const HCURSOR hc = QWindowsCursor::createCursorFromShape(shape, m_screen)) it = m_standardCursorCache.insert(shape, CursorHandlePtr(new CursorHandle(hc))); } return it != m_standardCursorCache.end() ? it.value() : CursorHandlePtr(new CursorHandle); diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h index ac4462f131..558e807201 100644 --- a/src/plugins/platforms/windows/qwindowscursor.h +++ b/src/plugins/platforms/windows/qwindowscursor.h @@ -104,9 +104,9 @@ public: static HCURSOR createPixmapCursor(QPixmap pixmap, const QPoint &hotSpot, qreal scaleFactor = 1); static HCURSOR createPixmapCursor(const PixmapCursor &pc, qreal scaleFactor = 1) { return createPixmapCursor(pc.pixmap, pc.hotSpot, scaleFactor); } - static PixmapCursor customCursor(Qt::CursorShape cursorShape); + static PixmapCursor customCursor(Qt::CursorShape cursorShape, const QPlatformScreen *screen = Q_NULLPTR); - static HCURSOR createCursorFromShape(Qt::CursorShape cursorShape); + static HCURSOR createCursorFromShape(Qt::CursorShape cursorShape, const QPlatformScreen *screen = Q_NULLPTR); static QPoint mousePosition(); static CursorState cursorState(); From 07efdb78f03fb2f75898cc769b3224baee4d8d90 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 19 Nov 2015 14:14:37 +0100 Subject: [PATCH 08/50] Windows: Fix the size of drag cursors in multi-screen setups. Move QWindowsDrag::defaultCursor() to the per-screen instance of QWindowsCursor so that the cached default drag cursor pixmaps are created with the correct size per screen. Task-number: QTBUG-49511 Change-Id: I02f75ac3b1e5e064325b066ee03e1d5c8a7c7ee8 Reviewed-by: Joerg Bornemann --- .../platforms/windows/qwindowscursor.cpp | 88 ++++++++++++++ .../platforms/windows/qwindowscursor.h | 7 ++ .../platforms/windows/qwindowsdrag.cpp | 111 ++---------------- src/plugins/platforms/windows/qwindowsdrag.h | 10 +- 4 files changed, 111 insertions(+), 105 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp index c138335b4b..c769eb04a4 100644 --- a/src/plugins/platforms/windows/qwindowscursor.cpp +++ b/src/plugins/platforms/windows/qwindowscursor.cpp @@ -692,6 +692,94 @@ void QWindowsCursor::setPos(const QPoint &pos) SetCursorPos(pos.x() , pos.y()); } +QPixmap QWindowsCursor::dragDefaultCursor(Qt::DropAction action) const +{ + switch (action) { + case Qt::CopyAction: + if (m_copyDragCursor.isNull()) + m_copyDragCursor = QWindowsCursor::customCursor(Qt::DragCopyCursor, m_screen).pixmap; + return m_copyDragCursor; + case Qt::TargetMoveAction: + case Qt::MoveAction: + if (m_moveDragCursor.isNull()) + m_moveDragCursor = QWindowsCursor::customCursor(Qt::DragMoveCursor, m_screen).pixmap; + return m_moveDragCursor; + case Qt::LinkAction: + if (m_linkDragCursor.isNull()) + m_linkDragCursor = QWindowsCursor::customCursor(Qt::DragLinkCursor, m_screen).pixmap; + return m_linkDragCursor; + default: + break; + } + + static const char * const ignoreDragCursorXpmC[] = { + "24 30 3 1", + ". c None", + "a c #000000", + "X c #FFFFFF", + "aa......................", + "aXa.....................", + "aXXa....................", + "aXXXa...................", + "aXXXXa..................", + "aXXXXXa.................", + "aXXXXXXa................", + "aXXXXXXXa...............", + "aXXXXXXXXa..............", + "aXXXXXXXXXa.............", + "aXXXXXXaaaa.............", + "aXXXaXXa................", + "aXXaaXXa................", + "aXa..aXXa...............", + "aa...aXXa...............", + "a.....aXXa..............", + "......aXXa.....XXXX.....", + ".......aXXa..XXaaaaXX...", + ".......aXXa.XaaaaaaaaX..", + "........aa.XaaaXXXXaaaX.", + "...........XaaaaX..XaaX.", + "..........XaaXaaaX..XaaX", + "..........XaaXXaaaX.XaaX", + "..........XaaX.XaaaXXaaX", + "..........XaaX..XaaaXaaX", + "...........XaaX..XaaaaX.", + "...........XaaaXXXXaaaX.", + "............XaaaaaaaaX..", + ".............XXaaaaXX...", + "...............XXXX....."}; + + if (m_ignoreDragCursor.isNull()) { +#if !defined (Q_OS_WINCE) + HCURSOR cursor = LoadCursor(NULL, IDC_NO); + ICONINFO iconInfo = {0, 0, 0, 0, 0}; + GetIconInfo(cursor, &iconInfo); + BITMAP bmColor = {0, 0, 0, 0, 0, 0, 0}; + + if (iconInfo.hbmColor + && GetObject(iconInfo.hbmColor, sizeof(BITMAP), &bmColor) + && bmColor.bmWidth == bmColor.bmWidthBytes / 4) { + const int colorBitsLength = bmColor.bmHeight * bmColor.bmWidthBytes; + uchar *colorBits = new uchar[colorBitsLength]; + GetBitmapBits(iconInfo.hbmColor, colorBitsLength, colorBits); + const QImage colorImage(colorBits, bmColor.bmWidth, bmColor.bmHeight, + bmColor.bmWidthBytes, QImage::Format_ARGB32); + + m_ignoreDragCursor = QPixmap::fromImage(colorImage); + delete [] colorBits; + } else { + m_ignoreDragCursor = QPixmap(ignoreDragCursorXpmC); + } + + DeleteObject(iconInfo.hbmMask); + DeleteObject(iconInfo.hbmColor); + DestroyCursor(cursor); +#else // !Q_OS_WINCE + m_ignoreDragCursor = QPixmap(ignoreDragCursorXpmC); +#endif // !Q_OS_WINCE + } + return m_ignoreDragCursor; +} + /*! \class QWindowsWindowCursor \brief Per-Window cursor. Contains a QCursor and manages its associated system diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h index 558e807201..e93f779f94 100644 --- a/src/plugins/platforms/windows/qwindowscursor.h +++ b/src/plugins/platforms/windows/qwindowscursor.h @@ -113,6 +113,8 @@ public: CursorHandlePtr standardWindowCursor(Qt::CursorShape s = Qt::ArrowCursor); CursorHandlePtr pixmapWindowCursor(const QCursor &c); + QPixmap dragDefaultCursor(Qt::DropAction action) const; + private: typedef QHash StandardCursorCache; typedef QHash PixmapCursorCache; @@ -120,6 +122,11 @@ private: const QPlatformScreen *const m_screen; StandardCursorCache m_standardCursorCache; PixmapCursorCache m_pixmapCursorCache; + + mutable QPixmap m_copyDragCursor; + mutable QPixmap m_moveDragCursor; + mutable QPixmap m_linkDragCursor; + mutable QPixmap m_ignoreDragCursor; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp index e16bb80714..021058fa33 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.cpp +++ b/src/plugins/platforms/windows/qwindowsdrag.cpp @@ -271,13 +271,6 @@ QDebug operator<<(QDebug d, const QWindowsOleDropSource::CursorEntry &e) } #endif // !QT_NO_DEBUG_STREAM -static qreal dragScaleFactor() -{ - const QWindowsScreenManager &screenManager = QWindowsContext::instance()->screenManager(); - const QWindowsScreen *screen = screenManager.screenAtDp(QWindowsCursor::mousePosition()); - return screen ? QHighDpiScaling::factor(screen) : qreal(1); -} - /*! \brief Blend custom pixmap with cursors. */ @@ -288,7 +281,17 @@ void QWindowsOleDropSource::createCursors() const QPixmap pixmap = drag->pixmap(); const bool hasPixmap = !pixmap.isNull(); - const qreal scaleFactor = dragScaleFactor(); + // Find screen for drag. Could be obtained from QDrag::source(), but that might be a QWidget. + + qreal scaleFactor = 1; + QPlatformCursor *platformCursor = Q_NULLPTR; + if (const QPlatformScreen *platformScreen = QWindowsContext::instance()->screenManager().screenAtDp(QWindowsCursor::mousePosition())) { + scaleFactor = QHighDpiScaling::factor(platformScreen); + platformCursor = platformScreen->cursor(); + } + if (!platformCursor && QGuiApplication::primaryScreen()) + platformCursor = QGuiApplication::primaryScreen()->handle()->cursor(); + const bool scalePixmap = hasPixmap && m_mode != TouchDrag // Touch drag: pixmap is shown in a separate QWindow, which will be scaled. && (scaleFactor != 1 && scaleFactor != qRound(pixmap.devicePixelRatio())); @@ -306,8 +309,8 @@ void QWindowsOleDropSource::createCursors() for (int cnum = 0; cnum < actionCount; ++cnum) { const Qt::DropAction action = actions[cnum]; QPixmap cursorPixmap = drag->dragCursor(action); - if (cursorPixmap.isNull()) - cursorPixmap = m_drag->defaultCursor(action); + if (cursorPixmap.isNull() && platformCursor) + cursorPixmap = static_cast(platformCursor)->dragDefaultCursor(action); const qint64 cacheKey = cursorPixmap.cacheKey(); const ActionCursorMapIt it = m_cursors.find(action); if (it != m_cursors.end() && it.value().cacheKey == cacheKey) @@ -704,94 +707,6 @@ IDropTargetHelper* QWindowsDrag::dropHelper() { return m_cachedDropTargetHelper; } -QPixmap QWindowsDrag::defaultCursor(Qt::DropAction action) const -{ - switch (action) { - case Qt::CopyAction: - if (m_copyDragCursor.isNull()) - m_copyDragCursor = QWindowsCursor::customCursor(Qt::DragCopyCursor).pixmap; - return m_copyDragCursor; - case Qt::TargetMoveAction: - case Qt::MoveAction: - if (m_moveDragCursor.isNull()) - m_moveDragCursor = QWindowsCursor::customCursor(Qt::DragMoveCursor).pixmap; - return m_moveDragCursor; - case Qt::LinkAction: - if (m_linkDragCursor.isNull()) - m_linkDragCursor = QWindowsCursor::customCursor(Qt::DragLinkCursor).pixmap; - return m_linkDragCursor; - default: - break; - } - - static const char * const ignoreDragCursorXpmC[] = { - "24 30 3 1", - ". c None", - "a c #000000", - "X c #FFFFFF", - "aa......................", - "aXa.....................", - "aXXa....................", - "aXXXa...................", - "aXXXXa..................", - "aXXXXXa.................", - "aXXXXXXa................", - "aXXXXXXXa...............", - "aXXXXXXXXa..............", - "aXXXXXXXXXa.............", - "aXXXXXXaaaa.............", - "aXXXaXXa................", - "aXXaaXXa................", - "aXa..aXXa...............", - "aa...aXXa...............", - "a.....aXXa..............", - "......aXXa.....XXXX.....", - ".......aXXa..XXaaaaXX...", - ".......aXXa.XaaaaaaaaX..", - "........aa.XaaaXXXXaaaX.", - "...........XaaaaX..XaaX.", - "..........XaaXaaaX..XaaX", - "..........XaaXXaaaX.XaaX", - "..........XaaX.XaaaXXaaX", - "..........XaaX..XaaaXaaX", - "...........XaaX..XaaaaX.", - "...........XaaaXXXXaaaX.", - "............XaaaaaaaaX..", - ".............XXaaaaXX...", - "...............XXXX....."}; - - if (m_ignoreDragCursor.isNull()) { -#if !defined (Q_OS_WINCE) - HCURSOR cursor = LoadCursor(NULL, IDC_NO); - ICONINFO iconInfo = {0, 0, 0, 0, 0}; - GetIconInfo(cursor, &iconInfo); - BITMAP bmColor = {0, 0, 0, 0, 0, 0, 0}; - - if (iconInfo.hbmColor - && GetObject(iconInfo.hbmColor, sizeof(BITMAP), &bmColor) - && bmColor.bmWidth == bmColor.bmWidthBytes / 4) { - const int colorBitsLength = bmColor.bmHeight * bmColor.bmWidthBytes; - uchar *colorBits = new uchar[colorBitsLength]; - GetBitmapBits(iconInfo.hbmColor, colorBitsLength, colorBits); - const QImage colorImage(colorBits, bmColor.bmWidth, bmColor.bmHeight, - bmColor.bmWidthBytes, QImage::Format_ARGB32); - - m_ignoreDragCursor = QPixmap::fromImage(colorImage); - delete [] colorBits; - } else { - m_ignoreDragCursor = QPixmap(ignoreDragCursorXpmC); - } - - DeleteObject(iconInfo.hbmMask); - DeleteObject(iconInfo.hbmColor); - DestroyCursor(cursor); -#else // !Q_OS_WINCE - m_ignoreDragCursor = QPixmap(ignoreDragCursorXpmC); -#endif // !Q_OS_WINCE - } - return m_ignoreDragCursor; -} - Qt::DropAction QWindowsDrag::drag(QDrag *drag) { // TODO: Accessibility handling? diff --git a/src/plugins/platforms/windows/qwindowsdrag.h b/src/plugins/platforms/windows/qwindowsdrag.h index 9a5e0b17f2..890ad6c142 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.h +++ b/src/plugins/platforms/windows/qwindowsdrag.h @@ -42,6 +42,9 @@ struct IDropTargetHelper; QT_BEGIN_NAMESPACE + +class QPlatformScreen; + class QWindowsDropMimeData : public QWindowsInternalMimeData { public: QWindowsDropMimeData() {} @@ -95,18 +98,11 @@ public: IDropTargetHelper* dropHelper(); - QPixmap defaultCursor(Qt::DropAction action) const; - private: QWindowsDropMimeData m_dropData; IDataObject *m_dropDataObject; IDropTargetHelper* m_cachedDropTargetHelper; - - mutable QPixmap m_copyDragCursor; - mutable QPixmap m_moveDragCursor; - mutable QPixmap m_linkDragCursor; - mutable QPixmap m_ignoreDragCursor; }; QT_END_NAMESPACE From 084df84bd096fe78eec5edd62424bd625dcfc00b Mon Sep 17 00:00:00 2001 From: Tim Blechmann Date: Wed, 18 Nov 2015 17:11:07 +0700 Subject: [PATCH 09/50] QPI/Cocoa: QNSView - guard removeFromSuperview by autorelease pool MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit removeFromSuperview could be called from outside the Qt domain (e.g from a native cocoa gui). we need to guard it by an autorelease pool to make sure that potential release/dealloc methods are not postponed to a point when we do not have a qapplication anymore Change-Id: If65cce4c524a16ffee125694c534f900c7d08fa8 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qnsview.h | 1 + src/plugins/platforms/cocoa/qnsview.mm | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index bad67f2516..50b456cab7 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -99,6 +99,7 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper)); - (void)textInputContextKeyboardSelectionDidChangeNotification : (NSNotification *) textInputContextKeyboardSelectionDidChangeNotification; - (void)viewDidHide; - (void)viewDidUnhide; +- (void)removeFromSuperview; - (BOOL)isFlipped; - (BOOL)acceptsFirstResponder; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index f414193bdb..3faa292ae0 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -498,6 +498,12 @@ QT_WARNING_POP m_platformWindow->exposeWindow(); } +- (void)removeFromSuperview +{ + QMacAutoReleasePool pool; + [super removeFromSuperview]; +} + - (void) flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset { m_backingStore = backingStore; From 5dbef0b7d2fbf35bb6b8c43e831ce48df84a4d86 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Thu, 12 Nov 2015 17:25:55 +0100 Subject: [PATCH 10/50] Fix QT_CPU_FEATURES The part of qmodule.pri that is supposed to set QT_CPU_FEATURES ends up missing in the output. Change-Id: I30f3dbad5ac22d32e25d63037980dac370adc4ea Reviewed-by: Oswald Buddenhagen --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 1eb893d9cc..443771af47 100755 --- a/configure +++ b/configure @@ -7103,7 +7103,7 @@ if [ -n "$DISABLED_FEATURES" ]; then fi echo "QT_QCONFIG_PATH = ${CFG_QCONFIG_PATH#$relpath/src/corelib/global/}" -cat >>"$QTMODULE.tmp" < Date: Thu, 19 Nov 2015 15:01:56 +0100 Subject: [PATCH 11/50] Doc: Online style: Decrease font size of enum tables' Value column A table in enum doc may have long literal strings defined as enum values - they take up space from the Description column, and often force a scrollbar to appear, making the entire table difficult to read. Alleviate this by reducing the font size for the text in Value column. Change-Id: I18495a4f506851f9eff2cd94f5cdfcb03096c698 Task-number: QTWEBSITE-658 Reviewed-by: Martin Smith Reviewed-by: Leena Miettinen --- doc/global/template/style/online.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/global/template/style/online.css b/doc/global/template/style/online.css index cfd0da0f4b..a98382e083 100644 --- a/doc/global/template/style/online.css +++ b/doc/global/template/style/online.css @@ -1261,6 +1261,9 @@ table td,table th { table.alignedsummary,table.propsummary { width:initial } +table.valuelist td.tblval { + font-size:0.75em +} div.main_index .row { border-bottom:1px solid #eee } From 1ab7880d73fa94befbeb5cdca3fd6d3bbd25f5ba Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Thu, 5 Nov 2015 05:49:07 +0400 Subject: [PATCH 12/50] Get rid of QT_USE_BUNDLED_LIBPNG In fact, this is an extra info no one ever cares about. We already have properly configured INCLUDEPATH to look for png.h. Change-Id: I27fec4d474570683c6c371dff34472a7c650fe65 Reviewed-by: Oswald Buddenhagen Reviewed-by: Lars Knoll --- src/3rdparty/libpng.pri | 1 - src/gui/image/qpnghandler.cpp | 5 ----- 2 files changed, 6 deletions(-) diff --git a/src/3rdparty/libpng.pri b/src/3rdparty/libpng.pri index f8516bd5db..a5fe32f867 100644 --- a/src/3rdparty/libpng.pri +++ b/src/3rdparty/libpng.pri @@ -1,4 +1,3 @@ -DEFINES *= QT_USE_BUNDLED_LIBPNG DEFINES += PNG_ARM_NEON_OPT=0 INCLUDEPATH += $$PWD/libpng SOURCES += $$PWD/libpng/png.c \ diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp index 776a61d8fe..e9944e1750 100644 --- a/src/gui/image/qpnghandler.cpp +++ b/src/gui/image/qpnghandler.cpp @@ -43,13 +43,8 @@ #include #include -#ifdef QT_USE_BUNDLED_LIBPNG -#include <../../3rdparty/libpng/png.h> -#include <../../3rdparty/libpng/pngconf.h> -#else #include #include -#endif #if PNG_LIBPNG_VER >= 10400 && PNG_LIBPNG_VER <= 10502 \ && defined(PNG_PEDANTIC_WARNINGS_SUPPORTED) From 0e99f3c853aa10f60aa33804c122b187edb565ea Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Mon, 23 Nov 2015 14:04:57 +0400 Subject: [PATCH 13/50] QTextLine::cursorToX: Always return the nearest valid cursor position The documentation already states we're doing this, so stop lying and implement it properly :) Change-Id: Ic78980d76f61e8aa64e59ea058a8105d9c507774 Reviewed-by: Lars Knoll --- src/gui/text/qtextlayout.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 9f046af47c..e69a591d59 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -2624,26 +2624,26 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR */ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const { - if (!eng->layoutData) - eng->itemize(); - const QScriptLine &line = eng->lines[index]; bool lastLine = index >= eng->lines.size() - 1; QFixed x = line.x; - x += eng->alignLine(line) - eng->leadingSpaceWidth(line); - if (!index && !eng->layoutData->items.size()) { - *cursorPos = 0; + if (!eng->layoutData) + eng->itemize(); + if (!eng->layoutData->items.size()) { + *cursorPos = line.from; return x.toReal(); } + x += eng->alignLine(line) - eng->leadingSpaceWidth(line); + int lineEnd = line.from + line.length + line.trailingSpaces; - int pos = qBound(0, *cursorPos, lineEnd); + int pos = qBound(line.from, *cursorPos, lineEnd); int itm; const QCharAttributes *attributes = eng->attributes(); if (!attributes) { - *cursorPos = 0; + *cursorPos = line.from; return x.toReal(); } while (pos < lineEnd && !attributes[pos].graphemeBoundary) @@ -2655,7 +2655,7 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const else itm = eng->findItem(pos); if (itm < 0) { - *cursorPos = 0; + *cursorPos = line.from; return x.toReal(); } eng->shapeLine(line); From 073a16e50e5803fc92dc46bca704f8a7ef79e597 Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Sat, 21 Nov 2015 00:34:43 +0400 Subject: [PATCH 14/50] QTextLine::cursorToX: Optimize by re-using the cached values (and move some code around) Change-Id: I2e26dcc7b769fdbcc750332845da11ec88e332dd Reviewed-by: Lars Knoll --- src/gui/text/qtextlayout.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index e69a591d59..67af3d316b 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -2663,18 +2663,14 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const const QScriptItem *si = &eng->layoutData->items[itm]; if (!si->num_glyphs) eng->shape(itm); - pos -= si->position; + + const int l = eng->length(itm); + pos = qBound(0, pos - si->position, l); QGlyphLayout glyphs = eng->shapedGlyphs(si); unsigned short *logClusters = eng->logClusters(si); Q_ASSERT(logClusters); - int l = eng->length(itm); - if (pos > l) - pos = l; - if (pos < 0) - pos = 0; - int glyph_pos = pos == l ? si->num_glyphs : logClusters[pos]; if (edge == Trailing && glyph_pos < si->num_glyphs) { // trailing edge is leading edge of next cluster @@ -2683,7 +2679,7 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const glyph_pos++; } - bool reverse = eng->layoutData->items[itm].analysis.bidiLevel % 2; + bool reverse = si->analysis.bidiLevel % 2; // add the items left of the cursor @@ -2710,13 +2706,15 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const x += si.width; continue; } + + const int itemLength = eng->length(item); int start = qMax(line.from, si.position); - int end = qMin(lineEnd, si.position + eng->length(item)); + int end = qMin(lineEnd, si.position + itemLength); logClusters = eng->logClusters(&si); int gs = logClusters[start-si.position]; - int ge = (end == si.position + eng->length(item)) ? si.num_glyphs-1 : logClusters[end-si.position-1]; + int ge = (end == si.position + itemLength) ? si.num_glyphs-1 : logClusters[end-si.position-1]; QGlyphLayout glyphs = eng->shapedGlyphs(&si); From fa00afe7d760d91cf9c91f57dd2f77625e758e28 Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Sat, 21 Nov 2015 01:04:39 +0400 Subject: [PATCH 15/50] Optimize QTextEngine::findItem() usage cases Since the item positions are guaranteed to grow, we could safely re-use the obtained first item while looking for the last item in the chain. Change-Id: I5e42f5de820c62a51a109a4b227b031c697aa898 Reviewed-by: Lars Knoll --- src/gui/text/qtextengine.cpp | 13 +++++++------ src/gui/text/qtextengine_p.h | 2 +- src/gui/text/qtextlayout.cpp | 4 ++-- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 50a242d81e..31b1109b6a 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -918,10 +918,11 @@ void QTextEngine::shapeLine(const QScriptLine &line) { QFixed x; bool first = true; - const int end = findItem(line.from + line.length - 1); int item = findItem(line.from); if (item == -1) return; + + const int end = findItem(line.from + line.length - 1, item); for ( ; item <= end; ++item) { QScriptItem &si = layoutData->items[item]; if (si.analysis.flags == QScriptAnalysis::Tab) { @@ -1747,13 +1748,13 @@ bool QTextEngine::isRightToLeft() const } -int QTextEngine::findItem(int strPos) const +int QTextEngine::findItem(int strPos, int firstItem) const { itemize(); - if (strPos < 0 || strPos >= layoutData->string.size()) + if (strPos < 0 || strPos >= layoutData->string.size() || firstItem < 0) return -1; - int left = 1; + int left = firstItem + 1; int right = layoutData->items.size()-1; while(left <= right) { int middle = ((right-left)/2)+left; @@ -2172,7 +2173,7 @@ void QTextEngine::justify(const QScriptLine &line) return; int firstItem = findItem(line.from); - int lastItem = findItem(line.from + line_length - 1); + int lastItem = findItem(line.from + line_length - 1, firstItem); int nItems = (firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0; QVarLengthArray justificationPoints; @@ -3529,7 +3530,7 @@ QTextLineItemIterator::QTextLineItemIterator(QTextEngine *_eng, int _lineNum, co lineNum(_lineNum), lineEnd(line.from + line.length), firstItem(eng->findItem(line.from)), - lastItem(eng->findItem(lineEnd - 1)), + lastItem(eng->findItem(lineEnd - 1, firstItem)), nItems((firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0), logicalItem(-1), item(-1), diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index dbe8e1ee2b..39c228fd52 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -512,7 +512,7 @@ public: void freeMemory(); - int findItem(int strPos) const; + int findItem(int strPos, int firstItem = 0) const; inline QTextFormatCollection *formatCollection() const { if (block.docHandle()) return block.docHandle()->formatCollection(); diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 67af3d316b..5f570fea82 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -2685,7 +2685,7 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const // add the items left of the cursor int firstItem = eng->findItem(line.from); - int lastItem = eng->findItem(lineEnd - 1); + int lastItem = eng->findItem(lineEnd - 1, itm); int nItems = (firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0; QVarLengthArray visualOrder(nItems); @@ -2786,7 +2786,7 @@ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const return line.from; int firstItem = eng->findItem(line.from); - int lastItem = eng->findItem(line.from + line_length - 1); + int lastItem = eng->findItem(line.from + line_length - 1, firstItem); int nItems = (firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0; if (!nItems) From 5b62a5e7aabcc818408f2fe28b9760082f474def Mon Sep 17 00:00:00 2001 From: Samuel Nevala Date: Thu, 19 Nov 2015 13:12:41 +0200 Subject: [PATCH 16/50] Fix deadlock when setting environment variables. Qt uses QHash as the container for faking environment variables on Windows Runtime and CE. Environment variable manipulation functions are protected by mutex. Accessing the QT_HASH_SEED environment variable inside QHash can lead to situation where qputenv() call leads to qgetenv() call and that leads to a deadlock. Since the application environment is faked anyway, drop support for QT_HASH_SEED and ifdef that functionality out on those platforms. Documentation is updated to reflect changes. Task-number: QTBUG-49529 Change-Id: I1b1c28cb0b041fe2a63ca3dce57068fcb46505a7 Reviewed-by: Oswald Buddenhagen Reviewed-by: Andrew Knight --- src/corelib/tools/qhash.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index b334a697a9..fe49e8c6a8 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -38,6 +38,14 @@ #ifndef _CRT_RAND_S #define _CRT_RAND_S #endif + +// Windows Runtime and CE use a QHash to fake environment variables. To avoid +// deadlock, disable reading the QT_HASH_SEED environment variable within +// QHash. +#if defined(Q_OS_WINRT) || defined(Q_OS_WINCE) +# define QHASH_NO_ENV_SEED +#endif + #include #include "qhash.h" @@ -223,9 +231,11 @@ static uint qt_create_qhash_seed() uint seed = 0; #ifndef QT_BOOTSTRAPPED +#ifdef QHASH_NO_ENV_SEED QByteArray envSeed = qgetenv("QT_HASH_SEED"); if (!envSeed.isNull()) return envSeed.toUInt(); +#endif // QHASH_NO_ENV_SEED #ifdef Q_OS_UNIX int randomfd = qt_safe_open("/dev/urandom", O_RDONLY); @@ -327,8 +337,10 @@ int qGlobalQHashSeed() */ void qSetGlobalQHashSeed(int newSeed) { +#ifdef QHASH_NO_ENV_SEED if (qEnvironmentVariableIsSet("QT_HASH_SEED")) return; +#endif // QHASH_NO_ENV_SEED if (newSeed == -1) { int x(qt_create_qhash_seed() & INT_MAX); qt_qhash_seed.store(x); @@ -1182,6 +1194,9 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW decimal value, will be used as the seed for qHash(). Alternatively, you can call the qSetGlobalQHashSeed() function. + \note The environment variable \c QT_HASH_SEED is unsupported on Windows + Runtime and CE. Use qSetGlobalQHashSeed() instead on those platforms. + \sa QHashIterator, QMutableHashIterator, QMap, QSet */ From 837b5d458970f3981859cb9dfa0cec5fcd6d0c4f Mon Sep 17 00:00:00 2001 From: Tilo Nitzsche Date: Mon, 23 Nov 2015 19:28:25 +0100 Subject: [PATCH 17/50] Fix undefined behavior in qRgba(). Shifting a signed integer that overflows is undefined behavior. All masks were changed to unsigned in qRgb and qRgba. While the alpha value is enough to fix the undefined behavior, Visual C++ generates slow code if not all of those constants are unsigned. Change-Id: Ia0ec3e9464088495173b4ad9c2e37a49e6f8e987 Task-number: QTBUG-49595 Reviewed-by: Thiago Macieira --- src/gui/painting/qrgb.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/painting/qrgb.h b/src/gui/painting/qrgb.h index f7f2185bef..ca9fc03d14 100644 --- a/src/gui/painting/qrgb.h +++ b/src/gui/painting/qrgb.h @@ -58,10 +58,10 @@ inline Q_DECL_CONSTEXPR int qAlpha(QRgb rgb) // get alpha part of { return rgb >> 24; } inline Q_DECL_CONSTEXPR QRgb qRgb(int r, int g, int b)// set RGB value -{ return (0xffu << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff); } +{ return (0xffu << 24) | ((r & 0xffu) << 16) | ((g & 0xffu) << 8) | (b & 0xffu); } inline Q_DECL_CONSTEXPR QRgb qRgba(int r, int g, int b, int a)// set RGBA value -{ return ((a & 0xff) << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff); } +{ return ((a & 0xffu) << 24) | ((r & 0xffu) << 16) | ((g & 0xffu) << 8) | (b & 0xffu); } inline Q_DECL_CONSTEXPR int qGray(int r, int g, int b)// convert R,G,B to gray 0..255 { return (r*11+g*16+b*5)/32; } From 4fd1e5f40c791a920007e842252229826d20c9c9 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Tue, 24 Nov 2015 12:39:23 +0100 Subject: [PATCH 18/50] winrt: Fix text rendering This is a partial revert of aecf3006bddb959795d03dd72d9c520e49713913. The DPI needs to be set inside the constructor to have the text rendering initialize properly. Landscape orientation fix is still valid and the dpi change was unrelated to resolve QTBUG-49470. Task-number: QTBUG-49610 Task-number: QTBUG-49470 Change-Id: I928b8d291b65cd744731c009917804b96253c276 Reviewed-by: Samuel Nevala Reviewed-by: Oliver Wolff --- src/plugins/platforms/winrt/qwinrtscreen.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 158917184c..a642443386 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -507,6 +507,8 @@ QWinRTScreen::QWinRTScreen() hr = d->displayInformation->get_NativeOrientation(&displayOrientation); Q_ASSERT_SUCCEEDED(hr); d->nativeOrientation = static_cast(static_cast(qtOrientationsFromNative(displayOrientation))); + // Set initial pixel density + onDpiChanged(Q_NULLPTR, Q_NULLPTR); d->orientation = d->nativeOrientation; ComPtr applicationViewStatics; @@ -753,7 +755,6 @@ void QWinRTScreen::initialize() Q_ASSERT_SUCCEEDED(hr); hr = d->displayInformation->add_DpiChanged(Callback(this, &QWinRTScreen::onDpiChanged).Get(), &d->displayTokens[&IDisplayInformation::remove_DpiChanged]); Q_ASSERT_SUCCEEDED(hr); - onDpiChanged(Q_NULLPTR, Q_NULLPTR); onOrientationChanged(Q_NULLPTR, Q_NULLPTR); onVisibilityChanged(nullptr, nullptr); } From 0ae8ef7acb96a01f7eada5d0a9e33b6c0ccaca85 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 17 Nov 2015 16:17:29 +0100 Subject: [PATCH 19/50] Simplify a search for terminator. We need to remember where the included file's name starts anyway; if we move this to before the search for the end, we don't need a separate variable to keep track of its length. Change-Id: Ia8d72839ac3fa32f2e748a21ee70dcab614562f4 Reviewed-by: Oswald Buddenhagen --- qmake/generators/makefiledeps.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/qmake/generators/makefiledeps.cpp b/qmake/generators/makefiledeps.cpp index f4479750c8..0f11745f4c 100644 --- a/qmake/generators/makefiledeps.cpp +++ b/qmake/generators/makefiledeps.cpp @@ -596,14 +596,11 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file) continue; } x++; - - int inc_len; - for (inc_len = 0; - buffer[x + inc_len] != term && !qmake_endOfLine(buffer[x + inc_len]); - ++inc_len) {} // skip until end of include name - buffer[x + inc_len] = '\0'; inc = buffer + x; - x += inc_len; + for (; + buffer[x] != term && !qmake_endOfLine(buffer[x]); + ++x) {} // skip until end of include name + buffer[x] = '\0'; } else if (buffer[x] == '\'' || buffer[x] == '"') { const char term = buffer[x++]; while(x < buffer_len) { From f30b75e569332558add552cde2b988c3a65e98cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 16 Nov 2015 14:25:48 +0100 Subject: [PATCH 20/50] xcb: Don't assume creating a window will result in ConfigureNotify event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We assumed that creating a window would always result in a configure notify event, so we delayed sending the initial expose event until receiving the configure notify. That strategy fails in cases where the window does not need a reconfigure after being created, such as when not running a window manager, or when creating child windows. In those cases the window is just mapped, and we ended up never sending an expose event. The problem was masked by sometimes receiving an explicit expose event from X, just after the mapped notification, which we then sent without waiting for configure. Unfortunately we can't rely on this behavior and need to remove the deferred expose event logic, so that we always ensure that at least one expose event is sent to Qt. Change-Id: I702be7f24de2a1e89c085fb6bd95bb8ff7792a27 Reviewed-by: Laszlo Agocs Reviewed-by: Uli Schlachter Reviewed-by: Frederik Gladhorn Reviewed-by: Jędrzej Nowacki --- src/plugins/platforms/xcb/qxcbwindow.cpp | 14 +++----------- src/plugins/platforms/xcb/qxcbwindow.h | 2 -- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index d76f1245e8..6023ee6b29 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -314,8 +314,6 @@ void QXcbWindow::create() destroy(); - m_deferredExpose = false; - m_configureNotifyPending = true; m_windowState = Qt::WindowNoState; Qt::WindowType type = window()->type(); @@ -2022,12 +2020,8 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * if (newScreen != currentScreen) QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); - m_configureNotifyPending = false; - - if (m_deferredExpose) { - m_deferredExpose = false; + if (m_mapped) QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size())); - } if (m_usingSyncProtocol && m_syncState == SyncReceived) m_syncState = SyncAndConfigureReceived; @@ -2094,10 +2088,8 @@ void QXcbWindow::handleMapNotifyEvent(const xcb_map_notify_event_t *event) m_mapped = true; if (m_deferredActivation) requestActivateWindow(); - if (m_configureNotifyPending) - m_deferredExpose = true; - else - QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size())); + + QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size())); } } diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 41c4b4443d..43e66a774d 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -231,8 +231,6 @@ protected: bool m_transparent; bool m_usingSyncProtocol; bool m_deferredActivation; - bool m_deferredExpose; - bool m_configureNotifyPending; bool m_embedded; bool m_alertState; xcb_window_t m_netWmUserTimeWindow; From bb5570082ecbb1494fd39a971f722cc159bf213a Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 24 Nov 2015 08:53:27 +0100 Subject: [PATCH 21/50] tst_QImageWriter: Use QTemporaryDir. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Create a temporary directory instead of writing to the test data directory or home path (Android). Change-Id: I6af583e5da91eefb603eaae179e7d789487dc626 Reviewed-by: aavit Reviewed-by: Jędrzej Nowacki Reviewed-by: Eskil Abrahamsen Blomfeldt --- tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp b/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp index 06c775dded..1dd4d69ea8 100644 --- a/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp +++ b/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp @@ -89,6 +89,7 @@ private slots: void saveToTemporaryFile(); private: + QTemporaryDir m_temporaryDir; QString prefix; QString writePrefix; }; @@ -112,14 +113,11 @@ static void initializePadding(QImage *image) void tst_QImageWriter::initTestCase() { + QVERIFY(m_temporaryDir.isValid()); prefix = QFINDTESTDATA("images/"); if (prefix.isEmpty()) QFAIL("Can't find images directory!"); -#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_NO_SDK) - writePrefix = QDir::homePath(); -#else - writePrefix = prefix; -#endif + writePrefix = m_temporaryDir.path(); } // Testing get/set functions From c7251e7dcd624b8225a2f9b2f14e6f73d1c09a60 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Tue, 24 Nov 2015 10:39:49 +0100 Subject: [PATCH 22/50] Revert "Fix deadlock when setting environment variables." This reverts commit 5b62a5e7aabcc818408f2fe28b9760082f474def. This commit is reverted due to two reasons: 1) It was written incorrectly and does not work as is. The ifdefs should be ifndefs. In its current state, it does the exact opposite of what it is supposed to be doing. 2) There is another environment access inside qsimd.cpp (which checks QT_NO_CPU_FEATURE). This access causes the app to hang. All in all that approach is not sustainable as we might get bitten by environment access again and again. Instead we should use another environment container or use a recursive mutex for WinRT and Windows CE. Task-number: QTBUG-49529 Change-Id: Iaca76404dc1023551a7c25489a609681135765fd Reviewed-by: Andrew Knight Reviewed-by: Samuel Nevala --- src/corelib/tools/qhash.cpp | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/corelib/tools/qhash.cpp b/src/corelib/tools/qhash.cpp index fe49e8c6a8..b334a697a9 100644 --- a/src/corelib/tools/qhash.cpp +++ b/src/corelib/tools/qhash.cpp @@ -38,14 +38,6 @@ #ifndef _CRT_RAND_S #define _CRT_RAND_S #endif - -// Windows Runtime and CE use a QHash to fake environment variables. To avoid -// deadlock, disable reading the QT_HASH_SEED environment variable within -// QHash. -#if defined(Q_OS_WINRT) || defined(Q_OS_WINCE) -# define QHASH_NO_ENV_SEED -#endif - #include #include "qhash.h" @@ -231,11 +223,9 @@ static uint qt_create_qhash_seed() uint seed = 0; #ifndef QT_BOOTSTRAPPED -#ifdef QHASH_NO_ENV_SEED QByteArray envSeed = qgetenv("QT_HASH_SEED"); if (!envSeed.isNull()) return envSeed.toUInt(); -#endif // QHASH_NO_ENV_SEED #ifdef Q_OS_UNIX int randomfd = qt_safe_open("/dev/urandom", O_RDONLY); @@ -337,10 +327,8 @@ int qGlobalQHashSeed() */ void qSetGlobalQHashSeed(int newSeed) { -#ifdef QHASH_NO_ENV_SEED if (qEnvironmentVariableIsSet("QT_HASH_SEED")) return; -#endif // QHASH_NO_ENV_SEED if (newSeed == -1) { int x(qt_create_qhash_seed() & INT_MAX); qt_qhash_seed.store(x); @@ -1194,9 +1182,6 @@ uint qHash(long double key, uint seed) Q_DECL_NOTHROW decimal value, will be used as the seed for qHash(). Alternatively, you can call the qSetGlobalQHashSeed() function. - \note The environment variable \c QT_HASH_SEED is unsupported on Windows - Runtime and CE. Use qSetGlobalQHashSeed() instead on those platforms. - \sa QHashIterator, QMutableHashIterator, QMap, QSet */ From 09b64aa9d338e6e1926bcf45494272565f5fa6bc Mon Sep 17 00:00:00 2001 From: Leena Miettinen Date: Fri, 20 Nov 2015 16:06:48 +0100 Subject: [PATCH 23/50] Doc: add links to new topics in Qt Creator Manual 3.6 Change-Id: I4e317c8dad847c4b4be5e9a9d7c904abc2fa95c7 Reviewed-by: Martin Smith --- doc/global/externalsites/qtcreator.qdoc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/global/externalsites/qtcreator.qdoc b/doc/global/externalsites/qtcreator.qdoc index 95200622f3..b8cd9dec00 100644 --- a/doc/global/externalsites/qtcreator.qdoc +++ b/doc/global/externalsites/qtcreator.qdoc @@ -105,6 +105,10 @@ \externalpage http://doc.qt.io/qtcreator/qtcreator-transitions-example.html \title Qt Creator: Creating a Qt Quick Application */ +/*! + \externalpage http://doc.qt.io/qtcreator/qtquick-iso-icon-browser.html + \title Qt Creator: Browsing ISO 7000 Icons +*/ /*! \externalpage http://doc.qt.io/qtcreator/quick-export-to-qml.html \title Qt Creator: Exporting Designs from Graphics Software @@ -209,6 +213,10 @@ \externalpage http://doc.qt.io/qtcreator/creator-mime-types.html \title Qt Creator: Editing MIME Types */ +/*! + \externalpage http://doc.qt.io/qtcreator/creator-modeling.html + \title Qt Creator: Modeling +*/ /*! \externalpage http://doc.qt.io/qtcreator/creator-qml-debugging-example.html \title Qt Creator: Debugging a Qt Quick Example Application From 1e8863e39dfc72422e76dae214d35268685eb52a Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 24 Nov 2015 08:40:32 +0100 Subject: [PATCH 24/50] tst_QImageReader: Fix file handling. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use a QTemporaryFile in readFromFileAfterJunk() instead writing to the current directory which might not have write permission. Enclose each call to QFile::open() in QVERIFY2() with error message. Change-Id: I3c5da31c6681a2396cee473cafe7d92c5c220de3 Reviewed-by: aavit Reviewed-by: Jędrzej Nowacki --- .../image/qimagereader/tst_qimagereader.cpp | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp index d1e4883cf9..86dd8c4daf 100644 --- a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp +++ b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp @@ -36,7 +36,6 @@ #include #include -#include #include #include #include @@ -46,6 +45,7 @@ #include #include #include +#include #include @@ -53,6 +53,22 @@ typedef QMap QStringMap; typedef QList QIntList; Q_DECLARE_METATYPE(QImage::Format) +static QByteArray msgFileOpenWriteFailed(const QFile &file) +{ + const QString result = QLatin1String("Cannot open \"") + + QDir::toNativeSeparators(file.fileName()) + + QLatin1String("\" for writing: ") + file.errorString(); + return result.toLocal8Bit(); +} + +static QByteArray msgFileOpenReadFailed(const QFile &file) +{ + const QString result = QLatin1String("Cannot open \"") + + QDir::toNativeSeparators(file.fileName()) + + QLatin1String("\" for reading: ") + file.errorString(); + return result.toLocal8Bit(); +} + class tst_QImageReader : public QObject { Q_OBJECT @@ -1051,7 +1067,7 @@ void tst_QImageReader::readFromDevice() const QString imageFileName = prefix + fileName; QImage expectedImage(imageFileName, format); QFile file(imageFileName); - QVERIFY(file.open(QFile::ReadOnly)); + QVERIFY2(file.open(QFile::ReadOnly), msgFileOpenReadFailed(file).constData()); QByteArray imageData = file.readAll(); QVERIFY(!imageData.isEmpty()); { @@ -1129,12 +1145,11 @@ void tst_QImageReader::readFromFileAfterJunk() SKIP_IF_UNSUPPORTED(format); - QFile::remove("junk"); - QFile junkFile("junk"); - QVERIFY(junkFile.open(QFile::WriteOnly)); + QTemporaryFile junkFile(m_temporaryDir.path() + QLatin1String("/junkXXXXXX")); + QVERIFY2(junkFile.open(), msgFileOpenWriteFailed(junkFile).constData()); QFile imageFile(prefix + fileName); - QVERIFY(imageFile.open(QFile::ReadOnly)); + QVERIFY2(imageFile.open(QFile::ReadOnly), msgFileOpenReadFailed(imageFile).constData()); QByteArray imageData = imageFile.readAll(); QVERIFY(!imageData.isNull()); @@ -1155,7 +1170,7 @@ void tst_QImageReader::readFromFileAfterJunk() } } junkFile.close(); - junkFile.open(QFile::ReadOnly); + QVERIFY2(junkFile.open(), msgFileOpenReadFailed(junkFile).constData()); for (int i = 0; i < iterations; ++i) { QByteArray ole = junkFile.read(9); @@ -1205,7 +1220,7 @@ void tst_QImageReader::devicePosition() QVERIFY(!expected.isNull()); QFile imageFile(prefix + fileName); - QVERIFY(imageFile.open(QFile::ReadOnly)); + QVERIFY2(imageFile.open(QFile::ReadOnly), msgFileOpenReadFailed(imageFile).constData()); QByteArray imageData = imageFile.readAll(); QVERIFY(!imageData.isNull()); int imageDataSize = imageData.size(); From a69c0bb38e8edb985417c10793350e40e401fed3 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 23 Oct 2015 09:50:52 +0200 Subject: [PATCH 25/50] tst_QNetworkReply: Fix repetitive invocation of cleanup(). Move the code from cleanup() into a separate cleanupTestData() and call this from initTestData() and cleanup(). Remove slot init(). Change-Id: I4e7b5b89197ed0aa50f46f730e9c1d9c59749614 Reviewed-by: Simon Hausmann --- .../access/qnetworkreply/tst_qnetworkreply.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp index fbeeec2ec4..ce56dcacba 100644 --- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -200,8 +200,7 @@ protected Q_SLOTS: void nestedEventLoops_slot(); private Q_SLOTS: - void init(); - void cleanup(); + void cleanup() { cleanupTestData(); } void initTestCase(); void cleanupTestCase(); @@ -485,6 +484,8 @@ private Q_SLOTS: // NOTE: This test must be last! void parentingRepliesToTheApp(); private: + void cleanupTestData(); + QString testDataDir; }; @@ -1492,6 +1493,8 @@ void tst_QNetworkReply::initTestCase() echoProcessDir = QFINDTESTDATA("echo"); QVERIFY2(!echoProcessDir.isEmpty(), qPrintable( QString::fromLatin1("Couldn't find echo dir starting from %1.").arg(QDir::currentPath()))); + + cleanupTestData(); } void tst_QNetworkReply::cleanupTestCase() @@ -1507,12 +1510,7 @@ void tst_QNetworkReply::cleanupTestCase() #endif } -void tst_QNetworkReply::init() -{ - cleanup(); -} - -void tst_QNetworkReply::cleanup() +void tst_QNetworkReply::cleanupTestData() { QFile file(testFileName); QVERIFY(!file.exists() || file.remove()); From 5c7f000cd4c9e3769e8cd4085cf0beee104f9886 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 18 Nov 2015 15:20:14 +0100 Subject: [PATCH 26/50] Reduce the number of paint events for QOpenGLWidget Changes to other widgets in the window, especially special cases like moving dock widgets around, trigger an unfortunately high number of paint events and calls to paintGL(). Let's try to avoid this. There is no need to send out a paint event to a texture-backed widget when it was not explicitly dirtied. Overlaps won't matter since such widgets are not part of the backingstore. Everything else has to work like ordinary widgets, though, it is only the QPaintEvent sending we can optimize away, nothing else. Task-number: QTBUG-49466 Change-Id: I8ef294ba0a6c305d0002a80e85c06db2c2501cf8 Reviewed-by: Paul Olav Tvete --- src/widgets/kernel/qwidget.cpp | 13 ++++++++++--- src/widgets/kernel/qwidget_p.h | 3 +++ src/widgets/kernel/qwidgetbackingstore.cpp | 3 +++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 0d07eedc0b..94099aac7a 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -271,6 +271,9 @@ QWidgetPrivate::QWidgetPrivate(int version) #ifndef QT_NO_IM , inheritsInputMethodHints(0) #endif +#ifndef QT_NO_OPENGL + , renderToTextureReallyDirty(1) +#endif #if defined(Q_OS_WIN) , noPaintOnScreen(0) #endif @@ -5547,7 +5550,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP << "geometry ==" << QRect(q->mapTo(q->window(), QPoint(0, 0)), q->size()); #endif - bool grabbed = false; + bool skipPaintEvent = false; #ifndef QT_NO_OPENGL if (renderToTexture) { // This widget renders into a texture which is composed later. We just need to @@ -5561,14 +5564,18 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP } else { // We are not drawing to a backingstore: fall back to QImage p.drawImage(q->rect(), grabFramebuffer()); - grabbed = true; + skipPaintEvent = true; } endBackingStorePainting(); } + if (renderToTextureReallyDirty) + renderToTextureReallyDirty = 0; + else + skipPaintEvent = true; } #endif // QT_NO_OPENGL - if (!grabbed) { + if (!skipPaintEvent) { //actually send the paint event sendPaintEvent(toBePainted); } diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index a78cf099ac..7eb8d048b3 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -743,6 +743,9 @@ public: #ifndef QT_NO_IM uint inheritsInputMethodHints : 1; #endif +#ifndef QT_NO_OPENGL + uint renderToTextureReallyDirty : 1; +#endif // *************************** Platform specific ************************************ #if defined(Q_OS_WIN) diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index 9036c28b9a..6d43adc33b 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -1230,6 +1230,9 @@ void QWidgetBackingStore::doSync() QWidget *w = static_cast(tl->source(i)); if (dirtyRenderToTextureWidgets.contains(w)) { const QRect rect = tl->geometry(i); // mapped to the tlw already + // Set a flag to indicate that the paint event for this + // render-to-texture widget must not to be optimized away. + w->d_func()->renderToTextureReallyDirty = 1; dirty += rect; toClean += rect; } From 68d100692b7175f62bdf1c9e5b899cec14d7e259 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Mon, 23 Nov 2015 15:10:46 +0100 Subject: [PATCH 27/50] Doc: added sample to QFileOpenEvent class details MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This sample will help user needing to react on QFileOpenEvent get started faster. Change-Id: I7def292894fc39d803f70cbf0453f6791b7aea15 Reviewed-by: Topi Reiniö --- .../doc/snippets/qfileopenevent/Info.plist | 59 +++++++++++++++ src/gui/doc/snippets/qfileopenevent/main.cpp | 73 +++++++++++++++++++ src/gui/kernel/qevent.cpp | 15 ++++ 3 files changed, 147 insertions(+) create mode 100644 src/gui/doc/snippets/qfileopenevent/Info.plist create mode 100644 src/gui/doc/snippets/qfileopenevent/main.cpp diff --git a/src/gui/doc/snippets/qfileopenevent/Info.plist b/src/gui/doc/snippets/qfileopenevent/Info.plist new file mode 100644 index 0000000000..6b8039bc7d --- /dev/null +++ b/src/gui/doc/snippets/qfileopenevent/Info.plist @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Samuel Gaist +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [Custom Info.plist] + + + + + CFBundleDocumentTypes + + + CFBundleTypeExtensions + + png + + CFBundleTypeRole + Viewer + + + + +//! [Custom Info.plist] \ No newline at end of file diff --git a/src/gui/doc/snippets/qfileopenevent/main.cpp b/src/gui/doc/snippets/qfileopenevent/main.cpp new file mode 100644 index 0000000000..3fd1757bd7 --- /dev/null +++ b/src/gui/doc/snippets/qfileopenevent/main.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Samuel Gaist +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [QApplication subclass] +#include +#include +#include + +class MyApplication : public QApplication +{ +public: + MyApplication(int &argc, char **argv) + : QApplication(argc, argv) + { + } + + bool event(QEvent *event) + { + if (event->type() == QEvent::FileOpen) { + QFileOpenEvent *openEvent = static_cast(event); + qDebug() << "Open file" << openEvent->file(); + } + + return QApplication::event(event); + } +}; +//! [QApplication subclass] + +int main(int argc, char *argv[]) +{ + MyApplication app(argc, argv); + QPushButton closeButton("Quit"); + QObject::connect(&closeButton, &QPushButton::clicked, &app, &QApplication::quit); + closeButton.show(); + return app.exec(); +} diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 0bb21752bc..2ca17692db 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -3417,6 +3417,21 @@ QShowEvent::~QShowEvent() It may be safely ignored. \note This class is currently supported for OS X only. + + \section1 OS X Example + + In order to trigger the event on OS X, the application must be configured + to let the OS know what kind of file(s) it should react on. + + For example, the following \c Info.plist file declares that the application + can act as a viewer for files with a PNG extension: + + \snippet qfileopenevent/Info.plist Custom Info.plist + + The following implementation of a QApplication subclass prints the path to + the file that was, for example, dropped on the Dock icon of the application. + + \snippet qfileopenevent/main.cpp QApplication subclass */ /*! From 2277e3b873ed2dc687ff49b0fc83f38c512748a1 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 20 Nov 2015 10:27:40 +0100 Subject: [PATCH 28/50] Proof-reading fixes to QCoreApplication documentation. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Things I noticed while reading - so I fixed them. Change-Id: I48f6f2eef7ac3cf901e2f1305c503fb18f5ab2ae Reviewed-by: Topi Reiniö --- src/corelib/kernel/qcoreapplication.cpp | 41 +++++++++++++------------ 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index a2a7eed064..aa44d2e74b 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -625,7 +625,7 @@ void QCoreApplicationPrivate::initLocale() \section1 The Event Loop and Event Handling - The event loop is started with a call to exec(). Long running + The event loop is started with a call to exec(). Long-running operations can call processEvents() to keep the application responsive. @@ -707,7 +707,7 @@ QCoreApplication::QCoreApplication(QCoreApplicationPrivate &p) #ifndef QT_NO_QOBJECT /*! - Flushes the platform specific event queues. + Flushes the platform-specific event queues. If you are doing graphical changes inside a loop that does not return to the event loop on asynchronous window systems like X11 @@ -725,9 +725,9 @@ void QCoreApplication::flush() #endif /*! - Constructs a Qt kernel application. Kernel applications are - applications without a graphical user interface. These type of - applications are used at the console or as server processes. + Constructs a Qt core application. Core applications are applications without + a graphical user interface. Such applications are used at the console or as + server processes. The \a argc and \a argv arguments are processed by the application, and made available in a more convenient form by the arguments() @@ -1209,7 +1209,7 @@ void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags) milliseconds or until there are no more events to process, whichever is shorter. - You can call this function occasionally when you program is busy + You can call this function occasionally when your program is busy doing a long operation (e.g. copying a file). Calling this function processes events only for the calling thread. @@ -1236,9 +1236,9 @@ void QCoreApplication::processEvents(QEventLoop::ProcessEventsFlags flags, int m *****************************************************************************/ /*! - Enters the main event loop and waits until exit() is called. - Returns the value that was set to exit() (which is 0 if exit() is - called via quit()). + Enters the main event loop and waits until exit() is called. Returns + the value that was passed to exit() (which is 0 if exit() is called via + quit()). It is necessary to call this function to start event handling. The main event loop receives events from the window system and @@ -1494,7 +1494,8 @@ bool QCoreApplication::compressEvent(QEvent *event, QObject *receiver, QPostEven If \a receiver is null, the events of \a event_type are sent for all objects. If \a event_type is 0, all the events are sent for \a receiver. - \note This method must be called from the same thread as its QObject parameter, \a receiver. + \note This method must be called from the thread in which its QObject + parameter, \a receiver, lives. \sa flush(), postEvent() */ @@ -1840,7 +1841,7 @@ void QCoreApplication::quit() This signal is emitted when the application is about to quit the main event loop, e.g. when the event loop level drops to zero. This may happen either after a call to quit() from inside the - application or when the users shuts down the entire desktop session. + application or when the user shuts down the entire desktop session. The signal is particularly useful if your application has to do some last-second cleanup. Note that no user interaction is possible in @@ -2070,8 +2071,8 @@ void QCoreApplicationPrivate::setApplicationFilePath(const QString &path) directory, and you run the \c{regexp} example, this function will return "C:/Qt/examples/tools/regexp". - On OS X and iOS this will point to the directory actually containing the - executable, which may be inside of an application bundle (if the + On OS X and iOS this will point to the directory actually containing + the executable, which may be inside an application bundle (if the application is bundled). \warning On Linux, this function will try to get the path from the @@ -2684,11 +2685,11 @@ void QCoreApplication::removeLibraryPath(const QString &path) The event filter \a filterObj receives events via its \l {QAbstractNativeEventFilter::}{nativeEventFilter()} function, which is called for all native events received in the main thread. - The QAbstractNativeEventFilter::nativeEventFilter() function should return true if the event should - be filtered, (i.e. stopped). It should return false to allow - normal Qt processing to continue: the native event can then be translated - into a QEvent and handled by the standard Qt \l{QEvent} {event} filtering, - e.g. QObject::installEventFilter(). + The QAbstractNativeEventFilter::nativeEventFilter() function should + return true if the event should be filtered, i.e. stopped. It should + return false to allow normal Qt processing to continue: the native + event can then be translated into a QEvent and handled by the standard + Qt \l{QEvent} {event} filtering, e.g. QObject::installEventFilter(). If multiple event filters are installed, the filter that was installed last is activated first. @@ -2696,7 +2697,7 @@ void QCoreApplication::removeLibraryPath(const QString &path) \note The filter function set here receives native messages, i.e. MSG or XCB event structs. - \note Native event filters will be disabled when the application the + \note Native event filters will be disabled in the application when the Qt::AA_MacPluginApplication attribute is set. For maximum portability, you should always try to use QEvent @@ -2885,7 +2886,7 @@ void QCoreApplication::setEventDispatcher(QAbstractEventDispatcher *eventDispatc \snippet code/src_corelib_kernel_qcoreapplication.cpp 7 The \a context parameter is normally the class name, but it can - be any string. + be any text. \sa Q_OBJECT, QObject::tr(), QObject::trUtf8() */ From 00db6dbc274c763ee75ebe74bec0a586826d3934 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 20 Nov 2015 13:17:38 +0100 Subject: [PATCH 29/50] Ignore stuff created during testing Change-Id: I05c93c9739ff8397606088d0b23e58d145f124a4 Reviewed-by: Oswald Buddenhagen --- tests/auto/tools/qmake/testdata/.gitignore | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 tests/auto/tools/qmake/testdata/.gitignore diff --git a/tests/auto/tools/qmake/testdata/.gitignore b/tests/auto/tools/qmake/testdata/.gitignore new file mode 100644 index 0000000000..1e997b287b --- /dev/null +++ b/tests/auto/tools/qmake/testdata/.gitignore @@ -0,0 +1,5 @@ +# Created by various tests, even for shadow builds: +/pro_file_cache/include.pri +/quotedfilenames/cpp folder/ +/quotedfilenames/quotedfilenames +/resources/resources From d06d7413d5ac22e2c0d65e3144e80da6c716f9f5 Mon Sep 17 00:00:00 2001 From: J-P Nurmi Date: Wed, 25 Nov 2015 11:16:12 +0100 Subject: [PATCH 30/50] Fix QTextLine::cursorToX() 0e99f3c broke tst_qquicktextinput::horizontalAlignment_RightToLeft() and tst_qquicktextedit::hAlign_RightToLeft(). This fix was proposed by Konstantin. Change-Id: I602b7301d415f266224ae2c1ffd81244e9565862 Reviewed-by: Simon Hausmann Reviewed-by: Lars Knoll --- src/gui/text/qtextlayout.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 5f570fea82..65650504ac 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -2627,7 +2627,7 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const const QScriptLine &line = eng->lines[index]; bool lastLine = index >= eng->lines.size() - 1; - QFixed x = line.x; + QFixed x = line.x + eng->alignLine(line) - eng->leadingSpaceWidth(line); if (!eng->layoutData) eng->itemize(); @@ -2636,8 +2636,6 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const return x.toReal(); } - x += eng->alignLine(line) - eng->leadingSpaceWidth(line); - int lineEnd = line.from + line.length + line.trailingSpaces; int pos = qBound(line.from, *cursorPos, lineEnd); int itm; From 9c430bc4c925ca61bc32c39fe0cfb1952553f501 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 25 Nov 2015 09:14:04 +0100 Subject: [PATCH 31/50] QSignalSpy: Improve warning about unregistered parameter types. Don't know how to handle 'hint', use qRegisterMetaType to register it. becomes: QSignalSpy: Unable to handle parameter 'hint' of type 'QAbstractItemModel::LayoutChangeHint' of method 'layoutChanged', use qRegisterMetaType to register it. Task-number: QTBUG-49623 Change-Id: I5020bb5b6f4ba87438d0f862279bed1ceb203d12 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/testlib/qsignalspy.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/testlib/qsignalspy.h b/src/testlib/qsignalspy.h index 1751220059..e9744d0b07 100644 --- a/src/testlib/qsignalspy.h +++ b/src/testlib/qsignalspy.h @@ -175,8 +175,11 @@ private: tp = QMetaType::UnknownType; } if (tp == QMetaType::UnknownType) { - qWarning("Don't know how to handle '%s', use qRegisterMetaType to register it.", - member.parameterNames().at(i).constData()); + qWarning("QSignalSpy: Unable to handle parameter '%s' of type '%s' of method '%s'," + " use qRegisterMetaType to register it.", + member.parameterNames().at(i).constData(), + member.parameterTypes().at(i).constData(), + member.name().constData()); } args << tp; } From 2182d6ae4057afeef3ef41d0dfb0cbec62fa79c4 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 25 Nov 2015 09:30:46 +0100 Subject: [PATCH 32/50] tst_QItemModel: Register QAbstractItemModel::LayoutChangeHint. Silence warning: Don't know how to handle 'hint', use qRegisterMetaType to register it. Task-number: QTBUG-49623 Change-Id: Iec0a823c7af87eddd9a3f126a1b970da1ff2f03f Reviewed-by: Olivier Goffart (Woboq GmbH) --- .../auto/corelib/itemmodels/qitemmodel/tst_qitemmodel.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/auto/corelib/itemmodels/qitemmodel/tst_qitemmodel.cpp b/tests/auto/corelib/itemmodels/qitemmodel/tst_qitemmodel.cpp index 709b35b6e0..6971f7ef78 100644 --- a/tests/auto/corelib/itemmodels/qitemmodel/tst_qitemmodel.cpp +++ b/tests/auto/corelib/itemmodels/qitemmodel/tst_qitemmodel.cpp @@ -49,6 +49,9 @@ class tst_QItemModel : public QObject { Q_OBJECT +public: + tst_QItemModel(); + public slots: void init(); void cleanup(); @@ -124,6 +127,11 @@ private: bool insertRecursively; }; +tst_QItemModel::tst_QItemModel() +{ + qRegisterMetaType(); +} + void tst_QItemModel::init() { testModels = new ModelsToTest(); From 3c56e33a2793eecad5f98632c165fc2cc90f51e4 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 25 Nov 2015 13:46:16 +0100 Subject: [PATCH 33/50] tst_QProcess: Remove macro QPROCESS_VERIFY(). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was used to verify waitForFinished() and printed QProcess::errorString() on failure, which is misleading, since the process is not in an error state - it is still running. Example: QWARN : tst_QProcess::setStandardOutputFileAndWaitForBytesWritten() QProcess error: 5: Unknown error FAIL! : tst_QProcess::setStandardOutputFileAndWaitForBytesWritten() 'ret' returned FALSE. () Use a plain QVERIFY instead. Task-number: QTBUG-47370 Change-Id: Iacfa6e1a5ffd2be4e1257a27a400ccc59671e8c8 Reviewed-by: Jędrzej Nowacki --- .../auto/corelib/io/qprocess/tst_qprocess.cpp | 22 ++++++------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp index 45d6cf3dcd..ca5f527b8b 100644 --- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp +++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp @@ -54,14 +54,6 @@ Q_DECLARE_METATYPE(QProcess::ExitStatus); Q_DECLARE_METATYPE(QProcess::ProcessState); #endif -#define QPROCESS_VERIFY(Process, Fn) \ -{ \ -const bool ret = Process.Fn; \ -if (ret == false) \ - qWarning("QProcess error: %d: %s", Process.error(), qPrintable(Process.errorString())); \ -QVERIFY(ret); \ -} - typedef void (QProcess::*QProcessFinishedSignal1)(int); typedef void (QProcess::*QProcessFinishedSignal2)(int, QProcess::ExitStatus); typedef void (QProcess::*QProcessErrorSignal)(QProcess::ProcessError); @@ -1957,7 +1949,7 @@ void tst_QProcess::setStandardInputFile() process.setStandardInputFile("data"); process.start("testProcessEcho/testProcessEcho"); - QPROCESS_VERIFY(process, waitForFinished()); + QVERIFY(process.waitForFinished()); QCOMPARE(process.exitStatus(), QProcess::NormalExit); QCOMPARE(process.exitCode(), 0); QByteArray all = process.readAll(); @@ -1967,7 +1959,7 @@ void tst_QProcess::setStandardInputFile() QProcess process2; process2.setStandardInputFile(QProcess::nullDevice()); process2.start("testProcessEcho/testProcessEcho"); - QPROCESS_VERIFY(process2, waitForFinished()); + QVERIFY(process2.waitForFinished()); all = process2.readAll(); QCOMPARE(all.size(), 0); } @@ -2031,7 +2023,7 @@ void tst_QProcess::setStandardOutputFile() process.start("testProcessEcho2/testProcessEcho2"); process.write(testdata, sizeof testdata); - QPROCESS_VERIFY(process,waitForFinished()); + QVERIFY(process.waitForFinished()); QCOMPARE(process.exitStatus(), QProcess::NormalExit); QCOMPARE(process.exitCode(), 0); @@ -2062,7 +2054,7 @@ void tst_QProcess::setStandardOutputFileNullDevice() process.setStandardOutputFile(QProcess::nullDevice()); process.start("testProcessEcho2/testProcessEcho2"); process.write(testdata, sizeof testdata); - QPROCESS_VERIFY(process,waitForFinished()); + QVERIFY(process.waitForFinished()); QCOMPARE(process.exitStatus(), QProcess::NormalExit); QCOMPARE(process.exitCode(), 0); QCOMPARE(process.bytesAvailable(), Q_INT64_C(0)); @@ -2080,7 +2072,7 @@ void tst_QProcess::setStandardOutputFileAndWaitForBytesWritten() process.start("testProcessEcho2/testProcessEcho2"); process.write(testdata, sizeof testdata); process.waitForBytesWritten(); - QPROCESS_VERIFY(process, waitForFinished()); + QVERIFY(process.waitForFinished()); QCOMPARE(process.exitStatus(), QProcess::NormalExit); QCOMPARE(process.exitCode(), 0); @@ -2122,10 +2114,10 @@ void tst_QProcess::setStandardOutputProcess() if (waitForBytesWritten) source.waitForBytesWritten(); source.closeWriteChannel(); - QPROCESS_VERIFY(source, waitForFinished()); + QVERIFY(source.waitForFinished()); QCOMPARE(source.exitStatus(), QProcess::NormalExit); QCOMPARE(source.exitCode(), 0); - QPROCESS_VERIFY(sink, waitForFinished()); + QVERIFY(sink.waitForFinished()); QCOMPARE(sink.exitStatus(), QProcess::NormalExit); QCOMPARE(sink.exitCode(), 0); QByteArray all = sink.readAll(); From eaf160c5861eed34410ea28b8725c4a0eb423cc1 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 19 Nov 2015 15:20:05 +0100 Subject: [PATCH 34/50] Add a manual test for cursors in multi-screen/High DPI setups. Change-Id: I4c0baeaf01f0b3d6162a16ef7fda822f5a4cb1db Task-number: QTBUG-49511 Reviewed-by: Joerg Bornemann --- tests/manual/qcursor/qcursor.pro | 2 +- tests/manual/qcursor/qcursorhighdpi/main.cpp | 321 ++++++++++++++++++ .../qcursor/qcursorhighdpi/qcursorhighdpi.pro | 6 + 3 files changed, 328 insertions(+), 1 deletion(-) create mode 100644 tests/manual/qcursor/qcursorhighdpi/main.cpp create mode 100644 tests/manual/qcursor/qcursorhighdpi/qcursorhighdpi.pro diff --git a/tests/manual/qcursor/qcursor.pro b/tests/manual/qcursor/qcursor.pro index af082a4b82..0b5c2b1945 100644 --- a/tests/manual/qcursor/qcursor.pro +++ b/tests/manual/qcursor/qcursor.pro @@ -1,3 +1,3 @@ TEMPLATE = subdirs -SUBDIRS = allcursors grab_override +SUBDIRS = allcursors grab_override qcursorhighdpi diff --git a/tests/manual/qcursor/qcursorhighdpi/main.cpp b/tests/manual/qcursor/qcursorhighdpi/main.cpp new file mode 100644 index 0000000000..fc45ae00d1 --- /dev/null +++ b/tests/manual/qcursor/qcursorhighdpi/main.cpp @@ -0,0 +1,321 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#if QT_VERSION > 0x050000 +# include +# include +# include +# include +#else +# define Q_NULLPTR 0 +# define Q_DECL_OVERRIDE +#endif + +#ifdef Q_OS_WIN +# include +#endif + +#include +#include + +// High DPI cursor test for testing cursor sizes in multi-screen setups. +// It creates one widget per screen with a grid of standard cursors, +// pixmap / bitmap cursors and pixmap / bitmap cursors with device pixel ratio 2. +// On the left, there is a ruler with 10 DIP marks. +// The code is meant to compile with Qt 4 also. + +static QString screenInfo(const QWidget *w) +{ + QString result; + QTextStream str(&result); +#if QT_VERSION > 0x050000 + QScreen *screen = Q_NULLPTR; + if (const QWindow *window = w->windowHandle()) + screen = window->screen(); + if (screen) { + str << '"' << screen->name() << "\" " << screen->size().width() << 'x' + << screen->size().height() << ", DPR=" << screen->devicePixelRatio() + << ", " << screen->logicalDotsPerInchX() << "DPI "; + if (QHighDpiScaling::isActive()) + str << ", factor=" << QHighDpiScaling::factor(screen); + else + str << ", no scaling"; + } else { + str << ""; + } +#else + QDesktopWidget *desktop = QApplication::desktop(); + int screenNumber = desktop->screenNumber(w); + str << "Screen #" <screenGeometry(screenNumber).width() + << 'x' << desktop->screenGeometry(screenNumber).height() << " PD: " << w->logicalDpiX() << "DPI"; +#endif +#ifdef Q_OS_WIN + str << ", SM_C_CURSOR: " << GetSystemMetrics(SM_CXCURSOR) << 'x' << GetSystemMetrics(SM_CYCURSOR); +#endif + return result; +} + +// Helpers for painting pixmaps and creating cursors +static QPixmap paintPixmap(int size, QColor c) +{ + QPixmap result(size, size); + result.fill(c); + QPainter p(&result); + p.drawRect(QRect(QPoint(0, 0), result.size() - QSize(1, 1))); + p.drawLine(0, 0, size, size); + p.drawLine(0, size, size, 0); + return result; +} + +static QCursor pixmapCursor(int size) +{ + QCursor result(paintPixmap(size, Qt::red), size / 2, size / 2); + return result; +} + +static QPair paintBitmaps(int size) +{ + QBitmap bitmap(size, size); + bitmap.fill(Qt::color1); + QBitmap mask(size, size); + mask.fill(Qt::color1); + { + QPainter mp(&mask); + mp.fillRect(QRect(0, 0, size / 2, size / 2), Qt::color0); + } + return QPair(bitmap, mask); +} + +static QCursor bitmapCursor(int size) +{ + QPair bitmaps = paintBitmaps(size); + return QCursor(bitmaps.first, bitmaps.second, size / 2, size / 2); +} + +#if QT_VERSION > 0x050000 +static QCursor pixmapCursorDevicePixelRatio(int size, int dpr) +{ + QPixmap pixmap = paintPixmap(dpr * size, Qt::yellow); + pixmap.setDevicePixelRatio(dpr); + return QCursor(pixmap, size / 2, size / 2); +} + +static QCursor bitmapCursorDevicePixelRatio(int size, int dpr) +{ + QPair bitmaps = paintBitmaps(dpr * size); + bitmaps.first.setDevicePixelRatio(dpr); + bitmaps.second.setDevicePixelRatio(dpr); + return QCursor(bitmaps.first, bitmaps.second, size / 2, size / 2); +} +#endif // Qt 5 + +// Vertical ruler widget with 10 px marks +class VerticalRuler : public QWidget { +public: + VerticalRuler(QWidget *parent = Q_NULLPTR); + +protected: + void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE; +}; + +VerticalRuler::VerticalRuler(QWidget *parent) : QWidget(parent) +{ + const int screenWidth = QApplication::desktop()->screenGeometry(this).width(); + setFixedWidth(screenWidth / 48); // 1920 pixel monitor ->40 +} + +void VerticalRuler::paintEvent(QPaintEvent *) +{ + const QSize sizeS(size()); + const QPoint sizeP(sizeS.width(), sizeS.height()); + const QPoint center = sizeP / 2; + QPainter painter(this); + painter.fillRect(QRect(QPoint(0, 0), sizeS), Qt::white); + painter.drawLine(center.x(), 0, center.x(), sizeP.y()); + for (int y = 0; y < sizeP.y(); y += 10) + painter.drawLine(center.x() - 5, y, center.x() + 5, y); +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT +public: + explicit MainWindow(QWidget *parent = Q_NULLPTR); + void updateScreenInfo() { m_screenInfoLabel->setText(screenInfo(this)); } + +public slots: + void screenChanged() { updateScreenInfo(); } + +private: + QLabel *m_screenInfoLabel; +}; + +static QLabel *createCursorLabel(const QCursor &cursor, const QString &additionalText = QString()) +{ + QString labelText; + QDebug(&labelText).nospace() << cursor.shape(); +#if QT_VERSION > 0x050000 + labelText.remove(0, labelText.indexOf('(') + 1); + labelText.chop(1); +#endif // Qt 5 + if (!additionalText.isEmpty()) + labelText += ' ' + additionalText; + QLabel *result = new QLabel(labelText); + result->setFrameShape(QFrame::Box); + result->setCursor(cursor); + return result; +} + +static void addToGrid(QWidget *w, QGridLayout *gridLayout, int columnCount, int &row, int &col) +{ + gridLayout->addWidget(w, row, col); + if (col >= columnCount) { + col = 0; + row++; + } else { + col++; + } +} + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) + , m_screenInfoLabel(new QLabel) +{ + QString title = "Cursors "; +#if QT_VERSION > 0x050000 + title += '(' + QGuiApplication::platformName() + ") "; +#endif + title += QT_VERSION_STR; + setWindowTitle(title); + + QMenu *fileMenu = menuBar()->addMenu("File"); + QAction *quitAction = fileMenu->addAction("Quit"); + quitAction->setShortcut(Qt::CTRL + Qt::Key_Q); + connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); + + QToolBar *fileToolBar = addToolBar("File"); + fileToolBar->addAction(quitAction); + + QWidget *cw = new QWidget; + QHBoxLayout *hLayout = new QHBoxLayout(cw); + hLayout->addWidget(new VerticalRuler(cw)); + QGridLayout *gridLayout = new QGridLayout; + hLayout->addLayout(gridLayout); + + const int columnCount = 5; + const int size = 32; + + int row = 0; + int col = 0; + for (int i = 0; i < Qt::BitmapCursor; ++i) + addToGrid(createCursorLabel(QCursor(static_cast(i))), gridLayout, columnCount, row, col); + + addToGrid(createCursorLabel(QCursor(pixmapCursor(size)), + QLatin1String("Plain PX ") + QString::number(size)), + gridLayout, columnCount, row, col); + + addToGrid(createCursorLabel(bitmapCursor(size), + QLatin1String("Plain BM ") + QString::number(size)), + gridLayout, columnCount, row, col); + +#if QT_VERSION > 0x050000 + addToGrid(createCursorLabel(QCursor(pixmapCursorDevicePixelRatio(size, 2)), + "PX with DPR 2 " + QString::number(size)), + gridLayout, columnCount, row, col); + + addToGrid(createCursorLabel(QCursor(bitmapCursorDevicePixelRatio(size, 2)), + "BM with DPR 2 " + QString::number(size)), + gridLayout, columnCount, row, col); +#endif // Qt 5 + + gridLayout->addWidget(m_screenInfoLabel, row + 1, 0, 1, columnCount); + + setCentralWidget(cw); +} + +typedef QSharedPointer MainWindowPtr; +typedef QList MainWindowPtrList; + +int main(int argc, char *argv[]) +{ + QStringList arguments; + std::copy(argv + 1, argv + argc, std::back_inserter(arguments)); + +#if QT_VERSION > 0x050000 + if (arguments.contains("-s")) + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + else if (arguments.contains("-n")) + QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling); +#endif // Qt 5 + + QApplication app(argc, argv); + + MainWindowPtrList windows; + + QDesktopWidget *desktopWidget = app.desktop(); + + for (int s = desktopWidget->screenCount() - 1; s >= 0; --s) { + MainWindowPtr window(new MainWindow(desktopWidget->screen(s))); + const QPoint pos = desktopWidget->screenGeometry(s).center() - QPoint(200, 100); + window->move(pos); + windows.append(window); + window->show(); + window->updateScreenInfo(); +#if QT_VERSION > 0x050000 + QObject::connect(window->windowHandle(), &QWindow::screenChanged, + window.data(), &MainWindow::updateScreenInfo); +#endif + } + return app.exec(); +} +#include "main.moc" diff --git a/tests/manual/qcursor/qcursorhighdpi/qcursorhighdpi.pro b/tests/manual/qcursor/qcursorhighdpi/qcursorhighdpi.pro new file mode 100644 index 0000000000..3a8fc25b33 --- /dev/null +++ b/tests/manual/qcursor/qcursorhighdpi/qcursorhighdpi.pro @@ -0,0 +1,6 @@ +TEMPLATE = app +QT = core gui +greaterThan(QT_MAJOR_VERSION, 4): QT += gui-private core-private widgets +CONFIG -= app_bundle +SOURCES += main.cpp +win32: LIBS += -lUser32 From 9b28fd5bfcedef16e2f4c59124f0628670f96556 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 24 Nov 2015 14:30:10 +0100 Subject: [PATCH 35/50] Fix inplaceRgbConversion test on non-x86 We test that inline conversion between same image depths always succeed inline, but that requires that any direct conversions exists both in non-inline and inline versions. This patch adds a non-sse2 inline conversion from ARGB32 to ARGB32PM which was missing. Change-Id: I71937cd4b77fb41fe2064da937f6dcbf2a6534e6 Reviewed-by: Gunnar Sletta --- src/gui/image/qimage_conversions.cpp | 32 +++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index 02f32aa34b..8e0e53c58d 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -375,7 +375,32 @@ static void convert_RGB888_to_RGB(QImageData *dest, const QImageData *src, Qt::I } } +#ifdef __SSE2__ extern bool convert_ARGB_to_ARGB_PM_inplace_sse2(QImageData *data, Qt::ImageConversionFlags); +#else +static bool convert_ARGB_to_ARGB_PM_inplace(QImageData *data,Qt::ImageConversionFlags) +{ + Q_ASSERT(data->format == QImage::Format_ARGB32 || data->format == QImage::Format_RGBA8888); + + const int pad = (data->bytes_per_line >> 2) - data->width; + QRgb *rgb_data = (QRgb *) data->data; + + for (int i = 0; i < data->height; ++i) { + const QRgb *end = rgb_data + data->width; + while (rgb_data < end) { + *rgb_data = qPremultiply(*rgb_data); + ++rgb_data; + } + rgb_data += pad; + } + + if (data->format == QImage::Format_ARGB32) + data->format = QImage::Format_ARGB32_Premultiplied; + else + data->format = QImage::Format_RGBA8888_Premultiplied; + return true; +} +#endif static void convert_ARGB_to_RGBx(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) { @@ -2592,7 +2617,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma #ifdef __SSE2__ convert_ARGB_to_ARGB_PM_inplace_sse2, #else - 0, + convert_ARGB_to_ARGB_PM_inplace, #endif 0, 0, @@ -2705,12 +2730,13 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, mask_alpha_converter_rgbx_inplace, -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN && __SSE2__ 0, +#ifdef __SSE2__ convert_ARGB_to_ARGB_PM_inplace_sse2, +#elif Q_BYTE_ORDER == Q_LITTLE_ENDIAN + convert_ARGB_to_ARGB_PM_inplace, #else 0, - 0, #endif 0, 0, 0, 0, 0, 0 }, // Format_RGBA8888 From 980f8aed32403527e2922c2c671bbe29a6911c70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 19 Oct 2015 14:11:28 +0200 Subject: [PATCH 36/50] iOS: Add support for delivering touch pressure on iPhone 6s/6s+ devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As 3D touch can be disabled/enabled at runtime on those devices, we need to watch for changes to the relevant settings and update the touch device capabilities that we report to the user. Note that iOS will deliver touchesBegan with a touch force of 0, which we will reflect/propagate as a 0 pressure, but there is no clear alternative, as we don't want to wait for a touchedMoved before sending a touch press event to Qt, just to have a valid pressure. Change-Id: I47fb8a9f98ab3244e16a337bbfcf1fe24e4c7aa2 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiosintegration.mm | 10 +++++-- src/plugins/platforms/ios/quiview.mm | 29 ++++++++++++++++++-- 2 files changed, 33 insertions(+), 6 deletions(-) diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm index eaff0daf19..0e3da8dce8 100644 --- a/src/plugins/platforms/ios/qiosintegration.mm +++ b/src/plugins/platforms/ios/qiosintegration.mm @@ -89,10 +89,11 @@ QIOSIntegration::QIOSIntegration() // Set current directory to app bundle folder QDir::setCurrent(QString::fromUtf8([[[NSBundle mainBundle] bundlePath] UTF8String])); + UIScreen *mainScreen = [UIScreen mainScreen]; NSMutableArray *screens = [[[UIScreen screens] mutableCopy] autorelease]; - if (![screens containsObject:[UIScreen mainScreen]]) { + if (![screens containsObject:mainScreen]) { // Fallback for iOS 7.1 (QTBUG-42345) - [screens insertObject:[UIScreen mainScreen] atIndex:0]; + [screens insertObject:mainScreen atIndex:0]; } for (UIScreen *screen in screens) @@ -103,7 +104,10 @@ QIOSIntegration::QIOSIntegration() m_touchDevice = new QTouchDevice; m_touchDevice->setType(QTouchDevice::TouchScreen); - m_touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::NormalizedPosition); + QTouchDevice::Capabilities touchCapabilities = QTouchDevice::Position | QTouchDevice::NormalizedPosition; + if (mainScreen.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) + touchCapabilities |= QTouchDevice::Pressure; + m_touchDevice->setCapabilities(touchCapabilities); QWindowSystemInterface::registerTouchDevice(m_touchDevice); QMacInternalPasteboardMime::initializeMimeTypes(); } diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index c6ef843b9f..53b3d30327 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -280,6 +280,19 @@ // ------------------------------------------------------------------------- +- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection +{ + [super traitCollectionDidChange: previousTraitCollection]; + + QTouchDevice *touchDevice = QIOSIntegration::instance()->touchDevice(); + QTouchDevice::Capabilities touchCapabilities = touchDevice->capabilities(); + if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) + touchCapabilities |= QTouchDevice::Pressure; + else + touchCapabilities &= ~QTouchDevice::Pressure; + touchDevice->setCapabilities(touchCapabilities); +} + -(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { if (m_qioswindow->window()->flags() & Qt::WindowTransparentForInput) @@ -289,6 +302,8 @@ - (void)updateTouchList:(NSSet *)touches withState:(Qt::TouchPointState)state { + bool supportsPressure = QIOSIntegration::instance()->touchDevice()->capabilities() & QTouchDevice::Pressure; + foreach (UITouch *uiTouch, m_activeTouches.keys()) { QWindowSystemInterface::TouchPoint &touchPoint = m_activeTouches[uiTouch]; if (![touches containsObject:uiTouch]) { @@ -309,9 +324,17 @@ touchPoint.normalPosition = QPointF(globalScreenPosition.x() / screenSize.width(), globalScreenPosition.y() / screenSize.height()); - // We don't claim that our touch device supports QTouchDevice::Pressure, - // but fill in a meaningfull value in case clients use it anyways. - touchPoint.pressure = (state == Qt::TouchPointReleased) ? 0.0 : 1.0; + if (supportsPressure) { + // Note: iOS will deliver touchesBegan with a touch force of 0, which + // we will reflect/propagate as a 0 pressure, but there is no clear + // alternative, as we don't want to wait for a touchedMoved before + // sending a touch press event to Qt, just to have a valid pressure. + touchPoint.pressure = uiTouch.force / uiTouch.maximumPossibleForce; + } else { + // We don't claim that our touch device supports QTouchDevice::Pressure, + // but fill in a meaningfull value in case clients use it anyways. + touchPoint.pressure = (state == Qt::TouchPointReleased) ? 0.0 : 1.0; + } } } } From 79447068579ea93d616d840bb8cbbf8adb1ed6ec Mon Sep 17 00:00:00 2001 From: Nicolas Capens Date: Tue, 10 Nov 2015 00:03:34 -0500 Subject: [PATCH 37/50] Fix potential division by zero. In a Chrome Remote Desktop session the htotal and/or vtotal timings can be zero and lead to a SIGFPE exception. Task-number: QTBUG-49322 Change-Id: Id530335cc760d1938ed888ad095427fcf32c651d Reviewed-by: Oswald Buddenhagen Reviewed-by: Nicolas Capens Reviewed-by: Gatis Paeglis --- src/plugins/platforms/xcb/qxcbscreen.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 2a53b18890..0e99d58679 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -558,7 +558,8 @@ void QXcbScreen::updateRefreshRate(xcb_randr_mode_t mode) for (; modesIter.rem; xcb_randr_mode_info_next(&modesIter)) { xcb_randr_mode_info_t *modeInfo = modesIter.data; if (modeInfo->id == mode) { - m_refreshRate = modeInfo->dot_clock / (modeInfo->htotal * modeInfo->vtotal); + const uint32_t dotCount = modeInfo->htotal * modeInfo->vtotal; + m_refreshRate = (dotCount != 0) ? modeInfo->dot_clock / dotCount : 0; m_mode = mode; break; } From 5c446031c3d570d9126e50b658199ca2a1e37eba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Thu, 26 Nov 2015 14:19:55 +0100 Subject: [PATCH 38/50] iOS: Map `make install` to `xcodebuild build` for the iOS simulator The xcodebuild tool only supports the install action for devices, not for the iOS simulator platform. Change-Id: I47e8bb7d44962bd4a433a314fa9d315ed3683ca6 Reviewed-by: Richard Moe Gustavsen --- mkspecs/macx-ios-clang/xcodebuild.mk | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mkspecs/macx-ios-clang/xcodebuild.mk b/mkspecs/macx-ios-clang/xcodebuild.mk index afe331240b..1bd18430df 100644 --- a/mkspecs/macx-ios-clang/xcodebuild.mk +++ b/mkspecs/macx-ios-clang/xcodebuild.mk @@ -40,6 +40,10 @@ $(EXPORT_SUBTARGETS): % : %-build %-install: ACTION = install %-install: xcodebuild-% ; +# iOS Simulator doesn't support archiving +%-iphonesimulator-install: ACTION = build +iphonesimulator-install: ACTION = build + # Limit check to a single configuration %-iphoneos-check: check-iphoneos ; %-iphonesimulator-check: check-iphonesimulator ; From 07fdfa559844403d0836ab0783f201b50a9961af Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Thu, 12 Nov 2015 15:50:00 +0100 Subject: [PATCH 39/50] Detect NEON on AArch64 The __ARM_NEON is the standard define for NEON instructions support __ARM_NEON__ is only legacy, and specifically not defined in AArch64 builds, which causes us not to detect NEON support there. The NEON assembler files doesn't build with AArch64, so the NEON drawhelper methods must be excluded for now. Change-Id: Ie32f855bde94ee7efd8a8ddb7766c931778e729b Reviewed-by: Thiago Macieira --- config.tests/arch/arch.cpp | 2 +- src/corelib/tools/qsimd_p.h | 6 +++++- src/gui/painting/painting.pri | 2 +- src/gui/painting/qdrawhelper.cpp | 4 ++-- src/gui/painting/qdrawhelper_neon.cpp | 4 +--- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/config.tests/arch/arch.cpp b/config.tests/arch/arch.cpp index 7e481d4cf5..c4f23f7bcd 100644 --- a/config.tests/arch/arch.cpp +++ b/config.tests/arch/arch.cpp @@ -237,7 +237,7 @@ const char msg2[] = "==Qt=magic=Qt== Sub-architecture:" #endif // -- ARM -- -#ifdef __ARM_NEON__ +#if defined(__ARM_NEON) || defined(__ARM_NEON__) " neon" #endif #ifdef __IWMMXT__ diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h index 1e8b3420cf..12a329f36c 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -250,9 +250,13 @@ // NEON intrinsics // note: as of GCC 4.9, does not support function targets for ARM -#if defined __ARM_NEON__ +#if defined(__ARM_NEON) || defined(__ARM_NEON__) #include #define QT_FUNCTION_TARGET_STRING_ARM_NEON "neon" +#ifndef __ARM_NEON__ +// __ARM_NEON__ is not defined on AArch64, but we need it in our NEON detection. +#define __ARM_NEON__ +#endif #endif #undef QT_COMPILER_SUPPORTS_SIMD_ALWAYS diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 2e2532a25f..fd9ae0aaca 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -101,7 +101,7 @@ SSE4_1_SOURCES += painting/qdrawhelper_sse4.cpp \ painting/qimagescale_sse4.cpp AVX2_SOURCES += painting/qdrawhelper_avx2.cpp -!ios { +!ios:!contains(QT_ARCH, "arm64") { CONFIG += no_clang_integrated_as NEON_SOURCES += painting/qdrawhelper_neon.cpp NEON_HEADERS += painting/qdrawhelper_neon_p.h diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 52843fa113..988bee9b27 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -6309,7 +6309,7 @@ void qt_memfill16(quint16 *dest, quint16 color, int count) qt_memfill_template(dest, color, count); } #endif -#if !defined(__SSE2__) && !defined(__ARM_NEON__) +#if !defined(__SSE2__) && (!defined(__ARM_NEON__) || defined(Q_PROCESSOR_ARM_64)) # ifdef QT_COMPILER_SUPPORTS_MIPS_DSP extern "C" void qt_memfill32_asm_mips_dsp(quint32 *, quint32, int); # endif @@ -6425,7 +6425,7 @@ void qInitDrawhelperAsm() #endif // SSE2 -#if defined(__ARM_NEON__) && !defined(Q_OS_IOS) +#if defined(__ARM_NEON__) && !defined(Q_OS_IOS) && !defined(Q_PROCESSOR_ARM_64) qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon; qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon; qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon; diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp index 08e564f017..bf4758afd2 100644 --- a/src/gui/painting/qdrawhelper_neon.cpp +++ b/src/gui/painting/qdrawhelper_neon.cpp @@ -31,15 +31,13 @@ ** ****************************************************************************/ -#include +#include #include #include #ifdef __ARM_NEON__ -#include #include -#include QT_BEGIN_NAMESPACE From acc3df2c4e65fac822fc0f69d9849f1996130741 Mon Sep 17 00:00:00 2001 From: Ilya Kotov Date: Sun, 22 Nov 2015 13:05:38 +0300 Subject: [PATCH 40/50] Send QEvent::Tooltip to QSystemTrayIcon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QSystemTrayIcon's window should send QEvent::ToolTip to QSystemTrayIcon main class under X11. This patch fixes regression inroduced in Qt 5.0. Change-Id: I81f6d85e13f492e5e7d13dacc44185a511e5085d Task-number: QTBUG-46130 Reviewed-by: Błażej Szczygieł Reviewed-by: Laszlo Agocs --- src/widgets/util/qsystemtrayicon.cpp | 6 ------ src/widgets/util/qsystemtrayicon_x11.cpp | 3 +++ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/widgets/util/qsystemtrayicon.cpp b/src/widgets/util/qsystemtrayicon.cpp index d22791048f..31bbbb9739 100644 --- a/src/widgets/util/qsystemtrayicon.cpp +++ b/src/widgets/util/qsystemtrayicon.cpp @@ -284,12 +284,6 @@ bool QSystemTrayIcon::isVisible() const */ bool QSystemTrayIcon::event(QEvent *e) { -#if defined(Q_DEAD_CODE_FROM_QT4_X11) - if (e->type() == QEvent::ToolTip) { - Q_D(QSystemTrayIcon); - return d->sys->deliverToolTipEvent(e); - } -#endif return QObject::event(e); } diff --git a/src/widgets/util/qsystemtrayicon_x11.cpp b/src/widgets/util/qsystemtrayicon_x11.cpp index 9a69db1bc8..02bab236c8 100644 --- a/src/widgets/util/qsystemtrayicon_x11.cpp +++ b/src/widgets/util/qsystemtrayicon_x11.cpp @@ -194,6 +194,9 @@ void QSystemTrayIconSys::mouseDoubleClickEvent(QMouseEvent *ev) bool QSystemTrayIconSys::event(QEvent *e) { switch (e->type()) { + case QEvent::ToolTip: + QApplication::sendEvent(q, e); + break; #ifndef QT_NO_WHEELEVENT case QEvent::Wheel: return QApplication::sendEvent(q, e); From 19e295b330db4b34570c1719b0b69e531288cbd0 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 26 Nov 2015 12:03:39 +0100 Subject: [PATCH 41/50] tst_QWaitCondition: Prevent test functions from interfering with each other. Introduce a base class for the threads that ensures termination in the destructor to ensure all QThreads instantiated on the stack are terminated. This should reduce crashes since the test thread classes have pointers to stack variables of the test slots. Set object names on the threads for better diagnostics. Decouple wakeOne()/wakeAll() that impact each other via the static count variables of the thread class by introducing a base class WakeThreadBase keeping a pointer to an QAtomicInt count variable on the stack instead (similar to the existing pointers to the mutexes, etc). Task-number: QTBUG-49653 Change-Id: I73537386bf36019efa81e8e24ba9af92506f7794 Reviewed-by: Frederik Gladhorn --- .../qwaitcondition/tst_qwaitcondition.cpp | 141 +++++++++++++----- 1 file changed, 106 insertions(+), 35 deletions(-) diff --git a/tests/auto/corelib/thread/qwaitcondition/tst_qwaitcondition.cpp b/tests/auto/corelib/thread/qwaitcondition/tst_qwaitcondition.cpp index dea305e3e1..6a2ea7c73c 100644 --- a/tests/auto/corelib/thread/qwaitcondition/tst_qwaitcondition.cpp +++ b/tests/auto/corelib/thread/qwaitcondition/tst_qwaitcondition.cpp @@ -33,6 +33,7 @@ #include +#include #include #include #include @@ -54,7 +55,25 @@ private slots: static const int iterations = 4; static const int ThreadCount = 4; -class wait_QMutex_Thread_1 : public QThread +// Terminate thread in destructor for threads instantiated on the stack +class TerminatingThread : public QThread +{ +public: + explicit TerminatingThread() + { + setTerminationEnabled(true); + } + + ~TerminatingThread() + { + if (isRunning()) { + qWarning() << "forcibly terminating " << objectName(); + terminate(); + } + } +}; + +class wait_QMutex_Thread_1 : public TerminatingThread { public: QMutex mutex; @@ -72,7 +91,7 @@ public: } }; -class wait_QMutex_Thread_2 : public QThread +class wait_QMutex_Thread_2 : public TerminatingThread { public: QWaitCondition started; @@ -93,7 +112,7 @@ public: } }; -class wait_QReadWriteLock_Thread_1 : public QThread +class wait_QReadWriteLock_Thread_1 : public TerminatingThread { public: QReadWriteLock readWriteLock; @@ -111,7 +130,7 @@ public: } }; -class wait_QReadWriteLock_Thread_2 : public QThread +class wait_QReadWriteLock_Thread_2 : public TerminatingThread { public: QWaitCondition started; @@ -155,7 +174,11 @@ void tst_QWaitCondition::wait_QMutex() // test multiple threads waiting on separate wait conditions wait_QMutex_Thread_1 thread[ThreadCount]; + const QString prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_mutex_") + + QString::number(i) + QLatin1Char('_'); + for (x = 0; x < ThreadCount; ++x) { + thread[x].setObjectName(prefix + QString::number(x)); thread[x].mutex.lock(); thread[x].start(); // wait for thread to start @@ -185,8 +208,12 @@ void tst_QWaitCondition::wait_QMutex() QWaitCondition cond1, cond2; wait_QMutex_Thread_2 thread[ThreadCount]; + const QString prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_mutex_") + + QString::number(i) + QLatin1Char('_'); + mutex.lock(); for (x = 0; x < ThreadCount; ++x) { + thread[x].setObjectName(prefix + QString::number(x)); thread[x].mutex = &mutex; thread[x].cond = (x < ThreadCount / 2) ? &cond1 : &cond2; thread[x].start(); @@ -289,7 +316,10 @@ void tst_QWaitCondition::wait_QReadWriteLock() // test multiple threads waiting on separate wait conditions wait_QReadWriteLock_Thread_1 thread[ThreadCount]; + const QString prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_lockforread_"); + for (x = 0; x < ThreadCount; ++x) { + thread[x].setObjectName(prefix + QString::number(x)); thread[x].readWriteLock.lockForRead(); thread[x].start(); // wait for thread to start @@ -319,8 +349,11 @@ void tst_QWaitCondition::wait_QReadWriteLock() QWaitCondition cond1, cond2; wait_QReadWriteLock_Thread_2 thread[ThreadCount]; + const QString prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_lockforwrite_"); + readWriteLock.lockForWrite(); for (x = 0; x < ThreadCount; ++x) { + thread[x].setObjectName(prefix + QString::number(x)); thread[x].readWriteLock = &readWriteLock; thread[x].cond = (x < ThreadCount / 2) ? &cond1 : &cond2; thread[x].start(); @@ -346,11 +379,17 @@ void tst_QWaitCondition::wait_QReadWriteLock() } } -class wake_Thread : public QThread +class WakeThreadBase : public TerminatingThread { public: - static int count; + QAtomicInt *count; + WakeThreadBase() : count(Q_NULLPTR) {} +}; + +class wake_Thread : public WakeThreadBase +{ +public: QWaitCondition started; QWaitCondition dummy; @@ -366,24 +405,23 @@ public: void run() { + Q_ASSERT(count); + Q_ASSERT(mutex); + Q_ASSERT(cond); mutex->lock(); - ++count; + ++*count; dummy.wakeOne(); // this wakeup should be lost started.wakeOne(); dummy.wakeAll(); // this one too cond->wait(mutex); - --count; + --*count; mutex->unlock(); } }; -int wake_Thread::count = 0; - -class wake_Thread_2 : public QThread +class wake_Thread_2 : public WakeThreadBase { public: - static int count; - QWaitCondition started; QWaitCondition dummy; @@ -399,22 +437,24 @@ public: void run() { + Q_ASSERT(count); + Q_ASSERT(readWriteLock); + Q_ASSERT(cond); readWriteLock->lockForWrite(); - ++count; + ++*count; dummy.wakeOne(); // this wakeup should be lost started.wakeOne(); dummy.wakeAll(); // this one too cond->wait(readWriteLock); - --count; + --*count; readWriteLock->unlock(); } }; -int wake_Thread_2::count = 0; - void tst_QWaitCondition::wakeOne() { int x; + QAtomicInt count; // wake up threads, one at a time for (int i = 0; i < iterations; ++i) { QMutex mutex; @@ -424,8 +464,13 @@ void tst_QWaitCondition::wakeOne() wake_Thread thread[ThreadCount]; bool thread_exited[ThreadCount]; + QString prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_mutex_") + + QString::number(i) + QLatin1Char('_'); + mutex.lock(); for (x = 0; x < ThreadCount; ++x) { + thread[x].setObjectName(prefix + QString::number(x)); + thread[x].count = &count; thread[x].mutex = &mutex; thread[x].cond = &cond; thread_exited[x] = false; @@ -438,7 +483,7 @@ void tst_QWaitCondition::wakeOne() } mutex.unlock(); - QCOMPARE(wake_Thread::count, ThreadCount); + QCOMPARE(count.load(), ThreadCount); // wake up threads one at a time for (x = 0; x < ThreadCount; ++x) { @@ -459,17 +504,22 @@ void tst_QWaitCondition::wakeOne() } QCOMPARE(exited, 1); - QCOMPARE(wake_Thread::count, ThreadCount - (x + 1)); + QCOMPARE(count.load(), ThreadCount - (x + 1)); } - QCOMPARE(wake_Thread::count, 0); + QCOMPARE(count.load(), 0); // QReadWriteLock QReadWriteLock readWriteLock; wake_Thread_2 rwthread[ThreadCount]; + prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_readwritelock_") + + QString::number(i) + QLatin1Char('_'); + readWriteLock.lockForWrite(); for (x = 0; x < ThreadCount; ++x) { + rwthread[x].setObjectName(prefix + QString::number(x)); + rwthread[x].count = &count; rwthread[x].readWriteLock = &readWriteLock; rwthread[x].cond = &cond; thread_exited[x] = false; @@ -482,7 +532,7 @@ void tst_QWaitCondition::wakeOne() } readWriteLock.unlock(); - QCOMPARE(wake_Thread_2::count, ThreadCount); + QCOMPARE(count.load(), ThreadCount); // wake up threads one at a time for (x = 0; x < ThreadCount; ++x) { @@ -503,10 +553,10 @@ void tst_QWaitCondition::wakeOne() } QCOMPARE(exited, 1); - QCOMPARE(wake_Thread_2::count, ThreadCount - (x + 1)); + QCOMPARE(count.load(), ThreadCount - (x + 1)); } - QCOMPARE(wake_Thread_2::count, 0); + QCOMPARE(count.load(), 0); } // wake up threads, two at a time @@ -518,8 +568,13 @@ void tst_QWaitCondition::wakeOne() wake_Thread thread[ThreadCount]; bool thread_exited[ThreadCount]; + QString prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_mutex2_") + + QString::number(i) + QLatin1Char('_'); + mutex.lock(); for (x = 0; x < ThreadCount; ++x) { + thread[x].setObjectName(prefix + QString::number(x)); + thread[x].count = &count; thread[x].mutex = &mutex; thread[x].cond = &cond; thread_exited[x] = false; @@ -532,7 +587,7 @@ void tst_QWaitCondition::wakeOne() } mutex.unlock(); - QCOMPARE(wake_Thread::count, ThreadCount); + QCOMPARE(count.load(), ThreadCount); // wake up threads one at a time for (x = 0; x < ThreadCount; x += 2) { @@ -555,17 +610,22 @@ void tst_QWaitCondition::wakeOne() } QCOMPARE(exited, 2); - QCOMPARE(wake_Thread::count, ThreadCount - (x + 2)); + QCOMPARE(count.load(), ThreadCount - (x + 2)); } - QCOMPARE(wake_Thread::count, 0); + QCOMPARE(count.load(), 0); // QReadWriteLock QReadWriteLock readWriteLock; wake_Thread_2 rwthread[ThreadCount]; + prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_readwritelock_") + + QString::number(i) + QLatin1Char('_'); + readWriteLock.lockForWrite(); for (x = 0; x < ThreadCount; ++x) { + rwthread[x].setObjectName(prefix + QString::number(x)); + rwthread[x].count = &count; rwthread[x].readWriteLock = &readWriteLock; rwthread[x].cond = &cond; thread_exited[x] = false; @@ -578,7 +638,7 @@ void tst_QWaitCondition::wakeOne() } readWriteLock.unlock(); - QCOMPARE(wake_Thread_2::count, ThreadCount); + QCOMPARE(count.load(), ThreadCount); // wake up threads one at a time for (x = 0; x < ThreadCount; x += 2) { @@ -601,16 +661,17 @@ void tst_QWaitCondition::wakeOne() } QCOMPARE(exited, 2); - QCOMPARE(wake_Thread_2::count, ThreadCount - (x + 2)); + QCOMPARE(count.load(), ThreadCount - (x + 2)); } - QCOMPARE(wake_Thread_2::count, 0); + QCOMPARE(count.load(), 0); } } void tst_QWaitCondition::wakeAll() { int x; + QAtomicInt count; for (int i = 0; i < iterations; ++i) { QMutex mutex; QWaitCondition cond; @@ -618,8 +679,13 @@ void tst_QWaitCondition::wakeAll() // QMutex wake_Thread thread[ThreadCount]; + QString prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_mutex_") + + QString::number(i) + QLatin1Char('_'); + mutex.lock(); for (x = 0; x < ThreadCount; ++x) { + thread[x].setObjectName(prefix + QString::number(x)); + thread[x].count = &count; thread[x].mutex = &mutex; thread[x].cond = &cond; thread[x].start(); @@ -628,7 +694,7 @@ void tst_QWaitCondition::wakeAll() } mutex.unlock(); - QCOMPARE(wake_Thread::count, ThreadCount); + QCOMPARE(count.load(), ThreadCount); // wake up all threads at once mutex.lock(); @@ -643,14 +709,19 @@ void tst_QWaitCondition::wakeAll() } QCOMPARE(exited, ThreadCount); - QCOMPARE(wake_Thread::count, 0); + QCOMPARE(count.load(), 0); // QReadWriteLock QReadWriteLock readWriteLock; wake_Thread_2 rwthread[ThreadCount]; + prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_readwritelock_") + + QString::number(i) + QLatin1Char('_'); + readWriteLock.lockForWrite(); for (x = 0; x < ThreadCount; ++x) { + rwthread[x].setObjectName(prefix + QString::number(x)); + rwthread[x].count = &count; rwthread[x].readWriteLock = &readWriteLock; rwthread[x].cond = &cond; rwthread[x].start(); @@ -659,7 +730,7 @@ void tst_QWaitCondition::wakeAll() } readWriteLock.unlock(); - QCOMPARE(wake_Thread_2::count, ThreadCount); + QCOMPARE(count.load(), ThreadCount); // wake up all threads at once readWriteLock.lockForWrite(); @@ -674,11 +745,11 @@ void tst_QWaitCondition::wakeAll() } QCOMPARE(exited, ThreadCount); - QCOMPARE(wake_Thread_2::count, 0); + QCOMPARE(count.load(), 0); } } -class wait_RaceConditionThread : public QThread +class wait_RaceConditionThread : public TerminatingThread { public: wait_RaceConditionThread(QMutex *mutex, QWaitCondition *startup, QWaitCondition *waitCondition, @@ -707,7 +778,7 @@ public: } }; -class wait_RaceConditionThread_2 : public QThread +class wait_RaceConditionThread_2 : public TerminatingThread { public: wait_RaceConditionThread_2(QReadWriteLock *readWriteLock, From ee632a21f6d4f6ea1d4fe7e41cca0fee307c5e39 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 26 Nov 2015 12:13:14 +0100 Subject: [PATCH 42/50] tst_QWaitCondition::wakeOne(): Increase wait interval. Introduce constants and make the interval for the 2nd thread a bit longer. Task-number: QTBUG-49653 Change-Id: I92ac0494ec6c9af5bde858007d08e26210215434 Reviewed-by: Joerg Bornemann --- .../thread/qwaitcondition/tst_qwaitcondition.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tests/auto/corelib/thread/qwaitcondition/tst_qwaitcondition.cpp b/tests/auto/corelib/thread/qwaitcondition/tst_qwaitcondition.cpp index 6a2ea7c73c..df52aa4949 100644 --- a/tests/auto/corelib/thread/qwaitcondition/tst_qwaitcondition.cpp +++ b/tests/auto/corelib/thread/qwaitcondition/tst_qwaitcondition.cpp @@ -453,6 +453,9 @@ public: void tst_QWaitCondition::wakeOne() { + static const int firstWaitInterval = 1000; + static const int waitInterval = 30; + int x; QAtomicInt count; // wake up threads, one at a time @@ -497,7 +500,7 @@ void tst_QWaitCondition::wakeOne() for (int y = 0; y < ThreadCount; ++y) { if (thread_exited[y]) continue; - if (thread[y].wait(exited > 0 ? 10 : 1000)) { + if (thread[y].wait(exited > 0 ? waitInterval : firstWaitInterval)) { thread_exited[y] = true; ++exited; } @@ -546,7 +549,7 @@ void tst_QWaitCondition::wakeOne() for (int y = 0; y < ThreadCount; ++y) { if (thread_exited[y]) continue; - if (rwthread[y].wait(exited > 0 ? 10 : 1000)) { + if (rwthread[y].wait(exited > 0 ? waitInterval : firstWaitInterval)) { thread_exited[y] = true; ++exited; } @@ -603,7 +606,7 @@ void tst_QWaitCondition::wakeOne() for (int y = 0; y < ThreadCount; ++y) { if (thread_exited[y]) continue; - if (thread[y].wait(exited > 0 ? 10 : 1000)) { + if (thread[y].wait(exited > 0 ? waitInterval : firstWaitInterval)) { thread_exited[y] = true; ++exited; } @@ -654,7 +657,7 @@ void tst_QWaitCondition::wakeOne() for (int y = 0; y < ThreadCount; ++y) { if (thread_exited[y]) continue; - if (rwthread[y].wait(exited > 0 ? 10 : 1000)) { + if (rwthread[y].wait(exited > 0 ? waitInterval : firstWaitInterval)) { thread_exited[y] = true; ++exited; } From 45470e71bcfefba577739a56ddecd0b1e9b97d5d Mon Sep 17 00:00:00 2001 From: Volker Krause Date: Tue, 24 Nov 2015 11:47:19 +0100 Subject: [PATCH 43/50] Remove O(n^2) behavior in fallbacksForFamily(). Speeds up application startup by a few percent, even with just a normal amount of fonts installed. Change-Id: I4c3d87119ddbc53e66166f21cb72946cdf7e4a41 Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Konstantin Ritt --- .../fontdatabases/fontconfig/qfontconfigdatabase.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index 0af9440b50..a5fe88871d 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -716,15 +716,19 @@ QStringList QFontconfigDatabase::fallbacksForFamily(const QString &family, QFont FcPatternDestroy(pattern); if (fontSet) { + QSet duplicates; + duplicates.reserve(fontSet->nfont + 1); + duplicates.insert(family.toCaseFolded()); for (int i = 0; i < fontSet->nfont; i++) { FcChar8 *value = 0; if (FcPatternGetString(fontSet->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch) continue; // capitalize(value); - QString familyName = QString::fromUtf8((const char *)value); - if (!fallbackFamilies.contains(familyName,Qt::CaseInsensitive) && - familyName.compare(family, Qt::CaseInsensitive)) { + const QString familyName = QString::fromUtf8((const char *)value); + const QString familyNameCF = familyName.toCaseFolded(); + if (!duplicates.contains(familyNameCF)) { fallbackFamilies << familyName; + duplicates.insert(familyNameCF); } } FcFontSetDestroy(fontSet); From adc4894fca0eeeb5a302009ca2bf597e80e28914 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 25 Nov 2015 14:30:41 +0100 Subject: [PATCH 44/50] tst_QProcess: Use a QTemporaryDir for files to be created. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ensure the test works in a working directory with read-only permission and that the file names are unique. The test can then be executed repeatedly by COIN even in case left-over hanging process helpers still lock the files. Also disambiguate the "data" files used by various tests. Task-number: QTBUG-47370 Change-Id: I3b9c7b70828da78f400196fcbba27bc61ea4538f Reviewed-by: Jędrzej Nowacki --- .../auto/corelib/io/qprocess/tst_qprocess.cpp | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp index ca5f527b8b..712e3440d8 100644 --- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp +++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -172,6 +173,7 @@ protected slots: private: qint64 bytesAvailable; + QTemporaryDir m_temporaryDir; #endif //QT_NO_PROCESS }; @@ -180,6 +182,7 @@ void tst_QProcess::initTestCase() #ifdef QT_NO_PROCESS QSKIP("This test requires QProcess support"); #else + QVERIFY2(m_temporaryDir.isValid(), qPrintable(m_temporaryDir.errorString())); // chdir to our testdata path and execute helper apps relative to that. QString testdata_dir = QFileInfo(QFINDTESTDATA("testProcessNormal")).absolutePath(); QVERIFY2(QDir::setCurrent(testdata_dir), qPrintable("Could not chdir to " + testdata_dir)); @@ -1709,7 +1712,7 @@ void tst_QProcess::failToStartEmptyArgs() // Reading and writing to a process is not supported on Qt/CE void tst_QProcess::removeFileWhileProcessIsRunning() { - QFile file("removeFile.txt"); + QFile file(m_temporaryDir.path() + QLatin1String("/removeFile.txt")); QVERIFY(file.open(QFile::WriteOnly)); QProcess process; @@ -1940,13 +1943,13 @@ void tst_QProcess::setStandardInputFile() { static const char data[] = "A bunch\1of\2data\3\4\5\6\7..."; QProcess process; - QFile file("data"); + QFile file(m_temporaryDir.path() + QLatin1String("/data-sif")); QVERIFY(file.open(QIODevice::WriteOnly)); file.write(data, sizeof data); file.close(); - process.setStandardInputFile("data"); + process.setStandardInputFile(file.fileName()); process.start("testProcessEcho/testProcessEcho"); QVERIFY(process.waitForFinished()); @@ -2008,7 +2011,7 @@ void tst_QProcess::setStandardOutputFile() QIODevice::OpenMode mode = append ? QIODevice::Append : QIODevice::Truncate; // create the destination file with data - QFile file("data"); + QFile file(m_temporaryDir.path() + QLatin1String("/data-stdof-") + QLatin1String(QTest::currentDataTag())); QVERIFY(file.open(QIODevice::WriteOnly)); file.write(data, sizeof data - 1); file.close(); @@ -2017,9 +2020,9 @@ void tst_QProcess::setStandardOutputFile() QProcess process; process.setReadChannelMode(channelMode); if (channelToTest == QProcess::StandardOutput) - process.setStandardOutputFile("data", mode); + process.setStandardOutputFile(file.fileName(), mode); else - process.setStandardErrorFile("data", mode); + process.setStandardErrorFile(file.fileName(), mode); process.start("testProcessEcho2/testProcessEcho2"); process.write(testdata, sizeof testdata); @@ -2066,10 +2069,11 @@ void tst_QProcess::setStandardOutputFileAndWaitForBytesWritten() { static const char testdata[] = "Test data."; - QFile file("data"); + QFile file(m_temporaryDir.path() + QLatin1String("/data-stdofawfbw")); QProcess process; process.setStandardOutputFile(file.fileName()); process.start("testProcessEcho2/testProcessEcho2"); + QVERIFY2(process.waitForStarted(), qPrintable(process.errorString())); process.write(testdata, sizeof testdata); process.waitForBytesWritten(); QVERIFY(process.waitForFinished()); @@ -2143,14 +2147,15 @@ void tst_QProcess::fileWriterProcess() QTime stopWatch; stopWatch.start(); - const QString fileName = QLatin1String("fileWriterProcess.txt"); + const QString fileName = m_temporaryDir.path() + QLatin1String("/fileWriterProcess.txt"); + const QString binary = QDir::currentPath() + QLatin1String("/fileWriterProcess/fileWriterProcess"); do { if (QFile::exists(fileName)) QVERIFY(QFile::remove(fileName)); QProcess process; - process.start("fileWriterProcess/fileWriterProcess", - QIODevice::ReadWrite | QIODevice::Text); + process.setWorkingDirectory(m_temporaryDir.path()); + process.start(binary, QIODevice::ReadWrite | QIODevice::Text); process.write(stdinStr); process.closeWriteChannel(); while (process.bytesToWrite()) { @@ -2173,8 +2178,9 @@ void tst_QProcess::detachedWorkingDirectoryAndPid() QTest::qSleep(1000); #endif - QFile infoFile(QDir::currentPath() + QLatin1String("/detachedinfo.txt")); - infoFile.remove(); + QFile infoFile(m_temporaryDir.path() + QLatin1String("/detachedinfo.txt")); + if (infoFile.exists()) + QVERIFY(infoFile.remove()); QString workingDir = QDir::currentPath() + "/testDetached"; From 4a4b17805c976b40a404b48ba51984c9abdba633 Mon Sep 17 00:00:00 2001 From: Robin Burchell Date: Tue, 24 Nov 2015 21:00:38 +0100 Subject: [PATCH 45/50] Fix QCOMPARE with enum classes. As these are strongly typed, they won't implicitly convert to int, so make sure to cast explicitly. (cherry picked from commit 9626baaea98edc13236250fc4b92d461b80e3875, auto test is not included) Task-number: QTBUG-49597 Change-Id: I29c4331a9b0c61f2e60c2bcab5a99f65daa7060f Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/testlib/qtestcase.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/testlib/qtestcase.h b/src/testlib/qtestcase.h index 7d2fd2e701..9d79439e04 100644 --- a/src/testlib/qtestcase.h +++ b/src/testlib/qtestcase.h @@ -238,7 +238,7 @@ namespace QTest inline typename QtPrivate::QEnableIf::Value, char*>::Type toString(T e) { QMetaEnum me = QMetaEnum::fromType(); - return qstrdup(me.key(e)); + return qstrdup(me.key(int(e))); // int cast is necessary to support enum classes } template // Fallback From 7cbbca586092944eab0f024e0c249044b7599c24 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 24 Nov 2015 14:32:53 +0100 Subject: [PATCH 46/50] Add AArch64 ASM to qimage_neon.cpp Since AArch64 NEON assembly is different from Arm32 NEON we need to write a separate version. Assembly is used over intrinsics as the intrinsics have trouble efficiently using the vstX and vldX instructions. Change-Id: I5b67fc87acb2433b503e658099b742d57a9cff18 Reviewed-by: Erik Verbruggen --- src/gui/image/qimage_conversions.cpp | 2 +- src/gui/image/qimage_neon.cpp | 30 ++++++++++++++++++++++++++-- src/gui/image/qjpeghandler.cpp | 3 +-- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index 8e0e53c58d..7d1fb23b15 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -2947,7 +2947,7 @@ void qInitImageConversions() } #endif -#if defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64) +#if defined(__ARM_NEON__) extern void convert_RGB888_to_RGB32_neon(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags); qimage_converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_neon; qimage_converter_map[QImage::Format_RGB888][QImage::Format_ARGB32] = convert_RGB888_to_RGB32_neon; diff --git a/src/gui/image/qimage_neon.cpp b/src/gui/image/qimage_neon.cpp index b51c43aa9d..5853510ee1 100644 --- a/src/gui/image/qimage_neon.cpp +++ b/src/gui/image/qimage_neon.cpp @@ -35,7 +35,7 @@ #include #include -#if defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64) +#if defined(__ARM_NEON__) QT_BEGIN_NAMESPACE @@ -55,6 +55,7 @@ Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_neon(quint32 *dst, cons if ((len - offsetToAlignOn8Bytes) >= 8) { const quint32 *const simdEnd = end - 7; +#if !defined(Q_PROCESSOR_ARM_64) register uint8x8_t fullVector asm ("d3") = vdup_n_u8(0xff); do { #if Q_BYTE_ORDER == Q_BIG_ENDIAN @@ -76,6 +77,31 @@ Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_neon(quint32 *dst, cons ); #endif } while (dst < simdEnd); +#else + register uint8x8_t fullVector asm ("v3") = vdup_n_u8(0xff); + do { +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + asm volatile ( + "ld3 { v4.8b, v5.8b, v6.8b }, [%[SRC]], #24 \n\t" + "st4 { v3.8b, v4.8b, v5.8b, v6.8b }, [%[DST]], #32 \n\t" + : [DST]"+r" (dst), [SRC]"+r" (src) + : "w"(fullVector) + : "memory", "v4", "v5", "v6" + ); +#else + asm volatile ( + "ld3 { v0.8b, v1.8b, v2.8b }, [%[SRC]], #24 \n\t" + "mov v4.8b, v2.8b\n\t" + "mov v2.8b, v0.8b\n\t" + "mov v0.8b, v4.8b\n\t" + "st4 { v0.8b, v1.8b, v2.8b, v3.8b }, [%[DST]], #32 \n\t" + : [DST]"+r" (dst), [SRC]"+r" (src) + : "w"(fullVector) + : "memory", "v0", "v1", "v2", "v4" + ); +#endif + } while (dst < simdEnd); +#endif } while (dst != end) { @@ -103,4 +129,4 @@ void convert_RGB888_to_RGB32_neon(QImageData *dest, const QImageData *src, Qt::I QT_END_NAMESPACE -#endif // defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64) +#endif // defined(__ARM_NEON__) diff --git a/src/gui/image/qjpeghandler.cpp b/src/gui/image/qjpeghandler.cpp index 7e9483e6f7..68709b708d 100644 --- a/src/gui/image/qjpeghandler.cpp +++ b/src/gui/image/qjpeghandler.cpp @@ -978,9 +978,8 @@ extern "C" void qt_convert_rgb888_to_rgb32_mips_dspr2_asm(quint32 *dst, const uc QJpegHandler::QJpegHandler() : d(new QJpegHandlerPrivate(this)) { -#if defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64) +#if defined(__ARM_NEON__) // from qimage_neon.cpp - if (qCpuHasFeature(NEON)) d->rgb888ToRgb32ConverterPtr = qt_convert_rgb888_to_rgb32_neon; #endif From a3bcb68bc8a87a4c6e3173ae26a9c67fde2d356b Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 18 Nov 2015 11:06:33 +0100 Subject: [PATCH 47/50] fix copy&paste-o in DeviceVar error message Change-Id: I2b7d95c004ce045527b124ef25b6d224535c895b Reviewed-by: Joerg Bornemann --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 443771af47..52c1be265f 100755 --- a/configure +++ b/configure @@ -453,7 +453,7 @@ DeviceVar() eq="=" ;; *) - echo >&2 "BUG: wrong command to QMakeVar: $1" + echo >&2 "BUG: wrong command to DeviceVar: $1" ;; esac From 94fb31be984513d24b00eff3badc3b13c93fb10f Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 20 Nov 2015 15:26:30 +0100 Subject: [PATCH 48/50] build QML plugins with relative RPATH as well amends 967372c97. Change-Id: I898950d6847e43d565748cd8d1ea583cf5ca5c9d Reviewed-by: Jake Petroules Reviewed-by: Eike Ziller --- mkspecs/features/qml_plugin.prf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mkspecs/features/qml_plugin.prf b/mkspecs/features/qml_plugin.prf index a639ac2969..1bc05caefe 100644 --- a/mkspecs/features/qml_plugin.prf +++ b/mkspecs/features/qml_plugin.prf @@ -19,6 +19,8 @@ if(win32|mac):!macx-xcode { contains(QT_CONFIG, build_all):CONFIG += build_all } +CONFIG += relative_qt_rpath # Qt's QML plugins should be relocatable + !no_cxx_module:isEmpty(CXX_MODULE) { CXX_MODULE = $$TARGET TARGET = declarative_$${TARGET} From 9b2e98245a95bec9179edf648d7b562d2d1cb692 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 20 Nov 2015 19:04:11 +0100 Subject: [PATCH 49/50] use bindir instead of libdir when launching tools on windows longer term, the redundant .dlls from the libdir will hopefully disappear. short term, this is a workaround for CI brokenness. Change-Id: Ia30173355f3aca222d4ca40e7a38c2cf535bbc03 Reviewed-by: Joerg Bornemann --- mkspecs/features/qt_functions.prf | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/mkspecs/features/qt_functions.prf b/mkspecs/features/qt_functions.prf index 403b847ac1..00f4bdf93e 100644 --- a/mkspecs/features/qt_functions.prf +++ b/mkspecs/features/qt_functions.prf @@ -120,15 +120,9 @@ defineTest(qtAddTargetEnv) { deps = $$replace($$2, -private$, _private) deps = $$resolve_depends(deps, "QT.", ".depends" ".run_depends") !isEmpty(deps) { - ptypes = - for(dep, deps) { - isEmpty(3): \ - deppath += $$shell_path($$eval(QT.$${dep}.libs)) - else: \ - deppath += $$system_path($$eval(QT.$${dep}.libs)) - ptypes += $$eval(QT.$${dep}.plugin_types) - } + libs = libs equals(QMAKE_HOST.os, Windows) { + libs = bins deppath.name = PATH } else:contains(QMAKE_HOST.os, Linux|FreeBSD|OpenBSD|NetBSD|DragonFly|SunOS|HP-UX|QNX|GNU) { deppath.name = LD_LIBRARY_PATH @@ -144,6 +138,14 @@ defineTest(qtAddTargetEnv) { } else { error("Operating system not supported.") } + ptypes = + for(dep, deps) { + isEmpty(3): \ + deppath += $$shell_path($$eval(QT.$${dep}.$$libs)) + else: \ + deppath += $$system_path($$eval(QT.$${dep}.$$libs)) + ptypes += $$eval(QT.$${dep}.plugin_types) + } deppath.value = $$unique(deppath) deppath.CONFIG = prepend From b13801fd550d4eef2e45ac3e11304571e0146dd9 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Wed, 25 Nov 2015 13:44:37 +0100 Subject: [PATCH 50/50] Avoid pulling in X11 headers in brcm backend In some configurations we may end up using Mesa's EGL headers instead of the Broadcom ones. Make this work by setting the usual define to prevent including Xlib headers that then conflict with all sorts of things in QtCore. Change-Id: I4970553428e5b0e81bd76694980f3b6b194ae4c2 Reviewed-by: Andy Nichols --- .../eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.pro | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.pro index 98797e2106..2026b6a6c6 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.pro +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.pro @@ -12,6 +12,9 @@ CONFIG += egl LIBS += -lbcm_host QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF +# Avoid X11 header collision +DEFINES += MESA_EGL_NO_X11_HEADERS + SOURCES += $$PWD/qeglfsbrcmmain.cpp \ $$PWD/qeglfsbrcmintegration.cpp