added quickshell

This commit is contained in:
2026-08-10 23:57:26 +02:00
parent cbaf55cfc5
commit 47ff5233bd
69 changed files with 6945 additions and 80 deletions
+182
View File
@@ -0,0 +1,182 @@
import QtQuick
import Quickshell
import Quickshell.Wayland
import "root:/config"
import "root:/components"
import "root:/services"
// Volume / mic / brightness heads-up, bottom centre. Appears on change and
// fades out on its own.
PanelWindow {
id: root
required property var modelData
screen: modelData
readonly property bool primaryScreen: Quickshell.screens.length === 0
|| Quickshell.screens[0] === modelData
WlrLayershell.layer: WlrLayer.Overlay
WlrLayershell.namespace: "takemi-osd"
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
anchors { bottom: true }
margins.bottom: 90
implicitWidth: 300
implicitHeight: 78
color: "transparent"
exclusionMode: ExclusionMode.Ignore
visible: primaryScreen && (shown || fade.running)
property bool shown: false
property string kind: "volume"
// Suppress the burst of change signals that fires while services warm up.
property bool armed: false
Timer {
interval: 1500
running: true
onTriggered: root.armed = true
}
readonly property string glyph: {
switch (root.kind) {
case "mic": return Audio.micIcon;
case "brightness": return Brightness.icon;
default: return Audio.icon;
}
}
readonly property string title: {
switch (root.kind) {
case "mic": return Audio.micMuted ? "Mic muted" : "Microphone";
case "brightness": return "Brightness";
default: return Audio.muted ? "Muted" : "Volume";
}
}
readonly property real level: {
switch (root.kind) {
case "mic": return Audio.micMuted ? 0 : Audio.micVolume;
case "brightness": return Brightness.percent / 100;
default: return Audio.muted ? 0 : Audio.volume;
}
}
readonly property color tone: {
switch (root.kind) {
case "mic": return Audio.micMuted ? Theme.accent : Theme.blue;
case "brightness": return Theme.warn;
default: return Audio.muted ? Theme.accent : Theme.primary;
}
}
function flash(k: string) {
if (!root.armed) return;
root.kind = k;
root.shown = true;
glyphIcon.bump();
hold.restart();
}
Timer {
id: hold
interval: 1600
onTriggered: root.shown = false
}
Connections {
target: Audio
function onVolumeBumped() { root.flash("volume"); }
function onMicBumped() { root.flash("mic"); }
}
Connections {
target: Brightness
function onBumped() { root.flash("brightness"); }
}
P5Panel {
id: panel
anchors.fill: parent
anchors.margins: 4
fill: Theme.mantle
fillOpacity: 0.97
border: Theme.alpha(root.tone, 0.85)
borderWidth: Theme.stroke
slash: true
slashColor: root.tone
slashWidth: 5
halftone: true
halftoneColor: root.tone
halftoneOpacity: 0.08
sheen: true
lean: 0.09
chop: 14
padding: Theme.padM
opacity: root.shown ? 1 : 0
scale: root.shown ? 1 : 0.9
Behavior on opacity {
NumberAnimation { id: fade; duration: Theme.durBase }
}
Behavior on scale {
NumberAnimation { duration: Theme.durSlow; easing.type: Easing.OutBack }
}
Icon {
id: glyphIcon
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
text: root.glyph
color: root.tone
font.pixelSize: 30
width: 36
}
Column {
anchors.left: glyphIcon.right
anchors.leftMargin: Theme.padM
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
spacing: 4
Row {
width: parent.width
Text {
text: root.title.toUpperCase()
color: Theme.subtext
font.family: Theme.fontMono
font.pixelSize: Theme.fsMicro
font.letterSpacing: 2
renderType: Text.NativeRendering
}
Item {
width: parent.width - 90
height: 1
}
SplitText {
text: Math.round(root.level * 100) + "%"
pixelSize: Theme.fsBody
split: 1
splitOpacity: 0.5
}
}
MeterBar {
width: parent.width
height: 10
segments: 20
segmentWidth: (width - 19 * 3) / 20
spacing: 3
value: root.level * 100
activeColor: root.tone
}
}
}
}