summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichal Klocek <michal.klocek@theqtcompany.com>2015-03-26 11:01:02 +0100
committerAlex Blasche <alexander.blasche@theqtcompany.com>2015-04-01 10:58:48 +0000
commit2d467627ea371af16ef39498b748fe1843d8d89a (patch)
tree761d049bf73bcf16aa00a0ed214f6ad98341c64d
parent31b85d235575c72274a57e894645720fe470ddc5 (diff)
Change mouse and touch handling in Map QML component.
Rewrite events handling in the map. This commit assumes, that first touch point is always synthesized to mouse event. Initial touch event is not handled, and map interaction is started by mouse event. This approach fits better for interaction with QML components, where mouse is primary way of control and simplifies mouse grabbing/ungrabbing. Moreover: * fixes issue, where grabbed synthesized mouse event is handled by top most element. * fixes correct value for previous zoomLevel in pinch update event. * fixes correct value for touch center in pinch end event. This commit on xcb platform depends on QTBUG-30417. Change-Id: Ic07dfa4bfaea20b4491135248abed44b25b2b950 Reviewed-by: Alex Blasche <alexander.blasche@theqtcompany.com>
-rw-r--r--src/imports/location/qdeclarativegeomap.cpp216
-rw-r--r--src/imports/location/qdeclarativegeomap_p.h6
-rw-r--r--src/imports/location/qdeclarativegeomapgesturearea.cpp282
-rw-r--r--src/imports/location/qdeclarativegeomapgesturearea_p.h31
-rw-r--r--tests/auto/declarative_ui/tst_map_mouse.qml5
5 files changed, 270 insertions, 270 deletions
diff --git a/src/imports/location/qdeclarativegeomap.cpp b/src/imports/location/qdeclarativegeomap.cpp
index ffd608fa..346f6487 100644
--- a/src/imports/location/qdeclarativegeomap.cpp
+++ b/src/imports/location/qdeclarativegeomap.cpp
@@ -43,6 +43,8 @@
#include <QtCore/QCoreApplication>
#include <QtCore/qnumeric.h>
#include <QThread>
+#include <QQuickWindow>
+#include <QtQuick/private/qquickwindow_p.h>
#include "qgeotilecache_p.h"
#include "qgeocameradata_p.h"
@@ -324,7 +326,10 @@ void QDeclarativeGeoMap::componentComplete()
*/
void QDeclarativeGeoMap::mousePressEvent(QMouseEvent *event)
{
- event->setAccepted(gestureArea_->handleMousePressEvent(event));
+ if (isInteractive())
+ gestureArea_->handleMousePressEvent(event);
+ else
+ QQuickItem::mousePressEvent(event);
}
/*!
@@ -332,7 +337,10 @@ void QDeclarativeGeoMap::mousePressEvent(QMouseEvent *event)
*/
void QDeclarativeGeoMap::mouseMoveEvent(QMouseEvent *event)
{
- event->setAccepted(gestureArea_->handleMouseMoveEvent(event));
+ if (isInteractive())
+ gestureArea_->handleMouseMoveEvent(event);
+ else
+ QQuickItem::mouseMoveEvent(event);
}
/*!
@@ -340,7 +348,12 @@ void QDeclarativeGeoMap::mouseMoveEvent(QMouseEvent *event)
*/
void QDeclarativeGeoMap::mouseReleaseEvent(QMouseEvent *event)
{
- event->setAccepted(gestureArea_->handleMouseReleaseEvent(event));
+ if (isInteractive()) {
+ gestureArea_->handleMouseReleaseEvent(event);
+ ungrabMouse();
+ } else {
+ QQuickItem::mouseReleaseEvent(event);
+ }
}
/*!
@@ -348,7 +361,18 @@ void QDeclarativeGeoMap::mouseReleaseEvent(QMouseEvent *event)
*/
void QDeclarativeGeoMap::mouseUngrabEvent()
{
- gestureArea_->handleMouseUngrabEvent();
+ if (isInteractive())
+ gestureArea_->handleMouseUngrabEvent();
+ else
+ QQuickItem::mouseUngrabEvent();
+}
+
+void QDeclarativeGeoMap::touchUngrabEvent()
+{
+ if (isInteractive())
+ gestureArea_->handleTouchUngrabEvent();
+ else
+ QQuickItem::touchUngrabEvent();
}
/*!
@@ -826,7 +850,15 @@ QGeoServiceProvider::Error QDeclarativeGeoMap::error() const
*/
void QDeclarativeGeoMap::touchEvent(QTouchEvent *event)
{
- event->setAccepted(gestureArea_->handleTouchEvent(event));
+ if (isInteractive()) {
+ gestureArea_->handleTouchEvent(event);
+ if ( event->type() == QEvent::TouchEnd ||
+ event->type() == QEvent::TouchCancel) {
+ ungrabTouchPoints();
+ }
+ }
+ //this will always ignore event so sythesized event is generated;
+ QQuickItem::touchEvent(event);
}
/*!
@@ -834,9 +866,18 @@ void QDeclarativeGeoMap::touchEvent(QTouchEvent *event)
*/
void QDeclarativeGeoMap::wheelEvent(QWheelEvent *event)
{
- event->setAccepted(gestureArea_->handleWheelEvent(event));
- //TODO: wheelAngleChanged wtf ?
- emit wheelAngleChanged(event->angleDelta());
+ if (isInteractive()) {
+ gestureArea_->handleWheelEvent(event);
+ //TODO: wheelAngleChanged wtf ? do we need that ?
+ emit wheelAngleChanged(event->angleDelta());
+ } else
+ QQuickItem::wheelEvent(event);
+
+}
+
+bool QDeclarativeGeoMap::isInteractive()
+{
+ return (gestureArea_->enabled() && gestureArea_->activeGestures()) || gestureArea_->isActive();
}
/*!
@@ -844,57 +885,43 @@ void QDeclarativeGeoMap::wheelEvent(QWheelEvent *event)
*/
bool QDeclarativeGeoMap::childMouseEventFilter(QQuickItem *item, QEvent *event)
{
- if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseMove ||
- event->type() == QEvent::MouseButtonRelease ||
- event->type() == QEvent::MouseButtonDblClick) {
- // Check if we have already grabbed input. This can happen if the previous touch event
- // immediately triggers a gesture, the synthesized mouse event is still generated. Filter
- // these events so that child items do no receive them.
- if (gestureArea_->hasGrabbedInput())
- return true;
+ Q_UNUSED(item)
+ if (!isVisible() || !isEnabled() || !isInteractive())
+ return QQuickItem::childMouseEventFilter(item, event);
- // Ignore synthesized mouse events, but don't filter them, as child items may not handle
- // touch events directly. After a gesture is recognized and an input grab obtained these
- // events should cease to be generated, except for the case above.
- QMouseEvent *me = static_cast<QMouseEvent *>(event);
- if (me->source() != Qt::MouseEventNotSynthesized)
- return false;
- } else if (event->type() == QEvent::TouchBegin || event->type() == QEvent::TouchUpdate ||
- event->type() == QEvent::TouchEnd) {
- // Check if already grabbed mouse, if so filter out touch events.
- // FIXME: Returning true here gives priority to touch input, which is not what is intended.
- // In response to returning true ungrabMouse() is called and touch input will be handled
- // thereafter.
- if (gestureArea_->hasGrabbedInput())
- return true;
- }
-
- QLOC_TRACE0;
switch (event->type()) {
case QEvent::MouseButtonPress:
case QEvent::MouseMove:
- if (item->keepMouseGrab())
- return false;
- return gestureArea_->filterMapChildMouseEvent(static_cast<QMouseEvent *>(event));
case QEvent::MouseButtonRelease:
- return gestureArea_->filterMapChildMouseEvent(static_cast<QMouseEvent *>(event));
- case QEvent::UngrabMouse:
- // Never filter ungrab mouse events. This event notifies 'item' that the mouse has been
- // grabbed and it should cancel any outstanding input event processing. For example, press
- // and hold timers.
- return false;
+ return sendMouseEvent(static_cast<QMouseEvent *>(event));
+ case QEvent::UngrabMouse: {
+ QQuickWindow *win = window();
+ if (!win) break;
+ if (!win->mouseGrabberItem() ||
+ (win->mouseGrabberItem() &&
+ win->mouseGrabberItem() != this)) {
+ // child lost grab, we could even lost
+ // some events if grab already belongs for example
+ // in item in diffrent window , clear up states
+ mouseUngrabEvent();
+ }
+ break;
+ }
case QEvent::TouchBegin:
case QEvent::TouchUpdate:
case QEvent::TouchEnd:
case QEvent::TouchCancel:
- if (item->keepMouseGrab())
- return false;
- return gestureArea_->filterMapChildTouchEvent(static_cast<QTouchEvent *>(event));
- case QEvent::Wheel:
- return gestureArea_->handleWheelEvent(static_cast<QWheelEvent *>(event));
+ if (static_cast<QTouchEvent *>(event)->touchPoints().count() >= 2) {
+ // 1 touch point = handle with MouseEvent (event is always synthesized)
+ // let the synthesized mouse event grab the mouse,
+ // note there is no mouse grabber at this point since
+ // touch event comes first (see Qt::AA_SynthesizeMouseForUnhandledTouchEvents)
+ return sendTouchEvent(static_cast<QTouchEvent *>(event));
+ }
default:
- return false;
+ break;
}
+ return QQuickItem::childMouseEventFilter(item, event);
}
/*!
@@ -1219,6 +1246,99 @@ void QDeclarativeGeoMap::fitViewportToMapItemsRefine(bool refine)
fitViewportToMapItemsRefine(false);
}
+bool QDeclarativeGeoMap::sendMouseEvent(QMouseEvent *event)
+{
+ QPointF localPos = mapFromScene(event->windowPos());
+ QQuickWindow *win = window();
+ QQuickItem *grabber = win ? win->mouseGrabberItem() : 0;
+ bool stealEvent = gestureArea_->isActive();
+
+ if ((stealEvent || contains(localPos)) && (!grabber || !grabber->keepMouseGrab())) {
+ QScopedPointer<QMouseEvent> mouseEvent(QQuickWindowPrivate::cloneMouseEvent(event, &localPos));
+ mouseEvent->setAccepted(false);
+
+ switch (mouseEvent->type()) {
+ case QEvent::MouseMove:
+ gestureArea_->handleMouseMoveEvent(mouseEvent.data());
+ break;
+ case QEvent::MouseButtonPress:
+ gestureArea_->handleMousePressEvent(mouseEvent.data());
+ break;
+ case QEvent::MouseButtonRelease:
+ gestureArea_->handleMouseReleaseEvent(mouseEvent.data());
+ break;
+ default:
+ break;
+ }
+
+ stealEvent = gestureArea_->isActive();
+ grabber = win ? win->mouseGrabberItem() : 0;
+
+ if (grabber && stealEvent && !grabber->keepMouseGrab() && grabber != this)
+ grabMouse();
+
+ if (stealEvent) {
+ //do not deliver
+ event->setAccepted(true);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ if (event->type() == QEvent::MouseButtonRelease) {
+ if (win && win->mouseGrabberItem() == this)
+ ungrabMouse();
+ }
+
+ return false;
+}
+
+bool QDeclarativeGeoMap::sendTouchEvent(QTouchEvent *event)
+{
+ QQuickWindowPrivate *win = window() ? QQuickWindowPrivate::get(window()) : 0;
+ const QTouchEvent::TouchPoint &point = event->touchPoints().first();
+ QQuickItem *grabber = win ? win->itemForTouchPointId.value(point.id()) : 0;
+
+ bool stealEvent = gestureArea_->isActive();
+ bool containsPoint = contains(mapFromScene(point.scenePos()));
+
+ if ((stealEvent || containsPoint) && (!grabber || !grabber->keepTouchGrab())) {
+ QScopedPointer<QTouchEvent> touchEvent(new QTouchEvent(event->type(), event->device(), event->modifiers(), event->touchPointStates(), event->touchPoints()));
+ touchEvent->setTimestamp(event->timestamp());
+ touchEvent->setAccepted(false);
+
+ gestureArea_->handleTouchEvent(touchEvent.data());
+ stealEvent = gestureArea_->isActive();
+ grabber = win ? win->itemForTouchPointId.value(point.id()) : 0;
+
+ if (grabber && stealEvent && !grabber->keepTouchGrab() && grabber != this) {
+ QVector<int> ids;
+ foreach (const QTouchEvent::TouchPoint &tp, event->touchPoints()) {
+ if (!(tp.state() & Qt::TouchPointReleased)) {
+ ids.append(tp.id());
+ }
+ }
+ grabTouchPoints(ids);
+ }
+
+ if (stealEvent) {
+ //do not deliver
+ event->setAccepted(true);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ if (event->type() == QEvent::TouchEnd) {
+ if (win && win->itemForTouchPointId.value(point.id()) == this) {
+ ungrabTouchPoints();
+ }
+ }
+ return false;
+}
+
#include "moc_qdeclarativegeomap_p.cpp"
QT_END_NAMESPACE
diff --git a/src/imports/location/qdeclarativegeomap_p.h b/src/imports/location/qdeclarativegeomap_p.h
index a24c3441..ed0c74dc 100644
--- a/src/imports/location/qdeclarativegeomap_p.h
+++ b/src/imports/location/qdeclarativegeomap_p.h
@@ -39,6 +39,7 @@
#include <QPointer>
#include <QTouchEvent>
+#include <QBasicTimer>
#include <QtQuick/QQuickItem>
#include <QtCore/QMutex>
@@ -164,11 +165,13 @@ protected:
void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE ;
void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE ;
void mouseUngrabEvent() Q_DECL_OVERRIDE ;
-
+ void touchUngrabEvent() Q_DECL_OVERRIDE;
void touchEvent(QTouchEvent *event) Q_DECL_OVERRIDE ;
void wheelEvent(QWheelEvent *event) Q_DECL_OVERRIDE ;
bool childMouseEventFilter(QQuickItem *item, QEvent *event) Q_DECL_OVERRIDE;
+ bool sendMouseEvent(QMouseEvent *event);
+ bool sendTouchEvent(QTouchEvent *event);
Q_SIGNALS:
void wheelAngleChanged(QPoint angleDelta);
@@ -197,6 +200,7 @@ private:
void setupMapView(QDeclarativeGeoMapItemView *view);
void populateMap();
void fitViewportToMapItemsRefine(bool refine);
+ bool isInteractive();
QDeclarativeGeoServiceProvider *plugin_;
QGeoServiceProvider *serviceProvider_;
diff --git a/src/imports/location/qdeclarativegeomapgesturearea.cpp b/src/imports/location/qdeclarativegeomapgesturearea.cpp
index b3251249..2f0a7b73 100644
--- a/src/imports/location/qdeclarativegeomapgesturearea.cpp
+++ b/src/imports/location/qdeclarativegeomapgesturearea.cpp
@@ -331,8 +331,6 @@ QDeclarativeGeoMapGestureArea::QDeclarativeGeoMapGestureArea(QDeclarativeGeoMap
: QObject(parent),
declarativeMap_(map),
enabled_(true),
- hasGrab_(false),
- activeInput_(NoInput),
activeGestures_(ZoomGesture | PanGesture | FlickGesture)
{
map_ = 0;
@@ -360,11 +358,6 @@ void QDeclarativeGeoMapGestureArea::setMap(QGeoMap *map)
map_, SLOT(cameraStopped()));
}
-bool QDeclarativeGeoMapGestureArea::hasGrabbedInput() const
-{
- return hasGrab_;
-}
-
QDeclarativeGeoMapGestureArea::~QDeclarativeGeoMapGestureArea()
{
}
@@ -551,74 +544,47 @@ void QDeclarativeGeoMapGestureArea::setFlickDeceleration(qreal deceleration)
/*!
\internal
*/
-QTouchEvent::TouchPoint makeTouchPointFromMouseEvent(QMouseEvent *event, Qt::TouchPointState state)
+QTouchEvent::TouchPoint* createTouchPointFromMouseEvent(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);
+ QTouchEvent::TouchPoint* newPoint = new QTouchEvent::TouchPoint();
+ newPoint->setPos(event->localPos());
+ newPoint->setScenePos(event->windowPos());
+ newPoint->setScreenPos(event->screenPos());
+ newPoint->setState(state);
+ newPoint->setId(0);
return newPoint;
}
/*!
\internal
*/
-bool QDeclarativeGeoMapGestureArea::handleMousePressEvent(QMouseEvent *event)
+void QDeclarativeGeoMapGestureArea::handleMousePressEvent(QMouseEvent *event)
{
- if (!(enabled_ && activeGestures_))
- return false;
-
- if (activeInput_ == TouchInput)
- return false;
-
- activeInput_ = MouseInput;
-
- touchPoints_.clear();
- touchPoints_ << makeTouchPointFromMouseEvent(event, Qt::TouchPointPressed);
-
- update();
- return true;
+ m_mousePoint.reset(createTouchPointFromMouseEvent(event, Qt::TouchPointPressed));
+ if (m_touchPoints.isEmpty()) update();
+ event->accept();
}
/*!
\internal
*/
-bool QDeclarativeGeoMapGestureArea::handleMouseMoveEvent(QMouseEvent *event)
+void QDeclarativeGeoMapGestureArea::handleMouseMoveEvent(QMouseEvent *event)
{
- if (!(enabled_ && activeGestures_))
- return false;
-
- if (activeInput_ != MouseInput)
- return false;
-
- touchPoints_.clear();
-
- touchPoints_ << makeTouchPointFromMouseEvent(event, Qt::TouchPointMoved);
- update();
- return true;
+ m_mousePoint.reset(createTouchPointFromMouseEvent(event, Qt::TouchPointMoved));
+ if (m_touchPoints.isEmpty()) update();
+ event->accept();
}
/*!
\internal
*/
-bool QDeclarativeGeoMapGestureArea::handleMouseReleaseEvent(QMouseEvent *)
+void QDeclarativeGeoMapGestureArea::handleMouseReleaseEvent(QMouseEvent *event)
{
- if (!(enabled_ && activeGestures_))
- return false;
-
- if (activeInput_ == TouchInput)
- return false;
-
- touchPoints_.clear();
- update();
-
- activeInput_ = NoInput;
-
- return true;
+ m_mousePoint.reset(createTouchPointFromMouseEvent(event, Qt::TouchPointReleased));
+ if (m_touchPoints.isEmpty()) update();
+ event->accept();
}
/*!
@@ -626,109 +592,34 @@ bool QDeclarativeGeoMapGestureArea::handleMouseReleaseEvent(QMouseEvent *)
*/
void QDeclarativeGeoMapGestureArea::handleMouseUngrabEvent()
{
- touchPoints_.clear();
- hasGrab_ = false;
- if (activeInput_ == MouseInput)
- activeInput_ = NoInput;
+ m_mousePoint.reset();
update();
}
/*!
\internal
*/
-bool QDeclarativeGeoMapGestureArea::handleTouchEvent(QTouchEvent *event)
-{
- if (!(enabled_ && activeGestures_))
- return false;
-
- if (activeInput_ == MouseInput)
- return false;
-
- switch (event->type()) {
- case QEvent::TouchBegin:
- case QEvent::TouchUpdate:
- activeInput_ = TouchInput;
- foreach (const QTouchEvent::TouchPoint &p, event->touchPoints()) {
- QList<QTouchEvent::TouchPoint>::iterator i;
- for (i = touchPoints_.begin(); i != touchPoints_.end(); ++i) {
- if (i->id() == p.id()) {
- i = touchPoints_.erase(i);
- break;
- }
- }
- switch (p.state()) {
- case Qt::TouchPointPressed:
- case Qt::TouchPointMoved:
- case Qt::TouchPointStationary:
- touchPoints_.insert(i, p);
- break;
- case Qt::TouchPointReleased:
- // already removed
- break;
- default:
- break;
- }
- }
- update();
- break;
- case QEvent::TouchEnd:
- case QEvent::TouchCancel:
- touchPoints_.clear();
- update();
- activeInput_ = NoInput;
- break;
- default:
- // no-op
- break;
- }
-
- return true;
-}
-
-bool QDeclarativeGeoMapGestureArea::handleWheelEvent(QWheelEvent *event)
+void QDeclarativeGeoMapGestureArea::handleTouchUngrabEvent()
{
- declarativeMap_->setZoomLevel(qBound(minimumZoomLevel(), declarativeMap_->zoomLevel() + event->angleDelta().y() * qreal(0.001), maximumZoomLevel()));
- return true;
+ m_touchPoints.clear();
+ update();
}
/*!
\internal
*/
-bool QDeclarativeGeoMapGestureArea::filterMapChildMouseEvent(QMouseEvent *event)
+void QDeclarativeGeoMapGestureArea::handleTouchEvent(QTouchEvent *event)
{
- if (!(enabled_ && activeGestures_))
- return false;
-
- // We have not grabbed the mouse yet. Process it but don't filter it so the child can use it
- // (until we grab it).
- switch (event->type()) {
- case QEvent::MouseButtonPress:
- handleMousePressEvent(event);
- break;
- case QEvent::MouseButtonRelease:
- handleMouseReleaseEvent(event);
- break;
- case QEvent::MouseMove:
- handleMouseMoveEvent(event);
- break;
- default:
- break;
- }
- return false;
+ m_touchPoints.clear();
+ for (int i = 0; i < event->touchPoints().count(); ++i)
+ m_touchPoints << event->touchPoints().at(i);
+ update();
}
-/*!
- \internal
-*/
-bool QDeclarativeGeoMapGestureArea::filterMapChildTouchEvent(QTouchEvent *event)
+void QDeclarativeGeoMapGestureArea::handleWheelEvent(QWheelEvent *event)
{
- if (!(enabled_ && activeGestures_))
- return false;
-
- // We have not grabbed the touch id associated with this touch event yet. Process it but don't
- // filter it so the child can use it (until we grab it).
- handleTouchEvent(event);
- return false;
+ declarativeMap_->setZoomLevel(qBound(minimumZoomLevel(), declarativeMap_->zoomLevel() + event->angleDelta().y() * qreal(0.001), maximumZoomLevel()));
+ event->accept();
}
/*!
@@ -772,11 +663,27 @@ void QDeclarativeGeoMapGestureArea::updateVelocityList(const QPointF &pos)
/*!
\internal
*/
+
+bool QDeclarativeGeoMapGestureArea::isActive() const
+{
+ return isPanActive() || isPinchActive();
+}
+
+/*!
+ \internal
+*/
// simplify the gestures by using a state-machine format (easy to move to a future state machine)
void QDeclarativeGeoMapGestureArea::update()
{
if (!map_) return;
// First state machine is for the number of touch points
+
+ //combine touch with mouse event
+ m_allPoints.clear();
+ m_allPoints << m_touchPoints;
+ if (m_allPoints.isEmpty() && !m_mousePoint.isNull())
+ m_allPoints << *m_mousePoint.data();
+
touchPointStateMachine();
// Parallel state machine for pinch
@@ -789,31 +696,6 @@ void QDeclarativeGeoMapGestureArea::update()
// the whole gesture (enabled_ flag), this keeps the enabled_ consistent with the pinch
if (isPanActive() || (enabled_ && pan_.enabled_ && (activeGestures_ & (PanGesture | FlickGesture))))
panStateMachine();
-
- if (pinchState_ != pinchInactive || panState_ == panActive) {
- if (!hasGrab_) {
- if (activeInput_ == MouseInput) {
- hasGrab_ = true;
- declarativeMap_->grabMouse();
- } else if (activeInput_ == TouchInput) {
- hasGrab_ = true;
- QVector<int> ids;
- foreach (const QTouchEvent::TouchPoint &tp, touchPoints_)
- ids.append(tp.id());
- declarativeMap_->grabTouchPoints(ids);
- }
- }
- } else {
- if (hasGrab_) {
- if (activeInput_ == MouseInput) {
- hasGrab_ = false;
- declarativeMap_->ungrabMouse();
- } else if (activeInput_ == TouchInput) {
- hasGrab_ = false;
- declarativeMap_->ungrabTouchPoints();
- }
- }
- }
}
/*!
@@ -824,29 +706,29 @@ void QDeclarativeGeoMapGestureArea::touchPointStateMachine()
// Transitions:
switch (touchPointState_) {
case touchPoints0:
- if (touchPoints_.count() == 1) {
+ if (m_allPoints.count() == 1) {
clearTouchData();
startOneTouchPoint();
touchPointState_ = touchPoints1;
- } else if (touchPoints_.count() >= 2) {
+ } else if (m_allPoints.count() >= 2) {
clearTouchData();
startTwoTouchPoints();
touchPointState_ = touchPoints2;
}
break;
case touchPoints1:
- if (touchPoints_.count() == 0) {
+ if (m_allPoints.count() == 0) {
touchPointState_ = touchPoints0;
- } else if (touchPoints_.count() == 2) {
+ } else if (m_allPoints.count() == 2) {
touchCenterCoord_ = map_->itemPositionToCoordinate(QDoubleVector2D(sceneCenter_), false);
startTwoTouchPoints();
touchPointState_ = touchPoints2;
}
break;
case touchPoints2:
- if (touchPoints_.count() == 0) {
+ if (m_allPoints.count() == 0) {
touchPointState_ = touchPoints0;
- } else if (touchPoints_.count() == 1) {
+ } else if (m_allPoints.count() == 1) {
touchCenterCoord_ = map_->itemPositionToCoordinate(QDoubleVector2D(sceneCenter_), false);
startOneTouchPoint();
touchPointState_ = touchPoints1;
@@ -872,7 +754,7 @@ void QDeclarativeGeoMapGestureArea::touchPointStateMachine()
*/
void QDeclarativeGeoMapGestureArea::startOneTouchPoint()
{
- sceneStartPoint1_ = declarativeMap_->mapFromScene(touchPoints_.at(0).scenePos());
+ sceneStartPoint1_ = declarativeMap_->mapFromScene(m_allPoints.at(0).scenePos());
lastPos_ = sceneStartPoint1_;
lastPosTime_.start();
QGeoCoordinate startCoord = map_->itemPositionToCoordinate(QDoubleVector2D(sceneStartPoint1_), false);
@@ -888,7 +770,7 @@ void QDeclarativeGeoMapGestureArea::startOneTouchPoint()
*/
void QDeclarativeGeoMapGestureArea::updateOneTouchPoint()
{
- sceneCenter_ = declarativeMap_->mapFromScene(touchPoints_.at(0).scenePos());
+ sceneCenter_ = declarativeMap_->mapFromScene(m_allPoints.at(0).scenePos());
updateVelocityList(sceneCenter_);
}
@@ -898,8 +780,8 @@ void QDeclarativeGeoMapGestureArea::updateOneTouchPoint()
*/
void QDeclarativeGeoMapGestureArea::startTwoTouchPoints()
{
- sceneStartPoint1_ = declarativeMap_->mapFromScene(touchPoints_.at(0).scenePos());
- sceneStartPoint2_ = declarativeMap_->mapFromScene(touchPoints_.at(1).scenePos());
+ sceneStartPoint1_ = declarativeMap_->mapFromScene(m_allPoints.at(0).scenePos());
+ sceneStartPoint2_ = declarativeMap_->mapFromScene(m_allPoints.at(1).scenePos());
QPointF startPos = (sceneStartPoint1_ + sceneStartPoint2_) * 0.5;
lastPos_ = startPos;
lastPosTime_.start();
@@ -915,13 +797,12 @@ void QDeclarativeGeoMapGestureArea::startTwoTouchPoints()
*/
void QDeclarativeGeoMapGestureArea::updateTwoTouchPoints()
{
- QPointF p1 = declarativeMap_->mapFromScene(touchPoints_.at(0).scenePos());
- QPointF p2 = declarativeMap_->mapFromScene(touchPoints_.at(1).scenePos());
+ QPointF p1 = declarativeMap_->mapFromScene(m_allPoints.at(0).scenePos());
+ QPointF p2 = declarativeMap_->mapFromScene(m_allPoints.at(1).scenePos());
qreal dx = p1.x() - p2.x();
qreal dy = p1.y() - p2.y();
distanceBetweenTouchPoints_ = sqrt(dx * dx + dy * dy);
sceneCenter_ = (p1 + p2) / 2;
-
updateVelocityList(sceneCenter_);
twoTouchAngle_ = QLineF(p1, p2).angle();
@@ -938,7 +819,7 @@ void QDeclarativeGeoMapGestureArea::pinchStateMachine()
// Transitions:
switch (pinchState_) {
case pinchInactive:
- if (touchPoints_.count() >= 2) {
+ if (m_allPoints.count() >= 2) {
if (canStartPinch()) {
startPinch();
pinchState_ = pinchActive;
@@ -948,7 +829,7 @@ void QDeclarativeGeoMapGestureArea::pinchStateMachine()
}
break;
case pinchInactiveTwoPoints:
- if (touchPoints_.count() <= 1) {
+ if (m_allPoints.count() <= 1) {
pinchState_ = pinchInactive;
} else {
if (canStartPinch()) {
@@ -958,7 +839,7 @@ void QDeclarativeGeoMapGestureArea::pinchStateMachine()
}
break;
case pinchActive:
- if (touchPoints_.count() <= 1) {
+ if (m_allPoints.count() <= 1) {
endPinch();
pinchState_ = pinchInactive;
}
@@ -989,9 +870,9 @@ bool QDeclarativeGeoMapGestureArea::canStartPinch()
{
const int startDragDistance = qApp->styleHints()->startDragDistance();
- if (touchPoints_.count() >= 2) {
- QPointF p1 = declarativeMap_->mapFromScene(touchPoints_.at(0).scenePos());
- QPointF p2 = declarativeMap_->mapFromScene(touchPoints_.at(1).scenePos());
+ if (m_allPoints.count() >= 2) {
+ QPointF p1 = declarativeMap_->mapFromScene(m_allPoints.at(0).scenePos());
+ QPointF p2 = declarativeMap_->mapFromScene(m_allPoints.at(1).scenePos());
if (qAbs(p1.x()-sceneStartPoint1_.x()) > startDragDistance
|| qAbs(p1.y()-sceneStartPoint1_.y()) > startDragDistance
|| qAbs(p2.x()-sceneStartPoint2_.x()) > startDragDistance
@@ -1000,7 +881,7 @@ bool QDeclarativeGeoMapGestureArea::canStartPinch()
pinch_.event.setAngle(twoTouchAngle_);
pinch_.event.setPoint1(p1);
pinch_.event.setPoint2(p2);
- pinch_.event.setPointCount(touchPoints_.count());
+ pinch_.event.setPointCount(m_allPoints.count());
pinch_.event.setAccepted(true);
emit pinchStarted(&pinch_.event);
return pinch_.event.accepted();
@@ -1015,11 +896,11 @@ bool QDeclarativeGeoMapGestureArea::canStartPinch()
void QDeclarativeGeoMapGestureArea::startPinch()
{
pinch_.startDist = distanceBetweenTouchPoints_;
- pinch_.zoom.previous = 1.0;
+ pinch_.zoom.previous = declarativeMap_->zoomLevel();
pinch_.lastAngle = twoTouchAngle_;
- pinch_.lastPoint1 = declarativeMap_->mapFromScene(touchPoints_.at(0).scenePos());
- pinch_.lastPoint2 = declarativeMap_->mapFromScene(touchPoints_.at(1).scenePos());
+ pinch_.lastPoint1 = declarativeMap_->mapFromScene(m_allPoints.at(0).scenePos());
+ pinch_.lastPoint2 = declarativeMap_->mapFromScene(m_allPoints.at(1).scenePos());
pinch_.zoom.start = declarativeMap_->zoomLevel();
}
@@ -1048,11 +929,11 @@ void QDeclarativeGeoMapGestureArea::updatePinch()
pinch_.event.setCenter(declarativeMap_->mapFromScene(sceneCenter_));
pinch_.event.setAngle(twoTouchAngle_);
- pinch_.lastPoint1 = declarativeMap_->mapFromScene(touchPoints_.at(0).scenePos());
- pinch_.lastPoint2 = declarativeMap_->mapFromScene(touchPoints_.at(1).scenePos());
+ pinch_.lastPoint1 = declarativeMap_->mapFromScene(m_allPoints.at(0).scenePos());
+ pinch_.lastPoint2 = declarativeMap_->mapFromScene(m_allPoints.at(1).scenePos());
pinch_.event.setPoint1(pinch_.lastPoint1);
pinch_.event.setPoint2(pinch_.lastPoint2);
- pinch_.event.setPointCount(touchPoints_.count());
+ pinch_.event.setPointCount(m_allPoints.count());
pinch_.event.setAccepted(true);
pinch_.lastAngle = twoTouchAngle_;
@@ -1064,6 +945,7 @@ void QDeclarativeGeoMapGestureArea::updatePinch()
qreal perPinchMaximumZoomLevel = qMin(pinch_.zoom.start + pinch_.zoom.maximumChange, pinch_.zoom.maximum);
newZoomLevel = qMin(qMax(perPinchMinimumZoomLevel, newZoomLevel), perPinchMaximumZoomLevel);
declarativeMap_->setZoomLevel(newZoomLevel);
+ pinch_.zoom.previous = newZoomLevel;
}
}
@@ -1072,11 +954,12 @@ void QDeclarativeGeoMapGestureArea::updatePinch()
*/
void QDeclarativeGeoMapGestureArea::endPinch()
{
- QPointF pinchCenter = declarativeMap_->mapFromScene(sceneCenter_);
- pinch_.event.setCenter(pinchCenter);
+ QPointF p1 = declarativeMap_->mapFromScene(pinch_.lastPoint1);
+ QPointF p2 = declarativeMap_->mapFromScene(pinch_.lastPoint2);
+ pinch_.event.setCenter((p1 + p2) / 2);
pinch_.event.setAngle(pinch_.lastAngle);
- pinch_.event.setPoint1(declarativeMap_->mapFromScene(pinch_.lastPoint1));
- pinch_.event.setPoint2(declarativeMap_->mapFromScene(pinch_.lastPoint2));
+ pinch_.event.setPoint1(p1);
+ pinch_.event.setPoint2(p2);
pinch_.event.setAccepted(true);
pinch_.event.setPointCount(0);
emit pinchFinished(&pinch_.event);
@@ -1102,7 +985,7 @@ void QDeclarativeGeoMapGestureArea::panStateMachine()
}
break;
case panActive:
- if (touchPoints_.count() == 0) {
+ if (m_allPoints.count() == 0) {
panState_ = panFlick;
if (!tryStartFlick())
{
@@ -1116,7 +999,7 @@ void QDeclarativeGeoMapGestureArea::panStateMachine()
}
break;
case panFlick:
- if (touchPoints_.count() > 0) { // re touched before movement ended
+ if (m_allPoints.count() > 0) { // re touched before movement ended
endFlick();
panState_ = panActive;
}
@@ -1145,13 +1028,13 @@ void QDeclarativeGeoMapGestureArea::panStateMachine()
*/
bool QDeclarativeGeoMapGestureArea::canStartPan()
{
- if (touchPoints_.count() == 0 || (activeGestures_ & PanGesture) == 0)
+ if (m_allPoints.count() == 0 || (activeGestures_ & PanGesture) == 0)
return false;
// Check if thresholds for normal panning are met.
// (normal panning vs flicking: flicking will start from mouse release event).
const int startDragDistance = qApp->styleHints()->startDragDistance();
- QPointF p1 = declarativeMap_->mapFromScene(touchPoints_.at(0).scenePos());
+ QPointF p1 = declarativeMap_->mapFromScene(m_allPoints.at(0).scenePos());
int dyFromPress = int(p1.y() - sceneStartPoint1_.y());
int dxFromPress = int(p1.x() - sceneStartPoint1_.x());
if ((qAbs(dyFromPress) > startDragDistance || qAbs(dxFromPress) > startDragDistance))
@@ -1272,7 +1155,6 @@ void QDeclarativeGeoMapGestureArea::endFlick()
-
#include "moc_qdeclarativegeomapgesturearea_p.cpp"
QT_END_NAMESPACE
diff --git a/src/imports/location/qdeclarativegeomapgesturearea_p.h b/src/imports/location/qdeclarativegeomapgesturearea_p.h
index e8347e01..2f959a50 100644
--- a/src/imports/location/qdeclarativegeomapgesturearea_p.h
+++ b/src/imports/location/qdeclarativegeomapgesturearea_p.h
@@ -52,6 +52,7 @@ class QTouchEvent;
class QWheelEvent;
class QGeoMap;
class QPropertyAnimation;
+class QQuickItem;
class QDeclarativeGeoMapPinchEvent : public QObject
{
@@ -133,6 +134,7 @@ public:
bool isPinchActive() const;
bool isPanActive() const;
+ bool isActive() const;
bool enabled() const;
void setEnabled(bool enabled);
@@ -149,15 +151,13 @@ public:
qreal flickDeceleration() const;
void setFlickDeceleration(qreal deceleration);
- bool handleTouchEvent(QTouchEvent *event);
- bool handleWheelEvent(QWheelEvent *event);
- bool handleMousePressEvent(QMouseEvent *event);
- bool handleMouseMoveEvent(QMouseEvent *event);
- bool handleMouseReleaseEvent(QMouseEvent *event);
+ void handleTouchEvent(QTouchEvent *event);
+ void handleWheelEvent(QWheelEvent *event);
+ void handleMousePressEvent(QMouseEvent *event);
+ void handleMouseMoveEvent(QMouseEvent *event);
+ void handleMouseReleaseEvent(QMouseEvent *event);
void handleMouseUngrabEvent();
-
- bool filterMapChildMouseEvent(QMouseEvent *event);
- bool filterMapChildTouchEvent(QTouchEvent *event);
+ void handleTouchUngrabEvent();
void setMinimumZoomLevel(qreal min);
qreal minimumZoomLevel() const;
@@ -167,8 +167,6 @@ public:
void setMap(QGeoMap *map);
- bool hasGrabbedInput() const;
-
Q_SIGNALS:
void panActiveChanged();
void pinchActiveChanged();
@@ -226,15 +224,6 @@ private:
QGeoMap *map_;
QDeclarativeGeoMap *declarativeMap_;
bool enabled_;
- bool hasGrab_;
-
- enum InputType
- {
- NoInput,
- MouseInput,
- TouchInput
- };
- InputType activeInput_;
struct Pinch
{
@@ -274,7 +263,9 @@ private:
qreal velocityY_;
QElapsedTimer lastPosTime_;
QPointF lastPos_;
- QList<QTouchEvent::TouchPoint> touchPoints_;
+ QList<QTouchEvent::TouchPoint> m_allPoints;
+ QList<QTouchEvent::TouchPoint> m_touchPoints;
+ QScopedPointer<QTouchEvent::TouchPoint> m_mousePoint;
QPointF sceneStartPoint1_;
// only set when two points in contact
diff --git a/tests/auto/declarative_ui/tst_map_mouse.qml b/tests/auto/declarative_ui/tst_map_mouse.qml
index 0c6ddb14..c49c2c1a 100644
--- a/tests/auto/declarative_ui/tst_map_mouse.qml
+++ b/tests/auto/declarative_ui/tst_map_mouse.qml
@@ -535,6 +535,8 @@ Item {
compare(mouseLowerPressedSpy.count, 1)
compare(mouseLowerReleasedSpy.count, 1)
+
+ compare(mouseOverlapperPressedSpy.count, 0)
mousePress(map, 55, 75)
compare(mouseUpperPressedSpy.count, 2)
compare(mouseLowerPressedSpy.count, 1)
@@ -545,7 +547,8 @@ Item {
compare(mouseUpperReleasedSpy.count, 2)
compare(mouseLowerPressedSpy.count, 1)
compare(mouseLowerReleasedSpy.count, 1)
- compare(mouseOverlapperReleasedSpy.count, 1)
+ //this should follow the same logic as Flickable
+ compare(mouseOverlapperReleasedSpy.count, 0)
}
function test_basic_click() {