#!/bin/bash
set -e
# command to run a screen keyboard
KEYBOARD="coolkbd"
# arguments for the screen keyboard
KEYBOARD_ARGS="/dev/input/event1"
# name of an input device to configure (from xinput)
INPUTDEV="Elan Touchscreen"
# name of a transformation matrix property of the device
MATRIX_PROP="Coordinate Transformation Matrix"
# name of a dead edges sizes property of the device
# by this property you can disable keyboard area from taps
# use it if the screen keyboard handle touches by it self directly from a device
# just comment out this if you don't need this feature
EDGE_PROP="Trackpad Edge Sizes"
# height of a dead zone area at the bottom of the screen
# integer value - count of percents of the screen height
KEYAREA=20
function usage() {
echo ""
echo "Usage ./rotate.sh [command] ..."
echo " available commands:"
echo " kbon - open screen keyboard"
echo " kboff - close screen keyboard"
echo " kbtoggle - toggle screen keyboard"
echo " normal,left,inverted,right"
echo " - comma separated looped sequence of orientations"
echo " screen will be turned to the next state relative to current"
echo " if only one item is in sequence"
echo " then screen will be turned into it"
echo " if current state is not present in the sequence"
echo " then the first sequence item will be chosen"
echo " without args script will just configure the input device for the current orientation"
echo ""
}
# function gets a next item from the looped sequence
# example: next normal,left,inverted,right left
# will be echoed: inverted
function next() {
local res="$(echo "$1" | tr -s , '\n' | grep -i -x -A 1 "$2" | tail +2)"
if [ -z "$res" ]; then
res="$(echo "$1" | tr -s , '\n' | head -1)"
fi
echo "$res"
}
# always returns a valid name of the rotation (bad values will replaced with 'normal')
function fix_rotation_name() {
case "$1" in
right | inverted | left) echo "$1";;
*) echo "normal";;
esac
}
# check if the first arg is a comma separated sequence of valid rotation names
function is_rotation_sequence() {
local s="$(echo "$1" | tr -s , ' ')"
local x=
for x in $s; do
[ "$x" == "$(fix_rotation_name "$x")" ]
done
}
# show the current screen rotation
function current_rotation() {
fix_rotation_name "$(xrandr --screen 0 --current --query | head -2 | tail -1 | cut -d' ' -f5)"
}
# turn screen to chosen rotation
# possible values: normal, left, inverted and right
function rotate_screen() {
xrandr -o "$1"
}
# keyboard functions
function is_keyboard_run() {
[ -n "$KEYBOARD" ]
pidof "$KEYBOARD" > /dev/null
}
function run_keyboard() {
if ! is_keyboard_run; then
nohup $KEYBOARD $KEYBOARD_ARGS &> /dev/null &
fi
}
function stop_keyboard() {
[ -z "$KEYBOARD" ] || killall -q "$KEYBOARD" || true
}
function toggle_keyboard() {
[ -n "$KEYBOARD" ] || return
if is_keyboard_run; then stop_keyboard; else run_keyboard; fi
}
# configure the input device for a specified rotation
function configure_input() {
local rot="$(current_rotation)"
local matrix=
local edges=
local area=0
if is_keyboard_run; then area="$KEYAREA"; fi
echo "configure the input device for orientation: $rot"
case "$rot" in
left)
matrix="0 -1 1 1 0 0 0 0 1"
edges="0 0 0 $area"
;;
right)
matrix="0 1 0 -1 0 1 0 0 1"
edges="0 0 $area 0"
;;
inverted)
matrix="-1 0 1 0 -1 1 0 0 1"
edges="$area 0 0 0"
;;
*)
matrix="1 0 0 0 1 0 0 0 1"
edges="0 $area 0 0"
;;
esac
[ -z "$INPUTDEV" ] || [ -z "$MATRIX_PROP" ] || \
xinput --set-prop "$INPUTDEV" "$MATRIX_PROP" $matrix
[ -z "$INPUTDEV" ] || [ -z "$EDGE_PROP" ] || [ -z "$KEYAREA" ] || \
xinput --set-prop "$INPUTDEV" "$EDGE_PROP" $edges
}
# parse arguments
SHOW_USAGE=
CHANGED=
while [ "$#" != "0" ]; do
IS_CMD=1
if [ "$1" = "kbon" ]; then
echo "open screen keyboard"
run_keyboard
elif [ "$1" = "kboff" ]; then
echo "close screen keyboard"
stop_keyboard
elif [ "$1" = "kbtoggle" ]; then
echo "toggle screen keyboard"
toggle_keyboard
elif is_rotation_sequence "$1"; then
ROT="$(current_rotation)"
ROT="$(next "$1" "$ROT")"
echo "turn screen to: $ROT"
rotate_screen "$ROT"
else
echo "unknown command: $1"
IS_CMD=
fi
if [ -n "$IS_CMD" ]; then CHANGED=1; else SHOW_USAGE=1; fi
shift
done
[ -z "$SHOW_USAGE" ] || usage
( [ -n "$SHOW_USAGE" ] && [ -z "$CHANGED" ] ) || configure_input