From b678445901b7fbae3d6d5816305cd3569ad9364a Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Fri, 27 Feb 2015 12:44:47 +0100 Subject: Fix leaking ISA extensions in LTCG builds Due to common subexpression elimination instruction set extensions may leak from the objects where they were enabled when doing link-time optimizations. To avoid that this patch disables LTCG/LTO on files built with extra instruction set extensions. Change-Id: Ie34ad900be7fb04a0dc4d3562187ee170c183333 Reviewed-by: Oswald Buddenhagen Reviewed-by: Thiago Macieira --- mkspecs/common/clang.conf | 2 ++ mkspecs/common/gcc-base.conf | 2 ++ mkspecs/features/simd.prf | 1 + 3 files changed, 5 insertions(+) diff --git a/mkspecs/common/clang.conf b/mkspecs/common/clang.conf index e188f10200..a0a2b3f3d1 100644 --- a/mkspecs/common/clang.conf +++ b/mkspecs/common/clang.conf @@ -20,10 +20,12 @@ QMAKE_CFLAGS_ISYSTEM = -isystem QMAKE_CFLAGS_PRECOMPILE = -x c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} QMAKE_CFLAGS_USE_PRECOMPILE = -Xclang -include-pch -Xclang ${QMAKE_PCH_OUTPUT} QMAKE_CFLAGS_LTCG = -flto +QMAKE_CFLAGS_DISABLE_LTCG = -fno-lto QMAKE_CXXFLAGS_PRECOMPILE = -x c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT} QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE QMAKE_CXXFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG +QMAKE_CXXFLAGS_DISABLE_LTCG = $$QMAKE_CFLAGS_DISABLE_LTCG QMAKE_CXXFLAGS_CXX11 = -std=c++11 QMAKE_LFLAGS_CXX11 = diff --git a/mkspecs/common/gcc-base.conf b/mkspecs/common/gcc-base.conf index d21ee38fb7..ff89accace 100644 --- a/mkspecs/common/gcc-base.conf +++ b/mkspecs/common/gcc-base.conf @@ -50,6 +50,7 @@ QMAKE_CFLAGS_EXCEPTIONS_OFF += -fno-exceptions QMAKE_CFLAGS_SPLIT_SECTIONS += -ffunction-sections QMAKE_CFLAGS_LTCG = -flto -fno-fat-lto-objects QMAKE_CFLAGS_LTCG_FATOBJECTS = -ffat-lto-objects +QMAKE_CFLAGS_DISABLE_LTCG = -fno-lto QMAKE_CXXFLAGS += $$QMAKE_CFLAGS QMAKE_CXXFLAGS_DEPS += $$QMAKE_CFLAGS_DEPS @@ -66,6 +67,7 @@ QMAKE_CXXFLAGS_EXCEPTIONS_OFF += $$QMAKE_CFLAGS_EXCEPTIONS_OFF QMAKE_CXXFLAGS_SPLIT_SECTIONS += $$QMAKE_CFLAGS_SPLIT_SECTIONS QMAKE_CXXFLAGS_LTCG = $$QMAKE_CFLAGS_LTCG QMAKE_CXXFLAGS_LTCG_FATOBJECTS = $$QMAKE_CFLAGS_LTCG_FATOBJECTS +QMAKE_CXXFLAGS_DISABLE_LTCG = $$QMAKE_CFLAGS_DISABLE_LTCG QMAKE_LFLAGS += QMAKE_LFLAGS_DEBUG += diff --git a/mkspecs/features/simd.prf b/mkspecs/features/simd.prf index 7d9eaffafa..700d79a1b5 100644 --- a/mkspecs/features/simd.prf +++ b/mkspecs/features/simd.prf @@ -27,6 +27,7 @@ defineTest(addSimdCompiler) { CONFIG($$1) { cflags = $$eval(QMAKE_CFLAGS_$${upname}) + ltcg: cflags += $$QMAKE_CFLAGS_DISABLE_LTCG contains(QT_CPU_FEATURES, $$name) { # Default compiler settings include this feature, so just add to SOURCES SOURCES += $$eval($$sources_var) -- cgit v1.2.3 From 38e64664a226e406a83fd0250584d5c57719a3a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 4 Mar 2015 19:01:58 +0100 Subject: Add __APPLE_CC_ to QMAKE_COMPILER_DEFINES for moc.prf Moc doesn't have the built in defines that clang has, so we need to hard-code some of these so that moc resolves the Q_OS_IOS define in the end, based on qsystemdetection.h and TargetConditionals.h Change-Id: Id9a7f870b940f99f27c55a2a887d0ce93217b821 Reviewed-by: Oswald Buddenhagen --- mkspecs/common/gcc-base-mac.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkspecs/common/gcc-base-mac.conf b/mkspecs/common/gcc-base-mac.conf index 43fa49c209..747f09ae81 100644 --- a/mkspecs/common/gcc-base-mac.conf +++ b/mkspecs/common/gcc-base-mac.conf @@ -10,7 +10,7 @@ include(gcc-base.conf) -QMAKE_COMPILER_DEFINES += __APPLE__ __GNUC__=4 +QMAKE_COMPILER_DEFINES += __APPLE__ __GNUC__=4 __APPLE_CC__ QMAKE_OBJECTIVE_CFLAGS = $$QMAKE_CFLAGS QMAKE_OBJECTIVE_CFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON -- cgit v1.2.3 From 196fde2ac780774b0e003dbc02bad23e1afc74ce Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 25 Feb 2015 12:58:23 +0100 Subject: Make the QItemSelectionModel::selection a property. QML code like this should be possible: Text { text: selModel.selection.contains(modelIndex) ? "blue" : "yellow" } If the selection is just a Q_INVOKABLE method, then all consumers need to set up Connections { target: selModel selectionChanged: foo() } That is obviously not the API we want (made more clear by the fact that the signal is already perfectly named) because it is not declarative but it can be. So, make it declarative by making selection a property. Change-Id: Id1a05ae9b91e45e6d462bea4272b8740571e9fc3 Reviewed-by: Gabriel de Dietrich --- src/corelib/itemmodels/qitemselectionmodel.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/corelib/itemmodels/qitemselectionmodel.h b/src/corelib/itemmodels/qitemselectionmodel.h index fe0bd459cd..09fab78214 100644 --- a/src/corelib/itemmodels/qitemselectionmodel.h +++ b/src/corelib/itemmodels/qitemselectionmodel.h @@ -146,6 +146,7 @@ class Q_CORE_EXPORT QItemSelectionModel : public QObject Q_PROPERTY(QAbstractItemModel *model READ model WRITE setModel NOTIFY modelChanged) Q_PROPERTY(bool hasSelection READ hasSelection NOTIFY selectionChanged STORED false DESIGNABLE false) Q_PROPERTY(QModelIndex currentIndex READ currentIndex NOTIFY currentChanged STORED false DESIGNABLE false) + Q_PROPERTY(QItemSelection selection READ selection NOTIFY selectionChanged STORED false DESIGNABLE false) Q_DECLARE_PRIVATE(QItemSelectionModel) @@ -186,7 +187,7 @@ public: Q_INVOKABLE QModelIndexList selectedIndexes() const; Q_INVOKABLE QModelIndexList selectedRows(int column = 0) const; Q_INVOKABLE QModelIndexList selectedColumns(int row = 0) const; - Q_INVOKABLE const QItemSelection selection() const; + const QItemSelection selection() const; // ### Qt 6: Merge these two as "QAbstractItemModel *model() const" const QAbstractItemModel *model() const; -- cgit v1.2.3 From 1a0dfd93bb18be6dd455397c5adfdb4f417cee53 Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Wed, 25 Feb 2015 12:58:24 +0100 Subject: Make some QAbstractItemModel API invokable As QAIM and related classes are becoming more useful in the QML environment, it makes sense to make these invokable. Make the access API and the setData method scriptable. Avoid making the structure changing APIs scriptable now to be conservative. Export the ItemDataRole enum through the staticQtMetaObject to make built-in roles available. Change-Id: I47b1682e6fa8ba32c7314c73fc10a7bbaa6d1f98 Reviewed-by: Gabriel de Dietrich Reviewed-by: Stephen Kelly --- src/corelib/global/qnamespace.h | 1 + src/corelib/itemmodels/qabstractitemmodel.h | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index e115cedc51..420b8b0430 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -1663,6 +1663,7 @@ public: QT_Q_ENUM(ItemSelectionOperation) QT_Q_FLAG(ItemFlags) QT_Q_ENUM(CheckState) + QT_Q_ENUM(ItemDataRole) QT_Q_ENUM(SortOrder) QT_Q_ENUM(CaseSensitivity) QT_Q_FLAG(MatchFlags) diff --git a/src/corelib/itemmodels/qabstractitemmodel.h b/src/corelib/itemmodels/qabstractitemmodel.h index 7789c0d483..1a4b12cd0a 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.h +++ b/src/corelib/itemmodels/qabstractitemmodel.h @@ -164,20 +164,20 @@ public: explicit QAbstractItemModel(QObject *parent = 0); virtual ~QAbstractItemModel(); - bool hasIndex(int row, int column, const QModelIndex &parent = QModelIndex()) const; - virtual QModelIndex index(int row, int column, + Q_INVOKABLE bool hasIndex(int row, int column, const QModelIndex &parent = QModelIndex()) const; + Q_INVOKABLE virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const = 0; - virtual QModelIndex parent(const QModelIndex &child) const = 0; + Q_INVOKABLE virtual QModelIndex parent(const QModelIndex &child) const = 0; - virtual QModelIndex sibling(int row, int column, const QModelIndex &idx) const; - virtual int rowCount(const QModelIndex &parent = QModelIndex()) const = 0; - virtual int columnCount(const QModelIndex &parent = QModelIndex()) const = 0; - virtual bool hasChildren(const QModelIndex &parent = QModelIndex()) const; + Q_INVOKABLE virtual QModelIndex sibling(int row, int column, const QModelIndex &idx) const; + Q_INVOKABLE virtual int rowCount(const QModelIndex &parent = QModelIndex()) const = 0; + Q_INVOKABLE virtual int columnCount(const QModelIndex &parent = QModelIndex()) const = 0; + Q_INVOKABLE virtual bool hasChildren(const QModelIndex &parent = QModelIndex()) const; - virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const = 0; - virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); + Q_INVOKABLE virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const = 0; + Q_INVOKABLE virtual bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); - virtual QVariant headerData(int section, Qt::Orientation orientation, + Q_INVOKABLE virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; virtual bool setHeaderData(int section, Qt::Orientation orientation, const QVariant &value, int role = Qt::EditRole); @@ -217,9 +217,9 @@ public: inline bool moveColumn(const QModelIndex &sourceParent, int sourceColumn, const QModelIndex &destinationParent, int destinationChild); - virtual void fetchMore(const QModelIndex &parent); - virtual bool canFetchMore(const QModelIndex &parent) const; - virtual Qt::ItemFlags flags(const QModelIndex &index) const; + Q_INVOKABLE virtual void fetchMore(const QModelIndex &parent); + Q_INVOKABLE virtual bool canFetchMore(const QModelIndex &parent) const; + Q_INVOKABLE virtual Qt::ItemFlags flags(const QModelIndex &index) const; virtual void sort(int column, Qt::SortOrder order = Qt::AscendingOrder); virtual QModelIndex buddy(const QModelIndex &index) const; virtual QModelIndexList match(const QModelIndex &start, int role, -- cgit v1.2.3 From f4a8dceb6739144df0cd898759fa798044a0258c Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Tue, 24 Feb 2015 15:29:20 +0100 Subject: Remove non-templated pixellayout methods Removes the non-templated pixellayout methods that were used for non-c++11 builds, and instead initialize with the templated ones verbatim. These versions are faster, and using only those removes duplicate code. Change-Id: I91a7d9122d2601ad282287a2f5ed6b88877d52fb Reviewed-by: Gunnar Sletta --- src/gui/painting/qdrawhelper.cpp | 220 +++++++-------------------------------- 1 file changed, 38 insertions(+), 182 deletions(-) diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 20fd41e0ae..04857fb0d6 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -69,8 +69,6 @@ enum { // must be multiple of 4 for easier SIMD implementations static const int buffer_size = 2048; -#ifdef Q_COMPILER_CONSTEXPR - template Q_DECL_CONSTEXPR uint redWidth(); template Q_DECL_CONSTEXPR uint redShift(); template Q_DECL_CONSTEXPR uint greenWidth(); @@ -310,6 +308,8 @@ static const uint *QT_FASTCALL convertARGBPMFromARGB32PM(uint *buffer, const uin return buffer; } +#ifdef Q_COMPILER_CONSTEXPR + template Q_DECL_CONSTEXPR static inline QPixelLayout pixelLayoutRGB() { return QPixelLayout{ @@ -338,177 +338,6 @@ template Q_DECL_CONSTEXPR static inline QPixelLayout pixe }; } -#else // CONSTEXPR - -static const uint *QT_FASTCALL convertToARGB32PM(uint *buffer, const uint *src, int count, - const QPixelLayout *layout, const QRgb *) -{ - Q_ASSERT(layout->redWidth >= 4); - Q_ASSERT(layout->greenWidth >= 4); - Q_ASSERT(layout->blueWidth >= 4); - Q_ASSERT(layout->alphaWidth >= 4); - - const uint redMask = ((1 << layout->redWidth) - 1); - const uint greenMask = ((1 << layout->greenWidth) - 1); - const uint blueMask = ((1 << layout->blueWidth) - 1); - - const uchar redLeftShift = 8 - layout->redWidth; - const uchar greenLeftShift = 8 - layout->greenWidth; - const uchar blueLeftShift = 8 - layout->blueWidth; - - const uchar redRightShift = 2 * layout->redWidth - 8; - const uchar greenRightShift = 2 * layout->greenWidth - 8; - const uchar blueRightShift = 2 * layout->blueWidth - 8; - - const uint alphaMask = ((1 << layout->alphaWidth) - 1); - const uchar alphaLeftShift = 8 - layout->alphaWidth; - const uchar alphaRightShift = 2 * layout->alphaWidth - 8; - - if (layout->premultiplied) { - for (int i = 0; i < count; ++i) { - uint alpha = (src[i] >> layout->alphaShift) & alphaMask; - uint red = (src[i] >> layout->redShift) & redMask; - uint green = (src[i] >> layout->greenShift) & greenMask; - uint blue = (src[i] >> layout->blueShift) & blueMask; - - alpha = (alpha << alphaLeftShift) | (alpha >> alphaRightShift); - red = qMin(alpha, (red << redLeftShift) | (red >> redRightShift)); - green = qMin(alpha, (green << greenLeftShift) | (green >> greenRightShift)); - blue = qMin(alpha, (blue << blueLeftShift) | (blue >> blueRightShift)); - buffer[i] = (alpha << 24) | (red << 16) | (green << 8) | blue; - } - } else { - for (int i = 0; i < count; ++i) { - uint alpha = (src[i] >> layout->alphaShift) & alphaMask; - uint red = (src[i] >> layout->redShift) & redMask; - uint green = (src[i] >> layout->greenShift) & greenMask; - uint blue = (src[i] >> layout->blueShift) & blueMask; - - alpha = (alpha << alphaLeftShift) | (alpha >> alphaRightShift); - red = (red << redLeftShift) | (red >> redRightShift); - green = (green << greenLeftShift) | (green >> greenRightShift); - blue = (blue << blueLeftShift) | (blue >> blueRightShift); - buffer[i] = qPremultiply((alpha << 24) | (red << 16) | (green << 8) | blue); - } - } - return buffer; -} - -static const uint *QT_FASTCALL convertToRGB32(uint *buffer, const uint *src, int count, - const QPixelLayout *layout, const QRgb *) -{ - Q_ASSERT(layout->redWidth >= 4); - Q_ASSERT(layout->greenWidth >= 4); - Q_ASSERT(layout->blueWidth >= 4); - Q_ASSERT(layout->alphaWidth == 0); - - const uint redMask = ((1 << layout->redWidth) - 1); - const uint greenMask = ((1 << layout->greenWidth) - 1); - const uint blueMask = ((1 << layout->blueWidth) - 1); - - const uchar redLeftShift = 8 - layout->redWidth; - const uchar greenLeftShift = 8 - layout->greenWidth; - const uchar blueLeftShift = 8 - layout->blueWidth; - - const uchar redRightShift = 2 * layout->redWidth - 8; - const uchar greenRightShift = 2 * layout->greenWidth - 8; - const uchar blueRightShift = 2 * layout->blueWidth - 8; - - for (int i = 0; i < count; ++i) { - uint red = (src[i] >> layout->redShift) & redMask; - uint green = (src[i] >> layout->greenShift) & greenMask; - uint blue = (src[i] >> layout->blueShift) & blueMask; - - red = (red << redLeftShift) | (red >> redRightShift); - green = (green << greenLeftShift) | (green >> greenRightShift); - blue = (blue << blueLeftShift) | (blue >> blueRightShift); - buffer[i] = 0xff000000 | (red << 16) | (green << 8) | blue; - } - return buffer; -} - -static const uint *QT_FASTCALL convertFromARGB32PM(uint *buffer, const uint *src, int count, - const QPixelLayout *layout, const QRgb *) -{ - Q_ASSERT(layout->redWidth <= 8); - Q_ASSERT(layout->greenWidth <= 8); - Q_ASSERT(layout->blueWidth <= 8); - Q_ASSERT(layout->alphaWidth <= 8); - - const uint redMask = (1 << layout->redWidth) - 1; - const uint greenMask = (1 << layout->greenWidth) - 1; - const uint blueMask = (1 << layout->blueWidth) - 1; - const uint alphaMask = (1 << layout->alphaWidth) - 1; - - const uchar redRightShift = 24 - layout->redWidth; - const uchar greenRightShift = 16 - layout->greenWidth; - const uchar blueRightShift = 8 - layout->blueWidth; - const uchar alphaRightShift = 32 - layout->alphaWidth; - - if (!layout->premultiplied) { - for (int i = 0; i < count; ++i) - buffer[i] = qUnpremultiply(src[i]); - src = buffer; - } - for (int i = 0; i < count; ++i) { - uint red = ((src[i] >> redRightShift) & redMask) << layout->redShift; - uint green = ((src[i] >> greenRightShift) & greenMask) << layout->greenShift; - uint blue = ((src[i] >> blueRightShift) & blueMask) << layout->blueShift; - uint alpha = ((src[i] >> alphaRightShift) & alphaMask) << layout->alphaShift; - buffer[i] = red | green | blue | alpha; - } - return buffer; -} - -static const uint *QT_FASTCALL convertFromRGB32(uint *buffer, const uint *src, int count, - const QPixelLayout *layout, const QRgb *) -{ - Q_ASSERT(layout->redWidth <= 8); - Q_ASSERT(layout->greenWidth <= 8); - Q_ASSERT(layout->blueWidth <= 8); - - const uint redMask = (1 << layout->redWidth) - 1; - const uint greenMask = (1 << layout->greenWidth) - 1; - const uint blueMask = (1 << layout->blueWidth) - 1; - const uint alphaMask = (1 << layout->alphaWidth) - 1; - - const uchar redRightShift = 24 - layout->redWidth; - const uchar greenRightShift = 16 - layout->greenWidth; - const uchar blueRightShift = 8 - layout->blueWidth; - - for (int i = 0; i < count; ++i) { - uint red = ((src[i] >> redRightShift) & redMask) << layout->redShift; - uint green = ((src[i] >> greenRightShift) & greenMask) << layout->greenShift; - uint blue = ((src[i] >> blueRightShift) & blueMask) << layout->blueShift; - uint alpha = (0xff & alphaMask) << layout->alphaShift; - buffer[i] = red | green | blue | alpha; - } - return buffer; -} - -static const uint *QT_FASTCALL convertRGB16ToRGB32(uint *buffer, const uint *src, int count, - const QPixelLayout *, const QRgb *) -{ - for (int i = 0; i < count; ++i) - buffer[i] = qConvertRgb16To32(src[i]); - return buffer; -} - -static const uint *QT_FASTCALL convertRGB16FromRGB32(uint *buffer, const uint *src, int count, - const QPixelLayout *, const QRgb *) -{ - for (int i = 0; i < count; ++i) - buffer[i] = qConvertRgb32To16(src[i]); - return buffer; -} - -static const uint *QT_FASTCALL convertRGB16FromARGB32PM(uint *buffer, const uint *src, int count, - const QPixelLayout *, const QRgb *) -{ - for (int i = 0; i < count; ++i) - buffer[i] = qConvertRgb32To16(qUnpremultiply(src[i])); - return buffer; -} #endif // To convert in place, let 'dest' and 'src' be the same. @@ -851,15 +680,42 @@ QPixelLayout qPixelLayouts[QImage::NImageFormats] = { pixelLayoutRGB(), pixelLayoutARGBPM(), #else - { 5, 11, 6, 5, 5, 0, 0, 0, false, QPixelLayout::BPP16, convertRGB16ToRGB32, convertRGB16FromARGB32PM, convertRGB16FromRGB32 }, // Format_RGB16 - { 5, 19, 6, 13, 5, 8, 8, 0, true, QPixelLayout::BPP24, convertToARGB32PM, convertFromARGB32PM, convertFromRGB32 }, // Format_ARGB8565_Premultiplied - { 6, 12, 6, 6, 6, 0, 0, 0, false, QPixelLayout::BPP24, convertToRGB32, convertFromARGB32PM, convertFromRGB32 }, // Format_RGB666 - { 6, 12, 6, 6, 6, 0, 6, 18, true, QPixelLayout::BPP24, convertToARGB32PM, convertFromARGB32PM, convertFromRGB32 }, // Format_ARGB6666_Premultiplied - { 5, 10, 5, 5, 5, 0, 0, 0, false, QPixelLayout::BPP16, convertToRGB32, convertFromARGB32PM, convertFromRGB32 }, // Format_RGB555 - { 5, 18, 5, 13, 5, 8, 8, 0, true, QPixelLayout::BPP24, convertToARGB32PM, convertFromARGB32PM, convertFromRGB32 }, // Format_ARGB8555_Premultiplied - { 8, 16, 8, 8, 8, 0, 0, 0, false, QPixelLayout::BPP24, convertToRGB32, convertFromARGB32PM, convertFromRGB32 }, // Format_RGB888 - { 4, 8, 4, 4, 4, 0, 0, 0, false, QPixelLayout::BPP16, convertToRGB32, convertFromARGB32PM, convertFromRGB32 }, // Format_RGB444 - { 4, 8, 4, 4, 4, 0, 4, 12, true, QPixelLayout::BPP16, convertToARGB32PM, convertFromARGB32PM, convertFromRGB32 }, // Format_ARGB4444_Premultiplied + { 5, 11, 6, 5, 5, 0, 0, 0, false, QPixelLayout::BPP16, + convertToRGB32, + convertRGBFromARGB32PM, + convertRGBFromRGB32}, + { 5, 19, 6, 13, 5, 8, 8, 0, true, QPixelLayout::BPP24, + convertARGBPMToARGB32PM, + convertARGBPMFromARGB32PM, + convertARGBPMFromRGB32}, + { 6, 12, 6, 6, 6, 0, 0, 0, false, QPixelLayout::BPP24, + convertToRGB32, + convertRGBFromARGB32PM, + convertRGBFromRGB32}, + { 6, 12, 6, 6, 6, 0, 6, 18, true, QPixelLayout::BPP24, + convertARGBPMToARGB32PM, + convertARGBPMFromARGB32PM, + convertARGBPMFromRGB32}, + { 5, 10, 5, 5, 5, 0, 0, 0, false, QPixelLayout::BPP16, + convertToRGB32, + convertRGBFromARGB32PM, + convertRGBFromRGB32 }, + { 5, 18, 5, 13, 5, 8, 8, 0, true, QPixelLayout::BPP24, + convertARGBPMToARGB32PM, + convertARGBPMFromARGB32PM, + convertARGBPMFromRGB32}, + { 8, 16, 8, 8, 8, 0, 0, 0, false, QPixelLayout::BPP24, + convertToRGB32, + convertRGBFromARGB32PM, + convertRGBFromRGB32}, + { 4, 8, 4, 4, 4, 0, 0, 0, false, QPixelLayout::BPP16, + convertToRGB32, + convertRGBFromARGB32PM, + convertRGBFromRGB32}, + { 4, 8, 4, 4, 4, 0, 4, 12, true, QPixelLayout::BPP16, + convertARGBPMToARGB32PM, + convertARGBPMFromARGB32PM, + convertARGBPMFromRGB32}, #endif #if Q_BYTE_ORDER == Q_BIG_ENDIAN { 8, 24, 8, 16, 8, 8, 0, 0, false, QPixelLayout::BPP32, convertRGBA8888PMToARGB32PM, convertRGBXFromARGB32PM, convertRGBXFromRGB32 }, // Format_RGBX8888 -- cgit v1.2.3 From 259b2b6cd76cbd86c6db1db782b5678df0686749 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 2 Mar 2015 23:03:22 -0800 Subject: XCB: Solve crash when plugging a screen with unshown QWindow If a QWindow has never been shown, it has no platformWindow (it's null). So it's a valid condition and we need to be sure that the pointer isn't null before dereferencing it. Task-number: QTBUG-44766 Change-Id: Ia0aac2f09e9245339951ffff13c7eb024d6a0773 Reviewed-by: Shawn Rutledge --- 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 58a364848a..78ced43af8 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -399,7 +399,8 @@ void QXcbScreen::handleScreenChange(xcb_randr_screen_change_notify_event_t *chan // They need to be told the screen is back, it's OK to render. foreach (QWindow *window, QGuiApplication::topLevelWindows()) { QXcbWindow *xcbWin = static_cast(window->handle()); - xcbWin->maybeSetScreen(this); + if (xcbWin) + xcbWin->maybeSetScreen(this); } } -- cgit v1.2.3 From 29051bce39d24a6e33155feeec2833b79b55ff16 Mon Sep 17 00:00:00 2001 From: Nikita Baryshnikov Date: Thu, 26 Feb 2015 09:04:20 +0300 Subject: QSslSocket: fix compilation error MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit invalid conversion from ‘unsigned char**’ to ‘const unsigned char**’ Task-number: QTBUG-44744 Change-Id: I6263db106fe28c6aa04db8ca79421b3a9fc5adc9 Reviewed-by: Richard J. Moore --- src/network/ssl/qsslcontext_openssl.cpp | 2 +- src/network/ssl/qsslsocket_openssl_symbols.cpp | 2 +- src/network/ssl/qsslsocket_openssl_symbols_p.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/network/ssl/qsslcontext_openssl.cpp b/src/network/ssl/qsslcontext_openssl.cpp index a7295933b5..b88ab54038 100644 --- a/src/network/ssl/qsslcontext_openssl.cpp +++ b/src/network/ssl/qsslcontext_openssl.cpp @@ -60,7 +60,7 @@ static DH *get_dh1024() "/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7OZTgf//////////AgEC")); const char *ptr = params.constData(); - DH *dh = q_d2i_DHparams(NULL, (unsigned char **)(&ptr), params.length()); + DH *dh = q_d2i_DHparams(NULL, reinterpret_cast(&ptr), params.length()); return dh; } diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index 7d29e25e33..e2700df3cc 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -399,7 +399,7 @@ DEFINEFUNC3(void, SSL_get0_next_proto_negotiated, const SSL *s, s, #endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ... DEFINEFUNC(DH *, DH_new, DUMMYARG, DUMMYARG, return 0, return) DEFINEFUNC(void, DH_free, DH *dh, dh, return, DUMMYARG) -DEFINEFUNC3(DH *, d2i_DHparams, DH**a, a, unsigned char **pp, pp, long length, length, return 0, return); +DEFINEFUNC3(DH *, d2i_DHparams, DH**a, a, const unsigned char **pp, pp, long length, length, return 0, return) DEFINEFUNC3(BIGNUM *, BN_bin2bn, const unsigned char *s, s, int len, len, BIGNUM *ret, ret, return 0, return) #ifndef OPENSSL_NO_EC DEFINEFUNC(EC_KEY *, EC_KEY_dup, const EC_KEY *ec, ec, return 0, return) diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h index aedd477b39..626c049629 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols_p.h +++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h @@ -440,7 +440,7 @@ STACK_OF(X509) *q_X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx); // Diffie-Hellman support DH *q_DH_new(); void q_DH_free(DH *dh); -DH *q_d2i_DHparams(DH **a, unsigned char **pp, long length); +DH *q_d2i_DHparams(DH **a, const unsigned char **pp, long length); BIGNUM *q_BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret); #define q_SSL_CTX_set_tmp_dh(ctx, dh) q_SSL_CTX_ctrl((ctx), SSL_CTRL_SET_TMP_DH, 0, (char *)dh) -- cgit v1.2.3 From 9fb68a90af79df3b8dc3225a3a97e2c6387afeec Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 23 Dec 2014 13:37:01 -0200 Subject: Fix bind+connect in both TCP and UDP This has been known to be broken for a while. Now it works: you can bind and you'll retain the port (and the file descriptor) for the connect call. Incidentally, in fixing the binding for more than one IP for the hostname (with event loop), this commit fixes the setSocketDescriptor XFAIL. [ChangeLog][QtNetwork] Fixed a bug that caused both QTcpSocket and QUdpSocket to close the socket and lose any bound ports before connecting. Now bind()/setSocketDescriptor() followed by connect() will retain the original file descriptor. Task-number: QTBUG-26538 Change-Id: I691caed7e8fd16a9cf687b5995afbf3006bf453a Reviewed-by: Richard J. Moore --- src/network/kernel/qhostinfo.cpp | 11 ++ src/network/kernel/qhostinfo_p.h | 1 + src/network/socket/qabstractsocket.cpp | 67 +++++---- src/network/socket/qabstractsocket.h | 2 + src/network/socket/qabstractsocket_p.h | 2 + src/network/socket/qnativesocketengine.cpp | 10 +- src/network/ssl/qsslsocket.cpp | 23 +++ src/network/ssl/qsslsocket_p.h | 1 + .../network/socket/qtcpsocket/tst_qtcpsocket.cpp | 159 +++++++++++++++++++-- .../network/socket/qudpsocket/tst_qudpsocket.cpp | 36 ++++- 10 files changed, 266 insertions(+), 46 deletions(-) diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index d2dc7c4850..a2ac9065fd 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -689,6 +689,7 @@ void qt_qhostinfo_clear_cache() } } +#ifdef QT_BUILD_INTERNAL void Q_AUTOTEST_EXPORT qt_qhostinfo_enable_cache(bool e) { QAbstractHostInfoLookupManager* manager = theHostInfoLookupManager(); @@ -697,6 +698,16 @@ void Q_AUTOTEST_EXPORT qt_qhostinfo_enable_cache(bool e) } } +void qt_qhostinfo_cache_inject(const QString &hostname, const QHostInfo &resolution) +{ + QAbstractHostInfoLookupManager* manager = theHostInfoLookupManager(); + if (!manager || !manager->cache.isEnabled()) + return; + + manager->cache.put(hostname, resolution); +} +#endif + // cache for 60 seconds // cache 128 items QHostInfoCache::QHostInfoCache() : max_age(60), enabled(true), cache(128) diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index 74cfe2a9aa..a99c3dc8ca 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -117,6 +117,7 @@ public: QHostInfo Q_NETWORK_EXPORT qt_qhostinfo_lookup(const QString &name, QObject *receiver, const char *member, bool *valid, int *id); void Q_AUTOTEST_EXPORT qt_qhostinfo_clear_cache(); void Q_AUTOTEST_EXPORT qt_qhostinfo_enable_cache(bool e); +void Q_AUTOTEST_EXPORT qt_qhostinfo_cache_inject(const QString &hostname, const QHostInfo &resolution); class QHostInfoCache { diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index f9fe40955a..3b10387b37 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -976,7 +976,7 @@ void QAbstractSocketPrivate::startConnectingByName(const QString &host) connectTimeElapsed = 0; - if (initSocketLayer(QAbstractSocket::UnknownNetworkLayerProtocol)) { + if (cachedSocketDescriptor != -1 || initSocketLayer(QAbstractSocket::UnknownNetworkLayerProtocol)) { if (socketEngine->connectToHostByName(host, port) || socketEngine->state() == QAbstractSocket::ConnectingState) { cachedSocketDescriptor = socketEngine->socketDescriptor(); @@ -1117,7 +1117,7 @@ void QAbstractSocketPrivate::_q_connectToNextAddress() host.toString().toLatin1().constData(), port, addresses.count()); #endif - if (!initSocketLayer(host.protocol())) { + if (cachedSocketDescriptor == -1 && !initSocketLayer(host.protocol())) { // hope that the next address is better #if defined(QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocketPrivate::_q_connectToNextAddress(), failed to initialize sock layer"); @@ -1134,9 +1134,6 @@ void QAbstractSocketPrivate::_q_connectToNextAddress() return; } - // cache the socket descriptor even if we're not fully connected yet - cachedSocketDescriptor = socketEngine->socketDescriptor(); - // Check that we're in delayed connection state. If not, try // the next address if (socketEngine->state() != QAbstractSocket::ConnectingState) { @@ -1481,54 +1478,60 @@ void QAbstractSocket::setPauseMode(PauseModes pauseMode) bool QAbstractSocket::bind(const QHostAddress &address, quint16 port, BindMode mode) { Q_D(QAbstractSocket); + return d->bind(address, port, mode); +} + +bool QAbstractSocketPrivate::bind(const QHostAddress &address, quint16 port, QAbstractSocket::BindMode mode) +{ + Q_Q(QAbstractSocket); // now check if the socket engine is initialized and to the right type - if (!d->socketEngine || !d->socketEngine->isValid()) { + if (!socketEngine || !socketEngine->isValid()) { QHostAddress nullAddress; - d->resolveProxy(nullAddress.toString(), port); + resolveProxy(nullAddress.toString(), port); QAbstractSocket::NetworkLayerProtocol protocol = address.protocol(); if (protocol == QAbstractSocket::UnknownNetworkLayerProtocol) protocol = nullAddress.protocol(); - if (!d->initSocketLayer(protocol)) + if (!initSocketLayer(protocol)) return false; } - if (mode != DefaultForPlatform) { + if (mode != QAbstractSocket::DefaultForPlatform) { #ifdef Q_OS_UNIX - if ((mode & ShareAddress) || (mode & ReuseAddressHint)) - d->socketEngine->setOption(QAbstractSocketEngine::AddressReusable, 1); + if ((mode & QAbstractSocket::ShareAddress) || (mode & QAbstractSocket::ReuseAddressHint)) + socketEngine->setOption(QAbstractSocketEngine::AddressReusable, 1); else - d->socketEngine->setOption(QAbstractSocketEngine::AddressReusable, 0); + socketEngine->setOption(QAbstractSocketEngine::AddressReusable, 0); #endif #ifdef Q_OS_WIN - if (mode & ReuseAddressHint) - d->socketEngine->setOption(QAbstractSocketEngine::AddressReusable, 1); + if (mode & QAbstractSocket::ReuseAddressHint) + socketEngine->setOption(QAbstractSocketEngine::AddressReusable, 1); else - d->socketEngine->setOption(QAbstractSocketEngine::AddressReusable, 0); - if (mode & DontShareAddress) - d->socketEngine->setOption(QAbstractSocketEngine::BindExclusively, 1); + socketEngine->setOption(QAbstractSocketEngine::AddressReusable, 0); + if (mode & QAbstractSocket::DontShareAddress) + socketEngine->setOption(QAbstractSocketEngine::BindExclusively, 1); else - d->socketEngine->setOption(QAbstractSocketEngine::BindExclusively, 0); + socketEngine->setOption(QAbstractSocketEngine::BindExclusively, 0); #endif } - bool result = d->socketEngine->bind(address, port); - d->cachedSocketDescriptor = d->socketEngine->socketDescriptor(); + bool result = socketEngine->bind(address, port); + cachedSocketDescriptor = socketEngine->socketDescriptor(); if (!result) { - d->socketError = d->socketEngine->error(); - setErrorString(d->socketEngine->errorString()); - emit error(d->socketError); + socketError = socketEngine->error(); + q->setErrorString(socketEngine->errorString()); + emit q->error(socketError); return false; } - d->state = BoundState; - d->localAddress = d->socketEngine->localAddress(); - d->localPort = d->socketEngine->localPort(); + state = QAbstractSocket::BoundState; + localAddress = socketEngine->localAddress(); + localPort = socketEngine->localPort(); - emit stateChanged(d->state); - d->socketEngine->setReadNotificationEnabled(true); + emit q->stateChanged(state); + socketEngine->setReadNotificationEnabled(true); return true; } @@ -1605,14 +1608,16 @@ void QAbstractSocket::connectToHost(const QString &hostName, quint16 port, d->preferredNetworkLayerProtocol = protocol; d->hostName = hostName; d->port = port; - d->state = UnconnectedState; d->buffer.clear(); d->writeBuffer.clear(); d->abortCalled = false; d->pendingClose = false; - d->localPort = 0; + if (d->state != BoundState) { + d->state = UnconnectedState; + d->localPort = 0; + d->localAddress.clear(); + } d->peerPort = 0; - d->localAddress.clear(); d->peerAddress.clear(); d->peerName = hostName; if (d->hostLookupId != -1) { diff --git a/src/network/socket/qabstractsocket.h b/src/network/socket/qabstractsocket.h index 76b1e5f538..f3d7f13f48 100644 --- a/src/network/socket/qabstractsocket.h +++ b/src/network/socket/qabstractsocket.h @@ -135,9 +135,11 @@ public: PauseModes pauseMode() const; void setPauseMode(PauseModes pauseMode); + // ### Qt6: make the first one virtual bool bind(const QHostAddress &address, quint16 port = 0, BindMode mode = DefaultForPlatform); bool bind(quint16 port = 0, BindMode mode = DefaultForPlatform); + // ### Qt6: de-virtualize connectToHost(QHostAddress) overload virtual void connectToHost(const QString &hostName, quint16 port, OpenMode mode = ReadWrite, NetworkLayerProtocol protocol = AnyIPProtocol); virtual void connectToHost(const QHostAddress &address, quint16 port, OpenMode mode = ReadWrite); virtual void disconnectFromHost(); diff --git a/src/network/socket/qabstractsocket_p.h b/src/network/socket/qabstractsocket_p.h index 379657f4fa..63440b6416 100644 --- a/src/network/socket/qabstractsocket_p.h +++ b/src/network/socket/qabstractsocket_p.h @@ -78,6 +78,8 @@ public: } #endif + virtual bool bind(const QHostAddress &address, quint16 port, QAbstractSocket::BindMode mode); + bool canReadNotification(); bool canWriteNotification(); void canCloseNotification(); diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp index db6c7c487a..fcfef87e3c 100644 --- a/src/network/socket/qnativesocketengine.cpp +++ b/src/network/socket/qnativesocketengine.cpp @@ -136,6 +136,12 @@ QT_BEGIN_NAMESPACE " not in "#state1" or "#state2); \ return (returnValue); \ } } while (0) +#define Q_CHECK_STATES3(function, state1, state2, state3, returnValue) do { \ + if (d->socketState != (state1) && d->socketState != (state2) && d->socketState != (state3)) { \ + qWarning(""#function" was called" \ + " not in "#state1" or "#state2); \ + return (returnValue); \ + } } while (0) #define Q_CHECK_TYPE(function, type, returnValue) do { \ if (d->socketType != (type)) { \ qWarning(#function" was called by a" \ @@ -495,7 +501,7 @@ bool QNativeSocketEngine::connectToHost(const QHostAddress &address, quint16 por if (!d->checkProxy(address)) return false; - Q_CHECK_STATES(QNativeSocketEngine::connectToHost(), + Q_CHECK_STATES3(QNativeSocketEngine::connectToHost(), QAbstractSocket::BoundState, QAbstractSocket::UnconnectedState, QAbstractSocket::ConnectingState, false); d->peerAddress = address; @@ -961,7 +967,7 @@ bool QNativeSocketEngine::waitForWrite(int msecs, bool *timedOut) QNativeSocketEnginePrivate::TimeOutErrorString); d->hasSetSocketError = false; // A timeout error is temporary in waitFor functions return false; - } else if (state() == QAbstractSocket::ConnectingState) { + } else if (state() == QAbstractSocket::ConnectingState || (state() == QAbstractSocket::BoundState && d->socketDescriptor != -1)) { connectToHost(d->peerAddress, d->peerPort); } diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index 508d300d42..b1076ebd68 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -2404,6 +2404,29 @@ bool QSslSocketPrivate::isPaused() const return paused; } +bool QSslSocketPrivate::bind(const QHostAddress &address, quint16 port, QAbstractSocket::BindMode mode) +{ + // this function is called from QAbstractSocket::bind + if (!initialized) + init(); + initialized = false; + +#ifdef QSSLSOCKET_DEBUG + qCDebug(lcSsl) << "QSslSocket::bind(" << address << ',' << port << ',' << mode << ')'; +#endif + if (!plainSocket) { +#ifdef QSSLSOCKET_DEBUG + qCDebug(lcSsl) << "\tcreating internal plain socket"; +#endif + createPlainSocket(QIODevice::ReadWrite); + } + bool ret = plainSocket->bind(address, port, mode); + localPort = plainSocket->localPort(); + localAddress = plainSocket->localAddress(); + cachedSocketDescriptor = plainSocket->socketDescriptor(); + return ret; +} + /*! \internal */ diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h index b110d65f9a..5f726f2371 100644 --- a/src/network/ssl/qsslsocket_p.h +++ b/src/network/ssl/qsslsocket_p.h @@ -172,6 +172,7 @@ public: static void checkSettingSslContext(QSslSocket*, QSharedPointer); static QSharedPointer sslContext(QSslSocket *socket); bool isPaused() const; + bool bind(const QHostAddress &address, quint16, QAbstractSocket::BindMode) Q_DECL_OVERRIDE; void _q_connectedSlot(); void _q_hostFoundSlot(); void _q_disconnectedSlot(); diff --git a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp index 878d5875b5..0ba9b6a58c 100644 --- a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp +++ b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp @@ -73,6 +73,7 @@ // RVCT compiles also unused inline methods # include +#include #ifdef Q_OS_LINUX #include #include @@ -123,6 +124,8 @@ private slots: void constructing(); void bind_data(); void bind(); + void bindThenResolveHost_data(); + void bindThenResolveHost(); void setInvalidSocketDescriptor(); #ifndef Q_OS_WINRT void setSocketDescriptor(); @@ -245,6 +248,9 @@ private: int earlyBytesWrittenCount; int earlyReadyReadCount; QString stressTestDir; + + QString firstFailName; + QHostInfo firstFailInfo; }; enum ProxyTests { @@ -297,7 +303,10 @@ public: }; tst_QTcpSocket::tst_QTcpSocket() + : firstFailName("qt-test-server-first-fail") { + qsrand(time(NULL)); + tmpSocket = 0; //This code relates to the socketsConstructedBeforeEventLoop test case @@ -308,6 +317,8 @@ tst_QTcpSocket::tst_QTcpSocket() connect(earlyConstructedSockets->endPoints[0], SIGNAL(readyRead()), this, SLOT(earlySocketReadyRead())); connect(earlyConstructedSockets->endPoints[1], SIGNAL(bytesWritten(qint64)), this, SLOT(earlySocketBytesSent(qint64))); earlyConstructedSockets->endPoints[1]->write("hello work"); + + firstFailInfo.setAddresses(QList() << QHostAddress("224.0.0.0") << QtNetworkSettings::serverIP()); } tst_QTcpSocket::~tst_QTcpSocket() @@ -389,6 +400,7 @@ void tst_QTcpSocket::init() } qt_qhostinfo_clear_cache(); + qt_qhostinfo_cache_inject(firstFailName, firstFailInfo); } QTcpSocket *tst_QTcpSocket::newSocket() const @@ -486,9 +498,12 @@ void tst_QTcpSocket::constructing() void tst_QTcpSocket::bind_data() { QTest::addColumn("stringAddr"); + QTest::addColumn("port"); QTest::addColumn("successExpected"); QTest::addColumn("stringExpectedLocalAddress"); + bool testIpv6 = false; + // iterate all interfaces, add all addresses on them as test data QList interfaces = QNetworkInterface::allInterfaces(); foreach (const QNetworkInterface &netinterface, interfaces) { @@ -501,10 +516,26 @@ void tst_QTcpSocket::bind_data() continue; // link-local bind will fail, at least on Linux, so skip it. QString ip(entry.ip().toString()); - QTest::newRow(ip.toLatin1().constData()) << ip << true << ip; + QTest::newRow(ip.toLatin1().constData()) << ip << 0 << true << ip; + + if (!testIpv6 && entry.ip().protocol() == QAbstractSocket::IPv6Protocol) + testIpv6 = true; } } + // test binding to localhost + QTest::newRow("0.0.0.0") << "0.0.0.0" << 0 << true << "0.0.0.0"; + if (testIpv6) + QTest::newRow("[::]") << "::" << 0 << true << "::"; + + // and binding with a port number... + // Since we want to test that we got the port number we asked for, we need a random port number. + // We use random in case a previous run of the test left the port lingering open. + // -1 indicates "random port" + QTest::newRow("0.0.0.0:randomport") << "0.0.0.0" << -1 << true << "0.0.0.0"; + if (testIpv6) + QTest::newRow("[::]:randomport") << "::" << -1 << true << "::"; + // additionally, try bind to known-bad addresses, and make sure this doesn't work // these ranges are guaranteed to be reserved for 'documentation purposes', // and thus, should be unused in the real world. Not that I'm assuming the @@ -513,8 +544,16 @@ void tst_QTcpSocket::bind_data() knownBad << "198.51.100.1"; knownBad << "2001:0DB8::1"; foreach (const QString &badAddress, knownBad) { - QTest::newRow(badAddress.toLatin1().constData()) << badAddress << false << QString(); + QTest::newRow(badAddress.toLatin1().constData()) << badAddress << 0 << false << QString(); } + +#ifdef Q_OS_UNIX + // try to bind to a privileged ports + // we should fail if we're not root (unless the ports are in use!) + QTest::newRow("127.0.0.1:1") << "127.0.0.1" << 1 << !geteuid() << (geteuid() ? QString() : "127.0.0.1"); + if (testIpv6) + QTest::newRow("[::]:1") << "::" << 1 << !geteuid() << (geteuid() ? QString() : "::"); +#endif } void tst_QTcpSocket::bind() @@ -523,23 +562,124 @@ void tst_QTcpSocket::bind() if (setProxy) return; // QTBUG-22964 for proxies, QTBUG-29972 for QSKIP QFETCH(QString, stringAddr); + QFETCH(int, port); QFETCH(bool, successExpected); QFETCH(QString, stringExpectedLocalAddress); QHostAddress addr(stringAddr); QHostAddress expectedLocalAddress(stringExpectedLocalAddress); + QTcpSocket dummySocket; // used only to "use up" a file descriptor + dummySocket.bind(); + QTcpSocket *socket = newSocket(); - qDebug() << "Binding " << addr; + quint16 boundPort; + qintptr fd; if (successExpected) { - QVERIFY2(socket->bind(addr), qPrintable(socket->errorString())); + bool randomPort = port == -1; + int attemptsLeft = 5; // only used with randomPort + do { + if (randomPort) { + // try to get a random port number + // we do this to ensure we're not trying to bind to the same port as we've just used in + // a previous run - race condition with the OS actually freeing the port + Q_STATIC_ASSERT(RAND_MAX > 1024); + port = qrand() & USHRT_MAX; + if (port < 1024) + continue; + } + + bool bindSuccess = socket->bind(addr, port); + if (!bindSuccess && randomPort && socket->error() == QTcpSocket::AddressInUseError) { + // we may have been unlucky and hit an already open port, so try another + --attemptsLeft; + continue; + } + + QVERIFY2(bindSuccess, qPrintable(socket->errorString() + ", tried port " + QString::number(port))); + break; + } while (randomPort && attemptsLeft); + + QCOMPARE(socket->state(), QAbstractSocket::BoundState); + boundPort = socket->localPort(); + if (port) + QCOMPARE(int(boundPort), port); + fd = socket->socketDescriptor(); + QVERIFY(fd != INVALID_SOCKET); } else { - QVERIFY(!socket->bind(addr)); + QVERIFY(!socket->bind(addr, port)); + QCOMPARE(socket->localPort(), quint16(0)); } QCOMPARE(socket->localAddress(), expectedLocalAddress); + if (successExpected) { + // try to use the socket and expect it to remain working + QTcpServer server; + QVERIFY(server.listen(addr)); + + // free up the file descriptor + dummySocket.close(); + + QHostAddress remoteAddr = addr; + if (addr == QHostAddress::AnyIPv4) + remoteAddr = QHostAddress::LocalHost; + else if (addr == QHostAddress::AnyIPv6) + remoteAddr = QHostAddress::LocalHostIPv6; + + socket->connectToHost(remoteAddr, server.serverPort()); + QVERIFY2(socket->waitForConnected(2000), socket->errorString().toLocal8Bit()); + QVERIFY(server.waitForNewConnection(2000)); + + QTcpSocket *acceptedSocket = server.nextPendingConnection(); + QCOMPARE(socket->localPort(), boundPort); + QCOMPARE(acceptedSocket->peerPort(), boundPort); + QCOMPARE(socket->localAddress(), remoteAddr); + QCOMPARE(socket->socketDescriptor(), fd); + } + + delete socket; +} + +//---------------------------------------------------------------------------------- + +void tst_QTcpSocket::bindThenResolveHost_data() +{ + QTest::addColumn("hostName"); + QTest::newRow("ip-literal") << QtNetworkSettings::serverIP().toString(); + QTest::newRow("name") << QtNetworkSettings::serverName(); + QTest::newRow("first-fail") << firstFailName; +} + +// similar to the previous test, but we'll connect to a host name that needs resolving +void tst_QTcpSocket::bindThenResolveHost() +{ + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; // doesn't make sense to test binding locally with proxies + + QFETCH(QString, hostName); + + QTcpSocket dummySocket; // used only to "use up" a file descriptor + dummySocket.bind(); + + QTcpSocket *socket = newSocket(); + + QVERIFY2(socket->bind(QHostAddress(QHostAddress::AnyIPv4), 0), socket->errorString().toLocal8Bit()); + QCOMPARE(socket->state(), QAbstractSocket::BoundState); + quint16 boundPort = socket->localPort(); + qintptr fd = socket->socketDescriptor(); + QVERIFY(fd != INVALID_SOCKET); + + dummySocket.close(); + + socket->connectToHost(hostName, 80); + QVERIFY2(socket->waitForConnected(), "Network timeout"); + + QCOMPARE(socket->localPort(), boundPort); + QCOMPARE(socket->socketDescriptor(), fd); + delete socket; } @@ -592,13 +732,10 @@ void tst_QTcpSocket::setSocketDescriptor() QCOMPARE(socket->socketDescriptor(), (qintptr)sock); qt_qhostinfo_clear_cache(); //avoid the HostLookupState being skipped due to address being in cache from previous test. - socket->connectToHost(QtNetworkSettings::serverName(), 143); + socket->connectToHost(QtNetworkSettings::serverName(), 80); QCOMPARE(socket->state(), QTcpSocket::HostLookupState); QCOMPARE(socket->socketDescriptor(), (qintptr)sock); QVERIFY(socket->waitForConnected(10000)); - // skip this, it has been broken for years, see task 260735 - // if somebody complains, consider fixing it, but it might break existing applications. - QEXPECT_FAIL("", "bug has been around for years, will not fix without need", Continue); QCOMPARE(socket->socketDescriptor(), (qintptr)sock); delete socket; #ifdef Q_OS_WIN @@ -615,8 +752,8 @@ void tst_QTcpSocket::socketDescriptor() QCOMPARE(socket->socketDescriptor(), (qintptr)-1); socket->connectToHost(QtNetworkSettings::serverName(), 143); - QVERIFY((socket->state() == QAbstractSocket::HostLookupState && socket->socketDescriptor() == -1) || - (socket->state() == QAbstractSocket::ConnectingState && socket->socketDescriptor() != -1)); + QVERIFY(socket->state() == QAbstractSocket::HostLookupState || + socket->state() == QAbstractSocket::ConnectingState); QVERIFY(socket->waitForConnected(10000)); QVERIFY(socket->state() == QAbstractSocket::ConnectedState); QVERIFY(socket->socketDescriptor() != -1); diff --git a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp index 76d4543da9..4bd330b04f 100644 --- a/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp +++ b/tests/auto/network/socket/qudpsocket/tst_qudpsocket.cpp @@ -85,7 +85,8 @@ private slots: void dualStack(); void dualStackAutoBinding(); void dualStackNoIPv4onV6only(); - void readLine(); + void connectToHost(); + void bindAndConnectToHost(); void pendingDatagramSize(); void writeDatagram(); void performance(); @@ -621,7 +622,7 @@ void tst_QUdpSocket::empty_connectedSlot() //---------------------------------------------------------------------------------- -void tst_QUdpSocket::readLine() +void tst_QUdpSocket::connectToHost() { QUdpSocket socket1; QUdpSocket socket2; @@ -629,10 +630,41 @@ void tst_QUdpSocket::readLine() socket1.setProperty("_q_networksession", QVariant::fromValue(networkSession)); socket2.setProperty("_q_networksession", QVariant::fromValue(networkSession)); #endif + + QVERIFY2(socket1.bind(), socket1.errorString().toLatin1().constData()); + + socket2.connectToHost(makeNonAny(socket1.localAddress()), socket1.localPort()); + QVERIFY(socket2.waitForConnected(5000)); +} + +//---------------------------------------------------------------------------------- + +void tst_QUdpSocket::bindAndConnectToHost() +{ + QUdpSocket socket1; + QUdpSocket socket2; + QUdpSocket dummysocket; +#ifdef FORCE_SESSION + socket1.setProperty("_q_networksession", QVariant::fromValue(networkSession)); + socket2.setProperty("_q_networksession", QVariant::fromValue(networkSession)); + dummysocket.setProperty("_q_networksession", QVariant::fromValue(networkSession)); +#endif + + // we use the dummy socket to use up a file descriptor + dummysocket.bind(); + + QVERIFY2(socket2.bind(), socket2.errorString().toLatin1()); + quint16 boundPort = socket2.localPort(); + qintptr fd = socket2.socketDescriptor(); + QVERIFY2(socket1.bind(), socket1.errorString().toLatin1().constData()); + dummysocket.close(); socket2.connectToHost(makeNonAny(socket1.localAddress()), socket1.localPort()); QVERIFY(socket2.waitForConnected(5000)); + + QCOMPARE(socket2.localPort(), boundPort); + QCOMPARE(socket2.socketDescriptor(), fd); } //---------------------------------------------------------------------------------- -- cgit v1.2.3 From 126d489f7f561bc3967ee2a36624c3b1fa26f974 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 24 Dec 2014 16:43:57 -0200 Subject: Adjust the socket address family before bind()/connect()/sendto() If our socket is already of a given type (probably due to a previous call to bind()), then constrain the incoming target address to be of the same family. On some OSs, trying to send or connect to an IPv4 address from an IPv6 socket will fail with EINVAL, even if the socket is not in "v6only" mode. bind() can't be called after already being bound, but the function can still be called on a socket created by the user and passed on with setSocketDescriptor(). Change-Id: I209a1f8d0c782c6b6de2b39ea4cfad74d63f3293 Reviewed-by: Richard J. Moore --- src/network/socket/qnativesocketengine.cpp | 38 +++++++++++++++++++++++++++--- src/network/socket/qnativesocketengine_p.h | 1 + 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp index fcfef87e3c..52e6922b5f 100644 --- a/src/network/socket/qnativesocketengine.cpp +++ b/src/network/socket/qnativesocketengine.cpp @@ -281,6 +281,38 @@ void QNativeSocketEnginePrivate::setError(QAbstractSocket::SocketError error, Er } } +/*! + \internal + + Adjusts the incoming \a address family to match the currently bound address + (if any). This function will convert v4-mapped IPv6 addresses to IPv4 and + vice-versa. All other address types and values will be left unchanged. + */ +QHostAddress QNativeSocketEnginePrivate::adjustAddressProtocol(const QHostAddress &address) const +{ + QAbstractSocket::NetworkLayerProtocol targetProtocol = socketProtocol; + if (Q_LIKELY(targetProtocol == QAbstractSocket::UnknownNetworkLayerProtocol)) + return address; + + QAbstractSocket::NetworkLayerProtocol sourceProtocol = address.protocol(); + + if (targetProtocol == QAbstractSocket::AnyIPProtocol) + targetProtocol = QAbstractSocket::IPv6Protocol; + if (targetProtocol == QAbstractSocket::IPv6Protocol && sourceProtocol == QAbstractSocket::IPv4Protocol) { + // convert to IPv6 v4-mapped address. This always works + return QHostAddress(address.toIPv6Address()); + } + + if (targetProtocol == QAbstractSocket::IPv4Protocol && sourceProtocol == QAbstractSocket::IPv6Protocol) { + // convert to IPv4 if the source is a v4-mapped address + quint32 ip4 = address.toIPv4Address(); + if (ip4) + return QHostAddress(ip4); + } + + return address; +} + bool QNativeSocketEnginePrivate::checkProxy(const QHostAddress &address) { if (address.isLoopback()) @@ -506,7 +538,7 @@ bool QNativeSocketEngine::connectToHost(const QHostAddress &address, quint16 por d->peerAddress = address; d->peerPort = port; - bool connected = d->nativeConnect(address, port); + bool connected = d->nativeConnect(d->adjustAddressProtocol(address), port); if (connected) d->fetchConnectionParameters(); @@ -566,7 +598,7 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port) Q_CHECK_STATE(QNativeSocketEngine::bind(), QAbstractSocket::UnconnectedState, false); - if (!d->nativeBind(address, port)) + if (!d->nativeBind(d->adjustAddressProtocol(address), port)) return false; d->fetchConnectionParameters(); @@ -776,7 +808,7 @@ qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 size, Q_D(QNativeSocketEngine); Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::writeDatagram(), -1); Q_CHECK_TYPE(QNativeSocketEngine::writeDatagram(), QAbstractSocket::UdpSocket, -1); - return d->nativeSendDatagram(data, size, host, port); + return d->nativeSendDatagram(data, size, d->adjustAddressProtocol(host), port); } /*! diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h index 4ec6023d4b..24909bf310 100644 --- a/src/network/socket/qnativesocketengine_p.h +++ b/src/network/socket/qnativesocketengine_p.h @@ -232,6 +232,7 @@ public: }; void setError(QAbstractSocket::SocketError error, ErrorString errorString) const; + QHostAddress adjustAddressProtocol(const QHostAddress &address) const; // native functions int option(QNativeSocketEngine::SocketOption option) const; -- cgit v1.2.3 From 212285639d748c7def8648f89b8c1c21c5f481e6 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 15 Jan 2015 15:16:53 -0800 Subject: Add missing fetchAndXxx methods to atomic classes based on std::atomic And add tests for the GCC intrinsics and for std::atomic. Task-number: QTBUG-43794 Change-Id: Ic5d393bfd36e48a193fcffff13b9b2dbaee80469 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/arch/qatomic_cxx11.h | 96 ++++++++++++++++++++++ src/corelib/thread/qbasicatomic.h | 8 ++ .../corelib/thread/qatomicinteger/char/char.pro | 1 - .../thread/qatomicinteger/char16_t/char16_t.pro | 1 - .../thread/qatomicinteger/char32_t/char32_t.pro | 1 - .../thread/qatomicinteger/cxx11/char/char.pro | 1 + .../qatomicinteger/cxx11/char16_t/char16_t.pro | 1 + .../qatomicinteger/cxx11/char32_t/char32_t.pro | 1 + .../thread/qatomicinteger/cxx11/int/int.pro | 1 + .../thread/qatomicinteger/cxx11/long/long.pro | 1 + .../qatomicinteger/cxx11/qlonglong/qlonglong.pro | 1 + .../qatomicinteger/cxx11/qptrdiff/qptrdiff.pro | 1 + .../qatomicinteger/cxx11/quintptr/quintptr.pro | 1 + .../qatomicinteger/cxx11/qulonglong/qulonglong.pro | 1 + .../thread/qatomicinteger/cxx11/schar/schar.pro | 1 + .../thread/qatomicinteger/cxx11/short/short.pro | 1 + .../thread/qatomicinteger/cxx11/uchar/uchar.pro | 1 + .../thread/qatomicinteger/cxx11/uint/uint.pro | 1 + .../thread/qatomicinteger/cxx11/ulong/ulong.pro | 1 + .../thread/qatomicinteger/cxx11/ushort/ushort.pro | 1 + .../qatomicinteger/cxx11/wchar_t/wchar_t.pro | 1 + .../thread/qatomicinteger/gcc/char/char.pro | 1 + .../qatomicinteger/gcc/char16_t/char16_t.pro | 1 + .../qatomicinteger/gcc/char32_t/char32_t.pro | 1 + .../corelib/thread/qatomicinteger/gcc/int/int.pro | 1 + .../thread/qatomicinteger/gcc/long/long.pro | 1 + .../qatomicinteger/gcc/qlonglong/qlonglong.pro | 1 + .../qatomicinteger/gcc/qptrdiff/qptrdiff.pro | 1 + .../qatomicinteger/gcc/quintptr/quintptr.pro | 1 + .../qatomicinteger/gcc/qulonglong/qulonglong.pro | 1 + .../thread/qatomicinteger/gcc/schar/schar.pro | 1 + .../thread/qatomicinteger/gcc/short/short.pro | 1 + .../thread/qatomicinteger/gcc/uchar/uchar.pro | 1 + .../thread/qatomicinteger/gcc/uint/uint.pro | 1 + .../thread/qatomicinteger/gcc/ulong/ulong.pro | 1 + .../thread/qatomicinteger/gcc/ushort/ushort.pro | 1 + .../thread/qatomicinteger/gcc/wchar_t/wchar_t.pro | 1 + .../auto/corelib/thread/qatomicinteger/int/int.pro | 1 - .../corelib/thread/qatomicinteger/long/long.pro | 1 - .../thread/qatomicinteger/qatomicinteger.pri | 19 ++++- .../thread/qatomicinteger/qatomicinteger.pro | 39 +++++++++ .../thread/qatomicinteger/qlonglong/qlonglong.pro | 1 - .../thread/qatomicinteger/qptrdiff/qptrdiff.pro | 1 - .../thread/qatomicinteger/quintptr/quintptr.pro | 1 - .../qatomicinteger/qulonglong/qulonglong.pro | 1 - .../corelib/thread/qatomicinteger/schar/schar.pro | 1 - .../corelib/thread/qatomicinteger/short/short.pro | 1 - .../thread/qatomicinteger/tst_qatomicinteger.cpp | 24 ++++++ .../corelib/thread/qatomicinteger/uchar/uchar.pro | 1 - .../corelib/thread/qatomicinteger/uint/uint.pro | 1 - .../corelib/thread/qatomicinteger/ulong/ulong.pro | 1 - .../thread/qatomicinteger/ushort/ushort.pro | 1 - .../thread/qatomicinteger/wchar_t/wchar_t.pro | 1 - 53 files changed, 215 insertions(+), 19 deletions(-) create mode 100644 tests/auto/corelib/thread/qatomicinteger/cxx11/char/char.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/cxx11/char16_t/char16_t.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/cxx11/char32_t/char32_t.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/cxx11/int/int.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/cxx11/long/long.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/cxx11/qlonglong/qlonglong.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/cxx11/qptrdiff/qptrdiff.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/cxx11/quintptr/quintptr.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/cxx11/qulonglong/qulonglong.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/cxx11/schar/schar.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/cxx11/short/short.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/cxx11/uchar/uchar.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/cxx11/uint/uint.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/cxx11/ulong/ulong.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/cxx11/ushort/ushort.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/cxx11/wchar_t/wchar_t.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/gcc/char/char.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/gcc/char16_t/char16_t.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/gcc/char32_t/char32_t.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/gcc/int/int.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/gcc/long/long.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/gcc/qlonglong/qlonglong.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/gcc/qptrdiff/qptrdiff.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/gcc/quintptr/quintptr.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/gcc/qulonglong/qulonglong.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/gcc/schar/schar.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/gcc/short/short.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/gcc/uchar/uchar.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/gcc/uint/uint.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/gcc/ulong/ulong.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/gcc/ushort/ushort.pro create mode 100644 tests/auto/corelib/thread/qatomicinteger/gcc/wchar_t/wchar_t.pro diff --git a/src/corelib/arch/qatomic_cxx11.h b/src/corelib/arch/qatomic_cxx11.h index a58c8ab72e..09e900f4ea 100644 --- a/src/corelib/arch/qatomic_cxx11.h +++ b/src/corelib/arch/qatomic_cxx11.h @@ -230,6 +230,102 @@ template struct QAtomicOps { return _q_value.fetch_add(valueToAdd, std::memory_order_acq_rel); } + + template static inline + T fetchAndSubRelaxed(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_sub(valueToAdd, std::memory_order_relaxed); + } + + template static inline + T fetchAndSubAcquire(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_sub(valueToAdd, std::memory_order_acquire); + } + + template static inline + T fetchAndSubRelease(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_sub(valueToAdd, std::memory_order_release); + } + + template static inline + T fetchAndSubOrdered(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_sub(valueToAdd, std::memory_order_acq_rel); + } + + template static inline + T fetchAndAndRelaxed(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_and(valueToAdd, std::memory_order_relaxed); + } + + template static inline + T fetchAndAndAcquire(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_and(valueToAdd, std::memory_order_acquire); + } + + template static inline + T fetchAndAndRelease(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_and(valueToAdd, std::memory_order_release); + } + + template static inline + T fetchAndAndOrdered(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_and(valueToAdd, std::memory_order_acq_rel); + } + + template static inline + T fetchAndOrRelaxed(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_or(valueToAdd, std::memory_order_relaxed); + } + + template static inline + T fetchAndOrAcquire(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_or(valueToAdd, std::memory_order_acquire); + } + + template static inline + T fetchAndOrRelease(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_or(valueToAdd, std::memory_order_release); + } + + template static inline + T fetchAndOrOrdered(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_or(valueToAdd, std::memory_order_acq_rel); + } + + template static inline + T fetchAndXorRelaxed(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_xor(valueToAdd, std::memory_order_relaxed); + } + + template static inline + T fetchAndXorAcquire(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_xor(valueToAdd, std::memory_order_acquire); + } + + template static inline + T fetchAndXorRelease(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_xor(valueToAdd, std::memory_order_release); + } + + template static inline + T fetchAndXorOrdered(std::atomic &_q_value, typename QAtomicAdditiveType::AdditiveT valueToAdd) Q_DECL_NOTHROW + { + return _q_value.fetch_xor(valueToAdd, std::memory_order_acq_rel); + } }; #ifdef ATOMIC_VAR_INIT diff --git a/src/corelib/thread/qbasicatomic.h b/src/corelib/thread/qbasicatomic.h index 16a27862c2..ecf39d699f 100644 --- a/src/corelib/thread/qbasicatomic.h +++ b/src/corelib/thread/qbasicatomic.h @@ -39,6 +39,14 @@ #if defined(QT_BOOTSTRAPPED) # include +// The following two are used for testing only. +// Note that we don't check the compiler support -- you had better +// know what you're doing if you set them +#elif defined(QT_ATOMIC_FORCE_CXX11) +# include +#elif defined(QT_ATOMIC_FORCE_GCC) +# include + // Compiler dependent implementation #elif defined(Q_CC_MSVC) # include diff --git a/tests/auto/corelib/thread/qatomicinteger/char/char.pro b/tests/auto/corelib/thread/qatomicinteger/char/char.pro index 51ef1add8f..1e97d5cbae 100644 --- a/tests/auto/corelib/thread/qatomicinteger/char/char.pro +++ b/tests/auto/corelib/thread/qatomicinteger/char/char.pro @@ -1,2 +1 @@ -TYPE = $$basename(PWD) include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/char16_t/char16_t.pro b/tests/auto/corelib/thread/qatomicinteger/char16_t/char16_t.pro index 51ef1add8f..1e97d5cbae 100644 --- a/tests/auto/corelib/thread/qatomicinteger/char16_t/char16_t.pro +++ b/tests/auto/corelib/thread/qatomicinteger/char16_t/char16_t.pro @@ -1,2 +1 @@ -TYPE = $$basename(PWD) include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/char32_t/char32_t.pro b/tests/auto/corelib/thread/qatomicinteger/char32_t/char32_t.pro index 51ef1add8f..1e97d5cbae 100644 --- a/tests/auto/corelib/thread/qatomicinteger/char32_t/char32_t.pro +++ b/tests/auto/corelib/thread/qatomicinteger/char32_t/char32_t.pro @@ -1,2 +1 @@ -TYPE = $$basename(PWD) include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/cxx11/char/char.pro b/tests/auto/corelib/thread/qatomicinteger/cxx11/char/char.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/cxx11/char/char.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/cxx11/char16_t/char16_t.pro b/tests/auto/corelib/thread/qatomicinteger/cxx11/char16_t/char16_t.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/cxx11/char16_t/char16_t.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/cxx11/char32_t/char32_t.pro b/tests/auto/corelib/thread/qatomicinteger/cxx11/char32_t/char32_t.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/cxx11/char32_t/char32_t.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/cxx11/int/int.pro b/tests/auto/corelib/thread/qatomicinteger/cxx11/int/int.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/cxx11/int/int.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/cxx11/long/long.pro b/tests/auto/corelib/thread/qatomicinteger/cxx11/long/long.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/cxx11/long/long.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/cxx11/qlonglong/qlonglong.pro b/tests/auto/corelib/thread/qatomicinteger/cxx11/qlonglong/qlonglong.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/cxx11/qlonglong/qlonglong.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/cxx11/qptrdiff/qptrdiff.pro b/tests/auto/corelib/thread/qatomicinteger/cxx11/qptrdiff/qptrdiff.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/cxx11/qptrdiff/qptrdiff.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/cxx11/quintptr/quintptr.pro b/tests/auto/corelib/thread/qatomicinteger/cxx11/quintptr/quintptr.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/cxx11/quintptr/quintptr.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/cxx11/qulonglong/qulonglong.pro b/tests/auto/corelib/thread/qatomicinteger/cxx11/qulonglong/qulonglong.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/cxx11/qulonglong/qulonglong.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/cxx11/schar/schar.pro b/tests/auto/corelib/thread/qatomicinteger/cxx11/schar/schar.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/cxx11/schar/schar.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/cxx11/short/short.pro b/tests/auto/corelib/thread/qatomicinteger/cxx11/short/short.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/cxx11/short/short.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/cxx11/uchar/uchar.pro b/tests/auto/corelib/thread/qatomicinteger/cxx11/uchar/uchar.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/cxx11/uchar/uchar.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/cxx11/uint/uint.pro b/tests/auto/corelib/thread/qatomicinteger/cxx11/uint/uint.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/cxx11/uint/uint.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/cxx11/ulong/ulong.pro b/tests/auto/corelib/thread/qatomicinteger/cxx11/ulong/ulong.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/cxx11/ulong/ulong.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/cxx11/ushort/ushort.pro b/tests/auto/corelib/thread/qatomicinteger/cxx11/ushort/ushort.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/cxx11/ushort/ushort.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/cxx11/wchar_t/wchar_t.pro b/tests/auto/corelib/thread/qatomicinteger/cxx11/wchar_t/wchar_t.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/cxx11/wchar_t/wchar_t.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/gcc/char/char.pro b/tests/auto/corelib/thread/qatomicinteger/gcc/char/char.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/gcc/char/char.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/gcc/char16_t/char16_t.pro b/tests/auto/corelib/thread/qatomicinteger/gcc/char16_t/char16_t.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/gcc/char16_t/char16_t.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/gcc/char32_t/char32_t.pro b/tests/auto/corelib/thread/qatomicinteger/gcc/char32_t/char32_t.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/gcc/char32_t/char32_t.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/gcc/int/int.pro b/tests/auto/corelib/thread/qatomicinteger/gcc/int/int.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/gcc/int/int.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/gcc/long/long.pro b/tests/auto/corelib/thread/qatomicinteger/gcc/long/long.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/gcc/long/long.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/gcc/qlonglong/qlonglong.pro b/tests/auto/corelib/thread/qatomicinteger/gcc/qlonglong/qlonglong.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/gcc/qlonglong/qlonglong.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/gcc/qptrdiff/qptrdiff.pro b/tests/auto/corelib/thread/qatomicinteger/gcc/qptrdiff/qptrdiff.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/gcc/qptrdiff/qptrdiff.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/gcc/quintptr/quintptr.pro b/tests/auto/corelib/thread/qatomicinteger/gcc/quintptr/quintptr.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/gcc/quintptr/quintptr.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/gcc/qulonglong/qulonglong.pro b/tests/auto/corelib/thread/qatomicinteger/gcc/qulonglong/qulonglong.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/gcc/qulonglong/qulonglong.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/gcc/schar/schar.pro b/tests/auto/corelib/thread/qatomicinteger/gcc/schar/schar.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/gcc/schar/schar.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/gcc/short/short.pro b/tests/auto/corelib/thread/qatomicinteger/gcc/short/short.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/gcc/short/short.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/gcc/uchar/uchar.pro b/tests/auto/corelib/thread/qatomicinteger/gcc/uchar/uchar.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/gcc/uchar/uchar.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/gcc/uint/uint.pro b/tests/auto/corelib/thread/qatomicinteger/gcc/uint/uint.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/gcc/uint/uint.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/gcc/ulong/ulong.pro b/tests/auto/corelib/thread/qatomicinteger/gcc/ulong/ulong.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/gcc/ulong/ulong.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/gcc/ushort/ushort.pro b/tests/auto/corelib/thread/qatomicinteger/gcc/ushort/ushort.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/gcc/ushort/ushort.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/gcc/wchar_t/wchar_t.pro b/tests/auto/corelib/thread/qatomicinteger/gcc/wchar_t/wchar_t.pro new file mode 100644 index 0000000000..64401f0229 --- /dev/null +++ b/tests/auto/corelib/thread/qatomicinteger/gcc/wchar_t/wchar_t.pro @@ -0,0 +1 @@ +include(../../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/int/int.pro b/tests/auto/corelib/thread/qatomicinteger/int/int.pro index 51ef1add8f..1e97d5cbae 100644 --- a/tests/auto/corelib/thread/qatomicinteger/int/int.pro +++ b/tests/auto/corelib/thread/qatomicinteger/int/int.pro @@ -1,2 +1 @@ -TYPE = $$basename(PWD) include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/long/long.pro b/tests/auto/corelib/thread/qatomicinteger/long/long.pro index 51ef1add8f..1e97d5cbae 100644 --- a/tests/auto/corelib/thread/qatomicinteger/long/long.pro +++ b/tests/auto/corelib/thread/qatomicinteger/long/long.pro @@ -1,2 +1 @@ -TYPE = $$basename(PWD) include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/qatomicinteger.pri b/tests/auto/corelib/thread/qatomicinteger/qatomicinteger.pri index dc7cc8bcec..d9ebe64d5b 100644 --- a/tests/auto/corelib/thread/qatomicinteger/qatomicinteger.pri +++ b/tests/auto/corelib/thread/qatomicinteger/qatomicinteger.pri @@ -1,7 +1,20 @@ -isEmpty(TYPE): error("Project must define TYPE variable") +# Get our build type from the directory name +TYPE = $$basename(_PRO_FILE_PWD_) +dn = $$dirname(_PRO_FILE_PWD_) +FORCE = $$basename(dn) + +equals(FORCE, cxx11) { + suffix = Cxx11_$$TYPE + DEFINES += QT_ATOMIC_FORCE_CXX11 +} else: equals(FORCE, gcc) { + suffix = Gcc_$$TYPE + DEFINES += QT_ATOMIC_FORCE_GCC +} else { + suffix = $$TYPE +} CONFIG += testcase parallel_test QT = core testlib -TARGET = tst_qatomicinteger_$$TYPE +TARGET = tst_qatomicinteger_$$lower($$suffix) SOURCES = $$PWD/tst_qatomicinteger.cpp -DEFINES += QATOMIC_TEST_TYPE=$$TYPE tst_QAtomicIntegerXX=tst_QAtomicInteger_$$TYPE +DEFINES += QATOMIC_TEST_TYPE=$$TYPE tst_QAtomicIntegerXX=tst_QAtomicInteger_$$suffix diff --git a/tests/auto/corelib/thread/qatomicinteger/qatomicinteger.pro b/tests/auto/corelib/thread/qatomicinteger/qatomicinteger.pro index 373e8801a4..58e5b157bd 100644 --- a/tests/auto/corelib/thread/qatomicinteger/qatomicinteger.pro +++ b/tests/auto/corelib/thread/qatomicinteger/qatomicinteger.pro @@ -17,3 +17,42 @@ SUBDIRS=\ ushort \ wchar_t \ + +contains(QT_CONFIG, c++11)|msvc: SUBDIRS +=\ + cxx11/char \ + cxx11/char16_t \ + cxx11/char32_t \ + cxx11/int \ + cxx11/long \ + cxx11/qlonglong \ + cxx11/qptrdiff \ + cxx11/quintptr \ + cxx11/qulonglong \ + cxx11/schar \ + cxx11/short \ + cxx11/uchar \ + cxx11/uint \ + cxx11/ulong \ + cxx11/ushort \ + cxx11/wchar_t \ + + +# The GCC-style atomics only support 32-bit and pointer-sized but add +# them all anyway so we ensure the macros are properly defined +gcc: SUBDIRS +=\ + gcc/char \ + gcc/char16_t \ + gcc/char32_t \ + gcc/int \ + gcc/long \ + gcc/qlonglong \ + gcc/qptrdiff \ + gcc/quintptr \ + gcc/qulonglong \ + gcc/schar \ + gcc/short \ + gcc/uchar \ + gcc/uint \ + gcc/ulong \ + gcc/ushort \ + gcc/wchar_t \ diff --git a/tests/auto/corelib/thread/qatomicinteger/qlonglong/qlonglong.pro b/tests/auto/corelib/thread/qatomicinteger/qlonglong/qlonglong.pro index 51ef1add8f..1e97d5cbae 100644 --- a/tests/auto/corelib/thread/qatomicinteger/qlonglong/qlonglong.pro +++ b/tests/auto/corelib/thread/qatomicinteger/qlonglong/qlonglong.pro @@ -1,2 +1 @@ -TYPE = $$basename(PWD) include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/qptrdiff/qptrdiff.pro b/tests/auto/corelib/thread/qatomicinteger/qptrdiff/qptrdiff.pro index 51ef1add8f..1e97d5cbae 100644 --- a/tests/auto/corelib/thread/qatomicinteger/qptrdiff/qptrdiff.pro +++ b/tests/auto/corelib/thread/qatomicinteger/qptrdiff/qptrdiff.pro @@ -1,2 +1 @@ -TYPE = $$basename(PWD) include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/quintptr/quintptr.pro b/tests/auto/corelib/thread/qatomicinteger/quintptr/quintptr.pro index 51ef1add8f..1e97d5cbae 100644 --- a/tests/auto/corelib/thread/qatomicinteger/quintptr/quintptr.pro +++ b/tests/auto/corelib/thread/qatomicinteger/quintptr/quintptr.pro @@ -1,2 +1 @@ -TYPE = $$basename(PWD) include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/qulonglong/qulonglong.pro b/tests/auto/corelib/thread/qatomicinteger/qulonglong/qulonglong.pro index 51ef1add8f..1e97d5cbae 100644 --- a/tests/auto/corelib/thread/qatomicinteger/qulonglong/qulonglong.pro +++ b/tests/auto/corelib/thread/qatomicinteger/qulonglong/qulonglong.pro @@ -1,2 +1 @@ -TYPE = $$basename(PWD) include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/schar/schar.pro b/tests/auto/corelib/thread/qatomicinteger/schar/schar.pro index 51ef1add8f..1e97d5cbae 100644 --- a/tests/auto/corelib/thread/qatomicinteger/schar/schar.pro +++ b/tests/auto/corelib/thread/qatomicinteger/schar/schar.pro @@ -1,2 +1 @@ -TYPE = $$basename(PWD) include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/short/short.pro b/tests/auto/corelib/thread/qatomicinteger/short/short.pro index 51ef1add8f..1e97d5cbae 100644 --- a/tests/auto/corelib/thread/qatomicinteger/short/short.pro +++ b/tests/auto/corelib/thread/qatomicinteger/short/short.pro @@ -1,2 +1 @@ -TYPE = $$basename(PWD) include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp b/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp index cb01237b85..d3c85c54a7 100644 --- a/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp +++ b/tests/auto/corelib/thread/qatomicinteger/tst_qatomicinteger.cpp @@ -31,6 +31,30 @@ ** ****************************************************************************/ +#ifdef QT_ATOMIC_FORCE_CXX11 +// We need to check if this compiler has C++11 atomics and constexpr support. +// We can't rely on qcompilerdetection.h because it forces all of qglobal.h to +// be included, which causes qbasicatomic.h to be included too. +// Incomplete, but ok +# if defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1500 && (__cplusplus >= 201103L || defined(__INTEL_CXX11_MODE__)) +# elif defined(__clang__) && (__cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)) +# if !__has_feature(cxx_constexpr) || !__has_feature(cxx_atomic) || !__has_include() +# undef QT_ATOMIC_FORCE_CXX11 +# endif +# elif defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 407 && (__cplusplus >= 201103L || defined(__GXX_EXPERIMENTAL_CXX0X__)) +# elif defined(_MSC_VER) && _MSC_VER >= 1900 + // We need MSVC 2015 because of: atomics (2012), constexpr (2015), and unrestricted unions (2015). + // Support for constexpr is not working completely on MSVC 2015 but it's enough for the test. +# else +# undef QT_ATOMIC_FORCE_CXX11 +# endif + +# ifndef QT_ATOMIC_FORCE_CXX11 +# undef QATOMIC_TEST_TYPE +# define QATOMIC_TEST_TYPE unsupported +# endif +#endif + #include #include diff --git a/tests/auto/corelib/thread/qatomicinteger/uchar/uchar.pro b/tests/auto/corelib/thread/qatomicinteger/uchar/uchar.pro index 51ef1add8f..1e97d5cbae 100644 --- a/tests/auto/corelib/thread/qatomicinteger/uchar/uchar.pro +++ b/tests/auto/corelib/thread/qatomicinteger/uchar/uchar.pro @@ -1,2 +1 @@ -TYPE = $$basename(PWD) include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/uint/uint.pro b/tests/auto/corelib/thread/qatomicinteger/uint/uint.pro index 51ef1add8f..1e97d5cbae 100644 --- a/tests/auto/corelib/thread/qatomicinteger/uint/uint.pro +++ b/tests/auto/corelib/thread/qatomicinteger/uint/uint.pro @@ -1,2 +1 @@ -TYPE = $$basename(PWD) include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/ulong/ulong.pro b/tests/auto/corelib/thread/qatomicinteger/ulong/ulong.pro index 51ef1add8f..1e97d5cbae 100644 --- a/tests/auto/corelib/thread/qatomicinteger/ulong/ulong.pro +++ b/tests/auto/corelib/thread/qatomicinteger/ulong/ulong.pro @@ -1,2 +1 @@ -TYPE = $$basename(PWD) include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/ushort/ushort.pro b/tests/auto/corelib/thread/qatomicinteger/ushort/ushort.pro index 51ef1add8f..1e97d5cbae 100644 --- a/tests/auto/corelib/thread/qatomicinteger/ushort/ushort.pro +++ b/tests/auto/corelib/thread/qatomicinteger/ushort/ushort.pro @@ -1,2 +1 @@ -TYPE = $$basename(PWD) include(../qatomicinteger.pri) diff --git a/tests/auto/corelib/thread/qatomicinteger/wchar_t/wchar_t.pro b/tests/auto/corelib/thread/qatomicinteger/wchar_t/wchar_t.pro index 51ef1add8f..1e97d5cbae 100644 --- a/tests/auto/corelib/thread/qatomicinteger/wchar_t/wchar_t.pro +++ b/tests/auto/corelib/thread/qatomicinteger/wchar_t/wchar_t.pro @@ -1,2 +1 @@ -TYPE = $$basename(PWD) include(../qatomicinteger.pri) -- cgit v1.2.3 From 7f5b94b473cd19217127a69c0b8995e00b023173 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20Str=C3=B8mme?= Date: Fri, 27 Feb 2015 16:32:33 +0100 Subject: Fix shortcut overriding. Moved to processKeyEvents() on all platforms except OS X. Previously QWindowSystemInterface::tryHandleShortcutEvent() was called from inside QWindowSystemInterface, this is considered unsafe as it ends up calling sendEvent(). On some platforms the call might come from a different thread then the receiver and cause an assert. Task-number: QTBUG-44712 Change-Id: Ie80c698f63b9c3d9f52aa94380e539a84caea912 Reviewed-by: Frederik Gladhorn --- src/gui/kernel/qguiapplication.cpp | 7 +++++++ src/gui/kernel/qwindowsysteminterface.cpp | 10 ++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index b60ef4b8c1..243ef70efc 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1859,6 +1859,13 @@ void QGuiApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyE window = QGuiApplication::focusWindow(); } +#if !defined(Q_OS_OSX) + // On OS X the shortcut override is checked earlier, see: QWindowSystemInterface::handleKeyEvent() + const bool checkShortcut = e->keyType == QEvent::KeyPress && window != 0; + if (checkShortcut && QWindowSystemInterface::tryHandleShortcutEvent(window, e->timestamp, e->key, e->modifiers, e->unicode)) + return; +#endif // Q_OS_OSX + QKeyEvent ev(e->keyType, e->key, e->modifiers, e->nativeScanCode, e->nativeVirtualKey, e->nativeModifiers, e->unicode, e->repeat, e->repeatCount); diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 9a2fb33bbc..73b1a84005 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -292,8 +292,13 @@ void QWindowSystemInterface::handleKeyEvent(QWindow *w, QEvent::Type t, int k, Q void QWindowSystemInterface::handleKeyEvent(QWindow *tlw, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count) { + // This is special handling needed for OS X which eventually will call sendEvent(), on other platforms + // this might not be safe, e.g., on Android. See: QGuiApplicationPrivate::processKeyEvent() for + // shortcut overriding on other platforms. +#if defined(Q_OS_OSX) if (t == QEvent::KeyPress && QWindowSystemInterface::tryHandleShortcutEvent(tlw, timestamp, k, mods, text)) return; +#endif // Q_OS_OSX QWindowSystemInterfacePrivate::KeyEvent * e = new QWindowSystemInterfacePrivate::KeyEvent(tlw, timestamp, t, k, mods, text, autorep, count); @@ -318,10 +323,7 @@ void QWindowSystemInterface::handleExtendedKeyEvent(QWindow *tlw, ulong timestam const QString& text, bool autorep, ushort count, bool tryShortcutOverride) { - // on OS X we try the shortcut override even earlier and thus shouldn't handle it here - if (tryShortcutOverride && type == QEvent::KeyPress && QWindowSystemInterface::tryHandleShortcutEvent(tlw, timestamp, key, modifiers, text)) - return; - + Q_UNUSED(tryShortcutOverride) QWindowSystemInterfacePrivate::KeyEvent * e = new QWindowSystemInterfacePrivate::KeyEvent(tlw, timestamp, type, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count); -- cgit v1.2.3 From 918e976d398365f49a8de871a680ecd7a6614e70 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Tue, 3 Mar 2015 11:06:14 +0100 Subject: xcb: QkeySequence::Quit is control-Q Until now it was mapped that way only under KDE and Gnome. Task-number: QTBUG-44772 Change-Id: I65a425bb531909dff4110f086c9aee8ae7a747c6 Reviewed-by: Laszlo Agocs --- src/gui/kernel/qplatformtheme.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/kernel/qplatformtheme.cpp b/src/gui/kernel/qplatformtheme.cpp index c53b71eafc..aa49d64309 100644 --- a/src/gui/kernel/qplatformtheme.cpp +++ b/src/gui/kernel/qplatformtheme.cpp @@ -315,7 +315,7 @@ const QKeyBinding QPlatformThemePrivate::keyBindings[] = { {QKeySequence::InsertLineSeparator, 0, Qt::META | Qt::Key_O, KB_Mac}, {QKeySequence::SaveAs, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_S, KB_Gnome | KB_Mac}, {QKeySequence::Preferences, 0, Qt::CTRL | Qt::Key_Comma, KB_Mac}, - {QKeySequence::Quit, 0, Qt::CTRL | Qt::Key_Q, KB_Gnome | KB_KDE | KB_Mac}, + {QKeySequence::Quit, 0, Qt::CTRL | Qt::Key_Q, KB_X11 | KB_Gnome | KB_KDE | KB_Mac}, {QKeySequence::FullScreen, 1, Qt::META | Qt::CTRL | Qt::Key_F, KB_Mac}, {QKeySequence::FullScreen, 0, Qt::ALT | Qt::Key_Enter, KB_Win}, {QKeySequence::FullScreen, 0, Qt::CTRL | Qt::SHIFT | Qt::Key_F, KB_KDE}, -- cgit v1.2.3 From 8ceb4d9dbcc8468e2bb4d40ee96ce38d86d985a1 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 27 Feb 2015 11:45:10 +0100 Subject: Implement debug operator for QStyle::State using the new operator for QFlags. Call the new operator and add ### fixme comments for removal. Change-Id: Ibe4dfe00b6ea1aa5ca5551f10b1f27fdde2114c4 Reviewed-by: Shawn Rutledge Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/widgets/styles/qstyle.cpp | 47 +++++++++---------------------------------- src/widgets/styles/qstyle.h | 3 +++ 2 files changed, 13 insertions(+), 37 deletions(-) diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp index 5fc2164c97..862a4302f3 100644 --- a/src/widgets/styles/qstyle.cpp +++ b/src/widgets/styles/qstyle.cpp @@ -2355,51 +2355,24 @@ int QStyle::combinedLayoutSpacing(QSizePolicy::ControlTypes controls1, return result; } +// ### Qt 6: Remove in favor of template QDebug operator<<(QDebug, const QFlags &). +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) QT_BEGIN_INCLUDE_NAMESPACE -#include +# include QT_END_INCLUDE_NAMESPACE -#if !defined(QT_NO_DEBUG_STREAM) +# if !defined(QT_NO_DEBUG_STREAM) QDebug operator<<(QDebug debug, QStyle::State state) { -#if !defined(QT_NO_DEBUG) - debug << "QStyle::State("; - - QStringList states; - if (state & QStyle::State_Active) states << QLatin1String("Active"); - if (state & QStyle::State_AutoRaise) states << QLatin1String("AutoRaise"); - if (state & QStyle::State_Bottom) states << QLatin1String("Bottom"); - if (state & QStyle::State_Children) states << QLatin1String("Children"); - if (state & QStyle::State_DownArrow) states << QLatin1String("DownArrow"); - if (state & QStyle::State_Editing) states << QLatin1String("Editing"); - if (state & QStyle::State_Enabled) states << QLatin1String("Enabled"); - if (state & QStyle::State_FocusAtBorder) states << QLatin1String("FocusAtBorder"); - if (state & QStyle::State_HasFocus) states << QLatin1String("HasFocus"); - if (state & QStyle::State_Horizontal) states << QLatin1String("Horizontal"); - if (state & QStyle::State_Item) states << QLatin1String("Item"); - if (state & QStyle::State_KeyboardFocusChange) states << QLatin1String("KeyboardFocusChange"); - if (state & QStyle::State_MouseOver) states << QLatin1String("MouseOver"); - if (state & QStyle::State_NoChange) states << QLatin1String("NoChange"); - if (state & QStyle::State_Off) states << QLatin1String("Off"); - if (state & QStyle::State_On) states << QLatin1String("On"); - if (state & QStyle::State_Open) states << QLatin1String("Open"); - if (state & QStyle::State_Raised) states << QLatin1String("Raised"); - if (state & QStyle::State_ReadOnly) states << QLatin1String("ReadOnly"); - if (state & QStyle::State_Selected) states << QLatin1String("Selected"); - if (state & QStyle::State_Sibling) states << QLatin1String("Sibling"); - if (state & QStyle::State_Sunken) states << QLatin1String("Sunken"); - if (state & QStyle::State_Top) states << QLatin1String("Top"); - if (state & QStyle::State_UpArrow) states << QLatin1String("UpArrow"); - - std::sort(states.begin(), states.end()); - debug << states.join(QLatin1String(" | ")); - debug << ')'; -#else +# if !defined(QT_NO_DEBUG) + return operator<< (debug, state); +# else Q_UNUSED(state); -#endif +# endif return debug; } -#endif +# endif // !QT_NO_DEBUG_STREAM +#endif // QT_VERSION < QT_VERSION_CHECK(6,0,0) /*! \since 4.6 diff --git a/src/widgets/styles/qstyle.h b/src/widgets/styles/qstyle.h index f1f063dfcc..b41762795d 100644 --- a/src/widgets/styles/qstyle.h +++ b/src/widgets/styles/qstyle.h @@ -848,7 +848,10 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QStyle::State) Q_DECLARE_OPERATORS_FOR_FLAGS(QStyle::SubControls) #if !defined(QT_NO_DEBUG_STREAM) +// ### Qt 6: Remove in favor of template QDebug operator<<(QDebug, const QFlags &). +# if QT_VERSION < QT_VERSION_CHECK(6,0,0) Q_WIDGETS_EXPORT QDebug operator<<(QDebug debug, QStyle::State state); +# endif #endif QT_END_NAMESPACE -- cgit v1.2.3 From 9d19753bfaec4a23490bba46984460a526380510 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pasi=20Pet=C3=A4j=C3=A4j=C3=A4rvi?= Date: Wed, 4 Mar 2015 16:35:38 +0200 Subject: Fix disabling libinput feature if libudev is not available When using default configure value (auto) for libudev + libinput and libudev is not available, disabling libinput failed and it is enabled even it requires libudev to work. Change-Id: Ia2ead66c5cebc8658f2c29445f5c81c9f8b30dc8 Reviewed-by: Laszlo Agocs Reviewed-by: Oswald Buddenhagen --- configure | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure b/configure index 61064bca59..94f23578c2 100755 --- a/configure +++ b/configure @@ -5283,6 +5283,8 @@ if [ "$CFG_LIBINPUT" != "no" ] && [ "$CFG_LIBUDEV" != "no" ]; then else CFG_LIBINPUT=no fi +else + CFG_LIBINPUT=no fi if [ "$CFG_LIBINPUT" = "no" ]; then QMakeVar add DEFINES QT_NO_LIBINPUT -- cgit v1.2.3 From 1ee25cedb41f4618cc4a2975dc08cf0f4c4e0fdf Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Wed, 4 Mar 2015 14:42:03 +0200 Subject: Android: Make sure applicationState is set correctly The Activity onResume function is always called before the application gets initialized and we let the applicationState set to the default value which is AppicationInactive. Change-Id: Ifc3c7e3dfc51f2b821f8ca87f8b711f485b6a6f8 Reviewed-by: Peter Rustler Reviewed-by: Alex Blasche --- .../jar/src/org/qtproject/qt5/android/QtActivityDelegate.java | 2 +- src/plugins/platforms/android/androidjnimain.cpp | 4 +++- src/plugins/platforms/android/qandroidplatformintegration.cpp | 5 +++++ src/plugins/platforms/android/qandroidplatformintegration.h | 3 +++ 4 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java index dc80689f63..93d7baabdb 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java +++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java @@ -866,8 +866,8 @@ public class QtActivityDelegate while (itr.hasNext()) m_activity.runOnUiThread(itr.next()); + QtNative.updateApplicationState(ApplicationActive); if (m_started) { - QtNative.updateApplicationState(ApplicationActive); QtNative.clearLostActions(); QtNative.updateWindow(); updateFullScreen(); // Suspending the app clears the immersive mode, so we need to set it again. diff --git a/src/plugins/platforms/android/androidjnimain.cpp b/src/plugins/platforms/android/androidjnimain.cpp index f711450fab..a18e9dac5f 100644 --- a/src/plugins/platforms/android/androidjnimain.cpp +++ b/src/plugins/platforms/android/androidjnimain.cpp @@ -589,8 +589,10 @@ static void updateApplicationState(JNIEnv */*env*/, jobject /*thiz*/, jint state { m_activityActive = (state == Qt::ApplicationActive); - if (!m_main || !m_androidPlatformIntegration || !QGuiApplicationPrivate::platformIntegration()) + if (!m_main || !m_androidPlatformIntegration || !QGuiApplicationPrivate::platformIntegration()) { + QAndroidPlatformIntegration::setDefaultApplicationState(Qt::ApplicationState(state)); return; + } if (state <= Qt::ApplicationInactive) { // Don't send timers and sockets events anymore if we are going to hide all windows diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp index 93532a62e9..5384b6faca 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.cpp +++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp @@ -34,6 +34,7 @@ #include "qandroidplatformintegration.h" #include +#include #include #include #include @@ -72,6 +73,8 @@ int QAndroidPlatformIntegration::m_defaultPhysicalSizeHeight = 71; Qt::ScreenOrientation QAndroidPlatformIntegration::m_orientation = Qt::PrimaryOrientation; Qt::ScreenOrientation QAndroidPlatformIntegration::m_nativeOrientation = Qt::PrimaryOrientation; +Qt::ApplicationState QAndroidPlatformIntegration::m_defaultApplicationState = Qt::ApplicationActive; + void *QAndroidPlatformNativeInterface::nativeResourceForIntegration(const QByteArray &resource) { if (resource=="JavaVM") @@ -176,6 +179,8 @@ QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList ¶ QWindowSystemInterface::registerTouchDevice(m_touchDevice); } } + + QGuiApplicationPrivate::instance()->setApplicationState(m_defaultApplicationState); } bool QAndroidPlatformIntegration::needsBasicRenderloopWorkaround() diff --git a/src/plugins/platforms/android/qandroidplatformintegration.h b/src/plugins/platforms/android/qandroidplatformintegration.h index b08d3d872c..c0a9229056 100644 --- a/src/plugins/platforms/android/qandroidplatformintegration.h +++ b/src/plugins/platforms/android/qandroidplatformintegration.h @@ -115,6 +115,7 @@ public: QTouchDevice *touchDevice() const { return m_touchDevice; } void setTouchDevice(QTouchDevice *touchDevice) { m_touchDevice = touchDevice; } + static void setDefaultApplicationState(Qt::ApplicationState applicationState) { m_defaultApplicationState = applicationState; } EGLDisplay m_eglDisplay; private: @@ -136,6 +137,8 @@ private: static Qt::ScreenOrientation m_orientation; static Qt::ScreenOrientation m_nativeOrientation; + static Qt::ApplicationState m_defaultApplicationState; + QPlatformFontDatabase *m_androidFDB; QImage *m_FbScreenImage; QPainter *m_compositePainter; -- cgit v1.2.3 From e1ae71d3c30c5616b8fc889745365965ec0d95e0 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 2 Mar 2015 12:11:51 +0100 Subject: Clean headers in the Direct2D plugin. Change-Id: Iab85ccdf49ee81214ada87a2e476f650b39a29ce Reviewed-by: Joerg Bornemann --- src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp | 1 + src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h | 4 ---- src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.h | 8 +++++++- src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.h | 2 -- src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp | 4 ++++ src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h | 4 +--- src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp | 3 +++ src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h | 8 +++++--- 8 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp index 272480e25f..9dc94df451 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.cpp @@ -32,6 +32,7 @@ ****************************************************************************/ #include "qwindowsdirect2dbackingstore.h" +#include "qwindowsdirect2dplatformpixmap.h" #include "qwindowsdirect2dintegration.h" #include "qwindowsdirect2dcontext.h" #include "qwindowsdirect2dpaintdevice.h" diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h index 3687f47f4d..1c7f65a12d 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h @@ -34,11 +34,7 @@ #ifndef QWINDOWSDIRECT2DBACKINGSTORE_H #define QWINDOWSDIRECT2DBACKINGSTORE_H -#include "qwindowsdirect2dplatformpixmap.h" - -#include #include -#include QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.h b/src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.h index 22c81cf658..a6ae6d76d8 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.h +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbitmap.h @@ -34,8 +34,9 @@ #ifndef QWINDOWSDIRECT2DBITMAP_H #define QWINDOWSDIRECT2DBITMAP_H +#include +#include #include -#include struct ID2D1DeviceContext; struct ID2D1Bitmap1; @@ -44,6 +45,11 @@ QT_BEGIN_NAMESPACE class QWindowsDirect2DDeviceContext; class QWindowsDirect2DBitmapPrivate; + +class QImage; +class QSize; +class QColor; + class QWindowsDirect2DBitmap { Q_DECLARE_PRIVATE(QWindowsDirect2DBitmap) diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.h b/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.h index e7c920cf53..312955b54a 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.h +++ b/src/plugins/platforms/direct2d/qwindowsdirect2ddevicecontext.h @@ -34,8 +34,6 @@ #ifndef QWINDOWSDIRECT2DDEVICECONTEXT_H #define QWINDOWSDIRECT2DDEVICECONTEXT_H -#include "qwindowsdirect2dhelpers.h" - #include QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp index 36cfff43f5..d439196dc1 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.cpp @@ -51,6 +51,10 @@ #include #include +#include +#include +#include + using Microsoft::WRL::ComPtr; QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h index a75c0b6cc7..5e0f0b4b97 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dpaintengine.h @@ -37,9 +37,7 @@ #include #include -#include -#include -#include +struct ID2D1Geometry; QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp index 414d2fb36e..e762eab711 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.cpp @@ -32,6 +32,7 @@ ****************************************************************************/ #include "qwindowsdirect2dcontext.h" +#include "qwindowsdirect2dbitmap.h" #include "qwindowsdirect2dwindow.h" #include "qwindowsdirect2ddevicecontext.h" #include "qwindowsdirect2dhelpers.h" @@ -39,6 +40,8 @@ #include #include +#include + using Microsoft::WRL::ComPtr; QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h index 0c0240b1dc..707305a515 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dwindow.h @@ -35,13 +35,15 @@ #define QWINDOWSDIRECT2DWINDOW_H #include "qwindowswindow.h" -#include "qwindowsdirect2dbitmap.h" - -#include #include +struct IDXGISwapChain1; +struct ID2D1DeviceContext; + QT_BEGIN_NAMESPACE +class QWindowsDirect2DBitmap; + class QWindowsDirect2DWindow : public QWindowsWindow { public: -- cgit v1.2.3 From eee4c6f190d427ab6d5a9acf9fe6327df6cf8c2d Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 2 Mar 2015 12:12:55 +0100 Subject: Clean headers in the Windows plugin. Change-Id: Ibc6b904e6e0b21f5daa0730a7eda2cae43cd3dcf Reviewed-by: Joerg Bornemann --- src/plugins/platforms/windows/qwindowsguieventdispatcher.h | 3 --- src/plugins/platforms/windows/qwindowsintegration.h | 1 - src/plugins/platforms/windows/qwindowsmime.h | 1 - src/plugins/platforms/windows/qwindowsnativeimage.h | 2 -- src/plugins/platforms/windows/qwindowsnativeinterface.cpp | 5 +++++ src/plugins/platforms/windows/qwindowsnativeinterface.h | 3 +-- src/plugins/platforms/windows/qwindowsole.h | 3 --- src/plugins/platforms/windows/qwindowsopengltester.h | 2 -- src/plugins/platforms/windows/qwindowstheme.cpp | 11 +++++++++++ src/plugins/platforms/windows/qwindowstheme.h | 9 --------- src/plugins/platforms/windows/qwindowswindow.cpp | 1 + src/plugins/platforms/windows/qwindowswindow.h | 1 - 12 files changed, 18 insertions(+), 24 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsguieventdispatcher.h b/src/plugins/platforms/windows/qwindowsguieventdispatcher.h index 3db6eac662..3389139461 100644 --- a/src/plugins/platforms/windows/qwindowsguieventdispatcher.h +++ b/src/plugins/platforms/windows/qwindowsguieventdispatcher.h @@ -34,11 +34,8 @@ #ifndef QWINDOWSGUIEVENTDISPATCHER_H #define QWINDOWSGUIEVENTDISPATCHER_H -#include "qtwindowsglobal.h" #include "qtwindows_additional.h" -#include -#include #include QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h index 8a2d14f172..fa5192ba03 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.h +++ b/src/plugins/platforms/windows/qwindowsintegration.h @@ -35,7 +35,6 @@ #ifndef QWINDOWSINTEGRATION_H #define QWINDOWSINTEGRATION_H -#include #include #include diff --git a/src/plugins/platforms/windows/qwindowsmime.h b/src/plugins/platforms/windows/qwindowsmime.h index e7a01ae79a..952410e14b 100644 --- a/src/plugins/platforms/windows/qwindowsmime.h +++ b/src/plugins/platforms/windows/qwindowsmime.h @@ -39,7 +39,6 @@ #include #include #include -#include QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsnativeimage.h b/src/plugins/platforms/windows/qwindowsnativeimage.h index cbf93b9602..6f9ce93ef0 100644 --- a/src/plugins/platforms/windows/qwindowsnativeimage.h +++ b/src/plugins/platforms/windows/qwindowsnativeimage.h @@ -38,8 +38,6 @@ #include -#include - QT_BEGIN_NAMESPACE class QWindowsNativeImage diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp index 84608edddc..9691156403 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.cpp +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.cpp @@ -192,6 +192,11 @@ QString QWindowsNativeInterface::registerWindowClass(const QString &classNameIn, return QWindowsContext::instance()->registerWindowClass(classNameIn, (WNDPROC)eventProc); } +void QWindowsNativeInterface::beep() +{ + MessageBeep(MB_OK); // For QApplication +} + bool QWindowsNativeInterface::asyncExpose() const { return QWindowsContext::instance()->asyncExpose(); diff --git a/src/plugins/platforms/windows/qwindowsnativeinterface.h b/src/plugins/platforms/windows/qwindowsnativeinterface.h index 4069d60f3b..be8418b769 100644 --- a/src/plugins/platforms/windows/qwindowsnativeinterface.h +++ b/src/plugins/platforms/windows/qwindowsnativeinterface.h @@ -34,7 +34,6 @@ #ifndef QWINDOWSNATIVEINTERFACE_H #define QWINDOWSNATIVEINTERFACE_H -#include "qtwindows_additional.h" #include QT_BEGIN_NAMESPACE @@ -73,7 +72,7 @@ public: Q_INVOKABLE QString registerWindowClass(const QString &classNameIn, void *eventProc) const; - Q_INVOKABLE void beep() { MessageBeep(MB_OK); } // For QApplication + Q_INVOKABLE void beep(); Q_INVOKABLE void registerWindowsMime(void *mimeIn); Q_INVOKABLE void unregisterWindowsMime(void *mime); diff --git a/src/plugins/platforms/windows/qwindowsole.h b/src/plugins/platforms/windows/qwindowsole.h index b63d7611da..09f6114e2d 100644 --- a/src/plugins/platforms/windows/qwindowsole.h +++ b/src/plugins/platforms/windows/qwindowsole.h @@ -36,12 +36,9 @@ #include "qtwindows_additional.h" -#include #include -#include #include #include -#include #include diff --git a/src/plugins/platforms/windows/qwindowsopengltester.h b/src/plugins/platforms/windows/qwindowsopengltester.h index f58bf305fc..7b6164946e 100644 --- a/src/plugins/platforms/windows/qwindowsopengltester.h +++ b/src/plugins/platforms/windows/qwindowsopengltester.h @@ -34,8 +34,6 @@ #ifndef QWINDOWSOPENGLTESTER_H #define QWINDOWSOPENGLTESTER_H -#include - #include #include #include diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp index 9b6ae7c445..d3f67e9eaa 100644 --- a/src/plugins/platforms/windows/qwindowstheme.cpp +++ b/src/plugins/platforms/windows/qwindowstheme.cpp @@ -62,6 +62,7 @@ #include #include #include +#include #include #include #include @@ -77,6 +78,16 @@ QT_BEGIN_NAMESPACE +static inline COLORREF qColorToCOLORREF(const QColor &color) +{ + return RGB(color.red(), color.green(), color.blue()); +} + +static inline QColor COLORREFToQColor(COLORREF cr) +{ + return QColor(GetRValue(cr), GetGValue(cr), GetBValue(cr)); +} + static inline QTextStream& operator<<(QTextStream &str, const QColor &c) { str.setIntegerBase(16); diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h index 3840e978cd..b2f8e13b64 100644 --- a/src/plugins/platforms/windows/qwindowstheme.h +++ b/src/plugins/platforms/windows/qwindowstheme.h @@ -35,9 +35,6 @@ #define QWINDOWSTHEME_H #include -#include - -#include "qtwindows_additional.h" QT_BEGIN_NAMESPACE @@ -79,12 +76,6 @@ private: QFont *m_fonts[NFonts]; }; -static inline COLORREF qColorToCOLORREF(const QColor &color) -{ return RGB(color.red(), color.green(), color.blue()); } - -static inline QColor COLORREFToQColor(COLORREF cr) -{ return QColor(GetRValue(cr), GetGValue(cr), GetBValue(cr)); } - QT_END_NAMESPACE #endif // QWINDOWSTHEME_H diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index b229ec4080..b6dbe91ff7 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -38,6 +38,7 @@ #include "qwindowsscreen.h" #include "qwindowsscaling.h" #include "qwindowsintegration.h" +#include "qwindowsopenglcontext.h" #ifdef QT_NO_CURSOR # include "qwindowscursor.h" #endif diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index ec419d8272..b47bd86ab8 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -40,7 +40,6 @@ #endif #include "qwindowsscaling.h" #include "qwindowscursor.h" -#include "qwindowsopenglcontext.h" #include #include -- cgit v1.2.3 From ae554cb8c2ba41c4285951abb9c9b0bc9a7d47e5 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 2 Mar 2015 12:18:57 +0100 Subject: Windows plugin: Simplify cursor code in platform screen. Change the shared pointer to store a QPlatformCursor instead of QWindowsCursor, removing the dependency of qwindowsscreen.h on qwindowscursor.h. Change-Id: I8b4bbc9fd4d5046c30ac3784f14229a9cc6d8dc6 Reviewed-by: Joerg Bornemann --- src/plugins/platforms/windows/qwindowsscreen.cpp | 6 +++--- src/plugins/platforms/windows/qwindowsscreen.h | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index 4ab4ac352e..28e2aadf14 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -191,13 +191,13 @@ static QDebug operator<<(QDebug dbg, const QWindowsScreenData &d) } // Return the cursor to be shared by all screens (virtual desktop). -static inline QSharedPointer sharedCursor() +static inline QSharedPointer sharedCursor() { #ifndef QT_NO_CURSOR if (const QScreen *primaryScreen = QGuiApplication::primaryScreen()) - return static_cast(primaryScreen->handle())->windowsCursor(); + return static_cast(primaryScreen->handle())->cursorPtr(); #endif - return QSharedPointer(new QWindowsCursor); + return QSharedPointer(new QWindowsCursor); } /*! diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h index b561f73804..7352c45777 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.h +++ b/src/plugins/platforms/windows/qwindowsscreen.h @@ -34,8 +34,8 @@ #ifndef QWINDOWSSCREEN_H #define QWINDOWSSCREEN_H -#include "qwindowscursor.h" #include "qwindowsscaling.h" +#include "qtwindowsglobal.h" #ifdef Q_OS_WINCE # include "qplatformfunctions_wince.h" #endif @@ -75,7 +75,7 @@ class QWindowsScreen : public QPlatformScreen { public: #ifndef QT_NO_CURSOR - typedef QSharedPointer WindowsCursorPtr; + typedef QSharedPointer CursorPtr; #endif explicit QWindowsScreen(const QWindowsScreenData &data); @@ -105,8 +105,8 @@ public: inline void handleChanges(const QWindowsScreenData &newData); #ifndef QT_NO_CURSOR - QPlatformCursor *cursor() const { return m_cursor.data(); } - const WindowsCursorPtr &windowsCursor() const { return m_cursor; } + QPlatformCursor *cursor() const Q_DECL_OVERRIDE { return m_cursor.data(); } + const CursorPtr &cursorPtr() const { return m_cursor; } #else QPlatformCursor *cursor() const { return 0; } #endif // !QT_NO_CURSOR @@ -117,7 +117,7 @@ public: private: QWindowsScreenData m_data; #ifndef QT_NO_CURSOR - const WindowsCursorPtr m_cursor; + const CursorPtr m_cursor; #endif }; -- cgit v1.2.3 From d70492d1eed698aa8ca362a276438c7eab9d63fb Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 27 Feb 2015 12:06:11 +0100 Subject: Remove debug formatting functions obsoleted by the new debug operator for QFlag. Change-Id: I6d737eb86b790eeefb537ca5e6a075bf30a3dcfb Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Shawn Rutledge --- src/gui/kernel/qplatformdrag.cpp | 59 ++------------------ .../platforms/windows/qwindowsintegration.cpp | 4 +- src/plugins/platforms/windows/qwindowswindow.cpp | 64 +--------------------- src/plugins/platforms/windows/qwindowswindow.h | 2 - 4 files changed, 9 insertions(+), 120 deletions(-) diff --git a/src/gui/kernel/qplatformdrag.cpp b/src/gui/kernel/qplatformdrag.cpp index f509408f8f..d789c75d1d 100644 --- a/src/gui/kernel/qplatformdrag.cpp +++ b/src/gui/kernel/qplatformdrag.cpp @@ -42,57 +42,7 @@ QT_BEGIN_NAMESPACE #ifndef QT_NO_DRAGANDDROP #ifdef QDND_DEBUG -QString dragActionsToString(Qt::DropActions actions) -{ - QString str; - if (actions == Qt::IgnoreAction) { - if (!str.isEmpty()) - str += QLatin1String(" | "); - str += QLatin1String("IgnoreAction"); - } - if (actions & Qt::LinkAction) { - if (!str.isEmpty()) - str += QLatin1String(" | "); - str += QLatin1String("LinkAction"); - } - if (actions & Qt::CopyAction) { - if (!str.isEmpty()) - str += QLatin1String(" | "); - str += QLatin1String("CopyAction"); - } - if (actions & Qt::MoveAction) { - if (!str.isEmpty()) - str += QLatin1String(" | "); - str += QLatin1String("MoveAction"); - } - if ((actions & Qt::TargetMoveAction) == Qt::TargetMoveAction ) { - if (!str.isEmpty()) - str += QLatin1String(" | "); - str += QLatin1String("TargetMoveAction"); - } - return str; -} - -QString KeyboardModifiersToString(Qt::KeyboardModifiers modifiers) -{ - QString str; - if (modifiers & Qt::ControlModifier) { - if (!str.isEmpty()) - str += QLatin1String(" | "); - str += QLatin1String("ControlModifier"); - } - if (modifiers & Qt::AltModifier) { - if (!str.isEmpty()) - str += QLatin1String(" | "); - str += QLatin1String("AltModifier"); - } - if (modifiers & Qt::ShiftModifier) { - if (!str.isEmpty()) - str += QLatin1String(" | "); - str += QLatin1String("ShiftModifier"); - } - return str; -} +# include #endif QPlatformDropQtResponse::QPlatformDropQtResponse(bool accepted, Qt::DropAction acceptedAction) @@ -156,8 +106,7 @@ Qt::DropAction QPlatformDrag::defaultAction(Qt::DropActions possibleActions, Qt::KeyboardModifiers modifiers) const { #ifdef QDND_DEBUG - qDebug("QDragManager::defaultAction(Qt::DropActions possibleActions)"); - qDebug("keyboard modifiers : %s", qPrintable(KeyboardModifiersToString(modifiers))); + qDebug() << "QDragManager::defaultAction(Qt::DropActions possibleActions)\nkeyboard modifiers : " << modifiers; #endif Qt::DropAction default_action = Qt::IgnoreAction; @@ -183,7 +132,7 @@ Qt::DropAction QPlatformDrag::defaultAction(Qt::DropActions possibleActions, default_action = Qt::LinkAction; #ifdef QDND_DEBUG - qDebug("possible actions : %s", qPrintable(dragActionsToString(possibleActions))); + qDebug() << "possible actions : " << possibleActions; #endif // Check if the action determined is allowed @@ -199,7 +148,7 @@ Qt::DropAction QPlatformDrag::defaultAction(Qt::DropActions possibleActions, } #ifdef QDND_DEBUG - qDebug("default action : %s", qPrintable(dragActionsToString(default_action))); + qDebug() << "default action : " << default_action; #endif return default_action; diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index af7ecd5834..62df7918c1 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -316,9 +316,9 @@ QWindowsWindowData QWindowsIntegration::createWindowData(QWindow *window) const << __FUNCTION__ << '<' << window << "\n Requested: " << requested.geometry << "frame incl.: " << QWindowsGeometryHint::positionIncludesFrame(window) - << " Flags=" << QWindowsWindow::debugWindowFlags(requested.flags) + << " Flags=" << requested.flags << "\n Obtained : " << obtained.geometry << " Margins "<< obtained.frame - << " Flags=" << QWindowsWindow::debugWindowFlags(obtained.flags) + << " Flags=" << obtained.flags << " Handle=" << obtained.hwnd << '\n'; if (obtained.hwnd) { diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index b6dbe91ff7..4cf8fcf4da 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -417,7 +417,7 @@ struct WindowCreationData QDebug operator<<(QDebug debug, const WindowCreationData &d) { - debug.nospace() << QWindowsWindow::debugWindowFlags(d.flags) + debug.nospace() << d.flags << " topLevel=" << d.topLevel << " popup=" << d.popup << " dialog=" << d.dialog << " desktop=" << d.desktop << " embedded=" << d.embedded @@ -1530,8 +1530,7 @@ void QWindowsWindow::setWindowTitle(const QString &title) void QWindowsWindow::setWindowFlags(Qt::WindowFlags flags) { qCDebug(lcQpaWindows) << '>' << __FUNCTION__ << this << window() << "\n from: " - << QWindowsWindow::debugWindowFlags(m_data.flags) - << "\n to: " << QWindowsWindow::debugWindowFlags(flags); + << m_data.flags << "\n to: " << flags; const QRect oldGeometry = geometryDp(); if (m_data.flags != flags) { m_data.flags = flags; @@ -1549,8 +1548,7 @@ void QWindowsWindow::setWindowFlags(Qt::WindowFlags flags) handleGeometryChange(); qCDebug(lcQpaWindows) << '<' << __FUNCTION__ << "\n returns: " - << QWindowsWindow::debugWindowFlags(m_data.flags) - << " geometry " << oldGeometry << "->" << newGeometry; + << m_data.flags << " geometry " << oldGeometry << "->" << newGeometry; } QWindowsWindowData QWindowsWindow::setWindowFlags_sys(Qt::WindowFlags wt, @@ -2202,62 +2200,6 @@ void QWindowsWindow::setEnabled(bool enabled) setStyle(newStyle); } -QByteArray QWindowsWindow::debugWindowFlags(Qt::WindowFlags wf) -{ - const int iwf = int(wf); - QByteArray rc = "0x"; - rc += QByteArray::number(iwf, 16); - rc += " ["; - - switch ((iwf & Qt::WindowType_Mask)) { - case Qt::Widget: - rc += " Widget"; - break; - case Qt::Window: - rc += " Window"; - break; - case Qt::Dialog: - rc += " Dialog"; - break; - case Qt::Sheet: - rc += " Sheet"; - break; - case Qt::Popup: - rc += " Popup"; - break; - case Qt::Tool: - rc += " Tool"; - break; - case Qt::ToolTip: - rc += " ToolTip"; - break; - case Qt::SplashScreen: - rc += " SplashScreen"; - break; - case Qt::Desktop: - rc += " Desktop"; - break; - case Qt::SubWindow: - rc += " SubWindow"; - break; - } - if (iwf & Qt::MSWindowsFixedSizeDialogHint) rc += " MSWindowsFixedSizeDialogHint"; - if (iwf & Qt::MSWindowsOwnDC) rc += " MSWindowsOwnDC"; - if (iwf & Qt::FramelessWindowHint) rc += " FramelessWindowHint"; - if (iwf & Qt::WindowTitleHint) rc += " WindowTitleHint"; - if (iwf & Qt::WindowSystemMenuHint) rc += " WindowSystemMenuHint"; - if (iwf & Qt::WindowMinimizeButtonHint) rc += " WindowMinimizeButtonHint"; - if (iwf & Qt::WindowMaximizeButtonHint) rc += " WindowMaximizeButtonHint"; - if (iwf & Qt::WindowContextHelpButtonHint) rc += " WindowContextHelpButtonHint"; - if (iwf & Qt::WindowShadeButtonHint) rc += " WindowShadeButtonHint"; - if (iwf & Qt::WindowStaysOnTopHint) rc += " WindowStaysOnTopHint"; - if (iwf & Qt::CustomizeWindowHint) rc += " CustomizeWindowHint"; - if (iwf & Qt::WindowStaysOnBottomHint) rc += " WindowStaysOnBottomHint"; - if (iwf & Qt::WindowCloseButtonHint) rc += " WindowCloseButtonHint"; - rc += ']'; - return rc; -} - static HICON createHIcon(const QIcon &icon, int xSize, int ySize) { if (!icon.isNull()) { diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index b47bd86ab8..f0b04fbc47 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -240,8 +240,6 @@ public: void setCursor(const QWindowsWindowCursor &c); void applyCursor(); - static QByteArray debugWindowFlags(Qt::WindowFlags wf); - inline bool testFlag(unsigned f) const { return (m_flags & f) != 0; } inline void setFlag(unsigned f) const { m_flags |= f; } inline void clearFlag(unsigned f) const { m_flags &= ~f; } -- cgit v1.2.3 From c29c6d9003b3ff67770dee66652dd2faecf842d5 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Fri, 27 Feb 2015 14:11:24 +0100 Subject: OS X: Fix mixing writing systems, ligatures and text formatting In QFontEngineMulti::stringToCMap() we call the primary engine's implementation of the same function. If this engine does not support the character in question, then it's supposed to clear the glyph array, otherwise there may be left-over junk in the glyph array from previous script items and the font selection algorithm will think it has already found a match for the character corresponding to the glyph position. The freetype engine, for instance, clears the respective entries in the array when it gets a 0 glyph from the font engine. In particular, this would happen when you had a ligature preceding an item that was shaped separately. The ligature (e.g. "fi") would set the first two slots of the glyph array, but later replace them with a single glyph. The next item would then get an offset of 1, i.e. pointing to the position in the glyph array where the glyph for i was originally contained. If this was not cleared, it would assume the primary engine supported the character. If the character was of an unsupported writing system, then you would get a box in place of it instead. [ChangeLog][OS X][Text] Fixed appending text with a different writing system and formatting to a latin ligature. Change-Id: Id8c81cdc8e2d8994cc1a999769fcae452c4f52ae Task-number: QTBUG-44708 Reviewed-by: Konstantin Ritt --- src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 64de364bfb..7e1dfd9275 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -250,11 +250,9 @@ bool QCoreTextFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout * int glyph_pos = 0; for (int i = 0; i < len; ++i) { - if (cgGlyphs[i]) { - glyphs->glyphs[glyph_pos] = cgGlyphs[i]; - if (glyph_pos < i) - cgGlyphs[glyph_pos] = cgGlyphs[i]; - } + glyphs->glyphs[glyph_pos] = cgGlyphs[i]; + if (glyph_pos < i) + cgGlyphs[glyph_pos] = cgGlyphs[i]; glyph_pos++; // If it's a non-BMP char, skip the lower part of surrogate pair and go -- cgit v1.2.3 From b35c389b6a2e3f4311047875893eb8e94b2415aa Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 27 Feb 2015 18:00:49 +0100 Subject: Add Raspberry Pi 2 specs Change-Id: Ifc99af49398e5d6e057035d2de55fe218c8418d6 Reviewed-by: Andy Nichols Reviewed-by: Robin Burchell --- mkspecs/devices/linux-rasp-pi2-g++/qmake.conf | 26 +++++++++++++++++ mkspecs/devices/linux-rasp-pi2-g++/qplatformdefs.h | 34 ++++++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 mkspecs/devices/linux-rasp-pi2-g++/qmake.conf create mode 100644 mkspecs/devices/linux-rasp-pi2-g++/qplatformdefs.h diff --git a/mkspecs/devices/linux-rasp-pi2-g++/qmake.conf b/mkspecs/devices/linux-rasp-pi2-g++/qmake.conf new file mode 100644 index 0000000000..bf6749534d --- /dev/null +++ b/mkspecs/devices/linux-rasp-pi2-g++/qmake.conf @@ -0,0 +1,26 @@ +# qmake configuration for the Raspberry Pi 2 + +include(../common/linux_device_pre.conf) + +QMAKE_LFLAGS += -Wl,-rpath-link,$$[QT_SYSROOT]/opt/vc/lib + +QMAKE_LIBDIR_OPENGL_ES2 = $$[QT_SYSROOT]/opt/vc/lib +QMAKE_LIBDIR_EGL = $$QMAKE_LIBDIR_OPENGL_ES2 + +QMAKE_INCDIR_EGL = $$[QT_SYSROOT]/opt/vc/include \ + $$[QT_SYSROOT]/opt/vc/include/interface/vcos/pthreads \ + $$[QT_SYSROOT]/opt/vc/include/interface/vmcs_host/linux +QMAKE_INCDIR_OPENGL_ES2 = $${QMAKE_INCDIR_EGL} + +QMAKE_LIBS_EGL = -lEGL -lGLESv2 +QMAKE_CFLAGS += -march=armv7-a -marm -mthumb-interwork -mfpu=neon-vfpv4 -mtune=cortex-a7 -mabi=aapcs-linux +QMAKE_CXXFLAGS = $$QMAKE_CFLAGS + +DISTRO_OPTS += hard-float + +EGLFS_PLATFORM_HOOKS_SOURCES = $$PWD/../linux-rasp-pi-g++/qeglfshooks_pi.cpp +EGLFS_PLATFORM_HOOKS_LIBS = -lbcm_host + +include(../common/linux_arm_device_post.conf) + +load(qt_config) diff --git a/mkspecs/devices/linux-rasp-pi2-g++/qplatformdefs.h b/mkspecs/devices/linux-rasp-pi2-g++/qplatformdefs.h new file mode 100644 index 0000000000..5ae49b35dd --- /dev/null +++ b/mkspecs/devices/linux-rasp-pi2-g++/qplatformdefs.h @@ -0,0 +1,34 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the qmake spec 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 "../../linux-g++/qplatformdefs.h" -- cgit v1.2.3 From dd06d036616b3f3de852ea51989d9b4944417c1c Mon Sep 17 00:00:00 2001 From: hjk Date: Tue, 3 Mar 2015 11:11:08 +0100 Subject: QLockFile: Avoid zero-sized lock file on write error Failure to write into a successfully opened lock file left the lock file with size 0 in the filesystem. Task-number: QTBUG-44771 Change-Id: I561bf629b9f160174d658bf105be828f71d78ff9 Reviewed-by: David Faure Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/io/qlockfile_unix.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index 5719d899a0..1c8da607a7 100644 --- a/src/corelib/io/qlockfile_unix.cpp +++ b/src/corelib/io/qlockfile_unix.cpp @@ -157,13 +157,17 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys() if (!setNativeLocks(fd)) qWarning() << "setNativeLocks failed:" << strerror(errno); + if (qt_write_loop(fd, fileData.constData(), fileData.size()) < fileData.size()) { + close(fd); + if (!QFile::remove(fileName)) + qWarning("QLockFile: Could not remove our own lock file %s.", qPrintable(fileName)); + return QLockFile::UnknownError; // partition full + } + // We hold the lock, continue. fileHandle = fd; - QLockFile::LockError error = QLockFile::NoError; - if (qt_write_loop(fd, fileData.constData(), fileData.size()) < fileData.size()) - error = QLockFile::UnknownError; // partition full - return error; + return QLockFile::NoError; } bool QLockFilePrivate::removeStaleLock() -- cgit v1.2.3 From c6045db4a6a1faec0365d88ab0a34d481540e543 Mon Sep 17 00:00:00 2001 From: Nico Vertriest Date: Tue, 3 Mar 2015 12:53:03 +0100 Subject: Doc: fixed links on index page QtConcurrent MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-35199 Change-Id: I1fa81e69d47ea150fb08c653c8569670c40b554a Reviewed-by: Topi Reiniö --- src/concurrent/doc/src/qtconcurrent-index.qdoc | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/concurrent/doc/src/qtconcurrent-index.qdoc b/src/concurrent/doc/src/qtconcurrent-index.qdoc index 2a4720a9a3..2157280021 100644 --- a/src/concurrent/doc/src/qtconcurrent-index.qdoc +++ b/src/concurrent/doc/src/qtconcurrent-index.qdoc @@ -50,25 +50,25 @@ \list - \li QtConcurrent::map() applies a function to every item in a container, + \li \l {QtConcurrent::map}{QtConcurrent::map()} applies a function to every item in a container, modifying the items in-place. - \li QtConcurrent::mapped() is like map(), except that it returns a new + \li \l {QtConcurrent::mapped}{QtConcurrent::mapped()} is like map(), except that it returns a new container with the modifications. - \li QtConcurrent::mappedReduced() is like mapped(), except that the + \li \l {QtConcurrent::mappedReduced}{QtConcurrent::mappedReduced()} is like mapped(), except that the modified results are reduced or folded into a single result. - \li QtConcurrent::filter() removes all items from a container based on the + \li \l {QtConcurrent::filter}{QtConcurrent::filter()} removes all items from a container based on the result of a filter function. - \li QtConcurrent::filtered() is like filter(), except that it returns a new + \li \l {QtConcurrent::filtered}{QtConcurrent::filtered()} is like filter(), except that it returns a new container with the filtered results. - \li QtConcurrent::filteredReduced() is like filtered(), except that the + \li \l {QtConcurrent::filteredReduced}{QtConcurrent::filteredReduced()} is like filtered(), except that the filtered results are reduced or folded into a single result. - \li QtConcurrent::run() runs a function in another thread. + \li \l {QtConcurrent::run}{QtConcurrent::run()} runs a function in another thread. \li QFuture represents the result of an asynchronous computation. -- cgit v1.2.3 From d04c3d2079e0df79592128a67e115ecb90b08454 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 2 Mar 2015 16:09:22 +0100 Subject: eglfs: Pluginize RPi, iMX6 and Mali backends eglfs does not depend on the device makespecs anymore when it comes to these device integration backends (hooks). Instead, backends are autodetected by configure. The name of the preferred plugin is still set in the device makespecs. This is optional. When not set and there is more than one plugin present in the system, the environment variable QT_QPA_EGLFS_INTEGRATION will have to be set at runtime. In the absence of that, the order is undefined. Change-Id: Ie1ced2c9aa1beff2adb13b4fdea7c499cb5a6aab Reviewed-by: Oswald Buddenhagen Reviewed-by: Andy Nichols --- config.tests/qpa/eglfs-brcm/eglfs-brcm.cpp | 45 ++++++ config.tests/qpa/eglfs-brcm/eglfs-brcm.pro | 9 ++ config.tests/qpa/eglfs-mali/eglfs-mali.cpp | 45 ++++++ config.tests/qpa/eglfs-mali/eglfs-mali.pro | 5 + config.tests/qpa/eglfs-viv/eglfs-viv.cpp | 42 ++++++ config.tests/qpa/eglfs-viv/eglfs-viv.pro | 6 + configure | 32 ++++- .../qeglfshooks_hix5hd2.cpp | 110 --------------- .../linux-arm-hisilicon-hix5hd2-g++/qmake.conf | 4 +- .../devices/linux-imx6-g++/qeglfshooks_imx6.cpp | 101 -------------- mkspecs/devices/linux-imx6-g++/qmake.conf | 5 +- .../devices/linux-rasp-pi-g++/qeglfshooks_pi.cpp | 154 --------------------- mkspecs/devices/linux-rasp-pi-g++/qmake.conf | 4 +- mkspecs/devices/linux-rasp-pi2-g++/qmake.conf | 4 +- .../eglfs/deviceintegration/deviceintegration.pro | 3 + .../deviceintegration/eglfs_brcm/eglfs_brcm.json | 3 + .../deviceintegration/eglfs_brcm/eglfs_brcm.pro | 20 +++ .../eglfs_brcm/qeglfsbrcmintegration.cpp | 132 ++++++++++++++++++ .../eglfs_brcm/qeglfsbrcmintegration.h | 55 ++++++++ .../eglfs_brcm/qeglfsbrcmmain.cpp | 50 +++++++ .../deviceintegration/eglfs_kms/eglfs_kms.pro | 5 +- .../deviceintegration/eglfs_mali/eglfs_mali.json | 3 + .../deviceintegration/eglfs_mali/eglfs_mali.pro | 18 +++ .../eglfs_mali/qeglfsmaliintegration.cpp | 96 +++++++++++++ .../eglfs_mali/qeglfsmaliintegration.h | 51 +++++++ .../eglfs_mali/qeglfsmalimain.cpp | 50 +++++++ .../deviceintegration/eglfs_viv/eglfs_viv.json | 3 + .../deviceintegration/eglfs_viv/eglfs_viv.pro | 20 +++ .../eglfs_viv/qeglfsvivintegration.cpp | 84 +++++++++++ .../eglfs_viv/qeglfsvivintegration.h | 57 ++++++++ .../deviceintegration/eglfs_viv/qeglfsvivmain.cpp | 50 +++++++ .../deviceintegration/eglfs_x11/eglfs_x11.pro | 5 +- 32 files changed, 892 insertions(+), 379 deletions(-) create mode 100644 config.tests/qpa/eglfs-brcm/eglfs-brcm.cpp create mode 100644 config.tests/qpa/eglfs-brcm/eglfs-brcm.pro create mode 100644 config.tests/qpa/eglfs-mali/eglfs-mali.cpp create mode 100644 config.tests/qpa/eglfs-mali/eglfs-mali.pro create mode 100644 config.tests/qpa/eglfs-viv/eglfs-viv.cpp create mode 100644 config.tests/qpa/eglfs-viv/eglfs-viv.pro delete mode 100644 mkspecs/devices/linux-arm-hisilicon-hix5hd2-g++/qeglfshooks_hix5hd2.cpp delete mode 100644 mkspecs/devices/linux-imx6-g++/qeglfshooks_imx6.cpp delete mode 100644 mkspecs/devices/linux-rasp-pi-g++/qeglfshooks_pi.cpp create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.json create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.pro create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/qeglfsbrcmintegration.cpp create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/qeglfsbrcmintegration.h create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/qeglfsbrcmmain.cpp create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/eglfs_mali.json create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/eglfs_mali.pro create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmaliintegration.cpp create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmaliintegration.h create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmalimain.cpp create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/eglfs_viv.json create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/eglfs_viv.pro create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.h create mode 100644 src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivmain.cpp diff --git a/config.tests/qpa/eglfs-brcm/eglfs-brcm.cpp b/config.tests/qpa/eglfs-brcm/eglfs-brcm.cpp new file mode 100644 index 0000000000..a97fb510c7 --- /dev/null +++ b/config.tests/qpa/eglfs-brcm/eglfs-brcm.cpp @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the config.tests 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 + +int main(int, char **) +{ + EGLDisplay dpy = 0; + EGLContext ctx = 0; + eglDestroyContext(dpy, ctx); + vc_dispmanx_display_open(0); + return 0; +} diff --git a/config.tests/qpa/eglfs-brcm/eglfs-brcm.pro b/config.tests/qpa/eglfs-brcm/eglfs-brcm.pro new file mode 100644 index 0000000000..623726c9f3 --- /dev/null +++ b/config.tests/qpa/eglfs-brcm/eglfs-brcm.pro @@ -0,0 +1,9 @@ +SOURCES = eglfs-brcm.cpp + +CONFIG -= qt + +INCLUDEPATH += $$[QT_SYSROOT]/opt/vc/include \ + $$[QT_SYSROOT]/opt/vc/include/interface/vcos/pthreads \ + $$[QT_SYSROOT]/opt/vc/include/interface/vmcs_host/linux + +LIBS += -L$$[QT_SYSROOT]/opt/vc/lib -lEGL -lGLESv2 -lbcm_host diff --git a/config.tests/qpa/eglfs-mali/eglfs-mali.cpp b/config.tests/qpa/eglfs-mali/eglfs-mali.cpp new file mode 100644 index 0000000000..8c1d33308d --- /dev/null +++ b/config.tests/qpa/eglfs-mali/eglfs-mali.cpp @@ -0,0 +1,45 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the config.tests 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 + +int main(int, char **) +{ + EGLDisplay dpy = 0; + EGLContext ctx = 0; + fbdev_window *w = 0; + eglDestroyContext(dpy, ctx); + return 0; +} diff --git a/config.tests/qpa/eglfs-mali/eglfs-mali.pro b/config.tests/qpa/eglfs-mali/eglfs-mali.pro new file mode 100644 index 0000000000..132918c4bc --- /dev/null +++ b/config.tests/qpa/eglfs-mali/eglfs-mali.pro @@ -0,0 +1,5 @@ +SOURCES = eglfs-mali.cpp + +CONFIG -= qt + +LIBS += -lEGL -lGLESv2 diff --git a/config.tests/qpa/eglfs-viv/eglfs-viv.cpp b/config.tests/qpa/eglfs-viv/eglfs-viv.cpp new file mode 100644 index 0000000000..7b5b02541b --- /dev/null +++ b/config.tests/qpa/eglfs-viv/eglfs-viv.cpp @@ -0,0 +1,42 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the config.tests 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 + +int main(int, char **) +{ + fbGetDisplayByIndex(0); + return 0; +} diff --git a/config.tests/qpa/eglfs-viv/eglfs-viv.pro b/config.tests/qpa/eglfs-viv/eglfs-viv.pro new file mode 100644 index 0000000000..99776940ec --- /dev/null +++ b/config.tests/qpa/eglfs-viv/eglfs-viv.pro @@ -0,0 +1,6 @@ +SOURCES = eglfs-viv.cpp +DEFINES += LINUX=1 EGL_API_FB=1 + +CONFIG -= qt + +LIBS += -lEGL -lGLESv2 -lGAL diff --git a/configure b/configure index 94f23578c2..ccc2cc4da0 100755 --- a/configure +++ b/configure @@ -5553,6 +5553,22 @@ fi if [ "$CFG_EGLFS" != "no" ]; then if [ "$XPLATFORM_QNX" = "no" ] && [ "$CFG_OPENGL" != "no" ]; then CFG_EGLFS="$CFG_EGL" + # Detect eglfs backends. + if compileTest qpa/eglfs-brcm "eglfs-brcm"; then + CFG_EGLFS_BRCM=yes + else + CFG_EGLFS_BRCM=no + fi + if compileTest qpa/eglfs-mali "eglfs-mali"; then + CFG_EGLFS_MALI=yes + else + CFG_EGLFS_MALI=no + fi + if compileTest qpa/eglfs-viv "eglfs-viv"; then + CFG_EGLFS_VIV=yes + else + CFG_EGLFS_VIV=no + fi else CFG_EGLFS="no" fi @@ -5964,6 +5980,16 @@ if [ "$CFG_EGLFS" = "yes" ]; then else QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_EGLFS" fi +# eglfs backends +if [ "$CFG_EGLFS_BRCM" = "yes" ]; then + QT_CONFIG="$QT_CONFIG eglfs_brcm" +fi +if [ "$CFG_EGLFS_MALI" = "yes" ]; then + QT_CONFIG="$QT_CONFIG eglfs_mali" +fi +if [ "$CFG_EGLFS_VIV" = "yes" ]; then + QT_CONFIG="$QT_CONFIG eglfs_viv" +fi # enable openvg if [ "$CFG_OPENVG" = "no" ]; then @@ -6998,7 +7024,11 @@ report_support " PulseAudio ............." "$CFG_PULSEAUDIO" report_support " QPA backends:" report_support " DirectFB ............." "$CFG_DIRECTFB" report_support " EGLFS ................" "$CFG_EGLFS" -report_support " KMS .................." "$CFG_KMS" +report_support " EGLFS i.MX6....... ." "$CFG_EGLFS_VIV" +report_support " EGLFS KMS .........." "$CFG_KMS" +report_support " EGLFS Mali ........." "$CFG_EGLFS_MALI" +report_support " EGLFS Raspberry Pi ." "$CFG_EGLFS_BRCM" +report_support " EGLFS X11 .........." "$CFG_EGL_X" report_support " LinuxFB .............." "$CFG_LINUXFB" report_support " XCB .................." "$CFG_XCB" system "system library" qt "bundled copy" if [ "$CFG_XCB" != "no" ]; then diff --git a/mkspecs/devices/linux-arm-hisilicon-hix5hd2-g++/qeglfshooks_hix5hd2.cpp b/mkspecs/devices/linux-arm-hisilicon-hix5hd2-g++/qeglfshooks_hix5hd2.cpp deleted file mode 100644 index 9100a97646..0000000000 --- a/mkspecs/devices/linux-arm-hisilicon-hix5hd2-g++/qeglfshooks_hix5hd2.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the qmake spec 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 "qeglfshooks.h" -#include - -#include -#include -#include -#include - -#include - -QT_BEGIN_NAMESPACE - -class QEglFSHiX5Hd2Hooks : public QEglFSHooks -{ -private: - void fbInit(); -public: - void platformInit() Q_DECL_OVERRIDE; - EGLNativeWindowType createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) Q_DECL_OVERRIDE; - void destroyNativeWindow(EGLNativeWindowType window) Q_DECL_OVERRIDE; -}; - -void QEglFSHiX5Hd2Hooks::fbInit() -{ - int fd = qt_safe_open("/dev/fb0", O_RDWR, 0); - if (fd == -1) - qWarning("Failed to open fb to detect screen resolution!"); - - struct fb_var_screeninfo vinfo; - memset(&vinfo, 0, sizeof(vinfo)); - if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) == -1) - qWarning("Could not get variable screen info"); - - vinfo.bits_per_pixel = 32; - vinfo.red.length = 8; - vinfo.green.length = 8; - vinfo.blue.length = 8; - vinfo.transp.length = 8; - vinfo.blue.offset = 0; - vinfo.green.offset = 8; - vinfo.red.offset = 16; - vinfo.transp.offset = 24; - vinfo.yres_virtual = 2 * vinfo.yres; - - if (ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo) == -1) - qErrnoWarning(errno, "Unable to set double buffer mode!"); - - qt_safe_close(fd); - return; -} - -void QEglFSHiX5Hd2Hooks::platformInit() -{ - QEglFSHooks::platformInit(); - fbInit(); -} - -EGLNativeWindowType QEglFSHiX5Hd2Hooks::createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) -{ - fbdev_window *fbwin = reinterpret_cast(malloc(sizeof(fbdev_window))); - if (NULL == fbwin) - return 0; - - fbwin->width = size.width(); - fbwin->height = size.height(); - return (EGLNativeWindowType)fbwin; -} - -void QEglFSHiX5Hd2Hooks::destroyNativeWindow(EGLNativeWindowType window) -{ - free(window); -} - -QEglFSHiX5Hd2Hooks eglFSHiX5Hd2Hooks; -QEglFSHooks *platformHooks = &eglFSHiX5Hd2Hooks; - -QT_END_NAMESPACE diff --git a/mkspecs/devices/linux-arm-hisilicon-hix5hd2-g++/qmake.conf b/mkspecs/devices/linux-arm-hisilicon-hix5hd2-g++/qmake.conf index 851d08600f..71ff90c9f8 100644 --- a/mkspecs/devices/linux-arm-hisilicon-hix5hd2-g++/qmake.conf +++ b/mkspecs/devices/linux-arm-hisilicon-hix5hd2-g++/qmake.conf @@ -18,7 +18,6 @@ # -prefix /home/abc/project/sysbase/qt_install include(../common/linux_device_pre.conf) -EGLFS_PLATFORM_HOOKS_SOURCES = $$PWD/qeglfshooks_hix5hd2.cpp QMAKE_INCDIR += /usr/arm-linux-gnueabihf/include QMAKE_LIBDIR += /usr/arm-linux-gnueabihf/lib @@ -39,6 +38,9 @@ DISTRO_OPTS += hard-float QMAKE_CFLAGS +=-march=armv7-a -mcpu=cortex-a9 -mfpu=vfpv3-d16 QMAKE_CXXFLAGS += $$QMAKE_CFLAGS +# Preferred eglfs backend +EGLFS_DEVICE_INTEGRATION = eglfs_mali + include(../common/linux_arm_device_post.conf) load(qt_config) diff --git a/mkspecs/devices/linux-imx6-g++/qeglfshooks_imx6.cpp b/mkspecs/devices/linux-imx6-g++/qeglfshooks_imx6.cpp deleted file mode 100644 index b5ddafefdc..0000000000 --- a/mkspecs/devices/linux-imx6-g++/qeglfshooks_imx6.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the qmake spec 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 "qeglfshooks.h" -#include -#include - -QT_BEGIN_NAMESPACE - -class QEglFSImx6Hooks : public QEglFSHooks -{ -public: - QEglFSImx6Hooks(); - virtual QSize screenSize() const; - virtual EGLNativeWindowType createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format); - virtual void destroyNativeWindow(EGLNativeWindowType window); - virtual EGLNativeDisplayType platformDisplay() const; - -private: - QSize mScreenSize; - EGLNativeDisplayType mNativeDisplay; -}; - - -QEglFSImx6Hooks::QEglFSImx6Hooks() -{ - int width, height; - - bool multiBufferNotEnabledYet = qEnvironmentVariableIsEmpty("FB_MULTI_BUFFER"); - bool multiBuffer = qEnvironmentVariableIsEmpty("QT_EGLFS_IMX6_NO_FB_MULTI_BUFFER"); - if (multiBufferNotEnabledYet && multiBuffer) { - qWarning() << "QEglFSImx6Hooks will set environment variable FB_MULTI_BUFFER=2 to enable double buffering and vsync.\n" - << "If this is not desired, you can override this via: export QT_EGLFS_IMX6_NO_FB_MULTI_BUFFER=1"; - qputenv("FB_MULTI_BUFFER", "2"); - } - - mNativeDisplay = fbGetDisplayByIndex(framebufferIndex()); - fbGetDisplayGeometry(mNativeDisplay, &width, &height); - mScreenSize.setHeight(height); - mScreenSize.setWidth(width); -} - -QSize QEglFSImx6Hooks::screenSize() const -{ - return mScreenSize; -} - -EGLNativeDisplayType QEglFSImx6Hooks::platformDisplay() const -{ - return mNativeDisplay; -} - -EGLNativeWindowType QEglFSImx6Hooks::createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) -{ - Q_UNUSED(window) - Q_UNUSED(format) - - EGLNativeWindowType eglWindow = fbCreateWindow(mNativeDisplay, 0, 0, size.width(), size.height()); - return eglWindow; -} - - -void QEglFSImx6Hooks::destroyNativeWindow(EGLNativeWindowType window) -{ - fbDestroyWindow(window); -} - -QEglFSImx6Hooks eglFSImx6Hooks; -QEglFSHooks *platformHooks = &eglFSImx6Hooks; - -QT_END_NAMESPACE diff --git a/mkspecs/devices/linux-imx6-g++/qmake.conf b/mkspecs/devices/linux-imx6-g++/qmake.conf index c8b6741e9a..1646c5fe77 100644 --- a/mkspecs/devices/linux-imx6-g++/qmake.conf +++ b/mkspecs/devices/linux-imx6-g++/qmake.conf @@ -4,8 +4,6 @@ include(../common/linux_device_pre.conf) -EGLFS_PLATFORM_HOOKS_SOURCES = $$PWD/qeglfshooks_imx6.cpp - QMAKE_INCDIR += $$[QT_SYSROOT]/usr/include QMAKE_LIBDIR += $$[QT_SYSROOT]/usr/lib @@ -21,6 +19,9 @@ QMAKE_CXXFLAGS += $$IMX6_CFLAGS DISTRO_OPTS += hard-float +# Preferred eglfs backend +EGLFS_DEVICE_INTEGRATION = eglfs_viv + include(../common/linux_arm_device_post.conf) load(qt_config) diff --git a/mkspecs/devices/linux-rasp-pi-g++/qeglfshooks_pi.cpp b/mkspecs/devices/linux-rasp-pi-g++/qeglfshooks_pi.cpp deleted file mode 100644 index 64a9617c48..0000000000 --- a/mkspecs/devices/linux-rasp-pi-g++/qeglfshooks_pi.cpp +++ /dev/null @@ -1,154 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the qmake spec 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 "qeglfshooks.h" - -#include - -#include -#include - -#include - -QT_BEGIN_NAMESPACE - -static DISPMANX_DISPLAY_HANDLE_T dispman_display = 0; - -static EGLNativeWindowType createDispmanxLayer(const QPoint &pos, const QSize &size, int z, DISPMANX_FLAGS_ALPHA_T flags) -{ - VC_RECT_T dst_rect; - dst_rect.x = pos.x(); - dst_rect.y = pos.y(); - dst_rect.width = size.width(); - dst_rect.height = size.height(); - - VC_RECT_T src_rect; - src_rect.x = 0; - src_rect.y = 0; - src_rect.width = size.width() << 16; - src_rect.height = size.height() << 16; - - DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start(0); - - VC_DISPMANX_ALPHA_T alpha; - alpha.flags = flags; - alpha.opacity = 0xFF; - alpha.mask = 0; - - DISPMANX_ELEMENT_HANDLE_T dispman_element = vc_dispmanx_element_add( - dispman_update, dispman_display, z, &dst_rect, 0, &src_rect, - DISPMANX_PROTECTION_NONE, &alpha, (DISPMANX_CLAMP_T *)NULL, (DISPMANX_TRANSFORM_T)0); - - vc_dispmanx_update_submit_sync(dispman_update); - - EGL_DISPMANX_WINDOW_T *eglWindow = new EGL_DISPMANX_WINDOW_T; - eglWindow->element = dispman_element; - eglWindow->width = size.width(); - eglWindow->height = size.height(); - - return eglWindow; -} - -static void destroyDispmanxLayer(EGLNativeWindowType window) -{ - EGL_DISPMANX_WINDOW_T *eglWindow = static_cast(window); - DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start(0); - vc_dispmanx_element_remove(dispman_update, eglWindow->element); - vc_dispmanx_update_submit_sync(dispman_update); - delete eglWindow; -} - -class QEglFSPiHooks : public QEglFSHooks -{ -public: - virtual void platformInit(); - virtual void platformDestroy(); - virtual EGLNativeDisplayType platformDisplay() const; - virtual QSize screenSize() const; - virtual EGLNativeWindowType createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format); - virtual void destroyNativeWindow(EGLNativeWindowType window); - virtual bool hasCapability(QPlatformIntegration::Capability cap) const; - -}; - -void QEglFSPiHooks::platformInit() -{ - bcm_host_init(); -} - -EGLNativeDisplayType QEglFSPiHooks::platformDisplay() const -{ - dispman_display = vc_dispmanx_display_open(0/* LCD */); - return EGL_DEFAULT_DISPLAY; -} - -void QEglFSPiHooks::platformDestroy() -{ - vc_dispmanx_display_close(dispman_display); -} - -QSize QEglFSPiHooks::screenSize() const -{ - uint32_t width, height; - graphics_get_display_size(0 /* LCD */, &width, &height); - return QSize(width, height); -} - -EGLNativeWindowType QEglFSPiHooks::createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) -{ - Q_UNUSED(window) - return createDispmanxLayer(QPoint(0, 0), size, 1, format.hasAlpha() ? DISPMANX_FLAGS_ALPHA_FROM_SOURCE : DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS); -} - -void QEglFSPiHooks::destroyNativeWindow(EGLNativeWindowType window) -{ - destroyDispmanxLayer(window); -} - -bool QEglFSPiHooks::hasCapability(QPlatformIntegration::Capability cap) const -{ - switch (cap) { - case QPlatformIntegration::ThreadedPixmaps: - case QPlatformIntegration::OpenGL: - case QPlatformIntegration::ThreadedOpenGL: - case QPlatformIntegration::BufferQueueingOpenGL: - return true; - default: - return false; - } -} - -QEglFSPiHooks eglFSPiHooks; -QEglFSHooks *platformHooks = &eglFSPiHooks; - -QT_END_NAMESPACE diff --git a/mkspecs/devices/linux-rasp-pi-g++/qmake.conf b/mkspecs/devices/linux-rasp-pi-g++/qmake.conf index 38e4b36cdd..20f8212f8f 100644 --- a/mkspecs/devices/linux-rasp-pi-g++/qmake.conf +++ b/mkspecs/devices/linux-rasp-pi-g++/qmake.conf @@ -36,8 +36,8 @@ QMAKE_CFLAGS += \ QMAKE_CXXFLAGS = $$QMAKE_CFLAGS -EGLFS_PLATFORM_HOOKS_SOURCES = $$PWD/qeglfshooks_pi.cpp -EGLFS_PLATFORM_HOOKS_LIBS = -lbcm_host +# Preferred eglfs backend +EGLFS_DEVICE_INTEGRATION = eglfs_brcm include(../common/linux_arm_device_post.conf) diff --git a/mkspecs/devices/linux-rasp-pi2-g++/qmake.conf b/mkspecs/devices/linux-rasp-pi2-g++/qmake.conf index bf6749534d..9be3f401ce 100644 --- a/mkspecs/devices/linux-rasp-pi2-g++/qmake.conf +++ b/mkspecs/devices/linux-rasp-pi2-g++/qmake.conf @@ -18,8 +18,8 @@ QMAKE_CXXFLAGS = $$QMAKE_CFLAGS DISTRO_OPTS += hard-float -EGLFS_PLATFORM_HOOKS_SOURCES = $$PWD/../linux-rasp-pi-g++/qeglfshooks_pi.cpp -EGLFS_PLATFORM_HOOKS_LIBS = -lbcm_host +# Preferred eglfs backend +EGLFS_DEVICE_INTEGRATION = eglfs_brcm include(../common/linux_arm_device_post.conf) diff --git a/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro b/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro index d8ce385636..0adbb0d49f 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro +++ b/src/plugins/platforms/eglfs/deviceintegration/deviceintegration.pro @@ -2,3 +2,6 @@ TEMPLATE = subdirs contains(QT_CONFIG, egl_x11): SUBDIRS += eglfs_x11 contains(QT_CONFIG, kms): SUBDIRS += eglfs_kms +contains(QT_CONFIG, eglfs_brcm): SUBDIRS += eglfs_brcm +contains(QT_CONFIG, eglfs_mali): SUBDIRS += eglfs_mali +contains(QT_CONFIG, eglfs_viv): SUBDIRS += eglfs_viv diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.json b/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.json new file mode 100644 index 0000000000..5f29d7dd0e --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "eglfs_brcm" ] +} diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.pro new file mode 100644 index 0000000000..98797e2106 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.pro @@ -0,0 +1,20 @@ +TARGET = qeglfs-brcm-integration + +PLUGIN_TYPE = egldeviceintegrations +PLUGIN_CLASS_NAME = QEglFSBrcmIntegrationPlugin +load(qt_plugin) + +QT += core-private gui-private platformsupport-private eglfs_device_lib-private + +INCLUDEPATH += $$PWD/../.. +CONFIG += egl + +LIBS += -lbcm_host +QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF + +SOURCES += $$PWD/qeglfsbrcmmain.cpp \ + $$PWD/qeglfsbrcmintegration.cpp + +HEADERS += $$PWD/qeglfsbrcmintegration.h + +OTHER_FILES += $$PWD/eglfs_brcm.json diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/qeglfsbrcmintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/qeglfsbrcmintegration.cpp new file mode 100644 index 0000000000..4813d9be04 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/qeglfsbrcmintegration.cpp @@ -0,0 +1,132 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qeglfsbrcmintegration.h" +#include + +QT_BEGIN_NAMESPACE + +static DISPMANX_DISPLAY_HANDLE_T dispman_display = 0; + +static EGLNativeWindowType createDispmanxLayer(const QPoint &pos, const QSize &size, int z, DISPMANX_FLAGS_ALPHA_T flags) +{ + VC_RECT_T dst_rect; + dst_rect.x = pos.x(); + dst_rect.y = pos.y(); + dst_rect.width = size.width(); + dst_rect.height = size.height(); + + VC_RECT_T src_rect; + src_rect.x = 0; + src_rect.y = 0; + src_rect.width = size.width() << 16; + src_rect.height = size.height() << 16; + + DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start(0); + + VC_DISPMANX_ALPHA_T alpha; + alpha.flags = flags; + alpha.opacity = 0xFF; + alpha.mask = 0; + + DISPMANX_ELEMENT_HANDLE_T dispman_element = vc_dispmanx_element_add( + dispman_update, dispman_display, z, &dst_rect, 0, &src_rect, + DISPMANX_PROTECTION_NONE, &alpha, (DISPMANX_CLAMP_T *)NULL, (DISPMANX_TRANSFORM_T)0); + + vc_dispmanx_update_submit_sync(dispman_update); + + EGL_DISPMANX_WINDOW_T *eglWindow = new EGL_DISPMANX_WINDOW_T; + eglWindow->element = dispman_element; + eglWindow->width = size.width(); + eglWindow->height = size.height(); + + return eglWindow; +} + +static void destroyDispmanxLayer(EGLNativeWindowType window) +{ + EGL_DISPMANX_WINDOW_T *eglWindow = static_cast(window); + DISPMANX_UPDATE_HANDLE_T dispman_update = vc_dispmanx_update_start(0); + vc_dispmanx_element_remove(dispman_update, eglWindow->element); + vc_dispmanx_update_submit_sync(dispman_update); + delete eglWindow; +} + +void QEglFSBrcmIntegration::platformInit() +{ + bcm_host_init(); +} + +EGLNativeDisplayType QEglFSBrcmIntegration::platformDisplay() const +{ + dispman_display = vc_dispmanx_display_open(0/* LCD */); + return EGL_DEFAULT_DISPLAY; +} + +void QEglFSBrcmIntegration::platformDestroy() +{ + vc_dispmanx_display_close(dispman_display); +} + +QSize QEglFSBrcmIntegration::screenSize() const +{ + uint32_t width, height; + graphics_get_display_size(0 /* LCD */, &width, &height); + return QSize(width, height); +} + +EGLNativeWindowType QEglFSBrcmIntegration::createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) +{ + Q_UNUSED(window) + return createDispmanxLayer(QPoint(0, 0), size, 1, format.hasAlpha() ? DISPMANX_FLAGS_ALPHA_FROM_SOURCE : DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS); +} + +void QEglFSBrcmIntegration::destroyNativeWindow(EGLNativeWindowType window) +{ + destroyDispmanxLayer(window); +} + +bool QEglFSBrcmIntegration::hasCapability(QPlatformIntegration::Capability cap) const +{ + switch (cap) { + case QPlatformIntegration::ThreadedPixmaps: + case QPlatformIntegration::OpenGL: + case QPlatformIntegration::ThreadedOpenGL: + case QPlatformIntegration::BufferQueueingOpenGL: + return true; + default: + return false; + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/qeglfsbrcmintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/qeglfsbrcmintegration.h new file mode 100644 index 0000000000..2a592b8445 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/qeglfsbrcmintegration.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QEGLFSBRCMINTEGRATION_H +#define QEGLFSBRCMINTEGRATION_H + +#include "qeglfsdeviceintegration.h" + +QT_BEGIN_NAMESPACE + +class QEglFSBrcmIntegration : public QEGLDeviceIntegration +{ +public: + void platformInit() Q_DECL_OVERRIDE; + void platformDestroy() Q_DECL_OVERRIDE; + EGLNativeDisplayType platformDisplay() const Q_DECL_OVERRIDE; + QSize screenSize() const Q_DECL_OVERRIDE; + EGLNativeWindowType createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) Q_DECL_OVERRIDE; + void destroyNativeWindow(EGLNativeWindowType window) Q_DECL_OVERRIDE; + bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/qeglfsbrcmmain.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/qeglfsbrcmmain.cpp new file mode 100644 index 0000000000..eb10f3a1e6 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/qeglfsbrcmmain.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qeglfsdeviceintegration.h" +#include "qeglfsbrcmintegration.h" + +QT_BEGIN_NAMESPACE + +class QEglFSBrcmIntegrationPlugin : public QEGLDeviceIntegrationPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QEGLDeviceIntegrationFactoryInterface_iid FILE "eglfs_brcm.json") + +public: + QEGLDeviceIntegration *create() Q_DECL_OVERRIDE { return new QEglFSBrcmIntegration; } +}; + +QT_END_NAMESPACE + +#include "qeglfsbrcmmain.moc" diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro index f79653127e..e53793ce54 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/eglfs_kms.pro @@ -1,8 +1,7 @@ TARGET = qeglfs-kms-integration -PLUGIN_CLASS_NAME=QEglFSKmsIntegrationPlugin -PLUGIN_TYPE=egldeviceintegrations - +PLUGIN_TYPE = egldeviceintegrations +PLUGIN_CLASS_NAME = QEglFSKmsIntegrationPlugin load(qt_plugin) QT += core-private gui-private platformsupport-private eglfs_device_lib-private diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/eglfs_mali.json b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/eglfs_mali.json new file mode 100644 index 0000000000..8cabc1abbd --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/eglfs_mali.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "eglfs_mali" ] +} diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/eglfs_mali.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/eglfs_mali.pro new file mode 100644 index 0000000000..dcfb4cd26d --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/eglfs_mali.pro @@ -0,0 +1,18 @@ +TARGET = qeglfs-mali-integration + +PLUGIN_TYPE = egldeviceintegrations +PLUGIN_CLASS_NAME = QEglFSMaliIntegrationPlugin +load(qt_plugin) + +QT += core-private gui-private platformsupport-private eglfs_device_lib-private + +INCLUDEPATH += $$PWD/../.. +CONFIG += egl +QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF + +SOURCES += $$PWD/qeglfsmalimain.cpp \ + $$PWD/qeglfsmaliintegration.cpp + +HEADERS += $$PWD/qeglfsmaliintegration.h + +OTHER_FILES += $$PWD/eglfs_mali.json diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmaliintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmaliintegration.cpp new file mode 100644 index 0000000000..6e5421d5b9 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmaliintegration.cpp @@ -0,0 +1,96 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qeglfsmaliintegration.h" +#include + +#include +#include +#include +#include + +#include + +QT_BEGIN_NAMESPACE + +void QEglFSMaliIntegration::platformInit() +{ + // Keep the non-overridden base class functions based on fb0 working. + QEGLDeviceIntegration::platformInit(); + + int fd = qt_safe_open("/dev/fb0", O_RDWR, 0); + if (fd == -1) + qWarning("Failed to open fb to detect screen resolution!"); + + struct fb_var_screeninfo vinfo; + memset(&vinfo, 0, sizeof(vinfo)); + if (ioctl(fd, FBIOGET_VSCREENINFO, &vinfo) == -1) + qWarning("Could not get variable screen info"); + + vinfo.bits_per_pixel = 32; + vinfo.red.length = 8; + vinfo.green.length = 8; + vinfo.blue.length = 8; + vinfo.transp.length = 8; + vinfo.blue.offset = 0; + vinfo.green.offset = 8; + vinfo.red.offset = 16; + vinfo.transp.offset = 24; + vinfo.yres_virtual = 2 * vinfo.yres; + + if (ioctl(fd, FBIOPUT_VSCREENINFO, &vinfo) == -1) + qErrnoWarning(errno, "Unable to set double buffer mode!"); + + qt_safe_close(fd); +} + +EGLNativeWindowType QEglFSMaliIntegration::createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) +{ + Q_UNUSED(window); + Q_UNUSED(format); + + fbdev_window *fbwin = reinterpret_cast(malloc(sizeof(fbdev_window))); + if (NULL == fbwin) + return 0; + + fbwin->width = size.width(); + fbwin->height = size.height(); + return (EGLNativeWindowType)fbwin; +} + +void QEglFSMaliIntegration::destroyNativeWindow(EGLNativeWindowType window) +{ + free(window); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmaliintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmaliintegration.h new file mode 100644 index 0000000000..ebe468d70b --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmaliintegration.h @@ -0,0 +1,51 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QEGLFSMALIINTEGRATION_H +#define QEGLFSMALIINTEGRATION_H + +#include "qeglfsdeviceintegration.h" + +QT_BEGIN_NAMESPACE + +class QEglFSMaliIntegration : public QEGLDeviceIntegration +{ +public: + void platformInit() Q_DECL_OVERRIDE; + EGLNativeWindowType createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) Q_DECL_OVERRIDE; + void destroyNativeWindow(EGLNativeWindowType window) Q_DECL_OVERRIDE; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmalimain.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmalimain.cpp new file mode 100644 index 0000000000..0b90858efe --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_mali/qeglfsmalimain.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qeglfsdeviceintegration.h" +#include "qeglfsmaliintegration.h" + +QT_BEGIN_NAMESPACE + +class QEglFSMaliIntegrationPlugin : public QEGLDeviceIntegrationPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QEGLDeviceIntegrationFactoryInterface_iid FILE "eglfs_mali.json") + +public: + QEGLDeviceIntegration *create() Q_DECL_OVERRIDE { return new QEglFSMaliIntegration; } +}; + +QT_END_NAMESPACE + +#include "qeglfsmalimain.moc" diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/eglfs_viv.json b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/eglfs_viv.json new file mode 100644 index 0000000000..ae0cada044 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/eglfs_viv.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "eglfs_viv" ] +} diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/eglfs_viv.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/eglfs_viv.pro new file mode 100644 index 0000000000..fc0533127c --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/eglfs_viv.pro @@ -0,0 +1,20 @@ +TARGET = qeglfs-viv-integration + +PLUGIN_TYPE = egldeviceintegrations +PLUGIN_CLASS_NAME = QEglFSVivIntegrationPlugin +load(qt_plugin) + +QT += core-private gui-private platformsupport-private eglfs_device_lib-private + +INCLUDEPATH += $$PWD/../.. +CONFIG += egl +DEFINES += LINUX=1 EGL_API_FB=1 +LIBS += -lGAL +QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF + +SOURCES += $$PWD/qeglfsvivmain.cpp \ + $$PWD/qeglfsvivintegration.cpp + +HEADERS += $$PWD/qeglfsvivintegration.h + +OTHER_FILES += $$PWD/eglfs_viv.json diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp new file mode 100644 index 0000000000..b7eb3fb2d3 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qeglfsvivintegration.h" +#include +#include + +QT_BEGIN_NAMESPACE + +void QEglFSVivIntegration::platformInit() +{ + QEGLDeviceIntegration::platformInit(); + + int width, height; + + bool multiBufferNotEnabledYet = qEnvironmentVariableIsEmpty("FB_MULTI_BUFFER"); + bool multiBuffer = qEnvironmentVariableIsEmpty("QT_EGLFS_IMX6_NO_FB_MULTI_BUFFER"); + if (multiBufferNotEnabledYet && multiBuffer) { + qWarning() << "QEglFSVivIntegration will set environment variable FB_MULTI_BUFFER=2 to enable double buffering and vsync.\n" + << "If this is not desired, you can override this via: export QT_EGLFS_IMX6_NO_FB_MULTI_BUFFER=1"; + qputenv("FB_MULTI_BUFFER", "2"); + } + + mNativeDisplay = fbGetDisplayByIndex(framebufferIndex()); + fbGetDisplayGeometry(mNativeDisplay, &width, &height); + mScreenSize.setHeight(height); + mScreenSize.setWidth(width); +} + +QSize QEglFSVivIntegration::screenSize() const +{ + return mScreenSize; +} + +EGLNativeDisplayType QEglFSVivIntegration::platformDisplay() const +{ + return mNativeDisplay; +} + +EGLNativeWindowType QEglFSVivIntegration::createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) +{ + Q_UNUSED(window) + Q_UNUSED(format) + + EGLNativeWindowType eglWindow = fbCreateWindow(mNativeDisplay, 0, 0, size.width(), size.height()); + return eglWindow; +} + +void QEglFSVivIntegration::destroyNativeWindow(EGLNativeWindowType window) +{ + fbDestroyWindow(window); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.h new file mode 100644 index 0000000000..181cd3ab94 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivintegration.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QEGLFSVIVINTEGRATION_H +#define QEGLFSVIVINTEGRATION_H + +#include "qeglfsdeviceintegration.h" + +QT_BEGIN_NAMESPACE + +class QEglFSVivIntegration : public QEGLDeviceIntegration +{ +public: + void platformInit() Q_DECL_OVERRIDE; + QSize screenSize() const Q_DECL_OVERRIDE; + EGLNativeWindowType createNativeWindow(QPlatformWindow *window, const QSize &size, const QSurfaceFormat &format) Q_DECL_OVERRIDE; + void destroyNativeWindow(EGLNativeWindowType window) Q_DECL_OVERRIDE; + EGLNativeDisplayType platformDisplay() const Q_DECL_OVERRIDE; + +private: + QSize mScreenSize; + EGLNativeDisplayType mNativeDisplay; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivmain.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivmain.cpp new file mode 100644 index 0000000000..11727f63f9 --- /dev/null +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_viv/qeglfsvivmain.cpp @@ -0,0 +1,50 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qeglfsdeviceintegration.h" +#include "qeglfsvivintegration.h" + +QT_BEGIN_NAMESPACE + +class QEglFSVivIntegrationPlugin : public QEGLDeviceIntegrationPlugin +{ + Q_OBJECT + Q_PLUGIN_METADATA(IID QEGLDeviceIntegrationFactoryInterface_iid FILE "eglfs_viv.json") + +public: + QEGLDeviceIntegration *create() Q_DECL_OVERRIDE { return new QEglFSVivIntegration; } +}; + +QT_END_NAMESPACE + +#include "qeglfsvivmain.moc" diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/eglfs_x11.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/eglfs_x11.pro index a1d08248ff..86fefac8aa 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/eglfs_x11.pro +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_x11/eglfs_x11.pro @@ -1,8 +1,7 @@ TARGET = qeglfs-x11-integration -PLUGIN_CLASS_NAME=QEglFSX11IntegrationPlugin -PLUGIN_TYPE=egldeviceintegrations - +PLUGIN_TYPE = egldeviceintegrations +PLUGIN_CLASS_NAME = QEglFSX11IntegrationPlugin load(qt_plugin) QT += core-private gui-private platformsupport-private eglfs_device_lib-private -- cgit v1.2.3 From dce3721f90eb7179df6f91d27614adfb29059b65 Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Thu, 15 Jan 2015 12:57:57 +0100 Subject: WinRT: Update documentation on icon handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ecf6e34efefcedbff0a457ed4b5e0f4e5d096b37 introduced new values to specify icons in the manifest. Change-Id: I8f0cc9790ffd2f50ed2008bc8bab053b3db4965e Reviewed-by: Leena Miettinen Reviewed-by: Topi Reiniö --- qmake/doc/src/qmake-manual.qdoc | 59 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc index 610bf0cca5..27399c1a1e 100644 --- a/qmake/doc/src/qmake-manual.qdoc +++ b/qmake/doc/src/qmake-manual.qdoc @@ -2555,18 +2555,64 @@ \li identity \li The unique ID of the app. Defaults to reusing the existing generated manifest's UUID, or generates a new UUID if none is present. + \row + \li logo_30x30 + \li Logo image file of size 30x30 pixels. This is not supported on Windows Phone. + \row + \li logo_41x41 + \li Logo image file of size 41x41 pixels. This is only supported on Windows Phone. + \row + \li logo_70x70 + \li Logo image file of size 70x70 pixels. This is not supported on Windows Phone. + \row + \li logo_71x71 + \li Logo image file of size 71x71 pixels. This is only supported on Windows Phone. + \row + \li logo_150x150 + \li Logo image file of size 150x150 pixels. This is supported on all Windows + Store App platforms. + \row + \li logo_310x150 + \li Logo image file of size 310x150 pixels. This is supported on all Windows + Store App platforms. + \row + \li logo_310x310 + \li Logo image file of size 310x310 pixels. This is supported on all Windows + Store App platforms. + \row + \li logo_620x300 + \li Splash screen image file of size 620x300 pixels. This is not supported on + Windows Phone. + \row + \li logo_480x800 + \li Splash sceen image file of size 480x800 pixels. This is only supported on + Windows Phone. \row \li logo_large - \li Large logo image file. Default provided by the mkspec. + \li Large logo image file. This has to be 150x150 pixels. Supported on all + Windows Store App platforms. Default provided by the mkspec. \row \li logo_medium - \li Medium logo image file. Default provided by the mkspec. + \li Medium logo image file. For Windows Phone the image must have a pixel size + of 71x71, for other Windows Store App platforms 70x70. Default provided by + the mkspec. \row \li logo_small - \li Small logo image file. Default provided by the mkspec. + \li Small logo image file. For Windows Phone the image must have a pixel size + of 44x44, for other Windows Store App platforms 30x30. Default provided by + the mkspec. + \row + \li logo_splash + \li Splash screen image file. For Windows Phone the image must have a pixel size + of 480x800, for other Windows Store App platforms 620x300. Default provided + by the mkspec. \row \li logo_store \li Logo image file for Windows Store. Default provided by the mkspec. + \row + \li logo_wide + \li Wide logo image file. This has to be 310x150 pixels. Supported on all + Windows Store App platforms. Default provided by the mkspec. \row \li name \li The name of the package as displayed to the user. Defaults to TARGET. @@ -2582,9 +2628,6 @@ \row \li publisher_id \li The publisher's distinguished name (default: \c{CN=MyCN}). - \row - \li splash_screen - \li Splash screen image file. Default provided by the mkspec. \row \li target \li The name of the target (.exe). Defaults to TARGET. @@ -2612,6 +2655,10 @@ WINRT_MANIFEST = someManifest.xml.in \endcode + \note The required image sizes of \e logo_small, \e logo_medium, and \e logo_large + depend on the target platform. The general descriptions are overwritten if a + description that specifies the size is provided. + \target YACCSOURCES \section1 YACCSOURCES -- cgit v1.2.3 From 6c973dee2cb1686ea32657fff7dced3e611b98ce Mon Sep 17 00:00:00 2001 From: David Faure Date: Sun, 22 Feb 2015 19:35:43 +0100 Subject: Make QCoreApplication::applicationName available after app destruction. Calling applicationName() in the destructor of a global static (e.g. via QLockFile) was working when calling setApplicationName explicitly but otherwise it would suddenly return an empty string. This led to inconsistencies, the application name switching from non-empty to empty at saving-on-destruction time. There was already a global static, used when setting the app name explicitly before construction. Use it now to store the app name in all cases (explicitly set, or fallback). Change-Id: I71d3a0c40158f8bfd022c385b198346a2594b1cb Reviewed-by: Oswald Buddenhagen Reviewed-by: Thiago Macieira --- src/corelib/kernel/qcoreapplication.cpp | 22 ++++++++++++++-------- .../qcoreapplication/tst_qcoreapplication.cpp | 13 +++++++++---- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 18a379f8b9..0bde57c8b3 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -368,7 +368,9 @@ struct QCoreApplicationData { } #endif - QString orgName, orgDomain, application; + QString orgName, orgDomain; + QString application; // application name, initially from argv[0], can then be modified. + QString applicationNameCompat; // for QDesktopServices. Only set explicitly. QString applicationVersion; #ifndef QT_NO_LIBRARY @@ -750,6 +752,9 @@ void QCoreApplication::init() Q_ASSERT_X(!self, "QCoreApplication", "there should be only one application object"); QCoreApplication::self = this; + // Store app name (so it's still available after QCoreApplication is destroyed) + coreappdata()->application = d_func()->appName(); + QLoggingRegistry::instance()->init(); #ifndef QT_NO_QOBJECT @@ -2345,9 +2350,13 @@ QString QCoreApplication::organizationDomain() */ void QCoreApplication::setApplicationName(const QString &application) { - if (coreappdata()->application == application) + QString newAppName = application; + if (newAppName.isEmpty() && QCoreApplication::self) + newAppName = QCoreApplication::self->d_func()->appName(); + if (coreappdata()->application == newAppName) return; - coreappdata()->application = application; + coreappdata()->application = newAppName; + coreappdata()->applicationNameCompat = newAppName; #ifndef QT_NO_QOBJECT if (QCoreApplication::self) emit QCoreApplication::self->applicationNameChanged(); @@ -2359,16 +2368,13 @@ QString QCoreApplication::applicationName() #ifdef Q_OS_BLACKBERRY coreappdata()->loadManifest(); #endif - QString appname = coreappdata() ? coreappdata()->application : QString(); - if (appname.isEmpty() && QCoreApplication::self) - appname = QCoreApplication::self->d_func()->appName(); - return appname; + return coreappdata() ? coreappdata()->application : QString(); } // Exported for QDesktopServices (Qt4 behavior compatibility) Q_CORE_EXPORT QString qt_applicationName_noFallback() { - return coreappdata()->application; + return coreappdata()->applicationNameCompat; } /*! diff --git a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp index 93a6daa6b9..ff4963a960 100644 --- a/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp +++ b/tests/auto/corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp @@ -102,10 +102,15 @@ void tst_QCoreApplication::qAppName() const char* appName = "tst_qcoreapplication"; #endif - int argc = 1; - char *argv[] = { const_cast(appName) }; - TestApplication app(argc, argv); - QCOMPARE(::qAppName(), QString::fromLatin1(appName)); + { + int argc = 1; + char *argv[] = { const_cast(appName) }; + TestApplication app(argc, argv); + QCOMPARE(::qAppName(), QString::fromLatin1(appName)); + QCOMPARE(QCoreApplication::applicationName(), QString::fromLatin1(appName)); + } + // The application name should still be available after destruction; + // global statics often rely on this. QCOMPARE(QCoreApplication::applicationName(), QString::fromLatin1(appName)); } -- cgit v1.2.3 From a5d5353b59ab7eb41d37048064f46490f98a228a Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Thu, 26 Feb 2015 17:46:14 +0400 Subject: Introduce QQuaternion::dotProduct() Change-Id: I14b9857ca0a43808b7d536fc258a6bb10f611211 Reviewed-by: Allan Sandfeld Jensen --- src/gui/math3d/qquaternion.cpp | 37 ++++++++------- src/gui/math3d/qquaternion.h | 7 +++ .../gui/math3d/qquaternion/tst_qquaternion.cpp | 55 ++++++++++++++++++++++ 3 files changed, 82 insertions(+), 17 deletions(-) diff --git a/src/gui/math3d/qquaternion.cpp b/src/gui/math3d/qquaternion.cpp index 4f07d82a25..141651eda1 100644 --- a/src/gui/math3d/qquaternion.cpp +++ b/src/gui/math3d/qquaternion.cpp @@ -212,10 +212,19 @@ QT_BEGIN_NAMESPACE \sa scalar(), setX(), setY(), setZ() */ +/*! + \fn float QQuaternion::dotProduct(const QQuaternion &q1, const QQuaternion &q2) + \since 5.5 + + Returns the dot product of \a q1 and \a q2. + + \sa length() +*/ + /*! Returns the length of the quaternion. This is also called the "norm". - \sa lengthSquared(), normalized() + \sa lengthSquared(), normalized(), dotProduct() */ float QQuaternion::length() const { @@ -225,7 +234,7 @@ float QQuaternion::length() const /*! Returns the squared length of the quaternion. - \sa length() + \sa length(), dotProduct() */ float QQuaternion::lengthSquared() const { @@ -240,7 +249,7 @@ float QQuaternion::lengthSquared() const will be returned as-is. Otherwise the normalized form of the quaternion of length 1 will be returned. - \sa length(), normalize() + \sa normalize(), length(), dotProduct() */ QQuaternion QQuaternion::normalized() const { @@ -792,13 +801,10 @@ QQuaternion QQuaternion::slerp return q2; // Determine the angle between the two quaternions. - QQuaternion q2b; - float dot; - dot = q1.xp * q2.xp + q1.yp * q2.yp + q1.zp * q2.zp + q1.wp * q2.wp; - if (dot >= 0.0f) { - q2b = q2; - } else { - q2b = -q2; + QQuaternion q2b(q2); + float dot = QQuaternion::dotProduct(q1, q2); + if (dot < 0.0f) { + q2b = -q2b; dot = -dot; } @@ -844,13 +850,10 @@ QQuaternion QQuaternion::nlerp return q2; // Determine the angle between the two quaternions. - QQuaternion q2b; - float dot; - dot = q1.xp * q2.xp + q1.yp * q2.yp + q1.zp * q2.zp + q1.wp * q2.wp; - if (dot >= 0.0f) - q2b = q2; - else - q2b = -q2; + QQuaternion q2b(q2); + float dot = QQuaternion::dotProduct(q1, q2); + if (dot < 0.0f) + q2b = -q2b; // Perform the linear interpolation. return (q1 * (1.0f - t) + q2b * t).normalized(); diff --git a/src/gui/math3d/qquaternion.h b/src/gui/math3d/qquaternion.h index a02c37ce1d..b4022e8579 100644 --- a/src/gui/math3d/qquaternion.h +++ b/src/gui/math3d/qquaternion.h @@ -78,6 +78,8 @@ public: void setZ(float z); void setScalar(float scalar); + Q_DECL_CONSTEXPR static inline float dotProduct(const QQuaternion &q1, const QQuaternion &q2); + float length() const; float lengthSquared() const; @@ -168,6 +170,11 @@ inline void QQuaternion::setY(float aY) { yp = aY; } inline void QQuaternion::setZ(float aZ) { zp = aZ; } inline void QQuaternion::setScalar(float aScalar) { wp = aScalar; } +Q_DECL_CONSTEXPR inline float QQuaternion::dotProduct(const QQuaternion &q1, const QQuaternion &q2) +{ + return q1.xp * q2.xp + q1.yp * q2.yp + q1.zp * q2.zp + q1.wp * q2.wp; +} + inline QQuaternion QQuaternion::inverted() const { // Need some extra precision if the length is very small. diff --git a/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp b/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp index ed93ff24b0..e358937a62 100644 --- a/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp +++ b/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp @@ -45,6 +45,9 @@ public: private slots: void create(); + void dotProduct_data(); + void dotProduct(); + void length_data(); void length(); @@ -219,6 +222,58 @@ void tst_QQuaternion::create() QCOMPARE(v10.w(), 34.0f); } +// Test the computation of dot product. +void tst_QQuaternion::dotProduct_data() +{ + QTest::addColumn("x1"); + QTest::addColumn("y1"); + QTest::addColumn("z1"); + QTest::addColumn("scalar1"); + QTest::addColumn("x2"); + QTest::addColumn("y2"); + QTest::addColumn("z2"); + QTest::addColumn("scalar2"); + QTest::addColumn("dot"); + + QTest::newRow("null") + << 0.0f << 0.0f << 0.0f << 0.0f + << 0.0f << 0.0f << 0.0f << 0.0f + << 0.0f; + + QTest::newRow("identity") + << 0.0f << 0.0f << 0.0f << 1.0f + << 0.0f << 0.0f << 0.0f << 1.0f + << 1.0f; + + QTest::newRow("unitvec") + << 1.0f << 0.0f << 0.0f << 0.0f + << 0.0f << 1.0f << 0.0f << 0.0f + << 0.0f; + + QTest::newRow("complex") + << 1.0f << 2.0f << 3.0f << 4.0f + << 4.0f << 5.0f << 6.0f << 7.0f + << 60.0f; +} +void tst_QQuaternion::dotProduct() +{ + QFETCH(float, x1); + QFETCH(float, y1); + QFETCH(float, z1); + QFETCH(float, scalar1); + QFETCH(float, x2); + QFETCH(float, y2); + QFETCH(float, z2); + QFETCH(float, scalar2); + QFETCH(float, dot); + + QQuaternion q1(scalar1, x1, y1, z1); + QQuaternion q2(scalar2, x2, y2, z2); + + QCOMPARE(QQuaternion::dotProduct(q1, q2), dot); + QCOMPARE(QQuaternion::dotProduct(q2, q1), dot); +} + // Test length computation for quaternions. void tst_QQuaternion::length_data() { -- cgit v1.2.3 From 87af240c86c6d99019fdf60ac5f4e688bac9229a Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 5 Mar 2015 16:49:14 +0100 Subject: Manual dialog test: Add a message box for printer errors. Task-number: QTCREATORBUG-13742 Change-Id: I137854eee589cde7a6cf3b841b0b63311e031517 Reviewed-by: Joerg Bornemann --- tests/manual/dialogs/printdialogpanel.cpp | 49 ++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/tests/manual/dialogs/printdialogpanel.cpp b/tests/manual/dialogs/printdialogpanel.cpp index d7291b016d..202a291e5f 100644 --- a/tests/manual/dialogs/printdialogpanel.cpp +++ b/tests/manual/dialogs/printdialogpanel.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -258,9 +259,27 @@ static void drawVertCmRuler(QPainter &painter, int x, int y1, int y2) } } -static void print(QPrinter *printer) +static bool print(QPrinter *printer, QString *errorMessage) { - QPainter painter(printer); + QPainter painter; + + if (!printer->isValid()) { + *errorMessage = QLatin1String("Invalid printer."); + return false; + } + + if (printer->printerState() != QPrinter::Idle) { + *errorMessage = QLatin1String("Printer not idle (state ") + + QString::number(printer->printerState()) + + QLatin1String(")."); + return false; + } + + if (!painter.begin(printer)) { + *errorMessage = QLatin1String("QPainter::begin() failed."); + return false; + } + const QRectF pageF = printer->pageRect(); QFont font = painter.font(); @@ -280,8 +299,8 @@ static void print(QPrinter *printer) << *printer; if (!painter.device()->logicalDpiY() || !painter.device()->logicalDpiX()) { - qWarning() << Q_FUNC_INFO << "Bailing out due to invalid DPI: " << msg; - return; + *errorMessage = QLatin1String("Bailing out due to invalid DPI."); + return false; } painter.drawRect(pageF); @@ -296,7 +315,21 @@ static void print(QPrinter *printer) textPoint.ry() += (15 * charHeight) / 10; } - painter.end(); + if (!painter.end()) { + *errorMessage = QLatin1String("QPainter::end() failed."); + return false; + } + + return true; +} + +static bool print(QPrinter *printer, QWidget *dialogParent) +{ + QString errorMessage; + const bool result = print(printer, &errorMessage); + if (!result) + QMessageBox::warning(dialogParent, QLatin1String("Printing Failed"), errorMessage); + return result; } class PrintPreviewDialog : public QPrintPreviewDialog { @@ -308,7 +341,7 @@ public: } public slots: - void slotPaintRequested(QPrinter *p) { print(p); } + void slotPaintRequested(QPrinter *p) { print(p, this); } }; PrintDialogPanel::PrintDialogPanel(QWidget *parent) @@ -669,7 +702,7 @@ void PrintDialogPanel::showPrintDialog() dialog.setOptions(m_panel.m_dialogOptionsGroupBox->value()); if (dialog.exec() == QDialog::Accepted) { retrieveSettings(m_printer.data()); - print(m_printer.data()); + print(m_printer.data(), this); } } @@ -693,7 +726,7 @@ void PrintDialogPanel::showPageSetupDialog() void PrintDialogPanel::directPrint() { applySettings(m_printer.data()); - print(m_printer.data()); + print(m_printer.data(), this); retrieveSettings(m_printer.data()); } -- cgit v1.2.3 From 4fe9798db3e32aae45d79bef7c1c82e50933658a Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 5 Mar 2015 11:46:27 +0100 Subject: Optimize egl cursor update events Avoid invokeMethod on every cursor movement and use an event instead. This is more lightweight and efficient. Also, there is no need to have a separate QObject just for this. Change-Id: I65ae202943eeb1e30cf22926576f84198f2487f8 Reviewed-by: Andy Nichols --- .../eglconvenience/qeglplatformcursor.cpp | 51 ++++++++++++++-------- .../eglconvenience/qeglplatformcursor_p.h | 21 +-------- 2 files changed, 34 insertions(+), 38 deletions(-) diff --git a/src/platformsupport/eglconvenience/qeglplatformcursor.cpp b/src/platformsupport/eglconvenience/qeglplatformcursor.cpp index fc6e4bad8d..bf23d52465 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcursor.cpp +++ b/src/platformsupport/eglconvenience/qeglplatformcursor.cpp @@ -62,7 +62,7 @@ QEGLPlatformCursor::QEGLPlatformCursor(QPlatformScreen *screen) m_textureCoordEntry(0), m_textureEntry(0), m_deviceListener(0), - m_updater(screen) + m_updateRequested(false) { QByteArray hideCursorVal = qgetenv("QT_QPA_EGLFS_HIDECURSOR"); if (!hideCursorVal.isEmpty()) @@ -246,30 +246,43 @@ bool QEGLPlatformCursor::setCurrentCursor(QCursor *cursor) } #endif -void QEGLPlatformCursorUpdater::update(const QPoint &pos, const QRegion &rgn) +class CursorUpdateEvent : public QEvent { - m_active = false; - QWindowSystemInterface::handleExposeEvent(m_screen->topLevelAt(pos), rgn); - QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); -} - -void QEGLPlatformCursorUpdater::scheduleUpdate(const QPoint &pos, const QRegion &rgn) +public: + CursorUpdateEvent(const QPoint &pos, const QRegion &rgn) + : QEvent(QEvent::Type(QEvent::User + 1)), + m_pos(pos), + m_region(rgn) + { } + QPoint pos() const { return m_pos; } + QRegion region() const { return m_region; } + +private: + QPoint m_pos; + QRegion m_region; +}; + +bool QEGLPlatformCursor::event(QEvent *e) { - if (m_active) - return; - - m_active = true; - - // Must not flush the window system events directly from here since we are likely to - // be a called directly from QGuiApplication's processMouseEvents. Flushing events - // could cause reentering by dispatching more queued mouse events. - QMetaObject::invokeMethod(this, "update", Qt::QueuedConnection, - Q_ARG(QPoint, pos), Q_ARG(QRegion, rgn)); + if (e->type() == QEvent::User + 1) { + CursorUpdateEvent *ev = static_cast(e); + m_updateRequested = false; + QWindowSystemInterface::handleExposeEvent(m_screen->topLevelAt(ev->pos()), ev->region()); + QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); + return true; + } + return QPlatformCursor::event(e); } void QEGLPlatformCursor::update(const QRegion &rgn) { - m_updater.scheduleUpdate(m_cursor.pos, rgn); + if (!m_updateRequested) { + // Must not flush the window system events directly from here since we are likely to + // be a called directly from QGuiApplication's processMouseEvents. Flushing events + // could cause reentering by dispatching more queued mouse events. + m_updateRequested = true; + QCoreApplication::postEvent(this, new CursorUpdateEvent(m_cursor.pos, rgn)); + } } QRect QEGLPlatformCursor::cursorRect() const diff --git a/src/platformsupport/eglconvenience/qeglplatformcursor_p.h b/src/platformsupport/eglconvenience/qeglplatformcursor_p.h index 1c05a06b63..481bb3c74c 100644 --- a/src/platformsupport/eglconvenience/qeglplatformcursor_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformcursor_p.h @@ -70,24 +70,6 @@ private: QEGLPlatformCursor *m_cursor; }; -class QEGLPlatformCursorUpdater : public QObject -{ - Q_OBJECT - -public: - QEGLPlatformCursorUpdater(QPlatformScreen *screen) - : m_screen(screen), m_active(false) { } - - void scheduleUpdate(const QPoint &pos, const QRegion &rgn); - -private slots: - void update(const QPoint &pos, const QRegion &rgn); - -private: - QPlatformScreen *m_screen; - bool m_active; -}; - class QEGLPlatformCursor : public QPlatformCursor, protected QOpenGLFunctions { Q_OBJECT @@ -109,6 +91,7 @@ public: void updateMouseStatus(); private: + bool event(QEvent *e) Q_DECL_OVERRIDE; #ifndef QT_NO_CURSOR bool setCurrentCursor(QCursor *cursor); #endif @@ -150,7 +133,7 @@ private: int m_textureCoordEntry; int m_textureEntry; QEGLPlatformCursorDeviceListener *m_deviceListener; - QEGLPlatformCursorUpdater m_updater; + bool m_updateRequested; }; QT_END_NAMESPACE -- cgit v1.2.3 From 9a3d7adaad367417aaa2e1ee1f996185a881a4b5 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 5 Mar 2015 09:31:20 -0800 Subject: Fix -Wunreachable-code warning from clang in preprocessed Q_ASSERT Q_ASSERT expands to: do {} while (false && ()) Which is fine for Clang as long as it's a macro. However, when you compile as a preprocessed source, the macro is gone and Clang prints the warning: warning: code will never be executed [-Wunreachable-code] do {} while (false && (f())); ^ note: silence by adding parentheses to mark code as explicitly dead So add the parentheses that it's asking about. The changelog refers to the full Q_ASSERT change from ebef2ad1360c80ad62de5f4a1c4e7e4051725c1c. [ChangeLog][Important Behavior Changes] Q_ASSERT will now expand the condition even in release mode when asserts are disabled, albeit in an unreachable code path. This solves compiler warnings about variables and functions that were unused in release mode because they were only used in assertions. Unfortunately, codebases that hid those functions and variables via #ifndef will need to remove the conditionals to compile with Qt 5.5. Change-Id: Ia0aac2f09e9245339951ffff13c8aa70229254d0 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/global/qglobal.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index a171f0894b..92027611b5 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -660,7 +660,7 @@ Q_CORE_EXPORT void qt_assert(const char *assertion, const char *file, int line) #if !defined(Q_ASSERT) # if defined(QT_NO_DEBUG) && !defined(QT_FORCE_ASSERTS) -# define Q_ASSERT(cond) do { } while (false && (cond)) +# define Q_ASSERT(cond) do { } while ((false) && (cond)) # else # define Q_ASSERT(cond) ((!(cond)) ? qt_assert(#cond,__FILE__,__LINE__) : qt_noop()) # endif -- cgit v1.2.3 From 374c60e046405601ff5089c1da6f63a4bc7ea6dc Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Mon, 2 Mar 2015 13:22:02 +0100 Subject: Make QPersistentModelIndex an internal meta-type It was already a user meta-type, so it only gets promoted to internal. [ChangeLog][QtCore] QPersistentModel index becomes an built-in meta-type, including QVariant support. Change-Id: I63d733d1eb66aa61691e7afce27fe7372a83ac00 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/itemmodels/qabstractitemmodel.h | 1 - src/corelib/kernel/qmetatype.cpp | 3 ++ src/corelib/kernel/qmetatype.h | 5 ++- src/corelib/kernel/qmetatype_p.h | 1 + src/corelib/kernel/qvariant.cpp | 52 ++++++++++++++++++++-- src/corelib/kernel/qvariant.h | 3 ++ .../corelib/kernel/qmetatype/tst_qmetatype.cpp | 4 ++ .../auto/corelib/kernel/qvariant/tst_qvariant.cpp | 13 ++++++ 8 files changed, 76 insertions(+), 6 deletions(-) diff --git a/src/corelib/itemmodels/qabstractitemmodel.h b/src/corelib/itemmodels/qabstractitemmodel.h index 1a4b12cd0a..1c2ff9f190 100644 --- a/src/corelib/itemmodels/qabstractitemmodel.h +++ b/src/corelib/itemmodels/qabstractitemmodel.h @@ -484,6 +484,5 @@ inline uint qHash(const QModelIndex &index) Q_DECL_NOTHROW QT_END_NAMESPACE Q_DECLARE_METATYPE(QModelIndexList) -Q_DECLARE_METATYPE(QPersistentModelIndex) #endif // QABSTRACTITEMMODEL_H diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index 305e998818..d4a69ee4b9 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -277,6 +277,7 @@ struct DefinedTypesFilter { \value QJsonArray QJsonArray \value QJsonDocument QJsonDocument \value QModelIndex QModelIndex + \value QPersistentModelIndex QPersistentModelIndex (since 5.5) \value QUuid QUuid \value QByteArrayList QByteArrayList @@ -1209,6 +1210,7 @@ bool QMetaType::save(QDataStream &stream, int type, const void *data) case QMetaType::VoidStar: case QMetaType::QObjectStar: case QMetaType::QModelIndex: + case QMetaType::QPersistentModelIndex: case QMetaType::QJsonValue: case QMetaType::QJsonObject: case QMetaType::QJsonArray: @@ -1429,6 +1431,7 @@ bool QMetaType::load(QDataStream &stream, int type, void *data) case QMetaType::VoidStar: case QMetaType::QObjectStar: case QMetaType::QModelIndex: + case QMetaType::QPersistentModelIndex: case QMetaType::QJsonValue: case QMetaType::QJsonObject: case QMetaType::QJsonArray: diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index 9659c015ff..2c2dbeef9d 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -113,6 +113,7 @@ inline Q_DECL_CONSTEXPR int qMetaTypeId(); F(QJsonObject, 46, QJsonObject) \ F(QJsonArray, 47, QJsonArray) \ F(QJsonDocument, 48, QJsonDocument) \ + F(QPersistentModelIndex, 50, QPersistentModelIndex) \ #define QT_FOR_EACH_STATIC_CORE_POINTER(F)\ F(QObjectStar, 39, QObject*) @@ -407,7 +408,7 @@ public: QT_FOR_EACH_STATIC_TYPE(QT_DEFINE_METATYPE_ID) FirstCoreType = Bool, - LastCoreType = QByteArrayList, + LastCoreType = QPersistentModelIndex, FirstGuiType = QFont, LastGuiType = QPolygonF, FirstWidgetsType = QSizePolicy, @@ -431,7 +432,7 @@ public: QLocale = 18, QRect = 19, QRectF = 20, QSize = 21, QSizeF = 22, QLine = 23, QLineF = 24, QPoint = 25, QPointF = 26, QRegExp = 27, QEasingCurve = 29, QUuid = 30, QVariant = 41, QModelIndex = 42, - QRegularExpression = 44, + QPersistentModelIndex = 50, QRegularExpression = 44, QJsonValue = 45, QJsonObject = 46, QJsonArray = 47, QJsonDocument = 48, QByteArrayList = 49, QObjectStar = 39, SChar = 40, Void = 43, diff --git a/src/corelib/kernel/qmetatype_p.h b/src/corelib/kernel/qmetatype_p.h index 7880baf0f1..7c0c984c9c 100644 --- a/src/corelib/kernel/qmetatype_p.h +++ b/src/corelib/kernel/qmetatype_p.h @@ -192,6 +192,7 @@ template<> struct TypeDefinition { static const bool IsAvailable template<> struct TypeDefinition { static const bool IsAvailable = false; }; template<> struct TypeDefinition { static const bool IsAvailable = false; }; template<> struct TypeDefinition { static const bool IsAvailable = false; }; +template<> struct TypeDefinition { static const bool IsAvailable = false; }; template<> struct TypeDefinition { static const bool IsAvailable = false; }; template<> struct TypeDefinition { static const bool IsAvailable = false; }; #endif diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index b14c9ed167..9ae6c779c0 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -390,7 +390,25 @@ static bool convert(const QVariant::Private *d, int t, void *result, bool *ok) return false; } break; -#endif + case QVariant::ModelIndex: + switch (d->type) { + case QVariant::PersistentModelIndex: + *static_cast(result) = QModelIndex(*v_cast(d)); + break; + default: + return false; + } + break; + case QVariant::PersistentModelIndex: + switch (d->type) { + case QVariant::ModelIndex: + *static_cast(result) = QPersistentModelIndex(*v_cast(d)); + break; + default: + return false; + } + break; +#endif // QT_BOOTSTRAPPED case QVariant::String: { QString *str = static_cast(result); switch (d->type) { @@ -1208,6 +1226,7 @@ Q_CORE_EXPORT void QVariantPrivate::registerHandler(const int /* Modules::Names \value EasingCurve a QEasingCurve \value Uuid a QUuid \value ModelIndex a QModelIndex + \value PersistentModelIndex a QPersistentModelIndex (since 5.5) \value Font a QFont \value Hash a QVariantHash \value Icon a QIcon @@ -1455,7 +1474,14 @@ QVariant::QVariant(const char *val) \since 5.0 \fn QVariant::QVariant(const QModelIndex &val) - Constructs a new variant with an modelIndex value, \a val. + Constructs a new variant with a QModelIndex value, \a val. +*/ + +/*! + \since 5.5 + \fn QVariant::QVariant(const QPersistentModelIndex &val) + + Constructs a new variant with a QPersistentModelIndex value, \a val. */ /*! @@ -1763,6 +1789,9 @@ QVariant::QVariant(const QUuid &uuid) QVariant::QVariant(const QModelIndex &modelIndex) : d(ModelIndex) { v_construct(&d, modelIndex); } +QVariant::QVariant(const QPersistentModelIndex &modelIndex) + : d(PersistentModelIndex) +{ v_construct(&d, modelIndex); } QVariant::QVariant(const QJsonValue &jsonValue) : d(QMetaType::QJsonValue) { v_construct(&d, jsonValue); } @@ -2492,13 +2521,26 @@ QUuid QVariant::toUuid() const Returns the variant as a QModelIndex if the variant has userType() \l QModelIndex; otherwise returns a default constructed QModelIndex. - \sa canConvert(), convert() + \sa canConvert(), convert(), toPersistentModelIndex() */ QModelIndex QVariant::toModelIndex() const { return qVariantToHelper(d, handlerManager); } +/*! + \since 5.5 + + Returns the variant as a QPersistentModelIndex if the variant has userType() \l + QPersistentModelIndex; otherwise returns a default constructed QPersistentModelIndex. + + \sa canConvert(), convert(), toModelIndex() +*/ +QModelIndex QVariant::toPersistentModelIndex() const +{ + return qVariantToHelper(d, handlerManager); +} + /*! \since 5.0 @@ -2966,6 +3008,10 @@ static bool canConvertMetaObject(int fromId, int toId, QObject *fromObject) */ bool QVariant::canConvert(int targetTypeId) const { + if ((targetTypeId == QMetaType::QModelIndex && d.type == QMetaType::QPersistentModelIndex) + || (targetTypeId == QMetaType::QPersistentModelIndex && d.type == QMetaType::QModelIndex)) + return true; + if (targetTypeId == QMetaType::QVariantList && (d.type == QMetaType::QVariantList || d.type == QMetaType::QStringList diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index b6a4133582..d9eca94391 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -156,6 +156,7 @@ class Q_CORE_EXPORT QVariant EasingCurve = QMetaType::QEasingCurve, Uuid = QMetaType::QUuid, ModelIndex = QMetaType::QModelIndex, + PersistentModelIndex = QMetaType::QPersistentModelIndex, LastCoreType = QMetaType::LastCoreType, Font = QMetaType::QFont, @@ -245,6 +246,7 @@ class Q_CORE_EXPORT QVariant QVariant(const QEasingCurve &easing); QVariant(const QUuid &uuid); QVariant(const QModelIndex &modelIndex); + QVariant(const QPersistentModelIndex &modelIndex); QVariant(const QJsonValue &jsonValue); QVariant(const QJsonObject &jsonObject); QVariant(const QJsonArray &jsonArray); @@ -318,6 +320,7 @@ class Q_CORE_EXPORT QVariant QEasingCurve toEasingCurve() const; QUuid toUuid() const; QModelIndex toModelIndex() const; + QModelIndex toPersistentModelIndex() const; QJsonValue toJsonValue() const; QJsonObject toJsonObject() const; QJsonArray toJsonArray() const; diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp index 717a7633f5..88b1bebb29 100644 --- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp @@ -661,6 +661,9 @@ template<> struct TestValueFactory { template<> struct TestValueFactory { static QModelIndex *create() { return new QModelIndex(); } }; +template<> struct TestValueFactory { + static QPersistentModelIndex *create() { return new QPersistentModelIndex(); } +}; template<> struct TestValueFactory { static QRegExp *create() { @@ -1735,6 +1738,7 @@ struct StreamingTraits DECLARE_NONSTREAMABLE(void) DECLARE_NONSTREAMABLE(void*) DECLARE_NONSTREAMABLE(QModelIndex) +DECLARE_NONSTREAMABLE(QPersistentModelIndex) DECLARE_NONSTREAMABLE(QJsonValue) DECLARE_NONSTREAMABLE(QJsonObject) DECLARE_NONSTREAMABLE(QJsonArray) diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp index 32674c587c..1f5132d369 100644 --- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp @@ -248,6 +248,7 @@ private slots: void movabilityTest(); void variantInVariant(); void userConversion(); + void modelIndexConversion(); void forwardDeclare(); void debugStream_data(); @@ -3846,6 +3847,17 @@ void tst_QVariant::userConversion() } } +void tst_QVariant::modelIndexConversion() +{ + QVariant modelIndexVariant = QModelIndex(); + QVERIFY(modelIndexVariant.canConvert(QMetaType::QPersistentModelIndex)); + QVERIFY(modelIndexVariant.convert(QMetaType::QPersistentModelIndex)); + QCOMPARE(modelIndexVariant.type(), QVariant::PersistentModelIndex); + QVERIFY(modelIndexVariant.canConvert(QMetaType::QModelIndex)); + QVERIFY(modelIndexVariant.convert(QMetaType::QModelIndex)); + QCOMPARE(modelIndexVariant.type(), QVariant::ModelIndex); +} + class Forward; Q_DECLARE_OPAQUE_POINTER(Forward*) Q_DECLARE_METATYPE(Forward*) @@ -4073,6 +4085,7 @@ void tst_QVariant::implicitConstruction() F(EasingCurve) \ F(Uuid) \ F(ModelIndex) \ + F(PersistentModelIndex) \ F(RegularExpression) \ F(JsonValue) \ F(JsonObject) \ -- cgit v1.2.3 From f6e6ef46b382e1a7f827afc5f70ce6e5deaa7e86 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Tue, 24 Feb 2015 13:51:21 +0100 Subject: Fix up signal handling in QFbVtHandler Start using signalfd where we can. Drop the crash (SIGSEGV, SIGBUS) handling completely. The crash handling that was in place previously was not async-safe. It also prevented getting a core dump. So just remove it. There is no safe solution for a single application process since restoring the keyboard, video modes, etc. all need unsafe calls in the signal handler almost for sure. We can however improve the handling of non-crash scenarios greatly: Introduce support for SIGINT, allowing nicely and cleanly restoring the video mode with the KMS backend when pressing Ctrl+C while QT_QPA_ENABLE_TERMINAL_KEYBOARD is set. Same goes for keyboard suspend (SIGTSTP, Ctrl+Z). When QT_QPA_ENABLE_TERMINAL_KEYBOARD is set, platform plugins now have the possibility to act upon Ctrl+Z. As an example eglfs' KMS backend is enhanced to handle this by restoring the video mode before suspending the process, and reinitializing when brought into foreground again (SIGCONT). SIGTERM is also handled. This is extremely handy when starting an application locally on the embedded device and then kill-ing it via a remote ssh session. Keyboard and video mode is now cleanly restored. Finally, when disabling the keyboard, try setting also KDSKBMUTE. Change-Id: I2b3608dc23c798e2b39f74cb27f12dcb0e958435 Reviewed-by: Louai Al-Khanji --- .../eglconvenience/qeglplatformintegration_p.h | 2 + src/platformsupport/fbconvenience/qfbvthandler.cpp | 138 ++++++++++++++++----- src/platformsupport/fbconvenience/qfbvthandler_p.h | 19 ++- .../eglfs_kms/qeglfskmsscreen.cpp | 34 ++++- .../deviceintegration/eglfs_kms/qeglfskmsscreen.h | 3 + 5 files changed, 159 insertions(+), 37 deletions(-) diff --git a/src/platformsupport/eglconvenience/qeglplatformintegration_p.h b/src/platformsupport/eglconvenience/qeglplatformintegration_p.h index 3b6c862333..42fbf8c8a1 100644 --- a/src/platformsupport/eglconvenience/qeglplatformintegration_p.h +++ b/src/platformsupport/eglconvenience/qeglplatformintegration_p.h @@ -90,6 +90,8 @@ public: QFunctionPointer platformFunction(const QByteArray &function) const Q_DECL_OVERRIDE; + QFbVtHandler *vtHandler() { return m_vtHandler.data(); } + protected: virtual QEGLPlatformWindow *createWindow(QWindow *window) const = 0; virtual QEGLPlatformContext *createContext(const QSurfaceFormat &format, diff --git a/src/platformsupport/fbconvenience/qfbvthandler.cpp b/src/platformsupport/fbconvenience/qfbvthandler.cpp index d534985129..84844d8eda 100644 --- a/src/platformsupport/fbconvenience/qfbvthandler.cpp +++ b/src/platformsupport/fbconvenience/qfbvthandler.cpp @@ -32,72 +32,148 @@ ****************************************************************************/ #include "qfbvthandler_p.h" -#include -#include +#include -#if defined(Q_OS_LINUX) && !defined(QT_NO_EVDEV) -#define HAS_VT -#endif +#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) && (!defined(QT_NO_EVDEV) || !defined(QT_NO_LIBINPUT)) -#ifdef HAS_VT +#define VTH_ENABLED +#include +#include +#include +#include #include #include +#ifndef KDSKBMUTE +#define KDSKBMUTE 0x4B51 +#endif + #ifdef K_OFF #define KBD_OFF_MODE K_OFF #else #define KBD_OFF_MODE K_RAW #endif -#endif // HAS_VT +#endif QT_BEGIN_NAMESPACE -QFbVtHandler *QFbVtHandler::self = 0; - QFbVtHandler::QFbVtHandler(QObject *parent) - : QObject(parent), m_tty(-1) + : QObject(parent), + m_tty(-1), + m_signalFd(-1), + m_signalNotifier(0) { - Q_ASSERT(!self); - self = this; +#ifdef VTH_ENABLED + if (isatty(0)) { + m_tty = 0; + ioctl(m_tty, KDGKBMODE, &m_oldKbdMode); + + if (!qEnvironmentVariableIntValue("QT_QPA_ENABLE_TERMINAL_KEYBOARD")) { + // Disable the tty keyboard. + ioctl(m_tty, KDSKBMUTE, 1); + ioctl(m_tty, KDSKBMODE, KBD_OFF_MODE); + } + } -#ifdef HAS_VT - if (!isatty(0)) - return; + // SIGSEGV and such cannot safely be blocked. We cannot handle them in an + // async-safe manner either. Restoring the keyboard, video mode, etc. may + // all contain calls that cannot safely be made from a signal handler. - m_tty = 0; - ::ioctl(m_tty, KDGKBMODE, &m_oldKbdMode); - if (!qEnvironmentVariableIntValue("QT_QPA_ENABLE_TERMINAL_KEYBOARD")) { - ::ioctl(m_tty, KDSKBMODE, KBD_OFF_MODE); - QGuiApplicationPrivate *appd = QGuiApplicationPrivate::instance(); - Q_ASSERT(appd); - QSegfaultHandler::initialize(appd->argv, appd->argc); - QSegfaultHandler::installCrashHandler(crashHandler); + // Other signals: block them and use signalfd. + sigset_t mask; + sigemptyset(&mask); + + // Catch Ctrl+C. + sigaddset(&mask, SIGINT); + + // Ctrl+Z. Up to the platform plugins to handle it in a meaningful way. + sigaddset(&mask, SIGTSTP); + sigaddset(&mask, SIGCONT); + + // Default signal used by kill. To overcome the common issue of no cleaning + // up when killing a locally started app via a remote session. + sigaddset(&mask, SIGTERM); + + m_signalFd = signalfd(-1, &mask, SFD_CLOEXEC); + if (m_signalFd < 0) { + qErrnoWarning(errno, "signalfd() failed"); + } else { + m_signalNotifier = new QSocketNotifier(m_signalFd, QSocketNotifier::Read, this); + connect(m_signalNotifier, &QSocketNotifier::activated, this, &QFbVtHandler::handleSignal); + + // Block the signals that are handled via signalfd. Applies only to the current + // thread, but new threads will inherit the creator's signal mask. + pthread_sigmask(SIG_BLOCK, &mask, 0); } #endif } QFbVtHandler::~QFbVtHandler() { - self->cleanup(); - self = 0; +#ifdef VTH_ENABLED + restoreKeyboard(); + + if (m_signalFd != -1) + close(m_signalFd); +#endif } -void QFbVtHandler::cleanup() +void QFbVtHandler::restoreKeyboard() { +#ifdef VTH_ENABLED if (m_tty == -1) return; -#ifdef HAS_VT - ::ioctl(m_tty, KDSKBMODE, m_oldKbdMode); + ioctl(m_tty, KDSKBMUTE, 0); + ioctl(m_tty, KDSKBMODE, m_oldKbdMode); +#endif +} + +// To be called from the slot connected to suspendRequested() in case the +// platform plugin does in fact allow suspending on Ctrl+Z. +void QFbVtHandler::suspend() +{ +#ifdef VTH_ENABLED + kill(getpid(), SIGSTOP); +#endif +} + +void QFbVtHandler::handleSignal() +{ +#ifdef VTH_ENABLED + m_signalNotifier->setEnabled(false); + + signalfd_siginfo sig; + if (read(m_signalFd, &sig, sizeof(sig)) == sizeof(sig)) { + switch (sig.ssi_signo) { + case SIGINT: // fallthrough + case SIGTERM: + handleInt(); + break; + case SIGTSTP: + emit suspendRequested(); + break; + case SIGCONT: + emit resumed(); + break; + default: + break; + } + } + + m_signalNotifier->setEnabled(true); #endif } -void QFbVtHandler::crashHandler() +void QFbVtHandler::handleInt() { - Q_ASSERT(self); - self->cleanup(); +#ifdef VTH_ENABLED + emit interrupted(); + restoreKeyboard(); + _exit(1); +#endif } QT_END_NAMESPACE diff --git a/src/platformsupport/fbconvenience/qfbvthandler_p.h b/src/platformsupport/fbconvenience/qfbvthandler_p.h index 53a39fd58b..3681def9f0 100644 --- a/src/platformsupport/fbconvenience/qfbvthandler_p.h +++ b/src/platformsupport/fbconvenience/qfbvthandler_p.h @@ -49,6 +49,8 @@ QT_BEGIN_NAMESPACE +class QSocketNotifier; + class QFbVtHandler : public QObject { Q_OBJECT @@ -57,13 +59,24 @@ public: QFbVtHandler(QObject *parent = 0); ~QFbVtHandler(); + void suspend(); + +signals: + void interrupted(); + void suspendRequested(); + void resumed(); + +private slots: + void handleSignal(); + private: - void cleanup(); - static void crashHandler(); + void restoreKeyboard(); + void handleInt(); - static QFbVtHandler *self; int m_tty; int m_oldKbdMode; + int m_signalFd; + QSocketNotifier *m_signalNotifier; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp index 45287ae36e..a36ce50b76 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.cpp @@ -37,10 +37,35 @@ #include +#include +#include +#include + QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(qLcEglfsKmsDebug) +class QEglFSKmsInterruptHandler : public QObject +{ +public: + QEglFSKmsInterruptHandler(QEglFSKmsScreen *screen) : m_screen(screen) { + m_vtHandler = static_cast(QGuiApplicationPrivate::platformIntegration())->vtHandler(); + connect(m_vtHandler, &QFbVtHandler::interrupted, this, &QEglFSKmsInterruptHandler::restoreVideoMode); + connect(m_vtHandler, &QFbVtHandler::suspendRequested, this, &QEglFSKmsInterruptHandler::handleSuspendRequest); + } + +public slots: + void restoreVideoMode() { m_screen->restoreMode(); } + void handleSuspendRequest() { + m_screen->restoreMode(); + m_vtHandler->suspend(); + } + +private: + QFbVtHandler *m_vtHandler; + QEglFSKmsScreen *m_screen; +}; + void QEglFSKmsScreen::bufferDestroyedHandler(gbm_bo *bo, void *data) { FrameBuffer *fb = static_cast(data); @@ -93,12 +118,18 @@ QEglFSKmsScreen::QEglFSKmsScreen(QEglFSKmsIntegration *integration, , m_output(output) , m_pos(position) , m_cursor(Q_NULLPTR) + , m_interruptHandler(new QEglFSKmsInterruptHandler(this)) { } QEglFSKmsScreen::~QEglFSKmsScreen() { restoreMode(); + if (m_output.saved_crtc) { + drmModeFreeCrtc(m_output.saved_crtc); + m_output.saved_crtc = Q_NULLPTR; + } + delete m_interruptHandler; } QRect QEglFSKmsScreen::geometry() const @@ -268,9 +299,6 @@ void QEglFSKmsScreen::restoreMode() &m_output.connector_id, 1, &m_output.saved_crtc->mode); - drmModeFreeCrtc(m_output.saved_crtc); - m_output.saved_crtc = Q_NULLPTR; - m_output.mode_set = false; } } diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h index cc2d6942d6..ed79d00896 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsscreen.h @@ -47,6 +47,7 @@ QT_BEGIN_NAMESPACE class QEglFSKmsDevice; class QEglFSKmsCursor; +class QEglFSKmsInterruptHandler; struct QEglFSKmsOutput { @@ -115,6 +116,8 @@ private: FrameBuffer *framebufferForBufferObject(gbm_bo *bo); static QMutex m_waitForFlipMutex; + + QEglFSKmsInterruptHandler *m_interruptHandler; }; QT_END_NAMESPACE -- cgit v1.2.3 From c64d27a9f7e33c9d8748e98e3c3a41ff1ce79729 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 24 Dec 2014 14:07:31 -0200 Subject: QHostAddress: Revert auto-converting of IPv6 v4-mapped addresses to IPv4 In 85136496bc8517951dcc3e670d1a46d340819f0d, Shane made QHostAddress automatically convert any IPv6 address that was v4-mapped to IPv4 in QHostAddress. While that is an interesting trick, it prevents us from being specific about what we want. On some OS (like FreeBSD and OS X), the distinction is relevant, so keep it. Moreover, it was inconsistent: it might fail depending on how the QHostAddress was constructed and the order of comparison. [ChangeLog][Important Behavior Changes] QHostAddress will no longer convert IPv6 addresses of type "v4-mapped" to IPv4. To perform this conversion manually, construct another QHostAddress with the result of toIPv4Address(). Change-Id: I06afbc7018539804bb3044ef1fe6a49ac7a5f240 Reviewed-by: Richard J. Moore --- src/network/kernel/qhostaddress.cpp | 14 ++++---------- .../auto/network/kernel/qhostaddress/tst_qhostaddress.cpp | 5 +++++ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp index 2054fb2c0a..d9de0202ef 100644 --- a/src/network/kernel/qhostaddress.cpp +++ b/src/network/kernel/qhostaddress.cpp @@ -153,10 +153,8 @@ void QHostAddressPrivate::setAddress(const quint8 *a_) for (int i = 0; i < 16; i++) a6[i] = a_[i]; a = 0; - if (parseMappedAddress(a, a6)) - protocol = QAbstractSocket::IPv4Protocol; - else - protocol = QAbstractSocket::IPv6Protocol; + parseMappedAddress(a, a6); + protocol = QAbstractSocket::IPv6Protocol; isParsed = true; } @@ -164,10 +162,8 @@ void QHostAddressPrivate::setAddress(const Q_IPV6ADDR &a_) { a6 = a_; a = 0; - if (parseMappedAddress(a, a6)) - protocol = QAbstractSocket::IPv4Protocol; - else - protocol = QAbstractSocket::IPv6Protocol; + parseMappedAddress(a, a6); + protocol = QAbstractSocket::IPv6Protocol; isParsed = true; } @@ -197,7 +193,6 @@ bool QHostAddressPrivate::parse() quint8 maybeIp6[16]; if (parseIp6(a, maybeIp6, &scopeId)) { setAddress(maybeIp6); - protocol = QAbstractSocket::IPv6Protocol; return true; } } @@ -205,7 +200,6 @@ bool QHostAddressPrivate::parse() quint32 maybeIp4 = 0; if (QIPAddressUtils::parseIp4(maybeIp4, a.constBegin(), a.constEnd())) { setAddress(maybeIp4); - protocol = QAbstractSocket::IPv4Protocol; return true; } diff --git a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp index 49a030aaaa..60b96d38b7 100644 --- a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp +++ b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp @@ -313,6 +313,10 @@ void tst_QHostAddress::compare_data() QTest::newRow("5") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::Broadcast) << false; QTest::newRow("6") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(QHostAddress::LocalHostIPv6) << false; QTest::newRow("7") << QHostAddress() << QHostAddress(QHostAddress::LocalHostIPv6) << false; + + Q_IPV6ADDR localhostv4mapped = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 127, 0, 0, 1 }; + QTest::newRow("v4-v4mapped") << QHostAddress(QHostAddress::LocalHost) << QHostAddress("::ffff:127.0.0.1") << false; + QTest::newRow("v4-v4mapped-2") << QHostAddress(QHostAddress::LocalHost) << QHostAddress(localhostv4mapped) << false; } void tst_QHostAddress::compare() @@ -322,6 +326,7 @@ void tst_QHostAddress::compare() QFETCH(bool, result); QCOMPARE(first == second, result); + QCOMPARE(second == first, result); if (result == true) QVERIFY(qHash(first) == qHash(second)); } -- cgit v1.2.3 From ab8d36d6f36119dc9ef211acc391d8c2bfb5ee83 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 24 Dec 2014 15:40:21 -0200 Subject: QHostAddress: Convert AnyIPv4 to AnyIPv6 instead of ::ffff:0.0.0.0 Unlike localhost (127.0.0.1), there's really no point in using ::ffff:0.0.0.0, since you shouldn't be sending packets to it. Linux transforms 0.0.0.0 to localhost, but that's non-standard and won't work on other OSs, so it's still a bad idea. Change-Id: I5982b21bf953e11e04fc19893f94be90ed29089b Reviewed-by: Richard J. Moore --- src/network/kernel/qhostaddress.cpp | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp index d9de0202ef..8d32711de3 100644 --- a/src/network/kernel/qhostaddress.cpp +++ b/src/network/kernel/qhostaddress.cpp @@ -123,28 +123,41 @@ QHostAddressPrivate::QHostAddressPrivate() void QHostAddressPrivate::setAddress(quint32 a_) { a = a_; - //create mapped address + //create mapped address, except for a_ == 0 (any) memset(&a6, 0, sizeof(a6)); + if (a) { + a6[11] = 0xFF; + a6[10] = 0xFF; + } else { + a6[11] = 0; + a6[10] = 0; + } + int i; for (i=15; a_ != 0; i--) { a6[i] = a_ & 0xFF; a_ >>=8; } Q_ASSERT(i >= 11); - a6[11] = 0xFF; - a6[10] = 0xFF; protocol = QAbstractSocket::IPv4Protocol; isParsed = true; } -static bool parseMappedAddress(quint32& a, const Q_IPV6ADDR &a6) +/// parses v4-mapped addresses or the AnyIPv6 address and stores in \a a; +/// returns true if the address was one of those +static bool convertToIpv4(quint32& a, const Q_IPV6ADDR &a6) { - int i; - for (i=0;i<10;i++) - if (a6[i]) return false; - for (;i<12;i++) - if (a6[i] != 0xFF) return false; - a=(a6[12] << 24) | (a6[13] << 16) | (a6[14] << 8) | a6[15]; + const uchar *ptr = a6.c; + if (qFromUnaligned(ptr) != 0) + return false; + if (qFromBigEndian(ptr + 8) == 0) { + // is it AnyIPv6? + a = 0; + return qFromBigEndian(ptr + 12) == 0; + } + if (qFromBigEndian(ptr + 8) != 0xFFFF) + return false; + a = qFromBigEndian(ptr + 12); return true; } @@ -153,7 +166,7 @@ void QHostAddressPrivate::setAddress(const quint8 *a_) for (int i = 0; i < 16; i++) a6[i] = a_[i]; a = 0; - parseMappedAddress(a, a6); + convertToIpv4(a, a6); protocol = QAbstractSocket::IPv6Protocol; isParsed = true; } @@ -162,7 +175,7 @@ void QHostAddressPrivate::setAddress(const Q_IPV6ADDR &a_) { a6 = a_; a = 0; - parseMappedAddress(a, a6); + convertToIpv4(a, a6); protocol = QAbstractSocket::IPv6Protocol; isParsed = true; } -- cgit v1.2.3 From 775d04f97ec1723c01c12f8faab05236686b9b05 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 24 Dec 2014 15:43:08 -0200 Subject: Add a QHostAddress::toIPv4Address overload taking a bool *ok This allows one to check whether the conversion is successful without checking for the return result, as the value of 0 represents the valid IPv4 address 0.0.0.0. Change-Id: I637fe55583f2255c85b0d955e5886b61494e0c7c Reviewed-by: Richard J. Moore --- src/network/kernel/qhostaddress.cpp | 24 +++++++++++ src/network/kernel/qhostaddress.h | 3 +- .../kernel/qhostaddress/tst_qhostaddress.cpp | 48 ++++++++++++++++++++++ 3 files changed, 74 insertions(+), 1 deletion(-) diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp index 8d32711de3..9a993392e9 100644 --- a/src/network/kernel/qhostaddress.cpp +++ b/src/network/kernel/qhostaddress.cpp @@ -633,8 +633,32 @@ void QHostAddress::setAddress(const struct sockaddr *sockaddr) \sa toString() */ quint32 QHostAddress::toIPv4Address() const +{ + return toIPv4Address(Q_NULLPTR); +} + +/*! + Returns the IPv4 address as a number. + + For example, if the address is 127.0.0.1, the returned value is + 2130706433 (i.e. 0x7f000001). + + This value is valid if the protocol() is + \l{QAbstractSocket::}{IPv4Protocol}, + or if the protocol is + \l{QAbstractSocket::}{IPv6Protocol}, + and the IPv6 address is an IPv4 mapped address. (RFC4291). In those + cases, \a ok will be set to true. Otherwise, it will be set to false. + + \sa toString() +*/ +quint32 QHostAddress::toIPv4Address(bool *ok) const { QT_ENSURE_PARSED(this); + quint32 dummy; + if (ok) + *ok = d->protocol == QAbstractSocket::IPv4Protocol || d->protocol == QAbstractSocket::AnyIPProtocol + || (d->protocol == QAbstractSocket::IPv6Protocol && convertToIpv4(dummy, d->a6)); return d->a; } diff --git a/src/network/kernel/qhostaddress.h b/src/network/kernel/qhostaddress.h index 93d64ff54a..de3a79278e 100644 --- a/src/network/kernel/qhostaddress.h +++ b/src/network/kernel/qhostaddress.h @@ -93,7 +93,8 @@ public: bool setAddress(const QString &address); QAbstractSocket::NetworkLayerProtocol protocol() const; - quint32 toIPv4Address() const; + quint32 toIPv4Address() const; // ### Qt6: merge with next overload + quint32 toIPv4Address(bool *ok) const; Q_IPV6ADDR toIPv6Address() const; QString toString() const; diff --git a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp index 60b96d38b7..ef24cbf3c8 100644 --- a/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp +++ b/tests/auto/network/kernel/qhostaddress/tst_qhostaddress.cpp @@ -83,6 +83,8 @@ private slots: void isInSubnet(); void isLoopback_data(); void isLoopback(); + void convertv4v6_data(); + void convertv4v6(); }; QT_BEGIN_NAMESPACE @@ -662,5 +664,51 @@ void tst_QHostAddress::isLoopback() QCOMPARE(address.isLoopback(), result); } +void tst_QHostAddress::convertv4v6_data() +{ + QTest::addColumn("source"); + QTest::addColumn("protocol"); + QTest::addColumn("result"); + + QTest::newRow("any-to-v4") << QHostAddress(QHostAddress::Any) << 4 << QHostAddress(QHostAddress::AnyIPv4); + QTest::newRow("any-to-v6") << QHostAddress(QHostAddress::Any) << 6 << QHostAddress(QHostAddress::AnyIPv6); + QTest::newRow("anyv4-to-v6") << QHostAddress(QHostAddress::AnyIPv4) << 6 << QHostAddress(QHostAddress::AnyIPv6); + QTest::newRow("anyv6-to-v4") << QHostAddress(QHostAddress::AnyIPv6) << 4 << QHostAddress(QHostAddress::AnyIPv4); + + QTest::newRow("v4mapped-to-v4") << QHostAddress("::ffff:192.0.2.1") << 4 << QHostAddress("192.0.2.1"); + QTest::newRow("v4-to-v4mapped") << QHostAddress("192.0.2.1") << 6 << QHostAddress("::ffff:192.0.2.1"); + + // we won't convert 127.0.0.1 to ::1 or vice-versa: + // you can connect to a v4 server socket with ::ffff:127.0.0.1, but not with ::1 + QTest::newRow("localhost-to-v4mapped") << QHostAddress(QHostAddress::LocalHost) << 6 << QHostAddress("::ffff:127.0.0.1"); + QTest::newRow("v4mapped-to-localhost") << QHostAddress("::ffff:127.0.0.1") << 4 << QHostAddress(QHostAddress::LocalHost); + + // in turn, that means localhost6 doesn't convert to v4 + QTest::newRow("localhost6-to-v4") << QHostAddress(QHostAddress::LocalHostIPv6) << 4 << QHostAddress(); + + // some other v6 addresses that won't convert to v4 + QTest::newRow("v4compat-to-v4") << QHostAddress("::192.0.2.1") << 4 << QHostAddress(); + QTest::newRow("localhostv4compat-to-v4") << QHostAddress("::127.0.0.1") << 4 << QHostAddress(); + QTest::newRow("v6global-to-v4") << QHostAddress("2001:db8::1") << 4 << QHostAddress(); + QTest::newRow("v6multicast-to-v4") << QHostAddress("ff02::1") << 4 << QHostAddress(); +} + +void tst_QHostAddress::convertv4v6() +{ + QFETCH(QHostAddress, source); + QFETCH(int, protocol); + QFETCH(QHostAddress, result); + + if (protocol == 4) { + bool ok; + quint32 v4 = source.toIPv4Address(&ok); + QCOMPARE(ok, result.protocol() == QAbstractSocket::IPv4Protocol); + if (ok) + QCOMPARE(QHostAddress(v4), result); + } else if (protocol == 6) { + QCOMPARE(QHostAddress(source.toIPv6Address()), result); + } +} + QTEST_MAIN(tst_QHostAddress) #include "tst_qhostaddress.moc" -- cgit v1.2.3 From ed42bf8c0562ce625ebf7bb3e6b0624da5a1d7ec Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Wed, 4 Mar 2015 11:46:28 +0100 Subject: Fix QMessageBox::aboutQt(). Add missing blanks and prevent line wraps "...Qt\napplications.." for clarity. Change-Id: I35932fb296ec47a1832f5c244b9719838621d5be Reviewed-by: Iikka Eklund Reviewed-by: Lars Knoll --- src/widgets/dialogs/qmessagebox.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/widgets/dialogs/qmessagebox.cpp b/src/widgets/dialogs/qmessagebox.cpp index 66152387e4..571b01802d 100644 --- a/src/widgets/dialogs/qmessagebox.cpp +++ b/src/widgets/dialogs/qmessagebox.cpp @@ -1894,18 +1894,17 @@ void QMessageBox::aboutQt(QWidget *parent, const QString &title) "want to share any source code with third parties or otherwise cannot " "comply with the terms of the GNU LGPL version 3 or GNU LGPL version 2.1.

" "

Qt licensed under the GNU LGPL version 3 is appropriate for the " - "development of Qt applications provided you can comply with the terms " + "development of Qt applications provided you can comply with the terms " "and conditions of the GNU LGPL version 3.

" "

Qt licensed under the GNU LGPL version 2.1 is appropriate for the " - "development of Qt applications provided you can comply with the terms " + "development of Qt applications provided you can comply with the terms " "and conditions of the GNU LGPL version 2.1.

" "

Please see %2 " "for an overview of Qt licensing.

" "

Copyright (C) %1 The Qt Company Ltd and other " "contributors.

" - "

Qt and the Qt logo are trademarks of The Qt Company Ltd and/or its" - "subsidiary(-ies).

" - "

Qt is The Qt Company Ltd product developed as an open source" + "

Qt and the Qt logo are trademarks of The Qt Company Ltd.

" + "

Qt is The Qt Company Ltd product developed as an open source " "project. See %3 for more information.

" ).arg(QStringLiteral("2015"), QStringLiteral("qt.io/licensing"), -- cgit v1.2.3 From d326952b51ccd8e92f54d9faee12475060ab0968 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 5 Mar 2015 10:08:11 +0100 Subject: Polish the Dir View example. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a command line parser so that the directory can be specified. Resize depending on screen size and make first (name) column larger. Change-Id: Ied5823b4e8f50345aae792628fb610b8604e37d3 Reviewed-by: Topi Reiniö --- examples/widgets/itemviews/dirview/main.cpp | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/examples/widgets/itemviews/dirview/main.cpp b/examples/widgets/itemviews/dirview/main.cpp index bc1b8a5d7b..abca413325 100644 --- a/examples/widgets/itemviews/dirview/main.cpp +++ b/examples/widgets/itemviews/dirview/main.cpp @@ -39,25 +39,45 @@ ****************************************************************************/ #include +#include #include #include +#include +#include int main(int argc, char *argv[]) { QApplication app(argc, argv); + QCoreApplication::setApplicationVersion(QT_VERSION_STR); + QCommandLineParser parser; + parser.setApplicationDescription("Qt Dir View Example"); + parser.addHelpOption(); + parser.addVersionOption(); + parser.addPositionalArgument("directory", "The directory to start in."); + parser.process(app); + const QString rootPath = parser.positionalArguments().isEmpty() + ? QString() : parser.positionalArguments().first(); + QFileSystemModel model; model.setRootPath(""); QTreeView tree; tree.setModel(&model); + if (!rootPath.isEmpty()) { + const QModelIndex rootIndex = model.index(QDir::cleanPath(rootPath)); + if (rootIndex.isValid()) + tree.setRootIndex(rootIndex); + } // Demonstrating look and feel features tree.setAnimated(false); tree.setIndentation(20); tree.setSortingEnabled(true); + const QSize availableSize = QApplication::desktop()->availableGeometry(&tree).size(); + tree.resize(availableSize / 2); + tree.setColumnWidth(0, tree.width() / 3); tree.setWindowTitle(QObject::tr("Dir View")); - tree.resize(640, 480); tree.show(); return app.exec(); -- cgit v1.2.3 From b0182069e57175216bc9aa6d71fcb7efbff54116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 4 Mar 2015 16:56:49 +0100 Subject: iOS: Define QT_NO_PROCESS, as the platform doesn't allow fork/exec MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I0928c4aaa0c308ee86b9611beeba3937b61e226c Reviewed-by: Richard Moe Gustavsen Reviewed-by: Tor Arne Vestbø --- src/corelib/global/qglobal.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 92027611b5..ddba460b06 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -585,6 +585,10 @@ class QDataStream; # define QT_NO_SOCKS5 #endif +#if defined(Q_OS_IOS) +# define QT_NO_PROCESS +#endif + inline void qt_noop(void) {} /* These wrap try/catch so we can switch off exceptions later. -- cgit v1.2.3 From ddf09adeeb165117f3802c64cb355f2e03c2bf5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 4 Mar 2015 12:43:03 +0100 Subject: iOS: Use qFatal when detecting QApplication before UIApplicationMain MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Gives a stack-trace at the point the error was caused, making it easier to debug what's going on. Change-Id: I0d65bb5061e9a97c142d41f6c99a1a1803cbe82d Reviewed-by: Richard Moe Gustavsen Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/ios/qiosintegration.mm | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm index 33328e0490..9d29b4edf7 100644 --- a/src/plugins/platforms/ios/qiosintegration.mm +++ b/src/plugins/platforms/ios/qiosintegration.mm @@ -69,12 +69,10 @@ QIOSIntegration::QIOSIntegration() , m_accessibility(0) { if (![UIApplication sharedApplication]) { - qWarning() - << "Error: You are creating QApplication before calling UIApplicationMain.\n" - << "If you are writing a native iOS application, and only want to use Qt for\n" - << "parts of the application, a good place to create QApplication is from within\n" - << "'applicationDidFinishLaunching' inside your UIApplication delegate.\n"; - exit(-1); + qFatal("Error: You are creating QApplication before calling UIApplicationMain.\n" \ + "If you are writing a native iOS application, and only want to use Qt for\n" \ + "parts of the application, a good place to create QApplication is from within\n" \ + "'applicationDidFinishLaunching' inside your UIApplication delegate.\n"); } // Set current directory to app bundle folder -- cgit v1.2.3 From 006fc32ca7ab5a837ef7b4d5bb4debb753414675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 13 Feb 2015 15:28:32 +0100 Subject: Xcode: Add support for generating XCTest test bundles out of Qt testcases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If the user adds CONFIG+=bundle and doesn't set QMAKE_BUNDLE_EXTENSION, we interpret that as a request to generate a test bundle. Change-Id: Id4fbb64d39cddd6f95ac641a910a9d5543c30daa Reviewed-by: Richard Moe Gustavsen Reviewed-by: Tor Arne Vestbø --- mkspecs/features/testcase.prf | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/mkspecs/features/testcase.prf b/mkspecs/features/testcase.prf index 770afa3386..c77f3b70ab 100644 --- a/mkspecs/features/testcase.prf +++ b/mkspecs/features/testcase.prf @@ -187,5 +187,11 @@ contains(INSTALLS, target) { } } +macx-xcode:bundle:isEmpty(QMAKE_BUNDLE_EXTENSION) { + QMAKE_PBX_PRODUCT_TYPE = com.apple.product-type.bundle.unit-test + QMAKE_PBX_BUNDLE_TYPE = wrapper.cfbundle + QMAKE_BUNDLE_EXTENSION = .xctest +} + } # have_target -- cgit v1.2.3 From 4fb2014657c1fcd74ee4cd7f669173eace4868e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 13 Feb 2015 15:25:06 +0100 Subject: iOS: Resolve correct SDK as part of sdk.prf instead of default_post.prf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The latter location resulted in the wrong SDK paths being resolved if sdk.prf was loaded before default_post.prf through an explicit load(sdk) call. Change-Id: Ia443260572fbdf5f9ed1daf558c2962703274e32 Reviewed-by: Richard Moe Gustavsen Reviewed-by: Tor Arne Vestbø --- mkspecs/macx-ios-clang/features/default_post.prf | 11 +---------- mkspecs/macx-ios-clang/features/sdk.prf | 11 +++++++++++ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/mkspecs/macx-ios-clang/features/default_post.prf b/mkspecs/macx-ios-clang/features/default_post.prf index f1f23dd716..38889150c8 100644 --- a/mkspecs/macx-ios-clang/features/default_post.prf +++ b/mkspecs/macx-ios-clang/features/default_post.prf @@ -1,14 +1,5 @@ -# In case the user sets the SDK manually -contains(QMAKE_MAC_SDK, ^iphonesimulator.*) { - iphonesimulator_and_iphoneos: \ - error("iOS simulator is handled automatically for iphonesimulator_and_iphoneos") - - CONFIG += iphonesimulator -} - -iphonesimulator_and_iphoneos:iphonesimulator: \ - QMAKE_MAC_SDK ~= s,^iphoneos,iphonesimulator, +load(sdk) # Resolve config so we don't need to use CONFIG() later on CONFIG(iphonesimulator, iphonesimulator|iphoneos) { diff --git a/mkspecs/macx-ios-clang/features/sdk.prf b/mkspecs/macx-ios-clang/features/sdk.prf index 607a71bb26..003789b5be 100644 --- a/mkspecs/macx-ios-clang/features/sdk.prf +++ b/mkspecs/macx-ios-clang/features/sdk.prf @@ -1,3 +1,14 @@ +# In case the user sets the SDK manually +contains(QMAKE_MAC_SDK, ^iphonesimulator.*) { + iphonesimulator_and_iphoneos: \ + error("iOS simulator is handled automatically for iphonesimulator_and_iphoneos") + + CONFIG += iphonesimulator +} + +iphonesimulator_and_iphoneos:iphonesimulator: \ + QMAKE_MAC_SDK ~= s,^iphoneos,iphonesimulator, + load(sdk) lessThan(QMAKE_MAC_SDK_VERSION, "8.0"): \ -- cgit v1.2.3 From 91828af6c508c5bb9c0c819d1fe18cc2273f1810 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 13 Feb 2015 15:17:47 +0100 Subject: qmake: Expose iOS/OS X SDK platform path as QMAKE_MAC_SDK_PLATFORM_PATH MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I2e58c22301a433208718c26b362b4dda2b891f0e Reviewed-by: Richard Moe Gustavsen Reviewed-by: Tor Arne Vestbø --- mkspecs/features/mac/sdk.prf | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mkspecs/features/mac/sdk.prf b/mkspecs/features/mac/sdk.prf index d2e698894f..e238f8e005 100644 --- a/mkspecs/features/mac/sdk.prf +++ b/mkspecs/features/mac/sdk.prf @@ -13,6 +13,14 @@ isEmpty(QMAKE_MAC_SDK.$${QMAKE_MAC_SDK}.path) { QMAKE_MAC_SDK_PATH = $$eval(QMAKE_MAC_SDK.$${QMAKE_MAC_SDK}.path) } +isEmpty(QMAKE_MAC_SDK.$${QMAKE_MAC_SDK}.platform_path) { + QMAKE_MAC_SDK_PLATFORM_PATH = $$system("/usr/bin/xcodebuild -sdk $$QMAKE_MAC_SDK -version PlatformPath 2>/dev/null") + isEmpty(QMAKE_MAC_SDK_PLATFORM_PATH): error("Could not resolve SDK platform path for \'$$QMAKE_MAC_SDK\'") + cache(QMAKE_MAC_SDK.$${QMAKE_MAC_SDK}.platform_path, set stash, QMAKE_MAC_SDK_PLATFORM_PATH) +} else { + QMAKE_MAC_SDK_PLATFORM_PATH = $$eval(QMAKE_MAC_SDK.$${QMAKE_MAC_SDK}.platform_path) +} + isEmpty(QMAKE_MAC_SDK.$${QMAKE_MAC_SDK}.version) { QMAKE_MAC_SDK_VERSION = $$system("/usr/bin/xcodebuild -sdk $$QMAKE_MAC_SDK -version SDKVersion 2>/dev/null") isEmpty(QMAKE_MAC_SDK_VERSION): error("Could not resolve SDK version for \'$$QMAKE_MAC_SDK\'") -- cgit v1.2.3 From 08f6af608a8269dfa7d3e2f58be45ee0df72b925 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 9 Feb 2015 15:01:30 +0100 Subject: Xcode: Generate scheme manually, instead of letting Xcode do it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A scheme is required to be able to run tests through Xcode, even from the command line, but Xcode doesn't auto-generate the schemes until launched as an application. Xcode also auto-generates schemes for all our targets, but we only need one for the primary application target. Change-Id: Ia42f3825aba3ffde3be93be55e165d6284434853 Reviewed-by: Richard Moe Gustavsen Reviewed-by: Tor Arne Vestbø --- mkspecs/macx-xcode/WorkspaceSettings.xcsettings | 8 +++ mkspecs/macx-xcode/default.xcscheme | 96 +++++++++++++++++++++++++ mkspecs/macx-xcode/qmake.conf | 2 + qmake/generators/mac/pbuilder_pbx.cpp | 46 ++++++++++++ 4 files changed, 152 insertions(+) create mode 100644 mkspecs/macx-xcode/WorkspaceSettings.xcsettings create mode 100644 mkspecs/macx-xcode/default.xcscheme diff --git a/mkspecs/macx-xcode/WorkspaceSettings.xcsettings b/mkspecs/macx-xcode/WorkspaceSettings.xcsettings new file mode 100644 index 0000000000..08de0be8d3 --- /dev/null +++ b/mkspecs/macx-xcode/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded + + + diff --git a/mkspecs/macx-xcode/default.xcscheme b/mkspecs/macx-xcode/default.xcscheme new file mode 100644 index 0000000000..53c736cc15 --- /dev/null +++ b/mkspecs/macx-xcode/default.xcscheme @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/mkspecs/macx-xcode/qmake.conf b/mkspecs/macx-xcode/qmake.conf index fde682b64b..6fc6160ec7 100644 --- a/mkspecs/macx-xcode/qmake.conf +++ b/mkspecs/macx-xcode/qmake.conf @@ -6,6 +6,8 @@ QMAKESPEC = $$dirname(PWD)/$$[QMAKE_XSPEC] +QMAKE_XCODE_SPECDIR = $$PWD + include($$QMAKESPEC/qmake.conf) MAKEFILE_GENERATOR = XCODE diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp index 36ec6ef742..e2b5f5f90b 100644 --- a/qmake/generators/mac/pbuilder_pbx.cpp +++ b/qmake/generators/mac/pbuilder_pbx.cpp @@ -1573,6 +1573,52 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t) } } + // Scheme + { + QString xcodeSpecDir = project->first("QMAKE_XCODE_SPECDIR").toQString(); + + bool wroteCustomScheme = false; + + QString projectSharedSchemesPath = pbx_dir + "/xcshareddata/xcschemes"; + if (mkdir(projectSharedSchemesPath)) { + QString target = project->first("QMAKE_ORIG_TARGET").toQString(); + + QFile defaultSchemeFile(xcodeSpecDir + "/default.xcscheme"); + QFile outputSchemeFile(projectSharedSchemesPath + Option::dir_sep + target + ".xcscheme"); + + if (defaultSchemeFile.open(QIODevice::ReadOnly) + && outputSchemeFile.open(QIODevice::WriteOnly | QIODevice::Text)) { + + QTextStream defaultSchemeStream(&defaultSchemeFile); + QString schemeData = defaultSchemeStream.readAll(); + + schemeData.replace("@QMAKE_ORIG_TARGET@", target); + schemeData.replace("@TARGET_PBX_KEY@", keyFor(pbx_dir + "QMAKE_PBX_TARGET")); + + QTextStream outputSchemeStream(&outputSchemeFile); + outputSchemeStream << schemeData; + + wroteCustomScheme = true; + } + } + + if (wroteCustomScheme) { + // Prevent Xcode from auto-generating schemes + QString workspaceSettingsFilename("WorkspaceSettings.xcsettings"); + QString workspaceSharedDataPath = pbx_dir + "/project.xcworkspace/xcshareddata"; + if (mkdir(workspaceSharedDataPath)) { + QFile::copy(xcodeSpecDir + Option::dir_sep + workspaceSettingsFilename, + workspaceSharedDataPath + Option::dir_sep + workspaceSettingsFilename); + } else { + wroteCustomScheme = false; + } + } + + if (!wroteCustomScheme) + warn_msg(WarnLogic, "Failed to generate schemes in '%s', " \ + "falling back to Xcode auto-generated schemes", qPrintable(projectSharedSchemesPath)); + } + qmake_setpwd(input_dir); return true; -- cgit v1.2.3 From 1480a9c22b330144e3655e0844ee3c586db54509 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 25 Feb 2015 12:11:23 +0100 Subject: write relative QT_INSTALL_CONFIGURATION also under windows amends 5b27d02c35. Change-Id: I5c8679ed746b81ca5a7f33f32c39a74ee1e03d5a Reviewed-by: Joerg Bornemann --- tools/configure/configureapp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 4c8adfaf30..015ba7e6a5 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -4088,7 +4088,7 @@ void Configure::generateQConfigCpp() << ";\n" << endl; if ((platform() != WINDOWS) && (platform() != WINDOWS_CE) && (platform() != WINDOWS_RT)) - tmpStream << "#define QT_CONFIGURE_SETTINGS_PATH \"" << QDir::cleanPath(dictionary["QT_INSTALL_SETTINGS"]) << "\"" << endl; + tmpStream << "#define QT_CONFIGURE_SETTINGS_PATH \"" << dictionary["QT_REL_INSTALL_SETTINGS"] << "\"" << endl; tmpStream << endl << "#ifdef QT_BUILD_QMAKE\n" -- cgit v1.2.3 From 6400e4bb10ad855bd62b019bf459b50aeac53468 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 5 Feb 2015 15:45:53 +0100 Subject: adjust configure's path output to relative paths amends 5b27d02c3 (literally - i forgot to push the squashed commit). Change-Id: I2c588d13d5c79f9d1e4cb1ce46c4637574377c6a Reviewed-by: Joerg Bornemann --- tools/configure/configureapp.cpp | 36 +++++++++++++++++++++++------------- tools/configure/configureapp.h | 2 ++ 2 files changed, 25 insertions(+), 13 deletions(-) diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 015ba7e6a5..ed4eb7e09a 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -3626,6 +3626,16 @@ void Configure::generateConfigfiles() } +QString Configure::formatConfigPath(const char *var) +{ + QString val = dictionary[var]; + if (QFileInfo(val).isRelative()) { + QString pfx = dictionary["QT_INSTALL_PREFIX"]; + val = (val == ".") ? pfx : QDir(pfx).absoluteFilePath(val); + } + return QDir::toNativeSeparators(val); +} + void Configure::displayConfig() { fstream sout; @@ -3767,19 +3777,19 @@ void Configure::displayConfig() sout << "Sources are in.............." << QDir::toNativeSeparators(sourcePath) << endl; sout << "Build is done in............" << QDir::toNativeSeparators(buildPath) << endl; sout << "Install prefix.............." << QDir::toNativeSeparators(dictionary["QT_INSTALL_PREFIX"]) << endl; - sout << "Headers installed to........" << QDir::toNativeSeparators(dictionary["QT_INSTALL_HEADERS"]) << endl; - sout << "Libraries installed to......" << QDir::toNativeSeparators(dictionary["QT_INSTALL_LIBS"]) << endl; - sout << "Arch-dep. data to..........." << QDir::toNativeSeparators(dictionary["QT_INSTALL_ARCHDATA"]) << endl; - sout << "Plugins installed to........" << QDir::toNativeSeparators(dictionary["QT_INSTALL_PLUGINS"]) << endl; - sout << "Library execs installed to.." << QDir::toNativeSeparators(dictionary["QT_INSTALL_LIBEXECS"]) << endl; - sout << "QML1 imports installed to..." << QDir::toNativeSeparators(dictionary["QT_INSTALL_IMPORTS"]) << endl; - sout << "QML2 imports installed to..." << QDir::toNativeSeparators(dictionary["QT_INSTALL_QML"]) << endl; - sout << "Binaries installed to......." << QDir::toNativeSeparators(dictionary["QT_INSTALL_BINS"]) << endl; - sout << "Arch-indep. data to........." << QDir::toNativeSeparators(dictionary["QT_INSTALL_DATA"]) << endl; - sout << "Docs installed to..........." << QDir::toNativeSeparators(dictionary["QT_INSTALL_DOCS"]) << endl; - sout << "Translations installed to..." << QDir::toNativeSeparators(dictionary["QT_INSTALL_TRANSLATIONS"]) << endl; - sout << "Examples installed to......." << QDir::toNativeSeparators(dictionary["QT_INSTALL_EXAMPLES"]) << endl; - sout << "Tests installed to.........." << QDir::toNativeSeparators(dictionary["QT_INSTALL_TESTS"]) << endl; + sout << "Headers installed to........" << formatConfigPath("QT_REL_INSTALL_HEADERS") << endl; + sout << "Libraries installed to......" << formatConfigPath("QT_REL_INSTALL_LIBS") << endl; + sout << "Arch-dep. data to..........." << formatConfigPath("QT_REL_INSTALL_ARCHDATA") << endl; + sout << "Plugins installed to........" << formatConfigPath("QT_REL_INSTALL_PLUGINS") << endl; + sout << "Library execs installed to.." << formatConfigPath("QT_REL_INSTALL_LIBEXECS") << endl; + sout << "QML1 imports installed to..." << formatConfigPath("QT_REL_INSTALL_IMPORTS") << endl; + sout << "QML2 imports installed to..." << formatConfigPath("QT_REL_INSTALL_QML") << endl; + sout << "Binaries installed to......." << formatConfigPath("QT_REL_INSTALL_BINS") << endl; + sout << "Arch-indep. data to........." << formatConfigPath("QT_REL_INSTALL_DATA") << endl; + sout << "Docs installed to..........." << formatConfigPath("QT_REL_INSTALL_DOCS") << endl; + sout << "Translations installed to..." << formatConfigPath("QT_REL_INSTALL_TRANSLATIONS") << endl; + sout << "Examples installed to......." << formatConfigPath("QT_REL_INSTALL_EXAMPLES") << endl; + sout << "Tests installed to.........." << formatConfigPath("QT_REL_INSTALL_TESTS") << endl; if (dictionary.contains("XQMAKESPEC") && dictionary["XQMAKESPEC"].startsWith(QLatin1String("wince"))) { sout << "Using c runtime detection..." << dictionary[ "CE_CRT" ] << endl; diff --git a/tools/configure/configureapp.h b/tools/configure/configureapp.h index 78fd956eda..e58a0feb2b 100644 --- a/tools/configure/configureapp.h +++ b/tools/configure/configureapp.h @@ -165,6 +165,8 @@ private: void desc(const char *option, const char *description, bool skipIndent = false, char fillChar = '.'); void desc(const char *mark_option, const char *mark, const char *option, const char *description, char fillChar = '.'); void applySpecSpecifics(); + + QString formatConfigPath(const char *var); }; class FileWriter : public QTextStream -- cgit v1.2.3 From 95d385466dc367532b3da5e4e38533b20288ac28 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 6 Feb 2015 18:00:57 +0100 Subject: centralize setup of shell-related variables in spec_post.prf it makes no sense to let every spec do that separately, as it's fixed by the generator+shell. putting it into a file which is loaded regardless of the spec also allows us to remove the hardcoded fallbacks from qmake. if somebody overrode the values in their spec for some weird reasons, they'll need to override spec_post.prf. shell-{unix,win32}.conf are now dummies and print warnings. Task-number: QTBUG-37269 Change-Id: I66c24fb4072ce4d63fdbfc57618daa2a48fa1d80 Reviewed-by: Jochen Seemann Reviewed-by: Joerg Bornemann --- mkspecs/android-g++/qmake.conf | 24 --------- mkspecs/common/linux.conf | 2 - mkspecs/common/shell-unix.conf | 15 +----- mkspecs/common/shell-win32.conf | 18 +------ mkspecs/common/unix.conf | 2 - mkspecs/common/wince/qmake.conf | 2 - mkspecs/common/winrt_winphone/qmake.conf | 2 - mkspecs/cygwin-g++/qmake.conf | 1 - mkspecs/features/spec_post.prf | 62 ++++++++++++++++++++++ mkspecs/hurd-g++/qmake.conf | 2 - mkspecs/unsupported/linux-host-g++/qmake.conf | 2 - mkspecs/unsupported/vxworks-ppc-dcc/qmake.conf | 2 - .../unsupported/vxworks-simpentium-dcc/qmake.conf | 2 - mkspecs/win32-g++/qmake.conf | 13 ----- mkspecs/win32-icc/qmake.conf | 2 - mkspecs/win32-msvc2005/qmake.conf | 1 - mkspecs/win32-msvc2008/qmake.conf | 1 - mkspecs/win32-msvc2010/qmake.conf | 1 - mkspecs/win32-msvc2012/qmake.conf | 1 - mkspecs/win32-msvc2013/qmake.conf | 1 - mkspecs/win32-msvc2015/qmake.conf | 1 - qmake/generators/unix/unixmake.cpp | 14 ----- qmake/generators/unix/unixmake2.cpp | 2 - qmake/generators/win32/mingw_make.cpp | 10 ---- qmake/generators/win32/msvc_nmake.cpp | 10 ---- qmake/generators/win32/winmakefile.cpp | 13 ----- 26 files changed, 64 insertions(+), 142 deletions(-) diff --git a/mkspecs/android-g++/qmake.conf b/mkspecs/android-g++/qmake.conf index e334686b49..2fb2f4cc20 100644 --- a/mkspecs/android-g++/qmake.conf +++ b/mkspecs/android-g++/qmake.conf @@ -10,30 +10,6 @@ include(../common/gcc-base-unix.conf) load(device_config) -# Passing in -win32 to qmake (from NQTC) causes this condition to pass, however -# qmake complains that -win32 is deprecated; should find another way, Q_OS_WIN -# should really be all QMAKE_HOST.os needs to depend on? -contains(QMAKE_HOST.os,Windows) { - # Not having sh.exe in your path causes this condition to pass - # To build Android Qt on Windows, this block must not be evaluated. - isEmpty(QMAKE_SH) { - # Override values from previously loaded shell-unix.conf - # (via unix.conf, via linux.conf). - include(../common/shell-win32.conf) - QMAKE_DEL_TREE = rmdir /s /q - QMAKE_INSTALL_FILE = copy /y - QMAKE_INSTALL_PROGRAM = copy /y - } else { - MINGW_IN_SHELL = 1 - QMAKE_DIR_SEP = / - QMAKE_DIRLIST_SEP = : - # Because install's ability to set permissions is not relevant on Windows, - # and git's msys does not provide it to start with. - QMAKE_INSTALL_FILE = cp -f - QMAKE_INSTALL_PROGRAM = cp -f - } -} - NDK_ROOT = $$(ANDROID_NDK_ROOT) !exists($$NDK_ROOT) { NDK_ROOT = $$DEFAULT_ANDROID_NDK_ROOT diff --git a/mkspecs/common/linux.conf b/mkspecs/common/linux.conf index e10ab71cd6..8d6fb6fe17 100644 --- a/mkspecs/common/linux.conf +++ b/mkspecs/common/linux.conf @@ -51,7 +51,5 @@ QMAKE_RANLIB = QMAKE_STRIP = strip QMAKE_STRIPFLAGS_LIB += --strip-unneeded -QMAKE_INSTALL_FILE = install -m 644 -p -QMAKE_INSTALL_PROGRAM = install -m 755 -p include(unix.conf) diff --git a/mkspecs/common/shell-unix.conf b/mkspecs/common/shell-unix.conf index a533e77cb5..2ab932f7b8 100644 --- a/mkspecs/common/shell-unix.conf +++ b/mkspecs/common/shell-unix.conf @@ -1,14 +1 @@ -QMAKE_TAR = tar -cf -QMAKE_GZIP = gzip -9f - -QMAKE_COPY = cp -f -QMAKE_COPY_FILE = $$QMAKE_COPY -QMAKE_COPY_DIR = $$QMAKE_COPY -R -QMAKE_MOVE = mv -f -QMAKE_DEL_FILE = rm -f -QMAKE_DEL_DIR = rmdir -QMAKE_CHK_EXISTS = test -e %1 || -QMAKE_CHK_DIR_EXISTS = test -d # legacy -QMAKE_MKDIR = mkdir -p # legacy -QMAKE_MKDIR_CMD = test -d %1 || mkdir -p %1 -QMAKE_STREAM_EDITOR = sed +warning("shell-unix.conf is deprecated and has no effect.") diff --git a/mkspecs/common/shell-win32.conf b/mkspecs/common/shell-win32.conf index 1da8057c43..c6f3514697 100644 --- a/mkspecs/common/shell-win32.conf +++ b/mkspecs/common/shell-win32.conf @@ -1,17 +1 @@ -QMAKE_ZIP = zip -r -9 - -QMAKE_COPY = copy /y -QMAKE_COPY_DIR = xcopy /s /q /y /i -QMAKE_MOVE = move -QMAKE_DEL_FILE = del -QMAKE_DEL_DIR = rmdir -QMAKE_CHK_EXISTS = if not exist %1 -QMAKE_CHK_DIR_EXISTS = if not exist # legacy -QMAKE_MKDIR = mkdir # legacy -QMAKE_MKDIR_CMD = if not exist %1 mkdir %1 & if not exist %1 exit 1 -# Ugly hack to support cross-building for unix (android). -QMAKE_SYMBOLIC_LINK = $$QMAKE_COPY -QMAKE_LN_SHLIB = $$QMAKE_SYMBOLIC_LINK -# xcopy copies the contained files if source is a directory. Deal with it. -CONFIG += copy_dir_files -QMAKE_STREAM_EDITOR = $(QMAKE) -install sed +warning("shell-win32.conf is deprecated and has no effect.") diff --git a/mkspecs/common/unix.conf b/mkspecs/common/unix.conf index c0deafd141..2146b62f17 100644 --- a/mkspecs/common/unix.conf +++ b/mkspecs/common/unix.conf @@ -14,5 +14,3 @@ QMAKE_YACC_SOURCE = $base.tab.c QMAKE_PREFIX_SHLIB = lib QMAKE_PREFIX_STATICLIB = lib QMAKE_EXTENSION_STATICLIB = a - -include(shell-unix.conf) diff --git a/mkspecs/common/wince/qmake.conf b/mkspecs/common/wince/qmake.conf index 6e2e24dbd0..434e063de8 100644 --- a/mkspecs/common/wince/qmake.conf +++ b/mkspecs/common/wince/qmake.conf @@ -73,8 +73,6 @@ QMAKE_IDL = midl QMAKE_LIB = lib QMAKE_RC = rc -include(../shell-win32.conf) - VCPROJ_EXTENSION = .vcproj VCSOLUTION_EXTENSION = .sln VCPROJ_KEYWORD = Qt4VSv1.0 diff --git a/mkspecs/common/winrt_winphone/qmake.conf b/mkspecs/common/winrt_winphone/qmake.conf index 70bd0a3945..d71915408d 100644 --- a/mkspecs/common/winrt_winphone/qmake.conf +++ b/mkspecs/common/winrt_winphone/qmake.conf @@ -85,8 +85,6 @@ QMAKE_IDL = midl QMAKE_LIB = lib /NOLOGO QMAKE_RC = rc -include(../shell-win32.conf) - VCPROJ_EXTENSION = .vcxproj VCSOLUTION_EXTENSION = .sln VCPROJ_KEYWORD = Qt4VSv1.0 diff --git a/mkspecs/cygwin-g++/qmake.conf b/mkspecs/cygwin-g++/qmake.conf index 06135beb30..caed4133b1 100644 --- a/mkspecs/cygwin-g++/qmake.conf +++ b/mkspecs/cygwin-g++/qmake.conf @@ -73,5 +73,4 @@ QMAKE_OBJCOPY = objcopy QMAKE_NM = nm -P QMAKE_RANLIB = -include(../common/shell-unix.conf) load(qt_config) diff --git a/mkspecs/features/spec_post.prf b/mkspecs/features/spec_post.prf index b4f9ca47ae..c9578773fe 100644 --- a/mkspecs/features/spec_post.prf +++ b/mkspecs/features/spec_post.prf @@ -54,3 +54,65 @@ isEmpty(QMAKE_COMPILER) { warning("qmake spec does not announce the compiler family. Guessed $${QMAKE_COMPILER}.") } CONFIG += $$QMAKE_COMPILER + +equals(MAKEFILE_GENERATOR, MSBUILD) \ +|equals(MAKEFILE_GENERATOR, MSVC.NET) \ +|isEmpty(QMAKE_SH) { + QMAKE_ZIP = zip -r -9 + + QMAKE_COPY = copy /y + QMAKE_COPY_FILE = $$QMAKE_COPY + QMAKE_COPY_DIR = xcopy /s /q /y /i + # xcopy copies the contained files if source is a directory. Deal with it. + CONFIG += copy_dir_files + QMAKE_MOVE = move + QMAKE_DEL_FILE = del + QMAKE_DEL_DIR = rmdir + QMAKE_DEL_TREE = rmdir /s /q + QMAKE_CHK_EXISTS = if not exist %1 + QMAKE_CHK_DIR_EXISTS = if not exist # legacy + QMAKE_MKDIR = mkdir # legacy + QMAKE_MKDIR_CMD = if not exist %1 mkdir %1 & if not exist %1 exit 1 + QMAKE_STREAM_EDITOR = $(QMAKE) -install sed + QMAKE_INSTALL_FILE = copy /y + QMAKE_INSTALL_PROGRAM = copy /y +} else { + QMAKE_TAR = tar -cf + QMAKE_GZIP = gzip -9f + + QMAKE_COPY = cp -f + QMAKE_COPY_FILE = $$QMAKE_COPY + QMAKE_COPY_DIR = $$QMAKE_COPY -R + QMAKE_MOVE = mv -f + QMAKE_DEL_FILE = rm -f + QMAKE_DEL_DIR = rmdir + QMAKE_DEL_TREE = rm -rf + QMAKE_CHK_EXISTS = test -e %1 || + QMAKE_CHK_DIR_EXISTS = test -d # legacy + QMAKE_MKDIR = mkdir -p # legacy + QMAKE_MKDIR_CMD = test -d %1 || mkdir -p %1 + QMAKE_STREAM_EDITOR = sed + + equals(QMAKE_HOST.os, Windows) { + MINGW_IN_SHELL = 1 # legacy + # Override built-ins. + QMAKE_DIR_SEP = / + QMAKE_DIRLIST_SEP = : + # Because install's ability to set permissions is not relevant on Windows, + # and git's msys does not provide it to start with. + QMAKE_INSTALL_FILE = cp -f + QMAKE_INSTALL_PROGRAM = cp -f + } else { + QMAKE_INSTALL_FILE = install -m 644 -p + QMAKE_INSTALL_PROGRAM = install -m 755 -p + } +} +QMAKE_INSTALL_DIR = $$QMAKE_COPY_DIR +equals(QMAKE_HOST.os, Windows) { + # Ugly (and broken for relative paths) hack to support cross-building for Unix. + QMAKE_SYMBOLIC_LINK = $$QMAKE_COPY + QMAKE_LN_SHLIB = $$QMAKE_SYMBOLIC_LINK +} else { + QMAKE_SYMBOLIC_LINK = ln -f -s + QMAKE_LN_SHLIB = ln -s +} diff --git a/mkspecs/hurd-g++/qmake.conf b/mkspecs/hurd-g++/qmake.conf index d53b49ced2..e7e4e3a82d 100644 --- a/mkspecs/hurd-g++/qmake.conf +++ b/mkspecs/hurd-g++/qmake.conf @@ -45,8 +45,6 @@ QMAKE_RANLIB = QMAKE_STRIP = strip QMAKE_STRIPFLAGS_LIB += --strip-unneeded -QMAKE_INSTALL_FILE = install -m 644 -p -QMAKE_INSTALL_PROGRAM = install -m 755 -p include(../common/unix.conf) include(../common/gcc-base-unix.conf) diff --git a/mkspecs/unsupported/linux-host-g++/qmake.conf b/mkspecs/unsupported/linux-host-g++/qmake.conf index 3dc490d6dd..1523126eaa 100644 --- a/mkspecs/unsupported/linux-host-g++/qmake.conf +++ b/mkspecs/unsupported/linux-host-g++/qmake.conf @@ -109,8 +109,6 @@ QMAKE_RANLIB = QMAKE_STRIP = host-strip QMAKE_STRIPFLAGS_LIB += --strip-unneeded -QMAKE_INSTALL_FILE = install -m 644 -p -QMAKE_INSTALL_PROGRAM = install -m 755 -p include(../../common/unix.conf) load(qt_config) diff --git a/mkspecs/unsupported/vxworks-ppc-dcc/qmake.conf b/mkspecs/unsupported/vxworks-ppc-dcc/qmake.conf index 814b844131..a4cf23df9c 100644 --- a/mkspecs/unsupported/vxworks-ppc-dcc/qmake.conf +++ b/mkspecs/unsupported/vxworks-ppc-dcc/qmake.conf @@ -87,8 +87,6 @@ QMAKE_RANLIB = QMAKE_STRIP = strip QMAKE_STRIPFLAGS_LIB += --strip-unneeded -QMAKE_INSTALL_FILE = install -m 644 -p -QMAKE_INSTALL_PROGRAM = install -m 755 -p include(../../common/unix.conf) load(qt_config) diff --git a/mkspecs/unsupported/vxworks-simpentium-dcc/qmake.conf b/mkspecs/unsupported/vxworks-simpentium-dcc/qmake.conf index c362d098db..49f0c21d4a 100644 --- a/mkspecs/unsupported/vxworks-simpentium-dcc/qmake.conf +++ b/mkspecs/unsupported/vxworks-simpentium-dcc/qmake.conf @@ -86,8 +86,6 @@ QMAKE_RANLIB = QMAKE_STRIP = strip QMAKE_STRIPFLAGS_LIB += --strip-unneeded -QMAKE_INSTALL_FILE = install -m 644 -p -QMAKE_INSTALL_PROGRAM = install -m 755 -p include(../../common/unix.conf) load(qt_config) diff --git a/mkspecs/win32-g++/qmake.conf b/mkspecs/win32-g++/qmake.conf index 9f0188be80..c6ff808a99 100644 --- a/mkspecs/win32-g++/qmake.conf +++ b/mkspecs/win32-g++/qmake.conf @@ -93,19 +93,6 @@ QMAKE_LIBS_OPENGL_ES2_DEBUG = -llibEGLd -llibGLESv2d -lgdi32 -luser32 QMAKE_LIBS_COMPAT = -ladvapi32 -lshell32 -lcomdlg32 -luser32 -lgdi32 -lws2_32 QMAKE_LIBS_QT_ENTRY = -lmingw32 -lqtmain -!isEmpty(QMAKE_SH) { - MINGW_IN_SHELL = 1 - QMAKE_DIR_SEP = / - QMAKE_DIRLIST_SEP = : - include(../common/shell-unix.conf) - # Because install's ability to set permissions is not relevant on Windows, - # and git's msys does not provide it to start with. - QMAKE_INSTALL_FILE = cp -f - QMAKE_INSTALL_PROGRAM = cp -f -} else { - include(../common/shell-win32.conf) -} - QMAKE_IDL = midl QMAKE_LIB = $${CROSS_COMPILE}ar -ru QMAKE_RC = $${CROSS_COMPILE}windres diff --git a/mkspecs/win32-icc/qmake.conf b/mkspecs/win32-icc/qmake.conf index d326cdeee3..2ec0d84918 100644 --- a/mkspecs/win32-icc/qmake.conf +++ b/mkspecs/win32-icc/qmake.conf @@ -79,7 +79,5 @@ QMAKE_IDL = midl QMAKE_LIB = xilib /NOLOGO QMAKE_RC = rc -include(../common/shell-win32.conf) - DSP_EXTENSION = .dsp load(qt_config) diff --git a/mkspecs/win32-msvc2005/qmake.conf b/mkspecs/win32-msvc2005/qmake.conf index ca901effd3..458f37cc04 100644 --- a/mkspecs/win32-msvc2005/qmake.conf +++ b/mkspecs/win32-msvc2005/qmake.conf @@ -7,5 +7,4 @@ MSC_VER = 1400 MSVC_VER = 8.0 include(../common/msvc-desktop.conf) -include(../common/shell-win32.conf) load(qt_config) diff --git a/mkspecs/win32-msvc2008/qmake.conf b/mkspecs/win32-msvc2008/qmake.conf index 1a04c9952b..d1382ff2d4 100644 --- a/mkspecs/win32-msvc2008/qmake.conf +++ b/mkspecs/win32-msvc2008/qmake.conf @@ -7,5 +7,4 @@ MSC_VER = 1500 MSVC_VER = 9.0 include(../common/msvc-desktop.conf) -include(../common/shell-win32.conf) load(qt_config) diff --git a/mkspecs/win32-msvc2010/qmake.conf b/mkspecs/win32-msvc2010/qmake.conf index 8160001a4b..3ad9d478ee 100644 --- a/mkspecs/win32-msvc2010/qmake.conf +++ b/mkspecs/win32-msvc2010/qmake.conf @@ -7,5 +7,4 @@ MSC_VER = 1600 MSVC_VER = 10.0 include(../common/msvc-desktop.conf) -include(../common/shell-win32.conf) load(qt_config) diff --git a/mkspecs/win32-msvc2012/qmake.conf b/mkspecs/win32-msvc2012/qmake.conf index 57161071c8..3d9c5864af 100644 --- a/mkspecs/win32-msvc2012/qmake.conf +++ b/mkspecs/win32-msvc2012/qmake.conf @@ -7,5 +7,4 @@ MSC_VER = 1700 MSVC_VER = 11.0 include(../common/msvc-desktop.conf) -include(../common/shell-win32.conf) load(qt_config) diff --git a/mkspecs/win32-msvc2013/qmake.conf b/mkspecs/win32-msvc2013/qmake.conf index ece04203ea..34108b2c32 100644 --- a/mkspecs/win32-msvc2013/qmake.conf +++ b/mkspecs/win32-msvc2013/qmake.conf @@ -7,5 +7,4 @@ MSC_VER = 1800 MSVC_VER = 12.0 include(../common/msvc-desktop.conf) -include(../common/shell-win32.conf) load(qt_config) diff --git a/mkspecs/win32-msvc2015/qmake.conf b/mkspecs/win32-msvc2015/qmake.conf index 617adb681c..ea654d4296 100644 --- a/mkspecs/win32-msvc2015/qmake.conf +++ b/mkspecs/win32-msvc2015/qmake.conf @@ -7,5 +7,4 @@ MSC_VER = 1900 MSVC_VER = 14.0 include(../common/msvc-desktop.conf) -include(../common/shell-win32.conf) load(qt_config) diff --git a/qmake/generators/unix/unixmake.cpp b/qmake/generators/unix/unixmake.cpp index 3a76d898ed..efea807209 100644 --- a/qmake/generators/unix/unixmake.cpp +++ b/qmake/generators/unix/unixmake.cpp @@ -58,22 +58,8 @@ UnixMakefileGenerator::init() project->values("ICON") = project->values("RC_FILE"); if(project->isEmpty("QMAKE_EXTENSION_PLUGIN")) project->values("QMAKE_EXTENSION_PLUGIN").append(project->first("QMAKE_EXTENSION_SHLIB")); - if(project->isEmpty("QMAKE_COPY_FILE")) - project->values("QMAKE_COPY_FILE").append("$(COPY)"); - if(project->isEmpty("QMAKE_STREAM_EDITOR")) - project->values("QMAKE_STREAM_EDITOR").append("sed"); - if(project->isEmpty("QMAKE_COPY_DIR")) - project->values("QMAKE_COPY_DIR").append("$(COPY) -R"); - if(project->isEmpty("QMAKE_INSTALL_FILE")) - project->values("QMAKE_INSTALL_FILE").append("$(COPY_FILE)"); - if(project->isEmpty("QMAKE_INSTALL_DIR")) - project->values("QMAKE_INSTALL_DIR").append("$(COPY_DIR)"); - if(project->isEmpty("QMAKE_INSTALL_PROGRAM")) - project->values("QMAKE_INSTALL_PROGRAM").append("$(COPY_FILE)"); if(project->isEmpty("QMAKE_LIBTOOL")) project->values("QMAKE_LIBTOOL").append("libtool --silent"); - if(project->isEmpty("QMAKE_SYMBOLIC_LINK")) - project->values("QMAKE_SYMBOLIC_LINK").append("ln -f -s"); project->values("QMAKE_ORIG_TARGET") = project->values("TARGET"); diff --git a/qmake/generators/unix/unixmake2.cpp b/qmake/generators/unix/unixmake2.cpp index c14395ae27..9d666509fd 100644 --- a/qmake/generators/unix/unixmake2.cpp +++ b/qmake/generators/unix/unixmake2.cpp @@ -1298,8 +1298,6 @@ void UnixMakefileGenerator::init2() else project->values("TARGET") = project->values("TARGET_x.y.z"); } - if(project->isEmpty("QMAKE_LN_SHLIB")) - project->values("QMAKE_LN_SHLIB").append("ln -s"); if (!project->values("QMAKE_LFLAGS_SONAME").isEmpty()) { ProString soname; if(project->isActiveConfig("plugin")) { diff --git a/qmake/generators/win32/mingw_make.cpp b/qmake/generators/win32/mingw_make.cpp index af5e62330e..c19e17bc0e 100644 --- a/qmake/generators/win32/mingw_make.cpp +++ b/qmake/generators/win32/mingw_make.cpp @@ -232,16 +232,6 @@ void MingwMakefileGenerator::init() project->values("QMAKE_LIB_FLAG").append("1"); else if(project->first("TEMPLATE") == "subdirs") { MakefileGenerator::init(); - if(project->isEmpty("QMAKE_COPY_FILE")) - project->values("QMAKE_COPY_FILE").append("$(COPY)"); - if(project->isEmpty("QMAKE_COPY_DIR")) - project->values("QMAKE_COPY_DIR").append("xcopy /s /q /y /i"); - if(project->isEmpty("QMAKE_INSTALL_FILE")) - project->values("QMAKE_INSTALL_FILE").append("$(COPY_FILE)"); - if(project->isEmpty("QMAKE_INSTALL_PROGRAM")) - project->values("QMAKE_INSTALL_PROGRAM").append("$(COPY_FILE)"); - if(project->isEmpty("QMAKE_INSTALL_DIR")) - project->values("QMAKE_INSTALL_DIR").append("$(COPY_DIR)"); if(project->values("MAKEFILE").isEmpty()) project->values("MAKEFILE").append("Makefile"); return; diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp index ae888cb96d..c719aa4cbf 100644 --- a/qmake/generators/win32/msvc_nmake.cpp +++ b/qmake/generators/win32/msvc_nmake.cpp @@ -340,16 +340,6 @@ void NmakeMakefileGenerator::init() MakefileGenerator::init(); if(project->values("MAKEFILE").isEmpty()) project->values("MAKEFILE").append("Makefile"); - if(project->isEmpty("QMAKE_COPY_FILE")) - project->values("QMAKE_COPY_FILE").append("$(COPY)"); - if(project->isEmpty("QMAKE_COPY_DIR")) - project->values("QMAKE_COPY_DIR").append("xcopy /s /q /y /i"); - if(project->isEmpty("QMAKE_INSTALL_FILE")) - project->values("QMAKE_INSTALL_FILE").append("$(COPY_FILE)"); - if(project->isEmpty("QMAKE_INSTALL_PROGRAM")) - project->values("QMAKE_INSTALL_PROGRAM").append("$(COPY_FILE)"); - if(project->isEmpty("QMAKE_INSTALL_DIR")) - project->values("QMAKE_INSTALL_DIR").append("$(COPY_DIR)"); return; } diff --git a/qmake/generators/win32/winmakefile.cpp b/qmake/generators/win32/winmakefile.cpp index ad6a19e5df..6ea129f82c 100644 --- a/qmake/generators/win32/winmakefile.cpp +++ b/qmake/generators/win32/winmakefile.cpp @@ -280,19 +280,6 @@ void Win32MakefileGenerator::processVars() && !project->values("VER_MAJ").isEmpty()) project->values("TARGET_VERSION_EXT").append(project->first("VER_MAJ")); - if(project->isEmpty("QMAKE_COPY_FILE")) - project->values("QMAKE_COPY_FILE").append("$(COPY)"); - if(project->isEmpty("QMAKE_COPY_DIR")) - project->values("QMAKE_COPY_DIR").append("xcopy /s /q /y /i"); - if (project->isEmpty("QMAKE_STREAM_EDITOR")) - project->values("QMAKE_STREAM_EDITOR").append("$(QMAKE) -install sed"); - if(project->isEmpty("QMAKE_INSTALL_FILE")) - project->values("QMAKE_INSTALL_FILE").append("$(COPY_FILE)"); - if(project->isEmpty("QMAKE_INSTALL_PROGRAM")) - project->values("QMAKE_INSTALL_PROGRAM").append("$(COPY_FILE)"); - if(project->isEmpty("QMAKE_INSTALL_DIR")) - project->values("QMAKE_INSTALL_DIR").append("$(COPY_DIR)"); - fixTargetExt(); processRcFileVar(); -- cgit v1.2.3 From d7401c32c5eb514da639753d939fafabd9d3492f Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Fri, 6 Mar 2015 14:17:57 +0100 Subject: Avoid crashing when there is no QWindowsIntegration anymore When destroying the QWindowsIntegration, the global instance is set to null in the destructor. This is followed by a lot of additional steps when destroying the members. Some of that cleanup calls to staticOpenGLContext() which was not handling the case of the integration global instance being null. Change-Id: Ib74faf491d4c81635934547968ec91e9dceec6e7 Reviewed-by: Friedemann Kleint --- src/plugins/platforms/windows/qwindowsintegration.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 62df7918c1..9fd18a1ef4 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -420,7 +420,10 @@ QOpenGLContext::OpenGLModuleType QWindowsIntegration::openGLModuleType() QWindowsStaticOpenGLContext *QWindowsIntegration::staticOpenGLContext() { - QWindowsIntegrationPrivate *d = QWindowsIntegration::instance()->d.data(); + QWindowsIntegration *integration = QWindowsIntegration::instance(); + if (!integration) + return 0; + QWindowsIntegrationPrivate *d = integration->d.data(); if (d->m_staticOpenGLContext.isNull()) d->m_staticOpenGLContext = QSharedPointer(QWindowsStaticOpenGLContext::create()); return d->m_staticOpenGLContext.data(); -- cgit v1.2.3 From 51ada7734ad780178ecced11e0dff454dfc2e5f2 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Mon, 2 Mar 2015 10:48:21 +0100 Subject: xcb: do not create a dummy QScreen when there are no outputs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Whenever a QWindow is associated with a QScreen, the screen is expected to be a real working one, so that rendering continues to be possible. This partially reverts 52f5e50f11a3ba82e32dc2efc656e4021a3fa4f5 [ChangeLog][QPA][Xcb] If all QScreens (xcb outputs) are disconnected while an application is running, QGuiApplication::primaryScreen() will return null until a screen is connected again. Task-number: QTBUG-40174 Task-number: QTBUG-42985 Change-Id: Id1b29dd70eaf3f2e7fd477516ce7e2bf24e095f6 Reviewed-by: Laszlo Agocs Reviewed-by: Jørgen Lind --- src/gui/kernel/qguiapplication.cpp | 7 ++++++- src/plugins/platforms/xcb/qxcbconnection.cpp | 15 +++++---------- src/widgets/kernel/qdesktopwidget.qdoc | 5 +++++ 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 243ef70efc..8c49b3a2b5 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -873,9 +873,14 @@ QWindowList QGuiApplication::topLevelWindows() } /*! - Returns the primary (or default) screen of the application. + Returns the primary (or default) screen of the application, or null if there is none This will be the screen where QWindows are initially shown, unless otherwise specified. + + On some platforms, it may be null when there are actually no screens connected. + It is not possible to start a new QGuiApplication while there are no screens. + Applications which were running at the time the primary screen was removed + will stop rendering graphics until one or more screens are restored. */ QScreen *QGuiApplication::primaryScreen() { diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 9247da814d..da973b5313 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -215,16 +215,6 @@ void QXcbConnection::updateScreens() } free(primary); } - // If there's no randr extension, or there was some error above, or the screen - // doesn't have outputs for some other reason (e.g. on VNC or ssh -X), just assume there is one screen. - if (connectedOutputCount == 0) { - qCDebug(lcQpaScreen, "found a screen with zero outputs"); - QXcbScreen *screen = findOrCreateScreen(newScreens, xcbScreenNumber, xcbScreen); - siblings << screen; - activeScreens << screen; - if (!primaryScreen) - primaryScreen = screen; - } foreach (QPlatformScreen* s, siblings) ((QXcbScreen*)s)->setVirtualSiblings(siblings); xcb_screen_next(&it); @@ -282,6 +272,11 @@ void QXcbConnection::updateScreens() if (!m_screens.isEmpty()) qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name(); + else + // QTBUG-40174, QTBUG-42985: If there are no outputs, then there must be + // no QScreen instances; a Qt application can survive this situation, and + // start rendering again later when there is a screen again. + qCDebug(lcQpaScreen) << "xcb connection has no outputs"; } QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, const char *displayName) diff --git a/src/widgets/kernel/qdesktopwidget.qdoc b/src/widgets/kernel/qdesktopwidget.qdoc index 822bb47a15..6ce312dc2f 100644 --- a/src/widgets/kernel/qdesktopwidget.qdoc +++ b/src/widgets/kernel/qdesktopwidget.qdoc @@ -238,6 +238,11 @@ \property QDesktopWidget::screenCount \brief the number of screens currently available on the system. + Note that on some platforms, screenCount will be zero if there are actually + no screens connected. Applications which were running at the time the + screenCount went to zero will stop rendering graphics until one or more + screens are restored. + \since 4.6 */ -- cgit v1.2.3 From 483328a956bfb9c8908ebe36e3695fab44384820 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Fri, 6 Mar 2015 09:29:56 +0100 Subject: docs: QPlatformWindow::screen() and QWindow::screen() can return null After change f4b8697c40bd476ef6bf83418e144adce7c7d4a3, it is normal on X11 to have a null screen when all outputs have been disconnected or turned off. Change-Id: I97eeefd86d97701be50f0757fe5c53ca36d79aaa Reviewed-by: Harri Porten Reviewed-by: Laszlo Agocs --- src/gui/kernel/qplatformwindow.cpp | 3 ++- src/gui/kernel/qwindow.cpp | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp index d8e4e7736e..114fcf8062 100644 --- a/src/gui/kernel/qplatformwindow.cpp +++ b/src/gui/kernel/qplatformwindow.cpp @@ -79,7 +79,8 @@ QPlatformWindow *QPlatformWindow::parent() const } /*! - Returns the platform screen handle corresponding to this platform window. + Returns the platform screen handle corresponding to this platform window, + or null if the window is not associated with a screen. */ QPlatformScreen *QPlatformWindow::screen() const { diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 33f0409216..06db4e81fa 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -1678,7 +1678,7 @@ bool QWindow::setMouseGrabEnabled(bool grab) } /*! - Returns the screen on which the window is shown. + Returns the screen on which the window is shown, or null if there is none. For child windows, this returns the screen of the corresponding top level window. -- cgit v1.2.3 From 7c3cfdbcb7d5506138efa9f06b1424f7a879fad6 Mon Sep 17 00:00:00 2001 From: Katja Marttila Date: Fri, 27 Feb 2015 15:01:54 +0200 Subject: Add getter for QSizePolicy to SpacerItem MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change allows to change width and height with changeSize() method without changing size policy. Task-number: QTBUG-38518 Change-Id: I3eabb5fbfd9792c57c0a533ce14ec99b64603631 Reviewed-by: Shawn Rutledge Reviewed-by: Jan Arve Sæther --- src/widgets/kernel/qlayoutitem.cpp | 8 ++++++++ src/widgets/kernel/qlayoutitem.h | 1 + 2 files changed, 9 insertions(+) diff --git a/src/widgets/kernel/qlayoutitem.cpp b/src/widgets/kernel/qlayoutitem.cpp index f195ac81c9..a79d9bb2c6 100644 --- a/src/widgets/kernel/qlayoutitem.cpp +++ b/src/widgets/kernel/qlayoutitem.cpp @@ -340,6 +340,14 @@ QSpacerItem * QSpacerItem::spacerItem() return this; } +/*! + Returns the size policy of this item. +*/ +QSizePolicy QSpacerItem::sizePolicy() const +{ + return sizeP; +} + /*! If this item is a QWidget, it is returned as a QWidget; otherwise 0 is returned. This function provides type-safe casting. diff --git a/src/widgets/kernel/qlayoutitem.h b/src/widgets/kernel/qlayoutitem.h index 7de94852e6..eaa129a85b 100644 --- a/src/widgets/kernel/qlayoutitem.h +++ b/src/widgets/kernel/qlayoutitem.h @@ -102,6 +102,7 @@ public: void setGeometry(const QRect&); QRect geometry() const; QSpacerItem *spacerItem(); + QSizePolicy sizePolicy() const; private: int width; -- cgit v1.2.3 From 8f1eb525250248966fd7edaea3567fe508994fe3 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 6 Mar 2015 15:45:26 +0100 Subject: Windows: Fix build of qwindowsfontdatabase.cpp with MinGW 4.9.2/-Werror. Disable warning: qwindowsfontdatabase.cpp: In member function 'virtual QFontEngine* QWindowsFontDatabase::fontEngine(const QByteArray&, qreal, QFont::HintingPreference)': qwindowsfontdatabase.cpp:1111:74: error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing] Change-Id: Ifce69db7d1f3b78d52e5b4e01db8e7bbfb62b439 Reviewed-by: Konstantin Ritt --- src/plugins/platforms/windows/qwindowsfontdatabase.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp index 287ee4c46e..9e037723fe 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp @@ -1104,11 +1104,18 @@ QFontEngine *QWindowsFontDatabase::fontEngine(const QByteArray &fontData, qreal GUID guid; CoCreateGuid(&guid); +#ifdef Q_CC_GNU +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wstrict-aliasing" +#endif QString uniqueFamilyName = QLatin1Char('f') + QString::number(guid.Data1, 36) + QLatin1Char('-') + QString::number(guid.Data2, 36) + QLatin1Char('-') + QString::number(guid.Data3, 36) + QLatin1Char('-') + QString::number(*reinterpret_cast(guid.Data4), 36); +#ifdef Q_CC_GNU +# pragma GCC diagnostic pop +#endif QString actualFontName = font.changeFamilyName(uniqueFamilyName); if (actualFontName.isEmpty()) { -- cgit v1.2.3 From 9a3754c570b71f610c1ee467bcfca83de3a55a4b Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Tue, 17 Feb 2015 11:36:36 +0400 Subject: [QCoreTextFontDatabase] Micro optimization With use of pre-allocated buffer, there is always a good chance to get the requested data with a single call. Change-Id: I8fed718e15970ab345ce96a9405578947b59f311 Reviewed-by: Lars Knoll --- .../fontdatabases/mac/qcoretextfontdatabase.mm | 32 +++++++++++++--------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index a022587e11..f48ea1b833 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -270,23 +270,29 @@ static void getFontDescription(CTFontDescriptorRef font, FontDescription *fd) fd->fixedPitch = false; if (QCFType tempFont = CTFontCreateWithFontDescriptor(font, 0.0, 0)) { - uint length = 0; uint tag = MAKE_TAG('O', 'S', '/', '2'); CTFontRef tempFontRef = tempFont; void *userData = reinterpret_cast(&tempFontRef); - if (QCoreTextFontEngine::ct_getSfntTable(userData, tag, 0, &length)) { - QVarLengthArray os2Table(length); - if (length >= 86 && QCoreTextFontEngine::ct_getSfntTable(userData, tag, os2Table.data(), &length)) { - quint32 unicodeRange[4] = { - qFromBigEndian(os2Table.data() + 42), - qFromBigEndian(os2Table.data() + 46), - qFromBigEndian(os2Table.data() + 50), - qFromBigEndian(os2Table.data() + 54) - }; - quint32 codePageRange[2] = { qFromBigEndian(os2Table.data() + 78), - qFromBigEndian(os2Table.data() + 82) }; - fd->writingSystems = QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRange, codePageRange); + uint length = 128; + QVarLengthArray os2Table(length); + if (QCoreTextFontEngine::ct_getSfntTable(userData, tag, os2Table.data(), &length) && length >= 86) { + if (length > os2Table.length()) { + os2Table.resize(length); + if (!QCoreTextFontEngine::ct_getSfntTable(userData, tag, os2Table.data(), &length)) + Q_UNREACHABLE(); + Q_ASSERT(length >= 86); } + quint32 unicodeRange[4] = { + qFromBigEndian(os2Table.data() + 42), + qFromBigEndian(os2Table.data() + 46), + qFromBigEndian(os2Table.data() + 50), + qFromBigEndian(os2Table.data() + 54) + }; + quint32 codePageRange[2] = { + qFromBigEndian(os2Table.data() + 78), + qFromBigEndian(os2Table.data() + 82) + }; + fd->writingSystems = QPlatformFontDatabase::writingSystemsFromTrueTypeBits(unicodeRange, codePageRange); } } -- cgit v1.2.3 From c4aea1ea20962bd12695147c8546558b02ad859c Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Sun, 15 Feb 2015 21:56:29 +0400 Subject: [QCoreTextFontDatabase] Minor clean-up Change-Id: I4579d4c4a516cc458aa7ddd8aca385b4ae21879b Reviewed-by: Lars Knoll --- src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm | 4 ---- src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h | 3 --- 2 files changed, 7 deletions(-) diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm index f48ea1b833..99f54237bc 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm @@ -348,11 +348,7 @@ void QCoreTextFontDatabase::populateFromDescriptor(CTFontDescriptorRef font) { FontDescription fd; getFontDescription(font, &fd); - populateFromFontDescription(font, fd); -} -void QCoreTextFontDatabase::populateFromFontDescription(CTFontDescriptorRef font, const FontDescription &fd) -{ CFRetain(font); QPlatformFontDatabase::registerFont(fd.familyName, fd.styleName, fd.foundryName, fd.weight, fd.style, fd.stretch, true /* antialiased */, true /* scalable */, diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h index 42c8701a71..822d6f9b9c 100644 --- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h +++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase_p.h @@ -70,8 +70,6 @@ Q_DECLARE_METATYPE(ATSFontContainerRef); QT_BEGIN_NAMESPACE -struct FontDescription; - class QCoreTextFontDatabase : public QPlatformFontDatabase { public: @@ -96,7 +94,6 @@ public: private: void populateFromDescriptor(CTFontDescriptorRef font); - void populateFromFontDescription(CTFontDescriptorRef font, const FontDescription &fd); mutable QString defaultFontName; -- cgit v1.2.3 From 1e441d298db5e7ad1635067106e4b7ed251fd4bd Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Thu, 26 Feb 2015 19:16:15 +0400 Subject: [QQuaternion] Add a way to convert to/from orthonormal axes It is just a convenience wrapper around convertion to/from the rotation matrix. Change-Id: I27511b43866827172960b0152f1c7b65da857f6f Reviewed-by: Lars Knoll --- src/gui/math3d/qquaternion.cpp | 51 ++++++++- src/gui/math3d/qquaternion.h | 5 + .../gui/math3d/qquaternion/tst_qquaternion.cpp | 123 ++++++++++++++++----- 3 files changed, 149 insertions(+), 30 deletions(-) diff --git a/src/gui/math3d/qquaternion.cpp b/src/gui/math3d/qquaternion.cpp index 141651eda1..d367f74e25 100644 --- a/src/gui/math3d/qquaternion.cpp +++ b/src/gui/math3d/qquaternion.cpp @@ -592,7 +592,7 @@ QQuaternion QQuaternion::fromEulerAngles(float pitch, float yaw, float roll) \note If this quaternion is not normalized, the resulting rotation matrix will contain scaling information. - \sa fromRotationMatrix() + \sa fromRotationMatrix(), getAxes() */ QMatrix3x3 QQuaternion::toRotationMatrix() const { @@ -635,7 +635,7 @@ QMatrix3x3 QQuaternion::toRotationMatrix() const \note If a given rotation matrix is not normalized, the resulting quaternion will contain scaling information. - \sa toRotationMatrix() + \sa toRotationMatrix(), fromAxes() */ QQuaternion QQuaternion::fromRotationMatrix(const QMatrix3x3 &rot3x3) { @@ -672,6 +672,53 @@ QQuaternion QQuaternion::fromRotationMatrix(const QMatrix3x3 &rot3x3) return QQuaternion(scalar, axis[0], axis[1], axis[2]); } +#ifndef QT_NO_VECTOR3D + +/*! + \since 5.5 + + Returns the 3 orthonormal axes (\a xAxis, \a yAxis, \a zAxis) defining the quaternion. + + \sa fromAxes(), toRotationMatrix() +*/ +void QQuaternion::getAxes(QVector3D *xAxis, QVector3D *yAxis, QVector3D *zAxis) const +{ + Q_ASSERT(xAxis && yAxis && zAxis); + + const QMatrix3x3 rot3x3(toRotationMatrix()); + + *xAxis = QVector3D(rot3x3(0, 0), rot3x3(1, 0), rot3x3(2, 0)); + *yAxis = QVector3D(rot3x3(0, 1), rot3x3(1, 1), rot3x3(2, 1)); + *zAxis = QVector3D(rot3x3(0, 2), rot3x3(1, 2), rot3x3(2, 2)); +} + +/*! + \since 5.5 + + Constructs the quaternion using 3 axes (\a xAxis, \a yAxis, \a zAxis). + + \note The axes are assumed to be orthonormal. + + \sa getAxes(), fromRotationMatrix() +*/ +QQuaternion QQuaternion::fromAxes(const QVector3D &xAxis, const QVector3D &yAxis, const QVector3D &zAxis) +{ + QMatrix3x3 rot3x3(Qt::Uninitialized); + rot3x3(0, 0) = xAxis.x(); + rot3x3(1, 0) = xAxis.y(); + rot3x3(2, 0) = xAxis.z(); + rot3x3(0, 1) = yAxis.x(); + rot3x3(1, 1) = yAxis.y(); + rot3x3(2, 1) = yAxis.z(); + rot3x3(0, 2) = zAxis.x(); + rot3x3(1, 2) = zAxis.y(); + rot3x3(2, 2) = zAxis.z(); + + return QQuaternion::fromRotationMatrix(rot3x3); +} + +#endif // QT_NO_VECTOR3D + /*! \fn bool operator==(const QQuaternion &q1, const QQuaternion &q2) \relates QQuaternion diff --git a/src/gui/math3d/qquaternion.h b/src/gui/math3d/qquaternion.h index b4022e8579..6ce3979bbe 100644 --- a/src/gui/math3d/qquaternion.h +++ b/src/gui/math3d/qquaternion.h @@ -134,6 +134,11 @@ public: QMatrix3x3 toRotationMatrix() const; static QQuaternion fromRotationMatrix(const QMatrix3x3 &rot3x3); +#ifndef QT_NO_VECTOR3D + void getAxes(QVector3D *xAxis, QVector3D *yAxis, QVector3D *zAxis) const; + static QQuaternion fromAxes(const QVector3D &xAxis, const QVector3D &yAxis, const QVector3D &zAxis); +#endif + static QQuaternion slerp (const QQuaternion& q1, const QQuaternion& q2, float t); static QQuaternion nlerp diff --git a/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp b/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp index e358937a62..6b8eeeaca5 100644 --- a/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp +++ b/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp @@ -35,6 +35,52 @@ #include #include +// This is a more tolerant version of qFuzzyCompare that also handles the case +// where one or more of the values being compare are close to zero +static inline bool myFuzzyCompare(float p1, float p2) +{ + if (qFuzzyIsNull(p1) && qFuzzyIsNull(p2)) + return true; + return qAbs(qAbs(p1) - qAbs(p2)) <= 0.00003f; +} + +static inline bool myFuzzyCompare(const QVector3D &v1, const QVector3D &v2) +{ + return myFuzzyCompare(v1.x(), v2.x()) + && myFuzzyCompare(v1.y(), v2.y()) + && myFuzzyCompare(v1.z(), v2.z()); +} + +static inline bool myFuzzyCompare(const QQuaternion &q1, const QQuaternion &q2) +{ + const float d = QQuaternion::dotProduct(q1, q2); + return myFuzzyCompare(d * d, 1.0f); +} + +static inline bool myFuzzyCompareRadians(float p1, float p2) +{ + static const float fPI = float(M_PI); + if (p1 < -fPI) + p1 += 2.0f * fPI; + else if (p1 > fPI) + p1 -= 2.0f * fPI; + + if (p2 < -fPI) + p2 += 2.0f * fPI; + else if (p2 > fPI) + p2 -= 2.0f * fPI; + + return qAbs(qAbs(p1) - qAbs(p2)) <= qDegreesToRadians(0.05f); +} + +static inline bool myFuzzyCompareDegrees(float p1, float p2) +{ + p1 = qDegreesToRadians(p1); + p2 = qDegreesToRadians(p2); + return myFuzzyCompareRadians(p1, p2); +} + + class tst_QQuaternion : public QObject { Q_OBJECT @@ -89,6 +135,9 @@ private slots: void fromRotationMatrix_data(); void fromRotationMatrix(); + void fromAxes_data(); + void fromAxes(); + void fromEulerAngles_data(); void fromEulerAngles(); @@ -826,40 +875,58 @@ void tst_QQuaternion::fromRotationMatrix() QVERIFY(qFuzzyCompare(answer, result) || qFuzzyCompare(-answer, result)); } -// This is a more tolerant version of qFuzzyCompare that also handles the case -// where one or more of the values being compare are close to zero -static inline bool myFuzzyCompare(float p1, float p2) +// Test quaternion convertion to and from orthonormal axes. +void tst_QQuaternion::fromAxes_data() { - if (qFuzzyIsNull(p1)) - return qFuzzyIsNull(p2); - if (qFuzzyIsNull(p2)) - return false; - // a very slightly looser version of qFuzzyCompare - // for use with values that are not very close to zero - return qAbs(p1 - p2) <= 0.00003f * qMin(qAbs(p1), qAbs(p2)); -} + QTest::addColumn("x1"); + QTest::addColumn("y1"); + QTest::addColumn("z1"); + QTest::addColumn("angle"); + QTest::addColumn("xAxis"); + QTest::addColumn("yAxis"); + QTest::addColumn("zAxis"); -static inline bool myFuzzyCompareRadians(float p1, float p2) -{ - static const float fPI = float(M_PI); - if (p1 < -fPI) - p1 += 2.0f * fPI; - else if (p1 > fPI) - p1 -= 2.0f * fPI; + QTest::newRow("null") + << 0.0f << 0.0f << 0.0f << 0.0f + << QVector3D(1, 0, 0) << QVector3D(0, 1, 0) << QVector3D(0, 0, 1); - if (p2 < -fPI) - p2 += 2.0f * fPI; - else if (p2 > fPI) - p2 -= 2.0f * fPI; + QTest::newRow("xonly") + << 1.0f << 0.0f << 0.0f << 90.0f + << QVector3D(1, 0, 0) << QVector3D(0, 0, 1) << QVector3D(0, -1, 0); - return qAbs(qAbs(p1) - qAbs(p2)) <= qDegreesToRadians(0.05f); -} + QTest::newRow("yonly") + << 0.0f << 1.0f << 0.0f << 180.0f + << QVector3D(-1, 0, 0) << QVector3D(0, 1, 0) << QVector3D(0, 0, -1); -static inline bool myFuzzyCompareDegrees(float p1, float p2) + QTest::newRow("zonly") + << 0.0f << 0.0f << 1.0f << 270.0f + << QVector3D(0, -1, 0) << QVector3D(1, 0, 0) << QVector3D(0, 0, 1); + + QTest::newRow("complex") + << 1.0f << 2.0f << -3.0f << 45.0f + << QVector3D(0.728028, -0.525105, -0.440727) << QVector3D(0.608789, 0.790791, 0.0634566) << QVector3D(0.315202, -0.314508, 0.895395); +} +void tst_QQuaternion::fromAxes() { - p1 = qDegreesToRadians(p1); - p2 = qDegreesToRadians(p2); - return myFuzzyCompareRadians(p1, p2); + QFETCH(float, x1); + QFETCH(float, y1); + QFETCH(float, z1); + QFETCH(float, angle); + QFETCH(QVector3D, xAxis); + QFETCH(QVector3D, yAxis); + QFETCH(QVector3D, zAxis); + + QQuaternion result = QQuaternion::fromAxisAndAngle(QVector3D(x1, y1, z1), angle); + + QVector3D axes[3]; + result.getAxes(&axes[0], &axes[1], &axes[2]); + QVERIFY(myFuzzyCompare(axes[0], xAxis)); + QVERIFY(myFuzzyCompare(axes[1], yAxis)); + QVERIFY(myFuzzyCompare(axes[2], zAxis)); + + QQuaternion answer = QQuaternion::fromAxes(axes[0], axes[1], axes[2]); + + QVERIFY(qFuzzyCompare(answer, result) || qFuzzyCompare(-answer, result)); } // Test quaternion creation from an axis and an angle. -- cgit v1.2.3 From da681a41cbe10be643c76b3150ab28eadf18df69 Mon Sep 17 00:00:00 2001 From: Konstantin Ritt Date: Thu, 26 Feb 2015 17:51:26 +0400 Subject: Introduce QQuaternion::rotationTo(vecFrom, vecTo) which returns the shortest arc quaternion to rotate vector from to the destination vector to. Change-Id: Ibd7a746789ecdfe6f7fe17e4ac9049f7ac46560d Reviewed-by: Lars Knoll Reviewed-by: Paul Lemire --- src/gui/math3d/qquaternion.cpp | 32 ++++++++++++ src/gui/math3d/qquaternion.h | 2 + .../gui/math3d/qquaternion/tst_qquaternion.cpp | 60 ++++++++++++++++++++++ 3 files changed, 94 insertions(+) diff --git a/src/gui/math3d/qquaternion.cpp b/src/gui/math3d/qquaternion.cpp index d367f74e25..90d90448e0 100644 --- a/src/gui/math3d/qquaternion.cpp +++ b/src/gui/math3d/qquaternion.cpp @@ -717,6 +717,38 @@ QQuaternion QQuaternion::fromAxes(const QVector3D &xAxis, const QVector3D &yAxis return QQuaternion::fromRotationMatrix(rot3x3); } +/*! + \since 5.5 + + Returns the shortest arc quaternion to rotate from the direction described by the vector \a from + to the direction described by the vector \a to. +*/ +QQuaternion QQuaternion::rotationTo(const QVector3D &from, const QVector3D &to) +{ + // Based on Stan Melax's article in Game Programming Gems + + const QVector3D v0(from.normalized()); + const QVector3D v1(to.normalized()); + + float d = QVector3D::dotProduct(v0, v1) + 1.0f; + + // if dest vector is close to the inverse of source vector, ANY axis of rotation is valid + if (qFuzzyIsNull(d)) { + QVector3D axis = QVector3D::crossProduct(QVector3D(1.0f, 0.0f, 0.0f), v0); + if (qFuzzyIsNull(axis.lengthSquared())) + axis = QVector3D::crossProduct(QVector3D(0.0f, 1.0f, 0.0f), v0); + axis.normalize(); + + // same as QQuaternion::fromAxisAndAngle(axis, 180.0f) + return QQuaternion(0.0f, axis.x(), axis.y(), axis.z()); + } + + d = std::sqrt(2.0f * d); + const QVector3D axis(QVector3D::crossProduct(v0, v1) / d); + + return QQuaternion(d * 0.5f, axis).normalized(); +} + #endif // QT_NO_VECTOR3D /*! diff --git a/src/gui/math3d/qquaternion.h b/src/gui/math3d/qquaternion.h index 6ce3979bbe..c3918645d4 100644 --- a/src/gui/math3d/qquaternion.h +++ b/src/gui/math3d/qquaternion.h @@ -137,6 +137,8 @@ public: #ifndef QT_NO_VECTOR3D void getAxes(QVector3D *xAxis, QVector3D *yAxis, QVector3D *zAxis) const; static QQuaternion fromAxes(const QVector3D &xAxis, const QVector3D &yAxis, const QVector3D &zAxis); + + static QQuaternion rotationTo(const QVector3D &from, const QVector3D &to); #endif static QQuaternion slerp diff --git a/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp b/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp index 6b8eeeaca5..2c38e4c111 100644 --- a/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp +++ b/tests/auto/gui/math3d/qquaternion/tst_qquaternion.cpp @@ -138,6 +138,9 @@ private slots: void fromAxes_data(); void fromAxes(); + void rotationTo_data(); + void rotationTo(); + void fromEulerAngles_data(); void fromEulerAngles(); @@ -929,6 +932,63 @@ void tst_QQuaternion::fromAxes() QVERIFY(qFuzzyCompare(answer, result) || qFuzzyCompare(-answer, result)); } +// Test shortest arc quaternion. +void tst_QQuaternion::rotationTo_data() +{ + QTest::addColumn("from"); + QTest::addColumn("to"); + + // same + QTest::newRow("+X -> +X") << QVector3D(10.0f, 0.0f, 0.0f) << QVector3D(10.0f, 0.0f, 0.0f); + QTest::newRow("-X -> -X") << QVector3D(-10.0f, 0.0f, 0.0f) << QVector3D(-10.0f, 0.0f, 0.0f); + QTest::newRow("+Y -> +Y") << QVector3D(0.0f, 10.0f, 0.0f) << QVector3D(0.0f, 10.0f, 0.0f); + QTest::newRow("-Y -> -Y") << QVector3D(0.0f, -10.0f, 0.0f) << QVector3D(0.0f, -10.0f, 0.0f); + QTest::newRow("+Z -> +Z") << QVector3D(0.0f, 0.0f, 10.0f) << QVector3D(0.0f, 0.0f, 10.0f); + QTest::newRow("-Z -> -Z") << QVector3D(0.0f, 0.0f, -10.0f) << QVector3D(0.0f, 0.0f, -10.0f); + QTest::newRow("+X+Y+Z -> +X+Y+Z") << QVector3D(10.0f, 10.0f, 10.0f) << QVector3D(10.0f, 10.0f, 10.0f); + QTest::newRow("-X-Y-Z -> -X-Y-Z") << QVector3D(-10.0f, -10.0f, -10.0f) << QVector3D(-10.0f, -10.0f, -10.0f); + + // arbitrary + QTest::newRow("+Z -> +X") << QVector3D(0.0f, 0.0f, 10.0f) << QVector3D(10.0f, 0.0f, 0.0f); + QTest::newRow("+Z -> -X") << QVector3D(0.0f, 0.0f, 10.0f) << QVector3D(-10.0f, 0.0f, 0.0f); + QTest::newRow("+Z -> +Y") << QVector3D(0.0f, 0.0f, 10.0f) << QVector3D(0.0f, 10.0f, 0.0f); + QTest::newRow("+Z -> -Y") << QVector3D(0.0f, 0.0f, 10.0f) << QVector3D(0.0f, -10.0f, 0.0f); + QTest::newRow("-Z -> +X") << QVector3D(0.0f, 0.0f, -10.0f) << QVector3D(10.0f, 0.0f, 0.0f); + QTest::newRow("-Z -> -X") << QVector3D(0.0f, 0.0f, -10.0f) << QVector3D(-10.0f, 0.0f, 0.0f); + QTest::newRow("-Z -> +Y") << QVector3D(0.0f, 0.0f, -10.0f) << QVector3D(0.0f, 10.0f, 0.0f); + QTest::newRow("-Z -> -Y") << QVector3D(0.0f, 0.0f, -10.0f) << QVector3D(0.0f, -10.0f, 0.0f); + QTest::newRow("+X -> +Y") << QVector3D(10.0f, 0.0f, 0.0f) << QVector3D(0.0f, 10.0f, 0.0f); + QTest::newRow("+X -> -Y") << QVector3D(10.0f, 0.0f, 0.0f) << QVector3D(0.0f, -10.0f, 0.0f); + QTest::newRow("-X -> +Y") << QVector3D(-10.0f, 0.0f, 0.0f) << QVector3D(0.0f, 10.0f, 0.0f); + QTest::newRow("-X -> -Y") << QVector3D(-10.0f, 0.0f, 0.0f) << QVector3D(0.0f, -10.0f, 0.0f); + QTest::newRow("+X+Y+Z -> +X-Y-Z") << QVector3D(10.0f, 10.0f, 10.0f) << QVector3D(10.0f, -10.0f, -10.0f); + QTest::newRow("-X-Y+Z -> -X+Y-Z") << QVector3D(-10.0f, -10.0f, 10.0f) << QVector3D(-10.0f, 10.0f, -10.0f); + QTest::newRow("+X+Y+Z -> +Z") << QVector3D(10.0f, 10.0f, 10.0f) << QVector3D(0.0f, 0.0f, 10.0f); + + // collinear + QTest::newRow("+X -> -X") << QVector3D(10.0f, 0.0f, 0.0f) << QVector3D(-10.0f, 0.0f, 0.0f); + QTest::newRow("+Y -> -Y") << QVector3D(0.0f, 10.0f, 0.0f) << QVector3D(0.0f, -10.0f, 0.0f); + QTest::newRow("+Z -> -Z") << QVector3D(0.0f, 0.0f, 10.0f) << QVector3D(0.0f, 0.0f, -10.0f); + QTest::newRow("+X+Y+Z -> -X-Y-Z") << QVector3D(10.0f, 10.0f, 10.0f) << QVector3D(-10.0f, -10.0f, -10.0f); +} +void tst_QQuaternion::rotationTo() +{ + QFETCH(QVector3D, from); + QFETCH(QVector3D, to); + + QQuaternion q1 = QQuaternion::rotationTo(from, to); + QVERIFY(myFuzzyCompare(q1, q1.normalized())); + QVector3D vec1(q1 * from); + vec1 *= (to.length() / from.length()); // discard rotated length + QVERIFY(myFuzzyCompare(vec1, to)); + + QQuaternion q2 = QQuaternion::rotationTo(to, from); + QVERIFY(myFuzzyCompare(q2, q2.normalized())); + QVector3D vec2(q2 * to); + vec2 *= (from.length() / to.length()); // discard rotated length + QVERIFY(myFuzzyCompare(vec2, from)); +} + // Test quaternion creation from an axis and an angle. void tst_QQuaternion::fromEulerAngles_data() { -- cgit v1.2.3 From e8f4ae555989fd0dcbee2a5877c3d63594d5363a Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 2 Mar 2015 16:25:25 +0100 Subject: Clarify QMatrix4x4::lookAt() docs Task-number: QTBUG-44603 Change-Id: I72d143a5d9ddd31ab1b64788cc0e2dd4fca2531c Reviewed-by: Konstantin Ritt --- src/gui/math3d/qmatrix4x4.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp index 19d1fe6a8c..09b41ac570 100644 --- a/src/gui/math3d/qmatrix4x4.cpp +++ b/src/gui/math3d/qmatrix4x4.cpp @@ -1523,10 +1523,13 @@ void QMatrix4x4::perspective(float verticalAngle, float aspectRatio, float nearP #ifndef QT_NO_VECTOR3D /*! - Multiplies this matrix by another that applies an \a eye position - transformation. The \a center value indicates the center of the - view that the \a eye is looking at. The \a up value indicates - which direction should be considered up with respect to the \a eye. + Multiplies this matrix by a viewing matrix derived from an eye + point. The \a center value indicates the center of the view that + the \a eye is looking at. The \a up value indicates which direction + should be considered up with respect to the \a eye. + + \note The \a up vector must not be parallel to the line of sight + from \a eye to \a center. */ void QMatrix4x4::lookAt(const QVector3D& eye, const QVector3D& center, const QVector3D& up) { -- cgit v1.2.3 From f58933f2a9a4a42aca4331f6a93cf5e796728c0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 4 Mar 2015 12:56:14 +0100 Subject: iOS: Resolve QT depends before checking if we need to link in platform plugin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The logic failed for cases like QT += core widgets. Change-Id: Ic49c1a2314a4698b03956acbd6778b658326f3e2 Reviewed-by: Tor Arne Vestbø --- mkspecs/macx-ios-clang/features/qt.prf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mkspecs/macx-ios-clang/features/qt.prf b/mkspecs/macx-ios-clang/features/qt.prf index 7ca3198dbe..697eb0ed60 100644 --- a/mkspecs/macx-ios-clang/features/qt.prf +++ b/mkspecs/macx-ios-clang/features/qt.prf @@ -1,5 +1,6 @@ -equals(TEMPLATE, app):contains(QT, gui(-private)?) { +qt_depends = $$resolve_depends(QT, "QT.") +equals(TEMPLATE, app):contains(qt_depends, gui(-private)?) { LIBS *= -L$$[QT_INSTALL_PLUGINS/get]/platforms lib_name = qios -- cgit v1.2.3 From d5e56fd9135f61b05596cfdf095b301bc5cb3fef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 13 Feb 2015 15:19:32 +0100 Subject: Xcode: Make QMAKE_MAC_SDK_(PLATFORM_)PATH depend on active SDK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Xcode project generator doesn't support exclusive builds, and always runs as the default debug/release config, and with iPhoneOS as the target platform. This means we need to parameterize the QMAKE_MAC_SDK_* build settings to depend on the currently active SDK in Xcode, so that the paths, when used in eg. linker flags, are up to date. Change-Id: I9ca10f794e14ab440d98820657758b3fd8a7cdb0 Reviewed-by: Oswald Buddenhagen Reviewed-by: Richard Moe Gustavsen Reviewed-by: Tor Arne Vestbø --- mkspecs/macx-ios-clang/features/sdk.prf | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/mkspecs/macx-ios-clang/features/sdk.prf b/mkspecs/macx-ios-clang/features/sdk.prf index 003789b5be..32fcbb7289 100644 --- a/mkspecs/macx-ios-clang/features/sdk.prf +++ b/mkspecs/macx-ios-clang/features/sdk.prf @@ -13,3 +13,21 @@ load(sdk) lessThan(QMAKE_MAC_SDK_VERSION, "8.0"): \ error("Current $$QMAKE_MAC_SDK SDK version ($$QMAKE_MAC_SDK_VERSION) is too old. Please upgrade Xcode.") + +macx-xcode { + sdk_path_iphoneos.name = "QMAKE_MAC_SDK_PATH[sdk=iphoneos*]" + sdk_path_iphoneos.value = $$QMAKE_MAC_SDK_PATH + QMAKE_MAC_SDK_PATH ~= s,iPhoneOS,iPhoneSimulator, + sdk_path_iphonesimulator.name = "QMAKE_MAC_SDK_PATH[sdk=iphonesimulator*]" + sdk_path_iphonesimulator.value = $$QMAKE_MAC_SDK_PATH + QMAKE_MAC_XCODE_SETTINGS += sdk_path_iphoneos sdk_path_iphonesimulator + QMAKE_MAC_SDK_PATH = "$(QMAKE_MAC_SDK_PATH)" + + sdk_platform_path_iphoneos.name = "QMAKE_MAC_SDK_PLATFORM_PATH[sdk=iphoneos*]" + sdk_platform_path_iphoneos.value = $$QMAKE_MAC_SDK_PLATFORM_PATH + QMAKE_MAC_SDK_PLATFORM_PATH ~= s,iPhoneOS,iPhoneSimulator, + sdk_platform_path_iphonesimulator.name = "QMAKE_MAC_SDK_PLATFORM_PATH[sdk=iphonesimulator*]" + sdk_platform_path_iphonesimulator.value = $$QMAKE_MAC_SDK_PLATFORM_PATH + QMAKE_MAC_XCODE_SETTINGS += sdk_platform_path_iphoneos sdk_platform_path_iphonesimulator + QMAKE_MAC_SDK_PLATFORM_PATH = "$(QMAKE_MAC_SDK_PLATFORM_PATH)" +} -- cgit v1.2.3 From 94bad40392ad89489744e4d59889fa0e920063b4 Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Fri, 27 Feb 2015 09:55:52 +0100 Subject: qdoc: Remove unnecessary ifndef Q_QDOC MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was preventing some functions in the Qt namespace from being documented and hence auto-links to these functions failed. Change-Id: Ie820eb7c8172deac40554e993e4d61a765a616f4 Task-number: QTBUG-44688 Reviewed-by: Topi Reiniö --- src/gui/text/qtextdocument.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h index 333bbb202f..ca80a88033 100644 --- a/src/gui/text/qtextdocument.h +++ b/src/gui/text/qtextdocument.h @@ -63,7 +63,6 @@ class QTextCursor; template class QVector; -#ifndef Q_QDOC // Workaround for QTBUG-35230 namespace Qt { Q_GUI_EXPORT bool mightBeRichText(const QString&); @@ -73,7 +72,6 @@ namespace Qt Q_GUI_EXPORT QTextCodec *codecForHtml(const QByteArray &ba); #endif } -#endif // Q_QDOC class Q_GUI_EXPORT QAbstractUndoItem { -- cgit v1.2.3 From 100ffb60ef07e026a054b9df9007ec1b25698c90 Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Wed, 4 Mar 2015 11:48:51 +0100 Subject: qdoc: Teach qdoc to resolve namespaces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It turns out this bug was caused by modularization, which created the situation where members of the Qt namespace are in different modules. Most are in QtCore, but a few are in QtGui. qdoc was creating a namespace node for the Qt namespace in the node tree for QtCore, and another namespace node in the node tree for QtGui. This meant that there were two NamespaceNodes for the Qt namespace. Correctly, only one of these nodes contained the text for the \namespace command for the Qt namespace. This was the namespace node that was being used to create the HTML reference page for the Qt namespace. Unfortunately, the Qt namespace node in the tree for QtGui was not being merged into the Qt namespace node in QtCore, so some of the members of the Qt namespace were not being shown on the reference page. This update teches qdoc how to merge namespace nodes to ensure that all the members appear on the reference page for the namespace. There can be a namespace node for the namespace xxx in any number of modules, but they will all be merged into the namespace node for namespace xxx that contains the qdoc comment for \namespace xxx. Change-Id: I0f6a653ea6f920aacd5d8e13f9865488d95f6458 Task-number: QTBUG-44688 Reviewed-by: Topi Reiniö --- src/tools/qdoc/codemarker.cpp | 7 +-- src/tools/qdoc/cppcodemarker.cpp | 119 +++++++++++++++++++-------------------- src/tools/qdoc/cppcodeparser.cpp | 4 ++ src/tools/qdoc/htmlgenerator.cpp | 7 ++- src/tools/qdoc/node.cpp | 15 ++++- src/tools/qdoc/node.h | 11 ++-- src/tools/qdoc/qdocdatabase.cpp | 71 ++++++++++++++++++----- src/tools/qdoc/qdocdatabase.h | 8 +-- 8 files changed, 153 insertions(+), 89 deletions(-) diff --git a/src/tools/qdoc/codemarker.cpp b/src/tools/qdoc/codemarker.cpp index 6a1675aeb5..2253aca183 100644 --- a/src/tools/qdoc/codemarker.cpp +++ b/src/tools/qdoc/codemarker.cpp @@ -391,12 +391,11 @@ void CodeMarker::insert(FastSection &fastSection, bool inheritedMember = false; if (!node->relates()) { InnerNode* p = node->parent(); - if (p->type() == Node::QmlPropertyGroup) + if (p->isQmlPropertyGroup()) p = p->parent(); if (p != fastSection.parent_) { - if ((!p->isQmlType() && !p->isJsType()) || !p->isAbstract()) { + if ((!p->isQmlType() && !p->isJsType()) || !p->isAbstract()) inheritedMember = true; - } } } @@ -438,7 +437,7 @@ void CodeMarker::insert(FastSection &fastSection, fastSection.memberMap.insertMulti(key, node); } else { - if (node->parent()->type() == Node::Class) { + if (node->parent()->isClass() || node->parent()->isNamespace()) { if (fastSection.inherited.isEmpty() || fastSection.inherited.last().first != node->parent()) { QPair p(node->parent(), 0); diff --git a/src/tools/qdoc/cppcodemarker.cpp b/src/tools/qdoc/cppcodemarker.cpp index 400c4808ed..1546b5226e 100644 --- a/src/tools/qdoc/cppcodemarker.cpp +++ b/src/tools/qdoc/cppcodemarker.cpp @@ -442,75 +442,73 @@ QList
CppCodeMarker::sections(const InnerNode *inner, { QList
sections; - if (inner->type() == Node::Class) { - const ClassNode *classNode = static_cast(inner); - + if (inner->isClass()) { if (style == Summary) { - FastSection privateFunctions(classNode, + FastSection privateFunctions(inner, "Private Functions", QString(), "private function", "private functions"); - FastSection privateSlots(classNode, "Private Slots", QString(), "private slot", "private slots"); - FastSection privateTypes(classNode, "Private Types", QString(), "private type", "private types"); - FastSection protectedFunctions(classNode, + FastSection privateSlots(inner, "Private Slots", QString(), "private slot", "private slots"); + FastSection privateTypes(inner, "Private Types", QString(), "private type", "private types"); + FastSection protectedFunctions(inner, "Protected Functions", QString(), "protected function", "protected functions"); - FastSection protectedSlots(classNode, + FastSection protectedSlots(inner, "Protected Slots", QString(), "protected slot", "protected slots"); - FastSection protectedTypes(classNode, + FastSection protectedTypes(inner, "Protected Types", QString(), "protected type", "protected types"); - FastSection protectedVariables(classNode, + FastSection protectedVariables(inner, "Protected Variables", QString(), "protected type", "protected variables"); - FastSection publicFunctions(classNode, + FastSection publicFunctions(inner, "Public Functions", QString(), "public function", "public functions"); - FastSection publicSignals(classNode, "Signals", QString(), "signal", "signals"); - FastSection publicSlots(classNode, "Public Slots", QString(), "public slot", "public slots"); - FastSection publicTypes(classNode, "Public Types", QString(), "public type", "public types"); - FastSection publicVariables(classNode, + FastSection publicSignals(inner, "Signals", QString(), "signal", "signals"); + FastSection publicSlots(inner, "Public Slots", QString(), "public slot", "public slots"); + FastSection publicTypes(inner, "Public Types", QString(), "public type", "public types"); + FastSection publicVariables(inner, "Public Variables", QString(), "public variable", "public variables"); - FastSection properties(classNode, "Properties", QString(), "property", "properties"); - FastSection relatedNonMembers(classNode, + FastSection properties(inner, "Properties", QString(), "property", "properties"); + FastSection relatedNonMembers(inner, "Related Non-Members", QString(), "related non-member", "related non-members"); - FastSection staticPrivateMembers(classNode, + FastSection staticPrivateMembers(inner, "Static Private Members", QString(), "static private member", "static private members"); - FastSection staticProtectedMembers(classNode, + FastSection staticProtectedMembers(inner, "Static Protected Members", QString(), "static protected member", "static protected members"); - FastSection staticPublicMembers(classNode, + FastSection staticPublicMembers(inner, "Static Public Members", QString(), "static public member", "static public members"); FastSection macros(inner, "Macros", QString(), "macro", "macros"); - NodeList::ConstIterator r = classNode->relatedNodes().constBegin(); - while (r != classNode->relatedNodes().constEnd()) { + NodeList::ConstIterator r = inner->relatedNodes().constBegin(); + while (r != inner->relatedNodes().constEnd()) { if ((*r)->type() == Node::Function) { FunctionNode *func = static_cast(*r); if (func->isMacro()) @@ -524,13 +522,13 @@ QList
CppCodeMarker::sections(const InnerNode *inner, ++r; } - QStack stack; - stack.push(classNode); + QStack stack; + stack.push(inner); while (!stack.isEmpty()) { - const ClassNode *ancestorClass = stack.pop(); + const InnerNode* ancestor = stack.pop(); - NodeList::ConstIterator c = ancestorClass->childNodes().constBegin(); - while (c != ancestorClass->childNodes().constEnd()) { + NodeList::ConstIterator c = ancestor->childNodes().constBegin(); + while (c != ancestor->childNodes().constEnd()) { bool isSlot = false; bool isSignal = false; bool isStatic = false; @@ -620,15 +618,16 @@ QList
CppCodeMarker::sections(const InnerNode *inner, ++c; } - QList::ConstIterator r = - ancestorClass->baseClasses().constBegin(); - while (r != ancestorClass->baseClasses().constEnd()) { - if ((*r).node_) - stack.prepend((*r).node_); - ++r; + if (ancestor->isClass()) { + const ClassNode* cn = static_cast(ancestor); + QList::ConstIterator r = cn->baseClasses().constBegin(); + while (r != cn->baseClasses().constEnd()) { + if ((*r).node_) + stack.prepend((*r).node_); + ++r; + } } } - append(sections, publicTypes); append(sections, properties); append(sections, publicFunctions); @@ -649,15 +648,15 @@ QList
CppCodeMarker::sections(const InnerNode *inner, append(sections, macros); } else if (style == Detailed) { - FastSection memberFunctions(classNode,"Member Function Documentation","func","member","members"); - FastSection memberTypes(classNode,"Member Type Documentation","types","member","members"); - FastSection memberVariables(classNode,"Member Variable Documentation","vars","member","members"); - FastSection properties(classNode,"Property Documentation","prop","member","members"); - FastSection relatedNonMembers(classNode,"Related Non-Members","relnonmem","member","members"); - FastSection macros(classNode,"Macro Documentation","macros","member","members"); - - NodeList::ConstIterator r = classNode->relatedNodes().constBegin(); - while (r != classNode->relatedNodes().constEnd()) { + FastSection memberFunctions(inner,"Member Function Documentation","func","member","members"); + FastSection memberTypes(inner,"Member Type Documentation","types","member","members"); + FastSection memberVariables(inner,"Member Variable Documentation","vars","member","members"); + FastSection properties(inner,"Property Documentation","prop","member","members"); + FastSection relatedNonMembers(inner,"Related Non-Members","relnonmem","member","members"); + FastSection macros(inner,"Macro Documentation","macros","member","members"); + + NodeList::ConstIterator r = inner->relatedNodes().constBegin(); + while (r != inner->relatedNodes().constEnd()) { if ((*r)->type() == Node::Function) { FunctionNode *func = static_cast(*r); if (func->isMacro()) @@ -671,8 +670,8 @@ QList
CppCodeMarker::sections(const InnerNode *inner, ++r; } - NodeList::ConstIterator c = classNode->childNodes().constBegin(); - while (c != classNode->childNodes().constEnd()) { + NodeList::ConstIterator c = inner->childNodes().constBegin(); + while (c != inner->childNodes().constEnd()) { if ((*c)->type() == Node::Enum || (*c)->type() == Node::Typedef) { insert(memberTypes, *c, style, status); @@ -700,28 +699,28 @@ QList
CppCodeMarker::sections(const InnerNode *inner, append(sections, macros); } else { - FastSection all(classNode,QString(),QString(),"member","members"); + FastSection all(inner,QString(),QString(),"member","members"); - QStack stack; - stack.push(classNode); + QStack stack; + stack.push(inner); while (!stack.isEmpty()) { - const ClassNode *ancestorClass = stack.pop(); - - NodeList::ConstIterator c = ancestorClass->childNodes().constBegin(); - while (c != ancestorClass->childNodes().constEnd()) { - if ((*c)->access() != Node::Private && - (*c)->type() != Node::Property) + const InnerNode* ancestor = stack.pop(); + NodeList::ConstIterator c = ancestor->childNodes().constBegin(); + while (c != ancestor->childNodes().constEnd()) { + if ((*c)->access() != Node::Private && (*c)->type() != Node::Property) insert(all, *c, style, status); ++c; } - QList::ConstIterator r = - ancestorClass->baseClasses().constBegin(); - while (r != ancestorClass->baseClasses().constEnd()) { - if ((*r).node_) - stack.prepend((*r).node_); - ++r; + if (ancestor->isClass()) { + const ClassNode* cn = static_cast(ancestor); + QList::ConstIterator r = cn->baseClasses().constBegin(); + while (r != cn->baseClasses().constEnd()) { + if ((*r).node_) + stack.prepend((*r).node_); + ++r; + } } } append(sections, all); diff --git a/src/tools/qdoc/cppcodeparser.cpp b/src/tools/qdoc/cppcodeparser.cpp index 6cb86a7515..bc24ff5daa 100644 --- a/src/tools/qdoc/cppcodeparser.cpp +++ b/src/tools/qdoc/cppcodeparser.cpp @@ -423,6 +423,10 @@ Node* CppCodeParser::processTopicCommand(const Doc& doc, } else if (node->isInnerNode()) { + if (type == Node::Namespace) { + NamespaceNode* ns = static_cast(node); + ns->markSeen(); + } /* This treats a class as a namespace. */ diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp index 8eb96bff17..7518b20fa3 100644 --- a/src/tools/qdoc/htmlgenerator.cpp +++ b/src/tools/qdoc/htmlgenerator.cpp @@ -291,7 +291,12 @@ void HtmlGenerator::generateKeywordAnchors(const Node* node) } /*! - Traverses the current tree generating all the HTML documentation. + If qdoc is in the \c {-prepare} phase, traverse the primary + tree to generate the index file for the current module. + + If qdoc is in the \c {-generate} phase, traverse the primary + tree to generate all the HTML documentation for the current + module. Then generate the help file and the tag file. */ void HtmlGenerator::generateDocs() { diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp index e14ca4af3e..25792a7c35 100644 --- a/src/tools/qdoc/node.cpp +++ b/src/tools/qdoc/node.cpp @@ -1112,7 +1112,9 @@ bool InnerNode::isSameSignature(const FunctionNode *f1, const FunctionNode *f2) } /*! - Adds the \a child to this node's child list. + Adds the \a child to this node's child list. It might also + be necessary to update this node's internal collections and + the child's parent pointer and output subdirectory. */ void InnerNode::addChild(Node *child) { @@ -1132,6 +1134,10 @@ void InnerNode::addChild(Node *child) enumChildren_.append(child); childMap.insertMulti(child->name(), child); } + if (child->parent() == 0) { + child->setParent(this); + child->setOutputSubdirectory(this->outputSubdirectory()); + } } /*! @@ -1146,6 +1152,10 @@ void InnerNode::addChild(Node* child, const QString& title) } /*! + The \a child is removed from this node's child list and + from this node's internal collections. The child's parent + pointer is set to 0, but its output subdirectory is not + changed. */ void InnerNode::removeChild(Node *child) { @@ -1185,6 +1195,7 @@ void InnerNode::removeChild(Node *child) } ++ent; } + child->setParent(0); } /*! @@ -1357,7 +1368,7 @@ LeafNode::LeafNode(InnerNode* parent, Type type, const QString& name) Constructs a namespace node. */ NamespaceNode::NamespaceNode(InnerNode *parent, const QString& name) - : InnerNode(Namespace, parent, name), tree_(0) + : InnerNode(Namespace, parent, name), seen_(false), tree_(0) { setGenus(Node::CPP); setPageType(ApiPage); diff --git a/src/tools/qdoc/node.h b/src/tools/qdoc/node.h index b6717b3b1b..5eeb7e7d3d 100644 --- a/src/tools/qdoc/node.h +++ b/src/tools/qdoc/node.h @@ -373,9 +373,7 @@ public: virtual ~InnerNode(); Node* findChildNode(const QString& name, Node::Genus genus) const; - //Node* findChildNode(const QString& name, bool qml) const; Node* findChildNode(const QString& name, Type type); - //void findNodes(const QString& name, NodeList& n); virtual void findChildren(const QString& name, NodeList& nodes) const Q_DECL_OVERRIDE; FunctionNode* findFunctionNode(const QString& name) const; FunctionNode* findFunctionNode(const FunctionNode* clone); @@ -410,6 +408,8 @@ public: const QStringList& groupNames() const { return groupNames_; } virtual void appendGroupName(const QString& t) Q_DECL_OVERRIDE { groupNames_.append(t); } void printChildren(const QString& title); + void addChild(Node* child); + void removeChild(Node* child); protected: InnerNode(Type type, InnerNode* parent, const QString& name); @@ -418,9 +418,7 @@ private: friend class Node; static bool isSameSignature(const FunctionNode* f1, const FunctionNode* f2); - void addChild(Node* child); void removeRelated(Node* pseudoChild); - void removeChild(Node* child); QString outputFileName_; QStringList pageKeywds; @@ -455,9 +453,14 @@ public: virtual ~NamespaceNode() { } virtual bool isNamespace() const Q_DECL_OVERRIDE { return true; } virtual Tree* tree() const Q_DECL_OVERRIDE { return (parent() ? parent()->tree() : tree_); } + virtual bool wasSeen() const Q_DECL_OVERRIDE { return seen_; } + + void markSeen() { seen_ = true; } + void markNotSeen() { seen_ = false; } void setTree(Tree* t) { tree_ = t; } private: + bool seen_; Tree* tree_; }; diff --git a/src/tools/qdoc/qdocdatabase.cpp b/src/tools/qdoc/qdocdatabase.cpp index 75295613f7..30d4d28a17 100644 --- a/src/tools/qdoc/qdocdatabase.cpp +++ b/src/tools/qdoc/qdocdatabase.cpp @@ -796,7 +796,6 @@ void QDocDatabase::processForest() { Tree* t = forest_.firstTree(); while (t) { - findAllNamespaces(t->root()); findAllClasses(t->root()); findAllFunctions(t->root()); findAllObsoleteThings(t->root()); @@ -805,6 +804,7 @@ void QDocDatabase::processForest() t->setTreeHasBeenAnalyzed(); t = forest_.nextTree(); } + resolveNamespaces(); } /*! @@ -872,16 +872,10 @@ NodeMap& QDocDatabase::getQmlTypesWithObsoleteMembers() return qmlTypesWithObsoleteMembers_; } -/*! - Constructs the C++ namespace data structure, if it has not - already been constructed. Returns a reference to it. +/*! \fn NodeMap& QDocDatabase::getNamespaces() + Returns a reference to the map of all namespace nodes. + This function must not be called in the -prepare phase. */ -NodeMap& QDocDatabase::getNamespaces() -{ - if (namespaceIndex_.isEmpty()) - processForest(&QDocDatabase::findAllNamespaces); - return namespaceIndex_; -} /*! Construct the C++ class data structures, if they have not @@ -1082,14 +1076,15 @@ void QDocDatabase::findAllNamespaces(InnerNode* node) { NodeList::ConstIterator c = node->childNodes().constBegin(); while (c != node->childNodes().constEnd()) { - if ((*c)->access() != Node::Private) { + if ((*c)->access() != Node::Private || (*c)->isNamespace()) { if ((*c)->isInnerNode()) { findAllNamespaces(static_cast(*c)); - if ((*c)->type() == Node::Namespace) { + if ((*c)->isNamespace()) { // Ensure that the namespace's name is not empty (the root // namespace has no name). - if (!(*c)->name().isEmpty()) - namespaceIndex_.insert((*c)->name(), *c); + if (!(*c)->name().isEmpty()) { + nmm_.insert((*c)->name(), *c); + } } } } @@ -1332,8 +1327,56 @@ void QDocDatabase::resolveStuff() //primaryTree()->resolveTargets(primaryTreeRoot()); primaryTree()->resolveCppToQmlLinks(); primaryTree()->resolveUsingClauses(); + resolveNamespaces(); +} + +/*! + */ +void QDocDatabase::resolveNamespaces() +{ + if (!namespaceIndex_.isEmpty()) + return; + Tree* t = forest_.firstTree(); + while (t) { + findAllNamespaces(t->root()); + t = forest_.nextTree(); + } + QList keys = nmm_.uniqueKeys(); + foreach (QString s, keys) { + NamespaceNode* ns = 0; + QList nodes = nmm_.values(s); + int count = nmm_.remove(s); + if (count > 1) { + foreach (Node* n, nodes) { + if (n->isNamespace() && n->wasSeen()) { + ns = static_cast(n); + break; + } + } + } + else if (count == 1) + ns = static_cast(nodes.at(0)); + if (ns && ns->wasSeen()) { + if (count >1) { + foreach (Node* n, nodes) { + if (n->isNamespace()) { + NamespaceNode* NS = static_cast(n); + if (NS != ns) { + while (!NS->childNodes().isEmpty()) { + Node* child = NS->childNodes().first(); + NS->removeChild(child); + ns->addChild(child); + } + } + } + } + } + namespaceIndex_.insert(ns->name(), ns); + } + } } + /*! This function is called for autolinking to a \a type, which could be a function return type or a parameter diff --git a/src/tools/qdoc/qdocdatabase.h b/src/tools/qdoc/qdocdatabase.h index 70307aa3ae..d0c59d731c 100644 --- a/src/tools/qdoc/qdocdatabase.h +++ b/src/tools/qdoc/qdocdatabase.h @@ -278,7 +278,7 @@ class QDocDatabase NodeMap& getClassesWithObsoleteMembers(); NodeMap& getObsoleteQmlTypes(); NodeMap& getQmlTypesWithObsoleteMembers(); - NodeMap& getNamespaces(); + NodeMap& getNamespaces() { resolveNamespaces(); return namespaceIndex_; } NodeMap& getServiceClasses(); NodeMap& getQmlBasicTypes(); NodeMap& getQmlTypes(); @@ -404,9 +404,8 @@ class QDocDatabase } TargetList* getTargetList(const QString& t) { return primaryTree()->getTargetList(t); } QStringList getTargetListKeys() { return primaryTree()->getTargetListKeys(); } - QStringList keys() { - return forest_.keys(); - } + QStringList keys() { return forest_.keys(); } + void resolveNamespaces(); private: friend class QDocIndexFiles; @@ -447,6 +446,7 @@ class QDocDatabase NodeMap obsoleteQmlTypes_; NodeMap qmlTypesWithObsoleteMembers_; NodeMap namespaceIndex_; + NodeMultiMap nmm_; NodeMap serviceClasses_; // MWS: not needed, should be deleted NodeMap qmlBasicTypes_; NodeMap qmlTypes_; -- cgit v1.2.3 From 495b3d357de9adcdd5378b2457b0a88dfc97e7f4 Mon Sep 17 00:00:00 2001 From: Martin Smith Date: Fri, 6 Mar 2015 10:32:16 +0100 Subject: qdoc: Fix regression in Node type testing When support for documenting JavaScript was added to qdoc, some tests qdoc uses to determine whether an entity is a QML signal or a QML method were modified incorrectly, a case of premature optimization. This caused QML methods to be listed as QML signals in the documentation. This update corrects those tests. Change-Id: Ie6d5b43a03a6f3ae39982292cb9ad92952de0bff Task-number: QTBUG-44825 Reviewed-by: Gunnar Sletta --- src/tools/qdoc/node.h | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/src/tools/qdoc/node.h b/src/tools/qdoc/node.h index 5eeb7e7d3d..73b705dd0f 100644 --- a/src/tools/qdoc/node.h +++ b/src/tools/qdoc/node.h @@ -884,12 +884,24 @@ public: bool isOverload() const { return ove; } bool isReimp() const Q_DECL_OVERRIDE { return reimp; } bool isFunction() const Q_DECL_OVERRIDE { return true; } - virtual bool isQmlSignal() const Q_DECL_OVERRIDE { return genus() == Node::QML; } - virtual bool isJsSignal() const Q_DECL_OVERRIDE { return genus() == Node::JS; } - virtual bool isQmlSignalHandler() const Q_DECL_OVERRIDE { return genus() == Node::QML; } - virtual bool isJsSignalHandler() const Q_DECL_OVERRIDE { return genus() == Node::JS; } - virtual bool isQmlMethod() const Q_DECL_OVERRIDE { return genus() == Node::QML; } - virtual bool isJsMethod() const Q_DECL_OVERRIDE { return genus() == Node::JS; } + virtual bool isQmlSignal() const Q_DECL_OVERRIDE { + return (type() == Node::QmlSignal) && (genus() == Node::QML); + } + virtual bool isJsSignal() const Q_DECL_OVERRIDE { + return (type() == Node::QmlSignal) && (genus() == Node::JS); + } + virtual bool isQmlSignalHandler() const Q_DECL_OVERRIDE { + return (type() == Node::QmlSignalHandler) && (genus() == Node::QML); + } + virtual bool isJsSignalHandler() const Q_DECL_OVERRIDE { + return (type() == Node::QmlSignalHandler) && (genus() == Node::JS); + } + virtual bool isQmlMethod() const Q_DECL_OVERRIDE { + return (type() == Node::QmlMethod) && (genus() == Node::QML); + } + virtual bool isJsMethod() const Q_DECL_OVERRIDE { + return (type() == Node::QmlMethod) && (genus() == Node::JS); + } int overloadNumber() const; const QList& parameters() const { return params; } QStringList parameterNames() const; -- cgit v1.2.3 From 8972ceea871f9737303132761b79f531763a6852 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 2 Mar 2015 18:19:36 +0100 Subject: iOS: Enable runnnig Qt tests using 'make check' via xcodebuild test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I1692cf3eb34726c15eaa969a369bb97a89773bfd Reviewed-by: Richard Moe Gustavsen Reviewed-by: Tor Arne Vestbø --- mkspecs/macx-ios-clang/features/default_post.prf | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/mkspecs/macx-ios-clang/features/default_post.prf b/mkspecs/macx-ios-clang/features/default_post.prf index 38889150c8..f9a8921a09 100644 --- a/mkspecs/macx-ios-clang/features/default_post.prf +++ b/mkspecs/macx-ios-clang/features/default_post.prf @@ -67,8 +67,8 @@ equals(TEMPLATE, app) { args += $$system_quote($$arg) system("cd $$system_quote($$OUT_PWD) && $$QMAKE_QMAKE $$args $$system_quote($$_PRO_FILE_) -spec macx-xcode") - check.commands = "$(MAKE) -f $(MAKEFILE).ReleaseSimulator xcode_build_check" - QMAKE_EXTRA_TARGETS += check + # We have a target, even though our template is aux + CONFIG += have_target } else { load(resolve_config) @@ -83,10 +83,13 @@ equals(TEMPLATE, app) { else: \ cfg = release - for(action, $$list(build install clean)) { + for(action, $$list(build install clean test)) { equals(action, build) { action_target_suffix = action_target = all + } else: equals(action, test) { + action_target_suffix = -check + action_target = check } else { action_target_suffix = -$$action action_target = $$action @@ -94,7 +97,7 @@ equals(TEMPLATE, app) { target = $${sdk}-$${cfg}$${action_target_suffix} - $${target}.commands = "@bash -o pipefail -c 'xcodebuild $$action -sdk $$sdk -configuration $$title($$cfg) | grep -v setenv'" + $${target}.commands = "@bash -o pipefail -c 'xcodebuild $$action -scheme $(TARGET) -sdk $$sdk -configuration $$title($$cfg) | grep -v setenv'" QMAKE_EXTRA_TARGETS += $$target $${action_target}.depends += $$target @@ -106,12 +109,7 @@ equals(TEMPLATE, app) { QMAKE_EXTRA_TARGETS += xcode_build_dir_distclean distclean.depends = xcode_build_dir_distclean QMAKE_EXTRA_TARGETS += distclean - - xcode_build_check.commands = "$(TESTRUNNER) $$title($$cfg)-$${sdk}/$(TARGET).app $(TESTARGS)" - QMAKE_EXTRA_TARGETS += xcode_build_check } - - CONFIG = } } } else: equals(TEMPLATE, lib) { -- cgit v1.2.3 From 84b9d071630a63a493773f612eefe83c8e68390d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 5 Mar 2015 15:27:32 -0800 Subject: Silence bogus MSVC warning about variable not used The compiler is wrong: the variable was used in the previous line. However, the line had no effect for a type T that has a trivial destructor, so the optimizer must have discarded the line and the reference to the variable before the checker for used variables. qsharedpointer_impl.h(247) : warning C4189: 'that' : local variable is initialized but not referenced Change-Id: Ia0aac2f09e9245339951ffff13c8bde02bb46816 Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/tools/qsharedpointer_impl.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h index 8cccc83e9d..9e6b48a97d 100644 --- a/src/corelib/tools/qsharedpointer_impl.h +++ b/src/corelib/tools/qsharedpointer_impl.h @@ -247,6 +247,7 @@ namespace QtSharedPointer { ExternalRefCountWithContiguousData *that = static_cast(self); that->data.~T(); + Q_UNUSED(that); // MSVC warns if T has a trivial destructor } static void safetyCheckDeleter(ExternalRefCountData *self) { -- cgit v1.2.3 From a8c74ddcf78604c9038ba2a2bea81e445e4b3c58 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 14 Jan 2015 16:33:03 -0800 Subject: Fix race condition in QDateTime::timeZone() and other methods When timezone support for QDateTime was added, we decided it was a good idea to delay creating the QTimeZone object and checking that the time is valid in that timezone (including for local time) until the user requested that information. Unfortunately, QExplicitlySharedDataPointer returns a non-const T* in operator->(), which meant we were accidentally modifying the d pointer's contents in const methods, which in turn means those const methods were not thread-safe when operating on the same object. This commit changes the d pointer to QSharedDataPointer, which is safer in this regard and pointed out where the issues with constness were located. Since we can't lazily calculate QTimeZone anymore, we need to do it whenever the date, time or offset changes. Task-number: QTBUG-43703 Change-Id: Ic5d393bfd36e48a193fcffff13b9686ef4ef1454 Reviewed-by: Lars Knoll --- src/corelib/tools/qdatetime.cpp | 55 ++++++++++++---------- src/corelib/tools/qdatetime.h | 2 +- src/corelib/tools/qdatetime_p.h | 14 ++---- .../auto/corelib/tools/qdatetime/tst_qdatetime.cpp | 53 +++++++++++++++++++++ 4 files changed, 89 insertions(+), 35 deletions(-) diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index eeefea8137..e5fbf5af5e 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -2607,7 +2607,6 @@ QDateTimePrivate::QDateTimePrivate(const QDate &toDate, const QTime &toTime, void QDateTimePrivate::setTimeSpec(Qt::TimeSpec spec, int offsetSeconds) { clearValidDateTime(); - clearTimeZoneCached(); clearSetToDaylightStatus(); #ifndef QT_BOOTSTRAPPED @@ -2707,27 +2706,44 @@ QDateTimePrivate::DaylightStatus QDateTimePrivate::daylightStatus() const return UnknownDaylightTime; } +qint64 QDateTimePrivate::toMSecsSinceEpoch() const +{ + switch (m_spec) { + case Qt::OffsetFromUTC: + case Qt::UTC: + return (m_msecs - (m_offsetFromUtc * 1000)); + + case Qt::LocalTime: + // recalculate the local timezone + return localMSecsToEpochMSecs(m_msecs); + + case Qt::TimeZone: +#ifndef QT_BOOTSTRAPPED + return zoneMSecsToEpochMSecs(m_msecs, m_timeZone); +#endif + break; + } + Q_UNREACHABLE(); + return 0; +} + // Check the UTC / offsetFromUTC validity void QDateTimePrivate::checkValidDateTime() { switch (m_spec) { case Qt::OffsetFromUTC: case Qt::UTC: + // for these, a valid date and a valid time imply a valid QDateTime if (isValidDate() && isValidTime()) setValidDateTime(); else clearValidDateTime(); break; case Qt::TimeZone: - // Defer checking until required as can be expensive - clearValidDateTime(); - clearTimeZoneCached(); - m_offsetFromUtc = 0; - break; case Qt::LocalTime: - // Defer checking until required as can be expensive - clearValidDateTime(); - m_offsetFromUtc = 0; + // for these, we need to check whether the timezone is valid and whether + // the time is valid in that timezone. Expensive, but no other option. + refreshDateTime(); break; } } @@ -2741,12 +2757,6 @@ void QDateTimePrivate::refreshDateTime() // Always set by setDateTime so just return return; case Qt::TimeZone: - // If already cached then don't need to refresh as tz won't change - if (isTimeZoneCached()) - return; - // Flag that will have a cached result after calculations - setTimeZoneCached(); - break; case Qt::LocalTime: break; } @@ -3082,7 +3092,6 @@ bool QDateTime::isNull() const bool QDateTime::isValid() const { - d->refreshDateTime(); return (d->isValidDateTime()); } @@ -3143,13 +3152,11 @@ Qt::TimeSpec QDateTime::timeSpec() const QTimeZone QDateTime::timeZone() const { switch (d->m_spec) { - case Qt::OffsetFromUTC: - if (!d->m_timeZone.isValid()) - d->m_timeZone = QTimeZone(d->m_offsetFromUtc); - return d->m_timeZone; case Qt::UTC: return QTimeZone::utc(); + case Qt::OffsetFromUTC: case Qt::TimeZone: + Q_ASSERT(d->m_timeZone.isValid()); return d->m_timeZone; case Qt::LocalTime: return QTimeZone::systemTimeZone(); @@ -3178,7 +3185,6 @@ QTimeZone QDateTime::timeZone() const int QDateTime::offsetFromUtc() const { - d->refreshDateTime(); return d->m_offsetFromUtc; } @@ -3350,7 +3356,7 @@ void QDateTime::setTimeZone(const QTimeZone &toZone) d->m_spec = Qt::TimeZone; d->m_offsetFromUtc = 0; d->m_timeZone = toZone; - d->m_status = d->m_status & ~QDateTimePrivate::ValidDateTime & ~QDateTimePrivate::TimeZoneCached; + d->refreshDateTime(); } #endif // QT_BOOTSTRAPPED @@ -3371,7 +3377,6 @@ void QDateTime::setTimeZone(const QTimeZone &toZone) */ qint64 QDateTime::toMSecsSinceEpoch() const { - d->refreshDateTime(); return d->toMSecsSinceEpoch(); } @@ -3453,8 +3458,8 @@ void QDateTime::setMSecsSinceEpoch(qint64 msecs) d->m_status = d->m_status | QDateTimePrivate::ValidDate | QDateTimePrivate::ValidTime - | QDateTimePrivate::ValidDateTime - | QDateTimePrivate::TimeZoneCached; + | QDateTimePrivate::ValidDateTime; + d->refreshDateTime(); #endif // QT_BOOTSTRAPPED break; case Qt::LocalTime: { diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h index 784aced71a..88288872df 100644 --- a/src/corelib/tools/qdatetime.h +++ b/src/corelib/tools/qdatetime.h @@ -326,7 +326,7 @@ private: // ### Qt6: Using a private here has high impact on runtime // on users such as QFileInfo. In Qt 6, the data members // should be inlined. - QExplicitlySharedDataPointer d; + QSharedDataPointer d; #ifndef QT_NO_DATASTREAM friend Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QDateTime &); diff --git a/src/corelib/tools/qdatetime_p.h b/src/corelib/tools/qdatetime_p.h index a139390a9d..b8934f7f70 100644 --- a/src/corelib/tools/qdatetime_p.h +++ b/src/corelib/tools/qdatetime_p.h @@ -79,10 +79,9 @@ public: enum StatusFlag { NullDate = 0x01, NullTime = 0x02, - ValidDate = 0x04, - ValidTime = 0x08, - ValidDateTime = 0x10, - TimeZoneCached = 0x20, + ValidDate = 0x04, // just the date field + ValidTime = 0x08, // just the time field + ValidDateTime = 0x10, // the whole object (including timezone) SetToStandardTime = 0x40, SetToDaylightTime = 0x80 }; @@ -120,7 +119,7 @@ public: DaylightStatus daylightStatus() const; // Returns msecs since epoch, assumes offset value is current - inline qint64 toMSecsSinceEpoch() const { return (m_msecs - (m_offsetFromUtc * 1000)); } + inline qint64 toMSecsSinceEpoch() const; void checkValidDateTime(); void refreshDateTime(); @@ -133,14 +132,11 @@ public: inline bool isValidDateTime() const { return m_status & ValidDateTime; } inline void setValidDateTime() { m_status |= ValidDateTime; } inline void clearValidDateTime() { m_status &= ~ValidDateTime; } - inline bool isTimeZoneCached() const { return m_status & TimeZoneCached; } - inline void setTimeZoneCached() { m_status |= TimeZoneCached; } - inline void clearTimeZoneCached() { m_status &= ~TimeZoneCached; } inline void clearSetToDaylightStatus() { m_status &= ~(SetToStandardTime | SetToDaylightTime); } #ifndef QT_BOOTSTRAPPED static qint64 zoneMSecsToEpochMSecs(qint64 msecs, const QTimeZone &zone, - QDate *localDate, QTime *localTime); + QDate *localDate = 0, QTime *localTime = 0); #endif // QT_BOOTSTRAPPED static inline qint64 minJd() { return QDate::minJd(); } diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp index c6806086d3..446e56e936 100644 --- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp @@ -142,6 +142,9 @@ private slots: void isDaylightTime() const; void daylightTransitions() const; void timeZones() const; +#if defined(Q_OS_UNIX) + void systemTimeZoneChange() const; +#endif void invalid() const; @@ -2984,6 +2987,56 @@ void tst_QDateTime::timeZones() const QCOMPARE(future.offsetFromUtc(), 28800); } +#if defined(Q_OS_UNIX) +// Currently disabled on Windows as adjusting the timezone +// requires additional privileges that aren't normally +// enabled for a process. This can be achieved by calling +// AdjustTokenPrivileges() and then SetTimeZoneInformation(), +// which will require linking to a different library to access that API. +static void setTimeZone(const QByteArray &tz) +{ + qputenv("TZ", tz); + ::tzset(); + +// following left for future reference, see comment above +// #if defined(Q_OS_WIN32) +// ::_tzset(); +// #endif +} + +void tst_QDateTime::systemTimeZoneChange() const +{ + struct ResetTZ { + QByteArray original; + ResetTZ() : original(qgetenv("TZ")) {} + ~ResetTZ() { setTimeZone(original); } + } scopedReset; + + // Set the timezone to Brisbane time + setTimeZone(QByteArray("AEST-10:00")); + + QDateTime localDate = QDateTime(QDate(2012, 6, 1), QTime(2, 15, 30), Qt::LocalTime); + QDateTime utcDate = QDateTime(QDate(2012, 6, 1), QTime(2, 15, 30), Qt::UTC); + QDateTime tzDate = QDateTime(QDate(2012, 6, 1), QTime(2, 15, 30), QTimeZone("Australia/Brisbane")); + qint64 localMsecs = localDate.toMSecsSinceEpoch(); + qint64 utcMsecs = utcDate.toMSecsSinceEpoch(); + qint64 tzMsecs = tzDate.toMSecsSinceEpoch(); + + // check that Australia/Brisbane is known + QVERIFY(tzDate.timeZone().isValid()); + + // Change to Indian time + setTimeZone(QByteArray("IST-05:30")); + + QCOMPARE(localDate, QDateTime(QDate(2012, 6, 1), QTime(2, 15, 30), Qt::LocalTime)); + QVERIFY(localMsecs != localDate.toMSecsSinceEpoch()); + QCOMPARE(utcDate, QDateTime(QDate(2012, 6, 1), QTime(2, 15, 30), Qt::UTC)); + QCOMPARE(utcDate.toMSecsSinceEpoch(), utcMsecs); + QCOMPARE(tzDate, QDateTime(QDate(2012, 6, 1), QTime(2, 15, 30), QTimeZone("Australia/Brisbane"))); + QCOMPARE(tzDate.toMSecsSinceEpoch(), tzMsecs); +} +#endif + void tst_QDateTime::invalid() const { QDateTime invalidDate = QDateTime(QDate(0, 0, 0), QTime(-1, -1, -1)); -- cgit v1.2.3 From 53ce0d1a31c8ebb54952887b8bcf769843d50d9c Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 4 Mar 2015 09:33:42 -0800 Subject: QStringAlgorithms::simplified_helper: add missing check for detached Otherwise, we modify shared strings that happened to be rvalues. Task-number: QTBUG-44706 Change-Id: Ia0aac2f09e9245339951ffff13c85bfc912f03d1 Reviewed-by: Friedemann Kleint --- src/corelib/tools/qstringalgorithms_p.h | 2 +- tests/auto/corelib/tools/qstring/tst_qstring.cpp | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/corelib/tools/qstringalgorithms_p.h b/src/corelib/tools/qstringalgorithms_p.h index 1481b194eb..b4be5c7ec7 100644 --- a/src/corelib/tools/qstringalgorithms_p.h +++ b/src/corelib/tools/qstringalgorithms_p.h @@ -114,7 +114,7 @@ template struct QStringAlgorithms return str; const Char *src = str.cbegin(); const Char *end = str.cend(); - NakedStringType result = isConst ? + NakedStringType result = isConst || !str.isDetached() ? StringType(str.size(), Qt::Uninitialized) : qMove(str); diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp index 52c3e65a24..8cd9610542 100644 --- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp @@ -2040,6 +2040,9 @@ void tst_QString::simplified() QFETCH(QString, full); QFETCH(QString, simple); + QString orig_full = full; + orig_full.data(); // forces a detach + QString result = full.simplified(); if (simple.isNull()) { QVERIFY2(result.isNull(), qPrintable("'" + full + "' did not yield null: " + result)); @@ -2048,6 +2051,12 @@ void tst_QString::simplified() } else { QCOMPARE(result, simple); } + QCOMPARE(full, orig_full); + + // without detaching: + QString copy1 = full; + QCOMPARE(qMove(full).simplified(), simple); + QCOMPARE(full, orig_full); // force a detach if (!full.isEmpty()) -- cgit v1.2.3 From 1cd8d67d5f9bb0cd17147481544db8fb9342354d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 5 Mar 2015 23:40:29 -0800 Subject: Fix NTLM possible data corruption A mistake in const correctness resulted in the incoming QByteArray getting modified when it shouldn't. I have no ldea if this could result in user-visible effects. Change-Id: Ia0aac2f09e9245339951ffff13c8d8c6b4f909bd Reviewed-by: Richard J. Moore --- src/network/kernel/qauthenticator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp index d31c04eb87..abb47e9e29 100644 --- a/src/network/kernel/qauthenticator.cpp +++ b/src/network/kernel/qauthenticator.cpp @@ -1078,7 +1078,7 @@ static QByteArray qStringAsUcs2Le(const QString& src) } -static QString qStringFromUcs2Le(const QByteArray& src) +static QString qStringFromUcs2Le(QByteArray src) { Q_ASSERT(src.size() % 2 == 0); unsigned short *d = (unsigned short*)src.data(); -- cgit v1.2.3