summaryrefslogtreecommitdiffstats
path: root/src/gui/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/kernel')
-rw-r--r--src/gui/kernel/kernel.pri17
-rw-r--r--src/gui/kernel/qapplication.cpp187
-rw-r--r--src/gui/kernel/qapplication.h9
-rw-r--r--src/gui/kernel/qapplication_p.h45
-rw-r--r--src/gui/kernel/qapplication_win.cpp271
-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.h105
-rw-r--r--src/gui/kernel/qdirectionsimplificator_p.h172
-rw-r--r--src/gui/kernel/qevent.cpp374
-rw-r--r--src/gui/kernel/qevent.h96
-rw-r--r--src/gui/kernel/qevent_p.h17
-rw-r--r--src/gui/kernel/qgesture.cpp290
-rw-r--r--src/gui/kernel/qgesture.h147
-rw-r--r--src/gui/kernel/qgesture_p.h113
-rw-r--r--src/gui/kernel/qgesturemanager.cpp642
-rw-r--r--src/gui/kernel/qgesturemanager_p.h126
-rw-r--r--src/gui/kernel/qgesturerecognizer.cpp159
-rw-r--r--src/gui/kernel/qgesturerecognizer.h87
-rw-r--r--src/gui/kernel/qgesturerecognizer_p.h72
-rw-r--r--src/gui/kernel/qgesturestandardrecognizers.cpp306
-rw-r--r--src/gui/kernel/qgesturestandardrecognizers_p.h130
-rw-r--r--src/gui/kernel/qwidget.cpp107
-rw-r--r--src/gui/kernel/qwidget.h9
-rw-r--r--src/gui/kernel/qwidget_p.h7
-rw-r--r--src/gui/kernel/qwidget_win.cpp4
26 files changed, 3638 insertions, 32 deletions
diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri
index a1b982a..3016afb 100644
--- a/src/gui/kernel/kernel.pri
+++ b/src/gui/kernel/kernel.pri
@@ -41,7 +41,15 @@ HEADERS += \
kernel/qwidgetaction.h \
kernel/qwidgetaction_p.h \
kernel/qwindowdefs.h \
- kernel/qkeymapper_p.h
+ kernel/qkeymapper_p.h \
+ kernel/qgesture.h \
+ kernel/qgesture_p.h \
+ kernel/qgesturemanager_p.h \
+ kernel/qgesturerecognizer_p.h \
+ kernel/qgesturerecognizer.h \
+ kernel/qgesturestandardrecognizers_p.h \
+ kernel/qdirectionrecognizer_p.h \
+ kernel/qdirectionsimplificator_p.h
SOURCES += \
kernel/qaction.cpp \
@@ -70,7 +78,12 @@ SOURCES += \
kernel/qwhatsthis.cpp \
kernel/qwidget.cpp \
kernel/qwidgetaction.cpp \
- kernel/qkeymapper.cpp
+ kernel/qkeymapper.cpp \
+ kernel/qgesture.cpp \
+ kernel/qgesturemanager.cpp \
+ kernel/qgesturerecognizer.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 824d6f1..b142f2e 100644
--- a/src/gui/kernel/qapplication.cpp
+++ b/src/gui/kernel/qapplication.cpp
@@ -85,10 +85,13 @@
#include <stdlib.h>
#include "qapplication_p.h"
+#include "qevent_p.h"
#include "qwidget_p.h"
#include "qapplication.h"
+#include <private/qgesturemanager_p.h>
+
#ifdef Q_WS_WINCE
#include "qdatetime.h"
#include "qguifunctions_wince.h"
@@ -97,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()
@@ -132,6 +137,14 @@ int QApplicationPrivate::autoMaximizeThreshold = -1;
bool QApplicationPrivate::autoSipEnabled = false;
#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)
{
@@ -155,6 +168,8 @@ QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, QApplication::T
directPainters = 0;
#endif
+ gestureManager = 0;
+
if (!self)
self = this;
}
@@ -2859,7 +2874,8 @@ QWidget *QApplicationPrivate::pickMouseReceiver(QWidget *candidate, const QPoint
*/
bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event,
QWidget *alienWidget, QWidget *nativeWidget,
- QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver)
+ QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver,
+ bool spontaneous)
{
Q_ASSERT(receiver);
Q_ASSERT(event);
@@ -2912,7 +2928,11 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event,
// We need this quard in case someone opens a modal dialog / popup. If that's the case
// leaveAfterRelease is set to null, but we shall not update lastMouseReceiver.
const bool wasLeaveAfterRelease = leaveAfterRelease != 0;
- bool result = QApplication::sendSpontaneousEvent(receiver, event);
+ bool result;
+ if (spontaneous)
+ result = QApplication::sendSpontaneousEvent(receiver, event);
+ else
+ result = QApplication::sendEvent(receiver, event);
if (!graphicsWidget && leaveAfterRelease && event->type() == QEvent::MouseButtonRelease
&& !event->buttons() && QWidget::mouseGrabber() != leaveAfterRelease) {
@@ -3571,6 +3591,18 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
#endif // !QT_NO_WHEELEVENT || !QT_NO_TABLETEVENT
}
+ if (!d->grabbedGestures.isEmpty() && e->spontaneous() && receiver->isWidgetType()) {
+ const QEvent::Type t = e->type();
+ if (t == QEvent::MouseButtonPress || t == QEvent::MouseButtonRelease || t == QEvent::MouseMove
+ || t == QEvent::MouseButtonDblClick || t == QEvent::Wheel
+ || t == QEvent::KeyPress || t == QEvent::KeyRelease
+ || t == QEvent::TabletPress || t == QEvent::TabletRelease || t == QEvent::TabletMove
+ || t >= QEvent::User) {
+ if (QGestureManager::instance()->filterEvent(static_cast<QWidget*>(receiver), e))
+ return true;
+ }
+ }
+
// User input and window activation makes tooltips sleep
switch (e->type()) {
case QEvent::Wheel:
@@ -3698,19 +3730,10 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
QPoint relpos = mouse->pos();
if (e->spontaneous()) {
-
if (e->type() == QEvent::MouseButtonPress) {
- QWidget *fw = w;
- while (fw) {
- if (fw->isEnabled()
- && QApplicationPrivate::shouldSetFocus(fw, Qt::ClickFocus)) {
- fw->setFocus(Qt::MouseFocusReason);
- break;
- }
- if (fw->isWindow())
- break;
- fw = fw->parentWidget();
- }
+ QApplicationPrivate::giveFocusAccordingToFocusPolicy(w,
+ Qt::ClickFocus,
+ Qt::MouseFocusReason);
}
if (e->type() == QEvent::MouseMove && mouse->buttons() == 0) {
@@ -3792,17 +3815,9 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
bool eventAccepted = wheel->isAccepted();
if (e->spontaneous()) {
- QWidget *fw = w;
- while (fw) {
- if (fw->isEnabled()
- && QApplicationPrivate::shouldSetFocus(fw, Qt::WheelFocus)) {
- fw->setFocus(Qt::MouseFocusReason);
- break;
- }
- if (fw->isWindow())
- break;
- fw = fw->parentWidget();
- }
+ QApplicationPrivate::giveFocusAccordingToFocusPolicy(w,
+ Qt::WheelFocus,
+ Qt::MouseFocusReason);
}
while (w) {
@@ -4007,7 +4022,48 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
}
break;
#endif
+ case QEvent::TouchBegin:
+ // Note: TouchUpdate and TouchEnd events are sent to d->currentMultitouchWidget and never propagated
+ {
+ QWidget *widget = static_cast<QWidget *>(receiver);
+ 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,
+ Qt::ClickFocus,
+ Qt::MouseFocusReason);
+ }
+ while (widget) {
+ // first, try to deliver the touch event
+ touchEvent->ignore();
+ res = widget->testAttribute(Qt::WA_AcceptTouchEvents)
+ && d->notify_helper(widget, touchEvent);
+ eventAccepted = touchEvent->isAccepted();
+ widget->setAttribute(Qt::WA_AcceptedTouchBeginEvent, res && eventAccepted);
+ touchEvent->spont = false;
+ if (res && eventAccepted) {
+ // the first widget to accept the TouchBegin gets an implicit grab.
+ for (int i = 0; i < touchEvent->_touchPoints.count(); ++i) {
+ QTouchEvent::TouchPoint *touchPoint = touchEvent->_touchPoints.at(i);
+ d->widgetForTouchPointId[touchPoint->d->id] = widget;
+ }
+ if (origin != widget)
+ d->widgetCurrentTouchPoints.remove(origin);
+ d->widgetCurrentTouchPoints[widget] = touchEvent->_touchPoints;
+ break;
+ } else if (widget->isWindow() || widget->testAttribute(Qt::WA_NoMousePropagation)) {
+ break;
+ }
+ widget = widget->parentWidget();
+ d->updateTouchPointsForWidget(widget, touchEvent);
+ }
+
+ touchEvent->setAccepted(eventAccepted);
+ break;
+ }
default:
res = d->notify_helper(receiver, e);
break;
@@ -4974,6 +5030,23 @@ Qt::LayoutDirection QApplication::keyboardInputDirection()
return qt_keymapper_private()->keyboardInputDirection;
}
+void QApplicationPrivate::giveFocusAccordingToFocusPolicy(QWidget *widget,
+ Qt::FocusPolicy focusPolicy,
+ Qt::FocusReason focusReason)
+{
+ QWidget *focusWidget = widget;
+ while (focusWidget) {
+ if (focusWidget->isEnabled()
+ && QApplicationPrivate::shouldSetFocus(focusWidget, focusPolicy)) {
+ focusWidget->setFocus(focusReason);
+ break;
+ }
+ if (focusWidget->isWindow())
+ break;
+ focusWidget = focusWidget->parentWidget();
+ }
+}
+
bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy)
{
QWidget *f = w;
@@ -4987,6 +5060,57 @@ bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy)
return true;
}
+/*!
+ \since 4.6
+
+ Adds custom gesture \a recognizer object.
+
+ Qt takes ownership of the provided \a recognizer.
+
+ \sa Qt::AA_EnableGestures, QGestureEvent
+*/
+void QApplication::addGestureRecognizer(QGestureRecognizer *recognizer)
+{
+ QGestureManager::instance()->addRecognizer(recognizer);
+}
+
+/*!
+ \since 4.6
+
+ Removes custom gesture \a recognizer object.
+
+ \sa Qt::AA_EnableGestures, QGestureEvent
+*/
+void QApplication::removeGestureRecognizer(QGestureRecognizer *recognizer)
+{
+ Q_D(QApplication);
+ if (!d->gestureManager)
+ return;
+ d->gestureManager->removeRecognizer(recognizer);
+}
+
+/*!
+ \property QApplication::eventDeliveryDelayForGestures
+ \since 4.6
+
+ Specifies the \a delay before input events are delivered to the
+ gesture enabled widgets.
+
+ The delay allows to postpone widget's input event handling until
+ gestures framework can successfully recognize a gesture.
+
+ \sa QWidget::grabGesture
+*/
+void QApplication::setEventDeliveryDelayForGestures(int delay)
+{
+ QGestureManager::instance()->setEventDeliveryDelay(delay);
+}
+
+int QApplication::eventDeliveryDelayForGestures()
+{
+ return QGestureManager::instance()->eventDeliveryDelay();
+}
+
/*! \fn QDecoration &QApplication::qwsDecoration()
Return the QWSDecoration used for decorating windows.
@@ -5118,6 +5242,19 @@ bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy)
This normally takes some time. Does nothing on other platforms.
*/
+void QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent)
+{
+ for (int i = 0; i < touchEvent->_touchPoints.count(); ++i) {
+ QTouchEvent::TouchPoint *touchPoint = touchEvent->_touchPoints.at(i);
+
+ // preserve the sub-pixel resolution
+ const QPointF delta = touchPoint->d->screenPos - touchPoint->d->screenPos.toPoint();
+ touchPoint->d->pos = widget->mapFromGlobal(touchPoint->d->screenPos.toPoint()) + delta;
+ touchPoint->d->startPos = widget->mapFromGlobal(touchPoint->d->startScreenPos.toPoint()) + delta;
+ touchPoint->d->lastPos = widget->mapFromGlobal(touchPoint->d->lastScreenPos.toPoint()) + delta;
+ }
+}
+
QT_END_NAMESPACE
#include "moc_qapplication.cpp"
diff --git a/src/gui/kernel/qapplication.h b/src/gui/kernel/qapplication.h
index 2baf6dc..e09ea08 100644
--- a/src/gui/kernel/qapplication.h
+++ b/src/gui/kernel/qapplication.h
@@ -71,6 +71,7 @@ class QStyle;
class QEventLoop;
class QIcon;
class QInputContext;
+class QGestureRecognizer;
template <typename T> class QList;
class QLocale;
#if defined(Q_WS_QWS)
@@ -106,6 +107,7 @@ class Q_GUI_EXPORT QApplication : public QCoreApplication
Q_PROPERTY(int autoMaximizeThreshold READ autoMaximizeThreshold WRITE setAutoMaximizeThreshold)
Q_PROPERTY(bool autoSipEnabled READ autoSipEnabled WRITE setAutoSipEnabled)
#endif
+ Q_PROPERTY(int eventDeliveryDelayForGestures READ eventDeliveryDelayForGestures WRITE setEventDeliveryDelayForGestures)
public:
enum Type { Tty, GuiClient, GuiServer };
@@ -266,6 +268,12 @@ public:
static bool keypadNavigationEnabled();
#endif
+ void addGestureRecognizer(QGestureRecognizer *recognizer);
+ void removeGestureRecognizer(QGestureRecognizer *recognizer);
+
+ void setEventDeliveryDelayForGestures(int delay);
+ int eventDeliveryDelayForGestures();
+
Q_SIGNALS:
void lastWindowClosed();
void focusChanged(QWidget *old, QWidget *now);
@@ -374,6 +382,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 7e97418..08020fb 100644
--- a/src/gui/kernel/qapplication_p.h
+++ b/src/gui/kernel/qapplication_p.h
@@ -55,6 +55,7 @@
//
#include "QtGui/qapplication.h"
+#include "QtGui/qevent.h"
#include "QtGui/qfont.h"
#include "QtGui/qcursor.h"
#include "QtGui/qregion.h"
@@ -77,11 +78,9 @@ class QClipboard;
class QGraphicsScene;
class QGraphicsSystem;
class QInputContext;
-class QKeyEvent;
-class QMouseEvent;
class QObject;
-class QWheelEvent;
class QWidget;
+class QGestureManager;
extern bool qt_is_gui_used;
#ifndef QT_NO_CLIPBOARD
@@ -189,6 +188,12 @@ extern "C" {
}
#endif
+#if defined(Q_WS_WIN)
+typedef BOOL (WINAPI *qt_RegisterTouchWindowPtr)(HWND, ULONG);
+typedef BOOL (WINAPI *qt_GetTouchInputInfoPtr)(HANDLE, UINT, PVOID, int);
+typedef BOOL (WINAPI *qt_CloseTouchInputHandlePtr)(HANDLE);
+#endif
+
class QScopedLoopLevelCounter
{
QThreadData *threadData;
@@ -419,17 +424,49 @@ public:
QEvent::Type type, Qt::MouseButtons buttons,
QWidget *buttonDown, QWidget *alienWidget);
static bool sendMouseEvent(QWidget *receiver, QMouseEvent *event, QWidget *alienWidget,
- QWidget *native, QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver);
+ QWidget *native, QWidget **buttonDown, QPointer<QWidget> &lastMouseReceiver,
+ bool spontaneous = true);
#if defined(Q_WS_WIN) || defined(Q_WS_X11)
void sendSyntheticEnterLeave(QWidget *widget);
#endif
+ QGestureManager *gestureManager;
+ // map<gesture name -> number of widget subscribed to it>
+ QMap<QString, int> grabbedGestures;
+
+ QHash<int, QWidget *> widgetForTouchPointId;
+ QMap<QWidget *, QList<QTouchEvent::TouchPoint *> > widgetCurrentTouchPoints;
+ static void updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent);
+
+#if defined(Q_WS_WIN)
+ static qt_RegisterTouchWindowPtr RegisterTouchWindow;
+ static qt_GetTouchInputInfoPtr GetTouchInputInfo;
+ static qt_CloseTouchInputHandlePtr CloseTouchInputHandle;
+
+ QHash<DWORD, int> touchInputIDToTouchPointID;
+ QVector<QTouchEvent::TouchPoint *> appAllTouchPoints;
+ QList<QTouchEvent::TouchPoint *> appCurrentTouchPoints;
+
+ void initializeMultitouch();
+ static QTouchEvent::TouchPoint *findClosestTouchPoint(const QList<QTouchEvent::TouchPoint *> &activeTouchPoints,
+ const QPointF &screenPos);
+ QEvent::Type appendTouchPoint(QTouchEvent::TouchPoint *touchPoint,
+ QList<QTouchEvent::TouchPoint *> *currentTouchPoints);
+ QEvent::Type removeTouchPoint(QTouchEvent::TouchPoint *touchPoint,
+ QList<QTouchEvent::TouchPoint *> *currentTouchPoints);
+ bool translateTouchEvent(const MSG &msg);
+#endif
+
private:
#ifdef Q_WS_QWS
QMap<const QScreen*, QRect> maxWindowRects;
#endif
static QApplicationPrivate *self;
+
+ static void giveFocusAccordingToFocusPolicy(QWidget *w,
+ Qt::FocusPolicy focusPolicy,
+ Qt::FocusReason focusReason);
static bool shouldSetFocus(QWidget *w, Qt::FocusPolicy policy);
};
diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp
index 6237657..f537805 100644
--- a/src/gui/kernel/qapplication_win.cpp
+++ b/src/gui/kernel/qapplication_win.cpp
@@ -88,6 +88,7 @@ extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.c
#include "qdebug.h"
#include <private/qkeymapper_p.h>
#include <private/qlocale_p.h>
+#include "qevent_p.h"
//#define ALIEN_DEBUG
@@ -112,6 +113,39 @@ extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.c
# include <winable.h>
#endif
+#ifndef WM_TOUCHMOVE
+
+# define WM_TOUCHMOVE 0x0240
+# define WM_TOUCHDOWN 0x0241
+# define WM_TOUCHUP 0x0242
+
+# define TOUCHEVENTF_MOVE 0x0001
+# define TOUCHEVENTF_DOWN 0x0002
+# define TOUCHEVENTF_UP 0x0004
+# define TOUCHEVENTF_INRANGE 0x0008
+# define TOUCHEVENTF_PRIMARY 0x0010
+# define TOUCHEVENTF_NOCOALESCE 0x0020
+# define TOUCHEVENTF_PEN 0x0040
+
+# define TOUCHINPUTMASKF_TIMEFROMSYSTEM 0x0001
+# define TOUCHINPUTMASKF_EXTRAINFO 0x0002
+# define TOUCHINPUTMASKF_CONTACTAREA 0x0004
+
+typedef struct tagTOUCHINPUT
+{
+ LONG x;
+ LONG y;
+ HANDLE hSource;
+ DWORD dwID;
+ DWORD dwFlags;
+ DWORD dwMask;
+ DWORD dwTime;
+ ULONG_PTR dwExtraInfo;
+ DWORD cxContact;
+ DWORD cyContact;
+} TOUCHINPUT, *PTOUCHINPUT;
+
+#endif
#ifndef FLASHW_STOP
typedef struct {
@@ -853,6 +887,8 @@ void qt_init(QApplicationPrivate *priv, int)
if (ptrUpdateLayeredWindow && !ptrUpdateLayeredWindowIndirect)
ptrUpdateLayeredWindowIndirect = qt_updateLayeredWindowIndirect;
#endif
+
+ priv->initializeMultitouch();
}
/*****************************************************************************
@@ -1716,6 +1752,11 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
result = widget->translateWheelEvent(msg);
} else {
switch (message) {
+ case WM_TOUCHMOVE:
+ case WM_TOUCHDOWN:
+ case WM_TOUCHUP:
+ result = getQApplicationPrivateInternal()->translateTouchEvent(msg);
+ break;
case WM_KEYDOWN: // keyboard event
case WM_SYSKEYDOWN:
qt_keymapper_private()->updateKeyMap(msg);
@@ -3956,4 +3997,234 @@ void QSessionManager::cancel()
#endif //QT_NO_SESSIONMANAGER
+qt_RegisterTouchWindowPtr QApplicationPrivate::RegisterTouchWindow = 0;
+qt_GetTouchInputInfoPtr QApplicationPrivate::GetTouchInputInfo = 0;
+qt_CloseTouchInputHandlePtr QApplicationPrivate::CloseTouchInputHandle = 0;
+
+void QApplicationPrivate::initializeMultitouch()
+{
+ QLibrary library(QLatin1String("user32"));
+ RegisterTouchWindow = static_cast<qt_RegisterTouchWindowPtr>(library.resolve("RegisterTouchWindow"));
+ GetTouchInputInfo = static_cast<qt_GetTouchInputInfoPtr>(library.resolve("GetTouchInputInfo"));
+ CloseTouchInputHandle = static_cast<qt_CloseTouchInputHandlePtr>(library.resolve("CloseTouchInputHandle"));
+
+ widgetForTouchPointId.clear();
+ widgetCurrentTouchPoints.clear();
+ touchInputIDToTouchPointID.clear();
+ appAllTouchPoints.clear();
+ appCurrentTouchPoints.clear();
+}
+
+QTouchEvent::TouchPoint *QApplicationPrivate::findClosestTouchPoint(const QList<QTouchEvent::TouchPoint *> &appActiveTouchPoints,
+ const QPointF &screenPos)
+{
+ QTouchEvent::TouchPoint *closestTouchPoint = 0;
+ qreal closestDistance;
+ for (int i = 0; i < appActiveTouchPoints.count(); ++i) {
+ QTouchEvent::TouchPoint *touchPoint = appActiveTouchPoints.at(i);
+ qreal distance = QLineF(screenPos, touchPoint->d->screenPos).length();
+ if (!closestTouchPoint || distance < closestDistance) {
+ closestTouchPoint = touchPoint;
+ closestDistance = distance;
+ }
+ }
+ return closestTouchPoint;
+}
+
+QEvent::Type QApplicationPrivate::appendTouchPoint(QTouchEvent::TouchPoint *touchPoint,
+ QList<QTouchEvent::TouchPoint *> *currentTouchPoints)
+{
+ QEvent::Type eventType = currentTouchPoints->isEmpty()
+ ? QEvent::TouchBegin
+ : QEvent::TouchUpdate;
+
+ // insort touch point (for the app)
+ int at = 0;
+ for (; at < appCurrentTouchPoints.count(); ++at) {
+ if (appCurrentTouchPoints.at(at)->id() > touchPoint->id())
+ break;
+ }
+ appCurrentTouchPoints.insert(at, touchPoint);
+ // again, for the widget's currentTouchPoints
+ for (at = 0; at < currentTouchPoints->count(); ++at) {
+ if (currentTouchPoints->at(at)->id() > touchPoint->id())
+ break;
+ }
+ currentTouchPoints->insert(at, touchPoint);
+
+ if (appCurrentTouchPoints.count() > appAllTouchPoints.count()) {
+ qFatal("Qt: INTERNAL ERROR: appCurrentTouchPoints.count() (%d) > appAllTouchPoints.count() (%d)",
+ appCurrentTouchPoints.count(),
+ appAllTouchPoints.count());
+ }
+
+ return eventType;
+}
+
+QEvent::Type QApplicationPrivate::removeTouchPoint(QTouchEvent::TouchPoint *touchPoint,
+ QList<QTouchEvent::TouchPoint *> *currentTouchPoints)
+{
+ // remove touch point from all known touch points
+ for (int i = qMin(appCurrentTouchPoints.count() - 1, touchPoint->id()); i >= 0; --i) {
+ if (appCurrentTouchPoints.at(i) == touchPoint) {
+ appCurrentTouchPoints.removeAt(i);
+ break;
+ }
+ }
+ // again, for the widget's currentTouchPoints
+ for (int i = qMin(currentTouchPoints->count() - 1, touchPoint->id()); i >= 0; --i) {
+ if (currentTouchPoints->at(i) == touchPoint) {
+ currentTouchPoints->removeAt(i);
+ break;
+ }
+ }
+
+ return currentTouchPoints->isEmpty() ? QEvent::TouchEnd : QEvent::TouchUpdate;
+}
+
+bool QApplicationPrivate::translateTouchEvent(const MSG &msg)
+{
+ Q_Q(QApplication);
+
+ QWidget *widgetForHwnd = QWidget::find(msg.hwnd);
+ if (!widgetForHwnd)
+ return false;
+
+ QList<QTouchEvent::TouchPoint *> appActiveTouchPoints = appCurrentTouchPoints;
+
+ QHash<QWidget *, QTouchEvent> widgetsNeedingEvents;
+ QVector<TOUCHINPUT> winTouchInputs(msg.wParam);
+ memset(winTouchInputs.data(), 0, sizeof(TOUCHINPUT) * winTouchInputs.count());
+ QApplicationPrivate::GetTouchInputInfo((HANDLE) msg.lParam, msg.wParam, winTouchInputs.data(), sizeof(TOUCHINPUT));
+ for (int i = 0; i < winTouchInputs.count(); ++i) {
+ const TOUCHINPUT &touchInput = winTouchInputs.at(i);
+
+ int touchPointID = touchInputIDToTouchPointID.value(touchInput.dwID, -1);
+ if (touchPointID == -1) {
+ touchPointID = touchInputIDToTouchPointID.count();
+ touchInputIDToTouchPointID.insert(touchInput.dwID, touchPointID);
+ }
+
+ if (appAllTouchPoints.count() <= touchPointID)
+ appAllTouchPoints.resize(touchPointID + 1);
+
+ QTouchEvent::TouchPoint *touchPoint = appAllTouchPoints.at(touchPointID);
+ if (!touchPoint)
+ touchPoint = appAllTouchPoints[touchPointID] = new QTouchEvent::TouchPoint(touchPointID);
+
+ // update state
+ QWidget *widget = 0;
+ bool down = touchPoint->d->state != Qt::TouchPointReleased;
+ QPointF screenPos(qreal(touchInput.x) / qreal(100.), qreal(touchInput.y) / qreal(100.));
+ QEvent::Type eventType = QEvent::None;
+
+ QList<QTouchEvent::TouchPoint *> activeTouchPoints;
+ if (!down && (touchInput.dwFlags & TOUCHEVENTF_DOWN)) {
+ // determine which widget this event will go to
+ widget = widgetForHwnd->childAt(widgetForHwnd->mapFromGlobal(screenPos.toPoint()));
+ if (!widget)
+ widget = widgetForHwnd;
+
+ QTouchEvent::TouchPoint *closestTouchPoint = findClosestTouchPoint(appActiveTouchPoints, screenPos);
+ if (closestTouchPoint) {
+ QWidget *closestWidget = widgetForTouchPointId.value(closestTouchPoint->d->id);
+ if (closestWidget
+ && (widget->isAncestorOf(closestWidget)
+ || closestWidget->isAncestorOf(widget)))
+ widget = closestWidget;
+ }
+ widgetForTouchPointId[touchPoint->d->id] = widget;
+
+ QList<QTouchEvent::TouchPoint *> &currentTouchPoints = widgetCurrentTouchPoints[widget];
+ eventType = appendTouchPoint(touchPoint, &currentTouchPoints);
+ // make sure new points are added to activeTouchPoints as well
+ appActiveTouchPoints = appCurrentTouchPoints;
+ activeTouchPoints = currentTouchPoints;
+
+ touchPoint->d->state = Qt::TouchPointPressed;
+ touchPoint->d->screenPos
+ = touchPoint->d->startScreenPos
+ = touchPoint->d->lastScreenPos
+ = screenPos;
+ touchPoint->d->pressure = qreal(1.);
+ } else if (down && (touchInput.dwFlags & TOUCHEVENTF_UP)) {
+ widget = widgetForTouchPointId.take(touchPoint->d->id);
+ QList<QTouchEvent::TouchPoint *> &currentTouchPoints = widgetCurrentTouchPoints[widget];
+ appActiveTouchPoints = appCurrentTouchPoints;
+ activeTouchPoints = currentTouchPoints;
+ eventType = removeTouchPoint(touchPoint, &currentTouchPoints);
+
+ touchPoint->d->state = Qt::TouchPointReleased;
+ touchPoint->d->lastScreenPos = touchPoint->d->screenPos;
+ touchPoint->d->screenPos = screenPos;
+ touchPoint->d->pressure = qreal(0.);
+ } else if (down) {
+ widget = widgetForTouchPointId.value(touchPoint->d->id);
+ appActiveTouchPoints = appCurrentTouchPoints;
+ activeTouchPoints = widgetCurrentTouchPoints.value(widget);
+ eventType = QEvent::TouchUpdate;
+ touchPoint->d->state = screenPos == touchPoint->d->screenPos
+ ? Qt::TouchPointStationary
+ : Qt::TouchPointMoved;
+ touchPoint->d->lastScreenPos = touchPoint->d->screenPos;
+ touchPoint->d->screenPos = screenPos;
+ // pressure should still be 1.
+ }
+ Q_ASSERT(widget != 0 && eventType != QEvent::None);
+
+ if (touchPoint->d->state != Qt::TouchPointStationary) {
+ widgetsNeedingEvents.insert(widget,
+ QTouchEvent(eventType, q->keyboardModifiers(), activeTouchPoints));
+ }
+ }
+ QApplicationPrivate::CloseTouchInputHandle((HANDLE) msg.lParam);
+
+ if (widgetsNeedingEvents.isEmpty())
+ return false;
+
+ bool returnValue = false;
+ qt_tabletChokeMouse = false;
+
+ QHash<QWidget *, QTouchEvent>::ConstIterator it = widgetsNeedingEvents.constBegin();
+ const QHash<QWidget *, QTouchEvent>::ConstIterator end = widgetsNeedingEvents.constEnd();
+ for (; it != end; ++it) {
+ QWidget *widget = it.key();
+ if (!QApplicationPrivate::tryModalHelper(widget, 0))
+ continue;
+
+ QTouchEvent touchEvent = it.value();
+ updateTouchPointsForWidget(widget, &touchEvent);
+
+ switch (touchEvent.type()) {
+ case QEvent::TouchBegin:
+ {
+ // if the TouchBegin handler recurses, we assume that means the event
+ // has been implicitly accepted and continue to send touch events
+ widget->setAttribute(Qt::WA_AcceptedTouchBeginEvent);
+ bool res = QApplication::sendSpontaneousEvent(widget, &touchEvent)
+ && touchEvent.isAccepted();
+ returnValue = returnValue || (qt_tabletChokeMouse = qt_tabletChokeMouse || res);
+ break;
+ }
+ case QEvent::TouchEnd:
+ {
+ QList<QTouchEvent::TouchPoint *> currentTouchPoints = widgetCurrentTouchPoints.take(widget);
+ if (!currentTouchPoints.isEmpty()) {
+ qFatal("Qt: INTERNAL ERROR, the widget's currentTouchPoints should be empty!");
+ }
+ // fall-through intended
+ }
+ default:
+ if (widget->testAttribute(Qt::WA_AcceptedTouchBeginEvent)) {
+ (void) QApplication::sendSpontaneousEvent(widget, &touchEvent);
+ qt_tabletChokeMouse = true;
+ }
+ returnValue = returnValue || qt_tabletChokeMouse;
+ break;
+ }
+ }
+
+ return returnValue;
+}
+
QT_END_NAMESPACE
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..2896523
--- /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();
+ Qt::DirectionType direction = Qt::NoDirection;
+ if (dx < 0) {
+ if (-1*dx >= SIZE/2)
+ direction = Qt::LeftDirection;
+ } else {
+ if (dx >= SIZE/2)
+ direction = Qt::RightDirection;
+ }
+ if (dy < 0) {
+ if (-1*dy >= SIZE/2)
+ direction = Qt::UpDirection;
+ } else {
+ if (dy >= SIZE/2)
+ direction = Qt::DownDirection;
+ }
+ if (direction == Qt::NoDirection)
+ 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();
+
+ Qt::DirectionType direction = Qt::NoDirection;
+ 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 = Qt::RightDirection;
+ else if (angle <= 65)
+ direction = Qt::RightUpDirection;
+ else if (angle <= 110)
+ direction = Qt::UpDirection;
+ else if (angle <= 155)
+ direction = Qt::LeftUpDirection;
+ else if (angle <= 200)
+ direction = Qt::LeftDirection;
+ else if (angle <= 245)
+ direction = Qt::LeftDownDirection;
+ else if (angle <= 290)
+ direction = Qt::DownDirection;
+ else if (angle <= 335)
+ direction = Qt::RightDownDirection;
+ else
+ direction = Qt::RightDirection;
+
+ if (direction == Qt::NoDirection)
+ 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..ca3d1c1
--- /dev/null
+++ b/src/gui/kernel/qdirectionrecognizer_p.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** 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
+{
+ Qt::DirectionType direction;
+ QPoint point;
+
+ Direction(Qt::DirectionType dir, const QPoint &pt)
+ : direction(dir), point(pt) { }
+ Direction()
+ : direction(Qt::NoDirection) { }
+
+ inline bool isEmpty() const { return direction == Qt::NoDirection; }
+ inline bool isNull() const { return direction == Qt::NoDirection; }
+};
+
+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 0ab4423..d616e5e 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -52,6 +52,8 @@
QT_BEGIN_NAMESPACE
+QString qt_getStandardGestureTypeName(Qt::GestureType type);
+
/*!
\class QInputEvent
\ingroup events
@@ -3322,6 +3324,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();
@@ -3518,4 +3523,373 @@ QMenubarUpdatedEvent::QMenubarUpdatedEvent(QMenuBar * const menuBar)
#endif
+/*!
+ \class QGestureEvent
+ \since 4.6
+ \ingroup events
+
+ \brief The QGestureEvent class provides the parameters used for
+ gesture recognition.
+
+ The QGestureEvent class contains a list of gestures that are being
+ executed right now (\l{QGestureEvent::}{gestureTypes()}) and a
+ list of gestures that are cancelled (the 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 that
+ are being executed and a list of gesture that were cancelled (\a
+ cancelledGestures).
+*/
+QGestureEvent::QGestureEvent(const QSet<QGesture*> &gestures,
+ const QSet<QString> &cancelledGestures)
+ : QEvent(QEvent::Gesture), m_cancelledGestures(cancelledGestures)
+{
+ setAccepted(false);
+ foreach(QGesture *r, gestures)
+ m_gestures.insert(r->type(), r);
+}
+
+/*!
+ Destroys the QGestureEvent object.
+*/
+QGestureEvent::~QGestureEvent()
+{
+}
+
+/*!
+ Returns true if the gesture event contains gesture of specific \a
+ type; returns false otherwise.
+*/
+bool QGestureEvent::contains(Qt::GestureType type) const
+{
+ return contains(qt_getStandardGestureTypeName(type));
+}
+
+/*!
+ Returns true if the gesture event contains gesture of specific \a
+ type; returns false otherwise.
+*/
+bool QGestureEvent::contains(const QString &type) const
+{
+ return gesture(type) != 0;
+}
+
+/*!
+ Returns a list of gesture names that this event contains.
+*/
+QList<QString> QGestureEvent::gestureTypes() const
+{
+ return m_gestures.keys();
+}
+
+/*!
+ Returns extended information about a gesture of specific \a type.
+*/
+const QGesture* QGestureEvent::gesture(Qt::GestureType type) const
+{
+ return gesture(qt_getStandardGestureTypeName(type));
+}
+
+/*!
+ Returns extended information about a gesture of specific \a type.
+*/
+const QGesture* QGestureEvent::gesture(const QString &type) const
+{
+ return m_gestures.value(type, 0);
+}
+
+/*!
+ Returns extended information about all gestures in the event.
+*/
+QList<QGesture*> QGestureEvent::gestures() const
+{
+ return m_gestures.values();
+}
+
+/*!
+ Returns a set of gesture names that used to be executed, but were
+ cancelled (i.e. they were not finished properly).
+*/
+QSet<QString> QGestureEvent::cancelledGestures() const
+{
+ return m_cancelledGestures;
+}
+
+/*!
+ Sets the accept flag of the all gestures inside the event object,
+ the equivalent of calling \l{QEvent::accept()}{accept()} or
+ \l{QEvent::setAccepted()}{setAccepted(true)}.
+
+ Setting the accept parameter indicates that the event receiver
+ wants the gesture. Unwanted gestures might be propagated to the parent
+ widget.
+*/
+void QGestureEvent::acceptAll()
+{
+ QHash<QString, QGesture*>::iterator it = m_gestures.begin(),
+ e = m_gestures.end();
+ for(; it != e; ++it)
+ it.value()->accept();
+ setAccepted(true);
+}
+
+/*!
+ Sets the accept flag of the specified gesture inside the event
+ object, the equivalent of calling
+ \l{QGestureEvent::gesture()}{gesture(type)}->\l{QGesture::accept()}{accept()}
+
+ Setting the accept parameter indicates that the event receiver
+ wants the gesture. Unwanted gestures might be propagated to the parent
+ widget.
+*/
+void QGestureEvent::accept(Qt::GestureType type)
+{
+ if (QGesture *g = m_gestures.value(qt_getStandardGestureTypeName(type), 0))
+ g->accept();
+}
+
+/*!
+ Sets the accept flag of the specified gesture inside the event
+ object, the equivalent of calling
+ \l{QGestureEvent::gesture()}{gesture(type)}->\l{QGesture::accept()}{accept()}
+
+ Setting the accept parameter indicates that the event receiver
+ wants the gesture. Unwanted gestures might be propagated to the parent
+ widget.
+*/
+void QGestureEvent::accept(const QString &type)
+{
+ if (QGesture *g = m_gestures.value(type, 0))
+ g->accept();
+}
+
+/*! \class QTouchEvent
+ \brief The QTouchEvent class contains parameters that describe a touch event
+.
+ \since 4.6
+ \ingroup events
+
+ Touch events occur when pressing, releasing, or moving one or more
+ touch points on a touch device (such as a touch-screen or
+ track-pad), and if the widget has the Qt::WA_AcceptTouchEvents
+ attribute.
+
+ Like QMouseEvent, Qt automatically grabs the touch device on the
+ first press inside a widget; the widget will receive all touch
+ events until the last touch point is released.
+
+ A touch event contains a special accept flag that indicates
+ whether the receiver wants the event. By default, the event is
+ ignored. You should call accept() if the touch event is handled by
+ your widget. A touch event is propagated up the parent widget
+ chain until a widget accepts it with accept(), or an event filter
+ consumes it. If the touch event is neither accepted nor consumed,
+ then mouse events are simulated from the state of the first touch
+ point.
+
+ All touch events are of type QEvent::Touch. The touchPoints()
+ function returns a list of all touch points contained in the
+ event. Information about each touch point can be retreived using
+ the QTouchEvent::TouchPoint class.
+
+ The Qt::TouchPointState enum describes the different states that a
+ touch point may have.
+
+ QTouchEvent::TouchPoint Qt::TouchPointState Qt::WA_AcceptTouchEvents
+*/
+
+/*! \enum Qt::TouchPointState
+ \since 4.6
+
+ This enum represents the state of a touch point at the time the
+ QTouchEvent occurred.
+
+ \value TouchPointPressed The touch point is now pressed.
+ \value TouchPointMoved The touch point moved.
+ \value TouchPointStationary The touch point did not move.
+ \value TouchPointReleased The touch point was released.
+*/
+
+/*! \class QTouchEvent::TouchPoint
+ \brief The QTouchEvent::TouchPoint class provide information about a touch point in a QTouchEvent.
+ \since 4.6
+*/
+
+/*!
+ Constructs a QTouchEvent with the given \a type and \a
+ touchPoints. The \a modifiers are the current keyboard modifiers
+ at the time of the event.
+*/
+QTouchEvent::QTouchEvent(QEvent::Type type,
+ Qt::KeyboardModifiers modifiers,
+ const QList<QTouchEvent::TouchPoint *> &touchPoints)
+ : QInputEvent(type, modifiers), _touchPoints(touchPoints)
+{ }
+
+/*!
+ Destroys the QTouchEvent.
+*/
+QTouchEvent::~QTouchEvent()
+{ }
+
+/*! \fn const QList<QTouchEvent::TouchPoint *> &QTouchEvent::TouchPoints() const
+
+ Returns the list of touch points contained in the touch event.
+*/
+
+/*! \internal
+
+ Constructs a QTouchEvent::TouchPoint for use in a QTouchEvent.
+*/
+QTouchEvent::TouchPoint::TouchPoint(int id)
+ : d(new QTouchEventTouchPointPrivate(id))
+{ }
+
+/*! \internal
+
+ Destroys the QTouchEvent::TouchPoint.
+*/
+QTouchEvent::TouchPoint::~TouchPoint()
+{
+ delete d;
+}
+
+/*!
+ Returns the id number of this touch point. Id numbers are
+ sequential, starting at zero, meaning the first touch point has id
+ 0, the second has id 1, and so on...
+*/
+int QTouchEvent::TouchPoint::id() const
+{
+ return d->id;
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setId(int id)
+{
+ d->id = id;
+}
+
+/*!
+ Returns the current state of this touch point.
+*/
+Qt::TouchPointState QTouchEvent::TouchPoint::state() const
+{
+ return d->state;
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setState(Qt::TouchPointState state)
+{
+ d->state = state;
+}
+
+/*!
+ Returns the position of this touch point, relative to the widget
+ or item that received the event.
+*/
+QPointF QTouchEvent::TouchPoint::pos() const
+{
+ return d->pos;
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setPos(const QPointF &pos)
+{
+ d->pos = pos;
+}
+
+/*!
+ Returns the starting position of this touch point, relative to the
+ widget that received the event.
+*/
+QPointF QTouchEvent::TouchPoint::startPos() const
+{
+ return d->startPos;
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setStartPos(const QPointF &startPos)
+{
+ d->startPos = startPos;
+}
+
+/*!
+ Returns the position of this touch point from the previous touch
+ event, relative to the widget that received the event.
+*/
+QPointF QTouchEvent::TouchPoint::lastPos() const
+{
+ return d->lastPos;
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setLastPos(const QPointF &lastPos)
+{
+ d->lastPos = lastPos;
+}
+
+/*!
+ Returns the screen position of this touch point.
+*/
+QPointF QTouchEvent::TouchPoint::screenPos() const
+{
+ return d->screenPos;
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setScreenPos(const QPointF &screenPos)
+{
+ d->screenPos = screenPos;
+}
+
+/*!
+ Returns the starting screen position of this touch point.
+*/
+QPointF QTouchEvent::TouchPoint::startScreenPos() const
+{
+ return d->startScreenPos;
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setStartScreenPos(const QPointF &startScreenPos)
+{
+ d->startScreenPos = startScreenPos;
+}
+
+/*!
+ Returns the screen position of this touch point from the previous
+ touch event.
+*/
+QPointF QTouchEvent::TouchPoint::lastScreenPos() const
+{
+ return d->lastScreenPos;
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setLastScreenPos(const QPointF &lastScreenPos)
+{
+ d->lastScreenPos = lastScreenPos;
+}
+
+/*!
+ Returns the pressure of this touch point. The return value is in
+ the range 0.0 to 1.0.
+*/
+qreal QTouchEvent::TouchPoint::pressure() const
+{
+ return d->pressure;
+}
+
+/*! \internal */
+void QTouchEvent::TouchPoint::setPressure(qreal pressure)
+{
+ d->pressure = pressure;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index 449730d..ed4129c 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -52,6 +52,9 @@
#include <QtGui/qmime.h>
#include <QtGui/qdrag.h>
#include <QtCore/qvariant.h>
+#include <QtCore/qmap.h>
+#include <QtCore/qset.h>
+#include <QtGui/qgesture.h>
QT_BEGIN_HEADER
@@ -710,6 +713,41 @@ private:
};
#endif
+class Q_GUI_EXPORT QGestureEvent : public QEvent
+{
+public:
+ QGestureEvent(const QSet<QGesture*> &gestures,
+ const QSet<QString> &cancelledGestures = QSet<QString>());
+ ~QGestureEvent();
+
+ bool contains(Qt::GestureType type) const;
+ bool contains(const QString &type) const;
+
+ QList<QString> gestureTypes() const;
+
+ const QGesture* gesture(Qt::GestureType type) const;
+ const QGesture* gesture(const QString &type) const;
+ QList<QGesture*> gestures() const;
+
+ QSet<QString> cancelledGestures() const;
+
+ void acceptAll();
+#ifndef Q_NO_USING_KEYWORD
+ using QEvent::accept;
+#else
+ inline void accept() { QEvent::accept(); }
+#endif
+ void accept(Qt::GestureType type);
+ void accept(const QString &type);
+
+protected:
+ QHash<QString, QGesture*> m_gestures;
+ QSet<QString> m_cancelledGestures;
+
+ friend class QApplication;
+ friend class QGestureManager;
+};
+
#ifndef QT_NO_DEBUG_STREAM
Q_GUI_EXPORT QDebug operator<<(QDebug, const QEvent *);
#endif
@@ -719,6 +757,64 @@ inline bool operator==(QKeyEvent *e, QKeySequence::StandardKey key){return (e ?
inline bool operator==(QKeySequence::StandardKey key, QKeyEvent *e){return (e ? e->matches(key) : false);}
#endif // QT_NO_SHORTCUT
+class QTouchEventTouchPointPrivate;
+class Q_GUI_EXPORT QTouchEvent : public QInputEvent
+{
+public:
+ class Q_GUI_EXPORT TouchPoint
+ {
+ public:
+ TouchPoint(int id = -1);
+ ~TouchPoint();
+
+ int id() const;
+ void setId(int id);
+
+ Qt::TouchPointState state() const;
+ void setState(Qt::TouchPointState state);
+
+ QPointF pos() const;
+ void setPos(const QPointF &pos);
+
+ QPointF startPos() const;
+ void setStartPos(const QPointF &startPos);
+
+ QPointF lastPos() const;
+ void setLastPos(const QPointF &lastPos);
+
+ QPointF screenPos() const;
+ void setScreenPos(const QPointF &screenPos);
+
+ QPointF startScreenPos() const;
+ void setStartScreenPos(const QPointF &startScreenPos);
+
+ QPointF lastScreenPos() const;
+ void setLastScreenPos(const QPointF &lastScreenPos);
+
+ qreal pressure() const; // 0.0 -> 1.0
+ void setPressure(qreal pressure);
+
+ protected:
+ QTouchEventTouchPointPrivate *d;
+
+ friend class QApplication;
+ friend class QApplicationPrivate;
+ };
+
+ QTouchEvent(QEvent::Type type,
+ Qt::KeyboardModifiers modifiers,
+ const QList<QTouchEvent::TouchPoint *> &touchPoints);
+ ~QTouchEvent();
+
+ inline const QList<QTouchEvent::TouchPoint *> &touchPoints() const { return _touchPoints; }
+
+protected:
+ QList<QTouchEvent::TouchPoint *> _touchPoints;
+
+ friend class QApplication;
+ friend class QApplicationPrivate;
+};
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h
index 8e762d6..dd78c3e 100644
--- a/src/gui/kernel/qevent_p.h
+++ b/src/gui/kernel/qevent_p.h
@@ -89,6 +89,23 @@ protected:
friend class QMouseEvent;
};
+class QTouchEventTouchPointPrivate
+{
+public:
+ inline QTouchEventTouchPointPrivate(int id)
+ : id(id),
+ state(Qt::TouchPointReleased),
+ pressure(qreal(-1.))
+ { }
+
+ int id;
+ Qt::TouchPointState state;
+ QPointF pos, startPos, lastPos;
+ QPointF scenePos, startScenePos, lastScenePos;
+ QPointF screenPos, startScreenPos, lastScreenPos;
+ qreal pressure;
+};
+
QT_END_NAMESPACE
#endif // QEVENT_P_H
diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp
new file mode 100644
index 0000000..ac55521
--- /dev/null
+++ b/src/gui/kernel/qgesture.cpp
@@ -0,0 +1,290 @@
+/****************************************************************************
+**
+** 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>
+
+QT_BEGIN_NAMESPACE
+
+QString qt_getStandardGestureTypeName(Qt::GestureType type);
+
+/*!
+ \class QGesture
+ \since 4.6
+
+ \brief The QGesture class represents a gesture, containing all
+ properties that describe a 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).
+
+ 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. However, if the gesture developer wants to add a new
+ property to the gesture object that describe coordinate (like a
+ QPoint or QRect), it is required to subclass the QGesture and
+ re-implement the \l{QGesture::}{translate()} function to make sure
+ the coordinates are translated properly when the gesture event is
+ propagated to parent widgets.
+
+ \sa QGestureEvent, QGestureRecognizer
+*/
+
+/*!
+ Creates a new gesture object of type \a type in a \a state and
+ marks it as a child of \a parent.
+
+ Usually QGesture objects should only be contructed by the
+ QGestureRecognizer classes.
+*/
+QGesture::QGesture(QObject *parent, const QString &type, Qt::GestureState state)
+ : QObject(*new QGesturePrivate, parent), m_accept(0)
+{
+ Q_D(QGesture);
+ d->type = type;
+ d->state = state;
+}
+
+/*!
+ Creates a new gesture object of type \a type in a \a state and
+ marks it as a child of \a parent.
+
+ This constructor also fills some basic information about the
+ gesture like a \a startPos which describes the start point of the
+ gesture, \a lastPos - last point where the gesture happened, \a
+ pos - a current point, \a rect - a bounding rect of the gesture,
+ \a hotSpot - a center point of the gesture, \a startTime - a time
+ when the gesture has started, \a duration - how long the gesture
+ is going on.
+
+ Usually QGesture objects should only be contructed by the
+ QGestureRecognizer classes.
+*/
+QGesture::QGesture(QObject *parent, const QString &type, const QPoint &startPos,
+ const QPoint &lastPos, const QPoint &pos, const QRect &rect,
+ const QPoint &hotSpot, const QDateTime &startTime,
+ uint duration, Qt::GestureState state)
+ : QObject(*new QGesturePrivate, parent)
+{
+ Q_D(QGesture);
+ d->type = type;
+ d->state = state;
+ d->init(startPos, lastPos, pos, rect, hotSpot, startTime, duration);
+}
+
+/*! \internal
+*/
+QGesture::QGesture(QGesturePrivate &dd, QObject *parent, const QString &type,
+ Qt::GestureState state)
+ : QObject(dd, parent)
+{
+ Q_D(QGesture);
+ d->type = type;
+ d->state = state;
+}
+
+/*!
+ Destroys the gesture object.
+*/
+QGesture::~QGesture()
+{
+}
+
+/*!
+ \property QGesture::type
+
+ \brief The type of the gesture.
+*/
+QString QGesture::type() const
+{
+ return d_func()->type;
+}
+
+
+/*!
+ \property QGesture::state
+
+ \brief The current state of the gesture.
+*/
+Qt::GestureState QGesture::state() const
+{
+ return d_func()->state;
+}
+
+/*!
+ Translates the internal gesture properties that represent
+ coordinates by \a offset.
+
+ Custom gesture recognizer developer have to re-implement this
+ function if they want to store custom properties that represent
+ coordinates.
+*/
+void QGesture::translate(const QPoint &offset)
+{
+ Q_D(QGesture);
+ d->rect.translate(offset);
+ d->hotSpot += offset;
+ d->startPos += offset;
+ d->lastPos += offset;
+ d->pos += offset;
+}
+
+/*!
+ \property QGesture::rect
+
+ \brief The bounding rect of a gesture.
+*/
+QRect QGesture::rect() const
+{
+ return d_func()->rect;
+}
+
+/*!
+ \property QGesture::hotSpot
+
+ \brief The center point of a gesture.
+*/
+QPoint QGesture::hotSpot() const
+{
+ return d_func()->hotSpot;
+}
+
+/*!
+ \property QGesture::startTime
+
+ \brief The time when the gesture has started.
+*/
+QDateTime QGesture::startTime() const
+{
+ return d_func()->startTime;
+}
+
+/*!
+ \property QGesture::duration
+
+ \brief The duration time of a gesture.
+*/
+uint QGesture::duration() const
+{
+ return d_func()->duration;
+}
+
+/*!
+ \property QGesture::startPos
+
+ \brief The start position of the pointer.
+*/
+QPoint QGesture::startPos() const
+{
+ return d_func()->startPos;
+}
+
+/*!
+ \property QGesture::lastPos
+
+ \brief The last recorded position of the pointer.
+*/
+QPoint QGesture::lastPos() const
+{
+ return d_func()->lastPos;
+}
+
+/*!
+ \property QGesture::pos
+
+ \brief The current position of the pointer.
+*/
+QPoint QGesture::pos() const
+{
+ return d_func()->pos;
+}
+
+/*!
+ \class QPanningGesture
+ \since 4.6
+
+ \brief The QPanningGesture class represents a Pan gesture,
+ providing additional information related to panning.
+
+ This class is provided for convenience, panning direction
+ information is also contained in the QGesture object in it's
+ properties.
+*/
+
+/*! \internal
+*/
+QPanningGesture::QPanningGesture(QObject *parent)
+ : QGesture(*new QPanningGesturePrivate, parent,
+ qt_getStandardGestureTypeName(Qt::PanGesture))
+{
+}
+
+/*! \internal
+*/
+QPanningGesture::~QPanningGesture()
+{
+}
+
+/*!
+ \property QPanningGesture::lastDirection
+
+ \brief The last recorded direction of panning.
+*/
+Qt::DirectionType QPanningGesture::lastDirection() const
+{
+ return d_func()->lastDirection;
+}
+
+/*!
+ \property QPanningGesture::direction
+
+ \brief The current direction of panning.
+*/
+Qt::DirectionType QPanningGesture::direction() const
+{
+ return d_func()->direction;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h
new file mode 100644
index 0000000..64a1424
--- /dev/null
+++ b/src/gui/kernel/qgesture.h
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** 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 "qmetatype.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QGesturePrivate;
+class Q_GUI_EXPORT QGesture : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QGesture)
+
+ Q_PROPERTY(QString type READ type)
+ Q_PROPERTY(Qt::GestureState state READ state)
+
+ Q_PROPERTY(QRect rect READ rect)
+ Q_PROPERTY(QPoint hotSpot READ hotSpot)
+ Q_PROPERTY(QDateTime startTime READ startTime)
+ Q_PROPERTY(uint duration READ duration)
+ Q_PROPERTY(QPoint startPos READ startPos)
+ Q_PROPERTY(QPoint lastPos READ lastPos)
+ Q_PROPERTY(QPoint pos READ pos)
+
+public:
+ QGesture(QObject *parent, const QString &type,
+ Qt::GestureState state = Qt::GestureStarted);
+ QGesture(QObject *parent,
+ const QString &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 void setAccepted(bool accepted) { m_accept = accepted; }
+ inline bool isAccepted() const { return m_accept; }
+
+ inline void accept() { m_accept = true; }
+ inline void ignore() { m_accept = false; }
+
+ QString type() const;
+ Qt::GestureState state() const;
+
+ 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, QObject *parent, const QString &type,
+ Qt::GestureState state = Qt::GestureStarted);
+ virtual void translate(const QPoint &offset);
+
+private:
+ ushort m_accept : 1;
+
+ friend class QGestureManager;
+ friend class QApplication;
+ friend class QGraphicsScene;
+ friend class QGraphicsScenePrivate;
+ friend class QGestureRecognizerPan;
+ friend class QDoubleTapGestureRecognizer;
+ friend class QTapAndHoldGestureRecognizer;
+};
+
+class QPanningGesturePrivate;
+class Q_GUI_EXPORT QPanningGesture : public QGesture
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QPanningGesture)
+
+ Q_PROPERTY(Qt::DirectionType lastDirection READ lastDirection)
+ Q_PROPERTY(Qt::DirectionType direction READ direction)
+
+public:
+ Qt::DirectionType lastDirection() const;
+ Qt::DirectionType direction() const;
+
+private:
+ QPanningGesture(QObject *parent = 0);
+ ~QPanningGesture();
+
+ friend class QGestureRecognizerPan;
+};
+
+Q_DECLARE_METATYPE(Qt::DirectionType)
+Q_DECLARE_METATYPE(Qt::GestureState)
+
+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..0f2e791
--- /dev/null
+++ b/src/gui/kernel/qgesture_p.h
@@ -0,0 +1,113 @@
+/****************************************************************************
+**
+** 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"
+#include "private/qobject_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QGraphicsItem;
+class QGesturePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QGesture)
+
+public:
+ QGesturePrivate()
+ : state(Qt::NoGesture), graphicsItem(0), singleshot(0), 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;
+ }
+
+ QString type;
+ Qt::GestureState state;
+
+ QPointer<QWidget> widget;
+ QGraphicsItem *graphicsItem;
+ uint singleshot:1;
+
+ QRect rect;
+ QPoint hotSpot;
+ QDateTime startTime;
+ uint duration;
+ QPoint startPos;
+ QPoint lastPos;
+ QPoint pos;
+};
+
+class QPanningGesturePrivate : public QGesturePrivate
+{
+ Q_DECLARE_PUBLIC(QPanningGesture)
+
+public:
+ Qt::DirectionType lastDirection;
+ Qt::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..9e8a5bb
--- /dev/null
+++ b/src/gui/kernel/qgesturemanager.cpp
@@ -0,0 +1,642 @@
+/****************************************************************************
+**
+** 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 "qgesture_p.h"
+#include "qevent.h"
+
+#include "qapplication.h"
+#include "qapplication_p.h"
+#include "qwidget.h"
+#include "qwidget_p.h"
+
+#include "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 const unsigned int MaximumGestureRecognitionTimeout = 2000;
+
+QGestureManager::QGestureManager(QObject *parent)
+ : QObject(parent), eventDeliveryDelayTimeout(300),
+ delayedPressTimer(0), lastMousePressReceiver(0), lastMousePressEvent(QEvent::None, QPoint(), Qt::NoButton, 0, 0),
+ lastGestureId(0), state(NotGesture)
+{
+ qRegisterMetaType<Qt::DirectionType>();
+ qRegisterMetaType<Qt::GestureState>();
+
+ recognizers << new QDoubleTapGestureRecognizer(this);
+ recognizers << new QTapAndHoldGestureRecognizer(this);
+ recognizers << new QGestureRecognizerPan(this);
+
+ foreach(QGestureRecognizer *r, recognizers)
+ connect(r, SIGNAL(stateChanged(QGestureRecognizer::Result)),
+ this, SLOT(recognizerStateChanged(QGestureRecognizer::Result)));
+}
+
+void QGestureManager::addRecognizer(QGestureRecognizer *recognizer)
+{
+ recognizer->setParent(this);
+ recognizers << recognizer;
+}
+
+void QGestureManager::removeRecognizer(QGestureRecognizer *recognizer)
+{
+ recognizers.remove(recognizer);
+}
+
+bool QGestureManager::filterEvent(QWidget *receiver, QEvent *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<QString, 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");
+
+ QSet<QGestureRecognizer*> stillMaybeGestures;
+ // try other recognizers.
+ foreach(QGestureRecognizer *r, recognizers) {
+ if (grabbedGestures.value(r->gestureType(), 0) <= 0)
+ continue;
+ QGestureRecognizer::Result result = r->filterEvent(event);
+ 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 (result == QGestureRecognizer::NotGesture) {
+ // if it was maybe gesture, but isn't a gesture anymore.
+ DEBUG() << "QGestureManager: not gesture: " << r;
+ notGestures << r;
+ }
+ }
+ Q_ASSERT(activeGestures.isEmpty());
+ activeGestures += startedGestures;
+ for(QMap<QGestureRecognizer*, int>::iterator it = maybeGestures.begin();
+ it != maybeGestures.end();) {
+ QGestureRecognizer *r = it.key();
+ if (startedGestures.contains(r) || finishedGestures.contains(r) ||
+ notGestures.contains(r)) {
+ killTimer(it.value());
+ it = maybeGestures.erase(it);
+ } else {
+ ++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() || !startedGestures.isEmpty()) {
+ // gesture found!
+ ret = true;
+ QSet<QGesture*> started;
+ foreach(QGestureRecognizer *r, finishedGestures) {
+ if (QGesture *gesture = r->getGesture()) {
+ started << gesture;
+ gesture->d_func()->singleshot = true;
+ }
+ }
+ foreach(QGestureRecognizer *r, startedGestures) {
+ if (QGesture *gesture = r->getGesture()) {
+ started << gesture;
+ gesture->d_func()->singleshot = false;
+ }
+ }
+ Q_ASSERT(!started.isEmpty());
+ ret = sendGestureEvent(receiver, started, QSet<QGesture*>());
+
+ 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->filterEvent(event);
+ 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 (result == QGestureRecognizer::NotGesture) {
+ // 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;
+ }
+ }
+ }
+
+ for(QMap<QGestureRecognizer*, int>::iterator it = maybeGestures.begin();
+ it != maybeGestures.end();) {
+ QGestureRecognizer *r = it.key();
+ if (startedGestures.contains(r) || finishedGestures.contains(r) ||
+ notGestures.contains(r)) {
+ killTimer(it.value());
+ it = maybeGestures.erase(it);
+ } else {
+ ++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);
+ }
+ }
+ QSet<QGesture*> started, updated;
+ if (!finishedGestures.isEmpty() || !startedGestures.isEmpty()) {
+ // another gesture found!
+ ret = true;
+ foreach(QGestureRecognizer *r, finishedGestures) {
+ if (QGesture *gesture = r->getGesture()) {
+ gesture->d_func()->singleshot = !activeGestures.contains(r);
+ if (gesture->d_func()->singleshot)
+ started << gesture;
+ else
+ updated << gesture;
+ }
+ }
+ foreach(QGestureRecognizer *r, startedGestures) {
+ if (QGesture *gesture = r->getGesture()) {
+ gesture->d_func()->singleshot = !activeGestures.contains(r);
+ if (gesture->d_func()->singleshot)
+ started << gesture;
+ else
+ updated << gesture;
+ }
+ }
+ }
+ activeGestures -= newMaybeGestures;
+ activeGestures -= cancelledGestures;
+ activeGestures += startedGestures;
+ activeGestures -= finishedGestures;
+ QSet<QString> cancelledGestureNames;
+ foreach(QGestureRecognizer *r, cancelledGestures)
+ cancelledGestureNames << r->gestureType();
+ ret = sendGestureEvent(receiver, started, updated, cancelledGestureNames);
+
+ 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;
+ }
+ }
+
+ if (delayedPressTimer && state == Gesture) {
+ DEBUG() << "QGestureManager: gesture started. Forgetting about postponed mouse press event";
+ killTimer(delayedPressTimer);
+ delayedPressTimer = 0;
+ lastMousePressReceiver = 0;
+ } else if (delayedPressTimer && (state == NotGesture ||
+ event->type() == QEvent::MouseButtonRelease)) {
+ // not a gesture or released button too fast, so replay press
+ // event back.
+ DEBUG() << "QGestureManager: replaying mouse press event";
+ QMap<QGestureRecognizer*, int>::const_iterator it = maybeGestures.begin(),
+ e = maybeGestures.end();;
+ for (; it != e; ++it) {
+ it.key()->reset();
+ killTimer(it.value());
+ }
+ maybeGestures.clear();
+ state = NotGesture;
+
+ if (lastMousePressReceiver) {
+ QApplication::sendEvent(lastMousePressReceiver, &lastMousePressEvent);
+ if (event->type() == QEvent::MouseButtonRelease) {
+ QMouseEvent *me = static_cast<QMouseEvent*>(event);
+ QMouseEvent move(QEvent::MouseMove, me->pos(), me->globalPos(), me->button(),
+ me->buttons(), me->modifiers());
+ QApplication::sendEvent(lastMousePressReceiver, &move);
+ ret = false;
+ }
+ lastMousePressReceiver = 0;
+ }
+ lastMousePressReceiver = 0;
+ killTimer(delayedPressTimer);
+ delayedPressTimer = 0;
+ } else if (state == MaybeGesture && event->type() == QEvent::MouseButtonPress
+ && eventDeliveryDelayTimeout) {
+ // postpone the press event delivery until we know for
+ // sure whether it is a gesture.
+ DEBUG() << "QGestureManager: postponing mouse press event";
+ QMouseEvent *me = static_cast<QMouseEvent*>(event);
+ lastMousePressReceiver = receiver;
+ lastMousePressEvent = QMouseEvent(QEvent::MouseButtonPress, me->pos(),
+ me->globalPos(), me->button(),
+ me->buttons(), me->modifiers());
+ Q_ASSERT(delayedPressTimer == 0);
+ delayedPressTimer = startTimer(eventDeliveryDelayTimeout);
+ if (!delayedPressTimer)
+ qWarning("QGestureManager: couldn't start delayed press timer!");
+ ret = true;
+ }
+ if (delayedPressTimer && event->type() == QEvent::MouseMove) {
+ // if we have postponed a mouse press event, postpone all
+ // subsequent mouse move events as well.
+ ret = true;
+ }
+
+ lastPos = currentPos;
+ return ret;
+}
+
+void QGestureManager::timerEvent(QTimerEvent *event)
+{
+ if (event->timerId() == delayedPressTimer) {
+ DEBUG() << "QGestureManager: replaying mouse press event due to timeout";
+ // sanity checks
+ Q_ASSERT(state != Gesture);
+
+ QMap<QGestureRecognizer*, int>::const_iterator it = maybeGestures.begin(),
+ e = maybeGestures.end();;
+ for (; it != e; ++it) {
+ it.key()->reset();
+ killTimer(it.value());
+ }
+ maybeGestures.clear();
+ state = NotGesture;
+
+ if (lastMousePressReceiver) {
+ // we neither received a mouse release event nor gesture
+ // started, so we replay stored mouse press event.
+ QApplication::sendEvent(lastMousePressReceiver, &lastMousePressEvent);
+ lastMousePressReceiver = 0;
+ }
+
+ lastMousePressReceiver = 0;
+ killTimer(delayedPressTimer);
+ delayedPressTimer = 0;
+ } else {
+ // 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::recognizerStateChanged(QGestureRecognizer::Result result)
+{
+ 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);
+ }
+ QSet<QGesture*> gestures;
+ if (QGesture *gesture = recognizer->getGesture())
+ gestures << gesture;
+ if(!gestures.isEmpty()) {
+ //FIXME: sendGestureEvent(targetWidget, gestures);
+ }
+ if (result == QGestureRecognizer::GestureFinished)
+ recognizer->reset();
+ }
+ break;
+ case QGestureRecognizer::MaybeGesture: {
+ DEBUG() << "QGestureManager: maybe gesture: " << recognizer;
+ if (activeGestures.contains(recognizer)) {
+ //FIXME: sendGestureEvent(targetWidget, QSet<QGesture*>(), QSet<QString>() << recognizer->gestureType());
+ }
+ 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);
+ }
+
+ if (delayedPressTimer && state == Gesture) {
+ killTimer(delayedPressTimer);
+ delayedPressTimer = 0;
+ }
+}
+
+bool QGestureManager::sendGestureEvent(QWidget *receiver,
+ const QSet<QGesture*> &startedGestures,
+ const QSet<QGesture*> &updatedGestures,
+ const QSet<QString> &cancelled)
+{
+ DEBUG() << "QGestureManager::sendGestureEvent: sending to" << receiver
+ << "gestures:" << startedGestures << "," << updatedGestures
+ << "cancelled:" << cancelled;
+ // grouping gesture objects by receiver widgets.
+ typedef QMap<QWidget*, QSet<QGesture*> > WidgetGesturesMap;
+ WidgetGesturesMap widgetGestures;
+ for(QSet<QGesture*>::const_iterator it = startedGestures.begin(), e = startedGestures.end();
+ it != e; ++it) {
+ QGesture *g = *it;
+ QGesturePrivate *gd = g->d_func();
+ if (receiver) {
+ // find the target widget
+ gd->widget = 0;
+ QWidget *w = receiver;
+ QPoint offset;
+ const QString gestureType = g->type();
+ while (w) {
+ if (w->d_func()->hasGesture(gestureType))
+ break;
+ if (w->isWindow()) {
+ w = 0;
+ break;
+ }
+ offset += w->pos();
+ w = w->parentWidget();
+ }
+ if (w && w != gd->widget) {
+ DEBUG() << "QGestureManager::sendGestureEvent:" << g << "propagating to widget" << w << "offset" << offset;
+ g->translate(offset);
+ }
+ gd->widget = w;
+ }
+ if (!gd->widget) {
+ DEBUG() << "QGestureManager: didn't find a widget to send gesture event ("
+ << g->type() << ") for tree:" << receiver;
+ // TODO: maybe we should reset gesture recognizers when nobody interested in its gestures.
+ continue;
+ }
+ widgetGestures[gd->widget].insert(g);
+ }
+
+ QSet<QGesture*> ignoredGestures;
+ bool ret = false;
+ for(WidgetGesturesMap::const_iterator it = widgetGestures.begin(), e = widgetGestures.end();
+ it != e; ++it) {
+ QWidget *receiver = it.key();
+ Q_ASSERT(receiver != 0 /*should be taken care above*/);
+ QSet<QGesture*> gestures = it.value();
+ // mark all gestures as ignored by default
+ for(QSet<QGesture*>::iterator it = gestures.begin(), e = gestures.end(); it != e; ++it)
+ (*it)->ignore();
+ // TODO: send cancelled gesture event to the widget that received the original gesture!
+ QGestureEvent event(gestures, cancelled);
+ DEBUG() << "QGestureManager::sendGestureEvent: sending now to" << receiver
+ << "gestures" << gestures;
+ bool processed = qt_sendSpontaneousEvent(receiver, &event);
+ QSet<QGesture*> started = startedGestures & gestures;
+ DEBUG() << "QGestureManager::sendGestureEvent:" <<
+ (event.isAccepted() ? "" : "not") << "all gestures were accepted";
+ if (!started.isEmpty() && !(processed && event.isAccepted())) {
+ // there are started gestures events that weren't
+ // accepted, so propagating each gesture independently.
+ if (event.isAccepted()) {
+ foreach(QGesture *g, started)
+ g->accept();
+ }
+ QSet<QGesture*>::const_iterator it = started.begin(),
+ e = started.end();
+ for(; it != e; ++it) {
+ QGesture *g = *it;
+ if (processed && g->isAccepted()) {
+ ret = true;
+ continue;
+ }
+ // if it wasn't accepted, find the first parent widget
+ // that is subscribed to the gesture.
+ QGesturePrivate *gd = g->d_func();
+ QWidget *w = gd->widget;
+ gd->widget = 0;
+
+ if (w && !w->isWindow()) {
+ g->translate(w->pos());
+ w = w->parentWidget();
+ QPoint offset;
+ const QString gestureType = g->type();
+ while (w) {
+ if (w->d_func()->hasGesture(gestureType)) {
+ DEBUG() << "QGestureManager::sendGestureEvent:" << receiver
+ << "didn't accept gesture" << g << "propagating to" << w;
+ ignoredGestures.insert(g);
+ gd->widget = w;
+ break;
+ }
+ if (w->isWindow()) {
+ w = 0;
+ break;
+ }
+ offset += w->pos();
+ w = w->parentWidget();
+ }
+ if (w) {
+ g->translate(offset);
+ } else {
+ DEBUG() << "QGestureManager::sendGestureEvent:" << receiver
+ << "didn't accept gesture" << g << "and nobody wants it";
+ }
+ }
+ }
+ }
+ }
+ if (ignoredGestures.isEmpty())
+ return ret;
+ // try to send all gestures that were ignored to the next parent
+ return sendGestureEvent(0, ignoredGestures, QSet<QGesture*>(), cancelled) || ret;
+}
+
+int QGestureManager::eventDeliveryDelay() const
+{
+ return eventDeliveryDelayTimeout;
+}
+
+void QGestureManager::setEventDeliveryDelay(int ms)
+{
+ eventDeliveryDelayTimeout = ms;
+}
+
+int QGestureManager::makeGestureId(const QString &name)
+{
+ gestureIdMap[++lastGestureId] = name;
+ return lastGestureId;
+}
+
+void QGestureManager::releaseGestureId(int gestureId)
+{
+ gestureIdMap.remove(gestureId);
+}
+
+QString QGestureManager::gestureNameFromId(int gestureId) const
+{
+ return gestureIdMap.value(gestureId);
+}
+
+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..745feb3
--- /dev/null
+++ b/src/gui/kernel/qgesturemanager_p.h
@@ -0,0 +1,126 @@
+/****************************************************************************
+**
+** 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 "qpointer.h"
+
+#include "qgesturerecognizer.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWidget;
+class Q_AUTOTEST_EXPORT QGestureManager : public QObject
+{
+ Q_OBJECT
+public:
+ QGestureManager(QObject *parent);
+
+ int eventDeliveryDelay() const;
+ void setEventDeliveryDelay(int ms);
+
+ void addRecognizer(QGestureRecognizer *recognizer);
+ void removeRecognizer(QGestureRecognizer *recognizer);
+
+ bool filterEvent(QWidget *receiver, QEvent *event);
+ bool inGestureMode();
+
+ int makeGestureId(const QString &name);
+ void releaseGestureId(int gestureId);
+ QString gestureNameFromId(int gestureId) const;
+
+ // declared in qapplication.cpp
+ static QGestureManager* instance();
+
+ bool sendGestureEvent(QWidget *receiver,
+ const QSet<QGesture*> &startedGestures,
+ const QSet<QGesture*> &updatedGestures,
+ const QSet<QString> &cancelled = QSet<QString>());
+
+protected:
+ void timerEvent(QTimerEvent *event);
+
+private slots:
+ void recognizerStateChanged(QGestureRecognizer::Result);
+
+private:
+ QSet<QGestureRecognizer*> activeGestures;
+ QMap<QGestureRecognizer*, int> maybeGestures;
+ QSet<QGestureRecognizer*> recognizers;
+
+ QPoint lastPos;
+
+ int eventDeliveryDelayTimeout;
+ int delayedPressTimer;
+ QPointer<QWidget> lastMousePressReceiver;
+ QMouseEvent lastMousePressEvent;
+
+ QMap<int, QString> gestureIdMap;
+ int lastGestureId;
+
+ 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.cpp b/src/gui/kernel/qgesturerecognizer.cpp
new file mode 100644
index 0000000..879f557
--- /dev/null
+++ b/src/gui/kernel/qgesturerecognizer.cpp
@@ -0,0 +1,159 @@
+/****************************************************************************
+**
+** 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 "qgesturerecognizer.h"
+#include "qgesture.h"
+
+#include <private/qobject_p.h>
+#include <private/qgesturerecognizer_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QString qt_getStandardGestureTypeName(Qt::GestureType gestureType);
+
+/*!
+ \class QGestureRecognizer
+ \since 4.6
+
+ \brief The QGestureRecognizer class is the base class for
+ implementing custom gestures.
+
+ This is a base class, to create a custom gesture type, you should
+ subclass it and implement its pure virtual functions.
+
+ Usually gesture recognizer implements state machine, storing its
+ state internally in the recognizer object. The recognizer receives
+ input events through the \l{QGestureRecognizer::}{filterEvent()}
+ virtual function and decides whether the parsed event should
+ change the state of the recognizer - i.e. if the event starts or
+ ends a gesture or if it isn't related to gesture at all.
+*/
+
+/*!
+ \enum QGestureRecognizer::Result
+ \since 4.6
+
+ This enum type defines the state of the gesture recognizer.
+
+ \value Ignore Gesture recognizer ignores the event.
+
+ \value NotGesture Not a gesture.
+
+ \value GestureStarted The continuous gesture has started. When the
+ recognizer is in this state, a \l{QGestureEvent}{gesture event}
+ containing QGesture objects returned by the
+ \l{QGestureRecognizer::}{getGesture()} will be sent to a widget.
+
+ \value GestureFinished The gesture has ended. A
+ \l{QGestureEvent}{gesture event} will be sent to a widget.
+
+ \value MaybeGesture Gesture recognizer hasn't decided yet if a
+ gesture has started, but it might start soon after the following
+ events are received by the recognizer. This means that gesture
+ manager shouldn't reset() the internal state of the gesture
+ recognizer.
+*/
+
+/*! \fn QGestureRecognizer::Result QGestureRecognizer::filterEvent(const QEvent *event)
+
+ This is a pure virtual function that needs to be implemented in
+ subclasses.
+
+ Parses input \a event and returns the result, which specifies if
+ the event sequence is a gesture or not.
+*/
+
+/*! \fn QGesture* QGestureRecognizer::getGesture()
+
+ Returns a gesture object that will be send to the widget. This
+ function is called when the gesture recognizer changed its state
+ to QGestureRecognizer::GestureStarted or
+ QGestureRecognizer::GestureFinished.
+
+ The returned QGesture object must point to the same object in a
+ single gesture sequence.
+
+ The gesture object is owned by the recognizer itself.
+*/
+
+/*! \fn void QGestureRecognizer::reset()
+
+ Resets the internal state of the gesture recognizer.
+*/
+
+/*! \fn void QGestureRecognizer::stateChanged(QGestureRecognizer::Result result)
+
+ The gesture recognizer might emit the stateChanged() signal when
+ the gesture state changes asynchronously, i.e. without any event
+ being filtered through filterEvent().
+*/
+
+QGestureRecognizerPrivate::QGestureRecognizerPrivate()
+ : gestureType(Qt::UnknownGesture)
+{
+}
+
+/*!
+ Creates a new gesture recognizer object that handles gestures of
+ the specific \a gestureType as a child of \a parent.
+
+ \sa QApplication::addGestureRecognizer(),
+ QApplication::removeGestureRecognizer(),
+*/
+QGestureRecognizer::QGestureRecognizer(const QString &gestureType, QObject *parent)
+ : QObject(*new QGestureRecognizerPrivate, parent)
+{
+ Q_D(QGestureRecognizer);
+ d->customGestureType = gestureType;
+}
+
+/*!
+ Returns the name of the gesture that is handled by the recognizer.
+*/
+QString QGestureRecognizer::gestureType() const
+{
+ Q_D(const QGestureRecognizer);
+ if (d->gestureType == Qt::UnknownGesture)
+ return d->customGestureType;
+ return qt_getStandardGestureTypeName(d->gestureType);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/kernel/qgesturerecognizer.h b/src/gui/kernel/qgesturerecognizer.h
new file mode 100644
index 0000000..67d7949
--- /dev/null
+++ b/src/gui/kernel/qgesturerecognizer.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** 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 "qevent.h"
+#include "qlist.h"
+#include "qset.h"
+
+QT_BEGIN_NAMESPACE
+
+class QGesture;
+class QGestureRecognizerPrivate;
+class Q_GUI_EXPORT QGestureRecognizer : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QGestureRecognizer)
+
+public:
+ enum Result
+ {
+ Ignore,
+ NotGesture,
+ GestureStarted, //TODO: rename to just Gesture?
+ GestureFinished,
+ MaybeGesture
+ };
+
+ explicit QGestureRecognizer(const QString &gestureType, QObject *parent = 0);
+
+ QString gestureType() const;
+
+ virtual QGestureRecognizer::Result filterEvent(const QEvent* event) = 0;
+ virtual QGesture* getGesture() = 0;
+ virtual void reset() = 0;
+
+signals:
+ void stateChanged(QGestureRecognizer::Result result);
+
+private:
+ friend class QDoubleTapGestureRecognizer;
+ friend class QTapAndHoldGestureRecognizer;
+ friend class QGestureRecognizerPan;
+};
+
+QT_END_NAMESPACE
+
+#endif // QGESTURERECOGNIZER_P_H
diff --git a/src/gui/kernel/qgesturerecognizer_p.h b/src/gui/kernel/qgesturerecognizer_p.h
new file mode 100644
index 0000000..4d80b99
--- /dev/null
+++ b/src/gui/kernel/qgesturerecognizer_p.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** 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_P_H
+#define QGESTURERECOGNIZER_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 <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QGestureRecognizerPrivate : public QObjectPrivate
+{
+public:
+ QGestureRecognizerPrivate();
+
+public:
+ Qt::GestureType gestureType;
+ QString customGestureType;
+};
+
+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..f6b8b90
--- /dev/null
+++ b/src/gui/kernel/qgesturestandardrecognizers.cpp
@@ -0,0 +1,306 @@
+/****************************************************************************
+**
+** 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"
+#include "qgesturerecognizer_p.h"
+
+// #define GESTURE_RECOGNIZER_DEBUG
+#ifndef GESTURE_RECOGNIZER_DEBUG
+# define DEBUG if (0) qDebug
+#else
+# define DEBUG qDebug
+#endif
+
+QT_BEGIN_NAMESPACE
+
+QString qt_getStandardGestureTypeName(Qt::GestureType gestureType)
+{
+ switch (gestureType) {
+ case Qt::TapGesture:
+ return QLatin1String("__QTapGesture");
+ case Qt::DoubleTapGesture:
+ return QLatin1String("__QDoubleTapGesture");
+ case Qt::TrippleTapGesture:
+ return QLatin1String("__QTrippleTapGesture");
+ case Qt::TapAndHoldGesture:
+ return QLatin1String("__QTapAndHoldGesture");
+ case Qt::PanGesture:
+ return QLatin1String("__QPanGesture");
+ case Qt::PinchGesture:
+ return QLatin1String("__QPinchGesture");
+ case Qt::UnknownGesture:
+ break;
+ }
+ qFatal("QGestureRecognizer::gestureType: got an unhandled gesture type.");
+ return QLatin1String("__unknown_gesture");
+}
+
+//
+// QGestureRecognizerPan
+//
+
+QGestureRecognizerPan::QGestureRecognizerPan(QObject *parent)
+ : QGestureRecognizer(QString(), parent),
+ mousePressed(false), gestureState(Qt::NoGesture),
+ lastDirection(Qt::NoDirection), currentDirection(Qt::NoDirection)
+{
+ Q_D(QGestureRecognizer);
+ d->gestureType = Qt::PanGesture;
+}
+
+QGestureRecognizer::Result QGestureRecognizerPan::filterEvent(const QEvent *event)
+{
+ if (event->type() == QEvent::MouseButtonPress) {
+ const QMouseEvent *ev = static_cast<const QMouseEvent*>(event);
+ if (currentDirection != Qt::NoDirection) {
+ DEBUG() << "Pan: MouseButtonPress: fail. another press during pan";
+ reset();
+ return QGestureRecognizer::NotGesture;
+ }
+ if (ev->button() != Qt::LeftButton) {
+ return QGestureRecognizer::NotGesture;
+ }
+ DEBUG() << "Pan: MouseButtonPress: maybe gesture started";
+ mousePressed = true;
+ pressedPos = lastPos = currentPos = ev->pos();
+ return QGestureRecognizer::MaybeGesture;
+ } else if (event->type() == QEvent::MouseButtonRelease) {
+ const QMouseEvent *ev = static_cast<const QMouseEvent*>(event);
+ if (mousePressed && currentDirection != Qt::NoDirection
+ && ev->button() == Qt::LeftButton) {
+ DEBUG() << "Pan: MouseButtonRelease: pan detected";
+ gestureState = Qt::GestureFinished;
+ currentPos = ev->pos();
+ internalReset();
+ return QGestureRecognizer::GestureFinished;
+ }
+ DEBUG() << "Pan: MouseButtonRelease: some weird release detected, ignoring";
+ reset();
+ return QGestureRecognizer::NotGesture;
+ } else if (event->type() == QEvent::MouseMove) {
+ if (!mousePressed)
+ return QGestureRecognizer::NotGesture;
+ const QMouseEvent *ev = static_cast<const QMouseEvent*>(event);
+ lastPos = currentPos;
+ currentPos = ev->pos();
+ Qt::DirectionType newDirection =
+ simpleRecognizer.addPosition(ev->pos()).direction;
+ DEBUG() << "Pan: MouseMove: simplerecognizer result = " << newDirection;
+ QGestureRecognizer::Result result = QGestureRecognizer::NotGesture;
+ if (currentDirection == Qt::NoDirection) {
+ if (newDirection == Qt::NoDirection) {
+ result = QGestureRecognizer::MaybeGesture;
+ } else {
+ result = QGestureRecognizer::GestureStarted;
+ gestureState = Qt::GestureStarted;
+ }
+ } else {
+ result = QGestureRecognizer::GestureStarted;
+ gestureState = Qt::GestureUpdated;
+ }
+ if (newDirection != Qt::NoDirection) {
+ if (currentDirection != newDirection)
+ lastDirection = currentDirection;
+ currentDirection = newDirection;
+ }
+ return result;
+ }
+ return QGestureRecognizer::Ignore;
+}
+
+QGesture* QGestureRecognizerPan::getGesture()
+{
+ if (currentDirection == Qt::NoDirection)
+ return 0;
+ QPanningGesturePrivate *d = gesture.d_func();
+ d->startPos = pressedPos;
+ d->lastPos = lastPos;
+ d->pos = currentPos;
+ d->hotSpot = pressedPos;
+ d->state = gestureState;
+ d->lastDirection = lastDirection;
+ d->direction = currentDirection;
+
+ return &gesture;
+}
+
+void QGestureRecognizerPan::reset()
+{
+ mousePressed = false;
+ lastDirection = Qt::NoDirection;
+ currentDirection = Qt::NoDirection;
+ gestureState = Qt::NoGesture;
+ diagonalRecognizer.reset();
+ simpleRecognizer.reset();
+}
+
+void QGestureRecognizerPan::internalReset()
+{
+ mousePressed = false;
+ diagonalRecognizer.reset();
+ simpleRecognizer.reset();
+}
+
+
+//
+// QDoubleTapGestureRecognizer
+//
+QDoubleTapGestureRecognizer::QDoubleTapGestureRecognizer(QObject *parent)
+ : QGestureRecognizer(QString(), parent),
+ gesture(0, qt_getStandardGestureTypeName(Qt::DoubleTapGesture))
+{
+ Q_D(QGestureRecognizer);
+ d->gestureType = Qt::DoubleTapGesture;
+}
+
+QGestureRecognizer::Result QDoubleTapGestureRecognizer::filterEvent(const QEvent *event)
+{
+ if (event->type() == QEvent::MouseButtonPress) {
+ const QMouseEvent *ev = static_cast<const QMouseEvent*>(event);
+ if (pressedPosition.isNull()) {
+ pressedPosition = ev->pos();
+ return QGestureRecognizer::MaybeGesture;
+ } else if ((pressedPosition - ev->pos()).manhattanLength() < 10) {
+ return QGestureRecognizer::GestureFinished;
+ }
+ return QGestureRecognizer::NotGesture;
+ } else if (event->type() == QEvent::MouseButtonRelease) {
+ const QMouseEvent *ev = static_cast<const QMouseEvent*>(event);
+ if (!pressedPosition.isNull() && (pressedPosition - ev->pos()).manhattanLength() < 10)
+ return QGestureRecognizer::MaybeGesture;
+ return QGestureRecognizer::NotGesture;
+ } else if (event->type() == QEvent::MouseButtonDblClick) {
+ const QMouseEvent *ev = static_cast<const QMouseEvent*>(event);
+ pressedPosition = ev->pos();
+ return QGestureRecognizer::GestureFinished;
+ }
+ return QGestureRecognizer::NotGesture;
+}
+
+QGesture* QDoubleTapGestureRecognizer::getGesture()
+{
+ QGesturePrivate *d = gesture.d_func();
+ d->startPos = pressedPosition;
+ d->lastPos = pressedPosition;
+ d->pos = pressedPosition;
+ d->hotSpot = pressedPosition;
+ d->state = Qt::GestureFinished;
+ return &gesture;
+}
+
+void QDoubleTapGestureRecognizer::reset()
+{
+ pressedPosition = QPoint();
+}
+
+//
+// QTapAndHoldGestureRecognizer
+//
+const int QTapAndHoldGestureRecognizer::iterationCount = 40;
+const int QTapAndHoldGestureRecognizer::iterationTimeout = 50;
+
+QTapAndHoldGestureRecognizer::QTapAndHoldGestureRecognizer(QObject *parent)
+ : QGestureRecognizer(QString(), parent),
+ gesture(0, qt_getStandardGestureTypeName(Qt::TapAndHoldGesture)),
+ iteration(0)
+{
+ Q_D(QGestureRecognizer);
+ d->gestureType = Qt::TapAndHoldGesture;
+}
+
+QGestureRecognizer::Result QTapAndHoldGestureRecognizer::filterEvent(const QEvent *event)
+{
+ if (event->type() == QEvent::MouseButtonPress) {
+ const QMouseEvent *ev = static_cast<const QMouseEvent*>(event);
+ if (timer.isActive())
+ timer.stop();
+ timer.start(QTapAndHoldGestureRecognizer::iterationTimeout, this);
+ pressedPosition = ev->pos();
+ return QGestureRecognizer::MaybeGesture;
+ } else if (event->type() == QEvent::MouseMove) {
+ const QMouseEvent *ev = static_cast<const QMouseEvent*>(event);
+ if ((pressedPosition - ev->pos()).manhattanLength() < 15)
+ return QGestureRecognizer::GestureStarted;
+ else
+ return QGestureRecognizer::NotGesture;
+ } else if (event->type() == QEvent::MouseButtonRelease) {
+ timer.stop();
+ return QGestureRecognizer::NotGesture;
+ }
+ return QGestureRecognizer::Ignore;
+}
+
+void QTapAndHoldGestureRecognizer::timerEvent(QTimerEvent *event)
+{
+ if (event->timerId() != timer.timerId())
+ return;
+ if (iteration == QTapAndHoldGestureRecognizer::iterationCount) {
+ timer.stop();
+ emit stateChanged(QGestureRecognizer::GestureFinished);
+ } else {
+ emit stateChanged(QGestureRecognizer::GestureStarted);
+ }
+ ++iteration;
+}
+
+QGesture* QTapAndHoldGestureRecognizer::getGesture()
+{
+ QGesturePrivate *d = gesture.d_func();
+ d->startPos = pressedPosition;
+ d->lastPos = pressedPosition;
+ d->pos = pressedPosition;
+ d->hotSpot = pressedPosition;
+ if (iteration >= QTapAndHoldGestureRecognizer::iterationCount)
+ d->state = Qt::GestureFinished;
+ else
+ d->state = iteration == 0 ? Qt::GestureStarted : Qt::GestureUpdated;
+ return &gesture;
+}
+
+void QTapAndHoldGestureRecognizer::reset()
+{
+ pressedPosition = QPoint();
+ timer.stop();
+ iteration = 0;
+}
+
+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..81db3e6
--- /dev/null
+++ b/src/gui/kernel/qgesturestandardrecognizers_p.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** 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 QGestureRecognizerPan : public QGestureRecognizer
+{
+ Q_OBJECT
+public:
+ QGestureRecognizerPan(QObject *parent);
+
+ QGestureRecognizer::Result filterEvent(const QEvent *event);
+ QGesture* getGesture();
+ void reset();
+
+private:
+ void internalReset();
+
+ QPanningGesture gesture;
+
+ QPoint pressedPos;
+ QPoint lastPos;
+ QPoint currentPos;
+ bool mousePressed;
+ Qt::GestureState gestureState;
+ Qt::DirectionType lastDirection;
+ Qt::DirectionType currentDirection;
+ QDirectionDiagonalRecognizer diagonalRecognizer;
+ QDirectionSimpleRecognizer simpleRecognizer;
+};
+
+class QDoubleTapGestureRecognizer : public QGestureRecognizer
+{
+ Q_OBJECT
+public:
+ QDoubleTapGestureRecognizer(QObject *parent);
+
+ QGestureRecognizer::Result filterEvent(const QEvent *event);
+ QGesture* getGesture();
+ void reset();
+
+private:
+ QGesture gesture;
+ QPoint pressedPosition;
+};
+
+class QTapAndHoldGestureRecognizer : public QGestureRecognizer
+{
+ Q_OBJECT
+public:
+ QTapAndHoldGestureRecognizer(QObject *parent);
+
+ QGestureRecognizer::Result filterEvent(const QEvent *event);
+ QGesture* getGesture();
+ void reset();
+
+protected:
+ void timerEvent(QTimerEvent *event);
+
+private:
+ QGesture gesture;
+ QPoint pressedPosition;
+ QBasicTimer timer;
+ int iteration;
+ static const int iterationCount;
+ static const int iterationTimeout;
+};
+
+QT_END_NAMESPACE
+
+#endif // QGESTURESTANDARDRECOGNIZERS_P_H
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index e186557..4b2fed7 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -109,6 +109,7 @@
#include "private/qabstractscrollarea_p.h"
#include "private/qgraphicssystem_p.h"
+#include "private/qgesturemanager_p.h"
// widget/widget data creation count
//#define QWIDGET_EXTRA_DEBUG
@@ -127,6 +128,8 @@ Q_GUI_EXPORT void qt_x11_set_global_double_buffer(bool enable)
}
#endif
+QString qt_getStandardGestureTypeName(Qt::GestureType);
+
static inline bool qRectIntersects(const QRect &r1, const QRect &r2)
{
return (qMax(r1.left(), r2.left()) <= qMin(r1.right(), r2.right()) &&
@@ -7473,10 +7476,14 @@ bool QWidget::event(QEvent *event)
case QEvent::MouseButtonRelease:
case QEvent::MouseButtonDblClick:
case QEvent::MouseMove:
+ case QEvent::TouchBegin:
+ case QEvent::TouchUpdate:
+ case QEvent::TouchEnd:
case QEvent::ContextMenu:
#ifndef QT_NO_WHEELEVENT
case QEvent::Wheel:
#endif
+ case QEvent::Gesture:
return false;
default:
break;
@@ -7872,6 +7879,9 @@ bool QWidget::event(QEvent *event)
d->needWindowChange = false;
break;
#endif
+ case QEvent::Gesture:
+ event->ignore();
+ break;
#ifndef QT_NO_PROPERTIES
case QEvent::DynamicPropertyChange: {
const QByteArray &propName = static_cast<QDynamicPropertyChangeEvent *>(event)->propertyName();
@@ -10961,6 +10971,103 @@ QWindowSurface *QWidget::windowSurface() const
return bs ? bs->windowSurface : 0;
}
+/*!
+ \since 4.6
+
+ Subscribes the widget to the specified \a gesture type.
+
+ Returns the id of the gesture.
+
+ \sa releaseGesture(), setGestureEnabled()
+*/
+int QWidget::grabGesture(const QString &gesture)
+{
+ Q_D(QWidget);
+ int id = d->grabGesture(QGestureManager::instance()->makeGestureId(gesture));
+ if (d->extra && d->extra->proxyWidget)
+ d->extra->proxyWidget->QGraphicsItem::d_ptr->grabGesture(id);
+ return id;
+}
+
+int QWidgetPrivate::grabGesture(int gestureId)
+{
+ gestures << gestureId;
+ ++qApp->d_func()->grabbedGestures[QGestureManager::instance()->gestureNameFromId(gestureId)];
+ return gestureId;
+}
+
+bool QWidgetPrivate::releaseGesture(int gestureId)
+{
+ QApplicationPrivate *qAppPriv = qApp->d_func();
+ if (gestures.contains(gestureId)) {
+ QString name = QGestureManager::instance()->gestureNameFromId(gestureId);
+ Q_ASSERT(qAppPriv->grabbedGestures[name] > 0);
+ --qAppPriv->grabbedGestures[name];
+ gestures.remove(gestureId);
+ return true;
+ }
+ return false;
+}
+
+bool QWidgetPrivate::hasGesture(const QString &name) const
+{
+ QGestureManager *gm = QGestureManager::instance();
+ QSet<int>::const_iterator it = gestures.begin(),
+ e = gestures.end();
+ for (; it != e; ++it) {
+ if (gm->gestureNameFromId(*it) == name)
+ return true;
+ }
+ return false;
+}
+
+/*!
+ \since 4.6
+
+ Subscribes the widget to the specified \a gesture type.
+
+ Returns the id of the gesture.
+
+ \sa releaseGesture(), setGestureEnabled()
+*/
+int QWidget::grabGesture(Qt::GestureType gesture)
+{
+ return grabGesture(qt_getStandardGestureTypeName(gesture));
+}
+
+/*!
+ \since 4.6
+
+ Unsubscribes the widget from a gesture, which is specified by the
+ \a gestureId.
+
+ \sa grabGesture(), setGestureEnabled()
+*/
+void QWidget::releaseGesture(int gestureId)
+{
+ Q_D(QWidget);
+ if (d->releaseGesture(gestureId)) {
+ if (d->extra && d->extra->proxyWidget)
+ d->extra->proxyWidget->QGraphicsItem::d_ptr->releaseGesture(gestureId);
+ QGestureManager::instance()->releaseGestureId(gestureId);
+ }
+}
+
+/*!
+ \since 4.6
+
+ If \a enable is true, the gesture with the given \a gestureId is
+ enabled; otherwise the gesture is disabled.
+
+ The id of the gesture is returned by the grabGesture().
+
+ \sa grabGesture(), releaseGesture()
+*/
+void QWidget::setGestureEnabled(int gestureId, bool enable)
+{
+ //###
+}
+
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..80d4f3e 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;
+ int grabGesture(const QString &gesture);
+ int grabGesture(Qt::GestureType gesture);
+ void releaseGesture(int gestureId);
+ void setGestureEnabled(int gestureId, bool enable = true);
+
Q_SIGNALS:
void customContextMenuRequested(const QPoint &pos);
@@ -745,6 +753,7 @@ private:
friend bool isWidgetOpaque(const QWidget *);
friend class QGLWidgetPrivate;
#endif
+ friend class QGestureManager;
#ifdef Q_WS_X11
friend void qt_net_update_user_time(QWidget *tlw, unsigned long timestamp);
friend void qt_net_remove_user_time(QWidget *tlw);
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index bf4f091..b2ae75e 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -57,9 +57,11 @@
#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"
+#include "QtGui/qevent.h"
#ifdef Q_WS_WIN
#include "QtCore/qt_windows.h"
@@ -516,6 +518,11 @@ public:
QList<QAction*> actions;
#endif
+ QSet<int> gestures;
+ int grabGesture(int gestureId);
+ bool releaseGesture(int gestureId);
+ bool hasGesture(const QString &type) const;
+
// Bit fields.
uint high_attributes[3]; // the low ones are in QWidget::widget_attributes
QPalette::ColorRole fg_role : 8;
diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp
index 0f341fd..d381cb2 100644
--- a/src/gui/kernel/qwidget_win.cpp
+++ b/src/gui/kernel/qwidget_win.cpp
@@ -497,6 +497,10 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
}
}
+ // ### don't always register for touch events
+ if (id && QApplicationPrivate::RegisterTouchWindow && !desktop)
+ QApplicationPrivate::RegisterTouchWindow(id, 0);
+
q->setAttribute(Qt::WA_WState_Created); // accept move/resize events
hd = 0; // no display context