void TS_TouchIrq() { u16 x, y; if(TSState()==TS_Pressed) { int m = 1; if(ts_touchTime>=0) { x = TSMeasureX(); y = TSMeasureY(); m = 0; if(ts_touchTime==0) { tslp_lastX = x; tslp_lastY = y; ts_touchTime += 1000/TOUCH_UPDATE_FREQUENCY; } else if(tslp_lastX-x>TS_LONG_TOUCH_COORD_DELTA || tslp_lastX-x<-TS_LONG_TOUCH_COORD_DELTA || tslp_lastY-y>TS_LONG_TOUCH_COORD_DELTA || tslp_lastY-y<-TS_LONG_TOUCH_COORD_DELTA ) { ts_touchTime = -1; } else if(ts_touchTime>=TS_LONG_TOUCH_TIME) { interstingEvents = touchEvent(tslp_lastX,tslp_lastY,TS_LongPress); ts_touchTime = -1; } else { ts_touchTime += 1000/TOUCH_UPDATE_FREQUENCY; } } if(pressed==TS_NotPressed || interstingEvents == TS_InterestingMovementAndUp) { if(m) { x = TSMeasureX(); y = TSMeasureY(); } EXTI->PR |= (1<<6); if(x==TS_ERROR||y==TS_ERROR || TSState()==TS_NotPressed) { if(pressed == TS_Pressed && interstingEvents!=TS_NotInteresting) touchEvent(ts_lastX,ts_lastY,TS_Up); pressed = TS_NotPressed; interstingEvents = TS_InterestingMovementAndUp; return; } if(pressed==TS_NotPressed) interstingEvents = touchEvent(x,y,TS_Down); else if (x!=ts_lastX ||y!=ts_lastY) interstingEvents = touchEvent(x, y, TS_Move); ts_lastX = x, ts_lastY = y; if(interstingEvents==TS_InterestingMovementAndUp) TIM5->CR1 |= TIM_CR1_CEN|TIM_CR1_OPM; // start delay timer pressed = TS_Pressed; } } else { if(pressed==TS_Pressed && interstingEvents!=TS_NotInteresting) { touchEvent(ts_lastX,ts_lastY,TS_Up); } pressed = TS_NotPressed; interstingEvents = TS_InterestingMovementAndUp; ts_touchTime = 0; } }
int TSCalibrate() { int waitUnpress = 1; int waitPress = 0; int pointNumber = 0; const u16 xpoints[TS_CALIBRATION_POINTS_COUNT] = TS_CALIBRATION_POINTS_X; const u16 ypoints[TS_CALIBRATION_POINTS_COUNT] = TS_CALIBRATION_POINTS_Y; s32 xpointsRes[TS_CALIBRATION_POINTS_COUNT]; s32 ypointsRes[TS_CALIBRATION_POINTS_COUNT]; NVIC_DisableIRQ(EXTI9_5_IRQn); mTsCalibrationInProgress = 1; touchEvent(xpoints[pointNumber], ypoints[pointNumber], TS_WaitTouchPointForCalibration); while(mTsCalibrationInProgress) { if(waitUnpress && TSState()==TS_NotPressed) { waitUnpress = 0; waitPress = 1; TSDelay (10000); } else if (waitPress && TSState()==TS_Pressed) { xpointsRes[pointNumber] = TSMeasure(TSReadXNative, TS_CALIBRATION_MEASURE_COUNT); if(xpointsRes[pointNumber]==TS_ERROR) continue; ypointsRes[pointNumber] = TSMeasure(TSReadYNative, TS_CALIBRATION_MEASURE_COUNT); if(ypointsRes[pointNumber]==TS_ERROR) continue; pointNumber++; if(pointNumber>=TS_CALIBRATION_POINTS_COUNT) { double xAdcPerPoint = ((double)(xpointsRes[2]-xpointsRes[0])/(double)(xpoints[2]-xpoints[0]) + (double)(xpointsRes[3]-xpointsRes[1])/(double)(xpoints[3]-xpoints[1]))/2.0L; double yAdcPerPoint = ((double)(ypointsRes[3]-ypointsRes[0])/(double)(ypoints[3]-ypoints[0]) + (double)(ypointsRes[2]-ypointsRes[1])/(double)(ypoints[2]-ypoints[1]))/2.0L; mCalibrationData.ADC_X_MIN = (xpointsRes[0]-xpoints[0]*xAdcPerPoint + xpointsRes[1]-xpoints[1]*xAdcPerPoint + xpointsRes[2]-xpoints[2]*xAdcPerPoint + xpointsRes[3]-xpoints[3]*xAdcPerPoint)/4; mCalibrationData.ADC_X_WIDTH = xAdcPerPoint*LCD_XSIZE; mCalibrationData.ADC_Y_MIN = (ypointsRes[0]-ypoints[0]*yAdcPerPoint + ypointsRes[1]-ypoints[1]*yAdcPerPoint + ypointsRes[2]-ypoints[2]*yAdcPerPoint + ypointsRes[3]-ypoints[3]*yAdcPerPoint)/4; mCalibrationData.ADC_Y_WIDTH = yAdcPerPoint*LCD_YSIZE; touchEvent(0, 0, TS_CalibrationDone); while(TSState()==TS_Pressed); EXTI->PR |= (1<<6); NVIC_EnableIRQ(EXTI9_5_IRQn); return 1; } else { touchEvent(xpoints[pointNumber], ypoints[pointNumber], TS_WaitTouchPointForCalibration); } waitPress = 0; waitUnpress = 1; TSDelay (10000); } } touchEvent(0, 0, TS_CalibrationDone); EXTI->PR |= (1<<6); NVIC_EnableIRQ(EXTI9_5_IRQn); return 0; }
bool Slider::mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta) { switch (evt) { case Mouse::MOUSE_PRESS_LEFT_BUTTON: return touchEvent(Touch::TOUCH_PRESS, x, y, 0); case Mouse::MOUSE_MOVE: return Control::mouseEvent(evt, x, y, 0); case Mouse::MOUSE_RELEASE_LEFT_BUTTON: return touchEvent(Touch::TOUCH_RELEASE, x, y, 0); case Mouse::MOUSE_WHEEL: { if ((hasFocus() && _state == HOVER) || _state == ACTIVE) { float total = _max - _min; float oldValue = _value; _value += (total * SCROLLWHEEL_FRACTION) * wheelDelta; if (_value > _max) _value = _max; else if (_value < _min) _value = _min; if (_step > 0.0f) { int numSteps = round(_value / _step); _value = _step * numSteps; } if (_value != oldValue) { notifyListeners(Control::Listener::VALUE_CHANGED); } _dirty = true; return true; } break; } default: break; } return false; }
bool Slider::mouseEvent(Mouse::MouseEvent evt, int x, int y, int wheelDelta) { if (!isEnabled()) { return false; } switch (evt) { case Mouse::MOUSE_PRESS_LEFT_BUTTON: return touchEvent(Touch::TOUCH_PRESS, x, y, 0); case Mouse::MOUSE_MOVE: return touchEvent(Touch::TOUCH_MOVE, x, y, 0); case Mouse::MOUSE_RELEASE_LEFT_BUTTON: return touchEvent(Touch::TOUCH_RELEASE, x, y, 0); case Mouse::MOUSE_WHEEL: { if (_state == FOCUS || _state == ACTIVE) { float total = _max - _min; float oldValue = _value; _value += (total * SCROLL_FRACTION) * wheelDelta; if (_value > _max) _value = _max; else if (_value < _min) _value = _min; if (_value != oldValue) { notifyListeners(Listener::VALUE_CHANGED); } _dirty = true; return _consumeInputEvents; } break; } default: break; } return false; }
bool QQuickPinchArea::childMouseEventFilter(QQuickItem *i, QEvent *e) { Q_D(QQuickPinchArea); if (!d->enabled || !isVisible()) return QQuickItem::childMouseEventFilter(i, e); switch (e->type()) { case QEvent::TouchBegin: case QEvent::TouchUpdate: { QTouchEvent *touch = static_cast<QTouchEvent*>(e); if (touch->touchPoints().count() > 1) { touchEvent(touch); } else { d->touchPoints.clear(); for (int i = 0; i < touch->touchPoints().count(); ++i) if (!(touch->touchPoints().at(i).state() & Qt::TouchPointReleased)) d->touchPoints << touch->touchPoints().at(i); updatePinch(); } } return d->inPinch; case QEvent::TouchEnd: d->touchPoints.clear(); updatePinch(); break; default: break; } return QQuickItem::childMouseEventFilter(i, e); }
void EventListener::onEvent(Event* e) { /* since we already checked which type we have we can safely use the faster static_cast (rl) */ if (typeid(*e) == typeid(MouseEvent)) { MouseEvent* me = static_cast<MouseEvent*>(e); if (me->action() == MouseEvent::PRESSED) mousePressEvent(me); else if (me->action() == MouseEvent::RELEASED) mouseReleaseEvent(me); else if (me->action() == MouseEvent::MOTION) mouseMoveEvent(me); else if (me->action() == MouseEvent::DOUBLECLICK) mouseDoubleClickEvent(me); else if (me->action() == MouseEvent::WHEEL) wheelEvent(me); } else if (typeid(*e) == typeid(KeyEvent)) { keyEvent(static_cast<KeyEvent*>(e)); } else if (typeid(*e) == typeid(TimeEvent)) { timerEvent(static_cast<TimeEvent*>(e)); } else if (typeid(*e) == typeid(TouchEvent)) { touchEvent(static_cast<TouchEvent*>(e)); } }
void ofxLua::scriptTouchCancelled(ofTouchEventArgs &touch) { if(L == NULL) return; ofxLuaTouchEvent touchEvent(touch); try { luabind::call_function<bool>(L, "touchCancelled", boost::ref(touchEvent)); } catch(exception& e) {} }
//-------------------------------------------------------------- // calling lua functions with objects: // http://www.nuclex.org/articles/cxx/1-quick-introduction-to-luabind void ofxLua::scriptTouchDown(ofTouchEventArgs &touch) { if(L == NULL) return; ofxLuaTouchEvent touchEvent(touch); // convert to wrapper with copy operator try { luabind::call_function<bool>(L, "touchDown", boost::ref(touchEvent)); } catch(exception& e) {} }
bool FlatTextarea::viewportEvent(QEvent *e) { if (e->type() == QEvent::TouchBegin || e->type() == QEvent::TouchUpdate || e->type() == QEvent::TouchEnd || e->type() == QEvent::TouchCancel) { QTouchEvent *ev = static_cast<QTouchEvent*>(e); if (ev->device()->type() == QTouchDevice::TouchScreen) { touchEvent(ev); return QTextEdit::viewportEvent(e); } } return QTextEdit::viewportEvent(e); }
bool ScrollArea::viewportEvent(QEvent *e) { if (e->type() == QEvent::TouchBegin || e->type() == QEvent::TouchUpdate || e->type() == QEvent::TouchEnd || e->type() == QEvent::TouchCancel) { QTouchEvent *ev = static_cast<QTouchEvent*>(e); if (_touchEnabled && ev->device()->type() == QTouchDevice::TouchScreen) { touchEvent(ev); return true; } } return QScrollArea::viewportEvent(e); }
bool FlatLabel::event(QEvent *e) { if (e->type() == QEvent::TouchBegin || e->type() == QEvent::TouchUpdate || e->type() == QEvent::TouchEnd || e->type() == QEvent::TouchCancel) { QTouchEvent *ev = static_cast<QTouchEvent*>(e); if (ev->device()->type() == QTouchDevice::TouchScreen) { touchEvent(ev); return true; } } return QWidget::event(e); }
void ViewerPageHandler::customEvent(QEvent* received) { if (received->type() != (int)MouseFilter::TOUCH_EVENT) { qDebug() << "UNEXPECTED TYPE"; return; } TouchEvent *event = static_cast<TouchEvent*>(received); if (event->touchType() == MouseFilter::TAP) emit tapEvent(event, true); else emit touchEvent(event); }
bool ScrollArea::viewportEvent(QEvent *e) { if (e->type() == QEvent::TouchBegin || e->type() == QEvent::TouchUpdate || e->type() == QEvent::TouchEnd || e->type() == QEvent::TouchCancel) { QTouchEvent *ev = static_cast<QTouchEvent*>(e); if (_touchEnabled && ev->device()->type() == QTouchDevice::TouchScreen) { if (ev->type() != QEvent::TouchBegin || ev->touchPoints().isEmpty() || !widget() || !widget()->childAt(widget()->mapFromGlobal(ev->touchPoints().cbegin()->screenPos().toPoint()))) { touchEvent(ev); return true; } } } return QScrollArea::viewportEvent(e); }
void CTouchDispather::DispatchEvent( EEventType type ) { CTouchEvent touchEvent(type); for ( auto iter : m_vecTouch ) { if ( iter ) { touchEvent.AddTouch( iter ); } } CEventDispatcher::DispatchEvent( &touchEvent ); }
bool ScrollArea::eventFilter(QObject *obj, QEvent *e) { bool res = QScrollArea::eventFilter(obj, e); if (e->type() == QEvent::TouchBegin || e->type() == QEvent::TouchUpdate || e->type() == QEvent::TouchEnd || e->type() == QEvent::TouchCancel) { QTouchEvent *ev = static_cast<QTouchEvent*>(e); if (_touchEnabled && ev->device()->type() == QTouchDevice::TouchScreen) { if (obj == widget()) { touchEvent(ev); return true; } } } return res; }
/*! \internal */ bool QDeclarativeGeoMapGestureArea::filterMapChildTouchEvent(QTouchEvent *event) { usingTouch_ = true; if (!(enabled_ && activeGestures_)) return false; if (event->touchPoints().count() > 1 || isPanActive() || isPinchActive()) return true; // Don't filter the event, but use it to see if we should start // a gesture. touchEvent(event); return false; }
bool MediaView::event(QEvent *e) { if (e->type() == QEvent::TouchBegin || e->type() == QEvent::TouchUpdate || e->type() == QEvent::TouchEnd || e->type() == QEvent::TouchCancel) { QTouchEvent *ev = static_cast<QTouchEvent*>(e); if (ev->device()->type() == QTouchDevice::TouchScreen) { if (!ev->touchPoints().isEmpty()) { QPoint p(mapFromGlobal(ev->touchPoints().cbegin()->screenPos().toPoint())); if ((!_close.isHidden() && _close.geometry().contains(p)) || (!_save.isHidden() && _save.geometry().contains(p)) || (!_forward.isHidden() && _forward.geometry().contains(p)) || (!_delete.isHidden() && _delete.geometry().contains(p))) { return QWidget::event(e); } } touchEvent(ev); return true; } } return QWidget::event(e); }
bool CanvasQt::event(QEvent *e) { switch (e->type()) { case QEvent::KeyPress: keyPressEvent(static_cast<QKeyEvent*>(e)); return true; case QEvent::KeyRelease: keyReleaseEvent(static_cast<QKeyEvent*>(e)); return true; case QEvent::MouseButtonPress: if(!gestureMode_) mousePressEvent(static_cast<QMouseEvent*>(e)); return true; case QEvent::MouseButtonRelease: if(!gestureMode_) mouseReleaseEvent(static_cast<QMouseEvent*>(e)); return true; case QEvent::MouseMove: if(!gestureMode_) mouseMoveEvent(static_cast<QMouseEvent*>(e)); return true; case QEvent::Wheel: wheelEvent(static_cast<QWheelEvent*>(e)); return true; #ifndef QT_NO_GESTURES case QEvent::TouchBegin: case QEvent::TouchEnd: case QEvent::TouchUpdate: touchEvent(static_cast<QTouchEvent*>(e)); return true; case QEvent::Gesture: return gestureEvent(static_cast<QGestureEvent*>(e)); #endif #ifdef USE_QWINDOW case QEvent::UpdateRequest: paintGL(); return true; #endif default: return QGLWindow::event(e); } }
void TouchDispatcher::dispatchTouchBegin( QTouchDevice *device, Qt::KeyboardModifiers modifiers, const QList<QTouchEvent::TouchPoint> &touchPoints, QWindow *window, ulong timestamp) { Q_ASSERT(m_status == NoActiveTouch); QQuickItem *targetItem = m_targetItem.data(); if (!targetItem->isEnabled() || !targetItem->isVisible()) { ugDebug("Cannot dispatch touch event to " << targetItem << " because it's disabled or invisible."); return; } // Map touch points to targetItem coordinates QList<QTouchEvent::TouchPoint> targetTouchPoints = touchPoints; transformTouchPoints(targetTouchPoints, QQuickItemPrivate::get(targetItem)->windowToItemTransform()); QScopedPointer<QTouchEvent> touchEvent( createQTouchEvent(QEvent::TouchBegin, device, modifiers, targetTouchPoints, window, timestamp)); ugDebug("dispatching " << qPrintable(touchEventToString(touchEvent.data())) << " to " << targetItem); QCoreApplication::sendEvent(targetItem, touchEvent.data()); if (touchEvent->isAccepted()) { ugDebug("Item accepted the touch event."); setStatus(DeliveringTouchEvents); } else if (targetItem->acceptedMouseButtons() & Qt::LeftButton) { ugDebug("Item rejected the touch event. Trying a QMouseEvent"); // NB: Arbitrarily chose the first touch point to emulate the mouse pointer QScopedPointer<QMouseEvent> mouseEvent( touchToMouseEvent(QEvent::MouseButtonPress, targetTouchPoints.at(0), timestamp, modifiers, false /* transformNeeded */)); Q_ASSERT(targetTouchPoints.at(0).state() == Qt::TouchPointPressed); ugDebug("dispatching " << qPrintable(mouseEventToString(mouseEvent.data())) << " to " << m_targetItem.data()); QCoreApplication::sendEvent(targetItem, mouseEvent.data()); if (mouseEvent->isAccepted()) { ugDebug("Item accepted the QMouseEvent."); setStatus(DeliveringMouseEvents); m_touchMouseId = targetTouchPoints.at(0).id(); if (checkIfDoubleClicked(timestamp)) { QScopedPointer<QMouseEvent> doubleClickEvent( touchToMouseEvent(QEvent::MouseButtonDblClick, targetTouchPoints.at(0), timestamp, modifiers, false /* transformNeeded */)); ugDebug("dispatching " << qPrintable(mouseEventToString(doubleClickEvent.data())) << " to " << m_targetItem.data()); QCoreApplication::sendEvent(targetItem, doubleClickEvent.data()); } } else { ugDebug("Item rejected the QMouseEvent."); setStatus(TargetRejectedTouches); } } else { ugDebug("Item rejected the touch event and does not accept mouse buttons."); setStatus(TargetRejectedTouches); } }
nsEventStatus GestureEventListener::HandlePinchGestureEvent(const MultiTouchInput& aEvent) { nsEventStatus rv = nsEventStatus_eIgnore; if (aEvent.mType == MultiTouchInput::MULTITOUCH_CANCEL) { mTouches.Clear(); mState = GESTURE_NONE; return rv; } if (mTouches.Length() > 1) { const ScreenIntPoint& firstTouch = mTouches[0].mScreenPoint, secondTouch = mTouches[1].mScreenPoint; ScreenPoint focusPoint = ScreenPoint(firstTouch + secondTouch) / 2; ScreenIntPoint delta = secondTouch - firstTouch; float currentSpan = float(NS_hypot(delta.x, delta.y)); switch (mState) { case GESTURE_NONE: mPreviousSpan = currentSpan; mState = GESTURE_WAITING_PINCH; // Deliberately fall through. If the user pinched and took their fingers // off the screen such that they still had 1 left on it, we want there to // be no resistance. We should only reset |mSpanChange| once all fingers // are off the screen. case GESTURE_WAITING_PINCH: { mSpanChange += fabsf(currentSpan - mPreviousSpan); if (mSpanChange > PINCH_START_THRESHOLD) { PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_START, aEvent.mTime, focusPoint, currentSpan, currentSpan, aEvent.modifiers); mAsyncPanZoomController->HandleInputEvent(pinchEvent); mState = GESTURE_PINCH; } break; } case GESTURE_PINCH: { PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_SCALE, aEvent.mTime, focusPoint, currentSpan, mPreviousSpan, aEvent.modifiers); mAsyncPanZoomController->HandleInputEvent(pinchEvent); break; } default: // What? break; } mPreviousSpan = currentSpan; rv = nsEventStatus_eConsumeNoDefault; } else if (mState == GESTURE_PINCH) { PinchGestureInput pinchEvent(PinchGestureInput::PINCHGESTURE_END, aEvent.mTime, ScreenPoint(), 1.0f, 1.0f, aEvent.modifiers); mAsyncPanZoomController->HandleInputEvent(pinchEvent); mState = GESTURE_NONE; // If the user left a finger on the screen, spoof a touch start event and // send it to APZC so that they can continue panning from that point. if (mTouches.Length() == 1) { MultiTouchInput touchEvent(MultiTouchInput::MULTITOUCH_START, aEvent.mTime, aEvent.modifiers); touchEvent.mTouches.AppendElement(mTouches[0]); mAsyncPanZoomController->HandleInputEvent(touchEvent); // The spoofed touch start will get back to GEL and make us enter the // GESTURE_WAITING_SINGLE_TAP state, but this isn't a new touch, so there // is no condition under which this touch should turn into any tap. mState = GESTURE_NONE; } rv = nsEventStatus_eConsumeNoDefault; } else if (mState == GESTURE_WAITING_PINCH) { mState = GESTURE_NONE; } return rv; }
bool MScenePrivate::eventEmulatePinch(QEvent *event) { Q_Q(MScene); bool sendTouchEvent = false; QGraphicsSceneMouseEvent *e = static_cast<QGraphicsSceneMouseEvent*>(event); QEvent::Type touchEventType; Qt::TouchPointState touchPointState; if (QEvent::GraphicsSceneMousePress == event->type()) { if (Qt::LeftButton == e->button() && e->modifiers().testFlag(Qt::ControlModifier)) { pinchEmulationEnabled = true; touchPointMirrorMousePosToPointPos(emuPoint1,e); touchPointMirrorMousePosToPointStartPos(emuPoint1,e); emuPoint1.setState(Qt::TouchPointPressed); touchPointCopyMousePosToPointPos(emuPoint2,e); touchPointCopyMousePosToPointStartPos(emuPoint2,e); emuPoint2.setState(Qt::TouchPointPressed); touchEventType = QEvent::TouchBegin; touchPointState = Qt::TouchPointPressed; sendTouchEvent = true; } } if (pinchEmulationEnabled && QEvent::GraphicsSceneMouseMove == event->type()) { touchPointCopyPosToLastPos(emuPoint1); touchPointMirrorMousePosToPointPos(emuPoint1,e); emuPoint1.setState(Qt::TouchPointMoved); touchPointCopyPosToLastPos(emuPoint2); touchPointCopyMousePosToPointPos(emuPoint2,e); emuPoint2.setState(Qt::TouchPointMoved); touchEventType = QEvent::TouchUpdate; touchPointState = Qt::TouchPointMoved; sendTouchEvent = true; } if (pinchEmulationEnabled && QEvent::GraphicsSceneMouseRelease == event->type()) { if (Qt::LeftButton == e->button()) { touchPointCopyPosToLastPos(emuPoint1); emuPoint1.setState(Qt::TouchPointReleased); touchPointCopyPosToLastPos(emuPoint2); touchPointCopyMousePosToPointPos(emuPoint2,e); emuPoint2.setState(Qt::TouchPointReleased); touchEventType = QEvent::TouchEnd; touchPointState = Qt::TouchPointReleased; pinchEmulationEnabled = false; sendTouchEvent = true; } } if (sendTouchEvent) { QList<QTouchEvent::TouchPoint> touchList; touchList.append(emuPoint1); touchList.append(emuPoint2); QTouchEvent touchEvent(touchEventType, QTouchEvent::TouchPad, Qt::NoModifier, touchPointState, touchList); if (q->views().size()>0) QApplication::sendEvent(q->views().at(0), &touchEvent); q->update(); return true; } return false; }
void Game::touchEventInternal(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex) { touchEvent(evt, x, y, contactIndex); if (_scriptTarget) _scriptTarget->fireScriptEvent<void>(GP_GET_SCRIPT_EVENT(GameScriptTarget, touchEvent), evt, x, y, contactIndex); }
void CanvasQt::touchEvent(QTouchEvent* touch) { size_t nTouchPoints = touch->touchPoints().size(); if (nTouchPoints < 1) { return; } QTouchEvent::TouchPoint firstPoint = touch->touchPoints()[0]; switch (firstPoint.state()) { case Qt::TouchPointPressed: gestureMode_ = nTouchPoints > 1; // Treat single touch point as mouse event break; case Qt::TouchPointMoved: gestureMode_ = nTouchPoints > 1; // Treat single touch point as mouse event break; case Qt::TouchPointStationary: gestureMode_ = nTouchPoints > 1; // Treat single touch point as mouse event break; case Qt::TouchPointReleased: gestureMode_ = false; break; default: gestureMode_ = false; } // Copy touch points std::vector<TouchPoint> touchPoints; touchPoints.reserve(touch->touchPoints().size()); // Fetch layer before loop (optimization) const LayerRAM* depthLayerRAM = getDepthLayerRAM(); vec2 screenSize(getScreenDimensions()); std::vector<int> endedTouchIds; for (auto& touchPoint : touch->touchPoints()) { vec2 screenTouchPos(touchPoint.pos().x(), touchPoint.pos().y()); vec2 prevScreenTouchPos(touchPoint.lastPos().x(), touchPoint.lastPos().y()); TouchPoint::TouchState touchState; switch (touchPoint.state()) { case Qt::TouchPointPressed: touchState = TouchPoint::TOUCH_STATE_STARTED; break; case Qt::TouchPointMoved: touchState = TouchPoint::TOUCH_STATE_UPDATED; break; case Qt::TouchPointStationary: touchState = TouchPoint::TOUCH_STATE_STATIONARY; break; case Qt::TouchPointReleased: touchState = TouchPoint::TOUCH_STATE_ENDED; break; default: touchState = TouchPoint::TOUCH_STATE_NONE; } ivec2 pixelCoord = ivec2(static_cast<int>(screenTouchPos.x), screenSize.y - 1 - static_cast<int>(screenTouchPos.y)); // Note that screenTouchPos/prevScreenTouchPos are in [0 screenDim] and does not need to be // adjusted to become centered in the pixel (+0.5) // Saving id order to preserve order of touch points at next touch event const auto lastIdIdx = std::find(lastTouchIds_.begin(), lastTouchIds_.end(), touchPoint.id()); if (lastIdIdx != lastTouchIds_.end()) { if (touchState == TouchPoint::TOUCH_STATE_ENDED){ endedTouchIds.push_back(touchPoint.id()); } } else{ lastTouchIds_.push_back(touchPoint.id()); } touchPoints.emplace_back(touchPoint.id(), screenTouchPos, (screenTouchPos) / screenSize, prevScreenTouchPos, (prevScreenTouchPos) / screenSize, touchState, getDepthValueAtCoord(pixelCoord, depthLayerRAM)); } // Ensure that the order to the touch points are the same as last touch event. // Note that the ID of a touch point is always the same but the order in which // they are given can vary. // Example // lastTouchIds_ touchPoints // 0 0 // 3 1 // 2 2 // 4 // Will result in: // touchPoints // 0 (no swap) // 2 (2 will swap with 1) // 1 auto touchIndex = 0; // Index to first unsorted element in touchPoints array for (const auto& lastTouchPointId : lastTouchIds_) { const auto touchPointIt = std::find_if(touchPoints.begin(), touchPoints.end(), [lastTouchPointId](const TouchPoint& p) { return p.getId() == lastTouchPointId; }); // Swap current location in the container with the location it was in last touch event. if (touchPointIt != touchPoints.end() && std::distance(touchPoints.begin(), touchPointIt) != touchIndex) { std::swap(*(touchPoints.begin() + touchIndex), *touchPointIt); ++touchIndex; } } for (auto& endedId : endedTouchIds) { std::vector<int>::iterator foundIdx = std::find(lastTouchIds_.begin(), lastTouchIds_.end(), endedId); if (foundIdx != lastTouchIds_.end()) lastTouchIds_.erase(foundIdx); } TouchEvent touchEvent(touchPoints, getScreenDimensions()); touch->accept(); // We need to send out touch event all the time to support one -> two finger touch switch Canvas::touchEvent(&touchEvent); // Mouse events will be triggered for touch events by Qt4 and Qt >= 5.3.0 // https://bugreports.qt.io/browse/QTBUG-40038 #if defined(USING_QT5) && (QT_VERSION < QT_VERSION_CHECK(5, 3, 0)) if(touch->touchPoints().size() == 1 && lastNumFingers_ < 2){ MouseEvent* mouseEvent = nullptr; ivec2 pos = ivec2(static_cast<int>(firstPoint.pos().x()), static_cast<int>(firstPoint.pos().y())); uvec2 screenPosInvY(static_cast<unsigned int>(pos.x), static_cast<unsigned int>(getScreenDimensions().y-1-pos.y)); double depth = getDepthValueAtCoord(screenPosInvY); switch (touchPoints.front().state()) { case TouchPoint::TOUCH_STATE_STARTED: mouseEvent = new MouseEvent(pos, MouseEvent::MOUSE_BUTTON_LEFT, MouseEvent::MOUSE_STATE_PRESS, EventConverterQt::getModifier(touch), getScreenDimensions(), depth); Canvas::mousePressEvent(mouseEvent); break; case TouchPoint::TOUCH_STATE_UPDATED: mouseEvent = new MouseEvent(pos, MouseEvent::MOUSE_BUTTON_LEFT, MouseEvent::MOUSE_STATE_MOVE, EventConverterQt::getModifier(touch), getScreenDimensions(), depth); Canvas::mouseMoveEvent(mouseEvent); break; case TouchPoint::TOUCH_STATE_STATIONARY: break; // Do not fire event while standing still. case TouchPoint::TOUCH_STATE_ENDED: mouseEvent = new MouseEvent(pos, MouseEvent::MOUSE_BUTTON_LEFT, MouseEvent::MOUSE_STATE_RELEASE, EventConverterQt::getModifier(touch), getScreenDimensions(), depth); Canvas::mouseReleaseEvent(mouseEvent); break; default: break; } delete mouseEvent; } #endif lastNumFingers_ = static_cast<int>(touch->touchPoints().size()); screenPositionNormalized_ = touchEvent.getCenterPointNormalized(); }
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 }