Add more QPointerEvent functions needed in Qt Quick
Change-Id: I87a874477b89eb3f5951930f03e305d896a24c2e Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>bb10
parent
d1fc991c6e
commit
8932e80d0c
|
|
@ -605,6 +605,44 @@ QPointerEvent::~QPointerEvent()
|
|||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the point whose \l {QEventPoint::id()}{id} matches the given \a id,
|
||||
or \c nullptr if no such point is found.
|
||||
*/
|
||||
QEventPoint *QPointerEvent::pointById(int id)
|
||||
{
|
||||
for (auto &p : m_points) {
|
||||
if (p.id() == id)
|
||||
return &p;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if every point in points() has an exclusiveGrabber().
|
||||
*/
|
||||
bool QPointerEvent::allPointsGrabbed() const
|
||||
{
|
||||
for (const auto &p : points()) {
|
||||
if (exclusiveGrabber(p) && passiveGrabbers(p).isEmpty())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if isPointAccepted() is \c true for every point in
|
||||
points(); otherwise \c false.
|
||||
*/
|
||||
bool QPointerEvent::allPointsAccepted() const
|
||||
{
|
||||
for (const auto &p : points()) {
|
||||
if (!p.isAccepted())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the source device from which this event originates.
|
||||
|
||||
|
|
@ -844,6 +882,27 @@ QSinglePointEvent::QSinglePointEvent(QEvent::Type type, const QPointingDevice *d
|
|||
m_points.append(mut);
|
||||
}
|
||||
|
||||
/*! \internal
|
||||
Constructs a single-point event with the given \a point, which must be an instance
|
||||
(or copy of one) that already exists in QPointingDevicePrivate::activePoints.
|
||||
Unlike the other constructor, it does not modify the given \a point in any way.
|
||||
This is useful when synthesizing a QMouseEvent from one point taken from a QTouchEvent, for example.
|
||||
|
||||
\sa QMutableSinglePointEvent()
|
||||
*/
|
||||
QSinglePointEvent::QSinglePointEvent(QEvent::Type type, const QPointingDevice *dev, const QEventPoint &point,
|
||||
Qt::MouseButton button, Qt::MouseButtons buttons,
|
||||
Qt::KeyboardModifiers modifiers, Qt::MouseEventSource source)
|
||||
: QPointerEvent(type, dev, modifiers),
|
||||
m_button(button),
|
||||
m_mouseState(buttons),
|
||||
m_source(source),
|
||||
m_doubleClick(false),
|
||||
m_reserved(0)
|
||||
{
|
||||
m_points << point;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns \c true if this event represents a \l {button()}{button} being pressed.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -63,8 +63,11 @@ QT_BEGIN_NAMESPACE
|
|||
|
||||
class QFile;
|
||||
class QAction;
|
||||
class QMouseEvent;
|
||||
class QPointerEvent;
|
||||
class QScreen;
|
||||
class QTabletEvent;
|
||||
class QTouchEvent;
|
||||
#if QT_CONFIG(gestures)
|
||||
class QGesture;
|
||||
#endif
|
||||
|
|
@ -94,6 +97,19 @@ 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,
|
||||
|
|
@ -192,9 +208,12 @@ public:
|
|||
qsizetype pointCount() const { return m_points.count(); }
|
||||
QEventPoint &point(qsizetype i) { return m_points[i]; }
|
||||
const QList<QEventPoint> &points() const { return m_points; }
|
||||
QEventPoint *pointById(int id);
|
||||
bool allPointsGrabbed() const;
|
||||
virtual bool isPressEvent() const { return false; }
|
||||
virtual bool isUpdateEvent() const { return false; }
|
||||
virtual bool isReleaseEvent() const { return false; }
|
||||
bool allPointsAccepted() const;
|
||||
QObject *exclusiveGrabber(const QEventPoint &point) const;
|
||||
void setExclusiveGrabber(const QEventPoint &point, QObject *exclusiveGrabber);
|
||||
QList<QPointer <QObject>> passiveGrabbers(const QEventPoint &point) const;
|
||||
|
|
@ -229,6 +248,10 @@ public:
|
|||
bool isReleaseEvent() const override;
|
||||
|
||||
protected:
|
||||
QSinglePointEvent(Type type, const QPointingDevice *dev, const QEventPoint &point,
|
||||
Qt::MouseButton button, Qt::MouseButtons buttons,
|
||||
Qt::KeyboardModifiers modifiers, Qt::MouseEventSource source);
|
||||
|
||||
Qt::MouseButton m_button = Qt::NoButton;
|
||||
Qt::MouseButtons m_mouseState = Qt::NoButton;
|
||||
quint32 m_source : 8; // actually Qt::MouseEventSource
|
||||
|
|
@ -346,6 +369,12 @@ protected:
|
|||
#if QT_CONFIG(wheelevent)
|
||||
class Q_GUI_EXPORT QWheelEvent : public QSinglePointEvent
|
||||
{
|
||||
Q_GADGET
|
||||
Q_PROPERTY(const QPointingDevice *device READ pointingDevice)
|
||||
Q_PROPERTY(QPoint pixelDelta READ pixelDelta)
|
||||
Q_PROPERTY(QPoint angleDelta READ angleDelta)
|
||||
Q_PROPERTY(Qt::ScrollPhase phase READ phase)
|
||||
Q_PROPERTY(bool inverted READ inverted)
|
||||
public:
|
||||
enum { DefaultDeltasPerStep = 120 };
|
||||
|
||||
|
|
@ -360,6 +389,8 @@ public:
|
|||
|
||||
inline Qt::ScrollPhase phase() const { return Qt::ScrollPhase(m_phase); }
|
||||
inline bool inverted() const { return m_invertedScrolling; }
|
||||
inline bool isInverted() const { return m_invertedScrolling; }
|
||||
inline bool hasPixelDelta() const { return !m_pixelDelta.isNull(); }
|
||||
|
||||
Qt::MouseEventSource source() const { return Qt::MouseEventSource(m_source); }
|
||||
|
||||
|
|
|
|||
|
|
@ -199,6 +199,12 @@ static_assert(sizeof(QMutableTouchEvent) == sizeof(QTouchEvent));
|
|||
class Q_GUI_EXPORT QMutableSinglePointEvent : public QSinglePointEvent
|
||||
{
|
||||
public:
|
||||
QMutableSinglePointEvent(Type type, const QPointingDevice *device, const QEventPoint &point,
|
||||
Qt::MouseButton button = Qt::NoButton, Qt::MouseButtons buttons = Qt::NoButton,
|
||||
Qt::KeyboardModifiers modifiers = Qt::NoModifier,
|
||||
Qt::MouseEventSource source = Qt::MouseEventSynthesizedByQt) :
|
||||
QSinglePointEvent(type, device, point, button, buttons, modifiers, source) { }
|
||||
|
||||
static QMutableSinglePointEvent *from(QSinglePointEvent *e) { return static_cast<QMutableSinglePointEvent *>(e); }
|
||||
|
||||
static QMutableSinglePointEvent &from(QSinglePointEvent &e) { return static_cast<QMutableSinglePointEvent &>(e); }
|
||||
|
|
|
|||
|
|
@ -354,6 +354,33 @@ const QPointingDevice *QPointingDevicePrivate::queryTabletDevice(QInputDevice::D
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
First, ensure that the \a cancelEvent's QTouchEvent::points() list contains
|
||||
all points that have exclusive grabs. Then send the event to each object
|
||||
that has an exclusive grab of any of the points.
|
||||
*/
|
||||
void QPointingDevicePrivate::sendTouchCancelEvent(QTouchEvent *cancelEvent)
|
||||
{
|
||||
// An incoming TouchCancel event will typically not contain any points, but
|
||||
// QQuickPointerHandler::onGrabChanged needs to be called for each point
|
||||
// that has an exclusive grabber. Adding those points to the event makes it
|
||||
// an easy iteration there.
|
||||
if (cancelEvent->points().isEmpty()) {
|
||||
for (auto &epd : activePoints.values()) {
|
||||
if (epd.exclusiveGrabber)
|
||||
QMutableTouchEvent::from(cancelEvent)->addPoint(epd.eventPoint);
|
||||
}
|
||||
}
|
||||
for (auto &epd : activePoints.values()) {
|
||||
if (epd.exclusiveGrabber)
|
||||
QCoreApplication::sendEvent(epd.exclusiveGrabber, cancelEvent);
|
||||
// The next touch event can only be a TouchBegin, so clean up.
|
||||
cancelEvent->setExclusiveGrabber(epd.eventPoint, nullptr);
|
||||
cancelEvent->clearPassiveGrabbers(epd.eventPoint);
|
||||
}
|
||||
}
|
||||
|
||||
/*! \internal
|
||||
Returns the active EventPointData instance with the given \a id, if available,
|
||||
or \c nullptr if not.
|
||||
|
|
@ -422,6 +449,19 @@ QWindow *QPointingDevicePrivate::firstActiveWindow() const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
/*! \internal
|
||||
Return the exclusive grabber of the first point in activePoints.
|
||||
This is mainly for autotests that try to verify the "current" grabber
|
||||
outside the context of event delivery, which is something that the rest
|
||||
of the codebase should not be doing.
|
||||
*/
|
||||
QObject *QPointingDevicePrivate::firstPointExclusiveGrabber() const
|
||||
{
|
||||
if (activePoints.isEmpty())
|
||||
return nullptr;
|
||||
return activePoints.values().first().exclusiveGrabber;
|
||||
}
|
||||
|
||||
void QPointingDevicePrivate::setExclusiveGrabber(const QPointerEvent *event, const QEventPoint &point, QObject *exclusiveGrabber)
|
||||
{
|
||||
Q_Q(QPointingDevice);
|
||||
|
|
@ -446,6 +486,22 @@ void QPointingDevicePrivate::setExclusiveGrabber(const QPointerEvent *event, con
|
|||
emit q->grabChanged(exclusiveGrabber, QPointingDevice::GrabExclusive, event, point);
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Call QEventPoint::setExclusiveGrabber(nullptr) on each active point that has a grabber.
|
||||
*/
|
||||
bool QPointingDevicePrivate::removeExclusiveGrabber(const QPointerEvent *event, const QObject *grabber)
|
||||
{
|
||||
bool ret = false;
|
||||
for (auto &pt : activePoints.values()) {
|
||||
if (pt.exclusiveGrabber == grabber) {
|
||||
setExclusiveGrabber(event, pt.eventPoint, nullptr);
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool QPointingDevicePrivate::addPassiveGrabber(const QPointerEvent *event, const QEventPoint &point, QObject *grabber)
|
||||
{
|
||||
Q_Q(QPointingDevice);
|
||||
|
|
@ -505,6 +561,43 @@ void QPointingDevicePrivate::clearPassiveGrabbers(const QPointerEvent *event, co
|
|||
persistentPoint->passiveGrabbers.clear();
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Removes the given \a grabber as both passive and exclusive grabber from all
|
||||
points in activePoints where it's currently found. If \a cancel is \c true,
|
||||
the transition emitted from the grabChanged() signal will be
|
||||
\c CancelGrabExclusive or \c CancelGrabPassive. Otherwise it will be
|
||||
\c UngrabExclusive or \c UngrabPassive.
|
||||
|
||||
\note This function provides a way to work around the limitation that we
|
||||
normally change grabbers only during event delivery; but it's also more expensive.
|
||||
*/
|
||||
void QPointingDevicePrivate::removeGrabber(QObject *grabber, bool cancel)
|
||||
{
|
||||
Q_Q(QPointingDevice);
|
||||
for (auto ap : activePoints) {
|
||||
auto &epd = ap.second;
|
||||
if (epd.exclusiveGrabber.data() == grabber) {
|
||||
qCDebug(lcPointerGrab) << name << "point" << epd.eventPoint.id() << epd.eventPoint.state()
|
||||
<< "@" << epd.eventPoint.scenePosition()
|
||||
<< ": grab" << grabber << "-> nullptr";
|
||||
epd.exclusiveGrabber.clear();
|
||||
emit q->grabChanged(grabber,
|
||||
cancel ? QPointingDevice::CancelGrabExclusive : QPointingDevice::UngrabExclusive,
|
||||
nullptr, epd.eventPoint);
|
||||
}
|
||||
int pi = epd.passiveGrabbers.indexOf(grabber);
|
||||
if (pi >= 0) {
|
||||
qCDebug(lcPointerGrab) << name << "point" << epd.eventPoint.id() << epd.eventPoint.state()
|
||||
<< ": removing passive grabber" << grabber;
|
||||
epd.passiveGrabbers.removeAt(pi);
|
||||
emit q->grabChanged(grabber,
|
||||
cancel ? QPointingDevice::CancelGrabPassive : QPointingDevice::UngrabPassive,
|
||||
nullptr, epd.eventPoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
Finds the device instance belonging to the drawing or eraser end of a particular stylus,
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ class QDebug;
|
|||
class QEventPoint;
|
||||
class QPointerEvent;
|
||||
class QPointingDevicePrivate;
|
||||
class QPointerEvent;
|
||||
class QScreen;
|
||||
|
||||
class Q_GUI_EXPORT QPointingDeviceUniqueId
|
||||
|
|
|
|||
|
|
@ -77,6 +77,8 @@ public:
|
|||
activePoints.reserve(maxPoints);
|
||||
}
|
||||
|
||||
void sendTouchCancelEvent(QTouchEvent *cancelEvent);
|
||||
|
||||
/*! \internal
|
||||
This struct (stored in activePoints) holds persistent state between event deliveries.
|
||||
*/
|
||||
|
|
@ -91,10 +93,13 @@ public:
|
|||
QObject *firstActiveTarget() const;
|
||||
QWindow *firstActiveWindow() const;
|
||||
|
||||
QObject *firstPointExclusiveGrabber() const;
|
||||
void setExclusiveGrabber(const QPointerEvent *event, const QEventPoint &point, QObject *exclusiveGrabber);
|
||||
bool removeExclusiveGrabber(const QPointerEvent *event, const QObject *grabber);
|
||||
bool addPassiveGrabber(const QPointerEvent *event, const QEventPoint &point, QObject *grabber);
|
||||
bool removePassiveGrabber(const QPointerEvent *event, const QEventPoint &point, QObject *grabber);
|
||||
void clearPassiveGrabbers(const QPointerEvent *event, const QEventPoint &point);
|
||||
void removeGrabber(QObject *grabber, bool cancel = false);
|
||||
|
||||
using EventPointMap = QFlatMap<int, EventPointData>;
|
||||
mutable EventPointMap activePoints;
|
||||
|
|
|
|||
Loading…
Reference in New Issue