Bug fix #62: Rewrite a part of compton-trans

Rewrite a part of compton-trans in order to provide more friendly
error messages, to support window title that contains spaces, and to
limit the number of xwininfo calls to a constant. Not much tests are
done, and I don't know bash well, so bugs could very well exist.
This commit is contained in:
Richard Grenville 2012-11-08 22:34:53 +08:00
parent 56ce896feb
commit 08ca5b4d1e
1 changed files with 75 additions and 51 deletions

View File

@ -15,7 +15,8 @@
# increment current window 5% # increment current window 5%
# settrans -c -o +5 # settrans -c -o +5
if test -z "$(which xprop)" -o -z "$(which xwininfo)"; then # "command" is a shell built-in, faster than "which"
if test -z "$(command -v xprop)" -o -z "$(command -v xwininfo)"; then
echo "Please install x11-utils/xorg-xprop/xorg-xwininfo." >& 2 echo "Please install x11-utils/xorg-xprop/xorg-xwininfo." >& 2
exit 1 exit 1
fi fi
@ -23,8 +24,6 @@ fi
window= window=
opacity= opacity=
cur= cur=
root=
parent=
active= active=
i= i=
@ -34,59 +33,84 @@ while getopts "scn:w:o:" option; do
c) c)
active=$(xprop -root -notype "_NET_ACTIVE_WINDOW" \ active=$(xprop -root -notype "_NET_ACTIVE_WINDOW" \
| sed 's/^.*\(0x\S*\).*$/\1/') | sed 's/^.*\(0x\S*\).*$/\1/')
window="-id $active" wprefix='-id '; window="$active"
;; ;;
n) window="-name $OPTARG" ;; n) wprefix='-name '; window="$OPTARG" ;;
w) window="-id $OPTARG" ;; w) wprefix='-id '; window="$OPTARG" ;;
o) opacity="$OPTARG" ;; o) opacity="$OPTARG" ;;
esac esac
done done
root=$(xwininfo -all -root \ # Validate opacity value
| grep "Root window id" \ if [ -z "$opacity" ]; then
| sed 's/^.*\(0x\S*\).*$/\1/') echo "No opacity specified."
parent=$window
i=0
while true; do
parent=$(xwininfo -all $parent \
| grep Parent \
| sed 's/^.*\(0x\S*\).*$/\1/')
if test "$parent" = "$root"; then
break
fi
parent="-id $parent"
window=$parent
i=$((i+1))
if test $i -ge 1000; then
echo "An error occurred while traversing up the window tree." >& 2
echo "Please report this to https://github.com/chjj/compton/issues." >& 2
echo "Please mention your WM and versions of xwininfo/xprop." >& 2
exit 1 exit 1
fi fi
done
inc=$(echo "$opacity" | sed 's/^\(+\|-\).*$\|^.*$/\1/') opacity="$(echo "$opacity" \
if test -n "$inc"; then | sed -rn 's/^[[:space:]]*([+-]?[[:digit:]]+)[[:space:]]*$/\1/p')"
cur=$(xprop $window -notype "_NET_WM_WINDOW_OPACITY" \
if [ -z "$opacity" ]; then
echo "Invalid opacity value."
exit 1
fi
# Get ID of the target window
wid=$(xwininfo $wprefix"$window" | sed -n 's/^xwininfo:.*: \(0x[[:xdigit:]]*\).*$/\1/p')
if [ -z "$wid" ]; then
echo "Failed to find window."
exit 1
fi
treeout="$(xwininfo -id "$wid" -children)"
# Make sure it's not root window
if echo "$treeout" | fgrep "Parent window id: 0x0" > /dev/null; then
echo "Cannot set opacity on root window."
exit 1
fi
# Get the whole window tree
treeout="$(xwininfo -root -tree)"
if [ -z "$treeout" ]; then
echo "Failed to get root window tree."
exit 1
fi
# Find the line number of the target window in the window tree
lineno="$(echo -n "$treeout" | grep -nw "$wid" | head -n1 | cut -d ':' -f 1)"
if [ -z "$lineno" ]; then
echo "Failed to find window in window tree."
exit 1
fi
# Find the highest ancestor of the target window below
topmost=$(echo -n "$treeout" | head -n $(($lineno + 1)) | sed -n 's/^ \(0x[[:xdigit:]]*\).*/\1/p' | tail -n1)
if [ -z "$topmost" ]; then
echo "Failed to find the highest parent window below root of the" \
"selected window."
exit 1
fi
# Calculate the desired opacity
if echo "$opacity" | grep '^[+-]' > /dev/null; then
sign=$(echo "$opacity" | cut -b1)
cur=$(xprop -id "$topmost" -notype "_NET_WM_WINDOW_OPACITY" \
| sed 's/^.*\b\([0-9]\+\).*$\|^.*$/\1/') | sed 's/^.*\b\([0-9]\+\).*$\|^.*$/\1/')
test -z "$cur" && cur=$((0xffffffff)) [ -z "$cur" ] && cur=0xffffffff
cur=$((cur*100/0xffffffff)) cur=$((cur * 100 / 0xffffffff))
opacity=$(echo "$opacity" | sed 's/\(\+\|\-\)//') opacity="$(echo "$opacity" | sed 's/^[+-]//')"
if test "$inc" = "+"; then opacity=$(($cur $sign $opacity))
opacity=$((cur+opacity))
else
opacity=$((cur-opacity))
fi
fi fi
if test -n "$opacity" -a -n "$window"; then [ $opacity -lt 0 ] && opacity=0
test $opacity -lt 0 && opacity=0 [ $opacity -gt 100 ] && opacity=100
test $opacity -gt 100 && opacity=100
opacity=$((opacity*0xffffffff/100)) # Set opacity
xprop $window -f _NET_WM_WINDOW_OPACITY 32c \ opacity=$(($opacity * 0xffffffff / 100))
xprop -id "$topmost" -f _NET_WM_WINDOW_OPACITY 32c \
-set _NET_WM_WINDOW_OPACITY "$opacity" -set _NET_WM_WINDOW_OPACITY "$opacity"
fi