externaldisplays 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. #!/usr/bin/env bash
  2. # UTILITY FUNCTIONS {{{
  3. # ===
  4. _hr="------------"
  5. # Dump to the screen in a formatted way
  6. # ---
  7. #
  8. # _headline string - First argument, printed above horizontal rule
  9. # $@ string - Remaining arguments, printed below horizontal rule
  10. puts() {
  11. local _headline="$1"
  12. shift
  13. local _arr="$@"
  14. local _i=1
  15. shift
  16. printf "\n %s:\n %s\n" "$_headline" "$_hr"
  17. for _x in ${_arr[@]}; do
  18. printf " %s. %s\n" "$_i" "$_x"
  19. (( i++ ))
  20. done
  21. unset _headline _i _x _arr
  22. }
  23. restart_trayer() {
  24. starttrayer
  25. }
  26. # --------------------------------------------------------------------- }}}
  27. # XRANDR FUNCTIONS {{{
  28. # =====
  29. _local_displays=("LVDS" "eDP1")
  30. _external_displays=("HDMI" "VGA" "DVI" "DP1")
  31. # Cache output of xrandr -q
  32. # ---
  33. #
  34. # refresh mixed - whether or not to refresh.
  35. # Any arugment is true here
  36. get_xrandr() {
  37. (( "$#" > 0 )) && xrandr=
  38. [[ -z "$xrandr" ]] && xrandr=$(xrandr -q)
  39. }
  40. get_all() {
  41. get_xrandr
  42. xrandr_all=( $(echo "$xrandr" | awk '/connected/ {print $1}' | sort) )
  43. }
  44. # Find connected ouputs
  45. get_connected() {
  46. get_xrandr
  47. [[ -z "$xrandr_connected" ]] && \
  48. xrandr_connected=( $(echo "$xrandr" | awk '/ connected/ {print $1}' | sort) )
  49. }
  50. get_disconnected() {
  51. get_xrandr
  52. xrandr_disconnected=( $(echo "$xrandr" | awk '/disconnected/ {print $1}' | sort) )
  53. }
  54. # Find local, connected output
  55. get_local() {
  56. get_connected
  57. for _local_display in "${_local_displays[@]}"; do
  58. for _conn_display in "${xrandr_connected[@]}"; do
  59. if [[ "$_conn_display" == $_local_display* ]]; then
  60. xrandr_local="$_conn_display"
  61. break
  62. fi
  63. done
  64. done
  65. }
  66. # Find primary external, connected output
  67. get_external() {
  68. get_connected
  69. for _ext_display in "${_external_displays[@]}"; do
  70. for _conn_display in "${xrandr_connected[@]}"; do
  71. if [[ "$_conn_display" =~ $_ext_display* ]]; then
  72. xrandr_external="$_conn_display"
  73. break
  74. fi
  75. done
  76. done
  77. }
  78. mirror() {
  79. get_local
  80. get_external
  81. local _primary="${xrandr_local[0]}"
  82. local _secondary="${xrandr_external[0]}"
  83. local -A _native_resolution
  84. local _auto="--auto"
  85. # Override navive resolution for high-dpi laptops. Looking at you ASUS Zenbook
  86. if [[ -r "$HOME/.monitorfix" ]]; then
  87. _auto=""
  88. local _override_display=$(grep ^display= "$HOME/.monitorfix" | cut -d= -f2)
  89. _native_resolution[$_override_display]=$(grep ^native_resolution= "$HOME/.monitorfix" | cut -d= -f2)
  90. fi
  91. # require external display
  92. [[ -z "$xrandr_external" ]] && exit 1
  93. while read _line; do
  94. if [[ "$_line" == Screen* ]]; then
  95. continue
  96. fi
  97. if [[ "$_line" == [A-Z]* ]]; then
  98. set -- $_line
  99. local _source="$1"
  100. else
  101. if [[ -z "${_native_resolution[$_source]}" ]]; then
  102. set -- $_line
  103. _native_resolution[$_source]="$(echo "$1" \
  104. | sed "s/\([[:digit:]]*x[[:digit:]]*\)\?.*/\1/")"
  105. fi
  106. fi
  107. done < <(xrandr -q)
  108. set -- $(echo ${_native_resolution[$_primary]} | tr "x" " ")
  109. local _primary_x="$1"
  110. local _primary_y="$2"
  111. set -- $(echo ${_native_resolution[$_secondary]} | tr "x" " ")
  112. local _secondary_x="$1"
  113. local _secondary_y="$2"
  114. local _x_scaling=$(echo "scale=4;$_primary_x/$_secondary_x" | bc)
  115. local _y_scaling=$(echo "scale=4;$_primary_y/$_secondary_y" | bc)
  116. local _sec="--output $_secondary --scale ${_x_scaling}x${_y_scaling} --auto"
  117. local _pri="--output $_primary --same-as ${_secondary} --scale 1x1 --primary ${_auto}"
  118. xrandr $_sec $_pri
  119. }
  120. nightmode() {
  121. get_local
  122. echo "$1"
  123. case $1 in
  124. on|On|ON|oN)
  125. xrandr --output "$xrandr_local" --gamma 1.68215:1:0.62 --brightness 0.75
  126. ;;
  127. of*|oF*|OF*|Of*)
  128. xrandr --output "$xrandr_local" --gamma 0.97:1:0.98 --brightness 0.98
  129. ;;
  130. *)
  131. show_help
  132. ;;
  133. esac
  134. }
  135. # Ben Wong, October 1, 2010
  136. # Public domain. No rights reserved.
  137. # Functionality extended by Chris Lockfort, August 23, 2012 for use in X230 tablets running gnome-shell.
  138. tablet() {
  139. get_local
  140. rot="$1"
  141. if [[ -z "$rot" ]]; then
  142. rot=$(xrandr -q | \
  143. awk -v display="$xrandr_local" \
  144. '$0 ~ display {
  145. gsub("[()]", "")
  146. gsub("primary ", "")
  147. print $4
  148. }')
  149. echo "The rot is $rot"
  150. # rot=$(xrandr -q | grep "$xrandr_local" | awk '{print $4}' | tr -d '(')
  151. fi
  152. case $rot in
  153. left) # Currently top is rotated left, we should set it normal (0°)
  154. xrandr --output "$xrandr_local" --rotate normal
  155. for _device in $(xsetwacom --list devices | awk '{ print $7 }'); do
  156. xsetwacom set $_device Rotate none;
  157. done
  158. ;;
  159. normal) # Screen is not rotated, we should rotate it right (90°)
  160. xrandr --output "$xrandr_local" --rotate right
  161. for _device in $(xsetwacom --list devices | awk '{ print $7 }'); do
  162. xsetwacom set $_device Rotate cw;
  163. done
  164. ;;
  165. right) # Top of screen is rotated right, we should invert it (180°)
  166. xrandr --output "$xrandr_local" --rotate inverted
  167. for _device in $(xsetwacom --list devices | awk '{ print $7 }'); do
  168. xsetwacom set $_device Rotate half;
  169. done
  170. ;;
  171. inverted) # Screen is inverted, we should rotate it left (270°)
  172. xrandr --output "$xrandr_local" --rotate left
  173. for _device in $(xsetwacom --list devices | awk '{ print $7 }'); do
  174. xsetwacom set $_device Rotate ccw;
  175. done
  176. ;;
  177. esac
  178. # restart_trayer
  179. }
  180. # --------------------------------------------------------------------- }}}
  181. # OUTPUT FUNCTIONS {{{
  182. # ===
  183. # help function, obvs
  184. show_help() {
  185. cat <<HELP
  186. Usage:
  187. $0 [COMMAND]...
  188. COMMANDS:
  189. all show all connected and disconnected displays
  190. connected show connected displays
  191. disconnected show disconnected displays
  192. local show local connected displays
  193. external show external connected displays
  194. mirror mirror local display with first connected display
  195. nightmode <on|off> modifys the gamma and brightness to approximate xflux
  196. Example:
  197. $0 disconnected
  198. HELP
  199. }
  200. show_all() {
  201. get_all
  202. puts "All Available Displays" "${xrandr_all[@]}"
  203. }
  204. show_connected() {
  205. get_connected
  206. puts "Connected Displays" "${xrandr_connected[@]}"
  207. }
  208. show_disconnected() {
  209. get_disconnected
  210. puts "Connected Displays" "${xrandr_disconnected[@]}"
  211. }
  212. show_local() {
  213. get_local
  214. puts "Local Connected Display" "${xrandr_local[@]}"
  215. }
  216. show_external() {
  217. get_external
  218. puts "External Connected Displays" "${xrandr_external[@]}"
  219. }
  220. # --------------------------------------------------------------------- }}}
  221. # MAIN EVENT LOOP {{{
  222. # ===
  223. main() {
  224. local _tabletfile="/tmp/tabletmode"
  225. case $1 in
  226. all) show_all ;;
  227. connected) show_connected ;;
  228. disconnected) show_disconnected ;;
  229. local) show_local ;;
  230. external) show_external ;;
  231. mirror) mirror ;;
  232. tablet) tablet ;;
  233. unfuck)
  234. notify-send "Attempting to unfuck the display"
  235. tablet "left" && sleep 2
  236. tablet "right" && sleep 2
  237. tablet "left" && sleep 2
  238. tablet "right" && sleep 2
  239. tablet "normal"
  240. ;;
  241. tabletmode)
  242. touch $_tabletfile
  243. if [[ "$(cat $_tabletfile)" == "on" ]]; then
  244. printf "off" > $_tabletfile
  245. notify-send "Laptop Mode"
  246. tablet "left"
  247. killall cellwriter
  248. else
  249. if command -v 'cellwriter' &> /dev/null; then
  250. cellwriter --window-x=15 --window-y=100 &
  251. fi
  252. printf "on" > $_tabletfile
  253. notify-send "Tablet Mode"
  254. tablet "right"
  255. fi
  256. ;;
  257. nightmode)
  258. shift
  259. nightmode "$1"
  260. ;;
  261. *) show_help ;;
  262. esac
  263. }
  264. # --------------------------------------------------------------------- }}}
  265. main "$@"