Compare commits
8 Commits
c62e8f10ea
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
3a98bc08e9
|
|||
|
f6796f3726
|
|||
|
6655c9c500
|
|||
|
b7ea18c751
|
|||
|
796be77341
|
|||
|
7a95288f81
|
|||
|
fa3e41ecc2
|
|||
|
e97a2b65c2
|
@@ -11,7 +11,8 @@ Singleton {
|
|||||||
readonly property string thermo: String.fromCharCode(0xf2c9) // thermometer-half
|
readonly property string thermo: String.fromCharCode(0xf2c9) // thermometer-half
|
||||||
readonly property string disk: String.fromCharCode(0xf0a0) // hdd-o
|
readonly property string disk: String.fromCharCode(0xf0a0) // hdd-o
|
||||||
readonly property string wifi: String.fromCharCode(0xf1eb) // wifi
|
readonly property string wifi: String.fromCharCode(0xf1eb) // wifi
|
||||||
readonly property string ethernet: String.fromCharCode(0xf6ff) // network-wired
|
readonly property string ethernet: String.fromCodePoint(0xf0200) // md-ethernet (FA5 network-wired 0xf6ff is absent from the bundled Nerd Fonts)
|
||||||
|
readonly property string netOff: String.fromCodePoint(0xf05aa) // md-wifi-off (shown when there is no active interface)
|
||||||
readonly property string down: String.fromCharCode(0xf063) // arrow-down
|
readonly property string down: String.fromCharCode(0xf063) // arrow-down
|
||||||
readonly property string up: String.fromCharCode(0xf062) // arrow-up
|
readonly property string up: String.fromCharCode(0xf062) // arrow-up
|
||||||
readonly property string clock: String.fromCharCode(0xf017) // clock-o
|
readonly property string clock: String.fromCharCode(0xf017) // clock-o
|
||||||
|
|||||||
@@ -11,28 +11,28 @@ Singleton {
|
|||||||
readonly property int padding: 10
|
readonly property int padding: 10
|
||||||
readonly property int gap: 4
|
readonly property int gap: 4
|
||||||
|
|
||||||
// --- palette (Catppuccin Mocha, darkened toward OLED black) ---
|
// --- palette (deep near-black base, high-contrast foreground) ---
|
||||||
readonly property color base: "#0d0d12"
|
readonly property color base: "#05060a"
|
||||||
readonly property color mantle: "#08080b"
|
readonly property color mantle: "#000000"
|
||||||
readonly property color surface0: "#1c1c28"
|
readonly property color surface0: "#15161f"
|
||||||
readonly property color surface1: "#2a2a3a"
|
readonly property color surface1: "#232532"
|
||||||
readonly property color overlay: "#52526a"
|
readonly property color overlay: "#4a4d63"
|
||||||
readonly property color text: "#cdd6f4"
|
readonly property color text: "#eef1f8"
|
||||||
readonly property color subtext: "#a6adc8"
|
readonly property color subtext: "#b4bbd0"
|
||||||
|
|
||||||
readonly property color rosewater: "#f5e0dc"
|
readonly property color rosewater: "#ffdfd6"
|
||||||
readonly property color red: "#f38ba8"
|
readonly property color red: "#ff7a93"
|
||||||
readonly property color peach: "#fab387"
|
readonly property color peach: "#ffb074"
|
||||||
readonly property color yellow: "#f9e2af"
|
readonly property color yellow: "#ffe07a"
|
||||||
readonly property color green: "#a6e3a1"
|
readonly property color green: "#8ff09a"
|
||||||
readonly property color teal: "#94e2d5"
|
readonly property color teal: "#7ff0df"
|
||||||
readonly property color sky: "#89dceb"
|
readonly property color sky: "#74d9ff"
|
||||||
readonly property color blue: "#89b4fa"
|
readonly property color blue: "#7aa9ff"
|
||||||
readonly property color mauve: "#cba6f7"
|
readonly property color mauve: "#c799ff"
|
||||||
readonly property color lavender: "#b4befe"
|
readonly property color lavender: "#aebcff"
|
||||||
|
|
||||||
// bar background, slightly translucent
|
// bar background, near-opaque true black
|
||||||
readonly property color barColor: Qt.rgba(0.051, 0.051, 0.071, 0.94)
|
readonly property color barColor: Qt.rgba(0.02, 0.024, 0.039, 0.96)
|
||||||
|
|
||||||
// --- typography ---
|
// --- typography ---
|
||||||
readonly property string font: "Inter, sans-serif"
|
readonly property string font: "Inter, sans-serif"
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
packages = forAllSystems (pkgs:
|
packages = forAllSystems (pkgs:
|
||||||
let
|
let
|
||||||
# Quickshell from the upstream flake rather than nixpkgs.
|
# Quickshell from the upstream flake rather than nixpkgs.
|
||||||
qsPkg = quickshell.packages.${pkgs.system}.default;
|
qsPkg = quickshell.packages.${pkgs.stdenv.hostPlatform.system}.default;
|
||||||
|
|
||||||
# Runtime tools the bar relies on: discover.sh (one-shot hardware
|
# Runtime tools the bar relies on: discover.sh (one-shot hardware
|
||||||
# probe), the periodic `df` for disk usage, and `ss` (iproute2) for
|
# probe), the periodic `df` for disk usage, and `ss` (iproute2) for
|
||||||
@@ -65,14 +65,14 @@
|
|||||||
apps = forAllSystems (pkgs: {
|
apps = forAllSystems (pkgs: {
|
||||||
default = {
|
default = {
|
||||||
type = "app";
|
type = "app";
|
||||||
program = "${self.packages.${pkgs.system}.default}/bin/quickshell-bar";
|
program = "${self.packages.${pkgs.stdenv.hostPlatform.system}.default}/bin/quickshell-bar";
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
devShells = forAllSystems (pkgs: {
|
devShells = forAllSystems (pkgs: {
|
||||||
default = pkgs.mkShell {
|
default = pkgs.mkShell {
|
||||||
packages = [
|
packages = [
|
||||||
quickshell.packages.${pkgs.system}.default
|
quickshell.packages.${pkgs.stdenv.hostPlatform.system}.default
|
||||||
pkgs.bash
|
pkgs.bash
|
||||||
pkgs.coreutils
|
pkgs.coreutils
|
||||||
pkgs.iproute2 # ss, for topnet.sh
|
pkgs.iproute2 # ss, for topnet.sh
|
||||||
|
|||||||
@@ -52,6 +52,12 @@ Singleton {
|
|||||||
// poll interval in seconds
|
// poll interval in seconds
|
||||||
readonly property int interval: 1
|
readonly property int interval: 1
|
||||||
|
|
||||||
|
// cpuFreq comes from /proc/cpuinfo, which the kernel regenerates in full on
|
||||||
|
// every read (cost grows with core count) — the priciest per-tick read here.
|
||||||
|
// Frequency on a status bar doesn't need 1 Hz precision, so only refresh it
|
||||||
|
// every Nth tick instead of on the CPU%/mem hot path.
|
||||||
|
readonly property int freqEveryTicks: 3
|
||||||
|
|
||||||
// discovered sysfs paths (filled once by discover.sh)
|
// discovered sysfs paths (filled once by discover.sh)
|
||||||
property string tempPath: ""
|
property string tempPath: ""
|
||||||
property string batPath: ""
|
property string batPath: ""
|
||||||
@@ -271,15 +277,17 @@ Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function _tickOnce() {
|
function _tickOnce() {
|
||||||
|
const doFreq = root._tick % root.freqEveryTicks === 0;
|
||||||
|
|
||||||
statView.reload();
|
statView.reload();
|
||||||
cpuInfoView.reload();
|
if (doFreq) cpuInfoView.reload();
|
||||||
memView.reload();
|
memView.reload();
|
||||||
routeView.reload();
|
routeView.reload();
|
||||||
if (root.tempPath) tempView.reload();
|
if (root.tempPath) tempView.reload();
|
||||||
if (root.batPath) { batCapView.reload(); batStatusView.reload(); }
|
if (root.batPath) { batCapView.reload(); batStatusView.reload(); }
|
||||||
|
|
||||||
_parseCpu();
|
_parseCpu();
|
||||||
_parseFreq();
|
if (doFreq) _parseFreq();
|
||||||
_parseMem();
|
_parseMem();
|
||||||
_parseTemp();
|
_parseTemp();
|
||||||
_parseBattery();
|
_parseBattery();
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
//@ pragma UseQApplication
|
//@ pragma UseQApplication
|
||||||
|
// Required: Quickshell renders the system-tray context menu (right-click in
|
||||||
|
// Tray.qml -> item.display()) via QtWidgets' QMenu. Dropping this loads the
|
||||||
|
// lighter QGuiApplication but breaks tray menus. Verified 2026-06-08.
|
||||||
|
|
||||||
import Quickshell
|
import Quickshell
|
||||||
import "widgets"
|
import "widgets"
|
||||||
|
|||||||
@@ -29,7 +29,20 @@ PanelWindow {
|
|||||||
left: true
|
left: true
|
||||||
right: true
|
right: true
|
||||||
}
|
}
|
||||||
implicitHeight: Theme.barHeight
|
|
||||||
|
// Wrap onto two rows when a single row can't hold everything (portrait
|
||||||
|
// outputs). Needed width is computed from implicit sizes, which don't
|
||||||
|
// depend on which row anything sits in, so this can't bind-loop.
|
||||||
|
readonly property real neededWidth:
|
||||||
|
(Theme.gap + 2) * 2 // outer margins
|
||||||
|
+ workspaces.implicitWidth
|
||||||
|
+ Theme.gap * 4 // breathing room between clusters
|
||||||
|
+ metricsRow.implicitWidth
|
||||||
|
+ Theme.gap
|
||||||
|
+ endRow.implicitWidth
|
||||||
|
readonly property bool twoRows: width > 0 && neededWidth > width
|
||||||
|
|
||||||
|
implicitHeight: twoRows ? Theme.barHeight * 2 : Theme.barHeight
|
||||||
|
|
||||||
// background strip
|
// background strip
|
||||||
Rectangle {
|
Rectangle {
|
||||||
@@ -37,24 +50,35 @@ PanelWindow {
|
|||||||
color: Theme.barColor
|
color: Theme.barColor
|
||||||
}
|
}
|
||||||
|
|
||||||
// left: workspaces
|
// row 1 left: workspaces
|
||||||
Workspaces {
|
Workspaces {
|
||||||
|
id: workspaces
|
||||||
anchors.left: parent.left
|
anchors.left: parent.left
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
|
||||||
anchors.leftMargin: Theme.gap + 2
|
anchors.leftMargin: Theme.gap + 2
|
||||||
|
y: (Theme.barHeight - height) / 2
|
||||||
screen: panel.modelData
|
screen: panel.modelData
|
||||||
}
|
}
|
||||||
|
|
||||||
// center: clock
|
// row 1 right: clock, tray
|
||||||
Clock {
|
RowLayout {
|
||||||
anchors.centerIn: parent
|
id: endRow
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: Theme.gap + 2
|
||||||
|
y: (Theme.barHeight - height) / 2
|
||||||
|
spacing: Theme.gap
|
||||||
|
|
||||||
|
Clock {}
|
||||||
|
Tray { panelWindow: panel }
|
||||||
}
|
}
|
||||||
|
|
||||||
// right: battery, system metrics, volume, tray
|
// metrics: left of the clock in one-row mode, own second row when narrow
|
||||||
RowLayout {
|
RowLayout {
|
||||||
anchors.right: parent.right
|
id: metricsRow
|
||||||
anchors.verticalCenter: parent.verticalCenter
|
anchors.right: panel.twoRows ? parent.right : endRow.left
|
||||||
anchors.rightMargin: Theme.gap + 2
|
anchors.rightMargin: panel.twoRows ? Theme.gap + 2 : Theme.gap
|
||||||
|
y: panel.twoRows
|
||||||
|
? Theme.barHeight + (Theme.barHeight - height) / 2
|
||||||
|
: (Theme.barHeight - height) / 2
|
||||||
spacing: Theme.gap
|
spacing: Theme.gap
|
||||||
|
|
||||||
Battery {}
|
Battery {}
|
||||||
@@ -64,6 +88,5 @@ PanelWindow {
|
|||||||
Disk {}
|
Disk {}
|
||||||
Network {}
|
Network {}
|
||||||
Volume {}
|
Volume {}
|
||||||
Tray { panelWindow: panel }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,11 @@ Item {
|
|||||||
spacing: Theme.spacing
|
spacing: Theme.spacing
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
text: SysStats.iface.startsWith("wl") ? Icons.wifi : Icons.ethernet
|
text: SysStats.iface === "" ? Icons.netOff
|
||||||
|
: SysStats.iface.startsWith("wl") ? Icons.wifi : Icons.ethernet
|
||||||
font.family: Theme.monoFont
|
font.family: Theme.monoFont
|
||||||
font.pixelSize: Theme.fontSize + 1
|
font.pixelSize: Theme.fontSize + 1
|
||||||
color: Theme.sky
|
color: SysStats.iface === "" ? Theme.overlay : Theme.sky
|
||||||
Layout.alignment: Qt.AlignVCenter
|
Layout.alignment: Qt.AlignVCenter
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,10 +128,11 @@ Item {
|
|||||||
spacing: Theme.spacing
|
spacing: Theme.spacing
|
||||||
|
|
||||||
Text {
|
Text {
|
||||||
text: SysStats.iface.startsWith("wl") ? Icons.wifi : Icons.ethernet
|
text: SysStats.iface === "" ? Icons.netOff
|
||||||
|
: SysStats.iface.startsWith("wl") ? Icons.wifi : Icons.ethernet
|
||||||
font.family: Theme.monoFont
|
font.family: Theme.monoFont
|
||||||
font.pixelSize: Theme.fontSize + 1
|
font.pixelSize: Theme.fontSize + 1
|
||||||
color: Theme.sky
|
color: SysStats.iface === "" ? Theme.overlay : Theme.sky
|
||||||
}
|
}
|
||||||
Text {
|
Text {
|
||||||
text: "Network by process"
|
text: "Network by process"
|
||||||
|
|||||||
@@ -17,11 +17,20 @@ MouseArea {
|
|||||||
cursorShape: Qt.PointingHandCursor
|
cursorShape: Qt.PointingHandCursor
|
||||||
acceptedButtons: Qt.LeftButton
|
acceptedButtons: Qt.LeftButton
|
||||||
|
|
||||||
|
// accumulate raw wheel deltas so high-res / inertial scrolling doesn't
|
||||||
|
// fire a full step per micro-event; one notch (120 units) == one step
|
||||||
|
property real _wheelAccum: 0
|
||||||
|
readonly property real _wheelStep: 0.02
|
||||||
|
|
||||||
onClicked: { if (audio) audio.muted = !audio.muted; }
|
onClicked: { if (audio) audio.muted = !audio.muted; }
|
||||||
onWheel: wheel => {
|
onWheel: wheel => {
|
||||||
if (!audio) return;
|
if (!audio) return;
|
||||||
|
_wheelAccum += wheel.angleDelta.y;
|
||||||
|
const notches = Math.trunc(_wheelAccum / 120);
|
||||||
|
if (notches === 0) return;
|
||||||
|
_wheelAccum -= notches * 120;
|
||||||
audio.volume = Math.max(0, Math.min(1,
|
audio.volume = Math.max(0, Math.min(1,
|
||||||
audio.volume + (wheel.angleDelta.y > 0 ? 0.05 : -0.05)));
|
audio.volume + notches * _wheelStep));
|
||||||
}
|
}
|
||||||
|
|
||||||
// keep the sink's audio properties live
|
// keep the sink's audio properties live
|
||||||
|
|||||||
Reference in New Issue
Block a user