diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/kernel/qevent.h | 4 | ||||
-rw-r--r-- | src/gui/kernel/qguiapplication.cpp | 142 | ||||
-rw-r--r-- | src/gui/kernel/qguiapplication_p.h | 3 | ||||
-rw-r--r-- | src/widgets/kernel/qwidgetwindow_qpa.cpp | 11 | ||||
-rw-r--r-- | src/widgets/kernel/qwidgetwindow_qpa_p.h | 1 |
5 files changed, 159 insertions, 2 deletions
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index de0d6b3793..d46e66b064 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -738,6 +738,8 @@ public: private: QTouchEventTouchPointPrivate *d; + friend class QGuiApplication; + friend class QGuiApplicationPrivate; friend class QApplication; friend class QApplicationPrivate; }; @@ -771,6 +773,8 @@ protected: Qt::TouchPointStates _touchPointStates; QList<QTouchEvent::TouchPoint> _touchPoints; + friend class QGuiApplication; + friend class QGuiApplicationPrivate; friend class QApplication; friend class QApplicationPrivate; }; diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index d5e08e1934..e1d40806bc 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -738,9 +738,147 @@ void QGuiApplicationPrivate::processCloseEvent(QWindowSystemInterfacePrivate::Cl QGuiApplication::sendSpontaneousEvent(e->window.data(), &event); } -void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::TouchEvent *) +void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::TouchEvent *e) { -// translateRawTouchEvent(e->widget.data(), e->devType, e->points); + QWindow *window = e->window.data(); + QGuiApplicationPrivate *d = self; + typedef QPair<Qt::TouchPointStates, QList<QTouchEvent::TouchPoint> > StatesAndTouchPoints; + QHash<QWindow *, StatesAndTouchPoints> windowsNeedingEvents; + + for (int i = 0; i < e->points.count(); ++i) { + QTouchEvent::TouchPoint touchPoint = e->points.at(i); + // explicitly detach from the original touch point that we got, so even + // if the touchpoint structs are reused, we will make a copy that we'll + // deliver to the user (which might want to store the struct for later use). + touchPoint.d = touchPoint.d->detach(); + + // update state + QWeakPointer<QWindow> w; + QTouchEvent::TouchPoint previousTouchPoint; + switch (touchPoint.state()) { + case Qt::TouchPointPressed: + if (e->devType == QTouchEvent::TouchPad) { + // on touch-pads, send all touch points to the same widget + w = d->windowForTouchPointId.isEmpty() + ? QWeakPointer<QWindow>() + : d->windowForTouchPointId.constBegin().value(); + } + + if (!w) { + // determine which window this event will go to + if (!window) + window = QGuiApplication::topLevelAt(touchPoint.screenPos().toPoint()); + if (!window) + continue; + w = window; + } + + d->windowForTouchPointId[touchPoint.id()] = w; + touchPoint.d->startScreenPos = touchPoint.screenPos(); + touchPoint.d->lastScreenPos = touchPoint.screenPos(); + touchPoint.d->startNormalizedPos = touchPoint.normalizedPos(); + touchPoint.d->lastNormalizedPos = touchPoint.normalizedPos(); + if (touchPoint.pressure() < qreal(0.)) + touchPoint.d->pressure = qreal(1.); + + d->appCurrentTouchPoints.insert(touchPoint.id(), touchPoint); + break; + + case Qt::TouchPointReleased: + w = d->windowForTouchPointId.take(touchPoint.id()); + if (!w) + continue; + previousTouchPoint = d->appCurrentTouchPoints.take(touchPoint.id()); + touchPoint.d->startScreenPos = previousTouchPoint.startScreenPos(); + touchPoint.d->lastScreenPos = previousTouchPoint.screenPos(); + touchPoint.d->startPos = previousTouchPoint.startPos(); + touchPoint.d->lastPos = previousTouchPoint.pos(); + touchPoint.d->startNormalizedPos = previousTouchPoint.startNormalizedPos(); + touchPoint.d->lastNormalizedPos = previousTouchPoint.normalizedPos(); + if (touchPoint.pressure() < qreal(0.)) + touchPoint.d->pressure = qreal(0.); + break; + + default: + w = d->windowForTouchPointId.value(touchPoint.id()); + if (!w) + continue; + Q_ASSERT(d->appCurrentTouchPoints.contains(touchPoint.id())); + previousTouchPoint = d->appCurrentTouchPoints.value(touchPoint.id()); + touchPoint.d->startScreenPos = previousTouchPoint.startScreenPos(); + touchPoint.d->lastScreenPos = previousTouchPoint.screenPos(); + touchPoint.d->startPos = previousTouchPoint.startPos(); + touchPoint.d->lastPos = previousTouchPoint.pos(); + touchPoint.d->startNormalizedPos = previousTouchPoint.startNormalizedPos(); + touchPoint.d->lastNormalizedPos = previousTouchPoint.normalizedPos(); + if (touchPoint.pressure() < qreal(0.)) + touchPoint.d->pressure = qreal(1.); + d->appCurrentTouchPoints[touchPoint.id()] = touchPoint; + break; + } + + Q_ASSERT(w.data() != 0); + + // make the *scene* functions return the same as the *screen* functions + touchPoint.d->sceneRect = touchPoint.screenRect(); + touchPoint.d->startScenePos = touchPoint.startScreenPos(); + touchPoint.d->lastScenePos = touchPoint.lastScreenPos(); + + StatesAndTouchPoints &maskAndPoints = windowsNeedingEvents[w.data()]; + maskAndPoints.first |= touchPoint.state(); + if (touchPoint.isPrimary()) + maskAndPoints.first |= Qt::TouchPointPrimary; + maskAndPoints.second.append(touchPoint); + } + + if (windowsNeedingEvents.isEmpty()) + return; + + QHash<QWindow *, StatesAndTouchPoints>::ConstIterator it = windowsNeedingEvents.constBegin(); + const QHash<QWindow *, StatesAndTouchPoints>::ConstIterator end = windowsNeedingEvents.constEnd(); + for (; it != end; ++it) { + QWindow *w = it.key(); + + QEvent::Type eventType; + switch (it.value().first & Qt::TouchPointStateMask) { + case Qt::TouchPointPressed: + eventType = QEvent::TouchBegin; + break; + case Qt::TouchPointReleased: + eventType = QEvent::TouchEnd; + break; + case Qt::TouchPointStationary: + // don't send the event if nothing changed + continue; + default: + eventType = QEvent::TouchUpdate; + break; + } + + QTouchEvent touchEvent(eventType, + e->devType, + QGuiApplication::keyboardModifiers(), + it.value().first, + it.value().second); + + for (int i = 0; i < touchEvent.touchPoints().count(); ++i) { + QTouchEvent::TouchPoint &touchPoint = touchEvent._touchPoints[i]; + + // preserve the sub-pixel resolution + QRectF rect = touchPoint.screenRect(); + const QPointF screenPos = rect.center(); + const QPointF delta = screenPos - screenPos.toPoint(); + + rect.moveCenter(w->mapFromGlobal(screenPos.toPoint()) + delta); + touchPoint.d->rect = rect; + if (touchPoint.state() == Qt::TouchPointPressed) { + touchPoint.d->startPos = w->mapFromGlobal(touchPoint.startScreenPos().toPoint()) + delta; + touchPoint.d->lastPos = w->mapFromGlobal(touchPoint.lastScreenPos().toPoint()) + delta; + } + } + + QGuiApplication::sendSpontaneousEvent(w, &touchEvent); + } } void QGuiApplicationPrivate::reportScreenCount(QWindowSystemInterfacePrivate::ScreenCountEvent *) diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h index 1591ed8990..511d3845d3 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -180,6 +180,9 @@ private: void init(); static QGuiApplicationPrivate *self; + + QMap<int, QWeakPointer<QWindow> > windowForTouchPointId; + QMap<int, QTouchEvent::TouchPoint> appCurrentTouchPoints; }; QT_END_NAMESPACE diff --git a/src/widgets/kernel/qwidgetwindow_qpa.cpp b/src/widgets/kernel/qwidgetwindow_qpa.cpp index ab8bacc1c7..a6bbfe4266 100644 --- a/src/widgets/kernel/qwidgetwindow_qpa.cpp +++ b/src/widgets/kernel/qwidgetwindow_qpa.cpp @@ -83,6 +83,12 @@ bool QWidgetWindow::event(QEvent *event) handleMouseEvent(static_cast<QMouseEvent *>(event)); return true; + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + handleTouchEvent(static_cast<QTouchEvent *>(event)); + return true; + case QEvent::Move: handleMoveEvent(static_cast<QMoveEvent *>(event)); return true; @@ -257,6 +263,11 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) } } +void QWidgetWindow::handleTouchEvent(QTouchEvent *event) +{ + QApplicationPrivate::translateRawTouchEvent(m_widget, event->deviceType(), event->touchPoints()); +} + void QWidgetWindow::handleKeyEvent(QKeyEvent *event) { if (QApplicationPrivate::instance()->modalState() && !qt_try_modal(m_widget, event->type())) diff --git a/src/widgets/kernel/qwidgetwindow_qpa_p.h b/src/widgets/kernel/qwidgetwindow_qpa_p.h index 4253072933..86290c693a 100644 --- a/src/widgets/kernel/qwidgetwindow_qpa_p.h +++ b/src/widgets/kernel/qwidgetwindow_qpa_p.h @@ -71,6 +71,7 @@ protected: void handleEnterLeaveEvent(QEvent *); void handleKeyEvent(QKeyEvent *); void handleMouseEvent(QMouseEvent *); + void handleTouchEvent(QTouchEvent *); void handleMoveEvent(QMoveEvent *); void handleResizeEvent(QResizeEvent *); void handleWheelEvent(QWheelEvent *); |