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