summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenis Dzyubenko <denis.dzyubenko@nokia.com>2009-11-18 12:27:24 (GMT)
committerDenis Dzyubenko <denis.dzyubenko@nokia.com>2009-11-18 15:15:49 (GMT)
commitc9ff28c5c56eaf5443921b937cf7c0270eaadd86 (patch)
tree99ee8c058948ee7aca56b09c76d7e0e292cf6d12
parent41e7781f76432ee821883505d68a89e0aadd56b1 (diff)
downloadQt-c9ff28c5c56eaf5443921b937cf7c0270eaadd86.zip
Qt-c9ff28c5c56eaf5443921b937cf7c0270eaadd86.tar.gz
Qt-c9ff28c5c56eaf5443921b937cf7c0270eaadd86.tar.bz2
Fixes in the multitouch handling.
When filling in touch point data for delivering to widget don't use the setter methods to avoid unnecessary detaches. Making it not detach also allows not to re-calculate widget-relative start position and last position on each delivery step. Also use the QWeakPointer to store a pointer to a widget that expects to receive a touch event, so that if the widget is destroyed we'll get notified. Reviewed-by: Bradley T. Hughes
-rw-r--r--src/gui/kernel/qapplication.cpp76
-rw-r--r--src/gui/kernel/qapplication_p.h2
-rw-r--r--src/gui/kernel/qevent.h3
-rw-r--r--src/gui/kernel/qmultitouch_mac.mm1
4 files changed, 52 insertions, 30 deletions
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp
index 4b8f6a0..4764a2d 100644
--- a/src/gui/kernel/qapplication.cpp
+++ b/src/gui/kernel/qapplication.cpp
@@ -4105,8 +4105,17 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
} else if (widget->isWindow() || widget->testAttribute(Qt::WA_NoMousePropagation)) {
break;
}
+ QPoint offset = widget->pos();
widget = widget->parentWidget();
- d->updateTouchPointsForWidget(widget, touchEvent);
+ touchEvent->setWidget(widget);
+ for (int i = 0; i < touchEvent->_touchPoints.size(); ++i) {
+ QTouchEvent::TouchPoint &pt = touchEvent->_touchPoints[i];
+ QRectF rect = pt.rect();
+ rect.moveCenter(offset);
+ pt.d->rect = rect;
+ pt.d->startPos = pt.startPos() + offset;
+ pt.d->lastPos = pt.lastPos() + offset;
+ }
}
touchEvent->setAccepted(eventAccepted);
@@ -5417,9 +5426,11 @@ void QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEven
const QPointF delta = screenPos - screenPos.toPoint();
rect.moveCenter(widget->mapFromGlobal(screenPos.toPoint()) + delta);
- touchPoint.setRect(rect);
- touchPoint.setStartPos(widget->mapFromGlobal(touchPoint.startScreenPos().toPoint()) + delta);
- touchPoint.setLastPos(widget->mapFromGlobal(touchPoint.lastScreenPos().toPoint()) + delta);
+ touchPoint.d->rect = rect;
+ if (touchPoint.state() == Qt::TouchPointPressed) {
+ touchPoint.d->startPos = widget->mapFromGlobal(touchPoint.startScreenPos().toPoint()) + delta;
+ touchPoint.d->lastPos = widget->mapFromGlobal(touchPoint.lastScreenPos().toPoint()) + delta;
+ }
}
}
@@ -5463,16 +5474,20 @@ void QApplicationPrivate::translateRawTouchEvent(QWidget *window,
for (int i = 0; i < touchPoints.count(); ++i) {
QTouchEvent::TouchPoint touchPoint = touchPoints.at(i);
+ // explicitly detach from the original touch point that we got, so even
+ // if the touchpoint structs are reused, we will make a copy that we'll
+ // deliver to the user (which might want to store the struct for later use).
+ touchPoint.d = touchPoint.d->detach();
// update state
- QWidget *widget = 0;
+ QWeakPointer<QWidget> widget;
switch (touchPoint.state()) {
case Qt::TouchPointPressed:
{
if (deviceType == QTouchEvent::TouchPad) {
// on touch-pads, send all touch points to the same widget
widget = d->widgetForTouchPointId.isEmpty()
- ? 0
+ ? QWeakPointer<QWidget>()
: d->widgetForTouchPointId.constBegin().value();
}
@@ -5489,20 +5504,21 @@ void QApplicationPrivate::translateRawTouchEvent(QWidget *window,
if (deviceType == QTouchEvent::TouchScreen) {
int closestTouchPointId = d->findClosestTouchPointId(touchPoint.screenPos());
- QWidget *closestWidget = d->widgetForTouchPointId.value(closestTouchPointId);
+ QWidget *closestWidget = d->widgetForTouchPointId.value(closestTouchPointId).data();
if (closestWidget
- && (widget->isAncestorOf(closestWidget) || closestWidget->isAncestorOf(widget))) {
+ && (widget.data()->isAncestorOf(closestWidget) || closestWidget->isAncestorOf(widget.data()))) {
widget = closestWidget;
}
}
d->widgetForTouchPointId[touchPoint.id()] = widget;
- touchPoint.setStartScreenPos(touchPoint.screenPos());
- touchPoint.setLastScreenPos(touchPoint.screenPos());
- touchPoint.setStartNormalizedPos(touchPoint.normalizedPos());
- touchPoint.setLastNormalizedPos(touchPoint.normalizedPos());
+ touchPoint.d->startScreenPos = touchPoint.screenPos();
+ touchPoint.d->lastScreenPos = touchPoint.screenPos();
+ touchPoint.d->startNormalizedPos = touchPoint.normalizedPos();
+ touchPoint.d->lastNormalizedPos = touchPoint.normalizedPos();
if (touchPoint.pressure() < qreal(0.))
- touchPoint.setPressure(qreal(1.));
+ touchPoint.d->pressure = qreal(1.);
+
d->appCurrentTouchPoints.insert(touchPoint.id(), touchPoint);
break;
}
@@ -5513,12 +5529,14 @@ void QApplicationPrivate::translateRawTouchEvent(QWidget *window,
continue;
QTouchEvent::TouchPoint previousTouchPoint = d->appCurrentTouchPoints.take(touchPoint.id());
- touchPoint.setStartScreenPos(previousTouchPoint.startScreenPos());
- touchPoint.setLastScreenPos(previousTouchPoint.screenPos());
- touchPoint.setStartNormalizedPos(previousTouchPoint.startNormalizedPos());
- touchPoint.setLastNormalizedPos(previousTouchPoint.normalizedPos());
+ touchPoint.d->startScreenPos = previousTouchPoint.startScreenPos();
+ touchPoint.d->lastScreenPos = previousTouchPoint.screenPos();
+ touchPoint.d->startPos = previousTouchPoint.startPos();
+ touchPoint.d->lastPos = previousTouchPoint.pos();
+ touchPoint.d->startNormalizedPos = previousTouchPoint.startNormalizedPos();
+ touchPoint.d->lastNormalizedPos = previousTouchPoint.normalizedPos();
if (touchPoint.pressure() < qreal(0.))
- touchPoint.setPressure(qreal(0.));
+ touchPoint.d->pressure = qreal(0.);
break;
}
default:
@@ -5528,23 +5546,25 @@ void QApplicationPrivate::translateRawTouchEvent(QWidget *window,
Q_ASSERT(d->appCurrentTouchPoints.contains(touchPoint.id()));
QTouchEvent::TouchPoint previousTouchPoint = d->appCurrentTouchPoints.value(touchPoint.id());
- touchPoint.setStartScreenPos(previousTouchPoint.startScreenPos());
- touchPoint.setLastScreenPos(previousTouchPoint.screenPos());
- touchPoint.setStartNormalizedPos(previousTouchPoint.startNormalizedPos());
- touchPoint.setLastNormalizedPos(previousTouchPoint.normalizedPos());
+ touchPoint.d->startScreenPos = previousTouchPoint.startScreenPos();
+ touchPoint.d->lastScreenPos = previousTouchPoint.screenPos();
+ touchPoint.d->startPos = previousTouchPoint.startPos();
+ touchPoint.d->lastPos = previousTouchPoint.pos();
+ touchPoint.d->startNormalizedPos = previousTouchPoint.startNormalizedPos();
+ touchPoint.d->lastNormalizedPos = previousTouchPoint.normalizedPos();
if (touchPoint.pressure() < qreal(0.))
- touchPoint.setPressure(qreal(1.));
+ touchPoint.d->pressure = qreal(1.);
d->appCurrentTouchPoints[touchPoint.id()] = touchPoint;
break;
}
- Q_ASSERT(widget != 0);
+ Q_ASSERT(widget.data() != 0);
// make the *scene* functions return the same as the *screen* functions
- touchPoint.setSceneRect(touchPoint.screenRect());
- touchPoint.setStartScenePos(touchPoint.startScreenPos());
- touchPoint.setLastScenePos(touchPoint.lastScreenPos());
+ touchPoint.d->sceneRect = touchPoint.screenRect();
+ touchPoint.d->startScenePos = touchPoint.startScreenPos();
+ touchPoint.d->lastScenePos = touchPoint.lastScreenPos();
- StatesAndTouchPoints &maskAndPoints = widgetsNeedingEvents[widget];
+ StatesAndTouchPoints &maskAndPoints = widgetsNeedingEvents[widget.data()];
maskAndPoints.first |= touchPoint.state();
if (touchPoint.isPrimary())
maskAndPoints.first |= Qt::TouchPointPrimary;
diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h
index 992e4be..14d7215 100644
--- a/src/gui/kernel/qapplication_p.h
+++ b/src/gui/kernel/qapplication_p.h
@@ -511,7 +511,7 @@ public:
QWidget *gestureWidget;
- QMap<int, QWidget *> widgetForTouchPointId;
+ QMap<int, QWeakPointer<QWidget> > widgetForTouchPointId;
QMap<int, QTouchEvent::TouchPoint> appCurrentTouchPoints;
static void updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent);
void initializeMultitouch();
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index 9839269..461cc92 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -787,6 +787,8 @@ public:
private:
QTouchEventTouchPointPrivate *d;
+ friend class QApplication;
+ friend class QApplicationPrivate;
};
enum DeviceType {
@@ -818,6 +820,7 @@ protected:
Qt::TouchPointStates _touchPointStates;
QList<QTouchEvent::TouchPoint> _touchPoints;
+ friend class QApplication;
friend class QApplicationPrivate;
};
diff --git a/src/gui/kernel/qmultitouch_mac.mm b/src/gui/kernel/qmultitouch_mac.mm
index 2f6f9ca..f736146 100644
--- a/src/gui/kernel/qmultitouch_mac.mm
+++ b/src/gui/kernel/qmultitouch_mac.mm
@@ -180,7 +180,6 @@ QCocoaTouch::getCurrentTouchPointList(NSEvent *event, bool acceptSingleTouch)
if (_touchCount != _currentTouches.size()) {
// Remove all instances, and basically start from scratch:
touchPoints.clear();
- QList<QCocoaTouch *> list = _currentTouches.values();
foreach (QCocoaTouch *qcocoaTouch, _currentTouches.values()) {
if (!_updateInternalStateOnly) {
qcocoaTouch->_touchPoint.setState(Qt::TouchPointReleased);