From c7c1ac78ea5a57fc599afb4e5b123ea36438e5ce Mon Sep 17 00:00:00 2001 From: Eric Edlund Date: Wed, 16 Mar 2022 15:42:42 -0400 Subject: [PATCH] Implement desktopSwitching() interface for realtime animations Added this interface to the VirtualDesktopManager. Realtime touchpad gestures update the interface to allow for mac os style desktop switching. --- autotests/test_virtual_desktops.cpp | 8 +++ src/effects.cpp | 10 ++++ src/libkwineffects/kwineffects.h | 11 ++++ src/virtualdesktops.cpp | 81 +++++++++++++++++++++++++++-- src/virtualdesktops.h | 27 ++++++++++ src/workspace.cpp | 13 +++++ src/workspace.h | 4 ++ 7 files changed, 151 insertions(+), 3 deletions(-) diff --git a/autotests/test_virtual_desktops.cpp b/autotests/test_virtual_desktops.cpp index 795acf8a45..0f33bff64a 100644 --- a/autotests/test_virtual_desktops.cpp +++ b/autotests/test_virtual_desktops.cpp @@ -35,8 +35,16 @@ void InputRedirection::registerAxisShortcut(Qt::KeyboardModifiers modifiers, Poi void InputRedirection::registerTouchpadSwipeShortcut(SwipeDirection, uint fingerCount, QAction*) { + Q_UNUSED(fingerCount) } +void InputRedirection::registerRealtimeTouchpadSwipeShortcut(SwipeDirection direction, uint fingerCount, QAction *action, std::function cb) +{ + Q_UNUSED(direction) + Q_UNUSED(fingerCount) + Q_UNUSED(action) + Q_UNUSED(cb) +} } Q_DECLARE_METATYPE(Qt::Orientation) diff --git a/src/effects.cpp b/src/effects.cpp index 75255bca24..07271838bf 100644 --- a/src/effects.cpp +++ b/src/effects.cpp @@ -155,6 +155,16 @@ EffectsHandlerImpl::EffectsHandlerImpl(Compositor *compositor, Scene *scene) } } ); + connect(ws, &Workspace::currentDesktopChanging, this, + [this](uint currentDesktop, QPointF offset, KWin::AbstractClient* c){ + Q_EMIT desktopChanging(currentDesktop, offset, c ? c->effectWindow() : nullptr); + } + ); + connect(ws, &Workspace::currentDesktopChangingCancelled, this, + [this](){ + Q_EMIT desktopChangingCancelled(); + } + ); connect(ws, &Workspace::desktopPresenceChanged, this, [this](AbstractClient *c, int old) { if (!c->effectWindow()) { diff --git a/src/libkwineffects/kwineffects.h b/src/libkwineffects/kwineffects.h index 4bb5e2878e..cc85970961 100644 --- a/src/libkwineffects/kwineffects.h +++ b/src/libkwineffects/kwineffects.h @@ -1468,6 +1468,17 @@ Q_SIGNALS: * @since 4.9 */ void desktopChanged(int oldDesktop, int newDesktop, KWin::EffectWindow *with); + + /** + * Signal emmitted while desktop is changing for animation. + * @param currentDesktop The current desktop untiotherwise. + * @param offset The current desktop offset. + * offset.x() = .6 means 60% of the way to the desktop to the right. + * Positive Values means Up and Right. + */ + void desktopChanging(uint currentDesktop, QPointF offset, KWin::EffectWindow *with); + void desktopChangingCancelled(); + /** * @since 4.7 * @deprecated diff --git a/src/virtualdesktops.cpp b/src/virtualdesktops.cpp index 5414afb830..593f4aac79 100644 --- a/src/virtualdesktops.cpp +++ b/src/virtualdesktops.cpp @@ -22,9 +22,11 @@ #include #include + namespace KWin { static bool s_loadingDesktopSettings = false; +static const double GESTURE_SWITCH_THRESHOLD = .25; static QString generateDesktopId() { @@ -535,7 +537,7 @@ VirtualDesktop *VirtualDesktopManager::currentDesktop() const bool VirtualDesktopManager::setCurrent(uint newDesktop) { - if (newDesktop < 1 || newDesktop > count() || newDesktop == current()) { + if (newDesktop < 1 || newDesktop > count()) { return false; } auto d = desktopForX11Id(newDesktop); @@ -800,9 +802,11 @@ void VirtualDesktopManager::initShortcuts() initSwitchToShortcuts(); QAction *nextAction = addAction(QStringLiteral("Switch to Next Desktop"), i18n("Switch to Next Desktop"), &VirtualDesktopManager::slotNext); - input()->registerTouchpadSwipeShortcut(SwipeDirection::Right, 4, nextAction); QAction *previousAction = addAction(QStringLiteral("Switch to Previous Desktop"), i18n("Switch to Previous Desktop"), &VirtualDesktopManager::slotPrevious); - input()->registerTouchpadSwipeShortcut(SwipeDirection::Left, 4, previousAction); + Q_UNUSED(nextAction) + Q_UNUSED(previousAction) + + //shortcuts QAction *slotRightAction = addAction(QStringLiteral("Switch One Desktop to the Right"), i18n("Switch One Desktop to the Right"), &VirtualDesktopManager::slotRight); KGlobalAccel::setGlobalShortcut(slotRightAction, QKeySequence(Qt::CTRL | Qt::META | Qt::Key_Right)); QAction *slotLeftAction = addAction(QStringLiteral("Switch One Desktop to the Left"), i18n("Switch One Desktop to the Left"), &VirtualDesktopManager::slotLeft); @@ -812,6 +816,39 @@ void VirtualDesktopManager::initShortcuts() QAction *slotDownAction = addAction(QStringLiteral("Switch One Desktop Down"), i18n("Switch One Desktop Down"), &VirtualDesktopManager::slotDown); KGlobalAccel::setGlobalShortcut(slotDownAction, QKeySequence(Qt::CTRL | Qt::META | Qt::Key_Down)); + // Gestures + // These connections decide which desktop to end on after gesture ends + connect(m_swipeGestureReleasedRight, &QAction::triggered, this, &VirtualDesktopManager::gestureReleasedRight); + connect(m_swipeGestureReleasedLeft, &QAction::triggered, this, &VirtualDesktopManager::gestureReleasedLeft); + connect(m_swipeGestureReleasedUp, &QAction::triggered, this, &VirtualDesktopManager::gestureReleasedUp); + connect(m_swipeGestureReleasedDown, &QAction::triggered, this, &VirtualDesktopManager::gestureReleasedDown); + + //These take the live feedback from a gesture + input()->registerRealtimeTouchpadSwipeShortcut(SwipeDirection::Right, 3, m_swipeGestureReleasedRight, [this](qreal cb) { + m_currentDesktopOffset.setX(cb); + Q_EMIT currentChanging(current(), m_currentDesktopOffset); + }); + input()->registerRealtimeTouchpadSwipeShortcut(SwipeDirection::Left, 3, m_swipeGestureReleasedLeft, [this](qreal cb) { + m_currentDesktopOffset.setX(-cb); + Q_EMIT currentChanging(current(), m_currentDesktopOffset); + }); + input()->registerRealtimeTouchpadSwipeShortcut(SwipeDirection::Right, 4, m_swipeGestureReleasedRight, [this](qreal cb) { + m_currentDesktopOffset.setX(cb); + Q_EMIT currentChanging(current(), m_currentDesktopOffset); + }); + input()->registerRealtimeTouchpadSwipeShortcut(SwipeDirection::Left, 4, m_swipeGestureReleasedLeft, [this](qreal cb) { + m_currentDesktopOffset.setX(-cb); + Q_EMIT currentChanging(current(), m_currentDesktopOffset); + }); + input()->registerRealtimeTouchpadSwipeShortcut(SwipeDirection::Up, 3, m_swipeGestureReleasedUp, [this](qreal cb) { + m_currentDesktopOffset.setY(-cb); + Q_EMIT currentChanging(current(), m_currentDesktopOffset); + }); + input()->registerRealtimeTouchpadSwipeShortcut(SwipeDirection::Down, 3, m_swipeGestureReleasedDown, [this](qreal cb) { + m_currentDesktopOffset.setY(cb); + Q_EMIT currentChanging(current(), m_currentDesktopOffset); + }); + // axis events input()->registerAxisShortcut(Qt::ControlModifier | Qt::AltModifier, PointerAxisDown, findChild(QStringLiteral("Switch to Next Desktop"))); @@ -819,6 +856,44 @@ void VirtualDesktopManager::initShortcuts() findChild(QStringLiteral("Switch to Previous Desktop"))); } +void VirtualDesktopManager::gestureReleasedUp() +{ + if (m_currentDesktopOffset.y() <= -GESTURE_SWITCH_THRESHOLD) { + slotUp(); + } else { + Q_EMIT currentChangingCancelled(); + } + m_currentDesktopOffset = QPointF(0, 0); +} +void VirtualDesktopManager::gestureReleasedDown() +{ + if (m_currentDesktopOffset.y() >= GESTURE_SWITCH_THRESHOLD) { + slotDown(); + } else { + Q_EMIT currentChangingCancelled(); + } + m_currentDesktopOffset = QPointF(0, 0); +} +void VirtualDesktopManager::gestureReleasedLeft() +{ + if (m_currentDesktopOffset.x() <= -GESTURE_SWITCH_THRESHOLD) { + slotLeft(); + } else { + Q_EMIT currentChangingCancelled(); + } + m_currentDesktopOffset = QPointF(0, 0); +} +void VirtualDesktopManager::gestureReleasedRight() +{ + if (m_currentDesktopOffset.x() >= GESTURE_SWITCH_THRESHOLD) { + slotRight(); + } else { + setCurrent(current()); + Q_EMIT currentChangingCancelled(); + } + m_currentDesktopOffset = QPointF(0, 0); +} + void VirtualDesktopManager::initSwitchToShortcuts() { const QString toDesktop = QStringLiteral("Switch to Desktop %1"); diff --git a/src/virtualdesktops.h b/src/virtualdesktops.h index 0a0cf05173..5246a0ebdd 100644 --- a/src/virtualdesktops.h +++ b/src/virtualdesktops.h @@ -16,6 +16,7 @@ #include #include #include +#include // KDE includes #include @@ -24,6 +25,7 @@ class KLocalizedString; class NETRootInfo; class QAction; +class Options; namespace KWaylandServer { @@ -390,6 +392,17 @@ Q_SIGNALS: * @param newDesktop The virtual desktop changed to */ void currentChanged(uint previousDesktop, uint newDesktop); + + /** + * Signal emmitted for realtime desktop switching animations. + * @param currentDesktop The current virtual desktop + * @param offset The current total change in desktop coordinate + * Offset x and y are negative if switching Left and Down. + * Example: x = 0.6 means 60% of the way to the desktop to the right. + */ + void currentChanging(uint currentDesktop, QPointF offset); + void currentChangingCancelled(); + /** * Signal emitted whenever the desktop layout changes. * @param columns The new number of columns in the layout @@ -433,6 +446,14 @@ private Q_SLOTS: */ void slotDown(); + /* For gestured desktopSwitching + * Called when gesture ended, the thing that actually switches the desktop. + */ + void gestureReleasedUp(); + void gestureReleasedDown(); + void gestureReleasedLeft(); + void gestureReleasedRight(); + private: /** * Generate a desktop layout from EWMH _NET_DESKTOP_LAYOUT property parameters. @@ -477,6 +498,12 @@ private: KWaylandServer::PlasmaVirtualDesktopManagementInterface *m_virtualDesktopManagement = nullptr; KSharedConfig::Ptr m_config; + QAction *m_swipeGestureReleasedUp = new QAction(); + QAction *m_swipeGestureReleasedDown = new QAction(); + QAction *m_swipeGestureReleasedLeft = new QAction(); + QAction *m_swipeGestureReleasedRight = new QAction(); + QPointF m_currentDesktopOffset = QPointF(0, 0); + KWIN_SINGLETON_VARIABLE(VirtualDesktopManager, s_manager) }; diff --git a/src/workspace.cpp b/src/workspace.cpp index 8d2eeadb5a..d4c8699538 100644 --- a/src/workspace.cpp +++ b/src/workspace.cpp @@ -236,6 +236,8 @@ void Workspace::init() connect(vds, &VirtualDesktopManager::desktopCreated, this, &Workspace::slotDesktopAdded); connect(vds, &VirtualDesktopManager::desktopRemoved, this, &Workspace::slotDesktopRemoved); connect(vds, &VirtualDesktopManager::currentChanged, this, &Workspace::slotCurrentDesktopChanged); + connect(vds, &VirtualDesktopManager::currentChanging, this, &Workspace::slotCurrentDesktopChanging); + connect(vds, &VirtualDesktopManager::currentChangingCancelled, this, &Workspace::slotCurrentDesktopChangingCancelled); vds->setNavigationWrappingAround(options->isRollOverDesktops()); connect(options, &Options::rollOverDesktopsChanged, vds, &VirtualDesktopManager::setNavigationWrappingAround); vds->setConfig(config); @@ -1022,6 +1024,17 @@ void Workspace::slotCurrentDesktopChanged(uint oldDesktop, uint newDesktop) Q_EMIT currentDesktopChanged(oldDesktop, movingClient); } +void Workspace::slotCurrentDesktopChanging(uint currentDesktop, QPointF offset) +{ + closeActivePopup(); + Q_EMIT currentDesktopChanging(currentDesktop, offset, movingClient); +} + +void Workspace::slotCurrentDesktopChangingCancelled() +{ + Q_EMIT currentDesktopChangingCancelled(); +} + void Workspace::updateClientVisibilityOnDesktopChange(VirtualDesktop *newDesktop) { for (auto it = stacking_order.constBegin(); diff --git a/src/workspace.h b/src/workspace.h index ea232accdf..00ceb7a865 100644 --- a/src/workspace.h +++ b/src/workspace.h @@ -491,6 +491,8 @@ private Q_SLOTS: void updateCurrentActivity(const QString &new_activity); // virtual desktop handling void slotCurrentDesktopChanged(uint oldDesktop, uint newDesktop); + void slotCurrentDesktopChanging(uint currentDesktop, QPointF delta); + void slotCurrentDesktopChangingCancelled(); void slotDesktopAdded(VirtualDesktop *desktop); void slotDesktopRemoved(VirtualDesktop *desktop); void slotOutputEnabled(AbstractOutput *output); @@ -508,6 +510,8 @@ Q_SIGNALS: void desktopPresenceChanged(KWin::AbstractClient*, int); void currentActivityChanged(); void currentDesktopChanged(int, KWin::AbstractClient*); + void currentDesktopChanging(uint currentDesktop, QPointF delta, KWin::AbstractClient*);//for realtime animations + void currentDesktopChangingCancelled(); void clientAdded(KWin::AbstractClient *); void clientRemoved(KWin::AbstractClient*); void clientActivated(KWin::AbstractClient*);