summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
diff options
context:
space:
mode:
authorAlexander Volkov <a.volkov@rusbitech.ru>2015-06-11 18:29:44 +0300
committerAlexander Volkov <a.volkov@rusbitech.ru>2016-02-03 07:44:14 +0000
commit40e4949674eaf7ceb09f6d18479ead1a36b384fd (patch)
tree000dad81d42969b9278b7d66fd007ae3585abc4f /src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
parent10bf53ae19836bfcac5d674f12c3915834878694 (diff)
xcb: Take into account the orientation of touch points
Add support for ABS_MT_ORIENTATION value. Linux kernel multi-touch protocol allows it to be in a wide range: https://www.kernel.org/doc/Documentation/input/multi-touch-protocol.txt, but we need only to know whether the touch point rect is rotated by 90 degress. So adjust the angle to the closest axis. Change-Id: Ie20725dc4bef509e2f9b19571efc69502d00c019 Reviewed-by: Shawn Rutledge <shawn.rutledge@theqtcompany.com>
Diffstat (limited to 'src/plugins/platforms/xcb/qxcbconnection_xi2.cpp')
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp43
1 files changed, 38 insertions, 5 deletions
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index e055ad1424..358988534b 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -48,6 +48,7 @@ struct XInput2TouchDeviceData {
XInput2TouchDeviceData()
: xiDeviceInfo(0)
, qtTouchDevice(0)
+ , providesTouchOrientation(false)
{
}
XIDeviceInfo *xiDeviceInfo;
@@ -59,6 +60,7 @@ struct XInput2TouchDeviceData {
QPointF firstPressedPosition; // in screen coordinates where the first point was pressed
QPointF firstPressedNormalPosition; // device coordinates (0 to 1, 0 to 1) where the first point was pressed
QSizeF size; // device size in mm
+ bool providesTouchOrientation;
};
void QXcbConnection::initializeXInput2()
@@ -413,6 +415,8 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
caps |= QTouchDevice::Position | QTouchDevice::NormalizedPosition;
else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor))
caps |= QTouchDevice::Area;
+ else if (vci->label == atom(QXcbAtom::AbsMTOrientation))
+ dev->providesTouchOrientation = true;
else if (vci->label == atom(QXcbAtom::AbsMTPressure) || vci->label == atom(QXcbAtom::AbsPressure))
caps |= QTouchDevice::Pressure;
else if (vci->label == atom(QXcbAtom::RelX)) {
@@ -574,7 +578,9 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
QXcbScreen* screen = platformWindow->xcbScreen();
qreal x = fixed1616ToReal(xiDeviceEvent->root_x);
qreal y = fixed1616ToReal(xiDeviceEvent->root_y);
- qreal nx = -1.0, ny = -1.0, d = 0.0;
+ qreal nx = -1.0, ny = -1.0;
+ qreal w = 0.0, h = 0.0;
+ bool majorAxisIsY = touchPoint.area.height() > touchPoint.area.width();
for (int i = 0; i < dev->xiDeviceInfo->num_classes; ++i) {
XIAnyClassInfo *classinfo = dev->xiDeviceInfo->classes[i];
if (classinfo->type == XIValuatorClass) {
@@ -599,7 +605,24 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
} else if (vci->label == atom(QXcbAtom::AbsMTPositionY)) {
ny = valuatorNormalized(value, vci);
} else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor)) {
- d = valuatorNormalized(value, vci) * screen->geometry().width();
+ const qreal sw = screen->geometry().width();
+ const qreal sh = screen->geometry().height();
+ w = valuatorNormalized(value, vci) * std::sqrt(sw * sw + sh * sh);
+ } else if (vci->label == atom(QXcbAtom::AbsMTTouchMinor)) {
+ const qreal sw = screen->geometry().width();
+ const qreal sh = screen->geometry().height();
+ h = valuatorNormalized(value, vci) * std::sqrt(sw * sw + sh * sh);
+ } else if (vci->label == atom(QXcbAtom::AbsMTOrientation)) {
+ // Find the closest axis.
+ // 0 corresponds to the Y axis, vci->max to the X axis.
+ // Flipping over the Y axis and rotating by 180 degrees
+ // don't change the result, so normalize value to range
+ // [0, vci->max] first.
+ value = qAbs(value);
+ while (value > vci->max)
+ value -= 2 * vci->max;
+ value = qAbs(value);
+ majorAxisIsY = value < vci->max - value;
} else if (vci->label == atom(QXcbAtom::AbsMTPressure) ||
vci->label == atom(QXcbAtom::AbsPressure)) {
touchPoint.pressure = valuatorNormalized(value, vci);
@@ -616,8 +639,18 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
ny = y / screen->geometry().height();
}
if (xiDeviceEvent->evtype != XI_TouchEnd) {
- if (d == 0.0)
- d = touchPoint.area.width();
+ if (!dev->providesTouchOrientation) {
+ if (w == 0.0)
+ w = touchPoint.area.width();
+ h = w;
+ } else {
+ if (w == 0.0)
+ w = qMax(touchPoint.area.width(), touchPoint.area.height());
+ if (h == 0.0)
+ h = qMin(touchPoint.area.width(), touchPoint.area.height());
+ if (majorAxisIsY)
+ qSwap(w, h);
+ }
}
switch (xiDeviceEvent->evtype) {
@@ -681,7 +714,7 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
}
dev->pointPressedPosition.remove(touchPoint.id);
}
- touchPoint.area = QRectF(x - d/2, y - d/2, d, d);
+ touchPoint.area = QRectF(x - w/2, y - h/2, w, h);
touchPoint.normalPosition = QPointF(nx, ny);
if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled()))