From 16192c5f715f6858c728a401a00b965678cf4804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luis=20B=C3=BCchi?= Date: Sun, 27 Oct 2024 16:37:14 +0100 Subject: [PATCH] add double tap to switch between 2 most recent apps in swicher also simplified openApp signature and fixed a typo in code FEATURE: 486555 --- .../mobiletaskswitchereffect.cpp | 18 +++++++++++++++- .../mobiletaskswitchereffect.h | 14 ++++++++++++- kwin/mobiletaskswitcher/qml/Task.qml | 3 ++- kwin/mobiletaskswitcher/qml/TaskSwitcher.qml | 21 ++++++++++++------- .../qml/TaskSwitcherHelpers.qml | 6 ++++-- 5 files changed, 50 insertions(+), 12 deletions(-) diff --git a/kwin/mobiletaskswitcher/mobiletaskswitchereffect.cpp b/kwin/mobiletaskswitcher/mobiletaskswitchereffect.cpp index a6b05ece..23ca3a6a 100644 --- a/kwin/mobiletaskswitcher/mobiletaskswitchereffect.cpp +++ b/kwin/mobiletaskswitcher/mobiletaskswitchereffect.cpp @@ -1,6 +1,6 @@ // SPDX-FileCopyrightText: 2021 Vlad Zahorodnii // SPDX-FileCopyrightText: 2023 Devin Lin -// SPDX-FileCopyrightText: 2024 Luis Büchi +// SPDX-FileCopyrightText: 2024 Luis Büchi // SPDX-License-Identifier: GPL-2.0-or-later #include "mobiletaskswitchereffect.h" @@ -20,6 +20,7 @@ namespace KWin MobileTaskSwitcherState::MobileTaskSwitcherState(EffectTouchBorderState *effectState) : m_effectState{effectState} + , m_doubleClickTimer{new QElapsedTimer{}} { connect(m_effectState, &EffectTouchBorderState::inProgressChanged, this, &MobileTaskSwitcherState::gestureInProgressChanged); } @@ -150,6 +151,11 @@ void MobileTaskSwitcherState::setInitialTaskIndex(int newTaskIndex) } } +void MobileTaskSwitcherState::restartDoubleClickTimer() +{ + m_doubleClickTimer->restart(); +} + void MobileTaskSwitcherState::calculateFilteredVelocity(qreal primaryDelta, qreal orthogonalDelta) { static qreal prevPrimaryDelta = 0; @@ -190,6 +196,15 @@ void MobileTaskSwitcherState::processTouchPositionChanged(qreal primaryDelta, qr Q_EMIT touchPositionChanged(); } +qint64 MobileTaskSwitcherState::getElapsedTimeSinceStart() +{ + if (m_doubleClickTimer->isValid()) + { + return m_doubleClickTimer->elapsed(); + } + return -1; +} + MobileTaskSwitcherEffect::MobileTaskSwitcherEffect() : m_effectState{new EffectTouchBorderState(this)} , m_taskSwitcherState{new MobileTaskSwitcherState(m_effectState)} @@ -269,6 +284,7 @@ void MobileTaskSwitcherEffect::grabbedKeyboardEvent(QKeyEvent *keyEvent) void MobileTaskSwitcherEffect::toggle() { if (!isRunning()) { + m_taskSwitcherState->restartDoubleClickTimer(); activate(); } else { deactivate(false); diff --git a/kwin/mobiletaskswitcher/mobiletaskswitchereffect.h b/kwin/mobiletaskswitcher/mobiletaskswitchereffect.h index ef87bc77..ce93aa2e 100644 --- a/kwin/mobiletaskswitcher/mobiletaskswitchereffect.h +++ b/kwin/mobiletaskswitcher/mobiletaskswitchereffect.h @@ -1,6 +1,6 @@ // SPDX-FileCopyrightText: 2021 Vlad Zahorodnii // SPDX-FileCopyrightText: 2023 Devin Lin -// SPDX-FileCopyrightText: 2024 Luis Büchi +// SPDX-FileCopyrightText: 2024 Luis Büchi // SPDX-License-Identifier: GPL-2.0-or-later #pragma once @@ -48,6 +48,9 @@ class MobileTaskSwitcherState : public QObject Q_PROPERTY(bool gestureInProgress READ gestureInProgress NOTIFY gestureInProgressChanged) Q_PROPERTY(Status status READ status WRITE setStatus NOTIFY statusChanged) + Q_PROPERTY(qint64 elapsedTimeSinceStart READ getElapsedTimeSinceStart) + Q_PROPERTY(qint64 doubleClickInterval READ getDoubleClickInterval) // is there a better way than to forward this? + public: enum class Status { // TODO! I could (should?) re-add the activating and deactivating states again to match EffectTogglableState. could help with/tie into @@ -97,6 +100,8 @@ public: return m_initialTaskIndex; } + void restartDoubleClickTimer(); + public Q_SLOTS: void processTouchPositionChanged(qreal primaryPosition, qreal orthogonalPosition); @@ -130,6 +135,7 @@ private: void clearVelocityFilter(); void calculateFilteredVelocity(qreal primaryPosition, qreal orthogonalPosition); + qint64 getElapsedTimeSinceStart(); // velocities in (logical) pixels/msec QElapsedTimer m_frameTimer; @@ -149,6 +155,12 @@ private: qreal m_yPosition = 0; bool m_wasInActiveTask; + + QElapsedTimer *m_doubleClickTimer; + qint64 getDoubleClickInterval() const + { + return qApp->doubleClickInterval(); + } }; class MobileTaskSwitcherEffect : public QuickSceneEffect diff --git a/kwin/mobiletaskswitcher/qml/Task.qml b/kwin/mobiletaskswitcher/qml/Task.qml index b119d0f6..5f32d01f 100644 --- a/kwin/mobiletaskswitcher/qml/Task.qml +++ b/kwin/mobiletaskswitcher/qml/Task.qml @@ -1,5 +1,6 @@ // SPDX-FileCopyrightText: 2015 Marco Martin // SPDX-FileCopyrightText: 2021-2023 Devin Lin +// SPDX-FileCopyrightText: 2024 Luis Büchi // SPDX-License-Identifier: GPL-2.0-or-later import QtQuick @@ -48,7 +49,7 @@ Item { if (!ShellSettings.Settings.convergenceModeEnabled) { delegate.window.setMaximize(true, true); } - taskSwitcherHelpers.openApp(model.index, delegate.window); + taskSwitcherHelpers.openApp(model.index); } function minimizeApp() { diff --git a/kwin/mobiletaskswitcher/qml/TaskSwitcher.qml b/kwin/mobiletaskswitcher/qml/TaskSwitcher.qml index 1e90a83b..2138aab4 100644 --- a/kwin/mobiletaskswitcher/qml/TaskSwitcher.qml +++ b/kwin/mobiletaskswitcher/qml/TaskSwitcher.qml @@ -1,5 +1,6 @@ // SPDX-FileCopyrightText: 2015 Marco Martin // SPDX-FileCopyrightText: 2021-2024 Devin Lin +// SPDX-FileCopyrightText: 2024 Luis Büchi // SPDX-License-Identifier: GPL-2.0-or-later import QtQuick @@ -37,6 +38,7 @@ FocusScope { property var taskSwitcherHelpers: TaskSwitcherHelpers { taskSwitcher: root stateClass: TaskSwitcherData.TaskSwitcherState + taskList: taskList } MobileShell.HapticsEffect { @@ -308,8 +310,7 @@ FocusScope { // if accidentally invoked, but can also be used to switch to an adjacent app and then open it function returnToApp() { let newIndex = taskSwitcherHelpers.getNearestTaskIndex(); - let appAtNewIndex = taskList.getTaskAt(newIndex).window; - taskSwitcherHelpers.openApp(newIndex, appAtNewIndex); + taskSwitcherHelpers.openApp(newIndex); } // diagonal quick switch gesture logic @@ -338,15 +339,14 @@ FocusScope { } else { // flick to the left on the home screen, dismiss the gesture taskSwitcherHelpers.close(); - retrun; + return; } } if (shouldSwitch) { if (!taskSwitcherHelpers.taskDrawerOpened && unmodifiedYposition < taskSwitcherHelpers.openedYPosition) { // if in a app, switch it to the new task when it is under the openedYPosition taskList.setTaskOffsetValue(0, unmodifiedYposition < taskSwitcherHelpers.openedYPosition && taskSwitcherHelpers.notHomeScreenState); - let appAtNewIndex = taskList.getTaskAt(newIndex).window; - taskSwitcherHelpers.openApp(newIndex, appAtNewIndex, Kirigami.Units.longDuration * 4, Easing.OutExpo); + taskSwitcherHelpers.openApp(newIndex, Kirigami.Units.longDuration * 4, Easing.OutExpo); } else { // if already in the task switcher or above the openedYPosition, only change the focus to the new task taskSwitcherHelpers.animateGoToTaskIndex(newIndex); @@ -380,7 +380,7 @@ FocusScope { taskSwitcherHelpers.open(); taskSwitcherHelpers.isInTaskScrubMode = false; } else { - taskSwitcherHelpers.openApp(state.currentTaskIndex, taskList.getTaskAt(state.currentTaskIndex).window); + taskSwitcherHelpers.openApp(state.currentTaskIndex); } } else if (taskSwitcherHelpers.gestureState == TaskSwitcherHelpers.GestureStates.Undecided) { if (taskSwitcherHelpers.taskDrawerOpened) { @@ -499,8 +499,15 @@ FocusScope { if (taskList.count === 0) { root.hide(); } else { + if (taskList.count > 1 && + state.elapsedTimeSinceStart != -1 && + state.elapsedTimeSinceStart < state.doubleClickInterval) { + taskSwitcherHelpers.openApp(1); + return; + } + const currentIndex = state.currentTaskIndex; - taskSwitcherHelpers.openApp(state.currentTaskIndex, taskList.getTaskAt(currentIndex).window); + taskSwitcherHelpers.openApp(state.currentTaskIndex); } } } diff --git a/kwin/mobiletaskswitcher/qml/TaskSwitcherHelpers.qml b/kwin/mobiletaskswitcher/qml/TaskSwitcherHelpers.qml index 34ab74d8..20aa4858 100644 --- a/kwin/mobiletaskswitcher/qml/TaskSwitcherHelpers.qml +++ b/kwin/mobiletaskswitcher/qml/TaskSwitcherHelpers.qml @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: 2021 Devin Lin +// SPDX-FileCopyrightText: 2024 Luis Büchi // SPDX-License-Identifier: GPL-2.0-or-later import QtQuick 2.15 @@ -19,6 +20,7 @@ QtObject { required property var taskSwitcher property var state: taskSwitcher.state required property var stateClass + required property var taskList // task switcher peek and pop setting for when it is toggled from the home screen readonly property real peekOffsetValue: 1.85 @@ -217,14 +219,14 @@ QtObject { closeFactorAnim.restart(); } - function openApp(index, window, duration = Kirigami.Units.shortDuration, horizontalEasing = Easing.OutBack) { + function openApp(index, duration = Kirigami.Units.shortDuration, horizontalEasing = Easing.OutBack) { // cancel any opening animations ongoing openAnim.stop(); cancelAnimations(); animateGoToTaskIndex(index, duration); openAppAnim.restart(); - KWinComponents.Workspace.activeWindow = window + KWinComponents.Workspace.activeWindow = taskList.getTaskAt(index).window; } // get the xPosition where the task will be centered on the screen