X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=autorandr;h=c2c3384e06e25d7de2e938a253efe82aeb773308;hb=bbdf3fb63999e8a5baadce042e04cae8cdc8cdd5;hp=abc33e0c0c512cc9e6b16633243d0f671c178854;hpb=f693721a70e9bb0aa891110a77a6f0ee64edcd19;p=deb_pkgs%2Fautorandr.git diff --git a/autorandr b/autorandr index abc33e0..c2c3384 100755 --- a/autorandr +++ b/autorandr @@ -1,26 +1,29 @@ #!/bin/sh # -# Automatically select a display configuration based on connected devives +# Automatically select a display configuration based on connected devices # # Stefan Tomanek # # How to use: # -# Save your current display configuration and setup with -# autorandr --save mobile +# Save your current display configuration and setup with: +# $ autorandr --save mobile # -# Connect an additional display, configure your setup and save it -# autorand --save docked +# Connect an additional display, configure your setup and save it: +# $ autorandr --save docked # # Now autorandr can detect which hardware setup is active: -# # autorandr -# mobile -# docked (detected) +# $ autorandr +# mobile +# docked (detected) # # To automatically reload your setup, just append --change to the command line # # To manually load a profile, you can use the --load option. # +# autorandr tries to avoid reloading an identical configuration. To force the +# (re)configuration, apply --force. +# # To prevent a profile from being loaded, place a script call "block" in its # directory. The script is evaluated before the screen setup is inspected, and # in case of it returning a value of 0 the profile is skipped. This can be used @@ -31,17 +34,45 @@ # --default # # Another script called "postswitch "can be placed in the directory -# ~/.auto-disper as well as in all profile directories: The scripts are -# executed after a mode switch has taken place and can notify window managers -# or other applications about it. +# ~/.autorandr as well as in all profile directories: The scripts are executed +# after a mode switch has taken place and can notify window managers or other +# applications about it. +# +# +# While the script uses xrandr by default, calling it by the name "autodisper" +# or "auto-disper" forces it to use the "disper" utility, which is useful for +# controlling nvidia chipsets. The formats for fingerprinting the current setup +# and saving/loading the current configuration are adjusted accordingly. XRANDR=/usr/bin/xrandr +DISPER=/usr/bin/disper +XDPYINFO=/usr/bin/xdpyinfo PROFILES=~/.autorandr/ +CONFIG=~/.autorandr.conf CHANGE_PROFILE=0 +FORCE_LOAD=0 DEFAULT_PROFILE="" SAVE_PROFILE="" +FP_METHODS="setup_fp_xrandr_edid setup_fp_sysfs_edid" +CURRENT_CFG_METHOD="current_cfg_xrandr" +LOAD_METHOD="load_cfg_xrandr" + +SCRIPTNAME="$(basename $0)" +# when called as autodisper/auto-disper, we assume different defaults +if [ "$SCRIPTNAME" = "auto-disper" ] || [ "$SCRIPTNAME" = "autodisper" ]; then + echo "Assuming disper defaults..." >&2 + FP_METHODS="setup_fp_disper" + CURRENT_CFG_METHOD="current_cfg_disper" + LOAD_METHOD="load_cfg_disper" +fi + +if [ -f $CONFIG ]; then + echo "Loading configuration from '$CONFIG'" >&2 + . $CONFIG +fi + setup_fp_xrandr_edid() { $XRANDR -q --verbose | awk ' /^[^ ]+ (dis)?connected / { DEV=$1; } @@ -50,8 +81,12 @@ setup_fp_xrandr_edid() { } setup_fp_sysfs_edid() { + # xrandr triggers the reloading of EDID data + $XRANDR -q > /dev/null # hash the EDIDs of all _connected_ devices for P in /sys/class/drm/card*-*/; do + # nothing found + [ ! -d "$P" ] && continue if grep -q "^connected$" < "${P}status"; then echo -n "$(basename "$P") " md5sum ${P}edid | awk '{print $1}' @@ -59,12 +94,17 @@ setup_fp_sysfs_edid() { done } +setup_fp_disper() { + $DISPER -l | grep '^display ' +} + setup_fp() { - local METHODS="setup_fp_xrandr_edid setup_fp_sysfs_edid" local FP=""; - for M in $METHODS; do + for M in $FP_METHODS; do FP="$($M)" - [ -n "$FP" ] && break; + if [ -n "$FP" ]; then + break + fi done if [ -z "$FP" ]; then echo "Unable to fingerprint display configuration" >&2 @@ -73,21 +113,42 @@ setup_fp() { echo "$FP" } - -current_cfg() { - $XRANDR -q | awk ' - /^[^ ]+ disconnected / { - print "output "$1; - print "off"; - } - /^[^ ]+ connected / { +current_cfg_xrandr() { + local PRIMARY_SETUP=""; + if [ -x "$XDPYINFO" ]; then + PRIMARY_SETUP="$($XDPYINFO -ext XINERAMA | awk '/^ head #0:/ {printf $3 $5}')" + fi + $XRANDR -q | awk -v primary_setup="${PRIMARY_SETUP}" ' + # display is connected and has a mode + /^[^ ]+ connected [^(]/ { split($3, A, "+"); print "output "$1; print "mode "A[1]; print "pos "A[2]"x"A[3]; + if ($4 !~ /^\(/) { + print "rotate "$4; + } + if (A[1] A[2] "," A[3] == primary_setup) + print "primary"; + next; + } + # disconnected or disabled displays + /^[^ ]+ (dis)?connected / || + /^[^ ]+ unknown connection / { + print "output "$1; + print "off"; + next; }' } +current_cfg_disper() { + $DISPER -p +} + +current_cfg() { + $CURRENT_CFG_METHOD; +} + blocked() { local PROFILE="$1" [ ! -x "$PROFILES/$PROFILE/block" ] && return 1 @@ -95,11 +156,30 @@ blocked() { "$PROFILES/$PROFILE/block" "$PROFILE" } +config_equal() { + local PROFILE="$1" + if [ "$(cat "$PROFILES/$PROFILE/config")" = "$(current_cfg)" ]; then + echo "Config already loaded" + return 0 + else + return 1 + fi +} + +load_cfg_xrandr() { + sed 's!^!--!' "$1" | xargs $XRANDR +} + +load_cfg_disper() { + $DISPER -i < "$1" +} + load() { local PROFILE="$1" - if [ "$CHANGE_PROFILE" -eq 1 ] && [ -e "$PROFILES/$PROFILE/config" ] ; then + local CONF="$PROFILES/$PROFILE/config" + if [ -e "$CONF" ] ; then echo " -> loading profile $PROFILE" - sed 's!^!--!' "$PROFILES/$PROFILE/config" | xargs xrandr + $LOAD_METHOD "$CONF" [ -x "$PROFILES/$PROFILE/postswitch" ] && \ "$PROFILES/$PROFILE/postswitch" "$PROFILE" @@ -108,8 +188,40 @@ load() { fi } +help() { + cat < save your current setup to profile +-l, --load load profile +-d, --default make profile the default profile +--force force (re)loading of a profile +--fingerprint fingerprint your current hardware setup +--config dump your current xrandr setup + + To prevent a profile from being loaded, place a script call "block" in its + directory. The script is evaluated before the screen setup is inspected, and + in case of it returning a value of 0 the profile is skipped. This can be used + to query the status of a docking station you are about to leave. + + If no suitable profile can be identified, the current configuration is kept. + To change this behaviour and switch to a fallback configuration, specify + --default . + + Another script called "postswitch "can be placed in the directory + ~/.autorandr as well as in any profile directories: The scripts are executed + after a mode switch has taken place and can notify window managers. + + When called by the name "autodisper" or "auto-disper", the script uses "disper" + instead of "xrandr" to detect, configure and save the display configuration. + +EOH + exit +} # process parameters -OPTS=$(getopt -n autorandr -o s:l:d:cf --long change,default:,save:,load:,fingerprint -- "$@") +OPTS=$(getopt -n autorandr -o s:l:d:cfh --long change,default:,save:,load:,force,fingerprint,config,help -- "$@") if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi eval set -- "$OPTS" @@ -119,7 +231,10 @@ while true; do -d|--default) DEFAULT_PROFILE="$2"; shift 2 ;; -s|--save) SAVE_PROFILE="$2"; shift 2 ;; -l|--load) LOAD_PROFILE="$2"; shift 2 ;; + -h|--help) help ;; + --force) FORCE_LOAD=1; shift ;; --fingerprint) setup_fp; exit 0;; + --config) current_cfg; exit 0;; --) shift; break ;; *) echo "Error: $1"; exit 1;; esac @@ -131,12 +246,12 @@ if [ -n "$SAVE_PROFILE" ]; then echo "Saving current configuration as profile '${SAVE_PROFILE}'" mkdir -p "$PROFILES/$SAVE_PROFILE" echo "$CURRENT_SETUP" > "$PROFILES/$SAVE_PROFILE/setup" - current_cfg > "$PROFILES/$SAVE_PROFILE/config" + $CURRENT_CFG_METHOD > "$PROFILES/$SAVE_PROFILE/config" exit 0 fi if [ -n "$LOAD_PROFILE" ]; then - CHANGE_PROFILE=1 load "$LOAD_PROFILE" + CHANGE_PROFILE=1 FORCE_LOAD=1 load "$LOAD_PROFILE" exit $? fi @@ -155,7 +270,11 @@ for SETUP_FILE in $PROFILES/*/setup; do FILE_SETUP="$(cat "$PROFILES/$PROFILE/setup")" if [ "$CURRENT_SETUP" = "$FILE_SETUP" ]; then echo " (detected)" - load "$PROFILE" + if [ "$CHANGE_PROFILE" -eq 1 ]; then + if [ "$FORCE_LOAD" -eq 1 ] || ! config_equal "$PROFILE"; then + load "$PROFILE" + fi + fi # found the profile, exit with success exit 0 else