import QtQuick import Quickshell import Quickshell.Wayland import Quickshell.Io import Quickshell.Services.Mpris import "." as D import "../services" as S import "../applets" as C import "../modules" as M PanelWindow { id: root visible: _winVisible color: "transparent" property bool _winVisible: false WlrLayershell.layer: S.DockState.mode === "pinned" ? WlrLayer.Bottom : WlrLayer.Overlay WlrLayershell.exclusiveZone: S.DockState.mode === "pinned" ? _dockWidth : 0 WlrLayershell.namespace: "nova-dock" anchors.top: true anchors.right: true anchors.bottom: true // Counteract the bar's exclusive zone so the dock extends to the top of the screen margins.top: -S.Theme.barHeight readonly property int _dockWidth: S.Modules.dock.width ?? 300 readonly property var _applets: S.Modules.dock.applets ?? {} readonly property color _accent: S.Theme.base0C 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 - managed manually so window stays visible during hide property real _slideX: _dockWidth Connections { target: S.DockState function onOpenChanged() { if (S.DockState.open) { root._winVisible = true; _hideAnim.stop(); if (S.Theme.reducedMotion) { root._slideX = 0; } else { _showAnim.start(); } } else { _showAnim.stop(); if (S.Theme.reducedMotion) { root._slideX = root._dockWidth; root._winVisible = false; } else { _hideAnim.start(); } } } } NumberAnimation { id: _showAnim target: root property: "_slideX" to: 0 duration: 200 easing.type: Easing.OutCubic } NumberAnimation { id: _hideAnim target: root property: "_slideX" to: root._dockWidth duration: 200 easing.type: Easing.OutCubic onFinished: root._winVisible = false } // Overlay mode: close when cursor leaves HoverHandler { id: _dockHover onHoveredChanged: { if (!hovered && S.DockState.mode === "overlay") _overlayCloseTimer.restart(); else _overlayCloseTimer.stop(); } } Timer { id: _overlayCloseTimer interval: 200 onTriggered: if (S.DockState.mode === "overlay") S.DockState.close() } // Background - fully opaque when pinned, semi-transparent in overlay Rectangle { id: _bg anchors.fill: parent color: S.Theme.base00 opacity: S.DockState.mode === "pinned" ? 1.0 : Math.max(S.Theme.barOpacity, 0.85) transform: Translate { x: root._slideX } } // Left edge line - marks the virtual screen edge, matches bar border width. // Uses base09 (rightmost bar gradient color). Rectangle { anchors.left: parent.left anchors.top: parent.top anchors.bottom: parent.bottom width: 1 color: S.Theme.base09 opacity: _bg.opacity transform: Translate { x: root._slideX } } // Dock bar - mirrors main bar style, hosts dock toggle when pinned Item { id: _dockBar anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right height: S.Theme.barHeight visible: S.DockState.mode === "pinned" transform: Translate { x: root._slideX } Rectangle { anchors.fill: parent color: S.Theme.base00 } // Bottom border - gradient matching bar style (base0C to base09, but just the right end) Rectangle { anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom height: 1 color: S.Theme.base09 } // Dock toggle M.BarGroup { anchors.centerIn: parent M.BarModule { tooltip: "Unpin dock" onTapped: S.DockState.toggle() M.BarIcon { icon: "\uDB80\uDD8B" anchors.verticalCenter: parent.verticalCenter } } } } // Content - inset past the edge line + gap Flickable { id: _flickable anchors.top: _dockBar.visible ? _dockBar.bottom : parent.top anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom anchors.leftMargin: S.Theme.groupSpacing + 1 contentHeight: _column.height clip: true boundsBehavior: Flickable.StopAtBounds transform: Translate { x: root._slideX } Column { id: _column width: root._dockWidth spacing: 8 topPadding: 8 bottomPadding: 8 leftPadding: 8 rightPadding: 8 // Clock D.DockCard { visible: root._applets.clock ?? true icon: "\uF017" title: "Clock" accentColor: root._accent width: parent.width - 16 C.ClockApplet { width: parent.width accentColor: root._accent currentDate: _clock.date } } // CPU D.DockCard { id: _cpuCard visible: root._applets.cpu ?? true icon: "\uF2DB" title: "CPU" accentColor: root._accent width: parent.width - 16 C.CpuApplet { width: parent.width processes: _cpuProcs.processes accentColor: root._accent active: _cpuCard.expanded } } // GPU D.DockCard { visible: (root._applets.gpu ?? true) && S.SystemStats.gpuAvailable icon: "\uEB4C" title: "GPU" accentColor: root._accent width: parent.width - 16 C.GpuApplet { width: parent.width active: parent.expanded accentColor: root._accent } } // Memory D.DockCard { id: _memCard visible: root._applets.memory ?? true icon: "\uEFC5" title: "Memory" accentColor: root._accent width: parent.width - 16 C.MemoryApplet { width: parent.width percent: S.SystemStats.memPercent usedGb: S.SystemStats.memUsedGb totalGb: S.SystemStats.memTotalGb availGb: S.SystemStats.memAvailGb cachedGb: S.SystemStats.memCachedGb buffersGb: S.SystemStats.memBuffersGb processes: _memProcs.processes accentColor: root._accent active: _memCard.expanded } } // Temperature D.DockCard { visible: root._applets.temperature ?? true icon: "\uF2C9" title: "Temperature" accentColor: root._accent width: parent.width - 16 C.TemperatureApplet { width: parent.width temp: S.SystemStats.tempCelsius warm: S.Modules.temperature.warm || 80 hot: S.Modules.temperature.hot || 90 history: S.SystemStats.tempHistory devices: S.SystemStats.tempDevices accentColor: root._accent deviceFilter: S.Modules.temperature.device || "" active: parent.expanded } } // Disk D.DockCard { visible: root._applets.disk ?? true icon: "\uF0C9" title: "Disk" accentColor: root._accent width: parent.width - 16 C.DiskApplet { width: parent.width mounts: S.SystemStats.diskMounts accentColor: root._accent } } // Battery D.DockCard { visible: (root._applets.battery ?? true) && S.BatteryService.available icon: "\uDB80\uDC84" title: "Battery" accentColor: root._accent width: parent.width - 16 C.BatteryApplet { width: parent.width active: parent.expanded accentColor: root._accent } } // Network D.DockCard { visible: root._applets.network ?? true icon: "\uF1EB" title: "Network" accentColor: root._accent width: parent.width - 16 C.NetworkApplet { width: parent.width accentColor: root._accent active: parent.expanded } } // Bluetooth D.DockCard { visible: (root._applets.bluetooth ?? true) && S.BluetoothService.state !== "unavailable" icon: "\uF294" title: "Bluetooth" accentColor: root._accent width: parent.width - 16 C.BluetoothApplet { width: parent.width accentColor: root._accent active: parent.expanded } } // Volume D.DockCard { visible: root._applets.volume ?? true icon: "\uF028" title: "Sound" accentColor: root._accent width: parent.width - 16 C.VolumeApplet { width: parent.width accentColor: root._accent } } // Backlight D.DockCard { visible: (root._applets.backlight ?? true) && S.BacklightService.available icon: "\uF185" title: "Brightness" accentColor: root._accent width: parent.width - 16 C.BacklightApplet { width: parent.width percent: S.BacklightService.percent accentColor: root._accent onSetPercent: pct => S.BacklightService.setPercent(pct) } } // Weather D.DockCard { visible: (root._applets.weather ?? true) && S.WeatherService.available icon: S.WeatherService.icon title: "Weather" accentColor: root._accent width: parent.width - 16 C.WeatherApplet { width: parent.width accentColor: root._accent } } // Now Playing D.DockCard { visible: (root._applets.mpris ?? true) && S.MprisService.player !== null icon: "\uF04B" title: "Now Playing" accentColor: root._accent width: parent.width - 16 C.MprisApplet { width: parent.width accentColor: root._accent } } // Notifications D.DockCard { visible: root._applets.notifications ?? true icon: "\uDB80\uDC9C" title: "Notifications" accentColor: root._accent width: parent.width - 16 C.NotifApplet { width: parent.width contentWidth: root._dockWidth - 16 accentColor: root._accent } } // Power D.DockCard { visible: root._applets.power ?? true icon: "\uF011" title: "Power" accentColor: root._accent width: parent.width - 16 C.PowerApplet { width: parent.width accentColor: root._accent onRunCommand: cmd => { _runner.command = cmd; _runner.running = true; } onDismiss: S.DockState.close() } } } } // Shared resources SystemClock { id: _clock precision: SystemClock.Seconds } M.ProcessList { id: _cpuProcs sortBy: "cpu" active: _cpuCard.expanded && S.DockState.open } M.ProcessList { id: _memProcs sortBy: "mem" active: _memCard.expanded && S.DockState.open } Process { id: _runner } }