Skip to content

Instantly share code, notes, and snippets.

@rschroll
Created August 10, 2021 03:25
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rschroll/60dc8c118e6751604a5321ee5b16f251 to your computer and use it in GitHub Desktop.
Save rschroll/60dc8c118e6751604a5321ee5b16f251 to your computer and use it in GitHub Desktop.
Wacom Tablet to Window Mapping
#!/bin/bash
# Map the tablet to cover a particular window, while maintaining its aspect
# ratio. If run from the terminal, it allows the user to click on the window
# for mapping. Otherwise, use the currently focused window. Should the
# window aspect ratio not match the tablet aspect ratio, the tablet will
# cover an additional area of the screen, to maintain the correct aspect
# ratio. By default, the window will be aligned with the top-left corner
# of the tablet, but options adjust the horizontal (-l, -c, -r) and vertical
# (-t, -m, -b) alignment.
#
# Note that for decorated windows, the window area does not include the
# title bar. For undecorated windows, the window area may extent beyond
# the visible area, to include any shadow effects.
#
# It can be handy to hook this script up to one of the buttons on the tablet.
# In GNOME, I did this by setting a system-wide shortcut to run the script,
# and then connected the left tablet button to that shortcut. Since the
# script isn't running in a terminal, it immediately sets the tablet to map
# to the current active window.
# If you have a different tablet, you may need to adjust the name. Run
# `xsetwacom --list devices` to see what yours is.
TABLET="Wacom Intuos S Pen stylus"
XWI_ARGS=""
if [[ ! -t 0 ]]; then
XWI_ARGS="-id $(xprop -root 32x '\t$0' _NET_ACTIVE_WINDOW | cut -f 2)"
fi
# Default is to map the upper-left corner of the tablet to the upper-left
# corner of the window. This makes sense, at least for right-handers, since
# it gives you more of the tablet under your hand. I originally thought
# centering would make more sense, but experience suggests otherwise.
xf=0
yf=0
while getopts ":tmblcr" opt; do
case ${opt} in
t)
yf=0
;;
m)
yf=1
;;
b)
yf=2
;;
l)
xf=0
;;
c)
xf=1
;;
r)
xf=2
;;
\?)
echo "Alignment options:"
echo " -t Top"
echo " -m Middle"
echo " -b Bottom"
echo " -l Left"
echo " -c Center"
echo " -r Right"
exit 1
;;
esac
done
shift $((OPTIND - 1))
# https://unix.stackexchange.com/a/14170
# Get the coordinates of the active window's
# top-left corner, and the window's size.
# This excludes the window decoration.
read -d '' wx wy ww wh <<<$(xwininfo $XWI_ARGS |
sed -n -e "s/^ \+Absolute upper-left X: \+\(-\?[0-9]\+\).*/\1/p" \
-e "s/^ \+Absolute upper-left Y: \+\(-\?[0-9]\+\).*/\1/p" \
-e "s/^ \+Width: \+\([0-9]\+\).*/\1/p" \
-e "s/^ \+Height: \+\([0-9]\+\).*/\1/p" )
read -r tx ty tw th <<<$(xsetwacom --get "$TABLET" Area)
war=$(bc -l <<<$(echo "$ww / $wh" ))
tar=$(bc -l <<<$(echo "$tw / $th" ))
if (( $(bc <<<$(echo "$war > $tar")) )); then
# Window is wider than tablet. Tablet should be mapped to greater height than window
mw=$ww
mh=$(bc <<<$(echo "$wh * $war / $tar" ))
mx=$wx
my=$(( $wy - ($mh - $wh) * $yf / 2 ))
else
# Tablet is wider than window. Tablet should be mapped to greater width than window
mw=$(bc <<<$(echo "$ww * $tar / $war" ))
mh=$wh
mx=$(( $wx - ($mw - $ww) * $xf / 2 ))
my=$wy
fi
set -x
xsetwacom --set "$TABLET" MapToOutput "${mw}x${mh}+${mx}+${my}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment