effects: Move the TogglableState class into a reusable space
parent
bb8e5458a7
commit
1b7a48de40
@ -0,0 +1,245 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2023 Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "togglablestate.h"
|
||||
#include "kwineffects.h"
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
TogglableState::TogglableState(Effect *effect)
|
||||
: QObject(effect)
|
||||
, m_deactivateAction(std::make_unique<QAction>())
|
||||
, m_activateAction(std::make_unique<QAction>())
|
||||
, m_toggleAction(std::make_unique<QAction>())
|
||||
{
|
||||
connect(m_activateAction.get(), &QAction::triggered, this, [this]() {
|
||||
if (m_status == Status::Activating) {
|
||||
if (m_partialActivationFactor > 0.5) {
|
||||
activate();
|
||||
Q_EMIT activated();
|
||||
} else {
|
||||
deactivate();
|
||||
Q_EMIT deactivated();
|
||||
}
|
||||
}
|
||||
});
|
||||
connect(m_deactivateAction.get(), &QAction::triggered, this, [this]() {
|
||||
if (m_status == Status::Deactivating) {
|
||||
if (m_partialActivationFactor < 0.5) {
|
||||
deactivate();
|
||||
Q_EMIT deactivated();
|
||||
} else {
|
||||
activate();
|
||||
Q_EMIT activated();
|
||||
}
|
||||
}
|
||||
});
|
||||
connect(m_toggleAction.get(), &QAction::triggered, this, &TogglableState::toggle);
|
||||
}
|
||||
|
||||
void TogglableState::activate()
|
||||
{
|
||||
setStatus(Status::Active);
|
||||
setInProgress(false);
|
||||
setPartialActivationFactor(0.0);
|
||||
}
|
||||
|
||||
void TogglableState::setPartialActivationFactor(qreal factor)
|
||||
{
|
||||
if (m_partialActivationFactor != factor) {
|
||||
m_partialActivationFactor = factor;
|
||||
Q_EMIT partialActivationFactorChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void TogglableState::deactivate()
|
||||
{
|
||||
setInProgress(false);
|
||||
setPartialActivationFactor(0.0);
|
||||
}
|
||||
|
||||
bool TogglableState::inProgress() const
|
||||
{
|
||||
return m_inProgress;
|
||||
}
|
||||
|
||||
void TogglableState::setInProgress(bool gesture)
|
||||
{
|
||||
if (m_inProgress != gesture) {
|
||||
m_inProgress = gesture;
|
||||
Q_EMIT inProgressChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void TogglableState::setStatus(Status status)
|
||||
{
|
||||
if (m_status != status) {
|
||||
m_status = status;
|
||||
Q_EMIT statusChanged(status);
|
||||
}
|
||||
}
|
||||
|
||||
void TogglableState::partialActivate(qreal factor)
|
||||
{
|
||||
if (effects->isScreenLocked()) {
|
||||
return;
|
||||
}
|
||||
|
||||
setStatus(Status::Activating);
|
||||
setPartialActivationFactor(factor);
|
||||
setInProgress(true);
|
||||
}
|
||||
|
||||
void TogglableState::partialDeactivate(qreal factor)
|
||||
{
|
||||
setStatus(Status::Deactivating);
|
||||
setPartialActivationFactor(1.0 - factor);
|
||||
setInProgress(true);
|
||||
}
|
||||
|
||||
void TogglableState::toggle()
|
||||
{
|
||||
if (m_status == Status::Inactive || m_partialActivationFactor > 0.5) {
|
||||
activate();
|
||||
Q_EMIT activated();
|
||||
} else {
|
||||
deactivate();
|
||||
Q_EMIT deactivated();
|
||||
}
|
||||
}
|
||||
|
||||
void TogglableState::setProgress(qreal progress)
|
||||
{
|
||||
if (!effects->hasActiveFullScreenEffect() || effects->activeFullScreenEffect() == parent()) {
|
||||
switch (m_status) {
|
||||
case Status::Inactive:
|
||||
case Status::Activating:
|
||||
partialActivate(progress);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TogglableState::setRegress(qreal regress)
|
||||
{
|
||||
if (!effects->hasActiveFullScreenEffect() || effects->activeFullScreenEffect() == parent()) {
|
||||
switch (m_status) {
|
||||
case Status::Active:
|
||||
case Status::Deactivating:
|
||||
partialDeactivate(regress);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TogglableGesture::TogglableGesture(TogglableState *state)
|
||||
: QObject(state)
|
||||
, m_state(state)
|
||||
{
|
||||
}
|
||||
|
||||
static PinchDirection opposite(PinchDirection direction)
|
||||
{
|
||||
switch (direction) {
|
||||
case PinchDirection::Contracting:
|
||||
return PinchDirection::Expanding;
|
||||
case PinchDirection::Expanding:
|
||||
return PinchDirection::Contracting;
|
||||
}
|
||||
}
|
||||
|
||||
static SwipeDirection opposite(SwipeDirection direction)
|
||||
{
|
||||
switch (direction) {
|
||||
case SwipeDirection::Invalid:
|
||||
return SwipeDirection::Invalid;
|
||||
case SwipeDirection::Down:
|
||||
return SwipeDirection::Up;
|
||||
case SwipeDirection::Up:
|
||||
return SwipeDirection::Down;
|
||||
case SwipeDirection::Left:
|
||||
return SwipeDirection::Right;
|
||||
case SwipeDirection::Right:
|
||||
return SwipeDirection::Left;
|
||||
}
|
||||
}
|
||||
|
||||
std::function<void(qreal progress)> TogglableState::progressCallback()
|
||||
{
|
||||
return [this](qreal progress) {
|
||||
setProgress(progress);
|
||||
};
|
||||
}
|
||||
|
||||
std::function<void(qreal progress)> TogglableState::regressCallback()
|
||||
{
|
||||
return [this](qreal progress) {
|
||||
setRegress(progress);
|
||||
};
|
||||
}
|
||||
|
||||
void TogglableGesture::addTouchpadPinchGesture(PinchDirection direction, uint fingerCount)
|
||||
{
|
||||
effects->registerTouchpadPinchShortcut(direction, fingerCount, m_state->activateAction(), m_state->progressCallback());
|
||||
effects->registerTouchpadPinchShortcut(opposite(direction), fingerCount, m_state->deactivateAction(), m_state->regressCallback());
|
||||
}
|
||||
|
||||
void TogglableGesture::addTouchpadSwipeGesture(SwipeDirection direction, uint fingerCount)
|
||||
{
|
||||
effects->registerTouchpadSwipeShortcut(direction, fingerCount, m_state->activateAction(), m_state->progressCallback());
|
||||
effects->registerTouchpadSwipeShortcut(opposite(direction), fingerCount, m_state->deactivateAction(), m_state->regressCallback());
|
||||
}
|
||||
|
||||
void TogglableGesture::addTouchscreenSwipeGesture(SwipeDirection direction, uint fingerCount)
|
||||
{
|
||||
effects->registerTouchscreenSwipeShortcut(direction, fingerCount, m_state->activateAction(), m_state->progressCallback());
|
||||
effects->registerTouchscreenSwipeShortcut(opposite(direction), fingerCount, m_state->deactivateAction(), m_state->regressCallback());
|
||||
}
|
||||
|
||||
TogglableTouchBorder::TogglableTouchBorder(TogglableState *state)
|
||||
: QObject(state)
|
||||
, m_state(state)
|
||||
{
|
||||
}
|
||||
|
||||
TogglableTouchBorder::~TogglableTouchBorder()
|
||||
{
|
||||
for (const ElectricBorder &border : std::as_const(m_touchBorderActivate)) {
|
||||
effects->unregisterTouchBorder(border, m_state->toggleAction());
|
||||
}
|
||||
}
|
||||
|
||||
void TogglableTouchBorder::setBorders(const QList<int> &touchActivateBorders)
|
||||
{
|
||||
for (const ElectricBorder &border : std::as_const(m_touchBorderActivate)) {
|
||||
effects->unregisterTouchBorder(border, m_state->toggleAction());
|
||||
}
|
||||
m_touchBorderActivate.clear();
|
||||
|
||||
for (const int &border : touchActivateBorders) {
|
||||
m_touchBorderActivate.append(ElectricBorder(border));
|
||||
effects->registerRealtimeTouchBorder(ElectricBorder(border), m_state->toggleAction(), [this](ElectricBorder border, const QPointF &deltaProgress, const EffectScreen *screen) {
|
||||
if (m_state->status() == TogglableState::Status::Active) {
|
||||
return;
|
||||
}
|
||||
const int maxDelta = 500; // Arbitrary logical pixels value seems to behave better than scaledScreenSize
|
||||
qreal progress = 0;
|
||||
if (border == ElectricTop || border == ElectricBottom) {
|
||||
progress = std::min(1.0, std::abs(deltaProgress.y()) / maxDelta);
|
||||
} else {
|
||||
progress = std::min(1.0, std::abs(deltaProgress.x()) / maxDelta);
|
||||
}
|
||||
m_state->setProgress(progress);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,120 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2023 Aleix Pol Gonzalez <aleixpol@kde.org>
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "libkwineffects/kwineffects_export.h"
|
||||
#include <QAction>
|
||||
#include <QObject>
|
||||
#include <kwinglobals.h>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
|
||||
class Effect;
|
||||
|
||||
class KWINEFFECTS_EXPORT TogglableState : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
enum class Status {
|
||||
Inactive,
|
||||
Activating,
|
||||
Deactivating,
|
||||
Active
|
||||
};
|
||||
Q_ENUM(Status);
|
||||
|
||||
TogglableState(Effect *parent);
|
||||
|
||||
bool inProgress() const;
|
||||
void setInProgress(bool gesture);
|
||||
|
||||
qreal partialActivationFactor() const
|
||||
{
|
||||
return m_partialActivationFactor;
|
||||
}
|
||||
void setPartialActivationFactor(qreal factor);
|
||||
|
||||
QAction *activateAction() const
|
||||
{
|
||||
return m_activateAction.get();
|
||||
}
|
||||
QAction *deactivateAction() const
|
||||
{
|
||||
return m_deactivateAction.get();
|
||||
}
|
||||
QAction *toggleAction() const
|
||||
{
|
||||
return m_toggleAction.get();
|
||||
}
|
||||
|
||||
void activate();
|
||||
void deactivate();
|
||||
void toggle();
|
||||
void setStatus(Status status);
|
||||
Status status() const
|
||||
{
|
||||
return m_status;
|
||||
}
|
||||
|
||||
Q_SIGNALS:
|
||||
void inProgressChanged();
|
||||
void partialActivationFactorChanged();
|
||||
void activated();
|
||||
void deactivated();
|
||||
void statusChanged(Status status);
|
||||
|
||||
protected:
|
||||
std::function<void(qreal progress)> progressCallback();
|
||||
std::function<void(qreal progress)> regressCallback();
|
||||
void setProgress(qreal progress);
|
||||
|
||||
/// regress being the progress when on an active state
|
||||
void setRegress(qreal regress);
|
||||
|
||||
private:
|
||||
void partialActivate(qreal factor);
|
||||
void partialDeactivate(qreal factor);
|
||||
|
||||
std::unique_ptr<QAction> m_deactivateAction;
|
||||
std::unique_ptr<QAction> m_activateAction;
|
||||
std::unique_ptr<QAction> m_toggleAction;
|
||||
Status m_status = Status::Inactive;
|
||||
bool m_inProgress = false;
|
||||
qreal m_partialActivationFactor = 0;
|
||||
|
||||
friend class TogglableGesture;
|
||||
friend class TogglableTouchBorder;
|
||||
};
|
||||
|
||||
class KWINEFFECTS_EXPORT TogglableGesture : public QObject
|
||||
{
|
||||
public:
|
||||
TogglableGesture(TogglableState *state);
|
||||
|
||||
void addTouchpadPinchGesture(PinchDirection dir, uint fingerCount);
|
||||
void addTouchpadSwipeGesture(SwipeDirection dir, uint fingerCount);
|
||||
void addTouchscreenSwipeGesture(SwipeDirection direction, uint fingerCount);
|
||||
|
||||
private:
|
||||
TogglableState *const m_state;
|
||||
};
|
||||
|
||||
class KWINEFFECTS_EXPORT TogglableTouchBorder : public QObject
|
||||
{
|
||||
public:
|
||||
TogglableTouchBorder(TogglableState *state);
|
||||
~TogglableTouchBorder();
|
||||
|
||||
void setBorders(const QList<int> &borders);
|
||||
|
||||
private:
|
||||
QList<ElectricBorder> m_touchBorderActivate;
|
||||
TogglableState *const m_state;
|
||||
};
|
||||
|
||||
}
|
Loading…
Reference in New Issue