a1191bea18
Use isNull on QSizeF to check for a zero delta instead of comparing it with a default-constructed QSizeF, which in practice initializes to (-1.0,-1.0). This caused relative motion events to be omitted if the delta happened to be equal to (-1.0,-1.0), causing mouse jumping in some applications. BUG: 444510 Signed-off-by: John Brooks <john@fastquake.com>
235 lines
6.1 KiB
C++
235 lines
6.1 KiB
C++
/*
|
|
KWin - the KDE window manager
|
|
This file is part of the KDE project.
|
|
|
|
SPDX-FileCopyrightText: 2017 Martin Gräßlin <mgraesslin@kde.org>
|
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
#ifndef KWIN_GESTURES_H
|
|
#define KWIN_GESTURES_H
|
|
|
|
#include <kwin_export.h>
|
|
|
|
#include <QMap>
|
|
#include <QObject>
|
|
#include <QPointF>
|
|
#include <QVector>
|
|
|
|
namespace KWin
|
|
{
|
|
/*
|
|
* Everytime the scale of the gesture changes by this much, the callback changes by 1.
|
|
* This is the amount of change for 1 unit of change, like switch by 1 desktop.
|
|
* */
|
|
static const qreal DEFAULT_UNIT_SCALE_DELTA = .2; // 20%
|
|
|
|
class Gesture : public QObject
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
~Gesture() override;
|
|
|
|
protected:
|
|
explicit Gesture(QObject *parent);
|
|
|
|
Q_SIGNALS:
|
|
/**
|
|
* Matching of a gesture started and this Gesture might match.
|
|
* On further evaluation either the signal @ref triggered or
|
|
* @ref cancelled will get emitted.
|
|
*/
|
|
void started();
|
|
/**
|
|
* Gesture matching ended and this Gesture matched.
|
|
*/
|
|
void triggered();
|
|
/**
|
|
* This Gesture no longer matches.
|
|
*/
|
|
void cancelled();
|
|
};
|
|
|
|
class SwipeGesture : public Gesture
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
enum class Direction {
|
|
Down,
|
|
Left,
|
|
Up,
|
|
Right,
|
|
};
|
|
|
|
explicit SwipeGesture(QObject *parent = nullptr);
|
|
~SwipeGesture() override;
|
|
|
|
bool minimumFingerCountIsRelevant() const;
|
|
void setMinimumFingerCount(uint count);
|
|
uint minimumFingerCount() const;
|
|
|
|
bool maximumFingerCountIsRelevant() const;
|
|
void setMaximumFingerCount(uint count);
|
|
uint maximumFingerCount() const;
|
|
|
|
Direction direction() const;
|
|
void setDirection(Direction direction);
|
|
|
|
void setMinimumX(int x);
|
|
int minimumX() const;
|
|
bool minimumXIsRelevant() const;
|
|
void setMinimumY(int y);
|
|
int minimumY() const;
|
|
bool minimumYIsRelevant() const;
|
|
|
|
void setMaximumX(int x);
|
|
int maximumX() const;
|
|
bool maximumXIsRelevant() const;
|
|
void setMaximumY(int y);
|
|
int maximumY() const;
|
|
bool maximumYIsRelevant() const;
|
|
void setStartGeometry(const QRect &geometry);
|
|
|
|
QPointF minimumDelta() const;
|
|
void setMinimumDelta(const QPointF &delta);
|
|
bool isMinimumDeltaRelevant() const;
|
|
|
|
qreal deltaToProgress(const QPointF &delta) const;
|
|
bool minimumDeltaReached(const QPointF &delta) const;
|
|
|
|
Q_SIGNALS:
|
|
/**
|
|
* The progress of the gesture if a minimumDelta is set.
|
|
* The progress is reported in [0.0,1.0]
|
|
*/
|
|
void progress(qreal);
|
|
|
|
/**
|
|
* The progress in actual pixel distance traveled by the fingers
|
|
*/
|
|
void deltaProgress(const QPointF &delta);
|
|
|
|
private:
|
|
bool m_minimumFingerCountRelevant = false;
|
|
uint m_minimumFingerCount = 0;
|
|
bool m_maximumFingerCountRelevant = false;
|
|
uint m_maximumFingerCount = 0;
|
|
Direction m_direction = Direction::Down;
|
|
bool m_minimumXRelevant = false;
|
|
int m_minimumX = 0;
|
|
bool m_minimumYRelevant = false;
|
|
int m_minimumY = 0;
|
|
bool m_maximumXRelevant = false;
|
|
int m_maximumX = 0;
|
|
bool m_maximumYRelevant = false;
|
|
int m_maximumY = 0;
|
|
bool m_minimumDeltaRelevant = false;
|
|
QPointF m_minimumDelta;
|
|
};
|
|
|
|
class PinchGesture : public Gesture
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
enum class Direction {
|
|
Expanding,
|
|
Contracting,
|
|
};
|
|
|
|
explicit PinchGesture(QObject *parent = nullptr);
|
|
~PinchGesture() override;
|
|
|
|
bool minimumFingerCountIsRelevant() const;
|
|
void setMinimumFingerCount(uint count);
|
|
uint minimumFingerCount() const;
|
|
|
|
bool maximumFingerCountIsRelevant() const;
|
|
void setMaximumFingerCount(uint count);
|
|
uint maximumFingerCount() const;
|
|
|
|
Direction direction() const;
|
|
void setDirection(Direction direction);
|
|
|
|
qreal minimumScaleDelta() const;
|
|
|
|
/**
|
|
* scaleDelta is the % scale difference needed to trigger
|
|
* 0.25 will trigger when scale reaches 0.75 or 1.25
|
|
*/
|
|
void setMinimumScaleDelta(const qreal &scaleDelta);
|
|
bool isMinimumScaleDeltaRelevant() const;
|
|
|
|
qreal scaleDeltaToProgress(const qreal &scaleDelta) const;
|
|
bool minimumScaleDeltaReached(const qreal &scaleDelta) const;
|
|
|
|
Q_SIGNALS:
|
|
/**
|
|
* The progress of the gesture if a minimumDelta is set.
|
|
* The progress is reported in [0.0,1.0]
|
|
*/
|
|
void progress(qreal);
|
|
|
|
private:
|
|
bool m_minimumFingerCountRelevant = false;
|
|
uint m_minimumFingerCount = 0;
|
|
bool m_maximumFingerCountRelevant = false;
|
|
uint m_maximumFingerCount = 0;
|
|
Direction m_direction = Direction::Expanding;
|
|
bool m_minimumScaleDeltaRelevant = false;
|
|
qreal m_minimumScaleDelta = DEFAULT_UNIT_SCALE_DELTA;
|
|
};
|
|
|
|
class KWIN_EXPORT GestureRecognizer : public QObject
|
|
{
|
|
Q_OBJECT
|
|
public:
|
|
GestureRecognizer(QObject *parent = nullptr);
|
|
~GestureRecognizer() override;
|
|
|
|
void registerSwipeGesture(SwipeGesture *gesture);
|
|
void unregisterSwipeGesture(SwipeGesture *gesture);
|
|
void registerPinchGesture(PinchGesture *gesture);
|
|
void unregisterPinchGesture(PinchGesture *gesture);
|
|
|
|
int startSwipeGesture(uint fingerCount);
|
|
int startSwipeGesture(const QPointF &startPos);
|
|
|
|
void updateSwipeGesture(const QPointF &delta);
|
|
void cancelSwipeGesture();
|
|
void endSwipeGesture();
|
|
|
|
int startPinchGesture(uint fingerCount);
|
|
void updatePinchGesture(qreal scale, qreal angleDelta, const QPointF &posDelta);
|
|
void cancelPinchGesture();
|
|
void endPinchGesture();
|
|
|
|
private:
|
|
void cancelActiveGestures();
|
|
enum class StartPositionBehavior {
|
|
Relevant,
|
|
Irrelevant,
|
|
};
|
|
enum class Axis {
|
|
Horizontal,
|
|
Vertical,
|
|
None,
|
|
};
|
|
int startSwipeGesture(uint fingerCount, const QPointF &startPos, StartPositionBehavior startPosBehavior);
|
|
QVector<SwipeGesture *> m_swipeGestures;
|
|
QVector<PinchGesture *> m_pinchGestures;
|
|
QVector<SwipeGesture *> m_activeSwipeGestures;
|
|
QVector<PinchGesture *> m_activePinchGestures;
|
|
QMap<Gesture *, QMetaObject::Connection> m_destroyConnections;
|
|
|
|
QPointF m_currentDelta = QPointF(0, 0);
|
|
qreal m_currentScale = 1; // For Pinch Gesture recognition
|
|
uint m_currentFingerCount = 0;
|
|
Axis m_currentSwipeAxis = Axis::None;
|
|
};
|
|
|
|
}
|
|
|
|
Q_DECLARE_METATYPE(KWin::SwipeGesture::Direction)
|
|
Q_DECLARE_METATYPE(KWin::PinchGesture::Direction)
|
|
|
|
#endif
|