diff --git a/config.tests/arch/arch.cpp b/config.tests/arch/arch.cpp index 7e481d4cf5..c4f23f7bcd 100644 --- a/config.tests/arch/arch.cpp +++ b/config.tests/arch/arch.cpp @@ -237,7 +237,7 @@ const char msg2[] = "==Qt=magic=Qt== Sub-architecture:" #endif // -- ARM -- -#ifdef __ARM_NEON__ +#if defined(__ARM_NEON) || defined(__ARM_NEON__) " neon" #endif #ifdef __IWMMXT__ diff --git a/configure b/configure index 5873112a16..b65519cce9 100755 --- a/configure +++ b/configure @@ -455,7 +455,7 @@ DeviceVar() eq="=" ;; *) - echo >&2 "BUG: wrong command to QMakeVar: $1" + echo >&2 "BUG: wrong command to DeviceVar: $1" ;; esac @@ -7203,7 +7203,7 @@ if [ -n "$DISABLED_FEATURES" ]; then fi echo "QT_QCONFIG_PATH = ${CFG_QCONFIG_PATH#$relpath/src/corelib/global/}" -cat >>"$QTMODULE.tmp" < #define QT_FUNCTION_TARGET_STRING_ARM_NEON "neon" +#ifndef __ARM_NEON__ +// __ARM_NEON__ is not defined on AArch64, but we need it in our NEON detection. +#define __ARM_NEON__ +#endif #endif #undef QT_COMPILER_SUPPORTS_SIMD_ALWAYS diff --git a/src/gui/doc/snippets/qfileopenevent/Info.plist b/src/gui/doc/snippets/qfileopenevent/Info.plist new file mode 100644 index 0000000000..6b8039bc7d --- /dev/null +++ b/src/gui/doc/snippets/qfileopenevent/Info.plist @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Samuel Gaist +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [Custom Info.plist] + + + + + CFBundleDocumentTypes + + + CFBundleTypeExtensions + + png + + CFBundleTypeRole + Viewer + + + + +//! [Custom Info.plist] \ No newline at end of file diff --git a/src/gui/doc/snippets/qfileopenevent/main.cpp b/src/gui/doc/snippets/qfileopenevent/main.cpp new file mode 100644 index 0000000000..3fd1757bd7 --- /dev/null +++ b/src/gui/doc/snippets/qfileopenevent/main.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Samuel Gaist +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +//! [QApplication subclass] +#include +#include +#include + +class MyApplication : public QApplication +{ +public: + MyApplication(int &argc, char **argv) + : QApplication(argc, argv) + { + } + + bool event(QEvent *event) + { + if (event->type() == QEvent::FileOpen) { + QFileOpenEvent *openEvent = static_cast(event); + qDebug() << "Open file" << openEvent->file(); + } + + return QApplication::event(event); + } +}; +//! [QApplication subclass] + +int main(int argc, char *argv[]) +{ + MyApplication app(argc, argv); + QPushButton closeButton("Quit"); + QObject::connect(&closeButton, &QPushButton::clicked, &app, &QApplication::quit); + closeButton.show(); + return app.exec(); +} diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp index 02f32aa34b..7d1fb23b15 100644 --- a/src/gui/image/qimage_conversions.cpp +++ b/src/gui/image/qimage_conversions.cpp @@ -375,7 +375,32 @@ static void convert_RGB888_to_RGB(QImageData *dest, const QImageData *src, Qt::I } } +#ifdef __SSE2__ extern bool convert_ARGB_to_ARGB_PM_inplace_sse2(QImageData *data, Qt::ImageConversionFlags); +#else +static bool convert_ARGB_to_ARGB_PM_inplace(QImageData *data,Qt::ImageConversionFlags) +{ + Q_ASSERT(data->format == QImage::Format_ARGB32 || data->format == QImage::Format_RGBA8888); + + const int pad = (data->bytes_per_line >> 2) - data->width; + QRgb *rgb_data = (QRgb *) data->data; + + for (int i = 0; i < data->height; ++i) { + const QRgb *end = rgb_data + data->width; + while (rgb_data < end) { + *rgb_data = qPremultiply(*rgb_data); + ++rgb_data; + } + rgb_data += pad; + } + + if (data->format == QImage::Format_ARGB32) + data->format = QImage::Format_ARGB32_Premultiplied; + else + data->format = QImage::Format_RGBA8888_Premultiplied; + return true; +} +#endif static void convert_ARGB_to_RGBx(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) { @@ -2592,7 +2617,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma #ifdef __SSE2__ convert_ARGB_to_ARGB_PM_inplace_sse2, #else - 0, + convert_ARGB_to_ARGB_PM_inplace, #endif 0, 0, @@ -2705,12 +2730,13 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma 0, 0, mask_alpha_converter_rgbx_inplace, -#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN && __SSE2__ 0, +#ifdef __SSE2__ convert_ARGB_to_ARGB_PM_inplace_sse2, +#elif Q_BYTE_ORDER == Q_LITTLE_ENDIAN + convert_ARGB_to_ARGB_PM_inplace, #else 0, - 0, #endif 0, 0, 0, 0, 0, 0 }, // Format_RGBA8888 @@ -2921,7 +2947,7 @@ void qInitImageConversions() } #endif -#if defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64) +#if defined(__ARM_NEON__) extern void convert_RGB888_to_RGB32_neon(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags); qimage_converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_neon; qimage_converter_map[QImage::Format_RGB888][QImage::Format_ARGB32] = convert_RGB888_to_RGB32_neon; diff --git a/src/gui/image/qimage_neon.cpp b/src/gui/image/qimage_neon.cpp index b51c43aa9d..5853510ee1 100644 --- a/src/gui/image/qimage_neon.cpp +++ b/src/gui/image/qimage_neon.cpp @@ -35,7 +35,7 @@ #include #include -#if defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64) +#if defined(__ARM_NEON__) QT_BEGIN_NAMESPACE @@ -55,6 +55,7 @@ Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_neon(quint32 *dst, cons if ((len - offsetToAlignOn8Bytes) >= 8) { const quint32 *const simdEnd = end - 7; +#if !defined(Q_PROCESSOR_ARM_64) register uint8x8_t fullVector asm ("d3") = vdup_n_u8(0xff); do { #if Q_BYTE_ORDER == Q_BIG_ENDIAN @@ -76,6 +77,31 @@ Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_neon(quint32 *dst, cons ); #endif } while (dst < simdEnd); +#else + register uint8x8_t fullVector asm ("v3") = vdup_n_u8(0xff); + do { +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + asm volatile ( + "ld3 { v4.8b, v5.8b, v6.8b }, [%[SRC]], #24 \n\t" + "st4 { v3.8b, v4.8b, v5.8b, v6.8b }, [%[DST]], #32 \n\t" + : [DST]"+r" (dst), [SRC]"+r" (src) + : "w"(fullVector) + : "memory", "v4", "v5", "v6" + ); +#else + asm volatile ( + "ld3 { v0.8b, v1.8b, v2.8b }, [%[SRC]], #24 \n\t" + "mov v4.8b, v2.8b\n\t" + "mov v2.8b, v0.8b\n\t" + "mov v0.8b, v4.8b\n\t" + "st4 { v0.8b, v1.8b, v2.8b, v3.8b }, [%[DST]], #32 \n\t" + : [DST]"+r" (dst), [SRC]"+r" (src) + : "w"(fullVector) + : "memory", "v0", "v1", "v2", "v4" + ); +#endif + } while (dst < simdEnd); +#endif } while (dst != end) { @@ -103,4 +129,4 @@ void convert_RGB888_to_RGB32_neon(QImageData *dest, const QImageData *src, Qt::I QT_END_NAMESPACE -#endif // defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64) +#endif // defined(__ARM_NEON__) diff --git a/src/gui/image/qjpeghandler.cpp b/src/gui/image/qjpeghandler.cpp index 7e9483e6f7..68709b708d 100644 --- a/src/gui/image/qjpeghandler.cpp +++ b/src/gui/image/qjpeghandler.cpp @@ -978,9 +978,8 @@ extern "C" void qt_convert_rgb888_to_rgb32_mips_dspr2_asm(quint32 *dst, const uc QJpegHandler::QJpegHandler() : d(new QJpegHandlerPrivate(this)) { -#if defined(__ARM_NEON__) && !defined(Q_PROCESSOR_ARM_64) +#if defined(__ARM_NEON__) // from qimage_neon.cpp - if (qCpuHasFeature(NEON)) d->rgb888ToRgb32ConverterPtr = qt_convert_rgb888_to_rgb32_neon; #endif diff --git a/src/gui/image/qpnghandler.cpp b/src/gui/image/qpnghandler.cpp index 776a61d8fe..e9944e1750 100644 --- a/src/gui/image/qpnghandler.cpp +++ b/src/gui/image/qpnghandler.cpp @@ -43,13 +43,8 @@ #include #include -#ifdef QT_USE_BUNDLED_LIBPNG -#include <../../3rdparty/libpng/png.h> -#include <../../3rdparty/libpng/pngconf.h> -#else #include #include -#endif #if PNG_LIBPNG_VER >= 10400 && PNG_LIBPNG_VER <= 10502 \ && defined(PNG_PEDANTIC_WARNINGS_SUPPORTED) diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 233b9ef3f7..bd1b4d6393 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -3418,6 +3418,21 @@ QShowEvent::~QShowEvent() It may be safely ignored. \note This class is currently supported for OS X only. + + \section1 OS X Example + + In order to trigger the event on OS X, the application must be configured + to let the OS know what kind of file(s) it should react on. + + For example, the following \c Info.plist file declares that the application + can act as a viewer for files with a PNG extension: + + \snippet qfileopenevent/Info.plist Custom Info.plist + + The following implementation of a QApplication subclass prints the path to + the file that was, for example, dropped on the Dock icon of the application. + + \snippet qfileopenevent/main.cpp QApplication subclass */ /*! diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 2e2532a25f..fd9ae0aaca 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -101,7 +101,7 @@ SSE4_1_SOURCES += painting/qdrawhelper_sse4.cpp \ painting/qimagescale_sse4.cpp AVX2_SOURCES += painting/qdrawhelper_avx2.cpp -!ios { +!ios:!contains(QT_ARCH, "arm64") { CONFIG += no_clang_integrated_as NEON_SOURCES += painting/qdrawhelper_neon.cpp NEON_HEADERS += painting/qdrawhelper_neon_p.h diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp index 52843fa113..988bee9b27 100644 --- a/src/gui/painting/qdrawhelper.cpp +++ b/src/gui/painting/qdrawhelper.cpp @@ -6309,7 +6309,7 @@ void qt_memfill16(quint16 *dest, quint16 color, int count) qt_memfill_template(dest, color, count); } #endif -#if !defined(__SSE2__) && !defined(__ARM_NEON__) +#if !defined(__SSE2__) && (!defined(__ARM_NEON__) || defined(Q_PROCESSOR_ARM_64)) # ifdef QT_COMPILER_SUPPORTS_MIPS_DSP extern "C" void qt_memfill32_asm_mips_dsp(quint32 *, quint32, int); # endif @@ -6425,7 +6425,7 @@ void qInitDrawhelperAsm() #endif // SSE2 -#if defined(__ARM_NEON__) && !defined(Q_OS_IOS) +#if defined(__ARM_NEON__) && !defined(Q_OS_IOS) && !defined(Q_PROCESSOR_ARM_64) qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon; qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32_neon; qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32_neon; diff --git a/src/gui/painting/qdrawhelper_neon.cpp b/src/gui/painting/qdrawhelper_neon.cpp index 08e564f017..bf4758afd2 100644 --- a/src/gui/painting/qdrawhelper_neon.cpp +++ b/src/gui/painting/qdrawhelper_neon.cpp @@ -31,15 +31,13 @@ ** ****************************************************************************/ -#include +#include #include #include #ifdef __ARM_NEON__ -#include #include -#include QT_BEGIN_NAMESPACE diff --git a/src/gui/painting/qrgb.h b/src/gui/painting/qrgb.h index f7f2185bef..ca9fc03d14 100644 --- a/src/gui/painting/qrgb.h +++ b/src/gui/painting/qrgb.h @@ -58,10 +58,10 @@ inline Q_DECL_CONSTEXPR int qAlpha(QRgb rgb) // get alpha part of { return rgb >> 24; } inline Q_DECL_CONSTEXPR QRgb qRgb(int r, int g, int b)// set RGB value -{ return (0xffu << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff); } +{ return (0xffu << 24) | ((r & 0xffu) << 16) | ((g & 0xffu) << 8) | (b & 0xffu); } inline Q_DECL_CONSTEXPR QRgb qRgba(int r, int g, int b, int a)// set RGBA value -{ return ((a & 0xff) << 24) | ((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff); } +{ return ((a & 0xffu) << 24) | ((r & 0xffu) << 16) | ((g & 0xffu) << 8) | (b & 0xffu); } inline Q_DECL_CONSTEXPR int qGray(int r, int g, int b)// convert R,G,B to gray 0..255 { return (r*11+g*16+b*5)/32; } diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 68747ad6ad..746a51318e 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -918,10 +918,11 @@ void QTextEngine::shapeLine(const QScriptLine &line) { QFixed x; bool first = true; - const int end = findItem(line.from + line.length - 1); int item = findItem(line.from); if (item == -1) return; + + const int end = findItem(line.from + line.length - 1, item); for ( ; item <= end; ++item) { QScriptItem &si = layoutData->items[item]; if (si.analysis.flags == QScriptAnalysis::Tab) { @@ -1747,13 +1748,13 @@ bool QTextEngine::isRightToLeft() const } -int QTextEngine::findItem(int strPos) const +int QTextEngine::findItem(int strPos, int firstItem) const { itemize(); - if (strPos < 0 || strPos >= layoutData->string.size()) + if (strPos < 0 || strPos >= layoutData->string.size() || firstItem < 0) return -1; - int left = 1; + int left = firstItem + 1; int right = layoutData->items.size()-1; while(left <= right) { int middle = ((right-left)/2)+left; @@ -2172,7 +2173,7 @@ void QTextEngine::justify(const QScriptLine &line) return; int firstItem = findItem(line.from); - int lastItem = findItem(line.from + line_length - 1); + int lastItem = findItem(line.from + line_length - 1, firstItem); int nItems = (firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0; QVarLengthArray justificationPoints; @@ -3529,7 +3530,7 @@ QTextLineItemIterator::QTextLineItemIterator(QTextEngine *_eng, int _lineNum, co lineNum(_lineNum), lineEnd(line.from + line.length), firstItem(eng->findItem(line.from)), - lastItem(eng->findItem(lineEnd - 1)), + lastItem(eng->findItem(lineEnd - 1, firstItem)), nItems((firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0), logicalItem(-1), item(-1), diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index dbe8e1ee2b..39c228fd52 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -512,7 +512,7 @@ public: void freeMemory(); - int findItem(int strPos) const; + int findItem(int strPos, int firstItem = 0) const; inline QTextFormatCollection *formatCollection() const { if (block.docHandle()) return block.docHandle()->formatCollection(); diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 9f046af47c..65650504ac 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -2624,26 +2624,24 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR */ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const { - if (!eng->layoutData) - eng->itemize(); - const QScriptLine &line = eng->lines[index]; bool lastLine = index >= eng->lines.size() - 1; - QFixed x = line.x; - x += eng->alignLine(line) - eng->leadingSpaceWidth(line); + QFixed x = line.x + eng->alignLine(line) - eng->leadingSpaceWidth(line); - if (!index && !eng->layoutData->items.size()) { - *cursorPos = 0; + if (!eng->layoutData) + eng->itemize(); + if (!eng->layoutData->items.size()) { + *cursorPos = line.from; return x.toReal(); } int lineEnd = line.from + line.length + line.trailingSpaces; - int pos = qBound(0, *cursorPos, lineEnd); + int pos = qBound(line.from, *cursorPos, lineEnd); int itm; const QCharAttributes *attributes = eng->attributes(); if (!attributes) { - *cursorPos = 0; + *cursorPos = line.from; return x.toReal(); } while (pos < lineEnd && !attributes[pos].graphemeBoundary) @@ -2655,7 +2653,7 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const else itm = eng->findItem(pos); if (itm < 0) { - *cursorPos = 0; + *cursorPos = line.from; return x.toReal(); } eng->shapeLine(line); @@ -2663,18 +2661,14 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const const QScriptItem *si = &eng->layoutData->items[itm]; if (!si->num_glyphs) eng->shape(itm); - pos -= si->position; + + const int l = eng->length(itm); + pos = qBound(0, pos - si->position, l); QGlyphLayout glyphs = eng->shapedGlyphs(si); unsigned short *logClusters = eng->logClusters(si); Q_ASSERT(logClusters); - int l = eng->length(itm); - if (pos > l) - pos = l; - if (pos < 0) - pos = 0; - int glyph_pos = pos == l ? si->num_glyphs : logClusters[pos]; if (edge == Trailing && glyph_pos < si->num_glyphs) { // trailing edge is leading edge of next cluster @@ -2683,13 +2677,13 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const glyph_pos++; } - bool reverse = eng->layoutData->items[itm].analysis.bidiLevel % 2; + bool reverse = si->analysis.bidiLevel % 2; // add the items left of the cursor int firstItem = eng->findItem(line.from); - int lastItem = eng->findItem(lineEnd - 1); + int lastItem = eng->findItem(lineEnd - 1, itm); int nItems = (firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0; QVarLengthArray visualOrder(nItems); @@ -2710,13 +2704,15 @@ qreal QTextLine::cursorToX(int *cursorPos, Edge edge) const x += si.width; continue; } + + const int itemLength = eng->length(item); int start = qMax(line.from, si.position); - int end = qMin(lineEnd, si.position + eng->length(item)); + int end = qMin(lineEnd, si.position + itemLength); logClusters = eng->logClusters(&si); int gs = logClusters[start-si.position]; - int ge = (end == si.position + eng->length(item)) ? si.num_glyphs-1 : logClusters[end-si.position-1]; + int ge = (end == si.position + itemLength) ? si.num_glyphs-1 : logClusters[end-si.position-1]; QGlyphLayout glyphs = eng->shapedGlyphs(&si); @@ -2788,7 +2784,7 @@ int QTextLine::xToCursor(qreal _x, CursorPosition cpos) const return line.from; int firstItem = eng->findItem(line.from); - int lastItem = eng->findItem(line.from + line_length - 1); + int lastItem = eng->findItem(line.from + line_length - 1, firstItem); int nItems = (firstItem >= 0 && lastItem >= firstItem)? (lastItem-firstItem+1) : 0; if (!nItems) diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index 2a39fc1bbd..02217a7179 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -717,15 +717,19 @@ QStringList QFontconfigDatabase::fallbacksForFamily(const QString &family, QFont FcPatternDestroy(pattern); if (fontSet) { + QSet duplicates; + duplicates.reserve(fontSet->nfont + 1); + duplicates.insert(family.toCaseFolded()); for (int i = 0; i < fontSet->nfont; i++) { FcChar8 *value = 0; if (FcPatternGetString(fontSet->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch) continue; // capitalize(value); - QString familyName = QString::fromUtf8((const char *)value); - if (!fallbackFamilies.contains(familyName,Qt::CaseInsensitive) && - familyName.compare(family, Qt::CaseInsensitive)) { + const QString familyName = QString::fromUtf8((const char *)value); + const QString familyNameCF = familyName.toCaseFolded(); + if (!duplicates.contains(familyNameCF)) { fallbackFamilies << familyName; + duplicates.insert(familyNameCF); } } FcFontSetDestroy(fontSet); diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index e754855e7f..a3541829c6 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -99,6 +99,7 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper)); - (void)textInputContextKeyboardSelectionDidChangeNotification : (NSNotification *) textInputContextKeyboardSelectionDidChangeNotification; - (void)viewDidHide; - (void)viewDidUnhide; +- (void)removeFromSuperview; - (BOOL)isFlipped; - (BOOL)acceptsFirstResponder; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index f414193bdb..3faa292ae0 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -498,6 +498,12 @@ QT_WARNING_POP m_platformWindow->exposeWindow(); } +- (void)removeFromSuperview +{ + QMacAutoReleasePool pool; + [super removeFromSuperview]; +} + - (void) flushBackingStore:(QCocoaBackingStore *)backingStore region:(const QRegion &)region offset:(QPoint)offset { m_backingStore = backingStore; diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.pro b/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.pro index 98797e2106..2026b6a6c6 100644 --- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.pro +++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_brcm/eglfs_brcm.pro @@ -12,6 +12,9 @@ CONFIG += egl LIBS += -lbcm_host QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF +# Avoid X11 header collision +DEFINES += MESA_EGL_NO_X11_HEADERS + SOURCES += $$PWD/qeglfsbrcmmain.cpp \ $$PWD/qeglfsbrcmintegration.cpp diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm index eaff0daf19..0e3da8dce8 100644 --- a/src/plugins/platforms/ios/qiosintegration.mm +++ b/src/plugins/platforms/ios/qiosintegration.mm @@ -89,10 +89,11 @@ QIOSIntegration::QIOSIntegration() // Set current directory to app bundle folder QDir::setCurrent(QString::fromUtf8([[[NSBundle mainBundle] bundlePath] UTF8String])); + UIScreen *mainScreen = [UIScreen mainScreen]; NSMutableArray *screens = [[[UIScreen screens] mutableCopy] autorelease]; - if (![screens containsObject:[UIScreen mainScreen]]) { + if (![screens containsObject:mainScreen]) { // Fallback for iOS 7.1 (QTBUG-42345) - [screens insertObject:[UIScreen mainScreen] atIndex:0]; + [screens insertObject:mainScreen atIndex:0]; } for (UIScreen *screen in screens) @@ -103,7 +104,10 @@ QIOSIntegration::QIOSIntegration() m_touchDevice = new QTouchDevice; m_touchDevice->setType(QTouchDevice::TouchScreen); - m_touchDevice->setCapabilities(QTouchDevice::Position | QTouchDevice::NormalizedPosition); + QTouchDevice::Capabilities touchCapabilities = QTouchDevice::Position | QTouchDevice::NormalizedPosition; + if (mainScreen.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) + touchCapabilities |= QTouchDevice::Pressure; + m_touchDevice->setCapabilities(touchCapabilities); QWindowSystemInterface::registerTouchDevice(m_touchDevice); QMacInternalPasteboardMime::initializeMimeTypes(); } diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index c6ef843b9f..53b3d30327 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -280,6 +280,19 @@ // ------------------------------------------------------------------------- +- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection +{ + [super traitCollectionDidChange: previousTraitCollection]; + + QTouchDevice *touchDevice = QIOSIntegration::instance()->touchDevice(); + QTouchDevice::Capabilities touchCapabilities = touchDevice->capabilities(); + if (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable) + touchCapabilities |= QTouchDevice::Pressure; + else + touchCapabilities &= ~QTouchDevice::Pressure; + touchDevice->setCapabilities(touchCapabilities); +} + -(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event { if (m_qioswindow->window()->flags() & Qt::WindowTransparentForInput) @@ -289,6 +302,8 @@ - (void)updateTouchList:(NSSet *)touches withState:(Qt::TouchPointState)state { + bool supportsPressure = QIOSIntegration::instance()->touchDevice()->capabilities() & QTouchDevice::Pressure; + foreach (UITouch *uiTouch, m_activeTouches.keys()) { QWindowSystemInterface::TouchPoint &touchPoint = m_activeTouches[uiTouch]; if (![touches containsObject:uiTouch]) { @@ -309,9 +324,17 @@ touchPoint.normalPosition = QPointF(globalScreenPosition.x() / screenSize.width(), globalScreenPosition.y() / screenSize.height()); - // We don't claim that our touch device supports QTouchDevice::Pressure, - // but fill in a meaningfull value in case clients use it anyways. - touchPoint.pressure = (state == Qt::TouchPointReleased) ? 0.0 : 1.0; + if (supportsPressure) { + // Note: iOS will deliver touchesBegan with a touch force of 0, which + // we will reflect/propagate as a 0 pressure, but there is no clear + // alternative, as we don't want to wait for a touchedMoved before + // sending a touch press event to Qt, just to have a valid pressure. + touchPoint.pressure = uiTouch.force / uiTouch.maximumPossibleForce; + } else { + // We don't claim that our touch device supports QTouchDevice::Pressure, + // but fill in a meaningfull value in case clients use it anyways. + touchPoint.pressure = (state == Qt::TouchPointReleased) ? 0.0 : 1.0; + } } } } diff --git a/src/plugins/platforms/mirclient/qmirclientplugin.cpp b/src/plugins/platforms/mirclient/qmirclientplugin.cpp index 43d913f8d2..203a1cbfd8 100644 --- a/src/plugins/platforms/mirclient/qmirclientplugin.cpp +++ b/src/plugins/platforms/mirclient/qmirclientplugin.cpp @@ -49,11 +49,6 @@ QPlatformIntegration* QMirClientIntegrationPlugin::create(const QString &system, const QStringList &) { if (system.toLower() == "mirclient") { -#ifdef PLATFORM_API_TOUCH - setenv("UBUNTU_PLATFORM_API_BACKEND", "touch_mirclient", 1); -#else - setenv("UBUNTU_PLATFORM_API_BACKEND", "desktop_mirclient", 1); -#endif return new QMirClientClientIntegration; } else { return 0; diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp index 800b79347c..c769eb04a4 100644 --- a/src/plugins/platforms/windows/qwindowscursor.cpp +++ b/src/plugins/platforms/windows/qwindowscursor.cpp @@ -43,15 +43,17 @@ #include #include #include // getPixmapCursor() +#include #include #include -static void initResources() +static bool initResources() { #if !defined (Q_OS_WINCE) && !defined (QT_NO_IMAGEFORMAT_PNG) Q_INIT_RESOURCE(cursors); #endif + return true; } QT_BEGIN_NAMESPACE @@ -92,9 +94,14 @@ QWindowsPixmapCursorCacheKey::QWindowsPixmapCursorCacheKey(const QCursor &c) \sa QWindowsWindowCursor */ -HCURSOR QWindowsCursor::createPixmapCursor(const QPixmap &pixmap, const QPoint &hotSpot) +HCURSOR QWindowsCursor::createPixmapCursor(QPixmap pixmap, const QPoint &hotSpot, qreal scaleFactor) { HCURSOR cur = 0; + scaleFactor /= pixmap.devicePixelRatioF(); + if (!qFuzzyCompare(scaleFactor, 1)) { + pixmap = pixmap.scaled((scaleFactor * QSizeF(pixmap.size())).toSize(), + Qt::KeepAspectRatio, Qt::SmoothTransformation); + } QBitmap mask = pixmap.mask(); if (mask.isNull()) { mask = QBitmap(pixmap.size()); @@ -202,17 +209,43 @@ static HCURSOR createBitmapCursor(const QImage &bbits, const QImage &mbits, } // Create a cursor from image and mask of the format QImage::Format_Mono. -static HCURSOR createBitmapCursor(const QCursor &cursor) +static HCURSOR createBitmapCursor(const QCursor &cursor, qreal scaleFactor = 1) { Q_ASSERT(cursor.shape() == Qt::BitmapCursor && cursor.bitmap()); - const QImage bbits = cursor.bitmap()->toImage().convertToFormat(QImage::Format_Mono); - const QImage mbits = cursor.mask()->toImage().convertToFormat(QImage::Format_Mono); + QImage bbits = cursor.bitmap()->toImage(); + QImage mbits = cursor.mask()->toImage(); + scaleFactor /= bbits.devicePixelRatioF(); + if (!qFuzzyCompare(scaleFactor, 1)) { + const QSize scaledSize = (QSizeF(bbits.size()) * scaleFactor).toSize(); + bbits = bbits.scaled(scaledSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); + mbits = mbits.scaled(scaledSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); + } + bbits = bbits.convertToFormat(QImage::Format_Mono); + mbits = mbits.convertToFormat(QImage::Format_Mono); const bool invb = bbits.colorCount() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1)); const bool invm = mbits.colorCount() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1)); return createBitmapCursor(bbits, mbits, cursor.hotSpot(), invb, invm); } -static inline QSize systemCursorSize() { return QSize(GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR)); } +static QSize systemCursorSize(const QPlatformScreen *screen = Q_NULLPTR) +{ + const QSize primaryScreenCursorSize(GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR)); + if (screen) { + // Correct the size if the DPI value of the screen differs from + // that of the primary screen. + if (const QScreen *primaryQScreen = QGuiApplication::primaryScreen()) { + const QPlatformScreen *primaryScreen = primaryQScreen->handle(); + if (screen != primaryScreen) { + const qreal logicalDpi = screen->logicalDpi().first; + const qreal primaryScreenLogicalDpi = primaryScreen->logicalDpi().first; + if (!qFuzzyCompare(logicalDpi, primaryScreenLogicalDpi)) + return (QSizeF(primaryScreenCursorSize) * logicalDpi / primaryScreenLogicalDpi).toSize(); + } + } + } + return primaryScreenCursorSize; +} + static inline QSize standardCursorSize() { return QSize(32, 32); } #if defined (Q_OS_WINCE) || defined (QT_NO_IMAGEFORMAT_PNG) @@ -242,7 +275,8 @@ static QWindowsCursor::PixmapCursor createPixmapCursorFromData(const QSize &syst return QWindowsCursor::PixmapCursor(rawImage, hotSpot); } -QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape) +QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape, + const QPlatformScreen *screen) { // Non-standard Windows cursors are created from bitmaps static const uchar vsplit_bits[] = { @@ -410,13 +444,13 @@ QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursor switch (cursorShape) { case Qt::SplitVCursor: - return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 32, vsplit_bits, vsplitm_bits); + return createPixmapCursorFromData(systemCursorSize(screen), standardCursorSize(), 32, vsplit_bits, vsplitm_bits); case Qt::SplitHCursor: - return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 32, hsplit_bits, hsplitm_bits); + return createPixmapCursorFromData(systemCursorSize(screen), standardCursorSize(), 32, hsplit_bits, hsplitm_bits); case Qt::OpenHandCursor: - return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 16, openhand_bits, openhandm_bits); + return createPixmapCursorFromData(systemCursorSize(screen), standardCursorSize(), 16, openhand_bits, openhandm_bits); case Qt::ClosedHandCursor: - return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 16, closedhand_bits, closedhandm_bits); + return createPixmapCursorFromData(systemCursorSize(screen), standardCursorSize(), 16, closedhand_bits, closedhandm_bits); case Qt::DragCopyCursor: return QWindowsCursor::PixmapCursor(QPixmap(copyDragCursorXpmC), QPoint(0, 0)); case Qt::DragMoveCursor: @@ -436,7 +470,7 @@ struct QWindowsCustomPngCursor { int hotSpotY; }; -QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape) +QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape, const QPlatformScreen *screen) { static const QWindowsCustomPngCursor pngCursors[] = { { Qt::SplitVCursor, 32, "splitvcursor_32.png", 11, 11 }, @@ -462,14 +496,14 @@ QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursor { Qt::DragLinkCursor, 64, "draglinkcursor_64.png", 0, 0 } }; - const int cursorSize = GetSystemMetrics(SM_CXCURSOR); + const QSize cursorSize = systemCursorSize(screen); const QWindowsCustomPngCursor *sEnd = pngCursors + sizeof(pngCursors) / sizeof(pngCursors[0]); const QWindowsCustomPngCursor *bestFit = 0; int sizeDelta = INT_MAX; for (const QWindowsCustomPngCursor *s = pngCursors; s < sEnd; ++s) { if (s->shape != cursorShape) continue; - const int currentSizeDelta = qMax(s->size, cursorSize) - qMin(s->size, cursorSize); + const int currentSizeDelta = qMax(s->size, cursorSize.width()) - qMin(s->size, cursorSize.width()); if (currentSizeDelta < sizeDelta) { bestFit = s; if (currentSizeDelta == 0) @@ -492,7 +526,7 @@ struct QWindowsStandardCursorMapping { LPCWSTR resource; }; -HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape) +HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape, const QPlatformScreen *screen) { Q_ASSERT(cursorShape != Qt::BitmapCursor); @@ -515,7 +549,7 @@ HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape) switch (cursorShape) { case Qt::BlankCursor: { - QImage blank = QImage(systemCursorSize(), QImage::Format_Mono); + QImage blank = QImage(systemCursorSize(screen), QImage::Format_Mono); blank.fill(0); // ignore color table return createBitmapCursor(blank, blank); } @@ -526,7 +560,7 @@ HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape) case Qt::DragCopyCursor: case Qt::DragMoveCursor: case Qt::DragLinkCursor: - return QWindowsCursor::createPixmapCursor(customCursor(cursorShape)); + return QWindowsCursor::createPixmapCursor(customCursor(cursorShape, screen)); default: break; } @@ -555,7 +589,7 @@ CursorHandlePtr QWindowsCursor::standardWindowCursor(Qt::CursorShape shape) { StandardCursorCache::Iterator it = m_standardCursorCache.find(shape); if (it == m_standardCursorCache.end()) { - if (const HCURSOR hc = QWindowsCursor::createCursorFromShape(shape)) + if (const HCURSOR hc = QWindowsCursor::createCursorFromShape(shape, m_screen)) it = m_standardCursorCache.insert(shape, CursorHandlePtr(new CursorHandle(hc))); } return it != m_standardCursorCache.end() ? it.value() : CursorHandlePtr(new CursorHandle); @@ -582,17 +616,21 @@ CursorHandlePtr QWindowsCursor::pixmapWindowCursor(const QCursor &c) ++it; } } + const qreal scaleFactor = QHighDpiScaling::factor(m_screen); const QPixmap pixmap = c.pixmap(); const HCURSOR hc = pixmap.isNull() - ? createBitmapCursor(c) : QWindowsCursor::createPixmapCursor(pixmap, c.hotSpot()); + ? createBitmapCursor(c, scaleFactor) + : QWindowsCursor::createPixmapCursor(pixmap, c.hotSpot(), scaleFactor); it = m_pixmapCursorCache.insert(cacheKey, CursorHandlePtr(new CursorHandle(hc))); } return it.value(); } -QWindowsCursor::QWindowsCursor() +QWindowsCursor::QWindowsCursor(const QPlatformScreen *screen) + : m_screen(screen) { - initResources(); + static const bool dummy = initResources(); + Q_UNUSED(dummy) } /*! @@ -654,6 +692,94 @@ void QWindowsCursor::setPos(const QPoint &pos) SetCursorPos(pos.x() , pos.y()); } +QPixmap QWindowsCursor::dragDefaultCursor(Qt::DropAction action) const +{ + switch (action) { + case Qt::CopyAction: + if (m_copyDragCursor.isNull()) + m_copyDragCursor = QWindowsCursor::customCursor(Qt::DragCopyCursor, m_screen).pixmap; + return m_copyDragCursor; + case Qt::TargetMoveAction: + case Qt::MoveAction: + if (m_moveDragCursor.isNull()) + m_moveDragCursor = QWindowsCursor::customCursor(Qt::DragMoveCursor, m_screen).pixmap; + return m_moveDragCursor; + case Qt::LinkAction: + if (m_linkDragCursor.isNull()) + m_linkDragCursor = QWindowsCursor::customCursor(Qt::DragLinkCursor, m_screen).pixmap; + return m_linkDragCursor; + default: + break; + } + + static const char * const ignoreDragCursorXpmC[] = { + "24 30 3 1", + ". c None", + "a c #000000", + "X c #FFFFFF", + "aa......................", + "aXa.....................", + "aXXa....................", + "aXXXa...................", + "aXXXXa..................", + "aXXXXXa.................", + "aXXXXXXa................", + "aXXXXXXXa...............", + "aXXXXXXXXa..............", + "aXXXXXXXXXa.............", + "aXXXXXXaaaa.............", + "aXXXaXXa................", + "aXXaaXXa................", + "aXa..aXXa...............", + "aa...aXXa...............", + "a.....aXXa..............", + "......aXXa.....XXXX.....", + ".......aXXa..XXaaaaXX...", + ".......aXXa.XaaaaaaaaX..", + "........aa.XaaaXXXXaaaX.", + "...........XaaaaX..XaaX.", + "..........XaaXaaaX..XaaX", + "..........XaaXXaaaX.XaaX", + "..........XaaX.XaaaXXaaX", + "..........XaaX..XaaaXaaX", + "...........XaaX..XaaaaX.", + "...........XaaaXXXXaaaX.", + "............XaaaaaaaaX..", + ".............XXaaaaXX...", + "...............XXXX....."}; + + if (m_ignoreDragCursor.isNull()) { +#if !defined (Q_OS_WINCE) + HCURSOR cursor = LoadCursor(NULL, IDC_NO); + ICONINFO iconInfo = {0, 0, 0, 0, 0}; + GetIconInfo(cursor, &iconInfo); + BITMAP bmColor = {0, 0, 0, 0, 0, 0, 0}; + + if (iconInfo.hbmColor + && GetObject(iconInfo.hbmColor, sizeof(BITMAP), &bmColor) + && bmColor.bmWidth == bmColor.bmWidthBytes / 4) { + const int colorBitsLength = bmColor.bmHeight * bmColor.bmWidthBytes; + uchar *colorBits = new uchar[colorBitsLength]; + GetBitmapBits(iconInfo.hbmColor, colorBitsLength, colorBits); + const QImage colorImage(colorBits, bmColor.bmWidth, bmColor.bmHeight, + bmColor.bmWidthBytes, QImage::Format_ARGB32); + + m_ignoreDragCursor = QPixmap::fromImage(colorImage); + delete [] colorBits; + } else { + m_ignoreDragCursor = QPixmap(ignoreDragCursorXpmC); + } + + DeleteObject(iconInfo.hbmMask); + DeleteObject(iconInfo.hbmColor); + DestroyCursor(cursor); +#else // !Q_OS_WINCE + m_ignoreDragCursor = QPixmap(ignoreDragCursorXpmC); +#endif // !Q_OS_WINCE + } + return m_ignoreDragCursor; +} + /*! \class QWindowsWindowCursor \brief Per-Window cursor. Contains a QCursor and manages its associated system diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h index ac9e87d1fb..e93f779f94 100644 --- a/src/plugins/platforms/windows/qwindowscursor.h +++ b/src/plugins/platforms/windows/qwindowscursor.h @@ -96,29 +96,37 @@ public: QPoint hotSpot; }; - QWindowsCursor(); + explicit QWindowsCursor(const QPlatformScreen *screen); void changeCursor(QCursor * widgetCursor, QWindow * widget) Q_DECL_OVERRIDE; QPoint pos() const Q_DECL_OVERRIDE; void setPos(const QPoint &pos) Q_DECL_OVERRIDE; - static HCURSOR createPixmapCursor(const QPixmap &pixmap, const QPoint &hotSpot); - static HCURSOR createPixmapCursor(const PixmapCursor &pc) { return createPixmapCursor(pc.pixmap, pc.hotSpot); } - static PixmapCursor customCursor(Qt::CursorShape cursorShape); + static HCURSOR createPixmapCursor(QPixmap pixmap, const QPoint &hotSpot, qreal scaleFactor = 1); + static HCURSOR createPixmapCursor(const PixmapCursor &pc, qreal scaleFactor = 1) { return createPixmapCursor(pc.pixmap, pc.hotSpot, scaleFactor); } + static PixmapCursor customCursor(Qt::CursorShape cursorShape, const QPlatformScreen *screen = Q_NULLPTR); - static HCURSOR createCursorFromShape(Qt::CursorShape cursorShape); + static HCURSOR createCursorFromShape(Qt::CursorShape cursorShape, const QPlatformScreen *screen = Q_NULLPTR); static QPoint mousePosition(); static CursorState cursorState(); CursorHandlePtr standardWindowCursor(Qt::CursorShape s = Qt::ArrowCursor); CursorHandlePtr pixmapWindowCursor(const QCursor &c); + QPixmap dragDefaultCursor(Qt::DropAction action) const; + private: typedef QHash StandardCursorCache; typedef QHash PixmapCursorCache; + const QPlatformScreen *const m_screen; StandardCursorCache m_standardCursorCache; PixmapCursorCache m_pixmapCursorCache; + + mutable QPixmap m_copyDragCursor; + mutable QPixmap m_moveDragCursor; + mutable QPixmap m_linkDragCursor; + mutable QPixmap m_ignoreDragCursor; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp index 5435c4820a..c68f05b5bb 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.cpp +++ b/src/plugins/platforms/windows/qwindowsdrag.cpp @@ -269,13 +269,6 @@ QDebug operator<<(QDebug d, const QWindowsOleDropSource::CursorEntry &e) } #endif // !QT_NO_DEBUG_STREAM -static qreal dragScaleFactor() -{ - const QWindowsScreenManager &screenManager = QWindowsContext::instance()->screenManager(); - const QWindowsScreen *screen = screenManager.screenAtDp(QWindowsCursor::mousePosition()); - return screen ? QHighDpiScaling::factor(screen) : qreal(1); -} - /*! \brief Blend custom pixmap with cursors. */ @@ -286,7 +279,17 @@ void QWindowsOleDropSource::createCursors() const QPixmap pixmap = drag->pixmap(); const bool hasPixmap = !pixmap.isNull(); - const qreal scaleFactor = dragScaleFactor(); + // Find screen for drag. Could be obtained from QDrag::source(), but that might be a QWidget. + + qreal scaleFactor = 1; + QPlatformCursor *platformCursor = Q_NULLPTR; + if (const QPlatformScreen *platformScreen = QWindowsContext::instance()->screenManager().screenAtDp(QWindowsCursor::mousePosition())) { + scaleFactor = QHighDpiScaling::factor(platformScreen); + platformCursor = platformScreen->cursor(); + } + if (!platformCursor && QGuiApplication::primaryScreen()) + platformCursor = QGuiApplication::primaryScreen()->handle()->cursor(); + const bool scalePixmap = hasPixmap && m_mode != TouchDrag // Touch drag: pixmap is shown in a separate QWindow, which will be scaled. && (scaleFactor != 1 && scaleFactor != qRound(pixmap.devicePixelRatio())); @@ -304,8 +307,8 @@ void QWindowsOleDropSource::createCursors() for (int cnum = 0; cnum < actionCount; ++cnum) { const Qt::DropAction action = actions[cnum]; QPixmap cursorPixmap = drag->dragCursor(action); - if (cursorPixmap.isNull()) - cursorPixmap = m_drag->defaultCursor(action); + if (cursorPixmap.isNull() && platformCursor) + cursorPixmap = static_cast(platformCursor)->dragDefaultCursor(action); const qint64 cacheKey = cursorPixmap.cacheKey(); const auto it = m_cursors.find(action); if (it != m_cursors.end() && it.value().cacheKey == cacheKey) @@ -704,94 +707,6 @@ IDropTargetHelper* QWindowsDrag::dropHelper() { return m_cachedDropTargetHelper; } -QPixmap QWindowsDrag::defaultCursor(Qt::DropAction action) const -{ - switch (action) { - case Qt::CopyAction: - if (m_copyDragCursor.isNull()) - m_copyDragCursor = QWindowsCursor::customCursor(Qt::DragCopyCursor).pixmap; - return m_copyDragCursor; - case Qt::TargetMoveAction: - case Qt::MoveAction: - if (m_moveDragCursor.isNull()) - m_moveDragCursor = QWindowsCursor::customCursor(Qt::DragMoveCursor).pixmap; - return m_moveDragCursor; - case Qt::LinkAction: - if (m_linkDragCursor.isNull()) - m_linkDragCursor = QWindowsCursor::customCursor(Qt::DragLinkCursor).pixmap; - return m_linkDragCursor; - default: - break; - } - - static const char * const ignoreDragCursorXpmC[] = { - "24 30 3 1", - ". c None", - "a c #000000", - "X c #FFFFFF", - "aa......................", - "aXa.....................", - "aXXa....................", - "aXXXa...................", - "aXXXXa..................", - "aXXXXXa.................", - "aXXXXXXa................", - "aXXXXXXXa...............", - "aXXXXXXXXa..............", - "aXXXXXXXXXa.............", - "aXXXXXXaaaa.............", - "aXXXaXXa................", - "aXXaaXXa................", - "aXa..aXXa...............", - "aa...aXXa...............", - "a.....aXXa..............", - "......aXXa.....XXXX.....", - ".......aXXa..XXaaaaXX...", - ".......aXXa.XaaaaaaaaX..", - "........aa.XaaaXXXXaaaX.", - "...........XaaaaX..XaaX.", - "..........XaaXaaaX..XaaX", - "..........XaaXXaaaX.XaaX", - "..........XaaX.XaaaXXaaX", - "..........XaaX..XaaaXaaX", - "...........XaaX..XaaaaX.", - "...........XaaaXXXXaaaX.", - "............XaaaaaaaaX..", - ".............XXaaaaXX...", - "...............XXXX....."}; - - if (m_ignoreDragCursor.isNull()) { -#if !defined (Q_OS_WINCE) - HCURSOR cursor = LoadCursor(NULL, IDC_NO); - ICONINFO iconInfo = {0, 0, 0, 0, 0}; - GetIconInfo(cursor, &iconInfo); - BITMAP bmColor = {0, 0, 0, 0, 0, 0, 0}; - - if (iconInfo.hbmColor - && GetObject(iconInfo.hbmColor, sizeof(BITMAP), &bmColor) - && bmColor.bmWidth == bmColor.bmWidthBytes / 4) { - const int colorBitsLength = bmColor.bmHeight * bmColor.bmWidthBytes; - uchar *colorBits = new uchar[colorBitsLength]; - GetBitmapBits(iconInfo.hbmColor, colorBitsLength, colorBits); - const QImage colorImage(colorBits, bmColor.bmWidth, bmColor.bmHeight, - bmColor.bmWidthBytes, QImage::Format_ARGB32); - - m_ignoreDragCursor = QPixmap::fromImage(colorImage); - delete [] colorBits; - } else { - m_ignoreDragCursor = QPixmap(ignoreDragCursorXpmC); - } - - DeleteObject(iconInfo.hbmMask); - DeleteObject(iconInfo.hbmColor); - DestroyCursor(cursor); -#else // !Q_OS_WINCE - m_ignoreDragCursor = QPixmap(ignoreDragCursorXpmC); -#endif // !Q_OS_WINCE - } - return m_ignoreDragCursor; -} - Qt::DropAction QWindowsDrag::drag(QDrag *drag) { // TODO: Accessibility handling? diff --git a/src/plugins/platforms/windows/qwindowsdrag.h b/src/plugins/platforms/windows/qwindowsdrag.h index b031faa884..ebe949a6af 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.h +++ b/src/plugins/platforms/windows/qwindowsdrag.h @@ -42,6 +42,9 @@ struct IDropTargetHelper; QT_BEGIN_NAMESPACE + +class QPlatformScreen; + class QWindowsDropMimeData : public QWindowsInternalMimeData { public: QWindowsDropMimeData() {} @@ -97,8 +100,6 @@ public: IDropTargetHelper* dropHelper(); - QPixmap defaultCursor(Qt::DropAction action) const; - private: static bool m_canceled; @@ -106,11 +107,6 @@ private: IDataObject *m_dropDataObject; IDropTargetHelper* m_cachedDropTargetHelper; - - mutable QPixmap m_copyDragCursor; - mutable QPixmap m_moveDragCursor; - mutable QPixmap m_linkDragCursor; - mutable QPixmap m_ignoreDragCursor; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp index de4ef79b81..e69665e4a9 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.cpp +++ b/src/plugins/platforms/windows/qwindowsscreen.cpp @@ -195,16 +195,6 @@ static QDebug operator<<(QDebug dbg, const QWindowsScreenData &d) } #endif // !QT_NO_DEBUG_STREAM -// Return the cursor to be shared by all screens (virtual desktop). -static inline QSharedPointer sharedCursor() -{ -#ifndef QT_NO_CURSOR - if (const QScreen *primaryScreen = QGuiApplication::primaryScreen()) - return static_cast(primaryScreen->handle())->cursorPtr(); -#endif - return QSharedPointer(new QWindowsCursor); -} - /*! \class QWindowsScreen \brief Windows screen. @@ -216,7 +206,7 @@ static inline QSharedPointer sharedCursor() QWindowsScreen::QWindowsScreen(const QWindowsScreenData &data) : m_data(data) #ifndef QT_NO_CURSOR - ,m_cursor(sharedCursor()) + , m_cursor(new QWindowsCursor(this)) #endif { } diff --git a/src/plugins/platforms/windows/qwindowsscreen.h b/src/plugins/platforms/windows/qwindowsscreen.h index bc8fbf553b..879cda047e 100644 --- a/src/plugins/platforms/windows/qwindowsscreen.h +++ b/src/plugins/platforms/windows/qwindowsscreen.h @@ -42,7 +42,7 @@ #include #include #include -#include +#include #include QT_BEGIN_NAMESPACE @@ -74,7 +74,7 @@ class QWindowsScreen : public QPlatformScreen { public: #ifndef QT_NO_CURSOR - typedef QSharedPointer CursorPtr; + typedef QScopedPointer CursorPtr; #endif explicit QWindowsScreen(const QWindowsScreenData &data); diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 158917184c..a642443386 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -507,6 +507,8 @@ QWinRTScreen::QWinRTScreen() hr = d->displayInformation->get_NativeOrientation(&displayOrientation); Q_ASSERT_SUCCEEDED(hr); d->nativeOrientation = static_cast(static_cast(qtOrientationsFromNative(displayOrientation))); + // Set initial pixel density + onDpiChanged(Q_NULLPTR, Q_NULLPTR); d->orientation = d->nativeOrientation; ComPtr applicationViewStatics; @@ -753,7 +755,6 @@ void QWinRTScreen::initialize() Q_ASSERT_SUCCEEDED(hr); hr = d->displayInformation->add_DpiChanged(Callback(this, &QWinRTScreen::onDpiChanged).Get(), &d->displayTokens[&IDisplayInformation::remove_DpiChanged]); Q_ASSERT_SUCCEEDED(hr); - onDpiChanged(Q_NULLPTR, Q_NULLPTR); onOrientationChanged(Q_NULLPTR, Q_NULLPTR); onVisibilityChanged(nullptr, nullptr); } diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index 901764bbf8..50d49ca798 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -1086,8 +1086,12 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event) case XCB_FOCUS_OUT: HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent); case XCB_KEY_PRESS: - m_keyboard->updateXKBStateFromCore(((xcb_key_press_event_t *)event)->state); + { + xcb_key_press_event_t *kp = (xcb_key_press_event_t *)event; + m_keyboard->updateXKBStateFromCore(kp->state); + setTime(kp->time); HANDLE_KEYBOARD_EVENT(xcb_key_press_event_t, handleKeyPressEvent); + } case XCB_KEY_RELEASE: m_keyboard->updateXKBStateFromCore(((xcb_key_release_event_t *)event)->state); HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent); diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp index 55bae05523..db7d837e01 100644 --- a/src/plugins/platforms/xcb/qxcbscreen.cpp +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -556,7 +556,8 @@ void QXcbScreen::updateRefreshRate(xcb_randr_mode_t mode) for (; modesIter.rem; xcb_randr_mode_info_next(&modesIter)) { xcb_randr_mode_info_t *modeInfo = modesIter.data; if (modeInfo->id == mode) { - m_refreshRate = modeInfo->dot_clock / (modeInfo->htotal * modeInfo->vtotal); + const uint32_t dotCount = modeInfo->htotal * modeInfo->vtotal; + m_refreshRate = (dotCount != 0) ? modeInfo->dot_clock / dotCount : 0; m_mode = mode; break; } diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 5d052a7ca1..4bd4639833 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -314,8 +314,6 @@ void QXcbWindow::create() destroy(); - m_deferredExpose = false; - m_configureNotifyPending = true; m_windowState = Qt::WindowNoState; Qt::WindowType type = window()->type(); @@ -2032,12 +2030,8 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * if (newScreen != currentScreen) QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); - m_configureNotifyPending = false; - - if (m_deferredExpose) { - m_deferredExpose = false; + if (m_mapped) QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size())); - } if (m_usingSyncProtocol && m_syncState == SyncReceived) m_syncState = SyncAndConfigureReceived; @@ -2104,10 +2098,8 @@ void QXcbWindow::handleMapNotifyEvent(const xcb_map_notify_event_t *event) m_mapped = true; if (m_deferredActivation) requestActivateWindow(); - if (m_configureNotifyPending) - m_deferredExpose = true; - else - QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size())); + + QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size())); } } diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 1a8e031779..c42c98c205 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -232,8 +232,6 @@ protected: bool m_transparent; bool m_usingSyncProtocol; bool m_deferredActivation; - bool m_deferredExpose; - bool m_configureNotifyPending; bool m_embedded; bool m_alertState; xcb_window_t m_netWmUserTimeWindow; diff --git a/src/testlib/qsignalspy.h b/src/testlib/qsignalspy.h index 1751220059..e9744d0b07 100644 --- a/src/testlib/qsignalspy.h +++ b/src/testlib/qsignalspy.h @@ -175,8 +175,11 @@ private: tp = QMetaType::UnknownType; } if (tp == QMetaType::UnknownType) { - qWarning("Don't know how to handle '%s', use qRegisterMetaType to register it.", - member.parameterNames().at(i).constData()); + qWarning("QSignalSpy: Unable to handle parameter '%s' of type '%s' of method '%s'," + " use qRegisterMetaType to register it.", + member.parameterNames().at(i).constData(), + member.parameterTypes().at(i).constData(), + member.name().constData()); } args << tp; } diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp index 1522b065a7..7051f970ff 100644 --- a/src/widgets/kernel/qopenglwidget.cpp +++ b/src/widgets/kernel/qopenglwidget.cpp @@ -1172,8 +1172,7 @@ void QOpenGLWidget::resizeEvent(QResizeEvent *e) d->recreateFbo(); resizeGL(width(), height()); - d->invokeUserPaint(); - d->resolveSamples(); + d->sendPaintEvent(QRect(QPoint(0, 0), size())); } /*! diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index e8169d0bd1..308403175a 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -271,6 +271,9 @@ QWidgetPrivate::QWidgetPrivate(int version) #ifndef QT_NO_IM , inheritsInputMethodHints(0) #endif +#ifndef QT_NO_OPENGL + , renderToTextureReallyDirty(1) +#endif #if defined(Q_OS_WIN) , noPaintOnScreen(0) #endif @@ -5560,7 +5563,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP << "geometry ==" << QRect(q->mapTo(q->window(), QPoint(0, 0)), q->size()); #endif - bool grabbed = false; + bool skipPaintEvent = false; #ifndef QT_NO_OPENGL if (renderToTexture) { // This widget renders into a texture which is composed later. We just need to @@ -5574,14 +5577,18 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP } else { // We are not drawing to a backingstore: fall back to QImage p.drawImage(q->rect(), grabFramebuffer()); - grabbed = true; + skipPaintEvent = true; } endBackingStorePainting(); } + if (renderToTextureReallyDirty) + renderToTextureReallyDirty = 0; + else + skipPaintEvent = true; } #endif // QT_NO_OPENGL - if (!grabbed) { + if (!skipPaintEvent) { //actually send the paint event sendPaintEvent(toBePainted); } diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index a78cf099ac..7eb8d048b3 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -743,6 +743,9 @@ public: #ifndef QT_NO_IM uint inheritsInputMethodHints : 1; #endif +#ifndef QT_NO_OPENGL + uint renderToTextureReallyDirty : 1; +#endif // *************************** Platform specific ************************************ #if defined(Q_OS_WIN) diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index 90311b0f0a..a108dcf03b 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -1000,6 +1000,16 @@ void QPlatformTextureListWatcher::onLockStatusChanged(bool locked) if (!isLocked()) m_backingStore->sync(); } + +#else + +static QPlatformTextureList *widgetTexturesFor(QWidget *tlw, QWidget *widget) +{ + Q_UNUSED(tlw); + Q_UNUSED(widget); + return Q_NULLPTR; +} + #endif // QT_NO_OPENGL static inline bool discardSyncRequest(QWidget *tlw, QTLWExtra *tlwExtra) @@ -1220,6 +1230,9 @@ void QWidgetBackingStore::doSync() QWidget *w = static_cast(tl->source(i)); if (dirtyRenderToTextureWidgets.contains(w)) { const QRect rect = tl->geometry(i); // mapped to the tlw already + // Set a flag to indicate that the paint event for this + // render-to-texture widget must not to be optimized away. + w->d_func()->renderToTextureReallyDirty = 1; dirty += rect; toClean += rect; } diff --git a/src/widgets/util/qsystemtrayicon.cpp b/src/widgets/util/qsystemtrayicon.cpp index 20f5c95ae9..47bc88cb43 100644 --- a/src/widgets/util/qsystemtrayicon.cpp +++ b/src/widgets/util/qsystemtrayicon.cpp @@ -284,12 +284,6 @@ bool QSystemTrayIcon::isVisible() const */ bool QSystemTrayIcon::event(QEvent *e) { -#if defined(Q_DEAD_CODE_FROM_QT4_X11) - if (e->type() == QEvent::ToolTip) { - Q_D(QSystemTrayIcon); - return d->sys->deliverToolTipEvent(e); - } -#endif return QObject::event(e); } diff --git a/src/widgets/util/qsystemtrayicon_x11.cpp b/src/widgets/util/qsystemtrayicon_x11.cpp index e50b0bd12c..13d58acebd 100644 --- a/src/widgets/util/qsystemtrayicon_x11.cpp +++ b/src/widgets/util/qsystemtrayicon_x11.cpp @@ -196,6 +196,9 @@ void QSystemTrayIconSys::mouseDoubleClickEvent(QMouseEvent *ev) bool QSystemTrayIconSys::event(QEvent *e) { switch (e->type()) { + case QEvent::ToolTip: + QApplication::sendEvent(q, e); + break; #ifndef QT_NO_WHEELEVENT case QEvent::Wheel: return QApplication::sendEvent(q, e); diff --git a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp index 83da28767f..1c639c94a8 100644 --- a/tests/auto/corelib/io/qprocess/tst_qprocess.cpp +++ b/tests/auto/corelib/io/qprocess/tst_qprocess.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -54,14 +55,6 @@ Q_DECLARE_METATYPE(QProcess::ExitStatus); Q_DECLARE_METATYPE(QProcess::ProcessState); #endif -#define QPROCESS_VERIFY(Process, Fn) \ -{ \ -const bool ret = Process.Fn; \ -if (ret == false) \ - qWarning("QProcess error: %d: %s", Process.error(), qPrintable(Process.errorString())); \ -QVERIFY(ret); \ -} - typedef void (QProcess::*QProcessFinishedSignal1)(int); typedef void (QProcess::*QProcessFinishedSignal2)(int, QProcess::ExitStatus); typedef void (QProcess::*QProcessErrorSignal)(QProcess::ProcessError); @@ -180,6 +173,7 @@ protected slots: private: qint64 bytesAvailable; + QTemporaryDir m_temporaryDir; #endif //QT_NO_PROCESS }; @@ -188,6 +182,7 @@ void tst_QProcess::initTestCase() #ifdef QT_NO_PROCESS QSKIP("This test requires QProcess support"); #else + QVERIFY2(m_temporaryDir.isValid(), qPrintable(m_temporaryDir.errorString())); // chdir to our testdata path and execute helper apps relative to that. QString testdata_dir = QFileInfo(QFINDTESTDATA("testProcessNormal")).absolutePath(); QVERIFY2(QDir::setCurrent(testdata_dir), qPrintable("Could not chdir to " + testdata_dir)); @@ -1717,7 +1712,7 @@ void tst_QProcess::failToStartEmptyArgs() // Reading and writing to a process is not supported on Qt/CE void tst_QProcess::removeFileWhileProcessIsRunning() { - QFile file("removeFile.txt"); + QFile file(m_temporaryDir.path() + QLatin1String("/removeFile.txt")); QVERIFY(file.open(QFile::WriteOnly)); QProcess process; @@ -1948,16 +1943,16 @@ void tst_QProcess::setStandardInputFile() { static const char data[] = "A bunch\1of\2data\3\4\5\6\7..."; QProcess process; - QFile file("data"); + QFile file(m_temporaryDir.path() + QLatin1String("/data-sif")); QVERIFY(file.open(QIODevice::WriteOnly)); file.write(data, sizeof data); file.close(); - process.setStandardInputFile("data"); + process.setStandardInputFile(file.fileName()); process.start("testProcessEcho/testProcessEcho"); - QPROCESS_VERIFY(process, waitForFinished()); + QVERIFY(process.waitForFinished()); QCOMPARE(process.exitStatus(), QProcess::NormalExit); QCOMPARE(process.exitCode(), 0); QByteArray all = process.readAll(); @@ -1967,7 +1962,7 @@ void tst_QProcess::setStandardInputFile() QProcess process2; process2.setStandardInputFile(QProcess::nullDevice()); process2.start("testProcessEcho/testProcessEcho"); - QPROCESS_VERIFY(process2, waitForFinished()); + QVERIFY(process2.waitForFinished()); all = process2.readAll(); QCOMPARE(all.size(), 0); } @@ -2016,7 +2011,7 @@ void tst_QProcess::setStandardOutputFile() QIODevice::OpenMode mode = append ? QIODevice::Append : QIODevice::Truncate; // create the destination file with data - QFile file("data"); + QFile file(m_temporaryDir.path() + QLatin1String("/data-stdof-") + QLatin1String(QTest::currentDataTag())); QVERIFY(file.open(QIODevice::WriteOnly)); file.write(data, sizeof data - 1); file.close(); @@ -2025,13 +2020,13 @@ void tst_QProcess::setStandardOutputFile() QProcess process; process.setReadChannelMode(channelMode); if (channelToTest == QProcess::StandardOutput) - process.setStandardOutputFile("data", mode); + process.setStandardOutputFile(file.fileName(), mode); else - process.setStandardErrorFile("data", mode); + process.setStandardErrorFile(file.fileName(), mode); process.start("testProcessEcho2/testProcessEcho2"); process.write(testdata, sizeof testdata); - QPROCESS_VERIFY(process,waitForFinished()); + QVERIFY(process.waitForFinished()); QCOMPARE(process.exitStatus(), QProcess::NormalExit); QCOMPARE(process.exitCode(), 0); @@ -2062,7 +2057,7 @@ void tst_QProcess::setStandardOutputFileNullDevice() process.setStandardOutputFile(QProcess::nullDevice()); process.start("testProcessEcho2/testProcessEcho2"); process.write(testdata, sizeof testdata); - QPROCESS_VERIFY(process,waitForFinished()); + QVERIFY(process.waitForFinished()); QCOMPARE(process.exitStatus(), QProcess::NormalExit); QCOMPARE(process.exitCode(), 0); QCOMPARE(process.bytesAvailable(), Q_INT64_C(0)); @@ -2074,13 +2069,14 @@ void tst_QProcess::setStandardOutputFileAndWaitForBytesWritten() { static const char testdata[] = "Test data."; - QFile file("data"); + QFile file(m_temporaryDir.path() + QLatin1String("/data-stdofawfbw")); QProcess process; process.setStandardOutputFile(file.fileName()); process.start("testProcessEcho2/testProcessEcho2"); + QVERIFY2(process.waitForStarted(), qPrintable(process.errorString())); process.write(testdata, sizeof testdata); process.waitForBytesWritten(); - QPROCESS_VERIFY(process, waitForFinished()); + QVERIFY(process.waitForFinished()); QCOMPARE(process.exitStatus(), QProcess::NormalExit); QCOMPARE(process.exitCode(), 0); @@ -2122,10 +2118,10 @@ void tst_QProcess::setStandardOutputProcess() if (waitForBytesWritten) source.waitForBytesWritten(); source.closeWriteChannel(); - QPROCESS_VERIFY(source, waitForFinished()); + QVERIFY(source.waitForFinished()); QCOMPARE(source.exitStatus(), QProcess::NormalExit); QCOMPARE(source.exitCode(), 0); - QPROCESS_VERIFY(sink, waitForFinished()); + QVERIFY(sink.waitForFinished()); QCOMPARE(sink.exitStatus(), QProcess::NormalExit); QCOMPARE(sink.exitCode(), 0); QByteArray all = sink.readAll(); @@ -2151,14 +2147,15 @@ void tst_QProcess::fileWriterProcess() QTime stopWatch; stopWatch.start(); - const QString fileName = QLatin1String("fileWriterProcess.txt"); + const QString fileName = m_temporaryDir.path() + QLatin1String("/fileWriterProcess.txt"); + const QString binary = QDir::currentPath() + QLatin1String("/fileWriterProcess/fileWriterProcess"); do { if (QFile::exists(fileName)) QVERIFY(QFile::remove(fileName)); QProcess process; - process.start("fileWriterProcess/fileWriterProcess", - QIODevice::ReadWrite | QIODevice::Text); + process.setWorkingDirectory(m_temporaryDir.path()); + process.start(binary, QIODevice::ReadWrite | QIODevice::Text); process.write(stdinStr); process.closeWriteChannel(); while (process.bytesToWrite()) { @@ -2181,8 +2178,9 @@ void tst_QProcess::detachedWorkingDirectoryAndPid() QTest::qSleep(1000); #endif - QFile infoFile(QDir::currentPath() + QLatin1String("/detachedinfo.txt")); - infoFile.remove(); + QFile infoFile(m_temporaryDir.path() + QLatin1String("/detachedinfo.txt")); + if (infoFile.exists()) + QVERIFY(infoFile.remove()); QString workingDir = QDir::currentPath() + "/testDetached"; diff --git a/tests/auto/corelib/itemmodels/qitemmodel/tst_qitemmodel.cpp b/tests/auto/corelib/itemmodels/qitemmodel/tst_qitemmodel.cpp index 1531e0ac40..20ff670835 100644 --- a/tests/auto/corelib/itemmodels/qitemmodel/tst_qitemmodel.cpp +++ b/tests/auto/corelib/itemmodels/qitemmodel/tst_qitemmodel.cpp @@ -49,6 +49,9 @@ class tst_QItemModel : public QObject { Q_OBJECT +public: + tst_QItemModel(); + public slots: void init(); void cleanup(); @@ -124,6 +127,11 @@ private: bool insertRecursively; }; +tst_QItemModel::tst_QItemModel() +{ + qRegisterMetaType(); +} + void tst_QItemModel::init() { testModels = new ModelsToTest(); diff --git a/tests/auto/corelib/thread/qwaitcondition/tst_qwaitcondition.cpp b/tests/auto/corelib/thread/qwaitcondition/tst_qwaitcondition.cpp index dea305e3e1..df52aa4949 100644 --- a/tests/auto/corelib/thread/qwaitcondition/tst_qwaitcondition.cpp +++ b/tests/auto/corelib/thread/qwaitcondition/tst_qwaitcondition.cpp @@ -33,6 +33,7 @@ #include +#include #include #include #include @@ -54,7 +55,25 @@ private slots: static const int iterations = 4; static const int ThreadCount = 4; -class wait_QMutex_Thread_1 : public QThread +// Terminate thread in destructor for threads instantiated on the stack +class TerminatingThread : public QThread +{ +public: + explicit TerminatingThread() + { + setTerminationEnabled(true); + } + + ~TerminatingThread() + { + if (isRunning()) { + qWarning() << "forcibly terminating " << objectName(); + terminate(); + } + } +}; + +class wait_QMutex_Thread_1 : public TerminatingThread { public: QMutex mutex; @@ -72,7 +91,7 @@ public: } }; -class wait_QMutex_Thread_2 : public QThread +class wait_QMutex_Thread_2 : public TerminatingThread { public: QWaitCondition started; @@ -93,7 +112,7 @@ public: } }; -class wait_QReadWriteLock_Thread_1 : public QThread +class wait_QReadWriteLock_Thread_1 : public TerminatingThread { public: QReadWriteLock readWriteLock; @@ -111,7 +130,7 @@ public: } }; -class wait_QReadWriteLock_Thread_2 : public QThread +class wait_QReadWriteLock_Thread_2 : public TerminatingThread { public: QWaitCondition started; @@ -155,7 +174,11 @@ void tst_QWaitCondition::wait_QMutex() // test multiple threads waiting on separate wait conditions wait_QMutex_Thread_1 thread[ThreadCount]; + const QString prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_mutex_") + + QString::number(i) + QLatin1Char('_'); + for (x = 0; x < ThreadCount; ++x) { + thread[x].setObjectName(prefix + QString::number(x)); thread[x].mutex.lock(); thread[x].start(); // wait for thread to start @@ -185,8 +208,12 @@ void tst_QWaitCondition::wait_QMutex() QWaitCondition cond1, cond2; wait_QMutex_Thread_2 thread[ThreadCount]; + const QString prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_mutex_") + + QString::number(i) + QLatin1Char('_'); + mutex.lock(); for (x = 0; x < ThreadCount; ++x) { + thread[x].setObjectName(prefix + QString::number(x)); thread[x].mutex = &mutex; thread[x].cond = (x < ThreadCount / 2) ? &cond1 : &cond2; thread[x].start(); @@ -289,7 +316,10 @@ void tst_QWaitCondition::wait_QReadWriteLock() // test multiple threads waiting on separate wait conditions wait_QReadWriteLock_Thread_1 thread[ThreadCount]; + const QString prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_lockforread_"); + for (x = 0; x < ThreadCount; ++x) { + thread[x].setObjectName(prefix + QString::number(x)); thread[x].readWriteLock.lockForRead(); thread[x].start(); // wait for thread to start @@ -319,8 +349,11 @@ void tst_QWaitCondition::wait_QReadWriteLock() QWaitCondition cond1, cond2; wait_QReadWriteLock_Thread_2 thread[ThreadCount]; + const QString prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_lockforwrite_"); + readWriteLock.lockForWrite(); for (x = 0; x < ThreadCount; ++x) { + thread[x].setObjectName(prefix + QString::number(x)); thread[x].readWriteLock = &readWriteLock; thread[x].cond = (x < ThreadCount / 2) ? &cond1 : &cond2; thread[x].start(); @@ -346,11 +379,17 @@ void tst_QWaitCondition::wait_QReadWriteLock() } } -class wake_Thread : public QThread +class WakeThreadBase : public TerminatingThread { public: - static int count; + QAtomicInt *count; + WakeThreadBase() : count(Q_NULLPTR) {} +}; + +class wake_Thread : public WakeThreadBase +{ +public: QWaitCondition started; QWaitCondition dummy; @@ -366,24 +405,23 @@ public: void run() { + Q_ASSERT(count); + Q_ASSERT(mutex); + Q_ASSERT(cond); mutex->lock(); - ++count; + ++*count; dummy.wakeOne(); // this wakeup should be lost started.wakeOne(); dummy.wakeAll(); // this one too cond->wait(mutex); - --count; + --*count; mutex->unlock(); } }; -int wake_Thread::count = 0; - -class wake_Thread_2 : public QThread +class wake_Thread_2 : public WakeThreadBase { public: - static int count; - QWaitCondition started; QWaitCondition dummy; @@ -399,22 +437,27 @@ public: void run() { + Q_ASSERT(count); + Q_ASSERT(readWriteLock); + Q_ASSERT(cond); readWriteLock->lockForWrite(); - ++count; + ++*count; dummy.wakeOne(); // this wakeup should be lost started.wakeOne(); dummy.wakeAll(); // this one too cond->wait(readWriteLock); - --count; + --*count; readWriteLock->unlock(); } }; -int wake_Thread_2::count = 0; - void tst_QWaitCondition::wakeOne() { + static const int firstWaitInterval = 1000; + static const int waitInterval = 30; + int x; + QAtomicInt count; // wake up threads, one at a time for (int i = 0; i < iterations; ++i) { QMutex mutex; @@ -424,8 +467,13 @@ void tst_QWaitCondition::wakeOne() wake_Thread thread[ThreadCount]; bool thread_exited[ThreadCount]; + QString prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_mutex_") + + QString::number(i) + QLatin1Char('_'); + mutex.lock(); for (x = 0; x < ThreadCount; ++x) { + thread[x].setObjectName(prefix + QString::number(x)); + thread[x].count = &count; thread[x].mutex = &mutex; thread[x].cond = &cond; thread_exited[x] = false; @@ -438,7 +486,7 @@ void tst_QWaitCondition::wakeOne() } mutex.unlock(); - QCOMPARE(wake_Thread::count, ThreadCount); + QCOMPARE(count.load(), ThreadCount); // wake up threads one at a time for (x = 0; x < ThreadCount; ++x) { @@ -452,24 +500,29 @@ void tst_QWaitCondition::wakeOne() for (int y = 0; y < ThreadCount; ++y) { if (thread_exited[y]) continue; - if (thread[y].wait(exited > 0 ? 10 : 1000)) { + if (thread[y].wait(exited > 0 ? waitInterval : firstWaitInterval)) { thread_exited[y] = true; ++exited; } } QCOMPARE(exited, 1); - QCOMPARE(wake_Thread::count, ThreadCount - (x + 1)); + QCOMPARE(count.load(), ThreadCount - (x + 1)); } - QCOMPARE(wake_Thread::count, 0); + QCOMPARE(count.load(), 0); // QReadWriteLock QReadWriteLock readWriteLock; wake_Thread_2 rwthread[ThreadCount]; + prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_readwritelock_") + + QString::number(i) + QLatin1Char('_'); + readWriteLock.lockForWrite(); for (x = 0; x < ThreadCount; ++x) { + rwthread[x].setObjectName(prefix + QString::number(x)); + rwthread[x].count = &count; rwthread[x].readWriteLock = &readWriteLock; rwthread[x].cond = &cond; thread_exited[x] = false; @@ -482,7 +535,7 @@ void tst_QWaitCondition::wakeOne() } readWriteLock.unlock(); - QCOMPARE(wake_Thread_2::count, ThreadCount); + QCOMPARE(count.load(), ThreadCount); // wake up threads one at a time for (x = 0; x < ThreadCount; ++x) { @@ -496,17 +549,17 @@ void tst_QWaitCondition::wakeOne() for (int y = 0; y < ThreadCount; ++y) { if (thread_exited[y]) continue; - if (rwthread[y].wait(exited > 0 ? 10 : 1000)) { + if (rwthread[y].wait(exited > 0 ? waitInterval : firstWaitInterval)) { thread_exited[y] = true; ++exited; } } QCOMPARE(exited, 1); - QCOMPARE(wake_Thread_2::count, ThreadCount - (x + 1)); + QCOMPARE(count.load(), ThreadCount - (x + 1)); } - QCOMPARE(wake_Thread_2::count, 0); + QCOMPARE(count.load(), 0); } // wake up threads, two at a time @@ -518,8 +571,13 @@ void tst_QWaitCondition::wakeOne() wake_Thread thread[ThreadCount]; bool thread_exited[ThreadCount]; + QString prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_mutex2_") + + QString::number(i) + QLatin1Char('_'); + mutex.lock(); for (x = 0; x < ThreadCount; ++x) { + thread[x].setObjectName(prefix + QString::number(x)); + thread[x].count = &count; thread[x].mutex = &mutex; thread[x].cond = &cond; thread_exited[x] = false; @@ -532,7 +590,7 @@ void tst_QWaitCondition::wakeOne() } mutex.unlock(); - QCOMPARE(wake_Thread::count, ThreadCount); + QCOMPARE(count.load(), ThreadCount); // wake up threads one at a time for (x = 0; x < ThreadCount; x += 2) { @@ -548,24 +606,29 @@ void tst_QWaitCondition::wakeOne() for (int y = 0; y < ThreadCount; ++y) { if (thread_exited[y]) continue; - if (thread[y].wait(exited > 0 ? 10 : 1000)) { + if (thread[y].wait(exited > 0 ? waitInterval : firstWaitInterval)) { thread_exited[y] = true; ++exited; } } QCOMPARE(exited, 2); - QCOMPARE(wake_Thread::count, ThreadCount - (x + 2)); + QCOMPARE(count.load(), ThreadCount - (x + 2)); } - QCOMPARE(wake_Thread::count, 0); + QCOMPARE(count.load(), 0); // QReadWriteLock QReadWriteLock readWriteLock; wake_Thread_2 rwthread[ThreadCount]; + prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_readwritelock_") + + QString::number(i) + QLatin1Char('_'); + readWriteLock.lockForWrite(); for (x = 0; x < ThreadCount; ++x) { + rwthread[x].setObjectName(prefix + QString::number(x)); + rwthread[x].count = &count; rwthread[x].readWriteLock = &readWriteLock; rwthread[x].cond = &cond; thread_exited[x] = false; @@ -578,7 +641,7 @@ void tst_QWaitCondition::wakeOne() } readWriteLock.unlock(); - QCOMPARE(wake_Thread_2::count, ThreadCount); + QCOMPARE(count.load(), ThreadCount); // wake up threads one at a time for (x = 0; x < ThreadCount; x += 2) { @@ -594,23 +657,24 @@ void tst_QWaitCondition::wakeOne() for (int y = 0; y < ThreadCount; ++y) { if (thread_exited[y]) continue; - if (rwthread[y].wait(exited > 0 ? 10 : 1000)) { + if (rwthread[y].wait(exited > 0 ? waitInterval : firstWaitInterval)) { thread_exited[y] = true; ++exited; } } QCOMPARE(exited, 2); - QCOMPARE(wake_Thread_2::count, ThreadCount - (x + 2)); + QCOMPARE(count.load(), ThreadCount - (x + 2)); } - QCOMPARE(wake_Thread_2::count, 0); + QCOMPARE(count.load(), 0); } } void tst_QWaitCondition::wakeAll() { int x; + QAtomicInt count; for (int i = 0; i < iterations; ++i) { QMutex mutex; QWaitCondition cond; @@ -618,8 +682,13 @@ void tst_QWaitCondition::wakeAll() // QMutex wake_Thread thread[ThreadCount]; + QString prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_mutex_") + + QString::number(i) + QLatin1Char('_'); + mutex.lock(); for (x = 0; x < ThreadCount; ++x) { + thread[x].setObjectName(prefix + QString::number(x)); + thread[x].count = &count; thread[x].mutex = &mutex; thread[x].cond = &cond; thread[x].start(); @@ -628,7 +697,7 @@ void tst_QWaitCondition::wakeAll() } mutex.unlock(); - QCOMPARE(wake_Thread::count, ThreadCount); + QCOMPARE(count.load(), ThreadCount); // wake up all threads at once mutex.lock(); @@ -643,14 +712,19 @@ void tst_QWaitCondition::wakeAll() } QCOMPARE(exited, ThreadCount); - QCOMPARE(wake_Thread::count, 0); + QCOMPARE(count.load(), 0); // QReadWriteLock QReadWriteLock readWriteLock; wake_Thread_2 rwthread[ThreadCount]; + prefix = QLatin1String(QTest::currentTestFunction()) + QLatin1String("_readwritelock_") + + QString::number(i) + QLatin1Char('_'); + readWriteLock.lockForWrite(); for (x = 0; x < ThreadCount; ++x) { + rwthread[x].setObjectName(prefix + QString::number(x)); + rwthread[x].count = &count; rwthread[x].readWriteLock = &readWriteLock; rwthread[x].cond = &cond; rwthread[x].start(); @@ -659,7 +733,7 @@ void tst_QWaitCondition::wakeAll() } readWriteLock.unlock(); - QCOMPARE(wake_Thread_2::count, ThreadCount); + QCOMPARE(count.load(), ThreadCount); // wake up all threads at once readWriteLock.lockForWrite(); @@ -674,11 +748,11 @@ void tst_QWaitCondition::wakeAll() } QCOMPARE(exited, ThreadCount); - QCOMPARE(wake_Thread_2::count, 0); + QCOMPARE(count.load(), 0); } } -class wait_RaceConditionThread : public QThread +class wait_RaceConditionThread : public TerminatingThread { public: wait_RaceConditionThread(QMutex *mutex, QWaitCondition *startup, QWaitCondition *waitCondition, @@ -707,7 +781,7 @@ public: } }; -class wait_RaceConditionThread_2 : public QThread +class wait_RaceConditionThread_2 : public TerminatingThread { public: wait_RaceConditionThread_2(QReadWriteLock *readWriteLock, diff --git a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp index 1425ce3c2f..68b92e1851 100644 --- a/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp +++ b/tests/auto/gui/image/qimagereader/tst_qimagereader.cpp @@ -36,7 +36,6 @@ #include #include -#include #include #include #include @@ -46,6 +45,7 @@ #include #include #include +#include #include @@ -53,6 +53,22 @@ typedef QMap QStringMap; typedef QList QIntList; Q_DECLARE_METATYPE(QImage::Format) +static QByteArray msgFileOpenWriteFailed(const QFile &file) +{ + const QString result = QLatin1String("Cannot open \"") + + QDir::toNativeSeparators(file.fileName()) + + QLatin1String("\" for writing: ") + file.errorString(); + return result.toLocal8Bit(); +} + +static QByteArray msgFileOpenReadFailed(const QFile &file) +{ + const QString result = QLatin1String("Cannot open \"") + + QDir::toNativeSeparators(file.fileName()) + + QLatin1String("\" for reading: ") + file.errorString(); + return result.toLocal8Bit(); +} + class tst_QImageReader : public QObject { Q_OBJECT @@ -1051,7 +1067,7 @@ void tst_QImageReader::readFromDevice() const QString imageFileName = prefix + fileName; QImage expectedImage(imageFileName, format); QFile file(imageFileName); - QVERIFY(file.open(QFile::ReadOnly)); + QVERIFY2(file.open(QFile::ReadOnly), msgFileOpenReadFailed(file).constData()); QByteArray imageData = file.readAll(); QVERIFY(!imageData.isEmpty()); { @@ -1129,12 +1145,11 @@ void tst_QImageReader::readFromFileAfterJunk() SKIP_IF_UNSUPPORTED(format); - QFile::remove("junk"); - QFile junkFile("junk"); - QVERIFY(junkFile.open(QFile::WriteOnly)); + QTemporaryFile junkFile(m_temporaryDir.path() + QLatin1String("/junkXXXXXX")); + QVERIFY2(junkFile.open(), msgFileOpenWriteFailed(junkFile).constData()); QFile imageFile(prefix + fileName); - QVERIFY(imageFile.open(QFile::ReadOnly)); + QVERIFY2(imageFile.open(QFile::ReadOnly), msgFileOpenReadFailed(imageFile).constData()); QByteArray imageData = imageFile.readAll(); QVERIFY(!imageData.isNull()); @@ -1155,7 +1170,7 @@ void tst_QImageReader::readFromFileAfterJunk() } } junkFile.close(); - junkFile.open(QFile::ReadOnly); + QVERIFY2(junkFile.open(), msgFileOpenReadFailed(junkFile).constData()); for (int i = 0; i < iterations; ++i) { QByteArray ole = junkFile.read(9); @@ -1205,7 +1220,7 @@ void tst_QImageReader::devicePosition() QVERIFY(!expected.isNull()); QFile imageFile(prefix + fileName); - QVERIFY(imageFile.open(QFile::ReadOnly)); + QVERIFY2(imageFile.open(QFile::ReadOnly), msgFileOpenReadFailed(imageFile).constData()); QByteArray imageData = imageFile.readAll(); QVERIFY(!imageData.isNull()); int imageDataSize = imageData.size(); diff --git a/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp b/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp index 6c22c47f0e..c49c9c9129 100644 --- a/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp +++ b/tests/auto/gui/image/qimagewriter/tst_qimagewriter.cpp @@ -89,6 +89,7 @@ private slots: void saveToTemporaryFile(); private: + QTemporaryDir m_temporaryDir; QString prefix; QString writePrefix; }; @@ -112,14 +113,11 @@ static void initializePadding(QImage *image) void tst_QImageWriter::initTestCase() { + QVERIFY(m_temporaryDir.isValid()); prefix = QFINDTESTDATA("images/"); if (prefix.isEmpty()) QFAIL("Can't find images directory!"); -#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_NO_SDK) - writePrefix = QDir::homePath(); -#else - writePrefix = prefix; -#endif + writePrefix = m_temporaryDir.path(); } // Testing get/set functions diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp index a84d290661..66aa26ccea 100644 --- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -202,8 +202,7 @@ protected Q_SLOTS: void notEnoughData(); private Q_SLOTS: - void init(); - void cleanup(); + void cleanup() { cleanupTestData(); } void initTestCase(); void cleanupTestCase(); @@ -487,6 +486,8 @@ private Q_SLOTS: // NOTE: This test must be last! void parentingRepliesToTheApp(); private: + void cleanupTestData(); + QString testDataDir; bool notEnoughDataForFastSender; }; @@ -1499,6 +1500,8 @@ void tst_QNetworkReply::initTestCase() echoProcessDir = QFINDTESTDATA("echo"); QVERIFY2(!echoProcessDir.isEmpty(), qPrintable( QString::fromLatin1("Couldn't find echo dir starting from %1.").arg(QDir::currentPath()))); + + cleanupTestData(); } void tst_QNetworkReply::cleanupTestCase() @@ -1514,12 +1517,7 @@ void tst_QNetworkReply::cleanupTestCase() #endif } -void tst_QNetworkReply::init() -{ - cleanup(); -} - -void tst_QNetworkReply::cleanup() +void tst_QNetworkReply::cleanupTestData() { QFile file(testFileName); QVERIFY(!file.exists() || file.remove()); diff --git a/tests/auto/tools/qmake/testdata/.gitignore b/tests/auto/tools/qmake/testdata/.gitignore new file mode 100644 index 0000000000..1e997b287b --- /dev/null +++ b/tests/auto/tools/qmake/testdata/.gitignore @@ -0,0 +1,5 @@ +# Created by various tests, even for shadow builds: +/pro_file_cache/include.pri +/quotedfilenames/cpp folder/ +/quotedfilenames/quotedfilenames +/resources/resources diff --git a/tests/manual/qcursor/qcursor.pro b/tests/manual/qcursor/qcursor.pro index af082a4b82..0b5c2b1945 100644 --- a/tests/manual/qcursor/qcursor.pro +++ b/tests/manual/qcursor/qcursor.pro @@ -1,3 +1,3 @@ TEMPLATE = subdirs -SUBDIRS = allcursors grab_override +SUBDIRS = allcursors grab_override qcursorhighdpi diff --git a/tests/manual/qcursor/qcursorhighdpi/main.cpp b/tests/manual/qcursor/qcursorhighdpi/main.cpp new file mode 100644 index 0000000000..fc45ae00d1 --- /dev/null +++ b/tests/manual/qcursor/qcursorhighdpi/main.cpp @@ -0,0 +1,321 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#if QT_VERSION > 0x050000 +# include +# include +# include +# include +#else +# define Q_NULLPTR 0 +# define Q_DECL_OVERRIDE +#endif + +#ifdef Q_OS_WIN +# include +#endif + +#include +#include + +// High DPI cursor test for testing cursor sizes in multi-screen setups. +// It creates one widget per screen with a grid of standard cursors, +// pixmap / bitmap cursors and pixmap / bitmap cursors with device pixel ratio 2. +// On the left, there is a ruler with 10 DIP marks. +// The code is meant to compile with Qt 4 also. + +static QString screenInfo(const QWidget *w) +{ + QString result; + QTextStream str(&result); +#if QT_VERSION > 0x050000 + QScreen *screen = Q_NULLPTR; + if (const QWindow *window = w->windowHandle()) + screen = window->screen(); + if (screen) { + str << '"' << screen->name() << "\" " << screen->size().width() << 'x' + << screen->size().height() << ", DPR=" << screen->devicePixelRatio() + << ", " << screen->logicalDotsPerInchX() << "DPI "; + if (QHighDpiScaling::isActive()) + str << ", factor=" << QHighDpiScaling::factor(screen); + else + str << ", no scaling"; + } else { + str << ""; + } +#else + QDesktopWidget *desktop = QApplication::desktop(); + int screenNumber = desktop->screenNumber(w); + str << "Screen #" <screenGeometry(screenNumber).width() + << 'x' << desktop->screenGeometry(screenNumber).height() << " PD: " << w->logicalDpiX() << "DPI"; +#endif +#ifdef Q_OS_WIN + str << ", SM_C_CURSOR: " << GetSystemMetrics(SM_CXCURSOR) << 'x' << GetSystemMetrics(SM_CYCURSOR); +#endif + return result; +} + +// Helpers for painting pixmaps and creating cursors +static QPixmap paintPixmap(int size, QColor c) +{ + QPixmap result(size, size); + result.fill(c); + QPainter p(&result); + p.drawRect(QRect(QPoint(0, 0), result.size() - QSize(1, 1))); + p.drawLine(0, 0, size, size); + p.drawLine(0, size, size, 0); + return result; +} + +static QCursor pixmapCursor(int size) +{ + QCursor result(paintPixmap(size, Qt::red), size / 2, size / 2); + return result; +} + +static QPair paintBitmaps(int size) +{ + QBitmap bitmap(size, size); + bitmap.fill(Qt::color1); + QBitmap mask(size, size); + mask.fill(Qt::color1); + { + QPainter mp(&mask); + mp.fillRect(QRect(0, 0, size / 2, size / 2), Qt::color0); + } + return QPair(bitmap, mask); +} + +static QCursor bitmapCursor(int size) +{ + QPair bitmaps = paintBitmaps(size); + return QCursor(bitmaps.first, bitmaps.second, size / 2, size / 2); +} + +#if QT_VERSION > 0x050000 +static QCursor pixmapCursorDevicePixelRatio(int size, int dpr) +{ + QPixmap pixmap = paintPixmap(dpr * size, Qt::yellow); + pixmap.setDevicePixelRatio(dpr); + return QCursor(pixmap, size / 2, size / 2); +} + +static QCursor bitmapCursorDevicePixelRatio(int size, int dpr) +{ + QPair bitmaps = paintBitmaps(dpr * size); + bitmaps.first.setDevicePixelRatio(dpr); + bitmaps.second.setDevicePixelRatio(dpr); + return QCursor(bitmaps.first, bitmaps.second, size / 2, size / 2); +} +#endif // Qt 5 + +// Vertical ruler widget with 10 px marks +class VerticalRuler : public QWidget { +public: + VerticalRuler(QWidget *parent = Q_NULLPTR); + +protected: + void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE; +}; + +VerticalRuler::VerticalRuler(QWidget *parent) : QWidget(parent) +{ + const int screenWidth = QApplication::desktop()->screenGeometry(this).width(); + setFixedWidth(screenWidth / 48); // 1920 pixel monitor ->40 +} + +void VerticalRuler::paintEvent(QPaintEvent *) +{ + const QSize sizeS(size()); + const QPoint sizeP(sizeS.width(), sizeS.height()); + const QPoint center = sizeP / 2; + QPainter painter(this); + painter.fillRect(QRect(QPoint(0, 0), sizeS), Qt::white); + painter.drawLine(center.x(), 0, center.x(), sizeP.y()); + for (int y = 0; y < sizeP.y(); y += 10) + painter.drawLine(center.x() - 5, y, center.x() + 5, y); +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT +public: + explicit MainWindow(QWidget *parent = Q_NULLPTR); + void updateScreenInfo() { m_screenInfoLabel->setText(screenInfo(this)); } + +public slots: + void screenChanged() { updateScreenInfo(); } + +private: + QLabel *m_screenInfoLabel; +}; + +static QLabel *createCursorLabel(const QCursor &cursor, const QString &additionalText = QString()) +{ + QString labelText; + QDebug(&labelText).nospace() << cursor.shape(); +#if QT_VERSION > 0x050000 + labelText.remove(0, labelText.indexOf('(') + 1); + labelText.chop(1); +#endif // Qt 5 + if (!additionalText.isEmpty()) + labelText += ' ' + additionalText; + QLabel *result = new QLabel(labelText); + result->setFrameShape(QFrame::Box); + result->setCursor(cursor); + return result; +} + +static void addToGrid(QWidget *w, QGridLayout *gridLayout, int columnCount, int &row, int &col) +{ + gridLayout->addWidget(w, row, col); + if (col >= columnCount) { + col = 0; + row++; + } else { + col++; + } +} + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent) + , m_screenInfoLabel(new QLabel) +{ + QString title = "Cursors "; +#if QT_VERSION > 0x050000 + title += '(' + QGuiApplication::platformName() + ") "; +#endif + title += QT_VERSION_STR; + setWindowTitle(title); + + QMenu *fileMenu = menuBar()->addMenu("File"); + QAction *quitAction = fileMenu->addAction("Quit"); + quitAction->setShortcut(Qt::CTRL + Qt::Key_Q); + connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit())); + + QToolBar *fileToolBar = addToolBar("File"); + fileToolBar->addAction(quitAction); + + QWidget *cw = new QWidget; + QHBoxLayout *hLayout = new QHBoxLayout(cw); + hLayout->addWidget(new VerticalRuler(cw)); + QGridLayout *gridLayout = new QGridLayout; + hLayout->addLayout(gridLayout); + + const int columnCount = 5; + const int size = 32; + + int row = 0; + int col = 0; + for (int i = 0; i < Qt::BitmapCursor; ++i) + addToGrid(createCursorLabel(QCursor(static_cast(i))), gridLayout, columnCount, row, col); + + addToGrid(createCursorLabel(QCursor(pixmapCursor(size)), + QLatin1String("Plain PX ") + QString::number(size)), + gridLayout, columnCount, row, col); + + addToGrid(createCursorLabel(bitmapCursor(size), + QLatin1String("Plain BM ") + QString::number(size)), + gridLayout, columnCount, row, col); + +#if QT_VERSION > 0x050000 + addToGrid(createCursorLabel(QCursor(pixmapCursorDevicePixelRatio(size, 2)), + "PX with DPR 2 " + QString::number(size)), + gridLayout, columnCount, row, col); + + addToGrid(createCursorLabel(QCursor(bitmapCursorDevicePixelRatio(size, 2)), + "BM with DPR 2 " + QString::number(size)), + gridLayout, columnCount, row, col); +#endif // Qt 5 + + gridLayout->addWidget(m_screenInfoLabel, row + 1, 0, 1, columnCount); + + setCentralWidget(cw); +} + +typedef QSharedPointer MainWindowPtr; +typedef QList MainWindowPtrList; + +int main(int argc, char *argv[]) +{ + QStringList arguments; + std::copy(argv + 1, argv + argc, std::back_inserter(arguments)); + +#if QT_VERSION > 0x050000 + if (arguments.contains("-s")) + QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + else if (arguments.contains("-n")) + QCoreApplication::setAttribute(Qt::AA_DisableHighDpiScaling); +#endif // Qt 5 + + QApplication app(argc, argv); + + MainWindowPtrList windows; + + QDesktopWidget *desktopWidget = app.desktop(); + + for (int s = desktopWidget->screenCount() - 1; s >= 0; --s) { + MainWindowPtr window(new MainWindow(desktopWidget->screen(s))); + const QPoint pos = desktopWidget->screenGeometry(s).center() - QPoint(200, 100); + window->move(pos); + windows.append(window); + window->show(); + window->updateScreenInfo(); +#if QT_VERSION > 0x050000 + QObject::connect(window->windowHandle(), &QWindow::screenChanged, + window.data(), &MainWindow::updateScreenInfo); +#endif + } + return app.exec(); +} +#include "main.moc" diff --git a/tests/manual/qcursor/qcursorhighdpi/qcursorhighdpi.pro b/tests/manual/qcursor/qcursorhighdpi/qcursorhighdpi.pro new file mode 100644 index 0000000000..3a8fc25b33 --- /dev/null +++ b/tests/manual/qcursor/qcursorhighdpi/qcursorhighdpi.pro @@ -0,0 +1,6 @@ +TEMPLATE = app +QT = core gui +greaterThan(QT_MAJOR_VERSION, 4): QT += gui-private core-private widgets +CONFIG -= app_bundle +SOURCES += main.cpp +win32: LIBS += -lUser32