effects/desktopgrid: port to realtime gestures

This ports the Desktop Grid effect to realtime gestures,
both to have the end-user result, and to demonstrate how
effects can have realtime gestures.
This commit is contained in:
Janet Blackquill 2021-05-31 15:12:59 -04:00 committed by Jan Blackquill
parent 6231699ac1
commit 0042d2d8c1
2 changed files with 136 additions and 78 deletions

View file

@ -5,6 +5,7 @@
SPDX-FileCopyrightText: 2007 Lubos Lunak <l.lunak@kde.org>
SPDX-FileCopyrightText: 2008 Lucas Murray <lmurray@undefinedfire.com>
SPDX-FileCopyrightText: 2009 Martin Gräßlin <mgraesslin@kde.org>
SPDX-FileCopyrightText: 2021 Carson Black <uhhadd@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
@ -58,19 +59,60 @@ DesktopGridEffect::DesktopGridEffect()
, scaledSize()
, scaledOffset()
, m_proxy(nullptr)
, m_activateAction(new QAction(this))
, m_gestureAction(new QAction(this))
, m_shortcutAction(new QAction(this))
{
initConfig<DesktopGridConfig>();
// Load shortcuts
QAction* a = m_activateAction;
a->setObjectName(QStringLiteral("ShowDesktopGrid"));
a->setText(i18n("Show Desktop Grid"));
KGlobalAccel::self()->setDefaultShortcut(a, QList<QKeySequence>() << Qt::CTRL + Qt::Key_F8);
KGlobalAccel::self()->setShortcut(a, QList<QKeySequence>() << Qt::CTRL + Qt::Key_F8);
shortcut = KGlobalAccel::self()->shortcut(a);
effects->registerGlobalShortcut(Qt::CTRL + Qt::Key_F8, a);
effects->registerTouchpadSwipeShortcut(SwipeDirection::Up, a);
connect(a, &QAction::triggered, this, &DesktopGridEffect::toggle);
// First we set up the gestures...
QAction* a = m_gestureAction;
connect(a, &QAction::triggered, this, [this]() {
if ((qreal(timeline.currentTime()) / qreal(timeline.duration())) > 0.5) {
activated = true;
timeline.setDirection(QTimeLine::Forward);
timelineRunning = true;
} else {
activated = false;
timeline.setDirection(QTimeLine::Backward);
timelineRunning = true;
}
});
effects->registerRealtimeTouchpadSwipeShortcut(SwipeDirection::Up, a, [this](qreal cb) {
if (activated) return;
if (timeline.currentValue() == 0) {
activated = true;
setup();
activated = false;
}
timeline.setDirection(QTimeLine::Forward);
timeline.setCurrentTime(timeline.duration() * cb);
effects->addRepaintFull();
});
connect(&timeline, &QTimeLine::frameChanged, this, []() {
effects->addRepaintFull();
});
connect(&timeline, &QTimeLine::finished, this, [this]() {
timelineRunning = false;
if (timeline.currentTime() == 0) {
finish();
}
});
// Now we set up the shortcut
QAction* s = m_shortcutAction;
s->setObjectName(QStringLiteral("ShowDesktopGrid"));
s->setText(i18n("Show Desktop Grid"));
KGlobalAccel::self()->setDefaultShortcut(s, QList<QKeySequence>() << Qt::CTRL + Qt::Key_F8);
KGlobalAccel::self()->setShortcut(s, QList<QKeySequence>() << Qt::CTRL + Qt::Key_F8);
shortcut = KGlobalAccel::self()->shortcut(s);
effects->registerGlobalShortcut(Qt::CTRL + Qt::Key_F8, s);
connect(s, &QAction::triggered, this, &DesktopGridEffect::toggle);
connect(KGlobalAccel::self(), &KGlobalAccel::globalShortcutChanged, this, &DesktopGridEffect::globalShortcutChanged);
connect(effects, &EffectsHandler::windowAdded, this, &DesktopGridEffect::slotWindowAdded);
connect(effects, &EffectsHandler::windowClosed, this, &DesktopGridEffect::slotWindowClosed);
@ -80,7 +122,7 @@ DesktopGridEffect::DesktopGridEffect()
connect(effects, &EffectsHandler::numberScreensChanged, this, &DesktopGridEffect::setup);
connect(effects, &EffectsHandler::screenAboutToLock, this, [this]() {
setActive(false);
deactivate();
windowMoveElevateTimer->stop();
if (keyboardGrab) {
effects->ungrabKeyboard();
@ -130,14 +172,14 @@ void DesktopGridEffect::reconfigure(ReconfigureFlags)
// deactivate and activate all touch border
const QVector<ElectricBorder> relevantBorders{ElectricLeft, ElectricTop, ElectricRight, ElectricBottom};
for (auto e : relevantBorders) {
effects->unregisterTouchBorder(e, m_activateAction);
effects->unregisterTouchBorder(e, m_shortcutAction);
}
const auto touchBorders = DesktopGridConfig::touchBorderActivate();
for (int i : touchBorders) {
if (!relevantBorders.contains(ElectricBorder(i))) {
continue;
}
effects->registerTouchBorder(ElectricBorder(i), m_activateAction);
effects->registerTouchBorder(ElectricBorder(i), m_shortcutAction);
}
}
@ -154,29 +196,37 @@ void DesktopGridEffect::prePaintScreen(ScreenPrePaintData& data, std::chrono::mi
time = 1;
}
lastPresentTime = presentTime;
if (timelineRunning) {
timeline.setCurrentTime(timeline.currentTime() + (timeline.direction() == QTimeLine::Forward ? time : -time));
if ((timeline.currentTime() <= 0 && timeline.direction() == QTimeLine::Backward)) {
timelineRunning = false;
// defer until the event loop to finish
QTimer::singleShot(0, [this]() {
finish();
});
}
}
for (int i = 0; i < effects->numberOfDesktops(); i++) {
auto item = hoverTimeline[i];
if (i == highlightedDesktop-1) { // if this is the highlighted desktop, we want to progress the animation from "not highlighted" to "highlight"
item->setCurrentTime(item->currentTime() + time);
} else { // otherwise we progress from "highlighted" to "not highlighted"
item->setCurrentTime(item->currentTime() - time);
}
}
if (timeline.currentValue() != 0 || activated || (isUsingPresentWindows() && isMotionManagerMovingWindows())) {
if (activated)
timeline.setCurrentTime(timeline.currentTime() + time);
else
timeline.setCurrentTime(timeline.currentTime() - time);
for (int i = 0; i < effects->numberOfDesktops(); i++) {
if (i == highlightedDesktop - 1)
hoverTimeline[i]->setCurrentTime(hoverTimeline[i]->currentTime() + time);
else
hoverTimeline[i]->setCurrentTime(hoverTimeline[i]->currentTime() - time);
}
if (isUsingPresentWindows()) {
QList<WindowMotionManager>::iterator i;
for (i = m_managers.begin(); i != m_managers.end(); ++i)
(*i).calculate(time);
(*i).calculate(timeline.currentTime());
}
// PAINT_SCREEN_BACKGROUND_FIRST is needed because screen will be actually painted more than once,
// so with normal screen painting second screen paint would erase parts of the first paint
if (timeline.currentValue() != 0 || (isUsingPresentWindows() && isMotionManagerMovingWindows()))
data.mask |= PAINT_SCREEN_TRANSFORMED | PAINT_SCREEN_BACKGROUND_FIRST;
if (!activated && timeline.currentValue() == 0 && !(isUsingPresentWindows() && isMotionManagerMovingWindows()))
finish();
}
const EffectWindowList windows = effects->stackingOrder();
@ -617,7 +667,7 @@ void DesktopGridEffect::windowInputMouseEvent(QEvent* e)
if (desk > effects->numberOfDesktops())
return; // don't quit when missing desktop
setCurrentDesktop(desk);
setActive(false);
deactivate();
}
if (windowMove) {
if (wasWindowMove && isUsingPresentWindows()) {
@ -644,6 +694,28 @@ void DesktopGridEffect::windowInputMouseEvent(QEvent* e)
}
}
void DesktopGridEffect::activate()
{
activated = true;
setup();
timeline.setDirection(QTimeLine::Forward);
timelineRunning = true;
// timeline.resume();
}
void DesktopGridEffect::deactivate()
{
activated = false;
timeline.setDirection(QTimeLine::Backward);
timelineRunning = true;
// timeline.resume();
}
void DesktopGridEffect::toggle()
{
if (activated) deactivate(); else activate();
}
void DesktopGridEffect::grabbedKeyboardEvent(QKeyEvent* e)
{
if (timeline.currentValue() != 1) // Block user input during animations
@ -654,7 +726,7 @@ void DesktopGridEffect::grabbedKeyboardEvent(QKeyEvent* e)
// check for global shortcuts
// HACK: keyboard grab disables the global shortcuts so we have to check for global shortcut (bug 156155)
if (shortcut.contains(e->key() + e->modifiers())) {
toggle();
deactivate();
return;
}
@ -668,7 +740,7 @@ void DesktopGridEffect::grabbedKeyboardEvent(QKeyEvent* e)
if (desktop <= effects->numberOfDesktops()) {
setHighlightedDesktop(desktop);
setCurrentDesktop(desktop);
setActive(false);
deactivate();
}
return;
}
@ -687,13 +759,13 @@ void DesktopGridEffect::grabbedKeyboardEvent(QKeyEvent* e)
setHighlightedDesktop(desktopDown(highlightedDesktop, !e->isAutoRepeat()));
break;
case Qt::Key_Escape:
setActive(false);
deactivate();
return;
case Qt::Key_Enter:
case Qt::Key_Return:
case Qt::Key_Space:
setCurrentDesktop(highlightedDesktop);
setActive(false);
deactivate();
return;
case Qt::Key_Plus:
slotAddDesktop();
@ -713,7 +785,7 @@ bool DesktopGridEffect::borderActivated(ElectricBorder border)
return false;
if (effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this)
return true;
toggle();
// toggle();
return true;
}
@ -989,48 +1061,6 @@ int DesktopGridEffect::desktopDown(int desktop, bool wrap) const
//-----------------------------------------------------------------------------
// Activation
void DesktopGridEffect::toggle()
{
setActive(!activated);
}
void DesktopGridEffect::setActive(bool active)
{
if (effects->activeFullScreenEffect() && effects->activeFullScreenEffect() != this)
return; // Only one fullscreen effect at a time thanks
if (active && isMotionManagerMovingWindows())
return; // Still moving windows from last usage - don't activate
if (activated == active)
return; // Already in that state
activated = active;
if (activated) {
effects->setShowingDesktop(false);
if (timeline.currentValue() == 0)
setup();
} else {
if (isUsingPresentWindows()) {
QList<WindowMotionManager>::iterator it;
for (it = m_managers.begin(); it != m_managers.end(); ++it) {
Q_FOREACH (EffectWindow * w, (*it).managedWindows()) {
(*it).moveWindow(w, w->frameGeometry());
}
}
}
QTimer::singleShot(zoomDuration + 1, this,
[this] {
if (activated)
return;
for (EffectQuickScene *view : qAsConst(m_desktopButtons)) {
view->hide();
}
}
);
setHighlightedDesktop(effects->currentDesktop()); // Ensure selected desktop is highlighted
}
effects->addRepaintFull();
}
void DesktopGridEffect::setup()
{
if (!isActive())
@ -1193,6 +1223,25 @@ void DesktopGridEffect::finish()
desktopNames.clear();
}
if (isUsingPresentWindows()) {
QList<WindowMotionManager>::iterator it;
for (it = m_managers.begin(); it != m_managers.end(); ++it) {
Q_FOREACH (EffectWindow * w, (*it).managedWindows()) {
(*it).moveWindow(w, w->frameGeometry());
}
}
}
QTimer::singleShot(zoomDuration + 1, this,
[this] {
if (activated)
return;
for (EffectQuickScene *view : qAsConst(m_desktopButtons)) {
view->hide();
}
}
);
setHighlightedDesktop(effects->currentDesktop()); // Ensure selected desktop is highlighted
windowMoveElevateTimer->stop();
if (keyboardGrab)
@ -1208,6 +1257,8 @@ void DesktopGridEffect::finish()
}
m_proxy = nullptr;
}
effects->addRepaintFull();
}
void DesktopGridEffect::globalShortcutChanged(QAction *action, const QKeySequence& seq)

View file

@ -83,7 +83,6 @@ public:
return clickBehavior == SwitchDesktopAndActivateWindow;
}
private Q_SLOTS:
void toggle();
// slots for global shortcut changed
// needed to toggle the effect
void globalShortcutChanged(QAction *action, const QKeySequence& seq);
@ -106,7 +105,9 @@ private:
int desktopToLeft(int desktop, bool wrap = true) const;
int desktopUp(int desktop, bool wrap = true) const;
int desktopDown(int desktop, bool wrap = true) const;
void setActive(bool active);
void deactivate();
void activate();
void toggle();
void setup();
void setupGrid();
void finish();
@ -127,7 +128,12 @@ private:
int clickBehavior;
bool activated;
QTimeLine timeline;
// used to indicate whether or not the prepaint thingy should drive the
// animation.
bool timelineRunning = false;
int paintingDesktop;
int highlightedDesktop;
int sourceDesktop;
@ -164,7 +170,8 @@ private:
QVector<EffectQuickScene*> m_desktopButtons;
QAction *m_activateAction;
QAction *m_gestureAction;
QAction *m_shortcutAction;
};