summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Moe Gustavsen <richard.gustavsen@nokia.com>2009-06-22 11:20:03 (GMT)
committerRichard Moe Gustavsen <richard.gustavsen@nokia.com>2009-06-22 11:29:05 (GMT)
commit627a3b8928157bb7f25af406f61a2f9c5cb41e06 (patch)
tree6a352342fc1f8a9fe68329a87175cdc4f1ccede8
parentcb9852297373b8bdf462ea097e639b7dee11b972 (diff)
downloadQt-627a3b8928157bb7f25af406f61a2f9c5cb41e06.zip
Qt-627a3b8928157bb7f25af406f61a2f9c5cb41e06.tar.gz
Qt-627a3b8928157bb7f25af406f61a2f9c5cb41e06.tar.bz2
Multitouch, Cocoa: Mask mouse hover from the touch set
After a lot of thinking, the conclusion is that we really need to to this. Lets see if we can add a flag to control it next.
-rw-r--r--src/gui/kernel/qcocoaview_mac.mm18
-rw-r--r--src/gui/kernel/qmultitouch_mac.mm140
-rw-r--r--src/gui/kernel/qmultitouch_mac_p.h10
3 files changed, 88 insertions, 80 deletions
diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm
index 9aa4dd2..e8e52f9 100644
--- a/src/gui/kernel/qcocoaview_mac.mm
+++ b/src/gui/kernel/qcocoaview_mac.mm
@@ -704,11 +704,6 @@ extern "C" {
- (void)mouseUp:(NSEvent *)theEvent
{
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6)
- QCocoaTouch::setMouseInDraggingState(false);
-#endif
-
bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseButtonRelease, Qt::LeftButton);
if (!mouseOK)
@@ -752,11 +747,6 @@ extern "C" {
- (void)mouseDragged:(NSEvent *)theEvent
{
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6)
- QCocoaTouch::setMouseInDraggingState(true);
-#endif
-
qMacDnDParams()->view = self;
qMacDnDParams()->theEvent = theEvent;
bool mouseOK = qt_mac_handleMouseEvent(self, theEvent, QEvent::MouseMove, Qt::LeftButton);
@@ -883,22 +873,22 @@ extern "C" {
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
- (void)touchesBeganWithEvent:(NSEvent *)event;
{
- qt_translateRawTouchEvent(QCocoaTouch::getCurrentTouchPointList(event), qwidget);
+ qt_translateRawTouchEvent(QCocoaTouch::getCurrentTouchPointList(event, true), qwidget);
}
- (void)touchesMovedWithEvent:(NSEvent *)event;
{
- qt_translateRawTouchEvent(QCocoaTouch::getCurrentTouchPointList(event), qwidget);
+ qt_translateRawTouchEvent(QCocoaTouch::getCurrentTouchPointList(event, true), qwidget);
}
- (void)touchesEndedWithEvent:(NSEvent *)event;
{
- qt_translateRawTouchEvent(QCocoaTouch::getCurrentTouchPointList(event), qwidget);
+ qt_translateRawTouchEvent(QCocoaTouch::getCurrentTouchPointList(event, true), qwidget);
}
- (void)touchesCancelledWithEvent:(NSEvent *)event;
{
- qt_translateRawTouchEvent(QCocoaTouch::getCurrentTouchPointList(event), qwidget);
+ qt_translateRawTouchEvent(QCocoaTouch::getCurrentTouchPointList(event, true), qwidget);
}
- (void)magnifyWithEvent:(NSEvent *)event;
diff --git a/src/gui/kernel/qmultitouch_mac.mm b/src/gui/kernel/qmultitouch_mac.mm
index 89cfc24..0f43299 100644
--- a/src/gui/kernel/qmultitouch_mac.mm
+++ b/src/gui/kernel/qmultitouch_mac.mm
@@ -39,11 +39,11 @@
**
****************************************************************************/
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
-
#include <private/qmultitouch_mac_p.h>
#include <qcursor.h>
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+
QT_BEGIN_NAMESPACE
#ifdef QT_MAC_USE_COCOA
@@ -51,33 +51,28 @@ QT_BEGIN_NAMESPACE
QHash<int, QCocoaTouch*> QCocoaTouch::_currentTouches;
QPointF QCocoaTouch::_screenReferencePos;
QPointF QCocoaTouch::_trackpadReferencePos;
-bool QCocoaTouch::_inMouseDraggingState = false;
int QCocoaTouch::_idAssignmentCount = 0;
+int QCocoaTouch::_touchCount = 0;
+bool QCocoaTouch::_maskMouseHover = true;
QCocoaTouch::QCocoaTouch(NSTouch *nstouch)
{
+ // Keep the identity that Cocoa assigns the
+ // touches, and use it as key in the touch hash:
_identity = int([nstouch identity]);
if (_currentTouches.size() == 0){
- // A new touch sequence is about to begin:
- _touchPoint.setState(Qt::TouchPointPressed | Qt::TouchPointPrimary);
- NSPoint npos = [nstouch normalizedPosition];
- _trackpadPos = QPointF(npos.x, npos.y);
- // This touch will act as reference for all subsequent
- // touches, so they appear next to each other on screen:
- _trackpadReferencePos = _trackpadPos;
- _screenReferencePos = QCursor::pos();
- _touchPoint.setScreenPos(_screenReferencePos);
- // The first touch should always have 0 as id:
+ // The first touch should always have
+ // 0 as id that we use in Qt:
_touchPoint.setId(0);
_idAssignmentCount = 0;
- _currentTouches.insert(_identity, this);
} else {
- // We are already tracking at least one touch point.
_touchPoint.setId(++_idAssignmentCount);
- _currentTouches.insert(_identity, this);
- updateTouchData(nstouch, NSTouchPhaseBegan);
}
+
+ _touchPoint.setPressure(1.0);
+ _currentTouches.insert(_identity, this);
+ updateTouchData(nstouch, NSTouchPhaseBegan);
}
QCocoaTouch::~QCocoaTouch()
@@ -87,10 +82,7 @@ QCocoaTouch::~QCocoaTouch()
void QCocoaTouch::updateTouchData(NSTouch *nstouch, NSTouchPhase phase)
{
- NSPoint npos = [nstouch normalizedPosition];
- _trackpadPos = QPointF(npos.x, npos.y);
-
- if (_inMouseDraggingState || _currentTouches.size() == 1)
+ if (_touchCount == 1)
_touchPoint.setState(toTouchPointState(phase) | Qt::TouchPointPrimary);
else
_touchPoint.setState(toTouchPointState(phase));
@@ -98,6 +90,14 @@ void QCocoaTouch::updateTouchData(NSTouch *nstouch, NSTouchPhase phase)
// From the normalized position on the trackpad, calculate
// where on screen the touchpoint should be according to the
// reference position:
+ NSPoint npos = [nstouch normalizedPosition];
+ _trackpadPos = QPointF(npos.x, npos.y);
+
+ if (_touchPoint.id() == 0 && phase == NSTouchPhaseBegan) {
+ _trackpadReferencePos = _trackpadPos;
+ _screenReferencePos = QCursor::pos();
+ }
+
NSSize dsize = [nstouch deviceSize];
float ppiX = (_trackpadPos.x() - _trackpadReferencePos.x()) * dsize.width;
float ppiY = (_trackpadPos.y() - _trackpadReferencePos.y()) * dsize.height;
@@ -136,65 +136,83 @@ Qt::TouchPointState QCocoaTouch::toTouchPointState(NSTouchPhase nsState)
return qtState;
}
-void QCocoaTouch::setMouseInDraggingState(bool inDraggingState)
-{
- // In mouse dragging state, _all_ fingers control the mouse.
- // As such, all fingers should have the primary flag.
- _inMouseDraggingState = inDraggingState;
-}
-
-void QCocoaTouch::validateCurrentTouchList(NSEvent *event)
-{
- // If the application shows the task switcher during a touch sequence
- // we get into an inconsistant state. We try to detect that here:
- NSTouchPhase p = NSTouchPhaseAny & ~NSTouchPhaseBegan;
- NSSet *s = [event touchesMatchingPhase:p inView:nil];
- if ([s count] == 0 && !_currentTouches.isEmpty()) {
- // Remove all instances, and basically start from scratch:
- QList<QCocoaTouch *> list = _currentTouches.values();
- foreach (QCocoaTouch *t, _currentTouches.values())
- delete t;
- _currentTouches.clear();
- }
-}
-
-QList<QTouchEvent::TouchPoint> QCocoaTouch::getCurrentTouchPointList(NSEvent *event)
+QList<QTouchEvent::TouchPoint> QCocoaTouch::getCurrentTouchPointList(NSEvent *event, bool maskMouseHover)
{
- validateCurrentTouchList(event);
- // Go through all the touchpoints in cocoa, find, or create, a QCocoaTouch for
- // them, update them, and return the result:
QList<QTouchEvent::TouchPoint> touchPoints;
-
NSSet *ended = [event touchesMatchingPhase:NSTouchPhaseEnded | NSTouchPhaseCancelled inView:nil];
+ NSSet *active = [event
+ touchesMatchingPhase:NSTouchPhaseBegan | NSTouchPhaseMoved | NSTouchPhaseStationary
+ inView:nil];
+ _touchCount = [active count];
+
+ // First: remove touches that were ended by the user. If we are
+ // currently masking the mouse hover touch, a corresponding 'begin'
+ // has never been posted to the app. So we should not send
+ // the following remove either.
+
for (int i=0; i<int([ended count]); ++i) {
NSTouch *touch = [[ended allObjects] objectAtIndex:i];
QCocoaTouch *qcocoaTouch = findQCocoaTouch(touch);
if (qcocoaTouch) {
qcocoaTouch->updateTouchData(touch, [touch phase]);
- touchPoints.append(qcocoaTouch->_touchPoint);
+ if (!_maskMouseHover)
+ touchPoints.append(qcocoaTouch->_touchPoint);
delete qcocoaTouch;
}
}
- NSSet *began = [event touchesMatchingPhase:NSTouchPhaseBegan inView:nil];
- for (int i=0; i<int([began count]); ++i) {
- NSTouch *touch = [[began allObjects] objectAtIndex:i];
+ bool wasMaskingMouseHover = _maskMouseHover;
+ _maskMouseHover = maskMouseHover && _touchCount < 2;
+
+ // Next: update, or create, existing touches.
+ // We always keep track of all touch points, even
+ // when masking the mouse hover touch:
+
+ for (int i=0; i<int([active count]); ++i) {
+ NSTouch *touch = [[active allObjects] objectAtIndex:i];
QCocoaTouch *qcocoaTouch = findQCocoaTouch(touch);
if (!qcocoaTouch)
qcocoaTouch = new QCocoaTouch(touch);
else
- qcocoaTouch->updateTouchData(touch, [touch phase]);
- touchPoints.append(qcocoaTouch->_touchPoint);
+ qcocoaTouch->updateTouchData(touch, wasMaskingMouseHover ? NSTouchPhaseBegan : [touch phase]);
+ if (!_maskMouseHover)
+ touchPoints.append(qcocoaTouch->_touchPoint);
}
- NSSet *active = [event touchesMatchingPhase:NSTouchPhaseMoved | NSTouchPhaseStationary inView:nil];
- for (int i=0; i<int([active count]); ++i) {
- NSTouch *touch = [[active allObjects] objectAtIndex:i];
- QCocoaTouch *qcocoaTouch = findQCocoaTouch(touch);
- if (qcocoaTouch) {
- qcocoaTouch->updateTouchData(touch, [touch phase]);
- touchPoints.append(qcocoaTouch->_touchPoint);
+ // Next: sadly, we need to check that our touch hash is in
+ // sync with cocoa. This is typically not the case after a system
+ // gesture happend (like a four-finger-swipe to show expose).
+
+ 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 (!_maskMouseHover) {
+ qcocoaTouch->_touchPoint.setState(Qt::TouchPointReleased);
+ touchPoints.append(qcocoaTouch->_touchPoint);
+ }
+ delete qcocoaTouch;
}
+ _currentTouches.clear();
+ _maskMouseHover = maskMouseHover;
+ return touchPoints;
+ }
+
+ // Finally: If we in this call _started_ to mask the mouse
+ // hover touch, we need to fake a relase for it now (and refake
+ // a begin for it later, if needed).
+
+ if (_maskMouseHover && !wasMaskingMouseHover && !_currentTouches.isEmpty()) {
+ // If one touch is still active, fake a release event for it.
+ QCocoaTouch *qcocoaTouch = _currentTouches.values().first();
+ qcocoaTouch->_touchPoint.setState(Qt::TouchPointReleased);
+ touchPoints.append(qcocoaTouch->_touchPoint);
+ // Since this last touch also will end up beeing the first
+ // touch (if the user adds a second finger without lifting
+ // the first), we promote it to be the primary touch:
+ qcocoaTouch->_touchPoint.setId(0);
+ _idAssignmentCount = 0;
}
return touchPoints;
diff --git a/src/gui/kernel/qmultitouch_mac_p.h b/src/gui/kernel/qmultitouch_mac_p.h
index 92ed11a..9ec256a 100644
--- a/src/gui/kernel/qmultitouch_mac_p.h
+++ b/src/gui/kernel/qmultitouch_mac_p.h
@@ -53,8 +53,6 @@
#ifndef QMULTITOUCH_MAC_P_H
#define QMULTITOUCH_MAC_P_H
-#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
-
#ifdef QT_MAC_USE_COCOA
#import <Cocoa/Cocoa.h>
#endif
@@ -63,6 +61,8 @@
#include <qhash.h>
#include <QtCore>
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+
QT_BEGIN_NAMESPACE
#ifdef QT_MAC_USE_COCOA
@@ -70,15 +70,16 @@ QT_BEGIN_NAMESPACE
class QCocoaTouch
{
public:
- static QList<QTouchEvent::TouchPoint> getCurrentTouchPointList(NSEvent *event);
+ static QList<QTouchEvent::TouchPoint> getCurrentTouchPointList(NSEvent *event, bool maskMouseHover);
static void setMouseInDraggingState(bool inDraggingState);
private:
static QHash<int, QCocoaTouch*> _currentTouches;
static QPointF _screenReferencePos;
static QPointF _trackpadReferencePos;
- static bool _inMouseDraggingState;
static int _idAssignmentCount;
+ static int _touchCount;
+ static bool _maskMouseHover;
QTouchEvent::TouchPoint _touchPoint;
QPointF _trackpadPos;
@@ -90,7 +91,6 @@ class QCocoaTouch
void updateTouchData(NSTouch *nstouch, NSTouchPhase phase);
static QCocoaTouch *findQCocoaTouch(NSTouch *nstouch);
static Qt::TouchPointState toTouchPointState(NSTouchPhase nsState);
- static void validateCurrentTouchList(NSEvent *event);
};
#endif // QT_MAC_USE_COCOA