Snap monitor scaling up to the nearest clean scale Hyprland accepts
Hyprland only takes scales where the mode divides into whole logical pixels (in 1/120 steps), so picking 3x on a 1280x800 QEMU display threw a red error overlay and silently kept the old scale. Round the request up to the nearest clean divisor instead, so 3x becomes 3.2x. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
503388b4d6
commit
0526ebefcc
@@ -52,15 +52,32 @@ audit_scale_change() {
|
||||
"$grandparent_cmd" >>"$SCALE_LOG"
|
||||
}
|
||||
|
||||
# Hyprland only accepts scales where the mode divides into whole logical
|
||||
# pixels (in 1/120 steps), so clean scales are divisors of gcd(w*120, h*120).
|
||||
# Round the requested scale up to the nearest one, so 3x on a 1280x800 QEMU
|
||||
# display becomes 3.2x instead of a red error overlay.
|
||||
clean_scale() {
|
||||
awk -v scale="$1" -v width="$2" -v height="$3" '
|
||||
function gcd(a, b, t) { while (b) { t = a % b; a = b; b = t } return a }
|
||||
BEGIN {
|
||||
g = gcd(width * 120, height * 120)
|
||||
k = int(scale * 120 + 0.5)
|
||||
if (k > g) k = g
|
||||
while (g % k != 0) k++
|
||||
printf "%g\n", k / 120
|
||||
}'
|
||||
}
|
||||
|
||||
set_scale() {
|
||||
local new_scale="$1"
|
||||
local requested="${2:-$new_scale}"
|
||||
local requested_scale="$1"
|
||||
local requested="${2:-$requested_scale}"
|
||||
local monitor_info="$(hyprctl monitors -j | jq -e -c '.[] | select(.focused == true)')"
|
||||
local active_monitor="$(echo "$monitor_info" | jq -r '.name')"
|
||||
local current_scale="$(echo "$monitor_info" | jq -r '.scale')"
|
||||
local width="$(echo "$monitor_info" | jq -r '.width')"
|
||||
local height="$(echo "$monitor_info" | jq -r '.height')"
|
||||
local refresh_rate="$(echo "$monitor_info" | jq -r '.refreshRate')"
|
||||
local new_scale="$(clean_scale "$requested_scale" "$width" "$height")"
|
||||
local monitor_lua="$HOME/.config/hypr/monitors.lua"
|
||||
|
||||
hyprctl eval "hl.monitor({ output = \"$active_monitor\", mode = \"${width}x${height}@${refresh_rate}\", position = \"auto\", scale = $new_scale })" >/dev/null
|
||||
|
||||
@@ -19,7 +19,8 @@ cat >"$stub_bin/hyprctl" <<'SH'
|
||||
#!/bin/bash
|
||||
|
||||
if [[ $1 == "monitors" && $2 == "-j" ]]; then
|
||||
printf '[{"name":"eDP-1","focused":true,"scale":%s,"width":2880,"height":1800,"refreshRate":120.0}]' "${OMARCHY_TEST_MONITOR_SCALE:-2}"
|
||||
printf '[{"name":"eDP-1","focused":true,"scale":%s,"width":%s,"height":%s,"refreshRate":120.0}]' \
|
||||
"${OMARCHY_TEST_MONITOR_SCALE:-2}" "${OMARCHY_TEST_MONITOR_WIDTH:-2880}" "${OMARCHY_TEST_MONITOR_HEIGHT:-1800}"
|
||||
elif [[ $1 == "eval" ]]; then
|
||||
printf '%s\n' "$2" >"$OMARCHY_TEST_HYPRCTL_EVAL_OUT"
|
||||
else
|
||||
@@ -72,3 +73,15 @@ pass "monitor scaling explicit 3x remains available"
|
||||
scale=$(OMARCHY_TEST_MONITOR_SCALE=3 run_scaling)
|
||||
[[ $scale == "3" ]] || fail "monitor scaling reports explicit 3x scale" "actual: $scale"
|
||||
pass "monitor scaling reports explicit 3x scale"
|
||||
|
||||
# 1280x800 (QEMU virtio-gpu) can't divide cleanly by 3; expect a snap up to 3.2.
|
||||
write_monitor_config
|
||||
OMARCHY_TEST_MONITOR_SCALE=2 OMARCHY_TEST_MONITOR_WIDTH=1280 OMARCHY_TEST_MONITOR_HEIGHT=800 run_scaling 3
|
||||
grep -F 'scale = 3.2' "$eval_out" >/dev/null || fail "monitor scaling snaps unclean 3x up to 3.2x"
|
||||
grep -Fx 'local omarchy_monitor_scale = 3.2' "$monitor_lua" >/dev/null || fail "monitor scaling persists snapped 3.2x"
|
||||
pass "monitor scaling snaps unclean 3x up to 3.2x"
|
||||
|
||||
write_monitor_config
|
||||
OMARCHY_TEST_MONITOR_SCALE=2 OMARCHY_TEST_MONITOR_WIDTH=1280 OMARCHY_TEST_MONITOR_HEIGHT=800 run_scaling up
|
||||
grep -F 'scale = 3.2' "$eval_out" >/dev/null || fail "monitor scaling up snaps unclean preset to 3.2x"
|
||||
pass "monitor scaling up snaps unclean preset to 3.2x"
|
||||
|
||||
Reference in New Issue
Block a user