summaryrefslogtreecommitdiffstats
path: root/src/gui/kernel
diff options
context:
space:
mode:
authorDenis Dzyubenko <denis.dzyubenko@nokia.com>2009-02-26 14:39:00 (GMT)
committerDenis Dzyubenko <denis.dzyubenko@nokia.com>2009-05-11 13:38:54 (GMT)
commita3d8cfb1ee89e0600add864db53d67552820b95a (patch)
treed396d751de49d26c052b8752c94d5247503083e2 /src/gui/kernel
parent7396eea79c9464d0c246106834cbce02320e7989 (diff)
downloadQt-a3d8cfb1ee89e0600add864db53d67552820b95a.zip
Qt-a3d8cfb1ee89e0600add864db53d67552820b95a.tar.gz
Qt-a3d8cfb1ee89e0600add864db53d67552820b95a.tar.bz2
Merge of the maemo-gestures branch onto qt/4.5.0
This is a squashed merge of all of the changes in the maemo-gestures branch on-top of the qt/4.5.0 branch.
Diffstat (limited to 'src/gui/kernel')
-rw-r--r--src/gui/kernel/kernel.pri14
-rw-r--r--src/gui/kernel/qapplication.cpp57
-rw-r--r--src/gui/kernel/qapplication.h1
-rw-r--r--src/gui/kernel/qapplication_p.h1
-rw-r--r--src/gui/kernel/qapplication_x11.cpp2
-rw-r--r--src/gui/kernel/qdirectionrecognizer.cpp176
-rw-r--r--src/gui/kernel/qdirectionrecognizer_p.h121
-rw-r--r--src/gui/kernel/qdirectionsimplificator_p.h172
-rw-r--r--src/gui/kernel/qevent.cpp24
-rw-r--r--src/gui/kernel/qevent.h34
-rw-r--r--src/gui/kernel/qgesture.cpp133
-rw-r--r--src/gui/kernel/qgesture.h128
-rw-r--r--src/gui/kernel/qgesture_p.h100
-rw-r--r--src/gui/kernel/qgesturemanager.cpp405
-rw-r--r--src/gui/kernel/qgesturemanager_p.h102
-rw-r--r--src/gui/kernel/qgesturerecognizer.h83
-rw-r--r--src/gui/kernel/qgesturestandardrecognizers.cpp543
-rw-r--r--src/gui/kernel/qgesturestandardrecognizers_p.h169
-rw-r--r--src/gui/kernel/qwidget.cpp45
-rw-r--r--src/gui/kernel/qwidget.h10
-rw-r--r--src/gui/kernel/qwidget_p.h3
21 files changed, 2319 insertions, 4 deletions
diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri
index a1b982a..b6ef6b2 100644
--- a/src/gui/kernel/kernel.pri
+++ b/src/gui/kernel/kernel.pri
@@ -41,7 +41,13 @@ HEADERS += \
kernel/qwidgetaction.h \
kernel/qwidgetaction_p.h \
kernel/qwindowdefs.h \
- kernel/qkeymapper_p.h
+ kernel/qkeymapper_p.h \
+ kernel/qgesture.h \
+ kernel/qgesturemanager_p.h \
+ kernel/qgesturerecognizer.h \
+ kernel/qgesturestandardrecognizers_p.h \
+ kernel/qdirectionrecognizer_p.h \
+ kernel/qdirectionsimplificator_p.h
SOURCES += \
kernel/qaction.cpp \
@@ -70,7 +76,11 @@ SOURCES += \
kernel/qwhatsthis.cpp \
kernel/qwidget.cpp \
kernel/qwidgetaction.cpp \
- kernel/qkeymapper.cpp
+ kernel/qkeymapper.cpp \
+ kernel/qgesture.cpp \
+ kernel/qgesturemanager.cpp \
+ kernel/qgesturestandardrecognizers.cpp \
+ kernel/qdirectionrecognizer.cpp
win32 {
DEFINES += QT_NO_DIRECTDRAW
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp
index 1f4e1fe..b39cbc3 100644
--- a/src/gui/kernel/qapplication.cpp
+++ b/src/gui/kernel/qapplication.cpp
@@ -90,6 +90,8 @@
#include "qapplication.h"
+#include <private/qgesturemanager_p.h>
+
#ifdef Q_WS_WINCE
#include "qdatetime.h"
#include "qguifunctions_wince.h"
@@ -98,6 +100,8 @@ extern bool qt_wince_is_mobile(); //qguifunctions_wince.cpp
extern bool qt_wince_is_pocket_pc(); //qguifunctions_wince.cpp
#endif
+#include "qdatetime.h"
+
//#define ALIEN_DEBUG
static void initResources()
@@ -133,6 +137,8 @@ int QApplicationPrivate::autoMaximizeThreshold = -1;
bool QApplicationPrivate::autoSipEnabled = false;
#endif
+QGestureManager *gestureManager = 0;
+
QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, QApplication::Type type)
: QCoreApplicationPrivate(argc, argv)
{
@@ -3700,6 +3706,27 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
QMouseEvent* mouse = static_cast<QMouseEvent*>(e);
QPoint relpos = mouse->pos();
+ if (QApplication::testAttribute(Qt::AA_EnableGestures)) {
+ if (!gestureManager)
+ gestureManager = new QGestureManager;
+ // if we are in gesture mode, we send all mouse events
+ // directly to gesture recognizer.
+ if (gestureManager->inGestureMode()) {
+ // ### should I send events through all application event filters?
+ if (gestureManager->filterEvent(e))
+ return true;
+ }
+ if (w && (mouse->type() != QEvent::MouseMove || mouse->buttons() != 0)) {
+ // find the gesture target widget
+ QWidget *target = w;
+ while (target && target->gestures().isEmpty())
+ target = target->parentWidget();
+ if (target) {
+ gestureManager->setGestureTargetWidget(target);
+ res = gestureManager->filterEvent(e);
+ }
+ }
+ }
if (e->spontaneous()) {
if (e->type() == QEvent::MouseButtonPress) {
QApplicationPrivate::giveFocusAccordingToFocusPolicy(w,
@@ -3993,6 +4020,35 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
}
break;
#endif
+
+ case QEvent::Gesture: {
+ QWidget *w = static_cast<QWidget*>(receiver);
+ QGestureEvent *g = static_cast<QGestureEvent*>(e);
+ bool eventAccepted = g->isAccepted();
+ // Q_ASSERT(g->gesture() != 0);
+ // const QGesture &gesture = *g->gesture();
+ QPoint relPos(0,0);
+ while (w) {
+ // QGesture qge(gesture.gestureType(), gesture.startPos()+relPos, gesture.lastPos()+relPos,
+ // gesture.currentPos()+relPos, gesture.direction(), gesture.rect().translated(relPos),
+ // gesture.hotSpot()+relPos, gesture.state(), gesture.startTime());
+ // QGestureEvent ge(&qge, false);
+ // ### TODO: fix widget-relative positions in gesture event.
+ QGestureEvent ge = *g;
+ ge.m_targetWidget = w;
+ ge.spont = g->spontaneous();
+ res = d->notify_helper(w, w == receiver ? g : &ge);
+ g->spont = false;
+ eventAccepted = (w == receiver ? g : &ge)->isAccepted();
+ if (res && eventAccepted)
+ break;
+ if (w->isWindow())
+ break;
+ relPos += w->pos();
+ w = w->parentWidget();
+ }
+ break;
+ }
case QEvent::TouchBegin:
// Note: TouchUpdate and TouchEnd events are sent to d->currentMultitouchWidget and never propagated
{
@@ -4000,7 +4056,6 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
QWidget *origin = widget;
QTouchEvent *touchEvent = static_cast<QTouchEvent *>(e);
bool eventAccepted = touchEvent->isAccepted();
-
if (widget->testAttribute(Qt::WA_AcceptTouchEvents) && e->spontaneous()) {
// give the widget focus if the focus policy allows it
QApplicationPrivate::giveFocusAccordingToFocusPolicy(widget,
diff --git a/src/gui/kernel/qapplication.h b/src/gui/kernel/qapplication.h
index 2baf6dc..634226f 100644
--- a/src/gui/kernel/qapplication.h
+++ b/src/gui/kernel/qapplication.h
@@ -374,6 +374,7 @@ private:
friend class QDirectPainter;
friend class QDirectPainterPrivate;
#endif
+ friend class QGestureManager;
#if defined(Q_WS_WIN)
friend QApplicationPrivate* getQApplicationPrivateInternal();
diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h
index 1a2bad2..40e928d 100644
--- a/src/gui/kernel/qapplication_p.h
+++ b/src/gui/kernel/qapplication_p.h
@@ -428,6 +428,7 @@ public:
void sendSyntheticEnterLeave(QWidget *widget);
#endif
+ QMap<Qt::GestureType, int> grabbedGestures;
static void updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent);
#if defined(Q_WS_WIN)
diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp
index 90376b3..060e948 100644
--- a/src/gui/kernel/qapplication_x11.cpp
+++ b/src/gui/kernel/qapplication_x11.cpp
@@ -4414,7 +4414,6 @@ bool QETWidget::translateMouseEvent(const XEvent *event)
QMouseEvent e(type, pos, globalPos, button, buttons, modifiers);
QApplicationPrivate::sendMouseEvent(widget, &e, alienWidget, this, &qt_button_down,
qt_last_mouse_receiver);
-
if (type == QEvent::MouseButtonPress
&& button == Qt::RightButton
&& (openPopupCount == oldOpenPopupCount)) {
@@ -5022,6 +5021,7 @@ bool QETWidget::translatePropertyEvent(const XEvent *event)
return true;
}
+
//
// Paint event translation
//
diff --git a/src/gui/kernel/qdirectionrecognizer.cpp b/src/gui/kernel/qdirectionrecognizer.cpp
new file mode 100644
index 0000000..37b64e7
--- /dev/null
+++ b/src/gui/kernel/qdirectionrecognizer.cpp
@@ -0,0 +1,176 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdirectionrecognizer_p.h"
+
+#include <math.h>
+
+QT_BEGIN_NAMESPACE
+
+static const int SIZE = 20;
+
+QDirectionSimpleRecognizer::QDirectionSimpleRecognizer()
+{
+}
+
+Direction QDirectionSimpleRecognizer::addPosition(const QPoint &pos)
+{
+ if (!directions.isEmpty()) {
+ const QPoint tmp = pos - directions.back().point;
+ if (tmp.manhattanLength() < 5)
+ return Direction();
+ }
+ if (lastPoint.isNull()) {
+ lastPoint = pos;
+ return Direction();
+ }
+ int dx = pos.x() - lastPoint.x();
+ int dy = pos.y() - lastPoint.y();
+ Direction::DirectionType direction = Direction::None;
+ if (dx < 0) {
+ if (-1*dx >= SIZE/2)
+ direction = Direction::Left;
+ } else {
+ if (dx >= SIZE/2)
+ direction = Direction::Right;
+ }
+ if (dy < 0) {
+ if (-1*dy >= SIZE/2)
+ direction = Direction::Up;
+ } else {
+ if (dy >= SIZE/2)
+ direction = Direction::Down;
+ }
+ if (direction == Direction::None)
+ return Direction();
+
+ lastPoint = pos;
+ directions.push_back(Direction(direction, pos));
+ return Direction(direction, pos);
+}
+
+
+DirectionList QDirectionSimpleRecognizer::getDirections() const
+{
+ return directions;
+}
+
+void QDirectionSimpleRecognizer::reset()
+{
+ directions.clear();
+ lastPoint = QPoint();
+}
+
+
+/// QDirectionDiagonalRecognizer
+
+QDirectionDiagonalRecognizer::QDirectionDiagonalRecognizer()
+{
+}
+
+Direction QDirectionDiagonalRecognizer::addPosition(const QPoint &pos)
+{
+ if (!directions.isEmpty()) {
+ const QPoint tmp = pos - directions.back().point;
+ if (tmp.manhattanLength() < 5)
+ return Direction();
+ }
+ if (lastPoint.isNull()) {
+ lastPoint = pos;
+ return Direction();
+ }
+ int dx = pos.x() - lastPoint.x();
+ int dy = pos.y() - lastPoint.y();
+ int distance = sqrt(static_cast<double>(dx*dx + dy*dy));
+ if (distance < SIZE/2)
+ return Direction();
+
+ Direction::DirectionType direction = Direction::None;
+ double angle = atan(1.0*qAbs(lastPoint.y() - pos.y())/qAbs(pos.x() - lastPoint.x())) * 180. / M_PI;
+ if (dx < 0 && dy <= 0) {
+ angle = 180 - angle;
+ } else if (dx <= 0 && dy > 0) {
+ angle += 180;
+ } else if (dx > 0 && dy > 0) {
+ angle = 360-angle;
+ }
+ if (angle < 0)
+ angle += 360;
+ if (angle <= 20)
+ direction = Direction::Right;
+ else if (angle <= 65)
+ direction = Direction::RightUp;
+ else if (angle <= 110)
+ direction = Direction::Up;
+ else if (angle <= 155)
+ direction = Direction::LeftUp;
+ else if (angle <= 200)
+ direction = Direction::Left;
+ else if (angle <= 245)
+ direction = Direction::LeftDown;
+ else if (angle <= 290)
+ direction = Direction::Down;
+ else if (angle <= 335)
+ direction = Direction::RightDown;
+ else
+ direction = Direction::Right;
+
+ if (direction == Direction::None)
+ return Direction();
+
+ lastPoint = pos;
+ directions.push_back(Direction(direction, pos));
+ return Direction(direction, pos);
+}
+
+
+DirectionList QDirectionDiagonalRecognizer::getDirections() const
+{
+ return directions;
+}
+
+void QDirectionDiagonalRecognizer::reset()
+{
+ directions.clear();
+ lastPoint = QPoint();
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qdirectionrecognizer_p.h b/src/gui/kernel/qdirectionrecognizer_p.h
new file mode 100644
index 0000000..6390990
--- /dev/null
+++ b/src/gui/kernel/qdirectionrecognizer_p.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDIRECTIONRECOGNIZER_P_H
+#define QDIRECTIONRECOGNIZER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qpoint.h"
+#include "qlist.h"
+
+QT_BEGIN_NAMESPACE
+
+struct Direction
+{
+ enum DirectionType
+ {
+ None = 0,
+ LeftDown = 1,
+ DownLeft = LeftDown,
+ Down = 2,
+ RightDown = 3,
+ DownRight = RightDown,
+ Left = 4,
+ Right = 6,
+ LeftUp = 7,
+ UpLeft = LeftUp,
+ Up = 8,
+ RightUp = 9,
+ UpRight = RightUp
+ };
+ DirectionType direction;
+ QPoint point;
+
+ Direction(DirectionType dir, const QPoint &pt)
+ : direction(dir), point(pt) { }
+ Direction()
+ : direction(None) { }
+
+ inline bool isEmpty() const { return direction == None; }
+ inline bool isNull() const { return direction == None; }
+};
+
+typedef QList<Direction> DirectionList;
+
+class QDirectionSimpleRecognizer
+{
+public:
+ QDirectionSimpleRecognizer();
+ Direction addPosition(const QPoint &pos);
+ DirectionList getDirections() const;
+ void reset();
+
+private:
+ QPoint lastPoint;
+ DirectionList directions;
+};
+
+class QDirectionDiagonalRecognizer
+{
+public:
+ QDirectionDiagonalRecognizer();
+ Direction addPosition(const QPoint &pos);
+ DirectionList getDirections() const;
+ void reset();
+
+private:
+ QPoint lastPoint;
+ DirectionList directions;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDIRECTIONRECOGNIZER_P_H
diff --git a/src/gui/kernel/qdirectionsimplificator_p.h b/src/gui/kernel/qdirectionsimplificator_p.h
new file mode 100644
index 0000000..7b71ca0
--- /dev/null
+++ b/src/gui/kernel/qdirectionsimplificator_p.h
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDIRECTIONSIMPLIFICATOR_P_H
+#define QDIRECTIONSIMPLIFICATOR_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qdirectionrecognizer_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QDirectionSimplificator
+{
+public:
+ QDirectionSimplificator(const DirectionList &dir);
+
+ bool simplify(DirectionList *result);
+
+private:
+ DirectionList directions;
+ DirectionList lastResult;
+ enum State {
+ None,
+ Trim, // remove first and last element
+ AccidentalMoves, // 66866 => 6666
+ ComplexAccidentalMoves, // 778788 => 777888 (swapping elements without changing direction)
+ ShortMoves, // (moves of length 1)
+ } state;
+
+ struct SimplifyTrim
+ {
+ SimplifyTrim() : state(0) { }
+ bool operator()(DirectionList &directions)
+ {
+ if (state == 0) {
+ directions.removeFirst();
+ state = 1;
+ } else if (state == 1) {
+ directions.removeLast();
+ state = 2;
+ } else if (state == 2 && directions.size() >= 2) {
+ directions.removeFirst();
+ directions.removeLast();
+ state = 3;
+ } else {
+ return false;
+ }
+ return true;
+ }
+ int state;
+ };
+ struct SimplifyAccidentalMoves
+ {
+ SimplifyAccidentalMoves() : state(0) { }
+ bool operator()(DirectionList &directions)
+ {
+ return false;
+ }
+ int state;
+ };
+ struct SimplifyComplexAccidentalMoves
+ {
+ SimplifyComplexAccidentalMoves() : state(0) { }
+ bool operator()(DirectionList &directions)
+ {
+ return false;
+ }
+ int state;
+ };
+
+ SimplifyTrim trim;
+ SimplifyAccidentalMoves accidentalMoves;
+ SimplifyComplexAccidentalMoves complexAccidentalMoves;
+ //SimplifyShortMoves shortMoves;
+};
+
+QDirectionSimplificator::QDirectionSimplificator(const DirectionList &dir)
+ : directions(dir), state(None)
+{
+}
+
+bool QDirectionSimplificator::simplify(DirectionList *result)
+{
+ if (directions.isEmpty() || !result)
+ return false;
+ *result = directions;
+ switch(state) {
+ case None:
+ state = Trim;
+ trim = SimplifyTrim();
+ case Trim:
+ if (trim(*result))
+ break;
+ *result = lastResult;
+ state = AccidentalMoves;
+ accidentalMoves = SimplifyAccidentalMoves();
+ case AccidentalMoves:
+ if (accidentalMoves(*result))
+ break;
+ *result = lastResult;
+ state = ComplexAccidentalMoves;
+ complexAccidentalMoves = SimplifyComplexAccidentalMoves();
+ case ComplexAccidentalMoves:
+ if (complexAccidentalMoves(*result))
+ break;
+ *result = lastResult;
+ // state = ShortMoves;
+ // shortMoves = SimplifyShortMoves();
+ // case ShortMoves:
+ // if (shortMoves(*result))
+ // break;
+ // state = None;
+ default:
+ return false;
+ }
+ lastResult = *result;
+ if (lastResult.isEmpty())
+ return false;
+ return true;
+}
+
+QT_END_NAMESPACE
+
+#endif // QDIRECTIONSIMPLIFICATOR_P_H
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index d571212..a7e1101 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -3310,6 +3310,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();
@@ -3506,6 +3509,27 @@ QMenubarUpdatedEvent::QMenubarUpdatedEvent(QMenuBar * const menuBar)
#endif
+QGestureEvent::QGestureEvent(QWidget *targetWidget, const QList<QGesture*> &gestures,
+ const QSet<Qt::GestureType> &cancelledGestures)
+ : QEvent(QEvent::Gesture), m_targetWidget(targetWidget),
+ m_cancelledGestures(cancelledGestures)
+{
+ foreach(QGesture *r, gestures)
+ m_gestures.insert(r->gestureType(), QSharedPointer<QGesture>(r));
+}
+
+QGestureEvent::QGestureEvent(const QGestureEvent &event, const QPoint &offset)
+ : QEvent(QEvent::Gesture), m_targetWidget(event.m_targetWidget),
+ m_gestures(event.m_gestures),
+ m_cancelledGestures(event.m_cancelledGestures)
+{
+ //### use offset!
+}
+
+QGestureEvent::~QGestureEvent()
+{
+}
+
/*! \class QTouchEvent
\brief The QTouchEvent class contains parameters that describe a touch event
.
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index e9a1386..858e2ea 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -52,6 +52,10 @@
#include <QtGui/qmime.h>
#include <QtGui/qdrag.h>
#include <QtCore/qvariant.h>
+#include <QtCore/qmap.h>
+#include <QtCore/qset.h>
+#include <QtCore/qsharedpointer.h>
+#include <QtGui/qgesture.h>
QT_BEGIN_HEADER
@@ -710,6 +714,36 @@ private:
};
#endif
+class Q_GUI_EXPORT QGestureEvent : public QEvent
+{
+public:
+ QGestureEvent(QWidget *targetWidget, const QList<QGesture*> &gestures,
+ const QSet<Qt::GestureType> &cancelledGestures = QSet<Qt::GestureType>());
+ // internal ctor
+ QGestureEvent(const QGestureEvent &gestures, const QPoint &offset);
+ ~QGestureEvent();
+
+ QWidget *targetWidget() const
+ { return m_targetWidget; }
+
+ inline bool contains(const Qt::GestureType &gestureType) const
+ { return gesture(gestureType) != 0; }
+ inline QList<Qt::GestureType> gestureTypes() const
+ { return m_gestures.keys(); }
+ inline const QGesture* gesture(const Qt::GestureType &gestureType) const
+ { return m_gestures.value(gestureType, QSharedPointer<QGesture>()).data(); }
+
+ inline QSet<Qt::GestureType> cancelledGestures() const
+ { return m_cancelledGestures; }
+
+protected:
+ QWidget *m_targetWidget;
+ QHash<Qt::GestureType, QSharedPointer<QGesture> > m_gestures;
+ QSet<Qt::GestureType> m_cancelledGestures;
+
+ friend class QApplication;
+};
+
#ifndef QT_NO_DEBUG_STREAM
Q_GUI_EXPORT QDebug operator<<(QDebug, const QEvent *);
#endif
diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp
new file mode 100644
index 0000000..fbabb8f
--- /dev/null
+++ b/src/gui/kernel/qgesture.cpp
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgesture.h"
+#include <private/qgesture_p.h>
+
+QGesture::QGesture(const Qt::GestureType &type, Qt::GestureState state)
+ : d(new QGesturePrivate), gestureType_(type), gestureState_(state)
+{
+}
+
+QGesture::QGesture(const Qt::GestureType &type, const QPoint &startPos,
+ const QPoint &lastPos, const QPoint &pos, const QRect &rect,
+ const QPoint &hotSpot, const QDateTime &startTime,
+ uint duration, Qt::GestureState state)
+ : d(new QGesturePrivate), gestureType_(type), gestureState_(state)
+{
+ d->init(startPos, lastPos, pos, rect, hotSpot, startTime, duration);
+}
+
+QGesture::QGesture(QGesturePrivate &dd, const Qt::GestureType &type,
+ Qt::GestureState state)
+ : d(&dd), gestureType_(type), gestureState_(state)
+{
+}
+
+QGesture::~QGesture()
+{
+ delete d; d = 0;
+}
+
+QRect QGesture::rect() const
+{
+ return d->rect;
+}
+
+QPoint QGesture::hotSpot() const
+{
+ return d->hotSpot;
+}
+
+QDateTime QGesture::startTime() const
+{
+ return d->startTime;
+}
+
+uint QGesture::duration() const
+{
+ return d->duration;
+}
+
+QPoint QGesture::startPos() const
+{
+ return d->startPos;
+}
+
+QPoint QGesture::lastPos() const
+{
+ return d->lastPos;
+}
+
+QPoint QGesture::pos() const
+{
+ return d->pos;
+}
+
+QPannableGesture::QPannableGesture(const Qt::GestureType &type, Qt::GestureState state)
+ : QGesture(*new QPannableGesturePrivate, type, state)
+{
+}
+
+QPannableGesture::QPannableGesture(const Qt::GestureType &type, const QPoint &startPos,
+ const QPoint &lastPos, const QPoint &pos, const QRect &rect,
+ const QPoint &hotSpot, const QDateTime &startTime,
+ uint duration, Qt::GestureState state)
+ : QGesture(*new QPannableGesturePrivate, type, state)
+{
+ d->init(startPos, lastPos, pos, rect, hotSpot, startTime, duration);
+ ((QPannableGesturePrivate*)d)->lastDirection = QPannableGesture::None;
+ ((QPannableGesturePrivate*)d)->direction = QPannableGesture::None;
+}
+
+QPannableGesture::~QPannableGesture()
+{
+}
+
+QPannableGesture::DirectionType QPannableGesture::lastDirection() const
+{
+ return ((QPannableGesturePrivate*)d)->lastDirection;
+}
+
+QPannableGesture::DirectionType QPannableGesture::direction() const
+{
+ return ((QPannableGesturePrivate*)d)->direction;
+}
diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h
new file mode 100644
index 0000000..16a5704
--- /dev/null
+++ b/src/gui/kernel/qgesture.h
@@ -0,0 +1,128 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGESTURE_H
+#define QGESTURE_H
+
+#include "qobject.h"
+#include "qlist.h"
+#include "qdatetime.h"
+#include "qpoint.h"
+#include "qrect.h"
+#include "qsharedpointer.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QGesturePrivate;
+class Q_GUI_EXPORT QGesture
+{
+public:
+ explicit QGesture(const Qt::GestureType &type, Qt::GestureState state = Qt::GestureStarted);
+ QGesture(const Qt::GestureType &type, const QPoint &startPos,
+ const QPoint &lastPos, const QPoint &pos, const QRect &rect,
+ const QPoint &hotSpot, const QDateTime &startTime,
+ uint duration, Qt::GestureState state);
+ virtual ~QGesture();
+
+ inline Qt::GestureType gestureType() const { return gestureType_; }
+ inline Qt::GestureState state() const { return gestureState_; }
+
+ QRect rect() const;
+ QPoint hotSpot() const;
+ QDateTime startTime() const;
+ uint duration() const;
+
+ QPoint startPos() const;
+ QPoint lastPos() const;
+ QPoint pos() const;
+
+protected:
+ QGesture(QGesturePrivate &dd, const Qt::GestureType &type, Qt::GestureState state = Qt::GestureStarted);
+ QGesturePrivate *d;
+
+private:
+ Qt::GestureType gestureType_;
+ Qt::GestureState gestureState_;
+};
+
+class Q_GUI_EXPORT QPannableGesture : public QGesture
+{
+public:
+ enum DirectionType
+ {
+ None = 0,
+ LeftDown = 1,
+ DownLeft = LeftDown,
+ Down = 2,
+ RightDown = 3,
+ DownRight = RightDown,
+ Left = 4,
+ Right = 6,
+ LeftUp = 7,
+ UpLeft = LeftUp,
+ Up = 8,
+ RightUp = 9,
+ UpRight = RightUp
+ };
+
+public:
+ explicit QPannableGesture(const Qt::GestureType &type, Qt::GestureState state = Qt::GestureStarted);
+ QPannableGesture(const Qt::GestureType &type, const QPoint &startPos,
+ const QPoint &lastPos, const QPoint &pos, const QRect &rect,
+ const QPoint &hotSpot, const QDateTime &startTime,
+ uint duration, Qt::GestureState state);
+ ~QPannableGesture();
+
+ DirectionType lastDirection() const;
+ DirectionType direction() const;
+
+ friend class QGestureRecognizerPan;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QGESTURE_H
diff --git a/src/gui/kernel/qgesture_p.h b/src/gui/kernel/qgesture_p.h
new file mode 100644
index 0000000..745590b
--- /dev/null
+++ b/src/gui/kernel/qgesture_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGESTURE_P_H
+#define QGESTURE_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 "qrect.h"
+#include "qpoint.h"
+#include "qdatetime.h"
+
+QT_BEGIN_NAMESPACE
+
+class QGesturePrivate
+{
+public:
+ QGesturePrivate()
+ : duration(0) { }
+
+ void init(const QPoint &startPos, const QPoint &lastPos,
+ const QPoint &pos, const QRect &rect,
+ const QPoint &hotSpot, const QDateTime &startTime,
+ uint duration)
+ {
+ this->rect = rect;
+ this->hotSpot = hotSpot;
+ this->startTime = startTime;
+ this->duration = duration;
+ this->startPos = startPos;
+ this->lastPos = lastPos;
+ this->pos = pos;
+ }
+
+ QRect rect;
+ QPoint hotSpot;
+ QDateTime startTime;
+ uint duration;
+ QPoint startPos;
+ QPoint lastPos;
+ QPoint pos;
+};
+
+class QPannableGesturePrivate : public QGesturePrivate
+{
+public:
+ QPannableGesture::DirectionType lastDirection;
+ QPannableGesture::DirectionType direction;
+};
+
+QT_END_NAMESPACE
+
+#endif // QGESTURE_P_H
diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp
new file mode 100644
index 0000000..c244a0b
--- /dev/null
+++ b/src/gui/kernel/qgesturemanager.cpp
@@ -0,0 +1,405 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgesturemanager_p.h"
+#include "qgesture.h"
+#include "qevent.h"
+
+#include "qapplication.h"
+#include "private/qapplication_p.h"
+
+#include "private/qgesturestandardrecognizers_p.h"
+
+#include "qdebug.h"
+
+// #define GESTURE_DEBUG
+#ifndef GESTURE_DEBUG
+# define DEBUG if (0) qDebug
+#else
+# define DEBUG qDebug
+#endif
+
+QT_BEGIN_NAMESPACE
+
+bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event);
+static bool qt_sendGestureEvent(QWidget *receiver, QGestureEvent *event)
+{
+ QSet<Qt::GestureType> eventGestures = event->gestureTypes().toSet();
+ while (receiver && (receiver->gestures() & eventGestures).isEmpty())
+ receiver = receiver->parentWidget();
+ return receiver ? qt_sendSpontaneousEvent(receiver, event) : false;
+}
+
+static const unsigned int maximumGestureRecognitionTimeout = 2000;
+
+QGestureManager::QGestureManager()
+ : targetWidget(0), state(NotGesture)
+{
+ recognizers << new QDoubleTapGestureRecognizer();
+ recognizers << new QLongTapGestureRecognizer();
+ recognizers << new QGestureRecognizerPan();
+ // recognizers << new QMultiTouchGestureRecognizer();
+
+ foreach(QGestureRecognizer *r, recognizers)
+ connect(r, SIGNAL(triggered(QGestureRecognizer::Result)),
+ this, SLOT(recognizerTriggered(QGestureRecognizer::Result)));
+}
+
+bool QGestureManager::filterEvent(QEvent *event)
+{
+ if (!QApplication::testAttribute(Qt::AA_EnableGestures))
+ return false;
+
+ QList<QEvent*> events;
+ events << event;
+
+ QPoint currentPos;
+ switch (event->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseMove:
+ currentPos = static_cast<QMouseEvent*>(event)->pos(); break;
+ default: break;
+ }
+
+ const QMap<Qt::GestureType, int> &grabbedGestures = qApp->d_func()->grabbedGestures;
+
+ bool ret = false;
+ QSet<QGestureRecognizer*> startedGestures;
+ QSet<QGestureRecognizer*> finishedGestures;
+ QSet<QGestureRecognizer*> newMaybeGestures;
+ QSet<QGestureRecognizer*> cancelledGestures;
+ QSet<QGestureRecognizer*> notGestures;
+ if (state == NotGesture || state == MaybeGesture) {
+ DEBUG() << "QGestureManager: current event processing state: "
+ << (state == NotGesture ? "NotGesture" : "MaybeGesture");
+
+ Q_ASSERT(targetWidget != 0);
+ QSet<QGestureRecognizer*> stillMaybeGestures;
+ // try other recognizers.
+ foreach(QGestureRecognizer *r, recognizers) {
+ if (grabbedGestures.value(r->gestureType(), 0) <= 0)
+ continue;
+ QGestureRecognizer::Result result = r->recognize(events);
+ if (result == QGestureRecognizer::GestureStarted) {
+ DEBUG() << "QGestureManager: gesture started: " << r;
+ startedGestures << r;
+ } else if (result == QGestureRecognizer::GestureFinished) {
+ DEBUG() << "QGestureManager: gesture finished: " << r;
+ finishedGestures << r;
+ } else if (result == QGestureRecognizer::MaybeGesture) {
+ DEBUG() << "QGestureManager: maybe gesture: " << r;
+ newMaybeGestures << r;
+ } else {
+ // if it was maybe gesture, but isn't a gesture anymore.
+ DEBUG() << "QGestureManager: not gesture: " << r;
+ notGestures << r;
+ }
+ }
+ activeGestures -= newMaybeGestures;
+ activeGestures += startedGestures;
+ foreach(QGestureRecognizer *r, startedGestures+notGestures) {
+ QMap<QGestureRecognizer*, int>::iterator it = maybeGestures.find(r);
+ if (it != maybeGestures.end()) {
+ killTimer(it.value());
+ maybeGestures.erase(it);
+ }
+ }
+ foreach(QGestureRecognizer *r, newMaybeGestures) {
+ if (!maybeGestures.contains(r)) {
+ int timerId = startTimer(maximumGestureRecognitionTimeout);
+ if (!timerId)
+ qWarning("QGestureManager: couldn't start timer!");
+ maybeGestures.insert(r, timerId);
+ }
+ }
+ if (!finishedGestures.isEmpty() || !activeGestures.isEmpty()) {
+ // gesture found!
+ ret = true;
+ DEBUG() << "QGestureManager: sending gesture event for: "
+ << activeGestures << " and " << finishedGestures;
+
+ QList<QGesture*> gestures;
+ foreach(QGestureRecognizer *r, finishedGestures) {
+ if (QGesture *gesture = r->makeEvent())
+ gestures << gesture;
+ }
+ foreach(QGestureRecognizer *r, activeGestures) {
+ if (QGesture *gesture = r->makeEvent())
+ gestures << gesture;
+ }
+ Q_ASSERT(!gestures.isEmpty());
+ QGestureEvent event(targetWidget, gestures);
+ qt_sendGestureEvent(targetWidget, &event);
+
+ if (!activeGestures.isEmpty()) {
+ DEBUG() << "QGestureManager: new state = Gesture";
+ state = Gesture;
+ } else if (!maybeGestures.isEmpty()) {
+ DEBUG() << "QGestureManager: new state = Maybe";
+ state = MaybeGesture;
+ } else {
+ DEBUG() << "QGestureManager: new state = NotGesture";
+ state = NotGesture;
+ }
+ } else if (!maybeGestures.isEmpty()) {
+ if (state != MaybeGesture) {
+ // We got a new set of events that look like a start
+ // of some gesture, so we switch to state MaybeGesture
+ // and wait for more events.
+ DEBUG() << "QGestureManager: new state = Maybe. Waiting for events";
+ state = MaybeGesture;
+ // start gesture timer
+ } else {
+ // we still not sure if it is a gesture or not.
+ }
+ } else if (state == MaybeGesture) {
+ // last time we thought it looks like gesture, but now we
+ // know for sure that it isn't.
+ DEBUG() << "QGestureManager: new state = NotGesture";
+ state = NotGesture;
+ }
+ foreach(QGestureRecognizer *r, finishedGestures)
+ r->reset();
+ foreach(QGestureRecognizer *r, cancelledGestures)
+ r->reset();
+ foreach(QGestureRecognizer *r, notGestures)
+ r->reset();
+ } else if (state == Gesture) {
+ DEBUG() << "QGestureManager: current event processing state: Gesture";
+ Q_ASSERT(!activeGestures.isEmpty());
+
+ foreach(QGestureRecognizer *r, recognizers) {
+ if (grabbedGestures.value(r->gestureType(), 0) <= 0)
+ continue;
+ QGestureRecognizer::Result result = r->recognize(events);
+ if (result == QGestureRecognizer::GestureStarted) {
+ DEBUG() << "QGestureManager: gesture started: " << r;
+ startedGestures << r;
+ } else if (result == QGestureRecognizer::GestureFinished) {
+ DEBUG() << "QGestureManager: gesture finished: " << r;
+ finishedGestures << r;
+ } else if (result == QGestureRecognizer::MaybeGesture) {
+ DEBUG() << "QGestureManager: maybe gesture: " << r;
+ newMaybeGestures << r;
+ } else {
+ // if it was an active gesture, but isn't a gesture anymore.
+ if (activeGestures.contains(r)) {
+ DEBUG() << "QGestureManager: cancelled gesture: " << r;
+ cancelledGestures << r;
+ } else {
+ DEBUG() << "QGestureManager: not gesture: " << r;
+ notGestures << r;
+ }
+ }
+ }
+
+ activeGestures -= newMaybeGestures;
+ activeGestures -= cancelledGestures;
+ activeGestures -= finishedGestures;
+ activeGestures += startedGestures;
+ foreach(QGestureRecognizer *r, startedGestures+finishedGestures+notGestures) {
+ QMap<QGestureRecognizer*, int>::iterator it = maybeGestures.find(r);
+ if (it != maybeGestures.end()) {
+ killTimer(it.value());
+ maybeGestures.erase(it);
+ }
+ }
+ foreach(QGestureRecognizer *r, newMaybeGestures) {
+ if (!maybeGestures.contains(r)) {
+ int timerId = startTimer(maximumGestureRecognitionTimeout);
+ if (!timerId)
+ qWarning("QGestureManager: couldn't start timer!");
+ maybeGestures.insert(r, timerId);
+ }
+ }
+ QList<QGesture*> gestures;
+ if (!finishedGestures.isEmpty() || !activeGestures.isEmpty()) {
+ // another gesture found!
+ ret = true;
+ DEBUG() << "QGestureManager: sending gesture event for: "
+ << activeGestures << " and " << finishedGestures;
+
+ foreach(QGestureRecognizer *r, finishedGestures) {
+ if (QGesture *gesture = r->makeEvent())
+ gestures << gesture;
+ }
+ foreach(QGestureRecognizer *r, activeGestures) {
+ if (QGesture *gesture = r->makeEvent())
+ gestures << gesture;
+ }
+ }
+ QSet<Qt::GestureType> cancelledGestureNames;
+ foreach(QGestureRecognizer *r, cancelledGestures)
+ cancelledGestureNames << r->gestureType();
+ if(!gestures.isEmpty()) {
+ QGestureEvent event(targetWidget, gestures, cancelledGestureNames);
+ qt_sendGestureEvent(targetWidget, &event);
+ }
+
+ foreach(QGestureRecognizer *r, finishedGestures)
+ r->reset();
+ foreach(QGestureRecognizer *r, cancelledGestures)
+ r->reset();
+ foreach(QGestureRecognizer *r, notGestures)
+ r->reset();
+ if (!activeGestures.isEmpty()) {
+ // nothing changed, we are still handling a gesture
+ } else if (!maybeGestures.isEmpty()) {
+ DEBUG() << "QGestureManager: new state = Maybe. Waiting for events: " << maybeGestures;
+ state = MaybeGesture;
+ } else {
+ DEBUG() << "QGestureManager: new state = NotGesture";
+ state = NotGesture;
+ }
+ ret = true;
+ }
+
+ lastPos = currentPos;
+ return ret;
+}
+
+void QGestureManager::timerEvent(QTimerEvent *event)
+{
+ // sanity checks, remove later
+ Q_ASSERT((state == Gesture && !activeGestures.isEmpty()) || (state != Gesture && activeGestures.isEmpty()));
+
+ typedef QMap<QGestureRecognizer*, int> MaybeGestureMap;
+ for (MaybeGestureMap::iterator it = maybeGestures.begin(), e = maybeGestures.end();
+ it != e; ++it) {
+ if (it.value() == event->timerId()) {
+ DEBUG() << "QGestureManager: gesture timeout.";
+ QGestureRecognizer *r = it.key();
+ r->reset();
+ maybeGestures.erase(it);
+ killTimer(event->timerId());
+ break;
+ }
+ }
+
+ if (state == MaybeGesture && maybeGestures.isEmpty()) {
+ DEBUG() << "QGestureManager: new state = NotGesture because of timeout";
+ state = NotGesture;
+ }
+}
+
+bool QGestureManager::inGestureMode()
+{
+ return state == Gesture;
+}
+
+void QGestureManager::setGestureTargetWidget(QWidget *widget)
+{
+ targetWidget = widget;
+}
+
+void QGestureManager::recognizerTriggered(QGestureRecognizer::Result result)
+{
+ if (!QApplication::testAttribute(Qt::AA_EnableGestures))
+ return;
+
+ QGestureRecognizer *recognizer = qobject_cast<QGestureRecognizer*>(sender());
+ if (!recognizer)
+ return;
+ if (qApp->d_func()->grabbedGestures.value(recognizer->gestureType(), 0) <= 0) {
+ recognizer->reset();
+ return;
+ }
+
+ switch (result) {
+ case QGestureRecognizer::GestureStarted:
+ case QGestureRecognizer::GestureFinished: {
+ if (result == QGestureRecognizer::GestureStarted) {
+ DEBUG() << "QGestureManager: gesture started: " << recognizer;
+ activeGestures << recognizer;
+ DEBUG() << "QGestureManager: new state = Gesture";
+ state = Gesture;
+ } else {
+ DEBUG() << "QGestureManager: gesture finished: " << recognizer;
+ }
+ if (maybeGestures.contains(recognizer)) {
+ killTimer(maybeGestures.value(recognizer));
+ maybeGestures.remove(recognizer);
+ }
+ QList<QGesture*> gestures;
+ if (QGesture *gesture = recognizer->makeEvent())
+ gestures << gesture;
+ if(!gestures.isEmpty()) {
+ QGestureEvent event(targetWidget, gestures);
+ qt_sendGestureEvent(targetWidget, &event);
+ }
+ if (result == QGestureRecognizer::GestureFinished)
+ recognizer->reset();
+ }
+ break;
+ case QGestureRecognizer::MaybeGesture: {
+ DEBUG() << "QGestureManager: maybe gesture: " << recognizer;
+ if (activeGestures.contains(recognizer)) {
+ QGestureEvent event(targetWidget, QList<QGesture*>(),
+ QSet<Qt::GestureType>() << recognizer->gestureType());
+ qt_sendGestureEvent(targetWidget, &event);
+ }
+ if (!maybeGestures.contains(recognizer)) {
+ int timerId = startTimer(maximumGestureRecognitionTimeout);
+ if (!timerId)
+ qWarning("QGestureManager: couldn't start timer!");
+ maybeGestures.insert(recognizer, timerId);
+ }
+ }
+ break;
+ case QGestureRecognizer::NotGesture:
+ DEBUG() << "QGestureManager: not gesture: " << recognizer;
+ if (maybeGestures.contains(recognizer)) {
+ killTimer(maybeGestures.value(recognizer));
+ maybeGestures.remove(recognizer);
+ }
+ recognizer->reset();
+ break;
+ default:
+ Q_ASSERT(false);
+ }
+}
+
+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..9853f1a
--- /dev/null
+++ b/src/gui/kernel/qgesturemanager_p.h
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@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 "qlist.h"
+#include "qset.h"
+#include "qevent.h"
+#include "qbasictimer.h"
+
+#include "qgesturerecognizer.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q_GUI_EXPORT QGestureManager : public QObject
+{
+ Q_OBJECT
+public:
+ QGestureManager();
+
+ // should be internal
+ void setGestureTargetWidget(QWidget *widget);
+
+ bool filterEvent(QEvent *event);
+ bool inGestureMode();
+
+protected:
+ void timerEvent(QTimerEvent *event);
+
+private slots:
+ void recognizerTriggered(QGestureRecognizer::Result);
+
+private:
+ QSet<QGestureRecognizer*> activeGestures;
+ QMap<QGestureRecognizer*, int> maybeGestures;
+ QSet<QGestureRecognizer*> recognizers;
+
+ QWidget *targetWidget;
+ QPoint lastPos;
+
+ enum State {
+ Gesture,
+ NotGesture,
+ MaybeGesture // that mean timers are up and waiting for some
+ // more events, and input events are handled by
+ // gesture recognizer explicitely
+ } state;
+};
+
+QT_END_NAMESPACE
+
+#endif // QGESTUREMANAGER_P_H
diff --git a/src/gui/kernel/qgesturerecognizer.h b/src/gui/kernel/qgesturerecognizer.h
new file mode 100644
index 0000000..3ed96c0
--- /dev/null
+++ b/src/gui/kernel/qgesturerecognizer.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGESTURERECOGNIZER_H
+#define QGESTURERECOGNIZER_H
+
+#include "qgesture.h"
+#include "qevent.h"
+#include "qlist.h"
+#include "qset.h"
+
+QT_BEGIN_NAMESPACE
+
+class QGestureRecognizer : public QObject
+{
+ Q_OBJECT
+public:
+ enum Result
+ {
+ NotGesture,
+ GestureStarted,
+ GestureFinished,
+ MaybeGesture
+ };
+
+ inline QGestureRecognizer() { }
+ //### remove this ctor
+ inline QGestureRecognizer(const char *type) : type_(QLatin1String(type)) { }
+ inline QGestureRecognizer(const Qt::GestureType &type) : type_(type) { }
+ inline Qt::GestureType gestureType() const { return type_; }
+
+ virtual Result recognize(const QList<QEvent*> &inputEvents) = 0;
+ virtual QGesture* makeEvent() const = 0;
+ virtual void reset() = 0;
+
+signals:
+ void triggered(QGestureRecognizer::Result result);
+
+protected:
+ Qt::GestureType type_;
+};
+
+QT_END_NAMESPACE
+
+#endif // QGESTURERECOGNIZER_P_H
diff --git a/src/gui/kernel/qgesturestandardrecognizers.cpp b/src/gui/kernel/qgesturestandardrecognizers.cpp
new file mode 100644
index 0000000..3a2fa1d
--- /dev/null
+++ b/src/gui/kernel/qgesturestandardrecognizers.cpp
@@ -0,0 +1,543 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgesturestandardrecognizers_p.h"
+#include "qgesture_p.h"
+
+// #define GESTURE_RECOGNIZER_DEBUG
+#ifndef GESTURE_RECOGNIZER_DEBUG
+# define DEBUG if (0) qDebug
+#else
+# define DEBUG qDebug
+#endif
+
+QT_BEGIN_NAMESPACE
+/*
+QGestureRecognizerMouseTwoButtons::QGestureRecognizerMouseTwoButtons()
+ : QGestureRecognizer(Qt::MouseTwoButtonClick)
+{
+ clear();
+}
+
+QGestureRecognizer::Result QGestureRecognizerMouseTwoButtons::recognize(const QList<QEvent*> &inputEvents)
+{
+ // get all mouse events
+ QList<QMouseEvent*> events;
+ for(int i = 0; i < inputEvents.count(); ++i) {
+ QEvent *event = inputEvents.at(i);
+ switch (event->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ events.push_back(static_cast<QMouseEvent*>(event));
+ default:
+ break;
+ }
+ }
+
+ QGestureRecognizer::Result result = QGestureRecognizer::NotGesture;
+ for(int i = 0; i < events.count(); ++i) {
+ QMouseEvent *event = events.at(i);
+ if (event->type() == QEvent::MouseButtonPress) {
+ if (userEvents[3]) {
+ // something wrong, we already has a gesture.
+ clear();
+ } else if (userEvents[2]) {
+ // 1d, 2d, 1u, and user press another button. not gesture.
+ DEBUG() << "1";
+ result = QGestureRecognizer::NotGesture;
+ clear();
+ break;
+ } else if (userEvents[1]) {
+ // 1d, 2d, and user pressed third button. not gesture.
+ DEBUG() << "2";
+ result = QGestureRecognizer::NotGesture;
+ clear();
+ break;
+ } else if (userEvents[0]) {
+ // second button press.
+ DEBUG() << "3";
+ userEvents[1] = event;
+ result = QGestureRecognizer::MaybeGesture;
+ } else {
+ // first button press.
+ DEBUG() << "4";
+ userEvents[0] = event;
+ result = QGestureRecognizer::MaybeGesture;
+ }
+ } else if (event->type() == QEvent::MouseButtonRelease) {
+ if (userEvents[3]) {
+ // something wrong, we already has a gesture.
+ clear();
+ } else if (userEvents[2]) {
+ // 1d, 2d, 1u, and button release
+ DEBUG() << "5";
+ if (userEvents[1]->button() != event->button()) {
+ // got weird buttonreleased event. doesn't look like gesture.
+ result = QGestureRecognizer::NotGesture;
+ clear();
+ break;
+ }
+ // gesture!
+ userEvents[3] = event;
+ result = QGestureRecognizer::GestureFinished;
+ break;
+ } else if (userEvents[1]) {
+ // 1d, 2d, and button release
+ DEBUG() << "6";
+ if (userEvents[0]->button() != event->button()) {
+ // user released the wrong button. not gesture.
+ result = QGestureRecognizer::NotGesture;
+ clear();
+ break;
+ }
+ // user released the right button! looks like gesture
+ userEvents[2] = event;
+ result = QGestureRecognizer::MaybeGesture;
+ } else if (userEvents[0]) {
+ // 1d, and some button was released. not a gesture.
+ DEBUG() << "7";
+ result = QGestureRecognizer::NotGesture;
+ clear();
+ break;
+ }
+ }
+ }
+ return result;
+}
+
+QGesture* QGestureRecognizerMouseTwoButtons::makeEvent() const
+{
+ if (!userEvents[0] || !userEvents[1] || !userEvents[2] || !userEvents[3])
+ return 0;
+ QGesture::Direction direction =
+ (userEvents[0]->button() < userEvents[1]->button() ?
+ QGesture::Left : QGesture::Right);
+ QList<QPoint> points;
+ points.push_back(userEvents[0]->globalPos());
+ points.push_back(userEvents[1]->globalPos());
+ QGesture *gesture =
+ new QGesture(Qt::MouseTwoButtonClick, points.at(0), points.at(1), points.at(1),
+ direction,
+ QRect(points.at(0), points.at(1)),
+ points.at(0));
+ return gesture;
+}
+
+void QGestureRecognizerMouseTwoButtons::reset()
+{
+ clear();
+}
+
+void QGestureRecognizerMouseTwoButtons::clear()
+{
+ userEvents[0] = userEvents[1] = userEvents[2] = userEvents[3] = 0;
+}
+*/
+
+//
+// QGestureRecognizerPan
+//
+
+QGestureRecognizerPan::QGestureRecognizerPan()
+ : QGestureRecognizer(Qt::Pan), mousePressed(false), gestureFinished(false),
+ lastDirection(Direction::None)
+{
+}
+
+QGestureRecognizer::Result QGestureRecognizerPan::recognize(const QList<QEvent*> &inputEvents)
+{
+ // get all mouse events
+ QList<QMouseEvent*> events;
+ for(int i = 0; i < inputEvents.count(); ++i) {
+ QEvent *event = inputEvents.at(i);
+ switch (event->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseMove:
+ events.push_back(static_cast<QMouseEvent*>(event));
+ default:
+ break;
+ }
+ }
+
+ QGestureRecognizer::Result result = QGestureRecognizer::NotGesture;
+ for(int i = 0; i < events.count(); ++i) {
+ QMouseEvent *event = events.at(i);
+ if (event->type() == QEvent::MouseButtonPress) {
+ if (lastDirection != Direction::None) {
+ DEBUG() << "Pan: MouseButtonPress: fail. another press during pan";
+ result = QGestureRecognizer::NotGesture;
+ reset();
+ break;
+ }
+ DEBUG() << "Pan: MouseButtonPress: maybe gesture started";
+ result = QGestureRecognizer::MaybeGesture;
+ mousePressed = true;
+ pressedPos = lastPos = currentPos = event->pos();
+ } else if (event->type() == QEvent::MouseButtonRelease) {
+ if (mousePressed && lastDirection != Direction::None) {
+ DEBUG() << "Pan: MouseButtonRelease: pan detected";
+ result = QGestureRecognizer::GestureFinished;
+ gestureFinished = true;
+ currentPos = event->pos();
+ internalReset();
+ break;
+ }
+ DEBUG() << "Pan: MouseButtonRelease: some weird release detected, ignoring";
+ result = QGestureRecognizer::NotGesture;
+ reset();
+ break;
+ } else if (event->type() == QEvent::MouseMove) {
+ if (!mousePressed)
+ continue;
+ lastPos = currentPos;
+ currentPos = event->pos();
+ Direction::DirectionType direction =
+ simpleRecognizer.addPosition(event->pos()).direction;
+ DEBUG() << "Pan: MouseMove: simplerecognizer result = " << direction;
+ if (lastDirection == Direction::None) {
+ if (direction == Direction::None)
+ result = QGestureRecognizer::MaybeGesture;
+ else
+ result = QGestureRecognizer::GestureStarted;
+ } else {
+ result = QGestureRecognizer::GestureStarted;
+ }
+ if (direction != Direction::None)
+ lastDirection = direction;
+ }
+ }
+ return result;
+}
+
+QGesture* QGestureRecognizerPan::makeEvent() const
+{
+ QPannableGesture::DirectionType dir = QPannableGesture::None;
+ if (lastDirection == Direction::Left)
+ dir = QPannableGesture::Left;
+ else if (lastDirection == Direction::Right)
+ dir = QPannableGesture::Right;
+ else if (lastDirection == Direction::Up)
+ dir = QPannableGesture::Up;
+ else if (lastDirection == Direction::Down)
+ dir = QPannableGesture::Down;
+ else
+ return 0;
+ QPannableGesture *g =
+ new QPannableGesture(Qt::Pan, pressedPos, lastPos, currentPos,
+ QRect(), pressedPos, QDateTime(), 0,
+ gestureFinished ? Qt::GestureFinished : Qt::GestureStarted);
+ QPannableGesturePrivate *d = (QPannableGesturePrivate*)g->d;
+ d->lastDirection = dir; ///###
+ d->direction = dir;
+
+ return g;
+}
+
+void QGestureRecognizerPan::reset()
+{
+ mousePressed = false;
+ lastDirection = Direction::None;
+ gestureFinished = false;
+ diagonalRecognizer.reset();
+ simpleRecognizer.reset();
+}
+
+void QGestureRecognizerPan::internalReset()
+{
+ mousePressed = false;
+ diagonalRecognizer.reset();
+ simpleRecognizer.reset();
+}
+
+
+//
+// QDoubleTapGestureRecognizer
+//
+QDoubleTapGestureRecognizer::QDoubleTapGestureRecognizer()
+ : QGestureRecognizer(Qt::DoubleTap)
+{
+}
+
+QGestureRecognizer::Result QDoubleTapGestureRecognizer::recognize(const QList<QEvent*> &inputEvents)
+{
+ // get all mouse events
+ QList<QMouseEvent*> events;
+ for(int i = 0; i < inputEvents.count(); ++i) {
+ QEvent *event = inputEvents.at(i);
+ switch (event->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseMove:
+ events.push_back(static_cast<QMouseEvent*>(event));
+ default:
+ break;
+ }
+ }
+
+ QGestureRecognizer::Result result = QGestureRecognizer::NotGesture;
+ for(int i = 0; i < events.count(); ++i) {
+ QMouseEvent *event = events.at(i);
+ if (event->type() == QEvent::MouseButtonPress) {
+ if (pressedPosition.isNull()) {
+ result = QGestureRecognizer::MaybeGesture;
+ pressedPosition = event->pos();
+ } else if ((pressedPosition - event->pos()).manhattanLength() < 10) {
+ result = QGestureRecognizer::GestureFinished;
+ }
+ } else if (event->type() == QEvent::MouseButtonRelease) {
+ if (!pressedPosition.isNull() && (pressedPosition - event->pos()).manhattanLength() < 10)
+ result = QGestureRecognizer::MaybeGesture;
+ } else if (event->type() == QEvent::MouseButtonDblClick) {
+ result = QGestureRecognizer::GestureFinished;
+ pressedPosition = event->pos();
+ break;
+ }
+ }
+ return result;
+}
+
+QGesture* QDoubleTapGestureRecognizer::makeEvent() const
+{
+ return new QGesture(Qt::DoubleTap,
+ pressedPosition, pressedPosition, pressedPosition,
+ QRect(), pressedPosition, QDateTime(), 0, Qt::GestureFinished);
+}
+
+void QDoubleTapGestureRecognizer::reset()
+{
+ pressedPosition = QPoint();
+}
+
+//
+// QLongTapGestureRecognizer
+//
+const int QLongTapGestureRecognizer::iterationCount = 40;
+const int QLongTapGestureRecognizer::iterationTimeout = 50;
+
+QLongTapGestureRecognizer::QLongTapGestureRecognizer()
+ : QGestureRecognizer(Qt::LongTap), iteration(0)
+{
+}
+
+QGestureRecognizer::Result QLongTapGestureRecognizer::recognize(const QList<QEvent*> &inputEvents)
+{
+ // get all mouse events
+ QList<QMouseEvent*> events;
+ for(int i = 0; i < inputEvents.count(); ++i) {
+ QEvent *event = inputEvents.at(i);
+ switch (event->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseMove:
+ events.push_back(static_cast<QMouseEvent*>(event));
+ default:
+ break;
+ }
+ }
+
+ QGestureRecognizer::Result result = QGestureRecognizer::NotGesture;
+ for(int i = 0; i < events.count(); ++i) {
+ QMouseEvent *event = events.at(i);
+ if (event->type() == QEvent::MouseButtonPress) {
+ if (timer.isActive())
+ timer.stop();
+ timer.start(QLongTapGestureRecognizer::iterationTimeout, this);
+ pressedPosition = event->pos();
+ result = QGestureRecognizer::MaybeGesture;
+ } else if (event->type() == QEvent::MouseMove) {
+ if ((pressedPosition - event->pos()).manhattanLength() < 15)
+ result = QGestureRecognizer::GestureStarted;
+ else
+ result = QGestureRecognizer::NotGesture;
+ } else if (event->type() == QEvent::MouseButtonRelease) {
+ result = QGestureRecognizer::NotGesture;
+ timer.stop();
+ break;
+ }
+ }
+ return result;
+}
+
+void QLongTapGestureRecognizer::timerEvent(QTimerEvent *event)
+{
+ if (event->timerId() != timer.timerId())
+ return;
+ if (++iteration == QLongTapGestureRecognizer::iterationCount) {
+ emit triggered(QGestureRecognizer::GestureFinished);
+ timer.stop();
+ } else {
+ emit triggered(QGestureRecognizer::GestureStarted);
+ }
+}
+
+QGesture* QLongTapGestureRecognizer::makeEvent() const
+{
+ return new QGesture(Qt::LongTap,
+ pressedPosition, pressedPosition, pressedPosition,
+ QRect(), pressedPosition, QDateTime(), 0,
+ iteration >= QLongTapGestureRecognizer::iterationCount ?
+ Qt::GestureFinished : Qt::GestureStarted);
+}
+
+void QLongTapGestureRecognizer::reset()
+{
+ pressedPosition = QPoint();
+ timer.stop();
+ iteration = 0;
+}
+
+//
+// QMultiTouchGestureRecognizer
+//
+
+/*
+QMultiTouchGestureRecognizer::QMultiTouchGestureRecognizer()
+ : QGestureRecognizer(Qt::Pinch)
+{
+}
+
+QGestureRecognizer::Result QMultiTouchGestureRecognizer::recognize(const QList<QEvent*> &inputEvents)
+{
+ QGestureRecognizer::Result result = QGestureRecognizer::NotGesture;
+ for(int i = 0; i < inputEvents.count(); ++i) {
+ QEvent *inputEvent = inputEvents.at(i);
+ if (inputEvent->type() != QEvent::Pointer) {
+ if (touches.size() == 2)
+ result = QGestureRecognizer::GestureStarted;
+ else if (touches.size() == 1)
+ result = QGestureRecognizer::MaybeGesture;
+ continue;
+ }
+ QPointerEvent *event = static_cast<QPointerEvent*>(inputEvent);
+ Q_ASSERT(event->pointerCount() > 0);
+ for (int idx = 0; idx < event->pointerCount(); ++idx) {
+ switch (event->state(idx)) {
+ case QPointerEvent::Begin:
+ qDebug() << "Begin" << idx;
+ if (touches.size() == 2) {
+ // too many touches
+ qDebug() << "too many touches";
+ result = QGestureRecognizer::MaybeGesture;
+ continue;
+ }
+ touches[event->pointerId(idx)].startPosition = event->pos(idx);
+ if (touches.size() == 1) {
+ result = QGestureRecognizer::MaybeGesture;
+ } else if (touches.size() == 2) {
+ result = QGestureRecognizer::GestureStarted;
+ } else {
+ result = QGestureRecognizer::NotGesture;
+ }
+ break;
+
+ case QPointerEvent::Move:
+ qDebug() << "Move" << idx;
+ touches[event->pointerId(idx)].lastPosition = touches[event->pointerId(idx)].currentPosition;
+ touches[event->pointerId(idx)].currentPosition = event->pos(idx);
+ if (touches.size() == 1)
+ result = QGestureRecognizer::MaybeGesture;
+ else if (touches.size() == 2)
+ result = QGestureRecognizer::GestureStarted;
+ else
+ result = QGestureRecognizer::NotGesture;
+ break;
+
+ case QPointerEvent::End:
+ qDebug() << "End" << idx;
+ touches.remove(event->pointerId(idx));
+ if (touches.size() == 1) {
+ result = QGestureRecognizer::MaybeGesture;
+ } else if (touches.size() == 0) {
+ result = QGestureRecognizer::NotGesture;
+ } else {
+ qDebug() << "unexpected touch end event";
+ return QGestureRecognizer::NotGesture;
+ }
+ break;
+
+ case QPointerEvent::Stationary:
+ qDebug() << "Stationary" << idx;
+ if (touches.size() == 2)
+ result = QGestureRecognizer::GestureStarted;
+ else if (touches.size() == 1)
+ result = QGestureRecognizer::MaybeGesture;
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ return result;
+}
+
+QGesture* QMultiTouchGestureRecognizer::makeEvent() const
+{
+ if (touches.size() != 2)
+ return 0;
+
+ QGesture *g = new QGesture(Qt::Pinch);
+ QGesture::Data data;
+
+ TapMap::const_iterator it = touches.begin();
+ data.startPos = it->startPosition.toPoint();
+ data.lastPos = it->lastPosition.toPoint();
+ data.currentPos = it->currentPosition.toPoint();
+ g->datas.push_back(data);
+
+ ++it;
+ data.startPos = it->startPosition.toPoint();
+ data.lastPos = it->lastPosition.toPoint();
+ data.currentPos = it->currentPosition.toPoint();
+ g->datas.push_back(data);
+
+ return g;
+}
+
+void QMultiTouchGestureRecognizer::reset()
+{
+ touches.clear();
+}
+*/
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qgesturestandardrecognizers_p.h b/src/gui/kernel/qgesturestandardrecognizers_p.h
new file mode 100644
index 0000000..3b314e7
--- /dev/null
+++ b/src/gui/kernel/qgesturestandardrecognizers_p.h
@@ -0,0 +1,169 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial Usage
+** Licensees holding valid Qt Commercial licenses may use this file in
+** accordance with the Qt Commercial License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Nokia.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGESTURESTANDARDRECOGNIZERS_P_H
+#define QGESTURESTANDARDRECOGNIZERS_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 "qevent.h"
+#include "qbasictimer.h"
+#include "qdebug.h"
+
+#include "qgesturerecognizer.h"
+#include "private/qdirectionrecognizer_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*
+class QGestureRecognizerMouseTwoButtons : public QGestureRecognizer
+{
+ Q_OBJECT
+public:
+ QGestureRecognizerMouseTwoButtons();
+ QGestureRecognizer::Result recognize(const QList<QEvent*> &inputEvents);
+
+ QGesture* makeEvent() const;
+ void reset();
+
+private:
+ void clear();
+
+ // find the last two button click events
+ QMouseEvent* userEvents[4];
+};
+*/
+
+class QGestureRecognizerPan : public QGestureRecognizer
+{
+ Q_OBJECT
+public:
+ QGestureRecognizerPan();
+
+ QGestureRecognizer::Result recognize(const QList<QEvent*> &inputEvents);
+ QGesture* makeEvent() const;
+
+ void reset();
+
+private:
+ void internalReset();
+
+ QPoint pressedPos;
+ QPoint lastPos;
+ QPoint currentPos;
+ bool mousePressed;
+ bool gestureFinished;
+ Direction::DirectionType lastDirection;
+ QDirectionDiagonalRecognizer diagonalRecognizer;
+ QDirectionSimpleRecognizer simpleRecognizer;
+};
+
+class QDoubleTapGestureRecognizer : public QGestureRecognizer
+{
+ Q_OBJECT
+public:
+ QDoubleTapGestureRecognizer();
+
+ QGestureRecognizer::Result recognize(const QList<QEvent*> &inputEvents);
+ QGesture* makeEvent() const;
+ void reset();
+
+private:
+ QPoint pressedPosition;
+};
+
+class QLongTapGestureRecognizer : public QGestureRecognizer
+{
+ Q_OBJECT
+public:
+ QLongTapGestureRecognizer();
+
+ QGestureRecognizer::Result recognize(const QList<QEvent*> &inputEvents);
+ QGesture* makeEvent() const;
+ void reset();
+
+protected:
+ void timerEvent(QTimerEvent *event);
+
+private:
+ QPoint pressedPosition;
+ QBasicTimer timer;
+ int iteration;
+ static const int iterationCount;
+ static const int iterationTimeout;
+};
+
+/*
+class QMultiTouchGestureRecognizer : public QGestureRecognizer
+{
+ Q_OBJECT
+public:
+ QMultiTouchGestureRecognizer();
+
+ QMap<Qt::GestureType, int> maybeGestureCompletion();
+ QGestureRecognizer::Result recognize(const QList<QEvent*> &inputEvents);
+ QGesture* makeEvent() const;
+ void reset();
+
+private:
+ struct Tap {
+ //### should I use QPointF everywhere internally ??
+ QPointF startPosition;
+ QPointF lastPosition;
+ QPointF currentPosition;
+ };
+ typedef QMap<int, Tap> TapMap;
+ TapMap touches;
+};
+*/
+
+QT_END_NAMESPACE
+
+#endif // QGESTURESTANDARDRECOGNIZERS_P_H
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index 968a423..f6be730 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -7532,6 +7532,7 @@ bool QWidget::event(QEvent *event)
#ifndef QT_NO_WHEELEVENT
case QEvent::Wheel:
#endif
+ case QEvent::Gesture:
return false;
default:
break;
@@ -7927,6 +7928,9 @@ bool QWidget::event(QEvent *event)
d->needWindowChange = false;
break;
#endif
+ case QEvent::Gesture:
+ gestureEvent((QGestureEvent*)event);
+ break;
#ifndef QT_NO_PROPERTIES
case QEvent::DynamicPropertyChange: {
const QByteArray &propName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName();
@@ -8732,6 +8736,11 @@ bool QWidget::qwsEvent(QWSEvent *)
#endif
+void QWidget::gestureEvent(QGestureEvent *event)
+{
+ event->ignore();
+}
+
/*!
Ensures that the widget has been polished by QStyle (i.e., has a
@@ -11016,6 +11025,42 @@ QWindowSurface *QWidget::windowSurface() const
return bs ? bs->windowSurface : 0;
}
+void QWidget::grabGesture(Qt::GestureType gesture)
+{
+ Q_D(QWidget);
+ if (d->gestures.contains(gesture))
+ return;
+ d->gestures << gesture;
+ ++qApp->d_func()->grabbedGestures[gesture];
+}
+
+void QWidget::grabGestures(const QSet<Qt::GestureType> &gestures)
+{
+ Q_D(QWidget);
+ foreach(const Qt::GestureType &gesture, gestures) {
+ if (!d->gestures.contains(gesture))
+ ++qApp->d_func()->grabbedGestures[gesture];
+ }
+ d->gestures.unite(gestures);
+}
+
+void QWidget::releaseGesture(Qt::GestureType gesture)
+{
+ Q_D(QWidget);
+ QMap<Qt::GestureType, int>::iterator it =
+ qApp->d_func()->grabbedGestures.find(gesture);
+ if (it != qApp->d_func()->grabbedGestures.end() &&
+ d->gestures.contains(gesture))
+ ++it.value();
+ d->gestures.remove(gesture);
+}
+
+QSet<Qt::GestureType> QWidget::gestures()
+{
+ Q_D(const QWidget);
+ return d->gestures;
+}
+
void QWidgetPrivate::getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const
{
if (left)
diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h
index 6703d26..afe637d 100644
--- a/src/gui/kernel/qwidget.h
+++ b/src/gui/kernel/qwidget.h
@@ -59,6 +59,8 @@
#include <QtGui/qevent.h>
#endif
+#include <QtGui/qgesture.h>
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
@@ -90,6 +92,7 @@ class QDragLeaveEvent;
class QDropEvent;
class QShowEvent;
class QHideEvent;
+class QGestureEvent;
class QInputContext;
class QIcon;
class QWindowSurface;
@@ -610,6 +613,11 @@ public:
void setWindowSurface(QWindowSurface *surface);
QWindowSurface *windowSurface() const;
+ void grabGesture(Qt::GestureType gesture);
+ void grabGestures(const QSet<Qt::GestureType> &gestures);
+ void releaseGesture(Qt::GestureType gesture);
+ QSet<Qt::GestureType> gestures();
+
Q_SIGNALS:
void customContextMenuRequested(const QPoint &pos);
@@ -669,6 +677,8 @@ protected:
// Misc. protected functions
virtual void changeEvent(QEvent *);
+ virtual void gestureEvent(QGestureEvent *);
+
int metric(PaintDeviceMetric) const;
virtual void inputMethodEvent(QInputMethodEvent *);
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index 5f5e1b1..178f7ba 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -57,6 +57,7 @@
#include "private/qobject_p.h"
#include "QtCore/qrect.h"
#include "QtCore/qlocale.h"
+#include "QtCore/qset.h"
#include "QtGui/qregion.h"
#include "QtGui/qsizepolicy.h"
#include "QtGui/qstyle.h"
@@ -592,6 +593,8 @@ public:
uint isGLWidget : 1;
#endif
+ QSet<Qt::GestureType> gestures;
+
#if defined(Q_WS_X11) || defined (Q_WS_WIN) || defined(Q_WS_MAC)
#ifdef Q_WS_MAC
void setWSGeometry(bool dontShow=false, const QRect &oldRect = QRect());