summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorBradley T. Hughes <bradley.hughes@nokia.com>2009-05-28 10:25:32 (GMT)
committerBradley T. Hughes <bradley.hughes@nokia.com>2009-05-28 10:25:32 (GMT)
commitec8654a61e574539f1b948b82a19371b160f4f4e (patch)
tree9e3f6bd91e26cd3fc4bb72a7300ebb53b53244ee /src/gui
parent9667870db5b929c76656f3a4235b9539a1d5de5b (diff)
downloadQt-ec8654a61e574539f1b948b82a19371b160f4f4e.zip
Qt-ec8654a61e574539f1b948b82a19371b160f4f4e.tar.gz
Qt-ec8654a61e574539f1b948b82a19371b160f4f4e.tar.bz2
Refactor the touch event dispatching code in preparation for allowing external event generators
This introduces QEvent::RawTouch event type, which should be used by the low-level translator. This raw QTouchEvent can be sent to either QApplication or to a window, and Qt will do the rest to dispatch the touch points to the correct place.
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/kernel/qapplication.cpp179
-rw-r--r--src/gui/kernel/qapplication_mac.mm5
-rw-r--r--src/gui/kernel/qapplication_p.h15
-rw-r--r--src/gui/kernel/qapplication_qws.cpp5
-rw-r--r--src/gui/kernel/qapplication_win.cpp145
-rw-r--r--src/gui/kernel/qapplication_x11.cpp5
6 files changed, 218 insertions, 136 deletions
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp
index 01c7c4a..3c7b808 100644
--- a/src/gui/kernel/qapplication.cpp
+++ b/src/gui/kernel/qapplication.cpp
@@ -4027,6 +4027,10 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
}
break;
#endif
+ case QEvent::RawTouch:
+ res = d->translateRawTouchEvent(qobject_cast<QWidget *>(receiver),
+ static_cast<QTouchEvent *>(e));
+ break;
case QEvent::TouchBegin:
// Note: TouchUpdate and TouchEnd events are sent to d->currentMultitouchWidget and never propagated
{
@@ -5256,6 +5260,181 @@ void QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEven
}
}
+void QApplicationPrivate::initializeMultitouch()
+{
+ widgetForTouchPointId.clear();
+ appCurrentTouchPoints.clear();
+
+ initializeMultitouch_sys();
+}
+
+void QApplicationPrivate::cleanupMultitouch()
+{
+ cleanupMultitouch_sys();
+
+ widgetForTouchPointId.clear();
+ appCurrentTouchPoints.clear();
+}
+
+QTouchEvent::TouchPoint *QApplicationPrivate::findClosestTouchPoint(const QPointF &screenPos)
+{
+ QTouchEvent::TouchPoint *closestTouchPoint = 0;
+ qreal closestDistance;
+ for (int i = 0; i < appCurrentTouchPoints.count(); ++i) {
+ QTouchEvent::TouchPoint *touchPoint = appCurrentTouchPoints.at(i);
+ qreal distance = QLineF(screenPos, touchPoint->screenPos()).length();
+ if (!closestTouchPoint || distance < closestDistance) {
+ closestTouchPoint = touchPoint;
+ closestDistance = distance;
+ }
+ }
+ return closestTouchPoint;
+}
+
+void QApplicationPrivate::appendTouchPoint(QTouchEvent::TouchPoint *touchPoint)
+{
+ // insort touch point
+ int at = 0;
+ for (; at < appCurrentTouchPoints.count(); ++at) {
+ if (appCurrentTouchPoints.at(at)->id() > touchPoint->id())
+ break;
+ }
+ appCurrentTouchPoints.insert(at, touchPoint);
+
+ if (appCurrentTouchPoints.count() > appAllTouchPoints.count()) {
+ qFatal("Qt: INTERNAL ERROR: appCurrentTouchPoints.count() (%d) > appAllTouchPoints.count() (%d)",
+ appCurrentTouchPoints.count(),
+ appAllTouchPoints.count());
+ }
+}
+
+void QApplicationPrivate::removeTouchPoint(QTouchEvent::TouchPoint *touchPoint)
+{
+ // 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;
+ }
+ }
+}
+
+bool QApplicationPrivate::translateRawTouchEvent(QWidget *window, QTouchEvent *rawTouchEvent)
+{
+ Q_Q(QApplication);
+
+ typedef QPair<Qt::TouchPointStates, QList<QTouchEvent::TouchPoint *> > StatesAndTouchPoints;
+ QHash<QWidget *, StatesAndTouchPoints> widgetsNeedingEvents;
+
+ for (int i = 0; i < rawTouchEvent->touchPoints().count(); ++i) {
+ QTouchEvent::TouchPoint *touchPoint = rawTouchEvent->touchPoints().at(i);
+
+ // update state
+ QWidget *widget = 0;
+ switch (touchPoint->state()) {
+ case Qt::TouchPointPressed:
+ {
+ // determine which widget this event will go to
+ if (!window)
+ window = q->topLevelAt(touchPoint->screenPos().toPoint());
+ if (!window)
+ continue;
+ widget = window->childAt(window->mapFromGlobal(touchPoint->screenPos().toPoint()));
+ if (!widget)
+ widget = window;
+
+ QTouchEvent::TouchPoint *closestTouchPoint = findClosestTouchPoint(touchPoint->screenPos());
+ if (closestTouchPoint) {
+ QWidget *closestWidget = widgetForTouchPointId.value(closestTouchPoint->id());
+ if (closestWidget
+ && (widget->isAncestorOf(closestWidget)
+ || closestWidget->isAncestorOf(widget)))
+ widget = closestWidget;
+ }
+ widgetForTouchPointId[touchPoint->id()] = widget;
+
+ appendTouchPoint(touchPoint);
+ break;
+ }
+ case Qt::TouchPointReleased:
+ widget = widgetForTouchPointId.take(touchPoint->id());
+ if (!widget)
+ continue;
+
+ removeTouchPoint(touchPoint);
+ break;
+ default:
+ widget = widgetForTouchPointId.value(touchPoint->id());
+ if (!widget)
+ continue;
+ break;
+ }
+ Q_ASSERT(widget != 0);
+
+ StatesAndTouchPoints &maskAndPoints = widgetsNeedingEvents[widget];
+ maskAndPoints.first |= touchPoint->state();
+ maskAndPoints.second.append(touchPoint);
+ }
+
+ if (widgetsNeedingEvents.isEmpty())
+ return false;
+
+ bool returnValue = false;
+
+ QHash<QWidget *, StatesAndTouchPoints>::ConstIterator it = widgetsNeedingEvents.constBegin();
+ const QHash<QWidget *, StatesAndTouchPoints>::ConstIterator end = widgetsNeedingEvents.constEnd();
+ for (; it != end; ++it) {
+ QWidget *widget = it.key();
+ if (!QApplicationPrivate::tryModalHelper(widget, 0))
+ continue;
+
+ QEvent::Type eventType;
+ switch(it.value().first) {
+ case Qt::TouchPointPressed:
+ eventType = QEvent::TouchBegin;
+ break;
+ case Qt::TouchPointReleased:
+ eventType = QEvent::TouchEnd;
+ break;
+ case Qt::TouchPointStationary:
+ // don't send the event if nothing changed
+ continue;
+ default:
+ eventType = QEvent::TouchUpdate;
+ break;
+ }
+
+ QTouchEvent touchEvent(eventType,
+ q->keyboardModifiers(),
+ it.value().first,
+ it.value().second);
+ updateTouchPointsForWidget(widget, &touchEvent);
+
+ bool res = false;
+ 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);
+ res = QApplication::sendSpontaneousEvent(widget, &touchEvent)
+ && touchEvent.isAccepted();
+ break;
+ }
+ default:
+ if (widget->testAttribute(Qt::WA_AcceptedTouchBeginEvent)) {
+ (void) QApplication::sendSpontaneousEvent(widget, &touchEvent);
+ res = true;
+ }
+ break;
+ }
+ returnValue = returnValue || res;
+ }
+
+ rawTouchEvent->setAccepted(returnValue);
+ return returnValue;
+}
+
QT_END_NAMESPACE
#include "moc_qapplication.cpp"
diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm
index d5fa9ea..82fbd7b 100644
--- a/src/gui/kernel/qapplication_mac.mm
+++ b/src/gui/kernel/qapplication_mac.mm
@@ -2970,4 +2970,9 @@ void onApplicationChangedActivation( bool activated )
#endif
}
+void QApplicationPrivate::initializeMultitouch_sys()
+{ }
+void QApplicationPrivate::cleanupMultitouch_sys()
+{ }
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h
index 1424611..55d8fc4 100644
--- a/src/gui/kernel/qapplication_p.h
+++ b/src/gui/kernel/qapplication_p.h
@@ -435,7 +435,16 @@ public:
QMap<QString, int> grabbedGestures;
QHash<int, QWidget *> widgetForTouchPointId;
+ QList<QTouchEvent::TouchPoint *> appCurrentTouchPoints;
static void updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent);
+ void initializeMultitouch();
+ void initializeMultitouch_sys();
+ void cleanupMultitouch();
+ void cleanupMultitouch_sys();
+ QTouchEvent::TouchPoint *findClosestTouchPoint(const QPointF &screenPos);
+ void appendTouchPoint(QTouchEvent::TouchPoint *touchPoint);
+ void removeTouchPoint(QTouchEvent::TouchPoint *touchPoint);
+ bool translateRawTouchEvent(QWidget *widget, QTouchEvent *rawTouchEvent);
#if defined(Q_WS_WIN)
static qt_RegisterTouchWindowPtr RegisterTouchWindow;
@@ -444,12 +453,6 @@ public:
QHash<DWORD, int> touchInputIDToTouchPointID;
QVector<QTouchEvent::TouchPoint *> appAllTouchPoints;
- QList<QTouchEvent::TouchPoint *> appCurrentTouchPoints;
-
- void initializeMultitouch();
- QTouchEvent::TouchPoint *findClosestTouchPoint(const QPointF &screenPos);
- void appendTouchPoint(QTouchEvent::TouchPoint *touchPoint);
- void removeTouchPoint(QTouchEvent::TouchPoint *touchPoint);
bool translateTouchEvent(const MSG &msg);
#endif
diff --git a/src/gui/kernel/qapplication_qws.cpp b/src/gui/kernel/qapplication_qws.cpp
index 1125610..a366ed6 100644
--- a/src/gui/kernel/qapplication_qws.cpp
+++ b/src/gui/kernel/qapplication_qws.cpp
@@ -3746,4 +3746,9 @@ void QApplication::setArgs(int c, char **v)
d->argv = v;
}
+void QApplicationPrivate::initializeMultitouch_sys()
+{ }
+void QApplicationPrivate::cleanupMultitouch_sys()
+{ }
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp
index f980f8e..a0c1184 100644
--- a/src/gui/kernel/qapplication_win.cpp
+++ b/src/gui/kernel/qapplication_win.cpp
@@ -3981,60 +3981,22 @@ qt_RegisterTouchWindowPtr QApplicationPrivate::RegisterTouchWindow = 0;
qt_GetTouchInputInfoPtr QApplicationPrivate::GetTouchInputInfo = 0;
qt_CloseTouchInputHandlePtr QApplicationPrivate::CloseTouchInputHandle = 0;
-void QApplicationPrivate::initializeMultitouch()
+void QApplicationPrivate::initializeMultitouch_sys()
{
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();
touchInputIDToTouchPointID.clear();
appAllTouchPoints.clear();
- appCurrentTouchPoints.clear();
}
-QTouchEvent::TouchPoint *QApplicationPrivate::findClosestTouchPoint(const QPointF &screenPos)
+void QApplicationPrivate::cleanupMultitouch_sys()
{
- QTouchEvent::TouchPoint *closestTouchPoint = 0;
- qreal closestDistance;
- for (int i = 0; i < appCurrentTouchPoints.count(); ++i) {
- QTouchEvent::TouchPoint *touchPoint = appCurrentTouchPoints.at(i);
- qreal distance = QLineF(screenPos, touchPoint->screenPos()).length();
- if (!closestTouchPoint || distance < closestDistance) {
- closestTouchPoint = touchPoint;
- closestDistance = distance;
- }
- }
- return closestTouchPoint;
-}
-
-void QApplicationPrivate::appendTouchPoint(QTouchEvent::TouchPoint *touchPoint)
-{
- // insort touch point
- int at = 0;
- for (; at < appCurrentTouchPoints.count(); ++at) {
- if (appCurrentTouchPoints.at(at)->id() > touchPoint->id())
- break;
- }
- appCurrentTouchPoints.insert(at, touchPoint);
-
- if (appCurrentTouchPoints.count() > appAllTouchPoints.count()) {
- qFatal("Qt: INTERNAL ERROR: appCurrentTouchPoints.count() (%d) > appAllTouchPoints.count() (%d)",
- appCurrentTouchPoints.count(),
- appAllTouchPoints.count());
- }
-}
-
-void QApplicationPrivate::removeTouchPoint(QTouchEvent::TouchPoint *touchPoint)
-{
- // 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;
- }
- }
+ qDeleteAll(appAllTouchPoints);
+ appAllTouchPoints.clear();
+ touchInputIDToTouchPointID.clear();
}
bool QApplicationPrivate::translateTouchEvent(const MSG &msg)
@@ -4045,8 +4007,8 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg)
if (!widgetForHwnd)
return false;
- typedef QPair<Qt::TouchPointStates, QList<QTouchEvent::TouchPoint *> > StatesAndTouchPoints;
- QHash<QWidget *, StatesAndTouchPoints> widgetsNeedingEvents;
+ Qt::TouchPointStates states = 0;
+ QList<QTouchEvent::TouchPoint *> touchPoints;
QVector<TOUCHINPUT> winTouchInputs(msg.wParam);
memset(winTouchInputs.data(), 0, sizeof(TOUCHINPUT) * winTouchInputs.count());
@@ -4068,45 +4030,21 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg)
touchPoint = appAllTouchPoints[touchPointID] = new QTouchEvent::TouchPoint(touchPointID);
// update state
- QWidget *widget = 0;
bool down = touchPoint->state() != Qt::TouchPointReleased;
QPointF screenPos(qreal(touchInput.x) / qreal(100.), qreal(touchInput.y) / qreal(100.));
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(screenPos);
- if (closestTouchPoint) {
- QWidget *closestWidget = widgetForTouchPointId.value(closestTouchPoint->id());
- if (closestWidget
- && (widget->isAncestorOf(closestWidget)
- || closestWidget->isAncestorOf(widget)))
- widget = closestWidget;
- }
- widgetForTouchPointId[touchPoint->id()] = widget;
-
- appendTouchPoint(touchPoint);
-
touchPoint->setState(Qt::TouchPointPressed);
touchPoint->setScreenPos(screenPos);
touchPoint->setStartScreenPos(screenPos);
touchPoint->setLastScreenPos(screenPos);
touchPoint->setPressure(qreal(1.));
} else if (down && (touchInput.dwFlags & TOUCHEVENTF_UP)) {
- widget = widgetForTouchPointId.take(touchPoint->id());
-
- removeTouchPoint(touchPoint);
-
touchPoint->setState(Qt::TouchPointReleased);
touchPoint->setLastScreenPos(touchPoint->screenPos());
touchPoint->setScreenPos(screenPos);
touchPoint->setPressure(qreal(0.));
} else if (down) {
- widget = widgetForTouchPointId.value(touchPoint->id());
-
touchPoint->setState(screenPos == touchPoint->screenPos()
? Qt::TouchPointStationary
: Qt::TouchPointMoved);
@@ -4114,71 +4052,18 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg)
touchPoint->setScreenPos(screenPos);
// pressure should still be 1.
}
- Q_ASSERT(widget != 0);
- StatesAndTouchPoints &maskAndPoints = widgetsNeedingEvents[widget];
- maskAndPoints.first |= touchPoint->state();
- maskAndPoints.second.append(touchPoint);
+ states |= touchPoint->state();
+ touchPoints.append(touchPoint);
}
QApplicationPrivate::CloseTouchInputHandle((HANDLE) msg.lParam);
- if (widgetsNeedingEvents.isEmpty())
- return false;
-
- bool returnValue = false;
- qt_tabletChokeMouse = false;
-
- QHash<QWidget *, StatesAndTouchPoints>::ConstIterator it = widgetsNeedingEvents.constBegin();
- const QHash<QWidget *, StatesAndTouchPoints>::ConstIterator end = widgetsNeedingEvents.constEnd();
- for (; it != end; ++it) {
- QWidget *widget = it.key();
- if (!QApplicationPrivate::tryModalHelper(widget, 0))
- continue;
-
- QEvent::Type eventType;
- switch(it.value().first) {
- case Qt::TouchPointPressed:
- eventType = QEvent::TouchBegin;
- break;
- case Qt::TouchPointReleased:
- eventType = QEvent::TouchEnd;
- break;
- case Qt::TouchPointStationary:
- // don't send the event if nothing changed
- continue;
- default:
- eventType = QEvent::TouchUpdate;
- break;
- }
-
- QTouchEvent touchEvent(eventType,
- q->keyboardModifiers(),
- it.value().first,
- it.value().second);
- 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;
- }
- default:
- if (widget->testAttribute(Qt::WA_AcceptedTouchBeginEvent)) {
- (void) QApplication::sendSpontaneousEvent(widget, &touchEvent);
- qt_tabletChokeMouse = true;
- }
- returnValue = returnValue || qt_tabletChokeMouse;
- break;
- }
- }
-
- return returnValue;
+ QTouchEvent touchEvent(QEvent::RawTouch,
+ q->keyboardModifiers(),
+ states,
+ touchPoints);
+ return qt_tabletChokeMouse = (QApplication::sendSpontaneousEvent(widgetForHwnd, &touchEvent)
+ && touchEvent.isAccepted());
}
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp
index 060e948..e16e416 100644
--- a/src/gui/kernel/qapplication_x11.cpp
+++ b/src/gui/kernel/qapplication_x11.cpp
@@ -5901,4 +5901,9 @@ void QSessionManager::requestPhase2()
#endif // QT_NO_SESSIONMANAGER
+void QApplicationPrivate::initializeMultitouch_sys()
+{ }
+void QApplicationPrivate::cleanupMultitouch_sys()
+{ }
+
QT_END_NAMESPACE