aboutsummaryrefslogtreecommitdiffstats
path: root/desktop
diff options
context:
space:
mode:
Diffstat (limited to 'desktop')
-rw-r--r--desktop/island/HeadphonesPanel.qml98
-rw-r--r--desktop/island/PanelSlider.qml106
2 files changed, 110 insertions, 94 deletions
diff --git a/desktop/island/HeadphonesPanel.qml b/desktop/island/HeadphonesPanel.qml
index 315bc6b..49a356e 100644
--- a/desktop/island/HeadphonesPanel.qml
+++ b/desktop/island/HeadphonesPanel.qml
@@ -267,7 +267,8 @@ Column {
// Ambient level 1-20, while in ambient mode. Wheel or drag, sent once it
// settles (levelSend above).
- Slider {
+ PanelSlider {
+ width: panel.width
visible: panel.mode === "ambient"
cp: 0xF07C5 // md-ear_hearing
value: panel.shownLevel / 20
@@ -311,7 +312,8 @@ Column {
}
// The headphones' volume; the icon mutes, the wheel steps 5%.
- Slider {
+ PanelSlider {
+ width: panel.width
enabled: panel.audio !== null
icon: Logic.volumeIcon(panel.audio?.volume ?? 0, panel.audio?.muted ?? false)
value: panel.audio?.volume ?? 0
@@ -408,96 +410,4 @@ Column {
}
}
}
-
- // One slider row: a glyph (cp) or a named icon (icon), a track, a label.
- // moved(v) gives 0..1 from a click or drag; stepped(+1|-1) one wheel notch.
- component Slider: Row {
- id: row
- property int cp: 0
- property string icon: ""
- property real value: 0
- property bool muted: false
- property string label: ""
- signal moved(real v)
- signal stepped(int d)
- signal iconClicked()
-
- width: panel.width
- spacing: 10
-
- Item {
- anchors.verticalCenter: parent.verticalCenter
- width: 20
- height: 20
-
- Text {
- visible: row.icon === ""
- anchors.centerIn: parent
- text: panel.glyph(row.cp)
- font { family: Theme.iconFamily; pixelSize: 20 }
- color: Theme.subtext
- }
-
- IconImage {
- visible: row.icon !== ""
- anchors.centerIn: parent
- implicitSize: 18
- source: row.icon !== "" ? Quickshell.iconPath(row.icon, true) : ""
- }
-
- MouseArea {
- anchors.fill: parent
- enabled: row.enabled
- cursorShape: Qt.PointingHandCursor
- onClicked: row.iconClicked()
- }
- }
-
- Rectangle {
- anchors.verticalCenter: parent.verticalCenter
- width: row.width - 20 - 44 - row.spacing * 2
- height: 8
- radius: 4
- color: Theme.surface
-
- Rectangle {
- height: parent.height
- radius: parent.radius
- width: parent.width * Math.max(0, Math.min(1, row.value))
- color: row.muted ? Theme.red : Theme.accent
- opacity: row.muted ? 0.5 : 1
- }
-
- // Taller than the track so it is easy to hit. A MouseArea for the
- // wheel, not a WheelHandler (AGENTS.md); one step per notch (120),
- // since a touchpad sends many small deltas.
- MouseArea {
- anchors { fill: parent; topMargin: -8; bottomMargin: -8 }
- enabled: row.enabled
- preventStealing: true
- cursorShape: Qt.PointingHandCursor
- property real acc: 0
- function at(x) { return Math.max(0, Math.min(1, x / width)); }
- onPressed: mouse => row.moved(at(mouse.x))
- onPositionChanged: mouse => { if (pressed) row.moved(at(mouse.x)); }
- onWheel: wheel => {
- acc += wheel.angleDelta.y;
- while (Math.abs(acc) >= 120) {
- row.stepped(acc > 0 ? 1 : -1);
- acc -= acc > 0 ? 120 : -120;
- }
- wheel.accepted = true;
- }
- }
- }
-
- Text {
- anchors.verticalCenter: parent.verticalCenter
- width: 44
- horizontalAlignment: Text.AlignRight
- text: row.label
- font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 }
- color: row.muted ? Theme.red : Theme.subtext
- }
- }
}
diff --git a/desktop/island/PanelSlider.qml b/desktop/island/PanelSlider.qml
new file mode 100644
index 0000000..bbc0872
--- /dev/null
+++ b/desktop/island/PanelSlider.qml
@@ -0,0 +1,106 @@
+// Copyright (C) 2026 Danilo M. <danix@danix.xyz>
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2 as
+// published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+import Quickshell
+import Quickshell.Widgets
+import QtQuick
+import ".."
+
+// An icon, a track and a label: drag or click sets, the wheel steps one per
+// notch. Shared by the headphones and Sonix panels. The width is the user's.
+Row {
+ id: row
+ property int cp: 0
+ property string icon: ""
+ property real value: 0
+ property bool muted: false
+ property string label: ""
+ signal moved(real v)
+ signal stepped(int d)
+ signal iconClicked()
+
+ spacing: 10
+
+ Item {
+ anchors.verticalCenter: parent.verticalCenter
+ width: 20
+ height: 20
+
+ Text {
+ visible: row.icon === ""
+ anchors.centerIn: parent
+ text: String.fromCodePoint(row.cp)
+ font { family: Theme.iconFamily; pixelSize: 20 }
+ color: Theme.subtext
+ }
+
+ IconImage {
+ visible: row.icon !== ""
+ anchors.centerIn: parent
+ implicitSize: 18
+ source: row.icon !== "" ? Quickshell.iconPath(row.icon, true) : ""
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ enabled: row.enabled
+ cursorShape: Qt.PointingHandCursor
+ onClicked: row.iconClicked()
+ }
+ }
+
+ Rectangle {
+ anchors.verticalCenter: parent.verticalCenter
+ width: row.width - 20 - 44 - row.spacing * 2
+ height: 8
+ radius: 4
+ color: Theme.surface
+
+ Rectangle {
+ height: parent.height
+ radius: parent.radius
+ width: parent.width * Math.max(0, Math.min(1, row.value))
+ color: row.muted ? Theme.red : Theme.accent
+ opacity: row.muted ? 0.5 : 1
+ }
+
+ // Taller than the track so it is easy to hit. A MouseArea for the
+ // wheel, not a WheelHandler (AGENTS.md); one step per notch (120),
+ // since a touchpad sends many small deltas.
+ MouseArea {
+ anchors { fill: parent; topMargin: -8; bottomMargin: -8 }
+ enabled: row.enabled
+ preventStealing: true
+ cursorShape: Qt.PointingHandCursor
+ property real acc: 0
+ function at(x) { return Math.max(0, Math.min(1, x / width)); }
+ onPressed: mouse => row.moved(at(mouse.x))
+ onPositionChanged: mouse => { if (pressed) row.moved(at(mouse.x)); }
+ onWheel: wheel => {
+ acc += wheel.angleDelta.y;
+ while (Math.abs(acc) >= 120) {
+ row.stepped(acc > 0 ? 1 : -1);
+ acc -= acc > 0 ? 120 : -120;
+ }
+ wheel.accepted = true;
+ }
+ }
+ }
+
+ Text {
+ anchors.verticalCenter: parent.verticalCenter
+ width: 44
+ horizontalAlignment: Text.AlignRight
+ text: row.label
+ font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 }
+ color: row.muted ? Theme.red : Theme.subtext
+ }
+}