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.
This commit is contained in:
Marco Allegretti 2026-04-16 17:25:37 +02:00
parent d1cd5f09d8
commit c2b864d8b4
10 changed files with 51 additions and 18 deletions

View file

@ -11,6 +11,7 @@ import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.components 3.0 as PC3 import org.kde.plasma.components 3.0 as PC3
import org.kde.kirigami as Kirigami import org.kde.kirigami as Kirigami
import org.kde.plasma.private.mobileshell.quicksettingsplugin as QS 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. * Root element that contains all the ActionDrawer's contents, and is anchored to the screen.
@ -62,7 +63,10 @@ Item {
Kirigami.Theme.backgroundColor.b, Kirigami.Theme.backgroundColor.b,
0.9) 0.9)
Behavior on color { ColorAnimation { duration: Kirigami.Units.longDuration; easing.type: Easing.OutQuad } } 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. // The base swipe area.
@ -106,8 +110,8 @@ Item {
anchors { anchors {
topMargin: notificationDrawer.height + 1 topMargin: notificationDrawer.height + 1
leftMargin: actionDrawer.mode == MobileShell.ActionDrawer.Portrait ? 0 : 10 leftMargin: actionDrawer.mode == MobileShell.ActionDrawer.Portrait ? 0 : (notificationDrawer.isConvergence ? Kirigami.Units.smallSpacing : 10)
rightMargin: actionDrawer.mode == MobileShell.ActionDrawer.Portrait ? 0 : notificationDrawer.notificationWidget.anchors.rightMargin + Kirigami.Units.gridUnit - notificationDrawer.anchors.leftMargin + 370 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 top: parent.top
left: parent.left left: parent.left
right: parent.right right: parent.right
@ -160,19 +164,28 @@ Item {
NotificationDrawer { NotificationDrawer {
id: notificationDrawer id: notificationDrawer
readonly property bool isConvergence: ShellSettings.Settings.convergenceModeEnabled
swipeArea: swipeAreaPortrait swipeArea: swipeAreaPortrait
actionDrawer: root.actionDrawer actionDrawer: root.actionDrawer
mediaControlsWidget: root.mediaControlsWidget mediaControlsWidget: root.mediaControlsWidget
contentContainer: root 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 { anchors {
top: parent.top top: parent.top
left: parent.left left: parent.left
right: parent.right right: parent.right
rightMargin: root.actionDrawer.mode == MobileShell.ActionDrawer.Portrait ? 0 : 360 topMargin: isConvergence ? Kirigami.Units.smallSpacing : 0
leftMargin: actionDrawer.mode == MobileShell.ActionDrawer.Portrait ? 0 : notificationDrawer.minWidthHeight * 0.06 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. // Secondary swipe area for uses in portrait.

View file

@ -56,10 +56,14 @@ Item {
: ShellSettings.Settings.quickSettingsColumns : ShellSettings.Settings.quickSettingsColumns
readonly property real intendedWidth: (columnWidth * effectiveColumns) + Kirigami.Units.gridUnit readonly property real intendedWidth: (columnWidth * effectiveColumns) + Kirigami.Units.gridUnit
property real offsetRatio: quickSettingsPanel.height / root.height readonly property bool isConvergence: ShellSettings.Settings.convergenceModeEnabled
anchors.topMargin: Math.min(root.actionDrawer.offsetResistance * offsetRatio - quickSettingsPanel.height, 0) 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.top: parent.top
anchors.right: parent.right 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 actionDrawer: root.actionDrawer
fullScreenHeight: root.height fullScreenHeight: root.height

View file

@ -11,6 +11,7 @@ import QtQuick.Layouts 1.1
import org.kde.plasma.clock import org.kde.plasma.clock
import org.kde.plasma.components 3.0 as PlasmaComponents import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.plasma.private.mobileshell as MobileShell import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.plasma.private.mobileshell.shellsettingsplugin as ShellSettings
import org.kde.kirigami as Kirigami import org.kde.kirigami as Kirigami
Item { Item {
@ -24,14 +25,26 @@ Item {
property alias notificationWidget: notificationWidget property alias notificationWidget: notificationWidget
property real contentY: notificationWidget.listView.contentY 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 property real topMargin: actionDrawer.mode == MobileShell.ActionDrawer.Portrait ? actionDrawer.offsetResistance + 1 : 0
readonly property real minWidthHeight: Math.min(actionDrawer.width, actionDrawer.height) readonly property real minWidthHeight: Math.min(actionDrawer.width, actionDrawer.height)
readonly property bool hasNotifications: notificationWidget.hasNotifications readonly property bool hasNotifications: notificationWidget.hasNotifications
readonly property bool listOverflowing: notificationWidget.listView.listOverflowing 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 // time source for the time and date whenin landscape mode
Clock { Clock {
@ -155,6 +168,7 @@ Item {
id: landscapeModeHeader id: landscapeModeHeader
anchors.fill: parent anchors.fill: parent
visible: actionDrawer.mode != MobileShell.ActionDrawer.Portrait visible: actionDrawer.mode != MobileShell.ActionDrawer.Portrait
&& !ShellSettings.Settings.convergenceModeEnabled
transform: [ transform: [
Translate { Translate {

View file

@ -73,9 +73,11 @@ MobileShell.BaseItem {
id: statusBarProxy id: statusBarProxy
Layout.alignment: Qt.AlignTop Layout.alignment: Qt.AlignTop
Layout.fillWidth: true 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 // 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.preferredHeight: visible ? Math.round(Kirigami.Units.gridUnit * 1.5 * ShellSettings.Settings.statusBarScaleFactor / 2) * 2 : 0
Layout.maximumHeight: Math.round(Kirigami.Units.gridUnit * 1.5 * ShellSettings.Settings.statusBarScaleFactor / 2) * 2 Layout.maximumHeight: visible ? Math.round(Kirigami.Units.gridUnit * 1.5 * ShellSettings.Settings.statusBarScaleFactor / 2) * 2 : 0
Kirigami.Theme.colorSet: Kirigami.Theme.Window Kirigami.Theme.colorSet: Kirigami.Theme.Window
Kirigami.Theme.inherit: false Kirigami.Theme.inherit: false

View file

@ -1,2 +1,2 @@
SPDX-FileCopyrightText: 2025 Marco A. SPDX-FileCopyrightText: 2026 Marco Allegretti.
SPDX-License-Identifier: EUPL-1.2 SPDX-License-Identifier: EUPL-1.2

View file

@ -1,2 +1,2 @@
SPDX-FileCopyrightText: 2025 Marco A. SPDX-FileCopyrightText: 2026 Marco Allegretti.
SPDX-License-Identifier: EUPL-1.2 SPDX-License-Identifier: EUPL-1.2

View file

@ -1,2 +1,2 @@
SPDX-FileCopyrightText: 2025 Marco A. SPDX-FileCopyrightText: 2026 Marco Allegretti.
SPDX-License-Identifier: EUPL-1.2 SPDX-License-Identifier: EUPL-1.2

View file

@ -1,2 +1,2 @@
SPDX-FileCopyrightText: 2025 Marco A. SPDX-FileCopyrightText: 2026 Marco Allegretti.
SPDX-License-Identifier: EUPL-1.2 SPDX-License-Identifier: EUPL-1.2

View file

@ -1,2 +1,2 @@
SPDX-FileCopyrightText: 2025 Marco A. SPDX-FileCopyrightText: 2026 Marco Allegretti.
SPDX-License-Identifier: EUPL-1.2 SPDX-License-Identifier: EUPL-1.2

View file

@ -1,2 +1,2 @@
SPDX-FileCopyrightText: 2025 Marco A. SPDX-FileCopyrightText: 2026 Marco Allegretti.
SPDX-License-Identifier: EUPL-1.2 SPDX-License-Identifier: EUPL-1.2