diff options
Diffstat (limited to 'tests')
48 files changed, 2997 insertions, 22 deletions
diff --git a/tests/auto/qmltest/events/tst_touch.qml b/tests/auto/qmltest/events/tst_touch.qml index 5b209a6d0b..fd603e5a71 100644 --- a/tests/auto/qmltest/events/tst_touch.qml +++ b/tests/auto/qmltest/events/tst_touch.qml @@ -35,6 +35,16 @@ MultiPointTouchArea { width: 100 height: 100 + // touchUpdatedSpy stores the QQuickTouchPoint, and in some cases + // MultiPointTouchArea can delete it out from under us. + // (test_simpleChain was failing because touchUpdatedSpy.signalArguments[0][0][0] + // ended up as an empty object somehow.) If we declare + // all the touchpoints that this test will use, that won't happen. + touchPoints: [ + TouchPoint { }, + TouchPoint { } + ] + SignalSpy { id: touchUpdatedSpy target: touchArea diff --git a/tests/auto/quick/handlers/qquickdraghandler/data/reparenting.qml b/tests/auto/quick/handlers/qquickdraghandler/data/reparenting.qml new file mode 100644 index 0000000000..3545badd86 --- /dev/null +++ b/tests/auto/quick/handlers/qquickdraghandler/data/reparenting.qml @@ -0,0 +1,60 @@ +import QtQuick 2.8 +import Qt.labs.handlers 1.0 + +Grid { + id: root + objectName: "root" + property bool reparentOnDrag: true + width: 200; height: 200 + columns: 3 + spacing: 10 + Repeater { + model: 9 + anchors.fill: parent + Item { + id: gridPlaceholder + objectName: "gridPlaceholder" + index + width: 60 + height: 60 + Rectangle { + id: icon + border.color: "black" + color: "beige" + radius: 3 + width: 60 + height: 60 + onParentChanged :console.log("parent " + parent) + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + } + DragHandler { + id: dragArea + } + Text { + anchors.centerIn: parent + text: index + "@" + Math.round(icon.x) + "," + Math.round(icon.y) + font.pointSize: 8 + } + states: [ + State { + when: dragArea.dragging + AnchorChanges { + target: icon + anchors.horizontalCenter: undefined + anchors.verticalCenter: undefined + } + ParentChange { + target: root.reparentOnDrag ? icon : null + parent: root + } + PropertyChanges { + target: icon + color: "yellow" + } + } + ] + } + } + } +} diff --git a/tests/auto/quick/pointerhandlers/pointerhandlers.pro b/tests/auto/quick/pointerhandlers/pointerhandlers.pro new file mode 100644 index 0000000000..4a3f99765e --- /dev/null +++ b/tests/auto/quick/pointerhandlers/pointerhandlers.pro @@ -0,0 +1,7 @@ +TEMPLATE = subdirs + +qtConfig(private_tests) { + SUBDIRS += \ + qquickpointerhandler \ +} + diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/singleitem.qml b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/singleitem.qml new file mode 100644 index 0000000000..fe05a3f935 --- /dev/null +++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/data/singleitem.qml @@ -0,0 +1,22 @@ +import QtQuick 2.8 +import Qt.test 1.0 + +Rectangle { + id: root + width: 320 + height: 480 + color: "green" + + EventItem { + objectName: "eventItem1" + x: 5 + y: 5 + height: 30 + width: 30 + + EventHandler { + + } + } +} + diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/qquickpointerhandler.pro b/tests/auto/quick/pointerhandlers/qquickpointerhandler/qquickpointerhandler.pro new file mode 100644 index 0000000000..c386969206 --- /dev/null +++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/qquickpointerhandler.pro @@ -0,0 +1,16 @@ +CONFIG += testcase + +TARGET = tst_qquickpointerhandler +QT += core-private gui-private qml-private quick-private testlib + +macos:CONFIG -= app_bundle + +SOURCES += tst_qquickpointerhandler.cpp + +include (../../../shared/util.pri) +include (../../shared/util.pri) + +TESTDATA = data/* + +# OTHER_FILES += data/foo.qml + diff --git a/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp b/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp new file mode 100644 index 0000000000..d822330f21 --- /dev/null +++ b/tests/auto/quick/pointerhandlers/qquickpointerhandler/tst_qquickpointerhandler.cpp @@ -0,0 +1,471 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> + +#include <QtGui/qstylehints.h> + +#include <QtQuick/qquickview.h> +#include <QtQuick/qquickitem.h> +#include <QtQuick/private/qquickmousearea_p.h> +#include <QtQuick/private/qquickmultipointtoucharea_p.h> +#include <QtQuick/private/qquickpincharea_p.h> +#include <QtQuick/private/qquickflickable_p.h> +#include <QtQuick/private/qquickpointerhandler_p.h> +#include <qpa/qwindowsysteminterface.h> + +#include <private/qquickwindow_p.h> + +#include <QtQml/qqmlengine.h> +#include <QtQml/qqmlproperty.h> + +#include "../../../shared/util.h" +#include "../../shared/viewtestutil.h" + +Q_LOGGING_CATEGORY(lcPointerTests, "qt.quick.pointer.tests") + +struct Event +{ + Event(QEvent::Type t, QPointF item, QPointF scene) + :type(t), posWrtItem(item), posWrtScene(scene) + {} + + QEvent::Type type; + QPointF posWrtItem; + QPointF posWrtScene; + +}; + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug dbg, const struct Event &event) { + QDebugStateSaver saver(dbg); + dbg.nospace(); + dbg << "Event(" << event.type << " @" << event.posWrtScene << ")"; + return dbg; +} +#endif + +class EventItem : public QQuickItem +{ + Q_OBJECT +public: + EventItem(QQuickItem *parent = 0) + : QQuickItem(parent), acceptPointer(false), grabPointer(false), acceptMouse(false), acceptTouch(false), filterTouch(false) + {} + + void touchEvent(QTouchEvent *event) + { + qCDebug(lcPointerTests) << event << "will accept?" << acceptTouch; + for (const QTouchEvent::TouchPoint &tp : event->touchPoints()) + eventList.append(Event(event->type(), tp.pos(), tp.scenePos())); + event->setAccepted(acceptTouch); + } + void mousePressEvent(QMouseEvent *event) + { + qCDebug(lcPointerTests) << event; + eventList.append(Event(event->type(), event->pos(), event->windowPos())); + event->setAccepted(acceptMouse); + } + void mouseMoveEvent(QMouseEvent *event) + { + qCDebug(lcPointerTests) << event; + eventList.append(Event(event->type(), event->pos(), event->windowPos())); + event->setAccepted(acceptMouse); + } + void mouseReleaseEvent(QMouseEvent *event) + { + qCDebug(lcPointerTests) << event; + eventList.append(Event(event->type(), event->pos(), event->windowPos())); + event->setAccepted(acceptMouse); + } + void mouseDoubleClickEvent(QMouseEvent *event) + { + qCDebug(lcPointerTests) << event; + eventList.append(Event(event->type(), event->pos(), event->windowPos())); + event->setAccepted(acceptMouse); + } + + void mouseUngrabEvent() + { + qCDebug(lcPointerTests); + eventList.append(Event(QEvent::UngrabMouse, QPoint(0,0), QPoint(0,0))); + } + + bool event(QEvent *event) + { + qCDebug(lcPointerTests) << event; + return QQuickItem::event(event); + } + + QList<Event> eventList; + bool acceptPointer; + bool grabPointer; + bool acceptMouse; + bool acceptTouch; + bool filterTouch; // when used as event filter + + bool eventFilter(QObject *o, QEvent *event) + { + qCDebug(lcPointerTests) << event << o; + if (event->type() == QEvent::TouchBegin || + event->type() == QEvent::TouchUpdate || + event->type() == QEvent::TouchCancel || + event->type() == QEvent::TouchEnd) { + QTouchEvent *touch = static_cast<QTouchEvent*>(event); + for (const QTouchEvent::TouchPoint &tp : touch->touchPoints()) + eventList.append(Event(event->type(), tp.pos(), tp.scenePos())); + if (filterTouch) + event->accept(); + return true; + } + return false; + } +}; + +class EventHandler : public QQuickPointerHandler +{ + void handlePointerEventImpl(QQuickPointerEvent *event) override + { + QQuickPointerHandler::handlePointerEventImpl(event); + if (!enabled()) + return; + EventItem *item = static_cast<EventItem *>(target()); + qCDebug(lcPointerTests) << item->objectName() << event; + int c = event->pointCount(); + for (int i = 0; i < c; ++i) { + QQuickEventPoint *point = event->point(i); + if (item->acceptPointer) + point->setAccepted(item->acceptPointer); // does NOT imply a grab + if (item->grabPointer) + setExclusiveGrab(point, true); + qCDebug(lcPointerTests) << " " << i << ":" << point << "accepted?" << item->acceptPointer << "grabbed?" << (point->exclusiveGrabber() == this); + item->eventList.append(Event(QEvent::Pointer, eventPos(point), point->scenePos())); + } + } +}; + +class tst_PointerHandlers : public QQmlDataTest +{ + Q_OBJECT +public: + tst_PointerHandlers() + :touchDevice(QTest::createTouchDevice()) + {} + +private slots: + void initTestCase(); + + void touchEventDelivery(); + void mouseEventDelivery(); + +protected: + bool eventFilter(QObject *, QEvent *event) + { + if (event->type() == QEvent::MouseButtonPress || + event->type() == QEvent::MouseMove || + event->type() == QEvent::MouseButtonRelease) { + QMouseEvent *me = static_cast<QMouseEvent*>(event); + filteredEventList.append(Event(me->type(), me->pos(), me->globalPos())); + } + return false; + } + +private: + QQuickView *createView(); + QTouchDevice *touchDevice; + QList<Event> filteredEventList; +}; + +QQuickView *tst_PointerHandlers::createView() +{ + QQuickView *window = new QQuickView(0); + window->setGeometry(0,0,240,320); + + return window; +} + +void tst_PointerHandlers::initTestCase() +{ + // This test assumes that we don't get synthesized mouse events from QGuiApplication + qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, false); + + QQmlDataTest::initTestCase(); + qmlRegisterType<EventItem>("Qt.test", 1, 0, "EventItem"); + qmlRegisterType<EventHandler>("Qt.test", 1, 0, "EventHandler"); +} + +void tst_PointerHandlers::touchEventDelivery() +{ + QQuickView *window = createView(); + + window->setSource(testFileUrl("singleitem.qml")); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(window->rootObject() != 0); + + EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1"); + QVERIFY(eventItem1); + + // Do not accept anything + QPoint p1 = QPoint(20, 20); + QTest::touchEvent(window, touchDevice).press(0, p1, window); + QQuickTouchUtils::flush(window); + QTRY_COMPARE(eventItem1->eventList.size(), 3); + QCOMPARE(eventItem1->eventList.at(0).type, QEvent::Pointer); + QCOMPARE(eventItem1->eventList.at(1).type, QEvent::TouchBegin); + QCOMPARE(eventItem1->eventList.at(2).type, QEvent::MouseButtonPress); + p1 += QPoint(10, 0); + QTest::touchEvent(window, touchDevice).move(0, p1, window); + QQuickTouchUtils::flush(window); + QCOMPARE(eventItem1->eventList.size(), 4); + QCOMPARE(eventItem1->eventList.at(3).type, QEvent::Pointer); + QTest::touchEvent(window, touchDevice).release(0, p1, window); + QQuickTouchUtils::flush(window); + QCOMPARE(eventItem1->eventList.size(), 5); + QCOMPARE(eventItem1->eventList.at(4).type, QEvent::Pointer); + eventItem1->eventList.clear(); + + // Accept touch + eventItem1->acceptTouch = true; + p1 = QPoint(20, 20); + QTest::touchEvent(window, touchDevice).press(0, p1, window); + QQuickTouchUtils::flush(window); + QCOMPARE(eventItem1->eventList.size(), 2); + QCOMPARE(eventItem1->eventList.at(0).type, QEvent::Pointer); + QCOMPARE(eventItem1->eventList.at(1).type, QEvent::TouchBegin); + auto pointerEvent = QQuickPointerDevice::touchDevices().at(0)->pointerEvent(); + QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), eventItem1); + p1 += QPoint(10, 0); + QTest::touchEvent(window, touchDevice).move(0, p1, window); + QQuickTouchUtils::flush(window); + QCOMPARE(eventItem1->eventList.size(), 4); + QCOMPARE(eventItem1->eventList.at(2).type, QEvent::Pointer); + QCOMPARE(eventItem1->eventList.at(3).type, QEvent::TouchUpdate); + QTest::touchEvent(window, touchDevice).release(0, p1, window); + QQuickTouchUtils::flush(window); + QCOMPARE(eventItem1->eventList.size(), 6); + QCOMPARE(eventItem1->eventList.at(4).type, QEvent::Pointer); + QCOMPARE(eventItem1->eventList.at(5).type, QEvent::TouchEnd); + eventItem1->eventList.clear(); + + // wait to avoid getting a double click event + QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10); + + // Accept mouse + eventItem1->acceptTouch = false; + eventItem1->acceptMouse = true; + eventItem1->setAcceptedMouseButtons(Qt::LeftButton); + p1 = QPoint(20, 20); + QTest::touchEvent(window, touchDevice).press(0, p1, window); + QQuickTouchUtils::flush(window); + QCOMPARE(eventItem1->eventList.size(), 3); + QCOMPARE(eventItem1->eventList.at(0).type, QEvent::Pointer); + QCOMPARE(eventItem1->eventList.at(1).type, QEvent::TouchBegin); + QCOMPARE(eventItem1->eventList.at(2).type, QEvent::MouseButtonPress); + QCOMPARE(window->mouseGrabberItem(), eventItem1); + + QPointF localPos = eventItem1->mapFromScene(p1); + QPointF scenePos = p1; // item is at 0,0 + QCOMPARE(eventItem1->eventList.at(1).posWrtItem, localPos); + QCOMPARE(eventItem1->eventList.at(1).posWrtScene, scenePos); + QCOMPARE(eventItem1->eventList.at(2).posWrtItem, localPos); + QCOMPARE(eventItem1->eventList.at(2).posWrtScene, scenePos); + + p1 += QPoint(10, 0); + QTest::touchEvent(window, touchDevice).move(0, p1, window); + QQuickTouchUtils::flush(window); + QCOMPARE(eventItem1->eventList.size(), 6); + QCOMPARE(eventItem1->eventList.at(3).type, QEvent::Pointer); + QCOMPARE(eventItem1->eventList.at(4).type, QEvent::TouchUpdate); + QCOMPARE(eventItem1->eventList.at(5).type, QEvent::MouseMove); + QTest::touchEvent(window, touchDevice).release(0, p1, window); + QQuickTouchUtils::flush(window); + QCOMPARE(eventItem1->eventList.size(), 10); + QCOMPARE(eventItem1->eventList.at(6).type, QEvent::Pointer); + QCOMPARE(eventItem1->eventList.at(7).type, QEvent::TouchEnd); + QCOMPARE(eventItem1->eventList.at(8).type, QEvent::MouseButtonRelease); + QCOMPARE(eventItem1->eventList.at(9).type, QEvent::UngrabMouse); + eventItem1->eventList.clear(); + + // wait to avoid getting a double click event + QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10); + + // Accept mouse buttons but not the touch event + eventItem1->acceptTouch = false; + eventItem1->acceptMouse = false; + eventItem1->setAcceptedMouseButtons(Qt::LeftButton); + p1 = QPoint(20, 20); + QTest::touchEvent(window, touchDevice).press(0, p1, window); + QQuickTouchUtils::flush(window); + QCOMPARE(eventItem1->eventList.size(), 3); + QCOMPARE(eventItem1->eventList.at(0).type, QEvent::Pointer); + QCOMPARE(eventItem1->eventList.at(1).type, QEvent::TouchBegin); + QCOMPARE(eventItem1->eventList.at(2).type, QEvent::MouseButtonPress); + QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), nullptr); + p1 += QPoint(10, 0); + QTest::touchEvent(window, touchDevice).move(0, p1, window); + QQuickTouchUtils::flush(window); + QCOMPARE(eventItem1->eventList.size(), 4); + QTest::touchEvent(window, touchDevice).release(0, p1, window); + QQuickTouchUtils::flush(window); + QCOMPARE(eventItem1->eventList.size(), 5); + eventItem1->eventList.clear(); + + // wait to avoid getting a double click event + QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10); + + // Accept touch + eventItem1->acceptTouch = true; + eventItem1->setAcceptedMouseButtons(Qt::LeftButton); + p1 = QPoint(20, 20); + QTest::touchEvent(window, touchDevice).press(0, p1, window); + QQuickTouchUtils::flush(window); + QCOMPARE(eventItem1->eventList.size(), 2); + QCOMPARE(eventItem1->eventList.at(0).type, QEvent::Pointer); + QCOMPARE(eventItem1->eventList.at(1).type, QEvent::TouchBegin); + p1 += QPoint(10, 0); + QTest::touchEvent(window, touchDevice).move(0, p1, window); + QQuickTouchUtils::flush(window); + QCOMPARE(eventItem1->eventList.size(), 4); + QCOMPARE(eventItem1->eventList.at(2).type, QEvent::Pointer); + QCOMPARE(eventItem1->eventList.at(3).type, QEvent::TouchUpdate); + QTest::touchEvent(window, touchDevice).release(0, p1, window); + QQuickTouchUtils::flush(window); + QCOMPARE(eventItem1->eventList.size(), 6); + QCOMPARE(eventItem1->eventList.at(4).type, QEvent::Pointer); + QCOMPARE(eventItem1->eventList.at(5).type, QEvent::TouchEnd); + eventItem1->eventList.clear(); + + // Accept pointer events + eventItem1->acceptPointer = true; + eventItem1->grabPointer = true; + p1 = QPoint(20, 20); + QTest::touchEvent(window, touchDevice).press(0, p1, window); + QQuickTouchUtils::flush(window); + QCOMPARE(eventItem1->eventList.size(), 1); + QCOMPARE(eventItem1->eventList.at(0).type, QEvent::Pointer); + p1 += QPoint(10, 0); + QTest::touchEvent(window, touchDevice).move(0, p1, window); + QQuickTouchUtils::flush(window); + QCOMPARE(eventItem1->eventList.size(), 2); + QCOMPARE(eventItem1->eventList.at(1).type, QEvent::Pointer); + QTest::touchEvent(window, touchDevice).release(0, p1, window); + QQuickTouchUtils::flush(window); + QCOMPARE(eventItem1->eventList.size(), 3); + QCOMPARE(eventItem1->eventList.at(2).type, QEvent::Pointer); + eventItem1->eventList.clear(); + + delete window; +} + +void tst_PointerHandlers::mouseEventDelivery() +{ + QQuickView *window = createView(); + + window->setSource(testFileUrl("singleitem.qml")); + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(window)); + QVERIFY(window->rootObject() != 0); + + EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1"); + QVERIFY(eventItem1); + + // Do not accept anything + QPoint p1 = QPoint(20, 20); + QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1); + QCOMPARE(eventItem1->eventList.size(), 2); + p1 += QPoint(10, 0); + QTest::mouseMove(window, p1); + QCOMPARE(eventItem1->eventList.size(), 3); + QTest::mouseRelease(window, Qt::LeftButton); + QCOMPARE(eventItem1->eventList.size(), 3); + eventItem1->eventList.clear(); + + // wait to avoid getting a double click event + QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10); + + // Accept mouse + eventItem1->acceptTouch = false; + eventItem1->acceptMouse = true; + eventItem1->setAcceptedMouseButtons(Qt::LeftButton); + p1 = QPoint(20, 20); + QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1); + QCOMPARE(eventItem1->eventList.size(), 2); + QCOMPARE(eventItem1->eventList.at(0).type, QEvent::Pointer); + QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress); + QCOMPARE(window->mouseGrabberItem(), eventItem1); + + QPointF localPos = eventItem1->mapFromScene(p1); + QPointF scenePos = p1; // item is at 0,0 + QCOMPARE(eventItem1->eventList.at(0).posWrtItem, localPos); + QCOMPARE(eventItem1->eventList.at(0).posWrtScene, scenePos); + QCOMPARE(eventItem1->eventList.at(1).posWrtItem, localPos); + QCOMPARE(eventItem1->eventList.at(1).posWrtScene, scenePos); + + p1 += QPoint(10, 0); + QTest::mouseMove(window, p1); + QCOMPARE(eventItem1->eventList.size(), 3); + QCOMPARE(eventItem1->eventList.at(2).type, QEvent::MouseMove); + QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1); + QCOMPARE(eventItem1->eventList.size(), 5); + QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseButtonRelease); + QCOMPARE(eventItem1->eventList.at(4).type, QEvent::UngrabMouse); + eventItem1->eventList.clear(); + + // wait to avoid getting a double click event + QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10); + + // Grab pointer events + eventItem1->acceptMouse = false; + eventItem1->acceptPointer = true; + eventItem1->grabPointer = true; + p1 = QPoint(20, 20); + QTest::mousePress(window, Qt::LeftButton, Qt::NoModifier, p1); + QTRY_COMPARE(eventItem1->eventList.size(), 1); + QCOMPARE(eventItem1->eventList.at(0).type, QEvent::Pointer); + p1 += QPoint(10, 0); + QTest::mouseMove(window, p1); + QCOMPARE(eventItem1->eventList.size(), 2); + QCOMPARE(eventItem1->eventList.at(1).type, QEvent::Pointer); + QTest::mouseRelease(window, Qt::LeftButton, Qt::NoModifier, p1); + QCOMPARE(eventItem1->eventList.size(), 3); + QCOMPARE(eventItem1->eventList.at(2).type, QEvent::Pointer); + eventItem1->eventList.clear(); + + delete window; +} + +QTEST_MAIN(tst_PointerHandlers) + +#include "tst_qquickpointerhandler.moc" + diff --git a/tests/auto/quick/qquickflickable/data/nestedStopAtBounds.qml b/tests/auto/quick/qquickflickable/data/nestedStopAtBounds.qml index 81187f3c2f..902920babc 100644 --- a/tests/auto/quick/qquickflickable/data/nestedStopAtBounds.qml +++ b/tests/auto/quick/qquickflickable/data/nestedStopAtBounds.qml @@ -18,6 +18,8 @@ Flickable { height: 300 color: "yellow" + objectName: "yellowRect" + Flickable { id: inner objectName: "innerFlickable" @@ -30,6 +32,7 @@ Flickable { Rectangle { anchors.fill: parent anchors.margins: 100 + objectName: "blueRect" color: "blue" } MouseArea { diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp index cd503a88d4..578f737c4d 100644 --- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp +++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp @@ -46,6 +46,8 @@ #include <QOpenGLFunctions> #include <QSGRendererInterface> +Q_LOGGING_CATEGORY(lcTests, "qt.quick.tests") + struct TouchEventData { QEvent::Type type; QWidget *widget; @@ -139,7 +141,7 @@ class TestTouchItem : public QQuickRectangle public: TestTouchItem(QQuickItem *parent = 0) : QQuickRectangle(parent), acceptTouchEvents(true), acceptMouseEvents(true), - mousePressId(0), + mousePressCount(0), mouseMoveCount(0), spinLoopWhenPressed(false), touchEventCount(0) { border()->setWidth(1); @@ -158,9 +160,10 @@ public: lastMousePos = QPointF(); lastMouseCapabilityFlags = 0; touchEventCount = 0; + mouseMoveCount = 0; } - static void clearMousePressCounter() + static void clearMouseEventCounters() { mousePressNum = mouseMoveNum = mouseReleaseNum = 0; } @@ -173,7 +176,8 @@ public: bool acceptTouchEvents; bool acceptMouseEvents; TouchEventData lastEvent; - int mousePressId; + int mousePressCount; + int mouseMoveCount; bool spinLoopWhenPressed; int touchEventCount; QVector2D lastVelocity; @@ -203,7 +207,7 @@ public: e->ignore(); return; } - mousePressId = ++mousePressNum; + mousePressCount = ++mousePressNum; lastMousePos = e->pos(); lastMouseCapabilityFlags = QGuiApplicationPrivate::mouseEventCaps(e); } @@ -213,7 +217,7 @@ public: e->ignore(); return; } - ++mouseMoveNum; + mouseMoveCount = ++mouseMoveNum; lastVelocityFromMouseMove = QGuiApplicationPrivate::mouseEventVelocity(e); lastMouseCapabilityFlags = QGuiApplicationPrivate::mouseEventCaps(e); lastMousePos = e->pos(); @@ -229,10 +233,19 @@ public: lastMouseCapabilityFlags = QGuiApplicationPrivate::mouseEventCaps(e); } - bool childMouseEventFilter(QQuickItem *, QEvent *event) { - // TODO Is it a bug if a QTouchEvent comes here? - if (event->type() == QEvent::MouseButtonPress) - mousePressId = ++mousePressNum; + bool childMouseEventFilter(QQuickItem *item, QEvent *e) { + qCDebug(lcTests) << objectName() << "filtering" << e << "ahead of delivery to" << item->metaObject()->className() << item->objectName(); + switch (e->type()) { + case QEvent::MouseButtonPress: + mousePressCount = ++mousePressNum; + break; + case QEvent::MouseMove: + mouseMoveCount = ++mouseMoveNum; + break; + default: + break; + } + return false; } @@ -502,7 +515,7 @@ void tst_qquickwindow::constantUpdatesOnWindow() void tst_qquickwindow::touchEvent_basic() { - TestTouchItem::clearMousePressCounter(); + TestTouchItem::clearMouseEventCounters(); QQuickWindow *window = new QQuickWindow; QScopedPointer<QQuickWindow> cleanup(window); @@ -631,7 +644,7 @@ void tst_qquickwindow::touchEvent_basic() void tst_qquickwindow::touchEvent_propagation() { - TestTouchItem::clearMousePressCounter(); + TestTouchItem::clearMouseEventCounters(); QFETCH(bool, acceptTouchEvents); QFETCH(bool, acceptMouseEvents); @@ -778,7 +791,7 @@ void tst_qquickwindow::touchEvent_propagation_data() void tst_qquickwindow::touchEvent_cancel() { - TestTouchItem::clearMousePressCounter(); + TestTouchItem::clearMouseEventCounters(); QQuickWindow *window = new QQuickWindow; QScopedPointer<QQuickWindow> cleanup(window); @@ -812,7 +825,7 @@ void tst_qquickwindow::touchEvent_cancel() void tst_qquickwindow::touchEvent_reentrant() { - TestTouchItem::clearMousePressCounter(); + TestTouchItem::clearMouseEventCounters(); QQuickWindow *window = new QQuickWindow; QScopedPointer<QQuickWindow> cleanup(window); @@ -851,7 +864,7 @@ void tst_qquickwindow::touchEvent_reentrant() void tst_qquickwindow::touchEvent_velocity() { - TestTouchItem::clearMousePressCounter(); + TestTouchItem::clearMouseEventCounters(); QQuickWindow *window = new QQuickWindow; QScopedPointer<QQuickWindow> cleanup(window); @@ -977,7 +990,7 @@ void tst_qquickwindow::mouseFromTouch_basic() // should result in sending mouse events generated from the touch // with the new event propagation system. - TestTouchItem::clearMousePressCounter(); + TestTouchItem::clearMouseEventCounters(); QQuickWindow *window = new QQuickWindow; QScopedPointer<QQuickWindow> cleanup(window); window->resize(250, 250); @@ -1066,7 +1079,7 @@ void tst_qquickwindow::clearWindow() void tst_qquickwindow::mouseFiltering() { - TestTouchItem::clearMousePressCounter(); + TestTouchItem::clearMouseEventCounters(); QQuickWindow *window = new QQuickWindow; QScopedPointer<QQuickWindow> cleanup(window); @@ -1080,6 +1093,11 @@ void tst_qquickwindow::mouseFiltering() bottomItem->setObjectName("Bottom Item"); bottomItem->setSize(QSizeF(150, 150)); + TestTouchItem *siblingItem = new TestTouchItem(bottomItem); + siblingItem->setObjectName("Sibling of Middle Item"); + siblingItem->setPosition(QPointF(90, 25)); + siblingItem->setSize(QSizeF(150, 150)); + TestTouchItem *middleItem = new TestTouchItem(bottomItem); middleItem->setObjectName("Middle Item"); middleItem->setPosition(QPointF(50, 50)); @@ -1099,9 +1117,41 @@ void tst_qquickwindow::mouseFiltering() // 1. middleItem filters event // 2. bottomItem filters event // 3. topItem receives event - QTRY_COMPARE(middleItem->mousePressId, 1); - QTRY_COMPARE(bottomItem->mousePressId, 2); - QTRY_COMPARE(topItem->mousePressId, 3); + QTRY_COMPARE(middleItem->mousePressCount, 1); + QTRY_COMPARE(bottomItem->mousePressCount, 2); + QTRY_COMPARE(topItem->mousePressCount, 3); + QCOMPARE(siblingItem->mousePressCount, 0); + + QTest::mouseRelease(window, Qt::LeftButton, 0, pos); + topItem->clearMouseEventCounters(); + middleItem->clearMouseEventCounters(); + bottomItem->clearMouseEventCounters(); + siblingItem->clearMouseEventCounters(); + + // Repeat, but this time have the top item accept the press + topItem->acceptMouseEvents = true; + + QTest::mousePress(window, Qt::LeftButton, 0, pos); + + // Mouse filtering propagates down the stack, so the + // correct order is + // 1. middleItem filters event + // 2. bottomItem filters event + // 3. topItem receives event + QTRY_COMPARE(middleItem->mousePressCount, 1); + QTRY_COMPARE(bottomItem->mousePressCount, 2); + QTRY_COMPARE(topItem->mousePressCount, 3); + QCOMPARE(siblingItem->mousePressCount, 0); + + pos += QPoint(50, 50); + QTest::mouseMove(window, pos); + + // The top item has grabbed, so the move goes there, but again + // all the ancestors can filter, even when the mouse is outside their bounds + QTRY_COMPARE(middleItem->mouseMoveCount, 1); + QTRY_COMPARE(bottomItem->mouseMoveCount, 2); + QTRY_COMPARE(topItem->mouseMoveCount, 3); + QCOMPARE(siblingItem->mouseMoveCount, 0); // clean up mouse press state for the next tests QTest::mouseRelease(window, Qt::LeftButton, 0, pos); diff --git a/tests/auto/quick/quick.pro b/tests/auto/quick/quick.pro index 6e9998c061..93a938b5e7 100644 --- a/tests/auto/quick/quick.pro +++ b/tests/auto/quick/quick.pro @@ -47,6 +47,7 @@ PRIVATETESTS += \ !qtHaveModule(xmlpatterns): PRIVATETESTS -= qquickxmllistmodel QUICKTESTS = \ + pointerhandlers \ qquickaccessible \ qquickanchors \ qquickanimatedimage \ diff --git a/tests/auto/quick/touchmouse/BLACKLIST b/tests/auto/quick/touchmouse/BLACKLIST new file mode 100644 index 0000000000..ac0352d10b --- /dev/null +++ b/tests/auto/quick/touchmouse/BLACKLIST @@ -0,0 +1,3 @@ +# QTBUG-40856 hover regression on pointerhandler branch: TODO fix before merging to dev +[hoverEnabled] +* diff --git a/tests/auto/quick/touchmouse/tst_touchmouse.cpp b/tests/auto/quick/touchmouse/tst_touchmouse.cpp index 032e682137..b02d60d0c5 100644 --- a/tests/auto/quick/touchmouse/tst_touchmouse.cpp +++ b/tests/auto/quick/touchmouse/tst_touchmouse.cpp @@ -565,7 +565,7 @@ void tst_TouchMouse::buttonOnFlickable() QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window.data()); QVERIFY(windowPriv->touchMouseId != -1); auto pointerEvent = QQuickPointerDevice::touchDevices().at(0)->pointerEvent(); - QCOMPARE(pointerEvent->point(0)->grabber(), eventItem1); + QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), eventItem1); QCOMPARE(window->mouseGrabberItem(), eventItem1); p1 += QPoint(0, -10); @@ -586,7 +586,7 @@ void tst_TouchMouse::buttonOnFlickable() QCOMPARE(window->mouseGrabberItem(), flickable); QVERIFY(windowPriv->touchMouseId != -1); - QCOMPARE(pointerEvent->point(0)->grabber(), flickable); + QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), flickable); QVERIFY(flickable->isMovingVertically()); QTest::touchEvent(window.data(), device).release(0, p3, window.data()); @@ -691,7 +691,7 @@ void tst_TouchMouse::buttonOnDelayedPressFlickable() QCOMPARE(window->mouseGrabberItem(), flickable); QVERIFY(windowPriv->touchMouseId != -1); auto pointerEvent = QQuickPointerDevice::touchDevices().at(0)->pointerEvent(); - QCOMPARE(pointerEvent->point(0)->grabber(), flickable); + QCOMPARE(pointerEvent->point(0)->exclusiveGrabber(), flickable); QTest::touchEvent(window.data(), device).release(0, p3, window.data()); QQuickTouchUtils::flush(window.data()); diff --git a/tests/manual/pointer/content/FakeFlickable.qml b/tests/manual/pointer/content/FakeFlickable.qml new file mode 100644 index 0000000000..bfae653503 --- /dev/null +++ b/tests/manual/pointer/content/FakeFlickable.qml @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.8 +import Qt.labs.handlers 1.0 + +Item { + id: root + default property alias data: __contentItem.data + property alias velocity: anim.velocity + property alias contentX: __contentItem.x // sign is reversed compared to Flickable.contentX + property alias contentY: __contentItem.y // sign is reversed compared to Flickable.contentY + property alias contentWidth: __contentItem.width + property alias contentHeight: __contentItem.height + signal flickStarted + signal flickEnded + + Item { + id: __contentItem + objectName: "__contentItem" + width: childrenRect.width + height: childrenRect.height + + property real xlimit: root.width - __contentItem.width + property real ylimit: root.height - __contentItem.height + + function returnToBounds() { + if (x > 0) + x = 0 + else if (x < xlimit) + x = xlimit + if (y > 0) + y = 0 + else if (y < ylimit) + y = ylimit + } + + DragHandler { + id: dragHandler + onActiveChanged: if (!active) anim.restart(velocity) + } + MomentumAnimation { + id: anim + target: __contentItem + onStarted: root.flickStarted() + onStopped: { + __contentItem.returnToBounds() + root.flickEnded() + } + } + } +} diff --git a/tests/manual/pointer/content/FlashAnimation.qml b/tests/manual/pointer/content/FlashAnimation.qml new file mode 100644 index 0000000000..b628255a3d --- /dev/null +++ b/tests/manual/pointer/content/FlashAnimation.qml @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 + +SequentialAnimation { + id: tapFlash + running: false + PropertyAction { value: false } + PauseAnimation { duration: 100 } + PropertyAction { value: true } + PauseAnimation { duration: 100 } + PropertyAction { value: false } + PauseAnimation { duration: 100 } + PropertyAction { value: true } + PauseAnimation { duration: 100 } + PropertyAction { value: false } + PauseAnimation { duration: 100 } + PropertyAction { value: true } +} diff --git a/tests/manual/pointer/content/MomentumAnimation.qml b/tests/manual/pointer/content/MomentumAnimation.qml new file mode 100644 index 0000000000..abd9ac9269 --- /dev/null +++ b/tests/manual/pointer/content/MomentumAnimation.qml @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.8 + +ParallelAnimation { + id: root + property Item target: null + property int duration: 500 + property vector2d velocity: Qt.vector2d(0,0) + + function restart(vel) { + stop() + velocity = vel + start() + } + + NumberAnimation { + id: xAnim + target: root.target + property: "x" + to: target.x + velocity.x / duration * 100000 + duration: root.duration + easing.type: Easing.OutQuad + } + NumberAnimation { + id: yAnim + target: root.target + property: "y" + to: target.y + velocity.y / duration * 100000 + duration: root.duration + easing.type: Easing.OutQuad + } +} diff --git a/tests/manual/pointer/content/MouseAreaButton.qml b/tests/manual/pointer/content/MouseAreaButton.qml new file mode 100644 index 0000000000..de1d972386 --- /dev/null +++ b/tests/manual/pointer/content/MouseAreaButton.qml @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.1 +import QtQuick.Window 2.1 + +Item { + id: container + + property alias text: buttonLabel.text + property alias label: buttonLabel + signal clicked + property alias containsMouse: mouseArea.containsMouse + property alias pressed: mouseArea.pressed + implicitHeight: Math.max(Screen.pixelDensity * 7, buttonLabel.implicitHeight * 1.2) + implicitWidth: Math.max(Screen.pixelDensity * 11, buttonLabel.implicitWidth * 1.3) + height: implicitHeight + width: implicitWidth + + SystemPalette { id: palette } + + Rectangle { + id: frame + anchors.fill: parent + color: palette.button + gradient: Gradient { + GradientStop { position: 0.0; color: mouseArea.pressed ? Qt.darker(palette.button, 1.3) : palette.button } + GradientStop { position: 1.0; color: Qt.darker(palette.button, 1.3) } + } + antialiasing: true + radius: height / 6 + border.color: Qt.darker(palette.button, 1.5) + border.width: 1 + } + + MouseArea { + id: mouseArea + anchors.fill: parent + onClicked: container.clicked() + hoverEnabled: true + } + + Text { + id: buttonLabel + text: container.text + color: palette.buttonText + anchors.centerIn: parent + } +} diff --git a/tests/manual/pointer/content/MouseAreaSlider.qml b/tests/manual/pointer/content/MouseAreaSlider.qml new file mode 100644 index 0000000000..c34c528c7d --- /dev/null +++ b/tests/manual/pointer/content/MouseAreaSlider.qml @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.7 + +Item { + id: root + property int value: 50 + property int maximumValue: 99 + property alias label: label.text + + Rectangle { + id: slot + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.margins: 10 + anchors.topMargin: 30 + anchors.bottomMargin: 30 + anchors.horizontalCenter: parent.horizontalCenter + width: 10 + color: "black" + radius: width / 2 + smooth: true + } + + Rectangle { + // RectangularGlow is better, but that's a different module + id: glow + anchors.fill: knob + anchors.margins: -5 + anchors.leftMargin: -2 + anchors.horizontalCenterOffset: 1 + radius: 5 + color: "#4400FFFF" + opacity: ma.pressed ? 1 : 0 + } + Image { + id: knob + source: "../resources/mixer-knob.png" + antialiasing: true + x: slot.x - width / 2 + slot.width / 2 + height: root.width / 2 + width: implicitWidth / implicitHeight * height + property bool programmatic: false + property real multiplier: root.maximumValue / (ma.drag.maximumY - ma.drag.minimumY) + onYChanged: if (!programmatic) root.value = root.maximumValue - (knob.y - ma.drag.minimumY) * multiplier + transformOrigin: Item.Center + function setValue(value) { knob.y = ma.drag.maximumY - value / knob.multiplier } + MouseArea { + id: ma + anchors.fill: parent + drag.target: parent + drag.minimumX: knob.x + drag.maximumX: knob.x + drag.minimumY: slot.y + drag.maximumY: slot.height + slot.y - knob.height + } + } + + Text { + font.pointSize: 16 + color: "red" + anchors.bottom: parent.bottom + anchors.horizontalCenter: parent.horizontalCenter + text: root.value + } + + Text { + id: label + font.pointSize: 12 + color: "red" + anchors.top: parent.top + anchors.topMargin: 5 + anchors.horizontalCenter: parent.horizontalCenter + } + + onHeightChanged: { + knob.programmatic = true + knob.setValue(root.value) + knob.programmatic = false + } +} diff --git a/tests/manual/pointer/content/MptaButton.qml b/tests/manual/pointer/content/MptaButton.qml new file mode 100644 index 0000000000..836744822b --- /dev/null +++ b/tests/manual/pointer/content/MptaButton.qml @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.7 +import QtQuick.Window 2.1 + +Item { + id: container + + property alias text: buttonLabel.text + property alias label: buttonLabel + signal clicked + property alias pressed: point.pressed + implicitHeight: Math.max(Screen.pixelDensity * 7, buttonLabel.implicitHeight * 1.2) + implicitWidth: Math.max(Screen.pixelDensity * 11, buttonLabel.implicitWidth * 1.3) + height: implicitHeight + width: implicitWidth + + SystemPalette { id: palette } + + Rectangle { + id: frame + anchors.fill: parent + color: palette.button + gradient: Gradient { + GradientStop { position: 0.0; color: container.pressed ? Qt.darker(palette.button, 1.3) : palette.button } + GradientStop { position: 1.0; color: Qt.darker(palette.button, 1.3) } + } + antialiasing: true + radius: height / 6 + border.color: Qt.darker(palette.button, 1.5) + border.width: 1 + } + + MultiPointTouchArea { + id: mpta + anchors.fill: parent + touchPoints: [ TouchPoint { + id: point + onPressedChanged: if (!pressed) container.clicked() + } ] + } + + Text { + id: buttonLabel + text: container.text + color: palette.buttonText + anchors.centerIn: parent + } +} diff --git a/tests/manual/pointer/content/MultiButton.qml b/tests/manual/pointer/content/MultiButton.qml new file mode 100644 index 0000000000..5b31e9ebd0 --- /dev/null +++ b/tests/manual/pointer/content/MultiButton.qml @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.8 +import Qt.labs.handlers 1.0 + +Rectangle { + id: root + property alias label: label.text + property alias pressed: tap.isPressed + property bool checked: false + property alias gesturePolicy: tap.gesturePolicy + signal tapped + + width: label.implicitWidth * 1.5; height: label.implicitHeight * 2.0 + border.color: "#9f9d9a"; border.width: 1; radius: height / 4; antialiasing: true + + gradient: Gradient { + GradientStop { position: 0.0; color: tap.isPressed ? "#b8b5b2" : "#efebe7" } + GradientStop { position: 1.0; color: "#b8b5b2" } + } + + TapHandler { + id: tap + objectName: label.text + onTapped: { + tapFlash.start() + root.tapped + } + } + + Text { + id: label + font.pointSize: 14 + text: "Button" + anchors.centerIn: parent + } + + Rectangle { + anchors.fill: parent + color: "transparent" + border.width: 2; radius: root.radius; antialiasing: true + opacity: tapFlash.running ? 1 : 0 + FlashAnimation on visible { + id: tapFlash + } + } +} diff --git a/tests/manual/pointer/content/Slider.qml b/tests/manual/pointer/content/Slider.qml new file mode 100644 index 0000000000..a1decf8c4b --- /dev/null +++ b/tests/manual/pointer/content/Slider.qml @@ -0,0 +1,132 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.8 +import Qt.labs.handlers 1.0 + +Item { + id: root + property int value: 50 + property int maximumValue: 99 + property alias label: label.text + property alias tapEnabled: tap.enabled + property alias pressed: tap.isPressed + signal tapped + + Rectangle { + id: slot + anchors.top: parent.top + anchors.bottom: parent.bottom + anchors.margins: 10 + anchors.topMargin: 30 + anchors.bottomMargin: 30 + anchors.horizontalCenter: parent.horizontalCenter + width: 10 + color: "black" + radius: width / 2 + smooth: true + } + + Rectangle { + // RectangularGlow is better, but that's a different module + id: glow + anchors.fill: knob + anchors.margins: -5 + anchors.leftMargin: -2 + anchors.horizontalCenterOffset: 1 + radius: 5 + color: "#4400FFFF" + opacity: dragHandler.active || tapFlash.running ? 1 : 0 + FlashAnimation on visible { + id: tapFlash + } + } + Image { + id: knob + source: "../resources/mixer-knob.png" + antialiasing: true + x: slot.x - width / 2 + slot.width / 2 + height: root.width / 2 + width: implicitWidth / implicitHeight * height + property bool programmatic: false + property real multiplier: root.maximumValue / (dragHandler.yAxis.maximum - dragHandler.yAxis.minimum) + onYChanged: if (!programmatic) root.value = root.maximumValue - (knob.y - dragHandler.yAxis.minimum) * multiplier + transformOrigin: Item.Center + function setValue(value) { knob.y = dragHandler.yAxis.maximum - value / knob.multiplier } + DragHandler { + id: dragHandler + xAxis.enabled: false + yAxis.minimum: slot.y + yAxis.maximum: slot.height + slot.y - knob.height + } + TapHandler { + id: tap + objectName: label.text + gesturePolicy: TapHandler.DragThreshold + onTapped: { + tapFlash.start() + root.tapped + } + } + } + + Text { + font.pointSize: 16 + color: "red" + anchors.bottom: parent.bottom + anchors.horizontalCenter: parent.horizontalCenter + text: root.value + } + + Text { + id: label + font.pointSize: 12 + color: "red" + anchors.top: parent.top + anchors.topMargin: 5 + anchors.horizontalCenter: parent.horizontalCenter + } + + onHeightChanged: { + knob.programmatic = true + knob.setValue(root.value) + knob.programmatic = false + } +} diff --git a/tests/manual/pointer/content/TapHandlerButton.qml b/tests/manual/pointer/content/TapHandlerButton.qml new file mode 100644 index 0000000000..e40c539686 --- /dev/null +++ b/tests/manual/pointer/content/TapHandlerButton.qml @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.7 +import QtQuick.Window 2.1 +import Qt.labs.handlers 1.0 + +Item { + id: container + + property alias text: buttonLabel.text + property alias label: buttonLabel + signal clicked + property alias pressed: th.isPressed + implicitHeight: Math.max(Screen.pixelDensity * 7, buttonLabel.implicitHeight * 1.2) + implicitWidth: Math.max(Screen.pixelDensity * 11, buttonLabel.implicitWidth * 1.3) + height: implicitHeight + width: implicitWidth + + SystemPalette { id: palette } + + Rectangle { + id: frame + anchors.fill: parent + color: palette.button + gradient: Gradient { + GradientStop { position: 0.0; color: container.pressed ? Qt.darker(palette.button, 1.3) : palette.button } + GradientStop { position: 1.0; color: Qt.darker(palette.button, 1.3) } + } + antialiasing: true + radius: height / 6 + border.color: Qt.darker(palette.button, 1.5) + border.width: 1 + } + + TapHandler { + id: th + onTapped: container.clicked() + } + + Text { + id: buttonLabel + text: container.text + color: palette.buttonText + anchors.centerIn: parent + } +} diff --git a/tests/manual/pointer/fakeFlickable.qml b/tests/manual/pointer/fakeFlickable.qml new file mode 100644 index 0000000000..31e3d9f74c --- /dev/null +++ b/tests/manual/pointer/fakeFlickable.qml @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.8 +import Qt.labs.handlers 1.0 +import "content" + +Rectangle { + color: "#444" + width: 480 + height: 480 + + FakeFlickable { + anchors.fill: parent + Row { + Item { + width: 100 + height: 400 + Slider { + id: slider + label: "font size" + anchors.fill: parent + maximumValue: 36 + value: 14 + } + } + Text { + id: text + color: "beige" + font.family: "mono" + font.pointSize: slider.value + onTextChanged: console.log("text geom " + width + "x" + height + + ", parent " + parent + " geom " + parent.width + "x" + parent.height) + } + } + + + onFlickStarted: console.log("flick started with velocity " + velocity) + onFlickEnded: console.log("flick ended") + + Component.onCompleted: { + var request = new XMLHttpRequest() + request.open('GET', 'content/FakeFlickable.qml') + request.onreadystatechange = function(event) { + if (request.readyState === XMLHttpRequest.DONE) + text.text = request.responseText + } + request.send() + } + } +} diff --git a/tests/manual/pointer/flickableWithHandlers.qml b/tests/manual/pointer/flickableWithHandlers.qml new file mode 100644 index 0000000000..8225012591 --- /dev/null +++ b/tests/manual/pointer/flickableWithHandlers.qml @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.7 +import Qt.labs.handlers 1.0 +import "qrc:/quick/shared/" as Examples +import "content" + +Rectangle { + id: root + width: 400 + height: 400 + objectName: "root" + color: "#222222" + + Flickable { + anchors.fill: parent + anchors.margins: 10 + anchors.topMargin: 40 + contentHeight: 600 + contentWidth: 600 + pressDelay: pressDelayCB.checked ? 1000 : 0 + + Column { + spacing: 6 + Rectangle { + radius: 5 + width: parent.width - 12 + height: pressDelayCB.implicitHeight + 12 + x: 6 + color: "lightgray" + Examples.CheckBox { + x: 6; y: 6 + id: pressDelayCB + text: "press delay" + } + } + + + Row { + spacing: 6 + Slider { + label: "DragHandler" + value: 49; width: 100; height: 400 + } + MouseAreaSlider { + label: "MouseArea" + value: 49; width: 100; height: 400 + } + Column { + spacing: 6 + MouseAreaButton { + text: "MouseArea" + } + MptaButton { + text: "MultiPointTouchArea" + } + MptaButton { + text: "MultiPointTouchArea" + } + TapHandlerButton { + text: "TapHandler" + } + TapHandlerButton { + text: "TapHandler" + } + } + } + } + } +} diff --git a/tests/manual/pointer/flingAnimation.qml b/tests/manual/pointer/flingAnimation.qml new file mode 100644 index 0000000000..11b97dbb31 --- /dev/null +++ b/tests/manual/pointer/flingAnimation.qml @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.8 +import Qt.labs.handlers 1.0 +import "content" + +Rectangle { + id: root + width: 640 + height: 480 + color: "black" + + Repeater { + model: 2 + + Image { + id: ball + objectName: "ball" + index + source: "resources/redball.png" + width: 80; height: 80; x: 200 + index * 200; y: 200 + + Text { + anchors.centerIn: parent + color: "white" + text: anim.velocity.x.toFixed(2) + "," + anim.velocity.y.toFixed(2) + } + + MomentumAnimation { id: anim; target: ball } + + DragHandler { + id: dragHandler + onActiveChanged: { + if (!active) + anim.restart(velocity) + } + } + Rectangle { + visible: dragHandler.active + anchors.fill: parent + anchors.margins: -5 + radius: width / 2 + opacity: 0.25 + } + } + } +} diff --git a/tests/manual/pointer/joystick.qml b/tests/manual/pointer/joystick.qml new file mode 100644 index 0000000000..bcc4564471 --- /dev/null +++ b/tests/manual/pointer/joystick.qml @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.8 +import Qt.labs.handlers 1.0 + +Rectangle { + width: 480 + height: 480 + color: "black" + + Image { + id: knob + source: "resources/redball.png" + anchors { + horizontalCenter: parent.horizontalCenter + verticalCenter: parent.verticalCenter + } + DragHandler { + id: dragHandler + } + states: [ + State { + when: dragHandler.active + AnchorChanges { + target: knob + anchors.horizontalCenter: undefined + anchors.verticalCenter: undefined + } + } + ] + transitions: [ + Transition { + AnchorAnimation { easing.type: Easing.OutElastic } + } + ] + } +} diff --git a/tests/manual/pointer/main.cpp b/tests/manual/pointer/main.cpp new file mode 100644 index 0000000000..7935b4072c --- /dev/null +++ b/tests/manual/pointer/main.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QGuiApplication> +#include <QQmlApplicationEngine> +#include <QQuickItem> +#include <QQuickWindow> + +int main(int argc, char *argv[]) +{ + QGuiApplication app(argc, argv); + + QQmlApplicationEngine engine; + engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); + if (!app.arguments().isEmpty()) { + QQuickWindow * win = static_cast<QQuickWindow *>(engine.rootObjects().first()); + auto lastArg = app.arguments().last(); + if (lastArg.endsWith(QLatin1String(".qml"))) { + auto root = win->findChild<QQuickItem *>("LauncherList"); + int showExampleIdx = -1; + for (int i = root->metaObject()->methodCount(); showExampleIdx < 0 && i >= 0; --i) + if (root->metaObject()->method(i).name() == QByteArray("showExample")) + showExampleIdx = i; + QMetaMethod showExampleFn = root->metaObject()->method(showExampleIdx); + showExampleFn.invoke(root, Q_ARG(QVariant, QVariant(QLatin1String("../../") + lastArg))); + } + } + + return app.exec(); +} diff --git a/tests/manual/pointer/main.qml b/tests/manual/pointer/main.qml new file mode 100644 index 0000000000..df34c7d4a3 --- /dev/null +++ b/tests/manual/pointer/main.qml @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.8 +import QtQuick.Window 2.2 +import "qrc:/quick/shared/" as Examples + +Window { + width: 800 + height: 600 + visible: true + Examples.LauncherList { + id: ll + objectName: "LauncherList" + anchors.fill: parent + Component.onCompleted: { + addExample("single point handler", "QQuickPointerSingleHandler: test properties copied from events", Qt.resolvedUrl("singlePointHandlerProperties.qml")) + addExample("joystick", "DragHandler: move one item inside another with any pointing device", Qt.resolvedUrl("joystick.qml")) + addExample("mixer", "mixing console", Qt.resolvedUrl("mixer.qml")) + addExample("pinch", "PinchHandler: scale, rotate and drag", Qt.resolvedUrl("pinchHandler.qml")) + addExample("map", "scale and pan", Qt.resolvedUrl("map.qml")) + addExample("custom map", "scale and pan", Qt.resolvedUrl("map2.qml")) + addExample("fling animation", "DragHandler: after dragging, use an animation to simulate momentum", Qt.resolvedUrl("flingAnimation.qml")) + addExample("fake Flickable", "implementation of a simplified Flickable using only Items, DragHandler and MomentumAnimation", Qt.resolvedUrl("fakeFlickable.qml")) + addExample("photo surface", "re-implementation of the existing photo surface demo using Handlers", Qt.resolvedUrl("photosurface.qml")) + addExample("tap", "TapHandler: device-agnostic tap/click detection for buttons", Qt.resolvedUrl("tapHandler.qml")) + addExample("multibuttons", "TapHandler: gesturePolicy (99 red balloons)", Qt.resolvedUrl("multibuttons.qml")) + addExample("flickable with Handlers", "Flickable with buttons, sliders etc. implemented in various ways", Qt.resolvedUrl("flickableWithHandlers.qml")) + } + } +} diff --git a/tests/manual/pointer/map.qml b/tests/manual/pointer/map.qml new file mode 100644 index 0000000000..e1ca889064 --- /dev/null +++ b/tests/manual/pointer/map.qml @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.8 +import Qt.labs.handlers 1.0 + +Item { + width: 640 + height: 480 + + Rectangle { + id: map + color: "aqua" + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + width: image.implicitWidth + height: image.implicitHeight + + Image { + id: image + anchors.centerIn: parent + fillMode: Image.PreserveAspectFit + source: "resources/map.svgz" + } + } + + PinchHandler { + id: pinch + target: map + minimumScale: 0.1 + maximumScale: 10 + } + + DragHandler { + target: map + } +} diff --git a/tests/manual/pointer/map2.qml b/tests/manual/pointer/map2.qml new file mode 100644 index 0000000000..fcd144bd7f --- /dev/null +++ b/tests/manual/pointer/map2.qml @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.8 +import Qt.labs.handlers 1.0 + +Item { + width: 640 + height: 480 + + Rectangle { + id: map + color: "aqua" + x: (parent.width - width) / 2 + y: (parent.height - height) / 2 + width: image.implicitWidth + height: image.implicitHeight + property point center : Qt.point(x + map.width/2, y + map.height/2) + + function setCenter(xx, yy) { + map.x = xx - map.width/2 + map.y = yy - map.height/2 + } + + + Image { + id: image + anchors.centerIn: parent + fillMode: Image.PreserveAspectFit + source: "resources/map.svgz" + } + } + + PinchHandler { + id: pinch + target: map + minimumScale: 0.1 + maximumScale: 10 + } + + DragHandler { + property point startDrag + target: null + onActiveChanged: { + if (active) + startDrag = map.center + } + + onTranslationChanged: { + if (!target) + map.setCenter(startDrag.x + translation.x, startDrag.y + translation.y) + } + } +} diff --git a/tests/manual/pointer/mixer.qml b/tests/manual/pointer/mixer.qml new file mode 100644 index 0000000000..84ad975340 --- /dev/null +++ b/tests/manual/pointer/mixer.qml @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.8 +import Qt.labs.handlers 1.0 +import "content" + +Rectangle { + id: root + width: 1280 + height: 960 + objectName: "root" + color: "#222222" + + ListView { + id: list + objectName: "listView" + anchors.fill: parent + anchors.margins: 10 + orientation: Qt.Horizontal + + model: 20 + + delegate: Item { + objectName: "delegateItem" + index + width: 154 + height: list.height + + Slider { + anchors.fill: parent + label: "Channel " + (index + 1) + } + } + } +} diff --git a/tests/manual/pointer/multibuttons.qml b/tests/manual/pointer/multibuttons.qml new file mode 100644 index 0000000000..16d2f191e7 --- /dev/null +++ b/tests/manual/pointer/multibuttons.qml @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.0 +import QtQuick.Particles 2.0 +import QtQuick.Layouts 1.0 +import Qt.labs.handlers 1.0 +import "content" + +Item { + width: 800 + height: 800 + ColumnLayout { + anchors.right: parent.right + spacing: 20 + Text { text: "protagonist"; font.pointSize: 12 } + MultiButton { + id: balloonsButton + label: "Launch Balloons" + Layout.fillWidth: true + gesturePolicy: TapHandler.DragThreshold + } + Text { text: "the goons"; font.pointSize: 12 } + MultiButton { + id: missilesButton + label: "Launch Missiles" + Layout.fillWidth: true + gesturePolicy: TapHandler.WithinBounds + } + MultiButton { + id: fightersButton + label: "Launch Fighters" + Layout.fillWidth: true + gesturePolicy: TapHandler.ReleaseWithinBounds + } + } + ParticleSystem { + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.leftMargin: 150 + ImageParticle { source: "resources/balloon.png" } + Emitter { anchors.bottom: parent.bottom; enabled: balloonsButton.pressed; lifeSpan: 5000; size: 64 + maximumEmitted: 99 + emitRate: 50; velocity: PointDirection { x: 10; y: -150; yVariation: 30; xVariation: 50 } } } + ParticleSystem { + anchors.verticalCenter: parent.verticalCenter + anchors.right: parent.right + ImageParticle { source: "resources/fighter.png" } + Emitter { anchors.bottom: parent.bottom; enabled: fightersButton.pressed; lifeSpan: 15000; size: 204 + emitRate: 3; velocity: PointDirection { x: -1000; y: -250; yVariation: 150; xVariation: 50 } } } + ParticleSystem { + anchors.bottom: parent.bottom + anchors.right: parent.right + anchors.rightMargin: 100 + ImageParticle { source: "resources/missile.png"; autoRotation: true; rotation: 90 } + Emitter { anchors.bottom: parent.bottom; enabled: missilesButton.pressed; lifeSpan: 5000; size: 128 + emitRate: 10; velocity: PointDirection { x: -200; y: -350; yVariation: 200; xVariation: 100 } } } +} diff --git a/tests/manual/pointer/photosurface.qml b/tests/manual/pointer/photosurface.qml new file mode 100644 index 0000000000..6601909a37 --- /dev/null +++ b/tests/manual/pointer/photosurface.qml @@ -0,0 +1,175 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.8 +import QtQuick.Dialogs 1.0 +import Qt.labs.folderlistmodel 1.0 +import Qt.labs.handlers 1.0 +import "content" + +Rectangle { + id: root + visible: true + width: 1024; height: 600 + color: "black" + property int highestZ: 0 + property real defaultSize: 200 + property real surfaceViewportRatio: 1.5 + + FileDialog { + id: fileDialog + title: "Choose a folder with some images" + selectFolder: true + onAccepted: folderModel.folder = fileUrl + "/" + } + Shortcut { + id: openShortcut + sequence: StandardKey.Open + onActivated: fileDialog.open() + } + + FakeFlickable { + id: flick + anchors.fill: parent + contentWidth: width * 2 + contentHeight: height * 2 + Repeater { + model: FolderListModel { + id: folderModel + folder: "resources/" + objectName: "folderModel" + showDirs: false + nameFilters: ["*.png", "*.jpg", "*.gif"] + } + Rectangle { + id: photoFrame + objectName: "frame-" + fileName + width: image.width * (1 + 0.10 * image.height / image.width) + height: image.height * 1.10 + scale: defaultSize / Math.max(image.sourceSize.width, image.sourceSize.height) + Behavior on scale { NumberAnimation { duration: 200 } } + Behavior on x { NumberAnimation { duration: 200 } } + Behavior on y { NumberAnimation { duration: 200 } } + border.color: pinchHandler.active || dragHandler.active ? "red" : "black" + border.width: 2 + smooth: true + antialiasing: true + Component.onCompleted: { + x = Math.random() * root.width - width / 2 + y = Math.random() * root.height - height / 2 + rotation = Math.random() * 13 - 6 + } + Image { + id: image + anchors.centerIn: parent + fillMode: Image.PreserveAspectFit + source: folderModel.folder + fileName + antialiasing: true + } + + MomentumAnimation { id: anim; target: photoFrame } + + DragHandler { + id: dragHandler + onActiveChanged: { + if (!active) + anim.restart(velocity) + } + } + + PinchHandler { + id: pinchHandler + minimumRotation: -360 + maximumRotation: 360 + minimumScale: 0.1 + maximumScale: 10 + property real zRestore: 0 + } + } + } + } + + Rectangle { + id: verticalScrollDecorator + anchors.right: parent.right + anchors.margins: 2 + color: "cyan" + border.color: "black" + border.width: 1 + width: 5 + radius: 2 + antialiasing: true + height: flick.height * (flick.height / flick.contentHeight) - (width - anchors.margins) * 2 + y: -flick.contentY * (flick.height / flick.contentHeight) + NumberAnimation on opacity { id: vfade; to: 0; duration: 500 } + onYChanged: { opacity = 1.0; fadeTimer.restart() } + } + + Rectangle { + id: horizontalScrollDecorator + anchors.bottom: parent.bottom + anchors.margins: 2 + color: "cyan" + border.color: "black" + border.width: 1 + height: 5 + radius: 2 + antialiasing: true + width: flick.width * (flick.width / flick.contentWidth) - (height - anchors.margins) * 2 + x: -flick.contentX * (flick.width / flick.contentWidth) + NumberAnimation on opacity { id: hfade; to: 0; duration: 500 } + onXChanged: { opacity = 1.0; fadeTimer.restart() } + } + + Timer { id: fadeTimer; interval: 1000; onTriggered: { hfade.start(); vfade.start() } } + + Text { + anchors.bottom: parent.bottom + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: 10 + color: "darkgrey" + wrapMode: Text.WordWrap + font.pointSize: 8 + text: "Press " + openShortcut.nativeText + " to choose a different image folder\n" + + "On a touchscreen: use two fingers to zoom and rotate, one finger to drag\n" + + "With a mouse: drag normally" + } +} diff --git a/tests/manual/pointer/pinchHandler.qml b/tests/manual/pointer/pinchHandler.qml new file mode 100644 index 0000000000..f317f361e2 --- /dev/null +++ b/tests/manual/pointer/pinchHandler.qml @@ -0,0 +1,130 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.8 +import Qt.labs.handlers 1.0 + +Rectangle { + width: 1024; height: 600 + color: "#eee" + + function getTransformationDetails(item, pinchhandler) { + return "\n\npinch.scale:" + pinchhandler.scale.toFixed(2) + + "\npinch.rotation:" + pinchhandler.rotation.toFixed(2) + + "\npinch.translation:" + "(" + pinchhandler.translation.x.toFixed(2) + "," + pinchhandler.translation.y.toFixed(2) + ")" + + "\nrect.scale: " + item.scale.toFixed(2) + + "\nrect.rotation: " + item.rotation.toFixed(2) + + "\nrect.position: " + "(" + item.x.toFixed(2) + "," + item.y.toFixed(2) + ")" + } + + Rectangle { + // Purpose of this item is just to make sure the rectangles are transformed into + // a coordinate system that is different from the scene coordinate system. + anchors.fill: parent + anchors.margins: 50 + color: "#ffe0e0e0" + + Rectangle { + id: rect2 + width: 400 + height: 300 + color: "lightsteelblue" + antialiasing: true + x: 100 + y: 200 + rotation: 30 + transformOrigin: Item.TopRight + + Text { + anchors.centerIn: parent + text: "Pinch with 2 fingers to scale, rotate and translate" + + getTransformationDetails(rect2, pinch2) + } + + PinchHandler { + id: pinch2 + objectName: "2-finger pinch" + minimumRotation: -45 + maximumRotation: 45 + minimumScale: 0.5 + maximumScale: 3 + minimumX: 0 + maximumX: 600 + pointDistanceThreshold: 0 + } + } + + Rectangle { + id: rect3 + x: 500 + width: 400 + height: 300 + color: "wheat" + antialiasing: true + + Text { + anchors.centerIn: parent + text: "Pinch with 3 fingers to scale, rotate and translate\nDrag with 1 finger" + + getTransformationDetails(rect3, pinch3) + } + DragHandler { objectName: "DragHandler" } + + PinchHandler { + id: pinch3 + objectName: "3-finger pinch" + requiredPointCount: 3 + minimumScale: 0.1 + maximumScale: 10 + } + } + } + Rectangle { + id: centroidIndicator + property QtObject pincher: pinch2.active ? pinch2 : pinch3 + x: pincher.centroid.x - radius + y: pincher.centroid.y - radius + z: 1 + visible: pincher.active + radius: width / 2 + width: 10 + height: width + color: "red" + } +} diff --git a/tests/manual/pointer/pointer.pro b/tests/manual/pointer/pointer.pro new file mode 100644 index 0000000000..3705d41df0 --- /dev/null +++ b/tests/manual/pointer/pointer.pro @@ -0,0 +1,7 @@ +TEMPLATE = app + +QT += qml quick + +SOURCES += main.cpp + +RESOURCES += qml.qrc ../../../examples/quick/shared/quick_shared.qrc diff --git a/tests/manual/pointer/qml.qrc b/tests/manual/pointer/qml.qrc new file mode 100644 index 0000000000..5bb79176c7 --- /dev/null +++ b/tests/manual/pointer/qml.qrc @@ -0,0 +1,38 @@ +<RCC> + <qresource prefix="/"> + <file>flingAnimation.qml</file> + <file>main.qml</file> + <file>fakeFlickable.qml</file> + <file>flickableWithHandlers.qml</file> + <file>joystick.qml</file> + <file>map.qml</file> + <file>mixer.qml</file> + <file>multibuttons.qml</file> + <file>photosurface.qml</file> + <file>pinchHandler.qml</file> + <file>singlePointHandlerProperties.qml</file> + <file>tapHandler.qml</file> + <file>content/FakeFlickable.qml</file> + <file>content/FlashAnimation.qml</file> + <file>content/MomentumAnimation.qml</file> + <file>content/MouseAreaButton.qml</file> + <file>content/MouseAreaSlider.qml</file> + <file>content/MptaButton.qml</file> + <file>content/MultiButton.qml</file> + <file>content/Slider.qml</file> + <file>content/TapHandlerButton.qml</file> + <file>resources/arrowhead.png</file> + <file>resources/balloon.png</file> + <file>resources/fighter.png</file> + <file>resources/grabbing-location.svg</file> + <file>resources/map.svgz</file> + <file>resources/missile.png</file> + <file>resources/mixer-knob.png</file> + <file>resources/mouse.png</file> + <file>resources/mouse_left.png</file> + <file>resources/mouse_middle.png</file> + <file>resources/mouse_right.png</file> + <file>resources/redball.png</file> + <file>map2.qml</file> + </qresource> +</RCC> diff --git a/tests/manual/pointer/resources/arrowhead.png b/tests/manual/pointer/resources/arrowhead.png Binary files differnew file mode 100644 index 0000000000..7719bc6d6a --- /dev/null +++ b/tests/manual/pointer/resources/arrowhead.png diff --git a/tests/manual/pointer/resources/balloon.png b/tests/manual/pointer/resources/balloon.png Binary files differnew file mode 100644 index 0000000000..6476facc49 --- /dev/null +++ b/tests/manual/pointer/resources/balloon.png diff --git a/tests/manual/pointer/resources/fighter.png b/tests/manual/pointer/resources/fighter.png Binary files differnew file mode 100644 index 0000000000..2acee43cba --- /dev/null +++ b/tests/manual/pointer/resources/fighter.png diff --git a/tests/manual/pointer/resources/grabbing-location.svg b/tests/manual/pointer/resources/grabbing-location.svg new file mode 100644 index 0000000000..c26881e9ba --- /dev/null +++ b/tests/manual/pointer/resources/grabbing-location.svg @@ -0,0 +1 @@ +<svg width="3408" height="3124"><path d="M1517 1562c0-126-93-229-208-229s-208 102-208 229c0 126 93 229 208 229s208-102 208-229zm123-172c-58-206-221-365-424-412l-270 531H380l203-223 219-241 346-380c42 14 82 32 121 54 232 128 402 375 449 671h-77zm-551-933c448 123 782 546 802 1055h1517C3386 673 2787 0 2050 0H696L0 1367h120l826-938 146 25c-1 1-2 2-3 4zm551 1277c-58 206-221 365-424 412l-270-531H380l203 223 219 241 346 380c42-14 82-32 121-54 232-128 402-375 449-671h-77zm-548 936l-146 25-826-938H0l696 1367h1354c737 0 1337-673 1358-1512H1891c-19 509-354 933-802 1055 1 1 2 2 3 4z" fill="#ee832b"/></svg> diff --git a/tests/manual/pointer/resources/map.svgz b/tests/manual/pointer/resources/map.svgz Binary files differnew file mode 100644 index 0000000000..64d509c106 --- /dev/null +++ b/tests/manual/pointer/resources/map.svgz diff --git a/tests/manual/pointer/resources/missile.png b/tests/manual/pointer/resources/missile.png Binary files differnew file mode 100644 index 0000000000..72c02d1fb9 --- /dev/null +++ b/tests/manual/pointer/resources/missile.png diff --git a/tests/manual/pointer/resources/mixer-knob.png b/tests/manual/pointer/resources/mixer-knob.png Binary files differnew file mode 100644 index 0000000000..b7d42ee3bd --- /dev/null +++ b/tests/manual/pointer/resources/mixer-knob.png diff --git a/tests/manual/pointer/resources/mouse.png b/tests/manual/pointer/resources/mouse.png Binary files differnew file mode 100644 index 0000000000..268946df0a --- /dev/null +++ b/tests/manual/pointer/resources/mouse.png diff --git a/tests/manual/pointer/resources/mouse_left.png b/tests/manual/pointer/resources/mouse_left.png Binary files differnew file mode 100644 index 0000000000..9292301b47 --- /dev/null +++ b/tests/manual/pointer/resources/mouse_left.png diff --git a/tests/manual/pointer/resources/mouse_middle.png b/tests/manual/pointer/resources/mouse_middle.png Binary files differnew file mode 100644 index 0000000000..064e8b9c16 --- /dev/null +++ b/tests/manual/pointer/resources/mouse_middle.png diff --git a/tests/manual/pointer/resources/mouse_right.png b/tests/manual/pointer/resources/mouse_right.png Binary files differnew file mode 100644 index 0000000000..cab1a36ba6 --- /dev/null +++ b/tests/manual/pointer/resources/mouse_right.png diff --git a/tests/manual/pointer/resources/redball.png b/tests/manual/pointer/resources/redball.png Binary files differnew file mode 100644 index 0000000000..68d2e1d638 --- /dev/null +++ b/tests/manual/pointer/resources/redball.png diff --git a/tests/manual/pointer/singlePointHandlerProperties.qml b/tests/manual/pointer/singlePointHandlerProperties.qml new file mode 100644 index 0000000000..f5a938e401 --- /dev/null +++ b/tests/manual/pointer/singlePointHandlerProperties.qml @@ -0,0 +1,162 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.9 +import Qt.labs.handlers 1.0 + +Rectangle { + id: root + width: 480 + height: 480 + color: "black" + + Item { + id: crosshairs + x: dragHandler.pos.x - width / 2 + y: dragHandler.pos.y - height / 2 + width: parent.width / 2; height: parent.height / 2 + visible: dragHandler.active + rotation: dragHandler.rotation + + Rectangle { + color: "goldenrod" + anchors.centerIn: parent + width: 2; height: parent.height + antialiasing: true + } + Rectangle { + color: "goldenrod" + anchors.centerIn: parent + width: parent.width; height: 2 + antialiasing: true + } + Rectangle { + color: "goldenrod" + width: Math.max(2, 50 * dragHandler.pressure) + height: width + radius: width / 2 + anchors.centerIn: parent + antialiasing: true + Rectangle { + y: -40 + anchors.horizontalCenter: parent.horizontalCenter + color: "lightsteelblue" + implicitWidth: label.implicitWidth + implicitHeight: label.implicitHeight + Text { + id: label + text: 'id: ' + dragHandler.pointId.toString(16) + " uid: " + dragHandler.uniquePointId.numericId + + '\npos: (' + dragHandler.pos.x.toFixed(2) + ', ' + dragHandler.pos.y.toFixed(2) + ')' + } + } + } + Rectangle { + color: "transparent" + border.color: "white" + antialiasing: true + width: dragHandler.ellipseDiameters.width + height: dragHandler.ellipseDiameters.height + radius: Math.min(width / 2, height / 2) + anchors.centerIn: parent + } + } + Rectangle { + id: velocityVector + visible: width > 0 + width: dragHandler.velocity.length() * 100 + height: 2 + x: dragHandler.pos.x + y: dragHandler.pos.y + rotation: Math.atan2(dragHandler.velocity.y, dragHandler.velocity.x) * 180 / Math.PI + transformOrigin: Item.BottomLeft + antialiasing: true + + Image { + source: "resources/arrowhead.png" + anchors.right: parent.right + anchors.verticalCenter: parent.verticalCenter + width: 16 + height: 12 + antialiasing: true + } + } + + Component { + id: grabbingLocationIndicator + Image { + source: "resources/grabbing-location.svg" + sourceSize.width: 32 + sourceSize.height: 32 + } + } + + Component { + id: mouseButtonIndicator + Image { + property int buttons + source: "resources/mouse.png" + Image { + source: "resources/mouse_left.png" + visible: buttons & Qt.LeftButton + } + Image { + source: "resources/mouse_middle.png" + visible: buttons & Qt.MidButton + } + Image { + source: "resources/mouse_right.png" + visible: buttons & Qt.RightButton + } + } + } + + DragHandler { + id: dragHandler + target: null + onGrabChanged: if (active) { + console.log("grabbed " + point.pointId + " @ " + sceneGrabPos) + grabbingLocationIndicator.createObject(root, {"x": sceneGrabPos.x, "y": sceneGrabPos.y - 16}) + } + onPressedButtonsChanged: { + if (pressedButtons) + mouseButtonIndicator.createObject(root, {"x": pressPos.x - 44, "y": pressPos.y - 64, "buttons": pressedButtons}) + } + } +} diff --git a/tests/manual/pointer/tapHandler.qml b/tests/manual/pointer/tapHandler.qml new file mode 100644 index 0000000000..06070a02ff --- /dev/null +++ b/tests/manual/pointer/tapHandler.qml @@ -0,0 +1,188 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the manual tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 2.8 +import Qt.labs.handlers 1.0 +import "qrc:/quick/shared/" as Examples + +Item { + width: 480 + height: 320 + + Rectangle { + id: rect + anchors.fill: parent; anchors.margins: 40 + border.width: 3; border.color: "transparent" + color: handler.isPressed ? "lightsteelblue" : "darkgrey" + + TapHandler { + id: handler + acceptedButtons: (leftAllowedCB.checked ? Qt.LeftButton : Qt.NoButton) | + (middleAllowedCB.checked ? Qt.MiddleButton : Qt.NoButton) | + (rightAllowedCB.checked ? Qt.RightButton : Qt.NoButton) + gesturePolicy: (policyDragThresholdCB.checked ? TapHandler.DragThreshold : + policyWithinBoundsCB.checked ? TapHandler.WithinBounds : + TapHandler.ReleaseWithinBounds) + onPressedButtonsChanged: switch (pressedButtons) { + case Qt.MiddleButton: borderBlink.blinkColor = "orange"; break; + case Qt.RightButton: borderBlink.blinkColor = "magenta"; break; + default: borderBlink.blinkColor = "green"; break; + } + onCanceled: { + console.log("canceled @ " + pos) + borderBlink.blinkColor = "red" + borderBlink.start() + } + onTapped: { + console.log("tapped @ " + point.pos + " button(s) " + point.event.button + " tapCount " + tapCount) + if (tapCount > 1) { + tapCountLabel.text = tapCount + flashAnimation.start() + } else { + borderBlink.start() + } + } + onLongPressed: longPressFeedback.createObject(rect, + {"x": pos.x, "y": pos.y, + "text": Math.round(handler.timeHeld).toFixed(3) + " sec", + "color": borderBlink.blinkColor}) + } + + Text { + id: tapCountLabel + anchors.centerIn: parent + font.pixelSize: 72 + font.weight: Font.Black + SequentialAnimation { + id: flashAnimation + PropertyAction { target: tapCountLabel; property: "visible"; value: true } + PropertyAction { target: tapCountLabel; property: "opacity"; value: 1.0 } + PropertyAction { target: tapCountLabel; property: "scale"; value: 1.0 } + ParallelAnimation { + NumberAnimation { + target: tapCountLabel + property: "opacity" + to: 0 + duration: 500 + } + NumberAnimation { + target: tapCountLabel + property: "scale" + to: 1.5 + duration: 500 + } + } + } + } + + Rectangle { + id: expandingCircle + radius: handler.timeHeld * 100 + visible: radius > 0 && handler.isPressed + border.width: 3 + border.color: borderBlink.blinkColor + color: "transparent" + width: radius * 2 + height: radius * 2 + x: handler.pressPos.x - radius + y: handler.pressPos.y - radius + opacity: 0.25 + } + + Component { + id: longPressFeedback + Text { } + } + + SequentialAnimation { + id: borderBlink + property color blinkColor: "blue" + loops: 3 + ScriptAction { script: rect.border.color = borderBlink.blinkColor } + PauseAnimation { duration: 100 } + ScriptAction { script: rect.border.color = "transparent" } + PauseAnimation { duration: 100 } + } + } + + Row { + spacing: 6 + Text { text: "accepted mouse clicks:"; anchors.verticalCenter: leftAllowedCB.verticalCenter } + Examples.CheckBox { + id: leftAllowedCB + checked: true + text: "left click" + } + Examples.CheckBox { + id: middleAllowedCB + text: "middle click" + } + Examples.CheckBox { + id: rightAllowedCB + text: "right click" + } + Text { text: " gesture policy:"; anchors.verticalCenter: leftAllowedCB.verticalCenter } + Examples.CheckBox { + id: policyDragThresholdCB + text: "drag threshold" + onCheckedChanged: if (checked) { + policyWithinBoundsCB.checked = false; + policyReleaseWithinBoundsCB.checked = false; + } + } + Examples.CheckBox { + id: policyWithinBoundsCB + text: "within bounds" + onCheckedChanged: if (checked) { + policyDragThresholdCB.checked = false; + policyReleaseWithinBoundsCB.checked = false; + } + } + Examples.CheckBox { + id: policyReleaseWithinBoundsCB + checked: true + text: "release within bounds" + onCheckedChanged: if (checked) { + policyDragThresholdCB.checked = false; + policyWithinBoundsCB.checked = false; + } + } + } +} |