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.

Owner

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.

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.

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.

maferv commented Dec 12, 2015

Beautiful script. God bless you.

@KoljaWindeler

This comment has been minimized.

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.

yzpaul commented Jan 10, 2016

This is phenomenal, thank you so much!

@Apollia

This comment has been minimized.

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.

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.

Owner

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.

@rbnbdd

This comment has been minimized.

rbnbdd 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.

aiya000 commented Jul 23, 2017

Great !!
Thank you !

@debdeepbh

This comment has been minimized.

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.

Owner

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.

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.

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.

Owner

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.

@Aaahh

This comment has been minimized.

Aaahh commented Mar 2, 2018

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

@zx6802

This comment has been minimized.

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.

TroyFletcher commented Jul 21, 2018

Extensible, flexible, and commented. Thank you!

@mbinnun

This comment has been minimized.

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

@JoshHouser

This comment has been minimized.

JoshHouser 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.

@zxc455233

This comment has been minimized.

zxc455233 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.

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

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