Align bar icons on a shared baseline
This commit is contained in:
@@ -343,6 +343,7 @@ QtObject {
|
||||
readonly property int sizeVertical: root.barToken("size-vertical", 28)
|
||||
readonly property int iconSlot: root.barToken("icon-slot", 27)
|
||||
readonly property int iconCanvas: root.barToken("icon-canvas", 16)
|
||||
readonly property int iconFont: root.barToken("icon-font", 13)
|
||||
}
|
||||
|
||||
function refresh() {
|
||||
|
||||
@@ -9,11 +9,12 @@ WidgetButton {
|
||||
property real opticalSize: Style.bar.iconCanvas
|
||||
property bool debugOpticalBounds: Quickshell.env("OMARCHY_DEBUG_BAR_ICONS") === "1"
|
||||
readonly property real opticalCenterErrorX: glyph.visible ? glyph.paintedCenterX - opticalCanvas.width / 2 : 0
|
||||
readonly property real opticalCenterErrorY: glyph.visible ? glyph.paintedCenterY - opticalCanvas.height / 2 : 0
|
||||
readonly property real glyphBaselineY: glyph.visible ? glyph.baselineY : 0
|
||||
readonly property int glyphFontSize: glyph.visible ? glyph.renderedFontSize : 0
|
||||
|
||||
labelVisible: false
|
||||
hasVisualContent: text !== "" || iconComponent !== null
|
||||
fontSize: Style.font.body
|
||||
fontSize: Style.bar.iconFont
|
||||
fixedWidth: vertical ? -1 : Style.bar.iconSlot
|
||||
fixedHeight: vertical ? Style.bar.iconSlot : -1
|
||||
|
||||
|
||||
+15
-18
@@ -8,43 +8,31 @@ Item {
|
||||
property string fontFamily: Style.font.family
|
||||
property real fontSize: Style.font.body
|
||||
property color color: Color.foreground
|
||||
property real targetExtent: Math.min(width, height) * 0.82
|
||||
property bool debugBounds: false
|
||||
|
||||
readonly property real baseTightWidth: Math.max(1, baseMetrics.tightBoundingRect.width)
|
||||
readonly property real baseTightHeight: Math.max(1, baseMetrics.tightBoundingRect.height)
|
||||
readonly property real normalizedScale: Math.min(1.5, targetExtent / Math.max(baseTightWidth, baseTightHeight))
|
||||
readonly property int normalizedFontSize: Math.max(1, Math.round(fontSize * normalizedScale))
|
||||
readonly property int renderedFontSize: Math.max(1, Math.round(fontSize))
|
||||
readonly property real tightWidth: Math.max(1, glyphMetrics.tightBoundingRect.width)
|
||||
readonly property real tightHeight: Math.max(1, glyphMetrics.tightBoundingRect.height)
|
||||
readonly property real horizontalCorrection: glyph.implicitWidth / 2 - (glyphMetrics.tightBoundingRect.x + tightWidth / 2)
|
||||
readonly property real verticalCorrection: glyph.implicitHeight / 2 - (glyph.baselineOffset + glyphMetrics.tightBoundingRect.y + tightHeight / 2)
|
||||
readonly property real paintedCenterX: glyph.x + glyphMetrics.tightBoundingRect.x + tightWidth / 2
|
||||
readonly property real paintedCenterY: glyph.y + glyph.baselineOffset + glyphMetrics.tightBoundingRect.y + tightHeight / 2
|
||||
|
||||
TextMetrics {
|
||||
id: baseMetrics
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: root.fontSize
|
||||
text: root.text
|
||||
}
|
||||
readonly property real baselineY: glyph.y + glyph.baselineOffset
|
||||
|
||||
TextMetrics {
|
||||
id: glyphMetrics
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: root.normalizedFontSize
|
||||
font.pixelSize: root.renderedFontSize
|
||||
text: root.text
|
||||
}
|
||||
|
||||
Text {
|
||||
id: glyph
|
||||
// Keep the shared line box and baseline intact. Correcting only the
|
||||
// horizontal painted bounds avoids per-glyph vertical drift.
|
||||
anchors.centerIn: parent
|
||||
anchors.horizontalCenterOffset: root.horizontalCorrection
|
||||
anchors.verticalCenterOffset: root.verticalCorrection
|
||||
text: root.text
|
||||
color: root.color
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: root.normalizedFontSize
|
||||
font.pixelSize: root.renderedFontSize
|
||||
renderType: Text.NativeRendering
|
||||
}
|
||||
|
||||
@@ -55,4 +43,13 @@ Item {
|
||||
border.width: 1
|
||||
border.color: "#4488ff"
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
visible: root.debugBounds
|
||||
x: 0
|
||||
y: Math.round(root.baselineY)
|
||||
width: parent.width
|
||||
height: 1
|
||||
color: "#44ff88"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,8 +38,12 @@ ShellRoot {
|
||||
fail(name + " optical canvas is " + icon.opticalSize)
|
||||
return false
|
||||
}
|
||||
if (Math.abs(icon.opticalCenterErrorX) > 0.5 || Math.abs(icon.opticalCenterErrorY) > 0.5) {
|
||||
fail(name + " painted bounds are over half a pixel off center by " + icon.opticalCenterErrorX + "," + icon.opticalCenterErrorY)
|
||||
if (Math.abs(icon.opticalCenterErrorX) > 0.5) {
|
||||
fail(name + " painted bounds are over half a pixel off center by " + icon.opticalCenterErrorX)
|
||||
return false
|
||||
}
|
||||
if (icon.glyphFontSize !== Style.bar.iconFont) {
|
||||
fail(name + " font size is " + icon.glyphFontSize)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
@@ -51,6 +55,12 @@ ShellRoot {
|
||||
if (!checkIcon(audio, "audio")) return
|
||||
if (!checkIcon(monitor, "monitor")) return
|
||||
if (!checkIcon(power, "power")) return
|
||||
var baseline = bluetooth.glyphBaselineY
|
||||
if (network.glyphBaselineY !== baseline || audio.glyphBaselineY !== baseline
|
||||
|| monitor.glyphBaselineY !== baseline || power.glyphBaselineY !== baseline) {
|
||||
fail("glyph baselines do not match")
|
||||
return
|
||||
}
|
||||
if (vector.implicitWidth !== Style.bar.iconSlot || vector.opticalSize !== Style.bar.iconCanvas) {
|
||||
fail("vector icon does not share glyph geometry")
|
||||
return
|
||||
@@ -96,7 +106,7 @@ output=$(timeout 15 env \
|
||||
|
||||
if ! grep -q 'RESULT pass' <<<"$output"; then
|
||||
printf '%s\n' "$output" >&2
|
||||
fail "bar icons share centered optical geometry"
|
||||
fail "bar icons share slot and baseline geometry"
|
||||
fi
|
||||
|
||||
pass "bar icons share centered optical geometry"
|
||||
pass "bar icons share slot and baseline geometry"
|
||||
|
||||
Reference in New Issue
Block a user