shift-shell/kwin/mobiletaskswitcher/plugin/mobiletaskswitchereffect.h

192 lines
6 KiB
C++

// SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
// SPDX-FileCopyrightText: 2023 Devin Lin <devin@kde.org>
// SPDX-FileCopyrightText: 2024 Luis Büchi <luis.buechi@kdemail.net>
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <effect/effect.h>
#include <effect/effecthandler.h>
#include <effect/quickeffect.h>
#include <window.h>
#include <span>
#include <QAction>
#include <QElapsedTimer>
#include <QKeySequence>
#include <QTimer>
#include <KGlobalAccel>
#include <KLocalizedString>
#include "effecttouchborder.h"
#include "taskfiltermodel.h"
#include "taskmodel.h"
namespace KWin
{
class MobileTaskSwitcherState : public QObject
{
Q_OBJECT
Q_PROPERTY(bool gestureEnabled READ gestureEnabled WRITE setGestureEnabled NOTIFY gestureEnabledChanged)
Q_PROPERTY(bool wasInActiveTask READ wasInActiveTask WRITE setWasInActiveTask NOTIFY wasInActiveTaskChanged)
Q_PROPERTY(int currentTaskIndex READ currentTaskIndex WRITE setCurrentTaskIndex NOTIFY currentTaskIndexChanged)
Q_PROPERTY(int initialTaskIndex READ initialTaskIndex WRITE setInitialTaskIndex NOTIFY initialTaskIndexChanged)
Q_PROPERTY(qreal touchXPosition READ touchXPosition NOTIFY touchPositionChanged)
Q_PROPERTY(qreal touchYPosition READ touchYPosition NOTIFY touchPositionChanged)
Q_PROPERTY(qreal xVelocity READ xVelocity NOTIFY velocityChanged)
Q_PROPERTY(qreal yVelocity READ yVelocity NOTIFY velocityChanged)
Q_PROPERTY(qreal totalSquaredVelocity READ totalSquaredVelocity NOTIFY velocityChanged)
Q_PROPERTY(qreal flickVelocityThreshold READ flickVelocityThreshold NOTIFY flickVelocityThresholdChanged)
Q_PROPERTY(qreal xPosition READ xPosition WRITE setXPosition NOTIFY xPositionChanged)
Q_PROPERTY(qreal yPosition READ yPosition WRITE setYPosition NOTIFY yPositionChanged)
Q_PROPERTY(bool gestureInProgress READ gestureInProgress NOTIFY gestureInProgressChanged)
Q_PROPERTY(KWin::MobileTaskSwitcherState::Status status READ status WRITE setStatus NOTIFY statusChanged)
Q_PROPERTY(qint64 elapsedTimeSinceStart READ getElapsedTimeSinceStart)
Q_PROPERTY(qint64 doubleClickInterval READ getDoubleClickInterval) // is there a better way than to forward this?
Q_PROPERTY(KWin::TaskModel *taskModel READ taskModel CONSTANT)
QML_ELEMENT
public:
enum class Status {
// TODO! I could (should?) re-add the activating and deactivating states again to match EffectTogglableState. could help with/tie into
// currentlyBeingOpened and currentlyBeingClosed
Inactive, // Task switcher is not fully showing
Active, // Task switcher is active and gesture not in progress anymore
Stopped // When is this the case?
};
Q_ENUM(Status)
MobileTaskSwitcherState(QObject *parent = nullptr);
Q_INVOKABLE void init(KWin::QuickSceneEffect *parent);
bool gestureEnabled() const;
void setGestureEnabled(bool gestureEnabled);
bool gestureInProgress() const;
void setGestureInProgress(bool gestureInProgress);
bool wasInActiveTask() const;
void setWasInActiveTask(bool wasInActiveTask);
Q_INVOKABLE void updateWasInActiveTask(KWin::Window *window);
qreal touchXPosition() const;
qreal touchYPosition() const;
qreal xVelocity() const;
qreal yVelocity() const;
qreal totalSquaredVelocity() const;
qreal flickVelocityThreshold() const;
void setFlickVelocityThreshold(qreal flickVelocityThreshold);
qreal xPosition() const;
void setXPosition(qreal positionX);
qreal yPosition() const;
void setYPosition(qreal positionY);
Status status() const;
void setStatus(Status status);
int currentTaskIndex() const;
void setCurrentTaskIndex(int newTaskIndex);
int initialTaskIndex() const;
void setInitialTaskIndex(int newTaskIndex);
void restartDoubleClickTimer();
int animationDuration() const;
void setDBusState(bool active);
TaskModel *taskModel() const;
public Q_SLOTS:
void processTouchPositionChanged(qreal primaryPosition, qreal orthogonalPosition);
void activate();
void realDeactivate();
void deactivate(bool deactivateInstantly);
void quickDeactivate();
void toggle();
Q_SIGNALS:
void gestureEnabledChanged();
void activated();
void deactivated();
void gestureInProgressChanged();
void statusChanged();
void wasInActiveTaskChanged();
void currentTaskIndexChanged();
void initialTaskIndexChanged();
void touchPositionChanged();
void velocityChanged();
void flickVelocityThresholdChanged();
void xPositionChanged();
void yPositionChanged();
private Q_SLOTS:
void refreshBorders();
private:
void invokeEffect();
bool m_gestureEnabled{false};
EffectTouchBorderState *m_effectState{nullptr};
EffectTouchBorder *m_border{nullptr};
TaskModel *m_taskModel{nullptr};
KWin::QuickSceneEffect *m_effect{nullptr};
Status m_status = Status::Inactive;
bool m_gestureInProgress = false;
int m_currentTaskIndex;
int m_initialTaskIndex;
void clearVelocityFilter();
void calculateFilteredVelocity(qreal primaryPosition, qreal orthogonalPosition);
qint64 getElapsedTimeSinceStart();
// velocities in (logical) pixels/msec
QElapsedTimer m_frameTimer;
qreal m_flickVelocityThreshold = 0.5 * 0.5; // squared because total velocity is kept as a square
qreal m_filterTimeConstant = 0.03; // time constant of velocity filter
qreal m_touchXPosition;
qreal m_touchYPosition;
qreal m_xVelocity = 0;
qreal m_yVelocity = 0;
// Using the square of velocity for the total (2-axis) because we just need it
// for one threshold comparison and we skip having to calculate the square root
qreal m_totalSquaredVelocity;
// Positions of the task switcher effect itself
qreal m_xPosition = 0;
qreal m_yPosition = 0;
bool m_wasInActiveTask;
QElapsedTimer *m_doubleClickTimer;
qint64 getDoubleClickInterval() const
{
return qApp->doubleClickInterval();
}
QTimer *m_shutdownTimer;
};
} // namespace KWin