import QtQuick import Quickshell import Quickshell.Wayland import "." as M // OSD overlay — slides out from the bar, centered on screen. // Attached to the bar (square top corners, flush below it). PanelWindow { id: root required property var screen // Stay visible while animating out visible: M.OsdState.visible || hideAnim.running color: "transparent" WlrLayershell.layer: WlrLayer.Overlay WlrLayershell.exclusiveZone: 0 WlrLayershell.namespace: "nova-osd" mask: Region {} anchors.top: true anchors.left: true margins.top: 0 margins.left: Math.round((screen.width - implicitWidth) / 2) implicitWidth: 200 implicitHeight: 48 // Slide + fade animation state property bool _shown: M.OsdState.visible on_ShownChanged: { if (_shown) { hideAnim.stop(); showAnim.start(); } else { showAnim.stop(); hideAnim.start(); } } ParallelAnimation { id: showAnim NumberAnimation { target: content; property: "opacity"; to: 1; duration: 150; easing.type: Easing.OutCubic } NumberAnimation { target: content; property: "y"; to: 0; duration: 200; easing.type: Easing.OutCubic } } ParallelAnimation { id: hideAnim NumberAnimation { target: content; property: "opacity"; to: 0; duration: 250; easing.type: Easing.InCubic } NumberAnimation { target: content; property: "y"; to: -content.height; duration: 250; easing.type: Easing.InCubic } } Item { id: content anchors.left: parent.left anchors.right: parent.right height: root.implicitHeight opacity: 0 y: -height // Background — flush with bar above Rectangle { anchors.fill: parent color: M.Theme.base00 opacity: Math.max(M.Theme.barOpacity, 0.85) topLeftRadius: 0 topRightRadius: 0 bottomLeftRadius: M.Theme.radius bottomRightRadius: M.Theme.radius } Row { anchors.centerIn: parent spacing: 10 // Icon Text { text: M.OsdState.icon color: M.Theme.base0D font.pixelSize: M.Theme.fontSize + 6 font.family: M.Theme.iconFontFamily anchors.verticalCenter: parent.verticalCenter } // Progress bar Item { width: 120 height: 6 anchors.verticalCenter: parent.verticalCenter Rectangle { anchors.fill: parent color: M.Theme.base02 radius: 3 } Rectangle { width: parent.width * Math.min(1, Math.max(0, M.OsdState.value)) height: parent.height color: M.Theme.base0D radius: 3 Behavior on width { NumberAnimation { duration: 120; easing.type: Easing.OutCubic } } } } // Percentage Text { text: Math.round(M.OsdState.value * 100) + "%" color: M.Theme.base05 font.pixelSize: M.Theme.fontSize font.family: M.Theme.fontFamily anchors.verticalCenter: parent.verticalCenter width: 32 } } } }