diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/corelib/global/qnamespace.h | 2 | ||||
-rw-r--r-- | src/corelib/global/qnamespace.qdoc | 9 | ||||
-rw-r--r-- | src/corelib/kernel/qcoreapplication.cpp | 2 | ||||
-rw-r--r-- | src/gui/kernel/qevent.cpp | 26 | ||||
-rw-r--r-- | src/gui/kernel/qevent.h | 4 | ||||
-rw-r--r-- | src/gui/kernel/qguiapplication.cpp | 46 | ||||
-rw-r--r-- | src/gui/kernel/qguiapplication_p.h | 1 | ||||
-rw-r--r-- | src/gui/kernel/qwindow.cpp | 82 | ||||
-rw-r--r-- | src/gui/kernel/qwindowsysteminterface_qpa.cpp | 40 | ||||
-rw-r--r-- | src/gui/kernel/qwindowsysteminterface_qpa_p.h | 5 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qmultitouch_mac.mm | 2 | ||||
-rw-r--r-- | src/plugins/platforms/windows/qwindowsmousehandler.cpp | 2 | ||||
-rw-r--r-- | src/plugins/platforms/xcb/qxcbconnection_maemo.cpp | 2 | ||||
-rw-r--r-- | src/widgets/kernel/qwidget.cpp | 35 |
14 files changed, 143 insertions, 115 deletions
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index d3b048579f..ee4000498f 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -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 diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index 3c2697e1f8..3add1a48c7 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -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 */ diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 7a4618be34..05f26cc87f 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -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; diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index e0ce334321..61ccaa5cfd 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -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 @@ -3593,15 +3588,6 @@ Qt::TouchPointState QTouchEvent::TouchPoint::state() const } /*! - 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. diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index 5d54d39378..a59b178cec 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -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; diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 9f1eaeacfd..f92e66b38e 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -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 diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h index b1269178d0..9c965cd109 100644 --- a/src/gui/kernel/qguiapplication_p.h +++ b/src/gui/kernel/qguiapplication_p.h @@ -205,6 +205,7 @@ private: void init(); static QGuiApplicationPrivate *self; + static QTouchDevice *m_fakeTouchDevice; }; Q_GUI_EXPORT uint qHash(const QGuiApplicationPrivate::ActiveTouchPointsKey &k); diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp index 0d08316945..97c6b0cbc9 100644 --- a/src/gui/kernel/qwindow.cpp +++ b/src/gui/kernel/qwindow.cpp @@ -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 diff --git a/src/gui/kernel/qwindowsysteminterface_qpa.cpp b/src/gui/kernel/qwindowsysteminterface_qpa.cpp index 29d134c51c..4a7ebd1c0c 100644 --- a/src/gui/kernel/qwindowsysteminterface_qpa.cpp +++ b/src/gui/kernel/qwindowsysteminterface_qpa.cpp @@ -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); diff --git a/src/gui/kernel/qwindowsysteminterface_qpa_p.h b/src/gui/kernel/qwindowsysteminterface_qpa_p.h index 886c1d0762..b5614eb38e 100644 --- a/src/gui/kernel/qwindowsysteminterface_qpa_p.h +++ b/src/gui/kernel/qwindowsysteminterface_qpa_p.h @@ -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 diff --git a/src/plugins/platforms/cocoa/qmultitouch_mac.mm b/src/plugins/platforms/cocoa/qmultitouch_mac.mm index cc85c47c58..43767b09b2 100644 --- a/src/plugins/platforms/cocoa/qmultitouch_mac.mm +++ b/src/plugins/platforms/cocoa/qmultitouch_mac.mm @@ -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 diff --git a/src/plugins/platforms/windows/qwindowsmousehandler.cpp b/src/plugins/platforms/windows/qwindowsmousehandler.cpp index 54a16d5013..e491029ea1 100644 --- a/src/plugins/platforms/windows/qwindowsmousehandler.cpp +++ b/src/plugins/platforms/windows/qwindowsmousehandler.cpp @@ -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(); diff --git a/src/plugins/platforms/xcb/qxcbconnection_maemo.cpp b/src/plugins/platforms/xcb/qxcbconnection_maemo.cpp index 1ac8e771fc..12b3d67b9f 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_maemo.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_maemo.cpp @@ -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; } diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index a66ccf8572..531a217b1d 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -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 |