/* * SPDX-FileCopyrightText: 2015 Marco Martin * SPDX-FileCopyrightText: 2021-2022 Devin Lin * * SPDX-License-Identifier: GPL-2.0-or-later */ import QtQuick 2.15 import QtQuick.Controls 2.15 as QQC2 import QtQuick.Layouts 1.1 import QtQuick.Window 2.15 import org.kde.taskmanager 0.1 as TaskManager import org.kde.plasma.core 2.1 as PlasmaCore import org.kde.plasma.components 3.0 as PlasmaComponents import org.kde.plasma.private.nanoshell 2.0 as NanoShell import org.kde.plasma.private.mobileshell 1.0 as MobileShell import "../components" as Components Item { id: root visible: false opacity: 0 // state object property var taskSwitcherState: TaskSwitcherState { taskSwitcher: root } // task list model property TaskManager.TasksModel tasksModel readonly property int tasksCount: tasksModel.count property var displaysModel: MobileShell.DisplaysModel {} // if a window has popped up in front, close the task switcher property bool windowActive: Window.active onWindowActiveChanged: { if (visible && !windowActive) { hide(); } } // update API property onVisibleChanged: MobileShell.HomeScreenControls.taskSwitcherVisible = visible; // keep track of task list events property int oldTasksCount: tasksCount onTasksCountChanged: { if (tasksCount == 0) { hide(); } else if (tasksCount < oldTasksCount && taskSwitcherState.currentTaskIndex >= tasksCount - 1) { // if the user is on the last task, and it is closed, scroll left taskSwitcherState.animateGoToTaskIndex(tasksCount - 1, PlasmaCore.Units.longDuration); } oldTasksCount = tasksCount; } //BEGIN functions function show(animation) { // reset values taskSwitcherState.cancelAnimations(); taskSwitcherState.yPosition = 0; taskSwitcherState.xPosition = 0; taskSwitcherState.wasInActiveTask = tasksModel.activeTask.row >= 0; taskSwitcherState.currentlyBeingOpened = true; // skip to first active task if (taskSwitcherState.wasInActiveTask) { taskSwitcherState.goToTaskIndex(tasksModel.activeTask.row); } // show task switcher, hide all running apps visible = true; opacity = 1; minimizeAll(); // fully open the panel (if this is a button press, not gesture) if (animation) { taskSwitcherState.open(); } } function instantHide() { opacity = 0; visible = false; } function hide() { closeAnim.restart(); } // scroll to delegate index, and activate it function activateWindow(id) { taskSwitcherState.openApp(id); } function setSingleActiveWindow(id) { if (id < 0) { return; } var newActiveIdx = tasksModel.index(id, 0) var newActiveGeo = tasksModel.data(newActiveIdx, TaskManager.AbstractTasksModel.ScreenGeometry) for (var i = 0 ; i < tasksModel.count; i++) { var idx = tasksModel.index(i, 0) if (i == id) { tasksModel.requestActivate(idx); // ensure the window is in maximized state if (!tasksModel.data(idx, TaskManager.AbstractTasksModel.IsMaximized)) { tasksModel.requestToggleMaximized(idx); } } else if (!tasksModel.data(idx, TaskManager.AbstractTasksModel.IsMinimized)) { var geo = tasksModel.data(idx, TaskManager.AbstractTasksModel.ScreenGeometry) // only minimize the other windows in the same screen if (geo === newActiveGeo) { tasksModel.requestToggleMinimized(idx); } } } instantHide(); } function minimizeAll() { for (var i = 0 ; i < tasksModel.count; i++) { var idx = tasksModel.makeModelIndex(i); if (!tasksModel.data(idx, TaskManager.AbstractTasksModel.IsMinimized)) { tasksModel.requestToggleMinimized(idx); } } } //END functions NumberAnimation on opacity { id: closeAnim to: 0 duration: PlasmaCore.Units.shortDuration easing.type: Easing.InOutQuad onFinished: { root.visible = false; } } // background colour Rectangle { id: backgroundRect anchors.fill: parent color: { // animate background colour only if opening from the homescreen if (taskSwitcherState.wasInActiveTask) { return Qt.rgba(0, 0, 0, 0.6); } else { return Qt.rgba(0, 0, 0, 0.6 * Math.min(1, taskSwitcherState.yPosition / taskSwitcherState.openedYPosition)); } } } Item { id: container // provide shell margins anchors.fill: parent anchors.leftMargin: MobileShell.Shell.leftMargin anchors.rightMargin: MobileShell.Shell.rightMargin anchors.bottomMargin: MobileShell.Shell.bottomMargin anchors.topMargin: MobileShell.Shell.topMargin FlickContainer { id: flickable anchors.fill: parent taskSwitcherState: root.taskSwitcherState // the item is effectively anchored to the flickable bounds TaskList { taskSwitcher: root x: flickable.contentX width: flickable.width height: flickable.height } } } }