diff --git a/components/mobileshell/qml/navigationpanel/NavigationPanel.qml b/components/mobileshell/qml/navigationpanel/NavigationPanel.qml index fcac9bbe..242a58d8 100644 --- a/components/mobileshell/qml/navigationpanel/NavigationPanel.qml +++ b/components/mobileshell/qml/navigationpanel/NavigationPanel.qml @@ -9,6 +9,7 @@ import QtQuick import QtQuick.Layouts import QtQuick.Window import QtQuick.Effects +import QtQuick.Controls as Controls import org.kde.kirigami as Kirigami import org.kde.taskmanager 0.1 as TaskManager @@ -34,6 +35,10 @@ Item { property bool isVertical: false + // Convergence mode: show running-app task strip + property bool convergenceMode: false + property var taskModel: null + // drop shadow for icons MultiEffect { anchors.fill: icons @@ -133,6 +138,63 @@ Item { } } } + + // Running-app task strip for convergence (desktop) mode + ListView { + id: taskStrip + visible: root.convergenceMode && root.taskModel !== null && root.taskModel.count > 0 + orientation: root.isVertical ? ListView.Vertical : ListView.Horizontal + spacing: Kirigami.Units.smallSpacing + clip: true + interactive: contentWidth > width + model: root.taskModel + + delegate: NavigationPanelButton { + id: taskDelegate + required property int index + required property var model + width: taskStrip.orientation === ListView.Horizontal ? height : taskStrip.width + height: taskStrip.orientation === ListView.Horizontal ? taskStrip.height : taskStrip.width + + Kirigami.Theme.colorSet: root.foregroundColorGroup + Kirigami.Theme.inherit: false + iconSource: taskDelegate.model.decoration + enabled: true + shrinkSize: 0 + + onClicked: { + root.taskModel.requestActivate(root.taskModel.makeModelIndex(taskDelegate.index)); + } + + // Right-click context menu + MouseArea { + anchors.fill: parent + acceptedButtons: Qt.RightButton + onClicked: taskContextMenu.popup() + } + + Controls.Menu { + id: taskContextMenu + Controls.MenuItem { + text: i18n("Close") + icon.name: "window-close" + onTriggered: root.taskModel.requestClose(root.taskModel.makeModelIndex(taskDelegate.index)) + } + } + + // Active-window indicator dot + Rectangle { + anchors.bottom: parent.bottom + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottomMargin: Kirigami.Units.smallSpacing / 2 + width: Kirigami.Units.smallSpacing * 2 + height: width + radius: width / 2 + color: Kirigami.Theme.highlightColor + visible: taskDelegate.model.IsActive === true + } + } + } } states: [ @@ -200,6 +262,21 @@ Item { height: Kirigami.Units.gridUnit * 2 width: icons.width } + // Task strip: vertical layout — positioned between leftCornerButton (bottom) and leftButton (above middle) + AnchorChanges { + target: taskStrip + anchors { + horizontalCenter: parent.horizontalCenter + bottom: leftButton.top + top: undefined + } + } + PropertyChanges { + target: taskStrip + width: parent.width + // Fill space between leftCorner (bottom) and the nav button group + height: taskStrip.visible ? (leftButton.y - leftCornerButton.y - leftCornerButton.height - Kirigami.Units.smallSpacing * 2) : 0 + } }, State { name: "horizontal" when: !root.isVertical @@ -264,6 +341,19 @@ Item { height: parent.height width: Kirigami.Units.gridUnit * 2 } + // Task strip: horizontal layout — positioned between leftCornerButton (left) and leftButton (near center) + AnchorChanges { + target: taskStrip + anchors { + verticalCenter: parent.verticalCenter + left: leftCornerButton.right + right: leftButton.left + } + } + PropertyChanges { + target: taskStrip + height: parent.height + } } ] } diff --git a/containments/taskpanel/qml/NavigationPanelComponent.qml b/containments/taskpanel/qml/NavigationPanelComponent.qml index 76346045..6ec5e6fd 100644 --- a/containments/taskpanel/qml/NavigationPanelComponent.qml +++ b/containments/taskpanel/qml/NavigationPanelComponent.qml @@ -35,6 +35,10 @@ MobileShell.NavigationPanel { foregroundColorGroup: forcedComplementary ? Kirigami.Theme.Complementary : Kirigami.Theme.Window shadow: forcedComplementary + // Convergence mode: expose running-app task strip + convergenceMode: ShellSettings.Settings.convergenceModeEnabled + taskModel: tasksModel + MobileShellState.PanelSettingsDBusClient { id: panelSettings screenName: Screen.name @@ -68,16 +72,20 @@ MobileShell.NavigationPanel { // ~~~~ // navigation panel actions - // toggle task switcher button + // toggle task switcher button (KWin Overview in convergence mode, mobile task switcher otherwise) leftAction: MobileShell.NavigationPanelAction { id: taskSwitcherAction enabled: true - iconSource: "mobile-task-switcher" - shrinkSize: 4 + iconSource: ShellSettings.Settings.convergenceModeEnabled ? "view-grid-symbolic" : "mobile-task-switcher" + shrinkSize: ShellSettings.Settings.convergenceModeEnabled ? 0 : 4 onTriggered: { - Plasmoid.triggerTaskSwitcher(); + if (ShellSettings.Settings.convergenceModeEnabled) { + Plasmoid.triggerOverview(); + } else { + Plasmoid.triggerTaskSwitcher(); + } } } diff --git a/containments/taskpanel/taskpanel.cpp b/containments/taskpanel/taskpanel.cpp index 385a4e3a..fd17e650 100644 --- a/containments/taskpanel/taskpanel.cpp +++ b/containments/taskpanel/taskpanel.cpp @@ -31,4 +31,11 @@ void TaskPanel::triggerTaskSwitcher() const QDBusConnection::sessionBus().send(message); } +void TaskPanel::triggerOverview() const +{ + QDBusMessage message = QDBusMessage::createMethodCall("org.kde.kglobalaccel", "/component/kwin", "org.kde.kglobalaccel.Component", "invokeShortcut"); + message.setArguments({QStringLiteral("Overview")}); + QDBusConnection::sessionBus().send(message); +} + #include "taskpanel.moc" diff --git a/containments/taskpanel/taskpanel.h b/containments/taskpanel/taskpanel.h index 6bf4552a..da764c54 100644 --- a/containments/taskpanel/taskpanel.h +++ b/containments/taskpanel/taskpanel.h @@ -15,4 +15,5 @@ class TaskPanel : public Plasma::Containment public: TaskPanel(QObject *parent, const KPluginMetaData &data, const QVariantList &args); Q_INVOKABLE void triggerTaskSwitcher() const; + Q_INVOKABLE void triggerOverview() const; }; diff --git a/envmanager/config.h b/envmanager/config.h index c2c967dd..9db358cf 100644 --- a/envmanager/config.h +++ b/envmanager/config.h @@ -56,6 +56,7 @@ QMap> getKwinrcSettings(KSharedConfig::Ptr m_mo {"blurEnabled", false}, // disable blur for performance reasons, we could reconsider in the future for more powerful devices {"convergentwindowsEnabled", true}, // enable our convergent window plugin {"mobiletaskswitcherEnabled", true}, // ensure the mobile task switcher plugin is enabled + {"overviewEnabled", convergenceModeEnabled}, // enable KWin Overview effect in convergence mode for desktop-style task switching {"screenedgeEnabled", false} // disable the blue highlighting of screen edge effects. TODO would be nice if we could only deactivate it on // touchscreen gestures and not mouse as well }}, @@ -76,7 +77,7 @@ QMap> getKwinrcSettings(KSharedConfig::Ptr m_mo // Have a separate list here because we need to trigger DBus calls to load/unload each effect/script. // Make sure that the effect/script is added to the kwinrc "Plugins" section above! -const QList KWIN_EFFECTS = {"blur", "mobiletaskswitcher", "screenedge"}; +const QList KWIN_EFFECTS = {"blur", "mobiletaskswitcher", "overview", "screenedge"}; const QList KWIN_SCRIPTS = {"convergentwindows"}; // .config/plasma-mobile/ksmserver - immutable settings: