File indexing completed on 2024-04-28 16:48:47

0001 /*
0002     KWin - the KDE window manager
0003     This file is part of the KDE project.
0004 
0005     SPDX-FileCopyrightText: 2017 Martin Gräßlin <mgraesslin@kde.org>
0006 
0007     SPDX-License-Identifier: GPL-2.0-or-later
0008 */
0009 #pragma once
0010 
0011 #include <kwin_export.h>
0012 
0013 #include <QMap>
0014 #include <QObject>
0015 #include <QPointF>
0016 #include <QVector>
0017 
0018 namespace KWin
0019 {
0020 /*
0021  * Everytime the scale of the gesture changes by this much, the callback changes by 1.
0022  * This is the amount of change for 1 unit of change, like switch by 1 desktop.
0023  * */
0024 static const qreal DEFAULT_UNIT_SCALE_DELTA = .2; // 20%
0025 
0026 class Gesture : public QObject
0027 {
0028     Q_OBJECT
0029 public:
0030     ~Gesture() override;
0031 
0032 protected:
0033     explicit Gesture(QObject *parent);
0034 
0035 Q_SIGNALS:
0036     /**
0037      * Matching of a gesture started and this Gesture might match.
0038      * On further evaluation either the signal @ref triggered or
0039      * @ref cancelled will get emitted.
0040      */
0041     void started();
0042     /**
0043      * Gesture matching ended and this Gesture matched.
0044      */
0045     void triggered();
0046     /**
0047      * This Gesture no longer matches.
0048      */
0049     void cancelled();
0050 };
0051 
0052 class SwipeGesture : public Gesture
0053 {
0054     Q_OBJECT
0055 public:
0056     enum class Direction {
0057         Down,
0058         Left,
0059         Up,
0060         Right,
0061     };
0062 
0063     explicit SwipeGesture(QObject *parent = nullptr);
0064     ~SwipeGesture() override;
0065 
0066     bool minimumFingerCountIsRelevant() const;
0067     void setMinimumFingerCount(uint count);
0068     uint minimumFingerCount() const;
0069 
0070     bool maximumFingerCountIsRelevant() const;
0071     void setMaximumFingerCount(uint count);
0072     uint maximumFingerCount() const;
0073 
0074     Direction direction() const;
0075     void setDirection(Direction direction);
0076 
0077     void setMinimumX(int x);
0078     int minimumX() const;
0079     bool minimumXIsRelevant() const;
0080     void setMinimumY(int y);
0081     int minimumY() const;
0082     bool minimumYIsRelevant() const;
0083 
0084     void setMaximumX(int x);
0085     int maximumX() const;
0086     bool maximumXIsRelevant() const;
0087     void setMaximumY(int y);
0088     int maximumY() const;
0089     bool maximumYIsRelevant() const;
0090     void setStartGeometry(const QRect &geometry);
0091 
0092     QPointF minimumDelta() const;
0093     void setMinimumDelta(const QPointF &delta);
0094     bool isMinimumDeltaRelevant() const;
0095 
0096     qreal deltaToProgress(const QPointF &delta) const;
0097     bool minimumDeltaReached(const QPointF &delta) const;
0098 
0099 Q_SIGNALS:
0100     /**
0101      * The progress of the gesture if a minimumDelta is set.
0102      * The progress is reported in [0.0,1.0]
0103      */
0104     void progress(qreal);
0105 
0106     /**
0107      * The progress in actual pixel distance traveled by the fingers
0108      */
0109     void deltaProgress(const QPointF &delta);
0110 
0111 private:
0112     bool m_minimumFingerCountRelevant = false;
0113     uint m_minimumFingerCount = 0;
0114     bool m_maximumFingerCountRelevant = false;
0115     uint m_maximumFingerCount = 0;
0116     Direction m_direction = Direction::Down;
0117     bool m_minimumXRelevant = false;
0118     int m_minimumX = 0;
0119     bool m_minimumYRelevant = false;
0120     int m_minimumY = 0;
0121     bool m_maximumXRelevant = false;
0122     int m_maximumX = 0;
0123     bool m_maximumYRelevant = false;
0124     int m_maximumY = 0;
0125     bool m_minimumDeltaRelevant = false;
0126     QPointF m_minimumDelta;
0127 };
0128 
0129 class PinchGesture : public Gesture
0130 {
0131     Q_OBJECT
0132 public:
0133     enum class Direction {
0134         Expanding,
0135         Contracting,
0136     };
0137 
0138     explicit PinchGesture(QObject *parent = nullptr);
0139     ~PinchGesture() override;
0140 
0141     bool minimumFingerCountIsRelevant() const;
0142     void setMinimumFingerCount(uint count);
0143     uint minimumFingerCount() const;
0144 
0145     bool maximumFingerCountIsRelevant() const;
0146     void setMaximumFingerCount(uint count);
0147     uint maximumFingerCount() const;
0148 
0149     Direction direction() const;
0150     void setDirection(Direction direction);
0151 
0152     qreal minimumScaleDelta() const;
0153 
0154     /**
0155      * scaleDelta is the % scale difference needed to trigger
0156      * 0.25 will trigger when scale reaches 0.75 or 1.25
0157      */
0158     void setMinimumScaleDelta(const qreal &scaleDelta);
0159     bool isMinimumScaleDeltaRelevant() const;
0160 
0161     qreal scaleDeltaToProgress(const qreal &scaleDelta) const;
0162     bool minimumScaleDeltaReached(const qreal &scaleDelta) const;
0163 
0164 Q_SIGNALS:
0165     /**
0166      * The progress of the gesture if a minimumDelta is set.
0167      * The progress is reported in [0.0,1.0]
0168      */
0169     void progress(qreal);
0170 
0171 private:
0172     bool m_minimumFingerCountRelevant = false;
0173     uint m_minimumFingerCount = 0;
0174     bool m_maximumFingerCountRelevant = false;
0175     uint m_maximumFingerCount = 0;
0176     Direction m_direction = Direction::Expanding;
0177     bool m_minimumScaleDeltaRelevant = false;
0178     qreal m_minimumScaleDelta = DEFAULT_UNIT_SCALE_DELTA;
0179 };
0180 
0181 class KWIN_EXPORT GestureRecognizer : public QObject
0182 {
0183     Q_OBJECT
0184 public:
0185     GestureRecognizer(QObject *parent = nullptr);
0186     ~GestureRecognizer() override;
0187 
0188     void registerSwipeGesture(SwipeGesture *gesture);
0189     void unregisterSwipeGesture(SwipeGesture *gesture);
0190     void registerPinchGesture(PinchGesture *gesture);
0191     void unregisterPinchGesture(PinchGesture *gesture);
0192 
0193     int startSwipeGesture(uint fingerCount);
0194     int startSwipeGesture(const QPointF &startPos);
0195 
0196     void updateSwipeGesture(const QPointF &delta);
0197     void cancelSwipeGesture();
0198     void endSwipeGesture();
0199 
0200     int startPinchGesture(uint fingerCount);
0201     void updatePinchGesture(qreal scale, qreal angleDelta, const QPointF &posDelta);
0202     void cancelPinchGesture();
0203     void endPinchGesture();
0204 
0205 private:
0206     void cancelActiveGestures();
0207     enum class StartPositionBehavior {
0208         Relevant,
0209         Irrelevant,
0210     };
0211     enum class Axis {
0212         Horizontal,
0213         Vertical,
0214         None,
0215     };
0216     int startSwipeGesture(uint fingerCount, const QPointF &startPos, StartPositionBehavior startPosBehavior);
0217     QVector<SwipeGesture *> m_swipeGestures;
0218     QVector<PinchGesture *> m_pinchGestures;
0219     QVector<SwipeGesture *> m_activeSwipeGestures;
0220     QVector<PinchGesture *> m_activePinchGestures;
0221     QMap<Gesture *, QMetaObject::Connection> m_destroyConnections;
0222 
0223     QPointF m_currentDelta = QPointF(0, 0);
0224     qreal m_currentScale = 1; // For Pinch Gesture recognition
0225     uint m_currentFingerCount = 0;
0226     Axis m_currentSwipeAxis = Axis::None;
0227 };
0228 
0229 }
0230 
0231 Q_DECLARE_METATYPE(KWin::SwipeGesture::Direction)
0232 Q_DECLARE_METATYPE(KWin::PinchGesture::Direction)