TouchPoint: add horizontalDiameter, verticalDiameter; deprecate rects
The contact patch of a finger on a touchscreen tends to be roughly elliptical. If we model it as a QRectF, it's not clear whether the ellipse should be considered to be inscribed in the rectangle and then rotated, or whether the rectangle represents the outer bounds of the rotated ellipse. In practice, since most touchscreens can't measure rotation, it is effectively the latter. But modeling it that way means information is lost if the touchscreen can measure rotation: you can determine the bounds of a rotated ellipse, but you cannot derive the rotated ellipse from its bounds. So it's better to model the axes of the ellipse explicitly. This has the added benefit of saving a little storage space: we replace 3 QRectF instances, whose width and height will normally be the same, with 3 positions (bringing the total to 12 QPointF's) and one set of axes. Further, most applications only care about the center of each contact patch, so it's better to store that explicitly instead of calculating QRectF::center() repeatedly. In the past there may have been an assumption that the width of the rect is the same as the horizontalDiameter of the ellipse, so the rect could be considered to be rotated, and the ellipse to be inscribed. But ind0b1c646b4
and40e4949674
the point was made that the rect is actually the bounding box of the rotated ellipse. [ChangeLog][QtGui][QTouchEvent] TouchPoint::rect(), sceneRect() and screenRect() are deprecated; a touchpoint is now modeled as an ellipse, so please use pos(), scenePos(), screenPos(), horizontalDiameter() and verticalDiameter() instead. Change-Id: Ic06f6165e2d90fc9d4cc19cf4938d4faf5766bb4 Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
This commit is contained in:
parent
f7253b2568
commit
3c159957f8
BIN
doc/src/images/touchpoint-metrics.png
Normal file
BIN
doc/src/images/touchpoint-metrics.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 45 KiB |
@ -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)
|
||||
{
|
||||
|
@ -870,6 +870,9 @@ public:
|
||||
|
||||
qreal pressure() const;
|
||||
qreal rotation() const;
|
||||
qreal horizontalDiameter() const;
|
||||
qreal verticalDiameter() const;
|
||||
|
||||
QVector2D velocity() const;
|
||||
InfoFlags flags() const;
|
||||
QVector<QPointF> 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<QPointF> &positions);
|
||||
|
@ -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<QPointF> rawScreenPositions;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user