QTouchEvent::TouchPoint makeTouchPointFromMouseEvent(QMouseEvent *event, Qt::TouchPointState state) { QTouchEvent::TouchPoint newPoint; #if defined ( QT_4 ) newPoint.setPos(event->posF()); newPoint.setScenePos(event->globalPos()); newPoint.setScreenPos(event->globalPos()); #elif defined ( QT_5 ) newPoint.setPos(event->localPos()); newPoint.setScenePos(event->windowPos()); newPoint.setScreenPos(event->screenPos()); #endif newPoint.setState(state); newPoint.setId(0); return newPoint; }
/*! \internal */ QTouchEvent::TouchPoint makeTouchPointFromMouseEvent(QMouseEvent *event, Qt::TouchPointState state) { // this is only partially filled. But since it is only partially used it works // more robust would be to store a list of QPointFs rather than TouchPoints QTouchEvent::TouchPoint newPoint; newPoint.setPos(event->localPos()); newPoint.setScenePos(event->windowPos()); newPoint.setScreenPos(event->screenPos()); newPoint.setState(state); newPoint.setId(0); return newPoint; }
bool RenderableWebEntityItem::buildWebSurface(EntityTreeRenderer* renderer) { if (_currentWebCount >= MAX_CONCURRENT_WEB_VIEWS) { qWarning() << "Too many concurrent web views to create new view"; return false; } qDebug() << "Building web surface"; ++_currentWebCount; // Save the original GL context, because creating a QML surface will create a new context QOpenGLContext * currentContext = QOpenGLContext::currentContext(); QSurface * currentSurface = currentContext->surface(); _webSurface = new OffscreenQmlSurface(); _webSurface->create(currentContext); _webSurface->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/controls/")); _webSurface->load("WebView.qml"); _webSurface->resume(); _webSurface->getRootItem()->setProperty("url", _sourceUrl); _webSurface->getRootContext()->setContextProperty("desktop", QVariant()); _connection = QObject::connect(_webSurface, &OffscreenQmlSurface::textureUpdated, [&](GLuint textureId) { _texture = textureId; }); // Restore the original GL context currentContext->makeCurrent(currentSurface); auto forwardPointerEvent = [=](const EntityItemID& entityItemID, const PointerEvent& event) { if (entityItemID == getID()) { handlePointerEvent(event); } }; _mousePressConnection = QObject::connect(renderer, &EntityTreeRenderer::mousePressOnEntity, forwardPointerEvent); _mouseReleaseConnection = QObject::connect(renderer, &EntityTreeRenderer::mouseReleaseOnEntity, forwardPointerEvent); _mouseMoveConnection = QObject::connect(renderer, &EntityTreeRenderer::mouseMoveOnEntity, forwardPointerEvent); _hoverLeaveConnection = QObject::connect(renderer, &EntityTreeRenderer::hoverLeaveEntity, [=](const EntityItemID& entityItemID, const PointerEvent& event) { if (this->_pressed && this->getID() == entityItemID) { // If the user mouses off the entity while the button is down, simulate a touch end. QTouchEvent::TouchPoint point; point.setId(event.getID()); point.setState(Qt::TouchPointReleased); glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _dpi); QPointF windowPoint(windowPos.x, windowPos.y); point.setPos(windowPoint); QList<QTouchEvent::TouchPoint> touchPoints; touchPoints.push_back(point); QTouchEvent* touchEvent = new QTouchEvent(QEvent::TouchEnd, nullptr, Qt::NoModifier, Qt::TouchPointReleased, touchPoints); QCoreApplication::postEvent(_webSurface->getWindow(), touchEvent); } }); return true; }
void MScenePrivate::touchPointMirrorMousePosToPointPos(QTouchEvent::TouchPoint &point, const QGraphicsSceneMouseEvent *event) { Q_Q(MScene); if (q->views().size() > 0) { QPointF windowPos(q->views().at(0)->pos()); QSize resolution = MDeviceProfile::instance()->resolution(); QPointF centerPoint(resolution.width() / 2, resolution.height() / 2); QPointF mirrorPoint = centerPoint + (centerPoint - event->screenPos() + windowPos); point.setPos(mirrorPoint); point.setScenePos(mirrorPoint); point.setScreenPos(mirrorPoint + windowPos); } }
// 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); } } } } }
void Web3DOverlay::handlePointerEventAsTouch(const PointerEvent& event) { if (!_webSurface) { return; } //do not send secondary button events to tablet if (event.getButton() == PointerEvent::SecondaryButton || //do not block composed events event.getButtons() == PointerEvent::SecondaryButton) { return; } QPointF windowPoint; { glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _dpi); windowPoint = QPointF(windowPos.x, windowPos.y); } Qt::TouchPointState state = Qt::TouchPointStationary; if (event.getType() == PointerEvent::Press && event.getButton() == PointerEvent::PrimaryButton) { state = Qt::TouchPointPressed; } else if (event.getType() == PointerEvent::Release) { state = Qt::TouchPointReleased; } else if (_activeTouchPoints.count(event.getID()) && windowPoint != _activeTouchPoints[event.getID()].pos()) { state = Qt::TouchPointMoved; } QEvent::Type touchType = QEvent::TouchUpdate; if (_activeTouchPoints.empty()) { // If the first active touch point is being created, send a begin touchType = QEvent::TouchBegin; } if (state == Qt::TouchPointReleased && _activeTouchPoints.size() == 1 && _activeTouchPoints.count(event.getID())) { // If the last active touch point is being released, send an end touchType = QEvent::TouchEnd; } { QTouchEvent::TouchPoint point; point.setId(event.getID()); point.setState(state); point.setPos(windowPoint); point.setScreenPos(windowPoint); _activeTouchPoints[event.getID()] = point; } QTouchEvent touchEvent(touchType, &_touchDevice, event.getKeyboardModifiers()); { QList<QTouchEvent::TouchPoint> touchPoints; Qt::TouchPointStates touchPointStates; for (const auto& entry : _activeTouchPoints) { touchPointStates |= entry.second.state(); touchPoints.push_back(entry.second); } touchEvent.setWindow(_webSurface->getWindow()); touchEvent.setTarget(_webSurface->getRootItem()); touchEvent.setTouchPoints(touchPoints); touchEvent.setTouchPointStates(touchPointStates); } // Send mouse events to the Web surface so that HTML dialog elements work with mouse press and hover. // FIXME: Scroll bar dragging is a bit unstable in the tablet (content can jump up and down at times). // This may be improved in Qt 5.8. Release notes: "Cleaned up touch and mouse event delivery". // // In Qt 5.9 mouse events must be sent before touch events to make sure some QtQuick components will // receive mouse events Qt::MouseButton button = Qt::NoButton; Qt::MouseButtons buttons = Qt::NoButton; if (event.getButton() == PointerEvent::PrimaryButton) { button = Qt::LeftButton; } if (event.getButtons() & PointerEvent::PrimaryButton) { buttons |= Qt::LeftButton; } #if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) if (event.getType() == PointerEvent::Move) { QMouseEvent mouseEvent(QEvent::MouseMove, windowPoint, windowPoint, windowPoint, button, buttons, Qt::NoModifier); QCoreApplication::sendEvent(_webSurface->getWindow(), &mouseEvent); } #endif if (touchType == QEvent::TouchBegin) { _touchBeginAccepted = QCoreApplication::sendEvent(_webSurface->getWindow(), &touchEvent); } else if (_touchBeginAccepted) { QCoreApplication::sendEvent(_webSurface->getWindow(), &touchEvent); } // If this was a release event, remove the point from the active touch points if (state == Qt::TouchPointReleased) { _activeTouchPoints.erase(event.getID()); } #if QT_VERSION < QT_VERSION_CHECK(5, 9, 0) if (event.getType() == PointerEvent::Move) { QMouseEvent mouseEvent(QEvent::MouseMove, windowPoint, windowPoint, windowPoint, button, buttons, Qt::NoModifier); QCoreApplication::sendEvent(_webSurface->getWindow(), &mouseEvent); } #endif }
void RenderableWebEntityItem::handlePointerEvent(const PointerEvent& event) { // Ignore mouse interaction if we're locked if (getLocked() || !_webSurface) { return; } glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _dpi); QPointF windowPoint(windowPos.x, windowPos.y); if (event.getType() == PointerEvent::Move) { // Forward a mouse move event to webSurface QMouseEvent* mouseEvent = new QMouseEvent(QEvent::MouseMove, windowPoint, windowPoint, windowPoint, Qt::NoButton, Qt::NoButton, Qt::NoModifier); QCoreApplication::postEvent(_webSurface->getWindow(), mouseEvent); } { // Forward a touch update event to webSurface if (event.getType() == PointerEvent::Press) { this->_pressed = true; } else if (event.getType() == PointerEvent::Release) { this->_pressed = false; } QEvent::Type type; Qt::TouchPointState touchPointState; switch (event.getType()) { case PointerEvent::Press: type = QEvent::TouchBegin; touchPointState = Qt::TouchPointPressed; break; case PointerEvent::Release: type = QEvent::TouchEnd; touchPointState = Qt::TouchPointReleased; break; case PointerEvent::Move: default: type = QEvent::TouchUpdate; touchPointState = Qt::TouchPointMoved; break; } QTouchEvent::TouchPoint point; point.setId(event.getID()); point.setState(touchPointState); point.setPos(windowPoint); point.setScreenPos(windowPoint); QList<QTouchEvent::TouchPoint> touchPoints; touchPoints.push_back(point); QTouchEvent* touchEvent = new QTouchEvent(type); touchEvent->setWindow(nullptr); touchEvent->setDevice(nullptr); touchEvent->setTarget(nullptr); touchEvent->setTouchPoints(touchPoints); touchEvent->setTouchPointStates(touchPointState); _lastTouchEvent = *touchEvent; QCoreApplication::postEvent(_webSurface->getWindow(), touchEvent); } }
void MScenePrivate::touchPointCopyMousePosToPointPos(QTouchEvent::TouchPoint &point, const QGraphicsSceneMouseEvent *event) { point.setPos(event->pos()); point.setScenePos(event->scenePos()); point.setScreenPos(event->screenPos()); }