diff --git a/modules/Bar.qml b/modules/Bar.qml index f200738..e1efa6f 100644 --- a/modules/Bar.qml +++ b/modules/Bar.qml @@ -171,6 +171,7 @@ PanelWindow { } M.Volume { visible: M.Modules.volume.enable + bar: bar } } diff --git a/modules/HoverPanel.qml b/modules/HoverPanel.qml index 03e5194..46b7e84 100644 --- a/modules/HoverPanel.qml +++ b/modules/HoverPanel.qml @@ -62,10 +62,7 @@ PanelWindow { } } - on_WinVisibleChanged: console.log("[hp:" + panelNamespace + "] _winVisible →", _winVisible) - onShowPanelChanged: { - console.log("[hp:" + panelNamespace + "] showPanel →", showPanel); if (showPanel) { _hideTimer.stop(); _updatePosition(); @@ -111,15 +108,11 @@ PanelWindow { duration: 150 easing.type: Easing.InCubic } - onStarted: console.log("[hp:" + panelNamespace + "] hideAnim started") onFinished: root._winVisible = false } HoverHandler { - onHoveredChanged: { - console.log("[hp:" + panelNamespace + "] hovered →", hovered); - root.panelHovered = hovered; - } + onHoveredChanged: root.panelHovered = hovered } M.PopupBackground { diff --git a/modules/Volume.qml b/modules/Volume.qml index 9631646..1b55d60 100644 --- a/modules/Volume.qml +++ b/modules/Volume.qml @@ -38,18 +38,9 @@ M.BarSection { return streams; } - property bool _expanded: false property bool _osdActive: false readonly property bool _anyHover: root._hovered || hoverPanel.panelHovered - readonly property bool _showPanel: _anyHover || _expanded || _osdActive - - on_ShowPanelChanged: { - console.log("[vol] showPanel →", _showPanel, "| expanded:", _expanded, "| anyHover:", _anyHover); - if (!_showPanel) - _expanded = false; - } - - on_ExpandedChanged: console.log("[vol] expanded →", _expanded) + readonly property bool _showPanel: _anyHover || _osdActive onVolumeChanged: _flashPanel() onMutedChanged: _flashPanel() @@ -65,6 +56,8 @@ M.BarSection { onTriggered: root._osdActive = false } + required property var bar + M.BarIcon { icon: root._volumeIcon minIcon: "\uF028" @@ -98,7 +91,7 @@ M.BarSection { } } - // Unified volume panel — hover shows slider, click expands to show devices + // OSD panel — hover shows slider only, fixed height, no resize M.HoverPanel { id: hoverPanel showPanel: root._showPanel @@ -107,14 +100,12 @@ M.BarSection { accentColor: root.accentColor panelNamespace: "nova-volume" contentWidth: 220 - animateHeight: true - // Compact: slider row + // Slider row Item { width: parent.width height: 36 - // Mute toggle Text { id: muteIcon anchors.left: parent.left @@ -132,7 +123,6 @@ M.BarSection { } } - // Slider Item { id: slider anchors.left: muteIcon.right @@ -147,13 +137,11 @@ M.BarSection { color: M.Theme.base02 radius: 3 } - Rectangle { width: parent.width * Math.min(1, Math.max(0, root.volume)) height: parent.height color: root._volumeColor radius: 3 - Behavior on width { NumberAnimation { duration: 80 @@ -191,7 +179,7 @@ M.BarSection { } } - // Sink name — click to expand/collapse device list + // Sink name row — click chevron to open mixer popup Item { width: parent.width height: 22 @@ -214,7 +202,7 @@ M.BarSection { anchors.right: parent.right anchors.rightMargin: 12 anchors.verticalCenter: parent.verticalCenter - text: root._expanded ? "\uF077" : "\uF078" + text: "\uF078" color: M.Theme.base04 font.pixelSize: M.Theme.fontSize - 3 font.family: M.Theme.iconFontFamily @@ -222,17 +210,24 @@ M.BarSection { TapHandler { cursorShape: Qt.PointingHandCursor - onTapped: root._expanded = true + onTapped: mixerLoader.active = true } } + } - // Expanded: output device list - Column { - id: deviceList - width: parent.width - visible: root._expanded + // Mixer popup — separate window, no resize issues + LazyLoader { + id: mixerLoader + active: false - // Separator + M.PopupPanel { + accentColor: root.accentColor + screen: root.bar.screen + anchorX: root.mapToGlobal(root.width / 2, 0).x - (root.bar.screen?.x ?? 0) + panelWidth: 220 + onDismissed: mixerLoader.active = false + + // Output devices Rectangle { width: parent.width - 16 height: 1 @@ -240,7 +235,6 @@ M.BarSection { color: M.Theme.base03 } - // Header Text { width: parent.width height: 24 @@ -258,7 +252,7 @@ M.BarSection { delegate: Item { required property var modelData - width: deviceList.width + width: 220 height: 28 readonly property bool _active: modelData === root.sink @@ -293,38 +287,31 @@ M.BarSection { TapHandler { onTapped: { Pipewire.preferredDefaultAudioSink = modelData; - root._expanded = false; + mixerLoader.active = false; } } } } - // Streams header (only if there are streams) - Item { + // Streams section + Rectangle { + visible: root._streamList.length > 0 + width: parent.width - 16 + height: visible ? 1 : 0 + anchors.horizontalCenter: parent.horizontalCenter + color: M.Theme.base03 + } + + Text { visible: root._streamList.length > 0 width: parent.width - height: visible ? streamSep.height + streamHeader.height : 0 - - Rectangle { - id: streamSep - width: parent.width - 16 - height: 1 - anchors.horizontalCenter: parent.horizontalCenter - color: M.Theme.base03 - } - - Text { - id: streamHeader - anchors.top: streamSep.bottom - width: parent.width - height: 24 - verticalAlignment: Text.AlignVCenter - leftPadding: 12 - text: "Applications" - color: M.Theme.base04 - font.pixelSize: M.Theme.fontSize - 1 - font.family: M.Theme.fontFamily - } + height: visible ? 24 : 0 + verticalAlignment: Text.AlignVCenter + leftPadding: 12 + text: "Applications" + color: M.Theme.base04 + font.pixelSize: M.Theme.fontSize - 1 + font.family: M.Theme.fontFamily } Repeater { @@ -334,7 +321,7 @@ M.BarSection { id: streamEntry required property var modelData - width: deviceList.width + width: 220 height: 32 readonly property string _appName: modelData.properties["application.name"] || modelData.description || modelData.name || "Unknown" @@ -422,12 +409,6 @@ M.BarSection { } } } - - // Bottom padding - Item { - width: 1 - height: 4 - } } } }