File indexing completed on 2024-04-28 05:30:17

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