Why multi-touch fail to work for multi-display?

Leslie Zhai xiangzhai83 at gmail.com
Sat Oct 19 05:31:08 CEST 2013


Hi Xorg developers,

I use Projected Capacitive touch screen device
http://en.wikipedia.org/wiki/Touchscreen#Projected_capacitance
It can be pasted on the normal monitor, then it is able to touch, the
cursor
will move to the position where touched. It experienced like iphone and
other
single touch screen device.

But when I put multiple Projected Capacitive touch screen devices on
several
monitors, then touch some of them simultaneously, the cursor of X Window
was
only moving in the first monitor, even though it was able to move to other
monitors` display, it still failed to show the correct position.

Why? Some people might argue that it is Linux kernel Multi-touch
Protocol issue
https://www.kernel.org/doc/Documentation/input/multi-touch-protocol.txt

Nope!

For Protocol Example B

Here is what a minimal event sequence for a two-contact touch would look
like for a type B device:

ABS_MT_SLOT 0
ABS_MT_TRACKING_ID 45
ABS_MT_POSITION_X x[0]
ABS_MT_POSITION_Y y[0]
ABS_MT_SLOT 1
ABS_MT_TRACKING_ID 46
ABS_MT_POSITION_X x[1]
ABS_MT_POSITION_Y y[1]
SYN_REPORT

Here is the sequence after moving contact 45 in the x direction:

ABS_MT_SLOT 0
ABS_MT_POSITION_X x[0]
SYN_REPORT

Here is the sequence after lifting the contact in slot 0:

ABS_MT_TRACKING_ID -1
SYN_REPORT

The slot being modified is already 0, so the ABS_MT_SLOT is omitted. The
message removes the association of slot 0 with contact 45, thereby
destroying contact 45 and freeing slot 0 to be reused for another contact.

Finally, here is the sequence after lifting the second contact:

ABS_MT_SLOT 1
ABS_MT_TRACKING_ID -1
SYN_REPORT

Here ABS_MT_SLOT distinguished which finger touch the screen,
ABS_MT_POSITION_X and ABS_MT_POSITION_Y shown the position where the finger
touched. In case ABS_MT_XXX martix like below:

(0, 0)-------------------------(4075, 0)
| |
| |
| |
| (X, Y) |
| |
| |
| |
| |
| |
| |
| |
(0, 4095)-------------------(4075, 4095)

For single touch screen device situation, the X axis range of the
position is
[0, 4075], the Y`s is [0, 4095]; then for multi-devices, the matrix
could not
be transformed, the range might never be changed, it will not increased by
multiply the number of monitors. It means if I could touch several
monitors in
the same or about position simultaneously, I am so lucky :) the (X, Y)
position
values might be the same, then the cursor of X Window wired.

Then someone might be doubt about it is X evdev input driver issue
http://cgit.freedesktop.org/xorg/driver/xf86-input-evdev/

In the function EvdevAddAbsValuatorClass(DeviceIntPtr device,
int want_scroll_axes)
http://cgit.freedesktop.org/xorg/driver/xf86-input-evdev/tree/src/evdev.c#n1249

It only consider about one single device, a Projected Capacitive touch
screen
device connected to Linux box via USB, but what about multi-touch
devices, how
to handle several file descriptors? It might be fixed by Leslie
MultiTouch way!

Leslie MultiTouch

I hacked the get devices function via reading /proc/bus/input/devices

void getDevices(std::string DeviceName, std::vector<std::string>* Devices)
{
std::string strLine;
std::string strDevPath;
std::ifstream DevFile("/proc/bus/input/devices");
int nPos;

while (std::getline(DevFile, strLine))
{
if (strLine.size() == 0)
continue;

if (strLine[0] == 'N')
{
if (ToLower(strLine).find(ToLower(DeviceName)) != std::string::npos)
{
while (std::getline(DevFile, strLine))
{
if (strLine[0] == 'H')
break;
}
nPos = strLine.find("event");
if (nPos != std::string::npos) {
strDevPath = "/dev/input/" + strLine.substr(nPos, strLine.size() - nPos
- 1);
#if DEBUG
// such as /dev/input/event13
std::cout << "DEBUG: " << strDevPath << std::endl;
#endif
Devices->push_back(strDevPath);
}
}
}
}
}

Then it need to create a thread pool to handle several DeviceIntPtr objects
simultaneously.

And it need to identify each touch screen device like Xorg Xinerama conf
style:

Section "MultiTouchLayout"
Identifier "MultiTouch Device"
Device 0 "Device0" 0 0
Device 1 "Device1" RightOf "Device0" # LeftOf, BelowOf, AboveOf
Option "MultiTouch" "true"
EndSection

Section "Device"
Identifier "Device0"
Device "/dev/input/event13"
Monitor "Monitor0"
DefaultDepth 24
SubSection "Display"
Viewport 0 0
Depth 24
Modes "1680x1050"
EndSubSection
EndSection

Section "Device"
Identifier "Device1"
Device "/dev/input/event16"
Monitor "Monitor1"
DefaultDepth 24
SubSection "Display"
Viewport 0 0
Depth 24
Modes "1680x1050"
EndSubSection
EndSection

Then when it send a (X, Y) position event from the touch screen devices`
thread
pool, it is able to know which device generate it, and it need to
transform the
old (X, Y) position to monitor_N`s new (X`, Y`), the cursor of X Window
might
never wired any more.

Best Regards,

Leslie


More information about the xorg-devel mailing list