diff options
Diffstat (limited to 'src/client/qwaylandinputdevice.cpp')
-rw-r--r-- | src/client/qwaylandinputdevice.cpp | 561 |
1 files changed, 355 insertions, 206 deletions
diff --git a/src/client/qwaylandinputdevice.cpp b/src/client/qwaylandinputdevice.cpp index a9da452dc..ce04971ba 100644 --- a/src/client/qwaylandinputdevice.cpp +++ b/src/client/qwaylandinputdevice.cpp @@ -1,45 +1,10 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qwaylandinputdevice_p.h" #include "qwaylandintegration_p.h" +#include "qwaylandtextinputv3_p.h" #include "qwaylandwindow_p.h" #include "qwaylandsurface_p.h" #include "qwaylandbuffer_p.h" @@ -50,17 +15,26 @@ #if QT_CONFIG(wayland_client_primary_selection) #include "qwaylandprimaryselectionv1_p.h" #endif +#if QT_CONFIG(tabletevent) +#include "qwaylandtabletv2_p.h" +#endif +#include "qwaylandpointergestures_p.h" #include "qwaylandtouch_p.h" #include "qwaylandscreen_p.h" #include "qwaylandcursor_p.h" #include "qwaylanddisplay_p.h" #include "qwaylandshmbackingstore_p.h" +#include "qwaylandtextinputv1_p.h" +#include "qwaylandtextinputv2_p.h" +#include "qwaylandtextinputinterface_p.h" #include "qwaylandinputcontext_p.h" +#include "qwaylandinputmethodcontext_p.h" #include <QtGui/private/qpixmap_raster_p.h> #include <QtGui/private/qguiapplication_p.h> #include <qpa/qplatformwindow.h> #include <qpa/qplatforminputcontext.h> +#include <qpa/qplatformtheme.h> #include <QDebug> #include <unistd.h> @@ -72,6 +46,7 @@ #endif #include <QtGui/QGuiApplication> +#include <QtGui/QPointingDevice> QT_BEGIN_NAMESPACE @@ -79,21 +54,27 @@ namespace QtWaylandClient { Q_LOGGING_CATEGORY(lcQpaWaylandInput, "qt.qpa.wayland.input"); +// The maximum number of concurrent touchpoints is not exposed in wayland, so we assume a +// reasonable number of them. As of 2021 most touchscreen panels support 10 concurrent touchpoints. +static const int MaxTouchPoints = 10; + QWaylandInputDevice::Keyboard::Keyboard(QWaylandInputDevice *p) : mParent(p) { - mRepeatTimer.callOnTimeout([&]() { + init(p->get_keyboard()); + mRepeatTimer.callOnTimeout(this, [&]() { 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(mRepeatRate); - handleKey(mRepeatKey.time, QEvent::KeyRelease, mRepeatKey.key, mRepeatKey.modifiers, - mRepeatKey.code, mRepeatKey.nativeVirtualKey, mRepeatKey.nativeModifiers, + mRepeatTimer.setInterval(1000 / mRepeatRate); + Qt::KeyboardModifiers modifiers = this->modifiers(); + handleKey(mRepeatKey.time, QEvent::KeyRelease, mRepeatKey.key, modifiers, + mRepeatKey.code, mRepeatKey.nativeVirtualKey, this->mNativeModifiers, mRepeatKey.text, true); - handleKey(mRepeatKey.time, QEvent::KeyPress, mRepeatKey.key, mRepeatKey.modifiers, - mRepeatKey.code, mRepeatKey.nativeVirtualKey, mRepeatKey.nativeModifiers, + handleKey(mRepeatKey.time, QEvent::KeyPress, mRepeatKey.key, modifiers, + mRepeatKey.code, mRepeatKey.nativeVirtualKey, this->mNativeModifiers, mRepeatKey.text, true); }); } @@ -128,8 +109,8 @@ bool QWaylandInputDevice::Keyboard::createDefaultKeymap() QWaylandInputDevice::Keyboard::~Keyboard() { if (mFocus) - QWindowSystemInterface::handleWindowActivated(nullptr); - if (mParent->mVersion >= 3) + QWindowSystemInterface::handleFocusWindowChanged(nullptr); + if (version() >= 3) wl_keyboard_release(object()); else wl_keyboard_destroy(object()); @@ -137,17 +118,28 @@ QWaylandInputDevice::Keyboard::~Keyboard() QWaylandWindow *QWaylandInputDevice::Keyboard::focusWindow() const { - return mFocus ? QWaylandWindow::fromWlSurface(mFocus) : nullptr; + return mFocus ? mFocus->waylandWindow() : nullptr; } QWaylandInputDevice::Pointer::Pointer(QWaylandInputDevice *seat) : mParent(seat) { + init(seat->get_pointer()); +#if QT_CONFIG(cursor) + if (auto cursorShapeManager = seat->mQDisplay->cursorShapeManager()) { + mCursor.shape.reset(new QWaylandCursorShape(cursorShapeManager->get_pointer(object()))); + } + + mCursor.frameTimer.setSingleShot(true); + mCursor.frameTimer.callOnTimeout(this, [&]() { + cursorTimerCallback(); + }); +#endif } QWaylandInputDevice::Pointer::~Pointer() { - if (mParent->mVersion >= 3) + if (version() >= 3) wl_pointer_release(object()); else wl_pointer_destroy(object()); @@ -162,23 +154,16 @@ QWaylandWindow *QWaylandInputDevice::Pointer::focusWindow() const class WlCallback : public QtWayland::wl_callback { public: - explicit WlCallback(::wl_callback *callback, std::function<void(uint32_t)> fn, bool autoDelete = false) + explicit WlCallback(::wl_callback *callback, std::function<void(uint32_t)> fn) : 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 @@ -188,25 +173,21 @@ public: : 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() + void reset() { - uint serial = m_pointer->mEnterSerial; - Q_ASSERT(serial); - m_pointer->set_cursor(serial, nullptr, 0, 0); m_setSerial = 0; + m_hotspot = QPoint(); } // 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); + Q_ASSERT(bufferScale == 1 || version() >= 3); auto enterSerial = m_pointer->mEnterSerial; if (m_setSerial < enterSerial || m_hotspot != hotspot) { @@ -215,7 +196,7 @@ public: m_hotspot = hotspot; } - if (m_version >= 3) + if (version() >= 3) set_buffer_scale(bufferScale); attach(buffer, 0, 0); @@ -224,7 +205,7 @@ public: if (animated) { m_frameCallback.reset(new WlCallback(frame(), [this](uint32_t time){ Q_UNUSED(time); - m_pointer->updateCursor(); + m_pointer->cursorFrameCallback(); })); } commit(); @@ -241,29 +222,15 @@ public: 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) + if (seat()->mQDisplay->compositor()->version() < 3) { return 1; + } if (auto *s = mCursor.surface.data()) { if (s->outputScale() > 0) @@ -275,17 +242,30 @@ int QWaylandInputDevice::Pointer::idealCursorScale() const void QWaylandInputDevice::Pointer::updateCursorTheme() { + QString cursorThemeName; + QSize cursorSize; + + if (const QPlatformTheme *platformTheme = QGuiApplicationPrivate::platformTheme()) { + cursorThemeName = platformTheme->themeHint(QPlatformTheme::MouseCursorTheme).toString(); + cursorSize = platformTheme->themeHint(QPlatformTheme::MouseCursorSize).toSize(); + } + + if (cursorThemeName.isEmpty()) + cursorThemeName = QStringLiteral("default"); + if (cursorSize.isEmpty()) + cursorSize = QSize(24, 24); + int scale = idealCursorScale(); - int pixelSize = cursorSize() * scale; + int pixelSize = cursorSize.width() * scale; auto *display = seat()->mQDisplay; - mCursor.theme = display->loadCursorTheme(cursorThemeName(), pixelSize); + mCursor.theme = display->loadCursorTheme(cursorThemeName, pixelSize); if (!mCursor.theme) return; // A warning has already been printed in loadCursorTheme - if (auto *arrow = mCursor.theme->cursorImage(Qt::ArrowCursor)) { - int arrowPixelSize = qMax(arrow->width, arrow->height); // Not all cursor themes are square - while (scale > 1 && arrowPixelSize / scale < cursorSize()) + 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.width()) --scale; } else { qCWarning(lcQpaWayland) << "Cursor theme does not support the arrow cursor"; @@ -302,7 +282,8 @@ void QWaylandInputDevice::Pointer::updateCursor() if (shape == Qt::BlankCursor) { if (mCursor.surface) - mCursor.surface->hide(); + mCursor.surface->reset(); + set_cursor(mEnterSerial, nullptr, 0, 0); return; } @@ -318,6 +299,14 @@ void QWaylandInputDevice::Pointer::updateCursor() return; } + if (mCursor.shape) { + if (mCursor.surface) { + mCursor.surface->reset(); + } + mCursor.shape->setShape(mEnterSerial, shape); + return; + } + if (!mCursor.theme || idealCursorScale() != mCursor.themeBufferScale) updateCursorTheme(); @@ -326,12 +315,26 @@ void QWaylandInputDevice::Pointer::updateCursor() // Set from shape using theme uint time = seat()->mCursor.animationTimer.elapsed(); - if (struct ::wl_cursor_image *image = mCursor.theme->cursorImage(shape, time)) { + + 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 = image->delay > 0; + bool animated = duration > 0; + if (animated) { + mCursor.gotFrameCallback = false; + mCursor.gotTimerCallback = false; + mCursor.frameTimer.start(duration); + } getOrCreateCursorSurface()->update(buffer, hotspot, size, bufferScale, animated); return; } @@ -346,26 +349,42 @@ CursorSurface *QWaylandInputDevice::Pointer::getOrCreateCursorSurface() 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) { + init(p->get_touch()); } QWaylandInputDevice::Touch::~Touch() { - if (mParent->mVersion >= 3) + if (version() >= 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)) + : QtWayland::wl_seat(display->wl_registry(), id, qMin(version, 9)) , mQDisplay(display) , mDisplay(display->wl_display()) - , mVersion(qMin(version, 5)) { #if QT_CONFIG(wayland_datadevice) if (mQDisplay->dndSelectionHandler()) { @@ -379,16 +398,33 @@ QWaylandInputDevice::QWaylandInputDevice(QWaylandDisplay *display, int version, setPrimarySelectionDevice(psm->createDevice(this)); #endif - if (mQDisplay->textInputManager()) - mTextInput.reset(new QWaylandTextInput(mQDisplay, mQDisplay->textInputManager()->get_text_input(wl_seat()))); + if (mQDisplay->textInputManagerv1()) { + auto textInput = new QWaylandTextInputv1(mQDisplay, mQDisplay->textInputManagerv1()->create_text_input()); + textInput->setSeat(wl_seat()); + mTextInput.reset(textInput); + } + + if (mQDisplay->textInputManagerv2()) + mTextInput.reset(new QWaylandTextInputv2(mQDisplay, mQDisplay->textInputManagerv2()->get_text_input(wl_seat()))); + if (mQDisplay->textInputManagerv3()) + mTextInput.reset(new QWaylandTextInputv3(mQDisplay, mQDisplay->textInputManagerv3()->get_text_input(wl_seat()))); + + if (mQDisplay->textInputMethodManager()) + mTextInputMethod.reset(new QWaylandTextInputMethod(mQDisplay, mQDisplay->textInputMethodManager()->get_text_input_method(wl_seat()))); + +#if QT_CONFIG(tabletevent) + if (auto *tm = mQDisplay->tabletManager()) + mTabletSeat.reset(new QWaylandTabletSeatV2(tm, this)); +#endif } QWaylandInputDevice::~QWaylandInputDevice() { - delete mPointer; - delete mKeyboard; - delete mTouch; + if (version() >= WL_SEAT_RELEASE_SINCE_VERSION) + release(); + else + wl_seat_destroy(object()); } void QWaylandInputDevice::seat_capabilities(uint32_t caps) @@ -396,37 +432,54 @@ void QWaylandInputDevice::seat_capabilities(uint32_t caps) mCaps = caps; if (caps & WL_SEAT_CAPABILITY_KEYBOARD && !mKeyboard) { - mKeyboard = createKeyboard(this); - mKeyboard->init(get_keyboard()); + mKeyboard.reset(createKeyboard(this)); } else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && mKeyboard) { - delete mKeyboard; - mKeyboard = nullptr; + mKeyboard.reset(); } if (caps & WL_SEAT_CAPABILITY_POINTER && !mPointer) { - mPointer = createPointer(this); - mPointer->init(get_pointer()); + mPointer.reset(createPointer(this)); + + auto *pointerGestures = mQDisplay->pointerGestures(); + if (pointerGestures) { + // NOTE: The name of the device and its system ID are not exposed on Wayland. + mTouchPadDevice = new QPointingDevice( + QLatin1String("touchpad"), 0, QInputDevice::DeviceType::TouchPad, + QPointingDevice::PointerType::Finger, QInputDevice::Capability::Position, + MaxTouchPoints, 0, QString(), QPointingDeviceUniqueId(), this); + QWindowSystemInterface::registerInputDevice(mTouchPadDevice); + mPointerGesturePinch.reset(pointerGestures->createPointerGesturePinch(this)); + mPointerGesturePinch->init(pointerGestures->get_pinch_gesture(mPointer->object())); + mPointerGestureSwipe.reset(pointerGestures->createPointerGestureSwipe(this)); + mPointerGestureSwipe->init(pointerGestures->get_swipe_gesture(mPointer->object())); + } } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && mPointer) { - delete mPointer; - mPointer = nullptr; + mPointer.reset(); + mPointerGesturePinch.reset(); + mPointerGestureSwipe.reset(); } if (caps & WL_SEAT_CAPABILITY_TOUCH && !mTouch) { - mTouch = createTouch(this); - mTouch->init(get_touch()); + mTouch.reset(createTouch(this)); if (!mTouchDevice) { - mTouchDevice = new QTouchDevice; - mTouchDevice->setType(QTouchDevice::TouchScreen); - mTouchDevice->setCapabilities(QTouchDevice::Position); - QWindowSystemInterface::registerTouchDevice(mTouchDevice); + // TODO number of touchpoints, actual name and ID + mTouchDevice = new QPointingDevice( + QLatin1String("some touchscreen"), 0, QInputDevice::DeviceType::TouchScreen, + QPointingDevice::PointerType::Finger, QInputDevice::Capability::Position, + MaxTouchPoints, 0,QString(), QPointingDeviceUniqueId(), this); + QWindowSystemInterface::registerInputDevice(mTouchDevice); } } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && mTouch) { - delete mTouch; - mTouch = nullptr; + mTouch.reset(); } } +void QWaylandInputDevice::seat_name(const QString &name) +{ + mSeatName = name; +} + QWaylandInputDevice::Keyboard *QWaylandInputDevice::createKeyboard(QWaylandInputDevice *device) { return new Keyboard(device); @@ -444,17 +497,27 @@ QWaylandInputDevice::Touch *QWaylandInputDevice::createTouch(QWaylandInputDevice QWaylandInputDevice::Keyboard *QWaylandInputDevice::keyboard() const { - return mKeyboard; + return mKeyboard.data(); } QWaylandInputDevice::Pointer *QWaylandInputDevice::pointer() const { - return mPointer; + return mPointer.data(); +} + +QWaylandPointerGestureSwipe *QWaylandInputDevice::pointerGestureSwipe() const +{ + return mPointerGestureSwipe.data(); +} + +QWaylandPointerGesturePinch *QWaylandInputDevice::pointerGesturePinch() const +{ + return mPointerGesturePinch.data(); } QWaylandInputDevice::Touch *QWaylandInputDevice::touch() const { - return mTouch; + return mTouch.data(); } void QWaylandInputDevice::handleEndDrag() @@ -489,16 +552,26 @@ QWaylandPrimarySelectionDeviceV1 *QWaylandInputDevice::primarySelectionDevice() } #endif -void QWaylandInputDevice::setTextInput(QWaylandTextInput *textInput) +void QWaylandInputDevice::setTextInput(QWaylandTextInputInterface *textInput) { mTextInput.reset(textInput); } -QWaylandTextInput *QWaylandInputDevice::textInput() const +void QWaylandInputDevice::setTextInputMethod(QWaylandTextInputMethod *textInputMethod) +{ + mTextInputMethod.reset(textInputMethod); +} + +QWaylandTextInputInterface *QWaylandInputDevice::textInput() const { return mTextInput.data(); } +QWaylandTextInputMethod *QWaylandInputDevice::textInputMethod() const +{ + return mTextInputMethod.data(); +} + void QWaylandInputDevice::removeMouseButtonFromState(Qt::MouseButton button) { if (mPointer) @@ -594,8 +667,8 @@ class EnterEvent : public QWaylandPointerEvent { public: EnterEvent(QWaylandWindow *surface, const QPointF &local, const QPointF &global) - : QWaylandPointerEvent(QWaylandPointerEvent::Enter, Qt::NoScrollPhase, surface, 0, - local, global, nullptr, Qt::NoModifier) + : QWaylandPointerEvent(QEvent::Enter, Qt::NoScrollPhase, surface, 0, + local, global, Qt::NoButton, Qt::NoButton, Qt::NoModifier) {} }; @@ -620,7 +693,7 @@ void QWaylandInputDevice::Pointer::pointer_enter(uint32_t serial, struct wl_surf 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()); + mGlobalPos = window->mapToGlobal(mSurfacePos.toPoint()); mParent->mSerial = serial; mEnterSerial = serial; @@ -639,13 +712,18 @@ class LeaveEvent : public QWaylandPointerEvent { public: LeaveEvent(QWaylandWindow *surface, const QPointF &localPos, const QPointF &globalPos) - : QWaylandPointerEvent(QWaylandPointerEvent::Leave, Qt::NoScrollPhase, surface, 0, - localPos, globalPos, nullptr, Qt::NoModifier) + : 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) { + invalidateFocus(); + mButtons = Qt::NoButton; + + mParent->mTime = time; + // The event may arrive after destroying the window, indicated by // a null surface. if (!surface) @@ -657,11 +735,6 @@ void QWaylandInputDevice::Pointer::pointer_leave(uint32_t time, struct wl_surfac if (!QWaylandWindow::mouseGrab()) setFrameEvent(new LeaveEvent(window, mSurfacePos, mGlobalPos)); - - invalidateFocus(); - mButtons = Qt::NoButton; - - mParent->mTime = time; } class MotionEvent : public QWaylandPointerEvent @@ -669,8 +742,8 @@ class MotionEvent : public QWaylandPointerEvent public: MotionEvent(QWaylandWindow *surface, ulong timestamp, const QPointF &localPos, const QPointF &globalPos, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers) - : QWaylandPointerEvent(QWaylandPointerEvent::Motion, Qt::NoScrollPhase, surface, - timestamp, localPos, globalPos, buttons, modifiers) + : QWaylandPointerEvent(QEvent::MouseMove, Qt::NoScrollPhase, surface, + timestamp, localPos, globalPos, buttons, Qt::NoButton, modifiers) { } }; @@ -686,7 +759,7 @@ void QWaylandInputDevice::Pointer::pointer_motion(uint32_t time, wl_fixed_t surf 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()); + QPointF global = window->mapToGlobal(pos.toPoint()); global += delta; mSurfacePos = pos; @@ -698,7 +771,7 @@ void QWaylandInputDevice::Pointer::pointer_motion(uint32_t time, wl_fixed_t surf // 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()); + global = grab->mapToGlobal(pos.toPoint()); window = grab; } setFrameEvent(new MotionEvent(window, time, pos, global, mButtons, mParent->modifiers())); @@ -708,9 +781,10 @@ class PressEvent : public QWaylandPointerEvent { public: PressEvent(QWaylandWindow *surface, ulong timestamp, const QPointF &localPos, - const QPointF &globalPos, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers) - : QWaylandPointerEvent(QWaylandPointerEvent::Press, Qt::NoScrollPhase, surface, - timestamp, localPos, globalPos, buttons, modifiers) + const QPointF &globalPos, Qt::MouseButtons buttons, Qt::MouseButton button, + Qt::KeyboardModifiers modifiers) + : QWaylandPointerEvent(QEvent::MouseButtonPress, Qt::NoScrollPhase, surface, + timestamp, localPos, globalPos, buttons, button, modifiers) { } }; @@ -719,9 +793,10 @@ class ReleaseEvent : public QWaylandPointerEvent { public: ReleaseEvent(QWaylandWindow *surface, ulong timestamp, const QPointF &localPos, - const QPointF &globalPos, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers) - : QWaylandPointerEvent(QWaylandPointerEvent::Release, Qt::NoScrollPhase, surface, - timestamp, localPos, globalPos, buttons, modifiers) + const QPointF &globalPos, Qt::MouseButtons buttons, Qt::MouseButton button, + Qt::KeyboardModifiers modifiers) + : QWaylandPointerEvent(QEvent::MouseButtonRelease, Qt::NoScrollPhase, surface, + timestamp, localPos, globalPos, buttons, button, modifiers) { } }; @@ -760,6 +835,8 @@ void QWaylandInputDevice::Pointer::pointer_button(uint32_t serial, uint32_t time default: return; // invalid button number (as far as Qt is concerned) } + mLastButton = qt_button; + if (state) mButtons |= qt_button; else @@ -776,15 +853,15 @@ void QWaylandInputDevice::Pointer::pointer_button(uint32_t serial, uint32_t time QPointF global = mGlobalPos; if (grab && grab != focusWindow()) { pos = QPointF(-1, -1); - global = grab->window()->mapToGlobal(pos.toPoint()); + global = grab->mapToGlobal(pos.toPoint()); window = grab; } if (state) - setFrameEvent(new PressEvent(window, time, pos, global, mButtons, mParent->modifiers())); + setFrameEvent(new PressEvent(window, time, pos, global, mButtons, qt_button, mParent->modifiers())); else - setFrameEvent(new ReleaseEvent(window, time, pos, global, mButtons, mParent->modifiers())); + setFrameEvent(new ReleaseEvent(window, time, pos, global, mButtons, qt_button, mParent->modifiers())); } void QWaylandInputDevice::Pointer::invalidateFocus() @@ -798,10 +875,13 @@ void QWaylandInputDevice::Pointer::invalidateFocus() void QWaylandInputDevice::Pointer::releaseButtons() { + if (mButtons == Qt::NoButton) + return; + mButtons = Qt::NoButton; if (auto *window = focusWindow()) { - MotionEvent e(focusWindow(), mParent->mTime, mSurfacePos, mGlobalPos, mButtons, mParent->modifiers()); + ReleaseEvent e(focusWindow(), mParent->mTime, mSurfacePos, mGlobalPos, mButtons, mLastButton, mParent->modifiers()); window->handleMouse(mParent, e); } } @@ -811,9 +891,11 @@ 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(QWaylandPointerEvent::Wheel, phase, surface, timestamp, - local, global, pixelDelta, angleDelta, source, modifiers) + Qt::MouseEventSource source, Qt::KeyboardModifiers modifiers, bool inverted) + : QWaylandPointerEvent(QEvent::Wheel, phase, surface, timestamp, local, global, + modifiers & Qt::AltModifier ? pixelDelta.transposed() : pixelDelta, + modifiers & Qt::AltModifier ? angleDelta.transposed() : angleDelta, + source, modifiers, inverted) { } }; @@ -844,7 +926,7 @@ void QWaylandInputDevice::Pointer::pointer_axis(uint32_t time, uint32_t axis, in mParent->mTime = time; - if (mParent->mVersion < WL_POINTER_FRAME_SINCE_VERSION) { + if (version() < WL_POINTER_FRAME_SINCE_VERSION) { qCDebug(lcQpaWaylandInput) << "Flushing new event; no frame event in this version"; flushFrameEvent(); } @@ -867,6 +949,8 @@ void QWaylandInputDevice::Pointer::pointer_axis_source(uint32_t source) case axis_source_continuous: qCDebug(lcQpaWaylandInput) << "Axis source continuous"; break; + case axis_source_wheel_tilt: + qCDebug(lcQpaWaylandInput) << "Axis source wheel tilt"; } mFrameData.axisSource = axis_source(source); } @@ -905,8 +989,9 @@ void QWaylandInputDevice::Pointer::pointer_axis_stop(uint32_t time, uint32_t axi if (!target) target = focusWindow(); Qt::KeyboardModifiers mods = mParent->modifiers(); + const bool inverted = mFrameData.verticalAxisInverted || mFrameData.horizontalAxisInverted; WheelEvent wheelEvent(focusWindow(), Qt::ScrollEnd, mParent->mTime, mSurfacePos, mGlobalPos, - QPoint(), QPoint(), Qt::MouseEventNotSynthesized, mods); + QPoint(), QPoint(), Qt::MouseEventNotSynthesized, mods, inverted); target->handleMouse(mParent, wheelEvent); mScrollBeginSent = false; mScrollDeltaRemainder = QPointF(); @@ -917,14 +1002,16 @@ void QWaylandInputDevice::Pointer::pointer_axis_discrete(uint32_t axis, int32_t if (!focusWindow()) return; + const int32_t delta120 = value * 15 * 8; + switch (axis) { case axis_vertical_scroll: qCDebug(lcQpaWaylandInput) << "wl_pointer.axis_discrete vertical:" << value; - mFrameData.discreteDelta.ry() += value; + mFrameData.delta120.ry() += delta120; break; case axis_horizontal_scroll: qCDebug(lcQpaWaylandInput) << "wl_pointer.axis_discrete horizontal:" << value; - mFrameData.discreteDelta.rx() += value; + mFrameData.delta120.rx() += delta120; break; default: //TODO: is this really needed? @@ -933,6 +1020,41 @@ void QWaylandInputDevice::Pointer::pointer_axis_discrete(uint32_t axis, int32_t } } +void QWaylandInputDevice::Pointer::pointer_axis_value120(uint32_t axis, int32_t value) +{ + if (!focusWindow()) + return; + + switch (axis) { + case axis_vertical_scroll: + qCDebug(lcQpaWaylandInput) << "wl_pointer.axis_value120 vertical:" << value; + mFrameData.delta120.ry() += value; + break; + case axis_horizontal_scroll: + qCDebug(lcQpaWaylandInput) << "wl_pointer.axis_value120 horizontal:" << value; + mFrameData.delta120.rx() += value; + break; + default: + qCWarning(lcQpaWaylandInput) << "wl_pointer.axis_value120: Unknown axis:" << axis; + return; + } +} + +void QWaylandInputDevice::Pointer::pointer_axis_relative_direction(uint32_t axis, uint32_t direction) +{ + const bool inverted = direction == axis_relative_direction_inverted; + switch (axis) { + case axis_vertical_scroll: + mFrameData.verticalAxisInverted = inverted; + break; + case axis_horizontal_scroll: + mFrameData.horizontalAxisInverted = inverted; + break; + default: + qCWarning(lcQpaWaylandInput) << "wl_pointer.axis_relative_direction: Unknown axis:" << axis; + } +} + void QWaylandInputDevice::Pointer::setFrameEvent(QWaylandPointerEvent *event) { qCDebug(lcQpaWaylandInput) << "Setting frame event " << event->type; @@ -943,7 +1065,7 @@ void QWaylandInputDevice::Pointer::setFrameEvent(QWaylandPointerEvent *event) mFrameData.event = event; - if (mParent->mVersion < WL_POINTER_FRAME_SINCE_VERSION) { + if (version() < WL_POINTER_FRAME_SINCE_VERSION) { qCDebug(lcQpaWaylandInput) << "Flushing new event; no frame event in this version"; flushFrameEvent(); } @@ -951,9 +1073,11 @@ void QWaylandInputDevice::Pointer::setFrameEvent(QWaylandPointerEvent *event) void QWaylandInputDevice::Pointer::FrameData::resetScrollData() { - discreteDelta = QPoint(); + delta120 = QPoint(); delta = QPointF(); axisSource = axis_source_wheel; + horizontalAxisInverted = false; + verticalAxisInverted = false; } bool QWaylandInputDevice::Pointer::FrameData::hasPixelDelta() const @@ -968,6 +1092,8 @@ bool QWaylandInputDevice::Pointer::FrameData::hasPixelDelta() const case axis_source_finger: case axis_source_continuous: return !delta.isNull(); + default: + return false; } } @@ -982,20 +1108,27 @@ QPoint QWaylandInputDevice::Pointer::FrameData::pixelDeltaAndError(QPointF *accu *accumulatedError += delta - pixelDelta; Q_ASSERT(qAbs(accumulatedError->x()) < 1.0); Q_ASSERT(qAbs(accumulatedError->y()) < 1.0); + + // for continuous scroll events things should be + // in the same direction + // i.e converted so downwards surface co-ordinates (positive axis_value) + // goes to downwards in wheel event (negative value) + pixelDelta *= -1; return pixelDelta; } QPoint QWaylandInputDevice::Pointer::FrameData::angleDelta() const { - if (discreteDelta.isNull()) { + if (delta120.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; + // 1 click = 15 degrees, i.e. 120 is one click. It's also in the opposite + // direction of surface space. + return -delta120; } Qt::MouseEventSource QWaylandInputDevice::Pointer::FrameData::wheelEventSource() const @@ -1026,7 +1159,7 @@ void QWaylandInputDevice::Pointer::flushScrollEvent() target->handleMouse(mParent, WheelEvent(focusWindow(), Qt::ScrollBegin, mParent->mTime, mSurfacePos, mGlobalPos, QPoint(), QPoint(), Qt::MouseEventNotSynthesized, - mParent->modifiers())); + mParent->modifiers(), false)); mScrollBeginSent = true; mScrollDeltaRemainder = QPointF(); } @@ -1035,11 +1168,15 @@ void QWaylandInputDevice::Pointer::flushScrollEvent() QPoint pixelDelta = mFrameData.pixelDeltaAndError(&mScrollDeltaRemainder); Qt::MouseEventSource source = mFrameData.wheelEventSource(); + + // The wayland protocol has separate horizontal and vertical axes, Qt has just the one inverted flag + // Pragmatically it should't come up + const bool inverted = mFrameData.verticalAxisInverted || mFrameData.horizontalAxisInverted; + qCDebug(lcQpaWaylandInput) << "Flushing scroll event" << phase << pixelDelta << angleDelta; target->handleMouse(mParent, WheelEvent(focusWindow(), phase, mParent->mTime, mSurfacePos, mGlobalPos, - pixelDelta, angleDelta, source, mParent->modifiers())); + pixelDelta, angleDelta, source, mParent->modifiers(), inverted)); } - mFrameData.resetScrollData(); } @@ -1048,11 +1185,13 @@ void QWaylandInputDevice::Pointer::flushFrameEvent() if (auto *event = mFrameData.event) { if (auto window = event->surface) { window->handleMouse(mParent, *event); - } else if (mFrameData.event->type == QWaylandPointerEvent::Type::Release) { + } 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->modifiers); + event->global, event->buttons, + event->button, event->type, + event->modifiers);// , Qt::MouseEventSource source = Qt::MouseEventNotSynthesized); } delete mFrameData.event; mFrameData.event = nullptr; @@ -1077,7 +1216,7 @@ void QWaylandInputDevice::Keyboard::keyboard_keymap(uint32_t format, int32_t fd, return; } - char *map_str = static_cast<char *>(mmap(nullptr, size, PROT_READ, MAP_SHARED, fd, 0)); + char *map_str = static_cast<char *>(mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0)); if (map_str == MAP_FAILED) { close(fd); return; @@ -1112,13 +1251,17 @@ void QWaylandInputDevice::Keyboard::keyboard_enter(uint32_t time, struct wl_surf return; } + QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface); + if (!window) + return; + if (mFocus) { qCWarning(lcQpaWayland()) << "Unexpected wl_keyboard.enter event. Keyboard already has focus"; - disconnect(focusWindow(), &QWaylandWindow::wlSurfaceDestroyed, this, &Keyboard::handleFocusDestroyed); + disconnect(mFocus, &QWaylandSurface::destroyed, this, &Keyboard::handleFocusDestroyed); } - mFocus = surface; - connect(focusWindow(), &QWaylandWindow::wlSurfaceDestroyed, this, &Keyboard::handleFocusDestroyed); + mFocus = window->waylandSurface(); + connect(mFocus, &QWaylandSurface::destroyed, this, &Keyboard::handleFocusDestroyed); mParent->mQDisplay->handleKeyboardFocusChanged(mParent); } @@ -1132,13 +1275,17 @@ void QWaylandInputDevice::Keyboard::keyboard_leave(uint32_t time, struct wl_surf return; } - if (surface != mFocus) { + QWaylandWindow *window = QWaylandWindow::fromWlSurface(surface); + if (!window) + return; + + if (window->waylandSurface() != 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); + disconnect(mFocus, &QWaylandSurface::destroyed, this, &Keyboard::handleFocusDestroyed); handleFocusLost(); } @@ -1150,7 +1297,7 @@ void QWaylandInputDevice::Keyboard::handleKey(ulong timestamp, QEvent::Type type QPlatformInputContext *inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext(); bool filtered = false; - if (inputContext && !mParent->mQDisplay->usingInputContextFromCompositor()) { + if (inputContext) { QKeyEvent event(type, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorepeat, count); event.setTimestamp(timestamp); @@ -1202,10 +1349,9 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time, 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 = QXkbCommon::modifiers(mXkbState.get(), sym); - Qt::KeyboardModifiers modifiers = mParent->modifiers(); - - int qtkey = QXkbCommon::keysymToQtKey(sym, modifiers, mXkbState.get(), code); + int qtkey = keysymToQtKey(sym, modifiers, mXkbState.get(), code); QString text = QXkbCommon::lookupString(mXkbState.get(), code); QEvent::Type type = isDown ? QEvent::KeyPress : QEvent::KeyRelease; @@ -1216,8 +1362,6 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time, mRepeatKey.code = code; mRepeatKey.time = time; mRepeatKey.text = text; - mRepeatKey.modifiers = modifiers; - mRepeatKey.nativeModifiers = mNativeModifiers; mRepeatKey.nativeVirtualKey = sym; mRepeatTimer.setInterval(mRepeatDelay); mRepeatTimer.start(); @@ -1238,25 +1382,12 @@ void QWaylandInputDevice::Keyboard::keyboard_key(uint32_t serial, uint32_t time, 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(); } @@ -1307,14 +1438,14 @@ void QWaylandInputDevice::Touch::touch_down(uint32_t 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); + mParent->handleTouchPoint(id, QEventPoint::Pressed, 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); + mParent->mTime = time; + mParent->handleTouchPoint(id, QEventPoint::Released); if (allTouchPointsReleased()) { mFocus = nullptr; @@ -1332,9 +1463,9 @@ void QWaylandInputDevice::Touch::touch_up(uint32_t serial, uint32_t time, int32_ 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); + mParent->mTime = time; + mParent->handleTouchPoint(id, QEventPoint::Updated, position); } void QWaylandInputDevice::Touch::touch_cancel() @@ -1345,21 +1476,30 @@ void QWaylandInputDevice::Touch::touch_cancel() if (touchExt) touchExt->touchCanceled(); + mFocus = nullptr; QWindowSystemInterface::handleTouchCancelEvent(nullptr, mParent->mTouchDevice); } -void QWaylandInputDevice::handleTouchPoint(int id, Qt::TouchPointState state, const QPointF &surfacePosition) +void QWaylandInputDevice::handleTouchPoint(int id, QEventPoint::State state, const QPointF &surfacePosition) { auto end = mTouch->mPendingTouchPoints.end(); - auto it = std::find_if(mTouch->mPendingTouchPoints.begin(), end, [id](auto tp){ return tp.id == id; }); + 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; } + // If the touch points were up and down in same frame, send out frame right away + else if ((it->state == QEventPoint::Pressed && state == QEventPoint::Released) + || (it->state == QEventPoint::Released && state == QEventPoint::Pressed)) { + mTouch->touch_frame(); + it = mTouch->mPendingTouchPoints.insert(mTouch->mPendingTouchPoints.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) { + if (state == QEventPoint::Updated || state == QEventPoint::Pressed) { // We need a global (screen) position. QWaylandWindow *win = mTouch->mFocus; @@ -1372,23 +1512,25 @@ void QWaylandInputDevice::handleTouchPoint(int id, Qt::TouchPointState state, co return; tp.area = QRectF(0, 0, 8, 8); - QMargins margins = win->frameMargins(); - QPointF localPosition = surfacePosition - QPointF(margins.left(), margins.top()); + 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; + QPointF globalPosition = win->mapToGlobal(localPosition.toPoint()) + delta; tp.area.moveCenter(globalPosition); } - tp.state = state; - tp.pressure = tp.state == Qt::TouchPointReleased ? 0 : 1; + // If the touch point was pressed earlier this frame, we don't want to overwrite its state. + if (tp.state != QEventPoint::Pressed) + tp.state = QEventPoint::State(state); + + tp.pressure = tp.state == QEventPoint::Released ? 0 : 1; } bool QWaylandInputDevice::Touch::allTouchPointsReleased() { - for (const auto &tp : qAsConst(mPendingTouchPoints)) { - if (tp.state != Qt::TouchPointReleased) + for (const auto &tp : std::as_const(mPendingTouchPoints)) { + if (tp.state != QEventPoint::Released) return false; } return true; @@ -1400,7 +1542,7 @@ void QWaylandInputDevice::Touch::releasePoints() return; for (QWindowSystemInterface::TouchPoint &tp : mPendingTouchPoints) - tp.state = Qt::TouchPointReleased; + tp.state = QEventPoint::Released; touch_frame(); } @@ -1412,26 +1554,31 @@ void QWaylandInputDevice::Touch::touch_frame() QWindow *window = mFocus ? mFocus->window() : nullptr; if (mFocus) { - const QWindowSystemInterface::TouchPoint &tp = mPendingTouchPoints.last(); + // Returns a reference to the last item in the list. The list must not be empty. + // If the list can be empty, call isEmpty() before calling this function. + // See: https://doc.qt.io/qt-5.15/qlist.html#last + if (mPendingTouchPoints.empty()) + return; + const QWindowSystemInterface::TouchPoint &tp = mPendingTouchPoints.constLast(); // 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(); + QMargins margins = mFocus->clientSideMargins(); QPoint p = tp.area.center().toPoint(); - QPointF localPos(window->mapFromGlobal(QPoint(p.x() + margins.left(), p.y() + margins.top()))); + QPointF localPos(mFocus->mapFromGlobal(p) + QPoint(margins.left(), margins.top())); if (mFocus->touchDragDecoration(mParent, localPos, tp.area.center(), tp.state, mParent->modifiers())) return; } - QWindowSystemInterface::handleTouchEvent(window, mParent->mTouchDevice, mPendingTouchPoints); + QWindowSystemInterface::handleTouchEvent(window, mParent->mTime, mParent->mTouchDevice, mPendingTouchPoints, mParent->modifiers()); // 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) { + if (prevPoint.state != QEventPoint::Released) { QWindowSystemInterface::TouchPoint tp = prevPoint; - tp.state = Qt::TouchPointStationary; // ... as stationary (unless proven otherwise) + tp.state = QEventPoint::Stationary; // ... as stationary (unless proven otherwise) mPendingTouchPoints.append(tp); } } @@ -1441,3 +1588,5 @@ void QWaylandInputDevice::Touch::touch_frame() } QT_END_NAMESPACE + +#include "moc_qwaylandinputdevice_p.cpp" |