Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Script to rotate the screen and touch devices on modern Linux desktops. Great for convertible laptops.
#!/bin/bash
#
# rotate_desktop.sh
#
# Rotates modern Linux desktop screen and input devices to match. Handy for
# convertible notebooks. Call this script from panel launchers, keyboard
# shortcuts, or touch gesture bindings (xSwipe, touchegg, etc.).
#
# Using transformation matrix bits taken from:
# https://wiki.ubuntu.com/X/InputCoordinateTransformation
#
# Configure these to match your hardware (names taken from `xinput` output).
TOUCHPAD='SynPS/2 Synaptics TouchPad'
TOUCHSCREEN='Atmel Atmel maXTouch Digitizer'
if [ -z "$1" ]; then
echo "Missing orientation."
echo "Usage: $0 [normal|inverted|left|right] [revert_seconds]"
echo
exit 1
fi
function do_rotate
{
xrandr --output $1 --rotate $2
TRANSFORM='Coordinate Transformation Matrix'
case "$2" in
normal)
[ ! -z "$TOUCHPAD" ] && xinput set-prop "$TOUCHPAD" "$TRANSFORM" 1 0 0 0 1 0 0 0 1
[ ! -z "$TOUCHSCREEN" ] && xinput set-prop "$TOUCHSCREEN" "$TRANSFORM" 1 0 0 0 1 0 0 0 1
;;
inverted)
[ ! -z "$TOUCHPAD" ] && xinput set-prop "$TOUCHPAD" "$TRANSFORM" -1 0 1 0 -1 1 0 0 1
[ ! -z "$TOUCHSCREEN" ] && xinput set-prop "$TOUCHSCREEN" "$TRANSFORM" -1 0 1 0 -1 1 0 0 1
;;
left)
[ ! -z "$TOUCHPAD" ] && xinput set-prop "$TOUCHPAD" "$TRANSFORM" 0 -1 1 1 0 0 0 0 1
[ ! -z "$TOUCHSCREEN" ] && xinput set-prop "$TOUCHSCREEN" "$TRANSFORM" 0 -1 1 1 0 0 0 0 1
;;
right)
[ ! -z "$TOUCHPAD" ] && xinput set-prop "$TOUCHPAD" "$TRANSFORM" 0 1 0 -1 0 1 0 0 1
[ ! -z "$TOUCHSCREEN" ] && xinput set-prop "$TOUCHSCREEN" "$TRANSFORM" 0 1 0 -1 0 1 0 0 1
;;
esac
}
XDISPLAY=`xrandr --current | grep primary | sed -e 's/ .*//g'`
XROT=`xrandr --current --verbose | grep primary | egrep -o ' (normal|left|inverted|right) '`
do_rotate $XDISPLAY $1
if [ ! -z "$2" ]; then
sleep $2
do_rotate $XDISPLAY $XROT
exit 0
fi
@mildmojo

This comment has been minimized.

Copy link
Owner Author

@mildmojo mildmojo commented Jun 18, 2014

Tested with the following versions:

$ xinput --version
xinput version 1.6.1
XI version on server: 2.3
$ xrandr --version
xrandr program version       1.4.1
Server reports RandR version 1.4
@JosephLeedy

This comment has been minimized.

Copy link

@JosephLeedy JosephLeedy commented Sep 6, 2014

Thanks! This worked great with my HP Envy x360! I had to calibrate it first by running the command xinput_calibrator --output-type xorg.conf.d and following its instructions to get the pointer orientation correct.

@mnpale

This comment has been minimized.

Copy link

@mnpale mnpale commented May 19, 2015

Thanks, this helped me flip the screen on my XPS 12 in Linux Mint. I tied this to keyboard shortcuts.

@maferv

This comment has been minimized.

Copy link

@maferv maferv commented Dec 12, 2015

Beautiful script. God bless you.

@KoljaWindeler

This comment has been minimized.

Copy link

@KoljaWindeler KoljaWindeler commented Dec 26, 2015

Great script! Thanks. I've extended it to toggle between left and normal by reading the current orientation.

@yzpaul

This comment has been minimized.

Copy link

@yzpaul yzpaul commented Jan 10, 2016

This is phenomenal, thank you so much!

@Apollia

This comment has been minimized.

Copy link

@Apollia Apollia commented Jun 10, 2016

Thank you so much!!! Works great on my Toughbook CF-C1 in Lighthouse 64 Puppy Linux 6.02 Beta 2!

My forked and slightly modified version:

https://github.com/Apollia/Rotate-Toughbook-CF-C1-Screen-in-Lighthouse-64-Puppy-Linux-6.02-Beta-2/tree/master

@infinitekh

This comment has been minimized.

Copy link

@infinitekh infinitekh commented Sep 24, 2016

Thanks!! This is so good!!
I use this script for watching youtube personal cam video that looks on stars.

Hmmm. But two touch or three touch events are yet normal mode.
Is this are impossible using xinput?

@mildmojo

This comment has been minimized.

Copy link
Owner Author

@mildmojo mildmojo commented Feb 15, 2017

I'm not sure about multitouch gestures; I think I use touchegg to manage them, and I use them so infrequently that I never noticed if they were correct after rotation. I've been pretty disappointed with multitouch gestures and touchscreen support in Linux, TBH.

@leabdd

This comment has been minimized.

Copy link

@leabdd leabdd commented Feb 18, 2017

I'm new to Linux/Ubuntu and have only tried it on my Yoga 2 11 per USB-Stick. So my question is if it somehow it possible to get the code in a GUI where you can just press 4 buttons and it will change the rotation of the Screen.

@aiya000

This comment has been minimized.

Copy link

@aiya000 aiya000 commented Jul 23, 2017

Great !!
Thank you !

@debdeepbh

This comment has been minimized.

Copy link

@debdeepbh debdeepbh commented Sep 23, 2017

Works perfectly except for the scrolling part. Both edge scrolling and two finger scrolling remain unchanged after the coordinate transform. Any idea how to fix this?
EDIT: If the stylus, touchscreen and eraser is a Wacom device, the following works instead of the coordinate transform:
xsetwacom set "$TOUCHSCREEN" Rotate ccw

The options for Rotate can be one of ccw/cw/half/none from this link.

@mildmojo

This comment has been minimized.

Copy link
Owner Author

@mildmojo mildmojo commented Sep 28, 2017

@rbnbdd A GUI is farther than I want to go with this, but a GUI could easily call this script.

You could add quick launcher icons to your panel or desktop that call this script with the proper arguments for the rotations. Just add a new shortcut the way you regularly would, and tell it to run this script like e.g. /Users/<username>/rotate_desktop.sh inverted.

@tuxflo

This comment has been minimized.

Copy link

@tuxflo tuxflo commented Dec 19, 2017

@rbnbdd It should be not too hard if you're using Zenity or something like that.

@mildmojo do you know an approach to remove the second parameter and do just a "toggle" through the different modes?

@yuletide

This comment has been minimized.

Copy link

@yuletide yuletide commented Jan 5, 2018

Haven't tried this exact script yet but another with similar approach here breaks the keyboard cover and touchpad (only when rotated!) on a Surface 2017 with running Ubuntu 16.04. Any ideas how to fix?

@mildmojo

This comment has been minimized.

Copy link
Owner Author

@mildmojo mildmojo commented Feb 2, 2018

@tuxflo The XROT line shows how to get the current mode; you'd want to get that and then look through a list of the modes to find the next one to switch to.

@yuletide Sorry, I haven't tried this on a Surface. My test box was a Lenovo Yoga.

@mmhobi7

This comment has been minimized.

Copy link

@mmhobi7 mmhobi7 commented Mar 2, 2018

@rbnbdd
if your own ubuntu or debian, search for shortcuts in keyboard settings

@zx6802

This comment has been minimized.

Copy link

@zx6802 zx6802 commented May 1, 2018

@ rbnbdd 18 Feb 2017
On Lubuntu LXHotkey provides a graphical interface for binding programs to keys.

@TroyFletcher

This comment has been minimized.

Copy link

@TroyFletcher TroyFletcher commented Jul 21, 2018

Extensible, flexible, and commented. Thank you!

@mbinnun

This comment has been minimized.

Copy link

@mbinnun mbinnun commented Aug 31, 2018

I have been using your script for a while but changed it a bit:

  • Added an option to transform all pointing devices (not from a hardcoded device name)
  • Added an option to transform only the devices from a specific type (see comments)
  • Removed the unnecessery option to transform back automatically after a while

Here's my code:

#!/bin/bash

if [ -z "$1" ] ; then
  echo "Usage: $0 [normal|inverted|left|right]"
  echo " "
  exit 1
fi

function do_rotate
{
  xrandr --output $1 --rotate $2

  TRANSFORM='Coordinate Transformation Matrix'

  POINTERS=`xinput | grep 'slave  pointer'`
  POINTERS=`echo $POINTERS | sed s/↳\ /\$/g`
  POINTERS=`echo $POINTERS | sed s/\ id=/\@/g`
  POINTERS=`echo $POINTERS | sed s/\ \\\[slave\ pointer/\#/g`
  iIndex=2
  POINTER=`echo $POINTERS | cut -d "@" -f $iIndex | cut -d "#" -f 1`
  while [ "$POINTER" != "" ] ; do
    POINTER=`echo $POINTERS | cut -d "@" -f $iIndex | cut -d "#" -f 1`
    POINTERNAME=`echo $POINTERS | cut -d "$" -f $iIndex | cut -d "@" -f 1`
    #if [ "$POINTER" != "" ] && [[ $POINTERNAME = *"TouchPad"* ]]; then    # ==> uncomment to transform only touchpads
    #if [ "$POINTER" != "" ] && [[ $POINTERNAME = *"TrackPoint"* ]]; then  # ==> uncomment to transform only trackpoints
    #if [ "$POINTER" != "" ] && [[ $POINTERNAME = *"Digitizer"* ]]; then   # ==> uncomment to transform only digitizers (touch)
    #if [ "$POINTER" != "" ] && [[ $POINTERNAME = *"MOUSE"* ]]; then       # ==> uncomment to transform only optical mice
    if [ "$POINTER" != "" ] ; then                                         # ==> uncomment to transform all pointer devices
        case "$2" in
            normal)
              [ ! -z "$POINTER" ]    && xinput set-prop "$POINTER" "$TRANSFORM" 1 0 0 0 1 0 0 0 1
              ;;
            inverted)
              [ ! -z "$POINTER" ]    && xinput set-prop "$POINTER" "$TRANSFORM" -1 0 1 0 -1 1 0 0 1
              ;;
            left)
              [ ! -z "$POINTER" ]    && xinput set-prop "$POINTER" "$TRANSFORM" 0 -1 1 1 0 0 0 0 1
              ;;
            right)
              [ ! -z "$POINTER" ]    && xinput set-prop "$POINTER" "$TRANSFORM" 0 1 0 -1 0 1 0 0 1
              ;;
        esac      
    fi
    iIndex=$[$iIndex+1]
  done
}

XDISPLAY=`xrandr --current | grep primary | sed -e 's/ .*//g'`
if [ "$XDISPLAY" == "" ] || [ "$XDISPLAY" == " " ] ; then
  XDISPLAY=`xrandr --current | grep connected | sed -e 's/ .*//g' | head -1`
fi

do_rotate $XDISPLAY $1

@DaringDreams

This comment has been minimized.

Copy link

@DaringDreams DaringDreams commented Oct 6, 2018

Was able to fix the touch screen on Linux Cinnamon by using the following:

  1. Type the following in the terminal:
    xrandr -o orientation
    Replace orientation with the orientation you want.

  2. Get the touch screen device name using the following command:
    xinput list

  3. xinput set-prop '' 'Coordinate Transformation Matrix' matrix-elements-rowwise
    Replace matrix-elements-rowwise with 0 1 0 -1 0 1 0 0 1 or one of the other three orientation number sets mentioned above.

@i-am-neet

This comment has been minimized.

Copy link

@i-am-neet i-am-neet commented Oct 11, 2018

Great Script!!! Thanks a lot!!!
I test it on NUC with gechic on-lap 1102i touch screen,
And it works perfectly, thanks!

@doublehp

This comment has been minimized.

Copy link

@doublehp doublehp commented Dec 3, 2018

On my Raspberry pi, with screen Quimat SPI, here is what I needed:

Landscape with ethernet on the left:
/boot/config.txt
dtoverlay=tft35a:rotate=270,swapxy=1
but Y axis is inverted, and no combination of xmin=200,xmax=3900,ymin=200,ymax=3900 could fix it for me.

I don't need console, so, I fixed inversion only for Xorg with this command:
xinput set-prop "$TOUCHPAD" "$TRANSFORM" 1 0 0 0 -1 1 0 0 1

@cunidev

This comment has been minimized.

Copy link

@cunidev cunidev commented Feb 6, 2019

A must-have. Thank you

@ebrensi

This comment has been minimized.

Copy link

@ebrensi ebrensi commented May 2, 2019

Hi all. I had a similar problem on my HP Spectre x360 Convertible using Linux Mint 19 with Cinnamon. The Cinnamon desktop manager has
System Settings >> General >> Enable/Disable automatic screen rotation

Automatic screen rotation correctly rotates the orientation of the touchscreen device, but not the pen (stylus) functionality.
I adapted an existing script to do that, and you might find my script useful to automate pointing device orientation.
Check it out here: https://gist.github.com/ebrensi/6d270bd84f04fbe0366fbbc3e5cf7054

@marian556

This comment has been minimized.

Copy link

@marian556 marian556 commented May 24, 2019

if the code posted by mbinnun is called rotate.sh
then call this rotateloop.sh:
while read line do ./rotate.sh "$line" done < /dev/stdin

and call this one liner autorotate.sh

/usr/bin/monitor-sensor | unbuffer -p grep -o "right|normal|bottom|left" | unbuffer -p sed 's/bottom/inverted/g' | unbuffer -p ./rotateloop.sh

This will detect orientation of laptop and adjusts the screen.
You need to install :
apt install iio-sensor-proxy expect

@mikelduke

This comment has been minimized.

Copy link

@mikelduke mikelduke commented Jun 8, 2019

Thanks for sharing this! I had the same issue on Ubuntu and combined the solutions here in a repo https://github.com/mikelduke/rotate-touchscreen to make it easier to run

@maxigit

This comment has been minimized.

Copy link

@maxigit maxigit commented Mar 11, 2020

Exactly what I was looking for, Thanks !
(I add to change "primary" to " connected" and set the TOUCHSCREEN to actual touchscreen Id but It works like a cham)

@mildmojo

This comment has been minimized.

Copy link
Owner Author

@mildmojo mildmojo commented Apr 13, 2020

I'm happy people are still getting some mileage out of this script! I'm actually still using that laptop and I've had this script bound to ctrl + super + alt + <arrows> to pick a screen orientation for years. It's especially handy when I want to fold the screen flat or bend it backwards in tent mode to show something to a person across the table from me.

Back when I originally checked, my model was a weird orphan in the Yoga line that compared accelerometer angles in the base and the screen to calculate orientation in Windows, and since no other laptop does it that way, there wasn't Linux support for an automatic solution.

@DarthColon

This comment has been minimized.

Copy link

@DarthColon DarthColon commented Dec 29, 2020

Thank you guys very much!

@denics

This comment has been minimized.

Copy link

@denics denics commented Feb 20, 2021

well, this is mine :) I run it on Debian Mate on a XPS13
the script is called /usr/local/bin/rotate.sh and it starts via mate startup programs. Thanks for all your inspiring comments!

#!/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
> /var/log/sensor.log

# Launch monitor-sensor and store the output in a variable that can be parsed by the rest of the script
monitor-sensor >> /var/log/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
TRANSFORM='Coordinate Transformation Matrix'
POINTER='DLL077A:01 06CB:76AF Touchpad'
TOUCH='Wacom HID 482F Finger touch'

while inotifywait -e modify /var/log/sensor.log; do
# Read the last line that was added to the file and get the orientation
	ORIENTATION=$(tail -n 1 /var/log/sensor.log | grep 'orientation' | grep -oE '[^ ]+$')

# Set the actions to be taken for each possible orientation
	case "$ORIENTATION" in
	normal)
		xrandr --output eDP-1 --rotate normal 
		xinput set-prop "$POINTER" "$TRANSFORM" 1 0 0 0 1 0 0 0 1
		xinput set-prop "$TOUCH" "$TRANSFORM" 1 0 0 0 1 0 0 0 1
		;;
	bottom-up)
		xrandr --output eDP-1 --rotate inverted 
		xinput set-prop "$POINTER" "$TRANSFORM" -1 0 1 0 -1 1 0 0 1
		xinput set-prop "$TOUCH" "$TRANSFORM" -1 0 1 0 -1 1 0 0 1
		;;
	right-up)
		xrandr --output eDP-1 --rotate right 
		xinput set-prop "$POINTER" "$TRANSFORM" 0 1 0 -1 0 1 0 0 1
		xinput set-prop "$TOUCH" "$TRANSFORM" 0 1 0 -1 0 1 0 0 1
		;;
	left-up)
		xrandr --output eDP-1 --rotate left 
		xinput set-prop "$POINTER" "$TRANSFORM" 0 -1 1 1 0 0 0 0 1
		xinput set-prop "$TOUCH" "$TRANSFORM" 0 -1 1 1 0 0 0 0 1
		;;
esac
done
@mihanich

This comment has been minimized.

Copy link

@mihanich mihanich commented Feb 27, 2021

got Y axis inverted and none of options fit to resolve it.
For those who get same pain as me - https://codepen.io/GottZ/full/pWpNgK
This tool helps to transform all rotation right.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment