Implement support for pointer gestures v1

Change-Id: Ie9ee615de123e6deab5b7a5081ca9bcf53399df7
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
This commit is contained in:
Povilas Kanapickas 2021-01-18 15:58:50 +02:00
parent ac704a5b90
commit 2679eeaac9
9 changed files with 638 additions and 2 deletions

View File

@ -33,6 +33,7 @@ qt_internal_add_module(WaylandClient
qwaylandinputmethodcontext.cpp qwaylandinputmethodcontext_p.h
qwaylandintegration.cpp qwaylandintegration_p.h
qwaylandnativeinterface.cpp qwaylandnativeinterface_p.h
qwaylandpointergestures.cpp qwaylandpointergestures_p.h
qwaylandqtkey.cpp qwaylandqtkey_p.h
qwaylandscreen.cpp qwaylandscreen_p.h
qwaylandshellsurface.cpp qwaylandshellsurface_p.h

View File

@ -68,6 +68,7 @@
#include "qwaylandclientbufferintegration_p.h"
#include "qwaylandextendedsurface_p.h"
#include "qwaylandpointergestures_p.h"
#include "qwaylandsubsurface_p.h"
#include "qwaylandtouch_p.h"
#include "qwaylandtabletv2_p.h"
@ -355,6 +356,8 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin
mQtKeyExtension.reset(new QWaylandQtKeyExtension(this, id));
} else if (interface == QStringLiteral("zwp_tablet_manager_v2")) {
mTabletManager.reset(new QWaylandTabletManagerV2(this, id, qMin(1, int(version))));
} else if (interface == QStringLiteral("zwp_pointer_gestures_v1")) {
mPointerGestures.reset(new QWaylandPointerGestures(this, id, 1));
#if QT_CONFIG(wayland_client_primary_selection)
} else if (interface == QStringLiteral("zwp_primary_selection_device_manager_v1")) {
mPrimarySelectionManager.reset(new QWaylandPrimarySelectionDeviceManagerV1(this, id, 1));

View File

@ -101,6 +101,7 @@ class QWaylandDataDeviceManager;
class QWaylandPrimarySelectionDeviceManagerV1;
#endif
class QWaylandTabletManagerV2;
class QWaylandPointerGestures;
class QWaylandTouchExtension;
class QWaylandQtKeyExtension;
class QWaylandWindow;
@ -172,6 +173,7 @@ public:
#endif
QtWayland::qt_surface_extension *windowExtension() const { return mWindowExtension.data(); }
QWaylandTabletManagerV2 *tabletManager() const { return mTabletManager.data(); }
QWaylandPointerGestures *pointerGestures() const { return mPointerGestures.data(); }
QWaylandTouchExtension *touchExtension() const { return mTouchExtension.data(); }
QtWayland::qt_text_input_method_manager_v1 *textInputMethodManager() const { return mTextInputMethodManager.data(); }
QtWayland::zwp_text_input_manager_v2 *textInputManager() const { return mTextInputManager.data(); }
@ -275,6 +277,7 @@ private:
QScopedPointer<QWaylandQtKeyExtension> mQtKeyExtension;
QScopedPointer<QWaylandWindowManagerIntegration> mWindowManagerIntegration;
QScopedPointer<QWaylandTabletManagerV2> mTabletManager;
QScopedPointer<QWaylandPointerGestures> mPointerGestures;
#if QT_CONFIG(wayland_client_primary_selection)
QScopedPointer<QWaylandPrimarySelectionDeviceManagerV1> mPrimarySelectionManager;
#endif

View File

@ -51,6 +51,7 @@
#include "qwaylandprimaryselectionv1_p.h"
#endif
#include "qwaylandtabletv2_p.h"
#include "qwaylandpointergestures_p.h"
#include "qwaylandtouch_p.h"
#include "qwaylandscreen_p.h"
#include "qwaylandcursor_p.h"
@ -82,6 +83,10 @@ 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)
{
@ -446,9 +451,28 @@ void QWaylandInputDevice::seat_capabilities(uint32_t caps)
if (caps & WL_SEAT_CAPABILITY_POINTER && !mPointer) {
mPointer = createPointer(this);
mPointer->init(get_pointer());
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);
QWindowSystemInterface::registerInputDevice(mTouchPadDevice);
mPointerGesturePinch = pointerGestures->createPointerGesturePinch(this);
mPointerGesturePinch->init(pointerGestures->get_pinch_gesture(get_pointer()));
mPointerGestureSwipe = pointerGestures->createPointerGestureSwipe(this);
mPointerGestureSwipe->init(pointerGestures->get_swipe_gesture(get_pointer()));
}
} else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && mPointer) {
delete mPointer;
mPointer = nullptr;
delete mPointerGesturePinch;
mPointerGesturePinch = nullptr;
delete mPointerGestureSwipe;
mPointerGestureSwipe = nullptr;
}
if (caps & WL_SEAT_CAPABILITY_TOUCH && !mTouch) {
@ -458,8 +482,8 @@ void QWaylandInputDevice::seat_capabilities(uint32_t caps)
if (!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, 10, 0);
QInputDevice::DeviceType::TouchScreen, QPointingDevice::PointerType::Finger,
QInputDevice::Capability::Position, MaxTouchPoints, 0);
QWindowSystemInterface::registerInputDevice(mTouchDevice);
}
} else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && mTouch) {
@ -493,6 +517,16 @@ QWaylandInputDevice::Pointer *QWaylandInputDevice::pointer() const
return mPointer;
}
QWaylandPointerGestureSwipe *QWaylandInputDevice::pointerGestureSwipe() const
{
return mPointerGestureSwipe;
}
QWaylandPointerGesturePinch *QWaylandInputDevice::pointerGesturePinch() const
{
return mPointerGesturePinch;
}
QWaylandInputDevice::Touch *QWaylandInputDevice::touch() const
{
return mTouch;

View File

@ -63,6 +63,7 @@
#include <qpa/qwindowsysteminterface.h>
#include <QtWaylandClient/private/qwayland-wayland.h>
#include <QtWaylandClient/private/qwayland-pointer-gestures-unstable-v1.h>
#if QT_CONFIG(xkbcommon)
#include <QtGui/private/qxkbcommon_p.h>
@ -90,6 +91,9 @@ class QWaylandDisplay;
class QWaylandPrimarySelectionDeviceV1;
#endif
class QWaylandTabletSeatV2;
class QWaylandPointerGestures;
class QWaylandPointerGestureSwipe;
class QWaylandPointerGesturePinch;
class QWaylandTextInput;
class QWaylandTextInputMethod;
#if QT_CONFIG(cursor)
@ -97,6 +101,8 @@ class QWaylandCursorTheme;
class CursorSurface;
#endif
Q_DECLARE_LOGGING_CATEGORY(lcQpaWaylandInput);
class Q_WAYLAND_CLIENT_EXPORT QWaylandInputDevice
: public QObject
, public QtWayland::wl_seat
@ -158,6 +164,8 @@ public:
Keyboard *keyboard() const;
Pointer *pointer() const;
QWaylandPointerGestureSwipe *pointerGestureSwipe() const;
QWaylandPointerGesturePinch *pointerGesturePinch() const;
Touch *touch() const;
protected:
@ -187,6 +195,8 @@ protected:
Keyboard *mKeyboard = nullptr;
Pointer *mPointer = nullptr;
QWaylandPointerGestureSwipe *mPointerGestureSwipe = nullptr;
QWaylandPointerGesturePinch *mPointerGesturePinch = nullptr;
Touch *mTouch = nullptr;
QScopedPointer<QWaylandTextInput> mTextInput;
@ -200,9 +210,13 @@ protected:
void handleTouchPoint(int id, Qt::TouchPointState state, const QPointF &surfacePosition = QPoint());
QPointingDevice *mTouchDevice = nullptr;
QPointingDevice *mTouchPadDevice = nullptr;
friend class QWaylandTouchExtension;
friend class QWaylandQtKeyExtension;
friend class QWaylandPointerGestureSwipe;
friend class QWaylandPointerGesturePinch;
friend class QWaylandWindow;
};
inline uint32_t QWaylandInputDevice::serial() const
@ -461,6 +475,63 @@ public:
QPointer<QWaylandWindow> surface;
};
#ifndef QT_NO_GESTURES
class QWaylandPointerGestureSwipeEvent
{
Q_GADGET
public:
inline QWaylandPointerGestureSwipeEvent(QWaylandWindow *surface, Qt::GestureState state,
ulong timestamp, const QPointF &local,
const QPointF &global, uint fingers, const QPointF& delta)
: surface(surface)
, state(state)
, timestamp(timestamp)
, local(local)
, global(global)
, fingers(fingers)
, delta(delta)
{}
QPointer<QWaylandWindow> surface;
Qt::GestureState state = Qt::GestureState::NoGesture;
ulong timestamp = 0;
QPointF local;
QPointF global;
uint fingers = 0;
QPointF delta;
};
class QWaylandPointerGesturePinchEvent
{
Q_GADGET
public:
inline QWaylandPointerGesturePinchEvent(QWaylandWindow *surface, Qt::GestureState state,
ulong timestamp, const QPointF &local,
const QPointF &global, uint fingers, const QPointF& delta,
qreal scale_delta, qreal rotation_delta)
: surface(surface)
, state(state)
, timestamp(timestamp)
, local(local)
, global(global)
, fingers(fingers)
, delta(delta)
, scale_delta(scale_delta)
, rotation_delta(rotation_delta)
{}
QPointer<QWaylandWindow> surface;
Qt::GestureState state = Qt::GestureState::NoGesture;
ulong timestamp = 0;
QPointF local;
QPointF global;
uint fingers = 0;
QPointF delta;
qreal scale_delta = 0;
qreal rotation_delta = 0;
};
#endif // #ifndef QT_NO_GESTURES
}
QT_END_NAMESPACE

View File

@ -0,0 +1,222 @@
/****************************************************************************
**
** Copyright (C) 2021 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 "qwaylandpointergestures_p.h"
#include "qwaylanddisplay_p.h"
#include "qwaylandinputdevice_p.h"
QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
QWaylandPointerGestures::QWaylandPointerGestures(QWaylandDisplay *display, uint id, uint version)
: zwp_pointer_gestures_v1(display->wl_registry(), id, qMin(version, uint(1)))
{
}
QWaylandPointerGestureSwipe *
QWaylandPointerGestures::createPointerGestureSwipe(QWaylandInputDevice *device)
{
return new QWaylandPointerGestureSwipe(device);
}
QWaylandPointerGesturePinch *
QWaylandPointerGestures::createPointerGesturePinch(QWaylandInputDevice *device)
{
return new QWaylandPointerGesturePinch(device);
}
QWaylandPointerGestureSwipe::QWaylandPointerGestureSwipe(QWaylandInputDevice *p)
: mParent(p)
{
}
QWaylandPointerGestureSwipe::~QWaylandPointerGestureSwipe()
{
destroy();
}
void QWaylandPointerGestureSwipe::zwp_pointer_gesture_swipe_v1_begin(uint32_t serial, uint32_t time,
struct ::wl_surface *surface,
uint32_t fingers)
{
#ifndef QT_NO_GESTURES
mParent->mSerial = serial;
mFocus = QWaylandWindow::fromWlSurface(surface);
mFingers = fingers;
const auto* pointer = mParent->pointer();
qCDebug(lcQpaWaylandInput) << "zwp_pointer_gesture_swipe_v1_begin @ "
<< pointer->mSurfacePos << "fingers" << fingers;
auto e = QWaylandPointerGestureSwipeEvent(mFocus, Qt::GestureStarted, time,
pointer->mSurfacePos, pointer->mGlobalPos, mFingers,
QPointF());
mFocus->handleSwipeGesture(mParent, e);
#endif
}
void QWaylandPointerGestureSwipe::zwp_pointer_gesture_swipe_v1_update(uint32_t time,
wl_fixed_t dx, wl_fixed_t dy)
{
#ifndef QT_NO_GESTURES
const auto* pointer = mParent->pointer();
const QPointF delta = QPointF(wl_fixed_to_double(dx), wl_fixed_to_double(dy));
qCDebug(lcQpaWaylandInput) << "zwp_pointer_gesture_swipe_v1_update @ "
<< pointer->mSurfacePos << "delta" << delta;
auto e = QWaylandPointerGestureSwipeEvent(mFocus, Qt::GestureUpdated, time,
pointer->mSurfacePos, pointer->mGlobalPos, mFingers, delta);
mFocus->handleSwipeGesture(mParent, e);
#endif
}
void QWaylandPointerGestureSwipe::zwp_pointer_gesture_swipe_v1_end(uint32_t serial, uint32_t time,
int32_t cancelled)
{
#ifndef QT_NO_GESTURES
mParent->mSerial = serial;
const auto* pointer = mParent->pointer();
qCDebug(lcQpaWaylandInput) << "zwp_pointer_gesture_swipe_v1_end @ "
<< pointer->mSurfacePos << (cancelled ? "CANCELED" : "");
auto gestureType = cancelled ? Qt::GestureFinished : Qt::GestureCanceled;
auto e = QWaylandPointerGestureSwipeEvent(mFocus, gestureType, time,
pointer->mSurfacePos, pointer->mGlobalPos, mFingers,
QPointF());
mFocus->handleSwipeGesture(mParent, e);
mFocus.clear();
mFingers = 0;
#endif
}
QWaylandPointerGesturePinch::QWaylandPointerGesturePinch(QWaylandInputDevice *p)
: mParent(p)
{
}
QWaylandPointerGesturePinch::~QWaylandPointerGesturePinch()
{
destroy();
}
void QWaylandPointerGesturePinch::zwp_pointer_gesture_pinch_v1_begin(uint32_t serial, uint32_t time,
struct ::wl_surface *surface,
uint32_t fingers)
{
#ifndef QT_NO_GESTURES
mParent->mSerial = serial;
mFocus = QWaylandWindow::fromWlSurface(surface);
mFingers = fingers;
mLastScale = 1;
const auto* pointer = mParent->pointer();
qCDebug(lcQpaWaylandInput) << "zwp_pointer_gesture_pinch_v1_begin @ "
<< pointer->mSurfacePos << "fingers" << fingers;
auto e = QWaylandPointerGesturePinchEvent(mFocus, Qt::GestureStarted, time,
pointer->mSurfacePos, pointer->mGlobalPos, mFingers,
QPointF(), 0, 0);
mFocus->handlePinchGesture(mParent, e);
#endif
}
void QWaylandPointerGesturePinch::zwp_pointer_gesture_pinch_v1_update(uint32_t time,
wl_fixed_t dx, wl_fixed_t dy,
wl_fixed_t scale,
wl_fixed_t rotation)
{
#ifndef QT_NO_GESTURES
const auto* pointer = mParent->pointer();
const qreal rscale = wl_fixed_to_double(scale);
const qreal rot = wl_fixed_to_double(rotation);
const QPointF delta = QPointF(wl_fixed_to_double(dx), wl_fixed_to_double(dy));
qCDebug(lcQpaWaylandInput) << "zwp_pointer_gesture_pinch_v1_update @ "
<< pointer->mSurfacePos << "delta" << delta
<< "scale" << mLastScale << "->" << rscale
<< "delta" << rscale - mLastScale << "rot" << rot;
auto e = QWaylandPointerGesturePinchEvent(mFocus, Qt::GestureUpdated, time,
pointer->mSurfacePos, pointer->mGlobalPos, mFingers,
delta, rscale - mLastScale, rot);
mFocus->handlePinchGesture(mParent, e);
mLastScale = rscale;
#endif
}
void QWaylandPointerGesturePinch::zwp_pointer_gesture_pinch_v1_end(uint32_t serial, uint32_t time,
int32_t cancelled)
{
#ifndef QT_NO_GESTURES
mParent->mSerial = serial;
const auto* pointer = mParent->pointer();
qCDebug(lcQpaWaylandInput) << "zwp_pointer_gesture_swipe_v1_end @ "
<< pointer->mSurfacePos << (cancelled ? "CANCELED" : "");
auto gestureType = cancelled ? Qt::GestureFinished : Qt::GestureCanceled;
auto e = QWaylandPointerGesturePinchEvent(mFocus, gestureType, time,
pointer->mSurfacePos, pointer->mGlobalPos, mFingers,
QPointF(), 0, 0);
mFocus->handlePinchGesture(mParent, e);
mFocus.clear();
mFingers = 0;
mLastScale = 1;
#endif
}
} // namespace QtWaylandClient
QT_END_NAMESPACE

View File

@ -0,0 +1,150 @@
/****************************************************************************
**
** Copyright (C) 2021 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$
**
****************************************************************************/
#ifndef QWAYLANDPOINTERGESTURES_P_H
#define QWAYLANDPOINTERGESTURES_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists purely as an
// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
#include <QtWaylandClient/private/qwayland-pointer-gestures-unstable-v1.h>
#include <QtWaylandClient/private/qtwaylandclientglobal_p.h>
#include <QtCore/QObject>
#include <QtCore/QPointer>
QT_BEGIN_NAMESPACE
namespace QtWaylandClient {
class QWaylandDisplay;
class QWaylandWindow;
class QWaylandInputDevice;
class QWaylandPointerGestureSwipe;
class QWaylandPointerGesturePinch;
class Q_WAYLAND_CLIENT_EXPORT QWaylandPointerGestures : public QtWayland::zwp_pointer_gestures_v1
{
public:
explicit QWaylandPointerGestures(QWaylandDisplay *display, uint id, uint version);
QWaylandPointerGestureSwipe *createPointerGestureSwipe(QWaylandInputDevice *device);
QWaylandPointerGesturePinch *createPointerGesturePinch(QWaylandInputDevice *device);
};
class Q_WAYLAND_CLIENT_EXPORT QWaylandPointerGestureSwipe :
public QtWayland::zwp_pointer_gesture_swipe_v1
{
public:
QWaylandPointerGestureSwipe(QWaylandInputDevice *p);
~QWaylandPointerGestureSwipe() override;
void zwp_pointer_gesture_swipe_v1_begin(uint32_t serial,
uint32_t time,
struct ::wl_surface *surface,
uint32_t fingers) override;
void zwp_pointer_gesture_swipe_v1_update(uint32_t time,
wl_fixed_t dx,
wl_fixed_t dy) override;
void zwp_pointer_gesture_swipe_v1_end(uint32_t serial,
uint32_t time,
int32_t cancelled) override;
struct ::zwp_pointer_gesture_swipe_v1 *zwp_pointer_gesture_swipe_v1()
{
return QtWayland::zwp_pointer_gesture_swipe_v1::object();
}
QWaylandInputDevice *mParent = nullptr;
QPointer<QWaylandWindow> mFocus;
uint mFingers = 0;
};
class Q_WAYLAND_CLIENT_EXPORT QWaylandPointerGesturePinch :
public QtWayland::zwp_pointer_gesture_pinch_v1
{
public:
QWaylandPointerGesturePinch(QWaylandInputDevice *p);
~QWaylandPointerGesturePinch() override;
void zwp_pointer_gesture_pinch_v1_begin(uint32_t serial,
uint32_t time,
struct ::wl_surface *surface,
uint32_t fingers) override;
void zwp_pointer_gesture_pinch_v1_update(uint32_t time,
wl_fixed_t dx,
wl_fixed_t dy,
wl_fixed_t scale,
wl_fixed_t rotation) override;
void zwp_pointer_gesture_pinch_v1_end(uint32_t serial,
uint32_t time,
int32_t cancelled) override;
struct ::zwp_pointer_gesture_pinch_v1 *zwp_pointer_gesture_pinch_v1()
{
return QtWayland::zwp_pointer_gesture_pinch_v1::object();
}
QWaylandInputDevice *mParent = nullptr;
QPointer<QWaylandWindow> mFocus;
uint mFingers = 0;
// We need to convert between absolute scale provided by wayland/libinput and zoom deltas
// that Qt expects. This stores the scale of the last pinch event or 1.0 if there was none.
qreal mLastScale = 1;
};
} // namespace QtWaylandClient
QT_END_NAMESPACE
#endif // QWAYLANDPOINTERGESTURES_P_H

View File

@ -978,6 +978,133 @@ void QWaylandWindow::handleMouse(QWaylandInputDevice *inputDevice, const QWaylan
#endif
}
#ifndef QT_NO_GESTURES
void QWaylandWindow::handleSwipeGesture(QWaylandInputDevice *inputDevice,
const QWaylandPointerGestureSwipeEvent &e)
{
switch (e.state) {
case Qt::GestureStarted:
if (mGestureState != GestureNotActive)
qCWarning(lcQpaWaylandInput) << "Unexpected gesture state. Gestures will act weird.";
if (mWindowDecoration && !mMouseEventsInContentArea) {
// whole gesture sequence will be ignored
mGestureState = GestureActiveInDecoration;
return;
}
mGestureState = GestureActiveInContentArea;
QWindowSystemInterface::handleGestureEvent(window(), e.timestamp,
inputDevice->mTouchPadDevice,
Qt::BeginNativeGesture,
e.local, e.global, e.fingers);
break;
case Qt::GestureUpdated:
if (mGestureState != GestureActiveInContentArea)
return;
if (!e.delta.isNull()) {
QWindowSystemInterface::handleGestureEventWithValueAndDeltas(
window(), e.timestamp, inputDevice->mTouchPadDevice,
Qt::PanNativeGesture,
0, QVector2D(e.delta), e.local, e.global, e.fingers);
}
break;
case Qt::GestureFinished:
case Qt::GestureCanceled:
if (mGestureState == GestureActiveInDecoration) {
mGestureState = GestureNotActive;
return;
}
if (mGestureState != GestureActiveInContentArea)
qCWarning(lcQpaWaylandInput) << "Unexpected gesture state. Gestures will act weird.";
mGestureState = GestureNotActive;
// There's currently no way to expose cancelled gestures to the rest of Qt, so
// this part of information is lost.
QWindowSystemInterface::handleGestureEvent(window(), e.timestamp,
inputDevice->mTouchPadDevice,
Qt::EndNativeGesture,
e.local, e.global, e.fingers);
break;
default:
break;
}
}
void QWaylandWindow::handlePinchGesture(QWaylandInputDevice *inputDevice,
const QWaylandPointerGesturePinchEvent &e)
{
switch (e.state) {
case Qt::GestureStarted:
if (mGestureState != GestureNotActive)
qCWarning(lcQpaWaylandInput) << "Unexpected gesture state. Gestures will act weird.";
if (mWindowDecoration && !mMouseEventsInContentArea) {
// whole gesture sequence will be ignored
mGestureState = GestureActiveInDecoration;
return;
}
mGestureState = GestureActiveInContentArea;
QWindowSystemInterface::handleGestureEvent(window(), e.timestamp,
inputDevice->mTouchPadDevice,
Qt::BeginNativeGesture,
e.local, e.global, e.fingers);
break;
case Qt::GestureUpdated:
if (mGestureState != GestureActiveInContentArea)
return;
if (!e.delta.isNull()) {
QWindowSystemInterface::handleGestureEventWithValueAndDeltas(
window(), e.timestamp, inputDevice->mTouchPadDevice,
Qt::PanNativeGesture,
0, QVector2D(e.delta), e.local, e.global, e.fingers);
}
if (e.rotation_delta != 0) {
QWindowSystemInterface::handleGestureEventWithRealValue(window(), e.timestamp,
inputDevice->mTouchPadDevice,
Qt::RotateNativeGesture,
e.rotation_delta,
e.local, e.global, e.fingers);
}
if (e.scale_delta != 0) {
QWindowSystemInterface::handleGestureEventWithRealValue(window(), e.timestamp,
inputDevice->mTouchPadDevice,
Qt::ZoomNativeGesture,
e.scale_delta,
e.local, e.global, e.fingers);
}
break;
case Qt::GestureFinished:
case Qt::GestureCanceled:
if (mGestureState == GestureActiveInDecoration) {
mGestureState = GestureNotActive;
return;
}
if (mGestureState != GestureActiveInContentArea)
qCWarning(lcQpaWaylandInput) << "Unexpected gesture state. Gestures will act weird.";
mGestureState = GestureNotActive;
// There's currently no way to expose cancelled gestures to the rest of Qt, so
// this part of information is lost.
QWindowSystemInterface::handleGestureEvent(window(), e.timestamp,
inputDevice->mTouchPadDevice,
Qt::EndNativeGesture,
e.local, e.global, e.fingers);
break;
default:
break;
}
}
#endif // #ifndef QT_NO_GESTURES
bool QWaylandWindow::touchDragDecoration(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global, Qt::TouchPointState state, Qt::KeyboardModifiers mods)
{
if (!mWindowDecoration)

View File

@ -83,6 +83,8 @@ class QWaylandInputDevice;
class QWaylandScreen;
class QWaylandShmBackingStore;
class QWaylandPointerEvent;
class QWaylandPointerGestureSwipeEvent;
class QWaylandPointerGesturePinchEvent;
class QWaylandSurface;
class Q_WAYLAND_CLIENT_EXPORT QWaylandWindow : public QObject, public QPlatformWindow
@ -177,6 +179,12 @@ public:
QWaylandAbstractDecoration *decoration() const;
void handleMouse(QWaylandInputDevice *inputDevice, const QWaylandPointerEvent &e);
#ifndef QT_NO_GESTURES
void handleSwipeGesture(QWaylandInputDevice *inputDevice,
const QWaylandPointerGestureSwipeEvent &e);
void handlePinchGesture(QWaylandInputDevice *inputDevice,
const QWaylandPointerGesturePinchEvent &e);
#endif
bool touchDragDecoration(QWaylandInputDevice *inputDevice, const QPointF &local, const QPointF &global,
Qt::TouchPointState state, Qt::KeyboardModifiers mods);
@ -241,6 +249,23 @@ protected:
bool mMouseEventsInContentArea = false;
Qt::MouseButtons mMousePressedInContentArea = Qt::NoButton;
#ifndef QT_NO_GESTURES
enum GestureState {
GestureNotActive,
GestureActiveInContentArea,
GestureActiveInDecoration
};
// We want gestures started in the decoration area to be completely ignored even if the mouse
// pointer is later moved to content area. Likewise, gestures started in the content area should
// keep sending events even if the mouse pointer is moved over the decoration (consider that
// the events for that gesture will be sent to us even if it's moved outside the window).
// So we track the gesture state and accept or ignore events based on that. Note that
// concurrent gestures of different types are not allowed in the protocol, so single state is
// enough
GestureState mGestureState = GestureNotActive;
#endif
WId mWindowId;
bool mWaitingForFrameCallback = false;
bool mFrameCallbackTimedOut = false; // Whether the frame callback has timed out