Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various enhancements #10

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions data/systemd-service/sleep-display-visor.service
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[Unit]
Description=Reconfigure the displays after waking up from sleep

[Service]
Type=oneshot
ExecStart=/usr/bin/pkill -x -RTMIN+5 display-visor

[Install]
WantedBy=sleep.target
317 changes: 172 additions & 145 deletions src/display-visor
Original file line number Diff line number Diff line change
@@ -1,19 +1,29 @@
#!/bin/bash
version="0.4"
notif_header_outputchange="Monitor settings change"
screen0=LVDS1
screen1=HDMI1
screen2=VGA1

usage ()
{
echo \
'Usage: display-visor [-f] [-i] [-l [switch]]
echo "Usage: display-visor [-h] [-f] [-i] [-l [switch]] [-n] [-e] [-0 [screen]] [-1 [screen]] [-2 [screen]] [-v]

-h, --help Print this help.
-f, --feh Run feh bg script.
Executes ~/.fehbg upon completion.
-i, --i3 Test for i3wm instance.
For avoiding conflict with multiple environments.
-l, --lid Check laptop lid status.
Ignored/Assumed closed if not given.
Ignored/Assumed closed if not given.
It is possible to specify switch. Defaults to 'LID0'
If unsure, look under /proc/acpi/button/lid/...
-n, --notif Issue a notification on each monitor change.
This uses notify-send over dbus. Notification daemon has to be running.
-e, --noecho Don't echo each monitor change.
-0, --screen0 Specify new name for screen 0 (default: LVDS1).
-1, --screen1 Specify new name for screen 1 (default: HDMI1).
-2, --screen2 Specify new name for screen 2 (default: VGA1).
-v, --version Print version info.

Useful for setting monitor layouts on system login/resume/hotplug
Expand All @@ -22,192 +32,209 @@ usage ()
Depends on xorg-xrandr.

This is free software.
2015, Michael Heyns <https://github.com/beanaroo>
'
2015, Michael Heyns <https://github.com/beanaroo>"
}

handle_args ()
{
while [ "$1" != "" ]; do
case $1 in
-h | --help ) usage
exit
;;
-f | --feh ) fehbg=true
;;
-i | --i3 ) i3test=true
;;
-l | --lid ) lidtest=true
lidswitch=${2:-LID0}
lidstatus=$(cat /proc/acpi/button/lid/$lidswitch/state 2>/dev/null | awk '{print $NF}')
shift
;;
-v | --version ) echo "display-visor $version"
exit
;;
* ) usage
exit 1
;;
exit;;
-f | --feh ) fehbg=true;;
-i | --i3 ) i3test=true;;
-l | --lid ) lidtest=true
if [ "${2:0:1}" == - -o -z "$2" ]; then
lidswitch=LID0
else
lidswitch=$2
shift
fi
lidstatus=$(cat /proc/acpi/button/lid/$lidswitch/state 2>/dev/null | awk '{print $NF}');;
-n | --notif ) notification=true;;
-e | --noecho ) noecho=true;;
-0 | --screen0 ) screen0=$2
shift;;
-1 | --screen1 ) screen1=$2
shift;;
-2 | --screen2 ) screen2=$2
shift;;
-v | --version ) echo "display-visor v$version"
exit;;
* ) usage
exit 1;;
esac
shift
done
}


## Error Handling
## error handling
handle_err ()
{
# Test for running Xorg server
if [ -z "$(ps -C Xorg --no-headers)" ]; then
echo "$prefix No Xorg server found. Exiting..."
exit 1
fi

# Test for running instance of i3
if [ "$i3test" == "true" -a -z "$(ps -C i3 --no-headers)" ]; then
echo "$prefix i3wm not running. Exiting..."
exit 1
fi

# Test for valid laptop lid status.
if [ "$lidtest" == "true" -a -z "$lidstatus" ]; then
echo "$prefix Laptop lid switch $lidswitch not found. Exiting..."
exit 1
fi
# test for running Xorg server
if [ -z "$(ps -C Xorg --no-headers)" ]; then
user_output "$prefix No Xorg server found. Exiting..."
exit 1
fi

# test for running instance of i3
if [ "$i3test" == "true" -a -z "$(ps -C i3 --no-headers)" ]; then
user_output "$prefix i3wm not running. Exiting..."
exit 1
fi

# test for valid laptop lid status
if [ "$lidtest" == "true" -a -z "$lidstatus" ]; then
user_output "$prefix Laptop lid switch $lidswitch not found. Exiting..."
exit 1
fi
}

# user output
user_output ()
{
if [ "$1" ]; then
if [ -z "$noecho" ]; then
echo $prefix $1
fi
if [ "$2" == "1" -a "$notification" ]; then
notify-send -u low -a "display-visor" "$3" "$1"
fi
fi
}

## Declare Output Devices
## declare output devices
declare_outputs ()
{
devices=$(find /sys/class/drm/*/status)
while read l ; do
dir=$(dirname $l)
status=$(cat $l)
dev=$(echo $dir | cut -d\- -f 2-)

if [ $(expr match $dev "HDMI") != "0" ]; then
dev=HDMI${dev#HDMI-?-}
else
dev=$(echo $dev | tr -d '-')
fi

if [ "connected" == "$status" ]; then
echo "$prefix $dev connected"
declare -gA $dev="yes"
fi
done <<< "$devices"
devices=$(find /sys/class/drm/*/status)
while read l ; do
dev=$(echo $(dirname $l) | cut -d\- -f 2-)

if [ $(expr match $dev "HDMI") != "0" ]; then
dev=HDMI${dev#HDMI-?-}
else
dev=$(echo $dev | tr -d '-')
fi

if [ "connected" == $(cat $l) ]; then
user_output "$dev connected"
declare -gA $dev="yes"
fi
done <<< "$devices"
}

## Configure monitors for closed lid
## configure monitors for closed lid
config_closed_lid ()
{
if [ "$lidstatus" == "closed" ]; then
echo "$prefix Laptop lid is closed"
elif [ -n "$LVDS1" -a -z "$lidtest" ]; then
echo "$prefix Laptop display will be ignored unless -l option is set"
fi
if [ -n "$HDMI1" -a -n "$VGA1" ]; then
echo "$prefix SETTING: HDMI1 (Primary) - VGA1 (Right)"
xrandr --output LVDS1 --off \
--output HDMI1 --auto --primary \
--output VGA1 --auto --right-of HDMI1
elif [ -n "$HDMI1" -a -z "$VGA1" ]; then
echo "$prefix SETTING: HDMI1 (Primary)"
xrandr --output LVDS1 --off \
--output VGA1 --off \
--output HDMI1 --auto --primary
elif [ -z "$HDMI1" -a -n "$VGA1" ]; then
echo "$prefix SETTING: VGA1 (Primary)"
xrandr --output LVDS1 --off \
--output HDMI1 --off \
--output VGA1 --auto --primary
else
echo "$prefix No external monitors are plugged in"
xrandr --output HDMI1 --off \
--output VGA1 --off \
--output LVDS1 --auto --primary
fi
if [ "$lidstatus" == "closed" ]; then
user_output "Laptop lid is closed."
elif [ "${!screen0}" -a -z "$lidtest" ]; then
user_output "Laptop display will be ignored unless -l option is set."
fi
if [ "${!screen1}" -a "${!screen2}" ]; then
user_output "SETTING: $screen1 (Primary) - $screen2 (Right)." 1 "$notif_header_outputchange"
xrandr --output $screen0 --off \
--output $screen1 --auto --primary \
--output $screen2 --auto --right-of $screen1
elif [ "${!screen1}" -a -z "${!screen2}" ]; then
user_output "SETTING: $screen1 (Primary)." 1 "$notif_header_outputchange"
xrandr --output $screen0 --off \
--output $screen1 --auto --primary \
--output $screen2 --off
elif [ -z "${!screen1}" -a "${!screen2}" ]; then
user_output "SETTING: $screen2 (Primary)." 1 "$notif_header_outputchange"
xrandr --output $screen0 --off \
--output $screen1 --off \
--output $screen2 --auto --primary
else
user_output "No external monitors are plugged in." 1 "$notif_header_outputchange"
xrandr --output $screen0 --auto --primary \
--output $screen1 --off \
--output $screen2 --off
fi
}

## Configure monitors for open lid
## configure monitors for open lid
config_open_lid ()
{
echo "$prefix Laptop lid is open"
if [ -n "$HDMI1" -a -n "$VGA1" ]; then
echo "$prefix SETTING: LVDS1 (Left) - HDMI1 (Primary) - VGA1 (Right)"
xrandr --output LVDS1 --off \
--output HDMI1 --auto --primary \
--output VGA1 --auto --right-of HDMI1
elif [ -n "$HDMI1" -a -z "$VGA1" ]; then
echo "$prefix HDMI1 is plugged in, but not VGA1"
echo "$prefix SETTING: LVDS1 (Primary) - HDMI1 (Right)"
xrandr --output VGA1 --off \
--output LVDS1 --auto --primary \
--output HDMI1 --auto --right-of LVDS1 --noprimary
elif [ -z "$HDMI1" -a -n "$VGA1" ]; then
echo "$prefix SETTING: LVDS1 (Primary) - VGA1 (Right)"
xrandr --output HDMI1 --off \
--output LVDS1 --auto --primary \
--output VGA1 --auto --right-of LVDS1 --noprimary
else
echo "$prefix No external monitors are plugged in"
xrandr --output HDMI1 --off \
--output VGA1 --off \
--output LVDS1 --auto --primary
fi
user_output "Laptop lid is open."
if [ "${!screen1}" -a "${!screen2}" ]; then
user_output "$screen1 and $screen2 are plugged in."
user_output "SETTING: $screen1 (Primary) - $screen2 (Right)." 1 "$notif_header_outputchange"
xrandr --output $screen0 --off \
--output $screen1 --auto --primary \
--output $screen2 --auto --right-of $screen1
elif [ "${!screen1}" -a -z "${!screen2}" ]; then
# work mode: one big screen as main, laptop with smaller screen right of it
user_output "$screen1 is plugged in, but not $screen2. Work mode."
user_output "SETTING: $screen1 (Primary) - $screen0 (Right)." 1 "$notif_header_outputchange"
xrandr --output $screen1 --auto --primary \
--output $screen0 --auto --right-of $screen1 \
--output $screen2 --off
elif [ -z "${!screen1}" -a "${!screen2}" ]; then
# presentation mode: laptop main screen, presentation on external output
user_output "$screen2 is plugged in, but not $screen1. Presentation mode."
user_output "SETTING: $screen0 (Primary) - $screen2 (Right)." 1 "$notif_header_outputchange"
xrandr --output $screen0 --auto --primary \
--output $screen1 --off \
--output $screen2 --auto --right-of $screen0
else
user_output "No external monitors are plugged in." 1 "$notif_header_outputchange"
xrandr --output $screen0 --auto --primary \
--output $screen1 --off \
--output $screen2 --off
fi
}

# main configuration function
configure_displays ()
{

handle_err

declare_outputs

if [ -z "$lidstatus" -o "$lidstatus" == "closed" ]; then
config_closed_lid
elif [ "$lidstatus" == "open" ]; then
config_open_lid
fi

# Run .fehbg script if -f argument is given.
if [ "$fehbg" == "true" ]; then
if [ -x $HOME/.fehbg ]; then
echo "$prefix Setting background using .fehbg."
$($HOME/.fehbg 2>/dev/null)
else
echo ".$prefix Failed to execute ~/.fehbg script. Use 'feh --bg-xxx' to generate one."
fi
fi

# FIXME: Prevent segfault occurring from simultanious signals. -- Issue #5 --
handle_err

declare_outputs

if [ -z "$lidstatus" -o "$lidstatus" == "closed" ]; then
config_closed_lid
elif [ "$lidstatus" == "open" ]; then
config_open_lid
fi

# run .fehbg script if -f argument is given
if [ "$fehbg" == "true" ]; then
if [ -x $HOME/.fehbg ]; then
user_output "Setting background using .fehbg."
$($HOME/.fehbg 2>/dev/null)
else
user_output "Failed to execute ~/.fehbg script. Use 'feh --bg-xxx' to generate one."
fi
fi

# FIXME: prevent segfault occurring from simultanious signals -- Issue #5 --
sleep 2

}

#-----------#
# Begin #
# Begin #
#-----------#

# Set exit signal trap.
# set exit signal trap
trap "echo 'Received interrupt. Exiting...' ; exit" SIGHUP SIGINT SIGQUIT

# Log output.
#prefix='[ display-visor: ]:'
exec 1> >(logger -s -t "display-visor") 2>&1
# log output
prefix='[ display-visor: ]:'
#exec 1> >(logger -s -t "display-visor") 2>&1

# Handle arguments.
# handle arguments
handle_args "$@"

# Configure displays upon initialization.
# configure displays upon initialization
configure_displays

# Set reconfigure trap.
# set reconfigure trap
trap "echo 'Received signal. Reconfiguring displays.' ; configure_displays" RTMIN+5

# Wait for signals
# wait for signals
while :
do
sleep 60 &
wait
sleep 60 &
wait
done