Example #1
0
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;
}
void QtWebPageEventHandler::handleInputEvent(const QInputEvent* event)
{
    if (m_viewportController) {
        switch (event->type()) {
        case QEvent::MouseButtonPress:
        case QEvent::TouchBegin:
            m_viewportController->touchBegin();

            // The page viewport controller might still be animating kinetic scrolling or a scale animation
            // such as double-tap to zoom or the bounce back effect. A touch stops the kinetic scrolling
            // where as it does not stop the scale animation.
            // The gesture recognizer stops the kinetic scrolling animation if needed.
            break;
        case QEvent::MouseMove:
        case QEvent::TouchUpdate:
            // The scale animation can only be interrupted by a pinch gesture, which will then take over.
            if (m_viewportController->scaleAnimationActive() && m_pinchGestureRecognizer.isRecognized())
                m_viewportController->interruptScaleAnimation();
            break;
        case QEvent::MouseButtonRelease:
        case QEvent::TouchEnd:
            m_viewportController->touchEnd();
            break;
        default:
            break;
        }

        // If the scale animation is active we don't pass the event to the recognizers. In the future
        // we would want to queue the event here and repost then when the animation ends.
        if (m_viewportController->scaleAnimationActive())
            return;
    }

    bool isMouseEvent = false;

    switch (event->type()) {
    case QEvent::MouseButtonPress:
        isMouseEvent = true;
        m_isMouseButtonPressed = true;
        break;
    case QEvent::MouseMove:
        if (!m_isMouseButtonPressed)
            return;
        isMouseEvent = true;
        break;
    case QEvent::MouseButtonRelease:
        isMouseEvent = true;
        m_isMouseButtonPressed = false;
        break;
    case QEvent::MouseButtonDblClick:
        return;
    default:
        break;
    }

    QList<QTouchEvent::TouchPoint> activeTouchPoints;
    QTouchEvent::TouchPoint currentTouchPoint;
    qint64 eventTimestampMillis = event->timestamp();
    int touchPointCount = 0;

    if (!isMouseEvent) {
        const QTouchEvent* touchEvent = static_cast<const QTouchEvent*>(event);
        const QList<QTouchEvent::TouchPoint>& touchPoints = touchEvent->touchPoints();
        currentTouchPoint = touchPoints.first();
        touchPointCount = touchPoints.size();
        activeTouchPoints.reserve(touchPointCount);

        for (int i = 0; i < touchPointCount; ++i) {
            if (touchPoints[i].state() != Qt::TouchPointReleased)
                activeTouchPoints << touchPoints[i];
        }
    } else {
        const QMouseEvent* mouseEvent = static_cast<const QMouseEvent*>(event);
        touchPointCount = 1;

        // Make a distinction between mouse events on the basis of pressed buttons.
        currentTouchPoint.setId(mouseEvent->buttons());
        currentTouchPoint.setScreenPos(mouseEvent->screenPos());
        // For tap gesture hit testing the float touch rect is translated to
        // an int rect representing the radius of the touch point (size/2),
        // thus the touch rect has to have a size of at least 2.
        currentTouchPoint.setRect(QRectF(mouseEvent->localPos(), QSizeF(2, 2)));

        if (m_isMouseButtonPressed)
            activeTouchPoints << currentTouchPoint;
    }

    const int activeTouchPointCount = activeTouchPoints.size();

    if (!activeTouchPointCount) {
        if (touchPointCount == 1) {
            // No active touch points, one finger released.
            if (m_panGestureRecognizer.isRecognized())
                m_panGestureRecognizer.finish(currentTouchPoint, eventTimestampMillis);
            else {
                // The events did not result in a pan gesture.
                m_panGestureRecognizer.cancel();
                m_tapGestureRecognizer.finish(currentTouchPoint);
            }

        } else
            m_pinchGestureRecognizer.finish();

        // Early return since this was a touch-end event.
        return;
    } else if (activeTouchPointCount == 1) {
        // If the pinch gesture recognizer was previously in active state the content might
        // be out of valid zoom boundaries, thus we need to finish the pinch gesture here.
        // This will resume the content to valid zoom levels before the pan gesture is started.
        m_pinchGestureRecognizer.finish();
        m_panGestureRecognizer.update(activeTouchPoints.first(), eventTimestampMillis);
    } else if (activeTouchPointCount == 2) {
        m_panGestureRecognizer.cancel();
        m_pinchGestureRecognizer.update(activeTouchPoints.first(), activeTouchPoints.last());
    }

    if (m_panGestureRecognizer.isRecognized() || m_pinchGestureRecognizer.isRecognized() || m_webView->isMoving())
        m_tapGestureRecognizer.cancel();
    else if (touchPointCount == 1)
        m_tapGestureRecognizer.update(currentTouchPoint);

}
Example #3
0
// 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);			
				}
			}
		}
	}
}
Example #4
0
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
}
Example #5
0
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);
    }
}
Example #6
0
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;
}