From c2b864d8b487d939557c8a0f142d6fcc8b95ab87 Mon Sep 17 00:00:00 2001 From: Marco Allegretti Date: Thu, 16 Apr 2026 17:25:37 +0200 Subject: [PATCH] Show action drawer as bounded panel in convergence Replace the full-screen slide-down sheet with two fade-in cards anchored to the top corners. Quick settings sit top-right, notifications top-left capped at 60% screen height. Background scrim reduced to 30%. Redundant clock header and status bar hidden since both are already visible in the top panel. --- .../actiondrawer/private/ContentContainer.qml | 25 ++++++++++++++----- .../private/LandscapeContentContainer.qml | 8 ++++-- .../private/NotificationDrawer.qml | 18 +++++++++++-- .../private/QuickSettingsPanel.qml | 6 +++-- screenshots/SHIFT-app_drawer.png.license | 2 +- screenshots/SHIFT-dock-pin.png.license | 2 +- screenshots/SHIFT-touch.png.license | 2 +- screenshots/quick_DesktopDemo.webm.license | 2 +- .../quick_DesktopDemo_docked.webm.license | 2 +- .../quick_DesktopDemo_tilling.webm.license | 2 +- 10 files changed, 51 insertions(+), 18 deletions(-) diff --git a/components/mobileshell/qml/actiondrawer/private/ContentContainer.qml b/components/mobileshell/qml/actiondrawer/private/ContentContainer.qml index 52674335..8586f57e 100644 --- a/components/mobileshell/qml/actiondrawer/private/ContentContainer.qml +++ b/components/mobileshell/qml/actiondrawer/private/ContentContainer.qml @@ -11,6 +11,7 @@ import org.kde.plasma.private.mobileshell as MobileShell import org.kde.plasma.components 3.0 as PC3 import org.kde.kirigami as Kirigami import org.kde.plasma.private.mobileshell.quicksettingsplugin as QS +import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings /** * Root element that contains all the ActionDrawer's contents, and is anchored to the screen. @@ -62,7 +63,10 @@ Item { Kirigami.Theme.backgroundColor.b, 0.9) Behavior on color { ColorAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.OutQuad } } - opacity: Math.max(0, Math.min(brightnessPressedValue, actionDrawer.offset / root.minimizedQuickSettingsOffset)) + opacity: { + let base = Math.max(0, Math.min(brightnessPressedValue, actionDrawer.offset / root.minimizedQuickSettingsOffset)); + return ShellSettings.Settings.convergenceModeEnabled ? base * 0.3 : base; + } } // The base swipe area. @@ -106,8 +110,8 @@ Item { anchors { topMargin: notificationDrawer.height + 1 - leftMargin: actionDrawer.mode == MobileShell.ActionDrawer.Portrait ? 0 : 10 - rightMargin: actionDrawer.mode == MobileShell.ActionDrawer.Portrait ? 0 : notificationDrawer.notificationWidget.anchors.rightMargin + Kirigami.Units.gridUnit - notificationDrawer.anchors.leftMargin + 370 + leftMargin: actionDrawer.mode == MobileShell.ActionDrawer.Portrait ? 0 : (notificationDrawer.isConvergence ? Kirigami.Units.smallSpacing : 10) + rightMargin: actionDrawer.mode == MobileShell.ActionDrawer.Portrait ? 0 : (notificationDrawer.isConvergence ? parent.width * 0.5 : notificationDrawer.notificationWidget.anchors.rightMargin + Kirigami.Units.gridUnit - notificationDrawer.anchors.leftMargin + 370) top: parent.top left: parent.left right: parent.right @@ -160,19 +164,28 @@ Item { NotificationDrawer { id: notificationDrawer + readonly property bool isConvergence: ShellSettings.Settings.convergenceModeEnabled + swipeArea: swipeAreaPortrait actionDrawer: root.actionDrawer mediaControlsWidget: root.mediaControlsWidget contentContainer: root - opacity: Math.max(0, Math.min(root.brightnessPressedValue, actionDrawer.offsetResistance / root.minimizedQuickSettingsOffset)) + opacity: { + let base = Math.max(0, Math.min(root.brightnessPressedValue, actionDrawer.offsetResistance / root.minimizedQuickSettingsOffset)); + return isConvergence ? Math.max(0, Math.min(1, actionDrawer.offset / root.minimizedQuickSettingsOffset)) : base; + } anchors { top: parent.top left: parent.left right: parent.right - rightMargin: root.actionDrawer.mode == MobileShell.ActionDrawer.Portrait ? 0 : 360 - leftMargin: actionDrawer.mode == MobileShell.ActionDrawer.Portrait ? 0 : notificationDrawer.minWidthHeight * 0.06 + topMargin: isConvergence ? Kirigami.Units.smallSpacing : 0 + rightMargin: root.actionDrawer.mode == MobileShell.ActionDrawer.Portrait ? 0 : (isConvergence ? parent.width * 0.5 : 360) + leftMargin: actionDrawer.mode == MobileShell.ActionDrawer.Portrait ? 0 : (isConvergence ? Kirigami.Units.smallSpacing : notificationDrawer.minWidthHeight * 0.06) } + + // In convergence, cap the height so it doesn't stretch full-screen + maximumHeight: isConvergence ? root.height * 0.6 : -1 } // Secondary swipe area for uses in portrait. diff --git a/components/mobileshell/qml/actiondrawer/private/LandscapeContentContainer.qml b/components/mobileshell/qml/actiondrawer/private/LandscapeContentContainer.qml index 1e4e1038..e19c8cbb 100644 --- a/components/mobileshell/qml/actiondrawer/private/LandscapeContentContainer.qml +++ b/components/mobileshell/qml/actiondrawer/private/LandscapeContentContainer.qml @@ -56,10 +56,14 @@ Item { : ShellSettings.Settings.quickSettingsColumns readonly property real intendedWidth: (columnWidth * effectiveColumns) + Kirigami.Units.gridUnit - property real offsetRatio: quickSettingsPanel.height / root.height - anchors.topMargin: Math.min(root.actionDrawer.offsetResistance * offsetRatio - quickSettingsPanel.height, 0) + readonly property bool isConvergence: ShellSettings.Settings.convergenceModeEnabled + property real offsetRatio: (quickSettingsPanel.height + restingTopMargin) / root.height + readonly property real restingTopMargin: isConvergence ? Kirigami.Units.smallSpacing : 0 + anchors.topMargin: isConvergence ? restingTopMargin : Math.min(root.actionDrawer.offsetResistance * offsetRatio - quickSettingsPanel.height, 0) anchors.top: parent.top anchors.right: parent.right + anchors.rightMargin: isConvergence ? Kirigami.Units.smallSpacing : 0 + opacity: isConvergence ? Math.max(0, Math.min(1, root.actionDrawer.offset / root.minimizedQuickSettingsOffset)) : 1 actionDrawer: root.actionDrawer fullScreenHeight: root.height diff --git a/components/mobileshell/qml/actiondrawer/private/NotificationDrawer.qml b/components/mobileshell/qml/actiondrawer/private/NotificationDrawer.qml index 290177f9..cd634944 100644 --- a/components/mobileshell/qml/actiondrawer/private/NotificationDrawer.qml +++ b/components/mobileshell/qml/actiondrawer/private/NotificationDrawer.qml @@ -11,6 +11,7 @@ import QtQuick.Layouts 1.1 import org.kde.plasma.clock import org.kde.plasma.components 3.0 as PlasmaComponents import org.kde.plasma.private.mobileshell as MobileShell +import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings import org.kde.kirigami as Kirigami Item { @@ -24,14 +25,26 @@ Item { property alias notificationWidget: notificationWidget property real contentY: notificationWidget.listView.contentY - property real topPadding: actionDrawer.mode == MobileShell.ActionDrawer.Portrait ? Kirigami.Units.largeSpacing : date.y + date.height + Kirigami.Units.smallSpacing * 6 + property real topPadding: { + if (actionDrawer.mode == MobileShell.ActionDrawer.Portrait) + return Kirigami.Units.largeSpacing; + if (ShellSettings.Settings.convergenceModeEnabled) + return Kirigami.Units.largeSpacing; + return date.y + date.height + Kirigami.Units.smallSpacing * 6; + } property real topMargin: actionDrawer.mode == MobileShell.ActionDrawer.Portrait ? actionDrawer.offsetResistance + 1 : 0 readonly property real minWidthHeight: Math.min(actionDrawer.width, actionDrawer.height) readonly property bool hasNotifications: notificationWidget.hasNotifications readonly property bool listOverflowing: notificationWidget.listView.listOverflowing - height: Math.min(actionDrawer.height - toolButtons.height, notificationWidget.listView.contentHeight + 10 + topMargin) + // External cap for convergence mode; -1 means uncapped. + property real maximumHeight: -1 + + height: { + let h = Math.min(actionDrawer.height - toolButtons.height, notificationWidget.listView.contentHeight + 10 + topMargin); + return maximumHeight > 0 ? Math.min(h, maximumHeight) : h; + } // time source for the time and date whenin landscape mode Clock { @@ -155,6 +168,7 @@ Item { id: landscapeModeHeader anchors.fill: parent visible: actionDrawer.mode != MobileShell.ActionDrawer.Portrait + && !ShellSettings.Settings.convergenceModeEnabled transform: [ Translate { diff --git a/components/mobileshell/qml/actiondrawer/private/QuickSettingsPanel.qml b/components/mobileshell/qml/actiondrawer/private/QuickSettingsPanel.qml index 3861dfba..f6db86e4 100644 --- a/components/mobileshell/qml/actiondrawer/private/QuickSettingsPanel.qml +++ b/components/mobileshell/qml/actiondrawer/private/QuickSettingsPanel.qml @@ -73,9 +73,11 @@ MobileShell.BaseItem { id: statusBarProxy Layout.alignment: Qt.AlignTop Layout.fillWidth: true + // Hide status bar in convergence — already visible in the top panel + visible: !ShellSettings.Settings.convergenceModeEnabled // Align these to double pixels to aid vertical alignment and sharper icon rendering - Layout.preferredHeight: Math.round(Kirigami.Units.gridUnit * 1.5 * ShellSettings.Settings.statusBarScaleFactor / 2) * 2 - Layout.maximumHeight: Math.round(Kirigami.Units.gridUnit * 1.5 * ShellSettings.Settings.statusBarScaleFactor / 2) * 2 + Layout.preferredHeight: visible ? Math.round(Kirigami.Units.gridUnit * 1.5 * ShellSettings.Settings.statusBarScaleFactor / 2) * 2 : 0 + Layout.maximumHeight: visible ? Math.round(Kirigami.Units.gridUnit * 1.5 * ShellSettings.Settings.statusBarScaleFactor / 2) * 2 : 0 Kirigami.Theme.colorSet: Kirigami.Theme.Window Kirigami.Theme.inherit: false diff --git a/screenshots/SHIFT-app_drawer.png.license b/screenshots/SHIFT-app_drawer.png.license index 53922e6b..d31163d3 100644 --- a/screenshots/SHIFT-app_drawer.png.license +++ b/screenshots/SHIFT-app_drawer.png.license @@ -1,2 +1,2 @@ -SPDX-FileCopyrightText: 2025 Marco A. +SPDX-FileCopyrightText: 2026 Marco Allegretti. SPDX-License-Identifier: EUPL-1.2 diff --git a/screenshots/SHIFT-dock-pin.png.license b/screenshots/SHIFT-dock-pin.png.license index 53922e6b..d31163d3 100644 --- a/screenshots/SHIFT-dock-pin.png.license +++ b/screenshots/SHIFT-dock-pin.png.license @@ -1,2 +1,2 @@ -SPDX-FileCopyrightText: 2025 Marco A. +SPDX-FileCopyrightText: 2026 Marco Allegretti. SPDX-License-Identifier: EUPL-1.2 diff --git a/screenshots/SHIFT-touch.png.license b/screenshots/SHIFT-touch.png.license index 53922e6b..d31163d3 100644 --- a/screenshots/SHIFT-touch.png.license +++ b/screenshots/SHIFT-touch.png.license @@ -1,2 +1,2 @@ -SPDX-FileCopyrightText: 2025 Marco A. +SPDX-FileCopyrightText: 2026 Marco Allegretti. SPDX-License-Identifier: EUPL-1.2 diff --git a/screenshots/quick_DesktopDemo.webm.license b/screenshots/quick_DesktopDemo.webm.license index 53922e6b..d31163d3 100644 --- a/screenshots/quick_DesktopDemo.webm.license +++ b/screenshots/quick_DesktopDemo.webm.license @@ -1,2 +1,2 @@ -SPDX-FileCopyrightText: 2025 Marco A. +SPDX-FileCopyrightText: 2026 Marco Allegretti. SPDX-License-Identifier: EUPL-1.2 diff --git a/screenshots/quick_DesktopDemo_docked.webm.license b/screenshots/quick_DesktopDemo_docked.webm.license index 53922e6b..d31163d3 100644 --- a/screenshots/quick_DesktopDemo_docked.webm.license +++ b/screenshots/quick_DesktopDemo_docked.webm.license @@ -1,2 +1,2 @@ -SPDX-FileCopyrightText: 2025 Marco A. +SPDX-FileCopyrightText: 2026 Marco Allegretti. SPDX-License-Identifier: EUPL-1.2 diff --git a/screenshots/quick_DesktopDemo_tilling.webm.license b/screenshots/quick_DesktopDemo_tilling.webm.license index 53922e6b..d31163d3 100644 --- a/screenshots/quick_DesktopDemo_tilling.webm.license +++ b/screenshots/quick_DesktopDemo_tilling.webm.license @@ -1,2 +1,2 @@ -SPDX-FileCopyrightText: 2025 Marco A. +SPDX-FileCopyrightText: 2026 Marco Allegretti. SPDX-License-Identifier: EUPL-1.2