Talk:Calibrating Touchscreen

From ArchWiki
Latest comment: 20 July 2018 by Sanderd17 in topic Wrapper around xinput_calibrator

Touch area

Are you sure about your math? Given the ratio touch_area_width / total_width, you're saying that if the touch area is smaller than the total width, the scaling factor will be less than 1, and thus make the result even smaller yet. On my device, the ratio total_width/touch_area_width is the right value to use for c0. Similar comment for the height/c2 value.

If you're in there, you might mention that all values are normalized WRT 1.0 before being multiplied by this matrix. It's easier to see the point of c1 and c3's equations if you have that fact in mind. Also, for cases where the touchscreen area is a subset of the screen area, these coefficients need to be negative.

Thanks for the most useful article on X's transformation matrices that I could find! Vandyswa (talk) 01:19, 6 October 2013 (UTC) Andy ValenciaReply[reply]

Google Docs calculator

This document is amazing, I created a google docs calculator to build the command for me. It really should not be this difficult to do this, but your instructions worked *perfectly* for me.

Here is the google doc of the calculator:

Sportpeppers (talk) 19:26, 21 April 2014 (UTC)Reply[reply]

the spreadsheet method is obsolete in most cases

As described on the Touchscreen page, now I can do this instead:

xinput --map-to-output $(xinput list --id-only "Advanced Silicon S.A CoolTouch(TM) System") DVI-0

This page is now showing only the hard way. As the header says, the two pages need merging. But the hard way is still relevant when xrandr cannot identify the separate screens because they've been merged into one large screen. —This unsigned comment is by Ecloud (talk) 17:12, 13 July 2016‎. Please sign your posts with ~~~~!

Did you open this to explain your edit? If yes: there is no need for such (as long as an edit is as self-explaining, please use the edit summary box for the edit reason). If you open this item for another point you want to discuss, it does not come across. --Indigo (talk) 20:04, 13 July 2016 (UTC)Reply[reply]

Libinput breaks xinput_calibrator

On my Panasonic CF-30, the xorg conf file generated by xinput_calibrator does not work with libinput. I worked out a very messy way of recalibrating. This could easily be scripted / xinput_calibrator forked, but I'm too lazy to do that at the moment. Here's my notes on how to do it manually:

1. Delete all xorg conf files for calibration and reload X.

2. Find your touchpanel name with the command:

$ xinput 

Mine was "Fujitsu Component USB Touch Panel".

3. Verify your current calibration with this command (replace panel name):

$ xinput list-props "Fujitsu Component USB Touch Panel" | grep "libinput Calibration Matrix"

The matrix should be 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000

4. Run xinput_calibrator in verbose mode:

$ xinput_calibrator -v

Do the calibration, then look for the DEBUG output lines:

DEBUG: Adding click 0 (X=181, Y=132)
DEBUG: Adding click 1 (X=862, Y=129)
DEBUG: Adding click 2 (X=186, Y=661)
DEBUG: Adding click 3 (X=868, Y=665)

We need the X and Y values from click 0 and click 3.

5. Get display resolution using xrandr:

$ xrandr | grep current
Screen 0: minimum 8 x 8, current 1024 x 768, maximum 32767 x 32767

6. We now need to calculate four values, called "a", "c", "e", and "f" (reference).

a = (screen_width * 6 / 8) / (click_3_X - click_0_X)
c = ((screen_width / 8) - (a * click_0_X)) / screen_width
e = (screen_height * 6 / 8) / (click_3_Y - click_0_Y)
f = ((screen_height / 8) - (e * click_0_Y)) / screen_height

7. Test the values with the following command (replace a, c, e, and f with your calculated numbers):

$ xinput set-prop "Fujitsu Component USB Touch Panel" "libinput Calibration Matrix" a, 0.0, c, 0.0, e, f, 0.0, 0.0, 1.0

The touchscreen should be calibrated now. If not, you can undo the calibration with this reset command:

$ xinput set-prop "Fujitsu Component USB Touch Panel" "libinput Calibration Matrix" 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0

8. Determine which udev device corresponds to your panel. I did this by testing all the mouse* devices in /sys/class/input with the following command:

$ udevadm info -a -p /sys/class/input/mouse0

Try each mouse device until you see your panel. You're looking for the lowest block that includes the text SUBSYSTEMS=="input", like so:

 looking at parent device '/devices/pci0000:00/0000:00:1d.0/usb5/5-2/5-2:1.0/0003:0430:0501.0001/input/input5':
   ATTRS{name}=="Fujitsu Component USB Touch Panel"

9. Edit a new udev config file like so:

sudo nano /etc/udev/rules.d/98-touchscreen-cal.rules

Fill in like so, using the ATTRS{name} found in step 8 and filling in the calculated numbers in place of a, c, e, and f):

ATTRS{name}=="Fujitsu Component USB Touch Panel", ENV{LIBINPUT_CALIBRATION_MATRIX}="a 0.0 c 0.0 e f"

10. Reboot and verify.

Zootboy (talk) 01:11, 31 January 2017 (UTC)Reply[reply]

Comments on matrix, fractional coordinates

Zootboy's description, above, was essential for me getting to a working calibration. xinput_calibrator was not working at all (had no effect). I have an old Panasonic CF-29 with a "Fujitsu Lifebook" touchscreen.

My method, with some differences:

  • Run his steps 1-5
  • The "a/c/e/f" calculation is a little hokey. The proper thing to do here is an inverse matrix transformation.

This should use all four points. If X and Y are the resolution width and height, then a Wolfram expression ( is:

{{1/8, 7/8, 1/8, 7/8},                  \[Continuation]
 {1/8, 1/8, 7/8, 7/8},                  \[Continuation]
 {  1,   1,   1,   1}} . PseudoInverse[ \[Continuation]
{{x1/X, x2/X, x3/X, x4/X},              \[Continuation]
{ y1/Y, y2/Y, y3/Y, y4/Y},              \[Continuation]
{    1,    1,    1,    1}}] //N
  • Run steps 7-10.

Reinderien (talk) 04:37, 18 July 2017 (UTC)Reply[reply]

To put some of these thoughts into code I've written - works for me, untested otherwise. Reinderien (talk) 23:55, 22 July 2017 (UTC)Reply[reply]

Comments on making transformation matrix permanent

I've found that instead of creating a udev rule (step 9 above), the transformation matrix can also be set permanently through an xorg.conf.d file. This can be achieved by setting the "TransformationMatrix" option on the input class.

Put the code below into a file called /etc/X11/xorg.conf.d/98-screen-calibration.conf . Change "MatchProduct" to match your touchscreen device name, and use the correct values for a, c, e, and f.

 Section "InputClass"
       Identifier      "calibration"
       MatchProduct    "FT5406 memory based driver"
       Option          "TransformationMatrix"  "a 0.0 c 0.0 e f 0.0 0.0 1.0"

Mogwai (talk) 20:25, 12 February 2018 (UTC)Reply[reply]

Wrapper around xinput_calibrator

Below is a bash script I wrote that wraps around xinput_calibrator and calculates the matrix.

It's a bit dirty:

  • It expects only one input device
  • It expects the xorg output from xinput_calibrator with separate "MinX", "MaxX", ... variables
  • I'm only a beginner when it comes to bash, so there are probably some issues with quoting

Apart from that, it works for me. It sets the calibration immediately by calling xinput (needs to be installed), and also outputs the contents of the xorg conf file

If anyone wants to build on it, or include it in some AUR package or whatnot, please go ahead. Consider it released under the WTFPL.

device=$(xinput_calibrator --list)
device=$(sed -n 's/.*Device\s\"\(.*\)\".*/\1/p' <<< $device)

#reset xinput matrix
xinput set-prop "$device" 'Coordinate Transformation Matrix' 1 0 0 0 1 0 0 0 1


device_name=$(sed -n 's/.*MatchProduct\"\s\"\([0-9]*\).*/\1/p' <<< $out)

wtot=$(sed -n 's/.*max_x=\([0-9]*\).*/\1/p' <<< $out)
htot=$(sed -n 's/.*max_y=\([0-9]*\).*/\1/p' <<< $out)

minx=$(sed -n 's/.*MinX\"\s\"\([0-9]*\).*/\1/p' <<< $out)
maxx=$(sed -n 's/.*MaxX\"\s\"\([0-9]*\).*/\1/p' <<< $out)
miny=$(sed -n 's/.*MinY\"\s\"\([0-9]*\).*/\1/p' <<< $out)
maxy=$(sed -n 's/.*MaxY\"\s\"\([0-9]*\).*/\1/p' <<< $out)

wtouch=$(bc <<< "$maxx - $minx")
htouch=$(bc <<< "$maxy - $miny")

c0=$(bc -l <<< "$wtot / $wtouch")
c1=$(bc -l <<< "-$minx / $wtouch")
c2=$(bc -l <<< "$htot / $htouch")
c3=$(bc -l <<< "-$miny / $htouch")

tf_matrix="$c0 0 $c1 0 $c2 $c3 0 0 1"

#alter the setting for now
xinput set-prop "$device" 'Coordinate Transformation Matrix' $tf_matrix

echo "To make this permanent, save the following content under '/etc/X11/xorg.conf.d/98-screen-calibration.conf' or '/usr/share/X11/xorg.conf.d/98-screen-calibration.conf'"
echo "Section \"InputClass\""
echo "	Identifier \"calibration\""
echo "	MatchProduct \"$device\""
echo "	Option \"TransformationMatrix\" \"$tf_matrix\""
echo "EndSection"

—This unsigned comment is by Sanderd17 (talk) 09:17, 20 July 2018‎ (UTC). Please sign your posts with ~~~~!Reply[reply]

Mention installing the qt5-virtualkeyboard package?

This is my first time commenting on the wiki. I hope this is the right way to go about this. I've been using Arch Linux for a while, but decided to install it on a tablet for the first time. Hours of frustration ensued as I struggled to get a touch keyboard working. It turns out that with Qt applications on Wayland, you need the qt5-virtualkeyboard package installed - or at least that is my understanding of it. But I didn't find anything at all about this on the wiki, and I still don't when I'm specifically looking for it. I only found this out on Reddit.

To be honest, the experience with touch keyboards seems very poor in general, so I feel like it would be helpful to have a section covering how this works. For X, you can use Onboard, but on Wayland you seem to be limited to Gnome's Caribou for GTK applications, and the qt5-virtualkeyboard package for Qt applications.

Bugfix in xinput_calibrator wrapper

I found the wrapper script for xinput_calibrator above had a bug which prevented it from setting the matrix on my machine due to the fact that my touchscreen also registers as a keyboard with the same name (integrated Super key)

This is corrected by prefixing the device name with "pointer:" to indicate that the property should be set to the pointer device, rather than the keyboard.

device="pointer:$(sed -n 's/.*Device\s\"\(.*\)\".*/\1/p' <<< $device)"