summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2010-02-25 23:54:53 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2010-02-25 23:54:53 (GMT)
commit22c2f6cfca945e9c377e509b7ff2252f55599b27 (patch)
tree52bd13356ab78cf6b201b3d20aa4e555fbf17a10 /src
parent8928e37c8b1b375e74c5981915c034123de11b3d (diff)
parentcf58c6bd5204edaff0a34bae5312798fc3700c94 (diff)
downloadQt-22c2f6cfca945e9c377e509b7ff2252f55599b27.zip
Qt-22c2f6cfca945e9c377e509b7ff2252f55599b27.tar.gz
Qt-22c2f6cfca945e9c377e509b7ff2252f55599b27.tar.bz2
Merge branch 'master' of scm.dev.nokia.troll.no:qt/oslo-staging-1 into master-integration
* 'master' of scm.dev.nokia.troll.no:qt/oslo-staging-1: (35 commits) Doc: Added a config file for creating Simplified Chinese docs directly. Doc: add a few lines about bearer managment to "What's New" page. Fix the SIMD implementations of QString::toLatin1() Update of the QScriptValue autotest suite. New data set for QScriptValue autotest generator. Autotest: make tst_qchar run out-of-source too Autotest: add a test for roundtrips through toLatin1/fromLatin1 Implement toLatin1_helper with Neon QRegExp::pos() should return -1 for empty/non-matching captures Revert "qdoc: Finished "Inherited by" list for QML elements." Revert "qdoc: List new QML elements in \sincelist for What's New page." Add the Unicode normalisation properties. Autotest: add a test for QDBusPendingCallWatcher use in threads Doc: placeholders for new feature highlights. doc: mark as reimplemented. Update of the QScriptValue autotest suite. New autotests cases for QScriptValue autotests generator. QScriptValue autotest generator templates change. Fix license template. QScriptValue::isQMetaObject crash fix. ...
Diffstat (limited to 'src')
-rw-r--r--src/corelib/corelib.pro22
-rw-r--r--src/corelib/tools/qregexp.cpp11
-rw-r--r--src/corelib/tools/qsharedpointer_impl.h1
-rw-r--r--src/corelib/tools/qsimd.cpp246
-rw-r--r--src/corelib/tools/qsimd_p.h126
-rw-r--r--src/corelib/tools/qstring.cpp112
-rw-r--r--src/corelib/tools/tools.pri2
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp452
-rw-r--r--src/gui/graphicsview/qgraphicsscene_p.h15
-rw-r--r--src/gui/kernel/qcocoaview_mac.mm52
-rw-r--r--src/gui/kernel/qcocoaview_mac_p.h1
-rw-r--r--src/gui/kernel/qgesture_p.h2
-rw-r--r--src/gui/kernel/qgesturerecognizer.cpp1
-rw-r--r--src/gui/kernel/qt_cocoa_helpers_mac.mm10
-rw-r--r--src/gui/kernel/qwidget.cpp9
-rw-r--r--src/gui/painting/qdrawhelper.cpp199
-rw-r--r--src/gui/painting/qdrawhelper_p.h9
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp3
-rw-r--r--src/multimedia/base/qgraphicsvideoitem.cpp3
-rw-r--r--src/multimedia/base/qmediacontent.cpp1
-rw-r--r--src/multimedia/base/qmediacontrol.cpp1
-rw-r--r--src/multimedia/base/qmediaobject.cpp1
-rw-r--r--src/multimedia/base/qmediaplaylist.cpp1
-rw-r--r--src/multimedia/base/qmediaplaylistcontrol.cpp1
-rw-r--r--src/multimedia/base/qmediaplaylistioplugin.cpp3
-rw-r--r--src/multimedia/base/qmediaplaylistnavigator.cpp1
-rw-r--r--src/multimedia/base/qmediaplaylistprovider.cpp1
-rw-r--r--src/multimedia/base/qmediaresource.cpp1
-rw-r--r--src/multimedia/base/qmediaservice.cpp1
-rw-r--r--src/multimedia/base/qmediaserviceprovider.cpp6
-rw-r--r--src/multimedia/base/qmediatimerange.cpp2
-rw-r--r--src/multimedia/base/qmetadatacontrol.cpp2
-rw-r--r--src/multimedia/base/qvideodevicecontrol.cpp1
-rw-r--r--src/multimedia/base/qvideooutputcontrol.cpp2
-rw-r--r--src/multimedia/base/qvideorenderercontrol.cpp2
-rw-r--r--src/multimedia/base/qvideowidget.cpp2
-rw-r--r--src/multimedia/base/qvideowidgetcontrol.cpp2
-rw-r--r--src/multimedia/base/qvideowindowcontrol.cpp1
-rw-r--r--src/multimedia/playback/qmediaplayer.cpp2
-rw-r--r--src/multimedia/playback/qmediaplayercontrol.cpp2
-rw-r--r--src/plugins/bearer/generic/qgenericengine.cpp1
-rw-r--r--src/plugins/mediaservices/gstreamer/qgstreamermessage.cpp2
-rw-r--r--src/script/api/qscriptengine_p.h2
43 files changed, 840 insertions, 477 deletions
diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro
index efee610..df9a463 100644
--- a/src/corelib/corelib.pro
+++ b/src/corelib/corelib.pro
@@ -52,3 +52,25 @@ symbian: {
partial_upgrade.path = c:/sys/bin
DEPLOYMENT = partial_upgrade $$DEPLOYMENT
}
+
+mmx {
+ DEFINES += QT_HAVE_MMX
+}
+3dnow {
+ DEFINES += QT_HAVE_3DNOW
+}
+sse {
+ DEFINES += QT_HAVE_SSE
+ DEFINES += QT_HAVE_MMXEXT
+}
+sse2 {
+ DEFINES += QT_HAVE_SSE2
+}
+iwmmxt {
+ DEFINES += QT_HAVE_IWMMXT
+}
+neon {
+ DEFINES += QT_HAVE_NEON
+ QMAKE_CXXFLAGS *= -mfpu=neon
+}
+
diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp
index 25255f9..20ad444 100644
--- a/src/corelib/tools/qregexp.cpp
+++ b/src/corelib/tools/qregexp.cpp
@@ -1466,9 +1466,14 @@ void QRegExpMatchState::match(const QChar *str0, int len0, int pos0,
#ifndef QT_NO_REGEXP_CAPTURE
for (int i = 0; i < numCaptures; ++i) {
int j = eng->captureForOfficialCapture.at(i);
- int len = capEnd[j] - capBegin[j];
- *c++ = (len > 0) ? pos + capBegin[j] : 0;
- *c++ = len;
+ if (capBegin[j] != EmptyCapture) {
+ int len = capEnd[j] - capBegin[j];
+ *c++ = (len > 0) ? pos + capBegin[j] : 0;
+ *c++ = len;
+ } else {
+ *c++ = -1;
+ *c++ = -1;
+ }
}
#endif
} else {
diff --git a/src/corelib/tools/qsharedpointer_impl.h b/src/corelib/tools/qsharedpointer_impl.h
index d85c248..bfc65bc 100644
--- a/src/corelib/tools/qsharedpointer_impl.h
+++ b/src/corelib/tools/qsharedpointer_impl.h
@@ -209,6 +209,7 @@ namespace QtSharedPointer {
inline bool destroy() { destroyer(this); return true; }
inline void operator delete(void *ptr) { ::operator delete(ptr); }
+ inline void operator delete(void *, void *) { }
};
// sizeof(ExternalRefCountWithDestroyFn) = 16 (32-bit) / 24 (64-bit)
diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp
new file mode 100644
index 0000000..52d2cea
--- /dev/null
+++ b/src/corelib/tools/qsimd.cpp
@@ -0,0 +1,246 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsimd_p.h"
+#include <QByteArray>
+
+QT_BEGIN_NAMESPACE
+
+uint qDetectCPUFeatures()
+{
+ static uint features = 0xffffffff;
+ if (features != 0xffffffff)
+ return features;
+
+#if defined (Q_OS_WINCE)
+#if defined (ARM)
+ if (IsProcessorFeaturePresent(PF_ARM_INTEL_WMMX)) {
+ features = IWMMXT;
+ return features;
+ }
+#elif defined(_X86_)
+ features = 0;
+#if defined QT_HAVE_MMX
+ if (IsProcessorFeaturePresent(PF_MMX_INSTRUCTIONS_AVAILABLE))
+ features |= MMX;
+#endif
+#if defined QT_HAVE_3DNOW
+ if (IsProcessorFeaturePresent(PF_3DNOW_INSTRUCTIONS_AVAILABLE))
+ features |= MMX3DNOW;
+#endif
+ return features;
+#endif
+ features = 0;
+ return features;
+#elif defined(QT_HAVE_IWMMXT)
+ // runtime detection only available when running as a previlegied process
+ static const bool doIWMMXT = !qgetenv("QT_NO_IWMMXT").toInt();
+ features = doIWMMXT ? IWMMXT : 0;
+ return features;
+#elif defined(QT_HAVE_NEON)
+ static const bool doNEON = !qgetenv("QT_NO_NEON").toInt();
+ features = doNEON ? NEON : 0;
+ return features;
+#else
+ features = 0;
+#if defined(__x86_64__) || defined(Q_OS_WIN64)
+ features = MMX|SSE|SSE2|CMOV;
+#elif defined(__ia64__)
+ features = MMX|SSE|SSE2;
+#elif defined(__i386__) || defined(_M_IX86)
+ unsigned int extended_result = 0;
+ uint result = 0;
+ /* see p. 118 of amd64 instruction set manual Vol3 */
+#if defined(Q_CC_GNU)
+ asm ("push %%ebx\n"
+ "pushf\n"
+ "pop %%eax\n"
+ "mov %%eax, %%ebx\n"
+ "xor $0x00200000, %%eax\n"
+ "push %%eax\n"
+ "popf\n"
+ "pushf\n"
+ "pop %%eax\n"
+ "xor %%edx, %%edx\n"
+ "xor %%ebx, %%eax\n"
+ "jz 1f\n"
+
+ "mov $0x00000001, %%eax\n"
+ "cpuid\n"
+ "1:\n"
+ "pop %%ebx\n"
+ "mov %%edx, %0\n"
+ : "=r" (result)
+ :
+ : "%eax", "%ecx", "%edx"
+ );
+
+ asm ("push %%ebx\n"
+ "pushf\n"
+ "pop %%eax\n"
+ "mov %%eax, %%ebx\n"
+ "xor $0x00200000, %%eax\n"
+ "push %%eax\n"
+ "popf\n"
+ "pushf\n"
+ "pop %%eax\n"
+ "xor %%edx, %%edx\n"
+ "xor %%ebx, %%eax\n"
+ "jz 2f\n"
+
+ "mov $0x80000000, %%eax\n"
+ "cpuid\n"
+ "cmp $0x80000000, %%eax\n"
+ "jbe 2f\n"
+ "mov $0x80000001, %%eax\n"
+ "cpuid\n"
+ "2:\n"
+ "pop %%ebx\n"
+ "mov %%edx, %0\n"
+ : "=r" (extended_result)
+ :
+ : "%eax", "%ecx", "%edx"
+ );
+#elif defined (Q_OS_WIN)
+ _asm {
+ push eax
+ push ebx
+ push ecx
+ push edx
+ pushfd
+ pop eax
+ mov ebx, eax
+ xor eax, 00200000h
+ push eax
+ popfd
+ pushfd
+ pop eax
+ mov edx, 0
+ xor eax, ebx
+ jz skip
+
+ mov eax, 1
+ cpuid
+ mov result, edx
+ skip:
+ pop edx
+ pop ecx
+ pop ebx
+ pop eax
+ }
+
+ _asm {
+ push eax
+ push ebx
+ push ecx
+ push edx
+ pushfd
+ pop eax
+ mov ebx, eax
+ xor eax, 00200000h
+ push eax
+ popfd
+ pushfd
+ pop eax
+ mov edx, 0
+ xor eax, ebx
+ jz skip2
+
+ mov eax, 80000000h
+ cpuid
+ cmp eax, 80000000h
+ jbe skip2
+ mov eax, 80000001h
+ cpuid
+ mov extended_result, edx
+ skip2:
+ pop edx
+ pop ecx
+ pop ebx
+ pop eax
+ }
+#endif
+
+ // result now contains the standard feature bits
+ if (result & (1u << 15))
+ features |= CMOV;
+ if (result & (1u << 23))
+ features |= MMX;
+ if (extended_result & (1u << 22))
+ features |= MMXEXT;
+ if (extended_result & (1u << 31))
+ features |= MMX3DNOW;
+ if (extended_result & (1u << 30))
+ features |= MMX3DNOWEXT;
+ if (result & (1u << 25))
+ features |= SSE;
+ if (result & (1u << 26))
+ features |= SSE2;
+#endif // i386
+
+#if defined(QT_HAVE_MMX)
+ if (qgetenv("QT_NO_MMX").toInt())
+ features ^= MMX;
+#endif
+ if (qgetenv("QT_NO_MMXEXT").toInt())
+ features ^= MMXEXT;
+
+#if defined(QT_HAVE_3DNOW)
+ if (qgetenv("QT_NO_3DNOW").toInt())
+ features ^= MMX3DNOW;
+#endif
+ if (qgetenv("QT_NO_3DNOWEXT").toInt())
+ features ^= MMX3DNOWEXT;
+
+#if defined(QT_HAVE_SSE)
+ if (qgetenv("QT_NO_SSE").toInt())
+ features ^= SSE;
+#endif
+#if defined(QT_HAVE_SSE2)
+ if (qgetenv("QT_NO_SSE2").toInt())
+ features ^= SSE2;
+#endif
+
+ return features;
+#endif
+}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h
new file mode 100644
index 0000000..556db14
--- /dev/null
+++ b/src/corelib/tools/qsimd_p.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** 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 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIMD_P_H
+#define QSIMD_P_H
+
+#include <qglobal.h>
+
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#if defined(QT_NO_MAC_XARCH) || (defined(Q_OS_DARWIN) && (defined(__ppc__) || defined(__ppc64__)))
+// Disable MMX and SSE on Mac/PPC builds, or if the compiler
+// does not support -Xarch argument passing
+#undef QT_HAVE_SSE2
+#undef QT_HAVE_SSE
+#undef QT_HAVE_3DNOW
+#undef QT_HAVE_MMX
+#endif
+
+// SSE intrinsics
+#if defined(__SSE2__)
+#if defined(QT_LINUXBASE)
+/// this is an evil hack - the posix_memalign declaration in LSB
+/// is wrong - see http://bugs.linuxbase.org/show_bug.cgi?id=2431
+# define posix_memalign _lsb_hack_posix_memalign
+# include <emmintrin.h>
+# undef posix_memalign
+#else
+# include <emmintrin.h>
+#endif
+
+#define QT_ALWAYS_HAVE_SSE2
+#endif
+
+// NEON intrinsics
+#if defined(QT_HAVE_NEON)
+#include <arm_neon.h>
+#endif
+
+
+// IWMMXT intrinsics
+#if defined(QT_HAVE_IWMMXT)
+#include <mmintrin.h>
+#if defined(Q_OS_WINCE)
+# include "qplatformdefs.h"
+#endif
+#endif
+
+#if defined(QT_HAVE_IWMMXT)
+#if !defined(__IWMMXT__) && !defined(Q_OS_WINCE)
+# include <xmmintrin.h>
+#elif defined(Q_OS_WINCE_STD) && defined(_X86_)
+# pragma warning(disable: 4391)
+# include <xmmintrin.h>
+#endif
+#endif
+
+// 3D now intrinsics
+#if defined(QT_HAVE_3DNOW)
+#include <mm3dnow.h>
+#endif
+
+enum CPUFeatures {
+ None = 0,
+ MMX = 0x1,
+ MMXEXT = 0x2,
+ MMX3DNOW = 0x4,
+ MMX3DNOWEXT = 0x8,
+ SSE = 0x10,
+ SSE2 = 0x20,
+ CMOV = 0x40,
+ IWMMXT = 0x80,
+ NEON = 0x100
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+Q_CORE_EXPORT uint qDetectCPUFeatures();
+
+#endif // QSIMD_P_H
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index ac1bee7..e9b7b9a 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -46,6 +46,7 @@
#include <qtextcodec.h>
#endif
#include <private/qutfcodec_p.h>
+#include "qsimd_p.h"
#include <qdatastream.h>
#include <qlist.h>
#include "qlocale.h"
@@ -3479,12 +3480,82 @@ static QByteArray toLatin1_helper(const QChar *data, int length)
QByteArray ba;
if (length) {
ba.resize(length);
- const ushort *i = reinterpret_cast<const ushort *>(data);
- const ushort *e = i + length;
- uchar *s = (uchar*) ba.data();
- while (i != e) {
- *s++ = (*i>0xff) ? '?' : (uchar) *i;
- ++i;
+ const ushort *src = reinterpret_cast<const ushort *>(data);
+ uchar *dst = (uchar*) ba.data();
+#if defined(QT_ALWAYS_HAVE_SSE2)
+ if (length >= 16) {
+ const int chunkCount = length >> 4; // divided by 16
+ const __m128i questionMark = _mm_set1_epi16('?');
+ // SSE has no compare instruction for unsigned comparison.
+ // The variables must be shiffted + 0x8000 to be compared
+ const __m128i signedBitOffset = _mm_set1_epi16(0x8000);
+ const __m128i thresholdMask = _mm_set1_epi16(0xff + 0x8000);
+ for (int i = 0; i < chunkCount; ++i) {
+ __m128i chunk1 = _mm_loadu_si128((__m128i*)src); // load
+ src += 8;
+ {
+ // each 16 bit is equal to 0xFF if the source is outside latin 1 (>0xff)
+ const __m128i signedChunk = _mm_add_epi16(chunk1, signedBitOffset);
+ const __m128i offLimitMask = _mm_cmpgt_epi16(signedChunk, thresholdMask);
+
+ // offLimitQuestionMark contains '?' for each 16 bits that was off-limit
+ // the 16 bits that were correct contains zeros
+ const __m128i offLimitQuestionMark = _mm_and_si128(offLimitMask, questionMark);
+
+ // correctBytes contains the bytes that were in limit
+ // the 16 bits that were off limits contains zeros
+ const __m128i correctBytes = _mm_andnot_si128(offLimitMask, chunk1);
+
+ // merge offLimitQuestionMark and correctBytes to have the result
+ chunk1 = _mm_or_si128(correctBytes, offLimitQuestionMark);
+ }
+
+ __m128i chunk2 = _mm_loadu_si128((__m128i*)src); // load
+ src += 8;
+ {
+ // exactly the same operations as for the previous chunk of data
+ const __m128i signedChunk = _mm_add_epi16(chunk2, signedBitOffset);
+ const __m128i offLimitMask = _mm_cmpgt_epi16(signedChunk, thresholdMask);
+ const __m128i offLimitQuestionMark = _mm_and_si128(offLimitMask, questionMark);
+ const __m128i correctBytes = _mm_andnot_si128(offLimitMask, chunk2);
+ chunk2 = _mm_or_si128(correctBytes, offLimitQuestionMark);
+ }
+
+ // pack the two vector to 16 x 8bits elements
+ const __m128i result = _mm_packus_epi16(chunk1, chunk2);
+
+ _mm_storeu_si128((__m128i*)dst, result); // store
+ dst += 16;
+ }
+ length = length % 16;
+ }
+#elif QT_HAVE_NEON
+ // Refer to the documentation of the SSE2 implementation
+ // this use eactly the same method as for SSE except:
+ // 1) neon has unsigned comparison
+ // 2) packing is done to 64 bits (8 x 8bits component).
+ if (length >= 16) {
+ const int chunkCount = length >> 3; // divided by 8
+ const uint16x8_t questionMark = vdupq_n_u16('?'); // set
+ const uint16x8_t thresholdMask = vdupq_n_u16(0xff); // set
+ for (int i = 0; i < chunkCount; ++i) {
+ uint16x8_t chunk = vld1q_u16((uint16_t *)src); // load
+ src += 8;
+
+ const uint16x8_t offLimitMask = vcgtq_u16(chunk, thresholdMask); // chunk > thresholdMask
+ const uint16x8_t offLimitQuestionMark = vandq_u16(offLimitMask, questionMark); // offLimitMask & questionMark
+ const uint16x8_t correctBytes = vbicq_u16(chunk, offLimitMask); // !offLimitMask & chunk
+ chunk = vorrq_u16(correctBytes, offLimitQuestionMark); // correctBytes | offLimitQuestionMark
+ const uint8x8_t result = vmovn_u16(chunk); // narrowing move->packing
+ vst1_u8(dst, result); // store
+ dst += 8;
+ }
+ length = length % 8;
+ }
+#endif
+ while (length--) {
+ *dst++ = (*src>0xff) ? '?' : (uchar) *src;
+ ++src;
}
}
return ba;
@@ -3647,10 +3718,35 @@ QString::Data *QString::fromLatin1_helper(const char *str, int size)
d->alloc = d->size = size;
d->clean = d->asciiCache = d->simpletext = d->righttoleft = d->capacity = 0;
d->data = d->array;
- ushort *i = d->data;
d->array[size] = '\0';
+ ushort *dst = d->data;
+ /* SIMD:
+ * Unpacking with SSE has been shown to improve performance on recent CPUs
+ * The same method gives no improvement with NEON.
+ */
+#if defined(QT_ALWAYS_HAVE_SSE2)
+ if (size >= 16) {
+ int chunkCount = size >> 4; // divided by 16
+ const __m128i nullMask = _mm_set1_epi32(0);
+ for (int i = 0; i < chunkCount; ++i) {
+ const __m128i chunk = _mm_loadu_si128((__m128i*)str); // load
+ str += 16;
+
+ // unpack the first 8 bytes, padding with zeros
+ const __m128i firstHalf = _mm_unpacklo_epi8(chunk, nullMask);
+ _mm_storeu_si128((__m128i*)dst, firstHalf); // store
+ dst += 8;
+
+ // unpack the last 8 bytes, padding with zeros
+ const __m128i secondHalf = _mm_unpackhi_epi8 (chunk, nullMask);
+ _mm_storeu_si128((__m128i*)dst, secondHalf); // store
+ dst += 8;
+ }
+ size = size % 16;
+ }
+#endif
while (size--)
- *i++ = (uchar)*str++;
+ *dst++ = (uchar)*str++;
}
return d;
}
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index 3406e41..6d64915 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -33,6 +33,7 @@ HEADERS += \
tools/qsharedpointer.h \
tools/qsharedpointer_impl.h \
tools/qset.h \
+ tools/qsimd_p.h \
tools/qsize.h \
tools/qstack.h \
tools/qstring.h \
@@ -68,6 +69,7 @@ SOURCES += \
tools/qregexp.cpp \
tools/qshareddata.cpp \
tools/qsharedpointer.cpp \
+ tools/qsimd.cpp \
tools/qsize.cpp \
tools/qstring.cpp \
tools/qstringbuilder.cpp \
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index aaae88e..40e1d2c 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -693,6 +693,18 @@ void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item)
--selectionChanging;
if (!selectionChanging && selectedItems.size() != oldSelectedItemsSize)
emit q->selectionChanged();
+
+ QHash<QGesture *, QGraphicsObject *>::iterator it;
+ for (it = gestureTargets.begin(); it != gestureTargets.end();) {
+ if (it.value() == item)
+ it = gestureTargets.erase(it);
+ else
+ ++it;
+ }
+ QGraphicsObject *dummy = static_cast<QGraphicsObject *>(item);
+ cachedTargetItems.removeOne(dummy);
+ cachedItemGestures.remove(dummy);
+ cachedAlreadyDeliveredGestures.remove(dummy);
}
/*!
@@ -5900,45 +5912,51 @@ void QGraphicsScenePrivate::leaveModal(QGraphicsItem *panel)
dispatchHoverEvent(&hoverEvent);
}
-void QGraphicsScenePrivate::getGestureTargets(const QSet<QGesture *> &gestures,
- QWidget *viewport,
- QMap<Qt::GestureType, QGesture *> *conflictedGestures,
- QList<QList<QGraphicsObject *> > *conflictedItems,
- QHash<QGesture *, QGraphicsObject *> *normalGestures)
+void QGraphicsScenePrivate::gestureTargetsAtHotSpots(const QSet<QGesture *> &gestures,
+ Qt::GestureFlag flag,
+ QHash<QGraphicsObject *, QSet<QGesture *> > *targets,
+ QSet<QGraphicsObject *> *itemsSet,
+ QSet<QGesture *> *normal,
+ QSet<QGesture *> *conflicts)
{
+ QSet<QGesture *> normalGestures; // that are not in conflicted state.
foreach (QGesture *gesture, gestures) {
- Qt::GestureType gestureType = gesture->gestureType();
- if (gesture->hasHotSpot()) {
- QPoint screenPos = gesture->hotSpot().toPoint();
- QList<QGraphicsItem *> items = itemsAtPosition(screenPos, QPointF(), viewport);
- QList<QGraphicsObject *> result;
- for (int j = 0; j < items.size(); ++j) {
- QGraphicsItem *item = items.at(j);
+ if (!gesture->hasHotSpot())
+ continue;
+ const Qt::GestureType gestureType = gesture->gestureType();
+ QList<QGraphicsItem *> items = itemsAtPosition(QPoint(), gesture->d_func()->sceneHotSpot, 0);
+ for (int j = 0; j < items.size(); ++j) {
+ QGraphicsItem *item = items.at(j);
- // Check if the item is blocked by a modal panel and use it as
- // a target instead of this item.
- (void) item->isBlockedByModalPanel(&item);
+ // Check if the item is blocked by a modal panel and use it as
+ // a target instead of this item.
+ (void) item->isBlockedByModalPanel(&item);
- if (QGraphicsObject *itemobj = item->toGraphicsObject()) {
- QGraphicsItemPrivate *d = item->d_func();
- if (d->gestureContext.contains(gestureType)) {
- result.append(itemobj);
+ if (QGraphicsObject *itemobj = item->toGraphicsObject()) {
+ QGraphicsItemPrivate *d = item->QGraphicsItem::d_func();
+ QMap<Qt::GestureType, Qt::GestureFlags>::const_iterator it =
+ d->gestureContext.find(gestureType);
+ if (it != d->gestureContext.end() && (!flag || (it.value() & flag))) {
+ if (normalGestures.contains(gesture)) {
+ normalGestures.remove(gesture);
+ if (conflicts)
+ conflicts->insert(gesture);
+ } else {
+ normalGestures.insert(gesture);
}
+ if (targets)
+ (*targets)[itemobj].insert(gesture);
+ if (itemsSet)
+ (*itemsSet).insert(itemobj);
}
- // Don't propagate through panels.
- if (item->isPanel())
- break;
- }
- DEBUG() << "QGraphicsScenePrivate::getGestureTargets:"
- << gesture << result;
- if (result.size() == 1) {
- normalGestures->insert(gesture, result.first());
- } else if (!result.isEmpty()) {
- conflictedGestures->insert(gestureType, gesture);
- conflictedItems->append(result);
}
+ // Don't propagate through panels.
+ if (item->isPanel())
+ break;
}
}
+ if (normal)
+ *normal = normalGestures;
}
void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event)
@@ -5946,266 +5964,215 @@ void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event)
QWidget *viewport = event->widget();
if (!viewport)
return;
+ QGraphicsView *graphicsView = qobject_cast<QGraphicsView *>(viewport->parent());
+ if (!graphicsView)
+ return;
+
QList<QGesture *> allGestures = event->gestures();
DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
<< "Delivering gestures:" << allGestures;
- typedef QHash<QGraphicsObject *, QList<QGesture *> > GesturesPerItem;
- GesturesPerItem gesturesPerItem;
-
- // gestures that are only supposed to propagate to parent items.
- QSet<QGesture *> parentPropagatedGestures;
-
QSet<QGesture *> startedGestures;
+ QPoint delta = graphicsView->mapFromGlobal(QPoint());
+ QTransform toScene = QTransform::fromTranslate(delta.x(), delta.y())
+ * graphicsView->viewportTransform().inverted();
foreach (QGesture *gesture, allGestures) {
+ // cache scene coordinates of the hot spot
+ if (gesture->hasHotSpot()) {
+ gesture->d_func()->sceneHotSpot = toScene.map(gesture->hotSpot());
+ } else {
+ gesture->d_func()->sceneHotSpot = QPointF();
+ }
+
QGraphicsObject *target = gestureTargets.value(gesture, 0);
if (!target) {
// when we are not in started mode but don't have a target
// then the only one interested in gesture is the view/scene
if (gesture->state() == Qt::GestureStarted)
startedGestures.insert(gesture);
- } else {
- gesturesPerItem[target].append(gesture);
- Qt::GestureFlags flags =
- target->QGraphicsItem::d_func()->gestureContext.value(gesture->gestureType());
- if (flags & Qt::IgnoredGesturesPropagateToParent)
- parentPropagatedGestures.insert(gesture);
}
}
- QMap<Qt::GestureType, QGesture *> conflictedGestures;
- QList<QList<QGraphicsObject *> > conflictedItems;
- QHash<QGesture *, QGraphicsObject *> normalGestures;
- getGestureTargets(startedGestures, viewport, &conflictedGestures, &conflictedItems,
- &normalGestures);
- DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
- << "Conflicting gestures:" << conflictedGestures.values() << conflictedItems;
- Q_ASSERT((conflictedGestures.isEmpty() && conflictedItems.isEmpty()) ||
- (!conflictedGestures.isEmpty() && !conflictedItems.isEmpty()));
-
- // gestures that were sent as override events, but no one accepted them
- QHash<QGesture *, QGraphicsObject *> ignoredConflictedGestures;
-
- // deliver conflicted gestures as override events first
- while (!conflictedGestures.isEmpty() && !conflictedItems.isEmpty()) {
- // get the topmost item to deliver the override event
- Q_ASSERT(!conflictedItems.isEmpty());
- Q_ASSERT(!conflictedItems.first().isEmpty());
- QGraphicsObject *topmost = conflictedItems.first().first();
- for (int i = 1; i < conflictedItems.size(); ++i) {
- QGraphicsObject *item = conflictedItems.at(i).first();
- if (qt_closestItemFirst(item, topmost)) {
- topmost = item;
- }
- }
- // get a list of gestures to send to the item
- QList<Qt::GestureType> grabbedGestures =
- topmost->QGraphicsItem::d_func()->gestureContext.keys();
- QList<QGesture *> gestures;
- for (int i = 0; i < grabbedGestures.size(); ++i) {
- if (QGesture *g = conflictedGestures.value(grabbedGestures.at(i), 0)) {
- gestures.append(g);
- if (!ignoredConflictedGestures.contains(g))
- ignoredConflictedGestures.insert(g, topmost);
- }
- }
-
- // send gesture override to the topmost item
- QGestureEvent ev(gestures);
- ev.t = QEvent::GestureOverride;
- ev.setWidget(event->widget());
- // mark event and individual gestures as ignored
- ev.ignore();
- foreach(QGesture *g, gestures)
- ev.setAccepted(g, false);
+ if (!startedGestures.isEmpty()) {
+ QSet<QGesture *> normalGestures; // that have just one target
+ QSet<QGesture *> conflictedGestures; // that have multiple possible targets
+ gestureTargetsAtHotSpots(startedGestures, Qt::GestureFlag(0), &cachedItemGestures, 0,
+ &normalGestures, &conflictedGestures);
+ cachedTargetItems = cachedItemGestures.keys();
+ qSort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst);
DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
- << "delivering override to"
- << topmost << gestures;
- sendEvent(topmost, &ev);
- // mark all accepted gestures to deliver them as normal gesture events
- foreach (QGesture *g, gestures) {
- if (ev.isAccepted() || ev.isAccepted(g)) {
- conflictedGestures.remove(g->gestureType());
- gestureTargets.remove(g);
- // add the gesture to the list of normal delivered gestures
- normalGestures.insert(g, topmost);
+ << "Conflicting gestures:" << conflictedGestures;
+
+ // deliver conflicted gestures as override events AND remember
+ // initial gesture targets
+ if (!conflictedGestures.isEmpty()) {
+ for (int i = 0; i < cachedTargetItems.size(); ++i) {
+ QWeakPointer<QGraphicsObject> item = cachedTargetItems.at(i);
+
+ // get gestures to deliver to the current item
+ QSet<QGesture *> gestures = conflictedGestures & cachedItemGestures.value(item.data());
+ if (gestures.isEmpty())
+ continue;
+
DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
- << "override was accepted:"
- << g << topmost;
- ignoredConflictedGestures.remove(g);
+ << "delivering override to"
+ << item.data() << gestures;
+ // send gesture override
+ QGestureEvent ev(gestures.toList());
+ ev.t = QEvent::GestureOverride;
+ ev.setWidget(event->widget());
+ // mark event and individual gestures as ignored
+ ev.ignore();
+ foreach(QGesture *g, gestures)
+ ev.setAccepted(g, false);
+ sendEvent(item.data(), &ev);
+ // mark all accepted gestures to deliver them as normal gesture events
+ foreach (QGesture *g, gestures) {
+ if (ev.isAccepted() || ev.isAccepted(g)) {
+ conflictedGestures.remove(g);
+ // mark the item as a gesture target
+ if (item)
+ gestureTargets.insert(g, item.data());
+ DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
+ << "override was accepted:"
+ << g << item.data();
+ }
+ // remember the first item that received the override event
+ // as it most likely become a target if noone else accepts
+ // the override event
+ if (!gestureTargets.contains(g) && item)
+ gestureTargets.insert(g, item.data());
+
+ }
+ if (conflictedGestures.isEmpty())
+ break;
}
}
- // remove the item that we've already delivered from the list
- for (int i = 0; i < conflictedItems.size(); ) {
- QList<QGraphicsObject *> &items = conflictedItems[i];
- if (items.first() == topmost) {
- items.removeFirst();
- if (items.isEmpty()) {
- conflictedItems.removeAt(i);
- continue;
+ // remember the initial target item for each gesture that was not in
+ // the conflicted state.
+ if (!normalGestures.isEmpty()) {
+ for (int i = 0; i < cachedTargetItems.size() && !normalGestures.isEmpty(); ++i) {
+ QGraphicsObject *item = cachedTargetItems.at(i);
+
+ // get gestures to deliver to the current item
+ foreach (QGesture *g, cachedItemGestures.value(item)) {
+ if (!gestureTargets.contains(g)) {
+ gestureTargets.insert(g, item);
+ normalGestures.remove(g);
+ }
}
}
- ++i;
}
}
- // put back those started gestures that are not in the conflicted state
- // and remember their targets
- QHash<QGesture *, QGraphicsObject *>::const_iterator it = normalGestures.begin(),
- e = normalGestures.end();
- for (; it != e; ++it) {
- QGesture *g = it.key();
- QGraphicsObject *receiver = it.value();
- Q_ASSERT(!gestureTargets.contains(g));
- gestureTargets.insert(g, receiver);
- gesturesPerItem[receiver].append(g);
- Qt::GestureFlags flags =
- receiver->QGraphicsItem::d_func()->gestureContext.value(g->gestureType());
- if (flags & Qt::IgnoredGesturesPropagateToParent)
- parentPropagatedGestures.insert(g);
- }
- it = ignoredConflictedGestures.begin();
- e = ignoredConflictedGestures.end();
- for (; it != e; ++it) {
- QGesture *g = it.key();
- QGraphicsObject *receiver = it.value();
- Q_ASSERT(!gestureTargets.contains(g));
- gestureTargets.insert(g, receiver);
- gesturesPerItem[receiver].append(g);
- Qt::GestureFlags flags =
- receiver->QGraphicsItem::d_func()->gestureContext.value(g->gestureType());
- if (flags & Qt::IgnoredGesturesPropagateToParent)
- parentPropagatedGestures.insert(g);
- }
-
- DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
- << "Started gestures:" << normalGestures.keys()
- << "All gestures:" << gesturesPerItem.values();
// deliver all gesture events
- QList<QGesture *> alreadyIgnoredGestures;
- QHash<QGraphicsObject *, QSet<QGesture *> > itemIgnoredGestures;
- QList<QGraphicsObject *> targetItems = gesturesPerItem.keys();
- qSort(targetItems.begin(), targetItems.end(), qt_closestItemFirst);
- for (int i = 0; i < targetItems.size(); ++i) {
- QGraphicsObject *item = targetItems.at(i);
- QList<QGesture *> gestures = gesturesPerItem.value(item);
- // remove gestures that were already delivered once and were ignored
- DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
- << "already ignored gestures for item"
- << item << ":" << itemIgnoredGestures.value(item);
-
- if (itemIgnoredGestures.contains(item)) // don't deliver twice to the same item
- continue;
-
- QGraphicsItemPrivate *gid = item->QGraphicsItem::d_func();
- foreach(QGesture *g, alreadyIgnoredGestures) {
- QMap<Qt::GestureType, Qt::GestureFlags>::iterator contextit =
- gid->gestureContext.find(g->gestureType());
- bool deliver = false;
- if (contextit != gid->gestureContext.end()) {
- if (g->state() == Qt::GestureStarted) {
- deliver = true;
- } else {
- const Qt::GestureFlags flags = contextit.value();
- if (flags & Qt::ReceivePartialGestures) {
- QGraphicsObject *originalTarget = gestureTargets.value(g);
- Q_ASSERT(originalTarget);
- QGraphicsItemPrivate *otd = originalTarget->QGraphicsItem::d_func();
- const Qt::GestureFlags originalTargetFlags = otd->gestureContext.value(g->gestureType());
- if (originalTargetFlags & Qt::IgnoredGesturesPropagateToParent) {
- // only deliver to parents of the original target item
- deliver = item->isAncestorOf(originalTarget);
- } else {
- deliver = true;
- }
- }
- }
- }
- if (deliver)
- gestures += g;
+ QSet<QGesture *> undeliveredGestures;
+ QSet<QGesture *> parentPropagatedGestures;
+ foreach (QGesture *gesture, allGestures) {
+ if (QGraphicsObject *target = gestureTargets.value(gesture, 0)) {
+ cachedItemGestures[target].insert(gesture);
+ cachedTargetItems.append(target);
+ undeliveredGestures.insert(gesture);
+ QGraphicsItemPrivate *d = target->QGraphicsItem::d_func();
+ const Qt::GestureFlags flags = d->gestureContext.value(gesture->gestureType());
+ if (flags & Qt::IgnoredGesturesPropagateToParent)
+ parentPropagatedGestures.insert(gesture);
}
+ }
+ qSort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst);
+ for (int i = 0; i < cachedTargetItems.size(); ++i) {
+ QWeakPointer<QGraphicsObject> receiver = cachedTargetItems.at(i);
+ QSet<QGesture *> gestures =
+ undeliveredGestures & cachedItemGestures.value(receiver.data());
+ gestures -= cachedAlreadyDeliveredGestures.value(receiver.data());
+
if (gestures.isEmpty())
continue;
+
+ cachedAlreadyDeliveredGestures[receiver.data()] += gestures;
+ const bool isPanel = receiver.data()->isPanel();
+
DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
<< "delivering to"
- << item << gestures;
- QGestureEvent ev(gestures);
+ << receiver.data() << gestures;
+ QGestureEvent ev(gestures.toList());
ev.setWidget(event->widget());
- sendEvent(item, &ev);
+ sendEvent(receiver.data(), &ev);
QSet<QGesture *> ignoredGestures;
foreach (QGesture *g, gestures) {
if (!ev.isAccepted() && !ev.isAccepted(g)) {
- ignoredGestures.insert(g);
+ // if the gesture was ignored by its target, we will update the
+ // targetItems list with a possible target items (items that
+ // want to receive partial gestures).
+ // ### wont' work if the target was destroyed in the event
+ // we will just stop delivering it.
+ if (receiver && receiver.data() == gestureTargets.value(g, 0))
+ ignoredGestures.insert(g);
} else {
- if (g->state() == Qt::GestureStarted)
- gestureTargets[g] = item;
- }
- }
- if (!ignoredGestures.isEmpty()) {
- // get a list of items under the (current) hotspot of each ignored
- // gesture and start delivery again from the beginning
- DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
- << "item has ignored the event, will propagate."
- << item << ignoredGestures;
- itemIgnoredGestures[item] += ignoredGestures;
- alreadyIgnoredGestures = ignoredGestures.toList();
-
- // remove gestures that are supposed to be propagated to
- // parent items only.
- QSet<QGesture *> parentGestures;
- for (QSet<QGesture *>::iterator it = ignoredGestures.begin();
- it != ignoredGestures.end();) {
- if (parentPropagatedGestures.contains(*it)) {
- parentGestures.insert(*it);
- it = ignoredGestures.erase(it);
- } else {
- ++it;
+ if (receiver && g->state() == Qt::GestureStarted) {
+ // someone accepted the propagated initial GestureStarted
+ // event, let it be the new target for all following events.
+ gestureTargets[g] = receiver.data();
}
+ undeliveredGestures.remove(g);
}
+ }
+ if (undeliveredGestures.isEmpty())
+ break;
- QSet<QGraphicsObject *> itemsSet = targetItems.toSet();
-
- foreach(QGesture *g, parentGestures) {
- // get the original target for the gesture
- QGraphicsItem *item = gestureTargets.value(g, 0);
- Q_ASSERT(item);
- const Qt::GestureType gestureType = g->gestureType();
- // iterate through parent items of the original gesture
- // target item and collect potential receivers
- do {
- if (QGraphicsObject *obj = item->toGraphicsObject()) {
- if (item->d_func()->gestureContext.contains(gestureType))
- itemsSet.insert(obj);
+ // ignoredGestures list is only filled when delivering to the gesture
+ // target item, so it is safe to assume item == target.
+ if (!ignoredGestures.isEmpty() && !isPanel) {
+ // look for new potential targets for gestures that were ignored
+ // and should be propagated.
+
+ QSet<QGraphicsObject *> targetsSet = cachedTargetItems.toSet();
+
+ if (receiver) {
+ // first if the gesture should be propagated to parents only
+ for (QSet<QGesture *>::iterator it = ignoredGestures.begin();
+ it != ignoredGestures.end();) {
+ if (parentPropagatedGestures.contains(*it)) {
+ QGesture *gesture = *it;
+ const Qt::GestureType gestureType = gesture->gestureType();
+ QGraphicsItem *item = receiver.data();
+ while (item) {
+ if (QGraphicsObject *obj = item->toGraphicsObject()) {
+ if (item->d_func()->gestureContext.contains(gestureType)) {
+ targetsSet.insert(obj);
+ cachedItemGestures[obj].insert(gesture);
+ }
+ }
+ if (item->isPanel())
+ break;
+ item = item->parentItem();
+ }
+
+ it = ignoredGestures.erase(it);
+ continue;
}
- if (item->isPanel())
- break;
- } while ((item = item->parentItem()));
+ ++it;
+ }
}
- QMap<Qt::GestureType, QGesture *> conflictedGestures;
- QList<QList<QGraphicsObject *> > itemsForConflictedGestures;
- QHash<QGesture *, QGraphicsObject *> normalGestures;
- getGestureTargets(ignoredGestures, viewport,
- &conflictedGestures, &itemsForConflictedGestures,
- &normalGestures);
- for (int k = 0; k < itemsForConflictedGestures.size(); ++k)
- itemsSet += itemsForConflictedGestures.at(k).toSet();
-
- targetItems = itemsSet.toList();
+ gestureTargetsAtHotSpots(ignoredGestures, Qt::ReceivePartialGestures,
+ &cachedItemGestures, &targetsSet, 0, 0);
- qSort(targetItems.begin(), targetItems.end(), qt_closestItemFirst);
+ cachedTargetItems = targetsSet.toList();
+ qSort(cachedTargetItems.begin(), cachedTargetItems.end(), qt_closestItemFirst);
DEBUG() << "QGraphicsScenePrivate::gestureEventHandler:"
- << "new targets:" << targetItems;
+ << "new targets:" << cachedTargetItems;
i = -1; // start delivery again
continue;
}
}
+
foreach (QGesture *g, startedGestures) {
if (g->gestureCancelPolicy() == QGesture::CancelAllInContext) {
DEBUG() << "lets try to cancel some";
// find gestures in context in Qt::GestureStarted or Qt::GestureUpdated state and cancel them
- cancelGesturesForChildren(g, event->widget());
+ cancelGesturesForChildren(g);
}
}
@@ -6220,9 +6187,13 @@ void QGraphicsScenePrivate::gestureEventHandler(QGestureEvent *event)
break;
}
}
+
+ cachedTargetItems.clear();
+ cachedItemGestures.clear();
+ cachedAlreadyDeliveredGestures.clear();
}
-void QGraphicsScenePrivate::cancelGesturesForChildren(QGesture *original, QWidget *viewport)
+void QGraphicsScenePrivate::cancelGesturesForChildren(QGesture *original)
{
Q_ASSERT(original);
QGraphicsItem *originalItem = gestureTargets.value(original);
@@ -6278,8 +6249,7 @@ void QGraphicsScenePrivate::cancelGesturesForChildren(QGesture *original, QWidge
if (!g->hasHotSpot())
continue;
- QPoint screenPos = g->hotSpot().toPoint();
- QList<QGraphicsItem *> items = itemsAtPosition(screenPos, QPointF(), viewport);
+ QList<QGraphicsItem *> items = itemsAtPosition(QPoint(), g->d_func()->sceneHotSpot, 0);
for (int j = 0; j < items.size(); ++j) {
QGraphicsObject *item = items.at(j)->toGraphicsObject();
if (!item)
diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h
index 04ffe0f..ca8b829 100644
--- a/src/gui/graphicsview/qgraphicsscene_p.h
+++ b/src/gui/graphicsview/qgraphicsscene_p.h
@@ -294,13 +294,18 @@ public:
bool allItemsIgnoreTouchEvents;
void enableTouchEventsOnViews();
+ QList<QGraphicsObject *> cachedTargetItems;
+ QHash<QGraphicsObject *, QSet<QGesture *> > cachedItemGestures;
+ QHash<QGraphicsObject *, QSet<QGesture *> > cachedAlreadyDeliveredGestures;
QHash<QGesture *, QGraphicsObject *> gestureTargets;
void gestureEventHandler(QGestureEvent *event);
- void getGestureTargets(const QSet<QGesture *> &gestures, QWidget *viewport,
- QMap<Qt::GestureType, QGesture *> *conflictedGestures,
- QList<QList<QGraphicsObject *> > *conflictedItems,
- QHash<QGesture *, QGraphicsObject *> *normalGestures);
- void cancelGesturesForChildren(QGesture *original, QWidget *viewport);
+ void gestureTargetsAtHotSpots(const QSet<QGesture *> &gestures,
+ Qt::GestureFlag flag,
+ QHash<QGraphicsObject *, QSet<QGesture *> > *targets,
+ QSet<QGraphicsObject *> *itemsSet = 0,
+ QSet<QGesture *> *normal = 0,
+ QSet<QGesture *> *conflicts = 0);
+ void cancelGesturesForChildren(QGesture *original);
void updateInputMethodSensitivityInViews();
diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm
index c347410..6a16403 100644
--- a/src/gui/kernel/qcocoaview_mac.mm
+++ b/src/gui/kernel/qcocoaview_mac.mm
@@ -419,6 +419,8 @@ extern "C" {
- (BOOL)isOpaque;
{
+ if (!qwidgetprivate)
+ return [super isOpaque];
return qwidgetprivate->isOpaque;
}
@@ -450,7 +452,7 @@ extern "C" {
}
// Make sure the opengl context is updated on resize.
- if (qwidgetprivate->isGLWidget) {
+ if (qwidgetprivate && qwidgetprivate->isGLWidget) {
qwidgetprivate->needWindowChange = true;
QEvent event(QEvent::MacGLWindowChange);
qApp->sendEvent(qwidget, &event);
@@ -459,6 +461,9 @@ extern "C" {
- (void)drawRect:(NSRect)aRect
{
+ if (!qwidget)
+ return;
+
if (QApplicationPrivate::graphicsSystem() != 0) {
if (QWidgetBackingStore *bs = qwidgetprivate->maybeBackingStore()) {
// Drawing is handled on the window level
@@ -552,12 +557,18 @@ extern "C" {
- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
{
+ if (!qwidget)
+ return NO;
+
Q_UNUSED(theEvent);
return !qwidget->testAttribute(Qt::WA_MacNoClickThrough);
}
- (NSView *)hitTest:(NSPoint)aPoint
{
+ if (!qwidget)
+ return [super hitTest:aPoint];
+
if (qwidget->testAttribute(Qt::WA_TransparentForMouseEvents))
return nil; // You cannot hit a transparent for mouse event widget.
return [super hitTest:aPoint];
@@ -565,6 +576,9 @@ extern "C" {
- (void)updateTrackingAreas
{
+ if (!qwidget)
+ return;
+
// [NSView addTrackingArea] is slow, so bail out early if we can:
if (NSIsEmptyRect([self visibleRect]))
return;
@@ -598,6 +612,9 @@ extern "C" {
- (void)mouseEntered:(NSEvent *)event
{
+ if (!qwidget)
+ return;
+
if (qwidgetprivate->data.in_destructor)
return;
QEvent enterEvent(QEvent::Enter);
@@ -620,6 +637,9 @@ extern "C" {
- (void)mouseExited:(NSEvent *)event
{
+ if (!qwidget)
+ return;
+
QEvent leaveEvent(QEvent::Leave);
NSPoint globalPoint = [[event window] convertBaseToScreen:[event locationInWindow]];
if (!qAppInstance()->activeModalWidget() || QApplicationPrivate::tryModalHelper(qwidget, 0)) {
@@ -638,6 +658,9 @@ extern "C" {
- (void)flagsChanged:(NSEvent *)theEvent
{
+ if (!qwidget)
+ return;
+
QWidget *widgetToGetKey = qwidget;
QWidget *popup = qAppInstance()->activePopupWidget();
@@ -649,6 +672,9 @@ extern "C" {
- (void)mouseMoved:(NSEvent *)theEvent
{
+ if (!qwidget)
+ return;
+
// We always enable mouse tracking for all QCocoaView-s. In cases where we have
// child views, we will receive mouseMoved for both parent & the child (if
// mouse is over the child). We need to ignore the parent mouseMoved in such
@@ -939,6 +965,8 @@ extern "C" {
- (void)frameDidChange:(NSNotification *)note
{
Q_UNUSED(note);
+ if (!qwidget)
+ return;
if (qwidget->isWindow())
return;
NSRect newFrame = [self frame];
@@ -962,7 +990,7 @@ extern "C" {
{
QMacCocoaAutoReleasePool pool;
[super setEnabled:flag];
- if (qwidget->isEnabled() != flag)
+ if (qwidget && qwidget->isEnabled() != flag)
qwidget->setEnabled(flag);
}
@@ -973,6 +1001,8 @@ extern "C" {
- (BOOL)acceptsFirstResponder
{
+ if (!qwidget)
+ return NO;
if (qwidget->isWindow())
return YES; // Always do it, so that windows can accept key press events.
return qwidget->focusPolicy() != Qt::NoFocus;
@@ -980,6 +1010,8 @@ extern "C" {
- (BOOL)resignFirstResponder
{
+ if (!qwidget)
+ return NO;
// Seems like the following test only triggers if this
// view is inside a QMacNativeWidget:
if (qwidget == QApplication::focusWidget())
@@ -1015,6 +1047,12 @@ extern "C" {
return qwidget;
}
+- (void) qt_clearQWidget
+{
+ qwidget = 0;
+ qwidgetprivate = 0;
+}
+
- (BOOL)qt_leftButtonIsRightButton
{
return leftButtonIsRightButton;
@@ -1068,9 +1106,11 @@ extern "C" {
- (void)viewWillMoveToWindow:(NSWindow *)window
{
+ if (qwidget == 0)
+ return;
+
if (qwidget->windowFlags() & Qt::MSWindowsOwnDC
&& (window != [self window])) { // OpenGL Widget
- // Create a stupid ClearDrawable Event
QEvent event(QEvent::MacGLClearDrawable);
qApp->sendEvent(qwidget, &event);
}
@@ -1078,6 +1118,9 @@ extern "C" {
- (void)viewDidMoveToWindow
{
+ if (qwidget == 0)
+ return;
+
if (qwidget->windowFlags() & Qt::MSWindowsOwnDC && [self window]) {
// call update paint event
qwidgetprivate->needWindowChange = true;
@@ -1273,6 +1316,9 @@ extern "C" {
- (NSArray*) validAttributesForMarkedText
{
+ if (qwidget == 0)
+ return nil;
+
if (!qwidget->testAttribute(Qt::WA_InputMethodEnabled))
return nil; // Not sure if that's correct, but it's saves a malloc.
diff --git a/src/gui/kernel/qcocoaview_mac_p.h b/src/gui/kernel/qcocoaview_mac_p.h
index 4bb10c5..33aaa24 100644
--- a/src/gui/kernel/qcocoaview_mac_p.h
+++ b/src/gui/kernel/qcocoaview_mac_p.h
@@ -103,6 +103,7 @@ Q_GUI_EXPORT
- (void)draggedImage:(NSImage *)anImage endedAt:(NSPoint)aPoint operation:(NSDragOperation)operation;
- (BOOL)isComposing;
- (QWidget *)qt_qwidget;
+- (void) qt_clearQWidget;
- (BOOL)qt_leftButtonIsRightButton;
- (void)qt_setLeftButtonIsRightButton:(BOOL)isSwapped;
+ (DnDParams*)currentMouseEvent;
diff --git a/src/gui/kernel/qgesture_p.h b/src/gui/kernel/qgesture_p.h
index dee5592..649a310 100644
--- a/src/gui/kernel/qgesture_p.h
+++ b/src/gui/kernel/qgesture_p.h
@@ -69,13 +69,13 @@ public:
QGesturePrivate()
: gestureType(Qt::CustomGesture), state(Qt::NoGesture),
isHotSpotSet(false), gestureCancelPolicy(0)
-
{
}
Qt::GestureType gestureType;
Qt::GestureState state;
QPointF hotSpot;
+ QPointF sceneHotSpot;
uint isHotSpotSet : 1;
uint gestureCancelPolicy : 2;
};
diff --git a/src/gui/kernel/qgesturerecognizer.cpp b/src/gui/kernel/qgesturerecognizer.cpp
index 8735d27..c88a9a7 100644
--- a/src/gui/kernel/qgesturerecognizer.cpp
+++ b/src/gui/kernel/qgesturerecognizer.cpp
@@ -181,6 +181,7 @@ void QGestureRecognizer::reset(QGesture *gesture)
QGesturePrivate *d = gesture->d_func();
d->state = Qt::NoGesture;
d->hotSpot = QPointF();
+ d->sceneHotSpot = QPointF();
d->isHotSpotSet = false;
}
}
diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm
index e9fdbda..9560952 100644
--- a/src/gui/kernel/qt_cocoa_helpers_mac.mm
+++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm
@@ -369,6 +369,16 @@ QMacTabletHash *qt_mac_tablet_hash()
}
#ifdef QT_MAC_USE_COCOA
+
+// Clears the QWidget pointer that each QCocoaView holds.
+void qt_mac_clearCocoaViewQWidgetPointers(QWidget *widget)
+{
+ QCocoaView *cocoaView = reinterpret_cast<QCocoaView *>(qt_mac_nativeview_for(widget));
+ if (cocoaView && [cocoaView respondsToSelector:@selector(qt_qwidget)]) {
+ [cocoaView qt_clearQWidget];
+ }
+}
+
void qt_dispatchTabletProximityEvent(void * /*NSEvent * */ tabletEvent)
{
NSEvent *proximityEvent = static_cast<NSEvent *>(tabletEvent);
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index d433048..1e9b1d9 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -1468,6 +1468,15 @@ QWidget::~QWidget()
d->declarativeData = 0; // don't activate again in ~QObject
}
+#ifdef QT_MAC_USE_COCOA
+ // QCocoaView holds a pointer back to this widget. Clear it now
+ // to make sure it's not followed later on. The lifetime of the
+ // QCocoaView might exceed the lifetime of this widget in cases
+ // where Cocoa itself holds references to it.
+ extern void qt_mac_clearCocoaViewQWidgetPointers(QWidget *);
+ qt_mac_clearCocoaViewQWidgetPointers(this);
+#endif
+
if (!d->children.isEmpty())
d->deleteChildren();
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index fae26e0..891f4c2 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -46,6 +46,7 @@
#include <private/qdrawhelper_armv6_p.h>
#include <private/qdrawhelper_neon_p.h>
#include <private/qmath_p.h>
+#include <private/qsimd_p.h>
#include <qmath.h>
QT_BEGIN_NAMESPACE
@@ -7720,199 +7721,6 @@ static void qt_memfill16_setup(quint16 *dest, quint16 value, int count);
qt_memfill32_func qt_memfill32 = qt_memfill32_setup;
qt_memfill16_func qt_memfill16 = qt_memfill16_setup;
-enum CPUFeatures {
- None = 0,
- MMX = 0x1,
- MMXEXT = 0x2,
- MMX3DNOW = 0x4,
- MMX3DNOWEXT = 0x8,
- SSE = 0x10,
- SSE2 = 0x20,
- CMOV = 0x40,
- IWMMXT = 0x80,
- NEON = 0x100
-};
-
-static uint detectCPUFeatures()
-{
-#if defined (Q_OS_WINCE)
-#if defined (ARM)
- if (IsProcessorFeaturePresent(PF_ARM_INTEL_WMMX))
- return IWMMXT;
-#elif defined(_X86_)
- uint features = 0;
-#if defined QT_HAVE_MMX
- if (IsProcessorFeaturePresent(PF_MMX_INSTRUCTIONS_AVAILABLE))
- features |= MMX;
-#endif
-#if defined QT_HAVE_3DNOW
- if (IsProcessorFeaturePresent(PF_3DNOW_INSTRUCTIONS_AVAILABLE))
- features |= MMX3DNOW;
-#endif
- return features;
-#endif
- return 0;
-#elif defined(QT_HAVE_IWMMXT)
- // runtime detection only available when running as a previlegied process
- static const bool doIWMMXT = !qgetenv("QT_NO_IWMMXT").toInt();
- return doIWMMXT ? IWMMXT : 0;
-#elif defined(QT_HAVE_NEON)
- static const bool doNEON = !qgetenv("QT_NO_NEON").toInt();
- return doNEON ? NEON : 0;
-#else
- uint features = 0;
-#if defined(__x86_64__) || defined(Q_OS_WIN64)
- features = MMX|SSE|SSE2|CMOV;
-#elif defined(__ia64__)
- features = MMX|SSE|SSE2;
-#elif defined(__i386__) || defined(_M_IX86)
- unsigned int extended_result = 0;
- uint result = 0;
- /* see p. 118 of amd64 instruction set manual Vol3 */
-#if defined(Q_CC_GNU)
- asm ("push %%ebx\n"
- "pushf\n"
- "pop %%eax\n"
- "mov %%eax, %%ebx\n"
- "xor $0x00200000, %%eax\n"
- "push %%eax\n"
- "popf\n"
- "pushf\n"
- "pop %%eax\n"
- "xor %%edx, %%edx\n"
- "xor %%ebx, %%eax\n"
- "jz 1f\n"
-
- "mov $0x00000001, %%eax\n"
- "cpuid\n"
- "1:\n"
- "pop %%ebx\n"
- "mov %%edx, %0\n"
- : "=r" (result)
- :
- : "%eax", "%ecx", "%edx"
- );
-
- asm ("push %%ebx\n"
- "pushf\n"
- "pop %%eax\n"
- "mov %%eax, %%ebx\n"
- "xor $0x00200000, %%eax\n"
- "push %%eax\n"
- "popf\n"
- "pushf\n"
- "pop %%eax\n"
- "xor %%edx, %%edx\n"
- "xor %%ebx, %%eax\n"
- "jz 2f\n"
-
- "mov $0x80000000, %%eax\n"
- "cpuid\n"
- "cmp $0x80000000, %%eax\n"
- "jbe 2f\n"
- "mov $0x80000001, %%eax\n"
- "cpuid\n"
- "2:\n"
- "pop %%ebx\n"
- "mov %%edx, %0\n"
- : "=r" (extended_result)
- :
- : "%eax", "%ecx", "%edx"
- );
-#elif defined (Q_OS_WIN)
- _asm {
- push eax
- push ebx
- push ecx
- push edx
- pushfd
- pop eax
- mov ebx, eax
- xor eax, 00200000h
- push eax
- popfd
- pushfd
- pop eax
- mov edx, 0
- xor eax, ebx
- jz skip
-
- mov eax, 1
- cpuid
- mov result, edx
- skip:
- pop edx
- pop ecx
- pop ebx
- pop eax
- }
-
- _asm {
- push eax
- push ebx
- push ecx
- push edx
- pushfd
- pop eax
- mov ebx, eax
- xor eax, 00200000h
- push eax
- popfd
- pushfd
- pop eax
- mov edx, 0
- xor eax, ebx
- jz skip2
-
- mov eax, 80000000h
- cpuid
- cmp eax, 80000000h
- jbe skip2
- mov eax, 80000001h
- cpuid
- mov extended_result, edx
- skip2:
- pop edx
- pop ecx
- pop ebx
- pop eax
- }
-#endif
-
- // result now contains the standard feature bits
- if (result & (1u << 15))
- features |= CMOV;
- if (result & (1u << 23))
- features |= MMX;
- if (extended_result & (1u << 22))
- features |= MMXEXT;
- if (extended_result & (1u << 31))
- features |= MMX3DNOW;
- if (extended_result & (1u << 30))
- features |= MMX3DNOWEXT;
- if (result & (1u << 25))
- features |= SSE;
- if (result & (1u << 26))
- features |= SSE2;
-#endif // i386
-
- if (qgetenv("QT_NO_MMX").toInt())
- features ^= MMX;
- if (qgetenv("QT_NO_MMXEXT").toInt())
- features ^= MMXEXT;
- if (qgetenv("QT_NO_3DNOW").toInt())
- features ^= MMX3DNOW;
- if (qgetenv("QT_NO_3DNOWEXT").toInt())
- features ^= MMX3DNOWEXT;
- if (qgetenv("QT_NO_SSE").toInt())
- features ^= SSE;
- if (qgetenv("QT_NO_SSE2").toInt())
- features ^= SSE2;
-
- return features;
-#endif
-}
-
#if defined(Q_CC_RVCT) && defined(QT_HAVE_ARMV6)
// Move these to qdrawhelper_arm.c when all
// functions are implemented using arm assembly.
@@ -8005,10 +7813,7 @@ static void qt_blend_color_argb_armv6(int count, const QSpan *spans, void *userD
void qInitDrawhelperAsm()
{
- static uint features = 0xffffffff;
- if (features != 0xffffffff)
- return;
- features = detectCPUFeatures();
+ const uint features = qDetectCPUFeatures();
qt_memfill32 = qt_memfill_template<quint32, quint32>;
qt_memfill16 = qt_memfill_quint16; //qt_memfill_template<quint16, quint16>;
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index 2f78b00..f5b17ea 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -67,15 +67,6 @@
#include "QtGui/qscreen_qws.h"
#endif
-// Disable MMX and SSE on Mac/PPC builds, or if the compiler
-// does not support -Xarch argument passing
-#if defined(QT_NO_MAC_XARCH) || (defined(Q_OS_DARWIN) && (defined(__ppc__) || defined(__ppc64__)))
-#undef QT_HAVE_SSE2
-#undef QT_HAVE_SSE
-#undef QT_HAVE_3DNOW
-#undef QT_HAVE_MMX
-#endif
-
QT_BEGIN_NAMESPACE
#if defined(Q_CC_MSVC) && _MSCVER <= 1300 && !defined(Q_CC_INTEL)
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 60265c5..a7c2a0b 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -3213,6 +3213,9 @@ QRasterPaintEnginePrivate::getPenFunc(const QRectF &rect,
return isUnclipped(rect, penWidth) ? data->unclipped_blend : data->blend;
}
+/*!
+ \reimp
+*/
void QRasterPaintEngine::drawStaticTextItem(QStaticTextItem *textItem)
{
ensurePen();
diff --git a/src/multimedia/base/qgraphicsvideoitem.cpp b/src/multimedia/base/qgraphicsvideoitem.cpp
index 21ba8c9..d5ca9e8 100644
--- a/src/multimedia/base/qgraphicsvideoitem.cpp
+++ b/src/multimedia/base/qgraphicsvideoitem.cpp
@@ -177,9 +177,10 @@ void QGraphicsVideoItemPrivate::_q_mediaObjectDestroyed()
/*!
\class QGraphicsVideoItem
-
\brief The QGraphicsVideoItem class provides a graphics item which display video produced by a QMediaObject.
+ \since 4.7
+
\ingroup multimedia
Attaching a QGraphicsVideoItem to a QMediaObject allows it to display
diff --git a/src/multimedia/base/qmediacontent.cpp b/src/multimedia/base/qmediacontent.cpp
index fd519c6..6f158d2 100644
--- a/src/multimedia/base/qmediacontent.cpp
+++ b/src/multimedia/base/qmediacontent.cpp
@@ -76,6 +76,7 @@ private:
\class QMediaContent
\preliminary
\brief The QMediaContent class provides access to the resources relating to a media content.
+ \since 4.7
\ingroup multimedia
diff --git a/src/multimedia/base/qmediacontrol.cpp b/src/multimedia/base/qmediacontrol.cpp
index c8bbfd4..b84c49e 100644
--- a/src/multimedia/base/qmediacontrol.cpp
+++ b/src/multimedia/base/qmediacontrol.cpp
@@ -52,6 +52,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QMediaControl
\ingroup multimedia-serv
+ \since 4.7
\preliminary
\brief The QMediaControl class provides a base interface for media service controls.
diff --git a/src/multimedia/base/qmediaobject.cpp b/src/multimedia/base/qmediaobject.cpp
index b2b8c1b..0422718 100644
--- a/src/multimedia/base/qmediaobject.cpp
+++ b/src/multimedia/base/qmediaobject.cpp
@@ -67,6 +67,7 @@ void QMediaObjectPrivate::_q_notify()
\class QMediaObject
\preliminary
\brief The QMediaObject class provides a common base for multimedia objects.
+ \since 4.7
\ingroup multimedia
diff --git a/src/multimedia/base/qmediaplaylist.cpp b/src/multimedia/base/qmediaplaylist.cpp
index ab91fd7..b3f3dd3 100644
--- a/src/multimedia/base/qmediaplaylist.cpp
+++ b/src/multimedia/base/qmediaplaylist.cpp
@@ -66,6 +66,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(QMediaPluginLoader, playlistIOLoader,
/*!
\class QMediaPlaylist
\ingroup multimedia
+ \since 4.7
\preliminary
\brief The QMediaPlaylist class provides a list of media content to play.
diff --git a/src/multimedia/base/qmediaplaylistcontrol.cpp b/src/multimedia/base/qmediaplaylistcontrol.cpp
index 2ae03ad..ba3d224 100644
--- a/src/multimedia/base/qmediaplaylistcontrol.cpp
+++ b/src/multimedia/base/qmediaplaylistcontrol.cpp
@@ -49,6 +49,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QMediaPlaylistControl
\ingroup multimedia-serv
+ \since 4.7
\preliminary
\brief The QMediaPlaylistControl class provides access to the playlist functionality of a
diff --git a/src/multimedia/base/qmediaplaylistioplugin.cpp b/src/multimedia/base/qmediaplaylistioplugin.cpp
index 5f11e38..48fd721 100644
--- a/src/multimedia/base/qmediaplaylistioplugin.cpp
+++ b/src/multimedia/base/qmediaplaylistioplugin.cpp
@@ -46,6 +46,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QMediaPlaylistReader
\preliminary
+ \since 4.7
\brief The QMediaPlaylistReader class provides an interface for reading a playlist file.
\sa QMediaPlaylistIOPlugin
@@ -83,6 +84,7 @@ QMediaPlaylistReader::~QMediaPlaylistReader()
/*!
\class QMediaPlaylistWriter
\preliminary
+ \since 4.7
\brief The QMediaPlaylistWriter class provides an interface for writing a playlist file.
\sa QMediaPlaylistIOPlugin
@@ -111,6 +113,7 @@ QMediaPlaylistWriter::~QMediaPlaylistWriter()
/*!
\class QMediaPlaylistIOPlugin
+ \since 4.7
\brief The QMediaPlaylistIOPlugin class provides an interface for media playlist I/O plug-ins.
*/
diff --git a/src/multimedia/base/qmediaplaylistnavigator.cpp b/src/multimedia/base/qmediaplaylistnavigator.cpp
index 3c22ea4..0c52c71 100644
--- a/src/multimedia/base/qmediaplaylistnavigator.cpp
+++ b/src/multimedia/base/qmediaplaylistnavigator.cpp
@@ -193,6 +193,7 @@ int QMediaPlaylistNavigatorPrivate::previousItemPos(int steps) const
/*!
\class QMediaPlaylistNavigator
\preliminary
+ \since 4.7
\brief The QMediaPlaylistNavigator class provides navigation for a media playlist.
\sa QMediaPlaylist, QMediaPlaylistProvider
diff --git a/src/multimedia/base/qmediaplaylistprovider.cpp b/src/multimedia/base/qmediaplaylistprovider.cpp
index 65105dc..942f155 100644
--- a/src/multimedia/base/qmediaplaylistprovider.cpp
+++ b/src/multimedia/base/qmediaplaylistprovider.cpp
@@ -50,6 +50,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QMediaPlaylistProvider
\preliminary
+ \since 4.7
\brief The QMediaPlaylistProvider class provides an abstract list of media.
\sa QMediaPlaylist
diff --git a/src/multimedia/base/qmediaresource.cpp b/src/multimedia/base/qmediaresource.cpp
index 515e432..646d9a7 100644
--- a/src/multimedia/base/qmediaresource.cpp
+++ b/src/multimedia/base/qmediaresource.cpp
@@ -51,6 +51,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QMediaResource
\preliminary
+ \since 4.7
\brief The QMediaResource class provides a description of a media resource.
\ingroup multimedia
diff --git a/src/multimedia/base/qmediaservice.cpp b/src/multimedia/base/qmediaservice.cpp
index e40688e..d9e980b 100644
--- a/src/multimedia/base/qmediaservice.cpp
+++ b/src/multimedia/base/qmediaservice.cpp
@@ -57,6 +57,7 @@ QT_MODULE(Multimedia)
service implementations.
\ingroup multimedia-serv
\preliminary
+ \since 4.7
Media services provide implementations of the functionality promised
by media objects, and allow multiple providers to implement a QMediaObject.
diff --git a/src/multimedia/base/qmediaserviceprovider.cpp b/src/multimedia/base/qmediaserviceprovider.cpp
index 02c9b29..eb6505c 100644
--- a/src/multimedia/base/qmediaserviceprovider.cpp
+++ b/src/multimedia/base/qmediaserviceprovider.cpp
@@ -82,6 +82,7 @@ public:
/*!
\class QMediaServiceProviderHint
\preliminary
+ \since 4.7
\brief The QMediaServiceProviderHint class describes what is required of a QMediaService.
\ingroup multimedia-serv
@@ -489,6 +490,7 @@ Q_GLOBAL_STATIC(QPluginServiceProvider, pluginProvider);
/*!
\class QMediaServiceProvider
\preliminary
+ \since 4.7
\brief The QMediaServiceProvider class provides an abstract allocator for media services.
*/
@@ -597,6 +599,7 @@ QMediaServiceProvider *QMediaServiceProvider::defaultServiceProvider()
/*!
\class QMediaServiceProviderPlugin
\preliminary
+ \since 4.7
\brief The QMediaServiceProviderPlugin class interface provides an interface for QMediaService
plug-ins.
@@ -630,6 +633,7 @@ QMediaServiceProvider *QMediaServiceProvider::defaultServiceProvider()
\class QMediaServiceSupportedFormatsInterface
\brief The QMediaServiceSupportedFormatsInterface class interface
identifies if a media service plug-in supports a media format.
+ \since 4.7
A QMediaServiceProviderPlugin may implement this interface.
*/
@@ -656,6 +660,7 @@ QMediaServiceProvider *QMediaServiceProvider::defaultServiceProvider()
\class QMediaServiceSupportedDevicesInterface
\brief The QMediaServiceSupportedDevicesInterface class interface
identifies the devices supported by a media service plug-in.
+ \since 4.7
A QMediaServiceProviderPlugin may implement this interface.
*/
@@ -682,6 +687,7 @@ QMediaServiceProvider *QMediaServiceProvider::defaultServiceProvider()
\class QMediaServiceFeaturesInterface
\brief The QMediaServiceFeaturesInterface class interface identifies
features supported by a media service plug-in.
+ \since 4.7
A QMediaServiceProviderPlugin may implement this interface.
*/
diff --git a/src/multimedia/base/qmediatimerange.cpp b/src/multimedia/base/qmediatimerange.cpp
index 0ca1948..e1cea7e 100644
--- a/src/multimedia/base/qmediatimerange.cpp
+++ b/src/multimedia/base/qmediatimerange.cpp
@@ -48,6 +48,7 @@ QT_BEGIN_NAMESPACE
\class QMediaTimeInterval
\brief The QMediaTimeInterval class represents a time interval with integer precision.
\ingroup multimedia
+ \since 4.7
An interval is specified by an inclusive start() and end() time.
These must be set in the constructor, as this is an immutable class.
@@ -308,6 +309,7 @@ void QMediaTimeRangePrivate::removeInterval(const QMediaTimeInterval &interval)
\brief The QMediaTimeRange class represents a set of zero or more disjoint
time intervals.
\ingroup multimedia
+ \since 4.7
\reentrant
diff --git a/src/multimedia/base/qmetadatacontrol.cpp b/src/multimedia/base/qmetadatacontrol.cpp
index 3ecbe8d..28a82ec 100644
--- a/src/multimedia/base/qmetadatacontrol.cpp
+++ b/src/multimedia/base/qmetadatacontrol.cpp
@@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QMetaDataControl
\ingroup multimedia-serv
-
+ \since 4.7
\preliminary
\brief The QMetaDataControl class provides access to the meta-data of a
QMediaService's media.
diff --git a/src/multimedia/base/qvideodevicecontrol.cpp b/src/multimedia/base/qvideodevicecontrol.cpp
index 21db500..c0fe9a8 100644
--- a/src/multimedia/base/qvideodevicecontrol.cpp
+++ b/src/multimedia/base/qvideodevicecontrol.cpp
@@ -49,6 +49,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QVideoDeviceControl
\preliminary
+ \since 4.7
\brief The QVideoDeviceControl class provides an video device selector media control.
\ingroup multimedia-serv
diff --git a/src/multimedia/base/qvideooutputcontrol.cpp b/src/multimedia/base/qvideooutputcontrol.cpp
index a904385..58f1527 100644
--- a/src/multimedia/base/qvideooutputcontrol.cpp
+++ b/src/multimedia/base/qvideooutputcontrol.cpp
@@ -47,7 +47,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QVideoOutputControl
\preliminary
-
+ \since 4.7
\brief The QVideoOutputControl class provides a means of selecting the
active video output control.
diff --git a/src/multimedia/base/qvideorenderercontrol.cpp b/src/multimedia/base/qvideorenderercontrol.cpp
index 4e7b3da..a34ef9b 100644
--- a/src/multimedia/base/qvideorenderercontrol.cpp
+++ b/src/multimedia/base/qvideorenderercontrol.cpp
@@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QVideoRendererControl
\preliminary
-
+ \since 4.7
\brief The QVideoRendererControl class provides a control for rendering
to a video surface.
diff --git a/src/multimedia/base/qvideowidget.cpp b/src/multimedia/base/qvideowidget.cpp
index 5df245e..aabfefc 100644
--- a/src/multimedia/base/qvideowidget.cpp
+++ b/src/multimedia/base/qvideowidget.cpp
@@ -488,7 +488,7 @@ void QVideoWidgetPrivate::_q_dimensionsChanged()
/*!
\class QVideoWidget
\preliminary
-
+ \since 4.7
\brief The QVideoWidget class provides a widget which presents video
produced by a media object.
\ingroup multimedia
diff --git a/src/multimedia/base/qvideowidgetcontrol.cpp b/src/multimedia/base/qvideowidgetcontrol.cpp
index bd7ce4e..c53c77b 100644
--- a/src/multimedia/base/qvideowidgetcontrol.cpp
+++ b/src/multimedia/base/qvideowidgetcontrol.cpp
@@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QVideoWidgetControl
\preliminary
-
+ \since 4.7
\brief The QVideoWidgetControl class provides a media control which
implements a video widget.
diff --git a/src/multimedia/base/qvideowindowcontrol.cpp b/src/multimedia/base/qvideowindowcontrol.cpp
index a23cb4b..da46823 100644
--- a/src/multimedia/base/qvideowindowcontrol.cpp
+++ b/src/multimedia/base/qvideowindowcontrol.cpp
@@ -47,6 +47,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QVideoWindowControl
\preliminary
+ \since 4.7
\ingroup multimedia-serv
\brief The QVideoWindowControl class provides a media control for rendering video to a window.
diff --git a/src/multimedia/playback/qmediaplayer.cpp b/src/multimedia/playback/qmediaplayer.cpp
index ca34993..27bff02 100644
--- a/src/multimedia/playback/qmediaplayer.cpp
+++ b/src/multimedia/playback/qmediaplayer.cpp
@@ -66,7 +66,7 @@ QT_MODULE(Multimedia)
\class QMediaPlayer
\brief The QMediaPlayer class allows the playing of a media source.
\ingroup multimedia
-
+ \since 4.7
\preliminary
The QMediaPlayer class is a high level media playback class. It can be used
diff --git a/src/multimedia/playback/qmediaplayercontrol.cpp b/src/multimedia/playback/qmediaplayercontrol.cpp
index 95ffade..2129098 100644
--- a/src/multimedia/playback/qmediaplayercontrol.cpp
+++ b/src/multimedia/playback/qmediaplayercontrol.cpp
@@ -50,7 +50,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QMediaPlayerControl
\ingroup multimedia-serv
-
+ \since 4.7
\preliminary
\brief The QMediaPlayerControl class provides access to the media playing
functionality of a QMediaService.
diff --git a/src/plugins/bearer/generic/qgenericengine.cpp b/src/plugins/bearer/generic/qgenericengine.cpp
index a95b14b..e96b80c 100644
--- a/src/plugins/bearer/generic/qgenericengine.cpp
+++ b/src/plugins/bearer/generic/qgenericengine.cpp
@@ -60,6 +60,7 @@
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/if_arp.h>
+#include <unistd.h>
#endif
diff --git a/src/plugins/mediaservices/gstreamer/qgstreamermessage.cpp b/src/plugins/mediaservices/gstreamer/qgstreamermessage.cpp
index 0a689d9..13a2454 100644
--- a/src/plugins/mediaservices/gstreamer/qgstreamermessage.cpp
+++ b/src/plugins/mediaservices/gstreamer/qgstreamermessage.cpp
@@ -48,7 +48,7 @@ static int wuchi = qRegisterMetaType<QGstreamerMessage>();
/*!
- \class QGstreamerMessage
+ \class gstreamer::QGstreamerMessage
\internal
*/
diff --git a/src/script/api/qscriptengine_p.h b/src/script/api/qscriptengine_p.h
index f69e537..79294fe 100644
--- a/src/script/api/qscriptengine_p.h
+++ b/src/script/api/qscriptengine_p.h
@@ -854,7 +854,7 @@ inline bool QScriptEnginePrivate::isQObject(JSC::JSValue value)
inline bool QScriptEnginePrivate::isQMetaObject(JSC::JSValue value)
{
#ifndef QT_NO_QOBJECT
- return JSC::asObject(value)->inherits(&QScript::QMetaObjectWrapperObject::info);
+ return isObject(value) && JSC::asObject(value)->inherits(&QScript::QMetaObjectWrapperObject::info);
#else
return false;
#endif