Revamp task switcher

This commit is contained in:
Devin Lin 2021-10-17 23:50:59 -04:00
parent 25e0f99f43
commit 90138d5442
6 changed files with 352 additions and 380 deletions

View file

@ -1,5 +1,6 @@
/* /*
* SPDX-FileCopyrightText: 2020 Marco Martin <mart@kde.org> * SPDX-FileCopyrightText: 2020 Marco Martin <mart@kde.org>
* SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org>
* *
* SPDX-License-Identifier: GPL-2.0-or-later * SPDX-License-Identifier: GPL-2.0-or-later
*/ */
@ -15,6 +16,7 @@ QtObject {
signal resetHomeScreenPosition() signal resetHomeScreenPosition()
signal snapHomeScreenPosition() signal snapHomeScreenPosition()
signal requestRelativeScroll(point pos) signal requestRelativeScroll(point pos)
signal setHomeScreenOpacity(int opacity)
property Item homeScreen property Item homeScreen
property QtObject homeScreenWindow property QtObject homeScreenWindow
property bool homeScreenVisible: true property bool homeScreenVisible: true

View file

@ -60,6 +60,17 @@ FocusScope {
lastRequestedPosition = pos.y; lastRequestedPosition = pos.y;
} }
} }
opacity: 1
Behavior on opacity {
NumberAnimation { duration: PlasmaCore.Units.shortDuration }
}
Connections {
target: MobileShell.HomeScreenControls
function onSetHomeScreenOpacity(opacity) {
root.opacity = opacity;
}
}
//END API implementation //END API implementation
property bool componentComplete: false property bool componentComplete: false

View file

@ -1,10 +1,11 @@
/* /*
* SPDX-FileCopyrightText: 2015 Marco Martin <notmart@gmail.com> * SPDX-FileCopyrightText: 2015 Marco Martin <notmart@gmail.com>
* SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org>
* *
* SPDX-License-Identifier: LGPL-2.0-or-later * SPDX-License-Identifier: LGPL-2.0-or-later
*/ */
import QtQuick 2.0 import QtQuick 2.15
import QtQuick.Layouts 1.1 import QtQuick.Layouts 1.1
import QtQuick.Window 2.2 import QtQuick.Window 2.2
import QtQuick.Controls 2.2 as QQC2 import QtQuick.Controls 2.2 as QQC2
@ -15,32 +16,25 @@ import org.kde.plasma.components 3.0 as PlasmaComponents
Item { Item {
id: delegate id: delegate
width: window.width/2
height: window.height/2
//Workaround
required property var model required property var model
property bool active: model.IsActive
readonly property point taskScreenPoint: Qt.point(model.ScreenGeometry.x, model.ScreenGeometry.y)
onActiveChanged: {
//sometimes the task switcher window itself appears, screwing up the state
if (model.IsActive) {
// window.currentTaskIndex = index
}
}
readonly property point taskScreenPoint: Qt.point(model.ScreenGeometry.x, model.ScreenGeometry.y)
readonly property real dragOffset: -control.y
property bool active: model.IsActive
required property real previewHeight
required property real previewWidth
property real scale: 1
opacity: 1 - dragOffset / window.height
Component.onCompleted: syncDelegateGeometry();
function syncDelegateGeometry() { function syncDelegateGeometry() {
let pos = pipeWireLoader.mapToItem(tasksView, 0, 0); let pos = pipeWireLoader.mapToItem(tasksView, 0, 0);
if (window.visible) { if (window.visible) {
tasksModel.requestPublishDelegateGeometry(tasksModel.index(model.index, 0), Qt.rect(pos.x, pos.y, pipeWireLoader.width, pipeWireLoader.height), pipeWireLoader); tasksModel.requestPublishDelegateGeometry(tasksModel.index(model.index, 0), Qt.rect(pos.x, pos.y, pipeWireLoader.width, pipeWireLoader.height), pipeWireLoader);
} else {
// tasksModel.requestPublishDelegateGeometry(tasksModel.index(model.index, 0), Qt.rect(pos.x, pos.y, delegate.width, delegate.height), dummyWindowTask);
}
}
Connections {
target: tasksView
onContentYChanged: {
syncDelegateGeometry();
} }
} }
Connections { Connections {
@ -49,125 +43,140 @@ Item {
syncDelegateGeometry(); syncDelegateGeometry();
} }
} }
function closeApp() {
tasksModel.requestClose(tasksModel.index(model.index, 0));
}
Component.onCompleted: syncDelegateGeometry(); QQC2.Control {
id: control
Item { width: parent.width
anchors { height: parent.height
fill: parent
margins: PlasmaCore.Units.smallSpacing // drag up gesture
} DragHandler {
id: dragHandler
SequentialAnimation { target: parent
id: slideAnim yAxis.enabled: true
property alias to: internalSlideAnim.to xAxis.enabled: false
NumberAnimation { yAxis.maximum: 0
id: internalSlideAnim onActiveChanged: {
target: background yAnimator.stop();
properties: "x"
duration: PlasmaCore.Units.longDuration if (parent.y < -PlasmaCore.Units.gridUnit * 2) {
easing.type: Easing.InOutQuad yAnimator.to = -window.height;
} else {
yAnimator.to = 0;
}
yAnimator.start();
} }
ScriptAction { }
script: {
if (background.x != 0) { NumberAnimation on y {
tasksModel.requestClose(tasksModel.index(model.index, 0)); id: yAnimator
} running: !dragHandler.active
duration: PlasmaCore.Units.longDuration
easing.type: Easing.InOutQuad
to: 0
onFinished: {
if (to != 0) { // close app
delegate.closeApp();
} }
} }
} }
Rectangle {
id: background
width: parent.width // application
height: parent.height ColumnLayout {
radius: PlasmaCore.Units.smallSpacing anchors.fill: parent
color: PlasmaCore.Theme.backgroundColor spacing: PlasmaCore.Units.smallSpacing
opacity: 1 * (1-Math.abs(x)/width)
RowLayout {
MouseArea { id: appHeader
anchors.fill: parent z: 99
drag { Layout.fillWidth: true
target: background Layout.alignment: Qt.AlignBottom
axis: Drag.XAxis
PlasmaCore.IconItem {
Layout.preferredHeight: PlasmaCore.Units.iconSizes.smallMedium
Layout.preferredWidth: PlasmaCore.Units.iconSizes.smallMedium
Layout.alignment: Qt.AlignVCenter
usesPlasmaTheme: false
source: model.decoration
} }
onPressed: delegate.z = 10;
onClicked: { PlasmaComponents.Label {
window.setSingleActiveWindow(model.index, delegate); Layout.fillWidth: true
if (!model.IsMinimized) { Layout.alignment: Qt.AlignVCenter
window.visible = false; elide: Text.ElideRight
text: model.AppName
color: "white"
}
Repeater {
id: rep
model: plasmoid.nativeInterface.outputs
delegate: PlasmaComponents.ToolButton {
text: model.modelName
visible: model.position !== delegate.taskScreenPoint
display: rep.count < 3 ? QQC2.Button.IconOnly : QQC2.Button.TextBesideIcon
icon.name: "tv" //TODO provide a more adequate icon
onClicked: {
plasmoid.nativeInterface.sendWindowToOutput(delegate.model.WinIdList[0], model.output)
}
} }
} }
onReleased: {
delegate.z = 0; PlasmaComponents.ToolButton {
if (Math.abs(background.x) > background.width/2) { z: 99
slideAnim.to = background.x > 0 ? background.width*2 : -background.width*2; icon.name: "window-close"
slideAnim.running = true; icon.width: PlasmaCore.Units.iconSizes.smallMedium
} else { icon.height: PlasmaCore.Units.iconSizes.smallMedium
slideAnim.to = 0; onClicked: delegate.closeApp()
slideAnim.running = true;
}
} }
}
ColumnLayout {
anchors { QQC2.Control {
fill: parent id: appView
margins: PlasmaCore.Units.smallSpacing Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
} Layout.preferredWidth: delegate.previewWidth
Layout.preferredHeight: delegate.previewHeight // keep same as window resolution
leftPadding: 0
rightPadding: 0
topPadding: 0
bottomPadding: 0
transform: Scale {
origin.x: item.width / 2
origin.y: item.height / 2
xScale: delegate.scale
yScale: delegate.scale
}
background: Rectangle {
color: PlasmaCore.Theme.backgroundColor
}
contentItem: Item {
id: item
RowLayout {
z: 99
Layout.fillWidth: true
Layout.maximumHeight: PlasmaCore.Units.gridUnit
PlasmaCore.IconItem {
Layout.fillHeight: true
Layout.preferredWidth: height
usesPlasmaTheme: false
source: model.decoration
}
PlasmaComponents.Label {
Layout.fillWidth: true
horizontalAlignment: Text.AlignHCenter
elide: Text.ElideRight
text: model.AppName
color: PlasmaCore.Theme.textColor
}
Repeater {
id: rep
model: plasmoid.nativeInterface.outputs
delegate: PlasmaComponents.ToolButton {
text: model.modelName
visible: model.position !== delegate.taskScreenPoint
display: rep.count < 3 ? QQC2.Button.IconOnly : QQC2.Button.TextBesideIcon
icon.name: "tv" //TODO provide a more adequate icon
onClicked: {
plasmoid.nativeInterface.sendWindowToOutput(delegate.model.WinIdList[0], model.output)
}
}
}
PlasmaComponents.ToolButton {
z: 99
icon.name: "window-close"
icon.width: PlasmaCore.Units.iconSizes.medium
icon.height: PlasmaCore.Units.iconSizes.medium
onClicked: {
slideAnim.to = -background.width*2;
slideAnim.running = true;
}
}
}
Loader { Loader {
id: pipeWireLoader id: pipeWireLoader
Layout.fillWidth: true anchors.fill: parent
Layout.fillHeight: true source: /*Qt.resolvedUrl("./TaskIcon.qml");*/ Qt.resolvedUrl("./Thumbnail.qml")
source: Qt.resolvedUrl("./Thumbnail.qml")
onStatusChanged: { onStatusChanged: {
if (status === Loader.Error) { if (status === Loader.Error) {
source = Qt.resolvedUrl("./TaskIcon.qml"); source = Qt.resolvedUrl("./TaskIcon.qml");
} }
} }
} }
TapHandler {
onTapped: {
window.setSingleActiveWindow(model.index, delegate);
window.visible = false;
}
}
} }
} }
} }

View file

@ -10,6 +10,8 @@ import org.kde.plasma.core 2.0 as PlasmaCore
PlasmaCore.IconItem { PlasmaCore.IconItem {
implicitWidth: PlasmaCore.Units.iconSizes.medium
implicitHeight: PlasmaCore.Units.iconSizes.medium
usesPlasmaTheme: false usesPlasmaTheme: false
source: model.decoration source: model.decoration
} }

View file

@ -1,5 +1,6 @@
/* /*
* SPDX-FileCopyrightText: 2015 Marco Martin <notmart@gmail.com> * SPDX-FileCopyrightText: 2015 Marco Martin <notmart@gmail.com>
* SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org>
* *
* SPDX-License-Identifier: LGPL-2.0-or-later * SPDX-License-Identifier: LGPL-2.0-or-later
*/ */
@ -19,18 +20,31 @@ NanoShell.FullScreenOverlay {
visible: false visible: false
width: Screen.width width: Screen.width
height: Screen.height height: Screen.height
property int offset: 0
property int overShoot: PlasmaCore.Units.gridUnit * 2 required property bool gestureDragging
required property real panelHeight // height of task panel, provided by main.qml
property int tasksCount: window.model.count property int tasksCount: window.model.count
property int currentTaskIndex: -1 property int currentTaskIndex: tasksView.contentX / (tasksView.width + tasksView.spacing)
property TaskManager.TasksModel model property TaskManager.TasksModel model
property real offset: 0
Component.onCompleted: plasmoid.nativeInterface.panel = window; Component.onCompleted: plasmoid.nativeInterface.panel = window;
enum MovementDirection { enum MovementDirection {
None = 0, None = 0,
Up, Left,
Down Right
}
onVisibleChanged: {
if (!visible) {
window.contentItem.opacity = 1;
}
// hide homescreen elements to make use of wallpaper
MobileShell.HomeScreenControls.setHomeScreenOpacity(visible ? 0 : 1);
MobileShell.HomeScreenControls.taskSwitcherVisible = visible;
} }
onTasksCountChanged: { onTasksCountChanged: {
@ -38,38 +52,35 @@ NanoShell.FullScreenOverlay {
hide(); hide();
} }
} }
color: "transparent" color: "transparent"
// More controllable than the color property
Rectangle { Rectangle {
id: backgroundRect
anchors.fill: parent anchors.fill: parent
color: Qt.rgba(0, 0, 0, 0.6) color: Qt.rgba(0, 0, 0, 0.6)
opacity: Math.min(
(Math.min(tasksView.contentY, tasksView.height) / tasksView.height), MouseArea {
((tasksView.contentHeight - tasksView.contentY - window.height) / tasksView.height)) anchors.fill: parent
onClicked: hide()
}
} }
function show() { function show() {
if (window.model.count == 0) { window.offset = 0;
return; // skip to first active task
if (window.model.activeTask.row >= 0) {
tasksView.contentX = window.model.activeTask.row * (tasksView.width + tasksView.spacing);
} }
visible = true; root.minimizeAll();
scrollAnim.from = tasksView.contentY; window.visible = true;
scrollAnim.to = window.height;
scrollAnim.restart();
} }
function hide() { function hide() {
if (!window.visible) { if (!window.visible) {
return; return;
} }
scrollAnim.from = tasksView.contentY; window.visible = false;
if (tasksView.contentY + window.height <= tasksView.contentHeight - tasksView.contentY) {
scrollAnim.to = 0;
} else {
scrollAnim.to = tasksView.contentHeight - window.height;
}
scrollAnim.restart();
} }
function setSingleActiveWindow(id, delegate) { function setSingleActiveWindow(id, delegate) {
@ -91,232 +102,179 @@ NanoShell.FullScreenOverlay {
} }
} }
} }
activateAnim.delegate = delegate;
activateAnim.restart(); window.visible = false;
} }
onOffsetChanged: tasksView.contentY = offset + grid.y //Rectangle {
onVisibleChanged: { //id: liveAppShrink
if (!visible) { //anchors.fill: parent
tasksView.contentY = 0; //anchors.topMargin: MobileShell.TopPanelControls.panelHeight
moveTransition.enabled = false; //anchors.bottomMargin: window.panelHeight
scrollAnim.running = false;
activateAnim.running = false; //// visible: window.gestureDragging
window.contentItem.opacity = 1; //z: tasksView.z + 1
if (activateAnim.delegate) { //color: Qt.rgba(255, 255, 255, 0.1)
activateAnim.delegate.z = 0;
activateAnim.delegate.scale = 1; //transform: Scale {
//origin.x: window.width / 2
//origin.y: MobileShell.TopPanelControls.panelHeight + liveAppShrink.height / 2
//xScale: {
//let minScale = tasksView.scalingFactor;
//let travelDist = window.height - tasksView.height;
//let subtract = (1 - minScale) * (window.offset / travelDist);
//return Math.min(1, Math.max(minScale, 1 - subtract));
//}
//yScale: xScale
//}
//Loader {
//id: pipeWireLoader
//anchors.fill: parent
//z: tasksView.z + 1
//source: Qt.resolvedUrl("./Thumbnail.qml")
//onStatusChanged: {
//if (status === Loader.Error) {
//visible = false;
//}
//}
//function syncDelegateGeometry() {
//window.model.requestPublishDelegateGeometry(window.model.activeTask, Qt.rect(parent.x, parent.y, pipeWireLoader.width, pipeWireLoader.height), pipeWireLoader);
//}
//Component.onCompleted: syncDelegateGeometry();
//Connections {
//target: window.model
//function onActiveTaskChanged() {
//pipeWireLoader.syncDelegateGeometry();
//}
//}
//}
//}
ListView {
id: tasksView
z: 100
property real horizontalMargin: PlasmaCore.Units.gridUnit * 3
anchors.centerIn: parent
width: window.width - horizontalMargin * 2
height: window.height - (MobileShell.TopPanelControls.panelHeight + window.panelHeight + footerButtons.height
+ PlasmaCore.Units.gridUnit * 2 + PlasmaCore.Units.largeSpacing * 2)
// ensure that window previews are exactly to the scale of the device screen
property real windowHeight: window.height - window.panelHeight - MobileShell.TopPanelControls.panelHeight
property real scalingFactor: {
let candidateWidth = tasksView.width;
let candidateHeight = (tasksView.width / window.width) * windowHeight;
if (candidateHeight > tasksView.height) {
return tasksView.height / windowHeight;
} else {
return tasksView.width / window.width;
} }
} }
MobileShell.HomeScreenControls.taskSwitcherVisible = visible;
} model: window.model
snapMode: ListView.SnapToItem
SequentialAnimation { orientation: ListView.Horizontal
id: scrollAnim spacing: PlasmaCore.Units.largeSpacing
property alias to: internalAnim.to displayMarginBeginning: 2 * (width + spacing)
property alias from: internalAnim.from displayMarginEnd: 2 * (width + spacing)
ScriptAction {
script: window.showFullScreen(); displaced: Transition {
NumberAnimation { properties: "x,y"; duration: PlasmaCore.Units.longDuration; easing.type: Easing.InOutQuad }
} }
NumberAnimation {
id: internalAnim property real offset: 0
target: tasksView property real currentIndexInView: indexAt(contentX, contentY)
properties: "contentY"
duration: PlasmaCore.Units.longDuration MouseArea {
easing.type: Easing.InOutQuad z: -1
} anchors.fill: parent
ScriptAction { visible: tasksView.count === 0
script: { enabled: visible
if (tasksView.contentY <= 0 || tasksView.contentY >= tasksView.contentHeight - window.height) { onClicked: { // close window on tap if there are no delegates
window.visible = false; if (tasksView.count === 0) {
setSingleActiveWindow(currentTaskIndex); window.hide()
} else {
moveTransition.enabled = true;
} }
} }
PlasmaComponents.Label {
anchors.centerIn: parent
text: i18n("No applications are open")
color: "white"
}
}
delegate: Task {
id: task
property int curIndex: model.index
width: tasksView.width
height: tasksView.height
// ensure that window previews are exactly to the scale of the device screen
previewWidth: tasksView.scalingFactor * window.width
previewHeight: tasksView.scalingFactor * tasksView.windowHeight
scale: {
if (task.curIndex === window.currentTaskIndex) {
let maxScale = 1 / tasksView.scalingFactor;
let travelDist = window.height - tasksView.height;
let subtract = (maxScale - 1) * (window.offset / travelDist);
let finalScale = Math.max(1, Math.min(maxScale, maxScale - subtract));
return finalScale;
}
return 1;
}
onDragOffsetChanged: tasksView.offset = dragOffset
// TODO slide right animation
//transform: Translate {
//x: task.curIndex < tasksView.currentIndexInView ? Math.min(task.width + tasksView.spacing, tasksView.offset / 2) : 0
//}
} }
} }
SequentialAnimation { RowLayout {
id: activateAnim id: footerButtons
property Item delegate anchors.left: parent.left
ScriptAction { anchors.right: parent.right
script: { anchors.bottom: parent.bottom
activateAnim.delegate.z = 2; anchors.bottomMargin: PlasmaCore.Units.largeSpacing + window.panelHeight
let pos = tasksView.mapFromItem(activateAnim.delegate, 0, 0); anchors.topMargin: PlasmaCore.Units.largeSpacing
if (pos.x < tasksView.width / 2 && pos.y < tasksView.height / 2) {
activateAnim.delegate.transformOrigin = Item.TopLeft; spacing: PlasmaCore.Units.largeSpacing
} else if (pos.x < tasksView.width / 2 && pos.y >= tasksView.height / 2) {
activateAnim.delegate.transformOrigin = Item.BottomLeft; PlasmaComponents.ToolButton {
} else if (pos.x >= tasksView.width / 2 && pos.y < tasksView.height / 2) { Layout.alignment: Qt.AlignRight
activateAnim.delegate.transformOrigin = Item.TopRight; icon.width: PlasmaCore.Units.iconSizes.medium
} else { icon.height: PlasmaCore.Units.iconSizes.medium
activateAnim.delegate.transformOrigin = Item.BottomRight; icon.name: "view-list-symbolic" // "view-grid-symbolic"
} text: i18n("Switch to list view")
} display: PlasmaComponents.ToolButton.IconOnly
} }
ParallelAnimation {
OpacityAnimator { PlasmaComponents.ToolButton {
target: window.contentItem Layout.alignment: Qt.AlignHCenter
from: 1 icon.width: PlasmaCore.Units.iconSizes.medium
to: 0 icon.height: PlasmaCore.Units.iconSizes.medium
duration: PlasmaCore.Units.longDuration icon.name: "trash-empty"
easing.type: Easing.InOutQuad text: i18n("Clear All")
} display: PlasmaComponents.ToolButton.IconOnly
ScaleAnimator {
target: activateAnim.delegate
from: 1
to: 2
// To try tosync up with kwin animation
duration: PlasmaCore.Units.longDuration * 0.85
easing.type: Easing.InOutQuad
}
} }
ScriptAction {
script: { PlasmaComponents.ToolButton {
window.visible = false; Layout.alignment: Qt.AlignLeft
} icon.width: PlasmaCore.Units.iconSizes.medium
} icon.height: PlasmaCore.Units.iconSizes.medium
} icon.name: "system-search"
text: i18n("Search")
Flickable { display: PlasmaComponents.ToolButton.IconOnly
id: tasksView
width: window.width
height: window.height
contentWidth: width
contentHeight: mainArea.implicitHeight
// topMargin: flickingVertically ? -height : 0
// bottomMargin: flickingVertically ? -height : 0
property int flickState: TaskSwitcher.MovementDirection.None
readonly property int movementDirection: {
if (flickState != TaskSwitcher.MovementDirection.None) {
return flickState;
} else if (verticalVelocity < 0) {
return TaskSwitcher.MovementDirection.Up;
} else if (verticalVelocity > 0) {
return TaskSwitcher.MovementDirection.Down;
} else {
return TaskSwitcher.MovementDirection.None;
}
}
onFlickingVerticallyChanged: {
if (flickingVertically) {
flickState = verticalVelocity < 0 ? TaskSwitcher.MovementDirection.Up : TaskSwitcher.MovementDirection.Down;
} else if (/*!draggingVertically &&*/ !flickingVertically) {
flickState = TaskSwitcher.MovementDirection.None
}
Qt.callLater(function() {
tasksView.topMargin = flickingVertically && !scrollAnim.running ? -tasksView.height : 0;
tasksView.bottomMargin = tasksView.topMargin;
});
}
onDraggingVerticallyChanged: {
if (draggingVertically) {
return;
}
let beforeBeginning = contentY < window.height;
let afterEnd = contentY > contentHeight - window.height * 2;
let topCloseCondition = contentY < window.height / 10 * 9;
let bottomClosecondition = contentY > contentHeight - window.height * 2 - window.height / 10;
switch (movementDirection) {
case TaskSwitcher.MovementDirection.Up: {
if (topCloseCondition) {
hide();
} else if (beforeBeginning) {
show();
} else if (afterEnd) {
scrollAnim.from = tasksView.contentY;
scrollAnim.to = tasksView.contentHeight - window.height * 2;
scrollAnim.restart();
}
break;
}
case TaskSwitcher.MovementDirection.Down: {
if (bottomClosecondition) {
hide();
} else if (beforeBeginning) {
show();
} else if (afterEnd) {
scrollAnim.from = tasksView.contentY;
scrollAnim.to = tasksView.contentHeight - window.height * 2;
scrollAnim.restart();
}
break;
}
case TaskSwitcher.MovementDirection.None:
default:
if (beforeBeginning) {
show();
} else if (afterEnd) {
scrollAnim.from = tasksView.contentY;
scrollAnim.to = tasksView.contentHeight - window.height * 2;
scrollAnim.restart();
}
break;
}
}
MouseArea {
id: mainArea
parent: tasksView.contentItem
width: tasksView.width
implicitHeight: window.height * 2 + Math.max(window.height, grid.implicitHeight)
onClicked: window.hide()
Grid {
id: grid
anchors {
left: parent.left
right: parent.right
}
columns: 2
y: parent.height - height - window.height
Behavior on y {
NumberAnimation {
duration: PlasmaCore.Units.longDuration
easing.type: Easing.InOutQuad
}
}
Repeater {
model: window.model
delegate: Task {}
}
move: Transition {
id: moveTransition
enabled: false
NumberAnimation {
properties: "x,y"
duration: PlasmaCore.Units.longDuration
easing.type: Easing.InOutQuad
}
}
}
}
}
PlasmaComponents.RoundButton {
anchors {
horizontalCenter: parent.horizontalCenter
bottom: parent.bottom
}
icon.name: "start-here-kde"
icon.width: PlasmaCore.Units.iconSizes.medium
icon.height: PlasmaCore.Units.iconSizes.medium
onClicked: {
currentTaskIndex = -1;
window.hide();
//plasmoid.nativeInterface.showDesktop = true;
root.minimizeAll();
} }
} }
} }

View file

@ -1,5 +1,6 @@
/* /*
* SPDX-FileCopyrightText: 2015 Marco Martin <mart@kde.org> * SPDX-FileCopyrightText: 2015 Marco Martin <mart@kde.org>
* SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org>
* *
* SPDX-License-Identifier: GPL-2.0-or-later * SPDX-License-Identifier: GPL-2.0-or-later
*/ */
@ -46,7 +47,7 @@ PlasmaCore.ColorScope {
running: true running: true
interval: 200 interval: 200
onTriggered: { onTriggered: {
taskSwitcherLoader.setSource(Qt.resolvedUrl("TaskSwitcher.qml"), {"model": tasksModel}); taskSwitcherLoader.setSource(Qt.resolvedUrl("TaskSwitcher.qml"), {"model": tasksModel, "panelHeight": root.height, "gestureDragging": mainMouseArea.pressed});
} }
} }
@ -77,8 +78,6 @@ PlasmaCore.ColorScope {
virtualDesktop: virtualDesktopInfo.currentDesktop virtualDesktop: virtualDesktopInfo.currentDesktop
activity: activityInfo.currentActivity activity: activityInfo.currentActivity
//FIXME: workaround
Component.onCompleted: tasksModel.countChanged();
} }
TaskManager.VirtualDesktopInfo { TaskManager.VirtualDesktopInfo {
@ -104,7 +103,6 @@ PlasmaCore.ColorScope {
onPressed: { onPressed: {
startMouseX = oldMouseX = mouse.y; startMouseX = oldMouseX = mouse.y;
startMouseY = oldMouseY = mouse.y; startMouseY = oldMouseY = mouse.y;
taskSwitcher.offset = -taskSwitcher.height;
activeButton = icons.childAt(mouse.x, mouse.y); activeButton = icons.childAt(mouse.x, mouse.y);
} }
onPositionChanged: { onPositionChanged: {
@ -119,18 +117,18 @@ PlasmaCore.ColorScope {
isDragging = true; isDragging = true;
} }
taskSwitcher.offset = taskSwitcher.offset - (mouse.y - oldMouseY); taskSwitcher.offset = Math.max(0, taskSwitcher.offset - (mouse.y - oldMouseY));
opening = oldMouseY > mouse.y; opening = oldMouseY > mouse.y;
if (taskSwitcher.visibility == Window.Hidden && taskSwitcher.offset > -taskSwitcher.height + units.gridUnit && taskSwitcher.tasksCount) { if (taskSwitcher.visibility == Window.Hidden && Math.abs(startMouseY - mouse.y) > PlasmaCore.Units.gridUnit && taskSwitcher.tasksCount) {
activeButton = null; activeButton = null;
taskSwitcher.showFullScreen(); taskSwitcher.show();
//no tasks, let's scroll up the homescreen instead
} else if (taskSwitcher.tasksCount === 0) { } else if (taskSwitcher.tasksCount === 0) {
//no tasks, let's scroll up the homescreen instead
MobileShell.HomeScreenControls.requestRelativeScroll(Qt.point(mouse.x - oldMouseX, mouse.y - oldMouseY)); MobileShell.HomeScreenControls.requestRelativeScroll(Qt.point(mouse.x - oldMouseX, mouse.y - oldMouseY));
} }
oldMouseY = mouse.y; oldMouseY = mouse.y;
oldMouseY = mouse.y; oldMouseX = mouse.x;
} }
onReleased: { onReleased: {
if (taskSwitcher.visibility == Window.Hidden) { if (taskSwitcher.visibility == Window.Hidden) {
@ -172,19 +170,11 @@ PlasmaCore.ColorScope {
visible: plasmoid.configuration.PanelButtonsVisible visible: plasmoid.configuration.PanelButtonsVisible
property real buttonLength: 0 property real buttonLength: 0
// background colour
Rectangle { Rectangle {
anchors.fill: parent anchors.fill: parent
gradient: Gradient { color: showingApp ? root.backgroundColor : "transparent"
GradientStop {
position: 0
color: showingApp ? root.backgroundColor : "transparent"
}
GradientStop {
position: 1
color: showingApp ? root.backgroundColor : Qt.rgba(0, 0, 0, 0.1)
}
}
} }
Button { Button {
@ -213,6 +203,7 @@ PlasmaCore.ColorScope {
} }
root.minimizeAll(); root.minimizeAll();
MobileShell.HomeScreenControls.resetHomeScreenPosition(); MobileShell.HomeScreenControls.resetHomeScreenPosition();
MobileShell.HomeScreenControls.setHomeScreenOpacity(1);
plasmoid.nativeInterface.allMinimizedChanged(); plasmoid.nativeInterface.allMinimizedChanged();
} }
iconSizeFactor: 1 iconSizeFactor: 1
@ -253,7 +244,6 @@ PlasmaCore.ColorScope {
return; return;
Window.window.offset = Qt.binding(() => { Window.window.offset = Qt.binding(() => {
// FIXME: find a more precise way to determine the top panel height
return plasmoid.formFactor === PlasmaCore.Types.Vertical ? MobileShell.TopPanelControls.panelHeight : 0 return plasmoid.formFactor === PlasmaCore.Types.Vertical ? MobileShell.TopPanelControls.panelHeight : 0
}); });
} }