If you use multiple displays on FreeBSD with X11 and have a drawing tablet like a Wacom, you've probably run into the problem where the tablet's drawing area maps to the size of all your screens.
Requirements
- Modern version of FreeBSD (of course)
- Working X11 Environment
- Wacom X11 Drivers and Libraries
The first two requirements will already be met if you are using the Installation script for a FreeBSD based MATE desktop.
To install the required drivers and libraries use:
pkg install -y libwacom xf86-input-wacom
Configure the Tablet
Configure X11 using xinput to limit the drawing area to a single screen.
First get the device ID's for your tablet:
# xinput
⎡ Virtual core pointer id=2 [master pointer (3)]
⎜ ↳ Virtual core XTEST pointer id=4 [slave pointer (2)]
⎜ ↳ System mouse id=6 [slave pointer (2)]
⎜ ↳ Wacom Intuos BT S Pen stylus id=8 [slave pointer (2)]
⎜ ↳ Wacom Intuos BT S Pad pad id=9 [slave pointer (2)]
⎜ ↳ Logitech USB Receiver id=10 [slave pointer (2)]
⎜ ↳ Logitech USB Receiver id=11 [slave pointer (2)]
⎜ ↳ Gamesir Gamesir-GK300 id=12 [slave pointer (2)]
⎜ ↳ Logitech USB Receiver id=13 [slave pointer (2)]
⎜ ↳ 2.4G 2.4G Wireless Device id=14 [slave pointer (2)]
⎜ ↳ Wacom Intuos BT S Pen eraser id=23 [slave pointer (2)]
⎜ ↳ Wacom Intuos BT S Pen cursor id=24 [slave pointer (2)]
⎣ Virtual core keyboard id=3 [master keyboard (2)]
↳ Virtual core XTEST keyboard id=5 [slave keyboard (3)]
↳ System keyboard multiplexer id=7 [slave keyboard (3)]
↳ Power Button id=15 [slave keyboard (3)]
↳ AT keyboard id=16 [slave keyboard (3)]
↳ Logitech USB Receiver id=17 [slave keyboard (3)]
↳ Logitech USB Receiver id=18 [slave keyboard (3)]
↳ Gamesir Gamesir-GK300 id=19 [slave keyboard (3)]
↳ Gamesir Gamesir-GK300 id=20 [slave keyboard (3)]
↳ 2.4G 2.4G Wireless Device id=21 [slave keyboard (3)]
↳ Logitech USB Receiver id=22 [slave keyboard (3)]
That's what my computer looks like. Your output will be different (and maybe have a lot less devices). From the list above we see the Wacom tablet's device ID's are 8, 9, 23, and 24.
Lets use awk to only print the lines with "Wacom" to filter the items.
# xinput | awk '/Wacom/'
⎜ ↳ Wacom Intuos BT S Pen stylus id=8 [slave pointer (2)]
⎜ ↳ Wacom Intuos BT S Pad pad id=9 [slave pointer (2)]
⎜ ↳ Wacom Intuos BT S Pen eraser id=23 [slave pointer (2)]
⎜ ↳ Wacom Intuos BT S Pen cursor id=24 [slave pointer (2)]
Next we need to find our primary screen.
$ xrandr --listactivemonitors
Monitors: 4
0: +*DVI-I-1 1920/521x1080/293+1920+2160 DVI-I-1
1: +HDMI-0 1920/521x1080/293+0+2160 HDMI-0
2: +DVI-D-0 1920/521x1080/293+3840+2160 DVI-D-0
3: +DP-1 3840/941x2160/529+426+0 DP-1
The primary display is indicated by the asterisk (*). The plus sign (+) indicates that it's an active display. Once again we use awk to filter for just the one we are interested in.
xrandr --listactivemonitors | awk '/\+\*/'
Lets save these pieces of information into variables that can be passed to xinput.
PRIMARY_DISPLAY=DVI-I-1
DEVICE_ID_STYLUS=8
DEVICE_ID_PAD=9
DEVICE_ID_ERASER=23
DEVICE_ID_CURSOR=24
Finally run the map-to-output function for xinput to apply the changes. There won't be any output produced unless there was an error.
xinput map-to-output $DEVICE_ID_STYLUS $PRIMARY_DISPLAY
xinput map-to-output $DEVICE_ID_PAD $PRIMARY_DISPLAY
xinput map-to-output $DEVICE_ID_ERASER $PRIMARY_DISPLAY
xinput map-to-output $DEVICE_ID_CURSOR $PRIMARY_DISPLAY
Try using your tablet. The drawing area should be restricted to a single screen, your primary in this case.
Scripting It
You probably noticed there is a lot of repetition in the above command. Perhaps we can do something about that.
With a little extra processing in awk we can have it print only the tablet's device ID's. We won't go into too much detail around awk syntax. The key thing to note is that both RSTART and RLENGTH are set by awk's regex match() function.
xinput | awk '\
/Wacom/ && match($0, /id=[[:space:]]*[0-9]+/) \
{ \
dev=substr($0, RSTART, RLENGTH); \
gsub(/id=[[:space:]]*/, "", dev); \
print dev \
}'
Running the above gives us a list of devices ID's
8
9
23
24
A similar thing can be done for the display. While we are at it, lets assign the result to a variable.
PRIMARY_DISPLAY=$(xrandr --listactivemonitors | awk '/\+\*/ { gsub(/\+\*/, ""); print $2}')
The shell variable PRIMARY_DISPLAY contains the value "DVI-I-1" (for our setup, yours may be different).
We should have enough to write a small script using a simple for loop.
# Case sensitive search for tablet vendor
TABLET_VENDOR="Wacom"
# Get the primary display's port
PRIMARY_DISPLAY=$(xrandr --listactivemonitors | awk '/\+\*/ { gsub(/\+\*/, ""); print $2}')
if [ -z $PRIMARY_DISPLAY ]; then
echo "Unable to find primary display";
exit 1;
fi
# Grab list of tablet device ID's
DEVICE_IDS=$(xinput | awk '/'${TABLET_VENDOR}'/ && match($0, /id=[[:space:]]*[0-9]+/) { dev=substr($0, RSTART, RLENGTH); gsub(/id=[[:space:]]*/, "", dev); print dev }')
# Map devices to the display
for DEVICE_ID in $DEVICE_IDS; do
xinput map-to-output $DEVICE_ID $PRIMARY_DISPLAY
done
I've added a few extra's such as being able to specify your own vendor name for the tablet in place of "Wacom" and a check to make sure a primary display was found.
Make it Persistent
The settings applied using xinput will be lost upon rebooting. To keep them permanent across reboots you need to have these commands executed automatically. There are several ways to do that, but we'll focus on how to do it with SDDM, the display manager used by our FreeBSD based MATE desktop install script.
Our desktop installation script automatically creates a file under /usr/local/etc/sddm.conf.d named FreeBSD.conf. If you do not have such a file, create one now and name it anything you want.
Add the following contents to the end of the file:
[XDisplay]
DisplayCommand=/usr/local/share/sddm/scripts/Xsetup
This creates a new configuration section where we direct SDDM to execute the script: /usr/local/share/sddm/scripts/Xsetup before showing the login screen. The script will run as root.
The file /usr/local/share/sddm/scripts/Xsetup should already exist by default. As the root user, add the Wacom xinput script to it.
#!/bin/sh
# Xsetup - run as root before the login dialog appears
# .... <You may or may not have other stuff in here already> ....
# Case sensitive search for tablet vendor
TABLET_VENDOR="Wacom"
# Get the primary display's port
PRIMARY_DISPLAY=$(xrandr --listactivemonitors | awk '/\+\*/ { gsub(/\+\*/, ""); print $2}')
if [ -z $PRIMARY_DISPLAY ]; then
echo "Unable to find primary display";
exit 1;
fi
# Grab list of tablet device ID's
DEVICE_IDS=$(xinput | awk '/'${TABLET_VENDOR}'/ && match($0, /id=[[:space:]]*[0-9]+/) { dev=substr($0, RSTART, RLENGTH); gsub(/id=[[:space:]]*/, "", dev); print dev }')
# Map devices to the display
for device in $DEVICE_IDS; do
xinput map-to-output $device $PRIMARY_DISPLAY
done
Save the file. Now log out and log back in.
A more portable way of doing this would be to put the script under ~/.xprofile, but that will only execute on a per users basis.
- Log in to post comments