I am developing a Qt 6.8 touch-based application where an Android client sends touch data to a Windows server application. The Windows server receives multi-touch data and needs to simulate touch events for pan and zoom gestures.
Issue:
Previously, in Qt 5, the following code worked perfectly using QTouchEvent with direct setters to simulate multi-touch gestures:
Qt 5 Working Code:
Code:
struct TouchPoint { int id; short posX, posY; short lastPosX, lastPosY; short startPosX, startPosY; int state; unsigned short pressure; // 0 to 65535. }; void simulateTouch (const TouchPacket *packet) { const TouchPacket::e_touchType type = packet->touchType(); const Qt::TouchPointStates states = static_cast<Qt::TouchPointStates>(packet->touchStates()); const Qt::KeyboardModifiers modifiers = packet->getQtModifiers(); const int numPoints = static_cast<int> ( packet->touchPoints().size() ); QList< QTouchEvent::TouchPoint > points; points.reserve( numPoints ); const int width = this->mainWindow->width(); const int height = this->mainWindow->height(); while (parent->parentWidget() != 0) { parent = parent->parentWidget(); } // need the position of the top level widget (position is relative to desktop and not parent widget) for (int i(0); i<numPoints; ++i) { const TouchPacket::TouchPoint & pkPoint( packet->touchPoints()[i] ); nextPt.setLastNormalizedPos(QPointF(pkPoint.lastPosX / qreal(width), pkPoint.lastPosY / qreal(height))); nextPt.setStartNormalizedPos(QPointF(pkPoint.startPosX / qreal(width), pkPoint.startPosY / qreal(height))); nextPt.setScenePos (nextPt.pos()); nextPt.setScreenPos(pos + nextPt.pos()); nextPt.setLastScenePos (nextPt.lastPos()); nextPt.setLastScreenPos(pos + nextPt.lastPos()); nextPt.setStartScenePos(nextPt.startPos()); nextPt.setStartScreenPos(pos + nextPt.startPos()); nextPt.setPressure( 1.0 ); //((double)pkPoint.pressure ) / 65535. ) ; nextPt.setState (static_cast<Qt::TouchPointStates>(pkPoint.state)); points.push_back(nextPt); //qDebug() << nextPt.pos() << nextPt.normalizedPos() << nextPt.state() << nextPt.pressure() << nextPt.screenRect(); } QTouchEvent * tevent = NULL; switch (type) { case TouchPacket::TouchBegin: break; case TouchPacket::TouchCancel: break; case TouchPacket::TouchEnd: break; case TouchPacket::TouchUpdate: break; default: qWarning() << "Unknown touch packet" << type; } if (tevent) { // The post event queue will take ownership of the event and delete it once it has been posted //qDebug() << "posting to" << currentWidget << "with" << tevent->touchPoints().count() << "points" << states; } }
Problem in Qt 6:
After migrating to Qt 6, QTouchEvent::TouchPoint and its setters are no longer available. Instead, Qt 6 uses QEventPoint and QMutableEventPoint, but only a few setters are available in QMutableEventPoint.
I receive touch data in the following struct from the client:
Code:
struct TouchPoint { int id; short posX, posY; short lastPosX, lastPosY; short startPosX, startPosY; int state; unsigned short pressure; // 0 to 65535 };
I attempted to migrate the Qt 5 code using QEventPoint but ran into issues:
Attempted Qt 6 Migration Code:
Code:
void simulateTouch (const TouchPacket *packet) { const TouchPacket::e_touchType type = packet->touchType(); const Qt::TouchPointStates states = static_cast<Qt::TouchPointStates>(packet->touchStates()); const Qt::KeyboardModifiers modifiers = packet->getQtModifiers(); const int numPoints = static_cast<int> ( packet->touchPoints().size() ); QList< QTouchEvent::TouchPoint > points; points.reserve( numPoints ); const int width = this->mainWindow->width(); const int height = this->mainWindow->height(); while (parent->parentWidget() != 0) { parent = parent->parentWidget(); } // need the position of the top level widget (position is relative to desktop and not parent widget) for (int i(0); i<numPoints; ++i) { const TouchPacket::TouchPoint & pkPoint( packet->touchPoints()[i] ); QTouchEvent::TouchPoint nextPt( pkPoint.id ); // Assign state based on touch type QEventPoint::State pointState = QEventPoint::State::Unknown; switch (type) { case TouchPacket::TouchBegin: pointState = QEventPoint::State::Pressed; break; case TouchPacket::TouchUpdate: pointState = QEventPoint::State::Updated; break; case TouchPacket::TouchEnd: pointState = QEventPoint::State::Released; break; case TouchPacket::TouchCancel: pointState = QEventPoint::State::Stationary; break; default: break; } QMutableEventPoint::setPressure(nextPtNew, pkPoint.pressure); QMutableEventPoint::setState(nextPtNew, pointState); QMutableEventPoint::setGlobalLastPosition(nextPtNew, QPointF(pkPoint.posX + pos.x(), pkPoint.posY + pos.y())); QMutableEventPoint::setScenePosition(nextPtNew, QPointF(pkPoint.posX + pos.x(), pkPoint.posY + pos.y())); points.push_back(nextPtNew); } QTouchEvent * tevent = NULL; switch (type) { case TouchPacket::TouchBegin: //tevent = new QTouchEvent( QEvent::TouchBegin, &this->touchDevice, modifiers, states, points ); break; case TouchPacket::TouchCancel: //tevent = new QTouchEvent( QEvent::TouchCancel, &this->touchDevice, modifiers, states, points ); break; case TouchPacket::TouchEnd: //tevent = new QTouchEvent( QEvent::TouchEnd, &this->touchDevice, modifiers, states, points ); break; case TouchPacket::TouchUpdate: //tevent = new QTouchEvent( QEvent::TouchUpdate, &this->touchDevice, modifiers, states, points ); break; default: qWarning() << "Unknown touch packet" << type; } if (tevent && !points.isEmpty()) { // The post event queue will take ownership of the event and delete it once it has been posted //qDebug() << "posting to" << currentWidget << "with" << tevent->touchPoints().count() << "points" << states; } }
Questions:
- How can I correctly migrate my Qt 5 touch event simulation code to Qt 6?
- What is the correct way to construct and append QMutableEventPoint to QPointerEvent?
- Are there additional event properties I need to set to ensure continuous pan and zoom gestures?
- Is there a recommended approach to simulate multi-touch gestures like pan and zoom in Qt 6?
Need alternative setters / ways for the below API
Code:
QTouchEvent::TouchPoint nextPt( pkPoint.id ); nextPt.setLastNormalizedPos(QPointF(pkPoint.lastPosX / qreal(width), pkPoint.lastPosY / qreal(height))); nextPt.setStartNormalizedPos(QPointF(pkPoint.startPosX / qreal(width), pkPoint.startPosY / qreal(height))); nextPt.setScenePos (nextPt.pos()); nextPt.setScreenPos(pos + nextPt.pos()); nextPt.setLastScenePos (nextPt.lastPos()); nextPt.setLastScreenPos(pos + nextPt.lastPos()); nextPt.setStartScenePos(nextPt.startPos()); nextPt.setStartScreenPos(pos + nextPt.startPos());
- Any guidance on this migration process would be highly appreciated!