From ae7442a4e93d4a63f28c1c2692be80a3d87f54a9 Mon Sep 17 00:00:00 2001 From: Shawn Rutledge Date: Thu, 3 Sep 2020 13:32:55 +0200 Subject: Give QEventPoint a d-pointer after all I still have doubts that QEventPoint can't be made small enough that copying would be cheaper than reference-counting and all the indirections in now-noninline accessors, but this gives us the usual freedom to change the data members later on. Change-Id: I792f7fc85ac3a9538589da9d7618b647edf0e70c Reviewed-by: Lars Knoll --- src/gui/kernel/qevent.cpp | 153 ++++++++++++++++++++++++++++++++++++++++------ src/gui/kernel/qevent.h | 85 +++++++++++--------------- src/gui/kernel/qevent_p.h | 78 ++++++++++++++++------- 3 files changed, 222 insertions(+), 94 deletions(-) (limited to 'src/gui/kernel') diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index b4880eff53..1e570a647b 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -240,18 +240,105 @@ QInputEvent::~QInputEvent() as in qgraphicsscene_p.h. */ QEventPoint::QEventPoint(int id, const QPointingDevice *device) - : m_device(device), m_pointId(id), m_state(State::Unknown), m_accept(false), m_stationaryWithModifiedProperty(false), m_reserved(0) + : d(new QEventPointPrivate(id, device)) {} + +/*! + Constructs an event point with the given \a pointId, \a state, + \a scenePosition and \a globalPosition. +*/ +QEventPoint::QEventPoint(int pointId, State state, const QPointF &scenePosition, const QPointF &globalPosition) + : d(new QEventPointPrivate(pointId, state, scenePosition, globalPosition)) {} + +QEventPoint::QEventPoint(const QEventPoint &other) + : d(other.d) { + d->refCount++; } -QEventPoint::QEventPoint(int pointId, State state, const QPointF &scenePosition, const QPointF &globalPosition) - : m_scenePos(scenePosition), m_globalPos(globalPosition), m_pointId(pointId), m_state(state), - m_accept(false), m_stationaryWithModifiedProperty(false), m_reserved(0) +QEventPoint &QEventPoint::operator=(const QEventPoint &other) { - if (state == QEventPoint::State::Released) - m_pressure = 0; + other.d->refCount++; + if (!(--d->refCount)) + delete d; + d = other.d; + return *this; } +QEventPoint::~QEventPoint() +{ + if (!(--d->refCount)) + delete d; +} + +QPointF QEventPoint::position() const +{ return d->pos; } + +QPointF QEventPoint::pressPosition() const +{ return d->globalPressPos - d->globalPos + d->pos; } + +QPointF QEventPoint::grabPosition() const +{ return d->globalGrabPos - d->globalPos + d->pos; } + +QPointF QEventPoint::lastPosition() const +{ return d->globalLastPos - d->globalPos + d->pos; } + +QPointF QEventPoint::scenePosition() const +{ return d->scenePos; } + +QPointF QEventPoint::scenePressPosition() const +{ return d->globalPressPos - d->globalPos + d->scenePos; } + +QPointF QEventPoint::sceneGrabPosition() const +{ return d->globalGrabPos - d->globalPos + d->scenePos; } + +QPointF QEventPoint::sceneLastPosition() const +{ return d->globalLastPos - d->globalPos + d->scenePos; } + +QPointF QEventPoint::globalPosition() const +{ return d->globalPos; } + +QPointF QEventPoint::globalPressPosition() const +{ return d->globalPressPos; } + +QPointF QEventPoint::globalGrabPosition() const +{ return d->globalGrabPos; } + +QPointF QEventPoint::globalLastPosition() const +{ return d->globalLastPos; } + +QVector2D QEventPoint::velocity() const +{ return d->velocity; } + +QEventPoint::State QEventPoint::state() const +{ return d->state; } + +const QPointingDevice *QEventPoint::device() const +{ return d->device; } + +int QEventPoint::id() const +{ return d->pointId; } + +QPointingDeviceUniqueId QEventPoint::uniqueId() const +{ return d->uniqueId; } + +ulong QEventPoint::pressTimestamp() const +{ return d->pressTimestamp; } + +qreal QEventPoint::timeHeld() const +{ return (d->timestamp - d->pressTimestamp) / qreal(1000); } + +qreal QEventPoint::pressure() const +{ return d->pressure; } + +qreal QEventPoint::rotation() const +{ return d->rotation; } + +QSizeF QEventPoint::ellipseDiameters() const +{ return d->ellipseDiameters; } + +bool QEventPoint::isAccepted() const +{ return d->accept; } + /* Sets the accepted state of the point. @@ -269,9 +356,12 @@ QEventPoint::QEventPoint(int pointId, State state, const QPointF &scenePosition, */ void QEventPoint::setAccepted(bool accepted) { - m_accept = accepted; + d->accept = accepted; } +QObject *QEventPoint::exclusiveGrabber() const +{ return d->exclusiveGrabber.data(); } + /* Informs the delivery logic that the given \a exclusiveGrabber is to receive all future update events and the release event containing @@ -281,16 +371,19 @@ void QEventPoint::setAccepted(bool accepted) */ void QEventPoint::setExclusiveGrabber(QObject *exclusiveGrabber) { - if (m_exclusiveGrabber == exclusiveGrabber) + if (d->exclusiveGrabber == exclusiveGrabber) return; if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) { - qCDebug(lcPointerGrab) << pointDeviceName(this) << "point" << Qt::hex << m_pointId << m_state << "@" << m_scenePos - << ": grab" << m_exclusiveGrabber << "->" << exclusiveGrabber; + qCDebug(lcPointerGrab) << pointDeviceName(this) << "point" << Qt::hex << d->pointId << d->state << "@" << d->scenePos + << ": grab" << d->exclusiveGrabber << "->" << exclusiveGrabber; } - m_exclusiveGrabber = exclusiveGrabber; - m_globalGrabPos = m_globalPos; + d->exclusiveGrabber = exclusiveGrabber; + d->globalGrabPos = d->globalPos; } +const QList > &QEventPoint::passiveGrabbers() const +{ return d->passiveGrabbers; } + /* Informs the delivery logic that the given \a grabbers are to receive all future update events and the release event containing this point, @@ -300,9 +393,9 @@ void QEventPoint::setExclusiveGrabber(QObject *exclusiveGrabber) */ void QEventPoint::setPassiveGrabbers(const QList > &grabbers) { - m_passiveGrabbers = grabbers; + d->passiveGrabbers = grabbers; if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) { - qCDebug(lcPointerGrab) << pointDeviceName(this) << "point" << Qt::hex << m_pointId << m_state + qCDebug(lcPointerGrab) << pointDeviceName(this) << "point" << Qt::hex << d->pointId << d->state << ": grab (passive)" << grabbers; } } @@ -310,10 +403,10 @@ void QEventPoint::setPassiveGrabbers(const QList > &grabbers) void QEventPoint::clearPassiveGrabbers() { if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) { - qCDebug(lcPointerGrab) << pointDeviceName(this) << "point" << Qt::hex << m_pointId << m_state - << ": clearing" << m_passiveGrabbers; + qCDebug(lcPointerGrab) << pointDeviceName(this) << "point" << Qt::hex << d->pointId << d->state + << ": clearing" << d->passiveGrabbers; } - m_passiveGrabbers.clear(); + d->passiveGrabbers.clear(); } /*! \internal @@ -329,7 +422,7 @@ void QEventPoint::clearPassiveGrabbers() QPointF QEventPoint::normalizedPos() const { - auto geom = m_device->availableVirtualGeometry(); + auto geom = d->device->availableVirtualGeometry(); if (geom.isNull()) return QPointF(); return (globalPosition() - geom.topLeft()) / geom.width(); @@ -337,7 +430,7 @@ QPointF QEventPoint::normalizedPos() const QPointF QEventPoint::startNormalizedPos() const { - auto geom = m_device->availableVirtualGeometry(); + auto geom = d->device->availableVirtualGeometry(); if (geom.isNull()) return QPointF(); return (globalPressPosition() - geom.topLeft()) / geom.width(); @@ -345,12 +438,32 @@ QPointF QEventPoint::startNormalizedPos() const QPointF QEventPoint::lastNormalizedPos() const { - auto geom = m_device->availableVirtualGeometry(); + auto geom = d->device->availableVirtualGeometry(); if (geom.isNull()) return QPointF(); return (globalLastPosition() - geom.topLeft()) / geom.width(); } + +/*! \internal + This class is explicitly shared, which means if you construct an event and + then the point(s) that it holds are modified before the event is delivered, + the event will be seen to hold the modified points. The workaround is that + any code which modifies an eventpoint that could already be included in an + event, or code that wants to save an eventpoint for later, has + responsibility to detach before calling any setters, so as to hold and + modify an independent copy. (The independent copy can then be used in a + subsequent event.) If detaching is unnecessary, because refCount shows that + there is only one QEventPoint referring to the QEventPointPrivate instance, + this function does nothing. +*/ +void QMutableEventPoint::detach() +{ + if (d->refCount == 1) + return; // no need: there is only one QEventPoint using it + d = new QEventPointPrivate(*d); +} + QPointerEvent::QPointerEvent(QEvent::Type type, const QPointingDevice *dev, Qt::KeyboardModifiers modifiers) : QInputEvent(type, QEvent::PointerEventTag{}, dev, modifiers) { diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index c8402b6632..eed6b93156 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -90,10 +90,7 @@ protected: qint64 m_extra = 0; // reserved, unused for now }; -namespace QTest { - class QTouchEventSequence; // just for the friend declaration below -} - +struct QEventPointPrivate; class Q_GUI_EXPORT QEventPoint { Q_GADGET @@ -110,19 +107,22 @@ public: QEventPoint(int id = -1, const QPointingDevice *device = nullptr); QEventPoint(int pointId, State state, const QPointF &scenePosition, const QPointF &globalPosition); - - QPointF position() const { return m_pos; } - QPointF pressPosition() const { return m_globalPressPos - m_globalPos + m_pos; } - QPointF grabPosition() const { return m_globalGrabPos - m_globalPos + m_pos; } - QPointF lastPosition() const { return m_globalLastPos - m_globalPos + m_pos; } - QPointF scenePosition() const { return m_scenePos; } - QPointF scenePressPosition() const { return m_globalPressPos - m_globalPos + m_scenePos; } - QPointF sceneGrabPosition() const { return m_globalGrabPos - m_globalPos + m_scenePos; } - QPointF sceneLastPosition() const { return m_globalLastPos - m_globalPos + m_scenePos; } - QPointF globalPosition() const { return m_globalPos; } - QPointF globalPressPosition() const { return m_globalPressPos; } - QPointF globalGrabPosition() const { return m_globalGrabPos; } - QPointF globalLastPosition() const { return m_globalLastPos; } + QEventPoint(const QEventPoint &other); + QEventPoint &operator=(const QEventPoint &other); + ~QEventPoint(); + + QPointF position() const; + QPointF pressPosition() const; + QPointF grabPosition() const; + QPointF lastPosition() const; + QPointF scenePosition() const; + QPointF scenePressPosition() const; + QPointF sceneGrabPosition() const; + QPointF sceneLastPosition() const; + QPointF globalPosition() const; + QPointF globalPressPosition() const; + QPointF globalGrabPosition() const; + QPointF globalLastPosition() const; #if QT_DEPRECATED_SINCE(6, 0) // QEventPoint replaces QTouchEvent::TouchPoint, so we need all its old accessors, for now @@ -151,45 +151,28 @@ public: QT_DEPRECATED_VERSION_X_6_0("Use globalLastPosition()") QPointF lastNormalizedPos() const; #endif // QT_DEPRECATED_SINCE(6, 0) - QVector2D velocity() const { return m_velocity; } - State state() const { return m_state; } - const QPointingDevice *device() const { return m_device; } - int id() const { return m_pointId; } - QPointingDeviceUniqueId uniqueId() const { return m_uniqueId; } - ulong pressTimestamp() const { return m_pressTimestamp; } - qreal timeHeld() const { return (m_timestamp - m_pressTimestamp) / qreal(1000); } - qreal pressure() const { return m_pressure; } - qreal rotation() const { return m_rotation; } - QSizeF ellipseDiameters() const { return m_ellipseDiameters; } - - bool isAccepted() const { return m_accept; } + QVector2D velocity() const; + State state() const; + const QPointingDevice *device() const; + int id() const; + QPointingDeviceUniqueId uniqueId() const; + ulong pressTimestamp() const; + qreal timeHeld() const; + qreal pressure() const; + qreal rotation() const; + QSizeF ellipseDiameters() const; + + bool isAccepted() const; void setAccepted(bool accepted = true); - QObject *exclusiveGrabber() const { return m_exclusiveGrabber.data(); } + QObject *exclusiveGrabber() const; void setExclusiveGrabber(QObject *exclusiveGrabber); - const QList> &passiveGrabbers() const { return m_passiveGrabbers; } + const QList> &passiveGrabbers() const; void setPassiveGrabbers(const QList> &grabbers); void clearPassiveGrabbers(); -protected: - const QPointingDevice *m_device = nullptr; - QPointF m_pos, m_scenePos, m_globalPos, - m_globalPressPos, m_globalGrabPos, m_globalLastPos; - qreal m_pressure = 1; - qreal m_rotation = 0; - QSizeF m_ellipseDiameters = QSizeF(0, 0); - QVector2D m_velocity; - QPointer m_exclusiveGrabber; - QList > m_passiveGrabbers; - ulong m_timestamp = 0; - ulong m_pressTimestamp = 0; - QPointingDeviceUniqueId m_uniqueId; - int m_pointId = -1; - State m_state : 8; - quint32 m_accept : 1; - quint32 m_stationaryWithModifiedProperty : 1; - quint32 m_reserved : 22; - - friend class QTest::QTouchEventSequence; +private: + QEventPointPrivate *d; + friend class QMutableEventPoint; }; #ifndef QT_NO_DEBUG_STREAM diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h index a8da0aede2..42b78b3810 100644 --- a/src/gui/kernel/qevent_p.h +++ b/src/gui/kernel/qevent_p.h @@ -58,6 +58,36 @@ QT_BEGIN_NAMESPACE +struct QEventPointPrivate { + QEventPointPrivate(int id, const QPointingDevice *device) + : device(device), pointId(id) { } + + QEventPointPrivate(int pointId, QEventPoint::State state, const QPointF &scenePosition, const QPointF &globalPosition) + : scenePos(scenePosition), globalPos(globalPosition), pointId(pointId), state(state) + { + if (state == QEventPoint::State::Released) + pressure = 0; + } + + const QPointingDevice *device = nullptr; + QPointF pos, scenePos, globalPos, + globalPressPos, globalGrabPos, globalLastPos; + qreal pressure = 1; + qreal rotation = 0; + QSizeF ellipseDiameters = QSizeF(0, 0); + QVector2D velocity; + QPointer exclusiveGrabber; + QList > passiveGrabbers; + ulong timestamp = 0; + ulong pressTimestamp = 0; + QPointingDeviceUniqueId uniqueId; + int refCount = 1; + int pointId = -1; + QEventPoint::State state = QEventPoint::State::Unknown; + bool accept = false; + bool stationaryWithModifiedProperty = false; +}; + // Private subclasses to allow accessing and modifying protected variables. // These should NOT hold any extra state. @@ -72,59 +102,61 @@ public: const QPointF &position, const QPointF &scenePosition, const QPointF &globalPosition) : QEventPoint(pointId, state, scenePosition, globalPosition) { - m_timestamp = timestamp; - m_pos = position; + d->timestamp = timestamp; + d->pos = position; } static QMutableEventPoint *from(QEventPoint *me) { return static_cast(me); } static QMutableEventPoint &from(QEventPoint &me) { return static_cast(me); } - bool stationaryWithModifiedProperty() const { return m_stationaryWithModifiedProperty; } + void detach(); + + bool stationaryWithModifiedProperty() const { return d->stationaryWithModifiedProperty; } - void setId(int pointId) { m_pointId = pointId; } + void setId(int pointId) { d->pointId = pointId; } - void setDevice(const QPointingDevice *device) { m_device = device; } + void setDevice(const QPointingDevice *device) { d->device = device; } - void setTimestamp(const ulong t) { m_timestamp = t; } + void setTimestamp(const ulong t) { d->timestamp = t; } - void setPressTimestamp(const ulong t) { m_pressTimestamp = t; } + void setPressTimestamp(const ulong t) { d->pressTimestamp = t; } - void setState(QEventPoint::State state) { m_state = state; } + void setState(QEventPoint::State state) { d->state = state; } - void setUniqueId(const QPointingDeviceUniqueId &uid) { m_uniqueId = uid; } + void setUniqueId(const QPointingDeviceUniqueId &uid) { d->uniqueId = uid; } - void setPosition(const QPointF &pos) { m_pos = pos; } + void setPosition(const QPointF &pos) { d->pos = pos; } - void setScenePosition(const QPointF &pos) { m_scenePos = pos; } + void setScenePosition(const QPointF &pos) { d->scenePos = pos; } - void setGlobalPosition(const QPointF &pos) { m_globalPos = pos; } + void setGlobalPosition(const QPointF &pos) { d->globalPos = pos; } #if QT_DEPRECATED_SINCE(6, 0) // temporary replacements for QTouchEvent::TouchPoint setters, mainly to make porting easier QT_DEPRECATED_VERSION_X_6_0("Use setPosition()") - void setPos(const QPointF &pos) { m_pos = pos; } + void setPos(const QPointF &pos) { d->pos = pos; } QT_DEPRECATED_VERSION_X_6_0("Use setScenePosition()") - void setScenePos(const QPointF &pos) { m_scenePos = pos; } + void setScenePos(const QPointF &pos) { d->scenePos = pos; } QT_DEPRECATED_VERSION_X_6_0("Use setGlobalPosition()") - void setScreenPos(const QPointF &pos) { m_globalPos = pos; } + void setScreenPos(const QPointF &pos) { d->globalPos = pos; } #endif - void setGlobalPressPosition(const QPointF &pos) { m_globalPressPos = pos; } + void setGlobalPressPosition(const QPointF &pos) { d->globalPressPos = pos; } - void setGlobalGrabPosition(const QPointF &pos) { m_globalGrabPos = pos; } + void setGlobalGrabPosition(const QPointF &pos) { d->globalGrabPos = pos; } - void setGlobalLastPosition(const QPointF &pos) { m_globalLastPos = pos; } + void setGlobalLastPosition(const QPointF &pos) { d->globalLastPos = pos; } - void setEllipseDiameters(const QSizeF &d) { m_ellipseDiameters = d; } + void setEllipseDiameters(const QSizeF &diams) { d->ellipseDiameters = diams; } - void setPressure(qreal v) { m_pressure = v; } + void setPressure(qreal v) { d->pressure = v; } - void setRotation(qreal v) { m_rotation = v; } + void setRotation(qreal v) { d->rotation = v; } - void setVelocity(const QVector2D &v) { m_velocity = v; } + void setVelocity(const QVector2D &v) { d->velocity = v; } - void setStationaryWithModifiedProperty(bool s = true) { m_stationaryWithModifiedProperty = s; } + void setStationaryWithModifiedProperty(bool s = true) { d->stationaryWithModifiedProperty = s; } }; static_assert(sizeof(QMutableEventPoint) == sizeof(QEventPoint)); -- cgit v1.2.3