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.
Also makes gestured switching use natural direction.

BUG: 185710
This commit is contained in:
Eric Edlund 2022-03-22 18:34:52 -04:00 committed by Nate Graham
parent 31ec0ceb24
commit 26a4f75944
7 changed files with 152 additions and 14 deletions

View file

@ -36,6 +36,13 @@ void InputRedirection::registerAxisShortcut(Qt::KeyboardModifiers modifiers, Poi
void InputRedirection::registerTouchpadSwipeShortcut(SwipeDirection, uint fingerCount, QAction *) void InputRedirection::registerTouchpadSwipeShortcut(SwipeDirection, uint fingerCount, QAction *)
{ {
Q_UNUSED(fingerCount)
}
void InputRedirection::registerRealtimeTouchpadSwipeShortcut(SwipeDirection, uint fingerCount, QAction *, std::function<void(qreal)> progressCallback)
{
Q_UNUSED(progressCallback)
Q_UNUSED(fingerCount)
} }
void InputRedirection::registerTouchscreenSwipeShortcut(SwipeDirection, uint fingerCount, QAction *) void InputRedirection::registerTouchscreenSwipeShortcut(SwipeDirection, uint fingerCount, QAction *)

View file

@ -145,13 +145,22 @@ EffectsHandlerImpl::EffectsHandlerImpl(Compositor *compositor, Scene *scene)
} }
}); });
connect(ws, &Workspace::currentDesktopChanged, this, [this](int old, AbstractClient *c) { connect(ws, &Workspace::currentDesktopChanged, this, [this](int old, AbstractClient *c) {
const int newDesktop = VirtualDesktopManager::self()->current(); const int newDesktop = VirtualDesktopManager::self()->current();
if (old != 0 && newDesktop != old) { if (old != 0 && newDesktop != old) {
Q_EMIT desktopChanged(old, newDesktop, c ? c->effectWindow() : nullptr); Q_EMIT desktopChanged(old, newDesktop, c ? c->effectWindow() : nullptr);
// TODO: remove in 4.10 // TODO: remove in 4.10
Q_EMIT desktopChanged(old, newDesktop); Q_EMIT desktopChanged(old, newDesktop);
}
} }
}); );
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) { connect(ws, &Workspace::desktopPresenceChanged, this, [this](AbstractClient *c, int old) {
if (!c->effectWindow()) { if (!c->effectWindow()) {
return; return;

View file

@ -1501,6 +1501,17 @@ Q_SIGNALS:
* @since 4.9 * @since 4.9
*/ */
void desktopChanged(int oldDesktop, int newDesktop, KWin::EffectWindow *with); 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 * @since 4.7
* @deprecated * @deprecated

View file

@ -19,13 +19,15 @@
// Qt // Qt
#include <QAction> #include <QAction>
#include <QUuid> #include <QUuid>
#include <QDebug> #include <QDebug>
#include <algorithm> #include <algorithm>
namespace KWin namespace KWin
{ {
static bool s_loadingDesktopSettings = false; static bool s_loadingDesktopSettings = false;
static const double GESTURE_SWITCH_THRESHOLD = .25;
static QString generateDesktopId() static QString generateDesktopId()
{ {
@ -209,6 +211,8 @@ VirtualDesktopManager::VirtualDesktopManager(QObject *parent)
: QObject(parent) : QObject(parent)
, m_navigationWrapsAround(false) , m_navigationWrapsAround(false)
, m_rootInfo(nullptr) , m_rootInfo(nullptr)
, m_swipeGestureReleasedY(new QAction(this))
, m_swipeGestureReleasedX(new QAction(this))
{ {
} }
@ -519,7 +523,7 @@ VirtualDesktop *VirtualDesktopManager::currentDesktop() const
bool VirtualDesktopManager::setCurrent(uint newDesktop) bool VirtualDesktopManager::setCurrent(uint newDesktop)
{ {
if (newDesktop < 1 || newDesktop > count() || newDesktop == current()) { if (newDesktop < 1 || newDesktop > count()) {
return false; return false;
} }
auto d = desktopForX11Id(newDesktop); auto d = desktopForX11Id(newDesktop);
@ -780,10 +784,10 @@ void VirtualDesktopManager::initShortcuts()
{ {
initSwitchToShortcuts(); initSwitchToShortcuts();
QAction *nextAction = addAction(QStringLiteral("Switch to Next Desktop"), i18n("Switch to Next Desktop"), &VirtualDesktopManager::slotNext); Q_UNUSED(addAction(QStringLiteral("Switch to Next Desktop"), i18n("Switch to Next Desktop"), &VirtualDesktopManager::slotNext))
input()->registerTouchpadSwipeShortcut(SwipeDirection::Right, 4, nextAction); Q_UNUSED(addAction(QStringLiteral("Switch to Previous Desktop"), i18n("Switch to Previous Desktop"), &VirtualDesktopManager::slotPrevious))
QAction *previousAction = addAction(QStringLiteral("Switch to Previous Desktop"), i18n("Switch to Previous Desktop"), &VirtualDesktopManager::slotPrevious);
input()->registerTouchpadSwipeShortcut(SwipeDirection::Left, 4, previousAction); //shortcuts
QAction *slotRightAction = addAction(QStringLiteral("Switch One Desktop to the Right"), i18n("Switch One Desktop to the Right"), &VirtualDesktopManager::slotRight); 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)); 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); QAction *slotLeftAction = addAction(QStringLiteral("Switch One Desktop to the Left"), i18n("Switch One Desktop to the Left"), &VirtualDesktopManager::slotLeft);
@ -793,14 +797,81 @@ void VirtualDesktopManager::initShortcuts()
QAction *slotDownAction = addAction(QStringLiteral("Switch One Desktop Down"), i18n("Switch One Desktop Down"), &VirtualDesktopManager::slotDown); 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)); 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_swipeGestureReleasedX.get(), &QAction::triggered, this, &VirtualDesktopManager::gestureReleasedX);
connect(m_swipeGestureReleasedY, &QAction::triggered, this, &VirtualDesktopManager::gestureReleasedY);
//These take the live feedback from a gesture
input()->registerRealtimeTouchpadSwipeShortcut(SwipeDirection::Left, 3, m_swipeGestureReleasedX.get(), [this](qreal cb) {
if (grid().width() > 1) {
m_currentDesktopOffset.setX(cb);
Q_EMIT currentChanging(current(), m_currentDesktopOffset);
}
});
input()->registerRealtimeTouchpadSwipeShortcut(SwipeDirection::Right, 3, m_swipeGestureReleasedX.get(), [this](qreal cb) {
if (grid().width() > 1) {
m_currentDesktopOffset.setX(-cb);
Q_EMIT currentChanging(current(), m_currentDesktopOffset);
}
});
input()->registerRealtimeTouchpadSwipeShortcut(SwipeDirection::Left, 4, m_swipeGestureReleasedX.get(), [this](qreal cb) {
if (grid().width() > 1) {
m_currentDesktopOffset.setX(cb);
Q_EMIT currentChanging(current(), m_currentDesktopOffset);
}
});
input()->registerRealtimeTouchpadSwipeShortcut(SwipeDirection::Right, 4, m_swipeGestureReleasedX.get(), [this](qreal cb) {
if (grid().width() > 1) {
m_currentDesktopOffset.setX(-cb);
Q_EMIT currentChanging(current(), m_currentDesktopOffset);
}
});
input()->registerRealtimeTouchpadSwipeShortcut(SwipeDirection::Down, 3, m_swipeGestureReleasedY.get(), [this](qreal cb) {
if (grid().height() > 1) {
m_currentDesktopOffset.setY(-cb);
Q_EMIT currentChanging(current(), m_currentDesktopOffset);
}
});
input()->registerRealtimeTouchpadSwipeShortcut(SwipeDirection::Up, 3, m_swipeGestureReleasedY.get(), [this](qreal cb) {
if (grid().height() > 1) {
m_currentDesktopOffset.setY(cb);
Q_EMIT currentChanging(current(), m_currentDesktopOffset);
}
});
input()->registerTouchscreenSwipeShortcut(SwipeDirection::Left, 3, slotRightAction);
input()->registerTouchscreenSwipeShortcut(SwipeDirection::Right, 3, slotLeftAction);
// axis events // axis events
input()->registerAxisShortcut(Qt::ControlModifier | Qt::AltModifier, PointerAxisDown, input()->registerAxisShortcut(Qt::ControlModifier | Qt::AltModifier, PointerAxisDown,
findChild<QAction *>(QStringLiteral("Switch to Next Desktop"))); findChild<QAction *>(QStringLiteral("Switch to Next Desktop")));
input()->registerAxisShortcut(Qt::ControlModifier | Qt::AltModifier, PointerAxisUp, input()->registerAxisShortcut(Qt::ControlModifier | Qt::AltModifier, PointerAxisUp,
findChild<QAction *>(QStringLiteral("Switch to Previous Desktop"))); findChild<QAction *>(QStringLiteral("Switch to Previous Desktop")));
}
input()->registerTouchscreenSwipeShortcut(SwipeDirection::Left, 3, nextAction); void VirtualDesktopManager::gestureReleasedY()
input()->registerTouchscreenSwipeShortcut(SwipeDirection::Right, 3, previousAction); {
if (m_currentDesktopOffset.y() <= -GESTURE_SWITCH_THRESHOLD) {
slotUp();
} else if (m_currentDesktopOffset.y() >= GESTURE_SWITCH_THRESHOLD) {
slotDown();
} else {
Q_EMIT currentChangingCancelled();
}
m_currentDesktopOffset = QPointF(0, 0);
}
void VirtualDesktopManager::gestureReleasedX()
{
if (m_currentDesktopOffset.x() <= -GESTURE_SWITCH_THRESHOLD) {
slotLeft();
} else if (m_currentDesktopOffset.x() >= GESTURE_SWITCH_THRESHOLD) {
slotRight();
} else {
Q_EMIT currentChangingCancelled();
}
m_currentDesktopOffset = QPointF(0, 0);
} }
void VirtualDesktopManager::initSwitchToShortcuts() void VirtualDesktopManager::initSwitchToShortcuts()

View file

@ -16,6 +16,7 @@
#include <QPoint> #include <QPoint>
#include <QPointer> #include <QPointer>
#include <QSize> #include <QSize>
#include <QAction>
// KDE includes // KDE includes
#include <KConfig> #include <KConfig>
@ -24,6 +25,7 @@
class KLocalizedString; class KLocalizedString;
class NETRootInfo; class NETRootInfo;
class QAction; class QAction;
class Options;
namespace KWaylandServer namespace KWaylandServer
{ {
@ -395,6 +397,17 @@ Q_SIGNALS:
* @param newDesktop The virtual desktop changed to * @param newDesktop The virtual desktop changed to
*/ */
void currentChanged(uint previousDesktop, uint newDesktop); 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. * Signal emitted whenever the desktop layout changes.
* @param columns The new number of columns in the layout * @param columns The new number of columns in the layout
@ -438,6 +451,12 @@ private Q_SLOTS:
*/ */
void slotDown(); void slotDown();
/* For gestured desktopSwitching
* Called when gesture ended, the thing that actually switches the desktop.
*/
void gestureReleasedY();
void gestureReleasedX();
private: private:
/** /**
* Generate a desktop layout from EWMH _NET_DESKTOP_LAYOUT property parameters. * Generate a desktop layout from EWMH _NET_DESKTOP_LAYOUT property parameters.
@ -482,6 +501,10 @@ private:
KWaylandServer::PlasmaVirtualDesktopManagementInterface *m_virtualDesktopManagement = nullptr; KWaylandServer::PlasmaVirtualDesktopManagementInterface *m_virtualDesktopManagement = nullptr;
KSharedConfig::Ptr m_config; KSharedConfig::Ptr m_config;
QScopedPointer<QAction> m_swipeGestureReleasedY;
QScopedPointer<QAction> m_swipeGestureReleasedX;
QPointF m_currentDesktopOffset = QPointF(0, 0);
KWIN_SINGLETON_VARIABLE(VirtualDesktopManager, s_manager) KWIN_SINGLETON_VARIABLE(VirtualDesktopManager, s_manager)
}; };

View file

@ -227,6 +227,8 @@ void Workspace::init()
connect(vds, &VirtualDesktopManager::desktopCreated, this, &Workspace::slotDesktopAdded); connect(vds, &VirtualDesktopManager::desktopCreated, this, &Workspace::slotDesktopAdded);
connect(vds, &VirtualDesktopManager::desktopRemoved, this, &Workspace::slotDesktopRemoved); connect(vds, &VirtualDesktopManager::desktopRemoved, this, &Workspace::slotDesktopRemoved);
connect(vds, &VirtualDesktopManager::currentChanged, this, &Workspace::slotCurrentDesktopChanged); 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()); vds->setNavigationWrappingAround(options->isRollOverDesktops());
connect(options, &Options::rollOverDesktopsChanged, vds, &VirtualDesktopManager::setNavigationWrappingAround); connect(options, &Options::rollOverDesktopsChanged, vds, &VirtualDesktopManager::setNavigationWrappingAround);
vds->setConfig(config); vds->setConfig(config);
@ -1024,6 +1026,17 @@ void Workspace::slotCurrentDesktopChanged(uint oldDesktop, uint newDesktop)
Q_EMIT currentDesktopChanged(oldDesktop, movingClient); 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) void Workspace::updateClientVisibilityOnDesktopChange(VirtualDesktop *newDesktop)
{ {
for (auto it = stacking_order.constBegin(); it != stacking_order.constEnd(); ++it) { for (auto it = stacking_order.constBegin(); it != stacking_order.constEnd(); ++it) {

View file

@ -510,6 +510,8 @@ private Q_SLOTS:
void updateCurrentActivity(const QString &new_activity); void updateCurrentActivity(const QString &new_activity);
// virtual desktop handling // virtual desktop handling
void slotCurrentDesktopChanged(uint oldDesktop, uint newDesktop); void slotCurrentDesktopChanged(uint oldDesktop, uint newDesktop);
void slotCurrentDesktopChanging(uint currentDesktop, QPointF delta);
void slotCurrentDesktopChangingCancelled();
void slotDesktopAdded(VirtualDesktop *desktop); void slotDesktopAdded(VirtualDesktop *desktop);
void slotDesktopRemoved(VirtualDesktop *desktop); void slotDesktopRemoved(VirtualDesktop *desktop);
void slotOutputEnabled(AbstractOutput *output); void slotOutputEnabled(AbstractOutput *output);
@ -527,6 +529,8 @@ Q_SIGNALS:
void desktopPresenceChanged(KWin::AbstractClient *, int); void desktopPresenceChanged(KWin::AbstractClient *, int);
void currentActivityChanged(); void currentActivityChanged();
void currentDesktopChanged(int, KWin::AbstractClient *); void currentDesktopChanged(int, KWin::AbstractClient *);
void currentDesktopChanging(uint currentDesktop, QPointF delta, KWin::AbstractClient*);//for realtime animations
void currentDesktopChangingCancelled();
void clientAdded(KWin::AbstractClient *); void clientAdded(KWin::AbstractClient *);
void clientRemoved(KWin::AbstractClient *); void clientRemoved(KWin::AbstractClient *);
void clientActivated(KWin::AbstractClient *); void clientActivated(KWin::AbstractClient *);