From 1b7a48de401b58f0e79e7ccc0a4e73ead99ccec4 Mon Sep 17 00:00:00 2001 From: Aleix Pol Date: Sun, 7 May 2023 23:42:14 +0200 Subject: [PATCH] effects: Move the TogglableState class into a reusable space --- src/libkwineffects/CMakeLists.txt | 3 + src/libkwineffects/togglablestate.cpp | 245 ++++++++++++++++++++++++ src/libkwineffects/togglablestate.h | 120 ++++++++++++ src/plugins/overview/overvieweffect.cpp | 224 +--------------------- src/plugins/overview/overvieweffect.h | 99 +--------- 5 files changed, 370 insertions(+), 321 deletions(-) create mode 100644 src/libkwineffects/togglablestate.cpp create mode 100644 src/libkwineffects/togglablestate.h diff --git a/src/libkwineffects/CMakeLists.txt b/src/libkwineffects/CMakeLists.txt index 9b0adedc68..fd728cec73 100644 --- a/src/libkwineffects/CMakeLists.txt +++ b/src/libkwineffects/CMakeLists.txt @@ -17,6 +17,9 @@ set(kwin_EFFECTSLIB_SRCS kwinoffscreenquickview.cpp kwinquickeffect.cpp logging.cpp + rendertarget.cpp + renderviewport.cpp + togglablestate.cpp ) add_library(kwineffects SHARED ${kwin_EFFECTSLIB_SRCS}) diff --git a/src/libkwineffects/togglablestate.cpp b/src/libkwineffects/togglablestate.cpp new file mode 100644 index 0000000000..64b57480e7 --- /dev/null +++ b/src/libkwineffects/togglablestate.cpp @@ -0,0 +1,245 @@ +/* + SPDX-FileCopyrightText: 2023 Aleix Pol Gonzalez + + 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()) + , m_activateAction(std::make_unique()) + , m_toggleAction(std::make_unique()) +{ + 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 TogglableState::progressCallback() +{ + return [this](qreal progress) { + setProgress(progress); + }; +} + +std::function 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 &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); + }); + } +} + +} diff --git a/src/libkwineffects/togglablestate.h b/src/libkwineffects/togglablestate.h new file mode 100644 index 0000000000..fc3926dc14 --- /dev/null +++ b/src/libkwineffects/togglablestate.h @@ -0,0 +1,120 @@ +/* + SPDX-FileCopyrightText: 2023 Aleix Pol Gonzalez + + SPDX-License-Identifier: GPL-2.0-or-later +*/ + +#pragma once + +#include "libkwineffects/kwineffects_export.h" +#include +#include +#include + +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 progressCallback(); + std::function 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 m_deactivateAction; + std::unique_ptr m_activateAction; + std::unique_ptr 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 &borders); + +private: + QList m_touchBorderActivate; + TogglableState *const m_state; +}; + +} diff --git a/src/plugins/overview/overvieweffect.cpp b/src/plugins/overview/overvieweffect.cpp index 0117288425..45a953b48f 100644 --- a/src/plugins/overview/overvieweffect.cpp +++ b/src/plugins/overview/overvieweffect.cpp @@ -18,235 +18,13 @@ namespace KWin { -TogglableState::TogglableState(QObject *effect) - : QObject(effect) -{ - m_activateAction = new QAction(this); - connect(m_activateAction, &QAction::triggered, this, [this]() { - if (m_status == Status::Activating) { - if (m_partialActivationFactor > 0.5) { - activate(); - Q_EMIT activated(); - } else { - deactivate(); - Q_EMIT deactivated(); - } - } - }); - m_deactivateAction = new QAction(this); - connect(m_deactivateAction, &QAction::triggered, this, [this]() { - if (m_status == Status::Deactivating) { - if (m_partialActivationFactor < 0.5) { - deactivate(); - Q_EMIT deactivated(); - } else { - activate(); - Q_EMIT activated(); - } - } - }); - m_toggleAction = new QAction(this); - connect(m_toggleAction, &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; - } - } -} - -void TogglableState::setRegress(qreal regress) -{ - if (!effects->hasActiveFullScreenEffect() || effects->activeFullScreenEffect() == parent()) { - switch (m_status) { - case Status::Active: - case Status::Deactivating: - partialDeactivate(regress); - 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; - } -} - -void TogglableGesture::addTouchpadGesture(PinchDirection direction, uint fingerCount) -{ - auto progressCallback = [this](qreal progress) { - m_state->setProgress(progress); - }; - auto progressCallbackInv = [this](qreal progress) { - m_state->setRegress(progress); - }; - - effects->registerTouchpadPinchShortcut(direction, 4, m_state->activateAction(), progressCallback); - effects->registerTouchpadPinchShortcut(opposite(direction), 4, m_state->deactivateAction(), progressCallbackInv); -} - -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; - } -} - -void TogglableGesture::addTouchscreenSwipeGesture(SwipeDirection direction, uint fingerCount) -{ - auto progressCallback = [this](qreal progress) { - m_state->setProgress(progress); - }; - auto progressCallbackInv = [this](qreal progress) { - m_state->setRegress(progress); - }; - - effects->registerTouchscreenSwipeShortcut(direction, 3, m_state->activateAction(), progressCallback); - effects->registerTouchscreenSwipeShortcut(opposite(direction), 3, m_state->deactivateAction(), progressCallbackInv); -} - -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 &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); - }); - } -} - OverviewEffect::OverviewEffect() : m_state(new TogglableState(this)) , m_border(new TogglableTouchBorder(m_state)) , m_shutdownTimer(new QTimer(this)) { auto gesture = new TogglableGesture(m_state); - gesture->addTouchpadGesture(PinchDirection::Contracting, 4); + gesture->addTouchpadPinchGesture(PinchDirection::Contracting, 4); gesture->addTouchscreenSwipeGesture(SwipeDirection::Up, 3); connect(m_state, &TogglableState::activated, this, &OverviewEffect::activate); diff --git a/src/plugins/overview/overvieweffect.h b/src/plugins/overview/overvieweffect.h index 8d66de158a..e79c44f3de 100644 --- a/src/plugins/overview/overvieweffect.h +++ b/src/plugins/overview/overvieweffect.h @@ -7,108 +7,11 @@ #pragma once #include "libkwineffects/kwinquickeffect.h" +#include "libkwineffects/togglablestate.h" namespace KWin { -class TogglableState : public QObject -{ - Q_OBJECT -public: - enum class Status { - Inactive, - Activating, - Deactivating, - Active - }; - Q_ENUM(Status); - - TogglableState(QObject *parent); - - bool inProgress() const; - void setInProgress(bool gesture); - - qreal partialActivationFactor() const - { - return m_partialActivationFactor; - } - void setPartialActivationFactor(qreal factor); - - QAction *activateAction() const - { - return m_activateAction; - } - QAction *deactivateAction() const - { - return m_deactivateAction; - } - QAction *toggleAction() const - { - return m_toggleAction; - } - - 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: - 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); - - QAction *m_deactivateAction = nullptr; - QAction *m_activateAction = nullptr; - QAction *m_toggleAction = nullptr; - Status m_status = Status::Inactive; - bool m_inProgress = false; - qreal m_partialActivationFactor = 0; - - friend class TogglableGesture; - friend class TogglableTouchBorder; -}; - -class TogglableGesture : public QObject -{ -public: - TogglableGesture(TogglableState *state); - - void addTouchpadGesture(PinchDirection dir, uint fingerCount); - void addTouchscreenSwipeGesture(SwipeDirection direction, uint fingerCount); - -private: - TogglableState *const m_state; -}; - -class TogglableTouchBorder : public QObject -{ -public: - TogglableTouchBorder(TogglableState *state); - ~TogglableTouchBorder(); - - void setBorders(const QList &borders); - -private: - QList m_touchBorderActivate; - TogglableState *const m_state; -}; - class OverviewEffect : public QuickSceneEffect { Q_OBJECT