Added application flags to translate between touch and mouse events.

The current way we do it of having the platform or touch plugin send
both mouse and touch events is not ideal. There's no good way to write
an application that works sanely both on a touch-only device and on a
desktop except by restricting yourself to only handling mouse events. If
you try to handle touch events you don't get any events at all on
desktop, and if you try to handle both, you end up getting duplicate
events on touch devices.

Instead, we should get rid of the code in the plugins that automatically
sends mouse events translated from touch events. This change enables
that by making the behaviour fully configurable in QtGui.

Two new application attributes are added to explicitly say whether
unhandled touch events should be sent as synthesized mouse events and
vice versa, and no duplicates are automatically sent as the current
situation. Synthesized mouse events are enabled by default.

We also get rid of the QTouchEvent::TouchPoint::Primary flag, which
was only used to signal that the windowing system automatically
generated mouse events for that touch point. Now we only generate mouse
events from the first touch point in the list.

Change-Id: I8e20f3480407ca8c31b42de0a4d2b319e1346b65
Reviewed-by: Laszlo Agocs <laszlo.p.agocs@nokia.com>
Reviewed-by: Jocelyn Turcotte <jocelyn.turcotte@nokia.com>
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@nokia.com>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@nokia.com>
Reviewed-by: Lars Knoll <lars.knoll@nokia.com>
Reviewed-by: Denis Dzyubenko <denis.dzyubenko@nokia.com>
This commit is contained in:
Samuel Rødal 2012-01-12 08:53:13 +01:00 committed by Qt by Nokia
parent b54cfb3124
commit e50416066c
15 changed files with 304 additions and 124 deletions

View File

@ -481,6 +481,8 @@ public:
AA_MacDontSwapCtrlAndMeta = 7,
AA_Use96Dpi = 8,
AA_X11InitThreads = 10,
AA_SynthesizeTouchForUnhandledMouseEvents = 11,
AA_SynthesizeMouseForUnhandledTouchEvents = 12,
// Add new attributes before this line
AA_AttributeCount

View File

@ -167,6 +167,15 @@
construction in order to make Xlib calls thread-safe. This
attribute must be set before QApplication is constructed.
\value AA_SynthesizeTouchForUnhandledMouseEvents All mouse events
that are not accepted by the application will be translated
to touch events instead.
\value AA_SynthesizeMouseForUnhandledTouchEvents All touch events
that are not accepted by the application will be translated
to left button mouse events instead. This attribute is enabled
by default.
\omitvalue AA_AttributeCount
*/

View File

@ -300,7 +300,7 @@ Q_CORE_EXPORT uint qGlobalPostedEventsCount()
QCoreApplication *QCoreApplication::self = 0;
QAbstractEventDispatcher *QCoreApplicationPrivate::eventDispatcher = 0;
uint QCoreApplicationPrivate::attribs;
uint QCoreApplicationPrivate::attribs = (1 << Qt::AA_SynthesizeMouseForUnhandledTouchEvents);
#ifdef Q_OS_UNIX
Qt::HANDLE qt_application_thread_id = 0;

View File

@ -3323,7 +3323,7 @@ QWindowStateChangeEvent::~QWindowStateChangeEvent()
\section1 Event Delivery and Propagation
By default, QWidget::event() translates the first non-primary touch point in a QTouchEvent into
By default, QGuiApplication translates the first touch point in a QTouchEvent into
a QMouseEvent. This makes it possible to enable touch events on existing widgets that do not
normally handle QTouchEvent. See below for information on some special considerations needed
when doing this.
@ -3361,17 +3361,12 @@ QWindowStateChangeEvent::~QWindowStateChangeEvent()
This makes it possible for sibling widgets to handle touch events independently while making
sure that the sequence of QTouchEvents is always correct.
\section1 Mouse Events and the Primary Touch Point
\section1 Mouse Events and Touch Event synthesizing
QTouchEvent delivery is independent from that of QMouseEvent. On some windowing systems, mouse
events are also sent for the \l{QTouchEvent::TouchPoint::isPrimary()}{primary touch point}.
This means it is possible for your widget to receive both QTouchEvent and QMouseEvent for the
same user interaction point. You can use the QTouchEvent::TouchPoint::isPrimary() function to
identify the primary touch point.
Note that on some systems, it is possible to receive touch events without a primary touch
point. All this means is that there will be no mouse event generated for the touch points in
the QTouchEvent.
QTouchEvent delivery is independent from that of QMouseEvent. The application flags
Qt::AA_SynthesizeTouchForUnhandledMouseEvents and Qt::AA_SynthesizeMouseForUnhandledTouchEvents
can be used to enable or disable automatic synthesizing of touch events to mouse events and
mouse events to touch events.
\section1 Caveats
@ -3592,15 +3587,6 @@ Qt::TouchPointState QTouchEvent::TouchPoint::state() const
return Qt::TouchPointState(int(d->state));
}
/*!
Returns true if this touch point is the primary touch point. The primary touch point is the
point for which the windowing system generates mouse events.
*/
bool QTouchEvent::TouchPoint::isPrimary() const
{
return (d->flags & Primary) != 0;
}
/*!
Returns the position of this touch point, relative to the widget
or QGraphicsItem that received the event.

View File

@ -690,8 +690,7 @@ public:
{
public:
enum InfoFlag {
Primary = 0x0001,
Pen = 0x0002
Pen = 0x0001
};
Q_DECLARE_FLAGS(InfoFlags, InfoFlag)
@ -702,7 +701,6 @@ public:
int id() const;
Qt::TouchPointState state() const;
bool isPrimary() const;
QPointF pos() const;
QPointF startPos() const;

View File

@ -113,6 +113,7 @@ static Qt::LayoutDirection layout_direction = Qt::LeftToRight;
static bool force_reverse = false;
QGuiApplicationPrivate *QGuiApplicationPrivate::self = 0;
QTouchDevice *QGuiApplicationPrivate::m_fakeTouchDevice = 0;
#ifndef QT_NO_CLIPBOARD
QClipboard *QGuiApplicationPrivate::qt_clipboard = 0;
@ -689,7 +690,38 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo
cursors.at(i).data()->pointerEvent(ev);
#endif
QGuiApplication::sendSpontaneousEvent(window, &ev);
return;
if (!e->synthetic && !ev.isAccepted() && qApp->testAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents)) {
if (!m_fakeTouchDevice) {
m_fakeTouchDevice = new QTouchDevice;
QWindowSystemInterface::registerTouchDevice(m_fakeTouchDevice);
}
QList<QWindowSystemInterface::TouchPoint> points;
QWindowSystemInterface::TouchPoint point;
point.id = 1;
point.area = QRectF(globalPoint.x() - 2, globalPoint.y() - 2, 4, 4);
// only translate left button related events to
// avoid strange touch event sequences when several
// buttons are pressed
if (type == QEvent::MouseButtonPress && button == Qt::LeftButton) {
point.state = Qt::TouchPointPressed;
} else if (type == QEvent::MouseButtonRelease && button == Qt::LeftButton) {
point.state = Qt::TouchPointReleased;
} else if (type == QEvent::MouseMove && (buttons & Qt::LeftButton)) {
point.state = Qt::TouchPointMoved;
} else {
return;
}
points << point;
QEvent::Type type;
QList<QTouchEvent::TouchPoint> touchPoints = QWindowSystemInterfacePrivate::convertTouchPoints(points, &type);
QWindowSystemInterfacePrivate::TouchEvent fake(window, e->timestamp, type, m_fakeTouchDevice, touchPoints, e->modifiers);
fake.synthetic = true;
processTouchEvent(&fake);
}
}
}
@ -999,6 +1031,18 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
}
QGuiApplication::sendSpontaneousEvent(w, &touchEvent);
if (!e->synthetic && !touchEvent.isAccepted() && qApp->testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents)) {
// exclude touchpads as those generate their own mouse events
if (touchEvent.device()->type() != QTouchDevice::TouchPad) {
Qt::MouseButtons b = eventType == QEvent::TouchEnd ? Qt::NoButton : Qt::LeftButton;
const QTouchEvent::TouchPoint &touchPoint = touchEvent.touchPoints().first();
QWindowSystemInterfacePrivate::MouseEvent fake(w, e->timestamp, touchPoint.pos(), touchPoint.screenPos(), b, e->modifiers);
fake.synthetic = true;
processMouseEvent(&fake);
}
}
}
// Remove released points from the hash table only after the event is

View File

@ -205,6 +205,7 @@ private:
void init();
static QGuiApplicationPrivate *self;
static QTouchDevice *m_fakeTouchDevice;
};
Q_GUI_EXPORT uint qHash(const QGuiApplicationPrivate::ActiveTouchPointsKey &k);

View File

@ -788,78 +788,83 @@ bool QWindow::close()
return true;
}
void QWindow::exposeEvent(QExposeEvent *)
void QWindow::exposeEvent(QExposeEvent *ev)
{
ev->ignore();
}
void QWindow::moveEvent(QMoveEvent *)
void QWindow::moveEvent(QMoveEvent *ev)
{
ev->ignore();
}
void QWindow::resizeEvent(QResizeEvent *)
void QWindow::resizeEvent(QResizeEvent *ev)
{
ev->ignore();
}
void QWindow::showEvent(QShowEvent *)
void QWindow::showEvent(QShowEvent *ev)
{
ev->ignore();
}
void QWindow::hideEvent(QHideEvent *)
void QWindow::hideEvent(QHideEvent *ev)
{
ev->ignore();
}
bool QWindow::event(QEvent *event)
bool QWindow::event(QEvent *ev)
{
switch (event->type()) {
switch (ev->type()) {
case QEvent::MouseMove:
mouseMoveEvent(static_cast<QMouseEvent*>(event));
mouseMoveEvent(static_cast<QMouseEvent*>(ev));
break;
case QEvent::MouseButtonPress:
mousePressEvent(static_cast<QMouseEvent*>(event));
mousePressEvent(static_cast<QMouseEvent*>(ev));
break;
case QEvent::MouseButtonRelease:
mouseReleaseEvent(static_cast<QMouseEvent*>(event));
mouseReleaseEvent(static_cast<QMouseEvent*>(ev));
break;
case QEvent::MouseButtonDblClick:
mouseDoubleClickEvent(static_cast<QMouseEvent*>(event));
mouseDoubleClickEvent(static_cast<QMouseEvent*>(ev));
break;
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
touchEvent(static_cast<QTouchEvent *>(event));
touchEvent(static_cast<QTouchEvent *>(ev));
break;
case QEvent::Move:
moveEvent(static_cast<QMoveEvent*>(event));
moveEvent(static_cast<QMoveEvent*>(ev));
break;
case QEvent::Resize:
resizeEvent(static_cast<QResizeEvent*>(event));
resizeEvent(static_cast<QResizeEvent*>(ev));
break;
case QEvent::KeyPress:
keyPressEvent(static_cast<QKeyEvent *>(event));
keyPressEvent(static_cast<QKeyEvent *>(ev));
break;
case QEvent::KeyRelease:
keyReleaseEvent(static_cast<QKeyEvent *>(event));
keyReleaseEvent(static_cast<QKeyEvent *>(ev));
break;
case QEvent::FocusIn:
focusInEvent(static_cast<QFocusEvent *>(event));
focusInEvent(static_cast<QFocusEvent *>(ev));
break;
case QEvent::FocusOut:
focusOutEvent(static_cast<QFocusEvent *>(event));
focusOutEvent(static_cast<QFocusEvent *>(ev));
break;
#ifndef QT_NO_WHEELEVENT
case QEvent::Wheel:
wheelEvent(static_cast<QWheelEvent*>(event));
wheelEvent(static_cast<QWheelEvent*>(ev));
break;
#endif
@ -872,66 +877,75 @@ bool QWindow::event(QEvent *event)
break; }
case QEvent::Expose:
exposeEvent(static_cast<QExposeEvent *>(event));
exposeEvent(static_cast<QExposeEvent *>(ev));
break;
case QEvent::Show:
showEvent(static_cast<QShowEvent *>(event));
showEvent(static_cast<QShowEvent *>(ev));
break;
case QEvent::Hide:
hideEvent(static_cast<QHideEvent *>(event));
hideEvent(static_cast<QHideEvent *>(ev));
break;
default:
return QObject::event(event);
return QObject::event(ev);
}
return true;
}
void QWindow::keyPressEvent(QKeyEvent *)
void QWindow::keyPressEvent(QKeyEvent *ev)
{
ev->ignore();
}
void QWindow::keyReleaseEvent(QKeyEvent *)
void QWindow::keyReleaseEvent(QKeyEvent *ev)
{
ev->ignore();
}
void QWindow::focusInEvent(QFocusEvent *)
void QWindow::focusInEvent(QFocusEvent *ev)
{
ev->ignore();
}
void QWindow::focusOutEvent(QFocusEvent *)
void QWindow::focusOutEvent(QFocusEvent *ev)
{
ev->ignore();
}
void QWindow::mousePressEvent(QMouseEvent *)
void QWindow::mousePressEvent(QMouseEvent *ev)
{
ev->ignore();
}
void QWindow::mouseReleaseEvent(QMouseEvent *)
void QWindow::mouseReleaseEvent(QMouseEvent *ev)
{
ev->ignore();
}
void QWindow::mouseDoubleClickEvent(QMouseEvent *)
void QWindow::mouseDoubleClickEvent(QMouseEvent *ev)
{
ev->ignore();
}
void QWindow::mouseMoveEvent(QMouseEvent *)
void QWindow::mouseMoveEvent(QMouseEvent *ev)
{
ev->ignore();
}
#ifndef QT_NO_WHEELEVENT
void QWindow::wheelEvent(QWheelEvent *)
void QWindow::wheelEvent(QWheelEvent *ev)
{
ev->ignore();
}
#endif //QT_NO_WHEELEVENT
void QWindow::touchEvent(QTouchEvent *)
void QWindow::touchEvent(QTouchEvent *ev)
{
ev->ignore();
}
/*!
\fn QPoint QWindow::mapToGlobal(const QPoint &pos) const

View File

@ -226,21 +226,14 @@ void QWindowSystemInterface::handleTouchEvent(QWindow *w, QTouchDevice *device,
handleTouchEvent(w, time, device, points, mods);
}
void QWindowSystemInterface::handleTouchEvent(QWindow *tlw, ulong timestamp, QTouchDevice *device,
const QList<TouchPoint> &points, Qt::KeyboardModifiers mods)
QList<QTouchEvent::TouchPoint> QWindowSystemInterfacePrivate::convertTouchPoints(const QList<QWindowSystemInterface::TouchPoint> &points, QEvent::Type *type)
{
if (!points.size()) // Touch events must have at least one point
return;
if (!QTouchDevicePrivate::isRegistered(device)) // Disallow passing bogus, non-registered devices.
return;
QList<QTouchEvent::TouchPoint> touchPoints;
Qt::TouchPointStates states;
QTouchEvent::TouchPoint p;
QList<struct TouchPoint>::const_iterator point = points.constBegin();
QList<struct TouchPoint>::const_iterator end = points.constEnd();
QList<QWindowSystemInterface::TouchPoint>::const_iterator point = points.constBegin();
QList<QWindowSystemInterface::TouchPoint>::const_iterator end = points.constEnd();
while (point != end) {
p.setId(point->id);
p.setPressure(point->pressure);
@ -264,11 +257,28 @@ void QWindowSystemInterface::handleTouchEvent(QWindow *tlw, ulong timestamp, QTo
}
// Determine the event type based on the combined point states.
QEvent::Type type = QEvent::TouchUpdate;
if (states == Qt::TouchPointPressed)
type = QEvent::TouchBegin;
else if (states == Qt::TouchPointReleased)
type = QEvent::TouchEnd;
if (type) {
*type = QEvent::TouchUpdate;
if (states == Qt::TouchPointPressed)
*type = QEvent::TouchBegin;
else if (states == Qt::TouchPointReleased)
*type = QEvent::TouchEnd;
}
return touchPoints;
}
void QWindowSystemInterface::handleTouchEvent(QWindow *tlw, ulong timestamp, QTouchDevice *device,
const QList<TouchPoint> &points, Qt::KeyboardModifiers mods)
{
if (!points.size()) // Touch events must have at least one point
return;
if (!QTouchDevicePrivate::isRegistered(device)) // Disallow passing bogus, non-registered devices.
return;
QEvent::Type type;
QList<QTouchEvent::TouchPoint> touchPoints = QWindowSystemInterfacePrivate::convertTouchPoints(points, &type);
QWindowSystemInterfacePrivate::TouchEvent *e =
new QWindowSystemInterfacePrivate::TouchEvent(tlw, timestamp, type, device, touchPoints, mods);

View File

@ -72,8 +72,9 @@ public:
class WindowSystemEvent {
public:
explicit WindowSystemEvent(EventType t)
: type(t) { }
: type(t), synthetic(false) { }
EventType type;
bool synthetic;
};
class CloseEvent : public WindowSystemEvent {
@ -261,6 +262,8 @@ public:
static void queueWindowSystemEvent(WindowSystemEvent *ev);
static QTime eventTime;
static QList<QTouchEvent::TouchPoint> convertTouchPoints(const QList<QWindowSystemInterface::TouchPoint> &points, QEvent::Type *type);
};
QT_END_HEADER

View File

@ -73,8 +73,6 @@ QCocoaTouch::~QCocoaTouch()
void QCocoaTouch::updateTouchData(NSTouch *nstouch, NSTouchPhase phase)
{
_touchPoint.state = toTouchPointState(phase);
if (_touchCount == 1)
_touchPoint.flags |= QTouchEvent::TouchPoint::Primary;
// From the normalized position on the trackpad, calculate
// where on screen the touchpoint should be according to the

View File

@ -240,8 +240,6 @@ bool QWindowsMouseHandler::translateTouchEvent(QWindow *window, HWND,
const TOUCHINPUT &winTouchInput = winTouchInputs[i];
QTouchPoint touchPoint;
touchPoint.pressure = 1.0;
if ((winTouchInput.dwFlags & TOUCHEVENTF_PRIMARY) != 0)
touchPoint.flags |= QTouchEvent::TouchPoint::Primary;
touchPoint.id = m_touchInputIDToTouchPointID.value(winTouchInput.dwID, -1);
if (touchPoint.id == -1) {
touchPoint.id = m_touchInputIDToTouchPointID.size();

View File

@ -222,8 +222,6 @@ void QXcbConnection::handleGenericEvent(xcb_ge_event_t *event)
for (int i = 0; i < m_xinputData->xiMaxContacts; ++i) {
QWindowSystemInterface::TouchPoint tp;
tp.id = i;
if (i == 0)
tp.flags |= QTouchEvent::TouchPoint::Primary;
tp.state = Qt::TouchPointReleased;
touchPoints << tp;
}

View File

@ -8227,40 +8227,7 @@ bool QWidget::event(QEvent *event)
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
{
#ifndef Q_WS_MAC
QTouchEvent *touchEvent = static_cast<QTouchEvent *>(event);
const QTouchEvent::TouchPoint &touchPoint = touchEvent->touchPoints().first();
if (touchPoint.isPrimary() || touchEvent->device()->type() == QTouchDevice::TouchPad)
break;
// fake a mouse event!
QEvent::Type eventType = QEvent::None;
switch (touchEvent->type()) {
case QEvent::TouchBegin:
eventType = QEvent::MouseButtonPress;
break;
case QEvent::TouchUpdate:
eventType = QEvent::MouseMove;
break;
case QEvent::TouchEnd:
eventType = QEvent::MouseButtonRelease;
break;
default:
Q_ASSERT(!true);
break;
}
if (eventType == QEvent::None)
break;
QMouseEvent mouseEvent(eventType,
touchPoint.pos(),
touchPoint.scenePos(),
touchPoint.screenPos(),
Qt::LeftButton,
Qt::LeftButton,
touchEvent->modifiers());
(void) QApplication::sendEvent(this, &mouseEvent);
#endif // Q_WS_MAC
event->ignore();
break;
}
#ifndef QT_NO_GESTURES

View File

@ -54,6 +54,18 @@ private slots:
void positioning();
void isActive();
void testInputEvents();
void touchToMouseTranslation();
void mouseToTouchTranslation();
void mouseToTouchLoop();
void initTestCase()
{
touchDevice = new QTouchDevice;
touchDevice->setType(QTouchDevice::TouchScreen);
QWindowSystemInterface::registerTouchDevice(touchDevice);
}
private:
QTouchDevice *touchDevice;
};
@ -234,12 +246,22 @@ public:
keyReleaseCode = event->key();
}
void mousePressEvent(QMouseEvent *event) {
mousePressButton = event->button();
if (ignoreMouse)
event->ignore();
else
mousePressButton = event->button();
}
void mouseReleaseEvent(QMouseEvent *event) {
mouseReleaseButton = event->button();
if (ignoreMouse)
event->ignore();
else
mouseReleaseButton = event->button();
}
void touchEvent(QTouchEvent *event) {
if (ignoreTouch) {
event->ignore();
return;
}
QList<QTouchEvent::TouchPoint> points = event->touchPoints();
for (int i = 0; i < points.count(); ++i) {
switch (points.at(i).state()) {
@ -249,6 +271,8 @@ public:
case Qt::TouchPointReleased:
++touchReleasedCount;
break;
default:
break;
}
}
}
@ -257,11 +281,14 @@ public:
keyPressCode = keyReleaseCode = 0;
mousePressButton = mouseReleaseButton = 0;
touchPressedCount = touchReleasedCount = 0;
ignoreMouse = ignoreTouch = 0;
}
int keyPressCode, keyReleaseCode;
int mousePressButton, mouseReleaseButton;
int touchPressedCount, touchReleasedCount;
bool ignoreMouse, ignoreTouch;
};
void tst_QWindow::testInputEvents()
@ -284,9 +311,32 @@ void tst_QWindow::testInputEvents()
QCOMPARE(window.mousePressButton, int(Qt::LeftButton));
QCOMPARE(window.mouseReleaseButton, int(Qt::LeftButton));
QTouchDevice *device = new QTouchDevice;
device->setType(QTouchDevice::TouchScreen);
QWindowSystemInterface::registerTouchDevice(device);
QList<QWindowSystemInterface::TouchPoint> points;
QWindowSystemInterface::TouchPoint tp1, tp2;
tp1.id = 1;
tp1.state = Qt::TouchPointPressed;
tp1.area = QRect(10, 10, 4, 4);
tp2.id = 2;
tp2.state = Qt::TouchPointPressed;
tp2.area = QRect(20, 20, 4, 4);
points << tp1 << tp2;
QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points);
points[0].state = Qt::TouchPointReleased;
points[1].state = Qt::TouchPointReleased;
QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points);
QCoreApplication::processEvents();
QTRY_COMPARE(window.touchPressedCount, 2);
QTRY_COMPARE(window.touchReleasedCount, 2);
}
void tst_QWindow::touchToMouseTranslation()
{
InputTestWindow window;
window.ignoreTouch = true;
window.setGeometry(80, 80, 40, 40);
window.show();
QTest::qWaitForWindowShown(&window);
QList<QWindowSystemInterface::TouchPoint> points;
QWindowSystemInterface::TouchPoint tp1, tp2;
tp1.id = 1;
@ -294,13 +344,115 @@ void tst_QWindow::testInputEvents()
tp2.id = 2;
tp2.state = Qt::TouchPointPressed;
points << tp1 << tp2;
QWindowSystemInterface::handleTouchEvent(&window, device, points);
QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points);
points[0].state = Qt::TouchPointReleased;
points[1].state = Qt::TouchPointReleased;
QWindowSystemInterface::handleTouchEvent(&window, device, points);
QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points);
QCoreApplication::processEvents();
QCOMPARE(window.touchPressedCount, 2);
QCOMPARE(window.touchReleasedCount, 2);
QTRY_COMPARE(window.mousePressButton, int(Qt::LeftButton));
QTRY_COMPARE(window.mouseReleaseButton, int(Qt::LeftButton));
window.mousePressButton = 0;
window.mouseReleaseButton = 0;
window.ignoreTouch = false;
points[0].state = Qt::TouchPointPressed;
points[1].state = Qt::TouchPointPressed;
QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points);
points[0].state = Qt::TouchPointReleased;
points[1].state = Qt::TouchPointReleased;
QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points);
QCoreApplication::processEvents();
// no new mouse events should be generated since the input window handles the touch events
QTRY_COMPARE(window.mousePressButton, 0);
QTRY_COMPARE(window.mouseReleaseButton, 0);
qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, false);
window.ignoreTouch = true;
points[0].state = Qt::TouchPointPressed;
points[1].state = Qt::TouchPointPressed;
QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points);
points[0].state = Qt::TouchPointReleased;
points[1].state = Qt::TouchPointReleased;
QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points);
QCoreApplication::processEvents();
qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, true);
// mouse event synthesizing disabled
QTRY_COMPARE(window.mousePressButton, 0);
QTRY_COMPARE(window.mouseReleaseButton, 0);
}
void tst_QWindow::mouseToTouchTranslation()
{
qApp->setAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents, true);
InputTestWindow window;
window.ignoreMouse = true;
window.setGeometry(80, 80, 40, 40);
window.show();
QTest::qWaitForWindowShown(&window);
QWindowSystemInterface::handleMouseEvent(&window, QPoint(10, 10), window.mapToGlobal(QPoint(10, 10)), Qt::LeftButton);
QWindowSystemInterface::handleMouseEvent(&window, QPoint(10, 10), window.mapToGlobal(QPoint(10, 10)), Qt::NoButton);
QCoreApplication::processEvents();
qApp->setAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents, false);
QTRY_COMPARE(window.touchPressedCount, 1);
QTRY_COMPARE(window.touchReleasedCount, 1);
qApp->setAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents, true);
window.ignoreMouse = false;
QWindowSystemInterface::handleMouseEvent(&window, QPoint(10, 10), window.mapToGlobal(QPoint(10, 10)), Qt::LeftButton);
QWindowSystemInterface::handleMouseEvent(&window, QPoint(10, 10), window.mapToGlobal(QPoint(10, 10)), Qt::NoButton);
QCoreApplication::processEvents();
qApp->setAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents, false);
// no new touch events should be generated since the input window handles the mouse events
QTRY_COMPARE(window.touchPressedCount, 1);
QTRY_COMPARE(window.touchReleasedCount, 1);
window.ignoreMouse = true;
QWindowSystemInterface::handleMouseEvent(&window, QPoint(10, 10), window.mapToGlobal(QPoint(10, 10)), Qt::LeftButton);
QWindowSystemInterface::handleMouseEvent(&window, QPoint(10, 10), window.mapToGlobal(QPoint(10, 10)), Qt::NoButton);
QCoreApplication::processEvents();
// touch event synthesis disabled
QTRY_COMPARE(window.touchPressedCount, 1);
QTRY_COMPARE(window.touchReleasedCount, 1);
}
void tst_QWindow::mouseToTouchLoop()
{
// make sure there's no infinite loop when synthesizing both ways
qApp->setAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents, true);
qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, true);
InputTestWindow window;
window.ignoreMouse = true;
window.ignoreTouch = true;
window.setGeometry(80, 80, 40, 40);
window.show();
QTest::qWaitForWindowShown(&window);
QWindowSystemInterface::handleMouseEvent(&window, QPoint(10, 10), window.mapToGlobal(QPoint(10, 10)), Qt::LeftButton);
QWindowSystemInterface::handleMouseEvent(&window, QPoint(10, 10), window.mapToGlobal(QPoint(10, 10)), Qt::NoButton);
QCoreApplication::processEvents();
qApp->setAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents, false);
qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, false);
}
#include <tst_qwindow.moc>