summaryrefslogtreecommitdiffstats
path: root/src/gui/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/kernel')
-rw-r--r--src/gui/kernel/kernel.pri4
-rw-r--r--src/gui/kernel/qapplication.cpp27
-rw-r--r--src/gui/kernel/qapplication_s60.cpp8
-rw-r--r--src/gui/kernel/qapplication_win.cpp9
-rw-r--r--src/gui/kernel/qcursor_s60.cpp24
-rw-r--r--src/gui/kernel/qdnd_s60.cpp4
-rw-r--r--src/gui/kernel/qevent.cpp80
-rw-r--r--src/gui/kernel/qevent.h2
-rw-r--r--src/gui/kernel/qeventdispatcher_mac.mm23
-rw-r--r--src/gui/kernel/qgesture.cpp91
-rw-r--r--src/gui/kernel/qgesture.h6
-rw-r--r--src/gui/kernel/qgesturemanager.cpp18
-rw-r--r--src/gui/kernel/qgesturerecognizer.cpp131
-rw-r--r--src/gui/kernel/qmacgesturerecognizer_mac.mm267
-rw-r--r--src/gui/kernel/qmacgesturerecognizer_mac_p.h103
-rw-r--r--src/gui/kernel/qwidget.cpp10
16 files changed, 726 insertions, 81 deletions
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/qapplication.cpp b/src/gui/kernel/qapplication.cpp
index afc6f63..b990fe2 100644
--- a/src/gui/kernel/qapplication.cpp
+++ b/src/gui/kernel/qapplication.cpp
@@ -943,7 +943,7 @@ void QApplicationPrivate::initialize()
graphics_system = QGraphicsSystemFactory::create(graphics_system_name);
#endif
#ifndef QT_NO_WHEELEVENT
-#ifdef Q_OS_MAC
+#ifdef Q_OS_MAC
QApplicationPrivate::wheel_scroll_lines = 1;
#else
QApplicationPrivate::wheel_scroll_lines = 3;
@@ -1034,11 +1034,11 @@ QApplication::~QApplication()
d->eventDispatcher->closingDown();
d->eventDispatcher = 0;
+ QApplicationPrivate::is_app_closing = true;
+ QApplicationPrivate::is_app_running = false;
delete qt_desktopWidget;
qt_desktopWidget = 0;
- QApplicationPrivate::is_app_closing = true;
- QApplicationPrivate::is_app_running = false;
#ifndef QT_NO_CLIPBOARD
delete qt_clipboard;
@@ -5619,11 +5619,32 @@ Q_GUI_EXPORT void qt_translateRawTouchEvent(QWidget *window,
QApplicationPrivate::translateRawTouchEvent(window, deviceType, touchPoints);
}
+/*!
+ \since 4.6
+
+ Registers the given \a recognizer in the gesture framework and returns a gesture ID
+ for it.
+
+ The application takes ownership of the \a recognizer and returns the gesture type
+ ID associated with it. For gesture recognizers which handle custom QGesture
+ objects (i.e., those which return Qt::CustomGesture in a QGesture::gestureType()
+ function) the return value is a gesture ID between Qt::CustomGesture and
+ Qt::LastGestureType, inclusive.
+
+ \sa unregisterGestureRecognizer(), QGestureRecognizer::createGesture(), QGesture
+*/
Qt::GestureType QApplication::registerGestureRecognizer(QGestureRecognizer *recognizer)
{
return QGestureManager::instance()->registerGestureRecognizer(recognizer);
}
+/*!
+ \since 4.6
+
+ Unregisters all gesture recognizers of the specified \a type.
+
+ \sa registerGestureRecognizer
+*/
void QApplication::unregisterGestureRecognizer(Qt::GestureType type)
{
QGestureManager::instance()->unregisterGestureRecognizer(type);
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp
index acd1041..6d50e55 100644
--- a/src/gui/kernel/qapplication_s60.cpp
+++ b/src/gui/kernel/qapplication_s60.cpp
@@ -352,7 +352,8 @@ QSymbianControl::~QSymbianControl()
{
if (S60->curWin == this)
S60->curWin = 0;
- setFocusSafely(false);
+ if (!QApplicationPrivate::is_app_closing)
+ setFocusSafely(false);
S60->appUi()->RemoveFromStack(this);
delete m_longTapDetector;
}
@@ -688,7 +689,7 @@ TKeyResponse QSymbianControl::OfferKeyEvent(const TKeyEvent& keyEvent, TEventCod
Qt::KeyboardModifiers mods = mapToQtModifiers(keyEvent.iModifiers);
QKeyEventEx qKeyEvent(type == EEventKeyUp ? QEvent::KeyRelease : QEvent::KeyPress, keyCode,
mods, qt_keymapper_private()->translateKeyEvent(keyCode, mods),
- false, 1, keyEvent.iScanCode, s60Keysym, mods);
+ false, 1, keyEvent.iScanCode, s60Keysym, keyEvent.iModifiers);
// WId wid = reinterpret_cast<RWindowGroup *>(keyEvent.Handle())->Child();
// if (!wid)
// Could happen if window isn't shown yet.
@@ -948,7 +949,8 @@ void QSymbianControl::setFocusSafely(bool focus)
S60->appUi()->RemoveFromStack(this);
QT_TRAP_THROWING(S60->appUi()->AddToStackL(this,
ECoeStackPriorityDefault, ECoeStackFlagStandard));
- lastFocusedControl = 0;
+ if(this == lastFocusedControl)
+ lastFocusedControl = 0;
this->SetFocus(false);
}
}
diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp
index 540f0a2..5bb25fa 100644
--- a/src/gui/kernel/qapplication_win.cpp
+++ b/src/gui/kernel/qapplication_win.cpp
@@ -819,13 +819,16 @@ void qt_init(QApplicationPrivate *priv, int)
priv->GetGestureInfo = 0;
priv->GetGestureExtraArgs = 0;
+ priv->CloseGestureInfoHandle = 0;
+ priv->SetGestureConfig = 0;
+ priv->GetGestureConfig = 0;
+ priv->BeginPanningFeedback = 0;
+ priv->UpdatePanningFeedback = 0;
+ priv->EndPanningFeedback = 0;
#if defined(Q_WS_WINCE_WM) && defined(QT_WINCE_GESTURES)
priv->GetGestureInfo = (PtrGetGestureInfo) &TKGetGestureInfo;
priv->GetGestureExtraArgs = (PtrGetGestureExtraArgs) &TKGetGestureExtraArguments;
- priv->CloseGestureInfoHandle = (PtrCloseGestureInfoHandle) 0;
- priv->SetGestureConfig = (PtrSetGestureConfig) 0;
- priv->GetGestureConfig = (PtrGetGestureConfig) 0;
#elif !defined(Q_WS_WINCE)
priv->GetGestureInfo =
(PtrGetGestureInfo)QLibrary::resolve(QLatin1String("user32"),
diff --git a/src/gui/kernel/qcursor_s60.cpp b/src/gui/kernel/qcursor_s60.cpp
index 0d8283d..7f5c32a 100644
--- a/src/gui/kernel/qcursor_s60.cpp
+++ b/src/gui/kernel/qcursor_s60.cpp
@@ -110,7 +110,7 @@ void qt_symbian_set_cursor_visible(bool visible) {
else
cursorSpriteVisible--;
Q_ASSERT(cursorSpriteVisible >=0);
-
+
if (cursorSpriteVisible && !S60->mouseInteractionEnabled) {
#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
if (S60->brokenPointerCursors)
@@ -119,7 +119,7 @@ void qt_symbian_set_cursor_visible(bool visible) {
#endif
S60->wsSession().SetPointerCursorMode(EPointerCursorNormal);
} else if (!cursorSpriteVisible && S60->mouseInteractionEnabled) {
-#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
+#ifndef Q_SYMBIAN_FIXED_POINTER_CURSORS
if (S60->brokenPointerCursors)
qt_symbian_hide_pointer_sprite();
else
@@ -188,7 +188,7 @@ Qt::HANDLE QCursor::handle() const
return reinterpret_cast<Qt::HANDLE> (&(d->pcurs));
#ifdef Q_SYMBIAN_HAS_SYSTEM_CURSORS
- // don't construct shape cursors, QApplication_s60 will use the system cursor instead
+ // don't construct shape cursors, QApplication_s60 will use the system cursor instead
if (!(d->bm))
return 0;
#endif
@@ -228,12 +228,12 @@ void QCursorData::loadShapeFromResource(RWsSpriteBase& target, QString resource,
/*
* Constructs the native cursor from resources compiled into QtGui
* This is needed only when the platform doesn't have system cursors.
- *
+ *
* System cursors are higher performance, since they are constructed once
* and shared by all applications by specifying the shape number.
* Due to symbian platform security considerations, and the fact most
* existing phones have a broken RWsPointerCursor, system cursors are not
- * being used.
+ * being used.
*/
void QCursorData::constructShapeSprite(RWsSpriteBase& target)
{
@@ -346,7 +346,7 @@ void QCursorData::constructCursorSprite(RWsSpriteBase& target)
member->iMaskBitmap = pixmap.mask().toSymbianCFbsBitmap();
}
else {
- member->iMaskBitmap = pixmap.createHeuristicMask().toSymbianCFbsBitmap();
+ member->iMaskBitmap = 0; //opaque rectangle cursor (due to EDrawModePEN)
}
}
@@ -371,11 +371,11 @@ void qt_symbian_show_pointer_sprite()
} else {
cursorSprite = QCursor(Qt::ArrowCursor);
}
-
+
cursorSprite.d->scurs = RWsSprite(S60->wsSession());
QPoint pos = QCursor::pos();
cursorSprite.d->scurs.Construct(S60->windowGroup(), TPoint(pos.x(), pos.y()), ESpriteNoChildClip | ESpriteNoShadows);
-
+
cursorSprite.d->constructCursorSprite(cursorSprite.d->scurs);
cursorSprite.d->scurs.Activate();
}
@@ -409,7 +409,7 @@ void qt_symbian_set_pointer_sprite(const QCursor& cursor)
* RWsPointerCursor, this function is called in response to pointer events
* and when QCursor::setPos() is called.
* Performance is worse than a real pointer cursor, due to extra context
- * switches vs. the window server moving the cursor by itself.
+ * switches vs. the window server moving the cursor by itself.
*/
void qt_symbian_move_cursor_sprite()
{
@@ -421,7 +421,7 @@ void qt_symbian_move_cursor_sprite()
/*
* Translate from Qt::CursorShape to OS system pointer cursor list index.
* Currently we control the implementation of the system pointer cursor list,
- * so this function is trivial. That may not always be the case.
+ * so this function is trivial. That may not always be the case.
*/
TInt qt_symbian_translate_cursor_shape(Qt::CursorShape shape)
{
@@ -462,7 +462,7 @@ void qt_symbian_set_cursor(QWidget *w, bool force)
/*
* Makes the specified cursor appear above a specific native window group
* Called from QSymbianControl and QApplication::restoreOverrideCursor
- *
+ *
* Window server is needed for this, so there is no equivalent when using
* the sprite workaround.
*/
@@ -486,7 +486,7 @@ void qt_symbian_setWindowGroupCursor(const QCursor &cursor, RWindowTreeNode &nod
/*
* Makes the specified cursor appear above a specific native window
* Called from QSymbianControl and QApplication::restoreOverrideCursor
- *
+ *
* Window server is needed for this, so there is no equivalent when using
* the sprite workaround.
*/
diff --git a/src/gui/kernel/qdnd_s60.cpp b/src/gui/kernel/qdnd_s60.cpp
index 3d6ecd2..a8d3ac5 100644
--- a/src/gui/kernel/qdnd_s60.cpp
+++ b/src/gui/kernel/qdnd_s60.cpp
@@ -277,7 +277,7 @@ Qt::DropAction QDragManager::drag(QDrag *o)
qApp->installEventFilter(this);
- global_accepted_action = Qt::MoveAction;
+ global_accepted_action = defaultAction(dragPrivate()->possible_actions, Qt::NoModifier);
qt_symbian_dnd_dragging = true;
eventLoop = new QEventLoop;
@@ -288,7 +288,7 @@ Qt::DropAction QDragManager::drag(QDrag *o)
#ifndef QT_NO_CURSOR
qt_symbian_set_cursor_visible(false);
-
+
overrideCursor = QCursor(); //deref the cursor data
qt_symbian_dnd_dragging = false;
#endif
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index 4316714..4826704 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -4196,31 +4196,47 @@ QTouchEvent::TouchPoint &QTouchEvent::TouchPoint::operator=(const QTouchEvent::T
\since 4.6
\ingroup events
- \brief The QGestureEvent class provides the description of triggered
- gestures.
+ \brief The QGestureEvent class provides the description of triggered gestures.
- The QGestureEvent class contains a list of gestures that are being executed
- right now (\l{QGestureEvent::}{activeGestures()}) and a list of gestures
- that are \l{QGestureEvent::canceledGestures}{cancelled} (a gesture might be
- cancelled because the window lost focus, or because of timeout, etc).
+ The QGestureEvent class contains a list of gestures, which can be obtained using the
+ allGestures() function.
- \sa QGesture
+ The gestures are either active or canceled. A list of those that are currently being
+ executed can be obtained using the activeGestures() function. A list of those which
+ were previously active and have been canceled can be accessed using the
+ canceledGestures() function. A gesture might be canceled if the current window loses
+ focus, for example, or because of a timeout, or for other reasons.
+
+ If the event handler does not accept the event by calling the generic
+ QEvent::accept() function, all individual QGesture object that were not accepted
+ will be propagated up the parent widget chain until a widget accepts them
+ individually, by calling QGestureEvent::accept() for each of them, or an event
+ filter consumes the event.
+
+ \sa QGesture, QGestureRecognizer,
+ QWidget::grabGesture(), QGraphicsObject::grabGesture()
*/
/*!
Creates new QGestureEvent containing a list of \a gestures.
*/
-QGestureEvent::QGestureEvent(const QList<QGesture*> &gestures)
+QGestureEvent::QGestureEvent(const QList<QGesture *> &gestures)
: QEvent(QEvent::Gesture), gestures_(gestures)
{
}
-QList<QGesture*> QGestureEvent::allGestures() const
+/*!
+ Returns all gestures that are delivered in the event.
+*/
+QList<QGesture *> QGestureEvent::allGestures() const
{
return gestures_;
}
-QGesture* QGestureEvent::gesture(Qt::GestureType type)
+/*!
+ Returns a gesture object by \a type.
+*/
+QGesture *QGestureEvent::gesture(Qt::GestureType type) const
{
for(int i = 0; i < gestures_.size(); ++i)
if (gestures_.at(i)->gestureType() == type)
@@ -4228,16 +4244,35 @@ QGesture* QGestureEvent::gesture(Qt::GestureType type)
return 0;
}
-QList<QGesture*> QGestureEvent::activeGestures() const
+/*!
+ Returns a list of active (not canceled) gestures.
+*/
+QList<QGesture *> QGestureEvent::activeGestures() const
{
return gestures_;
}
-QList<QGesture*> QGestureEvent::canceledGestures() const
+/*!
+ Returns a list of canceled gestures.
+*/
+QList<QGesture *> QGestureEvent::canceledGestures() const
{
return gestures_;
}
+/*!
+ Sets the accept flag of the given \a gesture object to the specified \a value.
+
+ Setting the accept flag indicates that the event receiver wants the \a gesture.
+ Unwanted gestures may be propagated to the parent widget.
+
+ By default, gestures in events of type QEvent::Gesture are accepted, and
+ gestures in QEvent::GestureOverride events are ignored.
+
+ For convenience, the accept flag can also be set with
+ \l{QGestureEvent::accept()}{accept(gesture)}, and cleared with
+ \l{QGestureEvent::ignore()}{ignore(gesture)}.
+*/
void QGestureEvent::setAccepted(QGesture *gesture, bool value)
{
setAccepted(false);
@@ -4245,16 +4280,37 @@ void QGestureEvent::setAccepted(QGesture *gesture, bool value)
gesture->d_func()->accept = value;
}
+/*!
+ Sets the accept flag of the given \a gesture object, the equivalent of calling
+ \l{QGestureEvent::setAccepted()}{setAccepted(gesture, true)}.
+
+ Setting the accept flag indicates that the event receiver wants the
+ gesture. Unwanted gestures may be propagated to the parent widget.
+
+ \sa QGestureEvent::ignore()
+*/
void QGestureEvent::accept(QGesture *gesture)
{
setAccepted(gesture, true);
}
+/*!
+ Clears the accept flag parameter of the given \a gesture object, the equivalent
+ of calling \l{QGestureEvent::setAccepted()}{setAccepted(gesture, false)}.
+
+ Clearing the accept flag indicates that the event receiver does not
+ want the gesture. Unwanted gestures may be propgated to the parent widget.
+
+ \sa QGestureEvent::accept()
+*/
void QGestureEvent::ignore(QGesture *gesture)
{
setAccepted(gesture, false);
}
+/*!
+ Returns true if the \a gesture is accepted; otherwise returns false.
+*/
bool QGestureEvent::isAccepted(QGesture *gesture) const
{
return gesture ? gesture->d_func()->accept : false;
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index 224b479..3516222 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -826,7 +826,7 @@ public:
QGestureEvent(const QList<QGesture *> &gestures);
QList<QGesture *> allGestures() const;
- QGesture *gesture(Qt::GestureType type);
+ QGesture *gesture(Qt::GestureType type) const;
QList<QGesture *> activeGestures() const;
QList<QGesture *> canceledGestures() const;
diff --git a/src/gui/kernel/qeventdispatcher_mac.mm b/src/gui/kernel/qeventdispatcher_mac.mm
index 7152705..c9dd949 100644
--- a/src/gui/kernel/qeventdispatcher_mac.mm
+++ b/src/gui/kernel/qeventdispatcher_mac.mm
@@ -136,14 +136,19 @@ void QEventDispatcherMacPrivate::activateTimer(CFRunLoopTimerRef, void *info)
if (tmr == 0 || tmr->pending == true)
return; // Can't send another timer event if it's pending.
- tmr->pending = true;
- QTimerEvent e(tmr->id);
- qt_sendSpontaneousEvent(tmr->obj, &e);
- // Get the value again in case the timer gets unregistered during the sendEvent.
- tmr = macTimerHash.value(timerID);
- if (tmr != 0)
- tmr->pending = false;
+ if (blockSendPostedEvents) {
+ QCoreApplication::postEvent(tmr->obj, new QTimerEvent(tmr->id));
+ } else {
+ tmr->pending = true;
+ QTimerEvent e(tmr->id);
+ qt_sendSpontaneousEvent(tmr->obj, &e);
+ // Get the value again in case the timer gets unregistered during the sendEvent.
+ tmr = macTimerHash.value(timerID);
+ if (tmr != 0)
+ tmr->pending = false;
+ }
+
}
void QEventDispatcherMac::registerTimer(int timerId, int interval, QObject *obj)
@@ -767,7 +772,7 @@ NSModalSession QEventDispatcherMacPrivate::currentModalSession()
// Sadly, we need to introduce this little event flush
// to stop dialogs from blinking/poping in front if a
// modal session restart was needed:
- while (NSEvent *event = [NSApp nextEventMatchingMask:NSAnyEventMask
+ while (NSEvent *event = [NSApp nextEventMatchingMask:0
untilDate:nil
inMode:NSDefaultRunLoopMode
dequeue: YES]) {
@@ -942,7 +947,7 @@ Boolean QEventDispatcherMacPrivate::postedEventSourceEqualCallback(const void *i
inline static void processPostedEvents(QEventDispatcherMacPrivate *const d, const bool blockSendPostedEvents)
{
- if (blockSendPostedEvents) {
+ if (blockSendPostedEvents || d->interrupt) {
CFRunLoopSourceSignal(d->postedEventsSource);
} else {
if (!d->threadData->canWait || (d->serialNumber != d->lastSerial)) {
diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp
index 68cb9cd..3639a45 100644
--- a/src/gui/kernel/qgesture.cpp
+++ b/src/gui/kernel/qgesture.cpp
@@ -48,38 +48,81 @@ QT_BEGIN_NAMESPACE
\class QGesture
\since 4.6
- \brief The QGesture class represents a gesture, containing all
- properties that describe a gesture.
+ \brief The QGesture class represents a gesture, containing properties that
+ describe the corresponding user input.
- The widget receives a QGestureEvent with a list of QGesture
- objects that represent gestures that are occuring on it. The class
- has a list of properties that can be queried by the user to get
- some gesture-specific arguments (i.e. position of the tap in the
- DoubleTap gesture).
+ QGesture objects are delivered to widgets and \l{QGraphicsObject}s with
+ \l{QGestureEvent}s.
- When creating custom gesture recognizers, they might add new
- properties to the gesture object, or custom gesture developers
- might subclass the QGesture objects to provide some extended
- information.
+ The class has a list of properties that can be queried by the user to get
+ some gesture-specific arguments. For example, the QPinchGesture gesture has a scale
+ factor that is exposed as a property.
+
+ Developers of custom gesture recognizers can add additional properties in
+ order to provide additional information about a gesture. This can be done
+ by adding new dynamic properties to a QGesture object, or by subclassing
+ the QGesture class (or one of its subclasses).
\sa QGestureEvent, QGestureRecognizer
*/
+/*!
+ Constructs a new gesture object with the given \a parent.
+
+ QGesture objects are created by gesture recognizers in the
+ QGestureRecognizer::createGesture() function.
+*/
QGesture::QGesture(QObject *parent)
: QObject(*new QGesturePrivate, parent)
{
d_func()->gestureType = Qt::CustomGesture;
}
+/*!
+ \internal
+*/
QGesture::QGesture(QGesturePrivate &dd, QObject *parent)
: QObject(dd, parent)
{
}
+/*!
+ Destroys the gesture object.
+*/
QGesture::~QGesture()
{
}
+/*!
+ \property QGesture::state
+ \brief the current state of the gesture
+*/
+
+/*!
+ \property QGesture::gestureType
+ \brief the type of the gesture
+*/
+
+/*!
+ \property QGesture::hotSpot
+
+ \brief The point that is used to find the receiver for the gesture event.
+
+ If the hot-spot is not set, the targetObject is used as the receiver of the
+ gesture event.
+*/
+
+/*!
+ \property QGesture::hasHotSpot
+ \brief whether the gesture has a hot-spot
+*/
+
+/*!
+ \property QGesture::targetObject
+ \brief the target object which will receive the gesture event if the hotSpot is
+ not set
+*/
+
Qt::GestureType QGesture::gestureType() const
{
return d_func()->gestureType;
@@ -292,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 000f44f..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()
@@ -279,8 +291,10 @@ bool QGestureManager::filterEvent(QObject *receiver, QEvent *event)
QSet<QGesture *> notStarted = finishedGestures - activeGestures;
if (!notStarted.isEmpty()) {
// there are some gestures that claim to be finished, but never started.
- qWarning("QGestureManager::filterEvent: some gestures were finished even though they've never started");
- finishedGestures -= notStarted;
+ // probably those are "singleshot" gestures so we'll fake the started state.
+ foreach (QGesture *gesture, notStarted)
+ gesture->d_func()->state = Qt::GestureStarted;
+ deliverEvents(notStarted, receiver);
}
activeGestures += startedGestures;
diff --git a/src/gui/kernel/qgesturerecognizer.cpp b/src/gui/kernel/qgesturerecognizer.cpp
index 590f09e..2af087f 100644
--- a/src/gui/kernel/qgesturerecognizer.cpp
+++ b/src/gui/kernel/qgesturerecognizer.cpp
@@ -45,27 +45,150 @@
QT_BEGIN_NAMESPACE
+/*!
+ \class QGestureRecognizer
+ \since 4.6
+ \brief The QGestureRecognizer class provides the infrastructure for gesture recognition.
+
+ Gesture recognizers are responsible for creating and managing QGesture objects and
+ monitoring input events sent to QWidget and QGraphicsObject subclasses.
+ QGestureRecognizer is the base class for implementing custom gestures.
+
+ Developers that only need to provide gesture recognition for standard gestures do not
+ need to use this class directly. Instances will be created behind the scenes by the
+ framework.
+
+ \section1 Recognizing Gestures
+
+ The process of recognizing gestures involves filtering input events sent to specific
+ objects, and modifying the associated QGesture objects to include relevant information
+ about the user's input.
+
+ Gestures are created when the framework calls createGesture() to handle user input
+ for a particular target QWidget or QGraphicsObject instance. Once a QGesture has been
+ created for one of these objects, the gesture recognizer will receive events for it
+ in its filterEvent() handler function.
+
+ When a gesture is canceled, the reset() function is called, giving the recognizer the
+ chance to update the appropriate properties in the corresponding QGesture object.
+
+ \section1 Supporting New Gestures
+
+ To add support for new gestures, you need to derive from QGestureRecognizer to create
+ a custom recognizer class and register it with the application by calling
+ QApplication::registerGestureRecognizer(). You can also derive from QGesture to create
+ a custom gesture class, or rely on dynamic properties to express specific details
+ of the gesture you want to handle.
+
+ Your custom QGestureRecognizer subclass needs to reimplement the filterEvent() function
+ to handle and filter the incoming input events for QWidget and QGraphicsObject subclasses.
+ Although the logic for gesture recognition is implemented in this function, the state of
+ recognition for each target object can be recorded in the QGesture object supplied.
+
+ If you choose to represent a gesture by a custom QGesture subclass, you will need to
+ reimplement the createGesture() function to construct instances of your gesture class.
+ Similarly, you may need to reimplement the reset() function if your custom gesture
+ objects need to be specially handled when a gesture is canceled.
+
+ \sa QGesture
+*/
+
+/*!
+ \enum QGestureRecognizer::ResultFlags
+
+ This enum describes the result of the current event filtering step in
+ a gesture recognizer state machine.
+
+ The result consists of a state value (one of Ignore, NotGesture,
+ MaybeGesture, GestureTriggered, GestureFinished) and an optional hint
+ (ConsumeEventHint).
+
+ \value Ignore The event does not change the state of the recognizer.
+
+ \value NotGesture The event made it clear that it is not a gesture. If the
+ gesture recognizer was in GestureTriggered state before, then the gesture
+ is canceled and the appropriate QGesture object will be delivered to the
+ target as a part of a QGestureEvent.
+
+ \value MaybeGesture The event changed the internal state of the recognizer,
+ but it isn't clear yet if it is a gesture or not. The recognizer needs to
+ filter more events to decide. Gesture recognizers in the MaybeGesture state
+ may be reset automatically if they take too long to recognize gestures.
+
+ \value GestureTriggered The gesture has been triggered and the appropriate
+ QGesture object will be delivered to the target as a part of a
+ QGestureEvent.
+
+ \value GestureFinished The gesture has been finished successfully and the
+ appropriate QGesture object will be delivered to the target as a part of a
+ QGestureEvent.
+
+ \value ConsumeEventHint This hint specifies that the gesture framework should
+ consume the filtered event and not deliver it to the receiver.
+
+ \omitvalue ResultState_Mask
+ \omitvalue ResultHint_Mask
+
+ \sa QGestureRecognizer::filterEvent()
+*/
+
+/*!
+ Constructs a new gesture recognizer object.
+*/
QGestureRecognizer::QGestureRecognizer()
{
}
+/*!
+ Destroys the gesture recognizer.
+*/
QGestureRecognizer::~QGestureRecognizer()
{
}
-QGesture *QGestureRecognizer::createGesture(QObject *)
+/*!
+ This function is called by Qt to create a new QGesture object for the
+ given \a target (QWidget or QGraphicsObject).
+
+ Reimplement this function to create a custom QGesture-derived gesture
+ object if necessary.
+*/
+QGesture *QGestureRecognizer::createGesture(QObject *target)
{
+ Q_UNUSED(target);
return new QGesture;
}
-void QGestureRecognizer::reset(QGesture *state)
+/*!
+ This function is called by the framework to reset a given \a gesture.
+
+ Reimplement this function to implement additional requirements for custom QGesture
+ objects. This may be necessary if you implement a custom QGesture whose properties
+ need special handling when the gesture is reset.
+*/
+void QGestureRecognizer::reset(QGesture *gesture)
{
- if (state) {
- QGesturePrivate *d = state->d_func();
+ if (gesture) {
+ QGesturePrivate *d = gesture->d_func();
d->state = Qt::NoGesture;
d->hotSpot = QPointF();
d->targetObject = 0;
}
}
+/*!
+ \fn QGestureRecognizer::filterEvent(QGesture *gesture, QObject *watched, QEvent *event)
+
+ Handles the given \a event for the \a watched object, updating the state of the \a gesture
+ object as required, and returns a suitable Result for the current recognition step.
+
+ This function is called by the framework to allow the recognizer to filter input events
+ dispatched to QWidget or QGraphicsObject instances that it is monitoring.
+
+ The result reflects how much of the gesture has been recognized. The state of the
+ \a gesture object is set depending on the result.
+
+ \sa Qt::GestureState
+*/
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qmacgesturerecognizer_mac.mm b/src/gui/kernel/qmacgesturerecognizer_mac.mm
new file mode 100644
index 0000000..7b19a54
--- /dev/null
+++ b/src/gui/kernel/qmacgesturerecognizer_mac.mm
@@ -0,0 +1,267 @@
+/****************************************************************************
+**
+** 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: {
+ if (_panCanceled)
+ break;
+
+ const QTouchEvent *ev = static_cast<const QTouchEvent*>(event);
+ if (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;
+ }
+ } else if (_panTimer.isActive()) {
+ // I only want to cancel the pan if the user is pressing
+ // more than one finger, and the pan hasn't started yet:
+ _panCanceled = true;
+ _panTimer.stop();
+ return QGestureRecognizer::NotGesture;
+ }
+ 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
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index bce06e0..7dc3ae9 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -11672,10 +11672,16 @@ QGraphicsProxyWidget *QWidget::graphicsProxyWidget() const
Synonym for QList<QWidget *>.
*/
-void QWidget::grabGesture(Qt::GestureType type, Qt::GestureContext context)
+/*!
+ Subscribes the widget to a given \a gesture with a \a context.
+
+ \sa QGestureEvent
+ \since 4.6
+*/
+void QWidget::grabGesture(Qt::GestureType gesture, Qt::GestureContext context)
{
Q_D(QWidget);
- d->gestureContext.insert(type, context);
+ d->gestureContext.insert(gesture, context);
(void)QGestureManager::instance(); // create a gesture manager
}