// generateTouchEvent - iterates through existing touches and creates a QTouchEvent. // For the primary finger, it also creates a mouse event if the location has move void QPAHiddTpHandler::generateTouchEvent() { if (m_touches.empty()) return; QList<QTouchEvent::TouchPoint> touchPoints; QList<HiddTouch>::const_iterator it; QWidget* widget = QWidget::mouseGrabber(); if (!widget) { QWidget* window = QApplication::topLevelAt(m_lastTouchDown); if (window) widget = window->childAt(window->mapFromGlobal(m_lastTouchDown)); } if (!widget) { QPoint dummyPt(10, 10); QWidget* window = QApplication::topLevelAt(dummyPt); if (window) widget = window->childAt(window->mapFromGlobal(dummyPt)); } if(!widget) { widget = QApplication::activeWindow(); if(QApplication::focusWidget()) { widget = QApplication::focusWidget(); } } Qt::KeyboardModifiers keyboardModifiers = QApplication::keyboardModifiers(); if (widget && m_sendPenCancel) { //printf("Mouse Up for Pen Cancel: %d, %d\n", m_penCancelPoint.x(), m_penCancelPoint.y()); QMouseEvent ev(QEvent::MouseButtonRelease, m_penCancelPoint, m_penCancelPoint, true, Qt::LeftButton, Qt::NoButton, keyboardModifiers); qt_sendSpontaneousEvent((QObject*) widget, &ev); m_sendPenCancel = false; m_penCancelPoint = QPoint (0,0); } for (it = m_touches.begin(); it != m_touches.end(); ++it) { QTouchEvent::TouchPoint touchPoint; touchPoint.setId(it->id); touchPoint.setPos(QPoint(it->x, it->y)); touchPoint.setScreenPos(touchPoint.pos()); switch (it->state) { case QPAHiddTpHandler::FingerDown: touchPoint.setState(Qt::TouchPointPressed); break; case QPAHiddTpHandler::FingerUp: touchPoint.setState(Qt::TouchPointReleased); break; case QPAHiddTpHandler::FingerMove: touchPoint.setState(Qt::TouchPointMoved); break; default: touchPoint.setState(Qt::TouchPointStationary); break; } if (it->isPrimary) { touchPoint.setState(touchPoint.state() | Qt::TouchPointPrimary); } touchPoints.append(touchPoint); // printf ("%s: adding touch point id %d (hiddId %llu) for pos (%d, %d) primary %d\n", // __func__, it->id, it->hiddId, it->x, it->y, it->isPrimary); if (it->isPrimary) { QPoint mousePos = QPoint(it->x, it->y); if (widget) { if (it->state == QPAHiddTpHandler::FingerDown) { uint32_t currTime = m_touchTimer.elapsed(); int dx = mousePos.x() - m_mousePress.x(); int dy = mousePos.y() - m_mousePress.y(); if (((currTime - m_mousePressTime) < (uint32_t) QApplication::doubleClickInterval()) && ((dx * dx + dy * dy) <= 144)) { //printf("Mouse Double Click: %d, %d\n", mousePos.x(), mousePos.y()); QMouseEvent ev(QEvent::MouseButtonDblClick, mousePos, mousePos, Qt::LeftButton, Qt::LeftButton, keyboardModifiers); qt_sendSpontaneousEvent((QObject*) widget, &ev); m_mousePressTime = 0; } else { //printf("Mouse Down: %d, %d\n", mousePos.x(), mousePos.y()); QMouseEvent ev(QEvent::MouseButtonPress, mousePos, mousePos, Qt::LeftButton, Qt::LeftButton, keyboardModifiers); qt_sendSpontaneousEvent((QObject*) widget, &ev); m_mousePress = mousePos; m_mousePressTime = currTime; } } else if (it->state == QPAHiddTpHandler::FingerMove) { //printf("Mouse Move: %d, %d\n", mousePos.x(), mousePos.y()); QMouseEvent ev(QEvent::MouseMove, mousePos, mousePos, Qt::LeftButton, Qt::LeftButton, keyboardModifiers); qt_sendSpontaneousEvent((QObject*) widget, &ev); } } } } //printf ("sending touch event\n"); qt_translateRawTouchEvent(QApplication::activeWindow(), QTouchEvent::TouchScreen, touchPoints); for (it = m_touches.begin(); it != m_touches.end(); ++it) { if (it->isPrimary) { QPoint mousePos = QPoint(it->x, it->y); if (widget) { if (it->state == QPAHiddTpHandler::FingerUp) { //printf("Mouse Up: %d, %d\n", mousePos.x(), mousePos.y()); QMouseEvent ev(QEvent::MouseButtonRelease, mousePos, mousePos, Qt::LeftButton, Qt::NoButton, keyboardModifiers); qt_sendSpontaneousEvent((QObject*) widget, &ev); } } } } }
bool MixxxApplication::notify(QObject* target, QEvent* event) { switch (event->type()) { case QEvent::TouchBegin: case QEvent::TouchUpdate: case QEvent::TouchEnd: { QTouchEvent* touchEvent = static_cast<QTouchEvent*>(event); QList<QTouchEvent::TouchPoint> touchPoints = touchEvent->touchPoints(); QEvent::Type eventType = QEvent::None; Qt::MouseButtons buttons = Qt::NoButton; QWidget* fakeMouseWidget = NULL; bool baseReturn; //qDebug() << "&" << touchEvent->type() << target; if (touchEvent->deviceType() != QTouchEvent::TouchScreen) { break; } switch (event->type()) { case QEvent::TouchBegin: // try to deliver as touch event baseReturn = QApplication::notify(target, event); if (dynamic_cast<MixxxMainWindow*>(touchEvent->widget())) { // the touchEvent has fallen trough to the MixxxMainWindow, because there // was no touch enabled widget found. // Now we resent this event and all following events for this touch point // as Mouse events. eventType = QEvent::MouseButtonPress; if (touchIsRightButton()) { // touch is right click m_activeTouchButton = Qt::RightButton; buttons = Qt::RightButton; } else { m_activeTouchButton = Qt::LeftButton; buttons = Qt::LeftButton; } m_fakeMouseSourcePointId = touchPoints.first().id(); m_fakeMouseWidget = dynamic_cast<QWidget*>(target); fakeMouseWidget = m_fakeMouseWidget; break; } return baseReturn; case QEvent::TouchUpdate: if (m_fakeMouseWidget) { eventType = QEvent::MouseMove; buttons = m_activeTouchButton; fakeMouseWidget = m_fakeMouseWidget; break; } return QApplication::notify(target, event); case QEvent::TouchEnd: if (m_fakeMouseWidget) { eventType = QEvent::MouseButtonRelease; m_fakeMouseSourcePointId = touchPoints.first().id(); fakeMouseWidget = m_fakeMouseWidget; m_fakeMouseWidget = NULL; break; } return QApplication::notify(target, event); default: return QApplication::notify(target, event); } for (int i = 0; i < touchPoints.count(); ++i) { const QTouchEvent::TouchPoint& touchPoint = touchPoints.at(i); if (touchPoint.id() == m_fakeMouseSourcePointId) { QMouseEvent mouseEvent(eventType, fakeMouseWidget->mapFromGlobal(touchPoint.screenPos().toPoint()), touchPoint.screenPos().toPoint(), m_activeTouchButton, // Button that causes the event buttons, touchEvent->modifiers()); //qDebug() << "#" << mouseEvent.type() << mouseEvent.button() << mouseEvent.buttons() << mouseEvent.pos() << mouseEvent.globalPos(); //if (m_fakeMouseWidget->focusPolicy() & Qt::ClickFocus) { // fakeMouseWidget->setFocus(); //} QApplication::notify(fakeMouseWidget, &mouseEvent); return true; } } //qDebug() << "return false"; return false; break; } case QEvent::MouseButtonRelease: { bool ret = QApplication::notify(target, event); if (m_fakeMouseWidget) { // It may happen the faked mouse event was grabbed by a non touch window. // eg.: if we have started to drag by touch. // In this case X11 generates a MouseButtonRelease instead of a TouchPointReleased Event. // QApplication still tracks the Touch point and prevent touch to other widgets // So we need to fake the Touch release event as well to clean up // QApplicationPrivate::widgetForTouchPointId and QApplicationPrivate::appCurrentTouchPoints; m_fakeMouseWidget = NULL; // Disable MouseButtonRelease fake QList<QTouchEvent::TouchPoint> touchPoints; QTouchEvent::TouchPoint tp; tp.setId(m_fakeMouseSourcePointId); tp.setState(Qt::TouchPointReleased); touchPoints.append(tp); qt_translateRawTouchEvent(NULL, QTouchEvent::TouchScreen, touchPoints); } return ret; } default: break; } // No touch event bool ret = QApplication::notify(target, event); return ret; }