summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/gestures/imageviewer/imageviewer.pro13
-rw-r--r--examples/gestures/imageviewer/imagewidget.cpp80
-rw-r--r--examples/gestures/imageviewer/imagewidget.h15
-rw-r--r--examples/gestures/imageviewer/tapandholdgesture.cpp155
-rw-r--r--src/corelib/global/qnamespace.h29
-rw-r--r--src/corelib/global/qnamespace.qdoc2
-rw-r--r--src/corelib/kernel/qcoreevent.cpp2
-rw-r--r--src/corelib/kernel/qcoreevent.h4
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp9
-rw-r--r--src/gui/graphicsview/qgraphicsitem.h4
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h1
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp11
-rw-r--r--src/gui/graphicsview/qgraphicsscene.h1
-rw-r--r--src/gui/kernel/kernel.pri23
-rw-r--r--src/gui/kernel/qapplication.cpp89
-rw-r--r--src/gui/kernel/qapplication.h5
-rw-r--r--src/gui/kernel/qapplication_p.h22
-rw-r--r--src/gui/kernel/qapplication_win.cpp39
-rw-r--r--src/gui/kernel/qevent.cpp74
-rw-r--r--src/gui/kernel/qevent.h34
-rw-r--r--src/gui/kernel/qgesture.cpp428
-rw-r--r--src/gui/kernel/qgesture.h153
-rw-r--r--src/gui/kernel/qgesture_p.h76
-rw-r--r--src/gui/kernel/qgesturemanager.cpp453
-rw-r--r--src/gui/kernel/qgesturemanager_p.h125
-rw-r--r--src/gui/kernel/qgesturerecognizer.cpp (renamed from tests/manual/gestures/pinch/pinchwidget.h)53
-rw-r--r--src/gui/kernel/qgesturerecognizer.h93
-rw-r--r--src/gui/kernel/qstandardgestures.cpp775
-rw-r--r--src/gui/kernel/qstandardgestures.h174
-rw-r--r--src/gui/kernel/qstandardgestures_p.h77
-rw-r--r--src/gui/kernel/qwidget.cpp11
-rw-r--r--src/gui/kernel/qwidget.h5
-rw-r--r--src/gui/kernel/qwidget_p.h4
-rw-r--r--src/gui/kernel/qwidget_win.cpp29
-rw-r--r--src/gui/kernel/qwinnativepangesturerecognizer_win.cpp124
-rw-r--r--src/gui/kernel/qwinnativepangesturerecognizer_win_p.h73
-rw-r--r--src/gui/widgets/qabstractscrollarea.cpp56
-rw-r--r--src/gui/widgets/qabstractscrollarea.h4
-rw-r--r--src/gui/widgets/qabstractscrollarea_p.h3
-rw-r--r--src/gui/widgets/qplaintextedit.cpp55
-rw-r--r--src/gui/widgets/qplaintextedit.h4
-rw-r--r--src/gui/widgets/qplaintextedit_p.h5
-rw-r--r--tests/auto/auto.pro3
-rw-r--r--tests/auto/gestures/gestures.pro5
-rw-r--r--tests/auto/gestures/tst_gestures.cpp625
-rw-r--r--tests/manual/gestures/graphicsview/gestures.cpp90
-rw-r--r--tests/manual/gestures/graphicsview/gestures.h37
-rw-r--r--tests/manual/gestures/graphicsview/graphicsview.pro17
-rw-r--r--tests/manual/gestures/graphicsview/imageitem.cpp52
-rw-r--r--tests/manual/gestures/graphicsview/imageitem.h36
-rw-r--r--tests/manual/gestures/graphicsview/main.cpp187
-rw-r--r--tests/manual/gestures/graphicsview/mousepangesturerecognizer.cpp95
-rw-r--r--tests/manual/gestures/graphicsview/mousepangesturerecognizer.h (renamed from examples/gestures/imageviewer/tapandholdgesture.h)35
-rw-r--r--tests/manual/gestures/pinch/pinch.pro4
-rw-r--r--tests/manual/gestures/pinch/pinch.qrc5
-rw-r--r--tests/manual/gestures/pinch/pinchwidget.cpp118
-rw-r--r--tests/manual/gestures/pinch/qt-logo.pngbin13923 -> 0 bytes
-rw-r--r--tests/manual/gestures/scrollarea/main.cpp188
-rw-r--r--tests/manual/gestures/scrollarea/mousepangesturerecognizer.cpp94
-rw-r--r--tests/manual/gestures/scrollarea/mousepangesturerecognizer.h (renamed from tests/manual/gestures/pinch/main.cpp)35
-rw-r--r--tests/manual/gestures/scrollarea/scrollarea.pro3
-rw-r--r--tests/manual/gestures/twopanwidgets/main.cpp135
-rw-r--r--tests/manual/gestures/twopanwidgets/twopanwidgets.pro1
63 files changed, 3300 insertions, 1857 deletions
diff --git a/examples/gestures/imageviewer/imageviewer.pro b/examples/gestures/imageviewer/imageviewer.pro
index 124175e..68c1f1c 100644
--- a/examples/gestures/imageviewer/imageviewer.pro
+++ b/examples/gestures/imageviewer/imageviewer.pro
@@ -1,11 +1,14 @@
-HEADERS += imagewidget.h \
- tapandholdgesture.h
+HEADERS += imagewidget.h
SOURCES += imagewidget.cpp \
- tapandholdgesture.cpp \
main.cpp
# install
target.path = $$[QT_INSTALL_EXAMPLES]/gestures/imageviewer
-sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS imageviewer.pro
+sources.files = $$SOURCES \
+ $$HEADERS \
+ $$RESOURCES \
+ $$FORMS \
+ imageviewer.pro
sources.path = $$[QT_INSTALL_EXAMPLES]/gestures/imageviewer
-INSTALLS += target sources
+INSTALLS += target \
+ sources
diff --git a/examples/gestures/imageviewer/imagewidget.cpp b/examples/gestures/imageviewer/imagewidget.cpp
index 3489b5b..5633942 100644
--- a/examples/gestures/imageviewer/imagewidget.cpp
+++ b/examples/gestures/imageviewer/imagewidget.cpp
@@ -59,24 +59,16 @@ ImageWidget::ImageWidget(QWidget *parent)
setAttribute(Qt::WA_OpaquePaintEvent);
setAttribute(Qt::WA_NoSystemBackground);
- QGesture *panGesture = new QPanGesture(this);
- connect(panGesture, SIGNAL(started()), this, SLOT(panTriggered()));
- connect(panGesture, SIGNAL(finished()), this, SLOT(panTriggered()));
- connect(panGesture, SIGNAL(canceled()), this, SLOT(panTriggered()));
- connect(panGesture, SIGNAL(triggered()), this, SLOT(panTriggered()));
-
- QGesture *pinchGesture = new QPinchGesture(this);
- connect(pinchGesture, SIGNAL(started()), this, SLOT(pinchTriggered()));
- connect(pinchGesture, SIGNAL(finished()), this, SLOT(pinchTriggered()));
- connect(pinchGesture, SIGNAL(canceled()), this, SLOT(pinchTriggered()));
- connect(pinchGesture, SIGNAL(triggered()), this, SLOT(pinchTriggered()));
-
-//! [construct swipe gesture]
- QGesture *swipeGesture = new QSwipeGesture(this);
-//! [construct swipe gesture]
-//! [connect swipe gesture]
- connect(swipeGesture, SIGNAL(triggered()), this, SLOT(swipeTriggered()));
-//! [connect swipe gesture]
+ grabGesture(Qt::PanGesture);
+ grabGesture(Qt::PinchGesture);
+ grabGesture(Qt::SwipeGesture);
+}
+
+bool ImageWidget::event(QEvent *event)
+{
+ if (event->type() == QEvent::Gesture)
+ return gestureEvent(static_cast<QGestureEvent*>(event));
+ return QWidget::event(event);
}
void ImageWidget::paintEvent(QPaintEvent*)
@@ -106,11 +98,25 @@ void ImageWidget::mouseDoubleClickEvent(QMouseEvent *)
update();
}
-void ImageWidget::panTriggered()
+bool ImageWidget::gestureEvent(QGestureEvent *event)
+{
+ if (QGesture *pan = event->gesture(Qt::PanGesture)) {
+ panTriggered(static_cast<QPanGesture*>(pan));
+ return true;
+ } else if (QGesture *pinch = event->gesture(Qt::PinchGesture)) {
+ pinchTriggered(static_cast<QPinchGesture*>(pan));
+ return true;
+ } else if (QGesture *swipe = event->gesture(Qt::SwipeGesture)) {
+ swipeTriggered(static_cast<QSwipeGesture*>(pan));
+ return true;
+ }
+ return false;
+}
+
+void ImageWidget::panTriggered(QPanGesture *gesture)
{
- QPanGesture *pg = qobject_cast<QPanGesture*>(sender());
#ifndef QT_NO_CURSOR
- switch (pg->state()) {
+ switch (gesture->state()) {
case Qt::GestureStarted:
case Qt::GestureUpdated:
setCursor(Qt::SizeAllCursor);
@@ -119,33 +125,37 @@ void ImageWidget::panTriggered()
setCursor(Qt::ArrowCursor);
}
#endif
- horizontalOffset += pg->lastOffset().width();
- verticalOffset += pg->lastOffset().height();
+ QSizeF lastOffset = gesture->property("lastOffset").toSizeF();
+ horizontalOffset += lastOffset.width();
+ verticalOffset += lastOffset.height();
update();
}
-void ImageWidget::pinchTriggered()
+void ImageWidget::pinchTriggered(QPinchGesture *gesture)
{
- QPinchGesture *pg = qobject_cast<QPinchGesture*>(sender());
- if (pg->whatChanged() & QPinchGesture::RotationAngleChanged)
- rotationAngle += pg->rotationAngle() - pg->lastRotationAngle();
- if (pg->whatChanged() & QPinchGesture::ScaleFactorChanged)
- scaleFactor += pg->scaleFactor() - pg->lastScaleFactor();
+ QPinchGesture::WhatChanged whatChanged = gesture->property("whatChanged").value<QPinchGesture::WhatChanged>();
+ if (whatChanged & QPinchGesture::RotationAngleChanged) {
+ qreal value = gesture->property("rotationAngle").toReal();
+ qreal lastValue = gesture->property("lastRotationAngle").toReal();
+ rotationAngle += value - lastValue;
+ }
+ if (whatChanged & QPinchGesture::ScaleFactorChanged) {
+ qreal value = gesture->property("scaleFactor").toReal();
+ qreal lastValue = gesture->property("lastScaleFactor").toReal();
+ scaleFactor += value - lastValue;
+ }
update();
}
-//! [swipe slot start]
-void ImageWidget::swipeTriggered()
+void ImageWidget::swipeTriggered(QSwipeGesture *gesture)
{
- QSwipeGesture *pg = qobject_cast<QSwipeGesture*>(sender());
- if (pg->horizontalDirection() == QSwipeGesture::Left
- || pg->verticalDirection() == QSwipeGesture::Up)
+ if (gesture->horizontalDirection() == QSwipeGesture::Left
+ || gesture->verticalDirection() == QSwipeGesture::Up)
goPrevImage();
else
goNextImage();
update();
}
-//! [swipe slot start]
void ImageWidget::resizeEvent(QResizeEvent*)
{
diff --git a/examples/gestures/imageviewer/imagewidget.h b/examples/gestures/imageviewer/imagewidget.h
index 2a1bfca..e05a67a 100644
--- a/examples/gestures/imageviewer/imagewidget.h
+++ b/examples/gestures/imageviewer/imagewidget.h
@@ -46,6 +46,11 @@
#include <QImage>
#include <QtGui>
+class QGestureEvent;
+class QPanGesture;
+class QPinchGesture;
+class QSwipeGesture;
+
class ImageWidget : public QWidget
{
Q_OBJECT
@@ -56,14 +61,16 @@ public:
void openDirectory(const QString &path);
protected:
+ bool event(QEvent*);
+ bool gestureEvent(QGestureEvent*);
void paintEvent(QPaintEvent*);
void resizeEvent(QResizeEvent*);
void mouseDoubleClickEvent(QMouseEvent*);
-private slots:
- void panTriggered();
- void pinchTriggered();
- void swipeTriggered();
+private:
+ void panTriggered(QPanGesture*);
+ void pinchTriggered(QPinchGesture*);
+ void swipeTriggered(QSwipeGesture*);
private:
void updateImage();
diff --git a/examples/gestures/imageviewer/tapandholdgesture.cpp b/examples/gestures/imageviewer/tapandholdgesture.cpp
deleted file mode 100644
index a10c192..0000000
--- a/examples/gestures/imageviewer/tapandholdgesture.cpp
+++ /dev/null
@@ -1,155 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "tapandholdgesture.h"
-
-#include <QtGui/qevent.h>
-
-// #define TAPANDHOLD_USING_MOUSE
-
-/*!
- \class TapAndHoldGesture
- \since 4.6
-
- \brief The TapAndHoldGesture class represents a Tap-and-Hold gesture,
- providing additional information.
-*/
-
-const int TapAndHoldGesture::iterationCount = 40;
-const int TapAndHoldGesture::iterationTimeout = 50;
-
-/*!
- Creates a new Tap and Hold gesture handler object and marks it as a child
- of \a parent.
-
- On some platforms like Windows there is a system-wide tap and hold gesture
- that cannot be overriden, hence the gesture might never trigger and default
- context menu will be shown instead.
-*/
-TapAndHoldGesture::TapAndHoldGesture(QWidget *parent)
- : QGesture(parent), iteration(0)
-{
-}
-
-/*! \internal */
-bool TapAndHoldGesture::filterEvent(QEvent *event)
-{
- const QTouchEvent *ev = static_cast<const QTouchEvent*>(event);
- switch (event->type()) {
- case QEvent::TouchBegin: {
- if (timer.isActive())
- timer.stop();
- timer.start(TapAndHoldGesture::iterationTimeout, this);
- const QPoint p = ev->touchPoints().at(0).pos().toPoint();
- position = p;
- break;
- }
- case QEvent::TouchUpdate:
- if (ev->touchPoints().size() == 1) {
- const QPoint startPos = ev->touchPoints().at(0).startPos().toPoint();
- const QPoint pos = ev->touchPoints().at(0).pos().toPoint();
- if ((startPos - pos).manhattanLength() > 15)
- reset();
- } else {
- reset();
- }
- break;
- case QEvent::TouchEnd:
- reset();
- break;
-#ifdef TAPANDHOLD_USING_MOUSE
- case QEvent::MouseButtonPress: {
- if (timer.isActive())
- timer.stop();
- timer.start(TapAndHoldGesture::iterationTimeout, this);
- const QPoint p = static_cast<QMouseEvent*>(event)->pos();
- position = startPosition = p;
- break;
- }
- case QEvent::MouseMove: {
- const QPoint startPos = startPosition;
- const QPoint pos = static_cast<QMouseEvent*>(event)->pos();
- if ((startPos - pos).manhattanLength() > 15)
- reset();
- break;
- }
- case QEvent::MouseButtonRelease:
- reset();
- break;
-#endif // TAPANDHOLD_USING_MOUSE
- default:
- break;
- }
- return false;
-}
-
-/*! \internal */
-void TapAndHoldGesture::timerEvent(QTimerEvent *event)
-{
- if (event->timerId() != timer.timerId())
- return;
- if (iteration == TapAndHoldGesture::iterationCount) {
- timer.stop();
- updateState(Qt::GestureFinished);
- } else {
- updateState(Qt::GestureUpdated);
- }
- ++iteration;
-}
-
-/*! \internal */
-void TapAndHoldGesture::reset()
-{
- timer.stop();
- iteration = 0;
- position = startPosition = QPoint();
- updateState(Qt::NoGesture);
-}
-
-/*!
- \property TapAndHoldGesture::pos
-
- \brief The position of the gesture.
-*/
-QPoint TapAndHoldGesture::pos() const
-{
- return position;
-}
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index 4234a7e..c90c096 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -501,8 +501,6 @@ public:
WA_WState_AcceptedTouchBeginEvent = 122,
WA_TouchPadAcceptSingleTouchEvents = 123,
- WA_DontUseStandardGestures = 124,
-
// Add new attributes before this line
WA_AttributeCount
};
@@ -1615,9 +1613,29 @@ public:
enum GestureState
{
NoGesture,
- GestureStarted = 1,
- GestureUpdated = 2,
- GestureFinished = 3
+ GestureStarted = 1,
+ GestureUpdated = 2,
+ GestureFinished = 3,
+ GestureCanceled = 4
+ };
+
+ enum GestureType
+ {
+ TapGesture = 1,
+ TapAndHoldGesture = 2,
+ PanGesture = 3,
+ PinchGesture = 4,
+ SwipeGesture = 5,
+
+ CustomGesture = 0x0100,
+
+ LastGestureType = ~0u
+ };
+
+ enum GestureContext
+ {
+ WidgetGesture = WidgetShortcut,
+ WidgetWithChildrenGesture = WidgetWithChildrenShortcut,
};
enum NavigationMode
@@ -1638,7 +1656,6 @@ public:
;
#endif
-
Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::MouseButtons)
Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::Orientations)
Q_DECLARE_OPERATORS_FOR_FLAGS(Qt::KeyboardModifiers)
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index ab232bf..385edad 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -1225,8 +1225,6 @@
\value WA_TouchPadAcceptSingleTouchEvents Allows touchpad single
touch events to be sent to the widget.
- \value WA_DontUseStandardGestures Disables standard gestures on Qt widgets.
-
\omitvalue WA_SetLayoutDirection
\omitvalue WA_InputMethodTransparent
\omitvalue WA_WState_CompressKeys
diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp
index 744e6a9..5883042 100644
--- a/src/corelib/kernel/qcoreevent.cpp
+++ b/src/corelib/kernel/qcoreevent.cpp
@@ -228,6 +228,8 @@ QT_BEGIN_NAMESPACE
\value TouchBegin Beginning of a sequence of touch-screen and/or track-pad events (QTouchEvent)
\value TouchUpdate Touch-screen event (QTouchEvent)
\value TouchEnd End of touch-event sequence (QTouchEvent)
+ \value Gesture A gesture was triggered (QGestureEvent)
+ \value GestureOverride A gesture override was triggered (QGestureEvent)
User events should have values between \c User and \c{MaxUser}:
diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h
index d66cead..ee1e1b9 100644
--- a/src/corelib/kernel/qcoreevent.h
+++ b/src/corelib/kernel/qcoreevent.h
@@ -283,6 +283,9 @@ public:
UpdateSoftKeys = 201, // Internal for compressing soft key updates
+ Gesture = 198,
+ GestureOverride = 202,
+
// 512 reserved for Qt Jambi's MetaCall event
// 513 reserved for Qt Jambi's DeleteOnMainThread event
@@ -324,6 +327,7 @@ private:
friend class QGraphicsView;
friend class QGraphicsViewPrivate;
friend class QGraphicsScenePrivate;
+ friend class QGestureManager;
};
class Q_CORE_EXPORT QTimerEvent : public QEvent
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index 3069733..81bbb5c 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -663,6 +663,8 @@
#include <private/qpixmap_x11_p.h>
#endif
+#include <private/qgesturemanager_p.h>
+
#include <math.h>
QT_BEGIN_NAMESPACE
@@ -7285,6 +7287,13 @@ QGraphicsObject::QGraphicsObject(QGraphicsItemPrivate &dd, QGraphicsItem *parent
QGraphicsItem::d_ptr->isObject = true;
}
+void QGraphicsObject::grabGesture(Qt::GestureType type, Qt::GestureContext context)
+{
+ QGraphicsItemPrivate * const d = QGraphicsItem::d_func();
+ d->gestureContext.insert(type, context);
+ (void)QGestureManager::instance(); // create a gesture manager
+}
+
/*!
\property QGraphicsObject::parent
\brief the parent of the item
diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h
index e6e324a..2665235 100644
--- a/src/gui/graphicsview/qgraphicsitem.h
+++ b/src/gui/graphicsview/qgraphicsitem.h
@@ -464,6 +464,7 @@ private:
friend class QGraphicsSceneBspTree;
friend class QGraphicsView;
friend class QGraphicsViewPrivate;
+ friend class QGraphicsObject;
friend class QGraphicsWidget;
friend class QGraphicsWidgetPrivate;
friend class QGraphicsProxyWidgetPrivate;
@@ -473,6 +474,7 @@ private:
friend class QGraphicsSceneBspTreeIndexPrivate;
friend class QGraphicsItemEffectSourcePrivate;
friend class QGraphicsTransformPrivate;
+ friend class QGestureManager;
friend class ::tst_QGraphicsItem;
friend bool qt_closestLeaf(const QGraphicsItem *, const QGraphicsItem *);
friend bool qt_closestItemFirst(const QGraphicsItem *, const QGraphicsItem *);
@@ -553,6 +555,8 @@ public:
using QObject::children;
#endif
+ void grabGesture(Qt::GestureType type, Qt::GestureContext context = Qt::WidgetWithChildrenGesture);
+
Q_SIGNALS:
void parentChanged();
void opacityChanged();
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index 51bfea1..6550362 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -450,6 +450,7 @@ public:
QGraphicsItem *focusScopeItem;
Qt::InputMethodHints imHints;
QGraphicsItem::PanelModality panelModality;
+ QMap<Qt::GestureType, Qt::GestureContext> gestureContext;
// Packed 32 bits
quint32 acceptedMouseButtons : 5;
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 961f44f..0f33a66 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -5475,11 +5475,11 @@ void QGraphicsScenePrivate::touchEventHandler(QTouchEvent *sceneTouchEvent)
}
if (itemsNeedingEvents.isEmpty()) {
- sceneTouchEvent->ignore();
+ sceneTouchEvent->accept();
return;
}
- bool acceptSceneTouchEvent = false;
+ bool ignoreSceneTouchEvent = true;
QHash<QGraphicsItem *, StatesAndTouchPoints>::ConstIterator it = itemsNeedingEvents.constBegin();
const QHash<QGraphicsItem *, StatesAndTouchPoints>::ConstIterator end = itemsNeedingEvents.constEnd();
for (; it != end; ++it) {
@@ -5522,19 +5522,20 @@ void QGraphicsScenePrivate::touchEventHandler(QTouchEvent *sceneTouchEvent)
item->d_ptr->acceptedTouchBeginEvent = true;
bool res = sendTouchBeginEvent(item, &touchEvent)
&& touchEvent.isAccepted();
- acceptSceneTouchEvent = acceptSceneTouchEvent || res;
+ if (!res)
+ ignoreSceneTouchEvent = false;
break;
}
default:
if (item->d_ptr->acceptedTouchBeginEvent) {
updateTouchPointsForItem(item, &touchEvent);
(void) sendEvent(item, &touchEvent);
- acceptSceneTouchEvent = true;
+ ignoreSceneTouchEvent = false;
}
break;
}
}
- sceneTouchEvent->setAccepted(acceptSceneTouchEvent);
+ sceneTouchEvent->setAccepted(ignoreSceneTouchEvent);
}
bool QGraphicsScenePrivate::sendTouchBeginEvent(QGraphicsItem *origin, QTouchEvent *touchEvent)
diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h
index ba47530..d6d48d7 100644
--- a/src/gui/graphicsview/qgraphicsscene.h
+++ b/src/gui/graphicsview/qgraphicsscene.h
@@ -311,6 +311,7 @@ private:
friend class QGraphicsSceneBspTreeIndex;
friend class QGraphicsSceneBspTreeIndexPrivate;
friend class QGraphicsItemEffectSourcePrivate;
+ friend class QGesture;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QGraphicsScene::SceneLayers)
diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri
index 760d73c..88c1f73 100644
--- a/src/gui/kernel/kernel.pri
+++ b/src/gui/kernel/kernel.pri
@@ -45,10 +45,11 @@ HEADERS += \
kernel/qkeymapper_p.h \
kernel/qgesture.h \
kernel/qgesture_p.h \
- kernel/qstandardgestures.h \
- kernel/qstandardgestures_p.h \
- kernel/qsoftkeymanager_p.h \
- kernel/qguiplatformplugin_p.h
+ kernel/qstandardgestures_p.h \
+ kernel/qgesturerecognizer.h \
+ kernel/qgesturemanager_p.h \
+ kernel/qsoftkeymanager_p.h \
+ kernel/qguiplatformplugin_p.h
SOURCES += \
kernel/qaction.cpp \
@@ -79,13 +80,18 @@ SOURCES += \
kernel/qwidgetaction.cpp \
kernel/qkeymapper.cpp \
kernel/qgesture.cpp \
- kernel/qstandardgestures.cpp \
- kernel/qsoftkeymanager.cpp \
- kernel/qguiplatformplugin.cpp
+ kernel/qstandardgestures.cpp \
+ kernel/qgesturerecognizer.cpp \
+ kernel/qgesturemanager.cpp \
+ kernel/qsoftkeymanager.cpp \
+ kernel/qguiplatformplugin.cpp
win32 {
DEFINES += QT_NO_DIRECTDRAW
+ HEADERS += \
+ kernel/qwinnativepangesturerecognizer_win_p.h
+
SOURCES += \
kernel/qapplication_win.cpp \
kernel/qclipboard_win.cpp \
@@ -96,7 +102,8 @@ win32 {
kernel/qsound_win.cpp \
kernel/qwidget_win.cpp \
kernel/qole_win.cpp \
- kernel/qkeymapper_win.cpp
+ kernel/qkeymapper_win.cpp \
+ kernel/qwinnativepangesturerecognizer_win.cpp
!contains(DEFINES, QT_NO_DIRECTDRAW):LIBS += ddraw.lib
}
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp
index 43addb6..afc6f63 100644
--- a/src/gui/kernel/qapplication.cpp
+++ b/src/gui/kernel/qapplication.cpp
@@ -99,6 +99,9 @@
#include "qapplication.h"
+#include "qgesture.h"
+#include "private/qgesturemanager_p.h"
+
#ifndef QT_NO_LIBRARY
#include "qlibrary.h"
#endif
@@ -154,6 +157,14 @@ bool QApplicationPrivate::autoSipEnabled = false;
bool QApplicationPrivate::autoSipEnabled = true;
#endif
+QGestureManager* QGestureManager::instance()
+{
+ QApplicationPrivate *d = qApp->d_func();
+ if (!d->gestureManager)
+ d->gestureManager = new QGestureManager(qApp);
+ return d->gestureManager;
+}
+
QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, QApplication::Type type)
: QCoreApplicationPrivate(argc, argv)
{
@@ -177,6 +188,8 @@ QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, QApplication::T
directPainters = 0;
#endif
+ gestureManager = 0;
+
if (!self)
self = this;
}
@@ -3632,6 +3645,13 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
#endif // !QT_NO_WHEELEVENT || !QT_NO_TABLETEVENT
}
+ // walk through parents and check for gestures
+ if (d->gestureManager) {
+ if (d->gestureManager->filterEvent(receiver, e))
+ return true;
+ }
+
+
// User input and window activation makes tooltips sleep
switch (e->type()) {
case QEvent::Wheel:
@@ -4133,6 +4153,65 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
}
break;
}
+ case QEvent::Gesture:
+ case QEvent::GestureOverride:
+ {
+ if (receiver->isWidgetType()) {
+ QWidget *w = static_cast<QWidget *>(receiver);
+ QGestureEvent *gestureEvent = static_cast<QGestureEvent *>(e);
+ QList<QGesture *> allGestures = gestureEvent->allGestures();
+
+ bool eventAccepted = gestureEvent->isAccepted();
+ bool wasAccepted = eventAccepted;
+ while (w) {
+ // send only gestures the widget expects
+ QList<QGesture *> gestures;
+ QWidgetPrivate *wd = w->d_func();
+ for (int i = 0; i < allGestures.size();) {
+ QGesture *g = allGestures.at(i);
+ Qt::GestureType type = g->gestureType();
+ if (wd->gestureContext.contains(type)) {
+ allGestures.removeAt(i);
+ gestures.append(g);
+ gestureEvent->setAccepted(g, false);
+ } else {
+ ++i;
+ }
+ }
+ if (!gestures.isEmpty()) {
+ QGestureEvent ge(gestures);
+ ge.t = gestureEvent->t;
+ ge.spont = gestureEvent->spont;
+ ge.m_accept = wasAccepted;
+ res = d->notify_helper(w, &ge);
+ gestureEvent->spont = false;
+ eventAccepted = ge.isAccepted();
+ if (res && eventAccepted)
+ break;
+ if (!eventAccepted) {
+ // ### two ways to ignore the event/gesture
+
+ // if the whole event wasn't accepted, put back those
+ // gestures that were not accepted.
+ for (int i = 0; i < gestures.size(); ++i) {
+ QGesture *g = gestures.at(i);
+ if (!ge.isAccepted(g))
+ allGestures.append(g);
+ }
+ }
+ }
+ if (allGestures.isEmpty())
+ break;
+ if (w->isWindow())
+ break;
+ w = w->parentWidget();
+ }
+ gestureEvent->m_accept = eventAccepted;
+ } else {
+ res = d->notify_helper(receiver, e);
+ }
+ break;
+ }
default:
res = d->notify_helper(receiver, e);
break;
@@ -5540,6 +5619,16 @@ Q_GUI_EXPORT void qt_translateRawTouchEvent(QWidget *window,
QApplicationPrivate::translateRawTouchEvent(window, deviceType, touchPoints);
}
+Qt::GestureType QApplication::registerGestureRecognizer(QGestureRecognizer *recognizer)
+{
+ return QGestureManager::instance()->registerGestureRecognizer(recognizer);
+}
+
+void QApplication::unregisterGestureRecognizer(Qt::GestureType type)
+{
+ QGestureManager::instance()->unregisterGestureRecognizer(type);
+}
+
QT_END_NAMESPACE
#include "moc_qapplication.cpp"
diff --git a/src/gui/kernel/qapplication.h b/src/gui/kernel/qapplication.h
index 5f21a56..12b398d 100644
--- a/src/gui/kernel/qapplication.h
+++ b/src/gui/kernel/qapplication.h
@@ -86,6 +86,7 @@ class QDecoration;
class QApplication;
class QApplicationPrivate;
+class QGestureRecognizer;
#if defined(qApp)
#undef qApp
#endif
@@ -289,6 +290,9 @@ public:
static Qt::NavigationMode navigationMode();
#endif
+ Qt::GestureType registerGestureRecognizer(QGestureRecognizer *recognizer);
+ void unregisterGestureRecognizer(Qt::GestureType type);
+
Q_SIGNALS:
void lastWindowClosed();
void focusChanged(QWidget *old, QWidget *now);
@@ -400,6 +404,7 @@ private:
friend class QDirectPainter;
friend class QDirectPainterPrivate;
#endif
+ friend class QGestureManager;
#if defined(Q_WS_MAC) || defined(Q_WS_X11)
Q_PRIVATE_SLOT(d_func(), void _q_alertTimeOut())
diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h
index 95b6d28..2d3d18c 100644
--- a/src/gui/kernel/qapplication_p.h
+++ b/src/gui/kernel/qapplication_p.h
@@ -83,8 +83,8 @@ class QGraphicsSystem;
class QInputContext;
class QObject;
class QWidget;
-class QGestureManager;
class QSocketNotifier;
+class QGestureManager;
extern bool qt_is_gui_used;
#ifndef QT_NO_CLIPBOARD
@@ -265,20 +265,6 @@ typedef struct tagGESTURECONFIG
#endif // Q_WS_WIN
-class QPanGesture;
-class QPinchGesture;
-class QSwipeGesture;
-
-struct QStandardGestures
-{
- QPanGesture *pan;
- QPinchGesture *pinch;
- QSwipeGesture *swipe;
-
- QStandardGestures() : pan(0), pinch(0), swipe(0) { }
-};
-
-
class QScopedLoopLevelCounter
{
QThreadData *threadData;
@@ -522,6 +508,8 @@ public:
void sendSyntheticEnterLeave(QWidget *widget);
#endif
+ QGestureManager *gestureManager;
+
QMap<int, QWidget *> widgetForTouchPointId;
QMap<int, QTouchEvent::TouchPoint> appCurrentTouchPoints;
static void updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent);
@@ -536,9 +524,6 @@ public:
QTouchEvent::DeviceType deviceType,
const QList<QTouchEvent::TouchPoint> &touchPoints);
- typedef QMap<QWidget*, QStandardGestures> WidgetStandardGesturesMap;
- WidgetStandardGesturesMap widgetGestures;
-
#if defined(Q_WS_WIN)
static PtrRegisterTouchWindow RegisterTouchWindow;
static PtrGetTouchInputInfo GetTouchInputInfo;
@@ -555,7 +540,6 @@ public:
PtrBeginPanningFeedback BeginPanningFeedback;
PtrUpdatePanningFeedback UpdatePanningFeedback;
PtrEndPanningFeedback EndPanningFeedback;
- QWidget *gestureWidget;
#endif
#ifdef QT_RX71_MULTITOUCH
diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp
index 270562f..540f0a2 100644
--- a/src/gui/kernel/qapplication_win.cpp
+++ b/src/gui/kernel/qapplication_win.cpp
@@ -92,8 +92,6 @@ extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.c
#include <private/qkeymapper_p.h>
#include <private/qlocale_p.h>
#include "qevent_p.h"
-#include "qstandardgestures.h"
-#include "qstandardgestures_p.h"
//#define ALIEN_DEBUG
@@ -854,7 +852,6 @@ void qt_init(QApplicationPrivate *priv, int)
(PtrEndPanningFeedback)QLibrary::resolve(QLatin1String("uxtheme"),
"EndPanningFeedback");
#endif
- priv->gestureWidget = 0;
}
/*****************************************************************************
@@ -2499,24 +2496,24 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
if (qAppPriv->GetGestureInfo)
bResult = qAppPriv->GetGestureInfo((HANDLE)msg.lParam, &gi);
if (bResult) {
- if (gi.dwID == GID_BEGIN) {
- // find the alien widget for the gesture position.
- // This might not be accurate as the position is the center
- // point of two fingers for multi-finger gestures.
- QPoint pt(gi.ptsLocation.x, gi.ptsLocation.y);
- QWidget *w = widget->childAt(widget->mapFromGlobal(pt));
- qAppPriv->gestureWidget = w ? w : widget;
- }
- if (qAppPriv->gestureWidget)
- static_cast<QETWidget*>(qAppPriv->gestureWidget)->translateGestureEvent(msg, gi);
- if (qAppPriv->CloseGestureInfoHandle)
- qAppPriv->CloseGestureInfoHandle((HANDLE)msg.lParam);
- if (gi.dwID == GID_END)
- qAppPriv->gestureWidget = 0;
- } else {
- DWORD dwErr = GetLastError();
- if (dwErr > 0)
- qWarning() << "translateGestureEvent: error = " << dwErr;
+// if (gi.dwID == GID_BEGIN) {
+// // find the alien widget for the gesture position.
+// // This might not be accurate as the position is the center
+// // point of two fingers for multi-finger gestures.
+// QPoint pt(gi.ptsLocation.x, gi.ptsLocation.y);
+// QWidget *w = widget->childAt(widget->mapFromGlobal(pt));
+// qAppPriv->gestureWidget = w ? w : widget;
+// }
+// if (qAppPriv->gestureWidget)
+// static_cast<QETWidget*>(qAppPriv->gestureWidget)->translateGestureEvent(msg, gi);
+// if (qAppPriv->CloseGestureInfoHandle)
+// qAppPriv->CloseGestureInfoHandle((HANDLE)msg.lParam);
+// if (gi.dwID == GID_END)
+// qAppPriv->gestureWidget = 0;
+// } else {
+// DWORD dwErr = GetLastError();
+// if (dwErr > 0)
+// qWarning() << "translateGestureEvent: error = " << dwErr;
}
result = true;
break;
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index 7b9cc9a..4316714 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -49,6 +49,8 @@
#include "qmime.h"
#include "qdnd_p.h"
#include "qevent_p.h"
+#include "qgesture.h"
+#include "qgesture_p.h"
QT_BEGIN_NAMESPACE
@@ -3357,6 +3359,9 @@ QDebug operator<<(QDebug dbg, const QEvent *e) {
case QEvent::ChildRemoved: n = n ? n : "ChildRemoved";
dbg.nospace() << "QChildEvent(" << n << ", " << (static_cast<const QChildEvent*>(e))->child();
return dbg.space();
+ case QEvent::Gesture:
+ n = "Gesture";
+ break;
default:
dbg.nospace() << "QEvent(" << (const void *)e << ", type = " << e->type() << ')';
return dbg.space();
@@ -4186,4 +4191,73 @@ QTouchEvent::TouchPoint &QTouchEvent::TouchPoint::operator=(const QTouchEvent::T
return *this;
}
+/*!
+ \class QGestureEvent
+ \since 4.6
+ \ingroup events
+
+ \brief The QGestureEvent class provides the description of triggered
+ gestures.
+
+ The QGestureEvent class contains a list of gestures that are being executed
+ right now (\l{QGestureEvent::}{activeGestures()}) and a list of gestures
+ that are \l{QGestureEvent::canceledGestures}{cancelled} (a gesture might be
+ cancelled because the window lost focus, or because of timeout, etc).
+
+ \sa QGesture
+*/
+
+/*!
+ Creates new QGestureEvent containing a list of \a gestures.
+*/
+QGestureEvent::QGestureEvent(const QList<QGesture*> &gestures)
+ : QEvent(QEvent::Gesture), gestures_(gestures)
+{
+}
+
+QList<QGesture*> QGestureEvent::allGestures() const
+{
+ return gestures_;
+}
+
+QGesture* QGestureEvent::gesture(Qt::GestureType type)
+{
+ for(int i = 0; i < gestures_.size(); ++i)
+ if (gestures_.at(i)->gestureType() == type)
+ return gestures_.at(i);
+ return 0;
+}
+
+QList<QGesture*> QGestureEvent::activeGestures() const
+{
+ return gestures_;
+}
+
+QList<QGesture*> QGestureEvent::canceledGestures() const
+{
+ return gestures_;
+}
+
+void QGestureEvent::setAccepted(QGesture *gesture, bool value)
+{
+ setAccepted(false);
+ if (gesture)
+ gesture->d_func()->accept = value;
+}
+
+void QGestureEvent::accept(QGesture *gesture)
+{
+ setAccepted(gesture, true);
+}
+
+void QGestureEvent::ignore(QGesture *gesture)
+{
+ setAccepted(gesture, false);
+}
+
+bool QGestureEvent::isAccepted(QGesture *gesture) const
+{
+ return gesture ? gesture->d_func()->accept : false;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index 4396766..224b479 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -819,6 +819,40 @@ protected:
friend class QApplicationPrivate;
};
+class QGesture;
+class Q_GUI_EXPORT QGestureEvent : public QEvent
+{
+public:
+ QGestureEvent(const QList<QGesture *> &gestures);
+
+ QList<QGesture *> allGestures() const;
+ QGesture *gesture(Qt::GestureType type);
+
+ QList<QGesture *> activeGestures() const;
+ QList<QGesture *> canceledGestures() const;
+
+#ifdef Q_NO_USING_KEYWORD
+ inline void setAccepted(bool accepted) { QEvent::setAccepted(accepted); }
+ inline bool isAccepted() const { return QEvent::isAccepted(); }
+
+ inline void accept() { QEvent::accept(); }
+ inline void ignore() { QEvent::ignore(); }
+#else
+ using QEvent::setAccepted;
+ using QEvent::isAccepted;
+ using QEvent::accept;
+ using QEvent::ignore;
+#endif
+
+ void setAccepted(QGesture *, bool);
+ void accept(QGesture *);
+ void ignore(QGesture *);
+ bool isAccepted(QGesture *) const;
+
+private:
+ QList<QGesture *> gestures_;
+};
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp
index 237ce46..bb74aec 100644
--- a/src/gui/kernel/qgesture.cpp
+++ b/src/gui/kernel/qgesture.cpp
@@ -40,274 +40,290 @@
****************************************************************************/
#include "qgesture.h"
-#include <private/qgesture_p.h>
-#include "qgraphicsitem.h"
+#include "private/qgesture_p.h"
QT_BEGIN_NAMESPACE
+ /*!
+ \class QGesture
+ \since 4.6
-class QEventFilterProxyGraphicsItem : public QGraphicsItem
-{
-public:
- QEventFilterProxyGraphicsItem(QGesture *g)
- : gesture(g)
- {
- }
- bool sceneEventFilter(QGraphicsItem *, QEvent *event)
- {
- return gesture ? gesture->filterEvent(event) : false;
- }
- QRectF boundingRect() const { return QRectF(); }
- void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) { }
+ \brief The QGesture class represents a gesture, containing all
+ properties that describe a gesture.
-private:
- QGesture *gesture;
-};
+ The widget receives a QGestureEvent with a list of QGesture
+ objects that represent gestures that are occuring on it. The class
+ has a list of properties that can be queried by the user to get
+ some gesture-specific arguments (i.e. position of the tap in the
+ DoubleTap gesture).
-/*!
- \class QGesture
- \since 4.6
- \preliminary
-
- \brief The QGesture class is the base class for implementing custom
- gestures.
-
- This class represents both an object that recognizes a gesture out of a set
- of input events (a gesture recognizer), and a gesture object itself that
- can be used to get extended information about the triggered gesture.
-
- The class has a list of properties that can be queried by the user to get
- some gesture-specific parameters (for example, an offset of a Pan gesture).
-
- Usually gesture recognizer implements a state machine, storing its state
- internally in the recognizer object. The recognizer receives input events
- through the \l{QGesture::}{filterEvent()} virtual function and decides
- whether the event should change the state of the recognizer by emitting an
- appropriate signal.
-
- Input events should be either fed to the recognizer one by one with a
- filterEvent() function, or the gesture recognizer should be attached to an
- object it filters events for by specifying it as a parent object. The
- QGesture object installs itself as an event filter to the parent object
- automatically, the unsetObject() function should be used to remove an event
- filter from the parent object. To make a
- gesture that operates on a QGraphicsItem, both the appropriate QGraphicsView
- should be passed as a parent object and setGraphicsItem() functions should
- be used to attach a gesture to a graphics item.
-
- This is a base class, to create a custom gesture type, you should subclass
- it and implement its pure virtual functions.
-
- \sa QPanGesture
+ When creating custom gesture recognizers, they might add new
+ properties to the gesture object, or custom gesture developers
+ might subclass the QGesture objects to provide some extended
+ information.
+
+ \sa QGestureEvent, QGestureRecognizer
*/
-/*! \fn bool QGesture::filterEvent(QEvent *event)
+QGesture::QGesture(Qt::GestureType type, QObject *parent)
+ : QObject(*new QGesturePrivate, parent)
+{
+ d_func()->gestureType = type;
+}
- Parses input \a event and emits a signal when detects a gesture.
+QGesture::QGesture(QObject *parent)
+ : QObject(*new QGesturePrivate, parent)
+{
+ d_func()->gestureType = Qt::CustomGesture;
+}
- In your reimplementation of this function, if you want to filter the \a
- event out, i.e. stop it being handled further, return true; otherwise
- return false;
+QGesture::QGesture(QGesturePrivate &dd, Qt::GestureType type, QObject *parent)
+ : QObject(dd, parent)
+{
+ d_func()->gestureType = type;
+}
- This is a pure virtual function that needs to be implemented in subclasses.
-*/
+QGesture::~QGesture()
+{
+}
-/*! \fn void QGesture::started()
+Qt::GestureType QGesture::gestureType() const
+{
+ return d_func()->gestureType;
+}
- The signal is emitted when the gesture is started. Extended information
- about the gesture is contained in the signal sender object.
+Qt::GestureState QGesture::state() const
+{
+ return d_func()->state;
+}
- In addition to started(), a triggered() signal should also be emitted.
-*/
+QObject* QGesture::targetObject() const
+{
+ return d_func()->targetObject;
+}
-/*! \fn void QGesture::triggered()
+void QGesture::setTargetObject(QObject *value)
+{
+ d_func()->targetObject = value;
+}
- The signal is emitted when the gesture is detected. Extended information
- about the gesture is contained in the signal sender object.
-*/
+QPointF QGesture::hotSpot() const
+{
+ return d_func()->hotSpot;
+}
-/*! \fn void QGesture::finished()
+void QGesture::setHotSpot(const QPointF &value)
+{
+ Q_D(QGesture);
+ d->hotSpot = value;
+ d->isHotSpotSet = true;
+}
- The signal is emitted when the gesture is finished. Extended information
- about the gesture is contained in the signal sender object.
-*/
+bool QGesture::hasHotSpot() const
+{
+ return d_func()->isHotSpotSet;
+}
-/*! \fn void QGesture::canceled()
+void QGesture::unsetHotSpot()
+{
+ d_func()->isHotSpotSet = false;
+}
- The signal is emitted when the gesture is canceled, for example the
- reset() function is called while the gesture was in the process of
- emitting a triggered() signal. Extended information about the
- gesture is contained in the sender object.
-*/
+// QPanGesture
-/*!
- Creates a new gesture handler object and marks it as a child of \a
- parent. \a gestureTarget is the object that the gesture will watch
- for events.
+QPanGesture::QPanGesture(QObject *parent)
+ : QGesture(*new QPanGesturePrivate, Qt::PanGesture, parent)
+{
- The \a parent object is also the default event source for the
- gesture, meaning that the gesture installs itself as an event filter
- for the \a parent.
+}
- \sa setGraphicsItem()
-*/
-QGesture::QGesture(QObject *gestureTarget, QObject *parent)
- : QObject(*new QGesturePrivate, parent)
+QSizeF QPanGesture::totalOffset() const
{
- setGestureTarget(gestureTarget);
+ return d_func()->totalOffset;
}
-/*! \internal
- */
-QGesture::QGesture(QGesturePrivate &dd, QObject *gestureTarget, QObject *parent)
- : QObject(dd, parent)
+QSizeF QPanGesture::lastOffset() const
{
- setGestureTarget(gestureTarget);
+ return d_func()->lastOffset;
}
-/*!
- Destroys the gesture object.
-*/
-QGesture::~QGesture()
+QSizeF QPanGesture::offset() const
{
+ return d_func()->offset;
}
-/*!
- \property QGesture::gestureTarget
+qreal QPanGesture::acceleration() const
+{
+ return d_func()->acceleration;
+}
- Gesture target is the object that the gesture will watch for events.
- Typically this means that the gesture installs an event filter on the
- target object.
-*/
-void QGesture::setGestureTarget(QObject *object)
+
+void QPanGesture::setTotalOffset(const QSizeF &value)
{
- d_func()->setupGestureTarget(object);
+ d_func()->totalOffset = value;
}
-QObject* QGesture::gestureTarget() const
+void QPanGesture::setLastOffset(const QSizeF &value)
{
- return d_func()->gestureTarget;
+ d_func()->lastOffset = value;
}
-void QGesturePrivate::setupGestureTarget(QObject *object)
+void QPanGesture::setOffset(const QSizeF &value)
{
- Q_Q(QGesture);
- if (gestureTarget)
- gestureTarget->removeEventFilter(q);
- if (object)
- object->installEventFilter(q);
- gestureTarget = object;
+ d_func()->offset = value;
}
-/*! \internal
- */
-bool QGesture::eventFilter(QObject *receiver, QEvent *event)
+void QPanGesture::setAcceleration(qreal value)
{
- Q_D(QGesture);
- if (d->graphicsItem && receiver == parent())
- return false;
- return filterEvent(event);
+ d_func()->acceleration = value;
}
-/*!
- \property QGesture::state
+// QPinchGesture
- \brief The current state of the gesture.
-*/
+QPinchGesture::QPinchGesture(QObject *parent)
+ : QGesture(*new QPinchGesturePrivate, Qt::PinchGesture, parent)
+{
-/*!
- Returns the gesture recognition state.
- */
-Qt::GestureState QGesture::state() const
+}
+
+QPinchGesture::WhatChanged QPinchGesture::whatChanged() const
{
- return d_func()->state;
+ return d_func()->whatChanged;
}
-/*!
- Sets this gesture's recognition state to \a state and emits appropriate
- signals.
+void QPinchGesture::setWhatChanged(QPinchGesture::WhatChanged value)
+{
+ d_func()->whatChanged = value;
+}
- This functions emits the signals according to the old state and the new
- \a state, and it should be called after all the internal properties have been
- initialized.
- \sa started(), triggered(), finished(), canceled()
- */
-void QGesture::updateState(Qt::GestureState state)
+QPointF QPinchGesture::startCenterPoint() const
{
- Q_D(QGesture);
- if (d->state == state) {
- if (state == Qt::GestureUpdated)
- emit triggered();
- return;
- }
- const Qt::GestureState oldState = d->state;
- if (state != Qt::NoGesture && oldState > state) {
- // comparing the state as ints: state should only be changed from
- // started to (optionally) updated and to finished.
- d->state = state;
- qWarning("QGesture::updateState: incorrect new state");
- return;
- }
- if (oldState == Qt::NoGesture) {
- d->state = Qt::GestureStarted;
- emit started();
- }
- d->state = state;
- if (state == Qt::GestureUpdated)
- emit triggered();
- else if (state == Qt::GestureFinished)
- emit finished();
- else if (state == Qt::NoGesture)
- emit canceled();
-
- if (state == Qt::GestureFinished) {
- // gesture is finished, so we reset the internal state.
- d->state = Qt::NoGesture;
- }
-}
-
-/*!
- Sets the \a graphicsItem the gesture is filtering events for.
-
- The gesture will install an event filter to the \a graphicsItem and
- redirect them to the filterEvent() function.
-
- \sa graphicsItem()
-*/
-void QGesture::setGraphicsItem(QGraphicsItem *graphicsItem)
+ return d_func()->startCenterPoint;
+}
+
+QPointF QPinchGesture::lastCenterPoint() const
{
- Q_D(QGesture);
- if (d->graphicsItem && d->eventFilterProxyGraphicsItem)
- d->graphicsItem->removeSceneEventFilter(d->eventFilterProxyGraphicsItem);
- d->graphicsItem = graphicsItem;
- if (!d->eventFilterProxyGraphicsItem)
- d->eventFilterProxyGraphicsItem = new QEventFilterProxyGraphicsItem(this);
- if (graphicsItem)
- graphicsItem->installSceneEventFilter(d->eventFilterProxyGraphicsItem);
+ return d_func()->lastCenterPoint;
}
-/*!
- Returns the graphics item the gesture is filtering events for.
+QPointF QPinchGesture::centerPoint() const
+{
+ return d_func()->centerPoint;
+}
- \sa setGraphicsItem()
-*/
-QGraphicsItem* QGesture::graphicsItem() const
+void QPinchGesture::setStartCenterPoint(const QPointF &value)
{
- return d_func()->graphicsItem;
+ d_func()->startCenterPoint = value;
}
-/*! \fn void QGesture::reset()
+void QPinchGesture::setLastCenterPoint(const QPointF &value)
+{
+ d_func()->lastCenterPoint = value;
+}
- Resets the internal state of the gesture. This function might be called by
- the filterEvent() implementation in a derived class, or by the user to
- cancel a gesture. The base class implementation calls
- updateState(Qt::NoGesture) which emits the canceled()
- signal if the state() of the gesture indicated it was active.
-*/
-void QGesture::reset()
+void QPinchGesture::setCenterPoint(const QPointF &value)
+{
+ d_func()->centerPoint = value;
+}
+
+
+qreal QPinchGesture::totalScaleFactor() const
+{
+ return d_func()->totalScaleFactor;
+}
+
+qreal QPinchGesture::lastScaleFactor() const
+{
+ return d_func()->lastScaleFactor;
+}
+
+qreal QPinchGesture::scaleFactor() const
+{
+ return d_func()->scaleFactor;
+}
+
+void QPinchGesture::setTotalScaleFactor(qreal value)
+{
+ d_func()->totalScaleFactor = value;
+}
+
+void QPinchGesture::setLastScaleFactor(qreal value)
+{
+ d_func()->lastScaleFactor = value;
+}
+
+void QPinchGesture::setScaleFactor(qreal value)
+{
+ d_func()->scaleFactor = value;
+}
+
+
+qreal QPinchGesture::totalRotationAngle() const
+{
+ return d_func()->totalRotationAngle;
+}
+
+qreal QPinchGesture::lastRotationAngle() const
+{
+ return d_func()->lastRotationAngle;
+}
+
+qreal QPinchGesture::rotationAngle() const
+{
+ return d_func()->rotationAngle;
+}
+
+void QPinchGesture::setTotalRotationAngle(qreal value)
+{
+ d_func()->totalRotationAngle = value;
+}
+
+void QPinchGesture::setLastRotationAngle(qreal value)
+{
+ d_func()->lastRotationAngle = value;
+}
+
+void QPinchGesture::setRotationAngle(qreal value)
+{
+ d_func()->rotationAngle = value;
+}
+
+// QSwipeGesture
+
+QSwipeGesture::QSwipeGesture(QObject *parent)
+ : QGesture(*new QSwipeGesturePrivate, Qt::SwipeGesture, parent)
+{
+}
+
+QSwipeGesture::SwipeDirection QSwipeGesture::horizontalDirection() const
+{
+ return d_func()->horizontalDirection;
+}
+
+QSwipeGesture::SwipeDirection QSwipeGesture::verticalDirection() const
+{
+ return d_func()->verticalDirection;
+}
+
+void QSwipeGesture::setHorizontalDirection(QSwipeGesture::SwipeDirection value)
+{
+ d_func()->horizontalDirection = value;
+}
+
+void QSwipeGesture::setVerticalDirection(QSwipeGesture::SwipeDirection value)
+{
+ d_func()->verticalDirection = value;
+}
+
+qreal QSwipeGesture::swipeAngle() const
+{
+ return d_func()->swipeAngle;
+}
+
+void QSwipeGesture::setSwipeAngle(qreal value)
{
- updateState(Qt::NoGesture);
+ d_func()->swipeAngle = value;
}
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h
index 440565e..b37120f 100644
--- a/src/gui/kernel/qgesture.h
+++ b/src/gui/kernel/qgesture.h
@@ -55,7 +55,8 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Gui)
-class QGraphicsItem;
+Q_DECLARE_METATYPE(Qt::GestureState)
+
class QGesturePrivate;
class Q_GUI_EXPORT QGesture : public QObject
{
@@ -63,37 +64,149 @@ class Q_GUI_EXPORT QGesture : public QObject
Q_DECLARE_PRIVATE(QGesture)
Q_PROPERTY(Qt::GestureState state READ state)
- Q_PROPERTY(QObject* gestureTarget READ gestureTarget WRITE setGestureTarget)
+ Q_PROPERTY(Qt::GestureType gestureType READ gestureType)
+ Q_PROPERTY(QPointF hotSpot READ hotSpot WRITE setHotSpot RESET unsetHotSpot)
+ Q_PROPERTY(bool hasHotSpot READ hasHotSpot)
+ Q_PROPERTY(QObject* targetObject READ targetObject WRITE setTargetObject)
public:
- explicit QGesture(QObject *gestureTarget = 0, QObject *parent = 0);
+ explicit QGesture(Qt::GestureType type = Qt::CustomGesture, QObject *parent = 0);
+ explicit QGesture(QObject *parent);
~QGesture();
- virtual bool filterEvent(QEvent *event) = 0;
+ Qt::GestureType gestureType() const;
- void setGestureTarget(QObject *object);
- QObject* gestureTarget() const;
+ Qt::GestureState state() const;
- void setGraphicsItem(QGraphicsItem *);
- QGraphicsItem *graphicsItem() const;
+ QObject *targetObject() const;
+ void setTargetObject(QObject *value);
- Qt::GestureState state() const;
+ QPointF hotSpot() const;
+ void setHotSpot(const QPointF &value);
+ bool hasHotSpot() const;
+ void unsetHotSpot();
protected:
- QGesture(QGesturePrivate &dd, QObject *gestureTarget, QObject *parent);
- bool eventFilter(QObject*, QEvent*);
+ QGesture(QGesturePrivate &dd, Qt::GestureType type, QObject *parent);
- virtual void reset();
- void updateState(Qt::GestureState state);
+private:
+ friend class QGestureEvent;
+ friend class QGestureRecognizer;
+ friend class QGestureManager;
+};
-Q_SIGNALS:
- void started();
- void triggered();
- void finished();
- void canceled();
+class QPanGesturePrivate;
+class Q_GUI_EXPORT QPanGesture : public QGesture
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QPanGesture)
-private:
- friend class QWidget;
+ Q_PROPERTY(QSizeF totalOffset READ totalOffset WRITE setTotalOffset)
+ Q_PROPERTY(QSizeF lastOffset READ lastOffset WRITE setLastOffset)
+ Q_PROPERTY(QSizeF offset READ offset WRITE setOffset)
+ Q_PROPERTY(qreal acceleration READ acceleration WRITE setAcceleration)
+
+public:
+ QPanGesture(QObject *parent = 0);
+
+ QSizeF totalOffset() const;
+ QSizeF lastOffset() const;
+ QSizeF offset() const;
+ qreal acceleration() const;
+
+ void setTotalOffset(const QSizeF &value);
+ void setLastOffset(const QSizeF &value);
+ void setOffset(const QSizeF &value);
+ void setAcceleration(qreal value);
+
+ friend class QPanGestureRecognizer;
+ friend class QWinNativePanGestureRecognizer;
+};
+
+class QPinchGesturePrivate;
+class Q_GUI_EXPORT QPinchGesture : public QGesture
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QPinchGesture)
+
+public:
+ enum WhatChange {
+ ScaleFactorChanged = 0x1,
+ RotationAngleChanged = 0x2,
+ CenterPointChanged = 0x4
+ };
+ Q_DECLARE_FLAGS(WhatChanged, WhatChange)
+
+ Q_PROPERTY(WhatChanged whatChanged READ whatChanged WRITE setWhatChanged)
+
+ Q_PROPERTY(qreal totalScaleFactor READ totalScaleFactor WRITE setTotalScaleFactor)
+ Q_PROPERTY(qreal lastScaleFactor READ lastScaleFactor WRITE setLastScaleFactor)
+ Q_PROPERTY(qreal scaleFactor READ scaleFactor WRITE setScaleFactor)
+
+ Q_PROPERTY(qreal totalRotationAngle READ totalRotationAngle WRITE setTotalRotationAngle)
+ Q_PROPERTY(qreal lastRotationAngle READ lastRotationAngle WRITE setLastRotationAngle)
+ Q_PROPERTY(qreal rotationAngle READ rotationAngle WRITE setRotationAngle)
+
+ Q_PROPERTY(QPointF startCenterPoint READ startCenterPoint WRITE setStartCenterPoint)
+ Q_PROPERTY(QPointF lastCenterPoint READ lastCenterPoint WRITE setLastCenterPoint)
+ Q_PROPERTY(QPointF centerPoint READ centerPoint WRITE setCenterPoint)
+
+public:
+ QPinchGesture(QObject *parent = 0);
+
+ WhatChanged whatChanged() const;
+ void setWhatChanged(WhatChanged value);
+
+ QPointF startCenterPoint() const;
+ QPointF lastCenterPoint() const;
+ QPointF centerPoint() const;
+ void setStartCenterPoint(const QPointF &value);
+ void setLastCenterPoint(const QPointF &value);
+ void setCenterPoint(const QPointF &value);
+
+ qreal totalScaleFactor() const;
+ qreal lastScaleFactor() const;
+ qreal scaleFactor() const;
+ void setTotalScaleFactor(qreal value);
+ void setLastScaleFactor(qreal value);
+ void setScaleFactor(qreal value);
+
+ qreal totalRotationAngle() const;
+ qreal lastRotationAngle() const;
+ qreal rotationAngle() const;
+ void setTotalRotationAngle(qreal value);
+ void setLastRotationAngle(qreal value);
+ void setRotationAngle(qreal value);
+
+ friend class QPinchGestureRecognizer;
+};
+
+Q_DECLARE_METATYPE(QPinchGesture::WhatChanged)
+
+class QSwipeGesturePrivate;
+class Q_GUI_EXPORT QSwipeGesture : public QGesture
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QSwipeGesture)
+ Q_ENUMS(SwipeDirection)
+
+ Q_PROPERTY(SwipeDirection horizontalDirection READ horizontalDirection WRITE setHorizontalDirection)
+ Q_PROPERTY(SwipeDirection verticalDirection READ verticalDirection WRITE setVerticalDirection)
+ Q_PROPERTY(qreal swipeAngle READ swipeAngle WRITE setSwipeAngle)
+
+public:
+ enum SwipeDirection { NoDirection, Left, Right, Up, Down };
+ QSwipeGesture(QObject *parent = 0);
+
+ SwipeDirection horizontalDirection() const;
+ SwipeDirection verticalDirection() const;
+ void setHorizontalDirection(SwipeDirection value);
+ void setVerticalDirection(SwipeDirection value);
+
+ qreal swipeAngle() const;
+ void setSwipeAngle(qreal value);
+
+ friend class QSwipeGestureRecognizer;
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qgesture_p.h b/src/gui/kernel/qgesture_p.h
index 52e399f..7f69a4e 100644
--- a/src/gui/kernel/qgesture_p.h
+++ b/src/gui/kernel/qgesture_p.h
@@ -61,29 +61,83 @@
QT_BEGIN_NAMESPACE
-class QObject;
-class QGraphicsItem;
class QGesturePrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QGesture)
public:
QGesturePrivate()
- : gestureTarget(0), graphicsItem(0), eventFilterProxyGraphicsItem(0),
- state(Qt::NoGesture), implicitGesture(false)
+ : gestureType(Qt::CustomGesture), state(Qt::NoGesture), isHotSpotSet(false),
+ targetObject(0), accept(true)
{
}
- virtual void setupGestureTarget(QObject *o);
+ Qt::GestureType gestureType;
+ Qt::GestureState state;
+ QPointF hotSpot;
+ bool isHotSpotSet;
+ QObject *targetObject;
+ bool accept;
+};
- QPointer<QObject> gestureTarget;
- QGraphicsItem *graphicsItem;
- QGraphicsItem *eventFilterProxyGraphicsItem;
+class QPanGesturePrivate : public QGesturePrivate
+{
+ Q_DECLARE_PUBLIC(QPanGesture)
- Qt::GestureState state;
+public:
+ QPanGesturePrivate()
+ : acceleration(0)
+ {
+ }
+
+ QSizeF totalOffset;
+ QSizeF lastOffset;
+ QSizeF offset;
+ QPoint lastPosition;
+ qreal acceleration;
+};
+
+class QPinchGesturePrivate : public QGesturePrivate
+{
+ Q_DECLARE_PUBLIC(QPinchGesture)
+
+public:
+ QPinchGesturePrivate()
+ : whatChanged(0), totalScaleFactor(0), lastScaleFactor(0), scaleFactor(0),
+ totalRotationAngle(0), lastRotationAngle(0), rotationAngle(0)
+ {
+ }
+
+ QPinchGesture::WhatChanged whatChanged;
+
+ QPointF startCenterPoint;
+ QPointF lastCenterPoint;
+ QPointF centerPoint;
+
+ qreal totalScaleFactor;
+ qreal lastScaleFactor;
+ qreal scaleFactor;
+
+ qreal totalRotationAngle;
+ qreal lastRotationAngle;
+ qreal rotationAngle;
+};
+
+class QSwipeGesturePrivate : public QGesturePrivate
+{
+ Q_DECLARE_PUBLIC(QSwipeGesture)
+
+public:
+ QSwipeGesturePrivate()
+ : horizontalDirection(QSwipeGesture::NoDirection),
+ verticalDirection(QSwipeGesture::NoDirection),
+ swipeAngle(0)
+ {
+ }
- // the flag specifies if the gesture was created implicitely by Qt.
- bool implicitGesture;
+ QSwipeGesture::SwipeDirection horizontalDirection;
+ QSwipeGesture::SwipeDirection verticalDirection;
+ qreal swipeAngle;
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp
new file mode 100644
index 0000000..000f44f
--- /dev/null
+++ b/src/gui/kernel/qgesturemanager.cpp
@@ -0,0 +1,453 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qgesturemanager_p.h"
+#include "private/qstandardgestures_p.h"
+#include "private/qwidget_p.h"
+#include "private/qgesture_p.h"
+#include "private/qgraphicsitem_p.h"
+#include "qgesture.h"
+#include "qevent.h"
+#include "qgraphicsitem.h"
+
+#include "qdebug.h"
+
+// #define GESTURE_DEBUG
+#ifndef GESTURE_DEBUG
+# define DEBUG if (0) qDebug
+#else
+# define DEBUG qDebug
+#endif
+
+QT_BEGIN_NAMESPACE
+
+QGestureManager::QGestureManager(QObject *parent)
+ : QObject(parent), state(NotGesture), lastCustomGestureId(0)
+{
+ qRegisterMetaType<Qt::GestureState>();
+
+ registerGestureRecognizer(new QPanGestureRecognizer);
+}
+
+QGestureManager::~QGestureManager()
+{
+
+}
+
+Qt::GestureType QGestureManager::registerGestureRecognizer(QGestureRecognizer *recognizer)
+{
+ QGesture *dummy = recognizer->createGesture(0);
+ if (!dummy) {
+ qWarning("QGestureManager::registerGestureRecognizer: the recognizer doesn't provide gesture object");
+ return Qt::GestureType(0);
+ }
+ Qt::GestureType type = dummy->gestureType();
+ if (type == Qt::CustomGesture) {
+ // generate a new custom gesture id
+ ++lastCustomGestureId;
+ type = Qt::GestureType(Qt::CustomGesture + lastCustomGestureId);
+ }
+ recognizers.insertMulti(type, recognizer);
+ delete dummy;
+ return type;
+}
+
+void QGestureManager::unregisterGestureRecognizer(Qt::GestureType)
+{
+
+}
+
+QGesture* QGestureManager::getState(QObject *object, Qt::GestureType type)
+{
+ // if the widget is being deleted we should be carefull and not to
+ // create a new state, as it will create QWeakPointer which doesnt work
+ // from the destructor.
+ if (object->isWidgetType()) {
+ if (static_cast<QWidget *>(object)->d_func()->data.in_destructor)
+ return 0;
+ }
+
+ QWeakPointer<QGesture> state = objectGestures.value(QGestureManager::ObjectGesture(object, type));
+ if (!state) {
+ QGestureRecognizer *recognizer = recognizers.value(type);
+ if (recognizer) {
+ state = recognizer->createGesture(object);
+ if (!state)
+ return 0;
+ if (state.data()->gestureType() == Qt::CustomGesture) {
+ // if the recognizer didn't fill in the gesture type, then this
+ // is a custom gesture with autogenerated it and we fill it.
+ state.data()->d_func()->gestureType = type;
+ }
+ objectGestures.insert(QGestureManager::ObjectGesture(object, type), state);
+ gestureToRecognizer[state.data()] = recognizer;
+ }
+ }
+ return state.data();
+}
+
+bool QGestureManager::filterEvent(QObject *receiver, QEvent *event)
+{
+ QSet<QGesture *> triggeredGestures;
+ QSet<QGesture *> finishedGestures;
+ QSet<QGesture *> newMaybeGestures;
+ QSet<QGesture *> canceledGestures;
+ QSet<QGesture *> notGestures;
+
+ QGraphicsObject *graphicsObject = qobject_cast<QGraphicsObject *>(receiver);
+ if (receiver->isWidgetType() || graphicsObject) {
+ QMap<QObject *, Qt::GestureType> contexts;
+ if (receiver->isWidgetType()) {
+ QWidget *w = static_cast<QWidget *>(receiver);
+ if (!w->d_func()->gestureContext.isEmpty()) {
+ typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator;
+ for(ContextIterator it = w->d_func()->gestureContext.begin(),
+ e = w->d_func()->gestureContext.end(); it != e; ++it) {
+ contexts.insertMulti(w, it.key());
+ }
+ }
+ // find all gesture contexts for the widget tree
+ w = w->parentWidget();
+ while (w)
+ {
+ typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator;
+ for (ContextIterator it = w->d_func()->gestureContext.begin(),
+ e = w->d_func()->gestureContext.end(); it != e; ++it) {
+ if (it.value() == Qt::WidgetWithChildrenGesture)
+ contexts.insertMulti(w, it.key());
+ }
+ w = w->parentWidget();
+ }
+ } else {
+ QGraphicsObject *item = graphicsObject;
+ if (!item->QGraphicsItem::d_func()->gestureContext.isEmpty()) {
+ typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator;
+ for(ContextIterator it = item->QGraphicsItem::d_func()->gestureContext.begin(),
+ e = item->QGraphicsItem::d_func()->gestureContext.end(); it != e; ++it) {
+ contexts.insertMulti(item, it.key());
+ }
+ }
+ // find all gesture contexts for the widget tree
+ item = item->parentObject();
+ while (item)
+ {
+ typedef QMap<Qt::GestureType, Qt::GestureContext>::const_iterator ContextIterator;
+ for (ContextIterator it = item->QGraphicsItem::d_func()->gestureContext.begin(),
+ e = item->QGraphicsItem::d_func()->gestureContext.end(); it != e; ++it) {
+ if (it.value() == Qt::WidgetWithChildrenGesture)
+ contexts.insertMulti(item, it.key());
+ }
+ item = item->parentObject();
+ }
+ }
+ // filter the event through recognizers
+ typedef QMap<QObject *, Qt::GestureType>::const_iterator ContextIterator;
+ for (ContextIterator cit = contexts.begin(), ce = contexts.end(); cit != ce; ++cit) {
+ Qt::GestureType gestureType = cit.value();
+ QMap<Qt::GestureType, QGestureRecognizer *>::const_iterator
+ rit = recognizers.lowerBound(gestureType),
+ re = recognizers.upperBound(gestureType);
+ for (; rit != re; ++rit) {
+ QGestureRecognizer *recognizer = rit.value();
+ QObject *target = cit.key();
+ QGesture *state = getState(target, gestureType);
+ if (!state)
+ continue;
+ QGestureRecognizer::Result result = recognizer->filterEvent(state, target, event);
+ QGestureRecognizer::Result type = result & QGestureRecognizer::ResultState_Mask;
+ if (type == QGestureRecognizer::GestureTriggered) {
+ DEBUG() << "QGestureManager: gesture triggered: " << state;
+ triggeredGestures << state;
+ } else if (type == QGestureRecognizer::GestureFinished) {
+ DEBUG() << "QGestureManager: gesture finished: " << state;
+ finishedGestures << state;
+ } else if (type == QGestureRecognizer::MaybeGesture) {
+ DEBUG() << "QGestureManager: maybe gesture: " << state;
+ newMaybeGestures << state;
+ } else if (type == QGestureRecognizer::NotGesture) {
+ DEBUG() << "QGestureManager: not gesture: " << state;
+ notGestures << state;
+ } else if (type == QGestureRecognizer::Ignore) {
+ DEBUG() << "QGestureManager: gesture ignored the event: " << state;
+ } else {
+ DEBUG() << "QGestureManager: hm, lets assume the recognizer ignored the event: " << state;
+ }
+ if (result & QGestureRecognizer::ConsumeEventHint) {
+ DEBUG() << "QGestureManager: we were asked to consume the event: " << state;
+ //TODO: consume events if asked
+ }
+ }
+ }
+ } else if (QGesture *state = qobject_cast<QGesture*>(receiver)) {
+ if (QGestureRecognizer *recognizer = gestureToRecognizer.value(state)) {
+ QGestureRecognizer::Result result = recognizer->filterEvent(state, state, event);
+ QGestureRecognizer::Result type = result & QGestureRecognizer::ResultState_Mask;
+ if (type == QGestureRecognizer::GestureTriggered) {
+ DEBUG() << "QGestureManager: gesture triggered: " << state;
+ triggeredGestures << state;
+ } else if (type == QGestureRecognizer::GestureFinished) {
+ DEBUG() << "QGestureManager: gesture finished: " << state;
+ finishedGestures << state;
+ } else if (type == QGestureRecognizer::MaybeGesture) {
+ DEBUG() << "QGestureManager: maybe gesture: " << state;
+ newMaybeGestures << state;
+ } else if (type == QGestureRecognizer::NotGesture) {
+ DEBUG() << "QGestureManager: not gesture: " << state;
+ notGestures << state;
+ } else if (type == QGestureRecognizer::Ignore) {
+ DEBUG() << "QGestureManager: gesture ignored the event: " << state;
+ } else {
+ DEBUG() << "QGestureManager: hm, lets assume the recognizer ignored the event: " << state;
+ }
+ }
+ } else {
+ return false;
+ }
+
+ QSet<QGesture *> startedGestures = triggeredGestures - activeGestures;
+ triggeredGestures &= activeGestures;
+
+ // check if a running gesture switched back to maybe state
+ QSet<QGesture *> activeToMaybeGestures = activeGestures & newMaybeGestures;
+
+ // check if a running gesture switched back to not gesture state, i.e. were canceled
+ QSet<QGesture *> activeToCancelGestures = activeGestures & notGestures;
+ canceledGestures += activeToCancelGestures;
+
+ // start timers for new gestures in maybe state
+ foreach (QGesture *state, newMaybeGestures) {
+ QBasicTimer &timer = maybeGestures[state];
+ if (!timer.isActive())
+ timer.start(3000, this);
+ }
+ // kill timers for gestures that were in maybe state
+ QSet<QGesture *> notMaybeGestures = (startedGestures | triggeredGestures | finishedGestures | canceledGestures | notGestures);
+ foreach(QGesture *gesture, notMaybeGestures) {
+ QMap<QGesture *, QBasicTimer>::iterator it =
+ maybeGestures.find(gesture);
+ if (it != maybeGestures.end()) {
+ it.value().stop();
+ maybeGestures.erase(it);
+ }
+ }
+
+ Q_ASSERT((startedGestures & finishedGestures).isEmpty());
+ Q_ASSERT((startedGestures & newMaybeGestures).isEmpty());
+ Q_ASSERT((startedGestures & canceledGestures).isEmpty());
+ Q_ASSERT((finishedGestures & newMaybeGestures).isEmpty());
+ Q_ASSERT((finishedGestures & canceledGestures).isEmpty());
+ Q_ASSERT((canceledGestures & newMaybeGestures).isEmpty());
+
+ QSet<QGesture *> notStarted = finishedGestures - activeGestures;
+ if (!notStarted.isEmpty()) {
+ // there are some gestures that claim to be finished, but never started.
+ qWarning("QGestureManager::filterEvent: some gestures were finished even though they've never started");
+ finishedGestures -= notStarted;
+ }
+
+ activeGestures += startedGestures;
+ // sanity check: all triggered gestures should already be in active gestures list
+ Q_ASSERT((activeGestures & triggeredGestures).size() == triggeredGestures.size());
+ activeGestures -= finishedGestures;
+ activeGestures -= activeToMaybeGestures;
+ activeGestures -= canceledGestures;
+
+ // set the proper gesture state on each gesture
+ foreach (QGesture *gesture, startedGestures)
+ gesture->d_func()->state = Qt::GestureStarted;
+ foreach (QGesture *gesture, triggeredGestures)
+ gesture->d_func()->state = Qt::GestureUpdated;
+ foreach (QGesture *gesture, finishedGestures)
+ gesture->d_func()->state = Qt::GestureFinished;
+ foreach (QGesture *gesture, canceledGestures)
+ gesture->d_func()->state = Qt::GestureCanceled;
+ foreach (QGesture *gesture, activeToMaybeGestures)
+ gesture->d_func()->state = Qt::GestureFinished;
+
+ if (!activeGestures.isEmpty() || !maybeGestures.isEmpty() ||
+ !startedGestures.isEmpty() || !triggeredGestures.isEmpty() ||
+ !finishedGestures.isEmpty() || !canceledGestures.isEmpty()) {
+ DEBUG() << "QGestureManager::filterEvent:"
+ << "\n\tactiveGestures:" << activeGestures
+ << "\n\tmaybeGestures:" << maybeGestures.keys()
+ << "\n\tstarted:" << startedGestures
+ << "\n\ttriggered:" << triggeredGestures
+ << "\n\tfinished:" << finishedGestures
+ << "\n\tcanceled:" << canceledGestures;
+ }
+
+ deliverEvents(startedGestures+triggeredGestures+finishedGestures+canceledGestures, receiver);
+
+ // reset gestures that ended
+ QSet<QGesture *> endedGestures = finishedGestures + canceledGestures;
+ foreach (QGesture *gesture, endedGestures) {
+ if (QGestureRecognizer *recognizer = gestureToRecognizer.value(gesture, 0)) {
+ recognizer->reset(gesture);
+ }
+ gestureTargets.remove(gesture);
+ }
+ return false;
+}
+
+void QGestureManager::deliverEvents(const QSet<QGesture*> &gestures, QObject *lastReceiver)
+{
+ if (gestures.isEmpty())
+ return;
+
+ // group gestures by widgets
+ typedef QMap<QObject *, QList<QGesture *> > GesturesPerReceiver;
+ GesturesPerReceiver groupedGestures;
+ // for conflicted gestures the key is always the innermost widget (i.e. the child)
+ GesturesPerReceiver conflictedGestures;
+ QMultiHash<QObject *, QGesture *> objectGestures;
+
+ foreach (QGesture *gesture, gestures) {
+ QObject *target = gestureTargets.value(gesture, 0);
+ if (!target) {
+ Q_ASSERT(gesture->state() == Qt::GestureStarted);
+ if (gesture->hasHotSpot()) {
+ // guess the target using the hotspot of the gesture
+ QPoint pt = gesture->hotSpot().toPoint();
+ if (!pt.isNull()) {
+ if (QWidget *w = qApp->topLevelAt(pt))
+ target = w->childAt(w->mapFromGlobal(pt));
+ }
+ }
+ if (!target) {
+ target = gesture->targetObject();
+ if (!target)
+ target = lastReceiver;
+ }
+ }
+ if (target) {
+ gestureTargets.insert(gesture, target);
+ if (target->isWidgetType())
+ objectGestures.insert(target, gesture);
+ groupedGestures[target].append(gesture);
+ } else {
+ qWarning() << "QGestureManager::deliverEvent: could not find the target for gesture"
+ << gesture->gestureType();
+ }
+ }
+
+ typedef QMultiHash<QObject *, QGesture *>::const_iterator ObjectGesturesIterator;
+ for (ObjectGesturesIterator it = objectGestures.begin(), e = objectGestures.end(); it != e; ++it) {
+ QObject *object1 = it.key();
+ QWidget *widget1 = qobject_cast<QWidget *>(object1);
+ QGraphicsObject *item1 = qobject_cast<QGraphicsObject *>(object1);
+ QGesture *gesture1 = it.value();
+ ObjectGesturesIterator cit = it;
+ for (++cit; cit != e; ++cit) {
+ QObject *object2 = cit.key();
+ QWidget *widget2 = qobject_cast<QWidget *>(object2);
+ QGraphicsObject *item2 = qobject_cast<QGraphicsObject *>(object2);
+ QGesture *gesture2 = cit.value();
+ // TODO: ugly, rewrite this.
+ if ((widget1 && widget2 && widget2->isAncestorOf(widget1)) ||
+ (item1 && item2 && item2->isAncestorOf(item1))) {
+ groupedGestures[object2].removeOne(gesture2);
+ groupedGestures[object1].removeOne(gesture1);
+ conflictedGestures[object1].append(gesture1);
+ } else if ((widget1 && widget2 && widget1->isAncestorOf(widget2)) ||
+ (item1 && item2 && item1->isAncestorOf(item2))) {
+ groupedGestures[object2].removeOne(gesture2);
+ groupedGestures[object1].removeOne(gesture1);
+ conflictedGestures[object2].append(gesture2);
+ }
+ }
+ }
+
+ DEBUG() << "deliverEvents: conflicted =" << conflictedGestures.values()
+ << " grouped =" << groupedGestures.values();
+
+ // if there are conflicting gestures, send the GestureOverride event
+ for (GesturesPerReceiver::const_iterator it = conflictedGestures.begin(),
+ e = conflictedGestures.end(); it != e; ++it) {
+ DEBUG() << "QGestureManager::deliverEvents: sending GestureOverride to"
+ << it.key()
+ << " gestures:" << it.value();
+ QGestureEvent event(it.value());
+ event.t = QEvent::GestureOverride;
+ event.ignore();
+ QApplication::sendEvent(it.key(), &event);
+ if (!event.isAccepted()) {
+ // nobody accepted the GestureOverride, put it back to deliver to
+ // the closest context (i.e. to the inner-most widget).
+ DEBUG() <<" override was not accepted";
+ groupedGestures[it.key()].append(it.value());
+ }
+ }
+
+ for (GesturesPerReceiver::const_iterator it = groupedGestures.begin(),
+ e = groupedGestures.end(); it != e; ++it) {
+ if (!it.value().isEmpty()) {
+ DEBUG() << "QGestureManager::deliverEvents: sending to" << it.key()
+ << " gestures:" << it.value();
+ QGestureEvent event(it.value());
+ QApplication::sendEvent(it.key(), &event);
+ }
+ }
+}
+
+void QGestureManager::timerEvent(QTimerEvent *event)
+{
+ QMap<QGesture*, QBasicTimer>::iterator it = maybeGestures.begin(),
+ e = maybeGestures.end();
+ for (; it != e; ) {
+ QBasicTimer &timer = it.value();
+ Q_ASSERT(timer.isActive());
+ if (timer.timerId() == event->timerId()) {
+ timer.stop();
+ QGesture *gesture = it.key();
+ it = maybeGestures.erase(it);
+ DEBUG() << "QGestureManager::timerEvent: gesture stopped due to timeout:" << gesture;
+ QGestureRecognizer *recognizer = gestureToRecognizer.value(gesture, 0);
+ if (recognizer)
+ recognizer->reset(gesture);
+ } else {
+ ++it;
+ }
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qgesturemanager_p.cpp"
diff --git a/src/gui/kernel/qgesturemanager_p.h b/src/gui/kernel/qgesturemanager_p.h
new file mode 100644
index 0000000..c61819f
--- /dev/null
+++ b/src/gui/kernel/qgesturemanager_p.h
@@ -0,0 +1,125 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGESTUREMANAGER_P_H
+#define QGESTUREMANAGER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qobject.h"
+#include "qbasictimer.h"
+#include "private/qwidget_p.h"
+#include "qgesturerecognizer.h"
+
+QT_BEGIN_NAMESPACE
+
+class QBasicTimer;
+class QGestureManager : public QObject
+{
+ Q_OBJECT
+public:
+ QGestureManager(QObject *parent);
+ ~QGestureManager();
+
+ Qt::GestureType registerGestureRecognizer(QGestureRecognizer *recognizer);
+ void unregisterGestureRecognizer(Qt::GestureType type);
+
+ bool filterEvent(QObject *receiver, QEvent *event);
+
+ // declared in qapplication.cpp
+ static QGestureManager* instance();
+
+protected:
+ void timerEvent(QTimerEvent *event);
+
+private:
+ QMultiMap<Qt::GestureType, QGestureRecognizer *> recognizers;
+
+ QSet<QGesture *> activeGestures;
+ QMap<QGesture *, QBasicTimer> maybeGestures;
+
+ enum State {
+ Gesture,
+ NotGesture,
+ MaybeGesture // this means timers are up and waiting for some
+ // more events, and input events are handled by
+ // gesture recognizer explicitely
+ } state;
+
+ struct ObjectGesture
+ {
+ QWeakPointer<QObject> object;
+ Qt::GestureType gesture;
+
+ ObjectGesture(QObject *o, const Qt::GestureType &g) : object(o), gesture(g) { }
+ inline bool operator<(const ObjectGesture& rhs) const
+ {
+ if (object.data() < rhs.object.data())
+ return true;
+ if (object == rhs.object)
+ return gesture < rhs.gesture;
+ return false;
+ }
+ };
+
+ QMap<ObjectGesture, QWeakPointer<QGesture> > objectGestures;
+ QMap<QGesture *, QGestureRecognizer *> gestureToRecognizer;
+
+ QHash<QGesture *, QObject *> gestureTargets;
+
+ int lastCustomGestureId;
+
+ QGesture *getState(QObject *widget, Qt::GestureType gesture);
+ void deliverEvents(const QSet<QGesture *> &gestures, QObject *lastReceiver);
+};
+
+QT_END_NAMESPACE
+
+#endif // QGESTUREMANAGER_P_H
diff --git a/tests/manual/gestures/pinch/pinchwidget.h b/src/gui/kernel/qgesturerecognizer.cpp
index 7628ffc..590f09e 100644
--- a/tests/manual/gestures/pinch/pinchwidget.h
+++ b/src/gui/kernel/qgesturerecognizer.cpp
@@ -4,7 +4,7 @@
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the test suite of the Qt Toolkit.
+** This file is part of the QtGui module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
@@ -39,40 +39,33 @@
**
****************************************************************************/
-#ifndef PINCHWIDGET_H
-#define PINCHWIDGET_H
+#include "qgesturerecognizer.h"
-#include <QWidget>
-#include <QTransform>
+#include "private/qgesture_p.h"
-class QPanGesture;
-class QPinchGesture;
+QT_BEGIN_NAMESPACE
-class PinchWidget : public QWidget
+QGestureRecognizer::QGestureRecognizer()
{
- Q_OBJECT
-public:
- PinchWidget(const QImage &image, QWidget *parent = 0);
+}
-private Q_SLOTS:
- void acceptTouchEvents();
- void onPanTriggered();
- void onPanFinished();
- void onPinchTriggered();
- void onPinchFinished();
-
-private:
- void paintEvent(QPaintEvent *);
- QSize sizeHint() const;
-
- QImage image;
+QGestureRecognizer::~QGestureRecognizer()
+{
+}
- QPanGesture *pan;
- QPinchGesture *pinch;
+QGesture *QGestureRecognizer::createGesture(QObject *)
+{
+ return new QGesture;
+}
- QTransform worldTransform;
- QTransform currentPanTransform;
- QTransform currentPinchTransform;
-};
+void QGestureRecognizer::reset(QGesture *state)
+{
+ if (state) {
+ QGesturePrivate *d = state->d_func();
+ d->state = Qt::NoGesture;
+ d->hotSpot = QPointF();
+ d->targetObject = 0;
+ }
+}
-#endif // PINCHWIDGET_H
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qgesturerecognizer.h b/src/gui/kernel/qgesturerecognizer.h
new file mode 100644
index 0000000..c85afd2
--- /dev/null
+++ b/src/gui/kernel/qgesturerecognizer.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGESTURERECOGNIZER_H
+#define QGESTURERECOGNIZER_H
+
+#include "qglobal.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QObject;
+class QEvent;
+class QGesture;
+class Q_GUI_EXPORT QGestureRecognizer
+{
+public:
+ enum ResultFlags
+ {
+ Ignore = 0x0001,
+ NotGesture = 0x0002,
+ MaybeGesture = 0x0004,
+ GestureTriggered = 0x0008, // Gesture started or updated
+ GestureFinished = 0x0010,
+
+ ResultState_Mask = 0x00ff,
+
+ ConsumeEventHint = 0x0100,
+ // StoreEventHint = 0x0200,
+ // ReplayStoredEventsHint = 0x0400,
+ // DiscardStoredEventsHint = 0x0800,
+
+ ResultHint_Mask = 0xff00
+ };
+ Q_DECLARE_FLAGS(Result, ResultFlags)
+
+ QGestureRecognizer();
+ virtual ~QGestureRecognizer();
+
+ virtual QGesture *createGesture(QObject *target);
+ virtual QGestureRecognizer::Result filterEvent(QGesture *state, QObject *watched, QEvent *event) = 0;
+
+ virtual void reset(QGesture *state);
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QGestureRecognizer::Result)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QGESTURERECOGNIZER_H
diff --git a/src/gui/kernel/qstandardgestures.cpp b/src/gui/kernel/qstandardgestures.cpp
index 3cfb987..dfc3499 100644
--- a/src/gui/kernel/qstandardgestures.cpp
+++ b/src/gui/kernel/qstandardgestures.cpp
@@ -39,174 +39,45 @@
**
****************************************************************************/
-#include "qstandardgestures.h"
#include "qstandardgestures_p.h"
-
-#include <qabstractscrollarea.h>
-#include <qscrollbar.h>
-#include <private/qapplication_p.h>
-#include <private/qevent_p.h>
-#include <private/qwidget_p.h>
-#include <qmath.h>
+#include "qgesture.h"
+#include "qgesture_p.h"
+#include "qevent.h"
+#include "qwidget.h"
QT_BEGIN_NAMESPACE
-#ifdef Q_WS_WIN
-QWidgetPrivate *qt_widget_private(QWidget *widget);
-#endif
-
-/*!
- \class QPanGesture
- \preliminary
- \since 4.6
-
- \brief The QPanGesture class represents a Pan gesture,
- providing additional information related to panning.
-*/
-
-/*!
- \enum QSwipeGesture::SwipeDirection
- \brief This enum specifies the direction of the swipe gesture.
-
- \value NoDirection
- \value Left
- \value Right
- \value Up
- \value Down
-*/
-
-/*!
- Creates a new pan gesture handler object and marks it as a child of
- \a parent. The pan gesture handler watches \a gestureTarget for its
- events.
-
- On some platform like Windows it's necessary to provide a non-null
- widget as \a parent to get native gesture support.
-*/
-QPanGesture::QPanGesture(QWidget *gestureTarget, QObject *parent)
- : QGesture(*new QPanGesturePrivate, gestureTarget, parent)
+QPanGestureRecognizer::QPanGestureRecognizer()
{
- setObjectName(QLatin1String("QPanGesture"));
-}
-
-void QPanGesturePrivate::setupGestureTarget(QObject *newGestureTarget)
-{
- Q_Q(QPanGesture);
- QApplicationPrivate *qAppPriv = QApplicationPrivate::instance();
-
- if (gestureTarget && gestureTarget->isWidgetType()) {
- QWidget *w = static_cast<QWidget*>(gestureTarget.data());
- if (qAppPriv->widgetGestures[w].pan == q)
- qAppPriv->widgetGestures[w].pan = 0;
-#if defined(Q_WS_WIN)
- qt_widget_private(w)->winSetupGestures();
-#elif defined(Q_WS_MAC)
- w->setAttribute(Qt::WA_AcceptTouchEvents, false);
- w->setAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents, false);
-#endif
- }
-
- if (newGestureTarget && newGestureTarget->isWidgetType()) {
- QWidget *w = static_cast<QWidget*>(newGestureTarget);
- qAppPriv->widgetGestures[w].pan = q;
-#if defined(Q_WS_WIN)
- qt_widget_private(w)->winSetupGestures();
-#elif defined(Q_WS_MAC)
- w->setAttribute(Qt::WA_AcceptTouchEvents);
- w->setAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents);
-#endif
- }
- QGesturePrivate::setupGestureTarget(newGestureTarget);
-}
-
-/*! \internal */
-bool QPanGesture::event(QEvent *event)
-{
-#if defined(QT_MAC_USE_COCOA)
- Q_D(QPanGesture);
- if (event->type() == QEvent::Timer) {
- const QTimerEvent *te = static_cast<QTimerEvent *>(event);
- if (te->timerId() == d->singleTouchPanTimer.timerId()) {
- d->singleTouchPanTimer.stop();
- updateState(Qt::GestureStarted);
- }
- }
-#endif
-
- return QObject::event(event);
}
-bool QPanGesture::eventFilter(QObject *receiver, QEvent *event)
+QGesture *QPanGestureRecognizer::createGesture(QObject *target)
{
- Q_D(QPanGesture);
-
- if (d->implicitGesture && d->gestureTarget && d->gestureTarget->isWidgetType() &&
- static_cast<QWidget*>(d->gestureTarget.data())->testAttribute(Qt::WA_DontUseStandardGestures))
- return false;
-
-#ifdef Q_WS_WIN
- if (receiver->isWidgetType() && event->type() == QEvent::NativeGesture) {
- QNativeGestureEvent *ev = static_cast<QNativeGestureEvent*>(event);
- QApplicationPrivate *qAppPriv = QApplicationPrivate::instance();
- QApplicationPrivate::WidgetStandardGesturesMap::iterator it;
- it = qAppPriv->widgetGestures.find(static_cast<QWidget*>(receiver));
- if (it == qAppPriv->widgetGestures.end())
- return false;
- if (this != it.value().pan)
- return false;
- Qt::GestureState nextState = Qt::NoGesture;
- switch(ev->gestureType) {
- case QNativeGestureEvent::GestureBegin:
- // next we might receive the first gesture update event, so we
- // prepare for it.
- d->state = Qt::NoGesture;
- return false;
- case QNativeGestureEvent::Pan:
- nextState = Qt::GestureUpdated;
- event->accept();
- break;
- case QNativeGestureEvent::GestureEnd:
- if (state() == Qt::NoGesture)
- return false; // some other gesture has ended
- nextState = Qt::GestureFinished;
- break;
- default:
- return false;
- }
- if (state() == Qt::NoGesture) {
- d->lastOffset = d->totalOffset = d->offset = QSize();
- } else {
- d->lastOffset = d->offset;
- d->offset = QSize(ev->position.x() - d->lastPosition.x(),
- ev->position.y() - d->lastPosition.y());
- d->totalOffset += d->offset;
- }
- d->lastPosition = ev->position;
- updateState(nextState);
- return true;
+ if (target && target->isWidgetType()) {
+ static_cast<QWidget *>(target)->setAttribute(Qt::WA_AcceptTouchEvents);
}
-#endif
- return QGesture::eventFilter(receiver, event);
+ return new QPanGesture;
}
-/*! \internal */
-bool QPanGesture::filterEvent(QEvent *event)
+QGestureRecognizer::Result QPanGestureRecognizer::filterEvent(QGesture *state, QObject *, QEvent *event)
{
- Q_D(QPanGesture);
+ QPanGesture *q = static_cast<QPanGesture*>(state);
+ QPanGesturePrivate *d = q->d_func();
- if (d->implicitGesture && d->gestureTarget && d->gestureTarget->isWidgetType() &&
- static_cast<QWidget*>(d->gestureTarget.data())->testAttribute(Qt::WA_DontUseStandardGestures))
- return false;
-
-#if defined(Q_WS_WIN)
const QTouchEvent *ev = static_cast<const QTouchEvent*>(event);
- if (event->type() == QEvent::TouchBegin) {
+ QGestureRecognizer::Result result;
+
+ switch (event->type()) {
+ case QEvent::TouchBegin: {
+ result = QGestureRecognizer::MaybeGesture;
QTouchEvent::TouchPoint p = ev->touchPoints().at(0);
d->lastPosition = p.pos().toPoint();
d->lastOffset = d->totalOffset = d->offset = QSize();
- } else if (event->type() == QEvent::TouchEnd) {
- if (state() != Qt::NoGesture) {
+ break;
+ }
+ case QEvent::TouchEnd: {
+ if (q->state() != Qt::NoGesture) {
if (ev->touchPoints().size() == 2) {
QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0);
QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1);
@@ -216,11 +87,14 @@ bool QPanGesture::filterEvent(QEvent *event)
p1.pos().y() - p1.lastPos().y() + p2.pos().y() - p2.lastPos().y()) / 2;
d->totalOffset += d->offset;
}
- updateState(Qt::GestureFinished);
+ result = QGestureRecognizer::GestureFinished;
+ } else {
+ result = QGestureRecognizer::NotGesture;
}
- reset();
- } else if (event->type() == QEvent::TouchUpdate) {
- if (ev->touchPoints().size() == 2) {
+ break;
+ }
+ case QEvent::TouchUpdate: {
+ if (ev->touchPoints().size() >= 2) {
QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0);
QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1);
d->lastOffset = d->offset;
@@ -230,10 +104,60 @@ bool QPanGesture::filterEvent(QEvent *event)
d->totalOffset += d->offset;
if (d->totalOffset.width() > 10 || d->totalOffset.height() > 10 ||
d->totalOffset.width() < -10 || d->totalOffset.height() < -10) {
- updateState(Qt::GestureUpdated);
+ result = QGestureRecognizer::GestureTriggered;
+ } else {
+ result = QGestureRecognizer::MaybeGesture;
}
}
+ break;
+ }
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonRelease:
+ result = QGestureRecognizer::Ignore;
+ break;
+ default:
+ result = QGestureRecognizer::Ignore;
+ break;
+ }
+ return result;
+}
+
+void QPanGestureRecognizer::reset(QGesture *state)
+{
+ QPanGesture *pan = static_cast<QPanGesture*>(state);
+ QPanGesturePrivate *d = pan->d_func();
+
+ d->totalOffset = d->lastOffset = d->offset = QSizeF();
+ d->lastPosition = QPoint();
+ d->acceleration = 0;
+
+//#if defined(QT_MAC_USE_COCOA)
+// d->singleTouchPanTimer.stop();
+// d->prevMousePos = QPointF(0, 0);
+//#endif
+
+ QGestureRecognizer::reset(state);
+}
+
+/*! \internal */
+/*
+bool QPanGestureRecognizer::event(QEvent *event)
+{
+#if defined(QT_MAC_USE_COCOA)
+ Q_D(QPanGesture);
+ if (event->type() == QEvent::Timer) {
+ const QTimerEvent *te = static_cast<QTimerEvent *>(event);
+ if (te->timerId() == d->singleTouchPanTimer.timerId()) {
+ d->singleTouchPanTimer.stop();
+ updateState(Qt::GestureStarted);
+ }
}
+#endif
+
+ bool consume = false;
+
+#if defined(Q_WS_WIN)
#elif defined(QT_MAC_USE_COCOA)
// The following implements single touch
// panning on Mac:
@@ -244,16 +168,25 @@ bool QPanGesture::filterEvent(QEvent *event)
switch (event->type()) {
case QEvent::TouchBegin: {
if (ev->touchPoints().size() == 1) {
+ d->delayManager->setEnabled(true);
+ consume = d->delayManager->append(d->gestureTarget, *event);
d->lastPosition = QCursor::pos();
d->singleTouchPanTimer.start(panBeginDelay, this);
}
break;}
case QEvent::TouchEnd: {
- if (state() != Qt::NoGesture)
+ d->delayManager->setEnabled(false);
+ if (state() != Qt::NoGesture) {
updateState(Qt::GestureFinished);
+ consume = true;
+ d->delayManager->clear();
+ } else {
+ d->delayManager->replay();
+ }
reset();
break;}
case QEvent::TouchUpdate: {
+ consume = d->delayManager->append(d->gestureTarget, *event);
if (ev->touchPoints().size() == 1) {
if (state() == Qt::NoGesture) {
// INVARIANT: The singleTouchTimer has still not fired.
@@ -261,11 +194,15 @@ bool QPanGesture::filterEvent(QEvent *event)
// the starting point that it makes sense to cancel:
const QPointF startPos = ev->touchPoints().at(0).startPos().toPoint();
const QPointF p = ev->touchPoints().at(0).pos().toPoint();
- if ((startPos - p).manhattanLength() > panBeginRadius)
+ if ((startPos - p).manhattanLength() > panBeginRadius) {
+ d->delayManager->replay();
+ consume = false;
reset();
- else
+ } else {
d->lastPosition = QCursor::pos();
+ }
} else {
+ d->delayManager->clear();
QPointF mousePos = QCursor::pos();
QPointF dist = mousePos - d->lastPosition;
d->lastPosition = mousePos;
@@ -275,527 +212,25 @@ bool QPanGesture::filterEvent(QEvent *event)
updateState(Qt::GestureUpdated);
}
} else if (state() == Qt::NoGesture) {
+ d->delayManager->replay();
+ consume = false;
reset();
}
break;}
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseMove:
+ case QEvent::MouseButtonRelease:
+ if (d->delayManager->isEnabled())
+ consume = d->delayManager->append(d->gestureTarget, *event);
+ break;
default:
return false;
}
#else
Q_UNUSED(event);
#endif
- return false;
-}
-
-/*! \internal */
-void QPanGesture::reset()
-{
- Q_D(QPanGesture);
- d->lastOffset = d->totalOffset = d->offset = QSize(0, 0);
- d->lastPosition = QPoint(0, 0);
-
-#if defined(QT_MAC_USE_COCOA)
- d->singleTouchPanTimer.stop();
- d->prevMousePos = QPointF(0, 0);
-#endif
-
- QGesture::reset();
-}
-
-/*!
- \property QPanGesture::totalOffset
-
- Specifies a total pan offset since the start of the gesture.
-*/
-QSizeF QPanGesture::totalOffset() const
-{
- Q_D(const QPanGesture);
- return d->totalOffset;
-}
-
-/*!
- \property QPanGesture::lastOffset
-
- Specifies a pan offset the last time the gesture was triggered.
-*/
-QSizeF QPanGesture::lastOffset() const
-{
- Q_D(const QPanGesture);
- return d->lastOffset;
-}
-
-/*!
- \property QPanGesture::offset
-
- Specifies the current pan offset since the last time the gesture was
- triggered.
-*/
-QSizeF QPanGesture::offset() const
-{
- Q_D(const QPanGesture);
- return d->offset;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-/*!
- \class QPinchGesture
- \preliminary
- \since 4.6
-
- \brief The QPinchGesture class represents a Pinch gesture,
- providing additional information related to zooming and/or rotation.
-*/
-
-/*!
- Creates a new Pinch gesture handler object and marks it as a child
- of \a parent. The pan gesture handler watches \a gestureTarget for its
- events.
-
- On some platform like Windows it's necessary to provide a non-null
- widget as \a parent to get native gesture support.
-*/
-QPinchGesture::QPinchGesture(QWidget *gestureTarget, QObject *parent)
- : QGesture(*new QPinchGesturePrivate, gestureTarget, parent)
-{
- setObjectName(QLatin1String("QPinchGesture"));
-}
-
-void QPinchGesturePrivate::setupGestureTarget(QObject *newGestureTarget)
-{
- Q_Q(QPinchGesture);
- if (gestureTarget && gestureTarget->isWidgetType()) {
- QWidget *w = static_cast<QWidget*>(gestureTarget.data());
- QApplicationPrivate::instance()->widgetGestures[w].pinch = 0;
-#ifdef Q_WS_WIN
- qt_widget_private(w)->winSetupGestures();
-#endif
- }
-
- if (newGestureTarget && newGestureTarget->isWidgetType()) {
- QWidget *w = static_cast<QWidget*>(newGestureTarget);
- QApplicationPrivate::instance()->widgetGestures[w].pinch = q;
-#ifdef Q_WS_WIN
- qt_widget_private(w)->winSetupGestures();
-#endif
- }
- QGesturePrivate::setupGestureTarget(newGestureTarget);
-}
-
-/*! \internal */
-bool QPinchGesture::event(QEvent *event)
-{
- return QObject::event(event);
-}
-
-bool QPinchGesture::eventFilter(QObject *receiver, QEvent *event)
-{
- Q_D(QPinchGesture);
-
- if (d->implicitGesture && d->gestureTarget && d->gestureTarget->isWidgetType() &&
- static_cast<QWidget*>(d->gestureTarget.data())->testAttribute(Qt::WA_DontUseStandardGestures))
- return false;
-
-#if defined(Q_WS_WIN) || defined(Q_WS_MAC)
- if (receiver->isWidgetType() && event->type() == QEvent::NativeGesture) {
- QNativeGestureEvent *ev = static_cast<QNativeGestureEvent*>(event);
-#if defined(Q_WS_WIN)
- QApplicationPrivate *qAppPriv = QApplicationPrivate::instance();
- QApplicationPrivate::WidgetStandardGesturesMap::iterator it;
- it = qAppPriv->widgetGestures.find(static_cast<QWidget*>(receiver));
- if (it == qAppPriv->widgetGestures.end())
- return false;
- if (this != it.value().pinch)
- return false;
-#endif
- Qt::GestureState nextState = Qt::NoGesture;
-
- switch(ev->gestureType) {
- case QNativeGestureEvent::GestureBegin:
- // next we might receive the first gesture update event, so we
- // prepare for it.
- d->state = Qt::NoGesture;
- d->changes = 0;
- d->totalScaleFactor = d->scaleFactor = d->lastScaleFactor = 1.;
- d->totalRotationAngle = d->rotationAngle = d->lastRotationAngle = 0.;
- d->startCenterPoint = d->centerPoint = d->lastCenterPoint = QPointF();
-#if defined(Q_WS_WIN)
- d->initialDistance = 0;
- d->lastSequenceId = ev->sequenceId;
-#endif
- return false;
- case QNativeGestureEvent::Rotate: {
- d->lastScaleFactor = d->scaleFactor;
- d->lastRotationAngle = d->rotationAngle;
-#if defined(Q_WS_MAC)
- d->rotationAngle += ev->percentage;
- nextState = Qt::GestureUpdated;
-#elif defined(Q_WS_WIN)
- // This is a workaround for an issue with the native rotation
- // gesture on Windows 7. For some reason the rotation angle in the
- // first WM_GESTURE message in a sequence contains value that is
- // off a little bit and causes the rotating item to "jump", so
- // we just ignore the first WM_GESTURE in every sequence.
- bool windowsRotateWorkaround = false;
- if (!d->lastSequenceId) {
- windowsRotateWorkaround = true;
- d->lastSequenceId = ev->sequenceId;
- }
- if (d->lastSequenceId > 0 && d->lastSequenceId != (ulong)-1 && ev->sequenceId != d->lastSequenceId) {
- // this is the first WM_GESTURE message in a sequence.
- d->totalRotationAngle += d->rotationAngle;
- windowsRotateWorkaround = true;
- // a magic value to mark that the next WM_GESTURE message is
- // the second message in a sequence and we should clear the
- // lastRotationAngle
- d->lastSequenceId = (ulong)-1;
- }
- if (!windowsRotateWorkaround) {
- d->rotationAngle = -1 * GID_ROTATE_ANGLE_FROM_ARGUMENT(ev->argument) * 180. / M_PI;
- if (d->lastSequenceId == (ulong)-1) {
- // a special case since we need to set the lastRotationAngle to
- // rotationAngle when the first WM_GESTURE is received in each
- // sequence.
- d->lastRotationAngle = d->rotationAngle;
- }
- d->lastSequenceId = ev->sequenceId;
- }
- if (!windowsRotateWorkaround)
- nextState = Qt::GestureUpdated;
-#endif
- d->changes = QPinchGesture::RotationAngleChanged;
- event->accept();
- break;
- }
- case QNativeGestureEvent::Zoom:
- d->lastRotationAngle = d->rotationAngle;
- d->lastScaleFactor = d->scaleFactor;
-#if defined(Q_WS_WIN)
- if (d->initialDistance != 0) {
- int distance = int(qint64(ev->argument));
- if (d->lastSequenceId && ev->sequenceId != d->lastSequenceId) {
- d->totalScaleFactor *= d->scaleFactor;
- d->initialDistance = int(qint64(ev->argument));
- d->lastScaleFactor = d->scaleFactor = (qreal) distance / d->initialDistance;
- } else {
- d->scaleFactor = (qreal) distance / d->initialDistance;
- }
- d->lastSequenceId = ev->sequenceId;
- } else {
- d->initialDistance = int(qint64(ev->argument));
- }
-#elif defined(Q_WS_MAC)
- d->scaleFactor += ev->percentage;
-#endif
- nextState = Qt::GestureUpdated;
- d->changes = QPinchGesture::ScaleFactorChanged;
- event->accept();
- break;
- case QNativeGestureEvent::GestureEnd:
- if (state() == Qt::NoGesture)
- return false; // some other gesture has ended
- nextState = Qt::GestureFinished;
- break;
- default:
- return false;
- }
- if (d->startCenterPoint.isNull())
- d->startCenterPoint = d->centerPoint;
- d->lastCenterPoint = d->centerPoint;
- d->centerPoint = static_cast<QWidget*>(receiver)->mapFromGlobal(ev->position);
- if (d->lastCenterPoint != d->centerPoint)
- d->changes |= QPinchGesture::CenterPointChanged;
- updateState(nextState);
- return true;
- }
-#endif
- return QGesture::eventFilter(receiver, event);
-}
-
-
-/*! \internal */
-bool QPinchGesture::filterEvent(QEvent *event)
-{
- Q_D(QPinchGesture);
-
- if (d->implicitGesture && d->gestureTarget && d->gestureTarget->isWidgetType() &&
- static_cast<QWidget*>(d->gestureTarget.data())->testAttribute(Qt::WA_DontUseStandardGestures))
- return false;
-
- Q_UNUSED(event);
- return false;
-}
-
-/*! \internal */
-void QPinchGesture::reset()
-{
- Q_D(QPinchGesture);
- d->changes = 0;
- d->totalScaleFactor = d->scaleFactor = d->lastScaleFactor = 1.;
- d->totalRotationAngle = d->rotationAngle = d->lastRotationAngle = 0.;
- d->startCenterPoint = d->centerPoint = d->lastCenterPoint = QPointF();
- QGesture::reset();
-}
-
-/*! \enum QPinchGesture::WhatChange
- \value ScaleFactorChanged
- \value RotationAngleChanged
- \value CenterPointChanged
-*/
-
-/*!
- \property QPinchGesture::whatChanged
-
- Specifies which values were changed in the gesture.
-*/
-QPinchGesture::WhatChanged QPinchGesture::whatChanged() const
-{
- return d_func()->changes;
-}
-
-/*!
- \property QPinchGesture::totalScaleFactor
-
- Specifies a total scale factor of the pinch gesture since the gesture
- started.
-*/
-qreal QPinchGesture::totalScaleFactor() const
-{
- Q_D(const QPinchGesture);
- return d->totalScaleFactor * d->scaleFactor;
-}
-
-/*!
- \property QPinchGesture::scaleFactor
-
- Specifies a scale factor of the pinch gesture.
-
- If the gesture consists of several pinch sequences (i.e. zoom and rotate
- sequences), then this property specifies the scale factor in the current
- sequence. When pinching changes the rotation angle only, the value of this
- property is 1.
-*/
-qreal QPinchGesture::scaleFactor() const
-{
- return d_func()->scaleFactor;
-}
-
-/*!
- \property QPinchGesture::lastScaleFactor
-
- Specifies a previous scale factor of the pinch gesture.
-*/
-qreal QPinchGesture::lastScaleFactor() const
-{
- return d_func()->lastScaleFactor;
-}
-
-/*!
- \property QPinchGesture::totalRotationAngle
-
- Specifies a total rotation angle of the gesture since the gesture started.
-
- The angle is specified in degrees.
-*/
-qreal QPinchGesture::totalRotationAngle() const
-{
- Q_D(const QPinchGesture);
- return d->totalRotationAngle + d->rotationAngle;
-}
-
-/*!
- \property QPinchGesture::rotationAngle
-
- Specifies a rotation angle of the gesture.
-
- If the gesture consists of several pinch sequences (i.e. zoom and rotate
- sequences), then this property specifies the rotation angle in the current
- sequence. When pinching changes the scale factor only, the value of this
- property is 0.
-
- The angle is specified in degrees.
-*/
-qreal QPinchGesture::rotationAngle() const
-{
- return d_func()->rotationAngle;
-}
-
-/*!
- \property QPinchGesture::lastRotationAngle
-
- Specifies a previous rotation angle of the gesture.
-
- The angle is specified in degrees.
-*/
-qreal QPinchGesture::lastRotationAngle() const
-{
- return d_func()->lastRotationAngle;
-}
-
-/*!
- \property QPinchGesture::centerPoint
-
- Specifies a center point of the gesture. The point can be used as a center
- point that the object is rotated around.
-*/
-QPointF QPinchGesture::centerPoint() const
-{
- return d_func()->centerPoint;
-}
-
-/*!
- \property QPinchGesture::lastCenterPoint
-
- Specifies a previous center point of the gesture.
-*/
-QPointF QPinchGesture::lastCenterPoint() const
-{
- return d_func()->lastCenterPoint;
-}
-
-/*!
- \property QPinchGesture::startCenterPoint
-
- Specifies an initial center point of the gesture. Difference between the
- startCenterPoint and the centerPoint is the distance at which pinching
- fingers has shifted.
-*/
-QPointF QPinchGesture::startCenterPoint() const
-{
- return d_func()->startCenterPoint;
-}
-
-//////////////////////////////////////////////////////////////////////////////
-
-/*!
- \class QSwipeGesture
- \preliminary
- \since 4.6
-
- \brief The QSwipeGesture class represents a swipe gesture,
- providing additional information related to swiping.
-*/
-
-/*!
- Creates a new Swipe gesture handler object and marks it as a
- child of \a parent. The swipe gesture handler watches \a
- gestureTarget for its events.
-
- On some platform like Windows it's necessary to provide a non-null
- widget as \a parent to get native gesture support.
-*/
-QSwipeGesture::QSwipeGesture(QWidget *gestureTarget, QObject *parent)
- : QGesture(*new QSwipeGesturePrivate, gestureTarget, parent)
-{
- setObjectName(QLatin1String("QSwipeGesture"));
-}
-
-void QSwipeGesturePrivate::setupGestureTarget(QObject *newGestureTarget)
-{
- Q_Q(QSwipeGesture);
- if (gestureTarget && gestureTarget->isWidgetType()) {
- QWidget *w = static_cast<QWidget*>(gestureTarget.data());
- QApplicationPrivate::instance()->widgetGestures[w].swipe = 0;
-#if defined(Q_WS_WIN)
- qt_widget_private(w)->winSetupGestures();
-#endif
- }
-
- if (newGestureTarget && newGestureTarget->isWidgetType()) {
- QWidget *w = static_cast<QWidget*>(newGestureTarget);
- QApplicationPrivate::instance()->widgetGestures[w].swipe = q;
-#if defined(Q_WS_WIN)
- qt_widget_private(w)->winSetupGestures();
-#endif
- }
- QGesturePrivate::setupGestureTarget(newGestureTarget);
-}
-
-/*!
- \property QSwipeGesture::swipeAngle
-
- Holds the angle of the swipe gesture, 0..360.
-*/
-qreal QSwipeGesture::swipeAngle() const
-{
- Q_D(const QSwipeGesture);
- return d->swipeAngle;
-}
-
-/*!
- \property QSwipeGesture::horizontalDirection
-
- Holds the direction for the horizontal component of the swipe
- gesture, SwipeDirection::Left or SwipeDirection::Right.
- SwipeDirection::NoDirection if there is no horizontal
- component to the swipe gesture.
-*/
-QSwipeGesture::SwipeDirection QSwipeGesture::horizontalDirection() const
-{
- Q_D(const QSwipeGesture);
- if (d->swipeAngle < 0 || d->swipeAngle == 90 || d->swipeAngle == 270)
- return QSwipeGesture::NoDirection;
- else if (d->swipeAngle < 90 || d->swipeAngle > 270)
- return QSwipeGesture::Right;
- else
- return QSwipeGesture::Left;
-}
-
-
-/*!
- \property QSwipeGesture::verticalDirection
-
- Holds the direction for the vertical component of the swipe
- gesture, SwipeDirection::Down or SwipeDirection::Up.
- SwipeDirection::NoDirection if there is no vertical
- component to the swipe gesture.
-*/
-QSwipeGesture::SwipeDirection QSwipeGesture::verticalDirection() const
-{
- Q_D(const QSwipeGesture);
- if (d->swipeAngle <= 0 || d->swipeAngle == 180)
- return QSwipeGesture::NoDirection;
- else if (d->swipeAngle < 180)
- return QSwipeGesture::Up;
- else
- return QSwipeGesture::Down;
-}
-
-bool QSwipeGesture::eventFilter(QObject *receiver, QEvent *event)
-{
- Q_D(QSwipeGesture);
- if (receiver->isWidgetType() && event->type() == QEvent::NativeGesture) {
- QNativeGestureEvent *ev = static_cast<QNativeGestureEvent*>(event);
- switch (ev->gestureType) {
- case QNativeGestureEvent::Swipe:
- d->swipeAngle = ev->angle;
- updateState(Qt::GestureStarted);
- updateState(Qt::GestureUpdated);
- updateState(Qt::GestureFinished);
- break;
- default:
- return false;
- }
- return true;
- }
- return QGesture::eventFilter(receiver, event);
-}
-
-/*! \internal */
-bool QSwipeGesture::filterEvent(QEvent *)
-{
- return false;
-}
-
-/*! \internal */
-void QSwipeGesture::reset()
-{
- Q_D(QSwipeGesture);
- d->swipeAngle = -1;
- QGesture::reset();
+ return QGestureRecognizer::Ignore;
}
+ */
QT_END_NAMESPACE
-
-#include "moc_qstandardgestures.cpp"
-
diff --git a/src/gui/kernel/qstandardgestures.h b/src/gui/kernel/qstandardgestures.h
deleted file mode 100644
index 9e8291b..0000000
--- a/src/gui/kernel/qstandardgestures.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QSTANDARDGESTURES_H
-#define QSTANDARDGESTURES_H
-
-#include <QtGui/qevent.h>
-#include <QtCore/qbasictimer.h>
-
-#include <QtGui/qgesture.h>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(Gui)
-
-class QPanGesturePrivate;
-class Q_GUI_EXPORT QPanGesture : public QGesture
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QPanGesture)
-
- Q_PROPERTY(QSizeF totalOffset READ totalOffset)
- Q_PROPERTY(QSizeF lastOffset READ lastOffset)
- Q_PROPERTY(QSizeF offset READ offset)
-
-public:
- QPanGesture(QWidget *gestureTarget, QObject *parent = 0);
-
- bool filterEvent(QEvent *event);
-
- QSizeF totalOffset() const;
- QSizeF lastOffset() const;
- QSizeF offset() const;
-
-protected:
- void reset();
-
-private:
- bool event(QEvent *event);
- bool eventFilter(QObject *receiver, QEvent *event);
-
- friend class QWidget;
- friend class QAbstractScrollAreaPrivate;
-};
-
-class QPinchGesturePrivate;
-class Q_GUI_EXPORT QPinchGesture : public QGesture
-{
- Q_OBJECT
- Q_DECLARE_PRIVATE(QPinchGesture)
-
-public:
- enum WhatChange {
- ScaleFactorChanged = 0x1,
- RotationAngleChanged = 0x2,
- CenterPointChanged = 0x4
- };
- Q_DECLARE_FLAGS(WhatChanged, WhatChange)
-
- Q_PROPERTY(WhatChanged whatChanged READ whatChanged)
-
- Q_PROPERTY(qreal totalScaleFactor READ totalScaleFactor)
- Q_PROPERTY(qreal lastScaleFactor READ lastScaleFactor)
- Q_PROPERTY(qreal scaleFactor READ scaleFactor)
-
- Q_PROPERTY(qreal totalRotationAngle READ totalRotationAngle)
- Q_PROPERTY(qreal lastRotationAngle READ lastRotationAngle)
- Q_PROPERTY(qreal rotationAngle READ rotationAngle)
-
- Q_PROPERTY(QPointF startCenterPoint READ startCenterPoint)
- Q_PROPERTY(QPointF lastCenterPoint READ lastCenterPoint)
- Q_PROPERTY(QPointF centerPoint READ centerPoint)
-
-public:
-
- QPinchGesture(QWidget *gestureTarget, QObject *parent = 0);
-
- bool filterEvent(QEvent *event);
- void reset();
-
- WhatChanged whatChanged() const;
-
- QPointF startCenterPoint() const;
- QPointF lastCenterPoint() const;
- QPointF centerPoint() const;
-
- qreal totalScaleFactor() const;
- qreal lastScaleFactor() const;
- qreal scaleFactor() const;
-
- qreal totalRotationAngle() const;
- qreal lastRotationAngle() const;
- qreal rotationAngle() const;
-
-private:
- bool event(QEvent *event);
- bool eventFilter(QObject *receiver, QEvent *event);
-
- friend class QWidget;
-};
-
-class QSwipeGesturePrivate;
-class Q_GUI_EXPORT QSwipeGesture : public QGesture
-{
- Q_OBJECT
- Q_ENUMS(SwipeDirection)
-
- Q_PROPERTY(SwipeDirection horizontalDirection READ horizontalDirection)
- Q_PROPERTY(SwipeDirection verticalDirection READ verticalDirection)
- Q_PROPERTY(qreal swipeAngle READ swipeAngle)
-
- Q_DECLARE_PRIVATE(QSwipeGesture)
-
-public:
- enum SwipeDirection { NoDirection, Left, Right, Up, Down };
- QSwipeGesture(QWidget *gestureTarget, QObject *parent = 0);
-
- bool filterEvent(QEvent *event);
- void reset();
-
- SwipeDirection horizontalDirection() const;
- SwipeDirection verticalDirection() const;
- qreal swipeAngle() const;
-
-private:
- bool eventFilter(QObject *receiver, QEvent *event);
-
- friend class QWidget;
-};
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QSTANDARDGESTURES_H
diff --git a/src/gui/kernel/qstandardgestures_p.h b/src/gui/kernel/qstandardgestures_p.h
index 79aadfd..fec5c2f 100644
--- a/src/gui/kernel/qstandardgestures_p.h
+++ b/src/gui/kernel/qstandardgestures_p.h
@@ -53,83 +53,20 @@
// We mean it.
//
-#include "qevent.h"
-#include "qbasictimer.h"
-#include "qdebug.h"
-
-#include "qgesture.h"
-#include "qgesture_p.h"
-
-#include "qstandardgestures.h"
-#include "qbasictimer.h"
+#include "qgesturerecognizer.h"
+#include "private/qgesture_p.h"
QT_BEGIN_NAMESPACE
-class QPanGesturePrivate : public QGesturePrivate
-{
- Q_DECLARE_PUBLIC(QPanGesture)
-
-public:
- void setupGestureTarget(QObject *o);
-
- QSizeF totalOffset;
- QSizeF lastOffset;
- QSizeF offset;
- QPointF lastPosition;
-
-#if defined(QT_MAC_USE_COCOA)
- QBasicTimer singleTouchPanTimer;
- QPointF prevMousePos;
-#endif
-};
-
-class QPinchGesturePrivate : public QGesturePrivate
+class QPanGestureRecognizer : public QGestureRecognizer
{
- Q_DECLARE_PUBLIC(QPinchGesture)
-
public:
- QPinchGesturePrivate()
- : changes(0), totalScaleFactor(0.), lastScaleFactor(0.), scaleFactor(0.),
- totalRotationAngle(0.), lastRotationAngle(0.), rotationAngle(0.)
-#ifdef Q_WS_WIN
- ,initialDistance(0), lastSequenceId(0)
-#endif
- {
- }
+ QPanGestureRecognizer();
- void setupGestureTarget(QObject *o);
-
- QPinchGesture::WhatChanged changes;
-
- qreal totalScaleFactor; // total scale factor, excluding the current sequence.
- qreal lastScaleFactor;
- qreal scaleFactor; // scale factor in the current sequence.
-
- qreal totalRotationAngle; // total rotation angle, excluding the current sequence.
- qreal lastRotationAngle;
- qreal rotationAngle; // rotation angle in the current sequence.
-
- QPointF startCenterPoint;
- QPointF lastCenterPoint;
- QPointF centerPoint;
-#ifdef Q_WS_WIN
- int initialDistance;
- ulong lastSequenceId;
-#endif
-};
-
-class QSwipeGesturePrivate : public QGesturePrivate
-{
- Q_DECLARE_PUBLIC(QSwipeGesture)
-
-public:
- QSwipeGesturePrivate()
- : swipeAngle(-1)
- {
- }
+ QGesture *createGesture(QObject *target);
- void setupGestureTarget(QObject *o);
- qreal swipeAngle;
+ QGestureRecognizer::Result filterEvent(QGesture *state, QObject *watched, QEvent *event);
+ void reset(QGesture *state);
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index 56602f7..bce06e0 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -115,6 +115,7 @@
#include "private/qevent_p.h"
#include "private/qgraphicssystem_p.h"
+#include "private/qgesturemanager_p.h"
// widget/widget data creation count
//#define QWIDGET_EXTRA_DEBUG
@@ -8332,6 +8333,9 @@ bool QWidget::event(QEvent *event)
(void) QApplication::sendEvent(this, &mouseEvent);
break;
}
+ case QEvent::Gesture:
+ event->ignore();
+ break;
#ifndef QT_NO_PROPERTIES
case QEvent::DynamicPropertyChange: {
const QByteArray &propName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName();
@@ -11668,6 +11672,13 @@ QGraphicsProxyWidget *QWidget::graphicsProxyWidget() const
Synonym for QList<QWidget *>.
*/
+void QWidget::grabGesture(Qt::GestureType type, Qt::GestureContext context)
+{
+ Q_D(QWidget);
+ d->gestureContext.insert(type, context);
+ (void)QGestureManager::instance(); // create a gesture manager
+}
+
QT_END_NAMESPACE
#include "moc_qwidget.cpp"
diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h
index 76418af..3501c6e 100644
--- a/src/gui/kernel/qwidget.h
+++ b/src/gui/kernel/qwidget.h
@@ -96,7 +96,6 @@ class QIcon;
class QWindowSurface;
class QLocale;
class QGraphicsProxyWidget;
-class QGestureManager;
class QGraphicsEffect;
#if defined(Q_WS_X11)
class QX11Info;
@@ -355,6 +354,8 @@ public:
QGraphicsEffect *graphicsEffect() const;
void setGraphicsEffect(QGraphicsEffect *effect);
+ void grabGesture(Qt::GestureType type, Qt::GestureContext context = Qt::WidgetWithChildrenGesture);
+
public Q_SLOTS:
void setWindowTitle(const QString &);
#ifndef QT_NO_STYLE_STYLESHEET
@@ -737,6 +738,8 @@ private:
friend class QGraphicsProxyWidgetPrivate;
friend class QStyleSheetStyle;
friend struct QWidgetExceptionCleaner;
+ friend class QGestureManager;
+ friend class QWinNativePanGestureRecognizer;
#ifdef Q_WS_MAC
friend class QCoreGraphicsPaintEnginePrivate;
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index c06ef73..a549740 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -64,6 +64,8 @@
#include "QtGui/qapplication.h"
#include <private/qgraphicseffect_p.h>
+#include <private/qgesture_p.h>
+
#ifdef Q_WS_WIN
#include "QtCore/qt_windows.h"
#include <private/qdnd_p.h>
@@ -578,6 +580,7 @@ public:
#ifndef QT_NO_ACTION
QList<QAction*> actions;
#endif
+ QMap<Qt::GestureType, Qt::GestureContext> gestureContext;
// Bit fields.
uint high_attributes[3]; // the low ones are in QWidget::widget_attributes
@@ -604,6 +607,7 @@ public:
bool isBackgroundInherited() const;
#elif defined(Q_WS_WIN) // <--------------------------------------------------------- WIN
uint noPaintOnScreen : 1; // see qwidget_win.cpp ::paintEngine()
+ uint nativeGesturePanEnabled : 1;
bool shouldShowMaximizeButton();
void winUpdateIsOpaque();
diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp
index a0982f4..2b11bec 100644
--- a/src/gui/kernel/qwidget_win.cpp
+++ b/src/gui/kernel/qwidget_win.cpp
@@ -2029,11 +2029,6 @@ void QWidgetPrivate::winSetupGestures()
if (!q || !q->isVisible())
return;
QApplicationPrivate *qAppPriv = QApplicationPrivate::instance();
- QApplicationPrivate::WidgetStandardGesturesMap::const_iterator it =
- qAppPriv->widgetGestures.find(q);
- if (it == qAppPriv->widgetGestures.end())
- return;
- const QStandardGestures &gestures = it.value();
WId winid = q->effectiveWinId();
bool needh = false;
@@ -2052,10 +2047,10 @@ void QWidgetPrivate::winSetupGestures()
singleFingerPanEnabled = asa->d_func()->singleFingerPanEnabled;
}
if (winid && qAppPriv->SetGestureConfig) {
- GESTURECONFIG gc[3];
+ GESTURECONFIG gc[1];
memset(gc, 0, sizeof(gc));
gc[0].dwID = GID_PAN;
- if (gestures.pan) {
+ if (nativeGesturePanEnabled) {
gc[0].dwWant = GC_PAN;
if (needv && singleFingerPanEnabled)
gc[0].dwWant |= GC_PAN_WITH_SINGLE_FINGER_VERTICALLY;
@@ -2069,16 +2064,16 @@ void QWidgetPrivate::winSetupGestures()
gc[0].dwBlock = GC_PAN;
}
- gc[1].dwID = GID_ZOOM;
- if (gestures.pinch)
- gc[1].dwWant = GC_ZOOM;
- else
- gc[1].dwBlock = GC_ZOOM;
- gc[2].dwID = GID_ROTATE;
- if (gestures.pinch)
- gc[2].dwWant = GC_ROTATE;
- else
- gc[2].dwBlock = GC_ROTATE;
+// gc[1].dwID = GID_ZOOM;
+// if (gestures.pinch)
+// gc[1].dwWant = GC_ZOOM;
+// else
+// gc[1].dwBlock = GC_ZOOM;
+// gc[2].dwID = GID_ROTATE;
+// if (gestures.pinch)
+// gc[2].dwWant = GC_ROTATE;
+// else
+// gc[2].dwBlock = GC_ROTATE;
qAppPriv->SetGestureConfig(winid, 0, sizeof(gc)/sizeof(gc[0]), gc, sizeof(gc[0]));
}
diff --git a/src/gui/kernel/qwinnativepangesturerecognizer_win.cpp b/src/gui/kernel/qwinnativepangesturerecognizer_win.cpp
new file mode 100644
index 0000000..4619594
--- /dev/null
+++ b/src/gui/kernel/qwinnativepangesturerecognizer_win.cpp
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "private/qwinnativepangesturerecognizer_win_p.h"
+
+#include "qevent.h"
+#include "qgraphicsitem.h"
+#include "qgesture.h"
+
+#include "private/qgesture_p.h"
+#include "private/qevent_p.h"
+#include "private/qapplication_p.h"
+#include "private/qwidget_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QWinNativePanGestureRecognizer::QWinNativePanGestureRecognizer()
+{
+}
+
+QGesture* QWinNativePanGestureRecognizer::createGesture(QObject *target) const
+{
+ if (!target)
+ return new QPanGesture; // a special case
+ if (qobject_cast<QGraphicsObject*>(target))
+ return 0;
+ if (!target->isWidgetType())
+ return 0;
+
+ QWidget *q = static_cast<QWidget*>(target);
+ QWidgetPrivate *d = q->d_func();
+ d->nativeGesturePanEnabled = true;
+ d->winSetupGestures();
+
+ return new QPanGesture;
+}
+
+QGestureRecognizer::Result QWinNativePanGestureRecognizer::filterEvent(QGesture *state, QObject *, QEvent *event)
+{
+ QPanGesture *q = static_cast<QPanGesture*>(state);
+ QPanGesturePrivate *d = q->d_func();
+
+ QGestureRecognizer::Result result = QGestureRecognizer::Ignore;
+ if (event->type() == QEvent::NativeGesture) {
+ QNativeGestureEvent *ev = static_cast<QNativeGestureEvent*>(event);
+ switch(ev->gestureType) {
+ case QNativeGestureEvent::GestureBegin:
+ break;
+ case QNativeGestureEvent::Pan:
+ result = QGestureRecognizer::GestureTriggered;
+ event->accept();
+ break;
+ case QNativeGestureEvent::GestureEnd:
+ if (q->state() == Qt::NoGesture)
+ return QGestureRecognizer::Ignore; // some other gesture has ended
+ result = QGestureRecognizer::GestureFinished;
+ break;
+ default:
+ return QGestureRecognizer::Ignore;
+ }
+ if (q->state() == Qt::NoGesture) {
+ d->lastOffset = d->totalOffset = d->offset = QSize();
+ } else {
+ d->lastOffset = d->offset;
+ d->offset = QSize(ev->position.x() - d->lastPosition.x(),
+ ev->position.y() - d->lastPosition.y());
+ d->totalOffset += d->offset;
+ }
+ d->lastPosition = ev->position;
+ }
+ return result;
+}
+
+void QWinNativePanGestureRecognizer::reset(QGesture *state)
+{
+ QPanGesture *pan = static_cast<QPanGesture*>(state);
+ QPanGesturePrivate *d = pan->d_func();
+
+ d->totalOffset = d->lastOffset = d->offset = QSizeF();
+ d->lastPosition = QPoint();
+ d->acceleration = 0;
+
+ QGestureRecognizer::reset(state);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qwinnativepangesturerecognizer_win_p.h b/src/gui/kernel/qwinnativepangesturerecognizer_win_p.h
new file mode 100644
index 0000000..a1e8511
--- /dev/null
+++ b/src/gui/kernel/qwinnativepangesturerecognizer_win_p.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINNATIVEPANGESTURERECOGNIZER_WIN_P_H
+#define QWINNATIVEPANGESTURERECOGNIZER_WIN_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QGestureRecognizer>
+
+QT_BEGIN_NAMESPACE
+
+class QWinNativePanGestureRecognizer : public QGestureRecognizer
+{
+public:
+ QWinNativePanGestureRecognizer();
+
+ QGesture* createGesture(QObject *target) const;
+
+ QGestureRecognizer::Result filterEvent(QGesture *state, QObject *watched, QEvent *event);
+ void reset(QGesture *state);
+};
+
+QT_END_NAMESPACE
+
+#endif // QWINNATIVEPANGESTURERECOGNIZER_WIN_P_H
diff --git a/src/gui/widgets/qabstractscrollarea.cpp b/src/gui/widgets/qabstractscrollarea.cpp
index d8702cf..0896256 100644
--- a/src/gui/widgets/qabstractscrollarea.cpp
+++ b/src/gui/widgets/qabstractscrollarea.cpp
@@ -52,11 +52,6 @@
#include "qboxlayout.h"
#include "qpainter.h"
-#ifdef Q_WS_WIN
-#include "qstandardgestures.h"
-#include <private/qstandardgestures_p.h>
-#endif
-
#include "qabstractscrollarea_p.h"
#include <qwidget.h>
@@ -165,7 +160,7 @@ QAbstractScrollAreaPrivate::QAbstractScrollAreaPrivate()
viewport(0), cornerWidget(0), left(0), top(0), right(0), bottom(0),
xoffset(0), yoffset(0), viewportFilter(0)
#ifdef Q_WS_WIN
- , panGesture(0), singleFingerPanEnabled(false)
+ , singleFingerPanEnabled(false)
#endif
{
}
@@ -298,14 +293,6 @@ void QAbstractScrollAreaPrivate::init()
q->setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
q->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
layoutChildren();
-
-#ifdef Q_WS_WIN
- panGesture = new QPanGesture(viewport, q);
- panGesture->d_func()->implicitGesture = true;
- QObject::connect(panGesture, SIGNAL(started()), q, SLOT(_q_gestureTriggered()));
- QObject::connect(panGesture, SIGNAL(triggered()), q, SLOT(_q_gestureTriggered()));
- QObject::connect(panGesture, SIGNAL(finished()), q, SLOT(_q_gestureTriggered()));
-#endif // Q_WS_WIN
}
#ifdef Q_WS_WIN
@@ -556,9 +543,6 @@ void QAbstractScrollArea::setViewport(QWidget *widget)
if (isVisible())
d->viewport->show();
QMetaObject::invokeMethod(this, "setupViewport", Q_ARG(QWidget *, widget));
-#ifdef Q_WS_WIN
- d->panGesture->setGestureTarget(widget);
-#endif
delete oldViewport;
}
}
@@ -1351,26 +1335,24 @@ void QAbstractScrollArea::setupViewport(QWidget *viewport)
Q_UNUSED(viewport);
}
-#ifdef Q_WS_WIN
-void QAbstractScrollAreaPrivate::_q_gestureTriggered()
-{
- Q_Q(QAbstractScrollArea);
- QPanGesture *g = qobject_cast<QPanGesture*>(q->sender());
- if (!g)
- return;
- QScrollBar *hBar = q->horizontalScrollBar();
- QScrollBar *vBar = q->verticalScrollBar();
- QSizeF delta = g->lastOffset();
- if (!delta.isNull()) {
- if (QApplication::isRightToLeft())
- delta.rwidth() *= -1;
- int newX = hBar->value() - delta.width();
- int newY = vBar->value() - delta.height();
- hbar->setValue(newX);
- vbar->setValue(newY);
- }
-}
-#endif
+//void QAbstractScrollAreaPrivate::_q_gestureTriggered()
+//{
+// Q_Q(QAbstractScrollArea);
+// QPanGesture *g = qobject_cast<QPanGesture*>(q->sender());
+// if (!g)
+// return;
+// QScrollBar *hBar = q->horizontalScrollBar();
+// QScrollBar *vBar = q->verticalScrollBar();
+// QSizeF delta = g->lastOffset();
+// if (!delta.isNull()) {
+// if (QApplication::isRightToLeft())
+// delta.rwidth() *= -1;
+// int newX = hBar->value() - delta.width();
+// int newY = vBar->value() - delta.height();
+// hbar->setValue(newX);
+// vbar->setValue(newY);
+// }
+//}
QT_END_NAMESPACE
diff --git a/src/gui/widgets/qabstractscrollarea.h b/src/gui/widgets/qabstractscrollarea.h
index 3773477..b3a1861 100644
--- a/src/gui/widgets/qabstractscrollarea.h
+++ b/src/gui/widgets/qabstractscrollarea.h
@@ -129,10 +129,6 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_vslide(int))
Q_PRIVATE_SLOT(d_func(), void _q_showOrHideScrollBars())
-#ifdef Q_WS_WIN
- Q_PRIVATE_SLOT(d_func(), void _q_gestureTriggered())
-#endif
-
friend class QStyleSheetStyle;
friend class QWidgetPrivate;
};
diff --git a/src/gui/widgets/qabstractscrollarea_p.h b/src/gui/widgets/qabstractscrollarea_p.h
index 0bb2851..bfb8917 100644
--- a/src/gui/widgets/qabstractscrollarea_p.h
+++ b/src/gui/widgets/qabstractscrollarea_p.h
@@ -60,7 +60,6 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_SCROLLAREA
-class QPanGesture;
class QScrollBar;
class QAbstractScrollAreaScrollBarContainer;
class Q_AUTOTEST_EXPORT QAbstractScrollAreaPrivate: public QFramePrivate
@@ -102,8 +101,6 @@ public:
QScopedPointer<QObject> viewportFilter;
#ifdef Q_WS_WIN
- QPanGesture *panGesture;
- virtual void _q_gestureTriggered();
bool singleFingerPanEnabled;
void setSingleFingerPanEnabled(bool on = true);
#endif
diff --git a/src/gui/widgets/qplaintextedit.cpp b/src/gui/widgets/qplaintextedit.cpp
index 2ed6cd7..22438bf 100644
--- a/src/gui/widgets/qplaintextedit.cpp
+++ b/src/gui/widgets/qplaintextedit.cpp
@@ -65,11 +65,6 @@
#include <limits.h>
#include <qtexttable.h>
#include <qvariant.h>
-
-#ifdef Q_WS_WIN
-#include <qstandardgestures.h>
-#endif
-
#include <qinputcontext.h>
#ifndef QT_NO_TEXTEDIT
@@ -2937,33 +2932,29 @@ QAbstractTextDocumentLayout::PaintContext QPlainTextEdit::getPaintContext() cons
(\a available is true) or unavailable (\a available is false).
*/
-#ifdef Q_WS_WIN
-
-void QPlainTextEditPrivate::_q_gestureTriggered()
-{
- Q_Q(QPlainTextEdit);
- QPanGesture *g = qobject_cast<QPanGesture*>(q->sender());
- if (!g)
- return;
- QScrollBar *hBar = q->horizontalScrollBar();
- QScrollBar *vBar = q->verticalScrollBar();
- if (g->state() == Qt::GestureStarted)
- originalOffsetY = vBar->value();
- QSizeF totalOffset = g->totalOffset();
- if (!totalOffset.isNull()) {
- if (QApplication::isRightToLeft())
- totalOffset.rwidth() *= -1;
- // QPlainTextEdit scrolls by lines only in vertical direction
- QFontMetrics fm(q->document()->defaultFont());
- int lineHeight = fm.height();
- int newX = hBar->value() - g->lastOffset().width();
- int newY = originalOffsetY - totalOffset.height()/lineHeight;
- hbar->setValue(newX);
- vbar->setValue(newY);
- }
-}
-
-#endif
+//void QPlainTextEditPrivate::_q_gestureTriggered()
+//{
+// Q_Q(QPlainTextEdit);
+// QPanGesture *g = qobject_cast<QPanGesture*>(q->sender());
+// if (!g)
+// return;
+// QScrollBar *hBar = q->horizontalScrollBar();
+// QScrollBar *vBar = q->verticalScrollBar();
+// if (g->state() == Qt::GestureStarted)
+// originalOffsetY = vBar->value();
+// QSizeF totalOffset = g->totalOffset();
+// if (!totalOffset.isNull()) {
+// if (QApplication::isRightToLeft())
+// totalOffset.rwidth() *= -1;
+// // QPlainTextEdit scrolls by lines only in vertical direction
+// QFontMetrics fm(q->document()->defaultFont());
+// int lineHeight = fm.height();
+// int newX = hBar->value() - g->lastOffset().width();
+// int newY = originalOffsetY - totalOffset.height()/lineHeight;
+// hbar->setValue(newX);
+// vbar->setValue(newY);
+// }
+//}
QT_END_NAMESPACE
diff --git a/src/gui/widgets/qplaintextedit.h b/src/gui/widgets/qplaintextedit.h
index 1d6881b..60aed1d 100644
--- a/src/gui/widgets/qplaintextedit.h
+++ b/src/gui/widgets/qplaintextedit.h
@@ -270,10 +270,6 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_verticalScrollbarActionTriggered(int))
Q_PRIVATE_SLOT(d_func(), void _q_cursorPositionChanged())
-#ifdef Q_WS_WIN
- Q_PRIVATE_SLOT(d_func(), void _q_gestureTriggered())
-#endif
-
friend class QPlainTextEditControl;
};
diff --git a/src/gui/widgets/qplaintextedit_p.h b/src/gui/widgets/qplaintextedit_p.h
index 5fe6f4d..7adf403 100644
--- a/src/gui/widgets/qplaintextedit_p.h
+++ b/src/gui/widgets/qplaintextedit_p.h
@@ -72,7 +72,6 @@ class QMimeData;
class QPlainTextEdit;
class ExtraArea;
-class QPanGesture;
class QPlainTextEditControl : public QTextControl
{
@@ -179,10 +178,6 @@ public:
void _q_modificationChanged(bool);
int originalOffsetY;
-
-#ifdef Q_WS_WIN
- void _q_gestureTriggered();
-#endif
};
QT_END_NAMESPACE
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index f3ecdae..9bc1d5c 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -398,7 +398,8 @@ SUBDIRS += \
selftests \
symbols \
qrand \
- utf8
+ utf8 \
+ gestures
!wince*:SUBDIRS += $$Q3SUBDIRS
diff --git a/tests/auto/gestures/gestures.pro b/tests/auto/gestures/gestures.pro
new file mode 100644
index 0000000..da5610f
--- /dev/null
+++ b/tests/auto/gestures/gestures.pro
@@ -0,0 +1,5 @@
+load(qttest_p4)
+SOURCES += tst_gestures.cpp
+
+
+
diff --git a/tests/auto/gestures/tst_gestures.cpp b/tests/auto/gestures/tst_gestures.cpp
new file mode 100644
index 0000000..0a6caff
--- /dev/null
+++ b/tests/auto/gestures/tst_gestures.cpp
@@ -0,0 +1,625 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include <QtTest/QtTest>
+#include "../../shared/util.h"
+
+#include <qevent.h>
+#include <qwidget.h>
+#include <qlayout.h>
+#include <qgesture.h>
+#include <qgesturerecognizer.h>
+#include <qgraphicsitem.h>
+#include <qgraphicsview.h>
+
+#include <qdebug.h>
+
+//TESTED_CLASS=
+//TESTED_FILES=
+
+class CustomGesture : public QGesture
+{
+ Q_OBJECT
+public:
+ static Qt::GestureType GestureType;
+
+ CustomGesture(QObject *parent = 0)
+ : QGesture(parent), target(0), serial(0)
+ {
+ }
+
+ QObject *target;
+ int serial;
+
+ static const int SerialMaybeThreshold;
+ static const int SerialStartedThreshold;
+ static const int SerialFinishedThreshold;
+};
+Qt::GestureType CustomGesture::GestureType = Qt::CustomGesture;
+const int CustomGesture::SerialMaybeThreshold = 1;
+const int CustomGesture::SerialStartedThreshold = 3;
+const int CustomGesture::SerialFinishedThreshold = 6;
+
+class CustomEvent : public QEvent
+{
+public:
+ static int EventType;
+
+ CustomEvent(int serial_ = 0)
+ : QEvent(QEvent::Type(CustomEvent::EventType)),
+ serial(serial_), targetObject(0)
+ {
+ }
+
+ int serial;
+ QObject *targetObject;
+ QPoint hotSpot;
+};
+int CustomEvent::EventType = 0;
+
+class CustomGestureRecognizer : public QGestureRecognizer
+{
+public:
+ CustomGestureRecognizer()
+ {
+ CustomEvent::EventType = QEvent::registerEventType();
+ eventsCounter = 0;
+ }
+
+ QGesture* createGesture(QObject *)
+ {
+ return new CustomGesture;
+ }
+
+ QGestureRecognizer::Result filterEvent(QGesture *state, QObject*, QEvent *event)
+ {
+ if (event->type() == CustomEvent::EventType) {
+ QGestureRecognizer::Result result = QGestureRecognizer::ConsumeEventHint;
+ CustomGesture *g = static_cast<CustomGesture*>(state);
+ CustomEvent *e = static_cast<CustomEvent*>(event);
+ g->serial = e->serial;
+ g->setTargetObject(e->targetObject);
+ g->setHotSpot(e->hotSpot);
+ ++eventsCounter;
+ if (g->serial >= CustomGesture::SerialFinishedThreshold)
+ result |= QGestureRecognizer::GestureFinished;
+ else if (g->serial >= CustomGesture::SerialStartedThreshold)
+ result |= QGestureRecognizer::GestureTriggered;
+ else if (g->serial >= CustomGesture::SerialMaybeThreshold)
+ result |= QGestureRecognizer::MaybeGesture;
+ else
+ result = QGestureRecognizer::NotGesture;
+ return result;
+ }
+ return QGestureRecognizer::Ignore;
+ }
+
+ void reset(QGesture *state)
+ {
+ CustomGesture *g = static_cast<CustomGesture*>(state);
+ g->serial = 0;
+ QGestureRecognizer::reset(state);
+ }
+
+ int eventsCounter;
+ QString name;
+};
+
+class GestureWidget : public QWidget
+{
+ Q_OBJECT
+public:
+ GestureWidget(const char *name = 0)
+ {
+ if (name)
+ setObjectName(QLatin1String(name));
+ reset();
+ acceptGestureOverride = false;
+ }
+ void reset()
+ {
+ customEventsReceived = 0;
+ gestureEventsReceived = 0;
+ gestureOverrideEventsReceived = 0;
+ events.clear();
+ overrideEvents.clear();
+ }
+
+ int customEventsReceived;
+ int gestureEventsReceived;
+ int gestureOverrideEventsReceived;
+ struct Events
+ {
+ QList<Qt::GestureType> all;
+ QList<Qt::GestureType> started;
+ QList<Qt::GestureType> updated;
+ QList<Qt::GestureType> finished;
+ QList<Qt::GestureType> canceled;
+
+ void clear()
+ {
+ all.clear();
+ started.clear();
+ updated.clear();
+ finished.clear();
+ canceled.clear();
+ }
+ } events, overrideEvents;
+
+ bool acceptGestureOverride;
+
+protected:
+ bool event(QEvent *event)
+ {
+ Events *eventsPtr = 0;
+ if (event->type() == QEvent::Gesture) {
+ ++gestureEventsReceived;
+ eventsPtr = &events;
+ } else if (event->type() == QEvent::GestureOverride) {
+ ++gestureOverrideEventsReceived;
+ eventsPtr = &overrideEvents;
+ if (acceptGestureOverride)
+ event->accept();
+ }
+ if (eventsPtr) {
+ QGestureEvent *e = static_cast<QGestureEvent*>(event);
+ QList<QGesture*> gestures = e->allGestures();
+ foreach(QGesture *g, gestures) {
+ eventsPtr->all << g->gestureType();
+ switch(g->state()) {
+ case Qt::GestureStarted:
+ eventsPtr->started << g->gestureType();
+ break;
+ case Qt::GestureUpdated:
+ eventsPtr->updated << g->gestureType();
+ break;
+ case Qt::GestureFinished:
+ eventsPtr->finished << g->gestureType();
+ break;
+ case Qt::GestureCanceled:
+ eventsPtr->canceled << g->gestureType();
+ break;
+ default:
+ Q_ASSERT(false);
+ }
+ }
+ } else if (event->type() == CustomEvent::EventType) {
+ ++customEventsReceived;
+ } else {
+ return QWidget::event(event);
+ }
+ return true;
+ }
+};
+
+static void sendCustomGesture(QObject *object)
+{
+ CustomEvent ev;
+ ev.targetObject = object;
+ for (int i = CustomGesture::SerialMaybeThreshold;
+ i <= CustomGesture::SerialFinishedThreshold; ++i) {
+ ev.serial = i;
+ QApplication::sendEvent(object, &ev);
+ }
+}
+
+class tst_Gestures : public QObject
+{
+Q_OBJECT
+
+public:
+ tst_Gestures();
+ virtual ~tst_Gestures();
+
+public slots:
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+
+private slots:
+ void customGesture();
+ void autoCancelingGestures();
+ void gestureOverChild();
+ void multipleWidgetOnlyGestureInTree();
+ void conflictingGestures();
+ void finishedWithoutStarted();
+ void unknownGesture();
+ void graphicsItemGesture();
+};
+
+tst_Gestures::tst_Gestures()
+{
+}
+
+tst_Gestures::~tst_Gestures()
+{
+}
+
+void tst_Gestures::initTestCase()
+{
+ CustomGesture::GestureType = qApp->registerGestureRecognizer(new CustomGestureRecognizer);
+ QVERIFY(CustomGesture::GestureType != Qt::GestureType(0));
+ QVERIFY(CustomGesture::GestureType != Qt::CustomGesture);
+}
+
+void tst_Gestures::cleanupTestCase()
+{
+}
+
+void tst_Gestures::init()
+{
+}
+
+void tst_Gestures::cleanup()
+{
+}
+
+void tst_Gestures::customGesture()
+{
+ GestureWidget widget;
+ widget.grabGesture(CustomGesture::GestureType, Qt::WidgetGesture);
+ sendCustomGesture(&widget);
+
+ static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
+ static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
+ QCOMPARE(widget.customEventsReceived, TotalCustomEventsCount);
+ QCOMPARE(widget.gestureEventsReceived, TotalGestureEventsCount);
+ QCOMPARE(widget.gestureOverrideEventsReceived, 0);
+ QCOMPARE(widget.events.all.size(), TotalGestureEventsCount);
+ for(int i = 0; i < widget.events.all.size(); ++i)
+ QCOMPARE(widget.events.all.at(i), CustomGesture::GestureType);
+ QCOMPARE(widget.events.started.size(), 1);
+ QCOMPARE(widget.events.updated.size(), TotalGestureEventsCount - 2);
+ QCOMPARE(widget.events.finished.size(), 1);
+ QCOMPARE(widget.events.canceled.size(), 0);
+}
+
+void tst_Gestures::autoCancelingGestures()
+{
+ GestureWidget widget;
+ widget.grabGesture(CustomGesture::GestureType, Qt::WidgetGesture);
+ // send partial gesture. The gesture will be in the "maybe" state, but will
+ // never get enough events to fire, so Qt will have to kill it.
+ CustomEvent ev;
+ for (int i = CustomGesture::SerialMaybeThreshold;
+ i < CustomGesture::SerialStartedThreshold; ++i) {
+ ev.serial = i;
+ QApplication::sendEvent(&widget, &ev);
+ }
+ // wait long enough so the gesture manager will cancel the gesture
+ QTest::qWait(5000);
+ QCOMPARE(widget.customEventsReceived, CustomGesture::SerialStartedThreshold - CustomGesture::SerialMaybeThreshold);
+ QCOMPARE(widget.gestureEventsReceived, 0);
+ QCOMPARE(widget.gestureOverrideEventsReceived, 0);
+ QCOMPARE(widget.events.all.size(), 0);
+}
+
+void tst_Gestures::gestureOverChild()
+{
+ GestureWidget widget("widget");
+ QVBoxLayout *l = new QVBoxLayout(&widget);
+ GestureWidget *child = new GestureWidget("child");
+ l->addWidget(child);
+
+ widget.grabGesture(CustomGesture::GestureType, Qt::WidgetGesture);
+
+ sendCustomGesture(child);
+
+ static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
+ static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
+
+ QCOMPARE(child->customEventsReceived, TotalCustomEventsCount);
+ QCOMPARE(widget.customEventsReceived, 0);
+ QCOMPARE(child->gestureEventsReceived, 0);
+ QCOMPARE(child->gestureOverrideEventsReceived, 0);
+ QCOMPARE(widget.gestureEventsReceived, 0);
+ QCOMPARE(widget.gestureOverrideEventsReceived, 0);
+
+ // enable gestures over the children
+ widget.grabGesture(CustomGesture::GestureType, Qt::WidgetWithChildrenGesture);
+
+ widget.reset();
+ child->reset();
+
+ sendCustomGesture(child);
+
+ QCOMPARE(child->customEventsReceived, TotalCustomEventsCount);
+ QCOMPARE(widget.customEventsReceived, 0);
+
+ QCOMPARE(child->gestureEventsReceived, 0);
+ QCOMPARE(child->gestureOverrideEventsReceived, 0);
+ QCOMPARE(widget.gestureEventsReceived, TotalGestureEventsCount);
+ QCOMPARE(widget.gestureOverrideEventsReceived, 0);
+ for(int i = 0; i < widget.events.all.size(); ++i)
+ QCOMPARE(widget.events.all.at(i), CustomGesture::GestureType);
+ QCOMPARE(widget.events.started.size(), 1);
+ QCOMPARE(widget.events.updated.size(), TotalGestureEventsCount - 2);
+ QCOMPARE(widget.events.finished.size(), 1);
+ QCOMPARE(widget.events.canceled.size(), 0);
+}
+
+void tst_Gestures::multipleWidgetOnlyGestureInTree()
+{
+ GestureWidget parent("parent");
+ QVBoxLayout *l = new QVBoxLayout(&parent);
+ GestureWidget *child = new GestureWidget("child");
+ l->addWidget(child);
+
+ parent.grabGesture(CustomGesture::GestureType, Qt::WidgetGesture);
+ child->grabGesture(CustomGesture::GestureType, Qt::WidgetGesture);
+
+ static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
+ static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
+
+ // sending events to the child and making sure there is no conflict
+ sendCustomGesture(child);
+
+ QCOMPARE(child->customEventsReceived, TotalCustomEventsCount);
+ QCOMPARE(parent.customEventsReceived, 0);
+ QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
+ QCOMPARE(child->gestureOverrideEventsReceived, 0);
+ QCOMPARE(parent.gestureEventsReceived, 0);
+ QCOMPARE(parent.gestureOverrideEventsReceived, 0);
+
+ parent.reset();
+ child->reset();
+
+ // same for the parent widget
+ sendCustomGesture(&parent);
+
+ QCOMPARE(child->customEventsReceived, 0);
+ QCOMPARE(parent.customEventsReceived, TotalCustomEventsCount);
+ QCOMPARE(child->gestureEventsReceived, 0);
+ QCOMPARE(child->gestureOverrideEventsReceived, 0);
+ QCOMPARE(parent.gestureEventsReceived, TotalGestureEventsCount);
+ QCOMPARE(parent.gestureOverrideEventsReceived, 0);
+}
+
+void tst_Gestures::conflictingGestures()
+{
+ GestureWidget parent("parent");
+ QVBoxLayout *l = new QVBoxLayout(&parent);
+ GestureWidget *child = new GestureWidget("child");
+ l->addWidget(child);
+
+ parent.grabGesture(CustomGesture::GestureType, Qt::WidgetWithChildrenGesture);
+ child->grabGesture(CustomGesture::GestureType, Qt::WidgetWithChildrenGesture);
+
+ static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
+
+ // child accepts the override, parent will not receive anything
+ parent.acceptGestureOverride = false;
+ child->acceptGestureOverride = true;
+
+ // sending events to the child and making sure there is no conflict
+ sendCustomGesture(child);
+
+ QCOMPARE(child->gestureOverrideEventsReceived, TotalGestureEventsCount);
+ QCOMPARE(child->gestureEventsReceived, 0);
+ QCOMPARE(parent.gestureOverrideEventsReceived, 0);
+ QCOMPARE(parent.gestureEventsReceived, 0);
+
+ parent.reset();
+ child->reset();
+
+ // parent accepts the override
+ parent.acceptGestureOverride = true;
+ child->acceptGestureOverride = false;
+
+ // sending events to the child and making sure there is no conflict
+ sendCustomGesture(child);
+
+ QCOMPARE(child->gestureOverrideEventsReceived, TotalGestureEventsCount);
+ QCOMPARE(child->gestureEventsReceived, 0);
+ QCOMPARE(parent.gestureOverrideEventsReceived, TotalGestureEventsCount);
+ QCOMPARE(parent.gestureEventsReceived, 0);
+
+ parent.reset();
+ child->reset();
+
+ // nobody accepts the override, we will send normal events to the closest context (to the child)
+ parent.acceptGestureOverride = false;
+ child->acceptGestureOverride = false;
+
+ // sending events to the child and making sure there is no conflict
+ sendCustomGesture(child);
+
+ QCOMPARE(child->gestureOverrideEventsReceived, TotalGestureEventsCount);
+ QCOMPARE(child->gestureEventsReceived, TotalGestureEventsCount);
+ QCOMPARE(parent.gestureOverrideEventsReceived, TotalGestureEventsCount);
+ QCOMPARE(parent.gestureEventsReceived, 0);
+}
+
+void tst_Gestures::finishedWithoutStarted()
+{
+ GestureWidget widget;
+ widget.grabGesture(CustomGesture::GestureType, Qt::WidgetGesture);
+ // the gesture will claim it finished, but it was never started.
+ CustomEvent ev;
+ QTest::ignoreMessage(QtWarningMsg, "QGestureManager::filterEvent: some gestures were finished even though they've never started");
+ for (int i = CustomGesture::SerialFinishedThreshold;
+ i < CustomGesture::SerialFinishedThreshold+1; ++i) {
+ ev.serial = i;
+ QApplication::sendEvent(&widget, &ev);
+ }
+
+ QCOMPARE(widget.gestureEventsReceived, 0);
+ QCOMPARE(widget.gestureOverrideEventsReceived, 0);
+}
+
+void tst_Gestures::unknownGesture()
+{
+ GestureWidget widget;
+ widget.grabGesture(CustomGesture::GestureType, Qt::WidgetGesture);
+ widget.grabGesture(Qt::CustomGesture, Qt::WidgetGesture);
+ widget.grabGesture(Qt::GestureType(Qt::PanGesture+512), Qt::WidgetGesture);
+
+ sendCustomGesture(&widget);
+
+ static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
+
+ QCOMPARE(widget.gestureEventsReceived, TotalGestureEventsCount);
+}
+
+class GestureItem : public QGraphicsObject
+{
+public:
+ GestureItem()
+ {
+ size = QRectF(0, 0, 100, 100);
+ customEventsReceived = 0;
+ gestureEventsReceived = 0;
+ gestureOverrideEventsReceived = 0;
+ events.clear();
+ overrideEvents.clear();
+ acceptGestureOverride = false;
+ }
+
+ int customEventsReceived;
+ int gestureEventsReceived;
+ int gestureOverrideEventsReceived;
+ struct Events
+ {
+ QList<Qt::GestureType> all;
+ QList<Qt::GestureType> started;
+ QList<Qt::GestureType> updated;
+ QList<Qt::GestureType> finished;
+ QList<Qt::GestureType> canceled;
+
+ void clear()
+ {
+ all.clear();
+ started.clear();
+ updated.clear();
+ finished.clear();
+ canceled.clear();
+ }
+ } events, overrideEvents;
+
+ bool acceptGestureOverride;
+
+ QRectF size;
+
+protected:
+ QRectF boundingRect() const
+ {
+ return size;
+ }
+ void paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *)
+ {
+ p->fillRect(boundingRect(), Qt::blue);
+ }
+
+ bool event(QEvent *event)
+ {
+ Events *eventsPtr = 0;
+ if (event->type() == QEvent::Gesture) {
+ ++gestureEventsReceived;
+ eventsPtr = &events;
+ } else if (event->type() == QEvent::GestureOverride) {
+ ++gestureOverrideEventsReceived;
+ eventsPtr = &overrideEvents;
+ if (acceptGestureOverride)
+ event->accept();
+ }
+ if (eventsPtr) {
+ QGestureEvent *e = static_cast<QGestureEvent*>(event);
+ QList<QGesture*> gestures = e->allGestures();
+ foreach(QGesture *g, gestures) {
+ eventsPtr->all << g->gestureType();
+ switch(g->state()) {
+ case Qt::GestureStarted:
+ eventsPtr->started << g->gestureType();
+ break;
+ case Qt::GestureUpdated:
+ eventsPtr->updated << g->gestureType();
+ break;
+ case Qt::GestureFinished:
+ eventsPtr->finished << g->gestureType();
+ break;
+ case Qt::GestureCanceled:
+ eventsPtr->canceled << g->gestureType();
+ break;
+ default:
+ Q_ASSERT(false);
+ }
+ }
+ } else if (event->type() == CustomEvent::EventType) {
+ ++customEventsReceived;
+ } else {
+ return QGraphicsObject::event(event);
+ }
+ return true;
+ }
+};
+
+void tst_Gestures::graphicsItemGesture()
+{
+ QGraphicsScene scene;
+ QGraphicsView view(&scene);
+
+ GestureItem *item = new GestureItem;
+ scene.addItem(item);
+ item->setPos(100, 100);
+
+ item->grabGesture(CustomGesture::GestureType);
+
+ sendCustomGesture(item);
+
+ static const int TotalGestureEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialStartedThreshold + 1;
+ static const int TotalCustomEventsCount = CustomGesture::SerialFinishedThreshold - CustomGesture::SerialMaybeThreshold + 1;
+
+ QCOMPARE(item->customEventsReceived, TotalCustomEventsCount);
+ QCOMPARE(item->gestureEventsReceived, TotalGestureEventsCount);
+ QCOMPARE(item->gestureOverrideEventsReceived, 0);
+ QCOMPARE(item->events.all.size(), TotalGestureEventsCount);
+ for(int i = 0; i < item->events.all.size(); ++i)
+ QCOMPARE(item->events.all.at(i), CustomGesture::GestureType);
+ QCOMPARE(item->events.started.size(), 1);
+ QCOMPARE(item->events.updated.size(), TotalGestureEventsCount - 2);
+ QCOMPARE(item->events.finished.size(), 1);
+ QCOMPARE(item->events.canceled.size(), 0);
+}
+
+QTEST_MAIN(tst_Gestures)
+#include "tst_gestures.moc"
diff --git a/tests/manual/gestures/graphicsview/gestures.cpp b/tests/manual/gestures/graphicsview/gestures.cpp
new file mode 100644
index 0000000..c888aa1
--- /dev/null
+++ b/tests/manual/gestures/graphicsview/gestures.cpp
@@ -0,0 +1,90 @@
+#include "gestures.h"
+
+#include <QTouchEvent>
+
+Qt::GestureType ThreeFingerSlideGesture::Type = Qt::CustomGesture;
+
+QGesture *ThreeFingerSlideGestureRecognizer::createGesture(QObject *)
+{
+ return new ThreeFingerSlideGesture;
+}
+
+QGestureRecognizer::Result ThreeFingerSlideGestureRecognizer::filterEvent(QGesture *state, QObject *, QEvent *event)
+{
+ ThreeFingerSlideGesture *d = static_cast<ThreeFingerSlideGesture *>(state);
+ QGestureRecognizer::Result result;
+ switch (event->type()) {
+ case QEvent::TouchBegin:
+ result = QGestureRecognizer::MaybeGesture;
+ case QEvent::TouchEnd:
+ if (d->gestureFired)
+ result = QGestureRecognizer::GestureFinished;
+ else
+ result = QGestureRecognizer::NotGesture;
+ case QEvent::TouchUpdate:
+ if (d->state() != Qt::NoGesture) {
+ QTouchEvent *ev = static_cast<QTouchEvent*>(event);
+ if (ev->touchPoints().size() == 3) {
+ d->gestureFired = true;
+ result = QGestureRecognizer::GestureTriggered;
+ } else {
+ result = QGestureRecognizer::MaybeGesture;
+ for (int i = 0; i < ev->touchPoints().size(); ++i) {
+ const QTouchEvent::TouchPoint &pt = ev->touchPoints().at(i);
+ const int distance = (pt.pos().toPoint() - pt.startPos().toPoint()).manhattanLength();
+ if (distance > 20) {
+ result = QGestureRecognizer::NotGesture;
+ }
+ }
+ }
+ } else {
+ result = QGestureRecognizer::NotGesture;
+ }
+
+ break;
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseMove:
+ if (d->state() != Qt::NoGesture)
+ result = QGestureRecognizer::Ignore;
+ else
+ result = QGestureRecognizer::NotGesture;
+ break;
+ default:
+ result = QGestureRecognizer::Ignore;
+ break;
+ }
+ return result;
+}
+
+void ThreeFingerSlideGestureRecognizer::reset(QGesture *state)
+{
+ static_cast<ThreeFingerSlideGesture *>(state)->gestureFired = false;
+ QGestureRecognizer::reset(state);
+}
+
+
+QGesture *RotateGestureRecognizer::createGesture(QObject *)
+{
+ return new QGesture;
+}
+
+QGestureRecognizer::Result RotateGestureRecognizer::filterEvent(QGesture *, QObject *, QEvent *event)
+{
+ switch (event->type()) {
+ case QEvent::TouchBegin:
+ case QEvent::TouchEnd:
+ case QEvent::TouchUpdate:
+ break;
+ default:
+ break;
+ }
+ return QGestureRecognizer::Ignore;
+}
+
+void RotateGestureRecognizer::reset(QGesture *state)
+{
+ QGestureRecognizer::reset(state);
+}
+
+#include "moc_gestures.cpp"
diff --git a/tests/manual/gestures/graphicsview/gestures.h b/tests/manual/gestures/graphicsview/gestures.h
new file mode 100644
index 0000000..630a7ef
--- /dev/null
+++ b/tests/manual/gestures/graphicsview/gestures.h
@@ -0,0 +1,37 @@
+#ifndef GESTURE_H
+#define GESTURE_H
+
+#include <QGestureRecognizer>
+#include <QGesture>
+
+class ThreeFingerSlideGesture : public QGesture
+{
+ Q_OBJECT
+public:
+ static Qt::GestureType Type;
+
+ ThreeFingerSlideGesture(QObject *parent = 0) : QGesture(parent) { }
+
+ bool gestureFired;
+};
+
+class ThreeFingerSlideGestureRecognizer : public QGestureRecognizer
+{
+private:
+ QGesture* createGesture(QObject *target);
+ QGestureRecognizer::Result filterEvent(QGesture *state, QObject *watched, QEvent *event);
+ void reset(QGesture *state);
+};
+
+class RotateGestureRecognizer : public QGestureRecognizer
+{
+public:
+ RotateGestureRecognizer();
+
+private:
+ QGesture* createGesture(QObject *target);
+ QGestureRecognizer::Result filterEvent(QGesture *state, QObject *watched, QEvent *event);
+ void reset(QGesture *state);
+};
+
+#endif // GESTURE_H
diff --git a/tests/manual/gestures/graphicsview/graphicsview.pro b/tests/manual/gestures/graphicsview/graphicsview.pro
new file mode 100644
index 0000000..a40c323
--- /dev/null
+++ b/tests/manual/gestures/graphicsview/graphicsview.pro
@@ -0,0 +1,17 @@
+# #####################################################################
+# Automatically generated by qmake (2.01a) Mon Sep 7 13:26:43 2009
+# #####################################################################
+TEMPLATE = app
+TARGET =
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# Input
+SOURCES += main.cpp \
+ imageitem.cpp \
+ gestures.cpp \
+ mousepangesturerecognizer.cpp
+
+HEADERS += imageitem.h \
+ gestures.h \
+ mousepangesturerecognizer.h
diff --git a/tests/manual/gestures/graphicsview/imageitem.cpp b/tests/manual/gestures/graphicsview/imageitem.cpp
new file mode 100644
index 0000000..d6f406c
--- /dev/null
+++ b/tests/manual/gestures/graphicsview/imageitem.cpp
@@ -0,0 +1,52 @@
+#include "imageitem.h"
+#include "gestures.h"
+
+#include <QPainter>
+#include <QEvent>
+
+ImageItem::ImageItem(const QImage &image)
+{
+ setImage(image);
+}
+
+void ImageItem::setImage(const QImage &image)
+{
+ image_ = image;
+ pixmap_ = QPixmap::fromImage(image.scaled(400, 400, Qt::KeepAspectRatio));
+ update();
+}
+
+QImage ImageItem::image() const
+{
+ return image_;
+}
+
+QRectF ImageItem::boundingRect() const
+{
+ const QSize size = pixmap_.size();
+ return QRectF(0, 0, size.width(), size.height());
+}
+
+void ImageItem::paint(QPainter *painter, const QStyleOptionGraphicsItem*, QWidget*)
+{
+ painter->drawPixmap(0, 0, pixmap_);
+}
+
+
+GestureImageItem::GestureImageItem(const QImage &image)
+ : ImageItem(image)
+{
+ grabGesture(Qt::PanGesture);
+ grabGesture(ThreeFingerSlideGesture::Type);
+}
+
+bool GestureImageItem::event(QEvent *event)
+{
+ if (event->type() == QEvent::Gesture) {
+ qDebug("gestureimageitem: gesture triggered");
+ return true;
+ }
+ return ImageItem::event(event);
+}
+
+#include "moc_imageitem.cpp"
diff --git a/tests/manual/gestures/graphicsview/imageitem.h b/tests/manual/gestures/graphicsview/imageitem.h
new file mode 100644
index 0000000..ad0e397
--- /dev/null
+++ b/tests/manual/gestures/graphicsview/imageitem.h
@@ -0,0 +1,36 @@
+#ifndef IMAGEITEM_H
+#define IMAGEITEM_H
+
+#include <QGraphicsItem>
+#include <QImage>
+#include <QPixmap>
+#include <QTransform>
+
+class ImageItem : public QGraphicsObject
+{
+ Q_OBJECT
+public:
+ ImageItem(const QImage &image);
+ void setImage(const QImage &image);
+ QImage image() const;
+ QRectF boundingRect() const;
+ void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
+
+private:
+ QImage image_;
+ QPixmap pixmap_;
+ QTransform transform;
+};
+
+class GestureImageItem : public ImageItem
+{
+ Q_OBJECT
+
+public:
+ GestureImageItem(const QImage &image);
+
+protected:
+ bool event(QEvent *event);
+};
+
+#endif // IMAGEITEM_H
diff --git a/tests/manual/gestures/graphicsview/main.cpp b/tests/manual/gestures/graphicsview/main.cpp
new file mode 100644
index 0000000..1db5614
--- /dev/null
+++ b/tests/manual/gestures/graphicsview/main.cpp
@@ -0,0 +1,187 @@
+#include <QtGui>
+
+#include "imageitem.h"
+#include "gestures.h"
+#include "mousepangesturerecognizer.h"
+
+class GraphicsView : public QGraphicsView
+{
+public:
+ GraphicsView(QGraphicsScene *scene, QWidget *parent = 0)
+ : QGraphicsView(scene, parent)
+ {
+ }
+protected:
+ bool viewportEvent(QEvent *event)
+ {
+ if (event->type() == QEvent::Gesture) {
+ QGestureEvent *ge = static_cast<QGestureEvent *>(event);
+ if (QPanGesture *pan = static_cast<QPanGesture *>(ge->gesture(Qt::PanGesture))) {
+ switch (pan->state()) {
+ case Qt::GestureStarted: qDebug("view: Pan: started"); break;
+ case Qt::GestureFinished: qDebug("view: Pan: finished"); break;
+ case Qt::GestureCanceled: qDebug("view: Pan: canceled"); break;
+ case Qt::GestureUpdated: break;
+ default: qDebug("view: Pan: <unknown state>"); break;
+ }
+
+ const QSizeF offset = pan->offset();
+ QScrollBar *vbar = verticalScrollBar();
+ QScrollBar *hbar = horizontalScrollBar();
+ vbar->setValue(vbar->value() - offset.height());
+ hbar->setValue(hbar->value() - offset.width());
+ ge->accept(pan);
+ return true;
+ }
+ }
+ return QGraphicsView::viewportEvent(event);
+ }
+};
+
+class StandardGestures : public QWidget
+{
+public:
+ StandardGestures(QWidget *parent = 0)
+ : QWidget(parent)
+ {
+ scene = new QGraphicsScene(this);
+ scene->setSceneRect(-2000, -2000, 4000, 4000);
+ view = new QGraphicsView(scene, 0);
+ QVBoxLayout *l = new QVBoxLayout(this);
+ l->addWidget(view);
+ }
+
+ QGraphicsScene *scene;
+ QGraphicsView *view;
+};
+
+class GlobalViewGestures : public QWidget
+{
+ Q_OBJECT
+public:
+ GlobalViewGestures(QWidget *parent = 0)
+ : QWidget(parent)
+ {
+ scene = new QGraphicsScene(this);
+ scene->setSceneRect(-2000, -2000, 4000, 4000);
+ view = new GraphicsView(scene, 0);
+ view->viewport()->grabGesture(Qt::PanGesture);
+ view->viewport()->grabGesture(ThreeFingerSlideGesture::Type);
+ QVBoxLayout *l = new QVBoxLayout(this);
+ l->addWidget(view);
+ }
+
+ QGraphicsScene *scene;
+ QGraphicsView *view;
+};
+
+class GraphicsItemGestures : public QWidget
+{
+ Q_OBJECT
+public:
+ GraphicsItemGestures(QWidget *parent = 0)
+ : QWidget(parent)
+ {
+ scene = new QGraphicsScene(this);
+ scene->setSceneRect(-2000, -2000, 4000, 4000);
+ view = new QGraphicsView(scene, 0);
+ QVBoxLayout *l = new QVBoxLayout(this);
+ l->addWidget(view);
+ }
+
+ QGraphicsScene *scene;
+ QGraphicsView *view;
+};
+
+class MainWindow : public QMainWindow
+{
+public:
+ MainWindow();
+
+ void setDirectory(const QString &path);
+
+private:
+ QTabWidget *tabWidget;
+ StandardGestures *standardGestures;
+ GlobalViewGestures *globalViewGestures;
+ GraphicsItemGestures *graphicsItemGestures;
+};
+
+MainWindow::MainWindow()
+{
+ (void)qApp->registerGestureRecognizer(new MousePanGestureRecognizer);
+ ThreeFingerSlideGesture::Type = qApp->registerGestureRecognizer(new ThreeFingerSlideGestureRecognizer);
+
+ tabWidget = new QTabWidget;
+
+ standardGestures = new StandardGestures;
+ tabWidget->addTab(standardGestures, "Standard gestures");
+
+ globalViewGestures = new GlobalViewGestures;
+ tabWidget->addTab(globalViewGestures , "Global gestures");
+
+ graphicsItemGestures = new GraphicsItemGestures;
+ tabWidget->addTab(graphicsItemGestures, "Graphics item gestures");
+
+ setCentralWidget(tabWidget);
+}
+
+void MainWindow::setDirectory(const QString &path)
+{
+ QDir dir(path);
+ QStringList files = dir.entryList(QDir::Files | QDir::Readable | QDir::NoDotAndDotDot);
+ foreach(const QString &file, files) {
+ QImageReader img(path + QLatin1String("/")+file);
+ QImage image = img.read();
+ if (!image.isNull()) {
+ {
+ ImageItem *item = new ImageItem(image);
+ item->setPos(0, 0);
+ item->setFlags(QGraphicsItem::ItemIsMovable);
+ standardGestures->scene->addItem(item);
+ }
+ {
+ ImageItem *item = new ImageItem(image);
+ item->setPos(0, 0);
+ item->setFlags(QGraphicsItem::ItemIsMovable);
+ globalViewGestures->scene->addItem(item);
+ }
+ {
+ GestureImageItem *item = new GestureImageItem(image);
+ item->setPos(0, 0);
+ item->setFlags(QGraphicsItem::ItemIsMovable);
+ graphicsItemGestures->scene->addItem(item);
+ }
+ }
+ }
+
+ {
+ QList<QGraphicsItem*> items = standardGestures->scene->items();
+ if (!items.isEmpty())
+ standardGestures->view->ensureVisible(items.at(0));
+ }
+ {
+ QList<QGraphicsItem*> items = globalViewGestures->scene->items();
+ if (!items.isEmpty())
+ globalViewGestures->view->ensureVisible(items.at(0));
+ }
+ {
+ QList<QGraphicsItem*> items = graphicsItemGestures->scene->items();
+ if (!items.isEmpty())
+ graphicsItemGestures->view->ensureVisible(items.at(0));
+ }
+}
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+ MainWindow window;
+ if (QApplication::arguments().size() > 1)
+ window.setDirectory(QApplication::arguments().at(1));
+ else
+ window.setDirectory(QFileDialog::getExistingDirectory(0, "Select image folder"));
+ window.show();
+ return app.exec();
+}
+
+#include "main.moc"
diff --git a/tests/manual/gestures/graphicsview/mousepangesturerecognizer.cpp b/tests/manual/gestures/graphicsview/mousepangesturerecognizer.cpp
new file mode 100644
index 0000000..f89f247
--- /dev/null
+++ b/tests/manual/gestures/graphicsview/mousepangesturerecognizer.cpp
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mousepangesturerecognizer.h"
+
+#include <QEvent>
+#include <QMouseEvent>
+#include <QGesture>
+
+MousePanGestureRecognizer::MousePanGestureRecognizer()
+{
+}
+
+QGesture* MousePanGestureRecognizer::createGesture(QObject *)
+{
+ return new QPanGesture;
+}
+
+QGestureRecognizer::Result MousePanGestureRecognizer::filterEvent(QGesture *state, QObject *, QEvent *event)
+{
+ QPanGesture *g = static_cast<QPanGesture *>(state);
+ QMouseEvent *me = static_cast<QMouseEvent *>(event);
+ if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick
+ || event->type() == QEvent::GraphicsSceneMousePress || event->type() == QEvent::GraphicsSceneMouseDoubleClick) {
+ g->setHotSpot(me->globalPos());
+ g->setProperty("lastPos", me->globalPos());
+ g->setProperty("pressed", QVariant::fromValue<bool>(true));
+ return QGestureRecognizer::GestureTriggered | QGestureRecognizer::ConsumeEventHint;
+ } else if (event->type() == QEvent::MouseMove || event->type() == QEvent::GraphicsSceneMouseMove) {
+ if (g->property("pressed").toBool()) {
+ QPoint pos = me->globalPos();
+ QPoint lastPos = g->property("lastPos").toPoint();
+ g->setLastOffset(g->offset());
+ lastPos = pos - lastPos;
+ g->setOffset(QSizeF(lastPos.x(), lastPos.y()));
+ g->setTotalOffset(g->totalOffset() + QSizeF(lastPos.x(), lastPos.y()));
+ g->setProperty("lastPos", pos);
+ return QGestureRecognizer::GestureTriggered | QGestureRecognizer::ConsumeEventHint;
+ }
+ return QGestureRecognizer::NotGesture;
+ } else if (event->type() == QEvent::MouseButtonRelease || event->type() == QEvent::GraphicsSceneMouseRelease) {
+ return QGestureRecognizer::GestureFinished | QGestureRecognizer::ConsumeEventHint;
+ }
+ return QGestureRecognizer::Ignore;
+}
+
+void MousePanGestureRecognizer::reset(QGesture *state)
+{
+ QPanGesture *g = static_cast<QPanGesture *>(state);
+ g->setTotalOffset(QSizeF());
+ g->setLastOffset(QSizeF());
+ g->setOffset(QSizeF());
+ g->setAcceleration(0);
+ g->setProperty("lastPos", QVariant());
+ g->setProperty("pressed", QVariant::fromValue<bool>(false));
+ QGestureRecognizer::reset(state);
+}
diff --git a/examples/gestures/imageviewer/tapandholdgesture.h b/tests/manual/gestures/graphicsview/mousepangesturerecognizer.h
index 682342e..e31799e 100644
--- a/examples/gestures/imageviewer/tapandholdgesture.h
+++ b/tests/manual/gestures/graphicsview/mousepangesturerecognizer.h
@@ -39,36 +39,19 @@
**
****************************************************************************/
-#ifndef TAPANDHOLDGESTURE_H
-#define TAPANDHOLDGESTURE_H
+#ifndef MOUSEPANGESTURERECOGNIZER_H
+#define MOUSEPANGESTURERECOGNIZER_H
-#include <QtCore/QBasicTimer>
-#include <QtGui/QGesture>
-#include <QtGui/QWidget>
+#include <QGestureRecognizer>
-class TapAndHoldGesture : public QGesture
+class MousePanGestureRecognizer : public QGestureRecognizer
{
- Q_OBJECT
- Q_PROPERTY(QPoint pos READ pos)
-
public:
- TapAndHoldGesture(QWidget *parent);
-
- bool filterEvent(QEvent *event);
- void reset();
-
- QPoint pos() const;
-
-protected:
- void timerEvent(QTimerEvent *event);
+ MousePanGestureRecognizer();
-private:
- QBasicTimer timer;
- int iteration;
- QPoint position;
- QPoint startPosition;
- static const int iterationCount;
- static const int iterationTimeout;
+ QGesture* createGesture(QObject *target);
+ QGestureRecognizer::Result filterEvent(QGesture *state, QObject *watched, QEvent *event);
+ void reset(QGesture *state);
};
-#endif // TAPANDHOLDGESTURE_H
+#endif // MOUSEPANGESTURERECOGNIZER_H
diff --git a/tests/manual/gestures/pinch/pinch.pro b/tests/manual/gestures/pinch/pinch.pro
deleted file mode 100644
index d1f28cc..0000000
--- a/tests/manual/gestures/pinch/pinch.pro
+++ /dev/null
@@ -1,4 +0,0 @@
-SOURCES = main.cpp \
- pinchwidget.cpp
-HEADERS += pinchwidget.h
-RESOURCES += pinch.qrc
diff --git a/tests/manual/gestures/pinch/pinch.qrc b/tests/manual/gestures/pinch/pinch.qrc
deleted file mode 100644
index 0be9ba1..0000000
--- a/tests/manual/gestures/pinch/pinch.qrc
+++ /dev/null
@@ -1,5 +0,0 @@
-<RCC>
- <qresource prefix="/images" >
- <file>qt-logo.png</file>
- </qresource>
-</RCC>
diff --git a/tests/manual/gestures/pinch/pinchwidget.cpp b/tests/manual/gestures/pinch/pinchwidget.cpp
deleted file mode 100644
index e93c8b5..0000000
--- a/tests/manual/gestures/pinch/pinchwidget.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "pinchwidget.h"
-
-#include <QPainter>
-#include <QImage>
-#include <QPixmap>
-#include <QPanGesture>
-#include <QPinchGesture>
-#include <QPushButton>
-
-PinchWidget::PinchWidget(const QImage &image, QWidget *parent)
- : QWidget(parent)
-{
- setMinimumSize(100,100);
- this->image = image;
- pan = new QPanGesture(this);
- connect(pan, SIGNAL(triggered()), this, SLOT(onPanTriggered()));
- connect(pan, SIGNAL(finished()), this, SLOT(onPanFinished()));
- pinch = new QPinchGesture(this);
- connect(pinch, SIGNAL(triggered()), this, SLOT(onPinchTriggered()));
- connect(pinch, SIGNAL(finished()), this, SLOT(onPinchFinished()));
-}
-
-QSize PinchWidget::sizeHint() const
-{
- return image.size()*1.5;
-}
-
-void PinchWidget::paintEvent(QPaintEvent *)
-{
- QPainter p(this);
- QTransform t = worldTransform * currentPanTransform * currentPinchTransform;
- p.setTransform(t);
- QPoint center = QPoint(width()/2, height()/2);
- QPoint size = QPoint(image.width()/2, image.height()/2);
- p.translate(center - size);
- p.drawImage(QPoint(0,0), image);
-}
-
-void PinchWidget::acceptTouchEvents()
-{
- setAttribute(Qt::WA_AcceptTouchEvents);
- if (QWidget *w = qobject_cast<QPushButton*>(sender()))
- w->setEnabled(false);
-}
-
-void PinchWidget::onPanTriggered()
-{
- currentPanTransform = QTransform()
- .translate(pan->totalOffset().width(),
- pan->totalOffset().height());
- update();
-}
-
-void PinchWidget::onPanFinished()
-{
- worldTransform *= currentPanTransform;
- currentPanTransform.reset();
- update();
-}
-
-void PinchWidget::onPinchTriggered()
-{
- QPoint transformCenter = worldTransform.map(QPoint(width()/2, height()/2));
- currentPinchTransform = QTransform()
- .translate(transformCenter.x(), transformCenter.y())
- .scale(pinch->totalScaleFactor(), pinch->totalScaleFactor())
- .rotate(pinch->totalRotationAngle())
- .translate(-transformCenter.x(), -transformCenter.y());
- update();
-}
-
-void PinchWidget::onPinchFinished()
-{
- worldTransform *= currentPinchTransform;
- currentPinchTransform.reset();
- update();
-}
diff --git a/tests/manual/gestures/pinch/qt-logo.png b/tests/manual/gestures/pinch/qt-logo.png
deleted file mode 100644
index 7d3e97e..0000000
--- a/tests/manual/gestures/pinch/qt-logo.png
+++ /dev/null
Binary files differ
diff --git a/tests/manual/gestures/scrollarea/main.cpp b/tests/manual/gestures/scrollarea/main.cpp
new file mode 100644
index 0000000..e2fa4d3
--- /dev/null
+++ b/tests/manual/gestures/scrollarea/main.cpp
@@ -0,0 +1,188 @@
+#include <QtGui>
+
+#include "mousepangesturerecognizer.h"
+
+class ScrollArea : public QScrollArea
+{
+ Q_OBJECT
+public:
+ ScrollArea(QWidget *parent = 0)
+ : QScrollArea(parent), outside(false)
+ {
+ viewport()->grabGesture(Qt::PanGesture);
+ }
+
+protected:
+ bool viewportEvent(QEvent *event)
+ {
+ if (event->type() == QEvent::Gesture) {
+ gestureEvent(static_cast<QGestureEvent *>(event));
+ return true;
+ } else if (event->type() == QEvent::GestureOverride) {
+ QGestureEvent *ge = static_cast<QGestureEvent *>(event);
+ if (QPanGesture *pan = static_cast<QPanGesture *>(ge->gesture(Qt::PanGesture)))
+ if (pan->state() == Qt::GestureStarted) {
+ outside = false;
+ }
+ }
+ return QScrollArea::viewportEvent(event);
+ }
+ void gestureEvent(QGestureEvent *event)
+ {
+ QPanGesture *pan = static_cast<QPanGesture *>(event->gesture(Qt::PanGesture));
+ if (pan) {
+ switch(pan->state()) {
+ case Qt::GestureStarted: qDebug("area: Pan: started"); break;
+ case Qt::GestureFinished: qDebug("area: Pan: finished"); break;
+ case Qt::GestureCanceled: qDebug("area: Pan: canceled"); break;
+ case Qt::GestureUpdated: break;
+ default: qDebug("area: Pan: <unknown state>"); break;
+ }
+
+ if (pan->state() == Qt::GestureStarted)
+ outside = false;
+ event->ignore();
+ event->ignore(pan);
+ if (outside)
+ return;
+
+ const QSizeF offset = pan->offset();
+ const QSizeF totalOffset = pan->totalOffset();
+ QScrollBar *vbar = verticalScrollBar();
+ QScrollBar *hbar = horizontalScrollBar();
+
+ if ((vbar->value() == vbar->minimum() && totalOffset.height() > 10) ||
+ (vbar->value() == vbar->maximum() && totalOffset.height() < -10)) {
+ outside = true;
+ return;
+ }
+ if ((hbar->value() == hbar->minimum() && totalOffset.width() > 10) ||
+ (hbar->value() == hbar->maximum() && totalOffset.width() < -10)) {
+ outside = true;
+ return;
+ }
+ vbar->setValue(vbar->value() - offset.height());
+ hbar->setValue(hbar->value() - offset.width());
+ event->accept(pan);
+ }
+ }
+
+private:
+ bool outside;
+};
+
+class Slider : public QSlider
+{
+public:
+ Slider(Qt::Orientation orientation, QWidget *parent = 0)
+ : QSlider(orientation, parent)
+ {
+ grabGesture(Qt::PanGesture);
+ }
+protected:
+ bool event(QEvent *event)
+ {
+ if (event->type() == QEvent::Gesture) {
+ gestureEvent(static_cast<QGestureEvent *>(event));
+ return true;
+ }
+ return QSlider::event(event);
+ }
+ void gestureEvent(QGestureEvent *event)
+ {
+ QPanGesture *pan = static_cast<QPanGesture *>(event->gesture(Qt::PanGesture));
+ if (pan) {
+ switch (pan->state()) {
+ case Qt::GestureStarted: qDebug("slider: Pan: started"); break;
+ case Qt::GestureFinished: qDebug("slider: Pan: finished"); break;
+ case Qt::GestureCanceled: qDebug("slider: Pan: canceled"); break;
+ case Qt::GestureUpdated: break;
+ default: qDebug("slider: Pan: <unknown state>"); break;
+ }
+
+ if (pan->state() == Qt::GestureStarted)
+ outside = false;
+ event->ignore();
+ event->ignore(pan);
+ if (outside)
+ return;
+ const QSizeF offset = pan->offset();
+ const QSizeF totalOffset = pan->totalOffset();
+ if (orientation() == Qt::Horizontal) {
+ if ((value() == minimum() && totalOffset.width() < -10) ||
+ (value() == maximum() && totalOffset.width() > 10)) {
+ outside = true;
+ return;
+ }
+ if (totalOffset.height() < 40 && totalOffset.height() > -40) {
+ setValue(value() + offset.width());
+ event->accept(pan);
+ } else {
+ outside = true;
+ }
+ } else if (orientation() == Qt::Vertical) {
+ if ((value() == maximum() && totalOffset.height() < -10) ||
+ (value() == minimum() && totalOffset.height() > 10)) {
+ outside = true;
+ return;
+ }
+ if (totalOffset.width() < 40 && totalOffset.width() > -40) {
+ setValue(value() - offset.height());
+ event->accept(pan);
+ } else {
+ outside = true;
+ }
+ }
+ }
+ }
+private:
+ bool outside;
+};
+
+class MainWindow : public QMainWindow
+{
+public:
+ MainWindow()
+ {
+ rootScrollArea = new ScrollArea;
+ setCentralWidget(rootScrollArea);
+
+ QWidget *root = new QWidget;
+ root->setFixedSize(3000, 3000);
+ rootScrollArea->setWidget(root);
+
+ Slider *verticalSlider = new Slider(Qt::Vertical, root);
+ verticalSlider ->move(650, 1100);
+ Slider *horizontalSlider = new Slider(Qt::Horizontal, root);
+ horizontalSlider ->move(600, 1000);
+
+ childScrollArea = new ScrollArea(root);
+ childScrollArea->move(500, 500);
+ QWidget *w = new QWidget;
+ w->setMinimumWidth(400);
+ QVBoxLayout *l = new QVBoxLayout(w);
+ l->setMargin(20);
+ for (int i = 0; i < 100; ++i) {
+ QWidget *w = new QWidget;
+ QHBoxLayout *ll = new QHBoxLayout(w);
+ ll->addWidget(new QLabel(QString("Label %1").arg(i)));
+ ll->addWidget(new QPushButton(QString("Button %1").arg(i)));
+ l->addWidget(w);
+ }
+ childScrollArea->setWidget(w);
+ }
+private:
+ ScrollArea *rootScrollArea;
+ ScrollArea *childScrollArea;
+};
+
+int main(int argc, char **argv)
+{
+ QApplication app(argc, argv);
+ app.registerGestureRecognizer(new MousePanGestureRecognizer);
+ MainWindow w;
+ w.show();
+ return app.exec();
+}
+
+#include "main.moc"
diff --git a/tests/manual/gestures/scrollarea/mousepangesturerecognizer.cpp b/tests/manual/gestures/scrollarea/mousepangesturerecognizer.cpp
new file mode 100644
index 0000000..6e2171c
--- /dev/null
+++ b/tests/manual/gestures/scrollarea/mousepangesturerecognizer.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the examples of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "mousepangesturerecognizer.h"
+
+#include <QEvent>
+#include <QMouseEvent>
+#include <QGesture>
+
+MousePanGestureRecognizer::MousePanGestureRecognizer()
+{
+}
+
+QGesture* MousePanGestureRecognizer::createGesture(QObject *) const
+{
+ return new QPanGesture;
+}
+
+QGestureRecognizer::Result MousePanGestureRecognizer::filterEvent(QGesture *state, QObject *, QEvent *event)
+{
+ QPanGesture *g = static_cast<QPanGesture *>(state);
+ QMouseEvent *me = static_cast<QMouseEvent *>(event);
+ if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonDblClick) {
+ g->setHotSpot(me->globalPos());
+ g->setProperty("lastPos", me->globalPos());
+ g->setProperty("pressed", QVariant::fromValue<bool>(true));
+ return QGestureRecognizer::GestureTriggered | QGestureRecognizer::ConsumeEventHint;
+ } else if (event->type() == QEvent::MouseMove) {
+ if (g->property("pressed").toBool()) {
+ QPoint pos = me->globalPos();
+ QPoint lastPos = g->property("lastPos").toPoint();
+ g->setLastOffset(g->offset());
+ lastPos = pos - lastPos;
+ g->setOffset(QSizeF(lastPos.x(), lastPos.y()));
+ g->setTotalOffset(g->totalOffset() + QSizeF(lastPos.x(), lastPos.y()));
+ g->setProperty("lastPos", pos);
+ return QGestureRecognizer::GestureTriggered | QGestureRecognizer::ConsumeEventHint;
+ }
+ return QGestureRecognizer::NotGesture;
+ } else if (event->type() == QEvent::MouseButtonRelease) {
+ return QGestureRecognizer::GestureFinished | QGestureRecognizer::ConsumeEventHint;
+ }
+ return QGestureRecognizer::Ignore;
+}
+
+void MousePanGestureRecognizer::reset(QGesture *state)
+{
+ QPanGesture *g = static_cast<QPanGesture *>(state);
+ g->setTotalOffset(QSizeF());
+ g->setLastOffset(QSizeF());
+ g->setOffset(QSizeF());
+ g->setAcceleration(0);
+ g->setProperty("lastPos", QVariant());
+ g->setProperty("pressed", QVariant::fromValue<bool>(false));
+ QGestureRecognizer::reset(state);
+}
diff --git a/tests/manual/gestures/pinch/main.cpp b/tests/manual/gestures/scrollarea/mousepangesturerecognizer.h
index 4d9c14c..f6df289 100644
--- a/tests/manual/gestures/pinch/main.cpp
+++ b/tests/manual/gestures/scrollarea/mousepangesturerecognizer.h
@@ -4,7 +4,7 @@
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
-** This file is part of the test suite of the Qt Toolkit.
+** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
@@ -39,30 +39,19 @@
**
****************************************************************************/
-#include <QtGui>
-#include "pinchwidget.h"
+#ifndef MOUSEPANGESTURERECOGNIZER_H
+#define MOUSEPANGESTURERECOGNIZER_H
-class MainWindow : public QWidget
+#include <QGestureRecognizer>
+
+class MousePanGestureRecognizer : public QGestureRecognizer
{
public:
- MainWindow();
-};
+ MousePanGestureRecognizer();
-MainWindow::MainWindow()
-{
- QVBoxLayout *l = new QVBoxLayout(this);
- QPushButton *btn = new QPushButton(QLatin1String("AcceptTouchEvents"));
- l->addWidget(btn);
- QImage image(":/images/qt-logo.png");
- PinchWidget *w = new PinchWidget(image);
- l->addWidget(w);
- connect(btn, SIGNAL(clicked()), w, SLOT(acceptTouchEvents()));
-}
+ QGesture* createGesture(QObject *target) const;
+ QGestureRecognizer::Result filterEvent(QGesture *state, QObject *watched, QEvent *event);
+ void reset(QGesture *state);
+};
-int main(int argc, char *argv[])
-{
- QApplication app(argc, argv);
- MainWindow w;
- w.show();
- return app.exec();
-}
+#endif // MOUSEPANGESTURERECOGNIZER_H
diff --git a/tests/manual/gestures/scrollarea/scrollarea.pro b/tests/manual/gestures/scrollarea/scrollarea.pro
new file mode 100644
index 0000000..554810e
--- /dev/null
+++ b/tests/manual/gestures/scrollarea/scrollarea.pro
@@ -0,0 +1,3 @@
+SOURCES = main.cpp \
+ mousepangesturerecognizer.cpp
+HEADERS += mousepangesturerecognizer.h
diff --git a/tests/manual/gestures/twopanwidgets/main.cpp b/tests/manual/gestures/twopanwidgets/main.cpp
deleted file mode 100644
index 20a35fc..0000000
--- a/tests/manual/gestures/twopanwidgets/main.cpp
+++ /dev/null
@@ -1,135 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the test suite of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <QtGui>
-
-static const char text[] =
- "Hello world! This is just a lot of text with to make sure scrollbar appear";
-
-class TextEdit : public QTextEdit
-{
- Q_OBJECT
-public Q_SLOTS:
- void acceptTouch()
- {
- viewport()->setAttribute(Qt::WA_AcceptTouchEvents);
- if (QWidget *w = qobject_cast<QPushButton*>(sender()))
- w->setEnabled(false);
- }
-};
-
-class PlainTextEdit : public QPlainTextEdit
-{
- Q_OBJECT
-public Q_SLOTS:
- void acceptTouch()
- {
- viewport()->setAttribute(Qt::WA_AcceptTouchEvents);
- if (QWidget *w = qobject_cast<QPushButton*>(sender()))
- w->setEnabled(false);
- }
-};
-
-class MainWindow : public QMainWindow
-{
-public:
- MainWindow();
-};
-
-MainWindow::MainWindow()
-{
- QTabWidget *tw = new QTabWidget;
- setCentralWidget(tw);
- {
- QWidget *tab = new QWidget;
- QGridLayout *layout = new QGridLayout(tab);
- QTextEdit *edit1 = new TextEdit;
- QTextEdit *edit2 = new TextEdit;
- QString text1 = QString(text).replace(' ', '\n');
- for (int i = 0; i < 5; ++i) text1 += text1;
- QString text2 = QString(text);
- for (int i = 0; i < 5; ++i) text2 += text2;
- edit1->setPlainText(text1);
- edit2->setPlainText(text2);
- edit2->setWordWrapMode(QTextOption::NoWrap);
- QPushButton *btn1 = new QPushButton(QLatin1String("AcceptTouchEvents"));
- connect(btn1, SIGNAL(clicked()), edit1, SLOT(acceptTouch()));
- QPushButton *btn2 = new QPushButton(QLatin1String("AcceptTouchEvents"));
- connect(btn2, SIGNAL(clicked()), edit2, SLOT(acceptTouch()));
- layout->addWidget(btn1, 0, 0);
- layout->addWidget(btn2, 0, 1);
- layout->addWidget(edit1, 1, 0);
- layout->addWidget(edit2, 1, 1);
- tw->addTab(tab, QLatin1String("QTextEdit"));
- }
- {
- QWidget *tab = new QWidget;
- QGridLayout *layout = new QGridLayout(tab);
- QPlainTextEdit *edit1 = new PlainTextEdit;
- QPlainTextEdit *edit2 = new PlainTextEdit;
- QString text1 = QString(text).replace(' ', '\n');
- for (int i = 0; i < 5; ++i) text1 += text1;
- QString text2 = QString(text);
- for (int i = 0; i < 5; ++i) text2 += text2;
- edit1->setPlainText(text1);
- edit2->setPlainText(text2);
- edit2->setWordWrapMode(QTextOption::NoWrap);
- QPushButton *btn1 = new QPushButton(QLatin1String("AcceptTouchEvents"));
- connect(btn1, SIGNAL(clicked()), edit1, SLOT(acceptTouch()));
- QPushButton *btn2 = new QPushButton(QLatin1String("AcceptTouchEvents"));
- connect(btn2, SIGNAL(clicked()), edit2, SLOT(acceptTouch()));
- layout->addWidget(btn1, 0, 0);
- layout->addWidget(btn2, 0, 1);
- layout->addWidget(edit1, 1, 0);
- layout->addWidget(edit2, 1, 1);
- tw->addTab(tab, QLatin1String("QPlainTextEdit"));
- }
-}
-
-int main(int argc, char **argv)
-{
- QApplication app(argc, argv);
- MainWindow window;
- window.show();
- return app.exec();
-}
-
-#include "main.moc"
diff --git a/tests/manual/gestures/twopanwidgets/twopanwidgets.pro b/tests/manual/gestures/twopanwidgets/twopanwidgets.pro
deleted file mode 100644
index 5254077..0000000
--- a/tests/manual/gestures/twopanwidgets/twopanwidgets.pro
+++ /dev/null
@@ -1 +0,0 @@
-SOURCES = main.cpp \ No newline at end of file