aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/3rdparty/masm/assembler/MacroAssembler.h11
-rw-r--r--src/3rdparty/masm/assembler/MacroAssemblerARM64.h2
-rw-r--r--src/3rdparty/masm/assembler/MacroAssemblerARMv7.h4
-rw-r--r--src/3rdparty/masm/assembler/MacroAssemblerMIPS.h1
-rw-r--r--src/3rdparty/masm/assembler/MacroAssemblerX86.h1
-rw-r--r--src/3rdparty/masm/assembler/MacroAssemblerX86_64.h1
-rw-r--r--src/qml/jit/qv4assembler.cpp10
-rw-r--r--src/qml/jit/qv4assembler_p.h9
-rw-r--r--src/qml/jit/qv4targetplatform_p.h6
-rw-r--r--src/qml/qml/qqmltypeloader.cpp1
-rw-r--r--src/quick/items/qquickflickable.cpp7
-rw-r--r--src/quick/items/qquickwindow.cpp26
-rw-r--r--src/quickwidgets/qquickwidget.cpp7
-rw-r--r--src/quickwidgets/qquickwidget_p.h2
-rw-r--r--tests/auto/auto.pro3
-rw-r--r--tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp2
-rw-r--r--tests/auto/qml/qml.pro20
-rw-r--r--tests/auto/quick/qquickflickable/data/nestedSlider.qml36
-rw-r--r--tests/auto/quick/qquickflickable/tst_qquickflickable.cpp187
-rw-r--r--tests/auto/quick/qquickimage/tst_qquickimage.cpp2
-rw-r--r--tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp28
21 files changed, 308 insertions, 58 deletions
diff --git a/src/3rdparty/masm/assembler/MacroAssembler.h b/src/3rdparty/masm/assembler/MacroAssembler.h
index 7d9f156c8c..f37861eb66 100644
--- a/src/3rdparty/masm/assembler/MacroAssembler.h
+++ b/src/3rdparty/masm/assembler/MacroAssembler.h
@@ -94,6 +94,7 @@ public:
using DataLabelCompact = typename MacroAssemblerBase::DataLabelCompact;
using Jump = typename MacroAssemblerBase::Jump;
using PatchableJump = typename MacroAssemblerBase::PatchableJump;
+ using MacroAssemblerBase::PointerSize;
using MacroAssemblerBase::pop;
using MacroAssemblerBase::jump;
@@ -200,19 +201,19 @@ public:
// described in terms of other macro assembly methods.
void pop()
{
- addPtr(TrustedImm32(sizeof(void*)), MacroAssemblerBase::stackPointerRegister);
+ addPtr(TrustedImm32(PointerSize), MacroAssemblerBase::stackPointerRegister);
}
void peek(RegisterID dest, int index = 0)
{
- loadPtr(Address(MacroAssemblerBase::stackPointerRegister, (index * sizeof(void*))), dest);
+ loadPtr(Address(MacroAssemblerBase::stackPointerRegister, (index * PointerSize)), dest);
}
Address addressForPoke(int index)
{
- return Address(MacroAssemblerBase::stackPointerRegister, (index * sizeof(void*)));
+ return Address(MacroAssemblerBase::stackPointerRegister, (index * PointerSize));
}
-
+
void poke(RegisterID src, int index = 0)
{
storePtr(src, addressForPoke(index));
@@ -223,10 +224,12 @@ public:
store32(value, addressForPoke(index));
}
+#if !defined(V4_BOOTSTRAP)
void poke(TrustedImmPtr imm, int index = 0)
{
storePtr(imm, addressForPoke(index));
}
+#endif
#if (CPU(X86_64) || CPU(ARM64)) && !defined(V4_BOOTSTRAP)
void peek64(RegisterID dest, int index = 0)
diff --git a/src/3rdparty/masm/assembler/MacroAssemblerARM64.h b/src/3rdparty/masm/assembler/MacroAssemblerARM64.h
index a11637f7ca..11f1672e15 100644
--- a/src/3rdparty/masm/assembler/MacroAssemblerARM64.h
+++ b/src/3rdparty/masm/assembler/MacroAssemblerARM64.h
@@ -127,6 +127,8 @@ private:
static const ptrdiff_t REPATCH_OFFSET_CALL_TO_POINTER = -16;
public:
+ static const int PointerSize = 8;
+
MacroAssemblerARM64()
: m_dataMemoryTempRegister(this, dataTempRegister)
, m_cachedMemoryTempRegister(this, memoryTempRegister)
diff --git a/src/3rdparty/masm/assembler/MacroAssemblerARMv7.h b/src/3rdparty/masm/assembler/MacroAssemblerARMv7.h
index 806f2e13b6..fe8170d098 100644
--- a/src/3rdparty/masm/assembler/MacroAssemblerARMv7.h
+++ b/src/3rdparty/masm/assembler/MacroAssemblerARMv7.h
@@ -46,6 +46,8 @@ protected: // the YarrJIT needs know about addressTempRegister in order to push
inline ARMRegisters::FPSingleRegisterID fpTempRegisterAsSingle() { return ARMRegisters::asSingle(fpTempRegister); }
public:
+ static const int PointerSize = 4;
+
MacroAssemblerARMv7()
: m_makeJumpPatchable(false)
{
@@ -1242,7 +1244,7 @@ public:
void pop(RegisterID dest)
{
// store postindexed with writeback
- m_assembler.ldr(dest, ARMRegisters::sp, sizeof(void*), false, true);
+ m_assembler.ldr(dest, ARMRegisters::sp, 4 /*sizeof(void*)*/, false, true);
}
void push(RegisterID src)
diff --git a/src/3rdparty/masm/assembler/MacroAssemblerMIPS.h b/src/3rdparty/masm/assembler/MacroAssemblerMIPS.h
index 68584527fc..f2ad6a4470 100644
--- a/src/3rdparty/masm/assembler/MacroAssemblerMIPS.h
+++ b/src/3rdparty/masm/assembler/MacroAssemblerMIPS.h
@@ -37,6 +37,7 @@ namespace JSC {
class MacroAssemblerMIPS : public AbstractMacroAssembler<MIPSAssembler> {
public:
typedef MIPSRegisters::FPRegisterID FPRegisterID;
+ static const int PointerSize = 4;
MacroAssemblerMIPS()
: m_fixedWidth(false)
diff --git a/src/3rdparty/masm/assembler/MacroAssemblerX86.h b/src/3rdparty/masm/assembler/MacroAssemblerX86.h
index 742a4b48f7..280cf427fc 100644
--- a/src/3rdparty/masm/assembler/MacroAssemblerX86.h
+++ b/src/3rdparty/masm/assembler/MacroAssemblerX86.h
@@ -35,6 +35,7 @@ namespace JSC {
class MacroAssemblerX86 : public MacroAssemblerX86Common {
public:
static const Scale ScalePtr = TimesFour;
+ static const int PointerSize = 4;
using MacroAssemblerX86Common::add32;
using MacroAssemblerX86Common::and32;
diff --git a/src/3rdparty/masm/assembler/MacroAssemblerX86_64.h b/src/3rdparty/masm/assembler/MacroAssemblerX86_64.h
index 14757f4ea2..c7c6aae637 100644
--- a/src/3rdparty/masm/assembler/MacroAssemblerX86_64.h
+++ b/src/3rdparty/masm/assembler/MacroAssemblerX86_64.h
@@ -37,6 +37,7 @@ namespace JSC {
class MacroAssemblerX86_64 : public MacroAssemblerX86Common {
public:
static const Scale ScalePtr = TimesEight;
+ static const int PointerSize = 8;
using MacroAssemblerX86Common::add32;
using MacroAssemblerX86Common::and32;
diff --git a/src/qml/jit/qv4assembler.cpp b/src/qml/jit/qv4assembler.cpp
index 81d34701a9..583719a3c7 100644
--- a/src/qml/jit/qv4assembler.cpp
+++ b/src/qml/jit/qv4assembler.cpp
@@ -95,6 +95,12 @@ bool CompilationUnit::memoryMapCode(QString *errorString)
JSC::MacroAssemblerCodeRef codeRef = JSC::MacroAssemblerCodeRef::createSelfManagedCodeRef(JSC::MacroAssemblerCodePtr(codePtr));
JSC::ExecutableAllocator::makeExecutable(codePtr, compiledFunction->codeSize);
codeRefs[i] = codeRef;
+
+ static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_ASM");
+ if (showCode) {
+ WTF::dataLogF("Mapped JIT code for %s\n", qPrintable(stringAt(compiledFunction->nameIndex)));
+ disassemble(codeRef.code(), compiledFunction->codeSize, " ", WTF::dataFile());
+ }
}
return true;
@@ -535,9 +541,7 @@ void Assembler<TargetConfiguration>::returnFromFunction(IR::Ret *s, RegisterInfo
const int locals = stackLayout().calculateJSStackFrameSize();
subPtr(TrustedImm32(sizeof(QV4::Value)*locals), JITTargetPlatform::LocalsRegister);
- loadPtr(Address(JITTargetPlatform::EngineRegister, targetStructureOffset(offsetof(QV4::EngineBase, current))), JITTargetPlatform::ScratchRegister);
- loadPtr(Address(JITTargetPlatform::ScratchRegister, targetStructureOffset(Heap::ExecutionContextData::baseOffset + offsetof(Heap::ExecutionContextData, engine))), JITTargetPlatform::ScratchRegister);
- storePtr(JITTargetPlatform::LocalsRegister, Address(JITTargetPlatform::ScratchRegister, targetStructureOffset(offsetof(EngineBase, jsStackTop))));
+ storePtr(JITTargetPlatform::LocalsRegister, Address(JITTargetPlatform::EngineRegister, targetStructureOffset(offsetof(EngineBase, jsStackTop))));
leaveStandardStackFrame(regularRegistersToSave, fpRegistersToSave);
ret();
diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h
index addbfc12a3..d4a18ae886 100644
--- a/src/qml/jit/qv4assembler_p.h
+++ b/src/qml/jit/qv4assembler_p.h
@@ -1387,13 +1387,6 @@ public:
RegisterSizeDependentOps::emitWriteBarrier(this, dest);
}
- void storeValue(QV4::Primitive value, RegisterID destination)
- {
- Q_UNUSED(value);
- Q_UNUSED(destination);
- Q_UNREACHABLE();
- }
-
void storeValue(QV4::Primitive value, Address destination, WriteBarrier::Type barrier)
{
RegisterSizeDependentOps::storeValue(this, value, destination, barrier);
@@ -1463,7 +1456,7 @@ public:
template <int ArgumentIndex, typename Parameter>
struct SizeOnStack
{
- enum { Size = Select<ArgumentIndex >= RegisterArgumentCount, sizeof(void*), 0>::Chosen };
+ enum { Size = Select<ArgumentIndex >= RegisterArgumentCount, RegisterSize, 0>::Chosen };
};
template <int ArgumentIndex>
diff --git a/src/qml/jit/qv4targetplatform_p.h b/src/qml/jit/qv4targetplatform_p.h
index d9f8034b1f..ce6156802d 100644
--- a/src/qml/jit/qv4targetplatform_p.h
+++ b/src/qml/jit/qv4targetplatform_p.h
@@ -370,7 +370,7 @@ public:
// There are two designated frame-pointer registers on ARM, depending on which instruction set
// is used for the subroutine: r7 for Thumb or Thumb2, and r11 for ARM. We assign the constants
// accordingly, and assign the locals-register to the "other" register.
-#if CPU(ARM_THUMB2)
+#if CPU(ARM_THUMB2) || defined(V4_BOOTSTRAP)
static const RegisterID FramePointerRegister = JSC::ARMRegisters::r7;
static const RegisterID LocalsRegister = JSC::ARMRegisters::r11;
#else // Thumbs down
@@ -397,7 +397,7 @@ public:
<< RI(JSC::ARMRegisters::r4, QStringLiteral("r4"), RI::RegularRegister, RI::CalleeSaved, RI::RegAlloc)
<< RI(JSC::ARMRegisters::r5, QStringLiteral("r5"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
<< RI(JSC::ARMRegisters::r6, QStringLiteral("r6"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
-#if !CPU(ARM_THUMB2)
+#if !CPU(ARM_THUMB2) && !defined(V4_BOOTSTRAP)
<< RI(JSC::ARMRegisters::r7, QStringLiteral("r7"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
#endif
<< RI(JSC::ARMRegisters::r8, QStringLiteral("r8"), RI::RegularRegister, RI::CalleeSaved, RI::RegAlloc)
@@ -405,7 +405,7 @@ public:
<< RI(JSC::ARMRegisters::r9, QStringLiteral("r9"), RI::RegularRegister, RI::CalleeSaved, RI::RegAlloc)
#endif
<< RI(JSC::ARMRegisters::r10, QStringLiteral("r10"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
-#if CPU(ARM_THUMB2)
+#if CPU(ARM_THUMB2) && !defined(V4_BOOTSTRAP)
<< RI(JSC::ARMRegisters::r11, QStringLiteral("r11"), RI::RegularRegister, RI::CalleeSaved, RI::Predefined)
#endif
<< RI(JSC::ARMRegisters::d2, QStringLiteral("d2"), RI::FloatingPointRegister, RI::CallerSaved, RI::RegAlloc)
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index f115d4227c..40bd2e5020 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -64,6 +64,7 @@
#include <QtCore/qwaitcondition.h>
#include <QtCore/qloggingcategory.h>
#include <QtQml/qqmlextensioninterface.h>
+#include <QtCore/qcryptographichash.h>
#include <functional>
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp
index 6a2946bdcc..27d7072f03 100644
--- a/src/quick/items/qquickflickable.cpp
+++ b/src/quick/items/qquickflickable.cpp
@@ -2301,7 +2301,8 @@ bool QQuickFlickable::filterMouseEvent(QQuickItem *receiver, QMouseEvent *event)
bool receiverDisabled = receiver && !receiver->isEnabled();
bool stealThisEvent = d->stealMouse;
- if ((stealThisEvent || contains(localPos)) && (!receiver || !receiver->keepMouseGrab() || receiverDisabled)) {
+ bool receiverKeepsGrab = receiver && (receiver->keepMouseGrab() || receiver->keepTouchGrab());
+ if ((stealThisEvent || contains(localPos)) && (!receiver || !receiverKeepsGrab || receiverDisabled)) {
QScopedPointer<QMouseEvent> mouseEvent(QQuickWindowPrivate::cloneMouseEvent(event, &localPos));
mouseEvent->setAccepted(false);
@@ -2321,7 +2322,7 @@ bool QQuickFlickable::filterMouseEvent(QQuickItem *receiver, QMouseEvent *event)
default:
break;
}
- if ((receiver && stealThisEvent && !receiver->keepMouseGrab() && receiver != this) || receiverDisabled) {
+ if ((receiver && stealThisEvent && !receiverKeepsGrab && receiver != this) || receiverDisabled) {
d->clearDelayedPress();
grabMouse();
} else if (d->delayedPressEvent) {
@@ -2337,7 +2338,7 @@ bool QQuickFlickable::filterMouseEvent(QQuickItem *receiver, QMouseEvent *event)
d->lastPosTime = -1;
returnToBounds();
}
- if (event->type() == QEvent::MouseButtonRelease || (receiver && receiver->keepMouseGrab() && !receiverDisabled)) {
+ if (event->type() == QEvent::MouseButtonRelease || (receiverKeepsGrab && !receiverDisabled)) {
// mouse released, or another item has claimed the grab
d->lastPosTime = -1;
d->clearDelayedPress();
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 80abf82e58..bd68f39e48 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -746,6 +746,7 @@ void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber)
qCDebug(DBG_MOUSE_TARGET) << "grabber" << q->mouseGrabberItem() << "->" << grabber;
QQuickItem *oldGrabber = q->mouseGrabberItem();
+ bool fromTouch = false;
if (grabber && touchMouseId != -1 && touchMouseDevice) {
// update the touch item for mouse touch id to the new grabber
@@ -753,6 +754,7 @@ void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber)
auto point = touchMouseDevice->pointerEvent()->pointById(touchMouseId);
if (point)
point->setGrabber(grabber);
+ fromTouch = true;
} else {
QQuickPointerEvent *event = QQuickPointerDevice::genericMouseDevice()->pointerEvent();
Q_ASSERT(event->pointCount() == 1);
@@ -762,8 +764,11 @@ void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber)
if (oldGrabber) {
QEvent e(QEvent::UngrabMouse);
QSet<QQuickItem *> hasFiltered;
- if (!sendFilteredMouseEvent(oldGrabber->parentItem(), oldGrabber, &e, &hasFiltered))
+ if (!sendFilteredMouseEvent(oldGrabber->parentItem(), oldGrabber, &e, &hasFiltered)) {
oldGrabber->mouseUngrabEvent();
+ if (fromTouch)
+ oldGrabber->touchUngrabEvent();
+ }
}
}
@@ -2585,28 +2590,39 @@ bool QQuickWindowPrivate::sendFilteredTouchEvent(QQuickItem *target, QQuickItem
break;
}
+ bool touchMouseUnset = (touchMouseId == -1);
// Only deliver mouse event if it is the touchMouseId or it could become the touchMouseId
- if (touchMouseId == -1 || touchMouseId == tp.id()) {
+ if (touchMouseUnset || touchMouseId == tp.id()) {
// targetEvent is already transformed wrt local position, velocity, etc.
// FIXME: remove asTouchEvent!!!
QScopedPointer<QMouseEvent> mouseEvent(touchToMouseEvent(t, tp, event->asTouchEvent(), item, false));
+ // If a filtering item calls QQuickWindow::mouseGrabberItem(), it should
+ // report the touchpoint's grabber. Whenever we send a synthetic mouse event,
+ // touchMouseId and touchMouseDevice must be set, even if it's only temporarily and isn't grabbed.
+ touchMouseId = tp.id();
+ touchMouseDevice = event->device();
if (target->childMouseEventFilter(item, mouseEvent.data())) {
qCDebug(DBG_TOUCH) << " - second chance intercepted on childMouseEventFilter by " << target;
if (t != QEvent::MouseButtonRelease) {
qCDebug(DBG_TOUCH_TARGET) << "TP" << tp.id() << "->" << target;
- touchMouseDevice = event->device();
- if (touchMouseId == -1) {
+ if (touchMouseUnset) {
// the point was grabbed as a pure touch point before, now it will be treated as mouse
// but the old receiver still needs to be informed
if (auto oldGrabber = touchMouseDevice->pointerEvent()->pointById(tp.id())->grabber())
oldGrabber->touchUngrabEvent();
}
- touchMouseId = tp.id();
+ touchMouseUnset = false; // We want to leave touchMouseId and touchMouseDevice set
target->grabMouse();
}
filtered = true;
}
+ if (touchMouseUnset) {
+ // Now that we're done sending a synth mouse event, and it wasn't grabbed,
+ // the touchpoint is no longer acting as a synthetic mouse. Restore previous state.
+ touchMouseId = -1;
+ touchMouseDevice = nullptr;
+ }
// Only one event can be filtered as a mouse event.
break;
}
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index ea02723db8..5d7fb04b9f 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -353,10 +353,9 @@ QImage QQuickWidgetPrivate::grabFramebuffer()
return renderControl->grab();
}
-QObject *QQuickWidgetPrivate::focusObject()
-{
- return offscreenWindow ? offscreenWindow->focusObject() : 0;
-}
+// Intentionally not overriding the QQuickWindow's focusObject.
+// Key events should go to our key event handlers, and then to the
+// QQuickWindow, not any in-scene item.
/*!
\module QtQuickWidgets
diff --git a/src/quickwidgets/qquickwidget_p.h b/src/quickwidgets/qquickwidget_p.h
index 559321cd51..6892e6e0b4 100644
--- a/src/quickwidgets/qquickwidget_p.h
+++ b/src/quickwidgets/qquickwidget_p.h
@@ -99,8 +99,6 @@ public:
void destroyContext();
void handleContextCreationFailure(const QSurfaceFormat &format, bool isEs);
- QObject *focusObject() Q_DECL_OVERRIDE;
-
#if QT_CONFIG(opengl)
GLuint textureId() const Q_DECL_OVERRIDE;
QImage grabFramebuffer() Q_DECL_OVERRIDE;
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index 1e80f1bf65..f9c1fcce91 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -18,4 +18,7 @@ qtHaveModule(gui):qtConfig(opengl(es1|es2)?) {
# console applications not supported
uikit: SUBDIRS -= qmltest
+# Restricted sub-set for now
+boot2qt: SUBDIRS = qml
+
installed_cmake.depends = cmake
diff --git a/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp b/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp
index 2ce0cfe210..5d7009e7c8 100644
--- a/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp
+++ b/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp
@@ -71,7 +71,7 @@ void tst_EcmaScriptTests::runTests()
#endif
}
-QTEST_MAIN(tst_EcmaScriptTests)
+QTEST_GUILESS_MAIN(tst_EcmaScriptTests)
#include "tst_ecmascripttests.moc"
diff --git a/tests/auto/qml/qml.pro b/tests/auto/qml/qml.pro
index a9b18e9f32..007eb0dc83 100644
--- a/tests/auto/qml/qml.pro
+++ b/tests/auto/qml/qml.pro
@@ -7,6 +7,9 @@ PUBLICTESTS += \
parserstress \
qjsvalueiterator \
qjsonbinding \
+
+!boot2qt {
+PUBLICTESTS += \
qmlmin \
qqmlcomponent \
qqmlconsole \
@@ -25,15 +28,21 @@ PUBLICTESTS += \
qquickfolderlistmodel \
qqmlapplicationengine \
qqmlsettings \
- qqmlstatemachine
+ qqmlstatemachine \
+ qmldiskcache
+}
PRIVATETESTS += \
- animation \
qqmlcpputils \
+ qqmldirparser \
+ v4misc \
+
+!boot2qt {
+PRIVATETESTS += \
+ animation \
qqmlecmascript \
qqmlcontext \
qqmlexpression \
- qqmldirparser \
qqmlglobal \
qqmllanguage \
qqmlopenmetaobject \
@@ -57,13 +66,12 @@ PRIVATETESTS += \
qqmltimer \
qqmlinstantiator \
qqmlenginecleanup \
- v4misc \
qqmltranslation \
qqmlimport \
qqmlobjectmodel \
- qmldiskcache \
qv4mm \
ecmascripttests
+}
qtHaveModule(widgets) {
PUBLICTESTS += \
@@ -73,7 +81,7 @@ qtHaveModule(widgets) {
SUBDIRS += $$PUBLICTESTS
SUBDIRS += $$METATYPETESTS
-qtConfig(process) {
+qtConfig(process):!boot2qt {
!contains(QT_CONFIG, no-qml-debug): SUBDIRS += debugger
SUBDIRS += qmllint qmlplugindump
}
diff --git a/tests/auto/quick/qquickflickable/data/nestedSlider.qml b/tests/auto/quick/qquickflickable/data/nestedSlider.qml
new file mode 100644
index 0000000000..2fd0cbfcc8
--- /dev/null
+++ b/tests/auto/quick/qquickflickable/data/nestedSlider.qml
@@ -0,0 +1,36 @@
+import QtQuick 2.0
+import Test 1.0
+
+Flickable {
+ width: 240
+ height: 320
+ contentWidth: width * 1.5
+ contentHeight: height * 1.5
+ contentY: height * 0.25
+
+ Rectangle {
+ id: slider
+ width: 50
+ height: 200
+ color: "lightgray"
+ border.color: drag.active ? "green" : "black"
+ anchors.centerIn: parent
+ radius: 4
+
+ TouchDragArea {
+ id: drag
+ objectName: "drag"
+ anchors.fill: parent
+ }
+
+ Rectangle {
+ width: parent.width - 2
+ height: 20
+ radius: 5
+ color: "darkgray"
+ border.color: "black"
+ x: 1
+ y: Math.min(slider.height - height, Math.max(0, drag.pos.y - height / 2))
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
index 9ead271bfe..3ecebfb48f 100644
--- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
+++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
@@ -46,12 +46,109 @@
using namespace QQuickViewTestUtil;
using namespace QQuickVisualTestUtil;
+// an abstract Slider which only handles touch events
+class TouchDragArea : public QQuickItem
+{
+ Q_OBJECT
+ Q_PROPERTY(QPointF pos READ pos NOTIFY posChanged)
+ Q_PROPERTY(bool active READ active NOTIFY activeChanged)
+ Q_PROPERTY(bool keepMouseGrab READ keepMouseGrab WRITE setKeepMouseGrab NOTIFY keepMouseGrabChanged)
+ Q_PROPERTY(bool keepTouchGrab READ keepTouchGrab WRITE setKeepTouchGrab NOTIFY keepTouchGrabChanged)
+
+public:
+ TouchDragArea(QQuickItem *parent = 0)
+ : QQuickItem(parent)
+ , touchEvents(0)
+ , touchUpdates(0)
+ , touchReleases(0)
+ , ungrabs(0)
+ , m_active(false)
+ {
+ setFlags(ItemAcceptsDrops);
+ }
+
+ QPointF pos() const { return m_pos; }
+
+ bool active() const { return m_active; }
+
+ void setKeepMouseGrab(bool keepMouseGrab)
+ {
+ QQuickItem::setKeepMouseGrab(keepMouseGrab);
+ emit keepMouseGrabChanged();
+ }
+
+ void setKeepTouchGrab(bool keepTouchGrab)
+ {
+ QQuickItem::setKeepTouchGrab(keepTouchGrab);
+ emit keepTouchGrabChanged();
+ }
+
+ int touchEvents;
+ int touchUpdates;
+ int touchReleases;
+ int ungrabs;
+ QVector<Qt::TouchPointState> touchPointStates;
+
+protected:
+ void touchEvent(QTouchEvent *ev) override
+ {
+ QCOMPARE(ev->touchPoints().count(), 1);
+ auto touchpoint = ev->touchPoints().first();
+ switch (touchpoint.state()) {
+ case Qt::TouchPointPressed:
+ QVERIFY(!m_active);
+ m_active = true;
+ emit activeChanged();
+ grabTouchPoints(QVector<int>() << touchpoint.id());
+ break;
+ case Qt::TouchPointMoved:
+ ++touchUpdates;
+ break;
+ case Qt::TouchPointReleased:
+ QVERIFY(m_active);
+ m_active = false;
+ ++touchReleases;
+ emit activeChanged();
+ case Qt::TouchPointStationary:
+ break;
+ }
+ touchPointStates << touchpoint.state();
+ ++touchEvents;
+ m_pos = touchpoint.pos();
+ emit posChanged();
+ }
+
+ void touchUngrabEvent() override
+ {
+ ++ungrabs;
+ QVERIFY(m_active);
+ emit ungrabbed();
+ m_active = false;
+ emit activeChanged();
+ }
+
+signals:
+ void ungrabbed();
+ void posChanged();
+ void keepMouseGrabChanged();
+ void keepTouchGrabChanged();
+ void activeChanged();
+
+private:
+ QPointF m_pos;
+ bool m_active;
+};
+
class tst_qquickflickable : public QQmlDataTest
{
Q_OBJECT
public:
+ tst_qquickflickable()
+ : touchDevice(QTest::createTouchDevice())
+ {}
private slots:
+ void initTestCase() override;
void create();
void horizontalViewportSize();
void verticalViewportSize();
@@ -89,6 +186,8 @@ private slots:
void stopAtBounds();
void stopAtBounds_data();
void nestedMouseAreaUsingTouch();
+ void nestedSliderUsingTouch();
+ void nestedSliderUsingTouch_data();
void pressDelayWithLoader();
void movementFromProgrammaticFlick();
void cleanup();
@@ -101,9 +200,16 @@ private slots:
void overshoot_reentrant();
private:
- void flickWithTouch(QQuickWindow *window, QTouchDevice *touchDevice, const QPoint &from, const QPoint &to);
+ void flickWithTouch(QQuickWindow *window, const QPoint &from, const QPoint &to);
+ QTouchDevice *touchDevice;
};
+void tst_qquickflickable::initTestCase()
+{
+ QQmlDataTest::initTestCase();
+ qmlRegisterType<TouchDragArea>("Test",1,0,"TouchDragArea");
+}
+
void tst_qquickflickable::cleanup()
{
QVERIFY(QGuiApplication::topLevelWindows().isEmpty());
@@ -1530,12 +1636,6 @@ void tst_qquickflickable::clickAndDragWhenTransformed()
void tst_qquickflickable::flickTwiceUsingTouches()
{
- QTouchDevice *touchDevice = new QTouchDevice;
- touchDevice->setName("Fake Touchscreen");
- touchDevice->setType(QTouchDevice::TouchScreen);
- touchDevice->setCapabilities(QTouchDevice::Position);
- QWindowSystemInterface::registerTouchDevice(touchDevice);
-
QScopedPointer<QQuickView> window(new QQuickView);
window->setSource(testFileUrl("longList.qml"));
QTRY_COMPARE(window->status(), QQuickView::Ready);
@@ -1548,7 +1648,7 @@ void tst_qquickflickable::flickTwiceUsingTouches()
QVERIFY(flickable != 0);
QCOMPARE(flickable->contentY(), 0.0f);
- flickWithTouch(window.data(), touchDevice, QPoint(100, 400), QPoint(100, 240));
+ flickWithTouch(window.data(), QPoint(100, 400), QPoint(100, 240));
qreal contentYAfterFirstFlick = flickable->contentY();
qDebug() << "contentYAfterFirstFlick " << contentYAfterFirstFlick;
@@ -1556,7 +1656,7 @@ void tst_qquickflickable::flickTwiceUsingTouches()
// Wait until view stops moving
QTRY_VERIFY(!flickable->isMoving());
- flickWithTouch(window.data(), touchDevice, QPoint(100, 400), QPoint(100, 240));
+ flickWithTouch(window.data(), QPoint(100, 400), QPoint(100, 240));
// In the original bug, that second flick would cause Flickable to halt immediately
qreal contentYAfterSecondFlick = flickable->contentY();
@@ -1564,7 +1664,7 @@ void tst_qquickflickable::flickTwiceUsingTouches()
QTRY_VERIFY(contentYAfterSecondFlick > (contentYAfterFirstFlick + 80.0f));
}
-void tst_qquickflickable::flickWithTouch(QQuickWindow *window, QTouchDevice *touchDevice, const QPoint &from, const QPoint &to)
+void tst_qquickflickable::flickWithTouch(QQuickWindow *window, const QPoint &from, const QPoint &to)
{
QTest::touchEvent(window, touchDevice).press(0, from, window);
QQuickTouchUtils::flush(window);
@@ -1869,12 +1969,6 @@ void tst_qquickflickable::stopAtBounds()
void tst_qquickflickable::nestedMouseAreaUsingTouch()
{
- QTouchDevice *touchDevice = new QTouchDevice;
- touchDevice->setName("Fake Touchscreen");
- touchDevice->setType(QTouchDevice::TouchScreen);
- touchDevice->setCapabilities(QTouchDevice::Position);
- QWindowSystemInterface::registerTouchDevice(touchDevice);
-
QScopedPointer<QQuickView> window(new QQuickView);
window->setSource(testFileUrl("nestedmousearea.qml"));
QTRY_COMPARE(window->status(), QQuickView::Ready);
@@ -1887,7 +1981,7 @@ void tst_qquickflickable::nestedMouseAreaUsingTouch()
QVERIFY(flickable != 0);
QCOMPARE(flickable->contentY(), 50.0f);
- flickWithTouch(window.data(), touchDevice, QPoint(100, 300), QPoint(100, 200));
+ flickWithTouch(window.data(), QPoint(100, 300), QPoint(100, 200));
// flickable should not have moved
QCOMPARE(flickable->contentY(), 50.0);
@@ -1897,6 +1991,65 @@ void tst_qquickflickable::nestedMouseAreaUsingTouch()
QVERIFY(nested->y() < 100.0);
}
+void tst_qquickflickable::nestedSliderUsingTouch_data()
+{
+ QTest::addColumn<bool>("keepMouseGrab");
+ QTest::addColumn<bool>("keepTouchGrab");
+ QTest::addColumn<int>("updates");
+ QTest::addColumn<int>("releases");
+ QTest::addColumn<int>("ungrabs");
+
+ QTest::newRow("keepBoth") << true << true << 8 << 1 << 0;
+ QTest::newRow("keepMouse") << true << false << 8 << 1 << 0;
+ QTest::newRow("keepTouch") << false << true << 8 << 1 << 0;
+ QTest::newRow("keepNeither") << false << false << 6 << 0 << 1;
+}
+
+void tst_qquickflickable::nestedSliderUsingTouch()
+{
+ QFETCH(bool, keepMouseGrab);
+ QFETCH(bool, keepTouchGrab);
+ QFETCH(int, updates);
+ QFETCH(int, releases);
+ QFETCH(int, ungrabs);
+
+ QQuickView *window = new QQuickView;
+ QScopedPointer<QQuickView> windowPtr(window);
+ windowPtr->setSource(testFileUrl("nestedSlider.qml"));
+ QTRY_COMPARE(window->status(), QQuickView::Ready);
+ QQuickViewTestUtil::centerOnScreen(window);
+ QQuickViewTestUtil::moveMouseAway(window);
+ window->show();
+ QVERIFY(QTest::qWaitForWindowActive(window));
+ QVERIFY(window->rootObject() != 0);
+
+ QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
+ QVERIFY(flickable);
+
+ TouchDragArea *tda = flickable->findChild<TouchDragArea*>("drag");
+ QVERIFY(tda);
+
+ // Drag down and a little to the right: flickable will steal the grab only if tda allows it
+ const int dragThreshold = qApp->styleHints()->startDragDistance();
+ tda->setKeepMouseGrab(keepMouseGrab);
+ tda->setKeepTouchGrab(keepTouchGrab);
+ QPoint p0 = tda->mapToScene(QPoint(20, 20)).toPoint();
+ QTest::touchEvent(window, touchDevice).press(0, p0, window);
+ QQuickTouchUtils::flush(window);
+ for (int i = 0; i < 8; ++i) {
+ p0 += QPoint(dragThreshold / 6, dragThreshold / 4);
+ QTest::touchEvent(window, touchDevice).move(0, p0, window);
+ QQuickTouchUtils::flush(window);
+ }
+ QCOMPARE(tda->active(), !ungrabs);
+ QTest::touchEvent(window, touchDevice).release(0, p0, window);
+ QQuickTouchUtils::flush(window);
+ QCOMPARE(tda->touchPointStates.first(), Qt::TouchPointPressed);
+ QCOMPARE(tda->touchUpdates, updates);
+ QCOMPARE(tda->touchReleases, releases);
+ QCOMPARE(tda->ungrabs, ungrabs);
+}
+
// QTBUG-31328
void tst_qquickflickable::pressDelayWithLoader()
{
diff --git a/tests/auto/quick/qquickimage/tst_qquickimage.cpp b/tests/auto/quick/qquickimage/tst_qquickimage.cpp
index 2681f1a966..36d99ad48d 100644
--- a/tests/auto/quick/qquickimage/tst_qquickimage.cpp
+++ b/tests/auto/quick/qquickimage/tst_qquickimage.cpp
@@ -375,7 +375,7 @@ void tst_qquickimage::mirror()
}
QImage img = expected.toImage();
- QCOMPARE(screenshots[fillMode], img);
+ QCOMPARE(screenshots[fillMode].convertToFormat(img.format()), img);
}
}
diff --git a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp
index 5e8f762e23..bd051ec990 100644
--- a/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp
+++ b/tests/auto/quickwidgets/qquickwidget/tst_qquickwidget.cpp
@@ -58,6 +58,7 @@ private slots:
void grabBeforeShow();
void reparentToNewWindow();
void nullEngine();
+ void keyEvents();
};
@@ -337,6 +338,33 @@ void tst_qquickwidget::nullEngine()
QVERIFY(widget.engine());
}
+class KeyHandlingWidget : public QQuickWidget
+{
+public:
+ void keyPressEvent(QKeyEvent *e) override {
+ if (e->key() == Qt::Key_A)
+ ok = true;
+ }
+
+ bool ok = false;
+};
+
+void tst_qquickwidget::keyEvents()
+{
+ // A QQuickWidget should behave like a normal widget when it comes to event handling.
+ // Verify that key events actually reach the widget. (QTBUG-45757)
+ KeyHandlingWidget widget;
+ widget.setSource(testFileUrl("rectangle.qml"));
+ widget.show();
+ QVERIFY(QTest::qWaitForWindowExposed(widget.window(), 5000));
+
+ // Note: send the event to the QWindow, not the QWidget, in order
+ // to simulate the full event processing chain.
+ QTest::keyClick(widget.window()->windowHandle(), Qt::Key_A);
+
+ QTRY_VERIFY(widget.ok);
+}
+
QTEST_MAIN(tst_qquickwidget)
#include "tst_qquickwidget.moc"