QPointerUniqueId: make fit for release
- Declare as Q_MOVABLE_TYPE - Prevent QList<QPointerUniqueId> from being instantiated (use QVector instead) - Add equality relational operators - Add qHash() overload - Replace non-default ctor with named ctor. - Add Q_DECL_NOTHROW. - Add Q_DECL_CONSTEXPR. - Rename numeric() -> numericId(). - Update docs. The extension vector for this class calls for additional properties to be added later, but these are not user- settable. It thus suffices to rely on the only data member, a qint64, which can be reinterpreted to an index into an array or hash with actual objects. This allows to make the class a Trivial Type (ie. no overhead over an int) while still supporting later extension. Cf. QSslEllipticCurve as another example of such a class. The extension has to maintain the following invariants, encoded into user code by way of being used in inline functions: - m_numericId == -1 <=> !isValid() This is trivial to support. An extension could not and still cannot reinterpret the qint64 member as a d-pointer, but a d-pointer is only necessary for user-settable properties where updating a central private data structure would cause too much contention. Add a test. Since this type is used in other modules, keep the existing functions, but mark them as deprecated with the expectation that these compat functions be removed before 5.8.0 final. Task-number: QTBUG-54616 Change-Id: Ia3ede0ecaeeef4cd3ffa94a72b1050bd409713a5 Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
This commit is contained in:
parent
f4a33e345e
commit
048447346b
@ -44,6 +44,7 @@
|
|||||||
#include "qpa/qplatformdrag.h"
|
#include "qpa/qplatformdrag.h"
|
||||||
#include "private/qevent_p.h"
|
#include "private/qevent_p.h"
|
||||||
#include "qfile.h"
|
#include "qfile.h"
|
||||||
|
#include "qhashfunctions.h"
|
||||||
#include "qmetaobject.h"
|
#include "qmetaobject.h"
|
||||||
#include "qmimedata.h"
|
#include "qmimedata.h"
|
||||||
#include "private/qdnd_p.h"
|
#include "private/qdnd_p.h"
|
||||||
@ -4474,7 +4475,7 @@ int QTouchEvent::TouchPoint::id() const
|
|||||||
\since 5.8
|
\since 5.8
|
||||||
Returns the unique ID of this touch point or token, if any.
|
Returns the unique ID of this touch point or token, if any.
|
||||||
|
|
||||||
It is normally invalid (with a \l {QPointerUniqueId::numeric()} {numeric()} value of -1),
|
It is normally invalid (see \l {QPointerUniqueId::isValid()} {isValid()}),
|
||||||
because touchscreens cannot uniquely identify fingers. But when the
|
because touchscreens cannot uniquely identify fingers. But when the
|
||||||
\l {TouchPoint::InfoFlag} {Token} flag is set, it is expected to uniquely
|
\l {TouchPoint::InfoFlag} {Token} flag is set, it is expected to uniquely
|
||||||
identify a specific token (fiducial object).
|
identify a specific token (fiducial object).
|
||||||
@ -4757,7 +4758,7 @@ void QTouchEvent::TouchPoint::setUniqueId(qint64 uid)
|
|||||||
{
|
{
|
||||||
if (d->ref.load() != 1)
|
if (d->ref.load() != 1)
|
||||||
d = d->detach();
|
d = d->detach();
|
||||||
d->uniqueId = QPointerUniqueId(uid);
|
d->uniqueId = QPointerUniqueId::fromNumericId(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \internal */
|
/*! \internal */
|
||||||
@ -5184,28 +5185,91 @@ Qt::ApplicationState QApplicationStateChangeEvent::applicationState() const
|
|||||||
\brief QPointerUniqueId identifies a unique object, such as a tagged token
|
\brief QPointerUniqueId identifies a unique object, such as a tagged token
|
||||||
or stylus, which is used with a pointing device.
|
or stylus, which is used with a pointing device.
|
||||||
|
|
||||||
|
QPointerUniqueIds can be compared for equality, and can be used as keys in a QHash.
|
||||||
|
You get access to the numerical ID via numericId(), if the device supports such IDs.
|
||||||
|
For future extensions, though, you should not use that function, but compare objects
|
||||||
|
of this type using the equality operator.
|
||||||
|
|
||||||
|
This class is a thin wrapper around an integer ID. You pass it into and out of
|
||||||
|
functions by value.
|
||||||
|
|
||||||
|
This type actively prevents you from holding it in a QList, because doing so would
|
||||||
|
be very inefficient. Use a QVector instead, which has the same API as QList, but more
|
||||||
|
efficient storage.
|
||||||
|
|
||||||
\sa QTouchEvent::TouchPoint
|
\sa QTouchEvent::TouchPoint
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
Constructs a unique pointer ID with a numeric \a id provided by the hardware.
|
\fn QPointerUniqueId::QPointerUniqueId()
|
||||||
The default is -1, which means an invalid pointer ID.
|
Constructs an invalid unique pointer ID.
|
||||||
*/
|
*/
|
||||||
QPointerUniqueId::QPointerUniqueId(qint64 id)
|
|
||||||
: m_numericId(id)
|
/*!
|
||||||
|
Constructs a unique pointer ID from numeric ID \a id.
|
||||||
|
*/
|
||||||
|
QPointerUniqueId QPointerUniqueId::fromNumericId(qint64 id)
|
||||||
{
|
{
|
||||||
|
QPointerUniqueId result;
|
||||||
|
result.m_numericId = id;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\property QPointerUniqueId::numeric
|
\fn bool QPointerUniqueId::isValid()
|
||||||
|
|
||||||
|
Returns whether this unique pointer ID is valid, that is, it represents an actual
|
||||||
|
pointer.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\property QPointerUniqueId::numericId
|
||||||
\brief the numeric unique ID of the token represented by a touchpoint
|
\brief the numeric unique ID of the token represented by a touchpoint
|
||||||
|
|
||||||
This is the numeric unique ID if the device provides that type of ID;
|
If the device provides a numeric ID, isValid() returns true, and this
|
||||||
|
property provides the numeric ID;
|
||||||
otherwise it is -1.
|
otherwise it is -1.
|
||||||
|
|
||||||
|
You should not use the value of this property in portable code, but
|
||||||
|
instead rely on equality to identify pointers.
|
||||||
|
|
||||||
|
\sa isValid()
|
||||||
*/
|
*/
|
||||||
qint64 QPointerUniqueId::numeric() const
|
qint64 QPointerUniqueId::numericId() const Q_DECL_NOTHROW
|
||||||
{
|
{
|
||||||
return m_numericId;
|
return m_numericId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\relates QPointerUniqueId
|
||||||
|
\since 5.8
|
||||||
|
|
||||||
|
Returns whether the two unique pointer IDs \a lhs and \a rhs identify the same pointer
|
||||||
|
(\c true) or not (\c false).
|
||||||
|
*/
|
||||||
|
bool operator==(QPointerUniqueId lhs, QPointerUniqueId rhs) Q_DECL_NOTHROW
|
||||||
|
{
|
||||||
|
return lhs.numericId() == rhs.numericId();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\fn bool operator!=(QPointerUniqueId lhs, QPointerUniqueId rhs)
|
||||||
|
\relates QPointerUniqueId
|
||||||
|
\since 5.8
|
||||||
|
|
||||||
|
Returns whether the two unique pointer IDs \a lhs and \a rhs identify different pointers
|
||||||
|
(\c true) or not (\c false).
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\relates QPointerUniqueId
|
||||||
|
\since 5.8
|
||||||
|
|
||||||
|
Returns the hash value for \a key, using \a seed to seed the calculation.
|
||||||
|
*/
|
||||||
|
uint qHash(QPointerUniqueId key, uint seed) Q_DECL_NOTHROW
|
||||||
|
{
|
||||||
|
return qHash(key.numericId(), seed);
|
||||||
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -793,21 +793,45 @@ inline bool operator==(QKeyEvent *e, QKeySequence::StandardKey key){return (e ?
|
|||||||
inline bool operator==(QKeySequence::StandardKey key, QKeyEvent *e){return (e ? e->matches(key) : false);}
|
inline bool operator==(QKeySequence::StandardKey key, QKeyEvent *e){return (e ? e->matches(key) : false);}
|
||||||
#endif // QT_NO_SHORTCUT
|
#endif // QT_NO_SHORTCUT
|
||||||
|
|
||||||
class QPointerUniqueIdPrivate;
|
|
||||||
class Q_GUI_EXPORT QPointerUniqueId
|
class Q_GUI_EXPORT QPointerUniqueId
|
||||||
{
|
{
|
||||||
Q_GADGET
|
Q_GADGET
|
||||||
Q_PROPERTY(qint64 numeric READ numeric CONSTANT)
|
// ### kept these to keep other modules compiling. Remove before 5.8.0 final!
|
||||||
|
#if QT_DEPRECATED_SINCE(5, 8)
|
||||||
|
Q_PROPERTY(qint64 numeric READ numericId CONSTANT)
|
||||||
|
#endif
|
||||||
|
Q_PROPERTY(qint64 numericId READ numericId CONSTANT)
|
||||||
public:
|
public:
|
||||||
explicit QPointerUniqueId(qint64 id = -1);
|
Q_ALWAYS_INLINE
|
||||||
|
Q_DECL_CONSTEXPR QPointerUniqueId() Q_DECL_NOTHROW : m_numericId(-1) {}
|
||||||
|
// compiler-generated copy/move ctor/assignment operators are ok!
|
||||||
|
// compiler-generated dtor is ok!
|
||||||
|
|
||||||
qint64 numeric() const;
|
static QPointerUniqueId fromNumericId(qint64 id);
|
||||||
|
|
||||||
|
Q_ALWAYS_INLINE Q_DECL_CONSTEXPR bool isValid() const Q_DECL_NOTHROW { return m_numericId != -1; }
|
||||||
|
qint64 numericId() const Q_DECL_NOTHROW;
|
||||||
|
|
||||||
|
// ### kept these to keep other modules compiling. Remove before 5.8.0 final!
|
||||||
|
#if QT_DEPRECATED_SINCE(5, 8)
|
||||||
|
Q_ALWAYS_INLINE Q_DECL_DEPRECATED qint64 numeric() const { return numericId(); }
|
||||||
|
Q_ALWAYS_INLINE Q_DECL_DEPRECATED explicit QPointerUniqueId(qint64 id) : m_numericId(id) {}
|
||||||
|
#endif
|
||||||
private:
|
private:
|
||||||
// TODO for TUIO 2, or any other type of complex token ID, a d-pointer can replace
|
// TODO: for TUIO 2, or any other type of complex token ID, an internal
|
||||||
// m_numericId without changing the size of this class.
|
// array (or hash) can be added to hold additional properties.
|
||||||
|
// In this case, m_numericId will then turn into an index into that array (or hash).
|
||||||
qint64 m_numericId;
|
qint64 m_numericId;
|
||||||
};
|
};
|
||||||
|
Q_DECLARE_TYPEINFO(QPointerUniqueId, Q_MOVABLE_TYPE);
|
||||||
|
template <> class QList<QPointerUniqueId> {}; // to prevent instantiation: use QVector instead
|
||||||
|
|
||||||
|
Q_GUI_EXPORT bool operator==(QPointerUniqueId lhs, QPointerUniqueId rhs) Q_DECL_NOTHROW;
|
||||||
|
inline bool operator!=(QPointerUniqueId lhs, QPointerUniqueId rhs) Q_DECL_NOTHROW
|
||||||
|
{ return !operator==(lhs, rhs); }
|
||||||
|
Q_GUI_EXPORT uint qHash(QPointerUniqueId key, uint seed = 0) Q_DECL_NOTHROW;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class QTouchEventTouchPointPrivate;
|
class QTouchEventTouchPointPrivate;
|
||||||
class Q_GUI_EXPORT QTouchEvent : public QInputEvent
|
class Q_GUI_EXPORT QTouchEvent : public QInputEvent
|
||||||
|
@ -194,6 +194,7 @@ public:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void cleanup();
|
void cleanup();
|
||||||
|
void qPointerUniqueId();
|
||||||
void touchDisabledByDefault();
|
void touchDisabledByDefault();
|
||||||
void touchEventAcceptedByDefault();
|
void touchEventAcceptedByDefault();
|
||||||
void touchBeginPropagatesWhenIgnored();
|
void touchBeginPropagatesWhenIgnored();
|
||||||
@ -224,6 +225,44 @@ void tst_QTouchEvent::cleanup()
|
|||||||
QVERIFY(QGuiApplication::topLevelWindows().isEmpty());
|
QVERIFY(QGuiApplication::topLevelWindows().isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QTouchEvent::qPointerUniqueId()
|
||||||
|
{
|
||||||
|
QPointerUniqueId id1, id2;
|
||||||
|
|
||||||
|
QCOMPARE(id1.numericId(), Q_INT64_C(-1));
|
||||||
|
QVERIFY(!id1.isValid());
|
||||||
|
|
||||||
|
QVERIFY( id1 == id2);
|
||||||
|
QVERIFY(!(id1 != id2));
|
||||||
|
|
||||||
|
QSet<QPointerUniqueId> set; // compile test
|
||||||
|
set.insert(id1);
|
||||||
|
set.insert(id2);
|
||||||
|
QCOMPARE(set.size(), 1);
|
||||||
|
|
||||||
|
|
||||||
|
const auto id3 = QPointerUniqueId::fromNumericId(-1);
|
||||||
|
QCOMPARE(id3.numericId(), Q_INT64_C(-1));
|
||||||
|
QVERIFY(!id3.isValid());
|
||||||
|
|
||||||
|
QVERIFY( id1 == id3);
|
||||||
|
QVERIFY(!(id1 != id3));
|
||||||
|
|
||||||
|
set.insert(id3);
|
||||||
|
QCOMPARE(set.size(), 1);
|
||||||
|
|
||||||
|
|
||||||
|
const auto id4 = QPointerUniqueId::fromNumericId(4);
|
||||||
|
QCOMPARE(id4.numericId(), Q_INT64_C(4));
|
||||||
|
QVERIFY(id4.isValid());
|
||||||
|
|
||||||
|
QVERIFY( id1 != id4);
|
||||||
|
QVERIFY(!(id1 == id4));
|
||||||
|
|
||||||
|
set.insert(id4);
|
||||||
|
QCOMPARE(set.size(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
void tst_QTouchEvent::touchDisabledByDefault()
|
void tst_QTouchEvent::touchDisabledByDefault()
|
||||||
{
|
{
|
||||||
// QWidget
|
// QWidget
|
||||||
|
Loading…
x
Reference in New Issue
Block a user