diff --git a/shell/Commons/Style.qml b/shell/Commons/Style.qml index 8854e052..b099e6f8 100644 --- a/shell/Commons/Style.qml +++ b/shell/Commons/Style.qml @@ -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() { diff --git a/shell/Ui/BarIconButton.qml b/shell/Ui/BarIconButton.qml index 21c4e94f..50275d4a 100644 --- a/shell/Ui/BarIconButton.qml +++ b/shell/Ui/BarIconButton.qml @@ -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 diff --git a/shell/Ui/OpticalGlyph.qml b/shell/Ui/OpticalGlyph.qml index 0900d78d..d446a52c 100644 --- a/shell/Ui/OpticalGlyph.qml +++ b/shell/Ui/OpticalGlyph.qml @@ -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" + } } diff --git a/test/shell.d/bar-icon-geometry-test.sh b/test/shell.d/bar-icon-geometry-test.sh index 6e6eb5cd..3d46feb7 100644 --- a/test/shell.d/bar-icon-geometry-test.sh +++ b/test/shell.d/bar-icon-geometry-test.sh @@ -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"