add double tap to switch between 2 most recent apps in swicher

also simplified openApp signature and fixed a typo in code
FEATURE: 486555
This commit is contained in:
Luis Büchi 2024-10-27 16:37:14 +01:00
parent d7ae1917af
commit 16192c5f71
5 changed files with 50 additions and 12 deletions

View file

@ -1,6 +1,6 @@
// SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
// SPDX-FileCopyrightText: 2023 Devin Lin <devin@kde.org>
// SPDX-FileCopyrightText: 2024 Luis Büchi <luis.buechi@server23.cc>
// SPDX-FileCopyrightText: 2024 Luis Büchi <luis.buechi@kdemail.net>
// 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);

View file

@ -1,6 +1,6 @@
// SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
// SPDX-FileCopyrightText: 2023 Devin Lin <devin@kde.org>
// SPDX-FileCopyrightText: 2024 Luis Büchi <luis.buechi@server23.cc>
// SPDX-FileCopyrightText: 2024 Luis Büchi <luis.buechi@kdemail.net>
// 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

View file

@ -1,5 +1,6 @@
// SPDX-FileCopyrightText: 2015 Marco Martin <notmart@gmail.com>
// SPDX-FileCopyrightText: 2021-2023 Devin Lin <devin@kde.org>
// SPDX-FileCopyrightText: 2024 Luis Büchi <luis.buechi@kdemail.net>
// 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() {

View file

@ -1,5 +1,6 @@
// SPDX-FileCopyrightText: 2015 Marco Martin <notmart@gmail.com>
// SPDX-FileCopyrightText: 2021-2024 Devin Lin <devin@kde.org>
// SPDX-FileCopyrightText: 2024 Luis Büchi <luis.buechi@kdemail.net>
// 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);
}
}
}

View file

@ -1,4 +1,5 @@
// SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org>
// SPDX-FileCopyrightText: 2024 Luis Büchi <luis.buechi@kdemail.net>
// 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