Build the Panama Hyprland desktop
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
// Volume row: mute button, slider, and a chevron that opens the device picker.
|
||||
//
|
||||
// PwObjectTracker is mandatory — without it node.audio.volume reads 0 and
|
||||
// writes are dropped on the floor with no error.
|
||||
|
||||
import QtQuick
|
||||
import Quickshell
|
||||
import Quickshell.Services.Pipewire
|
||||
import qs.widgets
|
||||
import qs.config
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property var node: null
|
||||
// Output vs input, purely for icon selection.
|
||||
property bool output: true
|
||||
property bool expanded: false
|
||||
|
||||
signal toggleExpanded
|
||||
|
||||
implicitHeight: 32
|
||||
visible: root.node !== null
|
||||
|
||||
readonly property real volume: root.node && root.node.audio ? root.node.audio.volume : 0
|
||||
readonly property bool muted: root.node && root.node.audio ? root.node.audio.muted : false
|
||||
|
||||
PwObjectTracker {
|
||||
objects: root.node ? [root.node] : []
|
||||
}
|
||||
|
||||
function iconName(): string {
|
||||
if (root.output) {
|
||||
if (root.muted || root.volume <= 0.001)
|
||||
return "audio-volume-muted-symbolic";
|
||||
if (root.volume < 0.34)
|
||||
return "audio-volume-low-symbolic";
|
||||
if (root.volume < 0.67)
|
||||
return "audio-volume-medium-symbolic";
|
||||
return "audio-volume-high-symbolic";
|
||||
}
|
||||
return root.muted ? "microphone-sensitivity-muted-symbolic" : "audio-input-microphone-symbolic";
|
||||
}
|
||||
|
||||
IconButton {
|
||||
id: muteButton
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
size: 30
|
||||
iconSize: 17
|
||||
icon: root.iconName()
|
||||
iconFallback: root.output ? "audio-volume-high-symbolic" : "audio-input-microphone-symbolic"
|
||||
onClicked: {
|
||||
if (root.node && root.node.audio)
|
||||
root.node.audio.muted = !root.node.audio.muted;
|
||||
}
|
||||
}
|
||||
|
||||
ValueSlider {
|
||||
anchors.left: muteButton.right
|
||||
anchors.leftMargin: 6
|
||||
anchors.right: chevron.left
|
||||
anchors.rightMargin: 4
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
value: root.muted ? 0 : root.volume
|
||||
onMoved: v => {
|
||||
if (!root.node || !root.node.audio)
|
||||
return;
|
||||
// Nudging the slider is also how you unmute, same as GNOME.
|
||||
root.node.audio.muted = false;
|
||||
root.node.audio.volume = v;
|
||||
}
|
||||
}
|
||||
|
||||
IconButton {
|
||||
id: chevron
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
size: 28
|
||||
iconSize: 14
|
||||
icon: root.expanded ? "pan-up-symbolic" : "pan-down-symbolic"
|
||||
iconFallback: "go-next-symbolic"
|
||||
onClicked: root.toggleExpanded()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user