From 48d0f84958fdc2dcffab75f33842a9dbc3d4d7b1 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Tue, 11 Aug 2009 09:39:26 +0200 Subject: Implement advanced pointer handling on S60 Since we only get one pointer event at a time, we need to keep a list of all known touch points in QApplicationPrivate (otherwise the QTouchEvent won't contain enough points). The QApplication machinery can handle having inactive touch-points in the list, so at the moment we don't clear the list. We treat PointerNumber zero as the primary touch point, and only send regular mouse events for that pointer, never for the others. Reviewed-by: Jason Barron --- src/gui/kernel/qapplication_p.h | 5 +++ src/gui/kernel/qapplication_s60.cpp | 76 ++++++++++++++++++++++++++++++++++++- src/gui/kernel/qt_s60_p.h | 1 + 3 files changed, 80 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 707caaa..aec21fd 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -576,6 +576,11 @@ public: void _q_readRX71MultiTouchEvents(); #endif +#if defined(Q_WS_S60) + int maxTouchPressure; + QList appAllTouchPoints; +#endif + private: #ifdef Q_WS_QWS QMap maxWindowRects; diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index a5d07fd..58aca83 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -368,8 +368,77 @@ void QSymbianControl::HandleLongTapEventL( const TPoint& aPenEventLocation, cons m_previousEventLongTap = true; } +void QSymbianControl::translateAdvancedPointerEvent(const TAdvancedPointerEvent *event) +{ + QApplicationPrivate *d = QApplicationPrivate::instance(); + + QRect screenGeometry = qApp->desktop()->screenGeometry(qwidget); + + while (d->appAllTouchPoints.count() <= event->PointerNumber()) + d->appAllTouchPoints.append(QTouchEvent::TouchPoint(d->appAllTouchPoints.count())); + + Qt::TouchPointStates allStates = 0; + for (int i = 0; i < d->appAllTouchPoints.count(); ++i) { + QTouchEvent::TouchPoint &touchPoint = d->appAllTouchPoints[i]; + + if (touchPoint.id() == event->PointerNumber()) { + Qt::TouchPointStates state; + switch (event->iType) { + case TPointerEvent::EButton1Down: + case TPointerEvent::EEnterHighPressure: + state = Qt::TouchPointPressed; + break; + case TPointerEvent::EButton1Up: + case TPointerEvent::EExitCloseProximity: + state = Qt::TouchPointReleased; + break; + case TPointerEvent::EDrag: + state = Qt::TouchPointMoved; + break; + default: + // how likely is this to happen? + state = Qt::TouchPointStationary; + break; + } + if (event->PointerNumber() == 0) + state |= Qt::TouchPointPrimary; + touchPoint.setState(state); + + QPointF screenPos = QPointF(event->iPosition.iX, event->iPosition.iY); + touchPoint.setScreenPos(screenPos); + touchPoint.setNormalizedPos(QPointF(screenPos.x() / screenGeometry.width(), + screenPos.y() / screenGeometry.height())); + + touchPoint.setPressure(event->Pressure() / qreal(d->maxTouchPressure)); + } else if (touchPoint.state() != Qt::TouchPointReleased) { + // all other active touch points should be marked as stationary + touchPoint.setState(Qt::TouchPointStationary); + } + + allStates |= touchPoint.state(); + } + + if ((allStates & Qt::TouchPointStateMask) == Qt::TouchPointReleased) { + // all touch points released + d->appAllTouchPoints.clear(); + } + + QApplicationPrivate::translateRawTouchEvent(qwidget, + QTouchEvent::TouchScreen, + d->appAllTouchPoints); +} + void QSymbianControl::HandlePointerEventL(const TPointerEvent& pEvent) { + if (pEvent.IsAdvancedPointerEvent()) { + const TAdvancedPointerEvent *advancedPointerEvent = pEvent.AdvancedPointerEvent(); + translateAdvancedPointerEvent(advancedPointerEvent); + if (advancedPointerEvent->PointerNumber() != 0) { + // only send mouse events for the first touch point + return; + } + } + m_longTapDetector->PointerEventL(pEvent); QT_TRYCATCH_LEAVING(HandlePointerEvent(pEvent)); } @@ -1441,9 +1510,12 @@ TUint QApplicationPrivate::resolveS60ScanCode(TInt scanCode, TUint keysym) } } - void QApplicationPrivate::initializeMultitouch_sys() -{ } +{ + if (HAL::Get(HALData::EPointer3DMaxPressure, maxTouchPressure) != KErrNone) + maxTouchPressure = KMaxTInt; +} + void QApplicationPrivate::cleanupMultitouch_sys() { } diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index aa39f9d..9939f2c 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -167,6 +167,7 @@ private: TKeyResponse sendKeyEvent(QWidget *widget, QKeyEvent *keyEvent); bool sendMouseEvent(QWidget *widget, QMouseEvent *mEvent); void HandleLongTapEventL( const TPoint& aPenEventLocation, const TPoint& aPenEventScreenLocation ); + void translateAdvancedPointerEvent(const TAdvancedPointerEvent *event); private: QWidget *qwidget; -- cgit v0.12