diff -r 6aeb7a756187 -r 3c88a81ff781 qstmgesturelib/qstmgestureevent.cpp --- a/qstmgesturelib/qstmgestureevent.cpp Thu Sep 23 15:32:11 2010 -0400 +++ b/qstmgesturelib/qstmgestureevent.cpp Fri Oct 15 17:30:59 2010 -0400 @@ -19,14 +19,97 @@ * */ -#include -#include #include "qstmgestureevent.h" #include "qstmuievent_if.h" +#include + using namespace qstmUiEventEngine; +using namespace qstmGesture; + +static Qt::GestureType s_assignedType = Qt::CustomGesture; +static int s_stmGestureEventType = QEvent::User; +static QGraphicsItem* s_gestureGrabberItem = NULL; +static QGraphicsItem* s_gestureFocusedItem = NULL; + + +QStm_GestureEventFilter* QStm_GestureEventFilter::m_instance = 0; + +QStm_GestureEventFilter* QStm_GestureEventFilter::instance() +{ + if (!m_instance) { + m_instance = new QStm_GestureEventFilter(); + } + return m_instance; +} + +bool QStm_GestureEventFilter::eventFilter(QObject* receiver, QEvent* evt) +{ + return qstmIsGraphicsSceneMouseEvent(evt) || qstmIsMouseEvent(evt) || + qstmIsTouchEvent(evt) || qstmIsContextMenuEvent(evt); +} + + + + +bool QStm_GestureEventFilter::sendGraphicsSceneMouseEvent(QEvent* event, QGraphicsObject* go) +{ + bool ret = false; + if (event->type() == QEvent::Gesture) { + QStm_Gesture* gesture = getQStmGesture(event); + if (gesture) { + ret = gesture->sendGraphicsSceneMouseEvent(go); + } + + } + return ret; +} + -Qt::GestureType QStm_Gesture::s_assignedType = Qt::CustomGesture; +bool QStm_GestureEventFilter::event(QEvent* event) +{ + if (event->type() == QEvent::Gesture) { + QStm_Gesture* gesture = getQStmGesture(event); + if (gesture) { + QStm_GestureType gtype = gesture->getGestureStmType(); + + /* + * Touch mapped to mouse press, Tap mapped to mouse release + * UpDown, LeftRight and Pan are mapped to mouse move. + */ + if (gtype == QStmMaybeTapGestureType) {// in case of tap send mouse release + gesture->setGestureStmType(QStmReleaseGestureType); + } + + bool ret = (gtype == QStmTouchGestureType || + gtype == QStmMaybeTapGestureType || + gtype == QStmLeftRightGestureType || + gtype == QStmUpDownGestureType || + gtype == QStmPanGestureType || + gtype == QStmReleaseGestureType || + gtype == QStmFlickGestureType || + gtype == QStmUknownGestureType) ; + + if (ret) { + gesture->sendMouseEvents(); + (static_cast(event))->accept(QStm_Gesture::assignedType()); + (static_cast(event))->accept(); + } + + if (gtype == QStmTapGestureType) {// restore gesture type. + gesture->setGestureStmType(QStmTapGestureType); + } + + return ret; + } + } + return false; +} + + + + + QStm_GestureEvent::QStm_GestureEvent(): QEvent(QStm_GestureEvent::stmGestureEventType()) @@ -39,8 +122,47 @@ } +QEvent::Type QStm_GestureEvent::stmGestureEventType() +{ + if (s_stmGestureEventType == QEvent::User) { + s_stmGestureEventType = QEvent::registerEventType(QStmGestureEventType); + } + return static_cast(QStmGestureEventType); +} + + + +void QStm_Gesture::setAssignedGestureType(Qt::GestureType type) +{ + s_assignedType = type; +} + +Qt::GestureType QStm_Gesture::assignedType() +{ + return s_assignedType; +} +QGraphicsItem* QStm_Gesture::gestureGrabberItem() +{ + return s_gestureGrabberItem; +} + +void QStm_Gesture::setGestureGrabberItem(QGraphicsItem* item) +{ + s_gestureGrabberItem = item; +} + + +QGraphicsItem* QStm_Gesture::gestureFocusedItem() +{ + return s_gestureFocusedItem; +} + +void QStm_Gesture::setGestureFocusedItem(QGraphicsItem* item) +{ + s_gestureFocusedItem = item; +} QStm_Gesture::QStm_Gesture(QObject* parent) : QGesture(parent) { @@ -51,9 +173,11 @@ m_state = Qt::NoGesture; m_gstSubType = 0; m_pos = QPoint(INT_MIN,INT_MIN); + m_pos2 = QPoint(INT_MIN,INT_MIN); m_details = NULL; m_speedVec = QPointF(0.0, 0.0); m_target = NULL; + m_timestamp = QTime::currentTime(); }; @@ -66,9 +190,12 @@ m_state = other.gestureState(); m_gstSubType = other.getGestureSubType(); m_pos = other.position(); + m_pos2 = other.position2(); m_details = other.getDetails(); m_speedVec = other.getSpeedVec(); - m_target = other.m_target; + m_target = other.target(); + m_timestamp = other.timestamp(); + setHotSpot(other.hotSpot()); return *this; } @@ -109,6 +236,104 @@ } } + + +QStm_GestureType QStm_Gesture::gestureUidToStmType(QStm_GestureUid uid, int stmGestSubType) +{ + QStm_GestureType gtype = QStmUknownGestureType; + + switch (uid) { + case EGestureUidTap: + { + QStm_TapType type = qstmGesture::QStm_TapType(stmGestSubType); + if (type == qstmGesture::ETapTypeDouble) { + gtype = QStmDoubleTapGestureType; + } + else { + gtype = QStmTapGestureType; + } + break; + } + + case EGestureUidTouch: + { + gtype = QStmTouchGestureType; + break; + } + + case EGestureUidRelease: + { + gtype = QStmReleaseGestureType; + break; + } + + case EGestureUidFlick: + { + gtype = QStmFlickGestureType; + break; + } + + case EGestureUidLeftRight: + { + gtype = QStmLeftRightGestureType; + break; + } + + case EGestureUidUpDown: + { + gtype = QStmUpDownGestureType; + break; + } + + case EGestureUidPan: + { + gtype = QStmPanGestureType; + break; + } + + case EGestureUidHover: + { + gtype = QStmHoverGestureType; + break; + } + + case EGestureUidLongPress: + { + gtype = QStmLongPressGestureType; + break; + } + + case EGestureUidEdgeScroll: + { + gtype = QStmEdgeScrollGestureType; + break; + } + + case EGestureUidCornerZoom: + { + gtype = QStmCornerZoomGestureType; + break; + } + + case EGestureUidPinch: + { + gtype = QStmPinchGestureType; + break; + } + case EGestureUidMaybeTap: + { + gtype = QStmMaybeTapGestureType; + break; + } + default: + { + gtype = QStmUknownGestureType; + break; + } + } + return gtype; +} + void QStm_Gesture::gestureTypeToMouseTypes(QVarLengthArray& types) { switch (m_gstType) { @@ -133,11 +358,13 @@ break; } case QStmReleaseGestureType: + case QStmFlickGestureType: { types.append(QEvent::MouseButtonRelease); break; } case QStmTapGestureType: + //case QStmMaybeTapGestureType: { types.append(QEvent::MouseButtonPress); types.append(QEvent::MouseButtonRelease); @@ -152,7 +379,6 @@ } break; } - case QStmFlickGestureType: case QStmEdgeScrollGestureType: case QStmPinchGestureType: case QStmLongPressGestureType: @@ -162,6 +388,9 @@ return; } + + + bool QStm_Gesture::sendOrPostMouseEvents(QObject* receiver, Qt::KeyboardModifier modifier, bool send) { bool ret = false; @@ -176,25 +405,37 @@ buttons &= Qt::MouseButtonMask; if (receiver->isWidgetType()) { - QWidget* w = static_cast(receiver); + w = static_cast(receiver); pos = w->mapFromGlobal(gpos); } + QVarLengthArray mouseTypes; gestureTypeToMouseTypes(mouseTypes); for (int i = 0; i < mouseTypes.size(); i++) { QEvent::Type mtype = static_cast(mouseTypes[i]); - + + if (mtype == QEvent::None) { + continue; + } + else if (mtype != QEvent::MouseButtonRelease && w) { + QPoint wtl = w->mapToGlobal(w->pos()); + QRect wgeom = QRect(wtl, w->size()); + if (!wgeom.contains(m_pos)) { + continue; + } + } + if (mtype == QEvent::MouseButtonRelease) { buttons = 0; } if (send) { QMouseEvent evt(mtype, pos, gpos, Qt::LeftButton, buttons, modifier); - if (w) w->grabMouse(); + //if (w) w->grabMouse(); QApplication::sendEvent(receiver, &evt); - if (w) w->releaseMouse(); + //if (w) w->releaseMouse(); } else { QMouseEvent* evt = new QMouseEvent(mtype, pos, gpos, Qt::LeftButton, buttons, modifier); @@ -210,6 +451,13 @@ { QWidget* target = static_cast(m_target); QWidget* w = NULL; + QWidget* modal = QApplication::activeModalWidget(); + + + + if (modal) { + target = modal; + } if (target) { QPoint pos = target->mapFromGlobal(m_pos); @@ -220,26 +468,97 @@ } if (w) { - if (event->type() == QStm_GestureEvent::stmGestureEventType() && + if (modal) { //we send mouse events to modal dialogs. + return(sendMouseEvents(w)); + } + /* + else if (event->type() == QStm_GestureEvent::stmGestureEventType() && m_gstType == QStmUknownGestureType) { QStm_UiEventIf* uiEvent = static_cast(m_details); - QWidget* modal = QApplication::activeModalWidget(); + if (uiEvent && m_target == modal) { //re-generate mouse events - sendMouseEvents(w); + return(sendMouseEvents(w)); } - } + else { - QApplication::sendEvent(w, event); + return(QApplication::sendEvent(w, event)); + } + } + */ + else { + if (!target->hasFocus()) { + target->setFocus(Qt::MouseFocusReason); + } + return(QApplication::sendEvent(w, event)); } } + return false; +} + + +bool QStm_Gesture::sendGraphicsSceneMouseEvent(QGraphicsObject* go) +{ + QEvent::Type eventType = gestureType2GraphicsSceneMouseType(); + bool ret = false; + + if (eventType != QEvent::None) { + QGraphicsSceneMouseEvent gsme(eventType); + QPointF scenePos = qstmMapToScene(m_pos, go); + qstmSetGraphicsSceneMouseEvent(scenePos, go, gsme); + ret = go->event(&gsme); + } + return ret; } +QEvent::Type QStm_Gesture::gestureType2GraphicsSceneMouseType() +{ + QEvent::Type type = QEvent::None; + switch(m_gstType) + { + case QStmTouchGestureType: + type = QEvent::GraphicsSceneMousePress; + break; + case QStmMaybeTapGestureType: + case QStmReleaseGestureType: + case QStmFlickGestureType: + type = QEvent::GraphicsSceneMouseRelease; + break; + case QStmLeftRightGestureType: + case QStmUpDownGestureType: + case QStmPanGestureType: + type = QEvent::GraphicsSceneMouseMove; + break; + case QStmUknownGestureType: + { + QVarLengthArray mouseTypes; + gestureTypeToMouseTypes(mouseTypes); + switch (mouseTypes[0]) + { + case QEvent::MouseButtonPress: + type = QEvent::GraphicsSceneMousePress; + break; + case QEvent::MouseButtonRelease: + type = QEvent::GraphicsSceneMouseRelease; + break; + case QEvent::MouseMove: + type = QEvent::GraphicsSceneMouseMove; + break; + } + } + } + return type; +} + bool QStm_Gesture::sendMouseEvents(Qt::KeyboardModifier modifier) { - Q_ASSERT(m_target); QWidget* target = static_cast(m_target); + + if (!target) { + target = QApplication::widgetAt(m_pos); + } + if (!target) return false; QPoint pos = target->mapFromGlobal(m_pos); QWidget* w = target->childAt(pos); if (!w) { @@ -283,6 +602,160 @@ } +bool QStm_Gesture::isGestureEnded() +{ + bool gestureEnded = false; + + if (m_gstType == QStmUknownGestureType) { + QStm_UiEventIf* uiEvent = static_cast(m_details); + if (uiEvent) { + QEvent::Type evType = uiEvent->mapToMouseEventType(); + gestureEnded = (evType == ERelease); + } + } + else if (m_gstType == QStmReleaseGestureType || + m_gstType == QStmFlickGestureType || + m_gstType == QStmTapGestureType || + m_gstType == QStmDoubleTapGestureType) { + gestureEnded = true; + } + return gestureEnded; +} + +bool QStm_Gesture::clearGestureFocusedItemIfNeeded() +{ + bool reset = isGestureEnded(); + if (reset) { + QStm_Gesture::setGestureFocusedItem(NULL); + } + return reset; +} + +void QStm_Gesture::updateGestureFocusedItemIfNeeded(QGraphicsItem* gi) +{ + if (isGestureEnded()) { + QStm_Gesture::setGestureFocusedItem(NULL); + } + else if (gestureState() != Qt::GestureFinished) { + QStm_Gesture::setGestureFocusedItem(gi); + } +} + +QPointF QStm_Gesture::scenePosition(QGraphicsItem* i) +{ + return qstmMapToScene(m_pos, static_cast(i)); +} + +QPointF QStm_Gesture::scenePosition2(QGraphicsItem* i) +{ + return qstmMapToScene(m_pos2, static_cast(i)); +} + +QPointF QStm_Gesture::sceneSpeedVec(QGraphicsItem* i) +{ + QGraphicsObject* o = static_cast(i); + + return qstmMapToScene(m_speedVec,o) - qstmMapToScene(QPointF(0, 0), o); +} + +QPointF QStm_Gesture::sceneLengthAndDirection(QGraphicsItem* i) +{ + QGraphicsObject* o = static_cast(i); + + return qstmMapToScene(QPointF(-m_vector.x(), m_vector.y()),o) - qstmMapToScene(QPointF(0, 0), o); +} + +int QStm_Gesture::sceneDirection(QGraphicsItem *i) +{ + QStm_GestureDirection dir = ENorth ; + QPointF v = sceneLengthAndDirection(i); + + qreal x = qAbs(v.x()) ; + qreal y = qAbs(v.y()) ; + + if (y == 0 && x == 0) { + dir = ENoDirection; + } + else if (y <= x/2) { + if (v.x() < 0) + dir = EWest ; + else + dir = EEast ; + } + else if (y > x/2 && y <= (x+x/2)) { + if (v.x() < 0) { + if (v.y() < 0 ) + dir = ESouthWest ; + else + dir = ENorthWest ; + } + else { + if (v.y() < 0 ) + dir = ESouthEast ; + else + dir = ENorthEast ; + } + } + else if (y > x+x/2) { + if (v.y() < 0) + dir = ESouth ; + else + dir = ENorth ; + } + + return dir ; +} + +QSTMGESTURELIB_EXPORT QPoint qstmMapFromScene(const QPointF& gpos, QGraphicsObject* graphicsObj) +{ + QGraphicsView* grView = qstmGetGraphicsView(graphicsObj); + QPointF pos = QPointF(0.0, 0.0); + if (grView) { + pos = grView->mapFromScene(gpos); + return grView->mapToGlobal(pos.toPoint()); + } + return QPoint(0, 0); +} + + +QSTMGESTURELIB_EXPORT QPointF qstmMapToScene(const QPointF& gpos, QGraphicsObject* graphicsObj) +{ + QGraphicsView* grView = qstmGetGraphicsView(graphicsObj); + QPointF pos = QPointF(0.0, 0.0); + if (grView) { + pos = grView->mapFromGlobal(gpos.toPoint()); + pos = grView->mapToScene(pos.toPoint()); + } + return pos; +} + + +QSTMGESTURELIB_EXPORT QPointF qstmMapFromGlobal(const QPointF& gpos, QGraphicsObject* graphicsObj) +{ + QGraphicsView* grView = qstmGetGraphicsView(graphicsObj); + QPointF pos = QPointF(0.0, 0.0); + if (grView) { + pos = grView->mapFromGlobal(gpos.toPoint()); + } + return pos; +} + +QSTMGESTURELIB_EXPORT QGraphicsView* qstmGetGraphicsView(QGraphicsObject* graphicsObj) +{ + QGraphicsScene* scene = graphicsObj->scene(); + QList gvList = scene->views(); + QList::iterator it; + + /* + for (it = gvList.begin(); it != gvList.end(); it++) { + if (static_cast(*it)->hasFocus()) { + return static_cast(*it); + } + } + */ + return gvList.isEmpty() ? NULL : gvList[0]; +} + QSTMGESTURELIB_EXPORT QStm_Gesture* getQStmGesture(QEvent* event) { QStm_Gesture* gesture = NULL; @@ -297,3 +770,120 @@ return gesture; } +QSTMGESTURELIB_EXPORT bool qstmDeliverGestureEventToGraphicsItem(QGraphicsView* gv, QEvent* event) +{ + if (event->type() != QEvent::Gesture) return false; + + bool ret = false; + QStm_Gesture* gesture = getQStmGesture(event); + if (gesture) { + + QGraphicsScene* gs = gv->scene(); + QGraphicsItem* gestureGrabber = QStm_Gesture::gestureGrabberItem(); + QGraphicsItem* gi = QStm_Gesture::gestureFocusedItem(); + QGraphicsItem* mgItem = gs->mouseGrabberItem(); + + if (gestureGrabber) { + gs->sendEvent(gestureGrabber, event); + ret = true; //no fallback to mouse events + } + else { + if (!gi) { + gi = mgItem; + } + if (!gi) { + QPoint pos = gv->mapFromGlobal(gesture->position()); + pos = gv->mapToScene(pos).toPoint(); + QList itemsList = gs->items(pos, Qt::IntersectsItemShape, + Qt::DescendingOrder); + for(int i = 0; i < itemsList.size(); i++) { + + if (itemsList[i] && (itemsList[i])->opacity() < qreal(0.001)) { + continue; + } + gi = itemsList[i]; + gs->setFocusItem(gi, Qt::MouseFocusReason); + break; + } + } + if (gi) { + //gs->setFocusItem(gi, Qt::MouseFocusReason); + //ret = gs->sendEvent(gi, event); + //gs->setFocusItem(0, Qt::MouseFocusReason); + + QGraphicsObject* go = gi->toGraphicsObject(); + if (go) { + ret = go->event(event); + } + + } + } + + if (!ret) { // fallback to mouse events + QStm_GestureEventFilter::instance()->event(event); + ret = true; + } + else if (!gestureGrabber) { + gesture->updateGestureFocusedItemIfNeeded(gi); + } + } + return ret; +} + + +QSTMGESTURELIB_EXPORT void qstmSetGraphicsSceneMouseEvent(const QPointF& scenePos, QGraphicsObject* graphicsObj, + QGraphicsSceneMouseEvent& event, bool select) +{ + QPointF pos = scenePos; + QPoint gpos = qstmMapFromScene(pos, graphicsObj); + + event.setScenePos(pos); + event.setScreenPos(gpos); + event.setPos(graphicsObj->mapFromScene(pos)); + if (!select && event.type() != QEvent::GraphicsSceneMouseMove) { + event.setButton(Qt::LeftButton); + } + else { + event.setButton(Qt::NoButton); + } + if (!select) { + event.setButtons(Qt::NoButton); + } + else { + event.setButtons(Qt::LeftButton); + } + event.setModifiers(Qt::NoModifier); +} + +QSTMGESTURELIB_EXPORT bool qstmIsGraphicsSceneMouseEvent(QEvent* event) +{ + QEvent::Type type = event->type(); + return type == QEvent::GraphicsSceneMouseMove || + type == QEvent::GraphicsSceneMousePress || + type == QEvent::GraphicsSceneMouseRelease || + type == QEvent::GraphicsSceneMouseDoubleClick; +} + +QSTMGESTURELIB_EXPORT bool qstmIsMouseEvent(QEvent* event) +{ + QEvent::Type type = event->type(); + return type == QEvent::MouseButtonPress || + type == QEvent::MouseButtonRelease || + type == QEvent::MouseMove || + type == QEvent::MouseButtonDblClick; +} + +QSTMGESTURELIB_EXPORT bool qstmIsTouchEvent(QEvent* event) +{ + QEvent::Type type = event->type(); + return type == QEvent::TouchBegin || + type == QEvent::TouchEnd || + type == QEvent::TouchUpdate; +} + +QSTMGESTURELIB_EXPORT bool qstmIsContextMenuEvent(QEvent* event) +{ + QEvent::Type type = event->type(); + return type == QEvent::ContextMenu || + type == QEvent::GraphicsSceneContextMenu; +}