Auto Screen Rotation in Ubuntu

I starting using a Dell XPS 12 (the one with the ferris wheel screen) at the end of last year and love it, however it was annoying that auto rotation wasn't working when I was in tablet mode. At first I created some keyboard shortcuts to do it quickly when I needed to, but still remained annoyed. After a while I finally set out to do something about it.

Fortunately there is a package already in Ubuntu called iio-sensor-proxy and it is capable of monitoring for orientation changes. If you are a Gnome user it's all you need because they have added auto rotation support to the settings, however if you use Unity then it still won't work. The solution is a script that uses iio-sensor-proxy to monitor and trigger the rotation instead of doing it by hand.

Step 1 is to install a couple tools we'll need. The first was mentioned already. inotify-tools is needed because in order to use the output of the monitor-sensor program I chose to have it write to a file, which inotify will be monitoring and allow us to take action. Note that I'm using the recent Ubuntu 16.04, however these instructions are not exclusive to that version.

sudo apt install iio-sensor-proxy inotify-tools

Step 2 is to create the script. Simply cut and paste the code below into a text file and give it execute permissions.

#!/bin/sh
# Auto rotate screen based on device orientation

# Receives input from monitor-sensor (part of iio-sensor-proxy package)
# Screen orientation and launcher location is set based upon accelerometer position
# Launcher will be on the left in a landscape orientation and on the bottom in a portrait orientation
# This script should be added to startup applications for the user

# Clear sensor.log so it doesn't get too long over time
> sensor.log

# Launch monitor-sensor and store the output in a variable that can be parsed by the rest of the script
monitor-sensor >> sensor.log 2>&1 &

# Parse output or monitor sensor to get the new orientation whenever the log file is updated
# Possibles are: normal, bottom-up, right-up, left-up
# Light data will be ignored
while inotifywait -e modify sensor.log; do
# Read the last line that was added to the file and get the orientation
ORIENTATION=$(tail -n 1 sensor.log | grep 'orientation' | grep -oE '[^ ]+$')

# Set the actions to be taken for each possible orientation
case "$ORIENTATION" in
normal)
xrandr --output eDP1 --rotate normal && gsettings set com.canonical.Unity.Launcher launcher-position Left ;;
bottom-up)
xrandr --output eDP1 --rotate inverted && gsettings set com.canonical.Unity.Launcher launcher-position Left ;;
right-up)
xrandr --output eDP1 --rotate right && gsettings set com.canonical.Unity.Launcher launcher-position Bottom ;;
left-up)
xrandr --output eDP1 --rotate left && gsettings set com.canonical.Unity.Launcher launcher-position Bottom ;;
esac
done

All this code does is start the monitor program and use inotify to watch for changes. Simple text processing is used to get on the last word if orientation is part of the description and rotate the screen using xrandr, however you'll notice that each command does something more. Because most displays are a wide screen format these days I also decided to adjust the launcher position to move it to the bottom in portrait mode. I typically prevent the launcher on the left because screen are so wide, but it looks ridiculous there when the screen is narrow and tall.

Now that we have our code, Step 3 is getting it to automatically run. You can do this by opening the Startup Applications program and clicking Add. Give it whatever name you like and point it to the file you saved your script as. That's it. Next time you login you'll have auto rotation enabled.

Bug note: Some have reported, and I also experienced, a bug where orientation changes are not reported by monitor-sensor on first boot. Once the system has gone into standby it will report correctly and the auto rotation script will work as intended. Enjoy.