diff --git a/hypr/hyprland.lua b/hypr/hyprland.lua index 2f6f5d9..6e9a9f8 100644 --- a/hypr/hyprland.lua +++ b/hypr/hyprland.lua @@ -28,6 +28,7 @@ hl.env("LIBVA_DRIVER_NAME", "nvidia") hl.env("__GLX_VENDOR_LIBRARY_NAME", "nvidia") hl.env("ELECTRON_OZONE_PLATFORM_HINT", "auto") hl.env("QT_QPA_PLATFORM", "wayland;xcb") +hl.env("QT_QPA_PLATFORMTHEME", "gtk3") hl.monitor({ output = "HDMI-A-2", diff --git a/quickshell/Bar.qml b/quickshell/Bar.qml index 483428c..d405d7a 100644 --- a/quickshell/Bar.qml +++ b/quickshell/Bar.qml @@ -7,13 +7,14 @@ import QtQuick.Layouts import Quickshell.Services.SystemTray import Quickshell.DBusMenu +import Quickshell.Widgets Scope { id: root property string time property int cpuUsage: 0 - property int memUsage: 0 + property string memUsage: "0" property var lastCpuIdle: 0 property var lastCpuTotal: 0 @@ -47,15 +48,15 @@ Scope { Process { id: memProc - command: ["sh", "-c", "free | grep Mem"] + command: ["sh", "-c", "free -m | grep Mem"] stdout: SplitParser { onRead: data => { if (!data) return; var parts = data.trim().split(/\s+/); - var total = parseInt(parts[1]) || 1; - var used = parseInt(parts[2]) || 0; - memUsage = Math.round(100 * used / total); + var total = (parts[1] / 1000).toFixed(2) || 1; + var used = (parts[2] / 1000).toFixed(2) || 0; + memUsage = `${used} / ${total}`; } } Component.onCompleted: running = true @@ -92,10 +93,6 @@ Scope { property string fontFamily: "Inter" property int fontSize: 16 - BackgroundEffect.blurRegion: Region { - item: barRoot.contentItem - } - anchors.bottom: true anchors.left: true anchors.right: true @@ -120,8 +117,8 @@ Scope { color: isActive ? barRoot.colRed : barRoot.colFg font { - family: root.fontFamily - pixelSize: root.fontSize + family: barRoot.fontFamily + pixelSize: barRoot.fontSize bold: true } @@ -141,8 +138,8 @@ Scope { color: barRoot.colFg font { - family: root.fontFamily - pixelSize: root.fontSize + family: barRoot.fontFamily + pixelSize: barRoot.fontSize bold: true } text: timeStr @@ -150,7 +147,7 @@ Scope { MouseArea { anchors.fill: parent onClicked: { - clock.timeFmt = (clock.timeFmt === "h:mm:ss AP") ? "ddd, MMM d - h:mm:ss AP" : "h:mm:ss AP"; + clock.timeFmt = (clock.timeFmt === "h:mm:ss AP") ? "dddd M/d/yyyy - h:mm:ss AP" : "h:mm:ss AP"; } } } @@ -159,13 +156,18 @@ Scope { Layout.fillWidth: true } + IconImage { + implicitSize: 20 + source: Quickshell.iconPath("device_cpu") + } + // CPU Text { - text: "CPU: " + cpuUsage + "%" + text: `${cpuUsage}%` color: barRoot.colFg font { - family: root.fontFamily - pixelSize: root.fontSize + family: barRoot.fontFamily + pixelSize: barRoot.fontSize bold: true } } @@ -176,13 +178,18 @@ Scope { color: root.colMuted } + IconImage { + implicitSize: 20 + source: Quickshell.iconPath("memory") + } + // Memory Text { - text: "Mem: " + memUsage + "%" + text: `${memUsage} GB` color: barRoot.colFg font { - family: root.fontFamily - pixelSize: root.fontSize + family: barRoot.fontFamily + pixelSize: barRoot.fontSize bold: true } } @@ -204,6 +211,10 @@ Scope { } } } + + BackgroundEffect.blurRegion: Region { + item: barRoot.contentItem + } } } } diff --git a/quickshell/VolumeOSD.qml b/quickshell/VolumeOSD.qml new file mode 100644 index 0000000..96b69de --- /dev/null +++ b/quickshell/VolumeOSD.qml @@ -0,0 +1,94 @@ +import QtQuick +import QtQuick.Layouts +import Quickshell +import Quickshell.Services.Pipewire +import Quickshell.Widgets + +Scope { + id: volumeOSD + + // Bind the pipewire node so its volume will be tracked + PwObjectTracker { + objects: [Pipewire.defaultAudioSink] + } + + Connections { + target: Pipewire.defaultAudioSink?.audio + + function onVolumeChanged() { + volumeOSD.shouldShowOsd = true; + hideTimer.restart(); + } + } + + property bool shouldShowOsd: false + + Timer { + id: hideTimer + interval: 1000 + onTriggered: volumeOSD.shouldShowOsd = false + } + + // The OSD window will be created and destroyed based on shouldShowOsd. + // PanelWindow.visible could be set instead of using a loader, but using + // a loader will reduce the memory overhead when the window isn't open. + LazyLoader { + active: volumeOSD.shouldShowOsd + + PanelWindow { + anchors.bottom: true + margins.bottom: screen.height / 5 + exclusiveZone: 0 + + implicitWidth: 400 + implicitHeight: 50 + color: "transparent" + + // An empty click mask prevents the window from blocking mouse events. + mask: Region {} + + Rectangle { + anchors.fill: parent + radius: height / 2 + color: "#80000000" + + RowLayout { + anchors { + fill: parent + leftMargin: 10 + rightMargin: 15 + } + + IconImage { + implicitSize: 30 + source: Quickshell.iconPath("audio-volume-high-symbolic") + } + + Rectangle { + // Stretches to fill all left-over space + Layout.fillWidth: true + + implicitHeight: 10 + radius: 20 + color: "#50ffffff" + Rectangle { + anchors { + left: parent.left + top: parent.top + bottom: parent.bottom + } + + implicitWidth: parent.width * (Pipewire.defaultAudioSink?.audio.volume ?? 0) + radius: parent.radius + } + } + + Text { + text: `${Math.round((Pipewire.defaultAudioSink?.audio.volume ?? 0) * 100)}%` + color: "white" + } + } + } + } + } +} diff --git a/quickshell/shell.qml b/quickshell/shell.qml index 9d093ad..9785164 100644 --- a/quickshell/shell.qml +++ b/quickshell/shell.qml @@ -1,5 +1,6 @@ import Quickshell Scope { - Bar {} + Bar {} + VolumeOSD {} }