diff --git a/doc/src/images/touchpoint-metrics.png b/doc/src/images/touchpoint-metrics.png new file mode 100644 index 0000000000..a9e6cd4f0f Binary files /dev/null and b/doc/src/images/touchpoint-metrics.png differ diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index fcb9c14406..8fd03cdb76 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -4417,6 +4417,8 @@ QTouchEvent::~QTouchEvent() \brief The TouchPoint class provides information about a touch point in a QTouchEvent. \since 4.6 \inmodule QtGui + + \image touchpoint-metrics.png */ /*! \enum TouchPoint::InfoFlag @@ -4502,7 +4504,7 @@ Qt::TouchPointState QTouchEvent::TouchPoint::state() const */ QPointF QTouchEvent::TouchPoint::pos() const { - return d->rect.center(); + return d->pos; } /*! @@ -4517,7 +4519,7 @@ QPointF QTouchEvent::TouchPoint::pos() const */ QPointF QTouchEvent::TouchPoint::scenePos() const { - return d->sceneRect.center(); + return d->scenePos; } /*! @@ -4527,7 +4529,7 @@ QPointF QTouchEvent::TouchPoint::scenePos() const */ QPointF QTouchEvent::TouchPoint::screenPos() const { - return d->screenRect.center(); + return d->screenPos; } /*! @@ -4650,10 +4652,19 @@ QPointF QTouchEvent::TouchPoint::lastNormalizedPos() const around the point returned by pos(). \note This function returns an empty rect if the device does not report touch point sizes. + + \obsolete This function is deprecated in 5.9 because it returns the outer bounds + of the touchpoint regardless of rotation, whereas a touchpoint is more correctly + modeled as an ellipse at position pos() with horizontalDiameter() and + verticalDiameter() which are independent of rotation(). + + \sa scenePos(), horizontalDiameter(), verticalDiameter() */ QRectF QTouchEvent::TouchPoint::rect() const { - return d->rect; + QRectF ret(0, 0, d->horizontalDiameter, d->verticalDiameter); + ret.moveCenter(d->pos); + return ret; } /*! @@ -4661,11 +4672,18 @@ QRectF QTouchEvent::TouchPoint::rect() const \note This function returns an empty rect if the device does not report touch point sizes. - \sa scenePos(), rect() + \obsolete This function is deprecated in 5.9 because it returns the outer bounds + of the touchpoint regardless of rotation, whereas a touchpoint is more correctly + modeled as an ellipse at position scenePos() with horizontalDiameter() and + verticalDiameter() which are independent of rotation(). + + \sa scenePos(), horizontalDiameter(), verticalDiameter() */ QRectF QTouchEvent::TouchPoint::sceneRect() const { - return d->sceneRect; + QRectF ret(0, 0, d->horizontalDiameter, d->verticalDiameter); + ret.moveCenter(d->scenePos); + return ret; } /*! @@ -4673,11 +4691,18 @@ QRectF QTouchEvent::TouchPoint::sceneRect() const \note This function returns an empty rect if the device does not report touch point sizes. - \sa screenPos(), rect() + \obsolete This function is deprecated because it returns the outer bounds of the + touchpoint regardless of rotation, whereas a touchpoint is more correctly + modeled as an ellipse at position screenPos() with horizontalDiameter() and + verticalDiameter() which are independent of rotation(). + + \sa screenPos(), horizontalDiameter(), verticalDiameter() */ QRectF QTouchEvent::TouchPoint::screenRect() const { - return d->screenRect; + QRectF ret(0, 0, d->horizontalDiameter, d->verticalDiameter); + ret.moveCenter(d->screenPos); + return ret; } /*! @@ -4702,6 +4727,30 @@ qreal QTouchEvent::TouchPoint::rotation() const return d->rotation; } +/*! + \since 5.9 + Returns the width of the bounding ellipse of this touch point. + The return value is in logical pixels, along the horizontal axis + when rotation() is zero. Most touchscreens do not detect the shape of the + contact point, so zero is the most common value. +*/ +qreal QTouchEvent::TouchPoint::horizontalDiameter() const +{ + return d->horizontalDiameter; +} + +/*! + \since 5.9 + Returns the height of the bounding ellipse of this touch point. + The return value is in logical pixels, along the vertical axis + when rotation() is zero. Most touchscreens do not detect the shape + of the contact point, so zero is the most common value. +*/ +qreal QTouchEvent::TouchPoint::verticalDiameter() const +{ + return d->verticalDiameter; +} + /*! Returns a velocity vector for this touch point. The vector is in the screen's coordinate system, using pixels per seconds for the magnitude. @@ -4773,7 +4822,7 @@ void QTouchEvent::TouchPoint::setPos(const QPointF &pos) { if (d->ref.load() != 1) d = d->detach(); - d->rect.moveCenter(pos); + d->pos = pos; } /*! \internal */ @@ -4781,7 +4830,7 @@ void QTouchEvent::TouchPoint::setScenePos(const QPointF &scenePos) { if (d->ref.load() != 1) d = d->detach(); - d->sceneRect.moveCenter(scenePos); + d->scenePos = scenePos; } /*! \internal */ @@ -4789,7 +4838,7 @@ void QTouchEvent::TouchPoint::setScreenPos(const QPointF &screenPos) { if (d->ref.load() != 1) d = d->detach(); - d->screenRect.moveCenter(screenPos); + d->screenPos = screenPos; } /*! \internal */ @@ -4864,28 +4913,35 @@ void QTouchEvent::TouchPoint::setLastNormalizedPos(const QPointF &lastNormalized d->lastNormalizedPos = lastNormalizedPos; } -/*! \internal */ +// ### remove the following 3 setRect functions and their usages soon +/*! \internal \obsolete */ void QTouchEvent::TouchPoint::setRect(const QRectF &rect) { if (d->ref.load() != 1) d = d->detach(); - d->rect = rect; + d->pos = rect.center(); + d->verticalDiameter = rect.height(); + d->horizontalDiameter = rect.width(); } -/*! \internal */ +/*! \internal \obsolete */ void QTouchEvent::TouchPoint::setSceneRect(const QRectF &sceneRect) { if (d->ref.load() != 1) d = d->detach(); - d->sceneRect = sceneRect; + d->scenePos = sceneRect.center(); + d->verticalDiameter = sceneRect.height(); + d->horizontalDiameter = sceneRect.width(); } -/*! \internal */ +/*! \internal \obsolete */ void QTouchEvent::TouchPoint::setScreenRect(const QRectF &screenRect) { if (d->ref.load() != 1) d = d->detach(); - d->screenRect = screenRect; + d->screenPos = screenRect.center(); + d->verticalDiameter = screenRect.height(); + d->horizontalDiameter = screenRect.width(); } /*! \internal */ @@ -4904,6 +4960,22 @@ void QTouchEvent::TouchPoint::setRotation(qreal angle) d->rotation = angle; } +/*! \internal */ +void QTouchEvent::TouchPoint::setVerticalDiameter(qreal dia) +{ + if (d->ref.load() != 1) + d = d->detach(); + d->verticalDiameter = dia; +} + +/*! \internal */ +void QTouchEvent::TouchPoint::setHorizontalDiameter(qreal dia) +{ + if (d->ref.load() != 1) + d = d->detach(); + d->horizontalDiameter = dia; +} + /*! \internal */ void QTouchEvent::TouchPoint::setVelocity(const QVector2D &v) { diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index a062331bd8..982072c7d4 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -870,6 +870,9 @@ public: qreal pressure() const; qreal rotation() const; + qreal horizontalDiameter() const; + qreal verticalDiameter() const; + QVector2D velocity() const; InfoFlags flags() const; QVector rawScreenPositions() const; @@ -890,11 +893,13 @@ public: void setLastScenePos(const QPointF &lastScenePos); void setLastScreenPos(const QPointF &lastScreenPos); void setLastNormalizedPos(const QPointF &lastNormalizedPos); - void setRect(const QRectF &rect); - void setSceneRect(const QRectF &sceneRect); - void setScreenRect(const QRectF &screenRect); + void setRect(const QRectF &rect); // deprecated + void setSceneRect(const QRectF &sceneRect); // deprecated + void setScreenRect(const QRectF &screenRect); // deprecated void setPressure(qreal pressure); void setRotation(qreal angle); + void setVerticalDiameter(qreal dia); + void setHorizontalDiameter(qreal dia); void setVelocity(const QVector2D &v); void setFlags(InfoFlags flags); void setRawScreenPositions(const QVector &positions); diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h index 7e82b9c654..a8b4d520d4 100644 --- a/src/gui/kernel/qevent_p.h +++ b/src/gui/kernel/qevent_p.h @@ -66,7 +66,9 @@ public: id(id), state(Qt::TouchPointReleased), pressure(qreal(-1.)), - rotation(qreal(0.)) + rotation(qreal(0.)), + verticalDiameter(0), + horizontalDiameter(0) { } inline QTouchEventTouchPointPrivate *detach() @@ -82,12 +84,13 @@ public: int id; QPointerUniqueId uniqueId; Qt::TouchPointStates state; - QRectF rect, sceneRect, screenRect; - QPointF normalizedPos, + QPointF pos, scenePos, screenPos, normalizedPos, startPos, startScenePos, startScreenPos, startNormalizedPos, lastPos, lastScenePos, lastScreenPos, lastNormalizedPos; qreal pressure; qreal rotation; + qreal verticalDiameter; + qreal horizontalDiameter; QVector2D velocity; QTouchEvent::TouchPoint::InfoFlags flags; QVector rawScreenPositions; diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index dda88da20c..1277e85d0a 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -2564,7 +2564,9 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To Q_ASSERT(w.data() != 0); // make the *scene* functions return the same as the *screen* functions - touchPoint.d->sceneRect = touchPoint.screenRect(); + touchPoint.d->scenePos = touchPoint.screenPos(); + touchPoint.d->verticalDiameter = touchPoint.screenRect().height(); + touchPoint.d->horizontalDiameter = touchPoint.screenRect().width(); touchPoint.d->startScenePos = touchPoint.startScreenPos(); touchPoint.d->lastScenePos = touchPoint.lastScreenPos(); @@ -2634,8 +2636,9 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To const QPointF screenPos = rect.center(); const QPointF delta = screenPos - screenPos.toPoint(); - rect.moveCenter(w->mapFromGlobal(screenPos.toPoint()) + delta); - touchPoint.d->rect = rect; + touchPoint.d->pos = w->mapFromGlobal(screenPos.toPoint()) + delta; + touchPoint.d->verticalDiameter = rect.height(); + touchPoint.d->horizontalDiameter = rect.width(); if (touchPoint.state() == Qt::TouchPointPressed) { touchPoint.d->startPos = w->mapFromGlobal(touchPoint.startScreenPos().toPoint()) + delta; touchPoint.d->lastPos = w->mapFromGlobal(touchPoint.lastScreenPos().toPoint()) + delta; diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h index 5368c75964..b6b57e01f5 100644 --- a/src/gui/kernel/qwindowsysteminterface.h +++ b/src/gui/kernel/qwindowsysteminterface.h @@ -131,9 +131,11 @@ public: qint64 uniqueId; // for TUIO: object/token ID; otherwise empty // TODO for TUIO 2.0: add registerPointerUniqueID(QPointerUniqueId) QPointF normalPosition; // touch device coordinates, (0 to 1, 0 to 1) - QRectF area; // the touched area, centered at position in screen coordinates + QRectF area; // dimensions of the elliptical contact patch, unrotated, and centered at position in screen coordinates + // width is the horizontal diameter, height is the vertical diameter qreal pressure; // 0 to 1 - qreal rotation; // 0 means pointing straight up; 0 if unknown (like QTabletEvent::rotation) + qreal rotation; // rotation applied to the elliptical contact patch + // 0 means pointing straight up; 0 if unknown (like QTabletEvent::rotation) Qt::TouchPointState state; //Qt::TouchPoint{Pressed|Moved|Stationary|Released} QVector2D velocity; // in screen coordinate system, pixels / seconds QTouchEvent::TouchPoint::InfoFlags flags; diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index b0e7293b88..9588b631a0 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -3552,7 +3552,9 @@ bool QApplication::notify(QObject *receiver, QEvent *e) QTouchEvent::TouchPoint &pt = touchEvent->_touchPoints[i]; QRectF rect = pt.rect(); rect.translate(offset); - pt.d->rect = rect; + pt.d->pos = rect.center(); + pt.d->verticalDiameter = rect.height(); + pt.d->horizontalDiameter = rect.width(); pt.d->startPos = pt.startPos() + offset; pt.d->lastPos = pt.lastPos() + offset; } @@ -4254,7 +4256,9 @@ bool QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEven const QPointF delta = screenPos - screenPos.toPoint(); rect.moveCenter(widget->mapFromGlobal(screenPos.toPoint()) + delta); - touchPoint.d->rect = rect; + touchPoint.d->pos = rect.center(); + touchPoint.d->verticalDiameter = rect.height(); + touchPoint.d->horizontalDiameter = rect.width(); touchPoint.d->startPos = widget->mapFromGlobal(touchPoint.startScreenPos().toPoint()) + delta; touchPoint.d->lastPos = widget->mapFromGlobal(touchPoint.lastScreenPos().toPoint()) + delta;