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 {
@ -50,124 +44,139 @@ Item {
} }
} }
Component.onCompleted: syncDelegateGeometry(); function closeApp() {
tasksModel.requestClose(tasksModel.index(model.index, 0));
}
Item { QQC2.Control {
anchors { id: control
fill: parent width: parent.width
margins: PlasmaCore.Units.smallSpacing height: parent.height
// drag up gesture
DragHandler {
id: dragHandler
target: parent
yAxis.enabled: true
xAxis.enabled: false
yAxis.maximum: 0
onActiveChanged: {
yAnimator.stop();
if (parent.y < -PlasmaCore.Units.gridUnit * 2) {
yAnimator.to = -window.height;
} else {
yAnimator.to = 0;
}
yAnimator.start();
}
} }
SequentialAnimation { NumberAnimation on y {
id: slideAnim id: yAnimator
property alias to: internalSlideAnim.to running: !dragHandler.active
NumberAnimation { duration: PlasmaCore.Units.longDuration
id: internalSlideAnim easing.type: Easing.InOutQuad
target: background to: 0
properties: "x" onFinished: {
duration: PlasmaCore.Units.longDuration if (to != 0) { // close app
easing.type: Easing.InOutQuad delegate.closeApp();
}
ScriptAction {
script: {
if (background.x != 0) {
tasksModel.requestClose(tasksModel.index(model.index, 0));
}
} }
} }
} }
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)
MouseArea { RowLayout {
anchors.fill: parent id: appHeader
drag { z: 99
target: background Layout.fillWidth: true
axis: Drag.XAxis Layout.alignment: Qt.AlignBottom
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"
} }
onReleased: {
delegate.z = 0; Repeater {
if (Math.abs(background.x) > background.width/2) { id: rep
slideAnim.to = background.x > 0 ? background.width*2 : -background.width*2; model: plasmoid.nativeInterface.outputs
slideAnim.running = true; delegate: PlasmaComponents.ToolButton {
} else { text: model.modelName
slideAnim.to = 0; visible: model.position !== delegate.taskScreenPoint
slideAnim.running = true; 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)
}
} }
} }
ColumnLayout { PlasmaComponents.ToolButton {
anchors { z: 99
fill: parent icon.name: "window-close"
margins: PlasmaCore.Units.smallSpacing icon.width: PlasmaCore.Units.iconSizes.smallMedium
} icon.height: PlasmaCore.Units.iconSizes.smallMedium
onClicked: delegate.closeApp()
}
}
RowLayout { QQC2.Control {
z: 99 id: appView
Layout.fillWidth: true Layout.alignment: Qt.AlignHCenter | Qt.AlignTop
Layout.maximumHeight: PlasmaCore.Units.gridUnit Layout.preferredWidth: delegate.previewWidth
PlasmaCore.IconItem { Layout.preferredHeight: delegate.previewHeight // keep same as window resolution
Layout.fillHeight: true
Layout.preferredWidth: height leftPadding: 0
usesPlasmaTheme: false rightPadding: 0
source: model.decoration topPadding: 0
} bottomPadding: 0
PlasmaComponents.Label {
Layout.fillWidth: true transform: Scale {
horizontalAlignment: Text.AlignHCenter origin.x: item.width / 2
elide: Text.ElideRight origin.y: item.height / 2
text: model.AppName xScale: delegate.scale
color: PlasmaCore.Theme.textColor yScale: delegate.scale
} }
Repeater {
id: rep background: Rectangle {
model: plasmoid.nativeInterface.outputs color: PlasmaCore.Theme.backgroundColor
delegate: PlasmaComponents.ToolButton { }
text: model.modelName
visible: model.position !== delegate.taskScreenPoint contentItem: Item {
display: rep.count < 3 ? QQC2.Button.IconOnly : QQC2.Button.TextBesideIcon id: item
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;
window.contentItem.opacity = 1;
if (activateAnim.delegate) {
activateAnim.delegate.z = 0;
activateAnim.delegate.scale = 1;
}
}
MobileShell.HomeScreenControls.taskSwitcherVisible = visible;
}
SequentialAnimation { //// visible: window.gestureDragging
id: scrollAnim //z: tasksView.z + 1
property alias to: internalAnim.to //color: Qt.rgba(255, 255, 255, 0.1)
property alias from: internalAnim.from
ScriptAction {
script: window.showFullScreen();
}
NumberAnimation {
id: internalAnim
target: tasksView
properties: "contentY"
duration: PlasmaCore.Units.longDuration
easing.type: Easing.InOutQuad
}
ScriptAction {
script: {
if (tasksView.contentY <= 0 || tasksView.contentY >= tasksView.contentHeight - window.height) {
window.visible = false;
setSingleActiveWindow(currentTaskIndex);
} else {
moveTransition.enabled = true;
}
}
}
}
SequentialAnimation { //transform: Scale {
id: activateAnim //origin.x: window.width / 2
property Item delegate //origin.y: MobileShell.TopPanelControls.panelHeight + liveAppShrink.height / 2
ScriptAction { //xScale: {
script: { //let minScale = tasksView.scalingFactor;
activateAnim.delegate.z = 2; //let travelDist = window.height - tasksView.height;
let pos = tasksView.mapFromItem(activateAnim.delegate, 0, 0); //let subtract = (1 - minScale) * (window.offset / travelDist);
if (pos.x < tasksView.width / 2 && pos.y < tasksView.height / 2) { //return Math.min(1, Math.max(minScale, 1 - subtract));
activateAnim.delegate.transformOrigin = Item.TopLeft; //}
} else if (pos.x < tasksView.width / 2 && pos.y >= tasksView.height / 2) { //yScale: xScale
activateAnim.delegate.transformOrigin = Item.BottomLeft; //}
} else if (pos.x >= tasksView.width / 2 && pos.y < tasksView.height / 2) {
activateAnim.delegate.transformOrigin = Item.TopRight;
} else {
activateAnim.delegate.transformOrigin = Item.BottomRight;
}
}
}
ParallelAnimation {
OpacityAnimator {
target: window.contentItem
from: 1
to: 0
duration: PlasmaCore.Units.longDuration
easing.type: Easing.InOutQuad
}
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: {
window.visible = false;
}
}
}
Flickable { //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 id: tasksView
width: window.width z: 100
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: { property real horizontalMargin: PlasmaCore.Units.gridUnit * 3
if (flickState != TaskSwitcher.MovementDirection.None) { anchors.centerIn: parent
return flickState;
} else if (verticalVelocity < 0) { width: window.width - horizontalMargin * 2
return TaskSwitcher.MovementDirection.Up; height: window.height - (MobileShell.TopPanelControls.panelHeight + window.panelHeight + footerButtons.height
} else if (verticalVelocity > 0) { + PlasmaCore.Units.gridUnit * 2 + PlasmaCore.Units.largeSpacing * 2)
return TaskSwitcher.MovementDirection.Down;
// 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 { } else {
return TaskSwitcher.MovementDirection.None; return tasksView.width / window.width;
} }
} }
onFlickingVerticallyChanged: { model: window.model
if (flickingVertically) { snapMode: ListView.SnapToItem
flickState = verticalVelocity < 0 ? TaskSwitcher.MovementDirection.Up : TaskSwitcher.MovementDirection.Down; orientation: ListView.Horizontal
} else if (/*!draggingVertically &&*/ !flickingVertically) { spacing: PlasmaCore.Units.largeSpacing
flickState = TaskSwitcher.MovementDirection.None displayMarginBeginning: 2 * (width + spacing)
} displayMarginEnd: 2 * (width + spacing)
Qt.callLater(function() {
tasksView.topMargin = flickingVertically && !scrollAnim.running ? -tasksView.height : 0; displaced: Transition {
tasksView.bottomMargin = tasksView.topMargin; NumberAnimation { properties: "x,y"; duration: PlasmaCore.Units.longDuration; easing.type: Easing.InOutQuad }
});
} }
onDraggingVerticallyChanged: { property real offset: 0
if (draggingVertically) { property real currentIndexInView: indexAt(contentX, contentY)
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 { MouseArea {
id: mainArea z: -1
parent: tasksView.contentItem anchors.fill: parent
width: tasksView.width visible: tasksView.count === 0
implicitHeight: window.height * 2 + Math.max(window.height, grid.implicitHeight) enabled: visible
onClicked: window.hide() onClicked: { // close window on tap if there are no delegates
if (tasksView.count === 0) {
window.hide()
}
}
Grid { PlasmaComponents.Label {
id: grid anchors.centerIn: parent
anchors { text: i18n("No applications are open")
left: parent.left color: "white"
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
}
}
} }
} }
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
//}
}
} }
PlasmaComponents.RoundButton { RowLayout {
anchors { id: footerButtons
horizontalCenter: parent.horizontalCenter anchors.left: parent.left
bottom: parent.bottom anchors.right: parent.right
} anchors.bottom: parent.bottom
icon.name: "start-here-kde" anchors.bottomMargin: PlasmaCore.Units.largeSpacing + window.panelHeight
icon.width: PlasmaCore.Units.iconSizes.medium anchors.topMargin: PlasmaCore.Units.largeSpacing
icon.height: PlasmaCore.Units.iconSizes.medium
onClicked: {
currentTaskIndex = -1;
window.hide();
//plasmoid.nativeInterface.showDesktop = true;
root.minimizeAll(); spacing: PlasmaCore.Units.largeSpacing
PlasmaComponents.ToolButton {
Layout.alignment: Qt.AlignRight
icon.width: PlasmaCore.Units.iconSizes.medium
icon.height: PlasmaCore.Units.iconSizes.medium
icon.name: "view-list-symbolic" // "view-grid-symbolic"
text: i18n("Switch to list view")
display: PlasmaComponents.ToolButton.IconOnly
}
PlasmaComponents.ToolButton {
Layout.alignment: Qt.AlignHCenter
icon.width: PlasmaCore.Units.iconSizes.medium
icon.height: PlasmaCore.Units.iconSizes.medium
icon.name: "trash-empty"
text: i18n("Clear All")
display: PlasmaComponents.ToolButton.IconOnly
}
PlasmaComponents.ToolButton {
Layout.alignment: Qt.AlignLeft
icon.width: PlasmaCore.Units.iconSizes.medium
icon.height: PlasmaCore.Units.iconSizes.medium
icon.name: "system-search"
text: i18n("Search")
display: PlasmaComponents.ToolButton.IconOnly
} }
} }
} }

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) {
@ -173,18 +171,10 @@ 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
}); });
} }