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"
|
"$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() {
|
set_scale() {
|
||||||
local new_scale="$1"
|
local requested_scale="$1"
|
||||||
local requested="${2:-$new_scale}"
|
local requested="${2:-$requested_scale}"
|
||||||
local monitor_info="$(hyprctl monitors -j | jq -e -c '.[] | select(.focused == true)')"
|
local monitor_info="$(hyprctl monitors -j | jq -e -c '.[] | select(.focused == true)')"
|
||||||
local active_monitor="$(echo "$monitor_info" | jq -r '.name')"
|
local active_monitor="$(echo "$monitor_info" | jq -r '.name')"
|
||||||
local current_scale="$(echo "$monitor_info" | jq -r '.scale')"
|
local current_scale="$(echo "$monitor_info" | jq -r '.scale')"
|
||||||
local width="$(echo "$monitor_info" | jq -r '.width')"
|
local width="$(echo "$monitor_info" | jq -r '.width')"
|
||||||
local height="$(echo "$monitor_info" | jq -r '.height')"
|
local height="$(echo "$monitor_info" | jq -r '.height')"
|
||||||
local refresh_rate="$(echo "$monitor_info" | jq -r '.refreshRate')"
|
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"
|
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
|
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
|
#!/bin/bash
|
||||||
|
|
||||||
if [[ $1 == "monitors" && $2 == "-j" ]]; then
|
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
|
elif [[ $1 == "eval" ]]; then
|
||||||
printf '%s\n' "$2" >"$OMARCHY_TEST_HYPRCTL_EVAL_OUT"
|
printf '%s\n' "$2" >"$OMARCHY_TEST_HYPRCTL_EVAL_OUT"
|
||||||
else
|
else
|
||||||
@@ -72,3 +73,15 @@ pass "monitor scaling explicit 3x remains available"
|
|||||||
scale=$(OMARCHY_TEST_MONITOR_SCALE=3 run_scaling)
|
scale=$(OMARCHY_TEST_MONITOR_SCALE=3 run_scaling)
|
||||||
[[ $scale == "3" ]] || fail "monitor scaling reports explicit 3x scale" "actual: $scale"
|
[[ $scale == "3" ]] || fail "monitor scaling reports explicit 3x scale" "actual: $scale"
|
||||||
pass "monitor scaling reports explicit 3x 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