aboutsummaryrefslogtreecommitdiff
path: root/.local/bin/xrandr-screenScaler
blob: 7ac1803188b0e0d051f60fb2f006b72c05467e5e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#!/bin/sh

# POSIX-compliant xrandr screen scaling shell script
# Requires: xrandr, fzf, awk, sed, printf, cut, grep

err() { printf "%s\n" "$*" >&2; exit 1; }

for cmd in xrandr fzf awk sed grep cut printf; do
  command -v "$cmd" >/dev/null 2>&1 || err "required command not found: $cmd"
done

TMPDIR=${TMPDIR:-/tmp}
tmp_out="$TMPDIR/xrandr_outputs_$"
tmp_scales="$TMPDIR/xrandr_scales_$"
xrandr --query > "$tmp_out" || err "xrandr failed"

awk '
/ connected/ {
  out=$1
  if (match($0, /[0-9]+x[0-9]+\+[0-9]+\+[0-9]+/)) {
    res=substr($0, RSTART, RLENGTH)
    sub(/\+.*/,"",res)
    print out "\t" res
  } else {
    found=0
    # scan following indented lines for "*" indicating current mode
    while (getline > 0) {
      if ($0 ~ /^[ \t]/) {
        if ($0 ~ /\*/) {
          split($1,a,"+")
          print out "\t" a[1]
          found=1
          break
        }
      } else {
        break
      }
    }
    if (!found) print out "\tunknown"
  }
}
' "$tmp_out" > "${tmp_out}.list"

[ -s "${tmp_out}.list" ] || { rm -f "$tmp_out" "${tmp_out}.list"; err "no connected outputs found."; }

chosen_line=$(awk -F'\t' '{printf "%s\t%s\n",$1,$2}' "${tmp_out}.list" | fzf --prompt="select output: " --with-nth=1,2 --tiebreak=index --exact) || { rm -f "$tmp_out" "${tmp_out}.list"; exit 1; }
out=$(printf '%s' "$chosen_line" | cut -f1)
cur_res=$(printf '%s' "$chosen_line" | cut -f2)

cat > "$tmp_scales" <<'EOF'
4k to 1080p	3840x2160	1920x1080
4k to 1440p	3840x2160	2560x1440
4k to 1600p	3840x2160	2560x1600
4k to 720p	3840x2160	1280x720
4k to 768p	3840x2160	1366x768
1440p to 1080p	2560x1440	1920x1080
1440p to 720p	2560x1440	1280x720
2560x1600 to 1080p	2560x1600	1920x1080
1080p to 768p	1920x1080	1366x768
1080p to 720p	1920x1080	1280x720
1080p to 4k	1920x1080	3840x2160
1080p to 1366x768	1920x1080	1366x768
1600x900 to 1080p	1600x900	1920x1080
1600x900 to 720p	1600x900	1280x720
720p to 1080p	1280x720	1920x1080
720p to 4k	1280x720	3840x2160
720p to 1366x768	1280x720	1366x768
1024x768 to 1080p	1024x768	1920x1080
3440x1440 to 1080p	3440x1440	1920x1080
3440x1440 to 1440p	3440x1440	2560x1440
3440x1440 to 2560x1080	3440x1440	2560x1080
3440x1440 to 1600p	3440x1440	2560x1600
3440x1440 to 720p	3440x1440	1280x720
3440x1440 to 1366x768	3440x1440	1366x768
3840x1600 to 1080p	3840x1600	1920x1080
3840x1600 to 1440p	3840x1600	2560x1440
3840x1600 to 2560x1080	3840x1600	2560x1080
2560x1080 to 1080p	2560x1080	1920x1080
2560x1080 to 1440p	2560x1080	2560x1440
2560x1080 to 1366x768	2560x1080	1366x768
3200x1800 to 1080p	3200x1800	1920x1080
3200x1800 to 1440p	3200x1800	2560x1440
1366x768 to 720p	1366x768	1280x720
1366x768 to 1024x768	1366x768	1024x768
1366x768 to 1080p	1366x768	1920x1080
1365x768 to 720p	1365x768	1280x720
1280x800 to 1080p	1280x800	1920x1080
1280x800 to 1366x768	1280x800	1366x768
1280x800 to 1440p	1280x800	2560x1440
1280x720 to 1080p	1280x720	1920x1080
1152x864 to 1024x768	1152x864	1024x768
800x600 to 1024x768	800x600	1024x768
800x600 to 1080p	800x600	1920x1080
800x480 to 720p	800x480	1280x720
640x480 to 1080p	640x480	1920x1080
1600x1200 to 1080p	1600x1200	1920x1080
1600x1200 to 1280x1024	1600x1200	1280x1024
1280x1024 to 1080p	1280x1024	1920x1080
1280x1024 to 1366x768	1280x1024	1366x768
1024x768 to 1280x800	1024x768	1280x800
1024x768 to 1080p	1024x768	1920x1080
1152x864 to 1024x768	1152x864	1024x768
1400x1050 to 1080p	1400x1050	1920x1080
1400x1050 to 1440p	1400x1050	2560x1440
3840x2160 to 1600x900	3840x2160	1600x900
3840x2160 to 1366x768	3840x2160	1366x768
3840x2160 to 1280x800	3840x2160	1280x800
3840x2160 to 1024x768	3840x2160	1024x768
3200x1800 to 1600x900	3200x1800	1600x900
1080p to 800x600	1920x1080	800x600
1080p to 1024x768	1920x1080	1024x768
1360x768 to 720p	1360x768	1280x720
1360x768 to 1080p	1360x768	1920x1080
1920x1200 to 1080p	1920x1200	1920x1080
reset scaling	-	-
EOF

# present options (strip comment lines). Use fzf with --exact to make matching
# stricter (slightly less fuzzy).
chosen_scale=$(grep -v '^#' "$tmp_scales" | awk -F'\t' '{printf "%s\t%s\t%s\n",$1,$2,$3}' \
  | fzf --prompt="select scaling option: " --with-nth=1,2,3 --exact --tiebreak=index --preview='echo {}') || { rm -f "$tmp_out" "${tmp_out}.list" "$tmp_scales"; exit 1; }

label=$(printf '%s' "$chosen_scale" | cut -f1)
src=$(printf '%s' "$chosen_scale" | cut -f2)
tgt=$(printf '%s' "$chosen_scale" | cut -f3)

if [ "$label" = "reset scaling" ]; then
  scale_for_xrandr="1x1"
else
  scale=$(awk -F'[x\t ]' -v s="$src" -v t="$tgt" '
    BEGIN{
      split(s,ss,"x"); split(t,tt,"x");
      if (ss[1]==0 || ss[2]==0) { print "1.000000,1.000000"; exit }
      sx = tt[1]/ss[1]; sy = tt[2]/ss[2];
      printf("%.6f,%.6f", sx, sy);
    }')
  scale_for_xrandr=$(printf '%s' "$scale" | sed 's/,/x/')
fi

printf 'applying: output=%s  current=%s  option=%s  scale=%s\n' "$out" "$cur_res" "$label" "$scale_for_xrandr"
xrandr --output "$out" --scale "$scale_for_xrandr" --filter bilinear

rm -f "$tmp_out" "${tmp_out}.list" "$tmp_scales"