feat(quickshell): add dense telemetry bar #4

Open
luna wants to merge 18 commits from feat/quickshell-dense-bar into master
3 changed files with 35 additions and 37 deletions
Showing only changes of commit c69aa4fea2 - Show all commits
@@ -47,6 +47,7 @@ PanelWindow {
visible: scrim.opacity > 0 visible: scrim.opacity > 0
WlrLayershell.namespace: "hyprchrome-scrim"
WlrLayershell.layer: WlrLayer.Top WlrLayershell.layer: WlrLayer.Top
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
exclusionMode: ExclusionMode.Ignore exclusionMode: ExclusionMode.Ignore
@@ -62,44 +62,33 @@ Scope {
// One layer above the scrim, so the stacking is guaranteed rather than // One layer above the scrim, so the stacking is guaranteed rather than
// dependent on surface creation order. See ChromeBackdrop. // dependent on surface creation order. See ChromeBackdrop.
// Own namespace so a layerrule can exempt the rail from Hyprland's layer
// animation without also catching the launchers, which share the default
// "quickshell" namespace and do want their fade.
WlrLayershell.namespace: "hyprchrome-bar"
WlrLayershell.layer: WlrLayer.Overlay WlrLayershell.layer: WlrLayer.Overlay
property int margin: 12 property int margin: 12
// Where the panels will SETTLE, not where they are mid-transition. Binding // The surface never resizes: it is always tall enough for the expanded
// the surface to the animated height instead resizes the layer surface — // rail, and only the exclusive zone tracks the current state. Resizing a
// and, with the automatic exclusive zone, relayouts every tiled window on // layer surface makes Hyprland animate the change, which showed up as the
// this output — on every frame of the animation. // panels twitching a pixel or two the moment the collapse finished.
//
// The zone still follows the target height, so tiled windows reflow once
// per toggle, at the start, and slide while the panels animate.
readonly property real expandedContent: Math.max(hostPanel.expandedHeight, vitalsPanel.expandedHeight, trayPanel.expandedHeight) + window.margin * 2
readonly property real contentHeight: Math.max(hostPanel.targetHeight, vitalsPanel.targetHeight, trayPanel.targetHeight) + window.margin * 2 readonly property real contentHeight: Math.max(hostPanel.targetHeight, vitalsPanel.targetHeight, trayPanel.targetHeight) + window.margin * 2
// The surface and the exclusive zone move on different clocks. The zone is implicitHeight: Math.round(window.expandedContent)
// the desktop-visible half: set it to the target immediately, so the tiled
// windows reflow ONCE, at the start, and slide while the bar animates.
// The surface itself grows before the panels do but shrinks only after they
// have finished, because a surface that shrank immediately would clip the
// panels still animating inside it.
property real barHeight: 0
exclusionMode: ExclusionMode.Normal exclusionMode: ExclusionMode.Normal
exclusiveZone: Math.round(window.contentHeight) exclusiveZone: Math.round(window.contentHeight)
implicitHeight: window.barHeight // Only the panels take input. Without this the surface would keep eating
// clicks across its full height while the rail is collapsed.
onContentHeightChanged: { mask: Region {
if (window.contentHeight > window.barHeight) item: panelRow
window.barHeight = window.contentHeight;
else
shrink.restart();
}
Component.onCompleted: window.barHeight = window.contentHeight
Timer {
id: shrink
// Longer than the panel's own collapse (200ms body + 110ms fade-in).
interval: 340
onTriggered: window.barHeight = window.contentHeight
} }
anchors { top: true; left: true; right: true; } anchors { top: true; left: true; right: true; }
@@ -93,16 +93,24 @@ Item {
property real bodyBottom: detail.y + detail.height property real bodyBottom: detail.y + detail.height
property real bodyEndPadding: panel.padding property real bodyEndPadding: panel.padding
implicitHeight: Math.max(panel.minimumHeight, panel.bodyBottom + panel.bodyEndPadding) // Rounded: bodyBottom and bodyEndPadding are animated reals, so the sum
// spends the tail of every transition on a fraction. A layout rounds that
// UP, then drops a pixel the moment the animation lands on its exact
// value — a 1px hop after the motion has visibly finished.
implicitHeight: Math.round(Math.max(panel.minimumHeight, panel.bodyBottom + panel.bodyEndPadding))
// Where the panel will settle in its current state, skipping the values // Where the panel settles in each state, skipping the values the transition
// the transition passes through. A window sized to this reconfigures once // passes through: a host sizes its surface and its exclusive zone from these
// per toggle rather than once per animation frame — which, for a // rather than from the animated height, so the desktop is relaid out once per
// layer-shell bar with an automatic exclusive zone, is the difference // toggle instead of once per animation frame.
// between one relayout of the desktop and a dozen. // Height of the expanded body regardless of the current state — what a
readonly property real targetHeight: Math.max(panel.minimumHeight, panel.expanded // host needs to size a surface that must not resize when panels collapse.
? detail.y + detail.height + panel.padding readonly property real expandedHeight: Math.round(Math.max(panel.minimumHeight,
: panel.collapsedHeight) detail.y + detail.height + panel.padding))
readonly property real targetHeight: panel.expanded
? panel.expandedHeight
: Math.round(Math.max(panel.minimumHeight, panel.collapsedHeight))
// The two chamfer cuts (top-right at y=chamfer, bottom-left at // The two chamfer cuts (top-right at y=chamfer, bottom-left at