From f501f977d18cd00926653816de4c796d0ecf5c42 Mon Sep 17 00:00:00 2001 From: Damocles Date: Sat, 25 Apr 2026 21:48:35 +0200 Subject: [PATCH] dock: pinned mode acts as screen split - bar shrinks, corners adjust, opaque background --- shell/dock/AppletDock.qml | 37 +++++++++++++++++--------- shell/dock/DockEdgeTrigger.qml | 8 +++--- shell/dock/qmldir | 1 - shell/modules/Bar.qml | 2 ++ shell/modules/DockModule.qml | 7 +++-- shell/modules/ScreenCorners.qml | 2 ++ shell/{dock => services}/DockState.qml | 9 +++++++ shell/services/qmldir | 1 + test/qmllint-baseline.txt | 6 +++++ 9 files changed, 52 insertions(+), 21 deletions(-) rename shell/{dock => services}/DockState.qml (68%) diff --git a/shell/dock/AppletDock.qml b/shell/dock/AppletDock.qml index 48f0b3e..1c770fe 100644 --- a/shell/dock/AppletDock.qml +++ b/shell/dock/AppletDock.qml @@ -14,11 +14,11 @@ PanelWindow { required property var screen - visible: D.DockState.open + visible: S.DockState.open color: "transparent" - WlrLayershell.layer: D.DockState.mode === "pinned" ? WlrLayer.Top : WlrLayer.Overlay - WlrLayershell.exclusiveZone: D.DockState.mode === "pinned" ? _dockWidth : 0 + WlrLayershell.layer: S.DockState.mode === "pinned" ? WlrLayer.Top : WlrLayer.Overlay + WlrLayershell.exclusiveZone: S.DockState.mode === "pinned" ? _dockWidth : 0 WlrLayershell.namespace: "nova-dock" anchors.top: true @@ -31,8 +31,21 @@ PanelWindow { implicitWidth: _dockWidth + // Set reserved width for bar/corners when pinned + onVisibleChanged: { + if (S.DockState.mode === "pinned") + S.DockState.reservedWidth = _dockWidth; + } + Connections { + target: S.DockState + function onModeChanged() { + if (S.DockState.mode === "pinned") + S.DockState.reservedWidth = root._dockWidth; + } + } + // Slide animation - property real _slideX: D.DockState.open ? 0 : _dockWidth + property real _slideX: S.DockState.open ? 0 : _dockWidth Behavior on _slideX { enabled: !S.Theme.reducedMotion @@ -46,7 +59,7 @@ PanelWindow { HoverHandler { id: _dockHover onHoveredChanged: { - if (!hovered && D.DockState.mode === "overlay") + if (!hovered && S.DockState.mode === "overlay") _overlayCloseTimer.restart(); else _overlayCloseTimer.stop(); @@ -56,16 +69,16 @@ PanelWindow { Timer { id: _overlayCloseTimer interval: 200 - onTriggered: if (D.DockState.mode === "overlay") - D.DockState.close() + onTriggered: if (S.DockState.mode === "overlay") + S.DockState.close() } - // Background + // Background - fully opaque when pinned, semi-transparent in overlay Rectangle { id: _bg anchors.fill: parent color: S.Theme.base00 - opacity: Math.max(S.Theme.barOpacity, 0.85) + opacity: S.DockState.mode === "pinned" ? 1.0 : Math.max(S.Theme.barOpacity, 0.85) transform: Translate { x: root._slideX @@ -355,7 +368,7 @@ PanelWindow { _runner.command = cmd; _runner.running = true; } - onDismiss: D.DockState.close() + onDismiss: S.DockState.close() } } } @@ -370,13 +383,13 @@ PanelWindow { M.ProcessList { id: _cpuProcs sortBy: "cpu" - active: _cpuCard.expanded && D.DockState.open + active: _cpuCard.expanded && S.DockState.open } M.ProcessList { id: _memProcs sortBy: "mem" - active: _memCard.expanded && D.DockState.open + active: _memCard.expanded && S.DockState.open } PwObjectTracker { diff --git a/shell/dock/DockEdgeTrigger.qml b/shell/dock/DockEdgeTrigger.qml index 2e5172b..6fcb4dc 100644 --- a/shell/dock/DockEdgeTrigger.qml +++ b/shell/dock/DockEdgeTrigger.qml @@ -1,7 +1,7 @@ import QtQuick import Quickshell import Quickshell.Wayland -import "." as D +import "../services" as S // Invisible 2px-wide PanelWindow at the right screen edge. // When cursor enters, opens the dock in overlay mode. @@ -10,7 +10,7 @@ PanelWindow { required property var screen - visible: !D.DockState.open + visible: !S.DockState.open color: "transparent" WlrLayershell.layer: WlrLayer.Overlay @@ -25,8 +25,8 @@ PanelWindow { HoverHandler { onHoveredChanged: { - if (hovered && !D.DockState.open) - D.DockState.openOverlay(); + if (hovered && !S.DockState.open) + S.DockState.openOverlay(); } } } diff --git a/shell/dock/qmldir b/shell/dock/qmldir index 776b954..98c5fbb 100644 --- a/shell/dock/qmldir +++ b/shell/dock/qmldir @@ -3,5 +3,4 @@ module dock AppletDock 1.0 AppletDock.qml DockCard 1.0 DockCard.qml DockEdgeTrigger 1.0 DockEdgeTrigger.qml -singleton DockState 1.0 DockState.qml # keep-sorted end diff --git a/shell/modules/Bar.qml b/shell/modules/Bar.qml index 2ea685c..a354cfe 100644 --- a/shell/modules/Bar.qml +++ b/shell/modules/Bar.qml @@ -19,6 +19,8 @@ PanelWindow { right: true } + margins.right: S.DockState.reservedWidth + implicitHeight: S.Theme.barHeight exclusiveZone: implicitHeight diff --git a/shell/modules/DockModule.qml b/shell/modules/DockModule.qml index 75ee6bf..f2db938 100644 --- a/shell/modules/DockModule.qml +++ b/shell/modules/DockModule.qml @@ -1,15 +1,14 @@ import QtQuick import "." as M import "../services" as S -import "../dock" as D M.BarModule { id: root - tooltip: D.DockState.open ? "Close dock" : "Open dock" - onTapped: D.DockState.toggle() + tooltip: S.DockState.open ? "Close dock" : "Open dock" + onTapped: S.DockState.toggle() M.BarIcon { - icon: D.DockState.open ? "\uDB80\uDD8B" : "\uDB80\uDD89" + icon: S.DockState.open ? "\uDB80\uDD8B" : "\uDB80\uDD89" anchors.verticalCenter: parent.verticalCenter } } diff --git a/shell/modules/ScreenCorners.qml b/shell/modules/ScreenCorners.qml index 8b81097..7c02d16 100644 --- a/shell/modules/ScreenCorners.qml +++ b/shell/modules/ScreenCorners.qml @@ -80,6 +80,7 @@ Item { corner: 1 anchors.top: true anchors.right: true + margins.right: S.DockState.reservedWidth } Corner { corner: 2 @@ -90,5 +91,6 @@ Item { corner: 3 anchors.bottom: true anchors.right: true + margins.right: S.DockState.reservedWidth } } diff --git a/shell/dock/DockState.qml b/shell/services/DockState.qml similarity index 68% rename from shell/dock/DockState.qml rename to shell/services/DockState.qml index 917decc..ad3f3ca 100644 --- a/shell/dock/DockState.qml +++ b/shell/services/DockState.qml @@ -7,6 +7,15 @@ QtObject { property string mode: "closed" readonly property bool open: mode !== "closed" + // Screen space reserved by the dock when pinned. + // Bar, screen corners, etc. read this to adjust layout. + property int reservedWidth: 0 + + onModeChanged: { + if (mode !== "pinned") + reservedWidth = 0; + } + function openPinned() { mode = "pinned"; } diff --git a/shell/services/qmldir b/shell/services/qmldir index 98ac21f..9a06401 100644 --- a/shell/services/qmldir +++ b/shell/services/qmldir @@ -4,6 +4,7 @@ NotifItem 1.0 NotifItem.qml singleton BacklightService 1.0 BacklightService.qml singleton BatteryService 1.0 BatteryService.qml singleton BluetoothService 1.0 BluetoothService.qml +singleton DockState 1.0 DockState.qml singleton IdleInhibitService 1.0 IdleInhibitService.qml singleton LockService 1.0 LockService.qml singleton Modules 1.0 Modules.qml diff --git a/test/qmllint-baseline.txt b/test/qmllint-baseline.txt index 94cace1..e3d318b 100644 --- a/test/qmllint-baseline.txt +++ b/test/qmllint-baseline.txt @@ -33,7 +33,10 @@ shell/modules/BarModule.qml: Member "accentColor" not found on type "QQuickItem" shell/modules/BarModule.qml: Member "keepOpen" not found on type "QObject" [missing-property] shell/modules/BarModule.qml: Member "screen" not found on type "QObject" [missing-property] shell/modules/BarModule.qml: Unqualified access [unqualified] +shell/modules/Bar.qml: Could not find property "right". [missing-property] +shell/modules/Bar.qml: Type margins is used but it is not resolved [unresolved-type] shell/modules/Bar.qml: Type PanelWindow is not creatable. [uncreatable-type] +shell/modules/Bar.qml: unknown grouped property scope margins. [unqualified] shell/modules/BatteryModule.qml: Unqualified access [unqualified] shell/modules/BluetoothModule.qml: Unqualified access [unqualified] shell/modules/ClockModule.qml: Unqualified access [unqualified] @@ -58,7 +61,10 @@ shell/modules/NotifPopup.qml: Unqualified access [unqualified] shell/modules/OverviewBackdrop.qml: Type PanelWindow is not creatable. [uncreatable-type] shell/modules/PowerModule.qml: Unqualified access [unqualified] shell/modules/ScreenCapture.qml: Type PanelWindow is not creatable. [uncreatable-type] +shell/modules/ScreenCorners.qml: Could not find property "right". [missing-property] +shell/modules/ScreenCorners.qml: Type margins is used but it is not resolved [unresolved-type] shell/modules/ScreenCorners.qml: Type PanelWindow is not creatable. [uncreatable-type] +shell/modules/ScreenCorners.qml: unknown grouped property scope margins. [unqualified] shell/modules/ScreenCorners.qml: Unqualified access [unqualified] shell/modules/TemperatureModule.qml: Unqualified access [unqualified] shell/modules/ThemedIcon.qml: Unqualified access [unqualified]