distro specific fixes
[distro-setup] / myx
1 #!/bin/bash
2 # I, Ian Kelling, follow the GNU license recommendations at
3 # https://www.gnu.org/licenses/license-recommendations.en.html. They
4 # recommend that small programs, < 300 lines, be licensed under the
5 # Apache License 2.0. This file contains or is part of one or more small
6 # programs. If a small program grows beyond 300 lines, I plan to change
7 # to a recommended GPL license.
8
9 # Copyright 2024 Ian Kelling
10
11 # Licensed under the Apache License, Version 2.0 (the "License");
12 # you may not use this file except in compliance with the License.
13 # You may obtain a copy of the License at
14
15 # http://www.apache.org/licenses/LICENSE-2.0
16
17 # Unless required by applicable law or agreed to in writing, software
18 # distributed under the License is distributed on an "AS IS" BASIS,
19 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20 # See the License for the specific language governing permissions and
21 # limitations under the License.
22
23 set -e; . /usr/local/lib/bash-bear; set +e
24
25 script_name="${0##*/}"
26 usage() {
27 cat <<EOF
28 Usage: $script_name [OPTIONS]
29
30 Turns on/off secondary monitor.
31
32 Sets resolution.
33
34 Alters i3 config.
35
36 -n Dry run
37
38 -r Restart secondary monitor
39
40 -s No stream setup. Normally, split monitor into 2 virtual screens and
41 set max resolution 2560x1440
42
43
44 -h|--help Print help and exit.
45
46 Note: Uses GNU getopt options parsing style
47 EOF
48 exit $1
49 }
50 edid() {
51 card=$1
52 sha256sum </sys/class/drm/$card/edid | grep -oE '^.{10}'
53 }
54
55 i3() {
56 if [[ $I3SOCK ]]; then
57 i3-msg "$@"
58 fi
59 }
60
61 move-ws() {
62 local target_out output tmps
63 target_out=$1
64 shift
65
66 if [[ ! ${ws_out[*]} ]]; then
67 declare -a ws_out
68 tmps=$(i3 -t get_workspaces)
69 if [[ ! $tmps ]]; then
70 return 0
71 fi
72 tmps=$(jq -r '.[] | .num, .output' <<<"$tmps")
73 while read -r ws; do
74 read -r output || break
75 ws_out["$ws"]=$output
76 done <<<"$tmps"
77 fi
78
79 for ws; do
80 if [[ ${ws_out[$ws]} && ${ws_out[$ws]} != "$target_out" ]]; then
81 # if the workspace is already there, this will fail.
82 # if the workspace doesn't exist yet, it fails with:
83 # ERROR: No output matched
84 m i3 '[workspace="'$ws'"]' move workspace to output $target_out
85 fi
86 done
87 }
88
89 date "+%A, %B %d, %r, %S seconds"
90
91 ##### begin command line parsing ########
92
93 dry_run=false
94 stream=true
95 restart=false
96 temp=$(getopt -l help nrs "$@") || usage 1
97 eval set -- "$temp"
98 while true; do
99 case $1 in
100 -n) dry_run=true ;;
101 -r) restart=true ;;
102 -s) stream=false ;;
103 -h|--help) usage 0 ;;
104 --) shift; break ;;
105 *) echo "$0: Internal error! unexpected args: $*" ; exit 1 ;;
106 esac
107 shift
108 done
109
110 ##### end command line parsing ########
111
112
113 xf=$(mktemp)
114 xrandr >$xf
115
116 m() { printf "$script_name: %s\n" "$*"; "$@"; }
117 if $dry_run; then
118 m() { printf "$script_name: %s\n" "$*"; }
119 fi
120
121 for mon_suffix in LEFT RIGHT; do
122 if xrandr --listmonitors | awk '$2 == "BIG-'$mon_suffix\" |grep . >/dev/null; then
123 m xrandr --delmonitor BIG-$mon_suffix
124 fi
125 done
126
127
128 secondary_out=$(awk '$2 == "connected" && $3 != "primary" {print $1}' $xf)
129 primary_info=$(awk '$2 == "connected" && $3 == "primary" {print $1,$4}' $xf)
130
131 # res_info eg: 3840x2160+1920+0
132 read -r primary_out primary_res_info <<<"$primary_info"
133
134 primary_res=${primary_res_info%%+*}
135 primary_x=${primary_res%x*}
136 primary_y=${primary_res#*x}
137
138
139 if [[ $secondary_out ]]; then
140
141 # some monitors need off then on to become active
142 if $restart; then
143 m xrandr --output $secondary_out --off
144 m sleep 2
145 fi
146
147 x_offset=$primary_x
148 left_right_arg=--right-of
149 if [[ $secondary_out == HDMI2 && $(edid card0-HDMI-A-2) == 192efbdcef ]] || \
150 [[ $secondary_out == HDMI-1 && $(edid card1-HDMI-A-1 ) == 7c58f9ac1e ]] || \
151 [[ $secondary_out == DP-1 && $(edid card1-DP-1 ) == f3364bc6c1 ]]; then
152 left_right_arg=--left-of
153 x_offset=0
154 fi
155 left_right_arg="$left_right_arg $primary_out"
156
157 target_out=$secondary_out
158 target_res=$(grep -A1 -E "^$secondary_out " $xf | tail -n1 | awk '{print $1}')
159 target_x=${target_res%x*}
160 target_y=${target_res#*x}
161 else
162 # disables any leftover secondary.
163 xrandr --auto
164 target_out=$primary_out
165 x_offset=0
166 target_res=$primary_res
167 target_x=$primary_x
168 target_y=$primary_y
169 fi
170
171
172
173 if $stream && (( target_x > 1280 )); then
174
175 if (( target_x > 2560 )); then
176 target_x=2560
177 target_y=1440
178 target_res=${target_x}x$target_y
179 fi
180
181 if [[ $secondary_out || $primary_res != "$target_res" ]]; then
182 m xrandr --output $target_out $left_right_arg --mode $target_res
183 fi
184
185 half_x=$(( target_x / 2 ))
186 # 298 & 336 are millimeters. I took them from a monitor I was using. I
187 # don't know if they are important, I assume not important enough to
188 # change for different monitors.
189 m xrandr --setmonitor BIG-LEFT $half_x/298x$target_y/336+$x_offset+0 $target_out
190 m xrandr --setmonitor BIG-RIGHT $half_x/298x$target_y/336+$(( x_offset + half_x ))+0 none
191
192 move-ws BIG-LEFT 2
193 move-ws BIG-RIGHT 3 4 5 6 7 8 9 10
194
195 else
196 m xrandr --output $target_out $left_right_arg --mode $target_res
197 move-ws $target_out 2 3 5 6 7 8 9 10
198 fi
199
200 m /a/bin/ds/i3-sway/gen
201 m /a/exe/input-setup
202
203 echo -n "myx end: "
204 date "+%A, %B %d, %r, %S seconds"