]> git.donarmstrong.com Git - deb_pkgs/autorandr.git/blobdiff - autorandr
Enable xrandr outputs one-by-one, --pos 0x0 first
[deb_pkgs/autorandr.git] / autorandr
index e455700210e436f0c29e3d415ffb9b7d1c24e1f0..5937f8a2a8ad3ded1cd9dd27a3d9d7b3535b1bcf 100755 (executable)
--- a/autorandr
+++ b/autorandr
 XRANDR=/usr/bin/xrandr
 DISPER=/usr/bin/disper
 XDPYINFO=/usr/bin/xdpyinfo
-PROFILES=~/.autorandr/
+PROFILES=~/.autorandr
 CONFIG=~/.autorandr.conf
+RESERVED_PROFILE_NAMES=`cat <<EOF
+ common     Clone all connected outputs at the largest common resolution
+ horizontal Stack all connected outputs horizontally at their largest resolution
+ vertical   Stack all connected outputs vertically at their largest resolution
+EOF`
 
 CHANGE_PROFILE=0
 FORCE_LOAD=0
@@ -209,6 +214,45 @@ common_cfg_xrandr() {
                | load_cfg_xrandr -
 }
 
+stack_cfg_xrandr() {
+       $XRANDR -q | awk -v stack="${STACK}" '
+       # variables:
+       #   stack: "horizontal" (anything except vertical) or "vertical"
+       #   output: current output
+       #   firstmode: pick first mode after output
+       #   posX,posY: position of the next output
+       BEGIN {
+           posX=posY=0
+       }
+       # display is connected
+       /^[^ ]+ connected / {
+           output=$1;
+           print "output " $1;
+           firstmode=1
+       }
+       # disconnected or disabled displays
+       /^[^ ]+ disconnected / ||
+       /^[^ ]+ unknown connection / {
+           print "output " $1;
+           print "off";
+       }
+       # modes available on a screen, but pick only the first
+       /^   [0-9]+x[0-9]+/ {
+           if (!firstmode) next;
+           firstmode=0
+           # output mode at current virtual desktop pos
+           print "mode " $1;
+           print "pos " posX "x" posY;
+           # calculate position of next output
+           split($1, wh, "x");
+           if (stack == "vertical")
+               posY += wh[2];
+           else
+               posX += wh[1];
+       }' \
+               | load_cfg_xrandr -
+}
+
 current_cfg() {
        $CURRENT_CFG_METHOD;
 }
@@ -233,26 +277,34 @@ config_equal() {
 load_cfg_xrandr() {
        # sed 1: Prefix arguments with "--"
        # sed 2: Merge arguments into one line per output
-       # sed 3: Merge into two lines, all --off outputs in the first one
+       # sed 3:  * Merge all --off outputs into the first line
+       #         * Place the output with --pos 0x0 on the second line
+       #         * Remaining outputs are appended as they appear
+       #         * Keep everything in hold buffer until the last line
+       # sed 4: Remove empty lines caused by G and H on empty hold buffer
        sed 's/^/--/' "$1" | sed -e '
                :START
                /\n--output/{P;D}
                s/\n/ /
                N;bSTART' | sed -e '
-                       ### First line
                        / --off/{
                                G
-                               # Merge if next line contains --off
+                               # Merge with next line if it contains --off
                                s/\n\([^\n]* --off\)/ \1/
                                h
                                $!d;b
                        }
-                       ### Last line
-                       H;x
-                       # Merge if previous line contains --mode
-                       s/\(--mode [^\n]*\)\n/\1 /
-                       h
-                       $!d' | xargs -L 1 $XRANDR
+                       / --pos 0x0/{
+                               G
+                               # Swap lines 1 and 2 if --off is found
+                               / --off/ s/^\([^\n]*\)\n\([^\n]*\)/\2\n\1/
+                               h
+                               $!d;b
+                       }
+                       H
+                       $!d
+                       x' | sed -e '
+                               /./ !d' | xargs -L 1 $XRANDR
 }
 
 load_cfg_disper() {
@@ -262,7 +314,13 @@ load_cfg_disper() {
 load() {
        local PROFILE="$1"
        local CONF="$PROFILES/$PROFILE/config"
-       [ -f "$CONF" -o "$PROFILE" = "common" ] || return 1
+       local IS_VIRTUAL_PROFILE=`echo "$RESERVED_PROFILE_NAMES" | grep -c "^ $PROFILE "`
+
+       if [ ! -f "$CONF" -a $IS_VIRTUAL_PROFILE -eq 0 ]; then
+               echo " -> Error: Profile '$PROFILE' does not exist." >&2
+               return
+       fi
+
        if [ -x "$PROFILES/preswitch" ]; then
                "$PROFILES/preswitch" "$PROFILE"
        fi
@@ -270,12 +328,24 @@ load() {
                "$PROFILES/$PROFILE/preswitch" "$PROFILE"
        fi
 
-       if [ $PROFILE = "common" ]; then
-               echo " -> setting largest common mode"
-               common_cfg_xrandr
-        else
+       if [ -f "$CONF" ]; then
                echo " -> loading profile $PROFILE"
+               if [ $IS_VIRTUAL_PROFILE -ne 0 ]; then
+                       echo " -> Warning: Existing profile overrides virtual profile with same name" >&2
+               fi
                $LOAD_METHOD "$CONF"
+       else
+               # Virtual profiles
+               if [ $PROFILE = "common" ]; then
+                       echo " -> setting largest common mode in cloned mode"
+                       common_cfg_xrandr
+               elif [ $PROFILE = "horizontal" ]; then
+                       echo " -> stacking all outputs horizontally at their largest modes"
+                       STACK="horizontal" stack_cfg_xrandr
+               elif [ $PROFILE = "vertical" ]; then
+                       echo " -> stacking all outputs vertically at their largest modes"
+                       STACK="vertical" stack_cfg_xrandr
+               fi
        fi
 
        if [ -x "$PROFILES/$PROFILE/postswitch" ]; then
@@ -315,6 +385,9 @@ Usage: $SCRIPTNAME [options]
  When called by the name "autodisper" or "auto-disper", the script uses "disper"
  instead of "xrandr" to detect, configure and save the display configuration.
 
+ If xrandr is used, the following virtual configurations are available:
+${RESERVED_PROFILE_NAMES}
+
 EOH
        exit
 }
@@ -341,6 +414,10 @@ done
 CURRENT_SETUP="$(setup_fp)"
 
 if [ -n "$SAVE_PROFILE" ]; then
+       if echo "$RESERVED_PROFILE_NAMES" | grep -q "^ $SAVE_PROFILE "; then
+               echo "Cannot save current configuration as profile '${SAVE_PROFILE}': This configuration name is a reserved virtual configuration."
+               exit 1
+       fi
        echo "Saving current configuration as profile '${SAVE_PROFILE}'"
        mkdir -p "$PROFILES/$SAVE_PROFILE"
        echo "$CURRENT_SETUP" > "$PROFILES/$SAVE_PROFILE/setup"