/****************************************************************************
**
** Copyright (C) 2018 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 "qquickpointerhandler_p.h"
#include "qquickpointerhandler_p_p.h"
#include <QtQuick/private/qquickitem_p.h>

QT_BEGIN_NAMESPACE

Q_LOGGING_CATEGORY(lcPointerHandlerDispatch, "qt.quick.handler.dispatch")
Q_LOGGING_CATEGORY(lcPointerHandlerGrab, "qt.quick.handler.grab")
Q_LOGGING_CATEGORY(lcPointerHandlerActive, "qt.quick.handler.active")

/*!
    \qmltype PointerHandler
    \qmlabstract
    \since 5.10
    \preliminary
    \instantiates QQuickPointerHandler
    \inqmlmodule QtQuick
    \brief Abstract handler for pointer events.

    PointerHandler is the base class Input Handler (not registered as a QML type) for
    events from any kind of pointing device (touch, mouse or graphics tablet).
*/

QQuickPointerHandler::QQuickPointerHandler(QQuickItem *parent)
  : QObject(*(new QQuickPointerHandlerPrivate), parent)
{
}

QQuickPointerHandler::QQuickPointerHandler(QQuickPointerHandlerPrivate &dd, QQuickItem *parent)
  : QObject(dd, parent)
{
}

QQuickPointerHandler::~QQuickPointerHandler()
{
    QQuickItem *parItem = parentItem();
    if (parItem) {
        QQuickItemPrivate *p = QQuickItemPrivate::get(parItem);
        p->extra.value().pointerHandlers.removeOne(this);
    }
}

/*!
     \qmlproperty real PointerHandler::margin

     The margin beyond the bounds of the \l {PointerHandler::parent}{parent}
     item within which an event point can activate this handler. For example, on
     a PinchHandler where the \l {PointerHandler::target}{target} is also the
     \c parent, it's useful to set this to a distance at least half the width
     of a typical user's finger, so that if the \c parent has been scaled down
     to a very small size, the pinch gesture is still possible.  Or, if a
     TapHandler-based button is placed near the screen edge, it can be used
     to comply with Fitts's Law: react to mouse clicks at the screen edge
     even though the button is visually spaced away from the edge by a few pixels.

     The default value is 0.

     \image pointerHandlerMargin.png
*/
qreal QQuickPointerHandler::margin() const
{
    Q_D(const QQuickPointerHandler);
    return d->m_margin;
}

void QQuickPointerHandler::setMargin(qreal pointDistanceThreshold)
{
    Q_D(QQuickPointerHandler);
    if (d->m_margin == pointDistanceThreshold)
        return;

    d->m_margin = pointDistanceThreshold;
    emit marginChanged();
}

/*!
    Notification that the grab has changed in some way which is relevant to this handler.
    The \a grabber (subject) will be the Input Handler whose state is changing,
    or null if the state change regards an Item.
    The \a transition (verb) tells what happened.
    The \a point (object) is the point that was grabbed or ungrabbed.
    EventPoint has the sole responsibility to call this function.
    The Input Handler must react in whatever way is appropriate, and must
    emit the relevant signals (for the benefit of QML code).
    A subclass is allowed to override this virtual function, but must always
    call its parent class's implementation in addition to (usually after)
    whatever custom behavior it implements.
*/
void QQuickPointerHandler::onGrabChanged(QQuickPointerHandler *grabber, QQuickEventPoint::GrabTransition transition, QQuickEventPoint *point)
{
    qCDebug(lcPointerHandlerGrab) << point << transition << grabber;
    Q_ASSERT(point);
    if (grabber == this) {
        bool wasCanceled = false;
        switch (transition) {
        case QQuickEventPoint::GrabPassive:
        case QQuickEventPoint::GrabExclusive:
            break;
        case QQuickEventPoint::CancelGrabPassive:
        case QQuickEventPoint::CancelGrabExclusive:
            wasCanceled = true; // the grab was stolen by something else
            Q_FALLTHROUGH();
        case QQuickEventPoint::UngrabPassive:
        case QQuickEventPoint::UngrabExclusive:
            setActive(false);
            point->setAccepted(false);
            if (auto par = parentItem()) {
                Q_D(const QQuickPointerHandler);
                par->setKeepMouseGrab(d->hadKeepMouseGrab);
                par->setKeepTouchGrab(d->hadKeepTouchGrab);
            }
            break;
        case QQuickEventPoint::OverrideGrabPassive:
            // Passive grab is still there, but we won't receive point updates right now.
            // No need to notify about this.
            return;
        }
        if (wasCanceled)
            emit canceled(point);
        emit grabChanged(transition, point);
    }
}

/*!
    Acquire or give up a passive grab of the given \a point, according to the \a grab state.

    Unlike the exclusive grab, multiple Input Handlers can have passive grabs
    simultaneously. This means that each of them will receive further events
    when the \a point moves, and when it is finally released. Typically an
    Input Handler should acquire a passive grab as soon as a point is pressed,
    if the handler's constraints do not clearly rule out any interest in that
    point. For example, DragHandler needs a passive grab in order to watch the
    movement of a point to see whether it will be dragged past the drag
    threshold. When a handler is actively manipulating its \l target (that is,
    when \l active is true), it may be able to do its work with only a passive
    grab, or it may acquire an exclusive grab if the gesture clearly must not
    be interpreted in another way by another handler.
*/
void QQuickPointerHandler::setPassiveGrab(QQuickEventPoint *point, bool grab)
{
    qCDebug(lcPointerHandlerGrab) << point << grab;
    if (grab) {
        point->setGrabberPointerHandler(this, false);
    } else {
        point->removePassiveGrabber(this);
    }
}

/*!
    Check whether it's OK to take an exclusive grab of the \a point.

    The default implementation will call approveGrabTransition() to check this
    handler's \l grabPermissions. If grabbing can be done only by taking over
    the exclusive grab from an Item, approveGrabTransition() checks the Item's
    \l keepMouseGrab or \l keepTouchGrab flags appropriately. If grabbing can
    be done only by taking over another handler's exclusive grab, canGrab()
    also calls approveGrabTransition() on the handler which is about to lose
    its grab. Either one can deny the takeover.
*/
bool QQuickPointerHandler::canGrab(QQuickEventPoint *point)
{
    QQuickPointerHandler *existingPhGrabber = point->grabberPointerHandler();
    return approveGrabTransition(point, this) &&
        (existingPhGrabber ? existingPhGrabber->approveGrabTransition(point, this) : true);
}

/*!
    Check this handler's rules to see if \l proposedGrabber will be allowed to take
    the exclusive grab.  This function may be called twice: once on the instance which
    will take the grab, and once on the instance which would thereby lose its grab,
    in case of a takeover scenario.
*/
bool QQuickPointerHandler::approveGrabTransition(QQuickEventPoint *point, QObject *proposedGrabber)
{
    Q_D(const QQuickPointerHandler);
    bool allowed = false;
    if (proposedGrabber == this) {
        QObject* existingGrabber = point->exclusiveGrabber();
        allowed = (existingGrabber == nullptr) || ((d->grabPermissions & CanTakeOverFromAnything) == CanTakeOverFromAnything);
        if (existingGrabber) {
            if (QQuickPointerHandler *existingPhGrabber = point->grabberPointerHandler()) {
                if (!allowed && (d->grabPermissions & CanTakeOverFromHandlersOfDifferentType) &&
                        existingPhGrabber->metaObject()->className() != metaObject()->className())
                    allowed = true;
                if (!allowed && (d->grabPermissions & CanTakeOverFromHandlersOfSameType) &&
                        existingPhGrabber->metaObject()->className() == metaObject()->className())
                    allowed = true;
            } else if ((d->grabPermissions & CanTakeOverFromItems)) {
                QQuickItem * existingItemGrabber = point->grabberItem();
                if (existingItemGrabber && !((existingItemGrabber->keepMouseGrab() && point->pointerEvent()->asPointerMouseEvent()) ||
                                             (existingItemGrabber->keepTouchGrab() && point->pointerEvent()->asPointerTouchEvent()))) {
                    allowed = true;
                    // If the handler wants to steal the exclusive grab from an Item, the Item can usually veto
                    // by having its keepMouseGrab flag set.  But an exception is if that Item is a parent that
                    // normally filters events (such as a Flickable): it needs to be possible for e.g. a
                    // DragHandler to operate on an Item inside a Flickable.  Flickable is aggressive about
                    // grabbing on press (for fear of missing updates), but DragHandler uses a passive grab
                    // at first and then expects to be able to steal the grab later on.  It cannot respect
                    // Flickable's wishes in that case, because then it would never have a chance.
                    if (existingItemGrabber->keepMouseGrab() &&
                            !(existingItemGrabber->filtersChildMouseEvents() && existingItemGrabber->isAncestorOf(parentItem()))) {
                        QQuickWindowPrivate *winPriv = QQuickWindowPrivate::get(parentItem()->window());
                        if (winPriv->isDeliveringTouchAsMouse() && point->pointId() == winPriv->touchMouseId) {
                            qCDebug(lcPointerHandlerGrab) << this << "wants to grab touchpoint" << point->pointId()
                                << "but declines to steal grab from touch-mouse grabber with keepMouseGrab=true" << existingItemGrabber;
                            allowed = false;
                        }
                    }
                }
            }
        }
    } else {
        // proposedGrabber is different: that means this instance will lose its grab
        if (proposedGrabber) {
            if ((d->grabPermissions & ApprovesTakeOverByAnything) == ApprovesTakeOverByAnything)
                allowed = true;
            if (!allowed && (d->grabPermissions & ApprovesTakeOverByHandlersOfDifferentType) &&
                    proposedGrabber->metaObject()->className() != metaObject()->className())
                allowed = true;
            if (!allowed && (d->grabPermissions & ApprovesTakeOverByHandlersOfSameType) &&
                    proposedGrabber->metaObject()->className() == metaObject()->className())
                allowed = true;
            if (!allowed && (d->grabPermissions & ApprovesTakeOverByItems) && proposedGrabber->inherits("QQuickItem"))
                allowed = true;
        } else {
            if (!allowed && (d->grabPermissions & ApprovesCancellation))
                allowed = true;
        }
    }
    qCDebug(lcPointerHandlerGrab) << "point" << hex << point->pointId() << "permission" <<
            QMetaEnum::fromType<GrabPermissions>().valueToKeys(grabPermissions()) <<
            ':' << this << (allowed ? "approved to" : "denied to") << proposedGrabber;
    return allowed;
}

/*!
    \qmlproperty flags QtQuick::PointerHandler::grabPermissions

    This property specifies the permissions when this handler's logic decides
    to take over the exclusive grab, or when it is asked to approve grab
    takeover or cancellation by another handler.

    \value PointerHandler.TakeOverForbidden
           This handler neither takes from nor gives grab permission to any type of Item or Handler.
    \value PointerHandler.CanTakeOverFromHandlersOfSameType
           This handler can take the exclusive grab from another handler of the same class.
    \value PointerHandler.CanTakeOverFromHandlersOfDifferentType
           This handler can take the exclusive grab from any kind of handler.
    \value PointerHandler.CanTakeOverFromAnything
           This handler can take the exclusive grab from any type of Item or Handler.
    \value PointerHandler.ApprovesTakeOverByHandlersOfSameType
           This handler gives permission for another handler of the same class to take the grab.
    \value PointerHandler.ApprovesTakeOverByHandlersOfDifferentType
           This handler gives permission for any kind of handler to take the grab.
    \value PointerHandler.ApprovesTakeOverByItems
           This handler gives permission for any kind of Item to take the grab.
    \value PointerHandler.ApprovesCancellation
           This handler will allow its grab to be set to null.
    \value PointerHandler.ApprovesTakeOverByAnything
           This handler gives permission for any any type of Item or Handler to take the grab.

    The default is
    \c {PointerHandler.CanTakeOverFromItems | PointerHandler.CanTakeOverFromHandlersOfDifferentType | PointerHandler.ApprovesTakeOverByAnything}
    which allows most takeover scenarios but avoids e.g. two PinchHandlers fighting
    over the same touchpoints.
*/
QQuickPointerHandler::GrabPermissions QQuickPointerHandler::grabPermissions() const
{
    Q_D(const QQuickPointerHandler);
    return static_cast<QQuickPointerHandler::GrabPermissions>(d->grabPermissions);
}

void QQuickPointerHandler::setGrabPermissions(GrabPermissions grabPermission)
{
    Q_D(QQuickPointerHandler);
    if (d->grabPermissions == grabPermission)
        return;

    d->grabPermissions = grabPermission;
    emit grabPermissionChanged();
}

void QQuickPointerHandler::classBegin()
{
}

void QQuickPointerHandler::componentComplete()
{
}

QQuickPointerEvent *QQuickPointerHandler::currentEvent()
{
    Q_D(const QQuickPointerHandler);
    return d->currentEvent;
}

/*!
    Acquire or give up the exclusive grab of the given \a point, according to
    the \a grab state, and subject to the rules: canGrab(), and the rule not to
    relinquish another handler's grab. Returns true if permission is granted,
    or if the exclusive grab has already been acquired or relinquished as
    specified. Returns false if permission is denied either by this handler or
    by the handler or item from which this handler would take over
*/
bool QQuickPointerHandler::setExclusiveGrab(QQuickEventPoint *point, bool grab)
{
    if ((grab && point->exclusiveGrabber() == this) || (!grab && point->exclusiveGrabber() != this))
        return true;
    // TODO m_hadKeepMouseGrab m_hadKeepTouchGrab
    bool allowed = true;
    if (grab) {
        allowed = canGrab(point);
    } else {
        QQuickPointerHandler *existingPhGrabber = point->grabberPointerHandler();
        // Ask before allowing one handler to cancel another's grab
        if (existingPhGrabber && existingPhGrabber != this && !existingPhGrabber->approveGrabTransition(point, nullptr))
            allowed = false;
    }
    qCDebug(lcPointerHandlerGrab) << point << (grab ? "grab" : "ungrab") << (allowed ? "allowed" : "forbidden") <<
        point->exclusiveGrabber() << "->" << (grab ? this : nullptr);
    if (allowed)
        point->setGrabberPointerHandler(grab ? this : nullptr, true);
    return allowed;
}

/*!
    Cancel any existing grab of the given \a point.
*/
void QQuickPointerHandler::cancelAllGrabs(QQuickEventPoint *point)
{
    qCDebug(lcPointerHandlerGrab) << point;
    point->cancelAllGrabs(this);
}

QPointF QQuickPointerHandler::eventPos(const QQuickEventPoint *point) const
{
    return (target() ? target()->mapFromScene(point->scenePosition()) : point->scenePosition());
}

bool QQuickPointerHandler::parentContains(const QQuickEventPoint *point) const
{
    if (!point)
        return false;
    if (QQuickItem *par = parentItem()) {
        if (par->window()) {
            QPoint screenPosition = par->window()->mapToGlobal(point->scenePosition().toPoint());
            if (!par->window()->geometry().contains(screenPosition))
                return false;
        }
        QPointF p = par->mapFromScene(point->scenePosition());
        qreal m = margin();
        if (m > 0)
            return p.x() >= -m && p.y() >= -m && p.x() <= par->width() + m && p.y() <= par->height() + m;
        return par->contains(p);
    }
    return false;
}

/*!
     \qmlproperty bool QtQuick::PointerHandler::enabled

     If a PointerHandler is disabled, it will reject all events
     and no signals will be emitted.
*/
bool QQuickPointerHandler::enabled() const
{
    Q_D(const QQuickPointerHandler);
    return d->enabled;
}

void QQuickPointerHandler::setEnabled(bool enabled)
{
    Q_D(QQuickPointerHandler);
    if (d->enabled == enabled)
        return;

    d->enabled = enabled;
    emit enabledChanged();
}

bool QQuickPointerHandler::active() const
{
    Q_D(const QQuickPointerHandler);
    return d->active;
}

/*!
    \qmlproperty Item QtQuick::PointerHandler::target

    The Item which this handler will manipulate.

    By default, it is the same as the \l [QML] {parent}, the Item within which
    the handler is declared. However, it can sometimes be useful to set the
    target to a different Item, in order to handle events within one item
    but manipulate another; or to \c null, to disable the default behavior
    and do something else instead.
*/
void QQuickPointerHandler::setTarget(QQuickItem *target)
{
    Q_D(QQuickPointerHandler);
    d->targetExplicitlySet = true;
    if (d->target == target)
        return;

    QQuickItem *oldTarget = d->target;
    d->target = target;
    onTargetChanged(oldTarget);
    emit targetChanged();
}

QQuickItem *QQuickPointerHandler::parentItem() const
{
    return static_cast<QQuickItem *>(QObject::parent());
}

QQuickItem *QQuickPointerHandler::target() const
{
    Q_D(const QQuickPointerHandler);
    if (!d->targetExplicitlySet)
        return parentItem();
    return d->target;
}

void QQuickPointerHandler::handlePointerEvent(QQuickPointerEvent *event)
{
    bool wants = wantsPointerEvent(event);
    qCDebug(lcPointerHandlerDispatch) << metaObject()->className() << objectName()
                                      << "on" << parentItem()->metaObject()->className() << parentItem()->objectName()
                                      << (wants ? "WANTS" : "DECLINES") << event;
    if (wants) {
        handlePointerEventImpl(event);
    } else {
        setActive(false);
        int pCount = event->pointCount();
        for (int i = 0; i < pCount; ++i) {
            QQuickEventPoint *pt = event->point(i);
            if (pt->grabberPointerHandler() == this && pt->state() != QQuickEventPoint::Stationary)
                pt->cancelExclusiveGrab();
        }
    }
    event->device()->eventDeliveryTargets().append(this);
}

bool QQuickPointerHandler::wantsPointerEvent(QQuickPointerEvent *event)
{
    Q_D(const QQuickPointerHandler);
    Q_UNUSED(event)
    return d->enabled;
}

bool QQuickPointerHandler::wantsEventPoint(QQuickEventPoint *point)
{
    bool ret = point->exclusiveGrabber() == this || point->passiveGrabbers().contains(this) || parentContains(point);
    qCDebug(lcPointerHandlerDispatch) << hex << point->pointId() << "@" << point->scenePosition()
                                      << metaObject()->className() << objectName() << ret;
    return ret;
}

/*!
    \readonly
    \qmlproperty bool QtQuick::PointerHandler::active

    This holds true whenever this Input Handler has taken sole responsibility
    for handing one or more EventPoints, by successfully taking an exclusive
    grab of those points. This means that it is keeping its properties
    up-to-date according to the movements of those Event Points and actively
    manipulating its \l target (if any).
*/
void QQuickPointerHandler::setActive(bool active)
{
    Q_D(QQuickPointerHandler);
    if (d->active != active) {
        qCDebug(lcPointerHandlerActive) << this << d->active << "->" << active;
        d->active = active;
        onActiveChanged();
        emit activeChanged();
    }
}

void QQuickPointerHandler::handlePointerEventImpl(QQuickPointerEvent *event)
{
    Q_D(QQuickPointerHandler);
    d->currentEvent = event;
}

/*!
    \readonly
    \qmlproperty Item QtQuick::PointerHandler::parent

    The \l Item which is the scope of the handler; the Item in which it was declared.
    The handler will handle events on behalf of this Item, which means a
    pointer event is relevant if at least one of its event points occurs within
    the Item's interior.  Initially \l [QML] {target} {target()} is the same, but it
    can be reassigned.

    \sa {target}, QObject::parent()
*/

/*!
    \qmlsignal QtQuick::PointerHandler::grabChanged(GrabTransition transition, EventPoint point)

    This signal is emitted when the grab has changed in some way which is
    relevant to this handler.

    The \a transition (verb) tells what happened.
    The \a point (object) is the point that was grabbed or ungrabbed.
*/

/*!
    \qmlsignal QtQuick::PointerHandler::canceled(EventPoint point)

    If this handler has already grabbed the given \a point, this signal is
    emitted when the grab is stolen by a different Pointer Handler or Item.
*/

QQuickPointerHandlerPrivate::QQuickPointerHandlerPrivate()
  : grabPermissions(QQuickPointerHandler::CanTakeOverFromItems |
                      QQuickPointerHandler::CanTakeOverFromHandlersOfDifferentType |
                      QQuickPointerHandler::ApprovesTakeOverByAnything)
  , enabled(true)
  , active(false)
  , targetExplicitlySet(false)
  , hadKeepMouseGrab(false)
  , hadKeepTouchGrab(false)
{
}

QT_END_NAMESPACE
