Warning, /plasma/plasma-mobile/kwin/mobiletaskswitcher/qml/Task.qml is written in an unsupported language. File is not indexed.
0001 // SPDX-FileCopyrightText: 2015 Marco Martin <notmart@gmail.com>
0002 // SPDX-FileCopyrightText: 2021-2023 Devin Lin <devin@kde.org>
0003 // SPDX-License-Identifier: GPL-2.0-or-later
0004
0005 import QtQuick
0006 import QtQuick.Layouts
0007 import Qt5Compat.GraphicalEffects
0008
0009 import org.kde.kirigami 2.20 as Kirigami
0010 import org.kde.plasma.core as PlasmaCore
0011 import org.kde.plasma.components 3.0 as PlasmaComponents
0012 import org.kde.kwin 3.0 as KWinComponents
0013
0014 Item {
0015 id: delegate
0016
0017 required property var taskSwitcher
0018
0019 required property QtObject window
0020 required property int index
0021
0022 required property var model
0023
0024 required property real previewHeight
0025 required property real previewWidth
0026
0027 readonly property real dragOffset: -control.y
0028
0029 // whether this task is being interacted with
0030 readonly property bool interactingActive: control.pressed && control.passedDragThreshold
0031
0032 // whether to show the text header
0033 property bool showHeader: true
0034
0035 // the amount to darken the task preview by
0036 property real darken: 0
0037
0038 opacity: 1 - dragOffset / taskSwitcher.height
0039
0040 //BEGIN functions
0041 function closeApp() {
0042 delegate.window.closeWindow();
0043 }
0044
0045 function activateApp() {
0046 taskSwitcherState.wasInActiveTask = false;
0047 taskSwitcher.activateWindow(model.index, delegate.window);
0048 delegate.window.setMaximize(true, true);
0049 }
0050
0051 function minimizeApp() {
0052 delegate.window.minimized = true;
0053 }
0054 //END functions
0055
0056 MouseArea {
0057 id: control
0058 width: parent.width
0059 height: parent.height
0060 enabled: !taskSwitcher.taskSwitcherState.currentlyBeingOpened
0061
0062 // set cursor shape here, since taphandler seems to not be able to do it
0063 cursorShape: Qt.PointingHandCursor
0064
0065 property bool movingUp: false
0066 property real oldY: y
0067 onYChanged: {
0068 movingUp = y < oldY;
0069 oldY = y;
0070 }
0071
0072 onClicked: {
0073 if (!taskSwitcher.taskSwitcherState.currentlyBeingOpened && !passedDragThreshold) {
0074 delegate.activateApp();
0075 }
0076 }
0077
0078 // pixels before we start treating it as drag event
0079 readonly property real dragThreshold: 5
0080
0081 property real startPosition: 0
0082 property bool hasStartPosition: false
0083 property bool passedDragThreshold: false
0084
0085 onPositionChanged: (mouse) => {
0086 // map it to the root area, so that it doesn't jitter (since this item is moving)
0087 const yPos = control.mapToItem(delegate, mouse.x, mouse.y).y
0088
0089 // reset start position
0090 if (!hasStartPosition) {
0091 startPosition = yPos;
0092 hasStartPosition = true;
0093 }
0094
0095 // set threshold
0096 if (!passedDragThreshold && Math.abs(y) > dragThreshold) {
0097 passedDragThreshold = true;
0098 }
0099
0100 // update position
0101 // y < 0 - dragging up (dismissing the app)
0102 y = Math.min(0, yPos - startPosition);
0103 }
0104
0105 onPressedChanged: {
0106 yAnimator.stop();
0107
0108 // reset values
0109 if (pressed) {
0110 hasStartPosition = false;
0111 passedDragThreshold = false;
0112 }
0113
0114 // run animation when finger lets go
0115 if (!pressed) {
0116 if (control.movingUp && control.y < -Kirigami.Units.gridUnit * 2) {
0117 yAnimator.to = -root.height;
0118 } else {
0119 yAnimator.to = 0;
0120 }
0121 yAnimator.start();
0122 }
0123 }
0124
0125 // if the app doesn't close within a certain time, drag it back
0126 Timer {
0127 id: uncloseTimer
0128 interval: 3000
0129 onTriggered: {
0130 yAnimator.to = 0;
0131 yAnimator.restart();
0132 }
0133 }
0134
0135 NumberAnimation on y {
0136 id: yAnimator
0137 running: !control.pressed
0138 duration: Kirigami.Units.longDuration
0139 easing.type: Easing.InOutQuad
0140 to: 0
0141 onFinished: {
0142 if (to != 0) { // close app
0143 delegate.closeApp();
0144 uncloseTimer.start();
0145 }
0146 }
0147 }
0148
0149 // application
0150 ColumnLayout {
0151 id: column
0152 anchors.fill: parent
0153 spacing: 0
0154
0155 // header
0156 RowLayout {
0157 id: appHeader
0158 Layout.fillWidth: true
0159 Layout.fillHeight: true
0160 Layout.minimumHeight: column.height - appView.height
0161 spacing: Kirigami.Units.smallSpacing * 2
0162 opacity: delegate.showHeader ? 1 : 0
0163
0164 Behavior on opacity {
0165 NumberAnimation { duration: Kirigami.Units.shortDuration }
0166 }
0167
0168 Kirigami.Icon {
0169 Layout.preferredHeight: Kirigami.Units.iconSizes.smallMedium
0170 Layout.preferredWidth: Kirigami.Units.iconSizes.smallMedium
0171 Layout.alignment: Qt.AlignVCenter
0172 source: delegate.window.icon
0173 }
0174
0175 PlasmaComponents.Label {
0176 Layout.fillWidth: true
0177 Layout.alignment: Qt.AlignVCenter
0178 elide: Text.ElideRight
0179 text: delegate.window.caption
0180 color: "white"
0181 }
0182
0183 PlasmaComponents.ToolButton {
0184 Layout.alignment: Qt.AlignVCenter
0185 z: 99
0186 icon.name: "window-close"
0187 icon.width: Kirigami.Units.iconSizes.smallMedium
0188 icon.height: Kirigami.Units.iconSizes.smallMedium
0189 onClicked: delegate.closeApp()
0190 }
0191 }
0192
0193 // app preview
0194 Rectangle {
0195 id: appView
0196 Layout.preferredWidth: delegate.previewWidth
0197 Layout.preferredHeight: delegate.previewHeight
0198 Layout.maximumWidth: delegate.previewWidth
0199 Layout.maximumHeight: delegate.previewHeight
0200
0201 color: "transparent"
0202 clip: true
0203
0204 // scale animation on press
0205 property real zoomScale: control.pressed ? 0.9 : 1
0206 Behavior on zoomScale {
0207 NumberAnimation {
0208 duration: 200
0209 easing.type: Easing.OutExpo
0210 }
0211 }
0212
0213 transform: Scale {
0214 origin.x: appView.width / 2;
0215 origin.y: appView.height / 2;
0216 xScale: appView.zoomScale
0217 yScale: appView.zoomScale
0218 }
0219
0220 Item {
0221 id: item
0222 anchors.fill: parent
0223
0224 KWinComponents.WindowThumbnail {
0225 id: thumbSource
0226 wId: delegate.window.internalId
0227 anchors.fill: parent
0228
0229 layer.enabled: true
0230 layer.effect: ColorOverlay {
0231 color: Qt.rgba(0, 0, 0, delegate.darken)
0232 }
0233 }
0234 }
0235 }
0236 }
0237 }
0238 }
0239
0240