shift-shell/kwin/mobiletaskswitcher/qml/TaskList.qml
Devin Lin 7cb6ebaae1 taskswitcher: Remove all interaction restrictions while the task switcher is opening
This allows users to properly interact (open apps, dismiss) while the task switcher is in its opening animation.

This fixes tapping on an app while the task switcher is opening dismissing the task switcher entirely (due to race condition)
2024-03-04 18:23:17 +00:00

140 lines
4.4 KiB
QML

// SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
import QtQuick
import QtQuick.Layouts
import org.kde.kirigami 2.20 as Kirigami
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.kwin 3.0 as KWinComponents
MouseArea {
id: root
readonly property int count: repeater.count
required property real shellTopMargin
required property real shellBottomMargin
required property var taskSwitcher
readonly property var taskSwitcherState: taskSwitcher.taskSwitcherState
property int taskInteractingCount: 0
// account for system header and footer offset (center the preview image)
readonly property real taskY: {
let headerHeight = shellTopMargin;
let footerHeight = shellBottomMargin;
let diff = headerHeight - footerHeight;
let baseY = (taskSwitcher.height / 2) - (taskSwitcherState.taskHeight / 2) - (taskSwitcherState.taskHeaderHeight / 2)
return baseY + diff / 2 - shellTopMargin;
}
function getTaskAt(index) {
return repeater.itemAt(index);
}
function closeAll() {
for (var i = 0; i < repeater.count; i++) {
repeater.itemAt(i).closeApp();
}
}
function minimizeAll() {
for (var i = 0; i < repeater.count; i++) {
let item = repeater.itemAt(i);
// update property
if (!item.window.minimized) {
taskSwitcherState.wasInActiveTask = true;
}
// minimize window immediately if it shows up
item.minimizeApp();
}
}
function jumpToFirstVisibleWindow() {
for (var i = 0; i < repeater.count; i++) {
let item = repeater.itemAt(i);
if (!item.window.minimized) {
taskSwitcherState.goToTaskIndex(i);
break;
}
}
}
transform: Scale {
origin.x: root.width / 2
origin.y: root.height / 2
xScale: taskSwitcherState.currentScale
yScale: taskSwitcherState.currentScale
}
onClicked: {
// if tapped on the background, then hide
taskSwitcher.hide();
}
onPressedChanged: {
if (!taskSwitcherState.currentlyBeingOpened && pressed) {
// ensure animations aren't running when finger is pressed
taskSwitcherState.cancelAnimations();
}
}
Repeater {
id: repeater
model: taskSwitcher.tasksModel
// left margin from root edge such that the task is centered
readonly property real leftMargin: (root.width / 2) - (taskSwitcherState.taskWidth / 2)
delegate: Task {
id: task
readonly property int currentIndex: model.index
// this is the x-position with respect to the list
property real listX: taskSwitcherState.xPositionFromTaskIndex(currentIndex);
Behavior on listX {
NumberAnimation {
duration: Kirigami.Units.longDuration
easing.type: Easing.InOutQuad
}
}
// this is the actual displayed x-position on screen
x: listX + repeater.leftMargin - taskSwitcherState.xPosition
y: root.taskY
// ensure current task is above others
z: taskSwitcherState.currentTaskIndex === currentIndex ? 1 : 0
// only show header once task switcher is opened
showHeader: !taskSwitcherState.currentlyBeingOpened
// darken effect as task gets away from the centre of the screen
darken: {
const distFromCentreProgress = Math.abs(x - repeater.leftMargin) / taskSwitcherState.taskWidth;
const upperBoundAdjust = Math.min(0.5, distFromCentreProgress) - 0.2;
return Math.max(0, upperBoundAdjust);
}
// update count of tasks being interacted with, so we know whether we are in a swipe up action
onInteractingActiveChanged: {
let offset = interactingActive ? 1 : -1;
taskInteractingCount = Math.max(0, taskInteractingCount + offset);
}
width: taskSwitcherState.taskWidth
height: taskSwitcherState.taskHeight
previewWidth: taskSwitcherState.previewWidth
previewHeight: taskSwitcherState.previewHeight
taskSwitcher: root.taskSwitcher
}
}
}