Details
-
Bug
-
Resolution: Fixed
-
P1: Critical
-
None
-
5.15.1, 6.2.0, 6.3.0
-
None
-
-
2419064c3532e2efd3bcf2f23c9c690b0a0fdd00(qt/qtwayland/dev) 7ce31f7f65f8d79c1f8763eb75b3ea238b727654(qt/tqtc-qtwayland/lts-5.15) 54d886d420bc0bc0a5d1c8fa28336665d8c77812(qt/qtwayland/6.3) 612a45059eae4cb7b30b70228f2debaf11f4e4cb(qt/qtwayland/6.2)
Description
Touch event may be ignored when main GUI thread is slow.
*. Current implementation
1. qwaylandintegration.cpp
Wayland event dispatch is done in the main GUI thread.
void QWaylandIntegration::initialize() { QAbstractEventDispatcher *dispatcher = QGuiApplicationPrivate::eventDispatcher; QObject::connect(dispatcher, SIGNAL(aboutToBlock()), mDisplay.data(), SLOT(flushRequests())); QObject::connect(dispatcher, SIGNAL(awake()), mDisplay.data(), SLOT(flushRequests())); int fd = wl_display_get_fd(mDisplay->wl_display()); QSocketNotifier *sn = new QSocketNotifier(fd, QSocketNotifier::Read, mDisplay.data()); QObject::connect(sn, SIGNAL(activated(QSocketDescriptor)), mDisplay.data(), SLOT(flushRequests())); // Qt does not support running with no screens mDisplay->ensureScreen(); }
2. Currently, the time stamp is set when event dispatch occurs in the main GUI thread, not when touch.frame occurs from wayland compositor.
qwaylandinputdevice.cpp
void QWaylandInputDevice::Touch::touch_frame() { ... QWindowSystemInterface::handleTouchEvent(window, mParent->mTouchDevice, mPendingTouchPoints); ... }
qwindowsysteminterface.cpp: timestamp will be set here using QWindowSystemInterfacePrivate::eventTime.elapsed() which is millisecond unit.
So, several touch events are likely to be ignored when the main thread is slow.
QT_DEFINE_QPA_EVENT_HANDLER(bool, handleTouchEvent, QWindow *window, QTouchDevice *device, const QList<TouchPoint> &points, Qt::KeyboardModifiers mods) { unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); return handleTouchEvent<Delivery>(window, time, device, points, mods); } QT_DEFINE_QPA_EVENT_HANDLER(bool, handleTouchEvent, QWindow *window, ulong timestamp, QTouchDevice *device, const QList<TouchPoint> &points, Qt::KeyboardModifiers mods) { if (!points.size()) // Touch events must have at least one point return false; if (!QTouchDevicePrivate::isRegistered(device)) // Disallow passing bogus, non-registered devices. return false; QEvent::Type type; QList<QTouchEvent::TouchPoint> touchPoints = QWindowSystemInterfacePrivate::fromNativeTouchPoints(points, window, QTouchDevicePrivate::get(device)->id, &type); QWindowSystemInterfacePrivate::TouchEvent *e = new QWindowSystemInterfacePrivate::TouchEvent(window, timestamp, type, device, touchPoints, mods); return QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e); }
For example, touch event could be ignored at this point.
void QQuickFlickablePrivate::handleMouseMoveEvent(QMouseEvent *event) { ... if (currentTimestamp == lastTimestamp) { return; // events are too close together: velocity would be infinite } ... }
Attachments
For Gerrit Dashboard: QTBUG-100150 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
391562,4 | Fix wayland touch event to use time stamp from wayland compositor | dev | qt/qtwayland | Status: MERGED | +2 | 0 |
391986,3 | Fix wayland touch event to use time stamp from wayland compositor | tqtc/lts-5.15 | qt/tqtc-qtwayland | Status: MERGED | +2 | 0 |
392028,2 | Fix wayland touch event to use time stamp from wayland compositor | 6.3 | qt/qtwayland | Status: MERGED | +2 | 0 |
392089,2 | Fix wayland touch event to use time stamp from wayland compositor | 6.2 | qt/qtwayland | Status: MERGED | +2 | 0 |