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

Proper multimonitor support (2nd try) #87

Closed
wants to merge 23 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
e99b02f
Indenting
patrick96 Jun 24, 2017
1d78815
Move brightness detection to function
patrick96 Jun 24, 2017
40b0ee2
Mutlimonitor with individual brightness detection
patrick96 Jun 24, 2017
bcb9c38
Save screenshot in same tmp folder
patrick96 Jun 24, 2017
5c21e0a
Apply the hue and effects to the whole image
patrick96 Jun 25, 2017
893ba91
Add get_text_width function
patrick96 Jun 25, 2017
65ea1a5
Do all operations on the same image
patrick96 Jun 25, 2017
57090a4
Stop creating a folder in /tmp
patrick96 Jun 25, 2017
48a5a61
Handle empty text or whitespace only text
patrick96 Jun 25, 2017
049f3e9
Non recursive rm
patrick96 Jun 25, 2017
4d20111
Mention multimonitor support in README
patrick96 Jun 26, 2017
67d0538
doc: add lock manapge
sim590 Jun 27, 2017
09dc623
Use e-mail address listed in script
patrick96 Jun 28, 2017
b2f2a36
Add "SEE ALSO" section with i3lock
patrick96 Jun 28, 2017
f027d9f
Don't use -h description used in script
patrick96 Jun 28, 2017
de5aec9
Make description more clear
patrick96 Jun 28, 2017
61b3e01
Update README.md
AladW Jun 29, 2017
0ed8cec
Mutlimonitor with individual brightness detection
patrick96 Jun 24, 2017
f35cc15
Save screenshot in same tmp folder
patrick96 Jun 24, 2017
87b7379
Stop creating a folder in /tmp
patrick96 Jun 25, 2017
7bf2980
Non recursive rm
patrick96 Jun 25, 2017
52b469f
Merge remote-tracking branch 'upstream/master' into multimonitor
patrick96 Jul 23, 2017
c3c0bc8
Lower the threshold for displaying the dark lock
patrick96 Mar 4, 2018
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
6 changes: 1 addition & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,4 @@ Systemd Unit file example (edit for your own use):

Multiple Monitors
-----------------
There is a branch called dual monitor with support for multiple monitors. This
branch uses a grey icon and text with outlines to make it visible on light and
dark backgrounds (though it looks better on dark backgrounds). I am still
working to get it looking just right right. The script is usable now, but it's
under developement and things may change.
This script fully supports multiple monitors. The lock and text are drawn on the center of each monitor.
144 changes: 125 additions & 19 deletions lock
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,80 @@
# Dependencies: imagemagick, i3lock-color-git, scrot, wmctrl (optional)
set -o errexit -o noclobber -o nounset

# Determines the brightness of the screenshot
# $1 - Image file to check
# $2 - Arguments passed to 'convert'. For example this can be used to crop the image, to just sample a part of it
get_brightness() {
# Quite fast way of getting a brightness value
convert "$1" +repage $2 -colorspace gray -format "%[fx:round(100*mean)]" info:
}

# Determines the width of the given text when processed using the text_options flag
# $1 - The text to checked
# Prints the text width in pixels to stdout
get_text_width() {
# empty text or text containing only whitespace would throw an error so we just return zero
if [ -z "${1// }" ]; then
echo 0
return
fi
convert "${text_options[@]}" label:"$1" -format "%[fx:w]\n" info:
}

# Calculates the absolute positions for the lock and text or the given monitor, generates the command line arguemnts
# for convert that apply the lock icon and the text to the proper locations and adds them to the decorations_params array
# $1 - Monitor Width
# $2 - Monitor Height
# $3 - X Offset
# $4 - Y Offset
# Prints the brigthness in the center of the monitor to file descriptor 3
# This is used to determine the average brightness in the centers of all the monitors and to then set the proper colors
# for i3lock-color
process_monitor() {
width=$1
height=$2
x_offset=$3
y_offset=$4

# center coordinates relative to the current monitor
x_mid=$((width / 2))
y_mid=$((height / 2))

# absolute X, Y coordinates of the top left edge of the text
x_text=$((x_offset + x_mid - (text_width / 2)))
y_text=$((y_offset + y_mid + 160))

# absolute X, Y coordinates of the top left edge of the icon
# The lock icon has dimensions 60x60, we subtract half of that from each dimension
# If the lock dimensions ever change, these values here need to be changed too
x_icon=$((x_offset + x_mid - 30))
y_icon=$((y_offset + y_mid - 30))

# Get brightness for the middle of the monitor
brightness="$(get_brightness "$image" "-crop 100x100+$x_icon+$y_icon")"

if [ "$brightness" -gt "$threshold" ]; then # bright background image and black text
text_color="black"
icon="$scriptpath/icons/lockdark.png"
else # dark background image and white text
text_color="white"
icon="$scriptpath/icons/lock.png"
fi

decoration_params+=(+repage)

if [ "$text_width" -ne 0 ]; then
# Only add text flags, if there actually is text
decoration_params+=("${text_options[@]}" -fill "$text_color" -annotate "+$x_text+$y_text" "$text")
fi

decoration_params+=("$icon" -geometry "+$x_icon+$y_icon" -composite)


# Write brightness to file descriptor
exec 3<<< "$brightness"
}

# get path where the script is located to find the lock icon
scriptpath=$(readlink -f -- "$0")
scriptpath=${scriptpath%/*}
Expand All @@ -11,9 +85,14 @@ hue=(-level "0%,100%,0.6")
effect=(-filter Gaussian -resize 20% -define "filter:sigma=1.5" -resize 500.5%)
# default system sans-serif font
font=$(convert -list font | awk "{ a[NR] = \$2 } /family: $(fc-match sans -f "%{family}\n")/ { print a[NR-1]; exit }")
image=$(mktemp --suffix=.png)
shot=(import -window root)

image="$(mktemp --suffix=.png)"

# brightness value to compare to, everything above is considered white and everything below black
threshold="40"

desktop=""
shot=(import -window root)
i3lock_cmd=(i3lock -i "$image")
shot_custom=false

Expand Down Expand Up @@ -77,9 +156,9 @@ while true ; do
esac ;;
-t|--text) text=$2 ; shift 2 ;;
-l|--listfonts)
convert -list font | awk -F: '/Font: / { print $2 }' | sort -du | command -- ${PAGER:-less}
exit 0 ;;
-n|--nofork) i3lock_cmd+=(--nofork) ; shift ;;
convert -list font | awk -F: '/Font: / { print $2 }' | sort -du | command -- ${PAGER:-less}
exit 0 ;;
-n|--nofork) i3lock_cmd+=(--nofork) ; shift ;;
--) shift; shot_custom=true; break ;;
*) echo "error" ; exit 1 ;;
esac
Expand All @@ -89,32 +168,59 @@ if "$shot_custom" && [[ $# -gt 0 ]]; then
shot=("$@");
fi

command -- "${shot[@]}" "$image"

value="60" #brightness value to compare to
text_options=(-font "$font" -pointsize 26)
text_width=$(get_text_width "$text")

color=$(convert "$image" -gravity center -crop 100x100+0+0 +repage -colorspace hsb \
-resize 1x1 txt:- | awk -F '[%$]' 'NR==2{gsub(",",""); printf "%.0f\n", $(NF-1)}');
command -- "${shot[@]}" "$image"

if [[ $color -gt $value ]]; then #white background image and black text
bw="black"
icon="$scriptpath/icons/lockdark.png"
# All the arguments to be passed to convert, to add the lock and text to the monitors is collected here so that we can
# apply them in a single call to convert
decoration_params=()

# We collect the brightness values from all the monitors and average them, from that we determine which flags to pass to
# i3lock-color since the colors for i3lock-color cannot be specified per monitor.
# We could also just call get_brightness on the whole image but process_monitor samples only the center
# of the screen where the lock actually is, so we get a better value for the brightness
sum_brightness=0
num_monitors=0

# Loop through all connected monitors (as reported by xrandr)
# For each monitor the convert arguments to add the lock and text to that monitor are generated
while read -r monitor; do
if [[ "$monitor" =~ ([0-9]+)x([0-9]+)\+([0-9]+)\+([0-9]+) ]]; then
width=${BASH_REMATCH[1]}
height=${BASH_REMATCH[2]}
x_offset=${BASH_REMATCH[3]}
y_offset=${BASH_REMATCH[4]}

# We get the return value from the function by using a new file descriptor
# The traditional approach of using $(process_monitor ...) and echo doesn't work because it forks into a
# subshell and then process_monitor cannot access decoration_params
exec 3>&-
process_monitor "$width" "$height" "$x_offset" "$y_offset" && read -r brightness <&3
exec 3>&-

sum_brightness=$((brightness + sum_brightness))
num_monitors=$((num_monitors + 1))
fi
done <<<"$(xrandr --verbose | grep "\bconnected\b")"

convert "$image" "${hue[@]}" "${effect[@]}" "${decoration_params[@]}" "$image"

avg_brightness=$((sum_brightness / num_monitors))

if [ "$avg_brightness" -gt "$threshold" ]; then # Screenshot is rather bright, so we use dark colors
param=("--textcolor=00000000" "--insidecolor=0000001c" "--ringcolor=0000003e" \
"--linecolor=00000000" "--keyhlcolor=ffffff80" "--ringvercolor=ffffff00" \
"--separatorcolor=22222260" "--insidevercolor=ffffff1c" \
"--ringwrongcolor=ffffff55" "--insidewrongcolor=ffffff1c")
else #black
bw="white"
icon="$scriptpath/icons/lock.png"
else # Bright colors
param=("--textcolor=ffffff00" "--insidecolor=ffffff1c" "--ringcolor=ffffff3e" \
"--linecolor=ffffff00" "--keyhlcolor=00000080" "--ringvercolor=00000000" \
"--separatorcolor=22222260" "--insidevercolor=0000001c" \
"--ringwrongcolor=00000055" "--insidewrongcolor=0000001c")
fi

convert "$image" "${hue[@]}" "${effect[@]}" -font "$font" -pointsize 26 -fill "$bw" -gravity center \
-annotate +0+160 "$text" "$icon" -gravity center -composite "$image"

# If invoked with -d/--desktop, we'll attempt to minimize all windows (ie. show
# the desktop) before locking.
${desktop} ${desktop:+-k on}
Expand Down