evdevtouch: Make TouchPointReleased working with certain drivers

The plugin failed to handle releases with protocol type A with some
drivers. There is no requirement to emit ABS_MT_TOUCH_MAJOR or
BTN_TOUCH to indicate a release. If the point is gone from the report,
it is a release as well.

Change-Id: I9527fbfb200fde3b160148e076357a29bf610427
Reviewed-by: Gunnar Sletta <gunnar.sletta@digia.com>
Reviewed-by: Andy Nichols <andy.nichols@digia.com>
This commit is contained in:
Laszlo Agocs 2013-09-17 12:26:03 +02:00 committed by The Qt Project
parent 61e0534aff
commit cfd5284249

View File

@ -114,6 +114,7 @@ public:
int findClosestContact(const QHash<int, Contact> &contacts, int x, int y, int *dist); int findClosestContact(const QHash<int, Contact> &contacts, int x, int y, int *dist);
void reportPoints(); void reportPoints();
void registerDevice(); void registerDevice();
void addTouchPoint(const Contact &contact, Qt::TouchPointStates *combinedStates);
int hw_range_x_min; int hw_range_x_min;
int hw_range_x_max; int hw_range_x_max;
@ -342,6 +343,31 @@ void QEvdevTouchScreenHandler::readData()
d->processInputEvent(&buffer[i]); d->processInputEvent(&buffer[i]);
} }
void QEvdevTouchScreenData::addTouchPoint(const Contact &contact, Qt::TouchPointStates *combinedStates)
{
QWindowSystemInterface::TouchPoint tp;
tp.id = contact.trackingId;
tp.flags = contact.flags;
tp.state = contact.state;
*combinedStates |= tp.state;
// Store the HW coordinates for now, will be updated later.
tp.area = QRectF(0, 0, contact.maj, contact.maj);
tp.area.moveCenter(QPoint(contact.x, contact.y));
tp.pressure = contact.pressure;
// Get a normalized position in range 0..1.
tp.normalPosition = QPointF((contact.x - hw_range_x_min) / qreal(hw_range_x_max - hw_range_x_min),
(contact.y - hw_range_y_min) / qreal(hw_range_y_max - hw_range_y_min));
if (!m_rotate.isIdentity())
tp.normalPosition = m_rotate.map(tp.normalPosition);
tp.rawPositions.append(QPointF(contact.x, contact.y));
m_touchPoints.append(tp);
}
void QEvdevTouchScreenData::processInputEvent(input_event *data) void QEvdevTouchScreenData::processInputEvent(input_event *data)
{ {
if (data->type == EV_ABS) { if (data->type == EV_ABS) {
@ -398,13 +424,11 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data)
m_touchPoints.clear(); m_touchPoints.clear();
Qt::TouchPointStates combinedStates; Qt::TouchPointStates combinedStates;
QMutableHashIterator<int, Contact> it(m_contacts); QMutableHashIterator<int, Contact> it(m_contacts);
while (it.hasNext()) { while (it.hasNext()) {
it.next(); it.next();
QWindowSystemInterface::TouchPoint tp;
Contact &contact(it.value()); Contact &contact(it.value());
tp.id = contact.trackingId;
tp.flags = contact.flags;
int key = m_typeB ? it.key() : contact.trackingId; int key = m_typeB ? it.key() : contact.trackingId;
if (m_lastContacts.contains(key)) { if (m_lastContacts.contains(key)) {
@ -427,29 +451,24 @@ void QEvdevTouchScreenData::processInputEvent(input_event *data)
continue; continue;
} }
tp.state = contact.state; addTouchPoint(contact, &combinedStates);
combinedStates |= tp.state;
// Store the HW coordinates for now, will be updated later.
tp.area = QRectF(0, 0, contact.maj, contact.maj);
tp.area.moveCenter(QPoint(contact.x, contact.y));
tp.pressure = contact.pressure;
// Get a normalized position in range 0..1.
tp.normalPosition = QPointF((contact.x - hw_range_x_min) / qreal(hw_range_x_max - hw_range_x_min),
(contact.y - hw_range_y_min) / qreal(hw_range_y_max - hw_range_y_min));
if (!m_rotate.isIdentity())
tp.normalPosition = m_rotate.map(tp.normalPosition);
tp.rawPositions.append(QPointF(contact.x, contact.y));
m_touchPoints.append(tp);
if (contact.state == Qt::TouchPointReleased) if (contact.state == Qt::TouchPointReleased)
it.remove(); it.remove();
} }
// Now look for contacts that have disappeared since the last sync.
it = m_lastContacts;
while (it.hasNext()) {
it.next();
Contact &contact(it.value());
int key = m_typeB ? it.key() : contact.trackingId;
if (!m_contacts.contains(key)) {
contact.state = Qt::TouchPointReleased;
addTouchPoint(contact, &combinedStates);
}
}
m_lastContacts = m_contacts; m_lastContacts = m_contacts;
if (!m_typeB && !m_singleTouch) if (!m_typeB && !m_singleTouch)
m_contacts.clear(); m_contacts.clear();