taskswitcher: Move component to homescreen and remove popup window

This commit is contained in:
Devin Lin 2021-12-24 22:31:33 -05:00
parent e407e76233
commit 4057122fb0
10 changed files with 235 additions and 202 deletions

View file

@ -13,12 +13,12 @@ pragma Singleton
QtObject { QtObject {
id: delegate id: delegate
signal openHomeScreen()
signal resetHomeScreenPosition() signal resetHomeScreenPosition()
signal snapHomeScreenPosition() signal snapHomeScreenPosition()
signal requestRelativeScroll(point pos) signal requestRelativeScroll(point pos)
signal hideHomeScreen(bool animate)
signal showHomeScreen(bool animate) property var taskSwitcher
property Item homeScreen
property QtObject homeScreenWindow property QtObject homeScreenWindow
property bool homeScreenVisible: true property bool homeScreenVisible: true
property bool taskSwitcherVisible: false property bool taskSwitcherVisible: false

View file

@ -0,0 +1,21 @@
/*
* SPDX-FileCopyrightText: 2021 Devin Lin <devin@kde.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
import QtQuick 2.12
import org.kde.plasma.core 2.0 as PlasmaCore
pragma Singleton
/**
* Properties exposed by the taskpanel containment.
*/
QtObject {
id: root
property bool isPortrait
property real panelHeight
property real panelWidth
}

View file

@ -82,7 +82,7 @@ Item {
opening = oldMouseY > mouse.y; opening = oldMouseY > mouse.y;
if (root.taskSwitcher.visibility == Window.Hidden && Math.abs(startMouseY - mouse.y) > PlasmaCore.Units.gridUnit && root.taskSwitcher.tasksCount) { if (!root.taskSwitcher.visible && Math.abs(startMouseY - mouse.y) > PlasmaCore.Units.gridUnit && root.taskSwitcher.tasksCount) {
// start task switcher gesture // start task switcher gesture
activeButton = null; activeButton = null;
root.taskSwitcher.show(false); root.taskSwitcher.show(false);

View file

@ -37,4 +37,5 @@ NotificationsWidget 1.0 widgets/NotificationsWidget.qml
# / # /
singleton HomeScreenControls 1.0 HomeScreenControls.qml singleton HomeScreenControls 1.0 HomeScreenControls.qml
singleton TaskPanelControls 1.0 TaskPanelControls.qml
singleton TopPanelControls 1.0 TopPanelControls.qml singleton TopPanelControls 1.0 TopPanelControls.qml

View file

@ -17,6 +17,8 @@ import org.kde.plasma.components 3.0 as PlasmaComponents
Item { Item {
id: delegate id: delegate
required property var taskSwitcher
required property var model required property var model
required property var displaysModel required property var displaysModel
@ -29,12 +31,12 @@ Item {
required property real previewWidth required property real previewWidth
property real scale: 1 property real scale: 1
opacity: 1 - dragOffset / window.height opacity: 1 - dragOffset / taskSwitcher.height
//BEGIN functions //BEGIN functions
function syncDelegateGeometry() { function syncDelegateGeometry() {
let pos = pipeWireLoader.mapToItem(tasksView, 0, 0); let pos = pipeWireLoader.mapToItem(tasksView, 0, 0);
if (window.visible) { if (taskSwitcher.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);
} }
} }
@ -44,14 +46,14 @@ Item {
} }
function activateApp() { function activateApp() {
window.activateWindow(model.index); taskSwitcher.activateWindow(model.index);
} }
//END functions //END functions
Component.onCompleted: syncDelegateGeometry(); Component.onCompleted: syncDelegateGeometry();
Connections { Connections {
target: window target: taskSwitcher
function onVisibleChanged() { function onVisibleChanged() {
syncDelegateGeometry(); syncDelegateGeometry();
} }
@ -78,7 +80,7 @@ Item {
yAnimator.stop(); yAnimator.stop();
if (parent.y < -PlasmaCore.Units.gridUnit * 2) { if (parent.y < -PlasmaCore.Units.gridUnit * 2) {
yAnimator.to = -window.height; yAnimator.to = -root.height;
} else { } else {
yAnimator.to = 0; yAnimator.to = 0;
} }

View file

@ -15,32 +15,31 @@ import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.plasma.private.nanoshell 2.0 as NanoShell import org.kde.plasma.private.nanoshell 2.0 as NanoShell
import org.kde.plasma.private.mobileshell 1.0 as MobileShell import org.kde.plasma.private.mobileshell 1.0 as MobileShell
NanoShell.FullScreenOverlay { Item {
id: window id: root
visible: false visible: false
width: Screen.width
height: Screen.height
required property real taskPanelHeight // height of task panel, provided by main.qml readonly property real taskPanelHeight: MobileShell.TaskPanelControls.panelHeight
readonly property real taskPanelWidth: MobileShell.TaskPanelControls.panelWidth
readonly property bool isPortrait: MobileShell.TaskPanelControls.isPortrait
// dimensions of a window on the screen // dimensions of a window on the screen
readonly property real windowHeight: window.height - (navPanel.isPortrait ? window.taskPanelHeight : 0) - MobileShell.TopPanelControls.panelHeight readonly property real windowHeight: root.height - (root.isPortrait ? root.taskPanelHeight : 0) - MobileShell.TopPanelControls.panelHeight
readonly property real windowWidth: window.width - (navPanel.isPortrait ? 0 : window.taskPanelHeight) readonly property real windowWidth: root.width - (root.isPortrait ? 0 : root.taskPanelWidth)
property int tasksCount: window.model.count readonly property int tasksCount: root.model.count
property int currentTaskIndex: tasksView.currentIndex readonly property int currentTaskIndex: tasksView.currentIndex
property TaskManager.TasksModel model property TaskManager.TasksModel model
// properties controlled from main.qml MouseArea (swipe to open gesture) // offset constants
readonly property real targetYOffsetDist: root.height - tasksView.height // offset distance to perfect opening
readonly property real dismissYOffsetDist: root.height
// properties controlled from NavigationPanel (swipe to open gesture)
property real oldYOffset: 0 property real oldYOffset: 0
property real yOffset: 0 property real yOffset: 0
// offset constants // set from NavigationPanel in taskpanel containment
readonly property real targetYOffsetDist: window.height - tasksView.height // offset distance to perfect opening
readonly property real dismissYOffsetDist: window.height
// set from NavigationPanel in main.qml
property bool wasInActiveTask: false // whether we were in an app before opening the task switcher property bool wasInActiveTask: false // whether we were in an app before opening the task switcher
property bool currentlyDragging: false // whether we are in a swipe up gesture property bool currentlyDragging: false // whether we are in a swipe up gesture
@ -52,18 +51,7 @@ NanoShell.FullScreenOverlay {
Right Right
} }
onVisibleChanged: { onVisibleChanged: MobileShell.HomeScreenControls.taskSwitcherVisible = visible;
if (!visible) {
window.contentItem.opacity = 1;
}
// hide homescreen elements to make use of wallpaper
if (visible) {
MobileShell.HomeScreenControls.hideHomeScreen(!window.wasInActiveTask); // only animate if going from homescreen
} else {
MobileShell.HomeScreenControls.showHomeScreen(true);
}
MobileShell.HomeScreenControls.taskSwitcherVisible = visible;
}
onTasksCountChanged: { onTasksCountChanged: {
if (tasksCount == 0) { if (tasksCount == 0) {
@ -71,52 +59,51 @@ NanoShell.FullScreenOverlay {
} }
} }
// background
color: "transparent"
Rectangle { Rectangle {
id: backgroundRect id: backgroundRect
anchors.fill: parent anchors.fill: parent
color: Qt.rgba(0, 0, 0, 0.6 * (window.wasInActiveTask ? 1 : Math.min(1, window.yOffset / window.targetYOffsetDist))) color: Qt.rgba(0, 0, 0, 0.6 * (root.wasInActiveTask ? 1 : Math.min(1, root.yOffset / root.targetYOffsetDist)))
MouseArea { MouseArea {
anchors.fill: parent anchors.fill: parent
onClicked: hide() onClicked: root.hide()
} }
} }
//BEGIN functions //BEGIN functions
function show(animation) { function show(animation) {
window.yOffset = 0; root.yOffset = 0;
window.wasInActiveTask = window.model.activeTask.row >= 0; root.wasInActiveTask = root.model.activeTask.row >= 0;
// skip to first active task // skip to first active task
if (window.wasInActiveTask) { if (root.wasInActiveTask) {
tasksView.currentIndex = window.model.activeTask.row; tasksView.currentIndex = root.model.activeTask.row;
tasksView.positionViewAtIndex(window.model.activeTask.row, ListView.SnapPosition); tasksView.positionViewAtIndex(root.model.activeTask.row, ListView.SnapPosition);
} }
window.visible = true; root.visible = true;
root.minimizeAll(); minimizeAll();
// animate app shrink // animate app shrink
if (animation) { if (animation) {
offsetAnimator.to = window.targetYOffsetDist; offsetAnimator.to = root.targetYOffsetDist;
offsetAnimator.restart(); offsetAnimator.restart();
} }
} }
function hide() { function hide() {
if (!window.visible) return; if (!root.visible) return;
window.visible = false; root.visible = false;
} }
function snapOffset() { function snapOffset() {
let movingUp = window.yOffset > window.oldYOffset; let movingUp = root.yOffset > root.oldYOffset;
if (movingUp || window.yOffset >= window.targetYOffsetDist) { // open task switcher and stay if (movingUp || root.yOffset >= root.targetYOffsetDist) { // open task switcher and stay
offsetAnimator.to = window.targetYOffsetDist; offsetAnimator.to = root.targetYOffsetDist;
offsetAnimator.restart(); offsetAnimator.restart();
} else { // close task switcher and return to app } else { // close task switcher and return to app
if (!window.wasInActiveTask) { // if pulled up from homescreen, don't activate app if (!root.wasInActiveTask) { // if pulled up from homescreen, don't activate app
offsetAnimator.activateApp = false; offsetAnimator.activateApp = false;
} }
offsetAnimator.to = 0; offsetAnimator.to = 0;
@ -135,12 +122,12 @@ NanoShell.FullScreenOverlay {
return; return;
} }
var newActiveIdx = window.model.index(id, 0) var newActiveIdx = root.model.index(id, 0)
var newActiveGeo = tasksModel.data(newActiveIdx, TaskManager.AbstractTasksModel.ScreenGeometry) var newActiveGeo = tasksModel.data(newActiveIdx, TaskManager.AbstractTasksModel.ScreenGeometry)
for (var i = 0 ; i < tasksModel.count; i++) { for (var i = 0 ; i < tasksModel.count; i++) {
var idx = window.model.index(i, 0) var idx = root.model.index(i, 0)
if (i == id) { if (i == id) {
window.model.requestActivate(idx); root.model.requestActivate(idx);
} else if (!tasksModel.data(idx, TaskManager.AbstractTasksModel.IsMinimized)) { } else if (!tasksModel.data(idx, TaskManager.AbstractTasksModel.IsMinimized)) {
var geo = tasksModel.data(idx, TaskManager.AbstractTasksModel.ScreenGeometry) var geo = tasksModel.data(idx, TaskManager.AbstractTasksModel.ScreenGeometry)
// Only minimize the other windows in the same screen // Only minimize the other windows in the same screen
@ -150,8 +137,27 @@ NanoShell.FullScreenOverlay {
} }
} }
window.visible = false; root.visible = false;
} }
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);
}
}
}
function restoreAll() {
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 //END functions
// animate app grow and shrink // animate app grow and shrink
@ -164,19 +170,19 @@ NanoShell.FullScreenOverlay {
// states of to: // states of to:
// 0 - open/resume app (zoom up the thumbnail) // 0 - open/resume app (zoom up the thumbnail)
// window.targetYOffsetDist - animate shrinking of thumbnail, to listview (open task switcher) // root.targetYOffsetDist - animate shrinking of thumbnail, to listview (open task switcher)
to: 0 to: 0
onFinished: { onFinished: {
if (to === 0) { // close task switcher, and switch to current app if (to === 0) { // close task switcher, and switch to current app
if (!window.visible) return; if (!root.visible) return;
window.visible = false; root.visible = false;
if (activateApp) { if (activateApp) {
setSingleActiveWindow(window.currentTaskIndex); setSingleActiveWindow(root.currentTaskIndex);
} }
activateApp = true; activateApp = true;
} else if (to == window.dismissYOffsetDist) { } else if (to == root.dismissYOffsetDist) {
window.hide(); root.hide();
} }
} }
} }
@ -186,23 +192,23 @@ NanoShell.FullScreenOverlay {
// provide shell margins // provide shell margins
anchors.fill: parent anchors.fill: parent
anchors.rightMargin: navPanel.isPortrait ? 0 : window.taskPanelHeight anchors.rightMargin: root.isPortrait ? 0 : root.taskPanelWidth
anchors.bottomMargin: navPanel.isPortrait ? window.taskPanelHeight : 0 anchors.bottomMargin: root.isPortrait ? root.taskPanelHeight : 0
anchors.topMargin: MobileShell.TopPanelControls.panelHeight anchors.topMargin: MobileShell.TopPanelControls.panelHeight
// applications list // applications list
ListView { ListView {
id: tasksView id: tasksView
opacity: window.wasInActiveTask ? 1 : Math.min(1, window.yOffset / window.targetYOffsetDist) opacity: root.wasInActiveTask ? 1 : Math.min(1, root.yOffset / root.targetYOffsetDist)
anchors.centerIn: parent anchors.centerIn: parent
readonly property real sizeFactor: 0.75 readonly property real sizeFactor: 0.75
readonly property real taskHeaderHeight: PlasmaCore.Units.gridUnit * 2 + PlasmaCore.Units.smallSpacing * 2 readonly property real taskHeaderHeight: PlasmaCore.Units.gridUnit * 2 + PlasmaCore.Units.smallSpacing * 2
width: window.windowWidth * sizeFactor width: root.windowWidth * sizeFactor
height: window.windowHeight * sizeFactor + taskHeaderHeight height: root.windowHeight * sizeFactor + taskHeaderHeight
model: window.model model: root.model
orientation: ListView.Horizontal orientation: ListView.Horizontal
highlightRangeMode: ListView.StrictlyEnforceRange // ensures currentIndex is updated highlightRangeMode: ListView.StrictlyEnforceRange // ensures currentIndex is updated
@ -217,22 +223,23 @@ NanoShell.FullScreenOverlay {
// ensure that window previews are exactly to the scale of the device screen // ensure that window previews are exactly to the scale of the device screen
property real scalingFactor: { property real scalingFactor: {
let candidateHeight = (tasksView.width / window.windowWidth) * window.windowHeight; let candidateHeight = (tasksView.width / root.windowWidth) * root.windowHeight;
if (candidateHeight > tasksView.height) { if (candidateHeight > tasksView.height) {
return tasksView.height / window.windowHeight; return tasksView.height / root.windowHeight;
} else { } else {
return tasksView.width / window.windowWidth; return tasksView.width / root.windowWidth;
} }
} }
delegate: Task { delegate: Task {
id: task id: task
property int curIndex: model.index property int curIndex: model.index
z: window.currentTaskIndex === curIndex ? 1 : 0 z: root.currentTaskIndex === curIndex ? 1 : 0
width: tasksView.width width: tasksView.width
height: tasksView.height height: tasksView.height
displaysModel: window.displaysModel taskSwitcher: root
displaysModel: root.displaysModel
// account for header offset (center the preview) // account for header offset (center the preview)
y: -tasksView.taskHeaderHeight / 2 y: -tasksView.taskHeaderHeight / 2
@ -240,18 +247,18 @@ NanoShell.FullScreenOverlay {
// scale gesture // scale gesture
scale: { scale: {
let maxScale = 1 / tasksView.scalingFactor; let maxScale = 1 / tasksView.scalingFactor;
let subtract = (maxScale - 1) * (window.yOffset / window.targetYOffsetDist); let subtract = (maxScale - 1) * (root.yOffset / root.targetYOffsetDist);
let finalScale = Math.max(0, Math.min(maxScale, maxScale - subtract)); let finalScale = Math.max(0, Math.min(maxScale, maxScale - subtract));
if ((window.wasInActiveTask || !taskSwitcher.currentlyDragging) && window.currentTaskIndex === task.curIndex) { if ((root.wasInActiveTask || !taskSwitcher.currentlyDragging) && root.currentTaskIndex === task.curIndex) {
return finalScale; return finalScale;
} }
return 1; return 1;
} }
// ensure that window previews are exactly to the scale of the device screen // ensure that window previews are exactly to the scale of the device screen
previewWidth: tasksView.scalingFactor * window.windowWidth previewWidth: tasksView.scalingFactor * root.windowWidth
previewHeight: tasksView.scalingFactor * window.windowHeight previewHeight: tasksView.scalingFactor * root.windowHeight
} }
} }
} }
@ -274,57 +281,4 @@ NanoShell.FullScreenOverlay {
} }
onReleased: MobileShell.TopPanelControls.endSwipe(); onReleased: MobileShell.TopPanelControls.endSwipe();
} }
// task panel
MobileShell.NavigationPanel {
id: navPanel
property bool isPortrait: Screen.width <= Screen.height
width: isPortrait ? implicitWidth : window.taskPanelHeight
height: isPortrait ? window.taskPanelHeight : implicitWidth
anchors.left: isPortrait ? parent.left : undefined
anchors.right: parent.right
anchors.top: isPortrait ? undefined: parent.top
anchors.bottom: parent.bottom
taskSwitcher: window
backgroundColor: window.visible ? Qt.rgba(0, 0, 0, 0.1) : "transparent"
foregroundColorGroup: PlasmaCore.Theme.ComplementaryColorGroup
dragGestureEnabled: false
Behavior on backgroundColor { ColorAnimation {} }
leftAction: MobileShell.NavigationPanelAction {
enabled: true
iconSource: "mobile-task-switcher"
iconSizeFactor: 0.75
onTriggered: {
if (window.wasInActiveTask) {
window.activateWindow(window.currentTaskIndex);
} else {
window.hide();
}
}
}
middleAction: MobileShell.NavigationPanelAction {
enabled: true
iconSource: "start-here-kde"
iconSizeFactor: 1
onTriggered: {
window.hide();
root.triggerHomescreen();
}
}
rightAction: MobileShell.NavigationPanelAction {
enabled: true
iconSource: "mobile-close-app"
iconSizeFactor: 0.75
onTriggered: {
tasksModel.requestClose(tasksModel.index(window.currentTaskIndex, 0));
}
}
}
} }

View file

@ -16,7 +16,9 @@ TaskManager.PipeWireSourceItem {
onVisibleChanged: { onVisibleChanged: {
if (visible && waylandItem.uuid.length === 0) { if (visible && waylandItem.uuid.length === 0) {
waylandItem.uuid = model.WinIdList[0] if (model.WinIdList) {
waylandItem.uuid = model.WinIdList[0];
}
} }
} }

View file

@ -29,6 +29,7 @@ Item {
readonly property real headerHeight: Math.round(PlasmaCore.Units.gridUnit * 3) readonly property real headerHeight: Math.round(PlasmaCore.Units.gridUnit * 3)
//BEGIN functions //BEGIN functions
function activate() { function activate() {
// there's a couple of steps: // there's a couple of steps:
// - minimize windows // - minimize windows
@ -44,6 +45,7 @@ Item {
root.appDrawer.close() root.appDrawer.close()
} }
} }
//END functions //END functions
HomeScreenComponents.FlickablePages { HomeScreenComponents.FlickablePages {

View file

@ -9,6 +9,7 @@ import QtQuick 2.15
import QtQuick.Window 2.15 import QtQuick.Window 2.15
import QtQuick.Layouts 1.1 import QtQuick.Layouts 1.1
import org.kde.taskmanager 0.1 as TaskManager
import org.kde.plasma.plasmoid 2.0 import org.kde.plasma.plasmoid 2.0
import org.kde.plasma.core 2.0 as PlasmaCore import org.kde.plasma.core 2.0 as PlasmaCore
import org.kde.plasma.components 3.0 as PlasmaComponents import org.kde.plasma.components 3.0 as PlasmaComponents
@ -30,6 +31,12 @@ FocusScope {
HomeScreenComponents.ApplicationListModel.maxFavoriteCount = Math.max(4, Math.floor(Math.min(width, height) / homescreen.homeScreenContents.appletsLayout.cellWidth)); HomeScreenComponents.ApplicationListModel.maxFavoriteCount = Math.max(4, Math.floor(Math.min(width, height) / homescreen.homeScreenContents.appletsLayout.cellWidth));
} }
function triggerHomeScreen() {
taskSwitcher.minimizeAll();
MobileShell.HomeScreenControls.resetHomeScreenPosition();
taskSwitcher.visible = false; // will trigger homescreen open
}
//END functions //END functions
//BEGIN API implementation //BEGIN API implementation
@ -38,6 +45,10 @@ FocusScope {
property real lastRequestedPosition: 0 property real lastRequestedPosition: 0
function onOpenHomeScreen() {
root.triggerHomeScreen();
}
function onResetHomeScreenPosition() { function onResetHomeScreenPosition() {
homescreen.flickablePages.scrollToPage(0); homescreen.flickablePages.scrollToPage(0);
homescreen.appDrawer.close(); homescreen.appDrawer.close();
@ -55,35 +66,17 @@ FocusScope {
homescreen.appDrawer.offset -= pos.y; homescreen.appDrawer.offset -= pos.y;
lastRequestedPosition = pos.y; lastRequestedPosition = pos.y;
} }
function onHideHomeScreen(animate) {
if (animate) {
opacityAnimation.to = 0;
opacityAnimation.restart();
} else {
homescreen.opacity = 0;
}
}
function onShowHomeScreen(animate) {
if (animate) {
opacityAnimation.to = 1;
opacityAnimation.restart();
} else {
homescreen.opacity = 1;
}
}
} }
Plasmoid.onScreenChanged: { Plasmoid.onScreenChanged: {
if (plasmoid.screen == 0) { if (plasmoid.screen == 0) {
MobileShell.HomeScreenControls.homeScreen = root MobileShell.HomeScreenControls.taskSwitcher = taskSwitcher;
MobileShell.HomeScreenControls.homeScreenWindow = root.Window.window MobileShell.HomeScreenControls.homeScreenWindow = root.Window.window;
} }
} }
Window.onWindowChanged: { Window.onWindowChanged: {
if (plasmoid.screen == 0) { if (plasmoid.screen == 0) {
MobileShell.HomeScreenControls.homeScreenWindow = root.Window.window MobileShell.HomeScreenControls.homeScreenWindow = root.Window.window;
} }
} }
@ -101,7 +94,7 @@ FocusScope {
// set API variables // set API variables
if (plasmoid.screen == 0) { if (plasmoid.screen == 0) {
MobileShell.HomeScreenControls.homeScreen = root; MobileShell.HomeScreenControls.taskSwitcher = taskSwitcher;
MobileShell.HomeScreenControls.homeScreenWindow = root.Window.window; MobileShell.HomeScreenControls.homeScreenWindow = root.Window.window;
} }
componentComplete = true; componentComplete = true;
@ -116,6 +109,7 @@ FocusScope {
homescreen.activate(); homescreen.activate();
} }
// homescreen component
HomeScreen { HomeScreen {
id: homescreen id: homescreen
anchors.fill: parent anchors.fill: parent
@ -126,5 +120,49 @@ FocusScope {
duration: PlasmaCore.Units.longDuration duration: PlasmaCore.Units.longDuration
} }
} }
// task switcher component
TaskManager.TasksModel {
id: tasksModel
groupMode: TaskManager.TasksModel.GroupDisabled
screenGeometry: plasmoid.screenGeometry
sortMode: TaskManager.TasksModel.SortAlpha
virtualDesktop: virtualDesktopInfo.currentDesktop
activity: activityInfo.currentActivity
}
TaskManager.VirtualDesktopInfo {
id: virtualDesktopInfo
}
TaskManager.ActivityInfo {
id: activityInfo
}
MobileShell.TaskSwitcher {
id: taskSwitcher
model: tasksModel
anchors.fill: parent
// hide homescreen elements to make use of wallpaper
onVisibleChanged: {
if (visible) {
// only animate if going from homescreen
if (taskSwitcher.wasInActiveTask) {
opacityAnimation.to = 0;
opacityAnimation.restart();
} else {
homescreen.opacity = 0;
}
} else {
opacityAnimation.to = 1;
opacityAnimation.restart();
}
}
}
} }

View file

@ -30,34 +30,27 @@ PlasmaCore.ColorScope {
readonly property bool hasTasks: tasksModel.count > 0 readonly property bool hasTasks: tasksModel.count > 0
property QtObject taskSwitcher: taskSwitcherLoader.item ? taskSwitcherLoader.item : null property var taskSwitcher: MobileShell.HomeScreenControls.taskSwitcher
//BEGIN functions //BEGIN API implementation
function minimizeAll() {
for (var i = 0 ; i < tasksModel.count; i++) { Binding {
var idx = tasksModel.makeModelIndex(i); target: MobileShell.TaskPanelControls
if (!tasksModel.data(idx, TaskManager.AbstractTasksModel.IsMinimized)) { property: "isPortrait"
tasksModel.requestToggleMinimized(idx); value: Screen.width <= Screen.height
} }
Binding {
target: MobileShell.TaskPanelControls
property: "panelHeight"
value: root.height
} }
Binding {
target: MobileShell.TaskPanelControls
property: "panelWidth"
value: root.width
} }
function restoreAll() { //END API implementation
for (var i = 0 ; i < tasksModel.count; i++) {
var idx = tasksModel.makeModelIndex(i);
if (tasksModel.data(idx, TaskManager.AbstractTasksModel.IsMinimized)) {
tasksModel.requestToggleMinimized(idx);
}
}
}
function triggerHomescreen() {
root.minimizeAll();
MobileShell.HomeScreenControls.resetHomeScreenPosition();
MobileShell.HomeScreenControls.showHomeScreen(true);
plasmoid.nativeInterface.allMinimizedChanged();
}
//END functions
Connections { Connections {
target: plasmoid.nativeInterface target: plasmoid.nativeInterface
@ -94,35 +87,44 @@ PlasmaCore.ColorScope {
}); });
} }
// task switcher
Loader {
id: taskSwitcherLoader
sourceComponent: MobileShell.TaskSwitcher {
model: tasksModel
taskPanelHeight: root.state === "portrait" ? root.height : root.width
}
}
// bottom navigation panel // bottom navigation panel
MobileShell.NavigationPanel { MobileShell.NavigationPanel {
id: panel id: panel
anchors.fill: parent anchors.fill: parent
opacity: (root.taskSwitcher && root.taskSwitcher.visible) ? 0 : 1 // hide bar when task switcher is open
backgroundColor: root.showingApp ? root.backgroundColor : "transparent"
foregroundColorGroup: root.showingApp ? PlasmaCore.Theme.NormalColorGroup : PlasmaCore.Theme.ComplementaryColorGroup
dragGestureEnabled: true
taskSwitcher: root.taskSwitcher taskSwitcher: root.taskSwitcher
backgroundColor: {
if (taskSwitcher.visible) {
return Qt.rgba(0, 0, 0, 0.1);
} else {
return root.showingApp ? root.backgroundColor : "transparent";
}
}
foregroundColorGroup: (!taskSwitcher.visible && root.showingApp) ? PlasmaCore.Theme.NormalColorGroup : PlasmaCore.Theme.ComplementaryColorGroup
// do not enable drag gesture when task switcher is already open
// also don't disable drag gesture mid-drag
dragGestureEnabled: !taskSwitcher.visible || taskSwitcher.currentlyDragging
leftAction: MobileShell.NavigationPanelAction { leftAction: MobileShell.NavigationPanelAction {
enabled: hasTasks enabled: hasTasks || taskSwitcher.visible
iconSource: "mobile-task-switcher" iconSource: "mobile-task-switcher"
iconSizeFactor: 0.75 iconSizeFactor: 0.75
onTriggered: { onTriggered: {
plasmoid.nativeInterface.showDesktop = false; plasmoid.nativeInterface.showDesktop = false;
taskSwitcher.visible ? taskSwitcher.hide() : taskSwitcher.show(true);
if (!taskSwitcher.visible) {
taskSwitcher.show(true);
} else {
// when task switcher is open
if (taskSwitcher.wasInActiveTask) {
// restore active window
taskSwitcher.activateWindow(root.currentTaskIndex);
} else {
taskSwitcher.hide();
}
}
} }
} }
@ -130,19 +132,30 @@ PlasmaCore.ColorScope {
enabled: true enabled: true
iconSource: "start-here-kde" iconSource: "start-here-kde"
iconSizeFactor: 1 iconSizeFactor: 1
onTriggered: root.triggerHomescreen() onTriggered: {
MobileShell.HomeScreenControls.openHomeScreen();
plasmoid.nativeInterface.allMinimizedChanged();
}
} }
rightAction: MobileShell.NavigationPanelAction { rightAction: MobileShell.NavigationPanelAction {
enabled: MobileShell.KWinVirtualKeyboard.visible || (plasmoid.nativeInterface.hasCloseableActiveWindow && !taskSwitcher.visible) enabled: MobileShell.KWinVirtualKeyboard.visible || taskSwitcher.visible || plasmoid.nativeInterface.hasCloseableActiveWindow
// mobile-close-app (from plasma-frameworks) seems to have less margins than icons from breeze-icons // mobile-close-app (from plasma-frameworks) seems to have less margins than icons from breeze-icons
iconSizeFactor: MobileShell.KWinVirtualKeyboard.visible ? 1 : 0.75 iconSizeFactor: MobileShell.KWinVirtualKeyboard.visible ? 1 : 0.75
iconSource: MobileShell.KWinVirtualKeyboard.visible ? "go-down-symbolic" : "mobile-close-app" iconSource: MobileShell.KWinVirtualKeyboard.visible ? "go-down-symbolic" : "mobile-close-app"
onTriggered: { onTriggered: {
if (MobileShell.KWinVirtualKeyboard.active) { if (MobileShell.KWinVirtualKeyboard.active) {
// close keyboard if it is open
MobileShell.KWinVirtualKeyboard.active = false; MobileShell.KWinVirtualKeyboard.active = false;
} else if (taskSwitcher.visible) {
// if task switcher is open, close the current window shown
taskSwitcher.model.requestClose(taskSwitcher.model.index(taskSwitcher.currentTaskIndex, 0));
} else if (plasmoid.nativeInterface.hasCloseableActiveWindow) { } else if (plasmoid.nativeInterface.hasCloseableActiveWindow) {
// if task switcher is closed, but there is an active window
var index = taskSwitcher.model.activeTask; var index = taskSwitcher.model.activeTask;
if (index) { if (index) {
taskSwitcher.model.requestClose(index); taskSwitcher.model.requestClose(index);