Fixing multiple monitor position in Ubuntu Gnome 14.04

Upon switching to Gnome 3/Shell I found that my two monitor positions were not persisting after reboot, or even after suspending. N. Bernaerts wrote an excellent post on how to fix this, complete with a dynamic script that fixes your monitor positions based on your monitors.xml. I have made a minor extension to this script that also handles correcting the primary monitor flag. For me, the display manager was not only reversing the left/right positions of the monitors, but was also setting the wrong one to be primary. Here are instructions, summarized from N. Bernaerts’ site for fixing these issues.

  1. Setup a clean configuration, as you want it by deleting your old monitors.xml file and starting fresh with a new one, created using the Gnome display settings tool.

    rm ~/.config/monitors.xml gnome-control-center

    Now go to Displays, and change the positions to how you would like them.

  2. Open ~/.config/monitors.xml in an editor and make sure the display you want to be primary has a “yes” for the primary flag.

  3. Install the libxml2-utils package if not already installed.

    sudo apt-get install libxml2-utils

  4. Copy and paste the below script (or download it using wget) to a directory on your path and make it executable.

    sudo wget -O /usr/local/sbin/update-monitor-position /assets/files/update-monitor-position chmod +x /usr/local/sbin/update-monitor-position

  5. Use the System - Startup Applications tool to add update-monitor-position so that it runs when you login.

  6. Reboot your machine and now your configuration should persist!

# -------------------------------------------------
#  Get monitors configuration from monitor.xml and apply it for current user session.
#  In case of multiple definitions in monitor.xml only first one is used.
#  See
#  for instructions
#  Revision history :
#    19/04/2014, V1.0 - Creation by N. Bernaerts
#    10/07/2014, V1.1 - Wait 5 seconds for X to fully initialize
#    30/07/2014, V1.2 - K. Callenberg added handling of primary monitor setting
# -------------------------------------------------

# get number of declared monitors
NUM=$(xmllint --xpath 'count(//monitors/configuration['1']/output)' $HOME/.config/monitors.xml)

# loop thru declared monitors to create the command line parameters
for (( i=1; i<=$NUM; i++)); do
  # get attributes of current monitor (name and x & y positions)
  NAME=$(xmllint --xpath 'string(//monitors/configuration['1']/output['$i']/@name)' $HOME/.config/monitors.xml 2>NULL)
  POS_X=$(xmllint --xpath '//monitors/configuration['1']/output['$i']/x/text()' $HOME/.config/monitors.xml 2>NULL)
  POS_Y=$(xmllint --xpath '//monitors/configuration['1']/output['$i']/y/text()' $HOME/.config/monitors.xml 2>NULL)
  PRIMARY=$(xmllint --xpath '//monitors/configuration['1']/output['$i']/primary/text()' $HOME/.config/monitors.xml 2>NULL)

  # if position is defined for current monitor, add its position to command line parameters
  if [ "$PRIMARY" == "yes" ] ; then
      [ -n "$POS_X" ] && PARAM_ARR=("${PARAM_ARR[@]}" "--output" "$NAME" "--primary" "--pos" "${POS_X}x${POS_Y}")
      [ -n "$POS_X" ] && PARAM_ARR=("${PARAM_ARR[@]}" "--output" "$NAME" "--pos" "${POS_X}x${POS_Y}")

# wait for 5 seconds (for X to finish initialisation)
sleep 5

#echo "${PARAM_ARR[@]}"

# position all monitors
xrandr "${PARAM_ARR[@]}"