From ed9e68957fe3ceb7e45ff67af67d8ca4c8f3b203 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Thu, 23 Jul 2026 16:48:29 -0700 Subject: [PATCH] Match display scale highlights to clean scales --- bin/omarchy-monitor-state | 3 ++- shell/plugins/panels/monitor/Model.js | 24 ++++++++++++++++++++++++ shell/plugins/panels/monitor/Panel.qml | 11 ++++++++++- test/shell.d/monitor-test.sh | 16 ++++++++++------ 4 files changed, 46 insertions(+), 8 deletions(-) diff --git a/bin/omarchy-monitor-state b/bin/omarchy-monitor-state index 26663aa2..13452679 100755 --- a/bin/omarchy-monitor-state +++ b/bin/omarchy-monitor-state @@ -18,4 +18,5 @@ printf '%s\n' "$monitors_json" | jq -r ' omarchy-hyprland-monitor-focused 2>/dev/null || echo omarchy-hyprland-monitor-scaling 2>/dev/null || echo -printf '%s\n' "$monitors_json" | jq -c '[.[] | {name, enabled:(.disabled != true), focused:(.focused == true)}]' +printf '%s\n' "$monitors_json" | jq -c \ + '[.[] | {name, enabled:(.disabled != true), focused:(.focused == true), width, height}]' diff --git a/shell/plugins/panels/monitor/Model.js b/shell/plugins/panels/monitor/Model.js index afe3efca..b37cf772 100644 --- a/shell/plugins/panels/monitor/Model.js +++ b/shell/plugins/panels/monitor/Model.js @@ -10,6 +10,29 @@ function normalizeScale(scale) { return String(Math.round(n * 100) / 100) } +function gcd(a, b) { + while (b) { + var remainder = a % b + a = b + b = remainder + } + return a +} + +function cleanScale(scale, width, height) { + var requested = Number(scale) + var modeWidth = Number(width) + var modeHeight = Number(height) + if (!isFinite(requested) || !isFinite(modeWidth) || !isFinite(modeHeight) + || requested <= 0 || modeWidth <= 0 || modeHeight <= 0) return "" + + var divisor = gcd(Math.round(modeWidth * 120), Math.round(modeHeight * 120)) + var scaleUnits = Math.round(requested * 120) + if (scaleUnits > divisor) scaleUnits = divisor + while (divisor % scaleUnits !== 0) scaleUnits++ + return normalizeScale(scaleUnits / 120) +} + function brightnessName(percent) { var p = Math.round(percent) if (p >= 95) return "Sun blast" @@ -46,6 +69,7 @@ if (typeof module !== "undefined") { module.exports = { clampBrightness: clampBrightness, normalizeScale: normalizeScale, + cleanScale: cleanScale, brightnessName: brightnessName, parseDisplays: parseDisplays } diff --git a/shell/plugins/panels/monitor/Panel.qml b/shell/plugins/panels/monitor/Panel.qml index b12ce8eb..a7ac51ef 100644 --- a/shell/plugins/panels/monitor/Panel.qml +++ b/shell/plugins/panels/monitor/Panel.qml @@ -246,6 +246,15 @@ Panel { return Model.normalizeScale(scale) } + function effectiveScale(scale) { + for (var i = 0; i < displays.length; i++) { + var display = displays[i] + if (display && display.focused) + return Model.cleanScale(scale, display.width, display.height) + } + return normalizeScale(scale) + } + // Playful mood-name for a given brightness percent. Bands intentionally // span ~10–20 points so casual tweaks change the label, while small // nudges within one band don't. @@ -771,7 +780,7 @@ Panel { verticalPadding: Style.spacing.controlPaddingY bordered: true - active: root.normalizeScale(root.monitorScale) === root.normalizeScale(scaleValue) + active: root.normalizeScale(root.monitorScale) === root.effectiveScale(scaleValue) hasCursor: root.cursorActive && root.focusSection === "scale" && root.selectedIndex === scaleIndex onClicked: root.setScale(scaleValue) diff --git a/test/shell.d/monitor-test.sh b/test/shell.d/monitor-test.sh index aa4ddac7..2fddc9a5 100644 --- a/test/shell.d/monitor-test.sh +++ b/test/shell.d/monitor-test.sh @@ -14,21 +14,25 @@ assertEqual(monitor.clampBrightness('nope'), 1, 'monitor rejects invalid brightn assertEqual(monitor.normalizeScale('1.250'), '1.25', 'monitor normalizes fractional scale') assertEqual(monitor.normalizeScale('nope'), '', 'monitor rejects invalid scale') +assertEqual(monitor.cleanScale(3, 1280, 800), '3.2', 'monitor matches clean VM scale') +assertEqual(monitor.cleanScale(1.25, 1280, 800), '1.25', 'monitor preserves an already clean scale') +assertEqual(monitor.cleanScale(1.25, 6016, 3384), '1.33', 'monitor matches clean physical display scale') +assertEqual(monitor.cleanScale(1.6, 0, 800), '', 'monitor rejects a missing display mode') assertEqual(monitor.brightnessName(96), 'Sun blast', 'monitor names very bright displays') assertEqual(monitor.brightnessName(12), 'Candlelit', 'monitor names dim displays') assertDeepEqual( monitor.parseDisplays(JSON.stringify([ - { name: 'eDP-1', enabled: true }, - { name: 'HDMI-A-1', enabled: false }, - { name: 'DP-1', enabled: true } + { name: 'eDP-1', enabled: true, focused: false, width: 1920, height: 1080 }, + { name: 'HDMI-A-1', enabled: false, focused: false, width: 0, height: 0 }, + { name: 'DP-1', enabled: true, focused: true, width: 1280, height: 800 } ])), { displays: [ - { name: 'eDP-1', enabled: true }, - { name: 'HDMI-A-1', enabled: false }, - { name: 'DP-1', enabled: true } + { name: 'eDP-1', enabled: true, focused: false, width: 1920, height: 1080 }, + { name: 'HDMI-A-1', enabled: false, focused: false, width: 0, height: 0 }, + { name: 'DP-1', enabled: true, focused: true, width: 1280, height: 800 } ], enabledDisplayCount: 2 },