-
Notifications
You must be signed in to change notification settings - Fork 66
Open
Labels
Description
General crash information
General information
===== Build Information =====
Git Revision: tag-v0.2.1
Buildtime Qt Version: 6.10.1
Build Type: RelWithDebInfo
Compiler: GNU (14.3.0)
Complie Flags:
Build configuration:
Distributor: Nixpkgs
Distributor provided debuginfo: TRUE
Disable precompild headers (dev): OFF
Build tests (dev): OFF
ASAN (dev): OFF
Keep Frame Pointers (dev): OFF
Crash Handling: ON
Use jemalloc: ON
Unix Sockets: ON
Wayland: ON
Wlroots Layer-Shell: ON
Session Lock: ON
Foreign Toplevel Management: ON
Hyprland: ON
Hyprland IPC: ON
Hyprland Global Shortcuts: ON
Hyprland Focus Grabbing: ON
Hyprland Surface Extensions: ON
Screencopy: ON
Image Copy Capture: ON
Wlroots Screencopy: ON
Hyprland Toplevel Export: ON
X11: ON
I3/Sway: ON
I3/Sway IPC: ON
System Tray: ON
PipeWire: ON
Mpris: ON
Pam: ON
Greetd: ON
UPower: ON
Notifications: ON
Bluetooth: ON
===== Runtime Information =====
Runtime Qt Version: 6.10.1
Crashed process ID: 1818778
Run ID: t1xzlidy6t
Shell ID: c1f59de81923405ebac28b985f4d2fa4
Config Path: /nix/store/rmij6w837bc6kpx18dwlyly18368srqi-hm_quickshellconfig/shell.qml
===== Report Integrity =====
Minidump save status: 0
Log save status: 0
Binary copy status: 0
===== System Information =====
/etc/os-release:
ANSI_COLOR="0;38;2;126;186;228"
BUG_REPORT_URL="https://github.com/NixOS/nixpkgs/issues"
BUILD_ID="26.05.20251205.a672be6"
CPE_NAME="cpe:/o:nixos:nixos:26.05"
DEFAULT_HOSTNAME=nixos
DOCUMENTATION_URL="https://nixos.org/learn.html"
HOME_URL="https://nixos.org/"
ID=nixos
ID_LIKE=""
IMAGE_ID=""
IMAGE_VERSION=""
LOGO="nix-snowflake"
NAME=NixOS
PRETTY_NAME="NixOS 26.05 (Yarara)"
SUPPORT_URL="https://nixos.org/community.html"
VARIANT=""
VARIANT_ID=""
VENDOR_NAME=NixOS
VENDOR_URL="https://nixos.org/"
VERSION="26.05 (Yarara)"
VERSION_CODENAME=yarara
VERSION_ID="26.05"
/etc/lsb-release:
DISTRIB_CODENAME=yarara
DISTRIB_DESCRIPTION="NixOS 26.05 (Yarara)"
DISTRIB_ID=nixos
DISTRIB_RELEASE="26.05"
LSB_VERSION="26.05 (Yarara)"
What caused the crash
No response
Minidump
Log file
Configuration
shell.qml
//@ pragma UseQApplication
import Quickshell
import QtQuick
ShellRoot {
Connections {
target: Quickshell
function onReloadCompleted() {
Quickshell.inhibitReloadPopup()
}
function onReloadFailed() {
Quickshell.inhibitReloadPopup()
}
}
Bar {}
}Bar.qml
import Quickshell
import Quickshell.Hyprland
import Quickshell.Services.SystemTray
import Quickshell.Services.Pipewire
import Quickshell.Services.UPower
import Quickshell.Services.Mpris
import Quickshell.Io
import QtQuick
import QtQuick.Layouts
Scope {
id: root
// 网络名称
property string networkName: ""
// 当前媒体播放器
property MprisPlayer currentPlayer: Mpris.players.values.length > 0 ? Mpris.players.values[0] : null
// Cava 音频可视化
property var cavaValues: Array(16).fill(0)
property bool cavaRunning: currentPlayer !== null && currentPlayer.isPlaying
// 电源模式配置
property bool powerMenuVisible: false
property int acProfile: PowerProfile.Performance
property int batProfile: PowerProfile.PowerSaver
property bool powerInitialized: false
// 是否有有效的活动窗口(通过监听 Hyprland 原始事件)
property bool hasActiveWindow: false
// 监听 Hyprland 原始事件来判断是否有活动窗口
Connections {
target: Hyprland
function onRawEvent(event) {
if (event.name === "activewindow") {
// activewindow 事件:格式为 "class,title"
// 如果两者都为空,说明没有活动窗口
root.hasActiveWindow = event.data.length > 1
}
}
}
// 监听电源状态变化自动切换
Connections {
target: UPower
function onOnBatteryChanged() {
if (root.powerInitialized) {
PowerProfiles.profile = UPower.onBattery ? root.batProfile : root.acProfile
}
}
}
// 启动时设置电源模式和初始化活动窗口状态
Component.onCompleted: {
PowerProfiles.profile = UPower.onBattery ? batProfile : acProfile
powerInitialized = true
hasActiveWindow = Hyprland.activeToplevel !== null
}
// 监听活动窗口变化,刷新 toplevel 数据以保持图标和标题同步
Connections {
target: Hyprland
function onActiveToplevelChanged() {
if (Hyprland.activeToplevel !== null) {
Hyprland.refreshToplevels()
}
}
}
// 绑定音频节点以获取音量信息
PwObjectTracker {
objects: [Pipewire.defaultAudioSink]
}
// 获取网络信息
Process {
id: networkProc
command: ["sh", "-c", "nmcli -t -f NAME connection show --active | grep -v '^lo$' | head -1"]
running: true
stdout: SplitParser {
onRead: data => root.networkName = data.trim()
}
}
Timer {
interval: 5000
running: true
repeat: true
onTriggered: {
networkProc.running = true
}
}
// Cava 进程
Process {
id: cavaProcess
stdinEnabled: true
running: root.cavaRunning
command: ["cava", "-p", "/dev/stdin"]
onStarted: {
write("[general]\n")
write("bars=16\n")
write("framerate=60\n")
write("sensitivity=100\n")
write("[output]\n")
write("method=raw\n")
write("data_format=ascii\n")
write("ascii_max_range=100\n")
write("channels=mono\n")
stdinEnabled = false
}
onExited: {
stdinEnabled = true
root.cavaValues = Array(16).fill(0)
}
stdout: SplitParser {
onRead: data => {
var parts = data.slice(0, -1).split(";")
root.cavaValues = parts.map(function(v) { return parseInt(v, 10) / 100 })
}
}
}
Variants {
model: Quickshell.screens
PanelWindow {
id: panel
required property var modelData
screen: modelData
anchors {
top: true
left: true
right: true
}
implicitHeight: 32
color: Qt.rgba(0.102, 0.106, 0.149, 0.85)
// 电源模式弹出菜单
PopupWindow {
id: powerMenu
anchor.window: panel
anchor.rect.x: 0
anchor.rect.y: panel.height
anchor.adjustment: PopupAdjustment.None
visible: root.powerMenuVisible
implicitWidth: panel.width
implicitHeight: 1000
color: "transparent"
// 点击遮罩关闭菜单
MouseArea {
anchors.fill: parent
onClicked: root.powerMenuVisible = false
}
// 菜单内容
Rectangle {
width: 60
height: 28 * 3
color: Qt.rgba(0.102, 0.106, 0.149, 0.95)
Column {
id: menuColumn
anchors.fill: parent
Repeater {
model: [
{ label: "性能", profile: PowerProfile.Performance },
{ label: "平衡", profile: PowerProfile.Balanced },
{ label: "省电", profile: PowerProfile.PowerSaver }
]
Item {
required property var modelData
width: menuColumn.width
height: 28
property bool isActive: PowerProfiles.profile === modelData.profile
Text {
id: menuItemText
anchors.centerIn: parent
text: modelData.label
color: parent.isActive ? "#ffffff" : "#c0caf5"
font.pixelSize: 13
}
Rectangle {
anchors.top: menuItemText.bottom
anchors.topMargin: 2
anchors.horizontalCenter: parent.horizontalCenter
width: menuItemText.implicitWidth
height: 2
color: "#ffffff"
visible: parent.isActive
}
MouseArea {
anchors.fill: parent
onClicked: {
PowerProfiles.profile = modelData.profile
root.powerMenuVisible = false
}
}
}
}
}
}
}
// 点击 bar 其他区域关闭菜单
MouseArea {
id: powerMenuCloser
anchors.fill: parent
enabled: root.powerMenuVisible
onClicked: root.powerMenuVisible = false
z: -1
}
// 左侧: 工作区指示器
Row {
anchors.left: parent.left
anchors.leftMargin: 8
anchors.verticalCenter: parent.verticalCenter
spacing: 8
// 发行版图标 + 电源模式切换
Image {
id: distroIcon
width: 18
height: 18
source: Quickshell.iconPath("nix-snowflake", "distributor-logo-nixos")
fillMode: Image.PreserveAspectFit
anchors.verticalCenter: parent.verticalCenter
MouseArea {
anchors.fill: parent
onClicked: root.powerMenuVisible = !root.powerMenuVisible
}
}
Repeater {
model: Hyprland.workspaces
Item {
required property var modelData
width: 14
height: 24
// 背景:当工作区有紧急窗口时显示红色
Rectangle {
anchors.fill: parent
color: "#f38ba8"
visible: modelData.urgent
}
Text {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
text: modelData.id
color: modelData.focused ? "#ffffff" : "#6c7086"
font.pixelSize: 14
font.bold: modelData.focused
}
Rectangle {
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
width: 12
height: 2
color: "#ffffff"
visible: modelData.focused
}
MouseArea {
anchors.fill: parent
onClicked: modelData.activate()
}
}
}
// 媒体组件
Item {
id: mediaWidget
visible: root.currentPlayer !== null && root.currentPlayer.isPlaying
width: 150
height: 24
clip: true
property string mediaText: {
if (!root.currentPlayer) return ""
var artist = root.currentPlayer.trackArtist
var title = root.currentPlayer.trackTitle || "Unknown"
return artist ? (artist + " - " + title) : title
}
onMediaTextChanged: scrollingRow.updatePosition()
onVisibleChanged: if (visible) scrollingRow.updatePosition()
// 音频波形背景
Canvas {
id: visualizerCanvas
anchors.fill: parent
opacity: 0.5
z: 0
onPaint: {
var ctx = getContext("2d")
ctx.reset()
var barCount = root.cavaValues.length
if (barCount === 0) return
var barWidth = width / barCount
var barGap = 1
ctx.fillStyle = "#89b4fa"
for (var i = 0; i < barCount; i++) {
var barHeight = root.cavaValues[i] * height
var x = i * barWidth
var y = height - barHeight
ctx.fillRect(x + barGap / 2, y, barWidth - barGap, barHeight)
}
}
}
Connections {
target: root
function onCavaValuesChanged() {
visualizerCanvas.requestPaint()
}
}
Text {
id: mediaTextMetrics
visible: false
text: parent.mediaText
font.pixelSize: 12
onImplicitWidthChanged: scrollingRow.updatePosition()
}
Item {
anchors.fill: parent
clip: true
z: 1
Row {
id: scrollingRow
spacing: 50
anchors.verticalCenter: parent.verticalCenter
property bool needsScroll: mediaTextMetrics.implicitWidth > mediaWidget.width
function updatePosition() {
scrollAnimation.stop()
var containerWidth = mediaWidget.width
var textWidth = mediaTextMetrics.implicitWidth
if (textWidth <= 0 || containerWidth <= 0) {
x = 0
return
}
if (needsScroll) {
x = 0
scrollAnimation.start()
} else {
x = Math.max(0, (containerWidth - textWidth) / 2)
}
}
Text {
text: mediaTextMetrics.text
color: "#cdd6f4"
font.pixelSize: 12
}
Text {
visible: scrollingRow.needsScroll
text: mediaTextMetrics.text
color: "#cdd6f4"
font.pixelSize: 12
}
NumberAnimation {
id: scrollAnimation
target: scrollingRow
property: "x"
from: 0
to: -(mediaTextMetrics.implicitWidth + 50)
duration: Math.max(5000, mediaTextMetrics.text.length * 150)
loops: Animation.Infinite
}
}
}
}
}
// 中间: 活动窗口 (全局居中)
Item {
anchors.centerIn: parent
width: windowRow.visible ? Math.min(windowTextMetrics.implicitWidth + 26, 600) : 0
height: 24
visible: root.hasActiveWindow && Hyprland.activeToplevel !== null
property string windowTitle: Hyprland.activeToplevel?.title ?? ""
Text {
id: windowTextMetrics
visible: false
text: parent.windowTitle
font.pixelSize: 14
}
Row {
id: windowRow
anchors.verticalCenter: parent.verticalCenter
spacing: 6
visible: root.hasActiveWindow && Hyprland.activeToplevel !== null
Image {
width: 20
height: 20
source: {
if (Hyprland.activeToplevel === null) return ""
var ipcObj = Hyprland.activeToplevel.lastIpcObject
var appClass = ipcObj?.initialClass || ipcObj?.class || ""
var entry = DesktopEntries.heuristicLookup(appClass)
return entry ? Quickshell.iconPath(entry.icon) : Quickshell.iconPath(appClass)
}
fillMode: Image.PreserveAspectFit
anchors.verticalCenter: parent.verticalCenter
}
Item {
width: Math.min(windowTextMetrics.implicitWidth, 574)
height: 24
clip: true
anchors.verticalCenter: parent.verticalCenter
Row {
id: windowScrollingRow
spacing: 50
anchors.verticalCenter: parent.verticalCenter
property bool needsScroll: windowTextMetrics.implicitWidth > 574
function updatePosition() {
windowScrollAnimation.stop()
var containerWidth = 574
var textWidth = windowTextMetrics.implicitWidth
if (textWidth <= 0 || containerWidth <= 0) {
x = 0
return
}
if (needsScroll) {
x = 0
windowScrollAnimation.start()
} else {
x = 0
}
}
Text {
text: windowTextMetrics.text
color: "#c0caf5"
font.pixelSize: 14
}
Text {
visible: windowScrollingRow.needsScroll
text: windowTextMetrics.text
color: "#c0caf5"
font.pixelSize: 14
}
NumberAnimation {
id: windowScrollAnimation
target: windowScrollingRow
property: "x"
from: 0
to: -(windowTextMetrics.implicitWidth + 50)
duration: Math.max(5000, windowTextMetrics.text.length * 150)
loops: Animation.Infinite
}
Component.onCompleted: updatePosition()
}
Connections {
target: windowRow.parent
function onWindowTitleChanged() {
windowScrollingRow.updatePosition()
}
}
}
}
}
// 右侧
Row {
anchors.right: parent.right
anchors.rightMargin: 8
anchors.verticalCenter: parent.verticalCenter
spacing: 12
// 系统托盘
Row {
spacing: 4
Repeater {
model: SystemTray.items
Item {
id: trayItem
required property var modelData
width: 20
height: 20
Image {
anchors.fill: parent
source: modelData.icon
fillMode: Image.PreserveAspectFit
}
QsMenuAnchor {
id: menuAnchor
menu: modelData.menu
anchor.item: trayItem
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.LeftButton | Qt.RightButton
onClicked: function(mouse) {
if (mouse.button === Qt.LeftButton) {
if (modelData.onlyMenu && modelData.hasMenu) {
menuAnchor.open()
} else {
modelData.activate()
}
} else if (mouse.button === Qt.RightButton && modelData.hasMenu) {
menuAnchor.open()
}
}
}
}
}
}
// 网络
Text {
text: root.networkName || "---"
color: "#c0caf5"
font.pixelSize: 14
}
// 音量
Item {
width: volumeText.implicitWidth
height: 24
property real volumePercent: Pipewire.defaultAudioSink?.audio?.volume ?? 0
property bool isMuted: Pipewire.defaultAudioSink?.audio?.muted ?? false
Text {
id: volumeText
anchors.top: parent.top
text: parent.isMuted ? "0%" : (Math.round(parent.volumePercent * 100) + "%")
color: "#c0caf5"
font.pixelSize: 14
}
Rectangle {
anchors.bottom: parent.bottom
anchors.left: parent.left
width: parent.isMuted ? parent.width : (parent.width * Math.min(1, parent.volumePercent))
height: 2
color: parent.isMuted ? "#f38ba8" : "#89b4fa"
}
}
// 电量
Repeater {
model: UPower.devices
Item {
required property var modelData
visible: modelData.isLaptopBattery
width: batteryText.implicitWidth
height: 24
property real batteryPercent: modelData.energy / modelData.energyCapacity
property bool isCharging: modelData.state === UPowerDeviceState.Charging
Text {
id: batteryText
anchors.top: parent.top
text: Math.round(parent.batteryPercent * 100) + "%"
color: "#c0caf5"
font.pixelSize: 14
}
Item {
id: batteryBar
anchors.bottom: parent.bottom
anchors.left: parent.left
width: parent.width
height: 2
clip: true
Rectangle {
visible: !batteryBar.parent.isCharging
width: parent.width * batteryBar.parent.batteryPercent
height: parent.height
color: {
var pct = batteryBar.parent.batteryPercent
if (pct <= 0.2) return "#f38ba8"
if (pct <= 0.4) return "#fab387"
return "#a6e3a1"
}
}
Rectangle {
id: chargingWave
visible: batteryBar.parent.isCharging
width: 8
height: parent.height
color: "#ffffff"
NumberAnimation on x {
running: chargingWave.visible
from: -8
to: batteryBar.width
duration: 1000
loops: Animation.Infinite
}
}
}
}
}
// 时间
Text {
color: "#c0caf5"
font.pixelSize: 14
SystemClock {
id: systemClock
precision: SystemClock.Minutes
}
text: Qt.formatDateTime(systemClock.date, "hh:mm")
}
}
}
}
}Backtrace
No response
Executable
No response