shift-shell/kwin/mobiletaskswitcher/mobiletaskswitchereffect.h
Luis Büchi 16192c5f71 add double tap to switch between 2 most recent apps in swicher
also simplified openApp signature and fixed a typo in code
FEATURE: 486555
2024-12-20 23:15:39 +01:00

213 lines
6.5 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 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(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?
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(EffectTouchBorderState *effectState);
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);
void setStatus(Status status);
Status status() const
{
return m_status;
}
void setCurrentTaskIndex(int newTaskIndex);
int currentTaskIndex() const
{
return m_currentTaskIndex;
}
void setInitialTaskIndex(int newTaskIndex);
int initialTaskIndex() const
{
return m_initialTaskIndex;
}
void restartDoubleClickTimer();
public Q_SLOTS:
void processTouchPositionChanged(qreal primaryPosition, qreal orthogonalPosition);
Q_SIGNALS:
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:
Status m_status = Status::Inactive;
EffectTouchBorderState *m_effectState;
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();
}
};
class MobileTaskSwitcherEffect : public QuickSceneEffect
{
Q_OBJECT
public:
enum class Status { Inactive, Activating, Deactivating, Active };
MobileTaskSwitcherEffect();
~MobileTaskSwitcherEffect() override;
int animationDuration() const;
void setAnimationDuration(int duration);
int requestedEffectChainPosition() const override;
bool borderActivated(ElectricBorder border) override;
void reconfigure(ReconfigureFlags flags) override;
void grabbedKeyboardEvent(QKeyEvent *keyEvent) override;
void setDBusState(bool active);
public Q_SLOTS:
void activate();
void realDeactivate();
void deactivate(bool deactivateInstantly);
void quickDeactivate();
void toggle();
Q_SIGNALS:
void animationDurationChanged();
void gestureInProgressChanged();
private:
void invokeEffect();
EffectTouchBorderState *const m_effectState;
MobileTaskSwitcherState *const m_taskSwitcherState;
TaskModel *const m_taskModel;
EffectTouchBorder *const m_border;
QList<int> m_borderActivate = {ElectricBorder::ElectricBottom};
std::unique_ptr<QAction> m_toggleAction;
QList<QKeySequence> m_toggleShortcut;
QTimer *m_shutdownTimer;
int m_animationDuration = 400;
};
} // namespace KWin