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>
This commit is contained in:
parent
10bf53ae19
commit
40e4949674
@ -1922,6 +1922,7 @@ static const char * xcb_atomnames = {
|
|||||||
"Abs MT Position Y\0"
|
"Abs MT Position Y\0"
|
||||||
"Abs MT Touch Major\0"
|
"Abs MT Touch Major\0"
|
||||||
"Abs MT Touch Minor\0"
|
"Abs MT Touch Minor\0"
|
||||||
|
"Abs MT Orientation\0"
|
||||||
"Abs MT Pressure\0"
|
"Abs MT Pressure\0"
|
||||||
"Abs MT Tracking ID\0"
|
"Abs MT Tracking ID\0"
|
||||||
"Max Contacts\0"
|
"Max Contacts\0"
|
||||||
|
@ -261,6 +261,7 @@ namespace QXcbAtom {
|
|||||||
AbsMTPositionY,
|
AbsMTPositionY,
|
||||||
AbsMTTouchMajor,
|
AbsMTTouchMajor,
|
||||||
AbsMTTouchMinor,
|
AbsMTTouchMinor,
|
||||||
|
AbsMTOrientation,
|
||||||
AbsMTPressure,
|
AbsMTPressure,
|
||||||
AbsMTTrackingID,
|
AbsMTTrackingID,
|
||||||
MaxContacts,
|
MaxContacts,
|
||||||
|
@ -48,6 +48,7 @@ struct XInput2TouchDeviceData {
|
|||||||
XInput2TouchDeviceData()
|
XInput2TouchDeviceData()
|
||||||
: xiDeviceInfo(0)
|
: xiDeviceInfo(0)
|
||||||
, qtTouchDevice(0)
|
, qtTouchDevice(0)
|
||||||
|
, providesTouchOrientation(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
XIDeviceInfo *xiDeviceInfo;
|
XIDeviceInfo *xiDeviceInfo;
|
||||||
@ -59,6 +60,7 @@ struct XInput2TouchDeviceData {
|
|||||||
QPointF firstPressedPosition; // in screen coordinates where the first point was pressed
|
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
|
QPointF firstPressedNormalPosition; // device coordinates (0 to 1, 0 to 1) where the first point was pressed
|
||||||
QSizeF size; // device size in mm
|
QSizeF size; // device size in mm
|
||||||
|
bool providesTouchOrientation;
|
||||||
};
|
};
|
||||||
|
|
||||||
void QXcbConnection::initializeXInput2()
|
void QXcbConnection::initializeXInput2()
|
||||||
@ -413,6 +415,8 @@ XInput2TouchDeviceData *QXcbConnection::touchDeviceForId(int id)
|
|||||||
caps |= QTouchDevice::Position | QTouchDevice::NormalizedPosition;
|
caps |= QTouchDevice::Position | QTouchDevice::NormalizedPosition;
|
||||||
else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor))
|
else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor))
|
||||||
caps |= QTouchDevice::Area;
|
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))
|
else if (vci->label == atom(QXcbAtom::AbsMTPressure) || vci->label == atom(QXcbAtom::AbsPressure))
|
||||||
caps |= QTouchDevice::Pressure;
|
caps |= QTouchDevice::Pressure;
|
||||||
else if (vci->label == atom(QXcbAtom::RelX)) {
|
else if (vci->label == atom(QXcbAtom::RelX)) {
|
||||||
@ -574,7 +578,9 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
|
|||||||
QXcbScreen* screen = platformWindow->xcbScreen();
|
QXcbScreen* screen = platformWindow->xcbScreen();
|
||||||
qreal x = fixed1616ToReal(xiDeviceEvent->root_x);
|
qreal x = fixed1616ToReal(xiDeviceEvent->root_x);
|
||||||
qreal y = fixed1616ToReal(xiDeviceEvent->root_y);
|
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) {
|
for (int i = 0; i < dev->xiDeviceInfo->num_classes; ++i) {
|
||||||
XIAnyClassInfo *classinfo = dev->xiDeviceInfo->classes[i];
|
XIAnyClassInfo *classinfo = dev->xiDeviceInfo->classes[i];
|
||||||
if (classinfo->type == XIValuatorClass) {
|
if (classinfo->type == XIValuatorClass) {
|
||||||
@ -599,7 +605,24 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
|
|||||||
} else if (vci->label == atom(QXcbAtom::AbsMTPositionY)) {
|
} else if (vci->label == atom(QXcbAtom::AbsMTPositionY)) {
|
||||||
ny = valuatorNormalized(value, vci);
|
ny = valuatorNormalized(value, vci);
|
||||||
} else if (vci->label == atom(QXcbAtom::AbsMTTouchMajor)) {
|
} 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) ||
|
} else if (vci->label == atom(QXcbAtom::AbsMTPressure) ||
|
||||||
vci->label == atom(QXcbAtom::AbsPressure)) {
|
vci->label == atom(QXcbAtom::AbsPressure)) {
|
||||||
touchPoint.pressure = valuatorNormalized(value, vci);
|
touchPoint.pressure = valuatorNormalized(value, vci);
|
||||||
@ -616,8 +639,18 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
|
|||||||
ny = y / screen->geometry().height();
|
ny = y / screen->geometry().height();
|
||||||
}
|
}
|
||||||
if (xiDeviceEvent->evtype != XI_TouchEnd) {
|
if (xiDeviceEvent->evtype != XI_TouchEnd) {
|
||||||
if (d == 0.0)
|
if (!dev->providesTouchOrientation) {
|
||||||
d = touchPoint.area.width();
|
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) {
|
switch (xiDeviceEvent->evtype) {
|
||||||
@ -681,7 +714,7 @@ void QXcbConnection::xi2ProcessTouch(void *xiDevEvent, QXcbWindow *platformWindo
|
|||||||
}
|
}
|
||||||
dev->pointPressedPosition.remove(touchPoint.id);
|
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);
|
touchPoint.normalPosition = QPointF(nx, ny);
|
||||||
|
|
||||||
if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled()))
|
if (Q_UNLIKELY(lcQpaXInput().isDebugEnabled()))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user