summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2016-03-23 22:26:08 +0100
committerShawn Rutledge <shawn.rutledge@qt.io>2016-12-07 08:33:35 +0000
commit3c159957f863cf8d367a9261e7016e52cd0348c1 (patch)
tree1a56cb165b674dd49170de88b4254cd4ad0d51a4
parentf7253b25684eabf68973cc4486b32f0dc346b70c (diff)
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 in d0b1c646b4a351f7eea2137c68993ae63b2b6bab and 40e4949674eaf7ceb09f6d18479ead1a36b384fd 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>
-rw-r--r--doc/src/images/touchpoint-metrics.pngbin0 -> 46111 bytes
-rw-r--r--src/gui/kernel/qevent.cpp106
-rw-r--r--src/gui/kernel/qevent.h11
-rw-r--r--src/gui/kernel/qevent_p.h9
-rw-r--r--src/gui/kernel/qguiapplication.cpp9
-rw-r--r--src/gui/kernel/qwindowsysteminterface.h6
-rw-r--r--src/widgets/kernel/qapplication.cpp8
7 files changed, 119 insertions, 30 deletions
diff --git a/doc/src/images/touchpoint-metrics.png b/doc/src/images/touchpoint-metrics.png
new file mode 100644
index 0000000000..a9e6cd4f0f
--- /dev/null
+++ b/doc/src/images/touchpoint-metrics.png
Binary files 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;
}
/*!
@@ -4703,6 +4728,30 @@ qreal QTouchEvent::TouchPoint::rotation() const
}
/*!
+ \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 */
@@ -4905,6 +4961,22 @@ void QTouchEvent::TouchPoint::setRotation(qreal 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)
{
if (d->ref.load() != 1)
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<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);
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<QPointF> 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;