Compare commits

..

3 Commits

Author SHA1 Message Date
3a98bc08e9 shell: document why UseQApplication is required
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 21:42:03 +02:00
f6796f3726 sysstats: refresh cpuFreq every 3rd tick instead of every tick
/proc/cpuinfo is regenerated in full by the kernel on every read and
its cost grows with core count, making it the priciest per-tick read.
Bar frequency display doesn't need 1 Hz precision.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 21:42:02 +02:00
6655c9c500 bar: wrap onto two rows when one row doesn't fit
On narrow outputs (portrait rotation) the single-row layout overflowed.
Compare the needed width (implicit sizes of all three clusters) against
the window width; when it doesn't fit, double the bar height and move
the metric pills to a second row, keeping workspaces + clock/tray on
the first.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 21:41:13 +02:00
3 changed files with 47 additions and 9 deletions

View File

@@ -52,6 +52,12 @@ Singleton {
// poll interval in seconds
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)
property string tempPath: ""
property string batPath: ""
@@ -271,15 +277,17 @@ Singleton {
}
function _tickOnce() {
const doFreq = root._tick % root.freqEveryTicks === 0;
statView.reload();
cpuInfoView.reload();
if (doFreq) cpuInfoView.reload();
memView.reload();
routeView.reload();
if (root.tempPath) tempView.reload();
if (root.batPath) { batCapView.reload(); batStatusView.reload(); }
_parseCpu();
_parseFreq();
if (doFreq) _parseFreq();
_parseMem();
_parseTemp();
_parseBattery();

View File

@@ -1,4 +1,7 @@
//@ 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 "widgets"

View File

@@ -29,7 +29,20 @@ PanelWindow {
left: 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
Rectangle {
@@ -37,19 +50,35 @@ PanelWindow {
color: Theme.barColor
}
// left: workspaces
// row 1 left: workspaces
Workspaces {
id: workspaces
anchors.left: parent.left
anchors.verticalCenter: parent.verticalCenter
anchors.leftMargin: Theme.gap + 2
y: (Theme.barHeight - height) / 2
screen: panel.modelData
}
// right: battery, system metrics, volume, clock, tray
// row 1 right: clock, tray
RowLayout {
id: endRow
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
anchors.rightMargin: Theme.gap + 2
y: (Theme.barHeight - height) / 2
spacing: Theme.gap
Clock {}
Tray { panelWindow: panel }
}
// metrics: left of the clock in one-row mode, own second row when narrow
RowLayout {
id: metricsRow
anchors.right: panel.twoRows ? parent.right : endRow.left
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
Battery {}
@@ -59,7 +88,5 @@ PanelWindow {
Disk {}
Network {}
Volume {}
Clock {}
Tray { panelWindow: panel }
}
}