/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the plugins 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 "qwaylandinputdevice_p.h"

#include "qwaylandintegration_p.h"
#include "qwaylandwindow_p.h"
#include "qwaylandsurface_p.h"
#include "qwaylandbuffer_p.h"
#if QT_CONFIG(wayland_datadevice)
#include "qwaylanddatadevice_p.h"
#include "qwaylanddatadevicemanager_p.h"
#endif
#if QT_CONFIG(wayland_client_primary_selection)
#include "qwaylandprimaryselectionv1_p.h"
#endif
#include "qwaylandtabletv2_p.h"
#include "qwaylandtouch_p.h"
#include "qwaylandscreen_p.h"
#include "qwaylandcursor_p.h"
#include "qwaylanddisplay_p.h"
#include "qwaylandshmbackingstore_p.h"
#include "qwaylandinputcontext_p.h"

#include <QtGui/private/qpixmap_raster_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformwindow.h>
#include <qpa/qplatforminputcontext.h>
#include <QDebug>

#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>

#if QT_CONFIG(cursor)
#include <wayland-cursor.h>
#endif

#include <QtGui/QGuiApplication>

QT_BEGIN_NAMESPACE

namespace QtWaylandClient {

Q_LOGGING_CATEGORY(lcQpaWaylandInput, "qt.qpa.wayland.input");

QWaylandInputDevice::Keyboard::Keyboard(QWaylandInputDevice *p)
    : mParent(p)
{
    mRepeatTimer.callOnTimeout([&]() {
        if (!focusWindow()) {
            // We destroyed the keyboard focus surface, but the server didn't get the message yet...
            // or the server didn't send an enter event first.
            return;
        }
        mRepeatTimer.setInterval(1000 / mRepeatRate);
        handleKey(mRepeatKey.time, QEvent::KeyRelease, mRepeatKey.key, mRepeatKey.modifiers,
                  mRepeatKey.code, mRepeatKey.nativeVirtualKey, mRepeatKey.nativeModifiers,
                  mRepeatKey.text, true);
        handleKey(mRepeatKey.time, QEvent::KeyPress, mRepeatKey.key, mRepeatKey.modifiers,
                  mRepeatKey.code, mRepeatKey.nativeVirtualKey, mRepeatKey.nativeModifiers,
                  mRepeatKey.text, true);
    });
}

#if QT_CONFIG(xkbcommon)
bool QWaylandInputDevice::Keyboard::createDefaultKeymap()
{
    struct xkb_context *ctx = mParent->mQDisplay->xkbContext();
    if (!ctx)
        return false;

    struct xkb_rule_names names;
    names.rules = "evdev";
    names.model = "pc105";
    names.layout = "us";
    names.variant = "";
    names.options = "";

    mXkbKeymap.reset(xkb_keymap_new_from_names(ctx, &names, XKB_KEYMAP_COMPILE_NO_FLAGS));
    if (mXkbKeymap)
        mXkbState.reset(xkb_state_new(mXkbKeymap.get()));

    if (!mXkbKeymap || !mXkbState) {
        qCWarning(lcQpaWayland, "failed to create default keymap");
        return false;
    }

    return true;
}
#endif

QWaylandInputDevice::Keyboard::~Keyboard()
{
    if (mFocus)
        QWindowSystemInterface::handleWindowActivated(nullptr);
    if (mParent->mVersion >= 3)
        wl_keyboard_release(object());
    else
        wl_keyboard_destroy(object());
}

QWaylandWindow *QWaylandInputDevice::Keyboard::focusWindow() const
{
    return mFocus ? QWaylandWindow::fromWlSurface(mFocus) : nullptr;
}

QWaylandInputDevice::Pointer::Pointer(QWaylandInputDevice *seat)
    : mParent(seat)
{
#if QT_CONFIG(cursor)
    mCursor.frameTimer.setSingleShot(true);
    mCursor.frameTimer.callOnTimeout([&]() {
        cursorTimerCallback();
    });
#endif
}

QWaylandInputDevice::Pointer::~Pointer()
{
    if (mParent->mVersion >= 3)
        wl_pointer_release(object());
    else
        wl_pointer_destroy(object());
}

QWaylandWindow *QWaylandInputDevice::Pointer::focusWindow() const
{
    return mFocus ? mFocus->waylandWindow() : nullptr;
}

#if QT_CONFIG(cursor)

class WlCallback : public QtWayland::wl_callback {
public:
    explicit WlCallback(::wl_callback *callback, std::function<void(uint32_t)> fn, bool autoDelete = false)
        : QtWayland::wl_callback(callback)
        , m_fn(fn)
        , m_autoDelete(autoDelete)
    {}
    ~WlCallback() override { wl_callback_destroy(object()); }
    bool done() const { return m_done; }
    void callback_done(uint32_t callback_data) override {
        m_done = true;
        m_fn(callback_data);
        if (m_autoDelete)
            delete this;
    }
private:
    bool m_done = false;
    std::function<void(uint32_t)> m_fn;
    bool m_autoDelete = false;
};

class CursorSurface : public QWaylandSurface
{
public:
    explicit CursorSurface(QWaylandInputDevice::Pointer *pointer, QWaylandDisplay *display)
        : QWaylandSurface(display)
        , m_pointer(pointer)
    {
        //TODO: When we upgrade to libwayland 1.10, use wl_surface_get_version instead.
        m_version = display->compositorVersion();
        connect(this, &QWaylandSurface::screensChanged,
                m_pointer, &QWaylandInputDevice::Pointer::updateCursor);
    }

    void hide()
    {
        uint serial = m_pointer->mEnterSerial;
        Q_ASSERT(serial);
        m_pointer->set_cursor(serial, nullptr, 0, 0);
        m_setSerial = 0;
    }

    // Size and hotspot are in surface coordinates
    void update(wl_buffer *buffer, const QPoint &hotspot, const QSize &size, int bufferScale, bool animated = false)
    {
        // Calling code needs to ensure buffer scale is supported if != 1
        Q_ASSERT(bufferScale == 1 || m_version >= 3);

        auto enterSerial = m_pointer->mEnterSerial;
        if (m_setSerial < enterSerial || m_hotspot != hotspot) {
            m_pointer->set_cursor(m_pointer->mEnterSerial, object(), hotspot.x(), hotspot.y());
            m_setSerial = enterSerial;
            m_hotspot = hotspot;
        }

        if (m_version >= 3)
            set_buffer_scale(bufferScale);

        attach(buffer, 0, 0);
        damage(0, 0, size.width(), size.height());
        m_frameCallback.reset();
        if (animated) {
            m_frameCallback.reset(new WlCallback(frame(), [this](uint32_t time){
               Q_UNUSED(time);
               m_pointer->cursorFrameCallback();
            }));
        }
        commit();
    }

    int outputScale() const
    {
        int scale = 0;
        for (auto *screen : m_screens)
            scale = qMax(scale, screen->scale());
        return scale;
    }

private:
    QScopedPointer<WlCallback> m_frameCallback;
    QWaylandInputDevice::Pointer *m_pointer = nullptr;
    uint m_version = 0;
    uint m_setSerial = 0;
    QPoint m_hotspot;
};

QString QWaylandInputDevice::Pointer::cursorThemeName() const
{
    static QString themeName = qEnvironmentVariable("XCURSOR_THEME", QStringLiteral("default"));
    return themeName;
}

int QWaylandInputDevice::Pointer::cursorSize() const
{
    constexpr int defaultCursorSize = 32;
    static const int xCursorSize = qEnvironmentVariableIntValue("XCURSOR_SIZE");
    return xCursorSize > 0 ? xCursorSize : defaultCursorSize;
}

int QWaylandInputDevice::Pointer::idealCursorScale() const
{
    // set_buffer_scale is not supported on earlier versions
    if (seat()->mQDisplay->compositorVersion() < 3)
        return 1;

    if (auto *s = mCursor.surface.data()) {
        if (s->outputScale() > 0)
            return s->outputScale();
    }

    return seat()->mCursor.fallbackOutputScale;
}

void QWaylandInputDevice::Pointer::updateCursorTheme()
{
    int scale = idealCursorScale();
    int pixelSize = cursorSize() * scale;
    auto *display = seat()->mQDisplay;
    mCursor.theme = display->loadCursorTheme(cursorThemeName(), pixelSize);

    if (!mCursor.theme)
        return; // A warning has already been printed in loadCursorTheme

    if (auto *arrow = mCursor.theme->cursor(Qt::ArrowCursor)) {
        int arrowPixelSize = qMax(arrow->images[0]->width, arrow->images[0]->height); // Not all cursor themes are square
        while (scale > 1 && arrowPixelSize / scale < cursorSize())
            --scale;
    } else {
        qCWarning(lcQpaWayland) << "Cursor theme does not support the arrow cursor";
    }
    mCursor.themeBufferScale = scale;
}

void QWaylandInputDevice::Pointer::updateCursor()
{
    if (mEnterSerial == 0)
        return;

    auto shape = seat()->mCursor.shape;

    if (shape == Qt::BlankCursor) {
        if (mCursor.surface)
            mCursor.surface->hide();
        return;
    }

    if (shape == Qt::BitmapCursor) {
        auto buffer = seat()->mCursor.bitmapBuffer;
        if (!buffer) {
            qCWarning(lcQpaWayland) << "No buffer for bitmap cursor, can't set cursor";
            return;
        }
        auto hotspot = seat()->mCursor.hotspot;
        int bufferScale = seat()->mCursor.bitmapScale;
        getOrCreateCursorSurface()->update(buffer->buffer(), hotspot, buffer->size(), bufferScale);
        return;
    }

    if (!mCursor.theme || idealCursorScale() != mCursor.themeBufferScale)
        updateCursorTheme();

    if (!mCursor.theme)
        return;

    // Set from shape using theme
    uint time = seat()->mCursor.animationTimer.elapsed();

    if (struct ::wl_cursor *waylandCursor = mCursor.theme->cursor(shape)) {
        uint duration = 0;
        int frame = wl_cursor_frame_and_duration(waylandCursor, time, &duration);
        ::wl_cursor_image *image = waylandCursor->images[frame];

        struct wl_buffer *buffer = wl_cursor_image_get_buffer(image);
        if (!buffer) {
            qCWarning(lcQpaWayland) << "Could not find buffer for cursor" << shape;
            return;
        }
        int bufferScale = mCursor.themeBufferScale;
        QPoint hotspot = QPoint(image->hotspot_x, image->hotspot_y) / bufferScale;
        QSize size = QSize(image->width, image->height) / bufferScale;
        bool animated = duration > 0;
        if (animated) {
            mCursor.gotFrameCallback = false;
            mCursor.gotTimerCallback = false;
            mCursor.frameTimer.start(duration);
        }
        getOrCreateCursorSurface()->update(buffer, hotspot, size, bufferScale, animated);
        return;
    }

    qCWarning(lcQpaWayland) << "Unable to change to cursor" << shape;
}

CursorSurface *QWaylandInputDevice::Pointer::getOrCreateCursorSurface()
{
    if (!mCursor.surface)
        mCursor.surface.reset(new CursorSurface(this, seat()->mQDisplay));
    return mCursor.surface.get();
}

void QWaylandInputDevice::Pointer::cursorTimerCallback()
{
    mCursor.gotTimerCallback = true;
    if (mCursor.gotFrameCallback) {
        updateCursor();
    }
}

void QWaylandInputDevice::Pointer::cursorFrameCallback()
{
    mCursor.gotFrameCallback = true;
    if (mCursor.gotTimerCallback) {
        updateCursor();
    }
}

#endif // QT_CONFIG(cursor)

QWaylandInputDevice::Touch::Touch(QWaylandInputDevice *p)
    : mParent(p)
{
}

QWaylandInputDevice::Touch::~Touch()
{
    if (mParent->mVersion >= 3)
        wl_touch_release(object());
    else
        wl_touch_destroy(object());
}

QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, int version, uint32_t id)
    : QtWayland::wl_seat(display->wl_registry(), id, qMin(version, 5))
    , mQDisplay(display)
    , mDisplay(display->wl_display())
    , mVersion(qMin(version, 5))
{
#if QT_CONFIG(wayland_datadevice)
    if (mQDisplay->dndSelectionHandler()) {
        mDataDevice = mQDisplay->dndSelectionHandler()->getDataDevice(this);
    }
#endif

#if QT_CONFIG(wayland_client_primary_selection)
    // TODO: Could probably decouple this more if there was a signal for new seat added
    if (auto *psm = mQDisplay->primarySelectionManager())
        setPrimarySelectionDevice(psm->createDevice(this));
#endif

    if (mQDisplay->textInputManager())
        mTextInput.reset(new QWaylandTextInput(mQDisplay, mQDisplay->textInputManager()->get_text_input(wl_seat())));

    if (auto *tm = mQDisplay->tabletManager())
        mTabletSeat.reset(new QWaylandTabletSeatV2(tm, this));
}

QWaylandInputDevice::~QWaylandInputDevice()
{
    delete mPointer;
    delete mKeyboard;
    delete mTouch;
}

void QWaylandInputDevice::seat_capabilities(uint32_t caps)
{
    mCaps = caps;

    if (caps & WL_SEAT_CAPABILITY_KEYBOARD && !mKeyboard) {
        mKeyboard = createKeyboard(this);
        mKeyboard->init(get_keyboard());
    } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && mKeyboard) {
        delete mKeyboard;
        mKeyboard = nullptr;
    }

    if (caps & WL_SEAT_CAPABILITY_POINTER && !mPointer) {
        mPointer = createPointer(this);
        mPointer->init(get_pointer());
    } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && mPointer) {
        delete mPointer;
        mPointer = nullptr;
    }

    if (caps & WL_SEAT_CAPABILITY_TOUCH && !mTouch) {
        mTouch = createTouch(this);
        mTouch->init(get_touch());

        if (!mTouchDevice) {
            mTouchDevice = new QTouchDevice;
            mTouchDevice->setType(QTouchDevice::TouchScreen);
            mTouchDevice->setCapabilities(QTouchDevice::Position);
            QWindowSystemInterface::registerTouchDevice(mTouchDevice);
        }
    } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && mTouch) {
        delete mTouch;
        mTouch = nullptr;
    }
}

QWaylandInputDevice::Keyboard *QWaylandInputDevice::createKeyboard(QWaylandInputDevice *device)
{
    return new Keyboard(device);
}

QWaylandInputDevice::Pointer *QWaylandInputDevice::createPointer(QWaylandInputDevice *device)
{
    return new Pointer(device);
}

QWaylandInputDevice::Touch *QWaylandInputDevice::createTouch(QWaylandInputDevice *device)
{
    return new Touch(device);
}

QWaylandInputDevice::Keyboard *QWaylandInputDevice::keyboard() const
{
    return mKeyboard;
}

QWaylandInputDevice::Pointer *QWaylandInputDevice::pointer() const
{
    return mPointer;
}

QWaylandInputDevice::Touch *QWaylandInputDevice::touch() const
{
    return mTouch;
}

void QWaylandInputDevice::handleEndDrag()
{
    if (mTouch)
        mTouch->releasePoints();
    if (mPointer)
        mPointer->releaseButtons();
}

#if QT_CONFIG(wayland_datadevice)
void QWaylandInputDevice::setDataDevice(QWaylandDataDevice *device)
{
    mDataDevice = device;
}

QWaylandDataDevice *QWaylandInputDevice::dataDevice() const
{
    return mDataDevice;
}
#endif

#if QT_CONFIG(wayland_client_primary_selection)
void QWaylandInputDevice::setPrimarySelectionDevice(QWaylandPrimarySelectionDeviceV1 *primarySelectionDevice)
{
    mPrimarySelectionDevice.reset(primarySelectionDevice);
}

QWaylandPrimarySelectionDeviceV1 *QWaylandInputDevice::primarySelectionDevice() const
{
    return mPrimarySelectionDevice.data();
}
#endif

void QWaylandInputDevice::setTextInput(QWaylandTextInput *textInput)
{
    mTextInput.reset(textInput);
}

QWaylandTextInput *QWaylandInputDevice::textInput() const
{
    return mTextInput.data();
}

void QWaylandInputDevice::removeMouseButtonFromState(Qt::MouseButton button)
{
    if (mPointer)
        mPointer->mButtons = mPointer->mButtons & !button;
}

QWaylandWindow *QWaylandInputDevice::pointerFocus() const
{
    return mPointer ? mPointer->focusWindow() : nullptr;
}

QWaylandWindow *QWaylandInputDevice::keyboardFocus() const
{
    return mKeyboard ? mKeyboard->focusWindow() : nullptr;
}

QWaylandWindow *QWaylandInputDevice::touchFocus() const
{
    return mTouch ? mTouch->mFocus : nullptr;
}

QPointF QWaylandInputDevice::pointerSurfacePosition() const
{
    return mPointer ? mPointer->mSurfacePos : QPointF();
}

QList<int> QWaylandInputDevice::possibleKeys(const QKeyEvent *event) const
{
#if QT_CONFIG(xkbcommon)
    if (mKeyboard && mKeyboard->mXkbState)
        return QXkbCommon::possibleKeys(mKeyboard->mXkbState.get(), event);
#else
    Q_UNUSED(event);
#endif
    return {};
}

Qt::KeyboardModifiers QWaylandInputDevice::modifiers() const
{
    if (!mKeyboard)
        return Qt::NoModifier;

    return mKeyboard->modifiers();
}

Qt::KeyboardModifiers QWaylandInputDevice::Keyboard::modifiers() const
{
    Qt::KeyboardModifiers ret = Qt::NoModifier;

#if QT_CONFIG(xkbcommon)
    if (!mXkbState)
        return ret;

    ret = QXkbCommon::modifiers(mXkbState.get());
#endif

    return ret;
}

#if QT_CONFIG(cursor)
void QWaylandInputDevice::setCursor(const QCursor *cursor, const QSharedPointer<QWaylandBuffer> &cachedBuffer, int fallbackOutputScale)
{
    CursorState oldCursor = mCursor;
    mCursor = CursorState(); // Clear any previous state
    mCursor.shape = cursor ? cursor->shape() : Qt::ArrowCursor;
    mCursor.hotspot = cursor ? cursor->hotSpot() : QPoint();
    mCursor.fallbackOutputScale = fallbackOutputScale;
    mCursor.animationTimer.start();

    if (mCursor.shape == Qt::BitmapCursor) {
        mCursor.bitmapBuffer = cachedBuffer ? cachedBuffer : QWaylandCursor::cursorBitmapBuffer(mQDisplay, cursor);
        qreal dpr = cursor->pixmap().devicePixelRatio();
        mCursor.bitmapScale = int(dpr); // Wayland doesn't support fractional buffer scale
        // If there was a fractional part of the dpr, we need to scale the hotspot accordingly
        if (mCursor.bitmapScale < dpr)
            mCursor.hotspot *= dpr / mCursor.bitmapScale;
    }

    // Return early if setCursor was called redundantly (mostly happens from decorations)
    if (mCursor.shape != Qt::BitmapCursor
            && mCursor.shape == oldCursor.shape
            && mCursor.hotspot == oldCursor.hotspot
            && mCursor.fallbackOutputScale == oldCursor.fallbackOutputScale) {
        return;
    }

    if (mPointer)
        mPointer->updateCursor();
}
#endif

class EnterEvent : public QWaylandPointerEvent
{
public:
    EnterEvent(QWaylandWindow *surface, const QPointF &local, const QPointF &global)
        : QWaylandPointerEvent(QEvent::Enter, Qt::NoScrollPhase, surface, 0,
                               local, global, Qt::NoButton, Qt::NoButton, Qt::NoModifier)
    {}
};

void QWaylandInputDevice::Pointer::pointer_enter(uint32_t serial, struct wl_surface *surface,
                                                 wl_fixed_t sx, wl_fixed_t sy)
{
    if (!surface)
        return;

    QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface);

    if (!window)
        return; // Ignore foreign surfaces

    if (mFocus) {
        qCWarning(lcQpaWayland) << "The compositor sent a wl_pointer.enter event before sending a"
                                << "leave event first, this is not allowed by the wayland protocol"
                                << "attempting to work around it by invalidating the current focus";
        invalidateFocus();
    }
    mFocus = window->waylandSurface();
    connect(mFocus.data(), &QObject::destroyed, this, &Pointer::handleFocusDestroyed);

    mSurfacePos = QPointF(wl_fixed_to_double(sx), wl_fixed_to_double(sy));
    mGlobalPos = window->window()->mapToGlobal(mSurfacePos.toPoint());

    mParent->mSerial = serial;
    mEnterSerial = serial;

#if QT_CONFIG(cursor)
    // Depends on mEnterSerial being updated
    updateCursor();
#endif

    QWaylandWindow *grab = QWaylandWindow::mouseGrab();
    if (!grab)
        setFrameEvent(new EnterEvent(window, mSurfacePos, mGlobalPos));
}

class LeaveEvent : public QWaylandPointerEvent
{
public:
    LeaveEvent(QWaylandWindow *surface, const QPointF &localPos, const QPointF &globalPos)
        : QWaylandPointerEvent(QEvent::Leave, Qt::NoScrollPhase, surface, 0,
                               localPos, globalPos, Qt::NoButton, Qt::NoButton, Qt::NoModifier)
    {}
};

void QWaylandInputDevice::Pointer::pointer_leave(uint32_t time, struct wl_surface *surface)
{
    // The event may arrive after destroying the window, indicated by
    // a null surface.
    if (!surface)
        return;

    auto *window = QWaylandWindow::fromWlSurface(surface);
    if (!window)
        return; // Ignore foreign surfaces

    if (!QWaylandWindow::mouseGrab())
        setFrameEvent(new LeaveEvent(window, mSurfacePos, mGlobalPos));

    invalidateFocus();
    mButtons = Qt::NoButton;

    mParent->mTime = time;
}

class MotionEvent : public QWaylandPointerEvent
{
public:
    MotionEvent(QWaylandWindow *surface, ulong timestamp, const QPointF &localPos,
                const QPointF &globalPos, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
        : QWaylandPointerEvent(QEvent::MouseMove, Qt::NoScrollPhase, surface,
                               timestamp, localPos, globalPos, buttons, Qt::NoButton, modifiers)
    {
    }
};

void QWaylandInputDevice::Pointer::pointer_motion(uint32_t time, wl_fixed_t surface_x, wl_fixed_t surface_y)
{
    QWaylandWindow *window = focusWindow();
    if (!window) {
        // We destroyed the pointer focus surface, but the server didn't get the message yet...
        // or the server didn't send an enter event first. In either case, ignore the event.
        return;
    }

    QPointF pos(wl_fixed_to_double(surface_x), wl_fixed_to_double(surface_y));
    QPointF delta = pos - pos.toPoint();
    QPointF global = window->window()->mapToGlobal(pos.toPoint());
    global += delta;

    mSurfacePos = pos;
    mGlobalPos = global;
    mParent->mTime = time;

    QWaylandWindow *grab = QWaylandWindow::mouseGrab();
    if (grab && grab != window) {
        // We can't know the true position since we're getting events for another surface,
        // so we just set it outside of the window boundaries.
        pos = QPointF(-1, -1);
        global = grab->window()->mapToGlobal(pos.toPoint());
        window = grab;
    }
    setFrameEvent(new MotionEvent(window, time, pos, global, mButtons, mParent->modifiers()));
}

class PressEvent : public QWaylandPointerEvent
{
public:
    PressEvent(QWaylandWindow *surface, ulong timestamp, const QPointF &localPos,
               const QPointF &globalPos, Qt::MouseButtons buttons, Qt::MouseButton button,
               Qt::KeyboardModifiers modifiers)
        : QWaylandPointerEvent(QEvent::MouseButtonPress, Qt::NoScrollPhase, surface,
                               timestamp, localPos, globalPos, buttons, button, modifiers)
    {
    }
};

class ReleaseEvent : public QWaylandPointerEvent
{
public:
    ReleaseEvent(QWaylandWindow *surface, ulong timestamp, const QPointF &localPos,
                 const QPointF &globalPos, Qt::MouseButtons buttons, Qt::MouseButton button,
                 Qt::KeyboardModifiers modifiers)
        : QWaylandPointerEvent(QEvent::MouseButtonRelease, Qt::NoScrollPhase, surface,
                               timestamp, localPos, globalPos, buttons, button, modifiers)
    {
    }
};

void QWaylandInputDevice::Pointer::pointer_button(uint32_t serial, uint32_t time,
                                                  uint32_t button, uint32_t state)
{
    QWaylandWindow *window = focusWindow();
    if (!window) {
        // We destroyed the pointer focus surface, but the server didn't get the message yet...
        // or the server didn't send an enter event first. In either case, ignore the event.
        return;
    }

    Qt::MouseButton qt_button;

    // translate from kernel (input.h) 'button' to corresponding Qt:MouseButton.
    // The range of mouse values is 0x110 <= mouse_button < 0x120, the first Joystick button.
    switch (button) {
    case 0x110: qt_button = Qt::LeftButton; break;    // kernel BTN_LEFT
    case 0x111: qt_button = Qt::RightButton; break;
    case 0x112: qt_button = Qt::MiddleButton; break;
    case 0x113: qt_button = Qt::ExtraButton1; break;  // AKA Qt::BackButton
    case 0x114: qt_button = Qt::ExtraButton2; break;  // AKA Qt::ForwardButton
    case 0x115: qt_button = Qt::ExtraButton3; break;  // AKA Qt::TaskButton
    case 0x116: qt_button = Qt::ExtraButton4; break;
    case 0x117: qt_button = Qt::ExtraButton5; break;
    case 0x118: qt_button = Qt::ExtraButton6; break;
    case 0x119: qt_button = Qt::ExtraButton7; break;
    case 0x11a: qt_button = Qt::ExtraButton8; break;
    case 0x11b: qt_button = Qt::ExtraButton9; break;
    case 0x11c: qt_button = Qt::ExtraButton10; break;
    case 0x11d: qt_button = Qt::ExtraButton11; break;
    case 0x11e: qt_button = Qt::ExtraButton12; break;
    case 0x11f: qt_button = Qt::ExtraButton13; break;
    default: return; // invalid button number (as far as Qt is concerned)
    }

    if (state)
        mButtons |= qt_button;
    else
        mButtons &= ~qt_button;

    mParent->mTime = time;
    mParent->mSerial = serial;
    if (state)
        mParent->mQDisplay->setLastInputDevice(mParent, serial, window);

    QWaylandWindow *grab = QWaylandWindow::mouseGrab();

    QPointF pos = mSurfacePos;
    QPointF global = mGlobalPos;
    if (grab && grab != focusWindow()) {
        pos = QPointF(-1, -1);
        global = grab->window()->mapToGlobal(pos.toPoint());

        window = grab;
    }

    if (state)
        setFrameEvent(new PressEvent(window, time, pos, global, mButtons, qt_button, mParent->modifiers()));
    else
        setFrameEvent(new ReleaseEvent(window, time, pos, global, mButtons, qt_button, mParent->modifiers()));
}

void QWaylandInputDevice::Pointer::invalidateFocus()
{
    if (mFocus) {
        disconnect(mFocus.data(), &QObject::destroyed, this, &Pointer::handleFocusDestroyed);
        mFocus = nullptr;
    }
    mEnterSerial = 0;
}

void QWaylandInputDevice::Pointer::releaseButtons()
{
    mButtons = Qt::NoButton;

    if (auto *window = focusWindow()) {
        MotionEvent e(focusWindow(), mParent->mTime, mSurfacePos, mGlobalPos, mButtons, mParent->modifiers());
        window->handleMouse(mParent, e);
    }
}

class WheelEvent : public QWaylandPointerEvent
{
public:
    WheelEvent(QWaylandWindow *surface, Qt::ScrollPhase phase, ulong timestamp, const QPointF &local,
               const QPointF &global, const QPoint &pixelDelta, const QPoint &angleDelta,
               Qt::MouseEventSource source, Qt::KeyboardModifiers modifiers)
        : QWaylandPointerEvent(QEvent::Wheel, phase, surface, timestamp,
                               local, global, pixelDelta, angleDelta, source, modifiers)
    {
    }
};

void QWaylandInputDevice::Pointer::pointer_axis(uint32_t time, uint32_t axis, int32_t value)
{
    if (!focusWindow()) {
        // We destroyed the pointer focus surface, but the server didn't get the message yet...
        // or the server didn't send an enter event first. In either case, ignore the event.
        return;
    }

    // Get the delta and convert it into the expected range
    switch (axis) {
    case WL_POINTER_AXIS_VERTICAL_SCROLL:
        mFrameData.delta.ry() += wl_fixed_to_double(value);
        qCDebug(lcQpaWaylandInput) << "wl_pointer.axis vertical:" << mFrameData.delta.y();
        break;
    case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
        mFrameData.delta.rx() += wl_fixed_to_double(value);
        qCDebug(lcQpaWaylandInput) << "wl_pointer.axis horizontal:" << mFrameData.delta.x();
        break;
    default:
        //TODO: is this really needed?
        qCWarning(lcQpaWaylandInput) << "wl_pointer.axis: Unknown axis:" << axis;
        return;
    }

    mParent->mTime = time;

    if (mParent->mVersion < WL_POINTER_FRAME_SINCE_VERSION) {
        qCDebug(lcQpaWaylandInput) << "Flushing new event; no frame event in this version";
        flushFrameEvent();
    }
}

void QWaylandInputDevice::Pointer::pointer_frame()
{
    flushFrameEvent();
}

void QWaylandInputDevice::Pointer::pointer_axis_source(uint32_t source)
{
    switch (source) {
    case axis_source_wheel:
        qCDebug(lcQpaWaylandInput) << "Axis source wheel";
        break;
    case axis_source_finger:
        qCDebug(lcQpaWaylandInput) << "Axis source finger";
        break;
    case axis_source_continuous:
        qCDebug(lcQpaWaylandInput) << "Axis source continuous";
        break;
    }
    mFrameData.axisSource = axis_source(source);
}

void QWaylandInputDevice::Pointer::pointer_axis_stop(uint32_t time, uint32_t axis)
{
    if (!focusWindow())
        return;

    mParent->mTime = time;
    switch (axis) {
    case axis_vertical_scroll:
        qCDebug(lcQpaWaylandInput) << "Received vertical wl_pointer.axis_stop";
        mFrameData.delta.setY(0); //TODO: what's the point of doing this?
        break;
    case axis_horizontal_scroll:
        qCDebug(lcQpaWaylandInput) << "Received horizontal wl_pointer.axis_stop";
        mFrameData.delta.setX(0);
        break;
    default:
        qCWarning(lcQpaWaylandInput) << "wl_pointer.axis_stop: Unknown axis: " << axis
                                     << "This is most likely a compositor bug";
        return;
    }

    // May receive axis_stop for events we haven't sent a ScrollBegin for because
    // most axis_sources do not mandate an axis_stop event to be sent.
    if (!mScrollBeginSent) {
        // TODO: For now, we just ignore these events, but we could perhaps take this as an
        // indication that this compositor will in fact send axis_stop events for these sources
        // and send a ScrollBegin the next time an axis_source event with this type is encountered.
        return;
    }

    QWaylandWindow *target = QWaylandWindow::mouseGrab();
    if (!target)
        target = focusWindow();
    Qt::KeyboardModifiers mods = mParent->modifiers();
    WheelEvent wheelEvent(focusWindow(), Qt::ScrollEnd, mParent->mTime, mSurfacePos, mGlobalPos,
                          QPoint(), QPoint(), Qt::MouseEventNotSynthesized, mods);
    target->handleMouse(mParent, wheelEvent);
    mScrollBeginSent = false;
    mScrollDeltaRemainder = QPointF();
}

void QWaylandInputDevice::Pointer::pointer_axis_discrete(uint32_t axis, int32_t value)
{
    if (!focusWindow())
        return;

    switch (axis) {
    case axis_vertical_scroll:
        qCDebug(lcQpaWaylandInput) << "wl_pointer.axis_discrete vertical:" << value;
        mFrameData.discreteDelta.ry() += value;
        break;
    case axis_horizontal_scroll:
        qCDebug(lcQpaWaylandInput) << "wl_pointer.axis_discrete horizontal:" << value;
        mFrameData.discreteDelta.rx() += value;
        break;
    default:
        //TODO: is this really needed?
        qCWarning(lcQpaWaylandInput) << "wl_pointer.axis_discrete: Unknown axis:" << axis;
        return;
    }
}

void QWaylandInputDevice::Pointer::setFrameEvent(QWaylandPointerEvent *event)
{
    qCDebug(lcQpaWaylandInput) << "Setting frame event " << event->type;
    if (mFrameData.event && mFrameData.event->type != event->type) {
        qCDebug(lcQpaWaylandInput) << "Flushing; previous was " << mFrameData.event->type;
        flushFrameEvent();
    }

    mFrameData.event = event;

    if (mParent->mVersion < WL_POINTER_FRAME_SINCE_VERSION) {
        qCDebug(lcQpaWaylandInput) << "Flushing new event; no frame event in this version";
        flushFrameEvent();
    }
}

void QWaylandInputDevice::Pointer::FrameData::resetScrollData()
{
    discreteDelta = QPoint();
    delta = QPointF();
    axisSource = axis_source_wheel;
}

bool QWaylandInputDevice::Pointer::FrameData::hasPixelDelta() const
{
    switch (axisSource) {
    case axis_source_wheel_tilt: // sideways tilt of the wheel
    case axis_source_wheel:
        // In the case of wheel events, a pixel delta doesn't really make sense,
        // and will make Qt think this is a continuous scroll event when it isn't,
        // so just ignore it.
        return false;
    case axis_source_finger:
    case axis_source_continuous:
        return !delta.isNull();
    default:
        return false;
    }
}

QPoint QWaylandInputDevice::Pointer::FrameData::pixelDeltaAndError(QPointF *accumulatedError) const
{
    if (!hasPixelDelta())
        return QPoint();

    Q_ASSERT(accumulatedError);
    // Add accumulated rounding error before rounding again
    QPoint pixelDelta = (delta + *accumulatedError).toPoint();
    *accumulatedError += delta - pixelDelta;
    Q_ASSERT(qAbs(accumulatedError->x()) < 1.0);
    Q_ASSERT(qAbs(accumulatedError->y()) < 1.0);
    return pixelDelta;
}

QPoint QWaylandInputDevice::Pointer::FrameData::angleDelta() const
{
    if (discreteDelta.isNull()) {
        // If we didn't get any discrete events, then we need to fall back to
        // the continuous information.
        return (delta * -12).toPoint(); //TODO: why multiply by 12?
    }

    // The angle delta is in eights of degrees, and our docs says most mice have
    // 1 click = 15 degrees. It's also in the opposite direction of surface space.
    return -discreteDelta * 15 * 8;
}

Qt::MouseEventSource QWaylandInputDevice::Pointer::FrameData::wheelEventSource() const
{
    switch (axisSource) {
    case axis_source_wheel_tilt: // sideways tilt of the wheel
    case axis_source_wheel:
        return Qt::MouseEventNotSynthesized;
    case axis_source_finger:
    case axis_source_continuous:
    default: // Whatever other sources might be added are probably not mouse wheels
        return Qt::MouseEventSynthesizedBySystem;
    }
}

void QWaylandInputDevice::Pointer::flushScrollEvent()
{
    QPoint angleDelta = mFrameData.angleDelta();

    // Angle delta is required for Qt wheel events, so don't try to send events if it's zero
    if (!angleDelta.isNull()) {
        QWaylandWindow *target = QWaylandWindow::mouseGrab();
        if (!target)
            target = focusWindow();

        if (isDefinitelyTerminated(mFrameData.axisSource) && !mScrollBeginSent) {
            qCDebug(lcQpaWaylandInput) << "Flushing scroll event sending ScrollBegin";
            target->handleMouse(mParent, WheelEvent(focusWindow(), Qt::ScrollBegin, mParent->mTime,
                                                    mSurfacePos, mGlobalPos, QPoint(), QPoint(),
                                                    Qt::MouseEventNotSynthesized,
                                                    mParent->modifiers()));
            mScrollBeginSent = true;
            mScrollDeltaRemainder = QPointF();
        }

        Qt::ScrollPhase phase = mScrollBeginSent ? Qt::ScrollUpdate : Qt::NoScrollPhase;
        QPoint pixelDelta = mFrameData.pixelDeltaAndError(&mScrollDeltaRemainder);
        Qt::MouseEventSource source = mFrameData.wheelEventSource();

        qCDebug(lcQpaWaylandInput) << "Flushing scroll event" << phase << pixelDelta << angleDelta;
        target->handleMouse(mParent, WheelEvent(focusWindow(), phase, mParent->mTime, mSurfacePos, mGlobalPos,
                                                pixelDelta, angleDelta, source, mParent->modifiers()));
    }

    mFrameData.resetScrollData();
}

void QWaylandInputDevice::Pointer::flushFrameEvent()
{
    if (auto *event = mFrameData.event) {
        if (auto window = event->surface) {
            window->handleMouse(mParent, *event);
        } else if (mFrameData.event->type == QEvent::MouseButtonRelease) {
            // If the window has been destroyed, we still need to report an up event, but it can't
            // be handled by the destroyed window (obviously), so send the event here instead.
            QWindowSystemInterface::handleMouseEvent(nullptr, event->timestamp, event->local,
                                 event->global, event->buttons,
                                 event->button, event->type,
                                 event->modifiers);// , Qt::MouseEventSource source = Qt::MouseEventNotSynthesized);
        }
        delete mFrameData.event;
        mFrameData.event = nullptr;
    }

    //TODO: do modifiers get passed correctly here?
    flushScrollEvent();
}

bool QWaylandInputDevice::Pointer::isDefinitelyTerminated(QtWayland::wl_pointer::axis_source source) const
{
    return source == axis_source_finger;
}

void QWaylandInputDevice::Keyboard::keyboard_keymap(uint32_t format, int32_t fd, uint32_t size)
{
    mKeymapFormat = format;
#if QT_CONFIG(xkbcommon)
    if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
        qCWarning(lcQpaWayland) << "unknown keymap format:" << format;
        close(fd);
        return;
    }

    char *map_str = static_cast<char *>(mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0));
    if (map_str == MAP_FAILED) {
        close(fd);
        return;
    }

    mXkbKeymap.reset(xkb_keymap_new_from_string(mParent->mQDisplay->xkbContext(), map_str,
                                                XKB_KEYMAP_FORMAT_TEXT_V1,
                                                XKB_KEYMAP_COMPILE_NO_FLAGS));
    QXkbCommon::verifyHasLatinLayout(mXkbKeymap.get());

    munmap(map_str, size);
    close(fd);

    if (mXkbKeymap)
        mXkbState.reset(xkb_state_new(mXkbKeymap.get()));
    else
        mXkbState.reset(nullptr);
#else
    Q_UNUSED(fd);
    Q_UNUSED(size);
#endif
}

void QWaylandInputDevice::Keyboard::keyboard_enter(uint32_t time, struct wl_surface *surface, struct wl_array *keys)
{
    Q_UNUSED(time);
    Q_UNUSED(keys);

    if (!surface) {
        // Ignoring wl_keyboard.enter event with null surface. This is either a compositor bug,
        // or it's a race with a wl_surface.destroy request. In either case, ignore the event.
        return;
    }

    if (mFocus) {
        qCWarning(lcQpaWayland()) << "Unexpected wl_keyboard.enter event. Keyboard already has focus";
        disconnect(focusWindow(), &QWaylandWindow::wlSurfaceDestroyed, this, &Keyboard::handleFocusDestroyed);
    }

    mFocus = surface;
    connect(focusWindow(), &QWaylandWindow::wlSurfaceDestroyed, this, &Keyboard::handleFocusDestroyed);

    mParent->mQDisplay->handleKeyboardFocusChanged(mParent);
}

void QWaylandInputDevice::Keyboard::keyboard_leave(uint32_t time, struct wl_surface *surface)
{
    Q_UNUSED(time);

    if (!surface) {
        // Either a compositor bug, or a race condition with wl_surface.destroy, ignore the event.
        return;
    }

    if (surface != mFocus) {
        qCWarning(lcQpaWayland) << "Ignoring unexpected wl_keyboard.leave event."
                                << "wl_surface argument does not match the current focus"
                                << "This is most likely a compositor bug";
        return;
    }
    disconnect(focusWindow(), &QWaylandWindow::wlSurfaceDestroyed, this, &Keyboard::handleFocusDestroyed);
    handleFocusLost();
}

void QWaylandInputDevice::Keyboard::handleKey(ulong timestamp, QEvent::Type type, int key,
                                              Qt::KeyboardModifiers modifiers, quint32 nativeScanCode,
                                              quint32 nativeVirtualKey, quint32 nativeModifiers,
                                              const QString &text, bool autorepeat, ushort count)
{
    QPlatformInputContext *inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext();
    bool filtered = false;

    if (inputContext && !mParent->mQDisplay->usingInputContextFromCompositor()) {
        QKeyEvent event(type, key, modifiers, nativeScanCode, nativeVirtualKey,
                        nativeModifiers, text, autorepeat, count);
        event.setTimestamp(timestamp);
        filtered = inputContext->filterEvent(&event);
    }

    if (!filtered) {
        auto window = focusWindow()->window();

        if (type == QEvent::KeyPress && key == Qt::Key_Menu) {
            auto cursor = window->screen()->handle()->cursor();
            if (cursor) {
                const QPoint globalPos = cursor->pos();
                const QPoint pos = window->mapFromGlobal(globalPos);
                QWindowSystemInterface::handleContextMenuEvent(window, false, pos, globalPos, modifiers);
            }
        }

        QWindowSystemInterface::handleExtendedKeyEvent(window, timestamp, type, key, modifiers,
                nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorepeat, count);
    }
}

void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
{
    if (mKeymapFormat != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1 && mKeymapFormat != WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP) {
        qCWarning(lcQpaWayland) << Q_FUNC_INFO << "unknown keymap format:" << mKeymapFormat;
        return;
    }

    auto *window = focusWindow();
    if (!window) {
        // We destroyed the keyboard focus surface, but the server didn't get the message yet...
        // or the server didn't send an enter event first. In either case, ignore the event.
        return;
    }

    mParent->mSerial = serial;

    const bool isDown = state != WL_KEYBOARD_KEY_STATE_RELEASED;
    if (isDown)
        mParent->mQDisplay->setLastInputDevice(mParent, serial, window);

    if (mKeymapFormat == WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
#if QT_CONFIG(xkbcommon)
        if ((!mXkbKeymap || !mXkbState) && !createDefaultKeymap())
            return;

        auto code = key + 8; // map to wl_keyboard::keymap_format::keymap_format_xkb_v1

        xkb_keysym_t sym = xkb_state_key_get_one_sym(mXkbState.get(), code);

        Qt::KeyboardModifiers modifiers = mParent->modifiers();

        int qtkey = QXkbCommon::keysymToQtKey(sym, modifiers, mXkbState.get(), code);
        QString text = QXkbCommon::lookupString(mXkbState.get(), code);

        QEvent::Type type = isDown ? QEvent::KeyPress : QEvent::KeyRelease;
        handleKey(time, type, qtkey, modifiers, code, sym, mNativeModifiers, text);

        if (state == WL_KEYBOARD_KEY_STATE_PRESSED && xkb_keymap_key_repeats(mXkbKeymap.get(), code) && mRepeatRate > 0) {
            mRepeatKey.key = qtkey;
            mRepeatKey.code = code;
            mRepeatKey.time = time;
            mRepeatKey.text = text;
            mRepeatKey.modifiers = modifiers;
            mRepeatKey.nativeModifiers = mNativeModifiers;
            mRepeatKey.nativeVirtualKey = sym;
            mRepeatTimer.setInterval(mRepeatDelay);
            mRepeatTimer.start();
        } else if (mRepeatKey.code == code) {
            mRepeatTimer.stop();
        }
#else
        Q_UNUSED(time);
        Q_UNUSED(key);
        qCWarning(lcQpaWayland, "xkbcommon not available on this build, not performing key mapping");
        return;
#endif
    } else if (mKeymapFormat == WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP) {
        // raw scan code
        return;
    }
}

void QWaylandInputDevice::Keyboard::handleFocusDestroyed()
{
    // The signal is emitted by QWaylandWindow, which is not necessarily destroyed along with the
    // surface, so we still need to disconnect the signal
    auto *window = qobject_cast<QWaylandWindow *>(sender());
    disconnect(window, &QWaylandWindow::wlSurfaceDestroyed, this, &Keyboard::handleFocusDestroyed);
    Q_ASSERT(window->wlSurface() == mFocus);
    handleFocusLost();
}

void QWaylandInputDevice::Keyboard::handleFocusLost()
{
    mFocus = nullptr;
#if QT_CONFIG(clipboard)
    if (auto *dataDevice = mParent->dataDevice())
        dataDevice->invalidateSelectionOffer();
#endif
#if QT_CONFIG(wayland_client_primary_selection)
    if (auto *device = mParent->primarySelectionDevice())
        device->invalidateSelectionOffer();
#endif
    mParent->mQDisplay->handleKeyboardFocusChanged(mParent);
    mRepeatTimer.stop();
}

void QWaylandInputDevice::Keyboard::keyboard_modifiers(uint32_t serial,
                                             uint32_t mods_depressed,
                                             uint32_t mods_latched,
                                             uint32_t mods_locked,
                                             uint32_t group)
{
    Q_UNUSED(serial);
#if QT_CONFIG(xkbcommon)
    if (mXkbState)
        xkb_state_update_mask(mXkbState.get(),
                              mods_depressed, mods_latched, mods_locked,
                              0, 0, group);
    mNativeModifiers = mods_depressed | mods_latched | mods_locked;
#else
    Q_UNUSED(mods_depressed);
    Q_UNUSED(mods_latched);
    Q_UNUSED(mods_locked);
    Q_UNUSED(group);
#endif
}

void QWaylandInputDevice::Keyboard::keyboard_repeat_info(int32_t rate, int32_t delay)
{
    mRepeatRate = rate;
    mRepeatDelay = delay;
}

void QWaylandInputDevice::Touch::touch_down(uint32_t serial,
                                     uint32_t time,
                                     struct wl_surface *surface,
                                     int32_t id,
                                     wl_fixed_t x,
                                     wl_fixed_t y)
{
    if (!surface)
        return;

    auto *window = QWaylandWindow::fromWlSurface(surface);
    if (!window)
        return; // Ignore foreign surfaces

    mParent->mTime = time;
    mParent->mSerial = serial;
    mFocus = window;
    mParent->mQDisplay->setLastInputDevice(mParent, serial, mFocus);
    QPointF position(wl_fixed_to_double(x), wl_fixed_to_double(y));
    mParent->handleTouchPoint(id, Qt::TouchPointPressed, position);
}

void QWaylandInputDevice::Touch::touch_up(uint32_t serial, uint32_t time, int32_t id)
{
    Q_UNUSED(serial);
    Q_UNUSED(time);
    mParent->handleTouchPoint(id, Qt::TouchPointReleased);

    if (allTouchPointsReleased()) {
        mFocus = nullptr;

        // As of Weston 7.0.0 there is no touch_frame after the last touch_up
        // (i.e. when the last finger is released). To accommodate for this, issue a
        // touch_frame. This cannot hurt since it is safe to call the touch_frame
        // handler multiple times when there are no points left.
        // See: https://gitlab.freedesktop.org/wayland/weston/issues/44
        // TODO: change logging category to lcQpaWaylandInput in newer versions.
        qCDebug(lcQpaWayland, "Generating fake frame event to work around Weston bug");
        touch_frame();
    }
}

void QWaylandInputDevice::Touch::touch_motion(uint32_t time, int32_t id, wl_fixed_t x, wl_fixed_t y)
{
    Q_UNUSED(time);
    QPointF position(wl_fixed_to_double(x), wl_fixed_to_double(y));
    mParent->handleTouchPoint(id, Qt::TouchPointMoved, position);
}

void QWaylandInputDevice::Touch::touch_cancel()
{
    mPendingTouchPoints.clear();

    QWaylandTouchExtension *touchExt = mParent->mQDisplay->touchExtension();
    if (touchExt)
        touchExt->touchCanceled();

    QWindowSystemInterface::handleTouchCancelEvent(nullptr, mParent->mTouchDevice);
}

void QWaylandInputDevice::handleTouchPoint(int id, Qt::TouchPointState state, const QPointF &surfacePosition)
{
    auto end = mTouch->mPendingTouchPoints.end();
    auto it = std::find_if(mTouch->mPendingTouchPoints.begin(), end, [id](const QWindowSystemInterface::TouchPoint &tp){ return tp.id == id; });
    if (it == end) {
        it = mTouch->mPendingTouchPoints.insert(end, QWindowSystemInterface::TouchPoint());
        it->id = id;
    }
    QWindowSystemInterface::TouchPoint &tp = *it;

    // Only moved and pressed needs to update/set position
    if (state == Qt::TouchPointMoved || state == Qt::TouchPointPressed) {
        // We need a global (screen) position.
        QWaylandWindow *win = mTouch->mFocus;

        //is it possible that mTouchFocus is null;
        if (!win && mPointer)
            win = mPointer->focusWindow();
        if (!win && mKeyboard)
            win = mKeyboard->focusWindow();
        if (!win || !win->window())
            return;

        tp.area = QRectF(0, 0, 8, 8);
        QPointF localPosition = win->mapFromWlSurface(surfacePosition);
        // TODO: This doesn't account for high dpi scaling for the delta, but at least it matches
        // what we have for mouse input.
        QPointF delta = localPosition - localPosition.toPoint();
        QPointF globalPosition = win->window()->mapToGlobal(localPosition.toPoint()) + delta;
        tp.area.moveCenter(globalPosition);
    }

    // If the touch point was pressed earlier this frame, we don't want to overwrite its state.
    if (tp.state != Qt::TouchPointPressed)
        tp.state = state;

    tp.pressure = tp.state == Qt::TouchPointReleased ? 0 : 1;
}

bool QWaylandInputDevice::Touch::allTouchPointsReleased()
{
    for (const auto &tp : qAsConst(mPendingTouchPoints)) {
        if (tp.state != Qt::TouchPointReleased)
            return false;
    }
    return true;
}

void QWaylandInputDevice::Touch::releasePoints()
{
    if (mPendingTouchPoints.empty())
        return;

    for (QWindowSystemInterface::TouchPoint &tp : mPendingTouchPoints)
        tp.state = Qt::TouchPointReleased;

    touch_frame();
}

void QWaylandInputDevice::Touch::touch_frame()
{
    // TODO: early return if no events?

    QWindow *window = mFocus ? mFocus->window() : nullptr;

    if (mFocus) {
        const QWindowSystemInterface::TouchPoint &tp = mPendingTouchPoints.last();
        // When the touch event is received, the global pos is calculated with the margins
        // in mind. Now we need to adjust again to get the correct local pos back.
        QMargins margins = window->frameMargins();
        QPoint p = tp.area.center().toPoint();
        QPointF localPos(window->mapFromGlobal(QPoint(p.x() + margins.left(), p.y() + margins.top())));
        if (mFocus->touchDragDecoration(mParent, localPos, tp.area.center(), tp.state, mParent->modifiers()))
            return;
    }

    QWindowSystemInterface::handleTouchEvent(window, mParent->mTouchDevice, mPendingTouchPoints);

    // Prepare state for next frame
    const auto prevTouchPoints = mPendingTouchPoints;
    mPendingTouchPoints.clear();
    for (const auto &prevPoint: prevTouchPoints) {
        // All non-released touch points should be part of the next touch event
        if (prevPoint.state != Qt::TouchPointReleased) {
            QWindowSystemInterface::TouchPoint tp = prevPoint;
            tp.state = Qt::TouchPointStationary; // ... as stationary (unless proven otherwise)
            mPendingTouchPoints.append(tp);
        }
    }

}

}

QT_END_NAMESPACE
