#!/bin/bash # What action to take on closing the laptop lid, # depending on whether a screen is attached or not. # This implies setting HandleLidSwitch=ignore in /etc/systemd/logind.conf # Call this script from /etc/acpi/handler.sh (or other properly set up script # for handling button/lid acpi event) with parameter 0 and 1 for close and open respectively set -e -u # Find current Xsession user through loginctl list-sessions (excluding lightdm) # TODO: make available for desktop manager, too! declare x_user="$(loginctl list-sessions --no-legend| sed -e 's/\s\{2,\}/ /g;s/^[[:space:]]*//' | \ cut -d ' ' -f 3| grep -v "lightdm"|uniq)" # Fail if there is no user set if [ -z "$x_user" ]; then echo "error no user!" exit 1 fi # Export Xorg DISPLAY and XAUTHORITY # TODO: Get number of X DISPLAY from tmp #declare x_display="/tmp/.X11-unix/X*" export DISPLAY=:0 export XAUTHORITY=/home/$x_user/.Xauthority # Define the log file declare log="/home/$x_user/.cache/$(basename $0)" if [[ ! -w "$log" ]]; then touch "$log" chown ${x_user}:${x_user} "$log" # exec > "$log" 2>&1 fi declare -a arguments=( ) declare -a connections=( ) declare -a active_connections=( ) declare -a available_connections=( ) declare -a non_primary=( "eDP1" ) declare -a pan=( "DP2-1" "eDP1" ) declare -a pan_vertical=( 'empty' 'empty' ) # with empty placeholders! declare internal="eDP1" declare current_primary="" declare action="" # declare keywords (xrandr arguments) declare pre_output=" --output " declare post_auto=" --auto " declare post_primary=" --primary " declare post_pos_rightof=" --right-of" declare post_pos_leftof=" --left-of" declare post_off=" --off " function setup_xscreen() { local outputs=( ) local connection_counter=0 case "$action" in "open") if [ ${#available_connections[@]} -gt 1 ]; then for connection in ${pan[@]} do echo "$connection" >> $log set +e find_component_in "$connection" ${available_connections[@]} if [ $? -eq 0 ]; then echo "$connection is amongst the available outputs." >> $log # adding --output argument outputs=( ${outputs[@]:+${outputs[@]}} "$pre_output" ) # adding name of output outputs=( ${outputs[@]:+${outputs[@]}} "$connection" ) # check whether output should not be primary in a multi output setup find_component_in "$connection" ${non_primary[@]} if [ $? -eq 0 ]; then echo "$connection is setup for non-primary." >> $log else echo "$connection is NOT setup for non-primary." >> $log # adding --primary argument outputs=( ${outputs[@]:+${outputs[@]}} "$post_primary" ) fi if [ $connection_counter -gt 0 ]; then # adding a --right-of argument outputs=( ${outputs[@]:+${outputs[@]}} "$post_pos_rightof" "${pan[$((connection_counter-1))]}" ) fi # adding --auto argument outputs=( ${outputs[@]:+${outputs[@]}}"$post_auto" ) connection_counter=$(( $connection_counter + 1 )) fi set -e done fi ;; "close") if [ ${#available_connections[@]} -gt 1 ]; then for connection in ${pan[@]} do echo "$connection" >> $log set +e find_component_in "$connection" ${available_connections[@]} if [ $? -eq 0 ]; then echo "$connection is amongst the available outputs." >> $log # adding --output argument outputs=( ${outputs[@]:+${outputs[@]}} "$pre_output" ) # adding name of output outputs=( ${outputs[@]:+${outputs[@]}} "$connection" ) # if the connection is not the internal output if [ $connection != $internal ]; then # check whether output should not be primary in a multi output setup find_component_in "$connection" ${non_primary[@]} if [ $? -eq 0 ]; then echo "$connection is setup for non-primary." >> $log else echo "$connection is NOT setup for non-primary." >> $log # adding --primary argument outputs=( ${outputs[@]:+${outputs[@]}} "$post_primary" ) fi if [ $connection_counter -gt 0 ]; then # adding a --right-of argument outputs=( ${outputs[@]:+${outputs[@]}} "$post_pos_rightof" "${pan[$((connection_counter-1))]}" ) fi # adding --auto argument outputs=( ${outputs[@]:+${outputs[@]}}"$post_auto" ) connection_counter=$(( $connection_counter + 1 )) else # adding a --off argument for the interal screen outputs=( ${outputs[@]:+${outputs[@]}} "$post_off" ) fi fi set -e done fi ;; esac echo "Calling: xrandr ${outputs[@]}" >> $log xrandr ${outputs[@]} } function find_component_in() { local -r component=$1 shift local value for value in "$@" do [[ $value == "$component" ]] && return 0 done return 1 } function get_current_x_information() { # get current xrandr settings current_xrandr=$(xrandr) # get current primary output from xrandr current_primary=$(echo "$current_xrandr" | \ grep -wE '(\bconnected.*primary.*[0-9]{1,5}\x[0-9]{1,5}\+[0-9]{1,5}\+[0-9]{1,5})' | \ cut -d ' ' -f 1) echo "Current primary output: $current_primary" >> $log # get all current active connections active_connections=( "${active_connections[@]:+${active_connections[@]}}" $(echo "$current_xrandr" | \ grep -wE '(\bconnected.*[0-9]{1,5}\x[0-9]{1,5}\+[0-9]{1,5}\+[0-9]{1,5})' | cut -d ' ' -f 1) ) echo "Current active connections: ${active_connections[@]}" >> $log # get all currently available connections available_connections=( "${available_connections[@]:+${available_connections[@]}}" $(echo "$current_xrandr" | \ grep -wE '(\bconnected.*)' | cut -d ' ' -f 1) ) echo "Currently available connections: ${available_connections[@]}" >> $log # get all available connections connections=( "${connections[@]:+${connections[@]}}" $(echo "$current_xrandr"| grep -v 'Screen' | cut -d ' ' -f 1)) echo "All current connections: ${connections[@]}" >> $log } function get_action() { arguments=( "${arguments[@]:+${arguments[@]}}" "${@:+$@}" ) # echo "${@:+$@}" >> $log # echo "${arguments[@]:+${arguments[@]}}" >> $log if [ ${#arguments[@]} -gt 0 ];then if [ "${arguments[0]}" = "button/lid" ]; then case "${arguments[2]}" in "open") action="open" ;; "close") action="close" ;; esac elif [ "${arguments[0]}" = "login" ]; then action="open" fi fi echo "Action set: $action" >> $log } # pass arguments to the script to the get_action function get_action "${@:+$@}" get_current_x_information setup_xscreen