X11 switch multi-monitors


Please note that this blog has been moved.

Now it has its own domain: mynixworld.info🙂

If you want to read the latest version of this article (recommended) please click here and I open the page for you.

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:

xrandr --output LVDS --output VGA-0 --left-of LVDS

Well, when I don’t need it any more (the VGA-0) then it’s time to set up just one monitor (eg LVDS or VGA-0 if you prefer). This can be done with:

xrandr --output VGA-0 --off

But I am lazy so I want to do that just by using a keyboard shortcut. Well, this is possible using the following simple solution:

  • write a simple bash script (eg dualmon) where you can define a comma-delimited list of all available monitors, in the physical order from left to right, and also the monitors to be switched on/off by using the keyboard shortcut
  • define a keyboard shortcut that will call this script, so you can switch these monitors on/off any time you want

The bash script:

#!/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:
dualmon

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 <auto|off>\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);\n\t\t\t\twhen -d is not used then the multi-monitor setup \"$MONITOR_SETUP\" is used insted\n"
echo "Report bugs to <eugenmihailescux@gmail.com>"
}

# 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 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

About Eugen Mihailescu

Always looking to learn more about *nix world, about the fundamental concepts of arithmetic, algebra and geometry. I am also passionate about programming, database and systems administration.
This entry was posted in linux, X11 and tagged . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s