diff options
author | Richard Moe Gustavsen <richard.gustavsen@nokia.com> | 2009-10-12 12:11:44 (GMT) |
---|---|---|
committer | Richard Moe Gustavsen <richard.gustavsen@nokia.com> | 2009-10-13 12:15:35 (GMT) |
commit | b6b6da647132f7fdf78d0601cbf7b411fda474f0 (patch) | |
tree | 42c6eddc023420111a4c080ad94d77172e24567a | |
parent | 8d9acba3ecac466fa86201e4eb760af1ccea68e3 (diff) | |
download | Qt-b6b6da647132f7fdf78d0601cbf7b411fda474f0.zip Qt-b6b6da647132f7fdf78d0601cbf7b411fda474f0.tar.gz Qt-b6b6da647132f7fdf78d0601cbf7b411fda474f0.tar.bz2 |
Mac: implement gestures conforming to the new API
-rw-r--r-- | examples/gestures/imageviewer/imagewidget.cpp | 8 | ||||
-rw-r--r-- | src/gui/kernel/kernel.pri | 4 | ||||
-rw-r--r-- | src/gui/kernel/qgesture.cpp | 26 | ||||
-rw-r--r-- | src/gui/kernel/qgesture.h | 6 | ||||
-rw-r--r-- | src/gui/kernel/qgesturemanager.cpp | 12 | ||||
-rw-r--r-- | src/gui/kernel/qmacgesturerecognizer_mac.mm | 258 | ||||
-rw-r--r-- | src/gui/kernel/qmacgesturerecognizer_mac_p.h | 103 |
7 files changed, 396 insertions, 21 deletions
diff --git a/examples/gestures/imageviewer/imagewidget.cpp b/examples/gestures/imageviewer/imagewidget.cpp index b8bb7b5..f3fd8e4 100644 --- a/examples/gestures/imageviewer/imagewidget.cpp +++ b/examples/gestures/imageviewer/imagewidget.cpp @@ -104,10 +104,10 @@ bool ImageWidget::gestureEvent(QGestureEvent *event) panTriggered(static_cast<QPanGesture*>(pan)); return true; } else if (QGesture *pinch = event->gesture(Qt::PinchGesture)) { - pinchTriggered(static_cast<QPinchGesture*>(pan)); + pinchTriggered(static_cast<QPinchGesture*>(pinch)); return true; } else if (QGesture *swipe = event->gesture(Qt::SwipeGesture)) { - swipeTriggered(static_cast<QSwipeGesture*>(pan)); + swipeTriggered(static_cast<QSwipeGesture*>(swipe)); return true; } return false; @@ -125,7 +125,7 @@ void ImageWidget::panTriggered(QPanGesture *gesture) setCursor(Qt::ArrowCursor); } #endif - QSizeF lastOffset = gesture->property("lastOffset").toSizeF(); + QSizeF lastOffset = gesture->offset(); horizontalOffset += lastOffset.width(); verticalOffset += lastOffset.height(); update(); @@ -133,7 +133,7 @@ void ImageWidget::panTriggered(QPanGesture *gesture) void ImageWidget::pinchTriggered(QPinchGesture *gesture) { - QPinchGesture::WhatChanged whatChanged = gesture->property("whatChanged").value<QPinchGesture::WhatChanged>(); + QPinchGesture::WhatChanged whatChanged = gesture->whatChanged(); if (whatChanged & QPinchGesture::RotationAngleChanged) { qreal value = gesture->property("rotationAngle").toReal(); qreal lastValue = gesture->property("lastRotationAngle").toReal(); diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index 88c1f73..53c2611 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -205,6 +205,7 @@ embedded { qcocoaview_mac_p.h \ qcocoaapplication_mac_p.h \ qcocoaapplicationdelegate_mac_p.h \ + qmacgesturerecognizer_mac_p.h \ qmultitouch_mac_p.h OBJECTIVE_SOURCES += \ @@ -224,7 +225,8 @@ embedded { kernel/qdesktopwidget_mac.mm \ kernel/qeventdispatcher_mac.mm \ kernel/qcocoawindowcustomthemeframe_mac.mm \ - kernel/qmultitouch_mac.mm \ + kernel/qmacgesturerecognizer_mac.mm \ + kernel/qmultitouch_mac.mm HEADERS += \ kernel/qt_cocoa_helpers_mac_p.h \ diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp index 7b2cd6d..3639a45 100644 --- a/src/gui/kernel/qgesture.cpp +++ b/src/gui/kernel/qgesture.cpp @@ -335,22 +335,24 @@ QSwipeGesture::QSwipeGesture(QObject *parent) QSwipeGesture::SwipeDirection QSwipeGesture::horizontalDirection() const { - return d_func()->horizontalDirection; + Q_D(const QSwipeGesture); + if (d->swipeAngle < 0 || d->swipeAngle == 90 || d->swipeAngle == 270) + return QSwipeGesture::NoDirection; + else if (d->swipeAngle < 90 || d->swipeAngle > 270) + return QSwipeGesture::Right; + else + return QSwipeGesture::Left; } QSwipeGesture::SwipeDirection QSwipeGesture::verticalDirection() const { - return d_func()->verticalDirection; -} - -void QSwipeGesture::setHorizontalDirection(QSwipeGesture::SwipeDirection value) -{ - d_func()->horizontalDirection = value; -} - -void QSwipeGesture::setVerticalDirection(QSwipeGesture::SwipeDirection value) -{ - d_func()->verticalDirection = value; + Q_D(const QSwipeGesture); + if (d->swipeAngle <= 0 || d->swipeAngle == 180) + return QSwipeGesture::NoDirection; + else if (d->swipeAngle < 180) + return QSwipeGesture::Up; + else + return QSwipeGesture::Down; } qreal QSwipeGesture::swipeAngle() const diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h index bf72759..0034819 100644 --- a/src/gui/kernel/qgesture.h +++ b/src/gui/kernel/qgesture.h @@ -189,8 +189,8 @@ class Q_GUI_EXPORT QSwipeGesture : public QGesture Q_DECLARE_PRIVATE(QSwipeGesture) Q_ENUMS(SwipeDirection) - Q_PROPERTY(SwipeDirection horizontalDirection READ horizontalDirection WRITE setHorizontalDirection) - Q_PROPERTY(SwipeDirection verticalDirection READ verticalDirection WRITE setVerticalDirection) + Q_PROPERTY(SwipeDirection horizontalDirection READ horizontalDirection STORED false) + Q_PROPERTY(SwipeDirection verticalDirection READ verticalDirection STORED false) Q_PROPERTY(qreal swipeAngle READ swipeAngle WRITE setSwipeAngle) public: @@ -199,8 +199,6 @@ public: SwipeDirection horizontalDirection() const; SwipeDirection verticalDirection() const; - void setHorizontalDirection(SwipeDirection value); - void setVerticalDirection(SwipeDirection value); qreal swipeAngle() const; void setSwipeAngle(qreal value); diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index b0ef703..0f0aef2 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -48,6 +48,10 @@ #include "qevent.h" #include "qgraphicsitem.h" +#ifdef Q_WS_MAC +#include "qmacgesturerecognizer_mac_p.h" +#endif + #include "qdebug.h" // #define GESTURE_DEBUG @@ -64,7 +68,15 @@ QGestureManager::QGestureManager(QObject *parent) { qRegisterMetaType<Qt::GestureState>(); +#if defined(Q_WS_MAC) + registerGestureRecognizer(new QMacSwipeGestureRecognizer); + registerGestureRecognizer(new QMacPinchGestureRecognizer); + #if defined(QT_MAC_USE_COCOA) + registerGestureRecognizer(new QMacPanGestureRecognizer); + #endif +#else registerGestureRecognizer(new QPanGestureRecognizer); +#endif } QGestureManager::~QGestureManager() diff --git a/src/gui/kernel/qmacgesturerecognizer_mac.mm b/src/gui/kernel/qmacgesturerecognizer_mac.mm new file mode 100644 index 0000000..583fc93 --- /dev/null +++ b/src/gui/kernel/qmacgesturerecognizer_mac.mm @@ -0,0 +1,258 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmacgesturerecognizer_mac_p.h" +#include "qgesture.h" +#include "qgesture_p.h" +#include "qevent.h" +#include "qevent_p.h" +#include "qwidget.h" +#include "qdebug.h" + +QT_BEGIN_NAMESPACE + +QMacSwipeGestureRecognizer::QMacSwipeGestureRecognizer() +{ +} + +QGesture *QMacSwipeGestureRecognizer::createGesture(QObject * /*target*/) +{ + return new QSwipeGesture; +} + +QGestureRecognizer::Result +QMacSwipeGestureRecognizer::filterEvent(QGesture *gesture, QObject *obj, QEvent *event) +{ + if (event->type() == QEvent::NativeGesture && obj->isWidgetType()) { + QNativeGestureEvent *ev = static_cast<QNativeGestureEvent*>(event); + switch (ev->gestureType) { + case QNativeGestureEvent::Swipe: { + QSwipeGesture *g = static_cast<QSwipeGesture *>(gesture); + g->setSwipeAngle(ev->angle); + return QGestureRecognizer::GestureTriggered | QGestureRecognizer::ConsumeEventHint; + break; } + default: + break; + } + } + + return QGestureRecognizer::Ignore; +} + +void QMacSwipeGestureRecognizer::reset(QGesture *gesture) +{ + QSwipeGesture *g = static_cast<QSwipeGesture *>(gesture); + g->setSwipeAngle(0); + QGestureRecognizer::reset(gesture); +} + +//////////////////////////////////////////////////////////////////////// + +QMacPinchGestureRecognizer::QMacPinchGestureRecognizer() +{ +} + +QGesture *QMacPinchGestureRecognizer::createGesture(QObject * /*target*/) +{ + return new QPinchGesture; +} + +QGestureRecognizer::Result +QMacPinchGestureRecognizer::filterEvent(QGesture *gesture, QObject *obj, QEvent *event) +{ + if (event->type() == QEvent::NativeGesture && obj->isWidgetType()) { + QPinchGesture *g = static_cast<QPinchGesture *>(gesture); + QNativeGestureEvent *ev = static_cast<QNativeGestureEvent*>(event); + switch(ev->gestureType) { + case QNativeGestureEvent::GestureBegin: + reset(gesture); + g->setStartCenterPoint(static_cast<QWidget*>(obj)->mapFromGlobal(ev->position)); + g->setCenterPoint(g->startCenterPoint()); + g->setWhatChanged(QPinchGesture::CenterPointChanged); + return QGestureRecognizer::MaybeGesture | QGestureRecognizer::ConsumeEventHint; + case QNativeGestureEvent::Rotate: { + g->setLastScaleFactor(g->scaleFactor()); + g->setLastRotationAngle(g->rotationAngle()); + g->setRotationAngle(g->rotationAngle() + ev->percentage); + g->setWhatChanged(QPinchGesture::RotationAngleChanged); + return QGestureRecognizer::GestureTriggered | QGestureRecognizer::ConsumeEventHint; + break; + } + case QNativeGestureEvent::Zoom: + g->setLastScaleFactor(g->scaleFactor()); + g->setLastRotationAngle(g->rotationAngle()); + g->setScaleFactor(g->scaleFactor() + ev->percentage); + g->setWhatChanged(QPinchGesture::ScaleFactorChanged); + return QGestureRecognizer::GestureTriggered | QGestureRecognizer::ConsumeEventHint; + break; + case QNativeGestureEvent::GestureEnd: + return QGestureRecognizer::GestureFinished | QGestureRecognizer::ConsumeEventHint; + break; + default: + break; + } + } + + return QGestureRecognizer::Ignore; +} + +void QMacPinchGestureRecognizer::reset(QGesture *gesture) +{ + QPinchGesture *g = static_cast<QPinchGesture *>(gesture); + g->setWhatChanged(0); + g->setScaleFactor(1.0f); + g->setTotalScaleFactor(1.0f); + g->setLastScaleFactor(1.0f); + g->setRotationAngle(0.0f); + g->setTotalRotationAngle(0.0f); + g->setLastRotationAngle(0.0f); + g->setCenterPoint(QPointF()); + g->setStartCenterPoint(QPointF()); + g->setLastCenterPoint(QPointF()); + QGestureRecognizer::reset(gesture); +} + +//////////////////////////////////////////////////////////////////////// + +#if defined(QT_MAC_USE_COCOA) + +QMacPanGestureRecognizer::QMacPanGestureRecognizer() : _panCanceled(true) +{ +} + +QGesture *QMacPanGestureRecognizer::createGesture(QObject *target) +{ + if (!target) + return new QPanGesture; + + if (QWidget *w = qobject_cast<QWidget *>(target)) { + w->setAttribute(Qt::WA_AcceptTouchEvents); + w->setAttribute(Qt::WA_TouchPadAcceptSingleTouchEvents); + return new QPanGesture; + } + return 0; +} + +QGestureRecognizer::Result +QMacPanGestureRecognizer::filterEvent(QGesture *gesture, QObject *target, QEvent *event) +{ + const int panBeginDelay = 300; + const int panBeginRadius = 3; + + QPanGesture *g = static_cast<QPanGesture *>(gesture); + + switch (event->type()) { + case QEvent::TouchBegin: { + const QTouchEvent *ev = static_cast<const QTouchEvent*>(event); + if (ev->touchPoints().size() == 1) { + reset(gesture); + _startPos = QCursor::pos(); + _lastPos = _startPos; + _panTimer.start(panBeginDelay, target); + _panCanceled = false; + return QGestureRecognizer::MaybeGesture; + } + break;} + case QEvent::TouchEnd: { + const QTouchEvent *ev = static_cast<const QTouchEvent*>(event); + if (!_panCanceled && ev->touchPoints().size() == 1) + return QGestureRecognizer::GestureFinished; + break;} + case QEvent::TouchUpdate: { + if (_panCanceled) + break; + + const QTouchEvent *ev = static_cast<const QTouchEvent*>(event); + if (ev->touchPoints().size() == 1) { + if (_panTimer.isActive()) { + // INVARIANT: Still in maybeGesture. Check if the user + // moved his finger so much that it makes sense to cancel the pan: + const QPointF p = QCursor::pos(); + if ((p - _startPos).manhattanLength() > panBeginRadius) { + _panCanceled = true; + _panTimer.stop(); + return QGestureRecognizer::NotGesture; + } + } else { + const QPointF p = QCursor::pos(); + const QPointF posOffset = p - _lastPos; + g->setLastOffset(g->offset()); + g->setOffset(QSizeF(posOffset.x(), posOffset.y())); + g->setTotalOffset(g->lastOffset() + g->offset()); + _lastPos = p; + return QGestureRecognizer::GestureTriggered; + } + } + break;} + case QEvent::Timer: { + QTimerEvent *ev = static_cast<QTimerEvent *>(event); + if (ev->timerId() == _panTimer.timerId()) { + _panTimer.stop(); + if (_panCanceled) + break; + // Begin new pan session! + _startPos = QCursor::pos(); + _lastPos = _startPos; + return QGestureRecognizer::GestureTriggered | QGestureRecognizer::ConsumeEventHint; + } + break; } + default: + break; + } + + return QGestureRecognizer::Ignore; +} + +void QMacPanGestureRecognizer::reset(QGesture *gesture) +{ + QPanGesture *g = static_cast<QPanGesture *>(gesture); + _startPos = QPointF(); + _lastPos = QPointF(); + _panCanceled = true; + g->setOffset(QSizeF(0, 0)); + g->setLastOffset(QSizeF(0, 0)); + g->setTotalOffset(QSizeF(0, 0)); + g->setAcceleration(qreal(1)); + QGestureRecognizer::reset(gesture); +} +#endif // QT_MAC_USE_COCOA + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qmacgesturerecognizer_mac_p.h b/src/gui/kernel/qmacgesturerecognizer_mac_p.h new file mode 100644 index 0000000..bdc2e08 --- /dev/null +++ b/src/gui/kernel/qmacgesturerecognizer_mac_p.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QMACSWIPEGESTURERECOGNIZER_MAC_P_H +#define QMACSWIPEGESTURERECOGNIZER_MAC_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qtimer.h" +#include "qpoint.h" +#include "qgesturerecognizer.h" + +QT_BEGIN_NAMESPACE + +class QMacSwipeGestureRecognizer : public QGestureRecognizer +{ +public: + QMacSwipeGestureRecognizer(); + + QGesture *createGesture(QObject *target); + QGestureRecognizer::Result filterEvent(QGesture *gesture, QObject *watched, QEvent *event); + void reset(QGesture *gesture); +}; + +class QMacPinchGestureRecognizer : public QGestureRecognizer +{ +public: + QMacPinchGestureRecognizer(); + + QGesture *createGesture(QObject *target); + QGestureRecognizer::Result filterEvent(QGesture *gesture, QObject *watched, QEvent *event); + void reset(QGesture *gesture); +}; + +#if defined(QT_MAC_USE_COCOA) + +class QMacPanGestureRecognizer : public QObject, public QGestureRecognizer +{ +public: + QMacPanGestureRecognizer(); + + QGesture *createGesture(QObject *target); + QGestureRecognizer::Result filterEvent(QGesture *gesture, QObject *watched, QEvent *event); + void reset(QGesture *gesture); +private: + QPointF _startPos; + QPointF _lastPos; + QBasicTimer _panTimer; + bool _panCanceled; +}; + +#endif + +QT_END_NAMESPACE + +#endif // QMACSWIPEGESTURERECOGNIZER_MAC_P_H |