My *nix world

X11 switch multi monitors

I have a laptop (LVDS display) and an external monitor (VGA-0 display). When I am working with many windows and I really need to see them in parallel (and the laptop's screen width is too small for that) I am using the external monitor too.
This suppose to set up a dual monitor using the xrandr (x11-apps/xrandr), something like:

#!/bin/bash
MONITOR_LIST="VGA-0,LVDS" # from left to right, exactly as they are physically positioned on your desk
MONITOR_TO_SWITCH="VGA-0" # comma-delimited list of monitors you want to switch off/on

#XRANDR_INFO=`xrandr -q` # query the xrandr about monitor status; store the result into variable, we'll use it multiple times

# return monitor name if is on, otherwise nothing
function is_monitor_on()
{
xrandr -q|awk '{if (index($0," connected")>0) mon=$1; if (mon!="" "" index($0,"*")>0) print mon}'|awk '/'$1'/'
}

# return the xrandr option required to switch ON the monitor(s) that are switched OFF
function monitor_output_str()
{
result=""
prev_monitor=""
for m in $(echo $MONITOR_LIST|awk 'BEGIN {RS=","} {print}');do
result="$result --output $m --auto"
if [ "$prev_monitor" != "" ];then
result="$result --right-of $prev_monitor"
fi
prev_monitor=$m
done
echo $result
}

# loop through each monitor to be switched and turn it on (if is off) or vice-versa
for m in $(echo $MONITOR_TO_SWITCH|awk 'BEGIN {RS=","} {print}');do
result=$(is_monitor_on $m)
if [ "$result" = "$m" ];then
xrandr --output $m --off
ICON="network-transmit.png"
STATE="off"
else
$(xrandr $(monitor_output_str))
ICON="network-transmit-receive.png"
STATE="auto"
fi
notify-send -i "/usr/share/icons/Tango/48x48/status/$ICON" "Monitor switch" "Monitor $m was switched $STATE"
done

Note: don't forget to set the script as executable (eg chmod +x dualmon)

The script will also print-out a balloon notification (via libnotify) so we'll be informed about which monitor was turned on/off:
switch multi monitor

For another workstation where I use also a multi-monitor setup, I've adapted the above script as following:

  • when I press the Win+F1 key combination I want 1st monitor turned off
  • when I press the Win+F2 key combination I want  1st monitor turned on
  • when I press the Win+F3 key combination I want 2nd monitor turned off
  • when I press the Win+F4 key combination I want  2nd monitor turned on
  • when I press the Win+F5 key combination I want all monitors turned off
  • when I press the Win+F6 key combination I want all monitors turned on, on a specified order from left to right

The script looks like the one bellow:

#!/bin/bash

# DP1=HP monitor; is positioned on the left
# VGA1=DELL monitor; is positioned on the right

MONITOR_SETUP="DP1,VGA1" # from left to right, exactly as they are physically positioned on your desk
ICON_RES="scalable"
ICON_EXT=".svg"

# Print the script help syntax
function print_syntax()
{
	echo -e "Usage : $0 [OPTION]...nStarts|stops the "$MONITOR_SETUP" multi-monitor setup or just turn on|off a specified display.n"
	echo -e "Mandatory arguments to long options are mandatory for short options too.n"
	echo -e "  -c tturn on|off either the predefined multi-monitor setup or when -d is used then the specified display"
	echo -e "  -d tspecify the display to start|stop (run xrandr -q to see the display names);nttttwhen -d is not used then the multi-monitor setup "$MONITOR_SETUP" is used instedn"
	echo "Report bugs to "
}

# Check for sufficent args
if [ $# -lt 2 ] ; then
        print_syntax;
        exit 1;
fi

# Read the options/arguments from command-line
while getopts c:d: flag; do
  case $flag in
    c|command)
	COMMAND=$OPTARG
	;;
    d|display)
	MONITOR=$OPTARG
	;;
    ?)	echo "Invalid option: $flag";
	print_syntax;
	exit 2;
 	;;
    🙂
	echo "Option -$flag requires an argument.";
	print_syntax;
	exit 3;
	;;
    h) print_syntax;
	exit 0;
	;;
    *) print_syntax;
	exit 2;
	;;
  esac
done

case $COMMAND in
 auto|off)
        STATE=$COMMAND
	;;
 *)
	print_syntax;
	exit 4;
	;;
esac

function set_monitor_state()
{
        m=$1 # 1st arg. indicates the monitor name
        MONITOR_STATE=$2 # 2nd arg. indicates the requested monitor state (auto|off)
        OPTIONS=$3

        CMD="xrandr --output $m --$MONITOR_STATE"
        MSG="Monitor $m was switched $MONITOR_STATE"
        if [ -n "$OPTIONS" ];then
                CMD="$CMD --right-of $OPTIONS"
                MSG="$MSG on right of $OPTIONS"
        fi
        $($CMD)

        case $MONITOR_STATE in
                auto)
                        ICON="network-transmit-receive${ICON_EXT}"
                        ;;
                off)
                        ICON="network-transmit${ICON_EXT}"
                        ;;
        esac
        notify-send -i "/usr/share/icons/Tango/${ICON_RES}/status/$ICON" "Monitor switch" "$MSG"

}

# if the monitor has been specified then set its required state
if [ -n "$MONITOR" ];then
	set_monitor_state $MONITOR $STATE
else
	prev=""
	# if no monitor was specified then loop throughout monitor list and start|stop them
	for m in $(echo "$MONITOR_SETUP"|awk 'BEGIN {RS=","} {print}');do
		if [ -n "$m" ];then
       	        	set_monitor_state $m $STATE $prev;
			if [ $STATE = "auto" ];then
				prev=$m
			fi
		fi
	done
fi

All I had to do in order to switch multi monitor was to define 6 keyboard combination for commands like:

  • dualmon -c off VGA0
  • dualmon -c auto VGA0
  • dualmon -c off DP1
  • dualmon -c auto DP1
  • dualmon -c off
  • dualmon -c auto

Now, if you think that this article was interesting don't forget to rate it. It shows me that you care and thus I will continue write about these things.

 
The following two tabs change content below.
X11 switch multi monitors

Eugen Mihailescu

Founder/programmer/one-man-show at Cubique Software
Always looking to learn more about *nix world, about the fundamental concepts of math, physics, electronics. I am also passionate about programming, database and systems administration. 16+ yrs experience in software development, designing enterprise systems, IT support and troubleshooting.
X11 switch multi monitors

Latest posts by Eugen Mihailescu (see all)

Tagged on:

Leave a Reply

Your email address will not be published. Required fields are marked *

Follow

Get every new post on this blog delivered to your Inbox.

Join other followers: