Work with any resolution monitor
This commit is contained in:
@@ -1,22 +1,165 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# Get the current scale from the first monitor
|
# Get the active monitor (the one with the cursor)
|
||||||
CURRENT_SCALE=$(hyprctl monitors -j | jq -r '.[0].scale')
|
ACTIVE_MONITOR=$(hyprctl monitors -j | jq -r '.[] | select(.focused == true) | .name')
|
||||||
|
MONITOR_INFO=$(hyprctl monitors -j | jq -r '.[] | select(.focused == true)')
|
||||||
|
|
||||||
# Define the scaling cycle based on current scale
|
# Get current scale and pixel dimensions of active monitor
|
||||||
# Cycles through 1.00 → 1.60 → 2.00 → 3.13 → 1.00
|
CURRENT_SCALE=$(echo "$MONITOR_INFO" | jq -r '.scale')
|
||||||
case "$CURRENT_SCALE" in
|
PIXEL_WIDTH=$(echo "$MONITOR_INFO" | jq -r '.width')
|
||||||
1.00) NEW_SCALE="1.6" ;;
|
PIXEL_HEIGHT=$(echo "$MONITOR_INFO" | jq -r '.height')
|
||||||
1.60) NEW_SCALE="2" ;;
|
|
||||||
2.00) NEW_SCALE="3.13" ;;
|
|
||||||
3.13) NEW_SCALE="1" ;;
|
|
||||||
*) NEW_SCALE="2" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Apply the new scale to all monitors
|
# Function to check if a scale produces integer logical dimensions using awk
|
||||||
hyprctl monitors -j | jq -r '.[].name' | while read -r monitor; do
|
is_valid_scale() {
|
||||||
hyprctl keyword monitor "$monitor,preferred,auto,$NEW_SCALE"
|
local scale=$1
|
||||||
done
|
local width=$2
|
||||||
|
local height=$3
|
||||||
|
|
||||||
|
awk -v w="$width" -v h="$height" -v s="$scale" 'BEGIN {
|
||||||
|
logical_w = w / s
|
||||||
|
logical_h = h / s
|
||||||
|
rounded_w = int(logical_w + 0.5)
|
||||||
|
rounded_h = int(logical_h + 0.5)
|
||||||
|
diff_w = (logical_w - rounded_w) < 0 ? -(logical_w - rounded_w) : (logical_w - rounded_w)
|
||||||
|
diff_h = (logical_h - rounded_h) < 0 ? -(logical_h - rounded_h) : (logical_h - rounded_h)
|
||||||
|
if (diff_w < 0.0001 && diff_h < 0.0001) exit 0
|
||||||
|
exit 1
|
||||||
|
}'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Function to find the nearest valid scale for a target
|
||||||
|
find_nearest_valid_scale() {
|
||||||
|
local target=$1
|
||||||
|
local width=$2
|
||||||
|
local height=$3
|
||||||
|
|
||||||
|
# Round to nearest 1/120th (Hyprland's precision)
|
||||||
|
awk -v t="$target" -v w="$width" -v h="$height" 'BEGIN {
|
||||||
|
base = t * 120
|
||||||
|
rounded = int(base + 0.5)
|
||||||
|
scale_zero = rounded / 120
|
||||||
|
|
||||||
|
# Test scale_zero first
|
||||||
|
logical_w = w / scale_zero
|
||||||
|
logical_h = h / scale_zero
|
||||||
|
rnd_w = int(logical_w + 0.5)
|
||||||
|
rnd_h = int(logical_h + 0.5)
|
||||||
|
diff_w = (logical_w - rnd_w) < 0 ? -(logical_w - rnd_w) : (logical_w - rnd_w)
|
||||||
|
diff_h = (logical_h - rnd_h) < 0 ? -(logical_h - rnd_h) : (logical_h - rnd_h)
|
||||||
|
|
||||||
|
if (diff_w < 0.0001 && diff_h < 0.0001) {
|
||||||
|
printf "%.6f\n", scale_zero
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Search outward
|
||||||
|
for (i = 1; i <= 90; i++) {
|
||||||
|
scale_up = (rounded + i) / 120
|
||||||
|
scale_down = (rounded - i) / 120
|
||||||
|
|
||||||
|
# Test scale_up
|
||||||
|
logical_w = w / scale_up
|
||||||
|
logical_h = h / scale_up
|
||||||
|
rnd_w = int(logical_w + 0.5)
|
||||||
|
rnd_h = int(logical_h + 0.5)
|
||||||
|
diff_w = (logical_w - rnd_w) < 0 ? -(logical_w - rnd_w) : (logical_w - rnd_w)
|
||||||
|
diff_h = (logical_h - rnd_h) < 0 ? -(logical_h - rnd_h) : (logical_h - rnd_h)
|
||||||
|
|
||||||
|
if (diff_w < 0.0001 && diff_h < 0.0001) {
|
||||||
|
printf "%.6f\n", scale_up
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test scale_down (must be > 0.1)
|
||||||
|
if (scale_down > 0.1) {
|
||||||
|
logical_w = w / scale_down
|
||||||
|
logical_h = h / scale_down
|
||||||
|
rnd_w = int(logical_w + 0.5)
|
||||||
|
rnd_h = int(logical_h + 0.5)
|
||||||
|
diff_w = (logical_w - rnd_w) < 0 ? -(logical_w - rnd_w) : (logical_w - rnd_w)
|
||||||
|
diff_h = (logical_h - rnd_h) < 0 ? -(logical_h - rnd_h) : (logical_h - rnd_h)
|
||||||
|
|
||||||
|
if (diff_w < 0.0001 && diff_h < 0.0001) {
|
||||||
|
printf "%.6f\n", scale_down
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fallback
|
||||||
|
printf "%.6f\n", scale_zero
|
||||||
|
}'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Define target scales and find their nearest valid equivalents
|
||||||
|
TARGET_SCALE_1=$(find_nearest_valid_scale "1" "$PIXEL_WIDTH" "$PIXEL_HEIGHT")
|
||||||
|
TARGET_SCALE_1_6=$(find_nearest_valid_scale "1.6" "$PIXEL_WIDTH" "$PIXEL_HEIGHT")
|
||||||
|
TARGET_SCALE_2=$(find_nearest_valid_scale "2" "$PIXEL_WIDTH" "$PIXEL_HEIGHT")
|
||||||
|
TARGET_SCALE_3=$(find_nearest_valid_scale "3" "$PIXEL_WIDTH" "$PIXEL_HEIGHT")
|
||||||
|
|
||||||
|
# Convert to comparable integers (multiply by 100) to avoid floating point issues
|
||||||
|
CURRENT_INT=$(echo "$CURRENT_SCALE" | awk '{printf "%.0f", $1 * 100}')
|
||||||
|
SCALE_1_INT=$(echo "$TARGET_SCALE_1" | awk '{printf "%.0f", $1 * 100}')
|
||||||
|
SCALE_1_6_INT=$(echo "$TARGET_SCALE_1_6" | awk '{printf "%.0f", $1 * 100}')
|
||||||
|
SCALE_2_INT=$(echo "$TARGET_SCALE_2" | awk '{printf "%.0f", $1 * 100}')
|
||||||
|
SCALE_3_INT=$(echo "$TARGET_SCALE_3" | awk '{printf "%.0f", $1 * 100}')
|
||||||
|
|
||||||
|
# Determine next scale using integer comparison
|
||||||
|
if [[ "$CURRENT_INT" -eq "$SCALE_1_INT" ]]; then
|
||||||
|
NEW_SCALE="$TARGET_SCALE_1_6"
|
||||||
|
elif [[ "$CURRENT_INT" -eq "$SCALE_1_6_INT" ]]; then
|
||||||
|
NEW_SCALE="$TARGET_SCALE_2"
|
||||||
|
elif [[ "$CURRENT_INT" -eq "$SCALE_2_INT" ]]; then
|
||||||
|
NEW_SCALE="$TARGET_SCALE_3"
|
||||||
|
elif [[ "$CURRENT_INT" -eq "$SCALE_3_INT" ]]; then
|
||||||
|
NEW_SCALE="$TARGET_SCALE_1"
|
||||||
|
else
|
||||||
|
# Find closest target to determine where we are
|
||||||
|
DIFF_1=$((CURRENT_INT - SCALE_1_INT))
|
||||||
|
[[ $DIFF_1 -lt 0 ]] && DIFF_1=$((-DIFF_1))
|
||||||
|
|
||||||
|
DIFF_1_6=$((CURRENT_INT - SCALE_1_6_INT))
|
||||||
|
[[ $DIFF_1_6 -lt 0 ]] && DIFF_1_6=$((-DIFF_1_6))
|
||||||
|
|
||||||
|
DIFF_2=$((CURRENT_INT - SCALE_2_INT))
|
||||||
|
[[ $DIFF_2 -lt 0 ]] && DIFF_2=$((-DIFF_2))
|
||||||
|
|
||||||
|
DIFF_3=$((CURRENT_INT - SCALE_3_INT))
|
||||||
|
[[ $DIFF_3 -lt 0 ]] && DIFF_3=$((-DIFF_3))
|
||||||
|
|
||||||
|
# Find minimum
|
||||||
|
MIN=$DIFF_1
|
||||||
|
CLOSEST="1"
|
||||||
|
|
||||||
|
if [[ $DIFF_1_6 -lt $MIN ]]; then
|
||||||
|
MIN=$DIFF_1_6
|
||||||
|
CLOSEST="1.6"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $DIFF_2 -lt $MIN ]]; then
|
||||||
|
MIN=$DIFF_2
|
||||||
|
CLOSEST="2"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $DIFF_3 -lt $MIN ]]; then
|
||||||
|
MIN=$DIFF_3
|
||||||
|
CLOSEST="3"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set next based on closest
|
||||||
|
case "$CLOSEST" in
|
||||||
|
"1") NEW_SCALE="$TARGET_SCALE_1_6" ;;
|
||||||
|
"1.6") NEW_SCALE="$TARGET_SCALE_2" ;;
|
||||||
|
"2") NEW_SCALE="$TARGET_SCALE_3" ;;
|
||||||
|
"3") NEW_SCALE="$TARGET_SCALE_1" ;;
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Apply the new scale to the active monitor only
|
||||||
|
hyprctl keyword monitor "$ACTIVE_MONITOR,preferred,auto,$NEW_SCALE"
|
||||||
|
|
||||||
|
# Format for display (remove trailing zeros)
|
||||||
|
DISPLAY_SCALE=$(echo "$NEW_SCALE" | sed 's/0*$//;s/\.$//')
|
||||||
|
|
||||||
# Notify the user
|
# Notify the user
|
||||||
notify-send " Display scaling set to ${NEW_SCALE}x"
|
notify-send " Display scaling set to ${DISPLAY_SCALE}x"
|
||||||
|
|||||||
Reference in New Issue
Block a user