# Diff for "XInputCoordinateTransformationMatrixUsage"

Differences between revisions 5 and 6
 ⇤ ← Revision 5 as of 2012-10-17 22:01:13 → Size: 10050 Editor: PeterHutterer Comment: ← Revision 6 as of 2012-12-14 06:33:03 → ⇥ Size: 10709 Editor: annarchy Comment: Add note about how to set the Coordinate Transformation Matrix in an xorg.conf.d file, because it's not at all obvious Deletions are marked like this. Additions are marked like this. Line 13: Line 13: Let's do a quick overview of the math involved. Using an affine transformation means translation can be expressed with matrix multiplication. An Identity matrix lookslike this: Let's do a quick overview of the math involved. Using an affine transformation means translation can be expressed with matrix multiplication.  An Identity matrix looks like this: Line 22: Line 21: Line 30: Line 30: Line 41: Line 42: Line 45: Line 47: Line 49: Line 52: Line 53: Line 57: {{{Coordinate Transformation Matrix (123): 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000}}} {{{Coordinate Transformation Matrix (123): 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000}}} Line 58: Line 62: Line 61: Line 66: To set the Coordinate Transformation Matrix in an xorg.conf type file (e.g., `/etc/X11/xorg.conf.d/90-rotate-screen.conf`), set the `"TransformationMatrix"` option ('''NOT''' `"CoordinateTransformationMatrix"` or `"Coordinate Transformation Matrix"`!!!!) in an `InputDevice` or `InputClass` section (see InputDevice and InputClass sections of www.x.org/archive/current/doc/man/man5/xorg.conf.5.xhtml - the wiki won't let me actually link to it); for example:{{{Section "InputClass" Identifier "RotateTouchCW" MatchProduct "N-Trig MultiTouch" Option "TransformationMatrix" "0 1 0 -1 0 1 0 0 1"EndSection}}} Line 65: Line 78: Line 72: Line 86: Line 83: Line 98: Line 87: Line 103: Line 90: Line 107: Line 95: Line 111: Line 104: Line 121: Line 108: Line 126: Line 111: Line 130: Line 116: Line 134: Line 123: Line 142: Line 127: Line 147: Line 131: Line 152: Line 137: Line 159: Line 143: Line 166: Line 154: Line 178: Line 157: Line 182: Line 159: Line 183: Line 170: Line 195: Line 173: Line 199: Line 176: Line 201: Line 178: Line 202: Line 192: Line 217: Line 196: Line 222: Line 200: Line 227: Line 203: Line 231: Line 205: Line 232:

This feature requires X server 1.8 or later for XRandR configurations, and server 1.12 or later for traditional multihead (== multiple Device sections in the xorg.conf)

# Overview

This page demonstrates how to use the Coordinate Transformation Matrix property to map an absolute device (e.g. a graphic tablet's device like a stylus) to a specific monitor in a multimonitor setup. This method works on a per-device basis, so for a Wacom tablet additional devices may include the eraser, cursor (Wacom tablet mouse), and touch. See here for Wacom-specific notes.

Note: This page describes how to map the tablet to a monitor using the xinput command. Any such configuration will not be persistent, unplugging the device or restarting the server requires re-configuration.

# Matrix-based transformation

Transformation for X input devices uses affine transformation with a matrix. If you know enough about transformation matrix maths already, skip to the next section.

Let's do a quick overview of the math involved. Using an affine transformation means translation can be expressed with matrix multiplication. An Identity matrix looks like this:

```[ 1 0 0 ]
[ 0 1 0 ]
[ 0 0 1 ]```

which has the effect of multiplying by 1, or in other words no transformation, the addition of a third vector value (beyond X & Y) makes it an affine transformation with homogeneous coordinates. We need to determine the transform matrix appropriate to the monitor you want to place the device on. What we will do with the transform is translate the currently assigned pixel coordinate vector X,Y of your tablet device to a new pixel coordinate vector X',Y'. The equation we are looking at is in the form of:

```[ x' ]   [ c0 c1 c2 ]   [ x ]
[ y' ] = [ c3 c4 c5 ] * [ y ]
[ 1  ]   [ c6 c7 c8 ]   [ w ]```

The third vector value w (the row) 0 0 1, with c8 or w always equal to 1, is what makes it affine.

The associated linear equations would be:

```x' = (c0x + c1y + c2) / w'
y' = (c3x + c4y + c5) / w'
w' = (c6x + c7y + c8) = 1```

So c0 and c4 corresponds to the scaling on the X and Y axes, c2 and c5 corresponds to the translation (X & Y offsets) on those axes, and c6, c7, and c8 are always 0, 0 and 1.

All values are in screen width/height units. The value 0 maps to 0, 1 maps width or height (whichever appropriate). Thus, to map a device to half the available screen width, we set c0 to 0.5, if it should be also translated to the right half, c2 is set to 0.5.

# Setting the matrix

First determine the "device name" of what you want bound on a specific screen. Your choices will be the stylus, eraser, cursor (Wacom tablet mouse), or touch. In a terminal enter the following.

`xinput list`

Using the "device name" (in quotes) enter in a terminal.

`xinput list-props "device name"`

For example:

`xinput list-props "Wacom BambooFun 2FG 6x8 Pen stylus"`

This will give an output that contains your current 'Coordinate Transformation Matrix' for the device as the X server sees it.

`Coordinate Transformation Matrix (123): 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000`

The numbers in the X server "Coordinate Transformation Matrix" are a 3x3 matrix read out row by row. To set the matrix to a new value, run

`xinput set-prop "device name" "Coordinate Transformation Matrix" 0.5 0 0.5 0 1 0 0 0 1`

To set the Coordinate Transformation Matrix in an xorg.conf type file (e.g., /etc/X11/xorg.conf.d/90-rotate-screen.conf), set the "TransformationMatrix" option (NOT "CoordinateTransformationMatrix" or "Coordinate Transformation Matrix"!!!!) in an InputDevice or InputClass section (see InputDevice and InputClass sections of www.x.org/archive/current/doc/man/man5/xorg.conf.5.xhtml - the wiki won't let me actually link to it); for example:

```Section "InputClass"
Identifier      "RotateTouchCW"
MatchProduct    "N-Trig MultiTouch"
Option  "TransformationMatrix" "0 1 0 -1 0 1 0 0 1"
EndSection```

## Dual Monitors

### Two monitors with the same resolution

Say both monitors are 1280x1024. You first set up the linear transform (matrix) like so.

```  left:                               right:
[ 1280/(1280+1280)  0         0 ]   [ 1280/(1280+1280)  0          1280/(1280+1280)]
[ 0                 1024/1024 0 ]   [ 0                 1024/1024  0               ]
[ 0                 0         1 ]   [ 0                 0          1               ]```

Using fractions amounts to scaling from 0-1 so you end up with the following.

```  left:         right:
[ 0.5 0 0 ]   [ 0.5 0 0.5 ]
[ 0   1 0 ]   [ 0   1 0   ]
[ 0   0 1 ]   [ 0   0 1   ]```

With the c2 = 0.5 in the right matrix being the x offset.

Now that you've determined the transform use the appropriate xinput command for the monitor you want your device on:

Left monitor

`xinput set-prop "device name" "Coordinate Transformation Matrix" 0.5 0 0 0 1 0 0 0 1`

Right monitor

`xinput set-prop "device name" "Coordinate Transformation Matrix" 0.5 0 0.5 0 1 0 0 0 1`

### Two monitors with different resolutions

example courtesy of Rumtscho @ Ubuntu forums

Left monitor 1280x1024 & right monitor 2560x1440. Setting up the linear transform (matrix).

```  left:                                right:
[ 1280/(1280+2560)  0          0 ]   [ 2560/(1280+2560)  0          1280/(1280+2560)]
[ 0                 1024/1440  0 ]   [ 0                 1440/1440  0               ]
[ 0                 0          1 ]   [ 0                 0          1               ]```

Since for Rumtscho 'xinput list' returned the stylus "device name" as "Wacom BambooFun 2FG 6x8 Pen stylus" the appropriate xinput commands for device placement on the monitors are these.

Left monitor

`xinput set-prop "Wacom BambooFun 2FG 6x8 Pen stylus" --type=float "Coordinate Transformation Matrix" 0.333333 0 0 0 .711111 0 0 0 1`

Right monitor

`xinput set-prop "Wacom BambooFun 2FG 6x8 Pen stylus" --type=float "Coordinate Transformation Matrix" 0.666666 0 0.333333 0 1 0 0 0 1`

### Two monitors with one rotated

example courtesy of lejono @ Ubuntu forums

Left monitor 1600x1200 & right monitor (tablet pc) 1280x800. Tablet pc in laptop mode.

```  left:                                right:
[ 1600/(1600+1280)  0          0 ]   [ 1280/(1600+1280)  0         1600/(1600+1280)]
[ 0                 1200/1200  0 ]   [ 0                 800/1200  0               ]
[ 0                 0          1 ]   [ 0                 0         1               ]```

Left monitor

`xinput set-prop "Serial Wacom Tablet stylus" --type=float "Coordinate Transformation Matrix" 0.555555 0 0 0 1 0 0 0 1`

Right monitor

`xinput set-prop "Serial Wacom Tablet stylus" --type=float "Coordinate Transformation Matrix" 0.444444 0 0.555555 0 0.666666 0 0 0 1`

Now if we rotate to tablet mode we are adding a rotional transformation. Let's use rotation by an angle A counter-clockwise about the origin. The functional form would be x' = xcosA − ysinA and y' = xsinA + ycosA but we want to make it affine so we can use multiplication. And we need to add it to the current matrix. So written in matrix form, it becomes the following.

```[ x' ]   [ cosA*c0 -sinA*c1 c2 ]   [ x ]
[ y' ] = [ sinA*c3  cosA*c4 c5 ] * [ y ]
[ 1  ]   [ c6       c7      c8 ]   [ w ]```

representing the equations:

```x' = (cosA*c0x + -sinA*c1y + c2) / w'
y' = (sinA*c3x +  cosA*c4y + c5) / w'
w' = (c6x      +  c7y      + c8) = 1```

We aren't rotating the left monitor so its matrix doesn't change and we can ignore it. If we rotate the tablet pc 180 degrees to inverted, since cos(180) = -1 and sin(180) = 0 you end up with:

```   right:
[ -1280/(1600+1280)  0        1280/1280 ]
[  0                -800/1200 800/1200  ]
[  0                 0        1         ]

[ -0.444444  0        1        ]
[  0        -0.666666 0.666666 ]
[  0         0        1        ]```

Right monitor rotated to inverted

`xinput set-prop "Serial Wacom Tablet stylus" --type=float "Coordinate Transformation Matrix" -0.444444 0 1 0 -0.666666 0.666666 0 0 1`

Now what happens if we rotate the tablet pc to portrait mode? Note X & Y swap, becoming 800x1280. Since cos(270) = 0 and sin(270) = -1 you end up with this matrix.

```   right:
[  0          800/(1600+800) 1600/(1600+800) ]
[ -1280/1280  0              1280/1280       ]
[  0          0              1               ]

[  0  0.333333 0.666666 ]
[ -1  0        1        ]
[  0  0        1        ]```

Right monitor rotated to portrait

`xinput set-prop "Serial Wacom Tablet stylus" --type=float "Coordinate Transformation Matrix" 0 0.333333 0.666666 -1 0 1 0 0 1`

## Three Monitors

### Three monitors with the same resolution

All three monitors have the same resolution, say 1280x1024. You set up the linear transform and since we're scaling from 0-1 you'd end up with this set of matrices.

```  left                           center                                     right
[ 1280/(3*1280) 0         0 ]  [ 1280/(3*1280) 0         1280/(3*1280) ]  [ 1280/(3*1280) 0         (2*1280)/(3*1280) ]
[ 0             1024/1024 0 ]  [ 0             1024/1024 0             ]  [ 0             1024/1024 0                 ]
[ 0             0         1 ]  [ 0             0         1             ]  [ 0             0         1                 ]

left               center                    right
[ 0.333333 0 0 ]   [ 0.333333 0 0.333333 ]   [ 0.333333 0 0.666666 ]
[ 0        1 0 ]   [ 0        1 0        ]   [ 0        1 0        ]
[ 0        0 1 ]   [ 0        0 1        ]   [ 0        0 1        ]```

So now the xinput commands to set the device to the desired monitor are these.

Left monitor

`xinput set-prop "Device name" --type=float "Coordinate Transformation Matrix" 0.333333 0 0 0 1 0 0 0 1`

Center monitor

`xinput set-prop "Device name" --type=float "Coordinate Transformation Matrix" 0.333333 0 0.333333 0 1 0 0 0 1`

Right monitor

`xinput set-prop "Device name" --type=float "Coordinate Transformation Matrix" 0.333333 0 0.666666 0 1 0 0 0 1`