#!/bin/sh # x41t.sh by thurse93 # thurse93[at]gmx.de # This script was released under public domain. # Disclaimer: Use this script at your own risk! Some functions might not # work as expected. ########## # CONFIG # ########## # The config section of the script. Make sure to fill out the variables # and functions correctly. ##### PATHS AND VARIABLES # Most of the values should be correct for an X41t running ArchLinux # with thinkpad_acpi loaded (as of 1/2015). # Path to the sysfs-brightness file. MUST BE WRITEABLE! [achieved for # example through an entry in your rc.local-script (in case of such old # machines with tons of tweaks and workarounds it's generally a good # idea to reactivate rc.local via a systemd-service file)] #(I know this is ugly but xbacklight's too slow...) BRIGHTNESSFILE="/sys/devices/virtual/backlight/thinkpad_screen/brightness" # Brightness minimum (better to keep it zero) BRIGHTNESSMIN=0 # Brightness maximum (check max_brightness in $BRIGHTNESSFILE-folder) BRIGHTNESSMAX=7 # Path to the file provided by thinkpad_acpi which gives us information about # the position of the display. TABLETMODEFILE="/sys/devices/platform/thinkpad_acpi/hotkey_tablet_mode" # Name of the default laptop screen and path to the drm-data LVDS="LVDS1" LVDSDRMPATH="/sys/class/drm/card0-LVDS-1" # Name of the VGA-Output and path to the drm-data VGA="VGA1" VGADRMPATH="/sys/class/drm/card0-VGA-1" # A space separated list of the wacom devices to configure. # Get the IDs with "xsetwacom --list devices" WACOMIDS="12 13" # Set the the resolution you need when giving presentations (1024x768 recommended!) PRESENTATIONRES="1024x768" ##### CUSTOM EXECUTION COMMANDS # Since these are one line functions make sure to end every command with # semicolon and space! # Wallpaper-change-command. Use one for horizontal and one for vertical pictures. WPCHANGE_H(){ wallpaperchanger /path/to/horizontal/picture; } WPCHANGE_V(){ wallpaperchanger /path/to/vertical/picture; } # Additional execution commands for display rotation. EXEC_NORMAL(){ } EXEC_RIGHT(){ } EXEC_INVERTED(){ } EXEC_LEFT(){ } # Example config for my x41t. I use them to remap the up and down display keys: # EXEC_NORMAL(){ xmodmap -e "keycode 111 = Up NoSymbol Up"; xmodmap -e "keycode 116 = Down NoSymbol Down"; } # EXEC_RIGHT(){ xmodmap -e "keycode 111 = Down NoSymbol Down"; modmap -e "keycode 116 = Up NoSymbol Up"; } # EXEC_INVERTED(){ xmodmap -e "keycode 111 = Down NoSymbol Down"; xmodmap -e "keycode 116 = Up NoSymbol Up"; } # EXEC_LEFT(){ xmodmap -e "keycode 111 = Up NoSymbol Up"; xmodmap -e "keycode 116 = Down NoSymbol Down"; } # GUI program for custom xrandr configuration. arandr recommended. XRANDRPROG(){ arandr; } # tablet keyboard programm. onboard or cellwriter recommended. KEYBOARDPROG(){ onboard; } ############## # TEST BLOCK # ############## # check 4 zenity, xsetwacom, xrandr # brightnessfile writable? [ ! -w "$BRIGHTNESSFILE" ] && \ { echo "ERROR: "$BRIGHTNESSFILE" not writeable."; exit 1; } for program in zenity xsetwacom xrandr do command -v $program > /dev/null 2>&1 || \ { echo >&2 '"$program" not found. Aborting.'; exit 1; } done ################## # FUNCTION BLOCK # ################## #### COMMAND LINE errorargf(){ echo "ERROR: Wrong Argument. Execute x41t.sh without options for help." exit 1 } helpf(){ printf %s "\ BEFORE EXECUTING: Check the configuration of x41t.sh at the beginning of the script! SYNTAX: x41t.sh [option] [argument] the options and their arguments. [output when given no argument] brightness: up, down, , [current brightness] rotation: normal, right, inverted, left, [current rotation] monitor: tablet, presentation, custom, [check for external screens] keyboard: [executes tablet keyboard command] zenity: brightness, rotation, monitor, keyboard " exit 0 } # brightness brightnessf(){ read brightness_current < "$BRIGHTNESSFILE" case "$1" in [$BRIGHTNESSMIN-$BRIGHTNESSMAX]) echo $1 > "$BRIGHTNESSFILE" ;; up) brightness_up=$((brightness_current+1)) [ "$brightness_up" -gt "$BRIGHTNESSMAX" ] && exit 0 echo $brightness_up > "$BRIGHTNESSFILE" ;; down) brightness_down=$((brightness_current-1)) [ "$brightness_down" -lt "$BRIGHTNESSMIN" ] && exit 0 echo $brightness_down > "$BRIGHTNESSFILE" ;; "") echo "$brightness_current" ;; *) errorargf ;; esac } # rotation rotationf(){ case "$1" in normal) xrandr --output "$LVDS" --auto xrandr --output "$LVDS" --rotate normal for i in $WACOMIDS; do /usr/bin/xsetwacom --set $i Rotate none; done for i in $WACOMIDS; do /usr/bin/xsetwacom --set $i MapToOutput "$LVDS"; done WPCHANGE_H EXEC_NORMAL ;; right) xrandr --output "$LVDS" --rotate right for i in $WACOMIDS; do /usr/bin/xsetwacom --set $i Rotate cw; done for i in $WACOMIDS; do /usr/bin/xsetwacom --set $i MapToOutput "$LVDS"; done WPCHANGE_V EXEC_RIGHT ;; inverted) xrandr --output "$LVDS" --rotate inverted for i in $WACOMIDS; do /usr/bin/xsetwacom --set $i Rotate Half; done for i in $WACOMIDS; do /usr/bin/xsetwacom --set $i MapToOutput "$LVDS"; done WPCHANGE_H EXEC_INVERTED ;; left) xrandr --output "$LVDS" --rotate left for i in $WACOMIDS; do /usr/bin/xsetwacom --set $i Rotate ccw; done for i in $WACOMIDS; do /usr/bin/xsetwacom --set $i MapToOutput "$LVDS"; done WPCHANGE_V EXEC_LEFT ;; "") rot_cur=$(xrandr | grep "$LVDS" | cut -d " " -f 4) case "$rot_cur" in \(normal) rotation_current="normal";; right) rotation_current="right";; inverted) rotation_current="inverted";; left) rotation_current="left";; *) echo "ERROR: Couldn't get valid rotation value" && exit 1;; esac echo "$rotation_current" ;; *) errorargf ;; esac } # monitor monitorf(){ read vga_state < "$VGADRMPATH"/status [ "$vga_state" == disconnected ] && { if [ "$2" == zenity ]; then zenity --error --text "No external screen connected." --title "ERROR" && exit 1 else echo "ERROR: No external screen connected." && exit 1 fi } read tablet_mode < "$TABLETMODEFILE" case "$1" in presentation) [ "$tablet_mode" == 1 ] && { if [ "$2" == zenity ]; then zenity --error --text "Put your display in an upright position." \ --title "ERROR" && return 5 else echo "ERROR: Put your display in an upright position" && exit 1 fi } xrandr --output "$LVDS" --off xrandr --output "$VGA" --mode "$PRESENTATIONRES" xrandr --output "$LVDS" --auto WPCHANGE_H for i in $WACOMIDS; do /usr/bin/xsetwacom --set $i MapToOutput "$VGA"; done ;; tablet) [ "$tablet_mode" == 0 ] && { if [ "$2" == zenity ]; then zenity --error --text "Put your display in the tablet position." \ --title "ERROR" && return 5 else echo "ERROR: Put your display in the tablet position" && exit 1 fi } [ -z "$XAUTHORITY" ] && { echo "ERROR: No .Xauthority-Path found. No X server running?"; exit 1; } xrandr --output "$VGA" --off xrandr --output "$LVDS" --off xrandr --output "$VGA" --auto for i in $WACOMIDS; do /usr/bin/xsetwacom --set $i Rotate Half; done for i in $WACOMIDS; do /usr/bin/xsetwacom --set $i MapToOutput "$VGA"; done EXEC_INVERTED zenity --info --title "Graphics Tablet Mode" --text "Hit OK to return to normal mode" xrandr --output "$VGA" --off xrandr --output "$LVDS" --auto for i in $WACOMIDS; do /usr/bin/xsetwacom --set $i MapToOutput "$LVDS"; done ;; custom) [ "$tablet_mode" == 1 ] && { if [ "$2" == zenity ]; then zenity --error --text "Put your display in an upright position." \ --title "ERROR" && return 5 else echo "ERROR: Put your display in an upright position" && exit 1 fi } XRANDRPROG ;; "") echo "There's no \$monitor_current defined. Maybe in a later version of this script." return 0 ;; *) errorargf ;; esac } # keyboard keyboardf(){ KEYBOARDPROG } #### GRAPHICAL # brightness brightnessz(){ brightnessf if ! brightness_new=$(zenity --scale --title="Set brightness level" \ --text="Brightness" --min-value="$BRIGHTNESSMIN" --max-value=$BRIGHTNESSMAX \ --step=1 --value="$brightness_current"); then exit; fi echo $brightness_new brightnessf $brightness_new } # rotation rotationz(){ rotationf SEL_RO_N=FALSE SEL_RO_R=FALSE SEL_RO_I=FALSE SEL_RO_L=FALSE case "$rotation_current" in normal) SEL_RO_N=TRUE;; right) SEL_RO_R=TRUE;; inverted) SEL_RO_I=TRUE;; left) SEL_RO_L=TRUE;; *) zenity --error --text "Couldn't get valid rotation value." \ --title "ERROR" && exit 1;; esac if ! i_r=$(zenity --list --text="Choose a rotation" --title="Rotation" \ --radiolist --column="" --column="Rotation" \ $SEL_RO_N Normal \ $SEL_RO_R Right \ $SEL_RO_I Inverted \ $SEL_RO_L Left); then exit fi case "$i_r" in Normal) rotationf normal;; Right) rotationf right;; Inverted) rotationf inverted;; Left) rotationf left;; *) echo 'ERROR: Rotation selection "$i_r" not found && exit 1';; esac } # monitor monitorz(){ monitorf "" zenity # weiß nicht ob das klappt if ! i_m=$(zenity --list --text="Choose a display mode" \ --title="External Screen" --radiolist \ --column="" --column="Mode" FALSE Presentation TRUE Graphics\ tablet FALSE Custom); then exit; fi case "$i_m" in Presentation) monitorf presentation zenity [ $? -eq 5 ] && monitorf presentation zenity ;; Graphics\ tablet) monitorf tablet zenity [ $? -eq 5 ] && monitorf tablet zenity ;; Custom) monitorf custom zenity [ $? -eq 5 ] && monitorf custom zenity ;; *) zenity --error --text "No correct argument '$i_m'." --title "ERROR" && exit 1 ;; esac } # zenity main zenityf(){ case "$1" in brightness) brightnessz ;; rotation) rotationz ;; monitor) monitorz ;; keyboard) keyboardf ;; *) zenity --error --text "No correct argument '$1'." --title "ERROR" && exit 1 ;; esac } ################## # INPUT HANDLING # ################## option="$1" argument="$2" ############## # EVAL BLOCK # ############## case "$option" in brightness) brightnessf "$argument" ;; rotation) rotationf "$argument" ;; monitor) monitorf "$argument" ;; keyboard) keyboardf "$argument" ;; zenity) if [ ! -z "$argument" ]; then zenityf "$argument" else if ! i=$(zenity --list --text="Choose an option" \ --title="X41 Tablet Preferences" --radiolist \ --column="" --column="Option" \ TRUE Brightness \ FALSE Rotation \ FALSE Monitor\ mode \ FALSE Keyboard); then exit; fi case "$i" in Brightness) argument=brightness ;; Rotation) argument=rotation ;; Monitor\ mode) argument=monitor ;; Keyboard) argument=keyboard ;; *) zenity --error --text "No correct argument '$i'." --title "ERROR" && exit 1 ;; esac zenityf "$argument" fi ;; *|-h|--help|help) helpf ;; esac