summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/kernel/qevent.cpp79
-rw-r--r--src/gui/kernel/qevent.h23
-rw-r--r--src/gui/kernel/qevent_p.h2
-rw-r--r--src/gui/kernel/qguiapplication.cpp4
-rw-r--r--src/gui/kernel/qwindowsysteminterface.cpp3
-rw-r--r--src/gui/kernel/qwindowsysteminterface.h5
-rw-r--r--src/plugins/generic/tuiotouch/qtuiohandler.cpp257
-rw-r--r--src/plugins/generic/tuiotouch/qtuiohandler_p.h8
-rw-r--r--src/plugins/generic/tuiotouch/qtuiotoken_p.h144
-rw-r--r--src/plugins/generic/tuiotouch/tuiotouch.pro3
10 files changed, 495 insertions, 33 deletions
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index 2b3b153537..2d3707c049 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -4421,6 +4421,7 @@ QTouchEvent::~QTouchEvent()
The values of this enum describe additional information about a touch point.
\value Pen Indicates that the contact has been made by a designated pointing device (e.g. a pen) instead of a finger.
+ \value Token Indicates that the contact has been made by a fiducial object (e.g. a knob or other token) instead of a finger.
*/
/*!
@@ -4467,6 +4468,22 @@ int QTouchEvent::TouchPoint::id() const
}
/*!
+ \since 5.8
+ Returns the unique ID of this touch point or token, if any.
+
+ It is normally invalid (with a \l {QPointerUniqueId::numeric()} {numeric()} value of -1),
+ because touchscreens cannot uniquely identify fingers. But when the
+ \l {TouchPoint::InfoFlag} {Token} flag is set, it is expected to uniquely
+ identify a specific token (fiducial object).
+
+ \sa flags
+*/
+QPointerUniqueId QTouchEvent::TouchPoint::uniqueId() const
+{
+ return d->uniqueId;
+}
+
+/*!
Returns the current state of this touch point.
*/
Qt::TouchPointState QTouchEvent::TouchPoint::state() const
@@ -4670,6 +4687,19 @@ qreal QTouchEvent::TouchPoint::pressure() const
}
/*!
+ \since 5.8
+ Returns the angular orientation of this touch point. The return value is in degrees,
+ where zero (the default) indicates the finger or token is pointing upwards,
+ a negative angle means it's rotated to the left, and a positive angle means
+ it's rotated to the right. Most touchscreens do not detect rotation, so
+ zero is the most common value.
+*/
+qreal QTouchEvent::TouchPoint::rotation() const
+{
+ return d->rotation;
+}
+
+/*!
Returns a velocity vector for this touch point.
The vector is in the screen's coordinate system, using pixels per seconds for the magnitude.
@@ -4720,6 +4750,14 @@ void QTouchEvent::TouchPoint::setId(int id)
}
/*! \internal */
+void QTouchEvent::TouchPoint::setUniqueId(qint64 uid)
+{
+ if (d->ref.load() != 1)
+ d = d->detach();
+ d->uniqueId = QPointerUniqueId(uid);
+}
+
+/*! \internal */
void QTouchEvent::TouchPoint::setState(Qt::TouchPointStates state)
{
if (d->ref.load() != 1)
@@ -4856,6 +4894,14 @@ void QTouchEvent::TouchPoint::setPressure(qreal pressure)
}
/*! \internal */
+void QTouchEvent::TouchPoint::setRotation(qreal angle)
+{
+ if (d->ref.load() != 1)
+ d = d->detach();
+ d->rotation = angle;
+}
+
+/*! \internal */
void QTouchEvent::TouchPoint::setVelocity(const QVector2D &v)
{
if (d->ref.load() != 1)
@@ -5126,4 +5172,37 @@ Qt::ApplicationState QApplicationStateChangeEvent::applicationState() const
return m_applicationState;
}
+/*!
+ \class QPointerUniqueId
+ \since 5.8
+ \ingroup events
+ \inmodule QtGui
+
+ \brief QPointerUniqueId identifies a unique object, such as a tagged token
+ or stylus, which is used with a pointing device.
+
+ \sa QTouchEvent::TouchPoint
+*/
+
+/*!
+ Constructs a unique pointer ID with a numeric \a id provided by the hardware.
+ The default is -1, which means an invalid pointer ID.
+*/
+QPointerUniqueId::QPointerUniqueId(qint64 id)
+ : m_numericId(id)
+{
+}
+
+/*!
+ \property QPointerUniqueId::numeric
+ \brief the numeric unique ID of the token represented by a touchpoint
+
+ This is the numeric unique ID if the device provides that type of ID;
+ otherwise it is -1.
+*/
+qint64 QPointerUniqueId::numeric()
+{
+ return m_numericId;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index 1c42c61e85..785884681f 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -790,6 +790,22 @@ inline bool operator==(QKeyEvent *e, QKeySequence::StandardKey key){return (e ?
inline bool operator==(QKeySequence::StandardKey key, QKeyEvent *e){return (e ? e->matches(key) : false);}
#endif // QT_NO_SHORTCUT
+class QPointerUniqueIdPrivate;
+class Q_GUI_EXPORT QPointerUniqueId
+{
+ Q_GADGET
+ Q_PROPERTY(qint64 numeric READ numeric CONSTANT)
+public:
+ explicit QPointerUniqueId(qint64 id = -1);
+
+ qint64 numeric();
+
+private:
+ // TODO for TUIO 2, or any other type of complex token ID, a d-pointer can replace
+ // m_numericId without changing the size of this class.
+ qint64 m_numericId;
+};
+
class QTouchEventTouchPointPrivate;
class Q_GUI_EXPORT QTouchEvent : public QInputEvent
{
@@ -798,7 +814,8 @@ public:
{
public:
enum InfoFlag {
- Pen = 0x0001
+ Pen = 0x0001,
+ Token = 0x0002
};
#ifndef Q_MOC_RUN
// otherwise moc gives
@@ -824,6 +841,7 @@ public:
{ qSwap(d, other.d); }
int id() const;
+ QPointerUniqueId uniqueId() const;
Qt::TouchPointState state() const;
@@ -848,12 +866,14 @@ public:
QRectF screenRect() const;
qreal pressure() const;
+ qreal rotation() const;
QVector2D velocity() const;
InfoFlags flags() const;
QVector<QPointF> rawScreenPositions() const;
// internal
void setId(int id);
+ void setUniqueId(qint64 uid);
void setState(Qt::TouchPointStates state);
void setPos(const QPointF &pos);
void setScenePos(const QPointF &scenePos);
@@ -871,6 +891,7 @@ public:
void setSceneRect(const QRectF &sceneRect);
void setScreenRect(const QRectF &screenRect);
void setPressure(qreal pressure);
+ void setRotation(qreal angle);
void setVelocity(const QVector2D &v);
void setFlags(InfoFlags flags);
void setRawScreenPositions(const QVector<QPointF> &positions);
diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h
index 726aa05d36..2d6a6560da 100644
--- a/src/gui/kernel/qevent_p.h
+++ b/src/gui/kernel/qevent_p.h
@@ -79,12 +79,14 @@ public:
QAtomicInt ref;
int id;
+ QPointerUniqueId uniqueId;
Qt::TouchPointStates state;
QRectF rect, sceneRect, screenRect;
QPointF normalizedPos,
startPos, startScenePos, startScreenPos, startNormalizedPos,
lastPos, lastScenePos, lastScreenPos, lastNormalizedPos;
qreal pressure;
+ qreal rotation;
QVector2D velocity;
QTouchEvent::TouchPoint::InfoFlags flags;
QVector<QPointF> rawScreenPositions;
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 3855c9dab9..c97d3bb61a 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -2518,7 +2518,9 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
// Stationary points might not be delivered down to the receiving item
// and get their position transformed, keep the old values instead.
- if (touchPoint.state() != Qt::TouchPointStationary)
+ if (touchPoint.state() == Qt::TouchPointStationary)
+ touchInfo.touchPoint.setVelocity(touchPoint.velocity());
+ else
touchInfo.touchPoint = touchPoint;
break;
}
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
index 5b91f1bc7e..abcd6c113b 100644
--- a/src/gui/kernel/qwindowsysteminterface.cpp
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
@@ -468,7 +468,10 @@ QList<QTouchEvent::TouchPoint>
QList<QWindowSystemInterface::TouchPoint>::const_iterator end = points.constEnd();
while (point != end) {
p.setId(point->id);
+ if (point->uniqueId >= 0)
+ p.setUniqueId(point->uniqueId);
p.setPressure(point->pressure);
+ p.setRotation(point->rotation);
states |= point->state;
p.setState(point->state);
diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h
index eff3986788..cde70a1102 100644
--- a/src/gui/kernel/qwindowsysteminterface.h
+++ b/src/gui/kernel/qwindowsysteminterface.h
@@ -117,11 +117,14 @@ public:
static void handleWheelEvent(QWindow *w, ulong timestamp, const QPointF & local, const QPointF & global, int d, Qt::Orientation o, Qt::KeyboardModifiers mods = Qt::NoModifier);
struct TouchPoint {
- TouchPoint() : id(0), pressure(0), state(Qt::TouchPointStationary), flags(0) { }
+ TouchPoint() : id(0), uniqueId(-1), pressure(0), rotation(0), state(Qt::TouchPointStationary), flags(0) { }
int id; // for application use
+ qint64 uniqueId; // for TUIO: object/token ID; otherwise empty
+ // TODO for TUIO 2.0: add registerPointerUniqueID(QPointerUniqueId)
QPointF normalPosition; // touch device coordinates, (0 to 1, 0 to 1)
QRectF area; // the touched area, centered at position in screen coordinates
qreal pressure; // 0 to 1
+ qreal rotation; // 0 means pointing straight up; 0 if unknown (like QTabletEvent::rotation)
Qt::TouchPointState state; //Qt::TouchPoint{Pressed|Moved|Stationary|Released}
QVector2D velocity; // in screen coordinate system, pixels / seconds
QTouchEvent::TouchPoint::InfoFlags flags;
diff --git a/src/plugins/generic/tuiotouch/qtuiohandler.cpp b/src/plugins/generic/tuiotouch/qtuiohandler.cpp
index 6026e06b55..86decd312b 100644
--- a/src/plugins/generic/tuiotouch/qtuiohandler.cpp
+++ b/src/plugins/generic/tuiotouch/qtuiohandler.cpp
@@ -43,10 +43,12 @@
#include <QWindow>
#include <QGuiApplication>
#include <QTouchDevice>
+#include <qmath.h>
#include <qpa/qwindowsysteminterface.h>
#include "qtuiocursor_p.h"
+#include "qtuiotoken_p.h"
#include "qtuiohandler_p.h"
#include "qoscbundle_p.h"
@@ -55,6 +57,12 @@ QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcTuioSource, "qt.qpa.tuio.source")
Q_LOGGING_CATEGORY(lcTuioSet, "qt.qpa.tuio.set")
+// With TUIO the first application takes exclusive ownership of the "device"
+// we cannot attach more than one application to the same port anyway.
+// Forcing delivery makes it easy to use simulators in the same machine
+// and forget about headaches about unfocused TUIO windows.
+static bool forceDelivery = qEnvironmentVariableIsSet("QT_TUIOTOUCH_DELIVER_WITHOUT_FOCUS");
+
QTuioHandler::QTuioHandler(const QString &specification)
: m_device(new QTouchDevice) // not leaked, QTouchDevice cleans up registered devices itself
{
@@ -157,29 +165,49 @@ void QTuioHandler::processPackets()
messages.push_back(msg);
}
- foreach (const QOscMessage &message, messages) {
- if (message.addressPattern() != "/tuio/2Dcur") {
- qWarning() << "Ignoring unknown address pattern " << message.addressPattern();
- continue;
- }
-
- QList<QVariant> arguments = message.arguments();
- if (arguments.count() == 0) {
- qWarning("Ignoring TUIO message with no arguments");
- continue;
- }
-
- QByteArray messageType = arguments.at(0).toByteArray();
- if (messageType == "source") {
- process2DCurSource(message);
- } else if (messageType == "alive") {
- process2DCurAlive(message);
- } else if (messageType == "set") {
- process2DCurSet(message);
- } else if (messageType == "fseq") {
- process2DCurFseq(message);
+ for (const QOscMessage &message : messages) {
+ if (message.addressPattern() == "/tuio/2Dcur") {
+ QList<QVariant> arguments = message.arguments();
+ if (arguments.count() == 0) {
+ qWarning("Ignoring TUIO message with no arguments");
+ continue;
+ }
+
+ QByteArray messageType = arguments.at(0).toByteArray();
+ if (messageType == "source") {
+ process2DCurSource(message);
+ } else if (messageType == "alive") {
+ process2DCurAlive(message);
+ } else if (messageType == "set") {
+ process2DCurSet(message);
+ } else if (messageType == "fseq") {
+ process2DCurFseq(message);
+ } else {
+ qWarning() << "Ignoring unknown TUIO message type: " << messageType;
+ continue;
+ }
+ } else if (message.addressPattern() == "/tuio/2Dobj") {
+ QList<QVariant> arguments = message.arguments();
+ if (arguments.count() == 0) {
+ qWarning("Ignoring TUIO message with no arguments");
+ continue;
+ }
+
+ QByteArray messageType = arguments.at(0).toByteArray();
+ if (messageType == "source") {
+ process2DObjSource(message);
+ } else if (messageType == "alive") {
+ process2DObjAlive(message);
+ } else if (messageType == "set") {
+ process2DObjSet(message);
+ } else if (messageType == "fseq") {
+ process2DObjFseq(message);
+ } else {
+ qWarning() << "Ignoring unknown TUIO message type: " << messageType;
+ continue;
+ }
} else {
- qWarning() << "Ignoring unknown TUIO message type: " << messageType;
+ qWarning() << "Ignoring unknown address pattern " << message.addressPattern();
continue;
}
}
@@ -328,11 +356,6 @@ void QTuioHandler::process2DCurFseq(const QOscMessage &message)
Q_UNUSED(message); // TODO: do we need to do anything with the frame id?
QWindow *win = QGuiApplication::focusWindow();
- // With TUIO the first application takes exclusive ownership of the "device"
- // we cannot attach more than one application to the same port anyway.
- // Forcing delivery makes it easy to use simulators in the same machine
- // and forget about headaches about unfocused TUIO windows.
- static bool forceDelivery = qEnvironmentVariableIsSet("QT_TUIOTOUCH_DELIVER_WITHOUT_FOCUS");
if (!win && QGuiApplication::topLevelWindows().length() > 0 && forceDelivery)
win = QGuiApplication::topLevelWindows().at(0);
@@ -342,12 +365,12 @@ void QTuioHandler::process2DCurFseq(const QOscMessage &message)
QList<QWindowSystemInterface::TouchPoint> tpl;
tpl.reserve(m_activeCursors.size() + m_deadCursors.size());
- foreach (const QTuioCursor &tc, m_activeCursors) {
+ for (const QTuioCursor &tc : m_activeCursors) {
QWindowSystemInterface::TouchPoint tp = cursorToTouchPoint(tc, win);
tpl.append(tp);
}
- foreach (const QTuioCursor &tc, m_deadCursors) {
+ for (const QTuioCursor &tc : m_deadCursors) {
QWindowSystemInterface::TouchPoint tp = cursorToTouchPoint(tc, win);
tp.state = Qt::TouchPointReleased;
tpl.append(tp);
@@ -357,5 +380,181 @@ void QTuioHandler::process2DCurFseq(const QOscMessage &message)
m_deadCursors.clear();
}
+void QTuioHandler::process2DObjSource(const QOscMessage &message)
+{
+ QList<QVariant> arguments = message.arguments();
+ if (arguments.count() != 2) {
+ qWarning() << "Ignoring malformed TUIO source message: " << arguments.count();
+ return;
+ }
+
+ if (QMetaType::Type(arguments.at(1).type()) != QMetaType::QByteArray) {
+ qWarning("Ignoring malformed TUIO source message (bad argument type)");
+ return;
+ }
+
+ qCDebug(lcTuioSource) << "Got TUIO source message from: " << arguments.at(1).toByteArray();
+}
+
+void QTuioHandler::process2DObjAlive(const QOscMessage &message)
+{
+ QList<QVariant> arguments = message.arguments();
+
+ // delta the notified tokens that are active, against the ones we already
+ // know of.
+ //
+ // TBD: right now we're assuming one 2DObj alive message corresponds to a
+ // new data source from the input. is this correct, or do we need to store
+ // changes and only process the deltas on fseq?
+ QMap<int, QTuioToken> oldActiveTokens = m_activeTokens;
+ QMap<int, QTuioToken> newActiveTokens;
+
+ for (int i = 1; i < arguments.count(); ++i) {
+ if (QMetaType::Type(arguments.at(i).type()) != QMetaType::Int) {
+ qWarning() << "Ignoring malformed TUIO alive message (bad argument on position" << i << arguments << ')';
+ return;
+ }
+
+ int sessionId = arguments.at(i).toInt();
+ if (!oldActiveTokens.contains(sessionId)) {
+ // newly active
+ QTuioToken token(sessionId);
+ token.setState(Qt::TouchPointPressed);
+ newActiveTokens.insert(sessionId, token);
+ } else {
+ // we already know about it, remove it so it isn't marked as released
+ QTuioToken token = oldActiveTokens.value(sessionId);
+ token.setState(Qt::TouchPointStationary); // position change in SET will update if needed
+ newActiveTokens.insert(sessionId, token);
+ oldActiveTokens.remove(sessionId);
+ }
+ }
+
+ // anything left is dead now
+ QMap<int, QTuioToken>::ConstIterator it = oldActiveTokens.constBegin();
+
+ // deadTokens should be cleared from the last FSEQ now
+ m_deadTokens.reserve(oldActiveTokens.size());
+
+ // TODO: there could be an issue of resource exhaustion here if FSEQ isn't
+ // sent in a timely fashion. we should probably track message counts and
+ // force-flush if we get too many built up.
+ while (it != oldActiveTokens.constEnd()) {
+ m_deadTokens.append(it.value());
+ ++it;
+ }
+
+ m_activeTokens = newActiveTokens;
+}
+
+void QTuioHandler::process2DObjSet(const QOscMessage &message)
+{
+ QList<QVariant> arguments = message.arguments();
+ if (arguments.count() < 7) {
+ qWarning() << "Ignoring malformed TUIO set message with too few arguments: " << arguments.count();
+ return;
+ }
+
+ if (QMetaType::Type(arguments.at(1).type()) != QMetaType::Int ||
+ QMetaType::Type(arguments.at(2).type()) != QMetaType::Int ||
+ QMetaType::Type(arguments.at(3).type()) != QMetaType::Float ||
+ QMetaType::Type(arguments.at(4).type()) != QMetaType::Float ||
+ QMetaType::Type(arguments.at(5).type()) != QMetaType::Float ||
+ QMetaType::Type(arguments.at(6).type()) != QMetaType::Float ||
+ QMetaType::Type(arguments.at(7).type()) != QMetaType::Float ||
+ QMetaType::Type(arguments.at(8).type()) != QMetaType::Float ||
+ QMetaType::Type(arguments.at(9).type()) != QMetaType::Float ||
+ QMetaType::Type(arguments.at(10).type()) != QMetaType::Float) {
+ qWarning() << "Ignoring malformed TUIO set message with bad types: " << arguments;
+ return;
+ }
+
+ int id = arguments.at(1).toInt();
+ int classId = arguments.at(2).toInt();
+ float x = arguments.at(3).toFloat();
+ float y = arguments.at(4).toFloat();
+ float angle = arguments.at(5).toFloat();
+ float vx = arguments.at(6).toFloat();
+ float vy = arguments.at(7).toFloat();
+ float angularVelocity = arguments.at(8).toFloat();
+ float acceleration = arguments.at(9).toFloat();
+ float angularAcceleration = arguments.at(10).toFloat();
+
+ QMap<int, QTuioToken>::Iterator it = m_activeTokens.find(id);
+ if (it == m_activeTokens.end()) {
+ qWarning() << "Ignoring malformed TUIO set for nonexistent token " << classId;
+ return;
+ }
+
+ qCDebug(lcTuioSet) << "Processing SET for token " << classId << id << " @ " << x << y << "∡" << angle <<
+ "vel" << vx << vy << angularVelocity << "acc" << acceleration << angularAcceleration;
+ QTuioToken &tok = *it;
+ tok.setClassId(classId);
+ tok.setX(x);
+ tok.setY(y);
+ tok.setVX(vx);
+ tok.setVY(vy);
+ tok.setAcceleration(acceleration);
+ tok.setAngle(angle);
+ tok.setAngularVelocity(angularAcceleration);
+ tok.setAngularAcceleration(angularAcceleration);
+}
+
+QWindowSystemInterface::TouchPoint QTuioHandler::tokenToTouchPoint(const QTuioToken &tc, QWindow *win)
+{
+ QWindowSystemInterface::TouchPoint tp;
+ tp.id = tc.id();
+ tp.uniqueId = tc.classId(); // TODO TUIO 2.0: populate a QVariant, and register the mapping from int to arbitrary UID data
+ tp.flags = QTouchEvent::TouchPoint::Token;
+ tp.pressure = 1.0f;
+
+ tp.normalPosition = QPointF(tc.x(), tc.y());
+
+ if (!m_transform.isIdentity())
+ tp.normalPosition = m_transform.map(tp.normalPosition);
+
+ tp.state = tc.state();
+ tp.area = QRectF(0, 0, 1, 1);
+
+ // We map the token position to the size of the window.
+ QPointF relPos = QPointF(win->size().width() * tp.normalPosition.x(), win->size().height() * tp.normalPosition.y());
+ QPointF delta = relPos - relPos.toPoint();
+ tp.area.moveCenter(win->mapToGlobal(relPos.toPoint()) + delta);
+ tp.velocity = QVector2D(win->size().width() * tc.vx(), win->size().height() * tc.vy());
+ tp.rotation = tc.angle() * 180.0 / M_PI; // convert radians to degrees
+ return tp;
+}
+
+
+void QTuioHandler::process2DObjFseq(const QOscMessage &message)
+{
+ Q_UNUSED(message); // TODO: do we need to do anything with the frame id?
+
+ QWindow *win = QGuiApplication::focusWindow();
+ if (!win && QGuiApplication::topLevelWindows().length() > 0 && forceDelivery)
+ win = QGuiApplication::topLevelWindows().at(0);
+
+ if (!win)
+ return;
+
+ QList<QWindowSystemInterface::TouchPoint> tpl;
+ tpl.reserve(m_activeTokens.size() + m_deadTokens.size());
+
+ for (const QTuioToken & t : m_activeTokens) {
+ QWindowSystemInterface::TouchPoint tp = tokenToTouchPoint(t, win);
+ tpl.append(tp);
+ }
+
+ for (const QTuioToken & t : m_deadTokens) {
+ QWindowSystemInterface::TouchPoint tp = tokenToTouchPoint(t, win);
+ tp.state = Qt::TouchPointReleased;
+ tp.velocity = QVector2D();
+ tpl.append(tp);
+ }
+ QWindowSystemInterface::handleTouchEvent(win, m_device, tpl);
+
+ m_deadTokens.clear();
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/generic/tuiotouch/qtuiohandler_p.h b/src/plugins/generic/tuiotouch/qtuiohandler_p.h
index 3034872aae..2e444f2a0d 100644
--- a/src/plugins/generic/tuiotouch/qtuiohandler_p.h
+++ b/src/plugins/generic/tuiotouch/qtuiohandler_p.h
@@ -54,6 +54,7 @@ QT_BEGIN_NAMESPACE
class QTouchDevice;
class QOscMessage;
class QTuioCursor;
+class QTuioToken;
class QTuioHandler : public QObject
{
@@ -69,14 +70,21 @@ private slots:
void process2DCurAlive(const QOscMessage &message);
void process2DCurSet(const QOscMessage &message);
void process2DCurFseq(const QOscMessage &message);
+ void process2DObjSource(const QOscMessage &message);
+ void process2DObjAlive(const QOscMessage &message);
+ void process2DObjSet(const QOscMessage &message);
+ void process2DObjFseq(const QOscMessage &message);
private:
QWindowSystemInterface::TouchPoint cursorToTouchPoint(const QTuioCursor &tc, QWindow *win);
+ QWindowSystemInterface::TouchPoint tokenToTouchPoint(const QTuioToken &tc, QWindow *win);
QTouchDevice *m_device;
QUdpSocket m_socket;
QMap<int, QTuioCursor> m_activeCursors;
QVector<QTuioCursor> m_deadCursors;
+ QMap<int, QTuioToken> m_activeTokens;
+ QVector<QTuioToken> m_deadTokens;
QTransform m_transform;
};
diff --git a/src/plugins/generic/tuiotouch/qtuiotoken_p.h b/src/plugins/generic/tuiotouch/qtuiotoken_p.h
new file mode 100644
index 0000000000..5084aeed11
--- /dev/null
+++ b/src/plugins/generic/tuiotouch/qtuiotoken_p.h
@@ -0,0 +1,144 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTUIOOBJECT_P_H
+#define QTUIOOBJECT_P_H
+
+#include <Qt>
+#include <qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+
+ A fiducial object, or token, represented by 2Dobj in TUIO 1.x and tok in TUIO 2:
+ a physical object whose position and rotation can be uniquely tracked
+ on the touchscreen surface.
+*/
+class QTuioToken
+{
+public:
+ QTuioToken(int id = -1)
+ : m_id(id)
+ , m_classId(-1)
+ , m_x(0)
+ , m_y(0)
+ , m_vx(0)
+ , m_vy(0)
+ , m_acceleration(0)
+ , m_angle(0)
+ , m_angularVelocity(0)
+ , m_angularAcceleration(0)
+ , m_state(Qt::TouchPointPressed)
+ {
+ }
+
+ int id() const { return m_id; }
+
+ int classId() const { return m_classId; }
+ void setClassId(int classId) { m_classId = classId; }
+
+ void setX(float x)
+ {
+ if (state() == Qt::TouchPointStationary &&
+ !qFuzzyCompare(m_x + 2.0, x + 2.0)) { // +2 because 1 is a valid value, and qFuzzyCompare can't cope with 0.0
+ setState(Qt::TouchPointMoved);
+ }
+ m_x = x;
+ }
+ float x() const { return m_x; }
+
+ void setY(float y)
+ {
+ if (state() == Qt::TouchPointStationary &&
+ !qFuzzyCompare(m_y + 2.0, y + 2.0)) { // +2 because 1 is a valid value, and qFuzzyCompare can't cope with 0.0
+ setState(Qt::TouchPointMoved);
+ }
+ m_y = y;
+ }
+ float y() const { return m_y; }
+
+ void setVX(float vx) { m_vx = vx; }
+ float vx() const { return m_vx; }
+
+ void setVY(float vy) { m_vy = vy; }
+ float vy() const { return m_vy; }
+
+ void setAcceleration(float acceleration) { m_acceleration = acceleration; }
+ float acceleration() const { return m_acceleration; }
+
+ float angle() const { return m_angle; }
+ void setAngle(float angle)
+ {
+ if (angle > M_PI)
+ angle = angle - M_PI * 2.0; // zero is pointing upwards, and is the default; but we want to have negative angles when rotating left
+ if (state() == Qt::TouchPointStationary &&
+ !qFuzzyCompare(m_angle + 2.0, angle + 2.0)) { // +2 because 1 is a valid value, and qFuzzyCompare can't cope with 0.0
+ setState(Qt::TouchPointMoved);
+ }
+ m_angle = angle;
+ }
+
+ float angularVelocity() const { return m_angularVelocity; }
+ void setAngularVelocity(float angularVelocity) { m_angularVelocity = angularVelocity; }
+
+ float angularAcceleration() const { return m_angularAcceleration; }
+ void setAngularAcceleration(float angularAcceleration) { m_angularAcceleration = angularAcceleration; }
+
+ void setState(const Qt::TouchPointState &state) { m_state = state; }
+ Qt::TouchPointState state() const { return m_state; }
+
+private:
+ int m_id; // sessionID, temporary object ID
+ int m_classId; // classID (e.g. marker ID)
+ float m_x;
+ float m_y;
+ float m_vx;
+ float m_vy;
+ float m_acceleration;
+ float m_angle;
+ float m_angularVelocity;
+ float m_angularAcceleration;
+ Qt::TouchPointState m_state;
+};
+
+QT_END_NAMESPACE
+
+#endif // QTUIOOBJECT_P_H
diff --git a/src/plugins/generic/tuiotouch/tuiotouch.pro b/src/plugins/generic/tuiotouch/tuiotouch.pro
index ae2ccde058..ad6a1c6876 100644
--- a/src/plugins/generic/tuiotouch/tuiotouch.pro
+++ b/src/plugins/generic/tuiotouch/tuiotouch.pro
@@ -15,7 +15,8 @@ HEADERS += \
qoscbundle_p.h \
qoscmessage_p.h \
qtuiohandler_p.h \
- qtuiocursor_p.h
+ qtuiocursor_p.h \
+ qtuiotoken_p.h
OTHER_FILES += \
tuiotouch.json