diff --git a/configure b/configure index b3ddfaa4b6..a58256f089 100755 --- a/configure +++ b/configure @@ -692,7 +692,7 @@ CFG_EGLFS_EGLDEVICE=no CFG_EGLFS_MALI=no CFG_EGLFS_VIV=no CFG_EGLFS_VIV_WL=no -CFG_DIRECTFB=auto +CFG_DIRECTFB=no CFG_GBM=auto CFG_LINUXFB=auto CFG_INTEGRITYFB=no @@ -2706,8 +2706,8 @@ Additional options: -no-gbm ............ Do not compile backends for GBM. * -gbm ............... Compile backends for GBM. - -no-directfb ....... Do not compile DirectFB support. - * -directfb .......... Compile DirectFB support. + * -no-directfb ....... Do not compile DirectFB support. + -directfb .......... Compile DirectFB support. -no-linuxfb ........ Do not compile Linux Framebuffer support. * -linuxfb ........... Compile Linux Framebuffer support. @@ -3931,7 +3931,7 @@ if true; then ###[ '!' -f "$outpath/bin/qmake" ]; setBootstrapVariable QMAKE_CXXFLAGS_RELEASE EXTRA_CFLAGS="$EXTRA_CFLAGS \$(QMAKE_CFLAGS_RELEASE)" EXTRA_CXXFLAGS="$EXTRA_CXXFLAGS \$(QMAKE_CXXFLAGS_RELEASE)" - elif [ "$CFG_DEBUG" = "yes" ]; then + else setBootstrapVariable QMAKE_CFLAGS_DEBUG setBootstrapVariable QMAKE_CXXFLAGS_DEBUG EXTRA_CFLAGS="$EXTRA_CFLAGS \$(QMAKE_CFLAGS_DEBUG)" diff --git a/examples/widgets/graphicsview/diagramscene/arrow.cpp b/examples/widgets/graphicsview/diagramscene/arrow.cpp index 383c126596..012b9ea2ed 100644 --- a/examples/widgets/graphicsview/diagramscene/arrow.cpp +++ b/examples/widgets/graphicsview/diagramscene/arrow.cpp @@ -120,12 +120,12 @@ void Arrow::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QPointF intersectPoint; QLineF polyLine; for (int i = 1; i < endPolygon.count(); ++i) { - p2 = endPolygon.at(i) + myEndItem->pos(); - polyLine = QLineF(p1, p2); - QLineF::IntersectType intersectType = - polyLine.intersect(centerLine, &intersectPoint); - if (intersectType == QLineF::BoundedIntersection) - break; + p2 = endPolygon.at(i) + myEndItem->pos(); + polyLine = QLineF(p1, p2); + QLineF::IntersectType intersectType = + polyLine.intersect(centerLine, &intersectPoint); + if (intersectType == QLineF::BoundedIntersection) + break; p1 = p2; } @@ -136,18 +136,18 @@ void Arrow::paint(QPainter *painter, const QStyleOptionGraphicsItem *, if (line().dy() >= 0) angle = (Pi * 2) - angle; - QPointF arrowP1 = line().p1() + QPointF(sin(angle + Pi / 3) * arrowSize, - cos(angle + Pi / 3) * arrowSize); - QPointF arrowP2 = line().p1() + QPointF(sin(angle + Pi - Pi / 3) * arrowSize, - cos(angle + Pi - Pi / 3) * arrowSize); + QPointF arrowP1 = line().p1() + QPointF(sin(angle + Pi / 3) * arrowSize, + cos(angle + Pi / 3) * arrowSize); + QPointF arrowP2 = line().p1() + QPointF(sin(angle + Pi - Pi / 3) * arrowSize, + cos(angle + Pi - Pi / 3) * arrowSize); - arrowHead.clear(); - arrowHead << line().p1() << arrowP1 << arrowP2; + arrowHead.clear(); + arrowHead << line().p1() << arrowP1 << arrowP2; //! [6] //! [7] - painter->drawLine(line()); - painter->drawPolygon(arrowHead); - if (isSelected()) { - painter->setPen(QPen(myColor, 1, Qt::DashLine)); + painter->drawLine(line()); + painter->drawPolygon(arrowHead); + if (isSelected()) { + painter->setPen(QPen(myColor, 1, Qt::DashLine)); QLineF myLine = line(); myLine.translate(0, 4.0); painter->drawLine(myLine); diff --git a/mkspecs/features/file_copies.prf b/mkspecs/features/file_copies.prf new file mode 100644 index 0000000000..f679129e03 --- /dev/null +++ b/mkspecs/features/file_copies.prf @@ -0,0 +1,41 @@ +isEmpty(COPIES): return() +contains(TEMPLATE, .*subdirs): error("COPIES does not work with TEMPLATE=subdirs") + +build_pass:build_all: \ + debug_and_release:debug { + # Avoid that multiple build passes race with each other. + # This will fail to copy anything if the user explicitly invokes + # only the non-primary build. This is unfixable, as at qmake time + # we cannot possibly know how make will be invoked, yet we must + # predict it here. + return() +} + +defineReplace(qtStripProPwd) { + return($$relative_path($$1, $$_PRO_FILE_PWD_)) +} + +for (cp, COPIES) { + isEmpty($${cp}.files): next() + pfx = copy_$${cp} + for (f, $${cp}.files): \ + $${pfx}.files += $$absolute_path($$f, $$_PRO_FILE_PWD_) + path = $$eval($${cp}.path) + isEmpty(path): error("COPY $cp defines no .path") + base = $$eval($${cp}.base) + isEmpty(base) { + $${pfx}.output = $$path/${QMAKE_FILE_BASE}${QMAKE_FILE_EXT} + } else: isEqual(base, $$_PRO_FILE_PWD_) { + $${pfx}.output = $$path/${QMAKE_FUNC_FILE_IN_qtStripProPwd} + } else { + eval(defineReplace(qtStripSrcDir_$$cp) { \ + return(\$\$relative_path(\$\$1, $$val_escape(base))) \ + }) + $${pfx}.output = $$path/${QMAKE_FUNC_FILE_IN_qtStripSrcDir_$$cp} + } + $${pfx}.input = $${pfx}.files + $${pfx}.commands = $$QMAKE_COPY ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT} + $${pfx}.name = COPY ${QMAKE_FILE_IN} + $${pfx}.CONFIG = no_link no_clean target_predeps + QMAKE_EXTRA_COMPILERS += $${pfx} +} diff --git a/mkspecs/features/qml_module.prf b/mkspecs/features/qml_module.prf index 2115b39c04..6b3ad81953 100644 --- a/mkspecs/features/qml_module.prf +++ b/mkspecs/features/qml_module.prf @@ -28,24 +28,6 @@ else: \ !qml1_target:static: CONFIG += builtin_resources -!force_independent:if(!debug_and_release|!build_all|CONFIG(release, debug|release)) { - # These bizarre rules copy the files to the qtbase build directory - - defineReplace(qmlModStripSrcDir) { - return($$relative_path($$1, $$_PRO_FILE_PWD_)) - } - - !builtin_resources: qmlfiles2build.input = fq_qml_files - else: qmlfiles2build.input = qmldir_file - qmlfiles2build.output = $$instbase/$$TARGETPATH/${QMAKE_FUNC_FILE_IN_qmlModStripSrcDir} - !contains(TEMPLATE, vc.*): qmlfiles2build.variable_out = PRE_TARGETDEPS - qmlfiles2build.commands = $$QMAKE_COPY ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT} - qmlfiles2build.name = COPY ${QMAKE_FILE_IN} - qmlfiles2build.CONFIG = no_link no_clean - - QMAKE_EXTRA_COMPILERS += qmlfiles2build -} - builtin_resources { URITARGET = $$replace(URI, "\\.", "_") # Ensure the qml files are included in the resources @@ -61,3 +43,5 @@ qmldir.base = $$_PRO_FILE_PWD_ else: qmldir.files = $$qmldir_file qmldir.path = $$instbase/$$TARGETPATH INSTALLS += qmldir + +!prefix_build: COPIES += qmldir diff --git a/mkspecs/features/qt_common.prf b/mkspecs/features/qt_common.prf index 39e6163967..bc661f4dd7 100644 --- a/mkspecs/features/qt_common.prf +++ b/mkspecs/features/qt_common.prf @@ -44,6 +44,10 @@ contains(TEMPLATE, .*lib) { QMAKE_PRL_INSTALL_REPLACE += lib_replace } +# The remainder of this file must not apply to bootstrapped tools, +# as the host compiler's version and capabilities are not checked. +host_build:force_bootstrap: return() + # Extra warnings for Qt non-example code, to ensure cleanliness of the sources. # The block below may turn these warnings into errors for some Qt targets. # -Wdate-time: warn if we use __DATE__ or __TIME__ (we want to be able to reproduce the exact same binary) diff --git a/mkspecs/features/spec_pre.prf b/mkspecs/features/spec_pre.prf index ff310d9793..090f348ebf 100644 --- a/mkspecs/features/spec_pre.prf +++ b/mkspecs/features/spec_pre.prf @@ -51,5 +51,5 @@ equals(QMAKE_HOST.os, Windows) { QMAKE_SH = sh } -CONFIG = qt warn_on release link_prl +CONFIG = file_copies qt warn_on release link_prl QT = core gui diff --git a/qmake/generators/makefiledeps.cpp b/qmake/generators/makefiledeps.cpp index 0f6326bc0e..57cb0ea854 100644 --- a/qmake/generators/makefiledeps.cpp +++ b/qmake/generators/makefiledeps.cpp @@ -405,9 +405,9 @@ static bool matchWhileUnsplitting(const char *buffer, int buffer_len, int start, int *matchlen, int *lines) { int x = start; - for (int n = 0; n < needle_len && x < buffer_len; + for (int n = 0; n < needle_len; n++, x = skipEscapedLineEnds(buffer, buffer_len, x + 1, lines)) { - if (buffer[x] != needle[n]) + if (x >= buffer_len || buffer[x] != needle[n]) return false; } // That also skipped any remaining BSNLs immediately after the match. @@ -568,24 +568,29 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file) ++x; if (buffer_len >= x + 12 && !strncmp(buffer + x, "includehint", 11) && (buffer[x + 11] == ' ' || buffer[x + 11] == '>')) { - for (x += 11; buffer[x] != '>'; ++x) {} // skip + for (x += 11; x < buffer_len && buffer[x] != '>'; ++x) {} // skip int inc_len = 0; - for (x += 1 ; buffer[x + inc_len] != '<'; ++inc_len) {} // skip - buffer[x + inc_len] = '\0'; - inc = buffer + x; + for (++x; x + inc_len < buffer_len && buffer[x + inc_len] != '<'; ++inc_len) {} // skip + if (x + inc_len < buffer_len) { + buffer[x + inc_len] = '\0'; + inc = buffer + x; + } } else if (buffer_len >= x + 13 && !strncmp(buffer + x, "customwidget", 12) && (buffer[x + 12] == ' ' || buffer[x + 12] == '>')) { - for (x += 13; buffer[x] != '>'; ++x) {} // skip up to > + for (x += 13; x < buffer_len && buffer[x] != '>'; ++x) {} // skip up to > while(x < buffer_len) { - for (x++; buffer[x] != '<'; ++x) {} // skip up to < + while (++x < buffer_len && buffer[x] != '<') {} // skip up to < x++; if(buffer_len >= x + 7 && !strncmp(buffer+x, "header", 6) && (buffer[x + 6] == ' ' || buffer[x + 6] == '>')) { - for (x += 7; buffer[x] != '>'; ++x) {} // skip up to > + for (x += 7; x < buffer_len && buffer[x] != '>'; ++x) {} // skip up to > int inc_len = 0; - for (x += 1 ; buffer[x + inc_len] != '<'; ++inc_len) {} // skip - buffer[x + inc_len] = '\0'; - inc = buffer + x; + for (++x; x + inc_len < buffer_len && buffer[x + inc_len] != '<'; + ++inc_len) {} // skip + if (x + inc_len < buffer_len) { + buffer[x + inc_len] = '\0'; + inc = buffer + x; + } break; } else if(buffer_len >= x + 14 && !strncmp(buffer+x, "/customwidget", 13) && (buffer[x + 13] == ' ' || buffer[x + 13] == '>')) { @@ -595,20 +600,18 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file) } } else if(buffer_len >= x + 8 && !strncmp(buffer + x, "include", 7) && (buffer[x + 7] == ' ' || buffer[x + 7] == '>')) { - for (x += 8; buffer[x] != '>'; ++x) { + for (x += 8; x < buffer_len && buffer[x] != '>'; ++x) { if (buffer_len >= x + 9 && buffer[x] == 'i' && !strncmp(buffer + x, "impldecl", 8)) { - for (x += 8; buffer[x] != '='; ++x) {} // skip - if (buffer[x] != '=') - continue; - for (++x; buffer[x] == '\t' || buffer[x] == ' '; ++x) {} // skip + for (x += 8; x < buffer_len && buffer[x] != '='; ++x) {} // skip + while (++x < buffer_len && (buffer[x] == '\t' || buffer[x] == ' ')) {} // skip char quote = 0; - if (buffer[x] == '\'' || buffer[x] == '"') { + if (x < buffer_len && (buffer[x] == '\'' || buffer[x] == '"')) { quote = buffer[x]; ++x; } int val_len; - for(val_len = 0; true; ++val_len) { + for (val_len = 0; x + val_len < buffer_len; ++val_len) { if(quote) { if (buffer[x + val_len] == quote) break; @@ -618,16 +621,22 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file) } } //? char saved = buffer[x + val_len]; - buffer[x + val_len] = '\0'; - if(!strcmp(buffer+x, "in implementation")) { - //### do this + if (x + val_len < buffer_len) { + buffer[x + val_len] = '\0'; + if (!strcmp(buffer + x, "in implementation")) { + //### do this + } } } } int inc_len = 0; - for (x += 1 ; buffer[x + inc_len] != '<'; ++inc_len) {} // skip - buffer[x + inc_len] = '\0'; - inc = buffer + x; + for (++x; x + inc_len < buffer_len && buffer[x + inc_len] != '<'; + ++inc_len) {} // skip + + if (x + inc_len < buffer_len) { + buffer[x + inc_len] = '\0'; + inc = buffer + x; + } } } //read past new line now.. @@ -641,14 +650,16 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file) #define SKIP_BSNL(pos) skipEscapedLineEnds(buffer, buffer_len, (pos), &line_count) // Seek code or directive, skipping comments and space: - for(; x < buffer_len; ++x) { - x = SKIP_BSNL(x); + for (; (x = SKIP_BSNL(x)) < buffer_len; ++x) { if (buffer[x] == ' ' || buffer[x] == '\t') { // keep going } else if (buffer[x] == '/') { int extralines = 0; int y = skipEscapedLineEnds(buffer, buffer_len, x + 1, &extralines); - if (buffer[y] == '/') { // C++-style comment + if (y >= buffer_len) { + x = y; + break; + } else if (buffer[y] == '/') { // C++-style comment line_count += extralines; x = SKIP_BSNL(y + 1); while (x < buffer_len && !qmake_endOfLine(buffer[x])) @@ -659,8 +670,7 @@ bool QMakeSourceFileInfo::findDeps(SourceFile *file) } else if (buffer[y] == '*') { // C-style comment line_count += extralines; x = y; - while (++x < buffer_len) { - x = SKIP_BSNL(x); + while ((x = SKIP_BSNL(++x)) < buffer_len) { if (buffer[x] == '*') { extralines = 0; y = skipEscapedLineEnds(buffer, buffer_len, diff --git a/qmake/generators/metamakefile.cpp b/qmake/generators/metamakefile.cpp index b816fc21f8..874b4286bc 100644 --- a/qmake/generators/metamakefile.cpp +++ b/qmake/generators/metamakefile.cpp @@ -225,10 +225,8 @@ MakefileGenerator build_proj->setExtraVars(basevars); build_proj->setExtraConfigs(basecfgs); - build_proj->read(project->projectFile()); - - //done - return createMakefileGenerator(build_proj); + if (build_proj->read(project->projectFile())) + return createMakefileGenerator(build_proj); } return 0; } diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 86d027eb35..a08fde8bb0 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -105,6 +105,12 @@ # endif # define Q_DECL_EXPORT __declspec(dllexport) # define Q_DECL_IMPORT __declspec(dllimport) +# if _MSC_VER >= 1800 +# define QT_MAKE_UNCHECKED_ARRAY_ITERATOR(x) stdext::make_unchecked_array_iterator(x) +# endif +# if _MSC_VER >= 1500 +# define QT_MAKE_CHECKED_ARRAY_ITERATOR(x, N) stdext::make_checked_array_iterator(x, size_t(N)) +# endif /* Intel C++ disguising as Visual C++: the `using' keyword avoids warnings */ # if defined(__INTEL_COMPILER) # define Q_DECL_VARIABLE_DEPRECATED @@ -1106,6 +1112,11 @@ # define Q_ALIGNOF(x) alignof(x) #endif +#if defined(Q_COMPILER_ALIGNAS) +# undef Q_DECL_ALIGN +# define Q_DECL_ALIGN(n) alignas(n) +#endif + /* * Fallback macros to certain compiler features */ @@ -1174,6 +1185,12 @@ #ifndef Q_DECL_CONST_FUNCTION # define Q_DECL_CONST_FUNCTION Q_DECL_PURE_FUNCTION #endif +#ifndef QT_MAKE_UNCHECKED_ARRAY_ITERATOR +# define QT_MAKE_UNCHECKED_ARRAY_ITERATOR(x) (x) +#endif +#ifndef QT_MAKE_CHECKED_ARRAY_ITERATOR +# define QT_MAKE_CHECKED_ARRAY_ITERATOR(x, N) (x) +#endif /* * SG10's SD-6 feature detection and some useful extensions from Clang and GCC diff --git a/src/corelib/itemmodels/qidentityproxymodel.h b/src/corelib/itemmodels/qidentityproxymodel.h index 7a75f42d81..e93740c1a2 100644 --- a/src/corelib/itemmodels/qidentityproxymodel.h +++ b/src/corelib/itemmodels/qidentityproxymodel.h @@ -62,6 +62,7 @@ public: QModelIndex mapFromSource(const QModelIndex& sourceIndex) const Q_DECL_OVERRIDE; QModelIndex mapToSource(const QModelIndex& proxyIndex) const Q_DECL_OVERRIDE; QModelIndex parent(const QModelIndex& child) const Q_DECL_OVERRIDE; + using QObject::parent; int rowCount(const QModelIndex& parent = QModelIndex()) const Q_DECL_OVERRIDE; QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const Q_DECL_OVERRIDE; bool dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) Q_DECL_OVERRIDE; diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 0c1c37c89d..7bb2e7a78c 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -419,7 +419,7 @@ QCoreApplicationPrivate::QCoreApplicationPrivate(int &aargc, char **aargv, uint if (!isArgvModified(argc, argv)) { origArgc = argc; origArgv = new char *[argc]; - std::copy(argv, argv + argc, origArgv); + std::copy(argv, argv + argc, QT_MAKE_CHECKED_ARRAY_ITERATOR(origArgv, argc)); } #endif // Q_OS_WIN && !Q_OS_WINRT diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h index ebe118dce4..b68dbacbd3 100644 --- a/src/corelib/kernel/qmetatype.h +++ b/src/corelib/kernel/qmetatype.h @@ -1189,6 +1189,7 @@ public: public: template QAssociativeIterableImpl(const T*p) : _iterable(p) + , _iterator(Q_NULLPTR) , _metaType_id_key(qMetaTypeId()) , _metaType_flags_key(QTypeInfo::isPointer) , _metaType_id_value(qMetaTypeId()) @@ -1208,6 +1209,7 @@ public: QAssociativeIterableImpl() : _iterable(Q_NULLPTR) + , _iterator(Q_NULLPTR) , _metaType_id_key(QMetaType::UnknownType) , _metaType_flags_key(0) , _metaType_id_value(QMetaType::UnknownType) diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index fc5e6abf00..2b0eff3708 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -2151,8 +2151,8 @@ void QObject::deleteLater() Returns a translated version of \a sourceText, optionally based on a \a disambiguation string and value of \a n for strings containing plurals; - otherwise returns \a sourceText itself if no appropriate translated string - is available. + otherwise returns QString::fromUtf8(\a sourceText) if no appropriate + translated string is available. Example: \snippet ../widgets/mainwindows/sdi/mainwindow.cpp implicit tr context @@ -2178,7 +2178,7 @@ void QObject::deleteLater() translators while performing translations is not supported. Doing so will probably result in crashes or other undesirable behavior. - \sa trUtf8(), QCoreApplication::translate(), {Internationalization with Qt} + \sa QCoreApplication::translate(), {Internationalization with Qt} */ /*! diff --git a/src/corelib/tools/qarraydata.cpp b/src/corelib/tools/qarraydata.cpp index 21ad799e25..bf336a8f31 100644 --- a/src/corelib/tools/qarraydata.cpp +++ b/src/corelib/tools/qarraydata.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include +#include #include #include @@ -93,16 +94,22 @@ QArrayData *QArrayData::allocate(size_t objectSize, size_t alignment, if (capacity > std::numeric_limits::max() / objectSize) return 0; - size_t alloc = objectSize * capacity; + size_t alloc; + if (mul_overflow(objectSize, capacity, &alloc)) + return 0; - // Make sure qAllocMore won't overflow. + // Make sure qAllocMore won't overflow qAllocMore. if (headerSize > size_t(MaxAllocSize) || alloc > size_t(MaxAllocSize) - headerSize) return 0; capacity = qAllocMore(int(alloc), int(headerSize)) / int(objectSize); } - size_t allocSize = headerSize + objectSize * capacity; + size_t allocSize; + if (mul_overflow(objectSize, capacity, &allocSize)) + return 0; + if (add_overflow(allocSize, headerSize, &allocSize)) + return 0; QArrayData *header = static_cast(::malloc(allocSize)); if (header) { diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h index 5509c3adce..ec279769eb 100644 --- a/src/corelib/tools/qlist.h +++ b/src/corelib/tools/qlist.h @@ -852,7 +852,7 @@ inline bool QList::op_eq_impl(const QList &l, QListData::ArrayCompatibleLayou const T *lb = reinterpret_cast(l.p.begin()); const T *b = reinterpret_cast(p.begin()); const T *e = reinterpret_cast(p.end()); - return std::equal(b, e, lb); + return std::equal(b, e, QT_MAKE_CHECKED_ARRAY_ITERATOR(lb, l.p.size())); } template diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index c3aae2fd22..9f968978dc 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -712,8 +712,8 @@ static int findChar(const QChar *str, int len, QChar ch, int from, } #define REHASH(a) \ - if (sl_minus_1 < (int)sizeof(int) * CHAR_BIT) \ - hashHaystack -= (a) << sl_minus_1; \ + if (sl_minus_1 < sizeof(uint) * CHAR_BIT) \ + hashHaystack -= uint(a) << sl_minus_1; \ hashHaystack <<= 1 inline bool qIsUpper(char ch) @@ -3096,8 +3096,9 @@ int qFindString( const ushort *needle = (const ushort *)needle0; const ushort *haystack = (const ushort *)haystack0 + from; const ushort *end = (const ushort *)haystack0 + (l-sl); - const int sl_minus_1 = sl-1; - int hashNeedle = 0, hashHaystack = 0, idx; + const uint sl_minus_1 = sl - 1; + uint hashNeedle = 0, hashHaystack = 0; + int idx; if (cs == Qt::CaseSensitive) { for (idx = 0; idx < sl; ++idx) { @@ -3172,10 +3173,11 @@ static int lastIndexOfHelper(const ushort *haystack, int from, const ushort *nee const ushort *end = haystack; haystack += from; - const int sl_minus_1 = sl-1; + const uint sl_minus_1 = sl - 1; const ushort *n = needle+sl_minus_1; const ushort *h = haystack+sl_minus_1; - int hashNeedle = 0, hashHaystack = 0, idx; + uint hashNeedle = 0, hashHaystack = 0; + int idx; if (cs == Qt::CaseSensitive) { for (idx = 0; idx < sl; ++idx) { diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h index 24574dc90b..c3ac104399 100644 --- a/src/corelib/tools/qvarlengtharray.h +++ b/src/corelib/tools/qvarlengtharray.h @@ -102,7 +102,8 @@ public: QVarLengthArray &operator=(std::initializer_list list) { resize(list.size()); - std::copy(list.begin(), list.end(), this->begin()); + std::copy(list.begin(), list.end(), + QT_MAKE_CHECKED_ARRAY_ITERATOR(this->begin(), this->size())); return *this; } #endif @@ -473,7 +474,7 @@ Q_OUTOFLINE_TEMPLATE typename QVarLengthArray::iterator QVarLengthA int l = int(aend - ptr); int n = l - f; if (QTypeInfo::isComplex) { - std::copy(ptr + l, ptr + s, ptr + f); + std::copy(ptr + l, ptr + s, QT_MAKE_CHECKED_ARRAY_ITERATOR(ptr + f, s - f)); T *i = ptr + s; T *b = ptr + s - n; while (i != b) { @@ -495,7 +496,7 @@ bool operator==(const QVarLengthArray &l, const QVarLengthArray diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h index 806a127cc2..557bec9676 100644 --- a/src/corelib/tools/qvector.h +++ b/src/corelib/tools/qvector.h @@ -773,7 +773,7 @@ bool QVector::operator==(const QVector &v) const const T *vb = v.d->begin(); const T *b = d->begin(); const T *e = d->end(); - return std::equal(b, e, vb); + return std::equal(b, e, QT_MAKE_CHECKED_ARRAY_ITERATOR(vb, v.d->size)); } template diff --git a/src/dbus/dbus_minimal_p.h b/src/dbus/dbus_minimal_p.h index 8b40742e0c..b52b0153e4 100644 --- a/src/dbus/dbus_minimal_p.h +++ b/src/dbus/dbus_minimal_p.h @@ -105,9 +105,11 @@ typedef dbus_uint32_t dbus_bool_t; /* dbus-shared.h */ #define DBUS_SERVICE_DBUS "org.freedesktop.DBus" #define DBUS_PATH_DBUS "/org/freedesktop/DBus" +#define DBUS_PATH_LOCAL "/org/freedesktop/DBus/Local" #define DBUS_INTERFACE_DBUS "org.freedesktop.DBus" #define DBUS_INTERFACE_INTROSPECTABLE "org.freedesktop.DBus.Introspectable" #define DBUS_INTERFACE_PROPERTIES "org.freedesktop.DBus.Properties" +#define DBUS_INTERFACE_LOCAL "org.freedesktop.DBus.Local" #define DBUS_NAME_FLAG_ALLOW_REPLACEMENT 0x1 /**< Allow another service to become the primary owner if requested */ #define DBUS_NAME_FLAG_REPLACE_EXISTING 0x2 /**< Request to replace the current primary owner */ diff --git a/src/dbus/qdbusconnection_p.h b/src/dbus/qdbusconnection_p.h index b2fa8faae8..f00988c05f 100644 --- a/src/dbus/qdbusconnection_p.h +++ b/src/dbus/qdbusconnection_p.h @@ -265,6 +265,8 @@ private: QString getNameOwnerNoCache(const QString &service); + void watchForDBusDisconnection(); + void _q_newConnection(QDBusConnectionPrivate *newConnection); protected: @@ -284,6 +286,7 @@ private slots: void serviceOwnerChangedNoLock(const QString &name, const QString &oldOwner, const QString &newOwner); void registerServiceNoLock(const QString &serviceName); void unregisterServiceNoLock(const QString &serviceName); + void handleDBusDisconnection(); signals: void dispatchStatusChanged(); diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp index cc3080e6db..c73f808485 100644 --- a/src/dbus/qdbusintegrator.cpp +++ b/src/dbus/qdbusintegrator.cpp @@ -1126,6 +1126,12 @@ void QDBusConnectionPrivate::closeConnection() rootNode.children.clear(); // free resources } +void QDBusConnectionPrivate::handleDBusDisconnection() +{ + while (!pendingCalls.isEmpty()) + processFinishedCall(pendingCalls.first()); +} + void QDBusConnectionPrivate::checkThread() { Q_ASSERT(thread() == QDBusConnectionManager::instance()); @@ -1651,6 +1657,19 @@ void QDBusConnectionPrivate::handleSignal(const QDBusMessage& msg) handleSignal(key, msg); // third try } +void QDBusConnectionPrivate::watchForDBusDisconnection() +{ + SignalHook hook; + // Initialize the hook for Disconnected signal + hook.service.clear(); // org.freedesktop.DBus.Local.Disconnected uses empty service name + hook.path = QDBusUtil::dbusPathLocal(); + hook.obj = this; + hook.params << QMetaType::Void; + hook.midx = staticMetaObject.indexOfSlot("handleDBusDisconnection()"); + Q_ASSERT(hook.midx != -1); + signalHooks.insert(QLatin1String("Disconnected:" DBUS_INTERFACE_LOCAL), hook); +} + void QDBusConnectionPrivate::setServer(QDBusServer *object, DBusServer *s, const QDBusErrorInternal &error) { mode = ServerMode; @@ -1716,6 +1735,8 @@ void QDBusConnectionPrivate::setPeer(DBusConnection *c, const QDBusErrorInternal qDBusSignalFilter, this, 0); + watchForDBusDisconnection(); + QMetaObject::invokeMethod(this, "doDispatch", Qt::QueuedConnection); } @@ -1792,6 +1813,8 @@ void QDBusConnectionPrivate::setConnection(DBusConnection *dbc, const QDBusError Q_ASSERT(hook.midx != -1); signalHooks.insert(QLatin1String("NameOwnerChanged:" DBUS_INTERFACE_DBUS), hook); + watchForDBusDisconnection(); + qDBusDebug() << this << ": connected successfully"; // schedule a dispatch: @@ -1818,10 +1841,16 @@ void QDBusConnectionPrivate::processFinishedCall(QDBusPendingCallPrivate *call) QDBusMessage &msg = call->replyMessage; if (call->pending) { - // decode the message - DBusMessage *reply = q_dbus_pending_call_steal_reply(call->pending); - msg = QDBusMessagePrivate::fromDBusMessage(reply, connection->capabilities); - q_dbus_message_unref(reply); + // when processFinishedCall is called and pending call is not completed, + // it means we received disconnected signal from libdbus + if (q_dbus_pending_call_get_completed(call->pending)) { + // decode the message + DBusMessage *reply = q_dbus_pending_call_steal_reply(call->pending); + msg = QDBusMessagePrivate::fromDBusMessage(reply, connection->capabilities); + q_dbus_message_unref(reply); + } else { + msg = QDBusMessage::createError(QDBusError::Disconnected, QDBusUtil::disconnectedErrorMessage()); + } } qDBusDebug() << connection << "got message reply:" << msg; @@ -2121,8 +2150,8 @@ void QDBusConnectionPrivate::sendInternal(QDBusPendingCallPrivate *pcall, void * pcall->pending = pending; q_dbus_pending_call_set_notify(pending, qDBusResultReceived, pcall, 0); - // DBus won't notify us when a peer disconnects so we need to track these ourselves - if (mode == QDBusConnectionPrivate::PeerMode) + // DBus won't notify us when a peer disconnects or server terminates so we need to track these ourselves + if (mode == QDBusConnectionPrivate::PeerMode || mode == QDBusConnectionPrivate::ClientMode) pendingCalls.append(pcall); return; diff --git a/src/dbus/qdbusutil_p.h b/src/dbus/qdbusutil_p.h index e0ba92be2e..e11fe573b5 100644 --- a/src/dbus/qdbusutil_p.h +++ b/src/dbus/qdbusutil_p.h @@ -164,6 +164,8 @@ namespace QDBusUtil { return QStringLiteral(DBUS_SERVICE_DBUS); } inline QString dbusPath() { return QStringLiteral(DBUS_PATH_DBUS); } + inline QString dbusPathLocal() + { return QStringLiteral(DBUS_PATH_LOCAL); } inline QString dbusInterface() { // it's the same string, but just be sure diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp index 8a6eeb4cc9..8ccd85795b 100644 --- a/src/gui/kernel/qkeysequence.cpp +++ b/src/gui/kernel/qkeysequence.cpp @@ -1643,7 +1643,7 @@ QDataStream &operator>>(QDataStream &s, QKeySequence &keysequence) s >> keys[i]; } qAtomicDetach(keysequence.d); - std::copy(keys, keys + MaxKeys, keysequence.d->key); + std::copy(keys, keys + MaxKeys, QT_MAKE_CHECKED_ARRAY_ITERATOR(keysequence.d->key, MaxKeys)); return s; } diff --git a/src/gui/kernel/qkeysequence_p.h b/src/gui/kernel/qkeysequence_p.h index eeea0f5772..116e91c0cd 100644 --- a/src/gui/kernel/qkeysequence_p.h +++ b/src/gui/kernel/qkeysequence_p.h @@ -76,7 +76,8 @@ public: } inline QKeySequencePrivate(const QKeySequencePrivate ©) : ref(1) { - std::copy(copy.key, copy.key + MaxKeyCount, key); + std::copy(copy.key, copy.key + MaxKeyCount, + QT_MAKE_CHECKED_ARRAY_ITERATOR(key, MaxKeyCount)); } QAtomicInt ref; int key[MaxKeyCount]; diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index bcef14ca61..0b205b8b0e 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -6183,7 +6183,8 @@ static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen) QString key = QLatin1String("WaveUnderline-") % pen.color().name() - % HexString(radiusBase); + % HexString(radiusBase) + % HexString(pen.widthF()); QPixmap pixmap; if (QPixmapCache::find(key, pixmap)) @@ -6191,7 +6192,7 @@ static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen) const qreal halfPeriod = qMax(qreal(2), qreal(radiusBase * 1.61803399)); // the golden ratio const int width = qCeil(100 / (2 * halfPeriod)) * (2 * halfPeriod); - const int radius = qFloor(radiusBase); + const qreal radius = qFloor(radiusBase * 2) / 2.; QPainterPath path; @@ -6214,7 +6215,7 @@ static QPixmap generateWavyPixmap(qreal maxRadius, const QPen &pen) // due to it having a rather thick width for the regular underline. const qreal maxPenWidth = .8 * radius; if (wavePen.widthF() > maxPenWidth) - wavePen.setWidth(maxPenWidth); + wavePen.setWidthF(maxPenWidth); QPainter imgPainter(&pixmap); imgPainter.setPen(wavePen); @@ -6267,14 +6268,15 @@ static void drawTextItemDecoration(QPainter *painter, const QPointF &pos, const if (underlineStyle == QTextCharFormat::WaveUnderline) { painter->save(); painter->translate(0, pos.y() + 1); + qreal maxHeight = fe->descent().toReal() - qreal(1); QColor uc = charFormat.underlineColor(); if (uc.isValid()) pen.setColor(uc); // Adapt wave to underlineOffset or pen width, whatever is larger, to make it work on all platforms - const QPixmap wave = generateWavyPixmap(qMax(underlineOffset, pen.widthF()), pen); - const int descent = (int) fe->descent().toReal(); + const QPixmap wave = generateWavyPixmap(qMin(qMax(underlineOffset, pen.widthF()), maxHeight / 2.), pen); + const int descent = qFloor(maxHeight); painter->setBrushOrigin(painter->brushOrigin().x(), 0); painter->fillRect(pos.x(), 0, qCeil(width), qMin(wave.height(), descent), wave); diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp index 8189351bd8..9e38c5272f 100644 --- a/src/gui/painting/qpdf.cpp +++ b/src/gui/painting/qpdf.cpp @@ -1202,7 +1202,7 @@ void QPdfEngine::setPen() switch(d->pen.joinStyle()) { case Qt::MiterJoin: case Qt::SvgMiterJoin: - *d->currentPage << d->pen.miterLimit() << "M "; + *d->currentPage << qMax(qreal(1.0), d->pen.miterLimit()) << "M "; pdfJoinStyle = 0; break; case Qt::BevelJoin: diff --git a/src/gui/text/qzip.cpp b/src/gui/text/qzip.cpp index 5178f5a9a8..7cb89543ba 100644 --- a/src/gui/text/qzip.cpp +++ b/src/gui/text/qzip.cpp @@ -822,12 +822,12 @@ void QZipWriterPrivate::addEntry(EntryType type, const QString &fileName, const QZipReader::QZipReader(const QString &archive, QIODevice::OpenMode mode) { QScopedPointer f(new QFile(archive)); - f->open(mode); + const bool result = f->open(mode); QZipReader::Status status; const QFileDevice::FileError error = f->error(); - if (error == QFile::NoError) + if (result && error == QFile::NoError) { status = NoError; - else { + } else { if (error == QFile::ReadError) status = FileReadError; else if (error == QFile::OpenError) @@ -1119,9 +1119,8 @@ void QZipReader::close() QZipWriter::QZipWriter(const QString &fileName, QIODevice::OpenMode mode) { QScopedPointer f(new QFile(fileName)); - f->open(mode); QZipWriter::Status status; - if (f->error() == QFile::NoError) + if (f->open(mode) && f->error() == QFile::NoError) status = QZipWriter::NoError; else { if (f->error() == QFile::WriteError) diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 67b4550607..45caaffe75 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -287,7 +287,6 @@ int q_X509Callback(int ok, X509_STORE_CTX *ctx) qCDebug(lcSsl) << QSslCertificatePrivate::QSslCertificate_from_X509(q_X509_STORE_CTX_get_current_cert(ctx)).toPem(); qCDebug(lcSsl) << "dumping chain"; foreach (QSslCertificate cert, QSslSocketBackendPrivate::STACKOFX509_to_QSslCertificates(q_X509_STORE_CTX_get_chain(ctx))) { - QString certFormat(QStringLiteral("O=%1 CN=%2 L=%3 OU=%4 C=%5 ST=%6")); qCDebug(lcSsl) << "Issuer:" << "O=" << cert.issuerInfo(QSslCertificate::Organization) << "CN=" << cert.issuerInfo(QSslCertificate::CommonName) << "L=" << cert.issuerInfo(QSslCertificate::LocalityName) diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp index b288a05e32..652a9f4add 100644 --- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -69,12 +69,6 @@ static inline int mapToQtWeightForRange(int fcweight, int fcLower, int fcUpper, return qtLower + ((fcweight - fcLower) * (qtUpper - qtLower)) / (fcUpper - fcLower); } -static inline bool requiresOpenType(int writingSystem) -{ - return ((writingSystem >= QFontDatabase::Syriac && writingSystem <= QFontDatabase::Sinhala) - || writingSystem == QFontDatabase::Khmer || writingSystem == QFontDatabase::Nko); -} - static inline int weightFromFcWeight(int fcweight) { // Font Config uses weights from 0 to 215 (the highest enum value) while QFont ranges from @@ -300,10 +294,10 @@ static const char *languageForWritingSystem[] = { Q_STATIC_ASSERT(sizeof(languageForWritingSystem) / sizeof(const char *) == QFontDatabase::WritingSystemsCount); #if FC_VERSION >= 20297 -// Newer FontConfig let's us sort out fonts that contain certain glyphs, but no -// open type tables for is directly. Do this so we don't pick some strange -// pseudo unicode font -static const char *openType[] = { +// Newer FontConfig let's us sort out fonts that report certain scripts support, +// but no open type tables for handling them correctly. +// Check the reported script presence in the FC_CAPABILITY's "otlayout:" section. +static const char *capabilityForWritingSystem[] = { 0, // Any 0, // Latin 0, // Greek @@ -339,7 +333,7 @@ static const char *openType[] = { 0, // Runic "nko " // N'Ko }; -Q_STATIC_ASSERT(sizeof(openType) / sizeof(const char *) == QFontDatabase::WritingSystemsCount); +Q_STATIC_ASSERT(sizeof(capabilityForWritingSystem) / sizeof(*capabilityForWritingSystem) == QFontDatabase::WritingSystemsCount); #endif static const char *getFcFamilyForStyleHint(const QFont::StyleHint style) @@ -422,11 +416,23 @@ static void populateFromPattern(FcPattern *pattern) FcResult res = FcPatternGetLangSet(pattern, FC_LANG, 0, &langset); if (res == FcResultMatch) { bool hasLang = false; +#if FC_VERSION >= 20297 + FcChar8 *cap = Q_NULLPTR; + FcResult capRes = FcResultNoMatch; +#endif for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) { const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[j]; if (lang) { FcLangResult langRes = FcLangSetHasLang(langset, lang); if (langRes != FcLangDifferentLang) { +#if FC_VERSION >= 20297 + if (capabilityForWritingSystem[j] != Q_NULLPTR) { + if (cap == Q_NULLPTR) + capRes = FcPatternGetString(pattern, FC_CAPABILITY, 0, &cap); + if (capRes == FcResultMatch && strstr(reinterpret_cast(cap), capabilityForWritingSystem[j]) == 0) + continue; + } +#endif writingSystems.setSupported(QFontDatabase::WritingSystem(j)); hasLang = true; } @@ -442,18 +448,6 @@ static void populateFromPattern(FcPattern *pattern) writingSystems.setSupported(QFontDatabase::Other); } -#if FC_VERSION >= 20297 - for (int j = 1; j < QFontDatabase::WritingSystemsCount; ++j) { - if (writingSystems.supported(QFontDatabase::WritingSystem(j)) - && requiresOpenType(j) && openType[j]) { - FcChar8 *cap; - res = FcPatternGetString (pattern, FC_CAPABILITY, 0, &cap); - if (res != FcResultMatch || !strstr((const char *)cap, openType[j])) - writingSystems.setSupported(QFontDatabase::WritingSystem(j),false); - } - } -#endif - FontFile *fontFile = new FontFile; fontFile->fileName = QString::fromLocal8Bit((const char *)file_value); fontFile->indexValue = indexValue; diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index 0690a8e0fa..a388155c03 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -105,7 +105,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaMenuDelegate); - (NSInteger)numberOfItemsInMenu:(NSMenu *)menu { Q_ASSERT(m_menu->nsMenu() == menu); - return m_menu->items().count(); + return menu.numberOfItems; } - (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 908277a1e3..697cece77f 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -747,8 +747,7 @@ QT_WARNING_POP - (void)handleMouseEvent:(NSEvent *)theEvent { - if ([self handleTabletEvent: theEvent]) - return; + bool isTabletEvent = [self handleTabletEvent: theEvent]; QPointF qtWindowPoint; QPointF qtScreenPoint; @@ -777,7 +776,8 @@ QT_WARNING_POP nativeDrag->setLastMouseEvent(theEvent, self); Qt::KeyboardModifiers keyboardModifiers = [QNSView convertKeyModifiers:[theEvent modifierFlags]]; - QWindowSystemInterface::handleMouseEvent(targetView->m_window, timestamp, qtWindowPoint, qtScreenPoint, m_buttons, keyboardModifiers); + QWindowSystemInterface::handleMouseEvent(targetView->m_window, timestamp, qtWindowPoint, qtScreenPoint, m_buttons, keyboardModifiers, + isTabletEvent ? Qt::MouseEventSynthesizedByQt : Qt::MouseEventNotSynthesized); } - (void)handleFrameStrutMouseEvent:(NSEvent *)theEvent diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp index f34649e327..5ba49a8a98 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp +++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -607,7 +608,8 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_keyBinding(long actionIndex // The IDL documents that the client must free with CoTaskMemFree arrayOfBindingsToReturn = coTaskMemAllocArray(numBindings); std::transform(keyBindings.constBegin(), keyBindings.constEnd(), - arrayOfBindingsToReturn, QStringToBSTR); + QT_MAKE_CHECKED_ARRAY_ITERATOR(arrayOfBindingsToReturn, numBindings), + QStringToBSTR); } } *keyBindings = arrayOfBindingsToReturn; @@ -666,9 +668,11 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_locationInParent(long *x, l QAccessibleInterface *parentIface = accessible->parent(); if (parentIface && parentIface->isValid()) topLeft -= parentIface->rect().topLeft(); + const QPoint nativeTopLeft = QHighDpi::toNativeLocalPosition(topLeft, accessible->window()); - *x = topLeft.x(); - *y = topLeft.y(); + + *x = nativeTopLeft.x(); + *y = nativeTopLeft.y(); return S_OK; } @@ -989,7 +993,8 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedColumns(long **sele *selectedColumns = Q_NULLPTR; if (count) { *selectedColumns = coTaskMemAllocArray(count); - std::copy(selectedIndices.constBegin(), selectedIndices.constEnd(), *selectedColumns); + std::copy(selectedIndices.constBegin(), selectedIndices.constEnd(), + QT_MAKE_CHECKED_ARRAY_ITERATOR(*selectedColumns, count)); } return count ? S_OK : S_FALSE; } @@ -1011,7 +1016,8 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::get_selectedRows(long **selecte *selectedRows = Q_NULLPTR; if (count) { *selectedRows = coTaskMemAllocArray(count); - std::copy(selectedIndices.constBegin(), selectedIndices.constEnd(), *selectedRows); + std::copy(selectedIndices.constBegin(), selectedIndices.constEnd(), + QT_MAKE_CHECKED_ARRAY_ITERATOR(*selectedRows, count)); } return count ? S_OK : S_FALSE; } @@ -1680,7 +1686,8 @@ HRESULT QWindowsIA2Accessible::wrapListOfCells(const QList(count); std::transform(inputCells.constBegin(), inputCells.constEnd(), - *outputAccessibles, QWindowsAccessibility::wrap); + QT_MAKE_CHECKED_ARRAY_ITERATOR(*outputAccessibles, count), + QWindowsAccessibility::wrap); } return count > 0 ? S_OK : S_FALSE; } diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp index 0fff804e29..5fb06a6ed1 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp +++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp @@ -55,6 +55,7 @@ #include #include #include +#include //#include #ifndef UiaRootObjectId @@ -503,7 +504,8 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accHitTest(long xLeft, long yT if (!accessible) return E_FAIL; - QAccessibleInterface *child = accessible->childAt(xLeft, yTop); + const QPoint pos = QHighDpi::fromNativeLocalPosition(QPoint(xLeft, yTop), accessible->window()); + QAccessibleInterface *child = accessible->childAt(pos.x(), pos.y()); if (child == 0) { // no child found, return this item if it contains the coordinates if (accessible->rect().contains(xLeft, yTop)) { @@ -545,7 +547,7 @@ HRESULT STDMETHODCALLTYPE QWindowsMsaaAccessible::accLocation(long *pxLeft, long QAccessibleInterface *acc = childPointer(accessible, varID); if (!acc || !acc->isValid()) return E_FAIL; - const QRect rect = acc->rect(); + const QRect rect = QHighDpi::toNativePixels(acc->rect(), accessible->window()); *pxLeft = rect.x(); *pyTop = rect.y(); diff --git a/src/plugins/platforms/windows/qwindowsinputcontext.cpp b/src/plugins/platforms/windows/qwindowsinputcontext.cpp index ea68ba8cab..501b956a68 100644 --- a/src/plugins/platforms/windows/qwindowsinputcontext.cpp +++ b/src/plugins/platforms/windows/qwindowsinputcontext.cpp @@ -654,7 +654,7 @@ int QWindowsInputContext::reconvertString(RECONVERTSTRING *reconv) reconv->dwTargetStrOffset = reconv->dwCompStrOffset; ushort *pastReconv = reinterpret_cast(reconv + 1); std::copy(surroundingText.utf16(), surroundingText.utf16() + surroundingText.size(), - pastReconv); + QT_MAKE_UNCHECKED_ARRAY_ITERATOR(pastReconv)); return memSize; } diff --git a/src/plugins/platforms/winrt/qwinrtfileengine.cpp b/src/plugins/platforms/winrt/qwinrtfileengine.cpp index ad81ef4f5f..53e7ebd30d 100644 --- a/src/plugins/platforms/winrt/qwinrtfileengine.cpp +++ b/src/plugins/platforms/winrt/qwinrtfileengine.cpp @@ -466,14 +466,20 @@ qint64 QWinRTFileEngine::read(char *data, qint64 maxlen) hr = stream->ReadAsync(buffer.Get(), length, InputStreamOptions_None, &op); RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::ReadError, -1); - hr = QWinRTFunctions::await(op, buffer.GetAddressOf()); + // Quoting MSDN IInputStream::ReadAsync() documentation: + // "Depending on the implementation, the data that's read might be placed + // into the input buffer, or it might be returned in a different buffer." + // Using GetAddressOf can cause ref counting errors leaking the original + // buffer. + ComPtr effectiveBuffer; + hr = QWinRTFunctions::await(op, effectiveBuffer.GetAddressOf()); RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::ReadError, -1); - hr = buffer->get_Length(&length); + hr = effectiveBuffer->get_Length(&length); RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::ReadError, -1); ComPtr byteArrayAccess; - hr = buffer.As(&byteArrayAccess); + hr = effectiveBuffer.As(&byteArrayAccess); RETURN_AND_SET_ERROR_IF_FAILED(QFileDevice::ReadError, -1); byte *bytes; diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index f3667aaa0d..aed33f6b48 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -955,8 +955,20 @@ HRESULT QWinRTScreen::onPointerEntered(ICoreWindow *, IPointerEventArgs *args) return S_OK; } -HRESULT QWinRTScreen::onPointerExited(ICoreWindow *, IPointerEventArgs *) +HRESULT QWinRTScreen::onPointerExited(ICoreWindow *, IPointerEventArgs *args) { + Q_D(QWinRTScreen); + + ComPtr pointerPoint; + if (FAILED(args->get_CurrentPoint(&pointerPoint))) + return E_INVALIDARG; + + quint32 id; + if (FAILED(pointerPoint->get_PointerId(&id))) + return E_INVALIDARG; + + d->touchPoints.remove(id); + QWindowSystemInterface::handleLeaveEvent(0); return S_OK; } @@ -1040,6 +1052,7 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args) break; } + case PointerDeviceType_Pen: case PointerDeviceType_Touch: { if (!d->touchDevice) { d->touchDevice = new QTouchDevice; @@ -1058,51 +1071,45 @@ HRESULT QWinRTScreen::onPointerUpdated(ICoreWindow *, IPointerEventArgs *args) float pressure; properties->get_Pressure(&pressure); - QHash::iterator it = d->touchPoints.find(id); - if (it != d->touchPoints.end()) { - boolean isPressed; + boolean isPressed; #ifndef Q_OS_WINPHONE - pointerPoint->get_IsInContact(&isPressed); + pointerPoint->get_IsInContact(&isPressed); #else - properties->get_IsLeftButtonPressed(&isPressed); // IsInContact not reliable on phone + properties->get_IsLeftButtonPressed(&isPressed); // IsInContact not reliable on phone #endif - it.value().state = isPressed ? Qt::TouchPointMoved : Qt::TouchPointReleased; - } else { + + const QRectF areaRect(area.X * d->scaleFactor, area.Y * d->scaleFactor, + area.Width * d->scaleFactor, area.Height * d->scaleFactor); + + QHash::iterator it = d->touchPoints.find(id); + if (it == d->touchPoints.end()) { it = d->touchPoints.insert(id, QWindowSystemInterface::TouchPoint()); - it.value().state = Qt::TouchPointPressed; it.value().id = id; } - it.value().area = QRectF(area.X * d->scaleFactor, area.Y * d->scaleFactor, - area.Width * d->scaleFactor, area.Height * d->scaleFactor); + + if (isPressed && it.value().pressure == 0.) + it.value().state = Qt::TouchPointPressed; + else if (!isPressed && it.value().pressure > 0.) + it.value().state = Qt::TouchPointReleased; + else if (it.value().area == areaRect) + it.value().state = Qt::TouchPointStationary; + else + it.value().state = Qt::TouchPointMoved; + + it.value().area = areaRect; it.value().normalPosition = QPointF(point.X/d->logicalRect.width(), point.Y/d->logicalRect.height()); it.value().pressure = pressure; QWindowSystemInterface::handleTouchEvent(topWindow(), d->touchDevice, d->touchPoints.values(), mods); - // Remove released points, station others - for (QHash::iterator i = d->touchPoints.begin(); i != d->touchPoints.end();) { - if (i.value().state == Qt::TouchPointReleased) - i = d->touchPoints.erase(i); - else - (i++).value().state = Qt::TouchPointStationary; - } - - break; - } - case PointerDeviceType_Pen: { - quint32 id; - pointerPoint->get_PointerId(&id); - - boolean isPressed; - pointerPoint->get_IsInContact(&isPressed); + // Fall-through for pen to generate tablet event + if (pointerDeviceType != PointerDeviceType_Pen) + break; boolean isEraser; properties->get_IsEraser(&isEraser); int pointerType = isEraser ? 3 : 1; - float pressure; - properties->get_Pressure(&pressure); - float xTilt; properties->get_XTilt(&xTilt); diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp index ea20ef7a04..1c9faa17ea 100644 --- a/src/plugins/platforms/xcb/qxcbdrag.cpp +++ b/src/plugins/platforms/xcb/qxcbdrag.cpp @@ -1078,6 +1078,40 @@ void QXcbDrag::cancel() send_leave(); } +// find an ancestor with XdndAware on it +static xcb_window_t findXdndAwareParent(QXcbConnection *c, xcb_window_t window) +{ + xcb_window_t target = 0; + forever { + // check if window has XdndAware + xcb_get_property_cookie_t gpCookie = Q_XCB_CALL( + xcb_get_property(c->xcb_connection(), false, window, + c->atom(QXcbAtom::XdndAware), XCB_GET_PROPERTY_TYPE_ANY, 0, 0)); + xcb_get_property_reply_t *gpReply = xcb_get_property_reply( + c->xcb_connection(), gpCookie, 0); + bool aware = gpReply && gpReply->type != XCB_NONE; + free(gpReply); + if (aware) { + target = window; + break; + } + + // try window's parent + xcb_query_tree_cookie_t qtCookie = Q_XCB_CALL( + xcb_query_tree_unchecked(c->xcb_connection(), window)); + xcb_query_tree_reply_t *qtReply = xcb_query_tree_reply( + c->xcb_connection(), qtCookie, NULL); + if (!qtReply) + break; + xcb_window_t root = qtReply->root; + xcb_window_t parent = qtReply->parent; + free(qtReply); + if (window == root) + break; + window = parent; + } + return target; +} void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event) { @@ -1105,17 +1139,16 @@ void QXcbDrag::handleSelectionRequest(const xcb_selection_request_event_t *event // xcb_convert_selection() that we sent the XdndDrop event to. at = findTransactionByWindow(event->requestor); } -// if (at == -1 && event->time == XCB_CURRENT_TIME) { -// // previous Qt versions always requested the data on a child of the target window -// // using CurrentTime... but it could be asking for either drop data or the current drag's data -// Window target = findXdndAwareParent(event->requestor); -// if (target) { -// if (current_target && current_target == target) -// at = -2; -// else -// at = findXdndDropTransactionByWindow(target); -// } -// } + + if (at == -1 && event->time == XCB_CURRENT_TIME) { + xcb_window_t target = findXdndAwareParent(connection(), event->requestor); + if (target) { + if (current_target == target) + at = -2; + else + at = findTransactionByWindow(target); + } + } } QDrag *transactionDrag = 0; diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp index f4f758df6c..dcd1268f6f 100644 --- a/src/testlib/qtestcase.cpp +++ b/src/testlib/qtestcase.cpp @@ -239,6 +239,7 @@ namespace QTest static int keyDelay = -1; static int mouseDelay = -1; static int eventDelay = -1; + static int timeout = -1; static bool noCrashHandler = false; /*! \internal @@ -290,6 +291,18 @@ int Q_TESTLIB_EXPORT defaultKeyDelay() return keyDelay; } +static int defaultTimeout() +{ + if (timeout == -1) { + bool ok = false; + timeout = qEnvironmentVariableIntValue("QTEST_FUNCTION_TIMEOUT", &ok); + + if (!ok || timeout <= 0) + timeout = 5*60*1000; + } + return timeout; +} + Q_TESTLIB_EXPORT bool printAvailableFunctions = false; Q_TESTLIB_EXPORT QStringList testFunctions; Q_TESTLIB_EXPORT QStringList testTags; @@ -867,7 +880,7 @@ public: void beginTest() { QMutexLocker locker(&mutex); - timeout.store(5*60*1000); + timeout.store(defaultTimeout()); waitCondition.wakeAll(); } diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index d9b6dc05bf..1cf2d2b05e 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -3596,7 +3596,7 @@ void QFileDialogPrivate::_q_enterDirectory(const QModelIndex &index) } } else { // Do not accept when shift-clicking to multi-select a file in environments with single-click-activation (KDE) - if (!q->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick) + if (!q->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick, Q_NULLPTR, qFileDialogUi->treeView) || q->fileMode() != QFileDialog::ExistingFiles || !(QGuiApplication::keyboardModifiers() & Qt::CTRL)) { q->accept(); } diff --git a/src/widgets/dialogs/qfilesystemmodel.h b/src/widgets/dialogs/qfilesystemmodel.h index b7e77f31db..6d50d0b606 100644 --- a/src/widgets/dialogs/qfilesystemmodel.h +++ b/src/widgets/dialogs/qfilesystemmodel.h @@ -81,6 +81,7 @@ public: QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; QModelIndex index(const QString &path, int column = 0) const; QModelIndex parent(const QModelIndex &child) const Q_DECL_OVERRIDE; + using QObject::parent; QModelIndex sibling(int row, int column, const QModelIndex &idx) const Q_DECL_OVERRIDE; bool hasChildren(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE; bool canFetchMore(const QModelIndex &parent) const Q_DECL_OVERRIDE; diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp index 103c49496e..3e17b22102 100644 --- a/src/widgets/styles/qstyle.cpp +++ b/src/widgets/styles/qstyle.cpp @@ -157,10 +157,10 @@ static int unpackControlTypes(QSizePolicy::ControlTypes controls, QSizePolicy::C Qt's built-in widgets use QStyle to perform nearly all of their drawing, ensuring that they look exactly like the equivalent - native widgets. The diagram below shows a QComboBox in eight + native widgets. The diagram below shows a QComboBox in nine different styles. - \image qstyle-comboboxes.png Eight combo boxes + \image qstyle-comboboxes.png Nine combo boxes Topics: diff --git a/src/widgets/widgets/qabstractscrollarea.cpp b/src/widgets/widgets/qabstractscrollarea.cpp index 2ad9f88e6b..1482b990a6 100644 --- a/src/widgets/widgets/qabstractscrollarea.cpp +++ b/src/widgets/widgets/qabstractscrollarea.cpp @@ -310,7 +310,7 @@ void QAbstractScrollAreaPrivate::init() viewportFilter.reset(new QAbstractScrollAreaFilter(this)); viewport->installEventFilter(viewportFilter.data()); viewport->setFocusProxy(q); - q->setFocusPolicy(Qt::WheelFocus); + q->setFocusPolicy(Qt::StrongFocus); q->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken); q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); layoutChildren(); diff --git a/src/widgets/widgets/qabstractslider.cpp b/src/widgets/widgets/qabstractslider.cpp index 3f6185b4e7..4221ff40ef 100644 --- a/src/widgets/widgets/qabstractslider.cpp +++ b/src/widgets/widgets/qabstractslider.cpp @@ -734,9 +734,10 @@ bool QAbstractSliderPrivate::scrollByDelta(Qt::Orientation orientation, Qt::Keyb if (stepsToScroll == 0) { // We moved less than a line, but might still have accumulated partial scroll, // unless we already are at one of the ends. - if (offset_accumulated > 0.f && value < maximum) + const float effective_offset = invertedControls ? -offset_accumulated : offset_accumulated; + if (effective_offset > 0.f && value < maximum) return true; - if (offset_accumulated < 0.f && value > minimum) + if (effective_offset < 0.f && value > minimum) return true; offset_accumulated = 0; return false; diff --git a/src/widgets/widgets/qdatetimeedit_p.h b/src/widgets/widgets/qdatetimeedit_p.h index 6abb3cd9a3..be7bc213a2 100644 --- a/src/widgets/widgets/qdatetimeedit_p.h +++ b/src/widgets/widgets/qdatetimeedit_p.h @@ -78,15 +78,14 @@ public: void init(const QVariant &var); void readLocaleSettings(); - void emitSignals(EmitPolicy ep, const QVariant &old); - QString textFromValue(const QVariant &f) const; - QVariant valueFromText(const QString &f) const; - QDateTime validateAndInterpret(QString &input, int &, QValidator::State &state, bool fixup = false) const; void clearSection(int index); // Override QAbstractSpinBoxPrivate: + void emitSignals(EmitPolicy ep, const QVariant &old) Q_DECL_OVERRIDE; + QString textFromValue(const QVariant &f) const Q_DECL_OVERRIDE; + QVariant valueFromText(const QString &f) const Q_DECL_OVERRIDE; void _q_editorCursorPositionChanged(int oldpos, int newpos) Q_DECL_OVERRIDE; void interpret(EmitPolicy ep) Q_DECL_OVERRIDE; void clearCache() const Q_DECL_OVERRIDE; @@ -94,16 +93,18 @@ public: void updateEditFieldGeometry() Q_DECL_OVERRIDE; QVariant getZeroVariant() const Q_DECL_OVERRIDE; void setRange(const QVariant &min, const QVariant &max) Q_DECL_OVERRIDE; + void updateEdit() Q_DECL_OVERRIDE; - // Override QDateTimePraser: + // Override QDateTimeParser: QString displayText() const Q_DECL_OVERRIDE { return edit->text(); } QDateTime getMinimum() const Q_DECL_OVERRIDE { return minimum.toDateTime(); } QDateTime getMaximum() const Q_DECL_OVERRIDE { return maximum.toDateTime(); } QLocale locale() const Q_DECL_OVERRIDE { return q_func()->locale(); } + QString getAmPmText(AmPm ap, Case cs) const Q_DECL_OVERRIDE; + int cursorPosition() const Q_DECL_OVERRIDE { return edit ? edit->cursorPosition() : -1; } int absoluteIndex(QDateTimeEdit::Section s, int index) const; int absoluteIndex(const SectionNode &s) const; - void updateEdit(); QDateTime stepBy(int index, int steps, bool test = false) const; int sectionAt(int pos) const; int closestSection(int index, bool forward) const; @@ -114,8 +115,6 @@ public: void updateTimeSpec(); QString valueToText(const QVariant &var) const { return textFromValue(var); } - QString getAmPmText(AmPm ap, Case cs) const; - int cursorPosition() const { return edit ? edit->cursorPosition() : -1; } void _q_resetButton(); void updateArrow(QStyle::StateFlag state); diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp index 1da8028efb..9675e5e9f2 100644 --- a/src/widgets/widgets/qplaintextedit.cpp +++ b/src/widgets/widgets/qplaintextedit.cpp @@ -802,7 +802,7 @@ void QPlainTextEditPrivate::init(const QString &txt) viewport->setBackgroundRole(QPalette::Base); q->setAcceptDrops(true); - q->setFocusPolicy(Qt::WheelFocus); + q->setFocusPolicy(Qt::StrongFocus); q->setAttribute(Qt::WA_KeyCompression); q->setAttribute(Qt::WA_InputMethodEnabled); q->setInputMethodHints(Qt::ImhMultiLine); diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp index a81781bd4d..df69b49687 100644 --- a/src/widgets/widgets/qtextedit.cpp +++ b/src/widgets/widgets/qtextedit.cpp @@ -177,7 +177,7 @@ void QTextEditPrivate::init(const QString &html) viewport->setBackgroundRole(QPalette::Base); q->setAcceptDrops(true); - q->setFocusPolicy(Qt::WheelFocus); + q->setFocusPolicy(Qt::StrongFocus); q->setAttribute(Qt::WA_KeyCompression); q->setAttribute(Qt::WA_InputMethodEnabled); q->setInputMethodHints(Qt::ImhMultiLine); diff --git a/tests/auto/corelib/tools/qtimezone/BLACKLIST b/tests/auto/corelib/tools/qtimezone/BLACKLIST deleted file mode 100644 index 665e78bc08..0000000000 --- a/tests/auto/corelib/tools/qtimezone/BLACKLIST +++ /dev/null @@ -1,2 +0,0 @@ -[tzTest] -opensuse-13.1 diff --git a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp b/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp index 077a6a20f1..9fd418742c 100644 --- a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp +++ b/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp @@ -762,16 +762,22 @@ void tst_QTimeZone::tzTest() // Warning: This could vary depending on age of TZ file! // Test low date uses first rule found + // Note: Depending on the OS in question, the database may be carrying the + // Local Mean Time. which for Berlin is 0:53:28 QTimeZonePrivate::Data dat = tzp.data(-9999999999999); QCOMPARE(dat.atMSecsSinceEpoch, (qint64)-9999999999999); - QCOMPARE(dat.standardTimeOffset, 3600); QCOMPARE(dat.daylightTimeOffset, 0); + if (dat.abbreviation == "LMT") { + QCOMPARE(dat.standardTimeOffset, 3208); + } else { + QCOMPARE(dat.standardTimeOffset, 3600); - // Test previous to low value is invalid - dat = tzp.previousTransition(-9999999999999); - QCOMPARE(dat.atMSecsSinceEpoch, std::numeric_limits::min()); - QCOMPARE(dat.standardTimeOffset, std::numeric_limits::min()); - QCOMPARE(dat.daylightTimeOffset, std::numeric_limits::min()); + // Test previous to low value is invalid + dat = tzp.previousTransition(-9999999999999); + QCOMPARE(dat.atMSecsSinceEpoch, std::numeric_limits::min()); + QCOMPARE(dat.standardTimeOffset, std::numeric_limits::min()); + QCOMPARE(dat.daylightTimeOffset, std::numeric_limits::min()); + } dat = tzp.nextTransition(-9999999999999); QCOMPARE(dat.atMSecsSinceEpoch, (qint64)-2422054408000); diff --git a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp index 3418a34c12..0163f44a36 100644 --- a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp +++ b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp @@ -1213,6 +1213,27 @@ void tst_QDBusConnection::callVirtualObjectLocal() QCOMPARE(obj.replyArguments, subPathReply.arguments()); } +void tst_QDBusConnection::pendingCallWhenDisconnected() +{ + if (!QCoreApplication::instance()) + QSKIP("Test requires a QCoreApplication"); + + QDBusServer *server = new QDBusServer; + QDBusConnection con = QDBusConnection::connectToPeer(server->address(), "disconnect"); + QTestEventLoop::instance().enterLoop(2); + QVERIFY(con.isConnected()); + QDBusMessage message = QDBusMessage::createMethodCall("", "/", QString(), "method"); + QDBusPendingCall reply = con.asyncCall(message); + + delete server; + + QTestEventLoop::instance().enterLoop(2); + QVERIFY(!con.isConnected()); + QVERIFY(reply.isFinished()); + QVERIFY(reply.isError()); + QVERIFY(reply.error().type() == QDBusError::Disconnected); +} + QString MyObject::path; QString MyObjectWithoutInterface::path; QString MyObjectWithoutInterface::interface; diff --git a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h index 0e2943b1c4..0402889c6e 100644 --- a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h +++ b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.h @@ -116,6 +116,7 @@ private slots: void registerVirtualObject(); void callVirtualObject(); void callVirtualObjectLocal(); + void pendingCallWhenDisconnected(); public: QString serviceName() const { return "org.qtproject.Qt.Autotests.QDBusConnection"; } diff --git a/tests/auto/other/compiler/tst_compiler.cpp b/tests/auto/other/compiler/tst_compiler.cpp index d554a50c8d..50cfe48cdf 100644 --- a/tests/auto/other/compiler/tst_compiler.cpp +++ b/tests/auto/other/compiler/tst_compiler.cpp @@ -679,25 +679,105 @@ void tst_Compiler::cxx11_atomics() #endif } +QT_WARNING_PUSH +QT_WARNING_DISABLE_CLANG("-Wignored-attributes") +QT_WARNING_DISABLE_CLANG("-Wunused-local-typedefs") +QT_WARNING_DISABLE_GCC("-Wattributes") +QT_WARNING_DISABLE_GCC("-Wunused-local-typedefs") + +#ifndef __has_cpp_attribute +# define __has_cpp_attribute(x) 0 +#endif +#ifdef Q_COMPILER_ATTRIBUTES +[[noreturn]] void attribute_f1(); +void attribute_f2 [[noreturn]] (); +# if (defined(__cpp_namespace_attributes) && __cpp_namespace_attributes >= 201411) && __has_cpp_attribute(deprecated) +namespace NS [[deprecated]] { } +# endif +#endif + void tst_Compiler::cxx11_attributes() { #ifndef Q_COMPILER_ATTRIBUTES QSKIP("Compiler does not support C++11 feature"); #else - struct [[deprecated]] C {}; + // Attributes in function parameters and using clauses cause MSVC 2015 to crash + // https://connect.microsoft.com/VisualStudio/feedback/details/2011594 +# if (!defined(Q_CC_MSVC) || _MSC_FULL_VER >= 190023811) && !defined(Q_CC_INTEL) + void f([[ ]] int); + [[ ]] using namespace QtPrivate; + [[ ]] try { + } catch ([[]] int) { + } +# endif + + struct [[ ]] A { }; + struct B : A { + [[ ]] int m_i : 32; + [[noreturn]] void f() const { ::exit(0); } + +# ifdef Q_COMPILER_DEFAULT_DELETE_MEMBERS + [[ ]] ~B() = default; + [[ ]] B(const B &) = delete; +# endif + }; +# if __has_cpp_attribute(deprecated) + struct [[deprecated]] C { }; +# endif + enum [[ ]] E { }; + [[ ]] void [[ ]] * [[ ]] * [[ ]] ptr = 0; + int B::* [[ ]] pmm = 0; + +# if __has_cpp_attribute(deprecated) + enum [[deprecated]] E2 { +# if defined(__cpp_enumerator_attributes) && __cpp_enumerator_attributes >= 201411 + value [[deprecated]] = 0 +# endif + }; +# endif +# ifdef Q_COMPILER_LAMBDA + []()[[ ]] {}(); +# endif +# ifdef Q_COMPILER_TEMPLATE_ALIAS + using B2 [[ ]] = B; +# endif + + [[ ]] goto end; +# ifdef Q_CC_GNU + // Attributes in gnu:: namespace + [[gnu::unused]] end: + ; [[gnu::unused]] struct D {} d; - [[noreturn]] void f(); struct D e [[gnu::used, gnu::unused]]; - [[gnu::aligned(8)]] int i; + [[gnu::aligned(8)]] int i [[ ]]; + int array[][[]] = { 1 }; +# else + // Non GNU, so use an empty attribute + [[ ]] end: + ; + [[ ]] struct D {} d; + struct D e [[ ]]; + [[ ]] int i [[ ]]; + int array[][[]] = { 1 }; +# endif -[[gnu::unused]] end: - ; + int & [[ ]] lref = i; + int && [[ ]] rref = 1; + [[ ]] (void)1; + [[ ]] for (i = 0; i < 2; ++i) + ; + Q_UNUSED(ptr); + Q_UNUSED(pmm); Q_UNUSED(d); Q_UNUSED(e); Q_UNUSED(i); + Q_UNUSED(array); + Q_UNUSED(lref); + Q_UNUSED(rref); #endif } +QT_WARNING_POP #ifdef Q_COMPILER_AUTO_FUNCTION auto autoFunction() -> unsigned diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 3183fc7375..f0e7cb5901 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -465,6 +465,7 @@ private: const QString m_platform; QSize m_testWidgetSize; QPoint m_availableTopLeft; + QPoint m_safeCursorPos; const bool m_windowsAnimationsEnabled; }; @@ -622,6 +623,7 @@ void tst_QWidget::getSetCheck() tst_QWidget::tst_QWidget() : m_platform(QGuiApplication::platformName().toLower()) + , m_safeCursorPos(0, 0) , m_windowsAnimationsEnabled(windowsAnimationsEnabled()) { if (m_windowsAnimationsEnabled) // Disable animations which can interfere with screen grabbing in moveChild(), showAndMoveChild() @@ -664,7 +666,13 @@ void tst_QWidget::initTestCase() // to avoid Windows warnings about minimum size for decorated windows. int width = 200; const QScreen *screen = QGuiApplication::primaryScreen(); - m_availableTopLeft = screen->availableGeometry().topLeft(); + const QRect availableGeometry = screen->availableGeometry(); + m_availableTopLeft = availableGeometry.topLeft(); + // XCB: Determine "safe" cursor position at bottom/right corner of screen. + // Pushing the mouse rapidly to the top left corner can trigger KDE / KWin's + // "Present all Windows" (Ctrl+F9) feature also programmatically. + if (m_platform == QLatin1String("xcb")) + m_safeCursorPos = availableGeometry.bottomRight() - QPoint(40, 40); const int screenWidth = screen->geometry().width(); if (screenWidth > 2000) width = 100 * ((screenWidth + 500) / 1000); @@ -5664,7 +5672,7 @@ void tst_QWidget::setToolTip() // Mouse over doesn't work on Windows mobile, so skip the rest of the test for that platform. #ifndef Q_OS_WINCE_WM for (int pass = 0; pass < 2; ++pass) { - QCursor::setPos(0, 0); + QCursor::setPos(m_safeCursorPos); QScopedPointer popup(new QWidget(0, Qt::Popup)); popup->setObjectName(QLatin1String("tst_qwidget setToolTip #") + QString::number(pass)); popup->setWindowTitle(popup->objectName()); @@ -6015,7 +6023,7 @@ void tst_QWidget::childEvents() // Move away the cursor; otherwise it might result in an enter event if it's // inside the widget when the widget is shown. - QCursor::setPos(qApp->desktop()->availableGeometry().bottomRight()); + QCursor::setPos(m_safeCursorPos); QTest::qWait(100); { @@ -8878,7 +8886,7 @@ void tst_QWidget::syntheticEnterLeave() int numLeaveEvents; }; - QCursor::setPos(QPoint(0,0)); + QCursor::setPos(m_safeCursorPos); MyWidget window; window.setWindowFlags(Qt::WindowStaysOnTopHint); @@ -8998,7 +9006,7 @@ void tst_QWidget::taskQTBUG_4055_sendSyntheticEnterLeave() int numEnterEvents, numMouseMoveEvents; }; - QCursor::setPos(QPoint(0,0)); + QCursor::setPos(m_safeCursorPos); SELParent parent; parent.move(200, 200); @@ -10174,7 +10182,7 @@ void tst_QWidget::destroyedSignal() void tst_QWidget::underMouse() { // Move the mouse cursor to a safe location - QCursor::setPos(0,0); + QCursor::setPos(m_safeCursorPos); ColorWidget topLevelWidget(0, Qt::FramelessWindowHint, Qt::blue); ColorWidget childWidget1(&topLevelWidget, Qt::Widget, Qt::yellow); @@ -10430,7 +10438,7 @@ public: void tst_QWidget::taskQTBUG_27643_enterEvents() { // Move the mouse cursor to a safe location so it won't interfere - QCursor::setPos(0,0); + QCursor::setPos(m_safeCursorPos); EnterTestMainDialog dialog; QPushButton button(&dialog); diff --git a/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp b/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp index d4b221a4a7..e68463a00e 100644 --- a/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp +++ b/tests/auto/widgets/widgets/qabstractslider/tst_qabstractslider.cpp @@ -77,6 +77,8 @@ private slots: #ifndef QT_NO_WHEELEVENT void wheelEvent_data(); void wheelEvent(); + void fineGrainedWheelEvent_data(); + void fineGrainedWheelEvent(); #endif void sliderPressedReleased_data(); void sliderPressedReleased(); @@ -892,6 +894,55 @@ void tst_QAbstractSlider::wheelEvent() if (expectedSignalCount) QVERIFY(actionTriggeredTimeStamp < valueChangedTimeStamp); } + +void tst_QAbstractSlider::fineGrainedWheelEvent_data() +{ + QTest::addColumn("invertedControls"); + QTest::newRow("invertedControls=false") << false; + QTest::newRow("invertedControls=true") << true; +} + +void tst_QAbstractSlider::fineGrainedWheelEvent() +{ + QFETCH(bool, invertedControls); + + QCoreApplication *applicationInstance = QCoreApplication::instance(); + QVERIFY(applicationInstance != 0); + QApplication::setWheelScrollLines(3); + + slider->setRange(0, 10); + slider->setSingleStep(1); + slider->setPageStep(10); + slider->setInvertedControls(invertedControls); + slider->setOrientation(Qt::Vertical); + slider->setSliderPosition(0); + + const int singleStepDelta = invertedControls ? (-WHEEL_DELTA / 3) : (WHEEL_DELTA / 3); + + QWheelEvent eventDown(slider->rect().bottomRight(), singleStepDelta / 2, + Qt::NoButton, Qt::NoModifier, Qt::Vertical); + QVERIFY(applicationInstance->sendEvent(slider,&eventDown)); + QCOMPARE(slider->sliderPosition(), 0); + QVERIFY(applicationInstance->sendEvent(slider,&eventDown)); + QCOMPARE(slider->sliderPosition(), 1); + + QWheelEvent eventUp(slider->rect().bottomRight(), -singleStepDelta / 2, + Qt::NoButton, Qt::NoModifier, Qt::Vertical); + QVERIFY(applicationInstance->sendEvent(slider,&eventUp)); + QCOMPARE(slider->sliderPosition(), 1); + QVERIFY(applicationInstance->sendEvent(slider,&eventUp)); + QCOMPARE(slider->sliderPosition(), 0); + QVERIFY(applicationInstance->sendEvent(slider,&eventUp)); + QCOMPARE(slider->sliderPosition(), 0); + QVERIFY(applicationInstance->sendEvent(slider,&eventUp)); + QCOMPARE(slider->sliderPosition(), 0); + + QVERIFY(applicationInstance->sendEvent(slider,&eventDown)); + QCOMPARE(slider->sliderPosition(), 0); + QVERIFY(applicationInstance->sendEvent(slider,&eventDown)); + QCOMPARE(slider->sliderPosition(), 1); +} + #endif // !QT_NO_WHEELEVENT void tst_QAbstractSlider::sliderPressedReleased_data() diff --git a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp index 607fc1625a..d568cf63d4 100644 --- a/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp +++ b/tests/auto/widgets/widgets/qmdiarea/tst_qmdiarea.cpp @@ -492,6 +492,7 @@ void tst_QMdiArea::subWindowActivated2() spy.clear(); mdiArea.show(); + mdiArea.activateWindow(); QVERIFY(QTest::qWaitForWindowActive(&mdiArea)); QTRY_COMPARE(spy.count(), 1); QVERIFY(mdiArea.currentSubWindow()); diff --git a/tests/manual/manual.pro b/tests/manual/manual.pro index 8777cc6e11..bec098d462 100644 --- a/tests/manual/manual.pro +++ b/tests/manual/manual.pro @@ -31,6 +31,7 @@ qsysinfo \ qtabletevent \ qtexteditlist \ qtbug-8933 \ +qtbug-52641 \ qtouchevent \ touch \ qwidget_zorder \ diff --git a/tests/manual/qtabletevent/device_information/tabletwidget.cpp b/tests/manual/qtabletevent/device_information/tabletwidget.cpp index a30e32b6d9..b4273bde8e 100644 --- a/tests/manual/qtabletevent/device_information/tabletwidget.cpp +++ b/tests/manual/qtabletevent/device_information/tabletwidget.cpp @@ -33,7 +33,7 @@ #include #include -TabletWidget::TabletWidget(bool mouseToo) : mMouseToo(mouseToo) +TabletWidget::TabletWidget(bool mouseToo) : mMouseToo(mouseToo), mWheelEventCount(0) { QPalette newPalette = palette(); newPalette.setColor(QPalette::Window, Qt::white); @@ -82,6 +82,10 @@ bool TabletWidget::eventFilter(QObject *, QEvent *ev) mGPos = event->globalPos(); mTimestamp = event->timestamp(); } + break; + case QEvent::Wheel: + ++mWheelEventCount; + break; default: break; } @@ -176,6 +180,8 @@ void TabletWidget::paintEvent(QPaintEvent *) eventInfo << QString("z: %1").arg(QString::number(mZ)); eventInfo << QString("Unique Id: %1").arg(QString::number(mUnique)); + + eventInfo << QString("Total wheel events: %1").arg(QString::number(mWheelEventCount)); } QString text = eventInfo.join("\n"); diff --git a/tests/manual/qtabletevent/device_information/tabletwidget.h b/tests/manual/qtabletevent/device_information/tabletwidget.h index 4e6520e4cc..2b014a213a 100644 --- a/tests/manual/qtabletevent/device_information/tabletwidget.h +++ b/tests/manual/qtabletevent/device_information/tabletwidget.h @@ -61,6 +61,7 @@ private: qint64 mUnique; bool mMouseToo; ulong mTimestamp; + int mWheelEventCount; }; #endif // TABLETWIDGET_H diff --git a/tests/manual/qtbug-52641/main.cpp b/tests/manual/qtbug-52641/main.cpp new file mode 100644 index 0000000000..33ebd8584c --- /dev/null +++ b/tests/manual/qtbug-52641/main.cpp @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Kai Pastor +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the test suite 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$ +** +****************************************************************************/ + +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + + QString filepath = QFileDialog::getSaveFileName(nullptr, "Save File", "", + "PDF files (*.pdf)"); + if (filepath.isEmpty()) + return 1; + QPdfWriter writer(filepath); + writer.setPageSize(QPageSize(QPageSize::A4)); + writer.setResolution(300); + + QPainterPath path; + path.moveTo(0,0); + path.lineTo(1000,0); + path.lineTo(1000,1000); + path.lineTo(0,800); + path.lineTo(500,100); + path.lineTo(800,900); + path.lineTo(300,600); + + QPen pen; + pen.setWidth(30); + pen.setJoinStyle(Qt::MiterJoin); + + // The black path on the first page must always be visible in the PDF viewer. + QPainter p(&writer); + pen.setMiterLimit(6.0); + p.setPen(pen); + p.drawPath(path); + + // If a miter limit below 1.0 is written to the PDF, + // broken PDF viewers may not show the red path on the second page. + writer.newPage(); + pen.setMiterLimit(0.6); + pen.setColor(Qt::red); + p.setPen(pen); + p.drawPath(path); + + p.end(); + return 0; +} diff --git a/tests/manual/qtbug-52641/qtbug-52641.pro b/tests/manual/qtbug-52641/qtbug-52641.pro new file mode 100644 index 0000000000..5a9ff6df52 --- /dev/null +++ b/tests/manual/qtbug-52641/qtbug-52641.pro @@ -0,0 +1,5 @@ +TARGET = qtbug-52641 +TEMPLATE = app +QT = core gui widgets +SOURCES = main.cpp +