# XInputCoordinateTransformationMatrixUsage

You can upload content for the page named below. If you change the page name, you can also upload content for another page. If the page name is empty, we derive the page name from the file name.

File to load page content from
Page name
Comment
What is 4 + 8

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`