diff options
author | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2020-11-05 18:11:56 +0100 |
---|---|---|
committer | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2020-11-07 06:24:28 +0100 |
commit | bdec189ecbc2cabbfa803a571b49533f190f053d (patch) | |
tree | a061307e207cfbdb989e463c9535208a822fab78 | |
parent | 1c6d6cbb62c5e93cbcad2d740c3b0ed01095618c (diff) | |
download | qtbase-bdec189ecbc2cabbfa803a571b49533f190f053d.tar.gz |
Move QEventPoint and QPointingDeviceUniqueId out of qevent
qevent.h/cpp are huge already, no need for more classes. Move QEventPoint
into new qeventpoint.h/cpp files, and QPointingDeviceUniqueId into
qpointingdevice.cpp; the class is already declared in qpointingdevice.h.
Move the documentation of QEventPoint APIs next to the implementation,
and document all APIs as properties. Add Q_PROPERTY macro where missing.
QEventPoint::device needs a workaround of qdoc due to the type being a
pointer-to-const; qdoc doesn't know how to tie a \property to it, but
documents it correctly.
While at it, move the logging category declarations to the header
matching the .cpp file where they are defined.
Change-Id: I096e609edbb760b5686d577e7fe47eea0807904e
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
-rw-r--r-- | src/gui/.prev_CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/gui/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/gui/kernel/kernel.pri | 3 | ||||
-rw-r--r-- | src/gui/kernel/qevent.cpp | 648 | ||||
-rw-r--r-- | src/gui/kernel/qevent.h | 110 | ||||
-rw-r--r-- | src/gui/kernel/qevent_p.h | 134 | ||||
-rw-r--r-- | src/gui/kernel/qeventpoint.cpp | 664 | ||||
-rw-r--r-- | src/gui/kernel/qeventpoint.h | 172 | ||||
-rw-r--r-- | src/gui/kernel/qeventpoint_p.h | 200 | ||||
-rw-r--r-- | src/gui/kernel/qinputdevice.cpp | 4 | ||||
-rw-r--r-- | src/gui/kernel/qpointingdevice.cpp | 91 | ||||
-rw-r--r-- | src/gui/kernel/qpointingdevice_p.h | 3 | ||||
-rw-r--r-- | src/gui/kernel/qwindowsysteminterface_p.h | 3 |
13 files changed, 1140 insertions, 894 deletions
diff --git a/src/gui/.prev_CMakeLists.txt b/src/gui/.prev_CMakeLists.txt index 981a88c603..f86e2bd89f 100644 --- a/src/gui/.prev_CMakeLists.txt +++ b/src/gui/.prev_CMakeLists.txt @@ -35,6 +35,7 @@ qt_internal_add_module(Gui image/qxpmhandler.cpp image/qxpmhandler_p.h kernel/qclipboard.cpp kernel/qclipboard.h kernel/qcursor.cpp kernel/qcursor.h kernel/qcursor_p.h + kernel/qeventpoint.cpp kernel/qeventpoint.h kernel/qeventpoint_p.h kernel/qevent.cpp kernel/qevent.h kernel/qevent_p.h kernel/qgenericplugin.cpp kernel/qgenericplugin.h kernel/qgenericpluginfactory.cpp kernel/qgenericpluginfactory.h diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt index 5d7037079a..1d4d44894b 100644 --- a/src/gui/CMakeLists.txt +++ b/src/gui/CMakeLists.txt @@ -86,6 +86,7 @@ qt_internal_add_module(Gui image/qxpmhandler.cpp image/qxpmhandler_p.h kernel/qclipboard.cpp kernel/qclipboard.h kernel/qcursor.cpp kernel/qcursor.h kernel/qcursor_p.h + kernel/qeventpoint.cpp kernel/qeventpoint.h kernel/qeventpoint_p.h kernel/qevent.cpp kernel/qevent.h kernel/qevent_p.h kernel/qgenericplugin.cpp kernel/qgenericplugin.h kernel/qgenericpluginfactory.cpp kernel/qgenericpluginfactory.h diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index 48fd18f8d2..f6f6002f76 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -48,6 +48,8 @@ HEADERS += \ kernel/qcursor_p.h \ kernel/qevent.h \ kernel/qevent_p.h \ + kernel/qeventpoint.h \ + kernel/qeventpoint_p.h \ kernel/qinputdevice.h \ kernel/qinputdevice_p.h \ kernel/qinputmethod.h \ @@ -108,6 +110,7 @@ SOURCES += \ kernel/qclipboard.cpp \ kernel/qcursor.cpp \ kernel/qevent.cpp \ + kernel/qeventpoint.cpp \ kernel/qinputdevice.cpp \ kernel/qinputmethod.cpp \ kernel/qinternalmimedata.cpp \ diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index a4e44f5b8d..9d27961071 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -61,10 +61,6 @@ QT_BEGIN_NAMESPACE -Q_LOGGING_CATEGORY(lcPointerGrab, "qt.pointer.grab") -Q_LOGGING_CATEGORY(lcPointerVel, "qt.pointer.velocity") -Q_LOGGING_CATEGORY(lcEPDetach, "qt.pointer.eventpoint.detach") - /*! \class QEnterEvent \ingroup events @@ -226,392 +222,6 @@ QInputEvent::~QInputEvent() */ /*! - \internal - Constructs an invalid event point with the given \a id and the \a device - from which it originated. - - This acts as a default constructor in usages like QMap<int, QEventPoint>, - as in qgraphicsscene_p.h. -*/ -QEventPoint::QEventPoint(int id, const QPointingDevice *device) - : 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)) {} - -/*! - Constructs an event point by making a shallow copy of \a other. -*/ -QEventPoint::QEventPoint(const QEventPoint &other) - : d(other.d) -{ - if (d) - d->refCount++; -} - -/*! - Assigns \a other to this event point and returns a reference to this - event point. -*/ -QEventPoint &QEventPoint::operator=(const QEventPoint &other) -{ - if (other.d) - other.d->refCount++; - if (d && !(--d->refCount)) - delete d; - d = other.d; - return *this; -} - -/*! - \fn QEventPoint::QEventPoint(QEventPoint &&other) noexcept - - Constructs an event point by moving \a other. -*/ - -/*! - \fn QEventPoint &QEventPoint::operator=(QEventPoint &&other) noexcept - - Move-assigns \a other to this event point instance. -*/ - -/*! - Returns \c true if this event point is equal to \a other, otherwise - return \c false. -*/ -bool QEventPoint::operator==(const QEventPoint &other) const noexcept -{ - if (d == other.d) - return true; - if (!d || !other.d) - return false; - return *d == *other.d; -} - -/*! - \fn bool QEventPoint::operator!=(const QEventPoint &other) const noexcept - - Returns \c true if this event point is not equal to \a other, otherwise - return \c false. -*/ - -/*! - Destroys the event point. -*/ -QEventPoint::~QEventPoint() -{ - if (d && !(--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::timestamp() const -{ return d->timestamp; } - -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; } - -/*! - Returns the time from the previous QPointerEvent that contained this point. - - \sa globalLastPosition() -*/ -ulong QEventPoint::lastTimestamp() const -{ return d->lastTimestamp; } - -/*! - Sets the accepted state of the point to \a accepted. - - In widget-based applications, this function is not used so far, because - it's only meaningful for a widget to accept or reject a complete QInputEvent. - - In Qt Quick however, it's normal for an Item or Event Handler to accept - only the individual points in a QTouchEvent that are actually participating - in a gesture, while other points can be delivered to other items or - handlers. For the sake of consistency, that applies to any QPointerEvent; - and delivery is done only when all points in a QPointerEvent have been - accepted. - - \sa QEvent::setAccepted() -*/ -void QEventPoint::setAccepted(bool accepted) -{ - d->accept = accepted; -} - -/*! - \obsolete - \fn QPointF QPointerEvent::normalizedPos() const - - Deprecated since Qt 6.0. Use normalizedPosition() instead. -*/ - -/*! - Returns the normalized position of this point. - - The coordinates are calculated by transforming globalPosition() into the - space of QInputDevice::availableVirtualGeometry(), i.e. \c (0, 0) is the - top-left corner and \c (1, 1) is the bottom-right corner. - - \sa globalPosition() -*/ -QPointF QEventPoint::normalizedPosition() const -{ - auto geom = d->device->availableVirtualGeometry(); - if (geom.isNull()) - return QPointF(); - return (globalPosition() - geom.topLeft()) / geom.width(); -} - -/*! - \obsolete - Deprecated since Qt 6.0. Use globalPressPosition() instead. - - Returns the normalized press position of this point. -*/ -QPointF QEventPoint::startNormalizedPos() const -{ - auto geom = d->device->availableVirtualGeometry(); - if (geom.isNull()) - return QPointF(); - return (globalPressPosition() - geom.topLeft()) / geom.width(); -} - -/*! - \obsolete - Deprecated since Qt 6.0. Use globalLastPosition() instead. - - Returns the normalized position of this point from the previous press or - move event. - - The coordinates are normalized to QInputDevice::availableVirtualGeometry(), - i.e. \c (0, 0) is the top-left corner and \c (1, 1) is the bottom-right corner. - - \sa normalizedPos(), startNormalizedPos() -*/ -QPointF QEventPoint::lastNormalizedPos() const -{ - 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 - qCDebug(lcEPDetach) << "detaching: refCount" << d->refCount << this; - auto old = d; - d = new QEventPointPrivate(*d); - d->refCount = 1; - --old->refCount; -} - -/*! \internal - Update current state from the given \a other point, assuming that this - instance contains state from the previous event and \a other contains new - values that came in from a device. - - That is: global position and other valuators will be updated, but - the following properties will not be updated: - - \list - \li other properties that are not likely to be set after a fresh touchpoint - has been received from a device - \li properties that should be persistent between events (such as grabbers) - \endlist -*/ -void QMutableEventPoint::updateFrom(const QEventPoint &other) -{ - detach(); - setPressure(other.pressure()); - - switch (other.state()) { - case QEventPoint::State::Pressed: - setGlobalPressPosition(other.globalPosition()); - setGlobalLastPosition(other.globalPosition()); - if (pressure() < 0) - setPressure(1); - break; - - case QEventPoint::State::Released: - if (globalPosition() != other.globalPosition()) - setGlobalLastPosition(globalPosition()); - setPressure(0); - break; - - default: // update or stationary - if (globalPosition() != other.globalPosition()) - setGlobalLastPosition(globalPosition()); - if (pressure() < 0) - setPressure(1); - break; - } - - setState(other.state()); - setPosition(other.position()); - setScenePosition(other.scenePosition()); - setGlobalPosition(other.globalPosition()); - setEllipseDiameters(other.ellipseDiameters()); - setRotation(other.rotation()); - setVelocity(other.velocity()); -} - -/*! \internal - Set the timestamp from the event that updated this point's positions, - and calculate a new value for velocity(). - - The velocity calculation is done here because none of the QPointerEvent - subclass constructors take the timestamp directly, and because - QGuiApplication traditionally constructs an event first and then sets its - timestamp (see for example QGuiApplicationPrivate::processMouseEvent()). - - This function looks up the corresponding instance in QPointingDevicePrivate::activePoints, - and assumes that its timestamp() still holds the previous time when this point - was updated, its velocity() holds this point's last-known velocity, and - its globalPosition() and globalLastPosition() hold this point's current - and previous positions, respectively. We assume timestamps are in milliseconds. - - The velocity calculation is skipped if the platform has promised to - provide velocities already by setting the QInputDevice::Velocity capability. -*/ -void QMutableEventPoint::setTimestamp(const ulong t) -{ - // On mouse press, if the mouse has moved from its last-known location, - // QGuiApplicationPrivate::processMouseEvent() sends first a mouse move and - // then a press. Both events will get the same timestamp. So we need to set - // the press timestamp and position even when the timestamp isn't advancing, - // but skip setting lastTimestamp and velocity because those need a time delta. - if (state() == QEventPoint::State::Pressed) { - d->pressTimestamp = t; - d->globalPressPos = d->globalPos; - } - if (d->timestamp == t) - return; - detach(); - if (device()) { - // get the persistent instance out of QPointingDevicePrivate::activePoints - // (which sometimes might be the same as this instance) - QEventPointPrivate *pd = QPointingDevicePrivate::get( - const_cast<QPointingDevice *>(d->device))->pointById(id())->eventPoint.d; - if (t > pd->timestamp) { - pd->lastTimestamp = pd->timestamp; - pd->timestamp = t; - if (state() == QEventPoint::State::Pressed) - pd->pressTimestamp = t; - if (pd->lastTimestamp > 0 && !device()->capabilities().testFlag(QInputDevice::Capability::Velocity)) { - // calculate instantaneous velocity according to time and distance moved since the previous point - QVector2D newVelocity = QVector2D(pd->globalPos - pd->globalLastPos) / (t - pd->lastTimestamp) * 1000; - // VERY simple kalman filter: does a weighted average - // where the older velocities get less and less significant - static const float KalmanGain = 0.7f; - pd->velocity = newVelocity * KalmanGain + pd->velocity * (1.0f - KalmanGain); - qCDebug(lcPointerVel) << "velocity" << newVelocity << "filtered" << pd->velocity << - "based on movement" << pd->globalLastPos << "->" << pd->globalPos << - "over time" << pd->lastTimestamp << "->" << pd->timestamp; - } - if (d != pd) { - d->lastTimestamp = pd->lastTimestamp; - d->velocity = pd->velocity; - } - } - } - d->timestamp = t; -} - -/*! \internal - void QMutableEventPoint::setPosition(const QPointF &pos) - Sets the localized position. - Often events need to be localized before delivery to specific widgets or - items. This can be done directly, or in a copy (for which we have a copy - constructor), depending on whether the original point needs to be retained. - Usually it's calculated by mapping scenePosition() to the target anyway. -*/ - -/*! \class QPointerEvent \since 6.0 \inmodule QtGui @@ -868,7 +478,7 @@ void QPointerEvent::clearPassiveGrabbers(const QEventPoint &point) Returns the position of the point in this event, relative to the window or scene. - \sa QEventPoint::scenePosition() + \sa QEventPoint::scenePosition */ /*! \fn QPointF QSinglePointEvent::globalPosition() const @@ -4843,177 +4453,6 @@ bool QTouchEvent::isEndEvent() const \sa QPointerEvent::point(), QPointerEvent::pointCount() */ -/*! \class QEventPoint - \brief The QEventPoint class provides information about a point in a QPointerEvent. - \since 6.0 - \inmodule QtGui -*/ - -/*! - \enum QEventPoint::State - - Specifies the state of this event point. - - \value Unknown - Unknown state. - - \value Stationary - The event point did not move. - - \value Pressed - The touch point or button is pressed. - - \value Updated - The event point was updated. - - \value Released - The touch point or button was released. -*/ - -/*! \fn int QEventPoint::id() const - - Returns the ID number of this event point. - - \note Do not assume that ID numbers start at zero or that they are - sequential. Such an assumption is often false due to the way - the underlying drivers work. -*/ - -/*! \fn QPointingDeviceUniqueId QEventPoint::uniqueId() const - - Returns the unique ID of this point or token, if any. - - It is often invalid (see \l {QPointingDeviceUniqueId::isValid()} {isValid()}), - because touchscreens cannot uniquely identify fingers. - - When it comes from a QTabletEvent, it identifies the serial number of the - stylus in use. - - It may identify a specific token (fiducial object) when the TUIO driver is - in use with a touchscreen that supports them. -*/ - -/*! \fn QEventPoint::State QEventPoint::state() const - Returns the current state of this point. -*/ - -/*! \fn QPointF QEventPoint::position() const - - Returns the position of this point, relative to the widget - or item that received the event. -*/ - -/*! \fn QPointF QEventPoint::pos() const - \obsolete - Deprecated since Qt 6.0. Use position() instead. - - Returns the position of this point, relative to the widget - or item that received the event. -*/ - -/*! \fn QPointF QEventPoint::scenePosition() const - Returns the position of this point relative to the window or scene. - - The scene position is the position relative to QQuickWindow if handled in QQuickItem::event(), - in QGraphicsScene coordinates if handled by an override of QGraphicsItem::touchEvent(), - or the window position in widget applications. - - \sa scenePressPosition(), position(), globalPosition() -*/ - -/*! \fn QPointF QEventPoint::globalPosition() const - Returns the position of this point on the screen or virtual desktop. - - \sa globalPressPosition(), position(), scenePosition() -*/ - -/*! \fn QPointF QEventPoint::pressPosition() const - Returns the position at which this point was pressed, relative to the - widget or item that received the event. - - \sa position() -*/ - -/*! \fn QPointF QEventPoint::scenePressPosition() const - Returns the scene position at which this point was pressed. - - The scene position is the position relative to QQuickWindow if handled in QQuickItem::event(), - in QGraphicsScene coordinates if handled by an override of QGraphicsItem::touchEvent(), - or the window position in widget applications. - - \sa scenePosition(), pressPosition(), globalPressPosition() -*/ - -/*! \fn QPointF QEventPoint::globalPressPosition() const - Returns the position at which this point was pressed on the screen or virtual desktop. - - \sa globalPosition(), pressPosition(), scenePressPosition() -*/ - -/*! \fn QPointF QEventPoint::lastPosition() const - Returns the position of this point from the previous press or move event, - relative to the widget or QGraphicsItem that received the event. - - \sa position(), pressPosition() -*/ - -/*! \fn QPointF QEventPoint::sceneLastPosition() const - Returns the scene position of this point from the previous press or move event. - - The scene position is the position in QGraphicsScene coordinates - if the QTouchEvent is handled by a QGraphicsItem::touchEvent() - reimplementation, and identical to the screen position for - widgets. - - \sa scenePosition(), scenePressPosition() -*/ - -/*! \fn qreal QEventPoint::pressure() const - Returns the pressure of this point. The return value is in - the range \c 0.0 to \c 1.0. -*/ - -/*! \fn qreal QEventPoint::rotation() const - - Returns the angular orientation of this point. The return value is in degrees, - where zero (the default) indicates the finger, token or stylus is pointing upwards, - a negative angle means it's rotated to the left, and a positive angle means - it's rotated to the right. Most touchscreens do not detect rotation, so - zero is the most common value. -*/ - -/*! \fn QSizeF QEventPoint::ellipseDiameters() const - - Returns the width and height of the bounding ellipse of the touch point. - The return value is in logical pixels. Most touchscreens do not detect the - shape of the contact point, and no mice or tablet devices can detect it, - so a null size is the most common value. On some touchscreens the diameters - may be nonzero and always equal (the ellipse is approximated as a circle). -*/ - -/*! - \fn QVector2D QEventPoint::velocity() const - Returns a velocity vector, in units of pixels per second, in the coordinate - system of the screen or desktop. - - \note If the device's capabilities include QInputDevice::Velocity, it means - velocity comes from the operating system (perhaps the touch hardware or - driver provides it). But usually the \c Velocity capability is not set, - indicating that the velocity is calculated by Qt, using a simple Kalman - filter to provide a smoothed average velocity rather than an instantaneous - value. Effectively it tells how fast and in what direction the user has - been dragging this point over the last few events, with the most recent - event having the strongest influence. - - \sa QInputDevice::capabilities(), QInputEvent::device() -*/ - -/*! \fn ulong QEventPoint::timestamp() const - Returns the most recent time at which this point was included in a QPointerEvent. - - \sa QPointerEvent::timestamp() -*/ - /*! \class QScrollPrepareEvent \since 4.8 @@ -5256,91 +4695,6 @@ void QMutableTouchEvent::addPoint(const QEventPoint &point) m_touchPointStates |= point.state(); } -/*! - \class QPointingDeviceUniqueId - \since 5.8 - \ingroup events - \inmodule QtGui - - \brief QPointingDeviceUniqueId identifies a unique object, such as a tagged token - or stylus, which is used with a pointing device. - - QPointingDeviceUniqueIds 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. - - \sa QEventPoint -*/ - -/*! - \fn QPointingDeviceUniqueId::QPointingDeviceUniqueId() - Constructs an invalid unique pointer ID. -*/ - -/*! - Constructs a unique pointer ID from numeric ID \a id. -*/ -QPointingDeviceUniqueId QPointingDeviceUniqueId::fromNumericId(qint64 id) -{ - QPointingDeviceUniqueId result; - result.m_numericId = id; - return result; -} - -/*! - \fn bool QPointingDeviceUniqueId::isValid() const - - Returns whether this unique pointer ID is valid, that is, it represents an actual - pointer. -*/ - -/*! - \property QPointingDeviceUniqueId::numericId - \brief the numeric unique ID of the token represented by a touchpoint - - If the device provides a numeric ID, isValid() returns true, and this - property provides the numeric ID; - 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 QPointingDeviceUniqueId::numericId() const noexcept -{ - return m_numericId; -} -/*! - \fn bool QPointingDeviceUniqueId::operator==(QPointingDeviceUniqueId lhs, QPointingDeviceUniqueId rhs) - \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). -*/ - -/*! - \fn bool QPointingDeviceUniqueId::operator!=(QPointingDeviceUniqueId lhs, QPointingDeviceUniqueId rhs) - \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 QPointingDeviceUniqueId - \since 5.8 - - Returns the hash value for \a key, using \a seed to seed the calculation. -*/ -size_t qHash(QPointingDeviceUniqueId key, size_t seed) noexcept -{ - return qHash(key.numericId(), seed); -} QT_END_NAMESPACE diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index 2459f1ba9d..4bd7a54022 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -50,9 +50,9 @@ #include <QtCore/qstring.h> #include <QtCore/qurl.h> #include <QtCore/qvariant.h> +#include <QtGui/qeventpoint.h> #include <QtGui/qpointingdevice.h> #include <QtGui/qregion.h> -#include <QtGui/qvector2d.h> #include <QtGui/qwindowdefs.h> #if QT_CONFIG(shortcut) @@ -93,114 +93,6 @@ protected: qint64 m_extra = 0; // reserved, unused for now }; -struct QEventPointPrivate; -class Q_GUI_EXPORT QEventPoint -{ - Q_GADGET - Q_PROPERTY(const QPointingDevice *device READ device) - Q_PROPERTY(int id READ id) - Q_PROPERTY(QPointingDeviceUniqueId uniqueId READ uniqueId) - Q_PROPERTY(State state READ state) - Q_PROPERTY(ulong timestamp READ timestamp) - Q_PROPERTY(qreal timeHeld READ timeHeld) - Q_PROPERTY(qreal pressure READ pressure) - Q_PROPERTY(qreal rotation READ rotation) - Q_PROPERTY(QSizeF ellipseDiameters READ ellipseDiameters) - Q_PROPERTY(QVector2D velocity READ velocity) - Q_PROPERTY(QPointF position READ position) - Q_PROPERTY(QPointF scenePosition READ scenePosition) - Q_PROPERTY(QPointF globalPosition READ globalPosition) -public: - enum State : quint8 { - Unknown = Qt::TouchPointUnknownState, - Stationary = Qt::TouchPointStationary, - Pressed = Qt::TouchPointPressed, - Updated = Qt::TouchPointMoved, - Released = Qt::TouchPointReleased - }; - Q_DECLARE_FLAGS(States, State) - Q_FLAG(States) - - QEventPoint(int id = -1, const QPointingDevice *device = nullptr); - QEventPoint(int pointId, State state, const QPointF &scenePosition, const QPointF &globalPosition); - QEventPoint(const QEventPoint &other); - QEventPoint(QEventPoint && other) noexcept : d(std::move(other.d)) { other.d = nullptr; } - QEventPoint &operator=(const QEventPoint &other); - QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QEventPoint) - bool operator==(const QEventPoint &other) const noexcept; - inline bool operator!=(const QEventPoint &other) const noexcept { return !operator==(other); } - ~QEventPoint(); - inline void swap(QEventPoint &other) noexcept - { qSwap(d, other.d); } - - 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; - QPointF normalizedPosition() const; - -#if QT_DEPRECATED_SINCE(6, 0) - // QEventPoint replaces QTouchEvent::TouchPoint, so we need all its old accessors, for now - QT_DEPRECATED_VERSION_X_6_0("Use position()") - QPointF pos() const { return position(); } - QT_DEPRECATED_VERSION_X_6_0("Use pressPosition()") - QPointF startPos() const { return pressPosition(); } - QT_DEPRECATED_VERSION_X_6_0("Use scenePosition()") - QPointF scenePos() const { return scenePosition(); } - QT_DEPRECATED_VERSION_X_6_0("Use scenePressPosition()") - QPointF startScenePos() const { return scenePressPosition(); } - QT_DEPRECATED_VERSION_X_6_0("Use globalPosition()") - QPointF screenPos() const { return globalPosition(); } - QT_DEPRECATED_VERSION_X_6_0("Use globalPressPosition()") - QPointF startScreenPos() const { return globalPressPosition(); } - QT_DEPRECATED_VERSION_X_6_0("Use globalPressPosition()") - QPointF startNormalizedPos() const; - QT_DEPRECATED_VERSION_X_6_0("Use normalizedPosition()") - QPointF normalizedPos() const { return normalizedPosition(); } - QT_DEPRECATED_VERSION_X_6_0("Use lastPosition()") - QPointF lastPos() const { return lastPosition(); } - QT_DEPRECATED_VERSION_X_6_0("Use sceneLastPosition()") - QPointF lastScenePos() const { return sceneLastPosition(); } - QT_DEPRECATED_VERSION_X_6_0("Use globalLastPosition()") - QPointF lastScreenPos() const { return globalLastPosition(); } - QT_DEPRECATED_VERSION_X_6_0("Use globalLastPosition()") - QPointF lastNormalizedPos() const; -#endif // QT_DEPRECATED_SINCE(6, 0) - QVector2D velocity() const; - State state() const; - const QPointingDevice *device() const; - int id() const; - QPointingDeviceUniqueId uniqueId() const; - ulong timestamp() const; - ulong lastTimestamp() const; - ulong pressTimestamp() const; - qreal timeHeld() const; - qreal pressure() const; - qreal rotation() const; - QSizeF ellipseDiameters() const; - - bool isAccepted() const; - void setAccepted(bool accepted = true); - -private: - QEventPointPrivate *d; - friend class QMutableEventPoint; - friend class QPointerEvent; -}; - -#ifndef QT_NO_DEBUG_STREAM -Q_GUI_EXPORT QDebug operator<<(QDebug, const QEventPoint *); -Q_GUI_EXPORT QDebug operator<<(QDebug, const QEventPoint &); -#endif - class Q_GUI_EXPORT QPointerEvent : public QInputEvent { public: diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h index 205673d53d..7c9974db7f 100644 --- a/src/gui/kernel/qevent_p.h +++ b/src/gui/kernel/qevent_p.h @@ -52,6 +52,7 @@ // #include <QtGui/private/qtguiglobal_p.h> +#include <QtGui/private/qeventpoint_p.h> #include <QtCore/qurl.h> #include <QtGui/qevent.h> #include <QtGui/qwindow.h> @@ -60,139 +61,6 @@ QT_BEGIN_NAMESPACE class QPointingDevice; -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; - } - inline bool operator==(const QEventPointPrivate &other) const - { - return device == other.device - && window == other.window - && target == other.target - && pos == other.pos - && scenePos == other.scenePos - && globalPos == other.globalPos - && globalPressPos == other.globalPressPos - && globalGrabPos == other.globalGrabPos - && globalLastPos == other.globalLastPos - && pressure == other.pressure - && rotation == other.rotation - && ellipseDiameters == other.ellipseDiameters - && velocity == other.velocity - && timestamp == other.timestamp - && lastTimestamp == other.lastTimestamp - && pressTimestamp == other.pressTimestamp - && uniqueId == other.uniqueId - && pointId == other.pointId - && state == other.state; - } - - const QPointingDevice *device = nullptr; - QPointer<QWindow> window; - QPointer<QObject> target; - QPointF pos, scenePos, globalPos, - globalPressPos, globalGrabPos, globalLastPos; - qreal pressure = 1; - qreal rotation = 0; - QSizeF ellipseDiameters = QSizeF(0, 0); - QVector2D velocity; - ulong timestamp = 0; - ulong lastTimestamp = 0; - ulong pressTimestamp = 0; - QPointingDeviceUniqueId uniqueId; - int refCount = 1; - int pointId = -1; - QEventPoint::State state = QEventPoint::State::Unknown; - bool accept = false; -}; - -// Private subclasses to allow accessing and modifying protected variables. -// These should NOT hold any extra state. - -class Q_GUI_EXPORT QMutableEventPoint : public QEventPoint -{ -public: - QMutableEventPoint(int pointId = -1, State state = QEventPoint::State::Stationary, - const QPointF &scenePosition = QPointF(), const QPointF &globalPosition = QPointF()) : - QEventPoint(pointId, state, scenePosition, globalPosition) {} - - QMutableEventPoint(ulong timestamp, int pointId, State state, - const QPointF &position, const QPointF &scenePosition, const QPointF &globalPosition) : - QEventPoint(pointId, state, scenePosition, globalPosition) - { - d->timestamp = timestamp; - d->pos = position; - } - - void updateFrom(const QEventPoint &other); - - static QMutableEventPoint *from(QEventPoint *me) { return static_cast<QMutableEventPoint *>(me); } - - static QMutableEventPoint &from(QEventPoint &me) { return static_cast<QMutableEventPoint &>(me); } - - static const QMutableEventPoint &constFrom(const QEventPoint &me) { return static_cast<const QMutableEventPoint &>(me); } - - void detach(); - - void setId(int pointId) { d->pointId = pointId; } - - void setDevice(const QPointingDevice *device) { d->device = device; } - - void setTimestamp(const ulong t); - - void setPressTimestamp(const ulong t) { d->pressTimestamp = t; } - - void setState(QEventPoint::State state) { d->state = state; } - - void setUniqueId(const QPointingDeviceUniqueId &uid) { d->uniqueId = uid; } - - void setPosition(const QPointF &pos) { d->pos = pos; } - - void setScenePosition(const QPointF &pos) { d->scenePos = 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) { d->pos = pos; } - QT_DEPRECATED_VERSION_X_6_0("Use setScenePosition()") - void setScenePos(const QPointF &pos) { d->scenePos = pos; } - QT_DEPRECATED_VERSION_X_6_0("Use setGlobalPosition()") - void setScreenPos(const QPointF &pos) { d->globalPos = pos; } -#endif - - void setGlobalPressPosition(const QPointF &pos) { d->globalPressPos = pos; } - - void setGlobalGrabPosition(const QPointF &pos) { d->globalGrabPos = pos; } - - void setGlobalLastPosition(const QPointF &pos) { d->globalLastPos = pos; } - - void setEllipseDiameters(const QSizeF &diams) { d->ellipseDiameters = diams; } - - void setPressure(qreal v) { d->pressure = v; } - - void setRotation(qreal v) { d->rotation = v; } - - void setVelocity(const QVector2D &v) { d->velocity = v; } - - QWindow *window() const { return d->window.data(); } - - void setWindow(const QPointer<QWindow> &w) { d->window = w; } - - QObject *target() const { return d->target.data(); } - - void setTarget(const QPointer<QObject> &t) { d->target = t; } -}; - -static_assert(sizeof(QMutableEventPoint) == sizeof(QEventPoint)); - class Q_GUI_EXPORT QMutableTouchEvent : public QTouchEvent { public: diff --git a/src/gui/kernel/qeventpoint.cpp b/src/gui/kernel/qeventpoint.cpp new file mode 100644 index 0000000000..e8a366885f --- /dev/null +++ b/src/gui/kernel/qeventpoint.cpp @@ -0,0 +1,664 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qeventpoint.h" +#include "private/qeventpoint_p.h" +#include "private/qpointingdevice_p.h" + +QT_BEGIN_NAMESPACE + +Q_LOGGING_CATEGORY(lcPointerVel, "qt.pointer.velocity") +Q_LOGGING_CATEGORY(lcEPDetach, "qt.pointer.eventpoint.detach") + +/*! \class QEventPoint + \brief The QEventPoint class provides information about a point in a QPointerEvent. + \since 6.0 + \inmodule QtGui +*/ + +/*! + \enum QEventPoint::State + + Specifies the state of this event point. + + \value Unknown + Unknown state. + + \value Stationary + The event point did not move. + + \value Pressed + The touch point or button is pressed. + + \value Updated + The event point was updated. + + \value Released + The touch point or button was released. +*/ + +/*! + \internal + Constructs an invalid event point with the given \a id and the \a device + from which it originated. + + This acts as a default constructor in usages like QMap<int, QEventPoint>, + as in qgraphicsscene_p.h. +*/ +QEventPoint::QEventPoint(int id, const QPointingDevice *device) + : 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)) {} + +/*! + Constructs an event point by making a shallow copy of \a other. +*/ +QEventPoint::QEventPoint(const QEventPoint &other) + : d(other.d) +{ + if (d) + d->refCount++; +} + +/*! + Assigns \a other to this event point and returns a reference to this + event point. +*/ +QEventPoint &QEventPoint::operator=(const QEventPoint &other) +{ + if (other.d) + other.d->refCount++; + if (d && !(--d->refCount)) + delete d; + d = other.d; + return *this; +} + +/*! + \fn QEventPoint::QEventPoint(QEventPoint &&other) noexcept + + Constructs an event point by moving \a other. +*/ + +/*! + \fn QEventPoint &QEventPoint::operator=(QEventPoint &&other) noexcept + + Move-assigns \a other to this event point instance. +*/ + +/*! + Returns \c true if this event point is equal to \a other, otherwise + return \c false. +*/ +bool QEventPoint::operator==(const QEventPoint &other) const noexcept +{ + if (d == other.d) + return true; + if (!d || !other.d) + return false; + return *d == *other.d; +} + +/*! + \fn bool QEventPoint::operator!=(const QEventPoint &other) const noexcept + + Returns \c true if this event point is not equal to \a other, otherwise + return \c false. +*/ + +/*! + Destroys the event point. +*/ +QEventPoint::~QEventPoint() +{ + if (d && !(--d->refCount)) + delete d; +} + +/*! \fn QPointF QEventPoint::pos() const + \obsolete + Deprecated since Qt 6.0. Use position() instead. + + Returns the position of this point, relative to the widget + or item that received the event. +*/ + +/*! + \property QEventPoint::position + the position of this point + + The position is relative to the widget or item that received the event. +*/ +QPointF QEventPoint::position() const +{ return d->pos; } + +/*! + \property QEventPoint::pressPosition + the position at which this point was pressed + + The position is relative to the widget or item that received the event. + + \sa position +*/ +QPointF QEventPoint::pressPosition() const +{ return d->globalPressPos - d->globalPos + d->pos; } + +/*! + \property QEventPoint::grabPosition + the position at which this point was grabbed + + The position is relative to the widget or item that received the event. + + \sa position +*/ +QPointF QEventPoint::grabPosition() const +{ return d->globalGrabPos - d->globalPos + d->pos; } + +/*! + \property QEventPoint::lastPosition + the position of this point from the previous press or move event + + The position is relative to the widget or item that received the event. + + \sa position, pressPosition +*/ +QPointF QEventPoint::lastPosition() const +{ return d->globalLastPos - d->globalPos + d->pos; } + +/*! + \property QEventPoint::scenePosition + the scene position of this point + + The scene position is the position relative to QQuickWindow if handled in QQuickItem::event(), + in QGraphicsScene coordinates if handled by an override of QGraphicsItem::touchEvent(), + or the window position in widget applications. + + \sa scenePressPosition, position, globalPosition +*/ +QPointF QEventPoint::scenePosition() const +{ return d->scenePos; } + +/*! + \property QEventPoint::scenePressPosition + the scene position at which this point was pressed + + The scene position is the position relative to QQuickWindow if handled in QQuickItem::event(), + in QGraphicsScene coordinates if handled by an override of QGraphicsItem::touchEvent(), + or the window position in widget applications. + + \sa scenePosition, pressPosition, globalPressPosition +*/ +QPointF QEventPoint::scenePressPosition() const +{ return d->globalPressPos - d->globalPos + d->scenePos; } + +/*! + \property QEventPoint::sceneGrabPosition + the scene position at which this point was grabbed + + The scene position is the position relative to QQuickWindow if handled in QQuickItem::event(), + in QGraphicsScene coordinates if handled by an override of QGraphicsItem::touchEvent(), + or the window position in widget applications. + + \sa scenePosition, grabPosition, globalGrabPosition +*/ +QPointF QEventPoint::sceneGrabPosition() const +{ return d->globalGrabPos - d->globalPos + d->scenePos; } + +/*! + \property QEventPoint::sceneLastPosition + the scene position of this point from the previous press or move event + + The scene position is the position relative to QQuickWindow if handled in QQuickItem::event(), + in QGraphicsScene coordinates if handled by an override of QGraphicsItem::touchEvent(), + or the window position in widget applications. + + \sa scenePosition, scenePressPosition +*/ +QPointF QEventPoint::sceneLastPosition() const +{ return d->globalLastPos - d->globalPos + d->scenePos; } + +/*! + \property QEventPoint::globalPosition + the global position of this point + + The global position is relative to the screen or virtual desktop. + + \sa globalPressPosition, position, scenePosition +*/ +QPointF QEventPoint::globalPosition() const +{ return d->globalPos; } + +/*! + \property QEventPoint::globalPressPosition + the global position at which this point was pressed + + The global position is relative to the screen or virtual desktop. + + \sa globalPosition, pressPosition, scenePressPosition +*/ +QPointF QEventPoint::globalPressPosition() const +{ return d->globalPressPos; } + +/*! + \property QEventPoint::globalGrabPosition + the global position at which this point was grabbed + + The global position is relative to the screen or virtual desktop. + + \sa globalPosition, grabPosition, sceneGrabPosition +*/ +QPointF QEventPoint::globalGrabPosition() const +{ return d->globalGrabPos; } + +/*! + \property QEventPoint::globalLastPosition + the global position of this point from the previous press or move event + + The global position is relative to the screen or virtual desktop. + + \sa globalPosition, lastPosition, sceneLastPosition +*/ +QPointF QEventPoint::globalLastPosition() const +{ return d->globalLastPos; } + +/*! + \property QEventPoint::velocity + a velocity vector, in units of pixels per second, in the coordinate + system of the screen or desktop. + + \note If the device's capabilities include QInputDevice::Velocity, it means + velocity comes from the operating system (perhaps the touch hardware or + driver provides it). But usually the \c Velocity capability is not set, + indicating that the velocity is calculated by Qt, using a simple Kalman + filter to provide a smoothed average velocity rather than an instantaneous + value. Effectively it tells how fast and in what direction the user has + been dragging this point over the last few events, with the most recent + event having the strongest influence. + + \sa QInputDevice::capabilities(), QInputEvent::device() +*/ +QVector2D QEventPoint::velocity() const +{ return d->velocity; } + +/*! + \property QEventPoint::state + the current state of the event point. +*/ +QEventPoint::State QEventPoint::state() const +{ return d->state; } + +/*! + \property QEventPoint::device + the pointing device from which this event point originates +*/ +const QPointingDevice *QEventPoint::device() const +{ return d->device; } + +/*! + \property QEventPoint::id + the ID number of this event point + + \note Do not assume that ID numbers start at zero or that they are + sequential. Such an assumption is often false due to the way + the underlying drivers work. +*/ +int QEventPoint::id() const +{ return d->pointId; } + +/*! + \property QEventPoint::uniqueId + the unique ID of this point or token, if any + + It is often invalid (see \l {QPointingDeviceUniqueId::isValid()} {isValid()}), + because touchscreens cannot uniquely identify fingers. + + When it comes from a QTabletEvent, it identifies the serial number of the + stylus in use. + + It may identify a specific token (fiducial object) when the TUIO driver is + in use with a touchscreen that supports them. +*/ +QPointingDeviceUniqueId QEventPoint::uniqueId() const +{ return d->uniqueId; } + +/*! + \property QEventPoint::timestamp + the most recent time at which this point was included in a QPointerEvent + + \sa QPointerEvent::timestamp() +*/ +ulong QEventPoint::timestamp() const +{ return d->timestamp; } + +/*! + \property QEventPoint::lastTimestamp + the time from the previous QPointerEvent that contained this point + + \sa globalLastPosition +*/ +ulong QEventPoint::lastTimestamp() const +{ return d->lastTimestamp; } + +/*! + \property QEventPoint::pressTimestamp + the most recent time at which this point was pressed + + \sa timestamp +*/ +ulong QEventPoint::pressTimestamp() const +{ return d->pressTimestamp; } + +/*! + \property QEventPoint::timeHeld + the duration, in milliseconds, since this point was pressed and not released + + \sa pressTimestamp, timestamp +*/ +qreal QEventPoint::timeHeld() const +{ return (d->timestamp - d->pressTimestamp) / qreal(1000); } + +/*! + \property QEventPoint::pressure + the pressure of this point + + The return value is in the range \c 0.0 to \c 1.0. +*/ +qreal QEventPoint::pressure() const +{ return d->pressure; } + +/*! + \property QEventPoint::rotation + the angular orientation of this point + + The return value is in degrees, where zero (the default) indicates the finger, + token or stylus is pointing upwards, a negative angle means it's rotated to the + left, and a positive angle means it's rotated to the right. + Most touchscreens do not detect rotation, so zero is the most common value. +*/ +qreal QEventPoint::rotation() const +{ return d->rotation; } + +/*! + \property QEventPoint::ellipseDiameters + the width and height of the bounding ellipse of the touch point + + The return value is in logical pixels. Most touchscreens do not detect the + shape of the contact point, and no mice or tablet devices can detect it, + so a null size is the most common value. On some touchscreens the diameters + may be nonzero and always equal (the ellipse is approximated as a circle). +*/ +QSizeF QEventPoint::ellipseDiameters() const +{ return d->ellipseDiameters; } + +/*! + \property QEventPoint::accepted + the accepted state of the event point + + In widget-based applications, this property is not used, as it's only meaningful + for a widget to accept or reject a complete QInputEvent. + + In Qt Quick however, it's normal for an Item or Event Handler to accept + only the individual points in a QTouchEvent that are actually participating + in a gesture, while other points can be delivered to other items or + handlers. For the sake of consistency, that applies to any QPointerEvent; + and delivery is done only when all points in a QPointerEvent have been + accepted. + + \sa QEvent::accepted +*/ +void QEventPoint::setAccepted(bool accepted) +{ + d->accept = accepted; +} + +bool QEventPoint::isAccepted() const +{ return d->accept; } + + +/*! + \obsolete + \fn QPointF QEventPoint::normalizedPos() const + + Deprecated since Qt 6.0. Use normalizedPosition() instead. +*/ + +/*! + Returns the normalized position of this point. + + The coordinates are calculated by transforming globalPosition() into the + space of QInputDevice::availableVirtualGeometry(), i.e. \c (0, 0) is the + top-left corner and \c (1, 1) is the bottom-right corner. + + \sa globalPosition +*/ +QPointF QEventPoint::normalizedPosition() const +{ + auto geom = d->device->availableVirtualGeometry(); + if (geom.isNull()) + return QPointF(); + return (globalPosition() - geom.topLeft()) / geom.width(); +} + +/*! + \obsolete + Deprecated since Qt 6.0. Use globalPressPosition() instead. + + Returns the normalized press position of this point. +*/ +QPointF QEventPoint::startNormalizedPos() const +{ + auto geom = d->device->availableVirtualGeometry(); + if (geom.isNull()) + return QPointF(); + return (globalPressPosition() - geom.topLeft()) / geom.width(); +} + +/*! + \obsolete + Deprecated since Qt 6.0. Use globalLastPosition() instead. + + Returns the normalized position of this point from the previous press or + move event. + + The coordinates are normalized to QInputDevice::availableVirtualGeometry(), + i.e. \c (0, 0) is the top-left corner and \c (1, 1) is the bottom-right corner. + + \sa normalizedPos(), startNormalizedPos() +*/ +QPointF QEventPoint::lastNormalizedPos() const +{ + 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 + qCDebug(lcEPDetach) << "detaching: refCount" << d->refCount << this; + auto old = d; + d = new QEventPointPrivate(*d); + d->refCount = 1; + --old->refCount; +} + +/*! \internal + Update current state from the given \a other point, assuming that this + instance contains state from the previous event and \a other contains new + values that came in from a device. + + That is: global position and other valuators will be updated, but + the following properties will not be updated: + + \list + \li properties that are not likely to be set after a fresh touchpoint + has been received from a device + \li properties that should be persistent between events (such as grabbers) + \endlist +*/ +void QMutableEventPoint::updateFrom(const QEventPoint &other) +{ + detach(); + setPressure(other.pressure()); + + switch (other.state()) { + case QEventPoint::State::Pressed: + setGlobalPressPosition(other.globalPosition()); + setGlobalLastPosition(other.globalPosition()); + if (pressure() < 0) + setPressure(1); + break; + + case QEventPoint::State::Released: + if (globalPosition() != other.globalPosition()) + setGlobalLastPosition(globalPosition()); + setPressure(0); + break; + + default: // update or stationary + if (globalPosition() != other.globalPosition()) + setGlobalLastPosition(globalPosition()); + if (pressure() < 0) + setPressure(1); + break; + } + + setState(other.state()); + setPosition(other.position()); + setScenePosition(other.scenePosition()); + setGlobalPosition(other.globalPosition()); + setEllipseDiameters(other.ellipseDiameters()); + setRotation(other.rotation()); + setVelocity(other.velocity()); +} + +/*! \internal + Set the timestamp from the event that updated this point's positions, + and calculate a new value for velocity(). + + The velocity calculation is done here because none of the QPointerEvent + subclass constructors take the timestamp directly, and because + QGuiApplication traditionally constructs an event first and then sets its + timestamp (see for example QGuiApplicationPrivate::processMouseEvent()). + + This function looks up the corresponding instance in QPointingDevicePrivate::activePoints, + and assumes that its timestamp() still holds the previous time when this point + was updated, its velocity() holds this point's last-known velocity, and + its globalPosition() and globalLastPosition() hold this point's current + and previous positions, respectively. We assume timestamps are in milliseconds. + + The velocity calculation is skipped if the platform has promised to + provide velocities already by setting the QInputDevice::Velocity capability. +*/ +void QMutableEventPoint::setTimestamp(const ulong t) +{ + // On mouse press, if the mouse has moved from its last-known location, + // QGuiApplicationPrivate::processMouseEvent() sends first a mouse move and + // then a press. Both events will get the same timestamp. So we need to set + // the press timestamp and position even when the timestamp isn't advancing, + // but skip setting lastTimestamp and velocity because those need a time delta. + if (state() == QEventPoint::State::Pressed) { + d->pressTimestamp = t; + d->globalPressPos = d->globalPos; + } + if (d->timestamp == t) + return; + detach(); + if (device()) { + // get the persistent instance out of QPointingDevicePrivate::activePoints + // (which sometimes might be the same as this instance) + QEventPointPrivate *pd = QPointingDevicePrivate::get( + const_cast<QPointingDevice *>(d->device))->pointById(id())->eventPoint.d; + if (t > pd->timestamp) { + pd->lastTimestamp = pd->timestamp; + pd->timestamp = t; + if (state() == QEventPoint::State::Pressed) + pd->pressTimestamp = t; + if (pd->lastTimestamp > 0 && !device()->capabilities().testFlag(QInputDevice::Capability::Velocity)) { + // calculate instantaneous velocity according to time and distance moved since the previous point + QVector2D newVelocity = QVector2D(pd->globalPos - pd->globalLastPos) / (t - pd->lastTimestamp) * 1000; + // VERY simple kalman filter: does a weighted average + // where the older velocities get less and less significant + static const float KalmanGain = 0.7f; + pd->velocity = newVelocity * KalmanGain + pd->velocity * (1.0f - KalmanGain); + qCDebug(lcPointerVel) << "velocity" << newVelocity << "filtered" << pd->velocity << + "based on movement" << pd->globalLastPos << "->" << pd->globalPos << + "over time" << pd->lastTimestamp << "->" << pd->timestamp; + } + if (d != pd) { + d->lastTimestamp = pd->lastTimestamp; + d->velocity = pd->velocity; + } + } + } + d->timestamp = t; +} + +/*! + \fn void QMutableEventPoint::setPosition(const QPointF &pos) + \internal + + Sets the localized position. + Often events need to be localized before delivery to specific widgets or + items. This can be done directly, or in a copy (for which we have a copy + constructor), depending on whether the original point needs to be retained. + Usually it's calculated by mapping scenePosition() to the target anyway. +*/ + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qeventpoint.h b/src/gui/kernel/qeventpoint.h new file mode 100644 index 0000000000..d4cce66b90 --- /dev/null +++ b/src/gui/kernel/qeventpoint.h @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QEVENTPOINT_H +#define QEVENTPOINT_H + +#include <QtGui/qtguiglobal.h> +#include <QtGui/qvector2d.h> +#include <QtGui/qpointingdevice.h> + +QT_BEGIN_NAMESPACE + +struct QEventPointPrivate; +class Q_GUI_EXPORT QEventPoint +{ + Q_GADGET + Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted) + QDOC_PROPERTY(QPointingDevice *device READ device CONSTANT) // qdoc doesn't know const + Q_PROPERTY(const QPointingDevice *device READ device CONSTANT) + Q_PROPERTY(int id READ id CONSTANT) + Q_PROPERTY(QPointingDeviceUniqueId uniqueId READ uniqueId CONSTANT) + Q_PROPERTY(State state READ state CONSTANT) + Q_PROPERTY(ulong timestamp READ timestamp CONSTANT) + Q_PROPERTY(ulong pressTimestamp READ pressTimestamp CONSTANT) + Q_PROPERTY(ulong lastTimestamp READ lastTimestamp CONSTANT) + Q_PROPERTY(qreal timeHeld READ timeHeld CONSTANT) + Q_PROPERTY(qreal pressure READ pressure CONSTANT) + Q_PROPERTY(qreal rotation READ rotation CONSTANT) + Q_PROPERTY(QSizeF ellipseDiameters READ ellipseDiameters CONSTANT) + Q_PROPERTY(QVector2D velocity READ velocity CONSTANT) + Q_PROPERTY(QPointF position READ position CONSTANT) + Q_PROPERTY(QPointF pressPosition READ pressPosition CONSTANT) + Q_PROPERTY(QPointF grabPosition READ grabPosition CONSTANT) + Q_PROPERTY(QPointF lastPosition READ lastPosition CONSTANT) + Q_PROPERTY(QPointF scenePosition READ scenePosition CONSTANT) + Q_PROPERTY(QPointF scenePressPosition READ scenePressPosition CONSTANT) + Q_PROPERTY(QPointF sceneGrabPosition READ sceneGrabPosition CONSTANT) + Q_PROPERTY(QPointF sceneLastPosition READ sceneLastPosition CONSTANT) + Q_PROPERTY(QPointF globalPosition READ globalPosition CONSTANT) + Q_PROPERTY(QPointF globalPressPosition READ globalPressPosition CONSTANT) + Q_PROPERTY(QPointF globalGrabPosition READ globalGrabPosition CONSTANT) + Q_PROPERTY(QPointF globalLastPosition READ globalLastPosition CONSTANT) +public: + enum State : quint8 { + Unknown = Qt::TouchPointUnknownState, + Stationary = Qt::TouchPointStationary, + Pressed = Qt::TouchPointPressed, + Updated = Qt::TouchPointMoved, + Released = Qt::TouchPointReleased + }; + Q_DECLARE_FLAGS(States, State) + Q_FLAG(States) + + QEventPoint(int id = -1, const QPointingDevice *device = nullptr); + QEventPoint(int pointId, State state, const QPointF &scenePosition, const QPointF &globalPosition); + QEventPoint(const QEventPoint &other); + QEventPoint(QEventPoint && other) noexcept : d(std::move(other.d)) { other.d = nullptr; } + QEventPoint &operator=(const QEventPoint &other); + QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QEventPoint) + bool operator==(const QEventPoint &other) const noexcept; + inline bool operator!=(const QEventPoint &other) const noexcept { return !operator==(other); } + ~QEventPoint(); + inline void swap(QEventPoint &other) noexcept + { qSwap(d, other.d); } + + 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; + QPointF normalizedPosition() const; + +#if QT_DEPRECATED_SINCE(6, 0) + // QEventPoint replaces QTouchEvent::TouchPoint, so we need all its old accessors, for now + QT_DEPRECATED_VERSION_X_6_0("Use position()") + QPointF pos() const { return position(); } + QT_DEPRECATED_VERSION_X_6_0("Use pressPosition()") + QPointF startPos() const { return pressPosition(); } + QT_DEPRECATED_VERSION_X_6_0("Use scenePosition()") + QPointF scenePos() const { return scenePosition(); } + QT_DEPRECATED_VERSION_X_6_0("Use scenePressPosition()") + QPointF startScenePos() const { return scenePressPosition(); } + QT_DEPRECATED_VERSION_X_6_0("Use globalPosition()") + QPointF screenPos() const { return globalPosition(); } + QT_DEPRECATED_VERSION_X_6_0("Use globalPressPosition()") + QPointF startScreenPos() const { return globalPressPosition(); } + QT_DEPRECATED_VERSION_X_6_0("Use globalPressPosition()") + QPointF startNormalizedPos() const; + QT_DEPRECATED_VERSION_X_6_0("Use normalizedPosition()") + QPointF normalizedPos() const { return normalizedPosition(); } + QT_DEPRECATED_VERSION_X_6_0("Use lastPosition()") + QPointF lastPos() const { return lastPosition(); } + QT_DEPRECATED_VERSION_X_6_0("Use sceneLastPosition()") + QPointF lastScenePos() const { return sceneLastPosition(); } + QT_DEPRECATED_VERSION_X_6_0("Use globalLastPosition()") + QPointF lastScreenPos() const { return globalLastPosition(); } + QT_DEPRECATED_VERSION_X_6_0("Use globalLastPosition()") + QPointF lastNormalizedPos() const; +#endif // QT_DEPRECATED_SINCE(6, 0) + QVector2D velocity() const; + State state() const; + const QPointingDevice *device() const; + int id() const; + QPointingDeviceUniqueId uniqueId() const; + ulong timestamp() const; + ulong lastTimestamp() const; + ulong pressTimestamp() const; + qreal timeHeld() const; + qreal pressure() const; + qreal rotation() const; + QSizeF ellipseDiameters() const; + + bool isAccepted() const; + void setAccepted(bool accepted = true); + +private: + QEventPointPrivate *d; + friend class QMutableEventPoint; + friend class QPointerEvent; +}; + +#ifndef QT_NO_DEBUG_STREAM +Q_GUI_EXPORT QDebug operator<<(QDebug, const QEventPoint *); +Q_GUI_EXPORT QDebug operator<<(QDebug, const QEventPoint &); +#endif + +QT_END_NAMESPACE + +#endif // QEVENTPOINT_H diff --git a/src/gui/kernel/qeventpoint_p.h b/src/gui/kernel/qeventpoint_p.h new file mode 100644 index 0000000000..147d134bda --- /dev/null +++ b/src/gui/kernel/qeventpoint_p.h @@ -0,0 +1,200 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QEVENTPOINT_P_H +#define QEVENTPOINT_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGui/private/qtguiglobal_p.h> +#include <QtGui/qevent.h> +#include <QtCore/qloggingcategory.h> + +QT_BEGIN_NAMESPACE + +Q_DECLARE_LOGGING_CATEGORY(lcPointerVel); +Q_DECLARE_LOGGING_CATEGORY(lcEPDetach); + +class QPointingDevice; + +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; + } + inline bool operator==(const QEventPointPrivate &other) const + { + return device == other.device + && window == other.window + && target == other.target + && pos == other.pos + && scenePos == other.scenePos + && globalPos == other.globalPos + && globalPressPos == other.globalPressPos + && globalGrabPos == other.globalGrabPos + && globalLastPos == other.globalLastPos + && pressure == other.pressure + && rotation == other.rotation + && ellipseDiameters == other.ellipseDiameters + && velocity == other.velocity + && timestamp == other.timestamp + && lastTimestamp == other.lastTimestamp + && pressTimestamp == other.pressTimestamp + && uniqueId == other.uniqueId + && pointId == other.pointId + && state == other.state; + } + + const QPointingDevice *device = nullptr; + QPointer<QWindow> window; + QPointer<QObject> target; + QPointF pos, scenePos, globalPos, + globalPressPos, globalGrabPos, globalLastPos; + qreal pressure = 1; + qreal rotation = 0; + QSizeF ellipseDiameters = QSizeF(0, 0); + QVector2D velocity; + ulong timestamp = 0; + ulong lastTimestamp = 0; + ulong pressTimestamp = 0; + QPointingDeviceUniqueId uniqueId; + int refCount = 1; + int pointId = -1; + QEventPoint::State state = QEventPoint::State::Unknown; + bool accept = false; +}; + +// Private subclasses to allow accessing and modifying protected variables. +// These should NOT hold any extra state. + +class Q_GUI_EXPORT QMutableEventPoint : public QEventPoint +{ +public: + QMutableEventPoint(int pointId = -1, State state = QEventPoint::State::Stationary, + const QPointF &scenePosition = QPointF(), const QPointF &globalPosition = QPointF()) : + QEventPoint(pointId, state, scenePosition, globalPosition) {} + + QMutableEventPoint(ulong timestamp, int pointId, State state, + const QPointF &position, const QPointF &scenePosition, const QPointF &globalPosition) : + QEventPoint(pointId, state, scenePosition, globalPosition) + { + d->timestamp = timestamp; + d->pos = position; + } + + void updateFrom(const QEventPoint &other); + + static QMutableEventPoint *from(QEventPoint *me) { return static_cast<QMutableEventPoint *>(me); } + + static QMutableEventPoint &from(QEventPoint &me) { return static_cast<QMutableEventPoint &>(me); } + + static const QMutableEventPoint &constFrom(const QEventPoint &me) { return static_cast<const QMutableEventPoint &>(me); } + + void detach(); + + void setId(int pointId) { d->pointId = pointId; } + + void setDevice(const QPointingDevice *device) { d->device = device; } + + void setTimestamp(const ulong t); + + void setPressTimestamp(const ulong t) { d->pressTimestamp = t; } + + void setState(QEventPoint::State state) { d->state = state; } + + void setUniqueId(const QPointingDeviceUniqueId &uid) { d->uniqueId = uid; } + + void setPosition(const QPointF &pos) { d->pos = pos; } + + void setScenePosition(const QPointF &pos) { d->scenePos = 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) { d->pos = pos; } + QT_DEPRECATED_VERSION_X_6_0("Use setScenePosition()") + void setScenePos(const QPointF &pos) { d->scenePos = pos; } + QT_DEPRECATED_VERSION_X_6_0("Use setGlobalPosition()") + void setScreenPos(const QPointF &pos) { d->globalPos = pos; } +#endif + + void setGlobalPressPosition(const QPointF &pos) { d->globalPressPos = pos; } + + void setGlobalGrabPosition(const QPointF &pos) { d->globalGrabPos = pos; } + + void setGlobalLastPosition(const QPointF &pos) { d->globalLastPos = pos; } + + void setEllipseDiameters(const QSizeF &diams) { d->ellipseDiameters = diams; } + + void setPressure(qreal v) { d->pressure = v; } + + void setRotation(qreal v) { d->rotation = v; } + + void setVelocity(const QVector2D &v) { d->velocity = v; } + + QWindow *window() const { return d->window.data(); } + + void setWindow(const QPointer<QWindow> &w) { d->window = w; } + + QObject *target() const { return d->target.data(); } + + void setTarget(const QPointer<QObject> &t) { d->target = t; } +}; + +static_assert(sizeof(QMutableEventPoint) == sizeof(QEventPoint)); + +QT_END_NAMESPACE + +#endif // QEVENTPOINT_P_H diff --git a/src/gui/kernel/qinputdevice.cpp b/src/gui/kernel/qinputdevice.cpp index 09b1939c29..eb3259347a 100644 --- a/src/gui/kernel/qinputdevice.cpp +++ b/src/gui/kernel/qinputdevice.cpp @@ -40,16 +40,14 @@ #include "qinputdevice.h" #include "qinputdevice_p.h" #include "qpointingdevice.h" +#include "qwindowsysteminterface_p.h" #include <QCoreApplication> #include <QDebug> -#include <QLoggingCategory> #include <QMutex> #include <QScreen> QT_BEGIN_NAMESPACE -Q_DECLARE_LOGGING_CATEGORY(lcQpaInputDevices) - /*! \class QInputDevice \brief The QInputDevice class describes a device from which a QInputEvent originates. diff --git a/src/gui/kernel/qpointingdevice.cpp b/src/gui/kernel/qpointingdevice.cpp index fa04ad21f6..24ce68e430 100644 --- a/src/gui/kernel/qpointingdevice.cpp +++ b/src/gui/kernel/qpointingdevice.cpp @@ -39,6 +39,7 @@ #include "qpointingdevice.h" #include "qpointingdevice_p.h" +#include "qwindowsysteminterface_p.h" #include <QList> #include <QLoggingCategory> #include <QMutex> @@ -48,8 +49,7 @@ QT_BEGIN_NAMESPACE -Q_DECLARE_LOGGING_CATEGORY(lcQpaInputDevices) -Q_DECLARE_LOGGING_CATEGORY(lcPointerGrab) +Q_LOGGING_CATEGORY(lcPointerGrab, "qt.pointer.grab"); /*! \class QPointingDevice @@ -663,4 +663,91 @@ QDebug operator<<(QDebug debug, const QPointingDevice *device) } #endif // !QT_NO_DEBUG_STREAM +/*! + \class QPointingDeviceUniqueId + \since 5.8 + \ingroup events + \inmodule QtGui + + \brief QPointingDeviceUniqueId identifies a unique object, such as a tagged token + or stylus, which is used with a pointing device. + + QPointingDeviceUniqueIds 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. + + \sa QEventPoint +*/ + +/*! + \fn QPointingDeviceUniqueId::QPointingDeviceUniqueId() + Constructs an invalid unique pointer ID. +*/ + +/*! + Constructs a unique pointer ID from numeric ID \a id. +*/ +QPointingDeviceUniqueId QPointingDeviceUniqueId::fromNumericId(qint64 id) +{ + QPointingDeviceUniqueId result; + result.m_numericId = id; + return result; +} + +/*! + \fn bool QPointingDeviceUniqueId::isValid() const + + Returns whether this unique pointer ID is valid, that is, it represents an actual + pointer. +*/ + +/*! + \property QPointingDeviceUniqueId::numericId + \brief the numeric unique ID of the token represented by a touchpoint + + If the device provides a numeric ID, isValid() returns true, and this + property provides the numeric ID; + 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 QPointingDeviceUniqueId::numericId() const noexcept +{ + return m_numericId; +} + +/*! + \fn bool QPointingDeviceUniqueId::operator==(QPointingDeviceUniqueId lhs, QPointingDeviceUniqueId rhs) + \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). +*/ + +/*! + \fn bool QPointingDeviceUniqueId::operator!=(QPointingDeviceUniqueId lhs, QPointingDeviceUniqueId rhs) + \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 QPointingDeviceUniqueId + \since 5.8 + + Returns the hash value for \a key, using \a seed to seed the calculation. +*/ +size_t qHash(QPointingDeviceUniqueId key, size_t seed) noexcept +{ + return qHash(key.numericId(), seed); +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qpointingdevice_p.h b/src/gui/kernel/qpointingdevice_p.h index 299b99959e..6f787b4159 100644 --- a/src/gui/kernel/qpointingdevice_p.h +++ b/src/gui/kernel/qpointingdevice_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <QtCore/qloggingcategory.h> #include <QtGui/private/qevent_p.h> #include <QtGui/qpointingdevice.h> #include <QtGui/private/qtguiglobal_p.h> @@ -59,6 +60,8 @@ QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcPointerGrab); + class Q_GUI_EXPORT QPointingDevicePrivate : public QInputDevicePrivate { Q_DECLARE_PUBLIC(QPointingDevice) diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h index a2927cbc02..af149cd2ab 100644 --- a/src/gui/kernel/qwindowsysteminterface_p.h +++ b/src/gui/kernel/qwindowsysteminterface_p.h @@ -60,9 +60,12 @@ #include <QList> #include <QWaitCondition> #include <QAtomicInt> +#include <QLoggingCategory> QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcQpaInputDevices); + class QWindowSystemEventHandler; class Q_GUI_EXPORT QWindowSystemInterfacePrivate { |