diff --git a/README.md b/README.md index 7a42fe3..d88f443 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,61 @@ # cutiepi-rotation-scripts -A set of scripts and services to manage screen rotation on the CutiePi + +A set of scripts and services to manage display rotation on the CutiePi tablet. + +It interacts with the CutiePi gyroscope over `iio-sensor-proxy` to detect the +orientation of the device, and it manipulates the display rotation using some +simple `xrandr` and `xinput` scripting. + +## Installation + +1. Ensure that the `iio-sensor-proxy` package is installed: + +```shell +$ sudo apt install iio-sensor-proxy +``` + +2. Clone the repo: + +```shell +$ git clone https://github.com/BlackLight/cutiepi-rotation-scripts +$ cd cutiepi-rotation-scripts +``` + +3. Simply add the `bin` folder to your `PATH`, or copy/symlink its content + somewhere in your `PATH` + +4. If you want to run the `autorotate` script as a startup service: + +```shell +$ mkdir -p ~/.config/systemd/user +$ cp systemd/autorotate.service ~/.config/systemd/user +$ systemctl --user daemon-reload +# Start the service +$ systemctl --user start autorotate +# Enable the service at startup +$ systemctl --user enable autorotate +``` + +## Usage + +As shown in the previous example, the `autorotate` script can be enabled as a +startup service and it can automatically handle the rotation of the display by +polling gyroscope sensor data. + +There are also two auxiliary scripts (`screen-rotate-left` and +`screen-rotate-right`) that can be programmatically called in your scripts or +launched from the panel to manually force display orientation. + +## Notes + +The `autorotate` script disables the HDMI input when started. The reason is +that the calculation of the coordinate transformation matrices for the touchpad +is much more complex when working with extended displays. If your tablet is +physically connected to a screen, however, the chances that you may want to +leverage auto-rotation are quite low anyway, so a workaround could be a simple +script that turns on the HDMI input and stops the `autorotate` service when an +HDMI input is plugged, and restarts it when it's unplugged. + +If a strong use case exists for handling auto-rotation on extended displays, +feel free to open an issue. + diff --git a/bin/autorotate b/bin/autorotate new file mode 100755 index 0000000..8f8f6e2 --- /dev/null +++ b/bin/autorotate @@ -0,0 +1,25 @@ +#!/bin/bash + +script_dir="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" +source "$script_dir/cutiepi-screen-common" + +# Turn off the HDMI interface. This actually shouldn't be required, but taking +# the second display into account would make the xinput coordinate transformation +# matrices more complex (TODO it can be tackled later if there's enough demand for +# screen rotation features while the tablet is attached to another screen) +xrandr --output HDMI-2 --off + +# Default rotation: standard horizontal +screen_set_horizontal + +monitor-sensor | while read line; do + echo "$line" | egrep '^\s*Accelerometer orientation changed: ' >/dev/null || continue + orientation=$(echo "$line" | awk '{print $4}') + case "$orientation" in + left-up) screen_set_horizontal;; + normal) screen_set_vertical;; + right-up) screen_set_horizontal_inverted;; + bottom-up) screen_set_vertical_inverted;; + esac +done + diff --git a/bin/cutiepi-screen-common b/bin/cutiepi-screen-common new file mode 100644 index 0000000..0947b28 --- /dev/null +++ b/bin/cutiepi-screen-common @@ -0,0 +1,30 @@ +#!/bin/bash + +# Ensure that the display variable is set +export DISPLAY=:0 + +screen_rotation() { + cur_rotation=$(xrandr --query --verbose | grep DSI-1 | cut -d ' ' -f 5) + echo $cur_rotation +} + +screen_set_horizontal() { + xrandr --output DSI-1 --rotate left + xinput set-prop 11 "Coordinate Transformation Matrix" 0 -1 1 1 0 0 0 0 1 +} + +screen_set_vertical() { + xrandr --output DSI-1 --rotate normal + xinput set-prop 11 "Coordinate Transformation Matrix" 1 0 0 0 1 0 0 0 1 +} + +screen_set_horizontal_inverted() { + xrandr --output DSI-1 --rotate right + xinput set-prop 11 "Coordinate Transformation Matrix" 0 1 0 -1 0 1 0 0 1 +} + +screen_set_vertical_inverted() { + xrandr --output DSI-1 --rotate inverted + xinput set-prop 11 "Coordinate Transformation Matrix" -1 0 1 0 -1 1 0 0 1 +} + diff --git a/bin/screen-rotate-left b/bin/screen-rotate-left new file mode 100755 index 0000000..dc861ad --- /dev/null +++ b/bin/screen-rotate-left @@ -0,0 +1,14 @@ +#!/bin/bash + +script_dir="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" +source "$script_dir/cutiepi-screen-common" + +cur_rotation=$(screen_rotation) + +case "$cur_rotation" in + left) screen_set_vertical_inverted;; + right) screen_set_vertical;; + normal) screen_set_horizontal;; + inverted) screen_set_horizontal_inverted;; +esac + diff --git a/bin/screen-rotate-right b/bin/screen-rotate-right new file mode 100755 index 0000000..d649475 --- /dev/null +++ b/bin/screen-rotate-right @@ -0,0 +1,14 @@ +#!/bin/bash + +script_dir="$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" +source "$script_dir/cutiepi-screen-common" + +cur_rotation=$(screen_rotation) + +case "$cur_rotation" in + left) screen_set_vertical;; + right) screen_set_vertical_inverted;; + normal) screen_set_horizontal_inverted;; + inverted) screen_set_horizontal;; +esac + diff --git a/systemd/autorotate.service b/systemd/autorotate.service new file mode 100644 index 0000000..5988870 --- /dev/null +++ b/systemd/autorotate.service @@ -0,0 +1,19 @@ +# Copy or symlink this systemd service to ~/.config/systemd/user +# (create the folder if it doesn't exist). +# Start with: systemctl --user start autorotate +# Stop with: systemctl --user stop autorotate +# Enable at startup with: systemctl --user enable autorotate +# Disable at startup with: systemctl --user disable autorotate + +[Unit] +Description=Manage screen auto-rotation on a CutiePi tablet +After=graphical.target + +[Service] +ExecStart=/home/pi/bin/autorotate +Restart=always +RestartSec=5 + +[Install] +WantedBy=default.target +