/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtQuick 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 "qquickevents_p_p.h"
#include <QtCore/qmap.h>
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/private/qtouchdevice_p.h>
#include <QtGui/private/qevent_p.h>
#include <QtQuick/private/qquickitem_p.h>
#include <QtQuick/private/qquickpointerhandler_p.h>
#include <QtQuick/private/qquickwindow_p.h>
#include <private/qdebug_p.h>

QT_BEGIN_NAMESPACE

Q_LOGGING_CATEGORY(lcPointerEvents, "qt.quick.pointer.events")
Q_LOGGING_CATEGORY(lcPointerGrab, "qt.quick.pointer.grab")

/*!
    \qmltype KeyEvent
    \instantiates QQuickKeyEvent
    \inqmlmodule QtQuick
    \ingroup qtquick-input-events

    \brief Provides information about a key event.

    For example, the following changes the Item's state property when the Enter
    key is pressed:
    \qml
Item {
    focus: true
    Keys.onPressed: { if (event.key == Qt.Key_Enter) state = 'ShowDetails'; }
}
    \endqml
*/

/*!
    \qmlproperty int QtQuick::KeyEvent::key

    This property holds the code of the key that was pressed or released.

    See \l {Qt::Key}{Qt.Key} for the list of keyboard codes. These codes are
    independent of the underlying window system. Note that this
    function does not distinguish between capital and non-capital
    letters; use the \l {KeyEvent::}{text} property for this purpose.

    A value of either 0 or \l {Qt::Key_unknown}{Qt.Key_Unknown} means that the event is not
    the result of a known key; for example, it may be the result of
    a compose sequence, a keyboard macro, or due to key event
    compression.
*/

/*!
    \qmlproperty string QtQuick::KeyEvent::text

    This property holds the Unicode text that the key generated.
    The text returned can be an empty string in cases where modifier keys,
    such as Shift, Control, Alt, and Meta, are being pressed or released.
    In such cases \c key will contain a valid value
*/

/*!
    \qmlproperty bool QtQuick::KeyEvent::isAutoRepeat

    This property holds whether this event comes from an auto-repeating key.
*/

/*!
    \qmlproperty quint32 QtQuick::KeyEvent::nativeScanCode

    This property contains the native scan code of the key that was pressed. It is
    passed through from QKeyEvent unchanged.

    \sa QKeyEvent::nativeScanCode()
*/

/*!
    \qmlproperty int QtQuick::KeyEvent::count

    This property holds the number of keys involved in this event. If \l KeyEvent::text
    is not empty, this is simply the length of the string.
*/

/*!
    \qmlproperty bool QtQuick::KeyEvent::accepted

    Setting \a accepted to true prevents the key event from being
    propagated to the item's parent.

    Generally, if the item acts on the key event then it should be accepted
    so that ancestor items do not also respond to the same event.
*/

/*!
    \qmlproperty int QtQuick::KeyEvent::modifiers

    This property holds the keyboard modifier flags that existed immediately
    before the event occurred.

    It contains a bitwise combination of:
    \list
    \li \l {Qt::NoModifier} {Qt.NoModifier} - No modifier key is pressed.
    \li \l {Qt::ShiftModifier} {Qt.ShiftModifier} - A Shift key on the keyboard is pressed.
    \li \l {Qt::ControlModifier} {Qt.ControlModifier} - A Ctrl key on the keyboard is pressed.
    \li \l {Qt::AltModifier} {Qt.AltModifier} - An Alt key on the keyboard is pressed.
    \li \l {Qt::MetaModifier} {Qt.MetaModifier} - A Meta key on the keyboard is pressed.
    \li \l {Qt::KeypadModifier} {Qt.KeypadModifier} - A keypad button is pressed.
    \li \l {Qt::GroupSwitchModifier} {Qt.GroupSwitchModifier} - X11 only. A Mode_switch key on the keyboard is pressed.
    \endlist

    For example, to react to a Shift key + Enter key combination:
    \qml
    Item {
        focus: true
        Keys.onPressed: {
            if ((event.key == Qt.Key_Enter) && (event.modifiers & Qt.ShiftModifier))
                doSomething();
        }
    }
    \endqml
*/

/*!
    \qmlmethod bool QtQuick::KeyEvent::matches(StandardKey key)
    \since 5.2

    Returns \c true if the key event matches the given standard \a key; otherwise returns \c false.

    \qml
    Item {
        focus: true
        Keys.onPressed: {
            if (event.matches(StandardKey.Undo))
                myModel.undo();
            else if (event.matches(StandardKey.Redo))
                myModel.redo();
        }
    }
    \endqml

    \sa QKeySequence::StandardKey
*/

/*!
    \qmltype MouseEvent
    \instantiates QQuickMouseEvent
    \inqmlmodule QtQuick
    \ingroup qtquick-input-events

    \brief Provides information about a mouse event.

    The position of the mouse can be found via the \l {Item::x} {x} and \l {Item::y} {y} properties.
    The button that caused the event is available via the \l button property.

    \sa MouseArea
*/

/*!
    \internal
    \class QQuickMouseEvent
*/

/*!
    \qmlproperty real QtQuick::MouseEvent::x
    \qmlproperty real QtQuick::MouseEvent::y

    These properties hold the coordinates of the position supplied by the mouse event.
*/


/*!
    \qmlproperty bool QtQuick::MouseEvent::accepted

    Setting \a accepted to true prevents the mouse event from being
    propagated to items below this item.

    Generally, if the item acts on the mouse event then it should be accepted
    so that items lower in the stacking order do not also respond to the same event.
*/

/*!
    \qmlproperty enumeration QtQuick::MouseEvent::button

    This property holds the button that caused the event.  It can be one of:
    \list
    \li \l {Qt::LeftButton} {Qt.LeftButton}
    \li \l {Qt::RightButton} {Qt.RightButton}
    \li \l {Qt::MiddleButton} {Qt.MiddleButton}
    \endlist
*/

/*!
    \qmlproperty bool QtQuick::MouseEvent::wasHeld

    This property is true if the mouse button has been held pressed longer
    than the threshold (800ms).
*/

/*!
    \qmlproperty int QtQuick::MouseEvent::buttons

    This property holds the mouse buttons pressed when the event was generated.
    For mouse move events, this is all buttons that are pressed down. For mouse
    press and double click events this includes the button that caused the event.
    For mouse release events this excludes the button that caused the event.

    It contains a bitwise combination of:
    \list
    \li \l {Qt::LeftButton} {Qt.LeftButton}
    \li \l {Qt::RightButton} {Qt.RightButton}
    \li \l {Qt::MiddleButton} {Qt.MiddleButton}
    \endlist
*/

/*!
    \qmlproperty int QtQuick::MouseEvent::modifiers

    This property holds the keyboard modifier flags that existed immediately
    before the event occurred.

    It contains a bitwise combination of:
    \list
    \li \l {Qt::NoModifier} {Qt.NoModifier} - No modifier key is pressed.
    \li \l {Qt::ShiftModifier} {Qt.ShiftModifier} - A Shift key on the keyboard is pressed.
    \li \l {Qt::ControlModifier} {Qt.ControlModifier} - A Ctrl key on the keyboard is pressed.
    \li \l {Qt::AltModifier} {Qt.AltModifier} - An Alt key on the keyboard is pressed.
    \li \l {Qt::MetaModifier} {Qt.MetaModifier} - A Meta key on the keyboard is pressed.
    \li \l {Qt::KeypadModifier} {Qt.KeypadModifier} - A keypad button is pressed.
    \endlist

    For example, to react to a Shift key + Left mouse button click:
    \qml
    MouseArea {
        onClicked: {
            if ((mouse.button == Qt.LeftButton) && (mouse.modifiers & Qt.ShiftModifier))
                doSomething();
        }
    }
    \endqml
*/

/*!
    \qmlproperty int QtQuick::MouseEvent::source
    \since 5.7

    This property holds the source of the mouse event.

    The mouse event source can be used to distinguish between genuine and
    artificial mouse events. When using other pointing devices such as
    touchscreens and graphics tablets, if the application does not make use of
    the actual touch or tablet events, mouse events may be synthesized by the
    operating system or by Qt itself.

    The value can be one of:

    \list
    \li \l{Qt::MouseEventNotSynthesized} {Qt.MouseEventNotSynthesized}
    - The most common value. On platforms where such information is
    available, this value indicates that the event represents a genuine
    mouse event from the system.

    \li \l{Qt::MouseEventSynthesizedBySystem} {Qt.MouseEventSynthesizedBySystem} - Indicates that the mouse event was
    synthesized from a touch or tablet event by the platform.

    \li \l{Qt::MouseEventSynthesizedByQt} {Qt.MouseEventSynthesizedByQt}
    - Indicates that the mouse event was synthesized from an unhandled
    touch or tablet event by Qt.

    \li \l{Qt::MouseEventSynthesizedByApplication} {Qt.MouseEventSynthesizedByApplication}
    - Indicates that the mouse event was synthesized by the application.
    This allows distinguishing application-generated mouse events from
    the ones that are coming from the system or are synthesized by Qt.
    \endlist

    For example, to react only to events which come from an actual mouse:
    \qml
    MouseArea {
        onPressed: if (mouse.source !== Qt.MouseEventNotSynthesized) {
            mouse.accepted = false
        }

        onClicked: doSomething()
    }
    \endqml

    If the handler for the press event rejects the event, it will be propagated
    further, and then another Item underneath can handle synthesized events
    from touchscreens. For example, if a Flickable is used underneath (and the
    MouseArea is not a child of the Flickable), it can be useful for the
    MouseArea to handle genuine mouse events in one way, while allowing touch
    events to fall through to the Flickable underneath, so that the ability to
    flick on a touchscreen is retained. In that case the ability to drag the
    Flickable via mouse would be lost, but it does not prevent Flickable from
    receiving mouse wheel events.
*/

/*!
    \qmlproperty int QtQuick::MouseEvent::flags
    \since 5.11

    This property holds the flags that provide additional information about the
    mouse event.

    \list
    \li \l {Qt::MouseEventCreatedDoubleClick} {Qt.MouseEventCreatedDoubleClick}
    - Indicates that Qt has created a double click event from this event.
    This flag is set in the event originating from a button press, and not
    in the resulting double click event.
    \endlist
*/

/*!
    \qmltype WheelEvent
    \instantiates QQuickWheelEvent
    \inqmlmodule QtQuick
    \ingroup qtquick-input-events
    \brief Provides information about a mouse wheel event.

    The position of the mouse can be found via the
    \l {Item::x} {x} and \l {Item::y} {y} properties.

    \sa MouseArea
*/

/*!
    \internal
    \class QQuickWheelEvent
*/

/*!
    \qmlproperty real QtQuick::WheelEvent::x
    \qmlproperty real QtQuick::WheelEvent::y

    These properties hold the coordinates of the position supplied by the wheel event.
*/

/*!
    \qmlproperty bool QtQuick::WheelEvent::accepted

    Setting \a accepted to true prevents the wheel event from being
    propagated to items below this item.

    Generally, if the item acts on the wheel event then it should be accepted
    so that items lower in the stacking order do not also respond to the same event.
*/

/*!
    \qmlproperty int QtQuick::WheelEvent::buttons

    This property holds the mouse buttons pressed when the wheel event was generated.

    It contains a bitwise combination of:
    \list
    \li \l {Qt::LeftButton} {Qt.LeftButton}
    \li \l {Qt::RightButton} {Qt.RightButton}
    \li \l {Qt::MiddleButton} {Qt.MiddleButton}
    \endlist
*/

/*!
    \qmlproperty point QtQuick::WheelEvent::angleDelta

    This property holds the distance that the wheel is rotated in wheel degrees.
    The x and y cordinate of this property holds the delta in horizontal and
    vertical orientation.

    A positive value indicates that the wheel was rotated up/right;
    a negative value indicates that the wheel was rotated down/left.

    Most mouse types work in steps of 15 degrees, in which case the delta value is a
    multiple of 120; i.e., 120 units * 1/8 = 15 degrees.
*/

/*!
    \qmlproperty point QtQuick::WheelEvent::pixelDelta

    This property holds the delta in screen pixels and is available in platforms that
    have high-resolution trackpads, such as \macos.
    The x and y cordinate of this property holds the delta in horizontal and
    vertical orientation. The value should be used directly to scroll content on screen.

    For platforms without high-resolution trackpad support, pixelDelta will always be (0,0),
    and angleDelta should be used instead.
*/

/*!
    \qmlproperty int QtQuick::WheelEvent::modifiers

    This property holds the keyboard modifier flags that existed immediately
    before the event occurred.

    It contains a bitwise combination of:
    \list
    \li \l {Qt::NoModifier} {Qt.NoModifier} - No modifier key is pressed.
    \li \l {Qt::ShiftModifier} {Qt.ShiftModifier} - A Shift key on the keyboard is pressed.
    \li \l {Qt::ControlModifier} {Qt.ControlModifier} - A Ctrl key on the keyboard is pressed.
    \li \l {Qt::AltModifier} {Qt.AltModifier} - An Alt key on the keyboard is pressed.
    \li \l {Qt::MetaModifier} {Qt.MetaModifier} - A Meta key on the keyboard is pressed.
    \li \l {Qt::KeypadModifier} {Qt.KeypadModifier} - A keypad button is pressed.
    \endlist

    For example, to react to a Control key pressed during the wheel event:
    \qml
    MouseArea {
        onWheel: {
            if (wheel.modifiers & Qt.ControlModifier) {
                adjustZoom(wheel.angleDelta.y / 120);
            }
        }
    }
    \endqml
*/

/*!
    \qmlproperty bool QtQuick::WheelEvent::inverted

    Returns whether the delta values delivered with the event are inverted.

    Normally, a vertical wheel will produce a WheelEvent with positive delta
    values if the top of the wheel is rotating away from the hand operating it.
    Similarly, a horizontal wheel movement will produce a QWheelEvent with
    positive delta values if the top of the wheel is moved to the left.

    However, on some platforms this is configurable, so that the same
    operations described above will produce negative delta values (but with the
    same magnitude). For instance, in a QML component (such as a tumbler or a
    slider) where it is appropriate to synchronize the movement or rotation of
    an item with the direction of the wheel, regardless of the system settings,
    the wheel event handler can use the inverted property to decide whether to
    negate the angleDelta or pixelDelta values.

    \note Many platforms provide no such information. On such platforms
    \l inverted always returns false.
*/

/*!
    \qmltype PointerDevice
    \instantiates QQuickPointerDevice
    \inqmlmodule QtQuick
    \ingroup qtquick-input-events

    \brief Provides information about a pointing device.

    A pointing device can be a mouse, a touchscreen, or a stylus on a graphics
    tablet.

    \sa PointerEvent, PointerHandler
*/

/*!
    \readonly
    \qmlproperty enumeration QtQuick::PointerDevice::type

    This property holds the type of the pointing device.

    Valid values are:

    \value DeviceType.UnknownDevice
        the device cannot be identified
    \value DeviceType.Mouse
        a mouse
    \value DeviceType.TouchScreen
        a touchscreen providing absolute coordinates
    \value DeviceType.TouchPad
        a trackpad or touchpad providing relative coordinates
    \value DeviceType.Stylus
        a pen-like device
    \value DeviceType.Airbrush
        a stylus with a thumbwheel to adjust
        \l {QTabletEvent::tangentialPressure}{tangentialPressure}
    \value DeviceType.Puck
        a device that is similar to a flat mouse with a
        transparent circle with cross-hairs
        (same as \l {QTabletEvent::Puck} {Puck})
    \value DeviceType.AllDevices
        any of the above; used as a default value for construction

    \sa QTouchDevice::DeviceType
*/

/*!
    \readonly
    \qmlproperty enumeration QtQuick::PointerDevice::pointerType

    This property holds a value indicating what is interacting with
    the device. Think of the device as having a planar 2D surface, and
    the value of this property as identifying what interacts with the
    device.

    There is some redundancy between this property and \l {PointerDevice::type}.
    If a tocuchscreen is used, then the device is TouchScreen and
    pointerType is Finger (always).

    Valid values are:

    \value PointerDevice.GenericPointer
        a mouse or something acting like a mouse (the core pointer on X11)
    \value PointerDevice.Finger
        the user's finger
    \value PointerDevice.Pen
        the drawing end of a stylus
    \value PointerDevice.Eraser
        the other end of the stylus (if it has a virtual eraser on the other end)
    \value PointerDevice.Cursor
        a cursor in the pre-computer sense of the word
    \value PointerDevice.AllPointerTypes
        any of the above (used as a default value in constructors)
*/


/*!
    \readonly
    \qmlproperty enumeration QtQuick::PointerDevice::capabilities

    This property holds a bitwise combination of the capabilities of the
    pointing device. It tells you under which conditions events are sent,
    and which properties of PointerEvent are expected to be valid.

    Valid values are:

    \value CapabilityFlag.Position
        the \l {QtQuick::EventPoint::position}{position} and
        \l {QtQuick::EventPoint::scenePosition}{scenePosition} properties
    \value CapabilityFlag.Area
        the \l {QtQuick::EventTouchPoint::ellipseDiameters}{ellipseDiameters} property
    \value CapabilityFlag.Pressure
        the \l {QtQuick::EventTouchPoint::pressure}{pressure} property
    \value CapabilityFlag.Velocity
        the \l {QtQuick::EventPoint::velocity}{velocity} property
    \value CapabilityFlag.Scroll
        a \l {QtQuick::PointerDevice::type}{Mouse} has a wheel, or the
        operating system recognizes scroll gestures on a
        \l {QtQuick::PointerDevice::type}{TouchPad}
    \value CapabilityFlag.Hover
        events are sent even when no button is pressed, or the finger or stylus
        is not in contact with the surface
    \value CapabilityFlag.Rotation
        the \l {QtQuick::EventTouchPoint::rotation}{rotation} property
    \value CapabilityFlag.XTilt
        horizontal angle between a stylus and the axis perpendicular to the surface
    \value CapabilityFlag.YTilt
        vertical angle between a stylus and the axis perpendicular to the surface

    \sa QTouchDevice::capabilities
*/

typedef QHash<const QTouchDevice *, QQuickPointerDevice *> PointerDeviceForTouchDeviceHash;
Q_GLOBAL_STATIC(PointerDeviceForTouchDeviceHash, g_touchDevices)

struct ConstructableQQuickPointerDevice : public QQuickPointerDevice
{
    ConstructableQQuickPointerDevice(DeviceType devType, PointerType pType, Capabilities caps,
                              int maxPoints, int buttonCount, const QString &name,
                              qint64 uniqueId = 0)
        : QQuickPointerDevice(devType, pType, caps, maxPoints, buttonCount, name, uniqueId) {}

};
Q_GLOBAL_STATIC_WITH_ARGS(ConstructableQQuickPointerDevice, g_genericMouseDevice,
                            (QQuickPointerDevice::Mouse,
                             QQuickPointerDevice::GenericPointer,
                             QQuickPointerDevice::Position | QQuickPointerDevice::Scroll | QQuickPointerDevice::Hover,
                             1, 3, QLatin1String("core pointer"), 0))

typedef QHash<qint64, QQuickPointerDevice *> PointerDeviceForDeviceIdHash;
Q_GLOBAL_STATIC(PointerDeviceForDeviceIdHash, g_tabletDevices)

// debugging helpers
static const char *pointStateString(const QQuickEventPoint *point)
{
    static const QMetaEnum stateMetaEnum = point->metaObject()->enumerator(point->metaObject()->indexOfEnumerator("State"));
    return stateMetaEnum.valueToKey(point->state());
}

static const QString pointDeviceName(const QQuickEventPoint *point)
{
    auto device = static_cast<const QQuickPointerEvent *>(point->parent())->device();
    QString deviceName = (device ? device->name() : QLatin1String("null device"));
    deviceName.resize(16, ' '); // shorten, and align in case of sequential output
    return deviceName;
}


QQuickPointerDevice *QQuickPointerDevice::touchDevice(const QTouchDevice *d)
{
    if (g_touchDevices->contains(d))
        return g_touchDevices->value(d);

    QQuickPointerDevice::DeviceType type = QQuickPointerDevice::TouchScreen;
    QString name;
    int maximumTouchPoints = 10;
    QQuickPointerDevice::Capabilities caps = QQuickPointerDevice::Capabilities(QTouchDevice::Position);
    if (d) {
        caps = static_cast<QQuickPointerDevice::Capabilities>(static_cast<int>(d->capabilities()) & 0xFF);
        if (d->type() == QTouchDevice::TouchPad) {
            type = QQuickPointerDevice::TouchPad;
            caps |= QQuickPointerDevice::Scroll;
        }
        name = d->name();
        maximumTouchPoints = d->maximumTouchPoints();
    } else {
        qWarning() << "QQuickWindowPrivate::touchDevice: creating touch device from nullptr device in QTouchEvent";
    }

    QQuickPointerDevice *dev = new QQuickPointerDevice(type, QQuickPointerDevice::Finger,
        caps, maximumTouchPoints, 0, name, 0);
    g_touchDevices->insert(d, dev);
    return dev;
}

const QTouchDevice *QQuickPointerDevice::qTouchDevice() const
{
    return g_touchDevices->key(const_cast<QQuickPointerDevice *>(this));
}

QList<QQuickPointerDevice*> QQuickPointerDevice::touchDevices()
{
    return g_touchDevices->values();
}

QQuickPointerDevice *QQuickPointerDevice::genericMouseDevice()
{
    return g_genericMouseDevice;
}

QQuickPointerDevice *QQuickPointerDevice::tabletDevice(qint64 id)
{
    auto it = g_tabletDevices->find(id);
    if (it != g_tabletDevices->end())
        return it.value();

    // ### Figure out how to populate the tablet devices
    return nullptr;
}

/*!
    \qmltype EventPoint
    \qmlabstract
    \instantiates QQuickEventPoint
    \inqmlmodule QtQuick
    \ingroup qtquick-input-events
    \brief Provides information about an individual point within a PointerEvent.

    A PointerEvent contains an EventPoint for each point of contact: one corresponding
    to the mouse cursor, or one for each finger touching a touchscreen.

    \sa PointerEvent, PointerHandler
*/

/*!
    \readonly
    \qmlproperty point QtQuick::EventPoint::position

    This property holds the coordinates of the position supplied by the event,
    relative to the upper-left corner of the Item which has the PointerHandler.
    If a contact patch is available from the pointing device, this point
    represents its centroid.
*/

/*!
    \readonly
    \qmlproperty point QtQuick::EventPoint::scenePosition

    This property holds the coordinates of the position supplied by the event,
    relative to the scene. If a contact patch is available from the
    \l {QtQuick::PointerEvent::device} {device}, this point represents its centroid.
*/

/*!
    \readonly
    \qmlproperty point QtQuick::EventPoint::scenePressPosition

    This property holds the scene-relative position at which the press event
    (on a touch device) or most recent change in QQuickPointerEvent::buttons()
    (on a mouse or tablet stylus) occurred.
*/

/*!
    \readonly
    \qmlproperty point QtQuick::EventPoint::sceneGrabPosition

    This property holds the scene-relative position at which the EventPoint was
    located when setGrabber() was called most recently.
*/

/*!
    \readonly
    \qmlproperty vector2d QtQuick::EventPoint::velocity

    This property holds average recent velocity: how fast and in which
    direction the event point has been moving recently.
*/

/*!
    \readonly
    \qmlproperty int QtQuick::EventPoint::state

    This property tells what the user is currently doing at this point.

    It can be one of:
    \value Pressed
        The user's finger is now pressing a touchscreen, button or stylus
        which was not pressed already
    \value Updated
        The touchpoint or position is being moved, with no change in pressed state
    \value Stationary
        The touchpoint or position is not being moved, and there is also
        no change in pressed state
    \value Released
        The user's finger has now released a touch point, button or stylus
        which was pressed
*/

/*!
    \readonly
    \qmlproperty int QtQuick::EventPoint::pointId

    This property holds the ID of the event, if any.

    Touchpoints have automatically-incrementing IDs: each time the user
    presses a finger against the touchscreen, it will be a larger number.
    In other cases, it will be -1.

    \sa {QtQuick::EventTouchPoint::uniqueId}{uniqueId}
*/

/*!
    \readonly
    \qmlproperty bool QtQuick::EventPoint::accepted

    Setting \a accepted to true prevents the event from being propagated to
    Items below the PointerHandler's Item.

    Generally, if the handler acts on the mouse event, then it should be
    accepted so that items lower in the stacking order do not also respond to
    the same event.
*/

/*!
    \readonly
    \qmlproperty real QtQuick::EventPoint::timeHeld

    This property holds the amount of time in seconds that the button or touchpoint has
    been held.  It can be used to detect a "long press", and can drive an
    animation to show progress toward activation of the "long press" action.
*/

void QQuickEventPoint::reset(Qt::TouchPointState state, const QPointF &scenePos, int pointId, ulong timestamp, const QVector2D &velocity)
{
    m_scenePos = scenePos;
    m_pointId = pointId;
    m_accept = false;
    m_state = static_cast<QQuickEventPoint::State>(state);
    m_timestamp = timestamp;
    if (state == Qt::TouchPointPressed) {
        m_pressTimestamp = timestamp;
        m_scenePressPos = scenePos;
    }
    m_velocity = (Q_LIKELY(velocity.isNull()) ? estimatedVelocity() : velocity);
}

void QQuickEventPoint::localizePosition(QQuickItem *target)
{
    if (target)
        m_pos = target->mapFromScene(scenePosition());
    else
        m_pos = QPointF();
}

/*!
    If this point has an exclusive grabber, returns a pointer to it; else
    returns null, if there is no grabber.  The grabber could be either
    an Item or a PointerHandler.
*/
QObject *QQuickEventPoint::exclusiveGrabber() const
{
    return m_exclusiveGrabber.data();
}

/*!
    Set the given Item or PointerHandler as the exclusive grabber of this point.
    If there was already an exclusive grab, it will be canceled.  If there
    were passive grabbers, they will continue to lurk, but the exclusive grab
    is a behavioral override of the passive grab as long as it remains.
    If you already know whether the grabber is to be an Item or a PointerHandler,
    you should instead call setGrabberItem() or setGrabberPointerHandler(),
    because it is slightly more efficient.
*/
void QQuickEventPoint::setExclusiveGrabber(QObject *grabber)
{
    if (QQuickPointerHandler *phGrabber = qmlobject_cast<QQuickPointerHandler *>(grabber))
        setGrabberPointerHandler(phGrabber, true);
    else
        setGrabberItem(static_cast<QQuickItem *>(grabber));
}

/*!
    If the exclusive grabber of this point is an Item, returns a
    pointer to that Item; else returns null, if there is no grabber or if
    the grabber is a PointerHandler.
*/
QQuickItem *QQuickEventPoint::grabberItem() const
{
    return (m_grabberIsHandler ? nullptr : static_cast<QQuickItem *>(m_exclusiveGrabber.data()));
}

/*!
    Set the given Item \a grabber as the exclusive grabber of this point.
    If there was already an exclusive grab, it will be canceled.  If there
    were passive grabbers, they will continue to lurk, but the exclusive grab
    is a behavioral override of the passive grab as long as it remains.
*/
void QQuickEventPoint::setGrabberItem(QQuickItem *grabber)
{
    if (grabber != m_exclusiveGrabber.data()) {
        QQuickPointerHandler *oldGrabberHandler = grabberPointerHandler();
        if (oldGrabberHandler && !oldGrabberHandler->approveGrabTransition(this, grabber))
            return;
        if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) {
            qCDebug(lcPointerGrab) << pointDeviceName(this) << "point" << hex << m_pointId << pointStateString(this) << "@" << m_scenePos
                                   << ": grab" << m_exclusiveGrabber << "->" << grabber;
        }
        QQuickItem *oldGrabberItem = grabberItem();
        m_exclusiveGrabber = QPointer<QObject>(grabber);
        m_grabberIsHandler = false;
        m_sceneGrabPos = m_scenePos;
        if (oldGrabberHandler) {
            oldGrabberHandler->onGrabChanged(oldGrabberHandler, (grabber ? CancelGrabExclusive : UngrabExclusive), this);
        } else if (oldGrabberItem && oldGrabberItem != grabber && grabber && grabber->window()) {
            QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(grabber->window());
            windowPriv->sendUngrabEvent(oldGrabberItem, windowPriv->isDeliveringTouchAsMouse());
        }
        if (grabber) {
            for (QPointer<QQuickPointerHandler> passiveGrabber : m_passiveGrabbers)
                if (passiveGrabber)
                    passiveGrabber->onGrabChanged(passiveGrabber, OverrideGrabPassive, this);
        }
    }
}

/*!
    If the exclusive grabber of this point is a PointerHandler, returns a
    pointer to that handler; else returns null, if there is no grabber or if
    the grabber is an Item.
*/
QQuickPointerHandler *QQuickEventPoint::grabberPointerHandler() const
{
    return (m_grabberIsHandler ? static_cast<QQuickPointerHandler *>(m_exclusiveGrabber.data()) : nullptr);
}

/*!
    Set the given PointerHandler \a grabber as grabber of this point. If \a
    exclusive is true, it will override any other grabs; if false, \a grabber
    will be added to the list of passive grabbers of this point.
*/
void QQuickEventPoint::setGrabberPointerHandler(QQuickPointerHandler *grabber, bool exclusive)
{
    if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) {
        if (exclusive) {
            if (m_exclusiveGrabber != grabber)
                qCDebug(lcPointerGrab) << pointDeviceName(this) << "point" << hex << m_pointId << pointStateString(this)
                                       << ": grab (exclusive)" << m_exclusiveGrabber << "->" << grabber;
        } else {
            qCDebug(lcPointerGrab) << pointDeviceName(this) << "point" << hex << m_pointId << pointStateString(this)
                                   << ": grab (passive)" << grabber;
        }
    }
    if (exclusive) {
        if (grabber != m_exclusiveGrabber.data()) {
            QQuickPointerHandler *oldGrabberHandler = grabberPointerHandler();
            QQuickItem *oldGrabberItem = grabberItem();
            m_exclusiveGrabber = QPointer<QObject>(grabber);
            m_grabberIsHandler = true;
            m_sceneGrabPos = m_scenePos;
            if (grabber) {
                grabber->onGrabChanged(grabber, GrabExclusive, this);
                for (QPointer<QQuickPointerHandler> passiveGrabber : m_passiveGrabbers) {
                    if (!passiveGrabber.isNull() && passiveGrabber != grabber)
                        passiveGrabber->onGrabChanged(grabber, OverrideGrabPassive, this);
                }
            }
            if (oldGrabberHandler) {
                oldGrabberHandler->onGrabChanged(oldGrabberHandler, (grabber ? CancelGrabExclusive : UngrabExclusive), this);
            } else if (oldGrabberItem) {
                if (pointerEvent()->asPointerTouchEvent())
                    oldGrabberItem->touchUngrabEvent();
                else if (pointerEvent()->asPointerMouseEvent())
                    oldGrabberItem->mouseUngrabEvent();
            }
            // touchUngrabEvent() can result in the grabber being set to null (MPTA does that, for example).
            // So set it again to ensure that final state is what we want.
            m_exclusiveGrabber = QPointer<QObject>(grabber);
            m_grabberIsHandler = true;
            m_sceneGrabPos = m_scenePos;
        }
    } else {
        if (!grabber) {
            qDebug() << "can't set passive grabber to null";
            return;
        }
        auto ptr = QPointer<QQuickPointerHandler>(grabber);
        if (!m_passiveGrabbers.contains(ptr)) {
            m_passiveGrabbers.append(ptr);
            grabber->onGrabChanged(grabber, GrabPassive, this);
        }
    }
}

/*!
    If this point has an existing exclusive grabber (Item or PointerHandler),
    inform the grabber that its grab is canceled, and remove it as grabber.
    This normally happens when the grab is stolen by another Item.
*/
void QQuickEventPoint::cancelExclusiveGrab()
{
    if (m_exclusiveGrabber.isNull())
        qWarning("cancelGrab: no grabber");
    else
        cancelExclusiveGrabImpl();
}

void QQuickEventPoint::cancelExclusiveGrabImpl(QTouchEvent *cancelEvent)
{
    if (m_exclusiveGrabber.isNull())
        return;
    if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) {
        qCDebug(lcPointerGrab) << pointDeviceName(this) << "point" << hex << m_pointId << pointStateString(this)
                               << ": grab (exclusive)" << m_exclusiveGrabber << "-> nullptr";
    }
    if (auto handler = grabberPointerHandler()) {
        handler->onGrabChanged(handler, CancelGrabExclusive, this);
    } else if (auto item = grabberItem()) {
        if (cancelEvent)
            QCoreApplication::sendEvent(item, cancelEvent);
        else
            item->touchUngrabEvent();
    }
    m_exclusiveGrabber.clear();
}

/*!
    If this point has the given \a handler as a passive grabber,
    inform the grabber that its grab is canceled, and remove it as grabber.
    This normally happens when another Item or PointerHandler does an exclusive grab.
*/
void QQuickEventPoint::cancelPassiveGrab(QQuickPointerHandler *handler)
{
    if (removePassiveGrabber(handler)) {
        if (Q_UNLIKELY(lcPointerGrab().isDebugEnabled())) {
            qCDebug(lcPointerGrab) << pointDeviceName(this) << "point" << hex << m_pointId << pointStateString(this)
                                   << ": grab (passive)" << handler << "removed";
        }
        handler->onGrabChanged(handler, CancelGrabPassive, this);
    }
}

/*!
    If this point has the given \a handler as a passive grabber, remove it as grabber.
    Returns true if it was removed, false if it wasn't a grabber.
*/
bool QQuickEventPoint::removePassiveGrabber(QQuickPointerHandler *handler)
{
    return m_passiveGrabbers.removeOne(handler);
}

/*!
    If the given \a handler is grabbing this point passively, exclusively
    or both, cancel the grab and remove it as grabber.
    This normally happens when the handler decides that the behavior of this
    point can no longer satisfy the handler's behavioral constraints within
    the remainder of the gesture which the user is performing: for example
    the handler tries to detect a tap but a drag is occurring instead, or
    it tries to detect a drag in one direction but the drag is going in
    another direction.  In such cases the handler no longer needs or wants
    to be informed of any further movements of this point.
*/
void QQuickEventPoint::cancelAllGrabs(QQuickPointerHandler *handler)
{
    if (m_exclusiveGrabber == handler) {
        handler->onGrabChanged(handler, CancelGrabExclusive, this);
        m_exclusiveGrabber.clear();
    }
    cancelPassiveGrab(handler);
}

/*!
    Sets this point as \a accepted (true) or rejected (false).

    During delivery of the current event to the Items in the scene, each Item
    or Pointer Handler should accept the points for which it is taking
    responsibility. As soon as all points within the event are accepted, event
    propagation stops. However accepting the point does not imply any kind of
    grab, passive or exclusive.

    \sa setExclusiveGrabber, QQuickPointerHandler::setPassiveGrab, QQuickPointerHandler::setExclusiveGrab
*/
void QQuickEventPoint::setAccepted(bool accepted)
{
    if (m_accept != accepted) {
        qCDebug(lcPointerEvents) << this << m_accept << "->" << accepted;
        m_accept = accepted;
    }
}


/*!
    \qmltype EventTouchPoint
    \qmlabstract
    \instantiates QQuickEventTouchPoint
    \inqmlmodule QtQuick
    \ingroup qtquick-input-events
    \brief Provides information about an individual touch point within a PointerEvent.

    \sa PointerEvent, PointerHandler
*/

/*!
    \readonly
    \qmlproperty QPointerUniqueId QtQuick::EventTouchPoint::uniqueId

    This property holds the unique ID of the fiducial or stylus in use, if any.

    On touchscreens that can track physical objects (such as knobs or game
    pieces) in addition to fingers, each object usually has a unique ID.
    Likewise, each stylus that can be used with a graphics tablet usually has a
    unique serial number. Qt so far only supports numeric IDs. You can get the
    actual number as uniqueId.numeric, but that is a device-specific detail.
    In the future, there may be support for non-numeric IDs, so you should
    not assume that the number is meaningful.

    If you need to identify specific objects, your application should provide
    UI for registering objects and mapping them to functionality: allow the
    user to select a meaning, virtual tool, or action, prompt the user to bring
    the object into proximity, and store a mapping from uniqueId to its
    purpose, for example in \l Settings.
*/

/*!
    \readonly
    \qmlproperty qreal QtQuick::EventTouchPoint::rotation

    This property holds the rotation angle of the stylus on a graphics tablet
    or the contact patch of a touchpoint on a touchscreen.

    It is valid only with certain tablet stylus devices and touchscreens that
    can measure the rotation angle. Otherwise, it will be zero.
*/

/*!
    \readonly
    \qmlproperty qreal QtQuick::EventTouchPoint::pressure

    This property tells how hard the user is pressing the stylus on a graphics
    tablet or the finger against a touchscreen, in the range from \c 0 (no
    measurable pressure) to \c 1.0 (maximum pressure which the device can
    measure).

    It is valid only with certain tablets and touchscreens that can measure
    pressure. Otherwise, it will be \c 1.0 when pressed.
*/

/*!
    \readonly
    \qmlproperty size QtQuick::EventTouchPoint::ellipseDiameters

    This property holds the diameters of the contact patch, if the event
    comes from a touchpoint and the \l {QtQuick::PointerEvent::device} {device}
    provides this information.

    A touchpoint is modeled as an elliptical area where the finger is
    pressed against the touchscreen. (In fact, it could also be
    modeled as a bitmap; but in that case we expect an elliptical
    bounding estimate to be fitted to the contact patch before the
    event is sent.) The harder the user presses, the larger the
    contact patch; so, these diameters provide an alternate way of
    detecting pressure, in case the device does not include a separate
    pressure sensor. The ellipse is centered on
    \l {QtQuick::EventPoint::scenePosition} {scenePosition}
    (\l {QtQuick::EventPoint::position} {position} in the PointerHandler's
    Item's local coordinates).  The \l rotation property provides the
    rotation of the ellipse, if known.  It is expected that if the
    \l rotation is zero, the verticalDiameter of the ellipse is the
    larger one (the major axis), because of the usual hand position,
    reaching upward or outward across the surface.

    If the contact patch is unknown, or the \l {QtQuick::PointerEvent::device} {device}
    is not a touchscreen, these values will be zero.
*/

QQuickEventTouchPoint::QQuickEventTouchPoint(QQuickPointerTouchEvent *parent)
    : QQuickEventPoint(parent), m_rotation(0), m_pressure(0)
{}

void QQuickEventTouchPoint::reset(const QTouchEvent::TouchPoint &tp, ulong timestamp)
{
    QQuickEventPoint::reset(tp.state(), tp.scenePos(), tp.id(), timestamp, tp.velocity());
    m_exclusiveGrabber.clear();
    m_passiveGrabbers.clear();
    m_rotation = tp.rotation();
    m_pressure = tp.pressure();
    m_ellipseDiameters = tp.ellipseDiameters();
    m_uniqueId = tp.uniqueId();
}

struct PointVelocityData {
    QVector2D velocity;
    QPointF pos;
    ulong timestamp = 0;
};

typedef QMap<quint64, PointVelocityData> PointDataForPointIdMap;
Q_GLOBAL_STATIC(PointDataForPointIdMap, g_previousPointData)
static const int PointVelocityAgeLimit = 500; // milliseconds

/*!
    \internal
    Estimates the velocity based on a weighted average of all previous velocities.
    The older the velocity is, the less significant it becomes for the estimate.
*/
QVector2D QQuickEventPoint::estimatedVelocity() const
{
    auto prevPointIt = g_previousPointData->find(m_pointId);
    auto end = g_previousPointData->end();
    if (prevPointIt == end) {
        // cleanup events older than PointVelocityAgeLimit
        for (auto it = g_previousPointData->begin(); it != end; ) {
            if (m_timestamp - it->timestamp > PointVelocityAgeLimit)
                it = g_previousPointData->erase(it);
            else
                ++it;
        }
        prevPointIt = g_previousPointData->insert(m_pointId, PointVelocityData());
    }

    auto &prevPoint = prevPointIt.value();
    const ulong timeElapsed = m_timestamp - prevPoint.timestamp;
    if (timeElapsed == 0)   // in case we call estimatedVelocity() twice on the same QQuickEventPoint
        return m_velocity;

    QVector2D newVelocity;
    if (prevPoint.timestamp != 0)
        newVelocity = QVector2D(m_scenePos - prevPoint.pos) / timeElapsed;

    // VERY simple kalman filter: does a weighted average
    // where the older velocities get less and less significant
    static const float KalmanGain = 0.7f;
    QVector2D filteredVelocity = newVelocity * KalmanGain + m_velocity * (1.0f - KalmanGain);

    prevPoint.velocity = filteredVelocity;
    prevPoint.pos = m_scenePos;
    prevPoint.timestamp = m_timestamp;
    return filteredVelocity;
}

/*!
    \qmltype PointerEvent
    \instantiates QQuickPointerEvent
    \inqmlmodule QtQuick
    \ingroup qtquick-input-events

    \brief Provides information about an event from a pointing device.

    A PointerEvent is an event describing contact or movement across a surface,
    provided by a mouse, a touchpoint (single finger on a touchscreen), or a
    stylus on a graphics tablet. The \l {QtQuick::PointerEvent::device} {device}
    property provides more information about where the event came from.

    \sa PointerHandler

    \image touchpoint-metrics.png
*/

/*!
    \internal
    \class QQuickPointerEvent

    QQuickPointerEvent is used as a long-lived object to store data related to
    an event from a pointing device, such as a mouse, touch or tablet event,
    during event delivery. It also provides properties which may be used later
    to expose the event to QML, the same as is done with QQuickMouseEvent,
    QQuickTouchPoint, QQuickKeyEvent, etc. Since only one event can be
    delivered at a time, this class is effectively a singleton.  We don't worry
    about the QObject overhead because the instances are long-lived: we don't
    dynamically create and destroy objects of this type for each event.
*/

/*!
    \readonly
    \qmlproperty enumeration QtQuick::PointerEvent::button

    This property holds the \l {Qt::MouseButton}{button} that caused the event,
    if any. If the \l {QtQuick::PointerEvent::device} {device} does not have
    buttons, or the event is a hover event, it will be \c Qt.NoButton.
*/

/*!
    \readonly
    \qmlproperty int QtQuick::PointerEvent::buttons

    This property holds the combination of mouse or stylus
    \l {Qt::MouseButton}{buttons} pressed when the event was generated. For move
    events, this is all buttons that are pressed down.  For press events, this
    includes the button that caused the event, as well as any others that were
    already held.  For release events, this excludes the button that caused the
    event.
*/

/*!
    \readonly
    \qmlproperty int QtQuick::PointerEvent::modifiers

    This property holds the \l {Qt::KeyboardModifier}{keyboard modifier} flags
    that existed immediately before the event occurred.

    It contains a bitwise combination of the following flags:
    \value Qt.NoModifier
        No modifier key is pressed.
    \value Qt.ShiftModifier
        A Shift key on the keyboard is pressed.
    \value Qt.ControlModifier
        A Ctrl key on the keyboard is pressed.
    \value Qt.AltModifier
        An Alt key on the keyboard is pressed.
    \value Qt.MetaModifier
        A Meta key on the keyboard is pressed.
    \value Qt.KeypadModifier
        A keypad button is pressed.

    For example, to react to a Shift key + Left mouse button click:
    \qml
    Item {
        TapHandler {
            onTapped: {
                if ((event.button == Qt.LeftButton) && (event.modifiers & Qt.ShiftModifier))
                    doSomething();
            }
        }
    }
    \endqml
*/

/*!
    \readonly
    \qmlproperty PointerDevice QtQuick::PointerEvent::device

    This property holds the device that generated the event.
*/

QQuickPointerEvent::~QQuickPointerEvent()
{}

QQuickPointerEvent *QQuickPointerMouseEvent::reset(QEvent *event)
{
    auto ev = static_cast<QMouseEvent*>(event);
    m_event = ev;
    if (!event)
        return this;

    m_device = QQuickPointerDevice::genericMouseDevice();
    m_device->eventDeliveryTargets().clear();
    m_button = ev->button();
    m_pressedButtons = ev->buttons();
    Qt::TouchPointState state = Qt::TouchPointStationary;
    switch (ev->type()) {
    case QEvent::MouseButtonPress:
        m_point->clearPassiveGrabbers();
        Q_FALLTHROUGH();
    case QEvent::MouseButtonDblClick:
        state = Qt::TouchPointPressed;
        break;
    case QEvent::MouseButtonRelease:
        state = Qt::TouchPointReleased;
        break;
    case QEvent::MouseMove:
        state = Qt::TouchPointMoved;
        break;
    default:
        break;
    }
    m_point->reset(state, ev->windowPos(), quint64(1) << 24, ev->timestamp());  // mouse has device ID 1
    return this;
}

void QQuickSinglePointEvent::localize(QQuickItem *target)
{
    m_point->localizePosition(target);
}

QQuickPointerEvent *QQuickPointerTouchEvent::reset(QEvent *event)
{
    auto ev = static_cast<QTouchEvent*>(event);
    m_event = ev;
    if (!event)
        return this;

    m_device = QQuickPointerDevice::touchDevice(ev->device());
    m_device->eventDeliveryTargets().clear();
    m_button = Qt::NoButton;
    m_pressedButtons = Qt::NoButton;

    const QList<QTouchEvent::TouchPoint> &tps = ev->touchPoints();
    int newPointCount = tps.count();
    m_touchPoints.reserve(newPointCount);

    for (int i = m_touchPoints.size(); i < newPointCount; ++i)
        m_touchPoints.insert(i, new QQuickEventTouchPoint(this));

    // Make sure the grabbers and on-pressed values are right from one event to the next
    struct ToPreserve {
        int pointId; // just for double-checking
        ulong pressTimestamp;
        QPointF scenePressPos;
        QPointF sceneGrabPos;
        QObject * grabber;
        QVector <QPointer <QQuickPointerHandler> > passiveGrabbers;

        ToPreserve() : pointId(0), pressTimestamp(0), grabber(nullptr) {}
    };
    QVector<ToPreserve> preserves(newPointCount); // jar of pickled touchpoints, in order of points in the _new_ event

    // Copy stuff we need to preserve, because the order of points might have changed in the event.
    // The ID is all that we can rely on (release might remove the first point etc).
    for (int i = 0; i < newPointCount; ++i) {
        int pid = tps.at(i).id();
        if (auto point = pointById(pid)) {
            preserves[i].pointId = pid;
            preserves[i].pressTimestamp = point->m_pressTimestamp;
            preserves[i].scenePressPos = point->scenePressPosition();
            preserves[i].sceneGrabPos = point->sceneGrabPosition();
            preserves[i].grabber = point->exclusiveGrabber();
            preserves[i].passiveGrabbers = point->passiveGrabbers();
        }
    }

    for (int i = 0; i < newPointCount; ++i) {
        auto point = m_touchPoints.at(i);
        point->reset(tps.at(i), ev->timestamp());
        const auto &preserved = preserves.at(i);
        if (point->state() == QQuickEventPoint::Pressed) {
            if (preserved.grabber)
                qWarning() << "TouchPointPressed without previous release event" << point;
            point->setGrabberItem(nullptr);
            point->clearPassiveGrabbers();
        } else {
            // Restore the grabbers without notifying (don't call onGrabChanged)
            Q_ASSERT(preserved.pointId == 0 || preserved.pointId == point->pointId());
            point->m_pressTimestamp = preserved.pressTimestamp;
            point->m_scenePressPos = preserved.scenePressPos;
            point->m_sceneGrabPos = preserved.sceneGrabPos;
            point->m_exclusiveGrabber = preserved.grabber;
            point->m_grabberIsHandler = (qmlobject_cast<QQuickPointerHandler *>(point->m_exclusiveGrabber) != nullptr);
            point->m_passiveGrabbers = preserved.passiveGrabbers;
        }
    }
    m_pointCount = newPointCount;
    return this;
}

void QQuickPointerTouchEvent::localize(QQuickItem *target)
{
    for (auto point : qAsConst(m_touchPoints))
        point->localizePosition(target);
}

#if QT_CONFIG(gestures)
QQuickPointerEvent *QQuickPointerNativeGestureEvent::reset(QEvent *event)
{
    auto ev = static_cast<QNativeGestureEvent*>(event);
    m_event = ev;
    if (!event)
        return this;

    m_device = QQuickPointerDevice::touchDevice(ev->device());
    m_device->eventDeliveryTargets().clear();
    Qt::TouchPointState state = Qt::TouchPointMoved;
    switch (type()) {
    case Qt::BeginNativeGesture:
        state = Qt::TouchPointPressed;
        break;
    case Qt::EndNativeGesture:
        state = Qt::TouchPointReleased;
        break;
    default:
        break;
    }
    quint64 deviceId = QTouchDevicePrivate::get(const_cast<QTouchDevice *>(ev->device()))->id; // a bit roundabout since QTouchDevice::mTouchDeviceId is protected
    m_point->reset(state, ev->windowPos(), deviceId << 24, ev->timestamp());
    return this;
}
#endif // QT_CONFIG(gestures)

QQuickEventPoint *QQuickSinglePointEvent::point(int i) const
{
    if (i == 0)
        return m_point;
    return nullptr;
}


/*!
    \qmltype PointerScrollEvent
    \instantiates QQuickPointerScrollEvent
    \inqmlmodule QtQuick
    \ingroup qtquick-input-events
    \brief Provides information about a scrolling event, such as from a mouse wheel.

    \sa WheelHandler
*/

/*!
    \internal
    \class QQuickPointerScrollEvent
*/

/*!
    \readonly
    \qmlproperty PointerDevice QtQuick::PointerScrollEvent::device

    This property holds the device that generated the event.
*/

/*!
    \qmlproperty int QtQuick::PointerScrollEvent::buttons

    This property holds the mouse buttons pressed when the wheel event was generated.

    It contains a bitwise combination of:
    \list
    \li \l {Qt::LeftButton} {Qt.LeftButton}
    \li \l {Qt::RightButton} {Qt.RightButton}
    \li \l {Qt::MiddleButton} {Qt.MiddleButton}
    \endlist
*/

/*!
    \readonly
    \qmlproperty int QtQuick::PointerScrollEvent::modifiers

    This property holds the \l {Qt::KeyboardModifier}{keyboard modifier} keys
    that were pressed immediately before the event occurred.

    It contains a bitwise combination of the following flags:
    \value Qt.NoModifier
        No modifier key is pressed.
    \value Qt.ShiftModifier
        A Shift key on the keyboard is pressed.
    \value Qt.ControlModifier
        A Ctrl key on the keyboard is pressed.
    \value Qt.AltModifier
        An Alt key on the keyboard is pressed.
    \value Qt.MetaModifier
        A Meta key on the keyboard is pressed.
    \value Qt.KeypadModifier
        A keypad button is pressed.

    For example, to react to a Shift key + Left mouse button click:
    \qml
    Item {
        TapHandler {
            onTapped: {
                if ((event.button == Qt.LeftButton) && (event.modifiers & Qt.ShiftModifier))
                    doSomething();
            }
        }
    }
    \endqml
*/

/*!
    \qmlproperty point QtQuick::PointerScrollEvent::angleDelta

    This property holds the distance that the wheel is rotated in wheel degrees.
    The x and y cordinate of this property holds the delta in horizontal and
    vertical orientation.

    A positive value indicates that the wheel was rotated up/right;
    a negative value indicates that the wheel was rotated down/left.

    Most mouse types work in steps of 15 degrees, in which case the delta value is a
    multiple of 120; i.e., 120 units * 1/8 = 15 degrees.
*/

/*!
    \qmlproperty point QtQuick::PointerScrollEvent::pixelDelta

    This property holds the delta in screen pixels and is available in platforms that
    have high-resolution trackpads, such as \macos.
    The x and y coordinates of this property hold the delta in horizontal and
    vertical orientation. The value should be used directly to scroll content on screen.

    For platforms without high-resolution touchpad support, pixelDelta will
    always be (0,0), and angleDelta should be used instead.
*/

/*!
    \qmlproperty bool QtQuick::PointerScrollEvent::hasAngleDelta

    Returns whether the \l angleDelta property has a non-null value.
*/

/*!
    \qmlproperty bool QtQuick::PointerScrollEvent::hasPixelDelta

    Returns whether the \l pixelDelta property has a non-null value.
*/

/*!
    \qmlproperty bool QtQuick::PointerScrollEvent::inverted

    Returns whether the delta values delivered with the event are inverted.

    Normally, a vertical wheel will produce a PointerScrollEvent with positive delta
    values if the top of the wheel is rotating away from the hand operating it.
    Similarly, a horizontal wheel movement will produce a PointerScrollEvent with
    positive delta values if the top of the wheel is moved to the left.

    However, on some platforms this is configurable, so that the same
    operations described above will produce negative delta values (but with the
    same magnitude). In a QML component (such as a tumbler or a slider) where
    it is appropriate to synchronize the movement or rotation of an item with
    the direction of the wheel, regardless of the system settings, the wheel
    event handler can use the inverted property to decide whether to negate the
    \l angleDelta or \l pixelDelta values.

    \note Many platforms provide no such information. On such platforms,
    \c inverted always returns false.
*/
QQuickPointerEvent *QQuickPointerScrollEvent::reset(QEvent *event)
{
    m_event = static_cast<QInputEvent*>(event);
    if (!event)
        return this;
#if QT_CONFIG(wheelevent)
    if (event->type() == QEvent::Wheel) {
        auto ev = static_cast<QWheelEvent*>(event);
        m_device = QQuickPointerDevice::genericMouseDevice();
        m_device->eventDeliveryTargets().clear();
        // m_button = Qt::NoButton;
        m_pressedButtons = ev->buttons();
        m_angleDelta = QVector2D(ev->angleDelta());
        m_pixelDelta = QVector2D(ev->pixelDelta());
        m_phase = ev->phase();
        m_synthSource = ev->source();
        m_inverted = ev->inverted();

        m_point->reset(Qt::TouchPointMoved, ev->position(), quint64(1) << 24, ev->timestamp()); // mouse has device ID 1
    }
#endif
    // TODO else if (event->type() == QEvent::Scroll) ...
    return this;
}

void QQuickPointerScrollEvent::localize(QQuickItem *target)
{
    m_point->localizePosition(target);
}

QQuickEventPoint *QQuickPointerTouchEvent::point(int i) const
{
    if (i >= 0 && i < m_pointCount)
        return m_touchPoints.at(i);
    return nullptr;
}

QQuickEventPoint::QQuickEventPoint(QQuickPointerEvent *parent)
  : QObject(parent), m_pointId(0), m_exclusiveGrabber(nullptr), m_timestamp(0), m_pressTimestamp(0),
    m_state(QQuickEventPoint::Released), m_accept(false), m_grabberIsHandler(false)
{
    Q_UNUSED(m_reserved);
}

QQuickPointerEvent *QQuickEventPoint::pointerEvent() const
{
    return static_cast<QQuickPointerEvent *>(parent());
}

bool QQuickSinglePointEvent::allPointsAccepted() const
{
    return m_point->isAccepted();
}

bool QQuickSinglePointEvent::allUpdatedPointsAccepted() const
{
    return m_point->state() == QQuickEventPoint::Pressed || m_point->isAccepted();
}

bool QQuickSinglePointEvent::allPointsGrabbed() const
{
    return m_point->exclusiveGrabber() != nullptr;
}

QMouseEvent *QQuickPointerMouseEvent::asMouseEvent(const QPointF &localPos) const
{
    auto event = static_cast<QMouseEvent *>(m_event);
    event->setLocalPos(localPos);
    return event;
}

/*!
    Returns the exclusive grabber of this event, if any, in a vector.
*/
QVector<QObject *> QQuickSinglePointEvent::exclusiveGrabbers() const
{
    QVector<QObject *> result;
    if (QObject *grabber = m_point->exclusiveGrabber())
        result << grabber;
    return result;
}

/*!
    Remove all passive and exclusive grabbers of this event, without notifying.
*/
void QQuickSinglePointEvent::clearGrabbers() const
{
    m_point->setGrabberItem(nullptr);
    m_point->clearPassiveGrabbers();
}

/*!
    Returns whether the given \a handler is the exclusive grabber of this event.
*/
bool QQuickSinglePointEvent::hasExclusiveGrabber(const QQuickPointerHandler *handler) const
{
    return handler && (m_point->exclusiveGrabber() == handler);
}

bool QQuickPointerMouseEvent::isPressEvent() const
{
    auto me = static_cast<QMouseEvent*>(m_event);
    return ((me->type() == QEvent::MouseButtonPress || me->type() == QEvent::MouseButtonDblClick) &&
            (me->buttons() & me->button()) == me->buttons());
}

bool QQuickPointerMouseEvent::isDoubleClickEvent() const
{
    auto me = static_cast<QMouseEvent*>(m_event);
    return (me->type() == QEvent::MouseButtonDblClick);
}

bool QQuickPointerMouseEvent::isUpdateEvent() const
{
    auto me = static_cast<QMouseEvent*>(m_event);
    return me->type() == QEvent::MouseMove;
}

bool QQuickPointerMouseEvent::isReleaseEvent() const
{
    auto me = static_cast<QMouseEvent*>(m_event);
    return me && me->type() == QEvent::MouseButtonRelease;
}

bool QQuickPointerTouchEvent::allPointsAccepted() const
{
    for (int i = 0; i < m_pointCount; ++i) {
        if (!m_touchPoints.at(i)->isAccepted())
            return false;
    }
    return true;
}

bool QQuickPointerTouchEvent::allUpdatedPointsAccepted() const
{
    for (int i = 0; i < m_pointCount; ++i) {
        auto point = m_touchPoints.at(i);
        if (point->state() != QQuickEventPoint::Pressed && !point->isAccepted())
            return false;
    }
    return true;
}

bool QQuickPointerTouchEvent::allPointsGrabbed() const
{
    for (int i = 0; i < m_pointCount; ++i) {
        if (!m_touchPoints.at(i)->exclusiveGrabber())
            return false;
    }
    return true;
}

/*!
    Returns the exclusive grabbers of all points in this event, if any, in a vector.
*/
QVector<QObject *> QQuickPointerTouchEvent::exclusiveGrabbers() const
{
    QVector<QObject *> result;
    for (int i = 0; i < m_pointCount; ++i) {
        if (QObject *grabber = m_touchPoints.at(i)->exclusiveGrabber()) {
            if (!result.contains(grabber))
                result << grabber;
        }
    }
    return result;
}

/*!
    Remove all passive and exclusive grabbers of all touchpoints in this event,
    without notifying.
*/
void QQuickPointerTouchEvent::clearGrabbers() const
{
    for (auto point: m_touchPoints) {
        point->setGrabberItem(nullptr);
        point->clearPassiveGrabbers();
    }
}

Qt::TouchPointStates QQuickPointerTouchEvent::touchPointStates() const
{
    return m_event
        ? static_cast<QTouchEvent*>(m_event)->touchPointStates()
        : Qt::TouchPointStates();
}

/*!
    Returns whether the given \a handler is the exclusive grabber of any
    touchpoint within this event.
*/
bool QQuickPointerTouchEvent::hasExclusiveGrabber(const QQuickPointerHandler *handler) const
{
    for (auto point: m_touchPoints)
        if (point->exclusiveGrabber() == handler)
            return true;
    return false;
}

bool QQuickPointerTouchEvent::isPressEvent() const
{
    return touchPointStates() & Qt::TouchPointPressed;
}

bool QQuickPointerTouchEvent::isUpdateEvent() const
{
    return touchPointStates() & (Qt::TouchPointMoved | Qt::TouchPointStationary);
}

bool QQuickPointerTouchEvent::isReleaseEvent() const
{
    return touchPointStates() & Qt::TouchPointReleased;
}

QVector<QPointF> QQuickPointerEvent::unacceptedPressedPointScenePositions() const
{
    QVector<QPointF> points;
    for (int i = 0; i < pointCount(); ++i) {
        if (!point(i)->isAccepted() && point(i)->state() == QQuickEventPoint::Pressed)
            points << point(i)->scenePosition();
    }
    return points;
}

/*!
    \internal
    Populate the reusable synth-mouse event from one touchpoint.
    It's required that isTouchEvent() be true when this is called.
    If the touchpoint cannot be found, this returns nullptr.
    Ownership of the event is NOT transferred to the caller.
*/
QMouseEvent *QQuickPointerTouchEvent::syntheticMouseEvent(int pointID, QQuickItem *relativeTo) const
{
    const QTouchEvent::TouchPoint *p = touchPointById(pointID);
    if (!p)
        return nullptr;
    QEvent::Type type;
    Qt::MouseButton buttons = Qt::LeftButton;
    switch (p->state()) {
    case Qt::TouchPointPressed:
        type = QEvent::MouseButtonPress;
        break;
    case Qt::TouchPointMoved:
    case Qt::TouchPointStationary:
        type = QEvent::MouseMove;
        break;
    case Qt::TouchPointReleased:
        type = QEvent::MouseButtonRelease;
        buttons = Qt::NoButton;
        break;
    default:
        Q_ASSERT(false);
        return nullptr;
    }
    m_synthMouseEvent = QMouseEvent(type, relativeTo->mapFromScene(p->scenePos()),
        p->scenePos(), p->screenPos(), Qt::LeftButton, buttons, m_event->modifiers());
    m_synthMouseEvent.setAccepted(true);
    m_synthMouseEvent.setTimestamp(m_event->timestamp());
    // In the future we will try to always have valid velocity in every QQuickEventPoint.
    // QQuickFlickablePrivate::handleMouseMoveEvent() checks for QTouchDevice::Velocity
    // and if it is set, then it does not need to do its own velocity calculations.
    // That's probably the only usecase for this, so far.  Some day Flickable should handle
    // pointer events, and then passing touchpoint velocity via QMouseEvent will be obsolete.
    // Conveniently (by design), QTouchDevice::Velocity == QQuickPointerDevice.Velocity
    // so that we don't need to convert m_device->capabilities().
    if (m_device)
        QGuiApplicationPrivate::setMouseEventCapsAndVelocity(&m_synthMouseEvent, m_device->capabilities(), p->velocity());
    QGuiApplicationPrivate::setMouseEventSource(&m_synthMouseEvent, Qt::MouseEventSynthesizedByQt);
    return &m_synthMouseEvent;
}

#if QT_CONFIG(gestures)
bool QQuickPointerNativeGestureEvent::isPressEvent() const
{
    return type() == Qt::BeginNativeGesture;
}

bool QQuickPointerNativeGestureEvent::isUpdateEvent() const
{
    switch (type()) {
    case Qt::BeginNativeGesture:
    case Qt::EndNativeGesture:
        return false;
    default:
        return true;
    }
}

bool QQuickPointerNativeGestureEvent::isReleaseEvent() const
{
    return type() == Qt::EndNativeGesture;
}

Qt::NativeGestureType QQuickPointerNativeGestureEvent::type() const
{
    return static_cast<QNativeGestureEvent *>(m_event)->gestureType();
}

qreal QQuickPointerNativeGestureEvent::value() const
{
    return static_cast<QNativeGestureEvent *>(m_event)->value();
}
#endif // QT_CONFIG(gestures)

/*!
    Returns whether the scroll event has Qt::ScrollBegin phase. On touchpads
    which provide phase information, this is true when the fingers are placed
    on the touchpad and scrolling begins. On other devices where this
    information is not available, it remains false.
*/
bool QQuickPointerScrollEvent::isPressEvent() const
{
    return phase() == Qt::ScrollBegin;
}

/*!
    Returns true when the scroll event has Qt::ScrollUpdate phase, or when the
    phase is unknown. Some multi-touch-capable touchpads and trackpads provide
    phase information; whereas ordinary mouse wheels and other types of
    trackpads do not, and in such cases this is always true.
*/
bool QQuickPointerScrollEvent::isUpdateEvent() const
{
    return phase() == Qt::ScrollUpdate || phase() == Qt::NoScrollPhase;
}

/*!
    Returns whether the scroll event has Qt::ScrollBegin phase. On touchpads
    which provide phase information, this is true when the fingers are lifted
    from the touchpad. On other devices where this information is not
    available, it remains false.
*/
bool QQuickPointerScrollEvent::isReleaseEvent() const
{
    return phase() == Qt::ScrollEnd;
}

/*!
    \internal
    Returns a pointer to the QQuickEventPoint which has the \a pointId as
    \l {QQuickEventPoint::pointId}{pointId}.
    Returns nullptr if there is no point with that ID.

    \fn QQuickPointerEvent::pointById(int pointId) const
*/
QQuickEventPoint *QQuickSinglePointEvent::pointById(int pointId) const
{
    if (m_point && pointId == m_point->pointId())
        return m_point;
    return nullptr;
}

QQuickEventPoint *QQuickPointerTouchEvent::pointById(int pointId) const
{
    auto it = std::find_if(m_touchPoints.constBegin(), m_touchPoints.constEnd(),
        [pointId](const QQuickEventTouchPoint *tp) { return tp->pointId() == pointId; } );
    if (it != m_touchPoints.constEnd())
        return *it;
    return nullptr;
}

/*!
    \internal
    Returns a pointer to the original TouchPoint which has the same
    \l {QTouchEvent::TouchPoint::id}{id} as \a pointId, if the original event is a
    QTouchEvent, and if that point is found. Otherwise, returns nullptr.
*/
const QTouchEvent::TouchPoint *QQuickPointerTouchEvent::touchPointById(int pointId) const
{
    const QTouchEvent *ev = asTouchEvent();
    if (!ev)
        return nullptr;
    const QList<QTouchEvent::TouchPoint> &tps = ev->touchPoints();
    auto it = std::find_if(tps.constBegin(), tps.constEnd(),
        [pointId](QTouchEvent::TouchPoint const& tp) { return tp.id() == pointId; } );
    // return the pointer to the actual TP in QTouchEvent::_touchPoints
    return (it == tps.constEnd() ? nullptr : it.operator->());
}

/*!
    \internal
    Make a new QTouchEvent, giving it a subset of the original touch points.

    Returns a nullptr if all points are stationary, or there are no points inside the item,
    or none of the points were pressed inside and the item was not grabbing any of them
    and isFiltering is false.  When isFiltering is true, it is assumed that the item
    cares about all points which are inside its bounds, because most filtering items
    need to monitor eventpoint movements until a drag threshold is exceeded or the
    requirements for a gesture to be recognized are met in some other way.
*/
QTouchEvent *QQuickPointerTouchEvent::touchEventForItem(QQuickItem *item, bool isFiltering) const
{
    QList<QTouchEvent::TouchPoint> touchPoints;
    Qt::TouchPointStates eventStates;
    // TODO maybe add QQuickItem::mapVector2DFromScene(QVector2D) to avoid needing QQuickItemPrivate here
    // Or else just document that velocity is always scene-relative and is not scaled and rotated with the item
    // but that would require changing tst_qquickwindow::touchEvent_velocity(): it expects transformed velocity

    bool anyPressOrReleaseInside = false;
    bool anyStationaryWithModifiedPropertyInside = false;
    bool anyGrabber = false;
    QMatrix4x4 transformMatrix(QQuickItemPrivate::get(item)->windowToItemTransform());
    for (int i = 0; i < m_pointCount; ++i) {
        auto p = m_touchPoints.at(i);
        if (p->isAccepted())
            continue;
        // include points where item is the grabber
        bool isGrabber = p->exclusiveGrabber() == item;
        if (isGrabber)
            anyGrabber = true;
        // include points inside the bounds if no other item is the grabber or if the item is filtering
        bool isInside = item->contains(item->mapFromScene(p->scenePosition()));
        bool hasAnotherGrabber = p->exclusiveGrabber() && p->exclusiveGrabber() != item;

        // filtering: (childMouseEventFilter) include points that are grabbed by children of the target item
        bool grabberIsChild = false;
        auto parent = p->grabberItem();
        while (isFiltering && parent) {
            if (parent == item) {
                grabberIsChild = true;
                break;
            }
            parent = parent->parentItem();
        }

        bool filterRelevant = isFiltering && grabberIsChild;
        if (!(isGrabber || (isInside && (!hasAnotherGrabber || isFiltering)) || filterRelevant))
            continue;
        if ((p->state() == QQuickEventPoint::Pressed || p->state() == QQuickEventPoint::Released) && isInside)
            anyPressOrReleaseInside = true;
        const QTouchEvent::TouchPoint *tp = touchPointById(p->pointId());
        if (tp) {
            if (isInside && tp->d->stationaryWithModifiedProperty)
                anyStationaryWithModifiedPropertyInside = true;
            eventStates |= tp->state();
            QTouchEvent::TouchPoint tpCopy = *tp;
            tpCopy.setPos(item->mapFromScene(tpCopy.scenePos()));
            tpCopy.setLastPos(item->mapFromScene(tpCopy.lastScenePos()));
            tpCopy.setStartPos(item->mapFromScene(tpCopy.startScenePos()));
            tpCopy.setRect(item->mapRectFromScene(tpCopy.sceneRect()));
            tpCopy.setVelocity(transformMatrix.mapVector(tpCopy.velocity()).toVector2D());
            touchPoints << tpCopy;
        }
    }

    // Now touchPoints will have only points which are inside the item.
    // But if none of them were just pressed inside, and the item has no other reason to care, ignore them anyway.
    if ((eventStates == Qt::TouchPointStationary && !anyStationaryWithModifiedPropertyInside) ||
            touchPoints.isEmpty() || (!anyPressOrReleaseInside && !anyGrabber && !isFiltering))
        return nullptr;

    // if all points have the same state, set the event type accordingly
    const QTouchEvent &event = *asTouchEvent();
    QEvent::Type eventType = event.type();
    switch (eventStates) {
    case Qt::TouchPointPressed:
        eventType = QEvent::TouchBegin;
        break;
    case Qt::TouchPointReleased:
        eventType = QEvent::TouchEnd;
        break;
    default:
        eventType = QEvent::TouchUpdate;
        break;
    }

    QTouchEvent *touchEvent = new QTouchEvent(eventType);
    touchEvent->setWindow(event.window());
    touchEvent->setTarget(item);
    touchEvent->setDevice(event.device());
    touchEvent->setModifiers(event.modifiers());
    touchEvent->setTouchPoints(touchPoints);
    touchEvent->setTouchPointStates(eventStates);
    touchEvent->setTimestamp(event.timestamp());
    touchEvent->accept();
    return touchEvent;
}

QTouchEvent *QQuickPointerTouchEvent::asTouchEvent() const
{
    return static_cast<QTouchEvent *>(m_event);
}

#ifndef QT_NO_DEBUG_STREAM

Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QQuickPointerDevice *dev)
{
    QDebugStateSaver saver(dbg);
    dbg.nospace();
    if (!dev) {
        dbg << "QQuickPointerDevice(0)";
        return dbg;
    }
    dbg << "QQuickPointerDevice("<< dev->name() << ' ';
    QtDebugUtils::formatQEnum(dbg, dev->type());
    dbg << ' ';
    QtDebugUtils::formatQEnum(dbg, dev->pointerType());
    dbg << " caps:";
    QtDebugUtils::formatQFlags(dbg, dev->capabilities());
    if (dev->type() == QQuickPointerDevice::TouchScreen ||
            dev->type() == QQuickPointerDevice::TouchPad)
        dbg << " maxTouchPoints:" << dev->maximumTouchPoints();
    else
        dbg << " buttonCount:" << dev->buttonCount();
    dbg << ')';
    return dbg;
}

Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QQuickPointerEvent *event)
{
    QDebugStateSaver saver(dbg);
    dbg.nospace();
    if (!event) {
        dbg << "QQuickPointerEvent(0)";
        return dbg;
    }
    dbg << "QQuickPointerEvent(";
    dbg << event->timestamp();
    dbg << " dev:";
    QtDebugUtils::formatQEnum(dbg, event->device()->type());
    if (event->buttons() != Qt::NoButton) {
        dbg << " buttons:";
        QtDebugUtils::formatQEnum(dbg, event->buttons());
    }
    dbg << " [";
    int c = event->pointCount();
    for (int i = 0; i < c; ++i)
        dbg << event->point(i) << ' ';
    dbg << "])";
    return dbg;
}

Q_QUICK_PRIVATE_EXPORT QDebug operator<<(QDebug dbg, const QQuickEventPoint *event)
{
    QDebugStateSaver saver(dbg);
    dbg.nospace();
    if (!event) {
        dbg << "QQuickEventPoint(0)";
        return dbg;
    }
    dbg << "QQuickEventPoint(accepted:" << event->isAccepted()
        << " state:";
    QtDebugUtils::formatQEnum(dbg, event->state());
    dbg << " scenePos:" << event->scenePosition() << " id:" << hex << event->pointId() << dec
        << " timeHeld:" << event->timeHeld() << ')';
    return dbg;
}

#endif

QT_END_NAMESPACE
