diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 219f782..7cfba86 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -3657,7 +3657,9 @@ static inline void formatTouchEvent(QDebug d, const QTouchEvent &t) d << " device: " << t.device()->name(); d << " states: "; QtDebugUtils::formatQFlags(d, t.touchPointStates()); - d << ", " << t.touchPoints().size() << " points: " << t.touchPoints() << ')'; + d << ", " << t.touchPoints().size() << " points: " << t.touchPoints(); + d << ", " << t.coalescedPoints().size() << " coalescedPoints: " << t.coalescedPoints(); + d << ", " << t.predictedPoints().size() << " predictedPoints: " << t.predictedPoints() << ')'; } static void formatUnicodeString(QDebug d, const QString &s) @@ -3890,7 +3892,12 @@ QDebug operator<<(QDebug dbg, const QTouchEvent::TouchPoint &tp) dbg.nospace(); dbg << "TouchPoint(" << tp.id() << " ("; QtDebugUtils::formatQRect(dbg, tp.rect()); - dbg << ") "; + dbg << ") screenPos:"; + + QtDebugUtils::formatQPoint(dbg, tp.screenPos()); + dbg << " scenePos:"; + QtDebugUtils::formatQPoint(dbg, tp.scenePos()); + dbg << " "; QtDebugUtils::formatQEnum(dbg, tp.state()); dbg << " press " << tp.pressure() << " vel " << tp.velocity() << " start ("; @@ -4319,13 +4326,17 @@ QTouchEvent::QTouchEvent(QEvent::Type eventType, QTouchDevice *device, Qt::KeyboardModifiers modifiers, Qt::TouchPointStates touchPointStates, - const QList &touchPoints) + const QList &touchPoints, + const QList &coalescedPoints, // pks: apple pencil + const QList &predictedPoints) : QInputEvent(eventType, modifiers), _window(0), _target(0), _device(device), _touchPointStates(touchPointStates), - _touchPoints(touchPoints) + _touchPoints(touchPoints), + _coalescedPoints(coalescedPoints), + _predictedPoints(predictedPoints) { } /*! @@ -4745,6 +4756,10 @@ QVector QTouchEvent::TouchPoint::rawScreenPositions() const return d->rawScreenPositions; } +bool QTouchEvent::TouchPoint::isStylus() const { + return d->isStylus; +} + /*! \internal */ void QTouchEvent::TouchPoint::setId(int id) { @@ -4921,6 +4936,14 @@ void QTouchEvent::TouchPoint::setRawScreenPositions(const QVector &posi d->rawScreenPositions = positions; } +/*! \internal */ +void QTouchEvent::TouchPoint::setIsStylus(bool on) +{ + if (d->ref.load() != 1) + d = d->detach(); + d->isStylus = on; +} + /*! \internal */ diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index 7881df2..8c9a7b7 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -889,6 +889,8 @@ public: InfoFlags flags() const; QVector rawScreenPositions() const; + bool isStylus() const; // pks: apple pencil + // internal void setId(int id); void setUniqueId(qint64 uid); @@ -914,6 +916,8 @@ public: void setFlags(InfoFlags flags); void setRawScreenPositions(const QVector &positions); + void setIsStylus(bool); // pks: apple pencil + private: QTouchEventTouchPointPrivate *d; friend class QGuiApplication; @@ -933,7 +937,10 @@ public: QTouchDevice *device = Q_NULLPTR, Qt::KeyboardModifiers modifiers = Qt::NoModifier, Qt::TouchPointStates touchPointStates = Qt::TouchPointStates(), - const QList &touchPoints = QList()); + const QList &touchPoints = QList(), + const QList &coalescedPoints = QList(), // pks: apple pencil + const QList &predictedPoints = QList() + ); ~QTouchEvent(); inline QWindow *window() const { return _window; } @@ -943,6 +950,8 @@ public: #endif inline Qt::TouchPointStates touchPointStates() const { return _touchPointStates; } inline const QList &touchPoints() const { return _touchPoints; } + inline const QList &coalescedPoints() const { return _coalescedPoints; } // pks: apple pencil + inline const QList &predictedPoints() const { return _predictedPoints; } inline QTouchDevice *device() const { return _device; } // internal @@ -958,6 +967,9 @@ protected: QTouchDevice *_device; Qt::TouchPointStates _touchPointStates; QList _touchPoints; + // pks + QList _coalescedPoints; + QList _predictedPoints; friend class QGuiApplication; friend class QGuiApplicationPrivate; diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h index 898ad16..34be099 100644 --- a/src/gui/kernel/qevent_p.h +++ b/src/gui/kernel/qevent_p.h @@ -66,7 +66,8 @@ public: id(id), state(Qt::TouchPointReleased), pressure(qreal(-1.)), - rotation(qreal(0.)) + rotation(qreal(0.)), + isStylus(false) { } inline QTouchEventTouchPointPrivate *detach() @@ -91,6 +92,7 @@ public: QVector2D velocity; QTouchEvent::TouchPoint::InfoFlags flags; QVector rawScreenPositions; + bool isStylus; // pks: apple pencil }; #ifndef QT_NO_TABLETEVENT diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 7beab72..7a92376 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1955,8 +1955,9 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo QEvent::Type type; QList touchPoints = QWindowSystemInterfacePrivate::fromNativeTouchPoints(points, window, &type); - - QWindowSystemInterfacePrivate::TouchEvent fake(window, e->timestamp, type, m_fakeTouchDevice, touchPoints, e->modifiers); + + QList empty; // pks: apple pencil + QWindowSystemInterfacePrivate::TouchEvent fake(window, e->timestamp, type, m_fakeTouchDevice, touchPoints, empty, empty, e->modifiers); fake.flags |= QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic; processTouchEvent(&fake); } @@ -2417,7 +2418,7 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To { QGuiApplicationPrivate *d = self; modifier_buttons = e->modifiers; - + if (e->touchType == QEvent::TouchCancel) { // The touch sequence has been canceled (e.g. by the compositor). // Send the TouchCancel to all windows with active touches and clean up. @@ -2568,6 +2569,22 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To maskAndPoints.second.append(touchPoint); } + // pks: just do the same as above, I guess + int cP = e->coalescedPoints.count(); + for (int i = 0; i < cP; ++i) { + QTouchEvent::TouchPoint &touchPoint = e->coalescedPoints[i]; + touchPoint.d->sceneRect = touchPoint.screenRect(); + touchPoint.d->startScenePos = touchPoint.startScreenPos(); + touchPoint.d->lastScenePos = touchPoint.lastScreenPos(); + } + cP = e->predictedPoints.count(); + for (int i = 0; i < cP; ++i) { + QTouchEvent::TouchPoint &touchPoint = e->predictedPoints[i]; + touchPoint.d->sceneRect = touchPoint.screenRect(); + touchPoint.d->startScenePos = touchPoint.startScreenPos(); + touchPoint.d->lastScenePos = touchPoint.lastScreenPos(); + } + if (windowsNeedingEvents.isEmpty()) return; @@ -2616,10 +2633,12 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To e->device, e->modifiers, it.value().first, - it.value().second); + it.value().second, + e->coalescedPoints, + e->predictedPoints); touchEvent.setTimestamp(e->timestamp); touchEvent.setWindow(w); - + const int pointCount = touchEvent.touchPoints().count(); for (int i = 0; i < pointCount; ++i) { QTouchEvent::TouchPoint &touchPoint = touchEvent._touchPoints[i]; @@ -2635,8 +2654,49 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To touchPoint.d->startPos = w->mapFromGlobal(touchPoint.startScreenPos().toPoint()) + delta; touchPoint.d->lastPos = w->mapFromGlobal(touchPoint.lastScreenPos().toPoint()) + delta; } + //qDebug() << "QGuiApplication::processTouchEvent touch:" << touchPoint.scenePos(); + } + + // pks: apple pencil + const int cPointCount = touchEvent._coalescedPoints.count(); + for (int i = 0; i < cPointCount; ++i) { + QTouchEvent::TouchPoint &touchPoint = touchEvent._coalescedPoints[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; + } + //qDebug() << "QGuiApplication::processTouchEvent coalesced:" << touchPoint.scenePos(); + } + + // pks: apple pencil + const int pPointCount = touchEvent._predictedPoints.count(); + for (int i = 0; i < pPointCount; ++i) { + QTouchEvent::TouchPoint &touchPoint = touchEvent._predictedPoints[i]; +// touchPoint.isStylus = true; + + // 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; + } } + // qDebug() << "QGuiApplication: coalesced: " << touchEvent.coalescedPoints().count() << ", predicted: " << touchEvent.predictedPoints().count(); + QGuiApplication::sendSpontaneousEvent(w, &touchEvent); if (!e->synthetic() && !touchEvent.isAccepted() && qApp->testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents)) { // exclude devices which generate their own mouse events diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 6673048..1da4385 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -535,12 +535,13 @@ QList // The local pos and rect are not set, they will be calculated // when the event gets processed by QGuiApplication. - p.setNormalizedPos(QHighDpi::fromNativePixels(point->normalPosition, window)); p.setVelocity(QHighDpi::fromNativePixels(point->velocity, window)); p.setFlags(point->flags); p.setRawScreenPositions(QHighDpi::fromNativePixels(point->rawPositions, window)); + p.setIsStylus(point->isStylus); // pks: apple pencil + touchPoints.append(p); ++point; } @@ -553,7 +554,6 @@ QList else if (states == Qt::TouchPointReleased) *type = QEvent::TouchEnd; } - return touchPoints; } @@ -582,11 +582,15 @@ QT_DEFINE_QPA_EVENT_HANDLER(void, handleTouchEvent, QWindow *w, QTouchDevice *de const QList &points, Qt::KeyboardModifiers mods) { unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); - handleTouchEvent(w, time, device, points, mods); + QList empty; // pks: apple pencil + handleTouchEvent(w, time, device, points, empty, empty, mods); } QT_DEFINE_QPA_EVENT_HANDLER(void, handleTouchEvent, QWindow *tlw, ulong timestamp, QTouchDevice *device, - const QList &points, Qt::KeyboardModifiers mods) + const QList &points, + const QList &coalesced, // pks: apple pencil + const QList &predicted, + Qt::KeyboardModifiers mods) { if (!points.size()) // Touch events must have at least one point return; @@ -596,9 +600,13 @@ QT_DEFINE_QPA_EVENT_HANDLER(void, handleTouchEvent, QWindow *tlw, ulong timestam QEvent::Type type; QList touchPoints = QWindowSystemInterfacePrivate::fromNativeTouchPoints(points, tlw, &type); - + + // pks: apple pencil + QList coalescedPoints = QWindowSystemInterfacePrivate::fromNativeTouchPoints(coalesced, tlw); + QList predictedPoints = QWindowSystemInterfacePrivate::fromNativeTouchPoints(predicted, tlw); + QWindowSystemInterfacePrivate::TouchEvent *e = - new QWindowSystemInterfacePrivate::TouchEvent(tlw, timestamp, type, device, touchPoints, mods); + new QWindowSystemInterfacePrivate::TouchEvent(tlw, timestamp, type, device, touchPoints, coalescedPoints, predictedPoints, mods); QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } @@ -614,7 +622,9 @@ QT_DEFINE_QPA_EVENT_HANDLER(void, handleTouchCancelEvent, QWindow *w, ulong time { QWindowSystemInterfacePrivate::TouchEvent *e = new QWindowSystemInterfacePrivate::TouchEvent(w, timestamp, QEvent::TouchCancel, device, - QList(), mods); + QList(), + QList(), // pks: apple pencil + QList(), mods); QWindowSystemInterfacePrivate::handleWindowSystemEvent(e); } @@ -910,7 +920,8 @@ Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QWindowSystemInterface::TouchPo { QDebugStateSaver saver(dbg); dbg.nospace() << "TouchPoint(" << p.id << " @" << p.area << " normalized " << p.normalPosition - << " press " << p.pressure << " vel " << p.velocity << " state " << (int)p.state; + << " press " << p.pressure << " vel " << p.velocity << " state " << (int)p.state + << " isStylus " << p.isStylus; // pks: apple pencil return dbg; } #endif diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h index a28d1c9..4e248c2 100644 --- a/src/gui/kernel/qwindowsysteminterface.h +++ b/src/gui/kernel/qwindowsysteminterface.h @@ -138,6 +138,7 @@ public: QVector2D velocity; // in screen coordinate system, pixels / seconds QTouchEvent::TouchPoint::InfoFlags flags; QVector rawPositions; // in screen coordinates + bool isStylus; // oks: apple pencil }; static void registerTouchDevice(const QTouchDevice *device); @@ -149,7 +150,10 @@ public: const QList &points, Qt::KeyboardModifiers mods = Qt::NoModifier); template static void handleTouchEvent(QWindow *w, ulong timestamp, QTouchDevice *device, - const QList &points, Qt::KeyboardModifiers mods = Qt::NoModifier); + const QList &points, + const QList &coalescedPoints, // pks: apple pencil + const QList &predictedPoints, + Qt::KeyboardModifiers mods = Qt::NoModifier); template static void handleTouchCancelEvent(QWindow *w, QTouchDevice *device, Qt::KeyboardModifiers mods = Qt::NoModifier); template diff --git a/src/gui/kernel/qwindowsysteminterface_p.h b/src/gui/kernel/qwindowsysteminterface_p.h index 7c9b1f2..30f4aad 100644 --- a/src/gui/kernel/qwindowsysteminterface_p.h +++ b/src/gui/kernel/qwindowsysteminterface_p.h @@ -280,10 +280,15 @@ public: class TouchEvent : public InputEvent { public: TouchEvent(QWindow *w, ulong time, QEvent::Type t, QTouchDevice *dev, - const QList &p, Qt::KeyboardModifiers mods) - :InputEvent(w, time, Touch, mods), device(dev), points(p), touchType(t) { } + const QList &p1, + const QList &p2, + const QList &p3, + Qt::KeyboardModifiers mods) + :InputEvent(w, time, Touch, mods), device(dev), points(p1), coalescedPoints(p2), predictedPoints(p3), touchType(t) { } QTouchDevice *device; QList points; + QList coalescedPoints; + QList predictedPoints; QEvent::Type touchType; }; diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm index 2a1444e..b44d62c 100644 --- a/src/plugins/platforms/ios/quiview.mm +++ b/src/plugins/platforms/ios/quiview.mm @@ -298,6 +298,8 @@ touchCapabilities &= ~QTouchDevice::Pressure; } + touchCapabilities |= QTouchDevice::Pressure; // pks: apple pencil + touchDevice->setCapabilities(touchCapabilities); } @@ -348,10 +350,51 @@ } } -- (void)sendTouchEventWithTimestamp:(ulong)timeStamp +- (void)sendTouchEventWithTimestamp:(ulong)timeStamp :(UIEvent*)event { QIOSIntegration *iosIntegration = QIOSIntegration::instance(); - QWindowSystemInterface::handleTouchEvent(m_qioswindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values()); + + // pks: apple pencil + QList coalesced; + QList predicted; + foreach(UITouch *uiTouch, m_activeTouches.keys()) { + NSArray *cTouches = [event coalescedTouchesForTouch:uiTouch]; + for(UITouch *cTouch in cTouches) { + QWindowSystemInterface::TouchPoint touchPoint; + touchPoint.state = m_activeTouches[uiTouch].state; + touchPoint.isStylus = (cTouch.type == UITouchTypeStylus); + + // taken from updateTouchList + QPoint localViewPosition = QPointF::fromCGPoint([cTouch locationInView:self]).toPoint(); + QPoint globalScreenPosition = m_qioswindow->mapToGlobal(localViewPosition); + touchPoint.area = QRectF(globalScreenPosition, QSize(0, 0)); + QSize screenSize = m_qioswindow->screen()->geometry().size(); + touchPoint.normalPosition = QPointF((qreal) globalScreenPosition.x() / (qreal) screenSize.width(), + (qreal) globalScreenPosition.y() / (qreal) screenSize.height()); + touchPoint.pressure = cTouch.force / cTouch.maximumPossibleForce; +// qDebug() << "QUIView:sendTouchEventWithTimestamp: coalesced: " << cTouch; + coalesced << touchPoint; + } + NSArray *pTouches = [event predictedTouchesForTouch:uiTouch]; + for(UITouch *pTouch in pTouches) { + QWindowSystemInterface::TouchPoint touchPoint; + touchPoint.state = m_activeTouches[uiTouch].state; + touchPoint.isStylus = (pTouch.type == UITouchTypeStylus); + + // taken from updateTouchList + QPoint localViewPosition = QPointF::fromCGPoint([pTouch locationInView:self]).toPoint(); + QPoint globalScreenPosition = m_qioswindow->mapToGlobal(localViewPosition); + touchPoint.area = QRectF(globalScreenPosition, QSize(0, 0)); + QSize screenSize = m_qioswindow->screen()->geometry().size(); + touchPoint.normalPosition = QPointF(globalScreenPosition.x() / screenSize.width(), + globalScreenPosition.y() / screenSize.height()); + touchPoint.pressure = pTouch.force / pTouch.maximumPossibleForce; + predicted << touchPoint; + } +// qDebug() << "QUIView:sendTouchEventWithTimestamp: touch: " << uiTouch; + } + + QWindowSystemInterface::handleTouchEvent(m_qioswindow->window(), timeStamp, iosIntegration->touchDevice(), m_activeTouches.values(), coalesced, predicted); } - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event @@ -363,8 +406,10 @@ for (UITouch *touch in touches) { Q_ASSERT(!m_activeTouches.contains(touch)); m_activeTouches[touch].id = m_nextTouchId++; + m_activeTouches[touch].isStylus = (touch.type == UITouchTypeStylus); } + if (m_qioswindow->shouldAutoActivateWindow() && m_activeTouches.size() == 1) { QPlatformWindow *topLevel = m_qioswindow; while (QPlatformWindow *p = topLevel->parent()) @@ -374,19 +419,19 @@ } [self updateTouchList:touches withState:Qt::TouchPointPressed]; - [self sendTouchEventWithTimestamp:ulong(event.timestamp * 1000)]; + [self sendTouchEventWithTimestamp:ulong(event.timestamp * 1000) :event]; } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { [self updateTouchList:touches withState:Qt::TouchPointMoved]; - [self sendTouchEventWithTimestamp:ulong(event.timestamp * 1000)]; + [self sendTouchEventWithTimestamp:ulong(event.timestamp * 1000) :event]; } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { [self updateTouchList:touches withState:Qt::TouchPointReleased]; - [self sendTouchEventWithTimestamp:ulong(event.timestamp * 1000)]; + [self sendTouchEventWithTimestamp:ulong(event.timestamp * 1000) :event]; // Remove ended touch points from the active set: for (UITouch *touch in touches) diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 358838b..6489958 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -4329,6 +4329,8 @@ void QApplicationPrivate::activateImplicitTouchGrab(QWidget *widget, QTouchEvent bool QApplicationPrivate::translateRawTouchEvent(QWidget *window, QTouchDevice *device, const QList &touchPoints, + const QList &coalesced, // pks: apple pencil + const QList &predicted, ulong timestamp) { QApplicationPrivate *d = self; @@ -4429,7 +4431,9 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window, device, QApplication::keyboardModifiers(), it.value().first, - it.value().second); + it.value().second, + coalesced, // pks: apple pencil + predicted); bool containsPress = updateTouchPointsForWidget(widget, &touchEvent); touchEvent.setTimestamp(timestamp); touchEvent.setWindow(window->windowHandle()); diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h index 3bef773..4349dea 100644 --- a/src/widgets/kernel/qapplication_p.h +++ b/src/widgets/kernel/qapplication_p.h @@ -286,6 +286,8 @@ public: static bool translateRawTouchEvent(QWidget *widget, QTouchDevice *device, const QList &touchPoints, + const QList &coalesced, // pks: apple pencil + const QList &predicted, ulong timestamp); static void translateTouchCancel(QTouchDevice *device, ulong timestamp); diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 3e15b69..d30d224 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -636,7 +636,9 @@ void QWidgetWindow::handleTouchEvent(QTouchEvent *event) // events instead, which QWidgetWindow::handleMouseEvent will forward correctly: event->ignore(); } else { - event->setAccepted(QApplicationPrivate::translateRawTouchEvent(m_widget, event->device(), event->touchPoints(), event->timestamp())); + event->setAccepted(QApplicationPrivate::translateRawTouchEvent(m_widget, event->device(), event->touchPoints(), + event->coalescedPoints(), event->predictedPoints(), // pks: apple pencil + event->timestamp())); } }