[plasma/plasma-mobile] kwin/mobiletaskswitcher: kwin/mobiletaskswitcher: Use effect caching
Devin Lin <[email protected]>
| Newsgroups | gmane.comp.kde.cvs |
|---|---|
| Message-ID | <[email protected]> |
Git commit 73c5b4fd2815dc5d845c09cf578f60a9af3e708b by Devin Lin.
Committed on 02/08/2026 at 00:22.
Pushed by devinlin into branch 'master'.
kwin/mobiletaskswitcher: Use effect caching
Keep the taskswitcher effect in the background between opens, so that it
is instantly available during a gesture/open.
M +17 -0 kwin/mobiletaskswitcher/package/contents/ui/FlickContainer.qml
M +12 -5 kwin/mobiletaskswitcher/package/contents/ui/TaskSwitcher.qml
M +30 -9 kwin/mobiletaskswitcher/plugin/mobiletaskswitchereffect.cpp
M +9 -6 kwin/mobiletaskswitcher/plugin/mobiletaskswitchereffect.h
M +6 -0 kwin/mobiletaskswitcher/plugin/taskfiltermodel.cpp
M +2 -0 kwin/mobiletaskswitcher/plugin/taskfiltermodel.h
https://invent.kde.org/plasma/plasma-mobile/-/commit/73c5b4fd2815dc5d845c09cf578f60a9af3e708b
diff --git a/kwin/mobiletaskswitcher/package/contents/ui/FlickContainer.qml b/kwin/mobiletaskswitcher/package/contents/ui/FlickContainer.qml
index 8f89960ab..8a8099182 100644
--- a/kwin/mobiletaskswitcher/package/contents/ui/FlickContainer.qml
+++ b/kwin/mobiletaskswitcher/package/contents/ui/FlickContainer.qml
@@ -25,10 +25,16 @@ Flickable {
readonly property real startContentX: (taskSwitcherHelpers.taskWidth + taskSwitcherHelpers.taskSpacing) * tasksCount
property bool movingRight: false // TODO needed for flickable not flicking workaround
+ property bool resettingPosition: false
// update position from horizontal flickable movement
property real oldContentX
onContentXChanged: {
+ if (resettingPosition) {
+ oldContentX = contentX;
+ return;
+ }
+
// disable if animations are running to prevent bugs
if (taskSwitcherHelpers.currentlyBeingClosed) {return}
@@ -43,6 +49,8 @@ Flickable {
onMovementStarted: {
if (taskSwitcherHelpers.currentlyBeingClosed) {return}
+ oldContentX = contentX;
+ movingRight = false;
taskSwitcherHelpers.cancelAnimations();
}
onMovementEnded: {
@@ -63,6 +71,8 @@ Flickable {
onDraggingChanged: {
if (taskSwitcherHelpers.currentlyBeingClosed) {return}
if (dragging) {
+ oldContentX = contentX;
+ movingRight = false;
taskSwitcherHelpers.cancelAnimations();
} else {
resetPosition();
@@ -70,7 +80,14 @@ Flickable {
}
function resetPosition(): void {
+ resettingPosition = true;
+ cancelFlick();
oldContentX = startContentX;
contentX = startContentX;
+ movingRight = false;
+ Qt.callLater(() => {
+ oldContentX = contentX;
+ resettingPosition = false;
+ });
}
}
diff --git a/kwin/mobiletaskswitcher/package/contents/ui/TaskSwitcher.qml b/kwin/mobiletaskswitcher/package/contents/ui/TaskSwitcher.qml
index e6146392f..ca3908eff 100644
--- a/kwin/mobiletaskswitcher/package/contents/ui/TaskSwitcher.qml
+++ b/kwin/mobiletaskswitcher/package/contents/ui/TaskSwitcher.qml
@@ -85,11 +85,12 @@ FocusScope {
Keys.onEscapePressed: hide();
- Component.onCompleted: {
- initialSetup();
- }
-
function initialSetup(): void {
+ closeAnim.stop();
+ container.opacity = 1;
+ closeAllButton.closeRequested = false;
+ oldTasksCount = tasksCount;
+
taskSwitcherHelpers.cancelAnimations();
state.updateWasInActiveTask(KWinComponents.Workspace.activeWindow);
@@ -102,12 +103,14 @@ FocusScope {
taskSwitcherHelpers.hasVibrated = false;
taskSwitcherHelpers.closingFactor = 1;
+ taskSwitcherHelpers.closingScalingFactor = 1;
taskSwitcherHelpers.taskSwitchCanLaunch = false;
taskSwitchCanLaunchTimer.restart()
taskList.taskOffsetEasing = Easing.InOutQuart;
taskList.homeTouchPositionX = 0;
+ flickable.resetPosition();
backgroundColorOpacityAn.enabled = false;
backgroundColorOpacity = state.wasInActiveTask ? 1 : 0;
@@ -161,6 +164,11 @@ FocusScope {
Connections {
target: root.state
+ function onActivated(): void {
+ root.tasksModel.refresh();
+ root.initialSetup();
+ }
+
// task scrub mode allows scrubbing through a number of tasks with a mostly horizontal motion
function taskScrubMode(): void {
taskList.setTaskOffsetValue(0, false, Easing.OutQuart);
@@ -827,4 +835,3 @@ FocusScope {
}
}
}
-
diff --git a/kwin/mobiletaskswitcher/plugin/mobiletaskswitchereffect.cpp b/kwin/mobiletaskswitcher/plugin/mobiletaskswitchereffect.cpp
index 5c2f37637..e8baaff0f 100644
--- a/kwin/mobiletaskswitcher/plugin/mobiletaskswitchereffect.cpp
+++ b/kwin/mobiletaskswitcher/plugin/mobiletaskswitchereffect.cpp
@@ -35,8 +35,11 @@ void MobileTaskSwitcherState::init(KWin::QuickSceneEffect *parent)
m_border = new EffectTouchBorder{m_effectState};
m_taskModel = new TaskModel{parent};
m_effect = parent;
+ m_effect->setViewCachingEnabled(true);
// Connect signals
+ connect(m_effect, &QuickSceneEffect::activated, this, &MobileTaskSwitcherState::activated);
+ connect(m_effect, &QuickSceneEffect::deactivated, this, &MobileTaskSwitcherState::deactivated);
connect(this, &MobileTaskSwitcherState::gestureEnabledChanged, this, &MobileTaskSwitcherState::refreshBorders);
connect(m_border, &EffectTouchBorder::touchPositionChanged, this, &MobileTaskSwitcherState::processTouchPositionChanged);
connect(this, &MobileTaskSwitcherState::gestureInProgressChanged, this, [this]() {
@@ -223,13 +226,10 @@ void MobileTaskSwitcherState::restartDoubleClickTimer()
void MobileTaskSwitcherState::calculateFilteredVelocity(qreal primaryDelta, qreal orthogonalDelta)
{
- static qreal prevPrimaryDelta = 0;
- static qreal prevOrthogonalDelta = 0;
-
qint64 frameTime = 0;
if (!m_frameTimer.isValid()) {
- prevPrimaryDelta = 0;
- prevOrthogonalDelta = 0;
+ m_previousPrimaryDelta = primaryDelta;
+ m_previousOrthogonalDelta = orthogonalDelta;
m_frameTimer.start();
return;
}
@@ -239,10 +239,10 @@ void MobileTaskSwitcherState::calculateFilteredVelocity(qreal primaryDelta, qrea
return;
}
- qreal framePrimaryDelta = primaryDelta - prevPrimaryDelta;
- qreal frameOrthogonalDelta = orthogonalDelta - prevOrthogonalDelta;
- prevPrimaryDelta = primaryDelta;
- prevOrthogonalDelta = orthogonalDelta;
+ qreal framePrimaryDelta = primaryDelta - m_previousPrimaryDelta;
+ qreal frameOrthogonalDelta = orthogonalDelta - m_previousOrthogonalDelta;
+ m_previousPrimaryDelta = primaryDelta;
+ m_previousOrthogonalDelta = orthogonalDelta;
// Implements an exponentially weighted moving average (EWMA) filter (= exponential smoothing)
// Smoothing factor is approximated each event to achieve a chosen filter time constant
@@ -253,6 +253,24 @@ void MobileTaskSwitcherState::calculateFilteredVelocity(qreal primaryDelta, qrea
Q_EMIT velocityChanged();
}
+void MobileTaskSwitcherState::clearVelocityFilter()
+{
+ m_frameTimer.invalidate();
+ m_previousPrimaryDelta = 0;
+ m_previousOrthogonalDelta = 0;
+ m_xVelocity = 0;
+ m_yVelocity = 0;
+ m_totalSquaredVelocity = 0;
+ Q_EMIT velocityChanged();
+}
+
+void MobileTaskSwitcherState::resetGestureState()
+{
+ m_touchXPosition = 0;
+ m_touchYPosition = 0;
+ clearVelocityFilter();
+}
+
void MobileTaskSwitcherState::processTouchPositionChanged(qreal primaryDelta, qreal orthogonalDelta)
{
calculateFilteredVelocity(primaryDelta, orthogonalDelta);
@@ -289,6 +307,7 @@ void MobileTaskSwitcherState::activate()
return;
}
+ resetGestureState();
m_effectState->setInProgress(false);
invokeEffect();
}
@@ -339,6 +358,8 @@ void MobileTaskSwitcherState::setDBusState(bool active)
void MobileTaskSwitcherState::invokeEffect()
{
+ m_shutdownTimer->stop();
+ resetGestureState();
setInitialTaskIndex(currentTaskIndex()); // TODO! this is only until the crashing bug is fixed and recency sorting is in
m_effect->setRunning(true);
setDBusState(true);
diff --git a/kwin/mobiletaskswitcher/plugin/mobiletaskswitchereffect.h b/kwin/mobiletaskswitcher/plugin/mobiletaskswitchereffect.h
index d85f1cc63..0aae2a74c 100644
--- a/kwin/mobiletaskswitcher/plugin/mobiletaskswitchereffect.h
+++ b/kwin/mobiletaskswitcher/plugin/mobiletaskswitchereffect.h
@@ -144,6 +144,7 @@ private Q_SLOTS:
private:
void invokeEffect();
+ void resetGestureState();
bool m_gestureEnabled{false};
EffectTouchBorderState *m_effectState{nullptr};
@@ -154,8 +155,8 @@ private:
Status m_status = Status::Inactive;
bool m_gestureInProgress = false;
- int m_currentTaskIndex;
- int m_initialTaskIndex;
+ int m_currentTaskIndex = 0;
+ int m_initialTaskIndex = 0;
void clearVelocityFilter();
void calculateFilteredVelocity(qreal primaryPosition, qreal orthogonalPosition);
@@ -163,22 +164,24 @@ private:
// velocities in (logical) pixels/msec
QElapsedTimer m_frameTimer;
+ qreal m_previousPrimaryDelta = 0;
+ qreal m_previousOrthogonalDelta = 0;
qreal m_flickVelocityThreshold = 0.5 * 0.5; // squared because total velocity is kept as a square
qreal m_filterTimeConstant = 0.03; // time constant of velocity filter
- qreal m_touchXPosition;
- qreal m_touchYPosition;
+ qreal m_touchXPosition = 0;
+ qreal m_touchYPosition = 0;
qreal m_xVelocity = 0;
qreal m_yVelocity = 0;
// Using the square of velocity for the total (2-axis) because we just need it
// for one threshold comparison and we skip having to calculate the square root
- qreal m_totalSquaredVelocity;
+ qreal m_totalSquaredVelocity = 0;
// Positions of the task switcher effect itself
qreal m_xPosition = 0;
qreal m_yPosition = 0;
- bool m_wasInActiveTask;
+ bool m_wasInActiveTask = false;
QElapsedTimer *m_doubleClickTimer;
qint64 getDoubleClickInterval() const
diff --git a/kwin/mobiletaskswitcher/plugin/taskfiltermodel.cpp b/kwin/mobiletaskswitcher/plugin/taskfiltermodel.cpp
index 59e1f48ca..6e04c8685 100644
--- a/kwin/mobiletaskswitcher/plugin/taskfiltermodel.cpp
+++ b/kwin/mobiletaskswitcher/plugin/taskfiltermodel.cpp
@@ -43,6 +43,12 @@ void TaskFilterModel::setWindowModel(TaskModel *taskModel)
sort(0);
}
+void TaskFilterModel::refresh()
+{
+ invalidateFilter();
+ sort(0);
+}
+
QString TaskFilterModel::screenName() const
{
return m_output ? m_output->name() : QString();
diff --git a/kwin/mobiletaskswitcher/plugin/taskfiltermodel.h b/kwin/mobiletaskswitcher/plugin/taskfiltermodel.h
index 87244cc78..ce3688a56 100644
--- a/kwin/mobiletaskswitcher/plugin/taskfiltermodel.h
+++ b/kwin/mobiletaskswitcher/plugin/taskfiltermodel.h
@@ -30,6 +30,8 @@ public:
TaskModel *windowModel() const;
void setWindowModel(KWin::TaskModel *taskModel);
+ Q_INVOKABLE void refresh();
+
QString screenName() const;
void setScreenName(const QString &screenName);