rewrite bar with quickshell

This commit is contained in:
2025-10-11 16:28:11 +02:00
parent e1a02f7994
commit abadf04aa2
49 changed files with 10246 additions and 7 deletions

View File

@@ -0,0 +1,81 @@
import QtQuick
import Quickshell
import Quickshell.Io
import qs.Services
Scope {
id: root
property int count: 32
property int noiseReduction: 60
property string channels: "mono"
property string monoOption: "average"
property var config: ({
"general": {
"bars": count,
"framerate": 30,
"autosens": 1
},
"smoothing": {
"monstercat": 1,
"gravity": 1e+06,
"noise_reduction": noiseReduction
},
"output": {
"method": "raw",
"bit_format": 8,
"channels": channels,
"mono_option": monoOption
}
})
property var values: Array(count).fill(0)
Process {
id: process
property int index: 0
stdinEnabled: true
running: !MusicManager.isAllPaused()
command: ["cava", "-p", "/dev/stdin"]
onExited: {
stdinEnabled = true;
index = 0;
values = Array(count).fill(0);
}
onStarted: {
for (const k in config) {
if (typeof config[k] !== "object") {
write(k + "=" + config[k] + "\n");
continue;
}
write("[" + k + "]\n");
const obj = config[k];
for (const k2 in obj) {
write(k2 + "=" + obj[k2] + "\n");
}
}
stdinEnabled = false;
}
stdout: SplitParser {
splitMarker: ""
onRead: (data) => {
const newValues = Array(count).fill(0);
for (let i = 0; i < values.length; i++) {
newValues[i] = values[i];
}
if (process.index + data.length > count)
process.index = 0;
for (let i = 0; i < data.length; i += 1) {
newValues[i + process.index] = Math.min(data.charCodeAt(i), 128) / 128;
}
process.index += data.length;
values = newValues;
}
}
}
}

View File

@@ -0,0 +1,10 @@
import QtQuick
import Quickshell
import qs.Constants
pragma Singleton
Singleton {
id: root
readonly property var colorList: [Colors.lavender, Colors.blue, Colors.sapphire, Colors.sky, Colors.teal, Colors.green, Colors.yellow, Colors.peach]
}

View File

@@ -0,0 +1,87 @@
import QtQuick
import QtQuick.Shapes
import qs.Constants
Shape {
id: root
property string position: "topleft" // Corner position: topleft/topright/bottomleft/bottomright
property real size: 1 // Scale multiplier for entire corner
property int concaveWidth: 100 * size
property int concaveHeight: 60 * size
property int offsetX: -20
property int offsetY: -20
property color fillColor: Colors.base
property int arcRadius: 20 * size
property var modelData: null
// Position flags derived from position string
property bool _isTop: position.includes("top")
property bool _isLeft: position.includes("left")
property bool _isRight: position.includes("right")
property bool _isBottom: position.includes("bottom")
// Shift the path vertically if offsetY is negative to pull shape up
property real pathOffsetY: Math.min(offsetY, 0)
// Base coordinates for left corner shape, shifted by pathOffsetY vertically
property real _baseStartX: 30 * size
property real _baseStartY: (_isTop ? 20 * size : 0) + pathOffsetY
property real _baseLineX: 30 * size
property real _baseLineY: (_isTop ? 0 : 20 * size) + pathOffsetY
property real _baseArcX: 50 * size
property real _baseArcY: (_isTop ? 20 * size : 0) + pathOffsetY
// Mirror coordinates for right corners
property real _startX: _isRight ? (concaveWidth - _baseStartX) : _baseStartX
property real _startY: _baseStartY
property real _lineX: _isRight ? (concaveWidth - _baseLineX) : _baseLineX
property real _lineY: _baseLineY
property real _arcX: _isRight ? (concaveWidth - _baseArcX) : _baseArcX
property real _arcY: _baseArcY
// Arc direction varies by corner to maintain proper concave shape
property int _arcDirection: {
if (_isTop && _isLeft)
return PathArc.Counterclockwise;
if (_isTop && _isRight)
return PathArc.Clockwise;
if (_isBottom && _isLeft)
return PathArc.Clockwise;
if (_isBottom && _isRight)
return PathArc.Counterclockwise;
return PathArc.Counterclockwise;
}
width: concaveWidth
height: concaveHeight
// Position relative to parent based on corner type
x: _isLeft ? offsetX : (parent ? parent.width - width + offsetX : 0)
y: _isTop ? offsetY : (parent ? parent.height - height + offsetY : 0)
preferredRendererType: Shape.CurveRenderer
layer.enabled: true
layer.samples: 4
ShapePath {
strokeWidth: 0
fillColor: root.fillColor
strokeColor: root.fillColor
startX: root._startX
startY: root._startY
PathLine {
x: root._lineX
y: root._lineY
}
PathArc {
x: root._arcX
y: root._arcY
radiusX: root.arcRadius
radiusY: root.arcRadius
useLargeArc: false
direction: root._arcDirection
}
}
}

View File

@@ -0,0 +1,178 @@
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import Quickshell
import Quickshell.Wayland
import qs.Constants
import qs.Modules.Misc
import qs.Services
Scope {
id: rootScope
property var shell
property string namespace: "quickshell-corners"
property int topMargin: 45
property int cornerHeight: 20
property real cornerSize: 1
property real opacity: Niri.noFocus ? 0 : 1
Item {
id: cornersRootItem
anchors.fill: parent
Variants {
model: Quickshell.screens
Item {
property var modelData
PanelWindow {
id: fakeBar
anchors.top: true
anchors.left: true
anchors.right: true
color: "transparent"
screen: modelData
WlrLayershell.exclusionMode: ExclusionMode.Ignore
visible: true
WlrLayershell.layer: WlrLayer.Background
aboveWindows: false
WlrLayershell.namespace: namespace
implicitHeight: topMargin
Rectangle {
anchors.fill: parent
color: Colors.base
opacity: rootScope.opacity
}
}
PanelWindow {
id: topLeftPanel
anchors.top: true
anchors.left: true
color: "transparent"
screen: modelData
margins.top: topMargin
WlrLayershell.exclusionMode: ExclusionMode.Ignore
visible: true
WlrLayershell.layer: WlrLayer.Background
aboveWindows: false
WlrLayershell.namespace: namespace
implicitHeight: cornerHeight
Corner {
id: topLeftCorner
position: "bottomleft"
size: rootScope.cornerSize
offsetX: -32
offsetY: 0
anchors.top: parent.top
opacity: rootScope.opacity
}
}
PanelWindow {
id: topRightPanel
anchors.top: true
anchors.right: true
color: "transparent"
screen: modelData
margins.top: topMargin
WlrLayershell.exclusionMode: ExclusionMode.Ignore
visible: true
WlrLayershell.layer: WlrLayer.Background
aboveWindows: false
WlrLayershell.namespace: namespace
implicitHeight: cornerHeight
Corner {
id: topRightCorner
position: "bottomright"
size: rootScope.cornerSize
offsetX: 32
offsetY: 0
anchors.top: parent.top
opacity: rootScope.opacity
}
}
PanelWindow {
id: bottomLeftPanel
anchors.bottom: true
anchors.left: true
color: "transparent"
screen: modelData
WlrLayershell.exclusionMode: ExclusionMode.Ignore
visible: true
WlrLayershell.layer: WlrLayer.Background
aboveWindows: false
WlrLayershell.namespace: namespace
implicitHeight: cornerHeight
Corner {
id: bottomLeftCorner
position: "topleft"
size: rootScope.cornerSize
offsetX: -32
offsetY: 0
anchors.top: parent.top
opacity: rootScope.opacity
}
}
PanelWindow {
id: bottomRightPanel
anchors.bottom: true
anchors.right: true
color: "transparent"
screen: modelData
WlrLayershell.exclusionMode: ExclusionMode.Ignore
visible: true
WlrLayershell.layer: WlrLayer.Background
aboveWindows: false
WlrLayershell.namespace: namespace
implicitHeight: cornerHeight
Corner {
id: bottomRightCorner
position: "topright"
size: rootScope.cornerSize
offsetX: 32
offsetY: 0
anchors.top: parent.top
opacity: rootScope.opacity
}
}
}
}
}
Behavior on opacity {
NumberAnimation {
duration: 1000
easing.type: Easing.InOutCubic
}
}
}