summaryrefslogtreecommitdiffstats
path: root/src/imports/widgets
ModeNameSize
-rw-r--r--graphicslayouts.cpp7721logstatsplain
-rw-r--r--graphicslayouts_p.h7870logstatsplain
-rw-r--r--graphicswidgets.cpp1500logstatsplain
-rw-r--r--graphicswidgets_p.h2026logstatsplain
-rw-r--r--qmldir15logstatsplain
-rw-r--r--widgets.cpp4925logstatsplain
-rw-r--r--widgets.pro709logstatsplain
ouch point also contains its starting and + previous coordinates. + + \sa QTouchEvent +*/ + +/*! + \class QGraphicsSceneTouchEvent::TouchPoint + \brief The QGraphicsSceneTouchEvent::TouchPoint class represents a single touch point in a QGraphicsSceneTouchEvent. + \since 4.6 + \ingroup multimedia + \ingroup graphicsview-api + + Each touch point in a QGraphicsSceneTouchEvent has an id() and + state() in addition to current, starting, and previous coordinates + for the touch point in item, scene, and screen coordinates. +*/ + #include "qgraphicssceneevent.h" #ifndef QT_NO_GRAPHICSVIEW @@ -522,7 +553,7 @@ void QGraphicsSceneMouseEvent::setLastPos(const QPointF &pos) } /*! - Returns the last recorded mouse cursor position in scene + Returns the last recorded mouse cursor position in scene coordinates. The last recorded position is the position of the previous mouse event received by the view that created the event. @@ -545,7 +576,7 @@ void QGraphicsSceneMouseEvent::setLastScenePos(const QPointF &pos) } /*! - Returns the last recorded mouse cursor position in screen + Returns the last recorded mouse cursor position in screen coordinates. The last recorded position is the position of the previous mouse event received by the view that created the event. @@ -1275,7 +1306,7 @@ QGraphicsSceneDragDropEvent::~QGraphicsSceneDragDropEvent() /*! Returns the mouse position of the event relative to the view that sent the event. - + \sa QGraphicsView, screenPos(), scenePos() */ QPointF QGraphicsSceneDragDropEvent::pos() const @@ -1373,7 +1404,7 @@ void QGraphicsSceneDragDropEvent::setButtons(Qt::MouseButtons buttons) /*! Returns the keyboard modifiers that were pressed when the drag - and drop event was created. + and drop event was created. \sa Qt::KeyboardModifiers */ @@ -1428,7 +1459,7 @@ void QGraphicsSceneDragDropEvent::setPossibleActions(Qt::DropActions actions) The action must be one of the possible actions as defined by \c possibleActions(). - \sa Qt::DropAction, possibleActions() + \sa Qt::DropAction, possibleActions() */ Qt::DropAction QGraphicsSceneDragDropEvent::proposedAction() const @@ -1673,6 +1704,291 @@ void QGraphicsSceneMoveEvent::setNewPos(const QPointF &pos) d->newPos = pos; } +class QGraphicsSceneTouchEventPrivate : public QGraphicsSceneEventPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsSceneTouchEvent) +public: + inline QGraphicsSceneTouchEventPrivate() + : modifiers(Qt::NoModifier) + { } + + QList touchPoints; + Qt::KeyboardModifiers modifiers; +}; + +/*! + \internal + + Constructs a generic QGraphicsSceneTouchEvent of type \a type. +*/ +QGraphicsSceneTouchEvent::QGraphicsSceneTouchEvent(Type type) + : QGraphicsSceneEvent(*new QGraphicsSceneTouchEventPrivate, type) +{ } + +/*! + Destroys the QGraphicsSceneTouchEvent. +*/ +QGraphicsSceneTouchEvent::~QGraphicsSceneTouchEvent() +{ + Q_D(QGraphicsSceneTouchEvent); + qDeleteAll(d->touchPoints); +} + +/*! + Returns the list of touch points for this event. + + \sa QGraphicsSceneTouchEvent::TouchPoint +*/ +const QList &QGraphicsSceneTouchEvent::touchPoints() const +{ + Q_D(const QGraphicsSceneTouchEvent); + return d->touchPoints; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::setTouchPoints(const QList &touchPoints) +{ + Q_D(QGraphicsSceneTouchEvent); + d->touchPoints = touchPoints; +} + +/*! + Returns the keyboard modifiers in use at the time the event was + sent. +*/ +Qt::KeyboardModifiers QGraphicsSceneTouchEvent::modifiers() const +{ + Q_D(const QGraphicsSceneTouchEvent); + return d->modifiers; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::setModifiers(Qt::KeyboardModifiers modifiers) +{ + Q_D(QGraphicsSceneTouchEvent); + d->modifiers = modifiers; +} + +class QGraphicsSceneTouchEventTouchPointPrivate +{ +public: + inline QGraphicsSceneTouchEventTouchPointPrivate() + : id(-1), state(Qt::TouchPointReleased), pressure(qreal(0.)) + { } + + int id; + Qt::TouchPointState state; + QPointF pos, startPos, lastPos; + QPointF scenePos, startScenePos, lastScenePos; + QPointF screenPos, startScreenPos, lastScreenPos; + qreal pressure; +}; + +/*! \internal + + Constructs a new touch point for use in a QGraphicsSceneTouchEvent. +*/ +QGraphicsSceneTouchEvent::TouchPoint::TouchPoint() + : d(new QGraphicsSceneTouchEventTouchPointPrivate) +{ +} + +/*! \internal + + Destroys the QGraphicsSceneTouchEvent::TouchPoint. +*/ +QGraphicsSceneTouchEvent::TouchPoint::~TouchPoint() +{ + delete d; +} + +/*! + Returns the identifier for this touch point. +*/ +int QGraphicsSceneTouchEvent::TouchPoint::id() const +{ + return d->id; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setId(int id) +{ + d->id = id; +} + +/*! + Returns the state of this touch point at the time the + QGraphicsSceneTouchEvent occurred. +*/ +Qt::TouchPointState QGraphicsSceneTouchEvent::TouchPoint::state() const +{ + return d->state; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setState(Qt::TouchPointState state) +{ + d->state = state; +} + +/*! + Returns the current position of this touch point in item coordinates. + + \sa scenePos(), screenPos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::pos() const +{ + return d->pos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setPos(const QPointF &pos) +{ + d->pos = pos; +} + +/*! + Returns the starting position of this touch point in item coordinates. + + \sa startScenePos(), startScreenPos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::startPos() const +{ + return d->startPos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setStartPos(const QPointF &startPos) +{ + d->startPos = startPos; +} + +/*! + Returns the previous position of this touch point in item coordinates. + + \sa lastScenePos(), lastScreenPos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::lastPos() const +{ + return d->lastPos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setLastPos(const QPointF &lastPos) +{ + d->lastPos = lastPos; +} + +/*! + Returns the current position of this touch point in scene coordinates. + + \sa pos(), screenPos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::scenePos() const +{ + return d->scenePos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setScenePos(const QPointF &scenePos) +{ + d->scenePos = scenePos; +} + +/*! + Returns the starting position of this touch point in scene coordinates. + + \sa startPos(), startScreenPos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::startScenePos() const +{ + return d->startScenePos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setStartScenePos(const QPointF &startScenePos) +{ + d->startScenePos = startScenePos; +} + +/*! + Returns the previous position of this touch point in scene coordinates. + + \sa lastPos(), lastScreenPos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::lastScenePos() const +{ + return d->lastScenePos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setLastScenePos(const QPointF &lastScenePos) +{ + d->lastScenePos = lastScenePos; +} + +/*! + Returns the current position of this touch point in screen coordinates. + + \sa pos(), scenePos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::screenPos() const +{ + return d->screenPos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setScreenPos(const QPointF &screenPos) +{ + d->screenPos = screenPos; +} + +/*! + Returns the starting position of this touch point in screen coordinates. + + \sa startPos(), startScenePos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::startScreenPos() const +{ + return d->startScreenPos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setStartScreenPos(const QPointF &startScreenPos) +{ + d->startScreenPos = startScreenPos; +} + +/*! + Returns the previous position of this touch point in screen coordinates. + + \sa lastPos(), lastScenePos() +*/ +QPointF QGraphicsSceneTouchEvent::TouchPoint::lastScreenPos() const +{ + return d->lastScreenPos; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setLastScreenPos(const QPointF &lastScreenPos) +{ + d->lastScreenPos = lastScreenPos; +} + +/*! + Returns the pressure of this touch point. +*/ +qreal QGraphicsSceneTouchEvent::TouchPoint::pressure() const +{ + return d->pressure; +} + +/*! \internal */ +void QGraphicsSceneTouchEvent::TouchPoint::setPressure(qreal pressure) +{ + d->pressure = pressure; +} + QT_END_NAMESPACE #endif // QT_NO_GRAPHICSVIEW diff --git a/src/gui/graphicsview/qgraphicssceneevent.h b/src/gui/graphicsview/qgraphicssceneevent.h index be50e96..8ae3a99 100644 --- a/src/gui/graphicsview/qgraphicssceneevent.h +++ b/src/gui/graphicsview/qgraphicssceneevent.h @@ -302,6 +302,70 @@ public: void setNewPos(const QPointF &pos); }; +class QGraphicsSceneTouchEventPrivate; +class QGraphicsSceneTouchEventTouchPointPrivate; +class Q_GUI_EXPORT QGraphicsSceneTouchEvent : public QGraphicsSceneEvent +{ +public: + QGraphicsSceneTouchEvent(Type type = None); + ~QGraphicsSceneTouchEvent(); + + class Q_GUI_EXPORT TouchPoint + { + public: + TouchPoint(); + ~TouchPoint(); + + int id() const; + void setId(int id); + + Qt::TouchPointState state() const; + void setState(Qt::TouchPointState state); + + QPointF pos() const; + void setPos(const QPointF &pos); + + QPointF startPos() const; + void setStartPos(const QPointF &startPos); + + QPointF lastPos() const; + void setLastPos(const QPointF &lastPos); + + QPointF scenePos() const; + void setScenePos(const QPointF &scenePos); + + QPointF startScenePos() const; + void setStartScenePos(const QPointF &startScenePos); + + QPointF lastScenePos() const; + void setLastScenePos(const QPointF &lastScenePos); + + QPointF screenPos() const; + void setScreenPos(const QPointF &screenPos); + + QPointF startScreenPos() const; + void setStartScreenPos(const QPointF &startScreenPos); + + QPointF lastScreenPos() const; + void setLastScreenPos(const QPointF &lastScreenPos); + + qreal pressure() const; // 0.0 -> 1.0 + void setPressure(qreal pressure); + + private: + QGraphicsSceneTouchEventTouchPointPrivate *d; + }; + + const QList &touchPoints() const; + void setTouchPoints(const QList &touchPoints); + + Qt::KeyboardModifiers modifiers() const; + void setModifiers(Qt::KeyboardModifiers modifiers); + +private: + Q_DECLARE_PRIVATE(QGraphicsSceneTouchEvent); +}; + #endif // QT_NO_GRAPHICSVIEW QT_END_NAMESPACE diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 3f1df5e..ff69c24 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -3506,4 +3506,168 @@ QMenubarUpdatedEvent::QMenubarUpdatedEvent(QMenuBar * const menuBar) #endif +/*! \class QTouchEvent + \brief The QTouchEvent class contains parameters that describe a touch event +. + \since 4.6 + \ingroup events + + Touch events occur when pressing, releasing, or moving one or more + touch points on a touch device (such as a touch-screen or + track-pad), and if the widget has the Qt::WA_AcceptTouchEvents + attribute. + + Like QMouseEvent, Qt automatically grabs the touch device on the + first press inside a widget; the widget will receive all touch + events until the last touch point is released. + + A touch event contains a special accept flag that indicates + whether the receiver wants the event. By default, the event is + ignored. You should call accept() if the touch event is handled by + your widget. A touch event is propagated up the parent widget + chain until a widget accepts it with accept(), or an event filter + consumes it. If the touch event is neither accepted nor consumed, + then mouse events are simulated from the state of the first touch + point. + + All touch events are of type QEvent::Touch. The touchPoints() + function returns a list of all touch points contained in the + event. Information about each touch point can be retreived using + the QTouchEvent::TouchPoint class. + + The Qt::TouchPointState enum describes the different states that a + touch point may have. + + QTouchEvent::TouchPoint Qt::TouchPointState Qt::WA_AcceptTouchEvents +*/ + +/*! \enum Qt::TouchPointState + \since 4.6 + + This enum represents the state of a touch point at the time the + QTouchEvent occurred. + + \value TouchPointPressed The touch point is now pressed. + \value TouchPointMoved The touch point moved. + \value TouchPointStationary The touch point did not move. + \value TouchPointReleased The touch point was released. +*/ + +/*! \class QTouchEvent::TouchPoint + \brief The QTouchEvent::TouchPoint class provide information about a touch point in a QTouchEvent. + \since 4.6 +*/ + +/*! + Constructs a QTouchEvent with the given \a type and \a + touchPoints. The \a modifiers are the current keyboard modifiers + at the time of the event. +*/ +QTouchEvent::QTouchEvent(QEvent::Type type, + Qt::KeyboardModifiers modifiers, + const QList &touchPoints) + : QInputEvent(type, modifiers), _touchPoints(touchPoints) +{ } + +/*! \fn const QList &QTouchEvent::touchPoints() const + + Returns the list of touch points contained in the touch event. +*/ + +/*! \internal + + Constructs a QTouchEvent::TouchPoint for use in a QTouchEvent. +*/ +QTouchEvent::TouchPoint::TouchPoint(int id) + : d(new QTouchEventTouchPointPrivate(id)) +{ } + +/*! \internal + + Destroys the QTouchEvent::TouchPoint. +*/ +QTouchEvent::TouchPoint::~TouchPoint() +{ + delete d; +} + +/*! + Returns the id number of this touch point. Id numbers are + sequential, starting at zero, meaning the first touch point has id + 0, the second has id 1, and so on... +*/ +int QTouchEvent::TouchPoint::id() const +{ + return d->id; +} + +/*! + Returns the current state of this touch point. +*/ +Qt::TouchPointState QTouchEvent::TouchPoint::state() const +{ + return d->state; +} + +/*! + Returns the position of this touch point, relative to the widget + that received the event. +*/ +const QPointF &QTouchEvent::TouchPoint::pos() const +{ + return d->pos; +} + +/*! + Returns the starting position of this touch point, relative to the + widget that received the event. +*/ +const QPointF &QTouchEvent::TouchPoint::startPos() const +{ + return d->startPos; +} + +/*! + Returns the position of this touch point from the previous touch + event, relative to the widget that received the event. +*/ +const QPointF &QTouchEvent::TouchPoint::lastPos() const +{ + return d->lastPos; +} + +/*! + Returns the global position of this touch point. +*/ +const QPointF &QTouchEvent::TouchPoint::globalPos() const +{ + return d->globalPos; +} + +/*! + Returns the global starting position of this touch point. +*/ +const QPointF &QTouchEvent::TouchPoint::startGlobalPos() const +{ + return d->startGlobalPos; +} + +/*! + Returns the global position of this touch point from the previous + touch event. +*/ +const QPointF &QTouchEvent::TouchPoint::lastGlobalPos() const +{ + return d->lastGlobalPos; +} + +/*! + Returns the pressure of this touch point. The return value is in + the range 0.0 to 1.0. +*/ +qreal QTouchEvent::TouchPoint::pressure() const +{ + return d->pressure; +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index 449730d..3cb712d 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -719,6 +719,47 @@ inline bool operator==(QKeyEvent *e, QKeySequence::StandardKey key){return (e ? inline bool operator==(QKeySequence::StandardKey key, QKeyEvent *e){return (e ? e->matches(key) : false);} #endif // QT_NO_SHORTCUT +class QTouchEventTouchPointPrivate; +class Q_GUI_EXPORT QTouchEvent : public QInputEvent +{ +public: + class Q_GUI_EXPORT TouchPoint + { + public: + TouchPoint(int id = -1); + ~TouchPoint(); + + int id() const; + + Qt::TouchPointState state() const; + + const QPointF &pos() const; + const QPointF &startPos() const; + const QPointF &lastPos() const; + + const QPointF &globalPos() const; + const QPointF &startGlobalPos() const; + const QPointF &lastGlobalPos() const; + + qreal pressure() const; // 0.0 -> 1.0 + + private: + QTouchEventTouchPointPrivate *d; + + friend class QApplicationPrivate; + }; + + QTouchEvent(QEvent::Type type, + Qt::KeyboardModifiers modifiers, + const QList &touchPoints); + + inline const QList &touchPoints() const { return _touchPoints; + } + +protected: + QList _touchPoints; +}; + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h index cc94aad..5e24eeb 100644 --- a/src/gui/kernel/qevent_p.h +++ b/src/gui/kernel/qevent_p.h @@ -89,6 +89,22 @@ protected: friend class QMouseEvent; }; +class QTouchEventTouchPointPrivate +{ +public: + inline QTouchEventTouchPointPrivate(int id) + : id(id), + state(Qt::TouchPointReleased), + pressure(qreal(-1.)) + { } + + int id; + Qt::TouchPointState state; + QPointF pos, startPos, lastPos; + QPointF globalPos, startGlobalPos, lastGlobalPos; + qreal pressure; +}; + QT_END_NAMESPACE #endif // QEVENT_P_H -- cgit v0.12 From 075a8a30560e20fee94d47aa447daa15f4cb138f Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Tue, 24 Mar 2009 12:01:44 +0100 Subject: add QGraphicsItem::acceptTouchEvents() and setAcceptTouchEvents() like Qt::WA_AcceptTouchEvents, QGraphicsItems don't receive touch events unless touch events are explicitly enabled. --- src/gui/graphicsview/qgraphicsitem.cpp | 25 +++++++++++++++++++++++++ src/gui/graphicsview/qgraphicsitem.h | 2 ++ src/gui/graphicsview/qgraphicsitem_p.h | 2 ++ 3 files changed, 29 insertions(+) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index fc81f39..0b51c8c 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -2063,6 +2063,31 @@ void QGraphicsItem::setAcceptsHoverEvents(bool enabled) d_ptr->acceptsHover = quint32(enabled); } +/*! \since 4.6 + + Returns true if an item accepts touch events + (QGraphicsSceneTouchEvent); otherwise, returns false. By default, + items do not accept touch events. + + \sa setAcceptTouchEvents() +*/ +bool QGraphicsItem::acceptTouchEvents() const +{ + return d_ptr->acceptTouchEvents; +} + +/*! + \since 4.6 + + If \a enabled is true, this item will accept touch events; + otherwise, it will ignore them. By default, items do not accept + touch events. +*/ +void QGraphicsItem::setAcceptTouchEvents(bool enabled) +{ + d_ptr->acceptTouchEvents = quint32(enabled); +} + /*! Returns true if this item handles child events (i.e., all events intended for any of its children are instead sent to this item); diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index b98882d..ec3373a 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -203,6 +203,8 @@ public: void setAcceptsHoverEvents(bool enabled); // obsolete bool acceptHoverEvents() const; void setAcceptHoverEvents(bool enabled); + bool acceptTouchEvents() const; + void setAcceptTouchEvents(bool enabled); bool handlesChildEvents() const; void setHandlesChildEvents(bool enabled); diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index af0b077..228368c 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -138,6 +138,7 @@ public: dirty(0), dirtyChildren(0), localCollisionHack(0), + acceptTouchEvents(0), globalStackingOrder(-1), sceneTransformIndex(-1), q_ptr(0) @@ -272,6 +273,7 @@ public: quint32 dirty : 1; quint32 dirtyChildren : 1; quint32 localCollisionHack : 1; + quint32 acceptTouchEvents : 1; // Optional stacking order int globalStackingOrder; -- cgit v0.12 From b9b9fc18d8ea5e9ddc2508ac6e9ce24960a8c24a Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Tue, 24 Mar 2009 12:03:21 +0100 Subject: implement support for touch events in QGraphicsScene QGraphicsView will convert QTouchEvents to QGraphicsSceneTouchEvents and send them to the scene. The scene will then send the touch events to the appropriate item. Like mouse event support, the item that accepts the touch begin is the item that will get all subsequent touch events. if no item accepts the touch begin event, then no touch events are sent to any item (and mouse events are sent instead). --- src/gui/graphicsview/qgraphicsscene.cpp | 166 ++++++++++++++++++++++++++++++++ src/gui/graphicsview/qgraphicsscene_p.h | 6 ++ src/gui/graphicsview/qgraphicsview.cpp | 106 ++++++++++++++++++++ src/gui/graphicsview/qgraphicsview_p.h | 5 + 4 files changed, 283 insertions(+) diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 553967c..b47ed5e 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -3609,6 +3609,9 @@ bool QGraphicsScene::event(QEvent *event) case QEvent::GraphicsSceneHoverEnter: case QEvent::GraphicsSceneHoverLeave: case QEvent::GraphicsSceneHoverMove: + case QEvent::GraphicsSceneTouchBegin: + case QEvent::GraphicsSceneTouchUpdate: + case QEvent::GraphicsSceneTouchEnd: // Reset the under-mouse list to ensure that this event gets fresh // item-under-mouse data. Be careful about this list; if people delete // items from inside event handlers, this list can quickly end up @@ -3760,6 +3763,15 @@ bool QGraphicsScene::event(QEvent *event) // geometries that do not have an explicit style set. update(); break; + case QEvent::GraphicsSceneTouchBegin: + d->touchBeginEvent(static_cast(event)); + break; + case QEvent::GraphicsSceneTouchUpdate: + d->touchUpdateEvent(static_cast(event)); + break; + case QEvent::GraphicsSceneTouchEnd: + d->touchEndEvent(static_cast(event)); + break; case QEvent::Timer: if (d->indexTimerId && static_cast(event)->timerId() == d->indexTimerId) { if (d->restartIndexTimer) { @@ -5370,6 +5382,160 @@ void QGraphicsScene::setActiveWindow(QGraphicsWidget *widget) } } +// ### FIXME: the code for touch event support is mosly copied from +// ### QGraphicsScenePrivate::mousePressEventHandler() and friends, need to +// ### refactor to reduce code duplication + +void QGraphicsScenePrivate::sendTouchEvent(QGraphicsSceneTouchEvent *touchEvent) +{ + if (touchEvent->type() == QEvent::GraphicsSceneTouchEnd && lastMouseGrabberItemHasImplicitMouseGrab) { + clearMouseGrabber(); + return; + } + + QGraphicsItem *item = mouseGrabberItems.last(); + QList touchPoints = touchEvent->touchPoints(); + for (int i = 0; i < touchPoints.count(); ++i) { + QGraphicsSceneTouchEvent::TouchPoint *touchPoint = touchPoints.at(i); + touchPoint->setPos(item->d_ptr->genericMapFromScene(touchPoint->scenePos(), touchEvent->widget())); + touchPoint->setStartPos(item->d_ptr->genericMapFromScene(touchPoint->startScenePos(), touchEvent->widget())); + touchPoint->setLastPos(item->d_ptr->genericMapFromScene(touchPoint->lastScenePos(), touchEvent->widget())); + } + sendEvent(item, touchEvent); +} + +void QGraphicsScenePrivate::touchBeginEvent(QGraphicsSceneTouchEvent *touchEvent) +{ + Q_Q(QGraphicsScene); + + // Ignore by default, unless we find a mouse grabber that accepts it. + touchEvent->ignore(); + + // Deliver to any existing mouse grabber. + if (!mouseGrabberItems.isEmpty()) { + // The event is ignored by default, but we disregard the event's + // accepted state after delivery; the mouse is grabbed, after all. + sendTouchEvent(touchEvent); + return; + } + + // Start by determining the number of items at the current position. + // Reuse value from earlier calculations if possible. + if (cachedItemsUnderMouse.isEmpty()) { + QGraphicsSceneTouchEvent::TouchPoint *touchPoint = touchEvent->touchPoints().first(); + // ### FIXME: should the itemsAtPosition() function support sub-pixel screenPos? + cachedItemsUnderMouse = itemsAtPosition(touchPoint->screenPos().toPoint(), + touchPoint->scenePos(), + touchEvent->widget()); + } + + // Update window activation. + QGraphicsWidget *newActiveWindow = windowForItem(cachedItemsUnderMouse.value(0)); + if (newActiveWindow != activeWindow) + q->setActiveWindow(newActiveWindow); + + // Set focus on the topmost enabled item that can take focus. + bool setFocus = false; + foreach (QGraphicsItem *item, cachedItemsUnderMouse) { + if (item->isEnabled() && (item->flags() & QGraphicsItem::ItemIsFocusable)) { + if (!item->isWidget() || ((QGraphicsWidget *)item)->focusPolicy() & Qt::ClickFocus) { + setFocus = true; + if (item != q->focusItem()) + q->setFocusItem(item, Qt::MouseFocusReason); + break; + } + } + } + + // If nobody could take focus, clear it. + if (!stickyFocus && !setFocus) + q->setFocusItem(0, Qt::MouseFocusReason); + + // Find a mouse grabber by sending touch events to all mouse grabber + // candidates one at a time, until the event is accepted. It's accepted by + // default, so the receiver has to explicitly ignore it for it to pass + // through. + foreach (QGraphicsItem *item, cachedItemsUnderMouse) { + if (!item->acceptTouchEvents()) { + // Skip items that don't accept the touch events + continue; + } + + grabMouse(item, /* implicit = */ true); + touchEvent->accept(); + + // check if the item we are sending to are disabled (before we send the event) + bool disabled = !item->isEnabled(); + bool isWindow = item->isWindow(); + sendTouchEvent(touchEvent); + + bool dontSendUngrabEvents = mouseGrabberItems.isEmpty() || mouseGrabberItems.last() != item; + if (disabled) { + ungrabMouse(item, /* itemIsDying = */ dontSendUngrabEvents); + break; + } + if (touchEvent->isAccepted()) { + lastMouseGrabberItem = item; + return; + } + ungrabMouse(item, /* itemIsDying = */ dontSendUngrabEvents); + + // Don't propagate through windows. + if (isWindow) + break; + } + + // Is the event still ignored? Then the mouse press goes to the scene. + // Reset the mouse grabber, clear the selection, clear focus, and leave + // the event ignored so that it can propagate through the originating + // view. + if (!touchEvent->isAccepted()) { + clearMouseGrabber(); + + QGraphicsView *view = touchEvent->widget() ? qobject_cast(touchEvent->widget()->parentWidget()) : 0; + bool dontClearSelection = view && view->dragMode() == QGraphicsView::ScrollHandDrag; + if (!dontClearSelection) { + // Clear the selection if the originating view isn't in scroll + // hand drag mode. The view will clear the selection if no drag + // happened. + q->clearSelection(); + } + } +} + +void QGraphicsScenePrivate::touchUpdateEvent(QGraphicsSceneTouchEvent *touchEvent) +{ + if (mouseGrabberItems.isEmpty()) { + touchEvent->ignore(); + return; + } + + // Forward the event to the mouse grabber + sendTouchEvent(touchEvent); + touchEvent->accept(); +} + +void QGraphicsScenePrivate::touchEndEvent(QGraphicsSceneTouchEvent *touchEvent) +{ + if (mouseGrabberItems.isEmpty()) { + touchEvent->ignore(); + return; + } + + // Forward the event to the mouse grabber + sendTouchEvent(touchEvent); + touchEvent->accept(); + + // Reset the mouse grabber + if (!mouseGrabberItems.isEmpty()) { + lastMouseGrabberItem = mouseGrabberItems.last(); + if (lastMouseGrabberItemHasImplicitMouseGrab) + mouseGrabberItems.last()->ungrabMouse(); + } else { + lastMouseGrabberItem = 0; + } +} + QT_END_NAMESPACE #include "moc_qgraphicsscene.cpp" diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 7f441da..d5e539b 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -73,6 +73,7 @@ QT_BEGIN_NAMESPACE class QGraphicsView; class QGraphicsWidget; +class QGraphicsSceneTouchEvent; class QGraphicsScenePrivate : public QObjectPrivate { @@ -259,6 +260,11 @@ public: mutable QVector sceneTransformCache; mutable QBitArray validTransforms; mutable QVector freeSceneTransformSlots; + + void sendTouchEvent(QGraphicsSceneTouchEvent *touchEvent); + void touchBeginEvent(QGraphicsSceneTouchEvent *touchEvent); + void touchUpdateEvent(QGraphicsSceneTouchEvent *touchEvent); + void touchEndEvent(QGraphicsSceneTouchEvent *touchEvent); }; QT_END_NAMESPACE diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index a661441..f95d328 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -2926,6 +2926,28 @@ bool QGraphicsView::viewportEvent(QEvent *event) d->scene->d_func()->updateAll = false; } break; + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + { + if (!isEnabled()) + return false; + QTouchEvent *touchEvent = static_cast(event); + switch (touchEvent->type()) { + case QEvent::TouchBegin: + d->touchBeginEvent(touchEvent); + break; + case QEvent::TouchUpdate: + d->touchUpdateEvent(touchEvent); + break; + case QEvent::TouchEnd: + d->touchEndEvent(touchEvent); + break; + default: + break; + } + return true; + } default: break; } @@ -3864,6 +3886,90 @@ void QGraphicsView::resetTransform() setTransform(QTransform()); } +static void qt_convertTouchEventToGraphicsSceneTouchEvent(QGraphicsViewPrivate *d, QTouchEvent *originalEvent, QGraphicsSceneTouchEvent *touchEvent) +{ + QList originalTouchPoints = originalEvent->touchPoints(); + QList touchPoints; + for (int i = 0; i < originalTouchPoints.count(); ++i) { + QTouchEvent::TouchPoint *originalTouchPoint = originalTouchPoints.at(i); + + QGraphicsSceneTouchEvent::TouchPoint *touchPoint = new QGraphicsSceneTouchEvent::TouchPoint(); + touchPoint->setId(originalTouchPoint->id()); + touchPoint->setState(originalTouchPoint->state()); + // the scene will set the pos before delivering to an item + touchPoint->setScenePos(d->mapToScene(originalTouchPoint->pos())); + touchPoint->setScreenPos(originalTouchPoint->globalPos()); + // the scene will set the startPos before delivering to an item + touchPoint->setStartScenePos(d->mapToScene(originalTouchPoint->startPos())); + touchPoint->setStartScreenPos(originalTouchPoint->startGlobalPos()); + // the scene will set the lastPos before delivering to an item + touchPoint->setLastScenePos(d->mapToScene(originalTouchPoint->lastPos())); + touchPoint->setLastScreenPos(originalTouchPoint->lastGlobalPos()); + touchPoint->setPressure(originalTouchPoint->pressure()); + + touchPoints.append(touchPoint); + } + + touchEvent->setTouchPoints(touchPoints); + touchEvent->setModifiers(originalEvent->modifiers()); +} + +QPointF QGraphicsViewPrivate::mapToScene(const QPointF &point) const +{ + QPointF p = point; + p.rx() += horizontalScroll(); + p.ry() += verticalScroll(); + return identityMatrix ? p : matrix.inverted().map(p); +} + +void QGraphicsViewPrivate::touchBeginEvent(QTouchEvent *event) +{ + Q_Q(QGraphicsView); + + if (!scene || !sceneInteractionAllowed) + return; + + // Convert and deliver the touch event to the scene. + QGraphicsSceneTouchEvent touchEvent(QEvent::GraphicsSceneTouchBegin); + touchEvent.setWidget(q->viewport()); + qt_convertTouchEventToGraphicsSceneTouchEvent(this, event, &touchEvent); + touchEvent.setAccepted(false); + QApplication::sendEvent(scene, &touchEvent); + event->setAccepted(touchEvent.isAccepted()); +} + +void QGraphicsViewPrivate::touchUpdateEvent(QTouchEvent *event) +{ + Q_Q(QGraphicsView); + + if (!scene || !sceneInteractionAllowed) + return; + + // Convert and deliver the touch event to the scene. + QGraphicsSceneTouchEvent touchEvent(QEvent::GraphicsSceneTouchUpdate); + touchEvent.setWidget(q->viewport()); + qt_convertTouchEventToGraphicsSceneTouchEvent(this, event, &touchEvent); + touchEvent.setAccepted(false); + QApplication::sendEvent(scene, &touchEvent); + event->setAccepted(touchEvent.isAccepted()); +} + +void QGraphicsViewPrivate::touchEndEvent(QTouchEvent *event) +{ + Q_Q(QGraphicsView); + + if (!scene || !sceneInteractionAllowed) + return; + + // Convert and deliver the touch event to the scene. + QGraphicsSceneTouchEvent touchEvent(QEvent::GraphicsSceneTouchEnd); + touchEvent.setWidget(q->viewport()); + qt_convertTouchEventToGraphicsSceneTouchEvent(this, event, &touchEvent); + touchEvent.setAccepted(false); + QApplication::sendEvent(scene, &touchEvent); + event->setAccepted(touchEvent.isAccepted()); +} + QT_END_NAMESPACE #include "moc_qgraphicsview.cpp" diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h index 2109673..e9479f3 100644 --- a/src/gui/graphicsview/qgraphicsview_p.h +++ b/src/gui/graphicsview/qgraphicsview_p.h @@ -182,6 +182,11 @@ public: const QTransform &worldTransform, bool allItems, const QRegion &exposedRegion) const; + + QPointF mapToScene(const QPointF &point) const; + void touchBeginEvent(QTouchEvent *event); + void touchUpdateEvent(QTouchEvent *event); + void touchEndEvent(QTouchEvent *event); }; QT_END_NAMESPACE -- cgit v0.12 From 96741cb1aba9feaf0099910884bee5241e52f794 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Tue, 24 Mar 2009 14:59:07 +0100 Subject: add a multitouch pinchzoom example, based on the collidingmice example --- examples/multitouch/multitouch.pro | 2 + examples/multitouch/pinchzoom/graphicsview.cpp | 78 +++++++++ examples/multitouch/pinchzoom/graphicsview.h | 53 +++++++ examples/multitouch/pinchzoom/images/cheese.jpg | Bin 0 -> 3029 bytes examples/multitouch/pinchzoom/main.cpp | 88 +++++++++++ examples/multitouch/pinchzoom/mice.qrc | 5 + examples/multitouch/pinchzoom/mouse.cpp | 200 ++++++++++++++++++++++++ examples/multitouch/pinchzoom/mouse.h | 72 +++++++++ examples/multitouch/pinchzoom/pinchzoom.pro | 16 ++ 9 files changed, 514 insertions(+) create mode 100644 examples/multitouch/multitouch.pro create mode 100644 examples/multitouch/pinchzoom/graphicsview.cpp create mode 100644 examples/multitouch/pinchzoom/graphicsview.h create mode 100644 examples/multitouch/pinchzoom/images/cheese.jpg create mode 100644 examples/multitouch/pinchzoom/main.cpp create mode 100644 examples/multitouch/pinchzoom/mice.qrc create mode 100644 examples/multitouch/pinchzoom/mouse.cpp create mode 100644 examples/multitouch/pinchzoom/mouse.h create mode 100644 examples/multitouch/pinchzoom/pinchzoom.pro diff --git a/examples/multitouch/multitouch.pro b/examples/multitouch/multitouch.pro new file mode 100644 index 0000000..7efa412 --- /dev/null +++ b/examples/multitouch/multitouch.pro @@ -0,0 +1,2 @@ +TEMPLATE = subdirs +SUBDIRS = pinchzoom \ No newline at end of file diff --git a/examples/multitouch/pinchzoom/graphicsview.cpp b/examples/multitouch/pinchzoom/graphicsview.cpp new file mode 100644 index 0000000..b77c926 --- /dev/null +++ b/examples/multitouch/pinchzoom/graphicsview.cpp @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "graphicsview.h" + +#include + + +GraphicsView::GraphicsView(QGraphicsScene *scene, QWidget *parent) + : QGraphicsView(scene, parent) +{ + setAttribute(Qt::WA_AcceptTouchEvents); +} + +bool GraphicsView::event(QEvent *event) +{ + switch (event->type()) { + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + { + qDebug("touch events"); + + QList touchPoints = static_cast(event)->touchPoints(); + if (touchPoints.count() == 2) { + // determine scale factor + const QTouchEvent::TouchPoint *touchPoint0 = touchPoints.first(); + const QTouchEvent::TouchPoint *touchPoint1 = touchPoints.last(); + const qreal scaleFactor = QLineF(touchPoint0->pos(), touchPoint1->pos()).length() + / QLineF(touchPoint0->startPos(), touchPoint1->startPos()).length(); + setTransform(QTransform().scale(scaleFactor, scaleFactor)); + } + event->accept(); + return true; + } + default: + break; + } + return QGraphicsView::event(event); +} diff --git a/examples/multitouch/pinchzoom/graphicsview.h b/examples/multitouch/pinchzoom/graphicsview.h new file mode 100644 index 0000000..626f23c --- /dev/null +++ b/examples/multitouch/pinchzoom/graphicsview.h @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#pragma once +#include + +class GraphicsView : public QGraphicsView +{ + Q_OBJECT + +public: + GraphicsView(QGraphicsScene *scene = 0, QWidget *parent = 0); + + bool event(QEvent *event); +}; diff --git a/examples/multitouch/pinchzoom/images/cheese.jpg b/examples/multitouch/pinchzoom/images/cheese.jpg new file mode 100644 index 0000000..dea5795 Binary files /dev/null and b/examples/multitouch/pinchzoom/images/cheese.jpg differ diff --git a/examples/multitouch/pinchzoom/main.cpp b/examples/multitouch/pinchzoom/main.cpp new file mode 100644 index 0000000..6b25060 --- /dev/null +++ b/examples/multitouch/pinchzoom/main.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "graphicsview.h" +#include "mouse.h" + +#include + +#include + +static const int MouseCount = 7; + +//! [0] +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); +//! [0] + +//! [1] + QGraphicsScene scene; + scene.setSceneRect(-300, -300, 600, 600); +//! [1] //! [2] + scene.setItemIndexMethod(QGraphicsScene::NoIndex); +//! [2] + +//! [3] + for (int i = 0; i < MouseCount; ++i) { + Mouse *mouse = new Mouse; + mouse->setPos(::sin((i * 6.28) / MouseCount) * 200, + ::cos((i * 6.28) / MouseCount) * 200); + scene.addItem(mouse); + } +//! [3] + +//! [4] + GraphicsView view(&scene); + view.setRenderHint(QPainter::Antialiasing); + view.setBackgroundBrush(QPixmap(":/images/cheese.jpg")); +//! [4] //! [5] + view.setCacheMode(QGraphicsView::CacheBackground); + view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); + view.setDragMode(QGraphicsView::ScrollHandDrag); +//! [5] //! [6] + view.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Colliding Mice")); + view.showMaximized(); + + return app.exec(); +} +//! [6] diff --git a/examples/multitouch/pinchzoom/mice.qrc b/examples/multitouch/pinchzoom/mice.qrc new file mode 100644 index 0000000..accdb4d --- /dev/null +++ b/examples/multitouch/pinchzoom/mice.qrc @@ -0,0 +1,5 @@ + + + images/cheese.jpg + + diff --git a/examples/multitouch/pinchzoom/mouse.cpp b/examples/multitouch/pinchzoom/mouse.cpp new file mode 100644 index 0000000..1d9fa89 --- /dev/null +++ b/examples/multitouch/pinchzoom/mouse.cpp @@ -0,0 +1,200 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mouse.h" + +#include +#include +#include + +#include + +static const double Pi = 3.14159265358979323846264338327950288419717; +static double TwoPi = 2.0 * Pi; + +static qreal normalizeAngle(qreal angle) +{ + while (angle < 0) + angle += TwoPi; + while (angle > TwoPi) + angle -= TwoPi; + return angle; +} + +//! [0] +Mouse::Mouse() + : angle(0), speed(0), mouseEyeDirection(0), + color(qrand() % 256, qrand() % 256, qrand() % 256) +{ + rotate(qrand() % (360 * 16)); + startTimer(1000 / 33); +} +//! [0] + +//! [1] +QRectF Mouse::boundingRect() const +{ + qreal adjust = 0.5; + return QRectF(-18 - adjust, -22 - adjust, + 36 + adjust, 60 + adjust); +} +//! [1] + +//! [2] +QPainterPath Mouse::shape() const +{ + QPainterPath path; + path.addRect(-10, -20, 20, 40); + return path; +} +//! [2] + +//! [3] +void Mouse::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + // Body + painter->setBrush(color); + painter->drawEllipse(-10, -20, 20, 40); + + // Eyes + painter->setBrush(Qt::white); + painter->drawEllipse(-10, -17, 8, 8); + painter->drawEllipse(2, -17, 8, 8); + + // Nose + painter->setBrush(Qt::black); + painter->drawEllipse(QRectF(-2, -22, 4, 4)); + + // Pupils + painter->drawEllipse(QRectF(-8.0 + mouseEyeDirection, -17, 4, 4)); + painter->drawEllipse(QRectF(4.0 + mouseEyeDirection, -17, 4, 4)); + + // Ears + painter->setBrush(scene()->collidingItems(this).isEmpty() ? Qt::darkYellow : Qt::red); + painter->drawEllipse(-17, -12, 16, 16); + painter->drawEllipse(1, -12, 16, 16); + + // Tail + QPainterPath path(QPointF(0, 20)); + path.cubicTo(-5, 22, -5, 22, 0, 25); + path.cubicTo(5, 27, 5, 32, 0, 30); + path.cubicTo(-5, 32, -5, 42, 0, 35); + painter->setBrush(Qt::NoBrush); + painter->drawPath(path); +} +//! [3] + +//! [4] +void Mouse::timerEvent(QTimerEvent *) +{ +//! [4] + // Don't move too far away +//! [5] + QLineF lineToCenter(QPointF(0, 0), mapFromScene(0, 0)); + if (lineToCenter.length() > 150) { + qreal angleToCenter = ::acos(lineToCenter.dx() / lineToCenter.length()); + if (lineToCenter.dy() < 0) + angleToCenter = TwoPi - angleToCenter; + angleToCenter = normalizeAngle((Pi - angleToCenter) + Pi / 2); + + if (angleToCenter < Pi && angleToCenter > Pi / 4) { + // Rotate left + angle += (angle < -Pi / 2) ? 0.25 : -0.25; + } else if (angleToCenter >= Pi && angleToCenter < (Pi + Pi / 2 + Pi / 4)) { + // Rotate right + angle += (angle < Pi / 2) ? 0.25 : -0.25; + } + } else if (::sin(angle) < 0) { + angle += 0.25; + } else if (::sin(angle) > 0) { + angle -= 0.25; +//! [5] //! [6] + } +//! [6] + + // Try not to crash with any other mice +//! [7] + QList dangerMice = scene()->items(QPolygonF() + << mapToScene(0, 0) + << mapToScene(-30, -50) + << mapToScene(30, -50)); + foreach (QGraphicsItem *item, dangerMice) { + if (item == this) + continue; + + QLineF lineToMouse(QPointF(0, 0), mapFromItem(item, 0, 0)); + qreal angleToMouse = ::acos(lineToMouse.dx() / lineToMouse.length()); + if (lineToMouse.dy() < 0) + angleToMouse = TwoPi - angleToMouse; + angleToMouse = normalizeAngle((Pi - angleToMouse) + Pi / 2); + + if (angleToMouse >= 0 && angleToMouse < Pi / 2) { + // Rotate right + angle += 0.5; + } else if (angleToMouse <= TwoPi && angleToMouse > (TwoPi - Pi / 2)) { + // Rotate left + angle -= 0.5; +//! [7] //! [8] + } +//! [8] //! [9] + } +//! [9] + + // Add some random movement +//! [10] + if (dangerMice.size() > 1 && (qrand() % 10) == 0) { + if (qrand() % 1) + angle += (qrand() % 100) / 500.0; + else + angle -= (qrand() % 100) / 500.0; + } +//! [10] + +//! [11] + speed += (-50 + qrand() % 100) / 100.0; + + qreal dx = ::sin(angle) * 10; + mouseEyeDirection = (qAbs(dx / 5) < 1) ? 0 : dx / 5; + + rotate(dx); + setPos(mapToParent(0, -(3 + sin(speed) * 3))); +} +//! [11] diff --git a/examples/multitouch/pinchzoom/mouse.h b/examples/multitouch/pinchzoom/mouse.h new file mode 100644 index 0000000..7545fe6 --- /dev/null +++ b/examples/multitouch/pinchzoom/mouse.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MOUSE_H +#define MOUSE_H + +#include +#include + +//! [0] +class Mouse : public QObject, public QGraphicsItem +{ + Q_OBJECT + +public: + Mouse(); + + QRectF boundingRect() const; + QPainterPath shape() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, + QWidget *widget); + +protected: + void timerEvent(QTimerEvent *event); + +private: + qreal angle; + qreal speed; + qreal mouseEyeDirection; + QColor color; +}; +//! [0] + +#endif diff --git a/examples/multitouch/pinchzoom/pinchzoom.pro b/examples/multitouch/pinchzoom/pinchzoom.pro new file mode 100644 index 0000000..bd87cf7 --- /dev/null +++ b/examples/multitouch/pinchzoom/pinchzoom.pro @@ -0,0 +1,16 @@ +HEADERS += \ + mouse.h \ + graphicsview.h +SOURCES += \ + main.cpp \ + mouse.cpp \ + graphicsview.cpp + +RESOURCES += \ + mice.qrc + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/multitouch/pinchzoom +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS pinchzoom.pro images +sources.path = $$[QT_INSTALL_EXAMPLES]/multitouch/pinchzoom +INSTALLS += target sources -- cgit v0.12 From 98619f427322ac7889b3db6f8991ca079209cec7 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Wed, 25 Mar 2009 11:31:33 +0100 Subject: add the multitouch fingerpaint example, based on the scribble example --- examples/multitouch/fingerpaint/fingerpaint.pro | 11 ++ examples/multitouch/fingerpaint/main.cpp | 52 ++++++ examples/multitouch/fingerpaint/mainwindow.cpp | 218 +++++++++++++++++++++++ examples/multitouch/fingerpaint/mainwindow.h | 89 +++++++++ examples/multitouch/fingerpaint/scribblearea.cpp | 213 ++++++++++++++++++++++ examples/multitouch/fingerpaint/scribblearea.h | 81 +++++++++ 6 files changed, 664 insertions(+) create mode 100644 examples/multitouch/fingerpaint/fingerpaint.pro create mode 100644 examples/multitouch/fingerpaint/main.cpp create mode 100644 examples/multitouch/fingerpaint/mainwindow.cpp create mode 100644 examples/multitouch/fingerpaint/mainwindow.h create mode 100644 examples/multitouch/fingerpaint/scribblearea.cpp create mode 100644 examples/multitouch/fingerpaint/scribblearea.h diff --git a/examples/multitouch/fingerpaint/fingerpaint.pro b/examples/multitouch/fingerpaint/fingerpaint.pro new file mode 100644 index 0000000..1d45635 --- /dev/null +++ b/examples/multitouch/fingerpaint/fingerpaint.pro @@ -0,0 +1,11 @@ +HEADERS = mainwindow.h \ + scribblearea.h +SOURCES = main.cpp \ + mainwindow.cpp \ + scribblearea.cpp + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/multitouch/fingerpaint +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS fingerpaint.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/multitouch/fingerpaint +INSTALLS += target sources diff --git a/examples/multitouch/fingerpaint/main.cpp b/examples/multitouch/fingerpaint/main.cpp new file mode 100644 index 0000000..49bf25b --- /dev/null +++ b/examples/multitouch/fingerpaint/main.cpp @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "mainwindow.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + MainWindow window; + window.showMaximized(); + return app.exec(); +} diff --git a/examples/multitouch/fingerpaint/mainwindow.cpp b/examples/multitouch/fingerpaint/mainwindow.cpp new file mode 100644 index 0000000..546c685 --- /dev/null +++ b/examples/multitouch/fingerpaint/mainwindow.cpp @@ -0,0 +1,218 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "mainwindow.h" +#include "scribblearea.h" + +//! [0] +MainWindow::MainWindow() +{ + scribbleArea = new ScribbleArea; + setCentralWidget(scribbleArea); + + createActions(); + createMenus(); + + setWindowTitle(tr("Scribble")); + resize(500, 500); +} +//! [0] + +//! [1] +void MainWindow::closeEvent(QCloseEvent *event) +//! [1] //! [2] +{ + if (maybeSave()) { + event->accept(); + } else { + event->ignore(); + } +} +//! [2] + +//! [3] +void MainWindow::open() +//! [3] //! [4] +{ + if (maybeSave()) { + QString fileName = QFileDialog::getOpenFileName(this, + tr("Open File"), QDir::currentPath()); + if (!fileName.isEmpty()) + scribbleArea->openImage(fileName); + } +} +//! [4] + +//! [5] +void MainWindow::save() +//! [5] //! [6] +{ + QAction *action = qobject_cast(sender()); + QByteArray fileFormat = action->data().toByteArray(); + saveFile(fileFormat); +} +//! [6] + +//! [11] +void MainWindow::about() +//! [11] //! [12] +{ + QMessageBox::about(this, tr("About Scribble"), + tr("

The Scribble example shows how to use QMainWindow as the " + "base widget for an application, and how to reimplement some of " + "QWidget's event handlers to receive the events generated for " + "the application's widgets:

We reimplement the mouse event " + "handlers to facilitate drawing, the paint event handler to " + "update the application and the resize event handler to optimize " + "the application's appearance. In addition we reimplement the " + "close event handler to intercept the close events before " + "terminating the application.

The example also demonstrates " + "how to use QPainter to draw an image in real time, as well as " + "to repaint widgets.

")); +} +//! [12] + +//! [13] +void MainWindow::createActions() +//! [13] //! [14] +{ + openAct = new QAction(tr("&Open..."), this); + openAct->setShortcut(tr("Ctrl+O")); + connect(openAct, SIGNAL(triggered()), this, SLOT(open())); + + foreach (QByteArray format, QImageWriter::supportedImageFormats()) { + QString text = tr("%1...").arg(QString(format).toUpper()); + + QAction *action = new QAction(text, this); + action->setData(format); + connect(action, SIGNAL(triggered()), this, SLOT(save())); + saveAsActs.append(action); + } + + printAct = new QAction(tr("&Print..."), this); + connect(printAct, SIGNAL(triggered()), scribbleArea, SLOT(print())); + + exitAct = new QAction(tr("E&xit"), this); + exitAct->setShortcut(tr("Ctrl+Q")); + connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); + + clearScreenAct = new QAction(tr("&Clear Screen"), this); + clearScreenAct->setShortcut(tr("Ctrl+L")); + connect(clearScreenAct, SIGNAL(triggered()), + scribbleArea, SLOT(clearImage())); + + aboutAct = new QAction(tr("&About"), this); + connect(aboutAct, SIGNAL(triggered()), this, SLOT(about())); + + aboutQtAct = new QAction(tr("About &Qt"), this); + connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt())); +} +//! [14] + +//! [15] +void MainWindow::createMenus() +//! [15] //! [16] +{ + saveAsMenu = new QMenu(tr("&Save As"), this); + foreach (QAction *action, saveAsActs) + saveAsMenu->addAction(action); + + fileMenu = new QMenu(tr("&File"), this); + fileMenu->addAction(openAct); + fileMenu->addMenu(saveAsMenu); + fileMenu->addAction(printAct); + fileMenu->addSeparator(); + fileMenu->addAction(exitAct); + + optionMenu = new QMenu(tr("&Options"), this); + optionMenu->addAction(clearScreenAct); + + helpMenu = new QMenu(tr("&Help"), this); + helpMenu->addAction(aboutAct); + helpMenu->addAction(aboutQtAct); + + menuBar()->addMenu(fileMenu); + menuBar()->addMenu(optionMenu); + menuBar()->addMenu(helpMenu); +} +//! [16] + +//! [17] +bool MainWindow::maybeSave() +//! [17] //! [18] +{ + if (scribbleArea->isModified()) { + QMessageBox::StandardButton ret; + ret = QMessageBox::warning(this, tr("Scribble"), + tr("The image has been modified.\n" + "Do you want to save your changes?"), + QMessageBox::Save | QMessageBox::Discard + | QMessageBox::Cancel); + if (ret == QMessageBox::Save) { + return saveFile("png"); + } else if (ret == QMessageBox::Cancel) { + return false; + } + } + return true; +} +//! [18] + +//! [19] +bool MainWindow::saveFile(const QByteArray &fileFormat) +//! [19] //! [20] +{ + QString initialPath = QDir::currentPath() + "/untitled." + fileFormat; + + QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), + initialPath, + tr("%1 Files (*.%2);;All Files (*)") + .arg(QString(fileFormat.toUpper())) + .arg(QString(fileFormat))); + if (fileName.isEmpty()) { + return false; + } else { + return scribbleArea->saveImage(fileName, fileFormat); + } +} +//! [20] diff --git a/examples/multitouch/fingerpaint/mainwindow.h b/examples/multitouch/fingerpaint/mainwindow.h new file mode 100644 index 0000000..fdb790d --- /dev/null +++ b/examples/multitouch/fingerpaint/mainwindow.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include + +class ScribbleArea; + +//! [0] +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + MainWindow(); + +protected: + void closeEvent(QCloseEvent *event); + +private slots: + void open(); + void save(); + void about(); + +private: + void createActions(); + void createMenus(); + bool maybeSave(); + bool saveFile(const QByteArray &fileFormat); + + ScribbleArea *scribbleArea; + + QMenu *saveAsMenu; + QMenu *fileMenu; + QMenu *optionMenu; + QMenu *helpMenu; + + QAction *openAct; + QList saveAsActs; + QAction *exitAct; + QAction *printAct; + QAction *clearScreenAct; + QAction *aboutAct; + QAction *aboutQtAct; +}; +//! [0] + +#endif diff --git a/examples/multitouch/fingerpaint/scribblearea.cpp b/examples/multitouch/fingerpaint/scribblearea.cpp new file mode 100644 index 0000000..a042fe7 --- /dev/null +++ b/examples/multitouch/fingerpaint/scribblearea.cpp @@ -0,0 +1,213 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "scribblearea.h" + +//! [0] +ScribbleArea::ScribbleArea(QWidget *parent) + : QWidget(parent) +{ + setAttribute(Qt::WA_AcceptTouchEvents); + setAttribute(Qt::WA_StaticContents); + modified = false; + + myPenColors + << QColor("green") + << QColor("purple") + << QColor("red") + << QColor("blue") + << QColor("yellow") + + << QColor("pink") + << QColor("orange") + << QColor("brown") + << QColor("grey") + << QColor("black"); +} +//! [0] + +//! [1] +bool ScribbleArea::openImage(const QString &fileName) +//! [1] //! [2] +{ + QImage loadedImage; + if (!loadedImage.load(fileName)) + return false; + + QSize newSize = loadedImage.size().expandedTo(size()); + resizeImage(&loadedImage, newSize); + image = loadedImage; + modified = false; + update(); + return true; +} +//! [2] + +//! [3] +bool ScribbleArea::saveImage(const QString &fileName, const char *fileFormat) +//! [3] //! [4] +{ + QImage visibleImage = image; + resizeImage(&visibleImage, size()); + + if (visibleImage.save(fileName, fileFormat)) { + modified = false; + return true; + } else { + return false; + } +} +//! [4] + +//! [9] +void ScribbleArea::clearImage() +//! [9] //! [10] +{ + image.fill(qRgb(255, 255, 255)); + modified = true; + update(); +} +//! [10] + +//! [12] //! [13] +void ScribbleArea::paintEvent(QPaintEvent *event) +//! [13] //! [14] +{ + QPainter painter(this); + const QRect rect = event->rect(); + painter.drawImage(rect.topLeft(), image, rect); +} +//! [14] + +//! [15] +void ScribbleArea::resizeEvent(QResizeEvent *event) +//! [15] //! [16] +{ + if (width() > image.width() || height() > image.height()) { + int newWidth = qMax(width() + 128, image.width()); + int newHeight = qMax(height() + 128, image.height()); + resizeImage(&image, QSize(newWidth, newHeight)); + update(); + } + QWidget::resizeEvent(event); +} +//! [16] + +//! [19] +void ScribbleArea::resizeImage(QImage *image, const QSize &newSize) +//! [19] //! [20] +{ + if (image->size() == newSize) + return; + + QImage newImage(newSize, QImage::Format_RGB32); + newImage.fill(qRgb(255, 255, 255)); + QPainter painter(&newImage); + painter.drawImage(QPoint(0, 0), *image); + *image = newImage; +} +//! [20] + +//! [21] +void ScribbleArea::print() +{ +#ifndef QT_NO_PRINTER + QPrinter printer(QPrinter::HighResolution); + + QPrintDialog *printDialog = new QPrintDialog(&printer, this); +//! [21] //! [22] + if (printDialog->exec() == QDialog::Accepted) { + QPainter painter(&printer); + QRect rect = painter.viewport(); + QSize size = image.size(); + size.scale(rect.size(), Qt::KeepAspectRatio); + painter.setViewport(rect.x(), rect.y(), size.width(), size.height()); + painter.setWindow(image.rect()); + painter.drawImage(0, 0, image); + } +#endif // QT_NO_PRINTER +} +//! [22] + +bool ScribbleArea::event(QEvent *event) +{ + switch (event->type()) { + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + { + QList touchPoints = static_cast(event)->touchPoints(); + foreach (QTouchEvent::TouchPoint *touchPoint, touchPoints) { + switch (touchPoint->state()) { + case Qt::TouchPointStationary: + // don't do anything if this touch point hasn't moved + continue; + default: + { + int diameter = int(50 * touchPoint->pressure()); + QRectF rectF(0, 0, diameter, diameter); + rectF.moveCenter(touchPoint->pos()); + QRect rect = rectF.toRect(); + + QPainter painter(&image); + painter.setPen(Qt::NoPen); + painter.setBrush(myPenColors.at(touchPoint->id())); + painter.drawEllipse(rectF); + painter.end(); + + modified = true; + int rad = 2; + update(rect.adjusted(-rad,-rad, +rad, +rad)); + } + break; + } + } + + event->accept(); + return true; + } + default: + break; + } + return QWidget::event(event); +} diff --git a/examples/multitouch/fingerpaint/scribblearea.h b/examples/multitouch/fingerpaint/scribblearea.h new file mode 100644 index 0000000..8928ce1 --- /dev/null +++ b/examples/multitouch/fingerpaint/scribblearea.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef SCRIBBLEAREA_H +#define SCRIBBLEAREA_H + +#include +#include +#include +#include + +//! [0] +class ScribbleArea : public QWidget +{ + Q_OBJECT + +public: + ScribbleArea(QWidget *parent = 0); + + bool openImage(const QString &fileName); + bool saveImage(const QString &fileName, const char *fileFormat); + + bool isModified() const { return modified; } + +public slots: + void clearImage(); + void print(); + +protected: + void paintEvent(QPaintEvent *event); + void resizeEvent(QResizeEvent *event); + bool event(QEvent *event); + +private: + void resizeImage(QImage *image, const QSize &newSize); + + bool modified; + QList myPenColors; + QImage image; +}; +//! [0] + +#endif -- cgit v0.12 From b5236dedd9ab72d6e0bd09151a6f55bb40a7034c Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Wed, 25 Mar 2009 11:32:52 +0100 Subject: have the window title in the fingerpaint example say Finger Paint, not Scribble --- examples/multitouch/fingerpaint/mainwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/multitouch/fingerpaint/mainwindow.cpp b/examples/multitouch/fingerpaint/mainwindow.cpp index 546c685..e510f89 100644 --- a/examples/multitouch/fingerpaint/mainwindow.cpp +++ b/examples/multitouch/fingerpaint/mainwindow.cpp @@ -53,7 +53,7 @@ MainWindow::MainWindow() createActions(); createMenus(); - setWindowTitle(tr("Scribble")); + setWindowTitle(tr("Finger Paint")); resize(500, 500); } //! [0] -- cgit v0.12 From 81b5a795a47f6d03c81756d7b5b4501f60528c41 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Wed, 25 Mar 2009 11:34:20 +0100 Subject: add fingerpaint to examples\multitouch.pro --- examples/multitouch/multitouch.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/multitouch/multitouch.pro b/examples/multitouch/multitouch.pro index 7efa412..b2b2b76 100644 --- a/examples/multitouch/multitouch.pro +++ b/examples/multitouch/multitouch.pro @@ -1,2 +1,2 @@ TEMPLATE = subdirs -SUBDIRS = pinchzoom \ No newline at end of file +SUBDIRS = pinchzoom fingerpaint -- cgit v0.12 From e1dd9242895e27afa63b255198ad541f738c06ef Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Wed, 25 Mar 2009 11:52:33 +0100 Subject: remove code duplication for setting the focus widget based on t he focus policy refactor duplicated code in the mouse and wheel event handlers that sets the focus widget based on the widget's (or its ancestors) focus policy --- src/gui/kernel/qapplication.cpp | 46 ++++++++++++++++++++--------------------- src/gui/kernel/qapplication_p.h | 4 ++++ 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 1bbb019..34c2d74 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -3735,19 +3735,10 @@ bool QApplication::notify(QObject *receiver, QEvent *e) QPoint relpos = mouse->pos(); if (e->spontaneous()) { - if (e->type() == QEvent::MouseButtonPress) { - QWidget *fw = w; - while (fw) { - if (fw->isEnabled() - && QApplicationPrivate::shouldSetFocus(fw, Qt::ClickFocus)) { - fw->setFocus(Qt::MouseFocusReason); - break; - } - if (fw->isWindow()) - break; - fw = fw->parentWidget(); - } + QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, + Qt::ClickFocus, + Qt::MouseFocusReason); } if (e->type() == QEvent::MouseMove && mouse->buttons() == 0) { @@ -3829,17 +3820,9 @@ bool QApplication::notify(QObject *receiver, QEvent *e) bool eventAccepted = wheel->isAccepted(); if (e->spontaneous()) { - QWidget *fw = w; - while (fw) { - if (fw->isEnabled() - && QApplicationPrivate::shouldSetFocus(fw, Qt::WheelFocus)) { - fw->setFocus(Qt::MouseFocusReason); - break; - } - if (fw->isWindow()) - break; - fw = fw->parentWidget(); - } + QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, + Qt::WheelFocus, + Qt::MouseFocusReason); } while (w) { @@ -5033,6 +5016,23 @@ Qt::LayoutDirection QApplication::keyboardInputDirection() return qt_keymapper_private()->keyboardInputDirection; } +void QApplicationPrivate::giveFocusAccordingToFocusPolicy(QWidget *widget, + Qt::FocusPolicy focusPolicy, + Qt::FocusReason focusReason) +{ + QWidget *focusWidget = widget; + while (focusWidget) { + if (focusWidget->isEnabled() + && QApplicationPrivate::shouldSetFocus(focusWidget, focusPolicy)) { + focusWidget->setFocus(focusReason); + break; + } + if (focusWidget->isWindow()) + break; + focusWidget = focusWidget->parentWidget(); + } +} + bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy) { QWidget *f = w; diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 7487f0a..6d75f37 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -430,6 +430,10 @@ private: #endif static QApplicationPrivate *self; + + static void giveFocusAccordingToFocusPolicy(QWidget *w, + Qt::FocusPolicy focusPolicy, + Qt::FocusReason focusReason); static bool shouldSetFocus(QWidget *w, Qt::FocusPolicy policy); }; -- cgit v0.12 From 480b0fe494cc7dec7d8082860c6216e970ce6a57 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Wed, 25 Mar 2009 11:57:14 +0100 Subject: implement event propagation for touch events behavior is similar to that of QGraphicsScene mouse events: the first touch event (the TouchBegin) is propagated to all parents. if a widget accepts the event, it will receive all other touch events (the TouchUpdate and TouchEnd events). If no widget accepts the TouchBegin, then we will fallback to normal mouse events (TBD). --- src/gui/kernel/qapplication.cpp | 48 +++++++++++++++++++++++++++++++++++++++++ src/gui/kernel/qapplication_p.h | 3 +++ src/gui/kernel/qevent.h | 2 ++ 3 files changed, 53 insertions(+) diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 34c2d74..9c70208 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -85,6 +85,7 @@ #include #include "qapplication_p.h" +#include "qevent_p.h" #include "qwidget_p.h" #include "qapplication.h" @@ -4027,7 +4028,41 @@ bool QApplication::notify(QObject *receiver, QEvent *e) } break; #endif + case QEvent::TouchBegin: + // Note: TouchUpdate and TouchEnd events are sent to d->currentMultitouchWidget and never propagated + { + QWidget *widget = static_cast(receiver); + QTouchEvent *touchEvent = static_cast(e); + bool eventAccepted = touchEvent->isAccepted(); + + if (widget->testAttribute(Qt::WA_AcceptTouchEvents) && e->spontaneous()) { + // give the widget focus if the focus policy allows it + QApplicationPrivate::giveFocusAccordingToFocusPolicy(widget, + Qt::ClickFocus, + Qt::MouseFocusReason); + } + + while (widget) { + // first, try to deliver the touch event + touchEvent->ignore(); + res = widget->testAttribute(Qt::WA_AcceptTouchEvents) + && d->notify_helper(widget, touchEvent); + eventAccepted = touchEvent->isAccepted(); + touchEvent->spont = false; + if (res && eventAccepted) { + // the first widget to accept the TouchBegin gets an implicit grab. + d->currentMultitouchWidget = widget; + break; + } else if (widget->isWindow() || widget->testAttribute(Qt::WA_NoMousePropagation)) { + break; + } + widget = widget->parentWidget(); + d->updateTouchPointsForWidget(widget, touchEvent); + } + touchEvent->setAccepted(eventAccepted); + break; + } default: res = d->notify_helper(receiver, e); break; @@ -5046,6 +5081,19 @@ bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy) return true; } +void QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent) +{ + for (int i = 0; i < touchEvent->_touchPoints.count(); ++i) { + QTouchEvent::TouchPoint *touchPoint = touchEvent->_touchPoints.at(i); + + // preserve the sub-pixel resolution + const QPointF delta = touchPoint->d->globalPos - touchPoint->d->globalPos.toPoint(); + touchPoint->d->pos = widget->mapFromGlobal(touchPoint->d->globalPos.toPoint()) + delta; + touchPoint->d->startPos = widget->mapFromGlobal(touchPoint->d->startGlobalPos.toPoint()) + delta; + touchPoint->d->lastPos = widget->mapFromGlobal(touchPoint->d->lastGlobalPos.toPoint()) + delta; + } +} + QT_END_NAMESPACE #include "moc_qapplication.cpp" diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 6d75f37..252d0cb 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -424,6 +424,9 @@ public: void sendSyntheticEnterLeave(QWidget *widget); #endif + QPointer currentMultitouchWidget; + static void updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent); + private: #ifdef Q_WS_QWS QMap maxWindowRects; diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index 3cb712d..506e0c1 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -758,6 +758,8 @@ public: protected: QList _touchPoints; + + friend class QApplicationPrivate; }; QT_END_NAMESPACE -- cgit v0.12 From aa50245865b5bf8655ee3d476ee961009f0c314e Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Wed, 25 Mar 2009 13:38:02 +0100 Subject: add a multitouch example that shows how to handle multitouch events in QGraphicsItems --- examples/multitouch/knobs/knob.cpp | 93 +++++++++++++++++++++++++++++++++++++ examples/multitouch/knobs/knob.h | 55 ++++++++++++++++++++++ examples/multitouch/knobs/knobs.pro | 2 + examples/multitouch/knobs/main.cpp | 66 ++++++++++++++++++++++++++ examples/multitouch/multitouch.pro | 2 +- 5 files changed, 217 insertions(+), 1 deletion(-) create mode 100644 examples/multitouch/knobs/knob.cpp create mode 100644 examples/multitouch/knobs/knob.h create mode 100644 examples/multitouch/knobs/knobs.pro create mode 100644 examples/multitouch/knobs/main.cpp diff --git a/examples/multitouch/knobs/knob.cpp b/examples/multitouch/knobs/knob.cpp new file mode 100644 index 0000000..4622f69 --- /dev/null +++ b/examples/multitouch/knobs/knob.cpp @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "knob.h" + +#include +#include + +Knob::Knob() + : QGraphicsEllipseItem(-50, -50, 100, 100) +{ + setAcceptTouchEvents(true); + setBrush(Qt::lightGray); + + QGraphicsEllipseItem *leftItem = new QGraphicsEllipseItem(0, 0, 10, 10, this); + leftItem->setPos(-45, -5); + leftItem->setBrush(Qt::darkGreen); + + QGraphicsEllipseItem *rightItem = new QGraphicsEllipseItem(0, 0, 10, 10, this); + rightItem->setPos(35, -5); + rightItem->setBrush(Qt::darkRed); +} + +bool Knob::sceneEvent(QEvent *event) +{ + switch (event->type()) { + case QEvent::GraphicsSceneTouchBegin: + event->accept(); + break; + + case QEvent::GraphicsSceneTouchUpdate: + case QEvent::GraphicsSceneTouchEnd: + { + QGraphicsSceneTouchEvent *touchEvent = static_cast(event); + + if (touchEvent->touchPoints().count() == 2) { + QGraphicsSceneTouchEvent::TouchPoint *touchPoint1 = touchEvent->touchPoints().first(); + QGraphicsSceneTouchEvent::TouchPoint *touchPoint2 = touchEvent->touchPoints().last(); + + QLineF line1(touchPoint1->lastScenePos(), touchPoint2->lastScenePos()); + QLineF line2(touchPoint1->scenePos(), touchPoint2->scenePos()); + + rotate(line2.angleTo(line1)); + } + + touchEvent->accept(); + break; + } + + default: + return QGraphicsItem::sceneEvent(event); + } + + return true; +} diff --git a/examples/multitouch/knobs/knob.h b/examples/multitouch/knobs/knob.h new file mode 100644 index 0000000..1079483 --- /dev/null +++ b/examples/multitouch/knobs/knob.h @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef KNOB_H +#define KNOB_H + +#include + +class Knob : public QGraphicsEllipseItem +{ +public: + Knob(); + + bool sceneEvent(QEvent *event); +}; + +#endif // KNOB_H diff --git a/examples/multitouch/knobs/knobs.pro b/examples/multitouch/knobs/knobs.pro new file mode 100644 index 0000000..90f0ba5 --- /dev/null +++ b/examples/multitouch/knobs/knobs.pro @@ -0,0 +1,2 @@ +HEADERS = knob.h +SOURCES = main.cpp knob.cpp diff --git a/examples/multitouch/knobs/main.cpp b/examples/multitouch/knobs/main.cpp new file mode 100644 index 0000000..c5a7ea7 --- /dev/null +++ b/examples/multitouch/knobs/main.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +#include "knob.h" + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + QGraphicsScene scene; + QGraphicsView view(&scene); + view.viewport()->setAttribute(Qt::WA_AcceptTouchEvents); + + Knob *knob1 = new Knob; + knob1->setPos(-110, 0); + Knob *knob2 = new Knob; + + scene.addItem(knob1); + scene.addItem(knob2); + + view.showFullScreen(); + view.fitInView(scene.sceneRect().adjusted(-20, -20, 20, 20), Qt::KeepAspectRatio); + + return app.exec(); +} diff --git a/examples/multitouch/multitouch.pro b/examples/multitouch/multitouch.pro index b2b2b76..b3d1d55 100644 --- a/examples/multitouch/multitouch.pro +++ b/examples/multitouch/multitouch.pro @@ -1,2 +1,2 @@ TEMPLATE = subdirs -SUBDIRS = pinchzoom fingerpaint +SUBDIRS = pinchzoom fingerpaint knobs -- cgit v0.12 From 0103e7871000f224a1048649b4eca18a7840fe3b Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Wed, 25 Mar 2009 13:30:38 +0100 Subject: initial implementation of multitouch support on Windows 7 WM_TOUCH* messages are translated to QTouchEvents and sent to the appropriate widget. we set the qt_tabletChokeMouse variable according to the result of the event processing to make sure that mouse events are sent when touch events are not handled. --- src/gui/kernel/qapplication_p.h | 27 ++++- src/gui/kernel/qapplication_win.cpp | 192 ++++++++++++++++++++++++++++++++++++ src/gui/kernel/qwidget_win.cpp | 4 + 3 files changed, 220 insertions(+), 3 deletions(-) diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 252d0cb..ccd9f41 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -55,6 +55,7 @@ // #include "QtGui/qapplication.h" +#include "QtGui/qevent.h" #include "QtGui/qfont.h" #include "QtGui/qcursor.h" #include "QtGui/qregion.h" @@ -77,10 +78,7 @@ class QClipboard; class QGraphicsScene; class QGraphicsSystem; class QInputContext; -class QKeyEvent; -class QMouseEvent; class QObject; -class QWheelEvent; class QWidget; extern bool qt_is_gui_used; @@ -189,6 +187,12 @@ extern "C" { } #endif +#if defined(Q_WS_WIN) +typedef BOOL (WINAPI *qt_RegisterTouchWindowPtr)(HWND, ULONG); +typedef BOOL (WINAPI *qt_GetTouchInputInfoPtr)(HANDLE, UINT, PVOID, int); +typedef BOOL (WINAPI *qt_CloseTouchInputHandlePtr)(HANDLE); +#endif + class QScopedLoopLevelCounter { QThreadData *threadData; @@ -427,6 +431,23 @@ public: QPointer currentMultitouchWidget; static void updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent); +#if defined(Q_WS_WIN) + static qt_RegisterTouchWindowPtr RegisterTouchWindow; + static qt_GetTouchInputInfoPtr GetTouchInputInfo; + static qt_CloseTouchInputHandlePtr CloseTouchInputHandle; + + QMap touchInputIDToTouchPointID; + QVector allTouchPoints; + QList currentTouchPoints, activeTouchPoints; + + static bool sendTouchEvent(QWidget *widget, QTouchEvent *touchEvent); + + void initializeMultitouch(); + void insertActiveTouch(QTouchEvent::TouchPoint *touchPoint); + void removeActiveTouch(QTouchEvent::TouchPoint *touchPoint); + bool translateTouchEvent(const MSG &msg); +#endif + private: #ifdef Q_WS_QWS QMap maxWindowRects; diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index fae0335..7c7f7f6 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -88,6 +88,7 @@ extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.c #include "qdebug.h" #include #include +#include "qevent_p.h" //#define ALIEN_DEBUG @@ -112,6 +113,39 @@ extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.c # include #endif +#ifndef WM_TOUCHMOVE + +# define WM_TOUCHMOVE 0x0240 +# define WM_TOUCHDOWN 0x0241 +# define WM_TOUCHUP 0x0242 + +# define TOUCHEVENTF_MOVE 0x0001 +# define TOUCHEVENTF_DOWN 0x0002 +# define TOUCHEVENTF_UP 0x0004 +# define TOUCHEVENTF_INRANGE 0x0008 +# define TOUCHEVENTF_PRIMARY 0x0010 +# define TOUCHEVENTF_NOCOALESCE 0x0020 +# define TOUCHEVENTF_PEN 0x0040 + +# define TOUCHINPUTMASKF_TIMEFROMSYSTEM 0x0001 +# define TOUCHINPUTMASKF_EXTRAINFO 0x0002 +# define TOUCHINPUTMASKF_CONTACTAREA 0x0004 + +typedef struct tagTOUCHINPUT +{ + LONG x; + LONG y; + HANDLE hSource; + DWORD dwID; + DWORD dwFlags; + DWORD dwMask; + DWORD dwTime; + ULONG_PTR dwExtraInfo; + DWORD cxContact; + DWORD cyContact; +} TOUCHINPUT, *PTOUCHINPUT; + +#endif #ifndef FLASHW_STOP typedef struct { @@ -856,6 +890,8 @@ void qt_init(QApplicationPrivate *priv, int) if (ptrUpdateLayeredWindow && !ptrUpdateLayeredWindowIndirect) ptrUpdateLayeredWindowIndirect = qt_updateLayeredWindowIndirect; #endif + + priv->initializeMultitouch(); } /***************************************************************************** @@ -1726,6 +1762,11 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam result = widget->translateWheelEvent(msg); } else { switch (message) { + case WM_TOUCHMOVE: + case WM_TOUCHDOWN: + case WM_TOUCHUP: + result = getQApplicationPrivateInternal()->translateTouchEvent(msg); + break; case WM_KEYDOWN: // keyboard event case WM_SYSKEYDOWN: qt_keymapper_private()->updateKeyMap(msg); @@ -3953,4 +3994,155 @@ void QSessionManager::cancel() #endif //QT_NO_SESSIONMANAGER +qt_RegisterTouchWindowPtr QApplicationPrivate::RegisterTouchWindow = 0; +qt_GetTouchInputInfoPtr QApplicationPrivate::GetTouchInputInfo = 0; +qt_CloseTouchInputHandlePtr QApplicationPrivate::CloseTouchInputHandle = 0; + +void QApplicationPrivate::initializeMultitouch() +{ + QLibrary library(QLatin1String("user32")); + RegisterTouchWindow = static_cast(library.resolve("RegisterTouchWindow")); + GetTouchInputInfo = static_cast(library.resolve("GetTouchInputInfo")); + CloseTouchInputHandle = static_cast(library.resolve("CloseTouchInputHandle")); + + currentMultitouchWidget = 0; + touchInputIDToTouchPointID.clear(); + allTouchPoints.clear(); + currentTouchPoints.clear(); + activeTouchPoints.clear(); +} + +void QApplicationPrivate::insertActiveTouch(QTouchEvent::TouchPoint *touchPoint) +{ + // insort deviceNumber + int at = 0; + for (; at < currentTouchPoints.count(); ++at) { + if (currentTouchPoints.at(at)->id() > touchPoint->id()) + break; + } + currentTouchPoints.insert(at, touchPoint); + activeTouchPoints = currentTouchPoints; + + if (currentTouchPoints.count() > allTouchPoints.count()) { + qFatal("Qt: INTERNAL ERROR: currentTouchPoints.count() (%d) > allTouchPoints.count() (%d)", + currentTouchPoints.count(), + allTouchPoints.count()); + } +} + +void QApplicationPrivate::removeActiveTouch(QTouchEvent::TouchPoint *touchPoint) +{ + for (int i = qMin(currentTouchPoints.count() - 1, touchPoint->id()); i >= 0; --i) { + if (currentTouchPoints.at(i) == touchPoint) { + currentTouchPoints.removeAt(i); + break; + } + } + + // leave activeTouchPoints unchanged, since we need to make sure + // that the Release for deviceNumber is sent +} + +bool QApplicationPrivate::translateTouchEvent(const MSG &msg) +{ + Q_Q(QApplication); + + bool sendTouchBegin = currentTouchPoints.isEmpty(); + activeTouchPoints = currentTouchPoints; + + QVector winTouchInputs(msg.wParam); + memset(winTouchInputs.data(), 0, sizeof(TOUCHINPUT) * winTouchInputs.count()); + QApplicationPrivate::GetTouchInputInfo((HANDLE) msg.lParam, msg.wParam, winTouchInputs.data(), sizeof(TOUCHINPUT)); + for (int i = 0; i < winTouchInputs.count(); ++i) { + const TOUCHINPUT &touchInput = winTouchInputs.at(i); + + int touchPointID = touchInputIDToTouchPointID.value(touchInput.dwID, -1); + if (touchPointID == -1) { + touchPointID = touchInputIDToTouchPointID.count(); + touchInputIDToTouchPointID.insert(touchInput.dwID, touchPointID); + } + + if (allTouchPoints.count() <= touchPointID) + allTouchPoints.resize(touchPointID + 1); + + QTouchEvent::TouchPoint *touchPoint = allTouchPoints.at(touchPointID); + if (!touchPoint) + touchPoint = allTouchPoints[touchPointID] = new QTouchEvent::TouchPoint(touchPointID); + + // update state + bool down = touchPoint->d->state != Qt::TouchPointReleased; + QPointF globalPos(qreal(touchInput.x) / qreal(100.), qreal(touchInput.y) / qreal(100.)); + if (!down && (touchInput.dwFlags & TOUCHEVENTF_DOWN)) { + insertActiveTouch(touchPoint); + touchPoint->d->state = Qt::TouchPointPressed; + touchPoint->d->globalPos = touchPoint->d->startGlobalPos = touchPoint->d->lastGlobalPos = globalPos; + touchPoint->d->pressure = qreal(1.); + } else if (down && (touchInput.dwFlags & TOUCHEVENTF_UP)) { + removeActiveTouch(touchPoint); + touchPoint->d->state = Qt::TouchPointReleased; + touchPoint->d->lastGlobalPos = touchPoint->d->globalPos; + touchPoint->d->globalPos = globalPos; + touchPoint->d->pressure = qreal(0.); + } else if (down) { + touchPoint->d->state = globalPos == touchPoint->d->globalPos + ? Qt::TouchPointStationary + : Qt::TouchPointMoved; + touchPoint->d->lastGlobalPos = touchPoint->d->globalPos; + touchPoint->d->globalPos = globalPos; + // pressure should still be 1. + } + } + QApplicationPrivate::CloseTouchInputHandle((HANDLE) msg.lParam); + + bool sendTouchEnd = currentTouchPoints.isEmpty(); + + if (activeTouchPoints.isEmpty()) + return false; + + if (sendTouchBegin) { + // the window under the first touch point gets the touch event + int firstTouchId = activeTouchPoints.first()->id(); + const QPoint &globalPos = allTouchPoints.at(firstTouchId)->d->globalPos.toPoint(); + QWidget *window = q->topLevelAt(globalPos); + if (window) { + QWidget *child = window->childAt(window->mapFromGlobal(globalPos)); + if (!child) + child = window; + currentMultitouchWidget = child; + } + } + + QWidget *widget = q->activePopupWidget(); + if (!widget) + widget = currentMultitouchWidget; + + if (sendTouchEnd) { + // reset currentMultitouchWindow when the last touch is released + currentMultitouchWidget = 0; + if (!currentTouchPoints.isEmpty()) { + qFatal("Qt: INTERNAL ERROR, currentTouchPoints should be empty!"); + } + } + + // deliver the event + if (widget && QApplicationPrivate::tryModalHelper(widget, 0)) { + QTouchEvent touchEvent((sendTouchBegin + ? QEvent::TouchBegin + : sendTouchEnd + ? QEvent::TouchEnd + : QEvent::TouchUpdate), + q->keyboardModifiers(), activeTouchPoints); + updateTouchPointsForWidget(widget, &touchEvent); + return (qt_tabletChokeMouse = sendTouchEvent(widget, &touchEvent)); + } + + return false; +} + +bool QApplicationPrivate::sendTouchEvent(QWidget *widget, QTouchEvent *touchEvent) +{ + bool res = QApplication::sendSpontaneousEvent(widget, touchEvent); + return res && touchEvent->isAccepted(); +} + QT_END_NAMESPACE diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index ffbb341..b55f1c8 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -503,6 +503,10 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO } } + // ### don't always register for touch events + if (QApplicationPrivate::RegisterTouchWindow && !desktop) + QApplicationPrivate::RegisterTouchWindow(id, 0); + q->setAttribute(Qt::WA_WState_Created); // accept move/resize events hd = 0; // no display context -- cgit v0.12 From 761cac16eb0a6d32f9e7d558867c5c1bbfb244f9 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Wed, 25 Mar 2009 13:49:34 +0100 Subject: show the example maximized, not fullscreen --- examples/multitouch/knobs/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/multitouch/knobs/main.cpp b/examples/multitouch/knobs/main.cpp index c5a7ea7..8f78cf9 100644 --- a/examples/multitouch/knobs/main.cpp +++ b/examples/multitouch/knobs/main.cpp @@ -59,7 +59,7 @@ int main(int argc, char **argv) scene.addItem(knob1); scene.addItem(knob2); - view.showFullScreen(); + view.showMaximized(); view.fitInView(scene.sceneRect().adjusted(-20, -20, 20, 20), Qt::KeepAspectRatio); return app.exec(); -- cgit v0.12 From e14f2ddd25a72f07a3215c1bc7f4755c48dd6e3a Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Thu, 12 Mar 2009 13:45:18 +0100 Subject: add a test for touch event propagation --- tests/auto/qapplication/tst_qapplication.cpp | 143 +++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) diff --git a/tests/auto/qapplication/tst_qapplication.cpp b/tests/auto/qapplication/tst_qapplication.cpp index cee3125..356768e 100644 --- a/tests/auto/qapplication/tst_qapplication.cpp +++ b/tests/auto/qapplication/tst_qapplication.cpp @@ -48,6 +48,7 @@ #include "qabstracteventdispatcher.h" #include +#include "private/qapplication_p.h" #include "private/qstylesheetstyle_p.h" #ifdef Q_OS_WINCE #include @@ -117,6 +118,8 @@ private slots: void windowsCommandLine_data(); void windowsCommandLine(); + + void touchEventPropagation(); }; class MyInputContext : public QInputContext @@ -1773,6 +1776,146 @@ void tst_QApplication::windowsCommandLine() #endif } +class TouchEventPropagationTestWidget : public QWidget +{ + Q_OBJECT + +public: + bool seenTouchEvent, acceptTouchEvent, seenMouseEvent, acceptMouseEvent; + + TouchEventPropagationTestWidget(QWidget *parent = 0) + : QWidget(parent), seenTouchEvent(false), acceptTouchEvent(false), seenMouseEvent(false), acceptMouseEvent(false) + { } + + void reset() + { + seenTouchEvent = acceptTouchEvent = seenMouseEvent = acceptMouseEvent = false; + } + + bool event(QEvent *event) + { + switch (event->type()) { + case QEvent::MouseButtonPress: + case QEvent::MouseMove: + case QEvent::MouseButtonRelease: + // qDebug() << objectName() << "seenMouseEvent = true"; + seenMouseEvent = true; + event->setAccepted(acceptMouseEvent); + break; + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: + // qDebug() << objectName() << "seenTouchEvent = true"; + seenTouchEvent = true; + event->setAccepted(acceptTouchEvent); + break; + default: + return QWidget::event(event); + } + return true; + } +}; + +void tst_QApplication::touchEventPropagation() +{ + int argc = 1; + QApplication app(argc, &argv0, QApplication::GuiServer); + QTouchEvent::TouchPoint touchPoint(0); + QTouchEvent touchEvent(QEvent::TouchBegin, Qt::NoModifier, QList() << (&touchPoint)); + + { + // touch event behavior on a window + TouchEventPropagationTestWidget window; + window.setObjectName("1. window"); + + QApplicationPrivate::sendTouchEvent(&window, &touchEvent); + QVERIFY(!window.seenTouchEvent); + QVERIFY(window.seenMouseEvent); + + window.reset(); + window.setAttribute(Qt::WA_AcceptsTouchEvents); + QApplicationPrivate::sendTouchEvent(&window, &touchEvent); + QVERIFY(window.seenTouchEvent); + QVERIFY(window.seenMouseEvent); + + window.reset(); + window.acceptTouchEvent = true; + QApplicationPrivate::sendTouchEvent(&window, &touchEvent); + QVERIFY(window.seenTouchEvent); + QVERIFY(!window.seenMouseEvent); + } + + { + // touch event behavior on a window with a child widget + TouchEventPropagationTestWidget window; + window.setObjectName("2. window"); + TouchEventPropagationTestWidget widget(&window); + widget.setObjectName("2. widget"); + + QApplicationPrivate::sendTouchEvent(&widget, &touchEvent); + QVERIFY(!widget.seenTouchEvent); + QVERIFY(widget.seenMouseEvent); + QVERIFY(!window.seenTouchEvent); + QVERIFY(window.seenMouseEvent); + + window.reset(); + widget.reset(); + widget.setAttribute(Qt::WA_AcceptsTouchEvents); + QApplicationPrivate::sendTouchEvent(&widget, &touchEvent); + QVERIFY(widget.seenTouchEvent); + QVERIFY(widget.seenMouseEvent); + QVERIFY(!window.seenTouchEvent); + QVERIFY(window.seenMouseEvent); + + window.reset(); + widget.reset(); + widget.acceptMouseEvent = true; + QApplicationPrivate::sendTouchEvent(&widget, &touchEvent); + QVERIFY(widget.seenTouchEvent); + QVERIFY(widget.seenMouseEvent); + QVERIFY(!window.seenTouchEvent); + QVERIFY(!window.seenMouseEvent); + + window.reset(); + widget.reset(); + widget.acceptTouchEvent = true; + QApplicationPrivate::sendTouchEvent(&widget, &touchEvent); + QVERIFY(widget.seenTouchEvent); + QVERIFY(!widget.seenMouseEvent); + QVERIFY(!window.seenTouchEvent); + QVERIFY(!window.seenMouseEvent); + + window.reset(); + widget.reset(); + widget.setAttribute(Qt::WA_AcceptsTouchEvents, false); + window.setAttribute(Qt::WA_AcceptsTouchEvents); + QApplicationPrivate::sendTouchEvent(&widget, &touchEvent); + QVERIFY(!widget.seenTouchEvent); + QVERIFY(widget.seenMouseEvent); + QVERIFY(window.seenTouchEvent); + QVERIFY(window.seenMouseEvent); + + window.reset(); + widget.reset(); + window.acceptTouchEvent = true; + QApplicationPrivate::sendTouchEvent(&widget, &touchEvent); + QVERIFY(!widget.seenTouchEvent); + QVERIFY(!widget.seenMouseEvent); + QVERIFY(window.seenTouchEvent); + QVERIFY(!window.seenMouseEvent); + + window.reset(); + widget.reset(); + widget.acceptMouseEvent = true; // doesn't matter, touch events are propagated first + window.acceptTouchEvent = true; + QApplicationPrivate::sendTouchEvent(&widget, &touchEvent); + QVERIFY(!widget.seenTouchEvent); + QVERIFY(!widget.seenMouseEvent); + QVERIFY(window.seenTouchEvent); + QVERIFY(!window.seenMouseEvent); + } +} + //QTEST_APPLESS_MAIN(tst_QApplication) int main(int argc, char *argv[]) { -- cgit v0.12 From b2824b384485ddba95091e49f81733485f1a73be Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Thu, 26 Mar 2009 08:24:39 +0100 Subject: remove QApplicationPrivate::sendTouchEvent --- src/gui/kernel/qapplication_p.h | 2 -- src/gui/kernel/qapplication_win.cpp | 10 +++------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index ccd9f41..ce7110d 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -440,8 +440,6 @@ public: QVector allTouchPoints; QList currentTouchPoints, activeTouchPoints; - static bool sendTouchEvent(QWidget *widget, QTouchEvent *touchEvent); - void initializeMultitouch(); void insertActiveTouch(QTouchEvent::TouchPoint *touchPoint); void removeActiveTouch(QTouchEvent::TouchPoint *touchPoint); diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 7c7f7f6..cef8cf2 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -4133,16 +4133,12 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) : QEvent::TouchUpdate), q->keyboardModifiers(), activeTouchPoints); updateTouchPointsForWidget(widget, &touchEvent); - return (qt_tabletChokeMouse = sendTouchEvent(widget, &touchEvent)); + + bool res = QApplication::sendSpontaneousEvent(widget, &touchEvent); + return (qt_tabletChokeMouse = res && touchEvent.isAccepted()); } return false; } -bool QApplicationPrivate::sendTouchEvent(QWidget *widget, QTouchEvent *touchEvent) -{ - bool res = QApplication::sendSpontaneousEvent(widget, touchEvent); - return res && touchEvent->isAccepted(); -} - QT_END_NAMESPACE -- cgit v0.12 From b3a2c210973a77d1517d017637a3d6ef849f4089 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Thu, 26 Mar 2009 08:54:36 +0100 Subject: implement panning using touch events since we don't get mouse events to send to QGraphicsView's ScrollHandDrag handlers, we need to do it ourselves --- examples/multitouch/pinchzoom/graphicsview.cpp | 13 ++++++++----- examples/multitouch/pinchzoom/main.cpp | 1 - 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/examples/multitouch/pinchzoom/graphicsview.cpp b/examples/multitouch/pinchzoom/graphicsview.cpp index b77c926..f763e6f 100644 --- a/examples/multitouch/pinchzoom/graphicsview.cpp +++ b/examples/multitouch/pinchzoom/graphicsview.cpp @@ -41,9 +41,9 @@ #include "graphicsview.h" +#include #include - GraphicsView::GraphicsView(QGraphicsScene *scene, QWidget *parent) : QGraphicsView(scene, parent) { @@ -57,10 +57,13 @@ bool GraphicsView::event(QEvent *event) case QEvent::TouchUpdate: case QEvent::TouchEnd: { - qDebug("touch events"); - - QList touchPoints = static_cast(event)->touchPoints(); - if (touchPoints.count() == 2) { + QList touchPoints = static_cast(event)->touchPoints(); + if (touchPoints.count() == 1) { + const QTouchEvent::TouchPoint *touchPoint = touchPoints.first(); + QPointF delta = touchPoint->pos() - touchPoint->lastPos(); + horizontalScrollBar()->setValue(horizontalScrollBar()->value() - delta.x()); + verticalScrollBar()->setValue(verticalScrollBar()->value() - delta.y()); + } else if (touchPoints.count() == 2) { // determine scale factor const QTouchEvent::TouchPoint *touchPoint0 = touchPoints.first(); const QTouchEvent::TouchPoint *touchPoint1 = touchPoints.last(); diff --git a/examples/multitouch/pinchzoom/main.cpp b/examples/multitouch/pinchzoom/main.cpp index 6b25060..bb86870 100644 --- a/examples/multitouch/pinchzoom/main.cpp +++ b/examples/multitouch/pinchzoom/main.cpp @@ -78,7 +78,6 @@ int main(int argc, char **argv) //! [4] //! [5] view.setCacheMode(QGraphicsView::CacheBackground); view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); - view.setDragMode(QGraphicsView::ScrollHandDrag); //! [5] //! [6] view.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Colliding Mice")); view.showMaximized(); -- cgit v0.12 From 46caddc9fa82df4fba88ea4ef87dba692b18c1c9 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Mon, 30 Mar 2009 11:08:12 +0200 Subject: compile --- src/network/kernel/qauthenticator.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp index 4f477bd..19243aa 100644 --- a/src/network/kernel/qauthenticator.cpp +++ b/src/network/kernel/qauthenticator.cpp @@ -52,7 +52,7 @@ QT_BEGIN_NAMESPACE -#include <../3rdparty/des/des.cpp> +#include <../../3rdparty/des/des.cpp> static QByteArray qNtlmPhase1(); static QByteArray qNtlmPhase3(QAuthenticatorPrivate *ctx, const QByteArray& phase2data); -- cgit v0.12 From be8b6047ccd43df1127beb4c602c58408ff9b612 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Tue, 31 Mar 2009 13:19:23 +0200 Subject: Add QSysInfo::WV_WINDOWS7 --- src/corelib/global/qglobal.cpp | 9 ++++++++- src/corelib/global/qglobal.h | 2 ++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 459167e..bcb17a2 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -1054,6 +1054,7 @@ bool qSharedBuild() \value WV_XP Windows XP (operating system version 5.1) \value WV_2003 Windows Server 2003, Windows Server 2003 R2, Windows Home Server, Windows XP Professional x64 Edition (operating system version 5.2) \value WV_VISTA Windows Vista, Windows Server 2008 (operating system version 6.0) + \value WV_WINDOWS7 Windows 7 (operating system version 6.1) Alternatively, you may use the following macros which correspond directly to the Windows operating system version number: @@ -1062,6 +1063,7 @@ bool qSharedBuild() \value WV_5_1 Operating system version 5.1, corresponds to Windows XP \value WV_5_2 Operating system version 5.2, corresponds to Windows Server 2003, Windows Server 2003 R2, Windows Home Server, and Windows XP Professional x64 Edition \value WV_6_0 Operating system version 6.0, corresponds to Windows Vista and Windows Server 2008 + \value WV_6_1 Operation system version 6.1, corresponds to Windows 7 CE-based versions: @@ -1632,7 +1634,10 @@ QSysInfo::WinVersion QSysInfo::windowsVersion() if (osver.dwMajorVersion < 5) { winver = QSysInfo::WV_NT; } else if (osver.dwMajorVersion == 6) { - winver = QSysInfo::WV_VISTA; + if (osver.dwMinorVersion == 0) + winver = QSysInfo::WV_VISTA; + else + winver = QSysInfo::WV_WINDOWS7; } else if (osver.dwMinorVersion == 0) { winver = QSysInfo::WV_2000; } else if (osver.dwMinorVersion == 1) { @@ -1667,6 +1672,8 @@ QSysInfo::WinVersion QSysInfo::windowsVersion() winver = QSysInfo::WV_XP; else if (override == "VISTA") winver = QSysInfo::WV_VISTA; + else if (override == "WINDOWS7") + winver = QSysInfo::WV_WINDOWS7; } #endif diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 9522e39..872dcf5 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -1309,6 +1309,7 @@ public: WV_XP = 0x0030, WV_2003 = 0x0040, WV_VISTA = 0x0080, + WV_WINDOWS7 = 0x0090, WV_NT_based = 0x00f0, /* version numbers */ @@ -1317,6 +1318,7 @@ public: WV_5_1 = WV_XP, WV_5_2 = WV_2003, WV_6_0 = WV_VISTA, + WV_6_1 = WV_WINDOWS7, WV_CE = 0x0100, WV_CENET = 0x0200, -- cgit v0.12 From 726694c873104ac484a3d09c1a9f64f06a88f864 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Thu, 23 Apr 2009 14:57:12 +0200 Subject: the start of a manual test for touch events --- tests/manual/qtouchevent/form.ui | 1843 ++++++++++++++++++++++++++++++ tests/manual/qtouchevent/main.cpp | 58 + tests/manual/qtouchevent/multitouch.pro | 5 + tests/manual/qtouchevent/touchwidget.cpp | 56 + tests/manual/qtouchevent/touchwidget.h | 42 + 5 files changed, 2004 insertions(+) create mode 100644 tests/manual/qtouchevent/form.ui create mode 100644 tests/manual/qtouchevent/main.cpp create mode 100644 tests/manual/qtouchevent/multitouch.pro create mode 100644 tests/manual/qtouchevent/touchwidget.cpp create mode 100644 tests/manual/qtouchevent/touchwidget.h diff --git a/tests/manual/qtouchevent/form.ui b/tests/manual/qtouchevent/form.ui new file mode 100644 index 0000000..00e15ae --- /dev/null +++ b/tests/manual/qtouchevent/form.ui @@ -0,0 +1,1843 @@ + + + Form + + + + 0 + 0 + 791 + 499 + + + + Form + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 170 + 0 + + + + + + + 0 + 255 + 0 + + + + + + + 0 + 212 + 0 + + + + + + + 0 + 85 + 0 + + + + + + + 0 + 113 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 170 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 127 + 212 + 127 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 170 + 0 + + + + + + + 0 + 255 + 0 + + + + + + + 0 + 212 + 0 + + + + + + + 0 + 85 + 0 + + + + + + + 0 + 113 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 170 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 127 + 212 + 127 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 85 + 0 + + + + + + + 0 + 170 + 0 + + + + + + + 0 + 255 + 0 + + + + + + + 0 + 212 + 0 + + + + + + + 0 + 85 + 0 + + + + + + + 0 + 113 + 0 + + + + + + + 0 + 85 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 85 + 0 + + + + + + + 0 + 170 + 0 + + + + + + + 0 + 170 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 170 + 0 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + true + + + + + + Qt::Vertical + + + + 20 + 290 + + + + + + + + Qt::Horizontal + + + + 84 + 20 + + + + + + + + + 180 + 120 + + + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 170 + + + + + + + 0 + 0 + 255 + + + + + + + 0 + 0 + 212 + + + + + + + 0 + 0 + 85 + + + + + + + 0 + 0 + 113 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 170 + + + + + + + 0 + 0 + 0 + + + + + + + 127 + 127 + 212 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 170 + + + + + + + 0 + 0 + 255 + + + + + + + 0 + 0 + 212 + + + + + + + 0 + 0 + 85 + + + + + + + 0 + 0 + 113 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 170 + + + + + + + 0 + 0 + 0 + + + + + + + 127 + 127 + 212 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 85 + + + + + + + 0 + 0 + 170 + + + + + + + 0 + 0 + 255 + + + + + + + 0 + 0 + 212 + + + + + + + 0 + 0 + 85 + + + + + + + 0 + 0 + 113 + + + + + + + 0 + 0 + 85 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 85 + + + + + + + 0 + 0 + 170 + + + + + + + 0 + 0 + 170 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 170 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + true + + + + + + + Qt::Horizontal + + + + 84 + 20 + + + + + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 170 + 0 + 0 + + + + + + + 255 + 0 + 0 + + + + + + + 212 + 0 + 0 + + + + + + + 85 + 0 + 0 + + + + + + + 113 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 170 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 212 + 127 + 127 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 170 + 0 + 0 + + + + + + + 255 + 0 + 0 + + + + + + + 212 + 0 + 0 + + + + + + + 85 + 0 + 0 + + + + + + + 113 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 170 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 212 + 127 + 127 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + + 85 + 0 + 0 + + + + + + + 170 + 0 + 0 + + + + + + + 255 + 0 + 0 + + + + + + + 212 + 0 + 0 + + + + + + + 85 + 0 + 0 + + + + + + + 113 + 0 + 0 + + + + + + + 85 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 85 + 0 + 0 + + + + + + + 170 + 0 + 0 + + + + + + + 170 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 170 + 0 + 0 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + true + + + + + + Qt::Vertical + + + + 20 + 290 + + + + + + + + Qt::Horizontal + + + + 84 + 20 + + + + + + + + + 180 + 120 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + true + + + + + + + Qt::Horizontal + + + + 83 + 20 + + + + + + + + + + + + 75 + true + + + + Test Name + + + + + + + Test description + + + + + + + + TouchWidget + QWidget +
touchwidget.h
+ 1 +
+
+ + +
diff --git a/tests/manual/qtouchevent/main.cpp b/tests/manual/qtouchevent/main.cpp new file mode 100644 index 0000000..c406543 --- /dev/null +++ b/tests/manual/qtouchevent/main.cpp @@ -0,0 +1,58 @@ +#include +#include + +#include "ui_form.h" +#include "touchwidget.h" + +class MultitouchTestWidget : public QWidget, public Ui::Form +{ + Q_OBJECT + +public: + MultitouchTestWidget(QWidget *parent = 0) + : QWidget(parent) + { + setupUi(this); + } +}; + +class tst_ManualMultitouch : public QObject +{ + Q_OBJECT + +public: + tst_ManualMultitouch(); + ~tst_ManualMultitouch(); + +private slots: + void touchBeginPropagation(); +}; + +tst_ManualMultitouch::tst_ManualMultitouch() +{ } + +tst_ManualMultitouch::~tst_ManualMultitouch() +{ } + +void tst_ManualMultitouch::touchBeginPropagation() +{ + MultitouchTestWidget testWidget; + testWidget.testNameLabel->setText("Touch event propagation"); + testWidget.testDescriptionLabel->setText("Touch, move, and release your finger over the green widget, the close this window."); + testWidget.greenWidget->setAttribute(Qt::WA_AcceptTouchEvents); + testWidget.greenWidget->acceptTouchBegin = true; + testWidget.show(); + + (void) qApp->exec(); + + QVERIFY(testWidget.greenWidget->seenTouchBegin); + QVERIFY(testWidget.greenWidget->seenTouchUpdate); + QVERIFY(testWidget.greenWidget->seenTouchEnd); + QVERIFY(!testWidget.greenWidget->seenMousePress); + QVERIFY(!testWidget.greenWidget->seenMouseMove); + QVERIFY(!testWidget.greenWidget->seenMouseRelease); +} + +QTEST_MAIN(tst_ManualMultitouch) + +#include "main.moc" diff --git a/tests/manual/qtouchevent/multitouch.pro b/tests/manual/qtouchevent/multitouch.pro new file mode 100644 index 0000000..de1ee06 --- /dev/null +++ b/tests/manual/qtouchevent/multitouch.pro @@ -0,0 +1,5 @@ +QT += testlib +SOURCES = main.cpp \ + touchwidget.cpp +FORMS += form.ui +HEADERS += touchwidget.h diff --git a/tests/manual/qtouchevent/touchwidget.cpp b/tests/manual/qtouchevent/touchwidget.cpp new file mode 100644 index 0000000..5205504 --- /dev/null +++ b/tests/manual/qtouchevent/touchwidget.cpp @@ -0,0 +1,56 @@ +#include "touchwidget.h" + +#include +#include + +bool TouchWidget::event(QEvent *event) +{ + switch (event->type()) { + case QEvent::TouchBegin: + seenTouchBegin = true; + if (acceptTouchBegin) { + event->accept(); + return true; + } + break; + case QEvent::TouchUpdate: + seenTouchUpdate = true; + if (acceptTouchUpdate) { + event->accept(); + return true; + } + break; + case QEvent::TouchEnd: + seenTouchEnd = true; + if (acceptTouchEnd) { + event->accept(); + return true; + } + break; + case QEvent::MouseButtonPress: + case QEvent::MouseButtonDblClick: + seenMousePress = true; + if (acceptMousePress) { + event->accept(); + return true; + } + break; + case QEvent::MouseMove: + seenMouseMove = true; + if (acceptMouseMove) { + event->accept(); + return true; + } + break; + case QEvent::MouseButtonRelease: + seenMouseRelease = true; + if (acceptMouseRelease) { + event->accept(); + return true; + } + break; + default: + break; + } + return QWidget::event(event); +} diff --git a/tests/manual/qtouchevent/touchwidget.h b/tests/manual/qtouchevent/touchwidget.h new file mode 100644 index 0000000..f438a87 --- /dev/null +++ b/tests/manual/qtouchevent/touchwidget.h @@ -0,0 +1,42 @@ +#ifndef TOUCHWIDGET_H +#define TOUCHWIDGET_H + +#include + +class TouchWidget : public QWidget +{ + Q_OBJECT + +public: + bool acceptTouchBegin, acceptTouchUpdate, acceptTouchEnd; + bool seenTouchBegin, seenTouchUpdate, seenTouchEnd; + bool acceptMousePress, acceptMouseMove, acceptMouseRelease; + bool seenMousePress, seenMouseMove, seenMouseRelease; + + inline TouchWidget(QWidget *parent = 0) + : QWidget(parent) + { + reset(); + } + + void reset() + { + acceptTouchBegin + = acceptTouchUpdate + = acceptTouchEnd + = seenTouchBegin + = seenTouchUpdate + = seenTouchEnd + = acceptMousePress + = acceptMouseMove + = acceptMouseRelease + = seenMousePress + = seenMouseMove + = seenMouseRelease + = false; + } + + bool event(QEvent *event); +}; + +#endif // TOUCHWIDGET_H -- cgit v0.12 From 704261859297dae22f90be32ed0e4b675fd02ed3 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Thu, 23 Apr 2009 15:54:06 +0200 Subject: Initial test for TouchBegin propagation and TouchUpdate/TouchEnd handling --- tests/manual/qtouchevent/main.cpp | 54 ++++++++++++++++++++++++++++++-- tests/manual/qtouchevent/touchwidget.cpp | 26 +++++++++++++++ tests/manual/qtouchevent/touchwidget.h | 20 +++--------- 3 files changed, 82 insertions(+), 18 deletions(-) diff --git a/tests/manual/qtouchevent/main.cpp b/tests/manual/qtouchevent/main.cpp index c406543..2aab4ca 100644 --- a/tests/manual/qtouchevent/main.cpp +++ b/tests/manual/qtouchevent/main.cpp @@ -38,13 +38,63 @@ void tst_ManualMultitouch::touchBeginPropagation() { MultitouchTestWidget testWidget; testWidget.testNameLabel->setText("Touch event propagation"); - testWidget.testDescriptionLabel->setText("Touch, move, and release your finger over the green widget, the close this window."); + testWidget.testDescriptionLabel->setText("Touch, move, and release your finger over the green widget."); testWidget.greenWidget->setAttribute(Qt::WA_AcceptTouchEvents); testWidget.greenWidget->acceptTouchBegin = true; - testWidget.show(); + testWidget.greenWidget->acceptTouchUpdate = true; + testWidget.greenWidget->acceptTouchEnd = true; + testWidget.greenWidget->closeWindowOnTouchEnd = true; + testWidget.showMaximized(); (void) qApp->exec(); + QVERIFY(testWidget.greenWidget->seenTouchBegin); + QVERIFY(testWidget.greenWidget->seenTouchUpdate); + QVERIFY(testWidget.greenWidget->seenTouchEnd); + QVERIFY(!testWidget.greenWidget->seenMousePress); + QVERIFY(!testWidget.greenWidget->seenMouseMove); + QVERIFY(!testWidget.greenWidget->seenMouseRelease); + + // again, ignoring the TouchEnd + testWidget.greenWidget->reset(); + testWidget.greenWidget->acceptTouchBegin = true; + testWidget.greenWidget->acceptTouchUpdate = true; + // testWidget.greenWidget->acceptTouchEnd = true; + testWidget.greenWidget->closeWindowOnTouchEnd = true; + testWidget.showMaximized(); + (void) qApp->exec(); + QVERIFY(testWidget.greenWidget->seenTouchBegin); + QVERIFY(testWidget.greenWidget->seenTouchUpdate); + QVERIFY(testWidget.greenWidget->seenTouchEnd); + QVERIFY(!testWidget.greenWidget->seenMousePress); + QVERIFY(!testWidget.greenWidget->seenMouseMove); + QVERIFY(!testWidget.greenWidget->seenMouseRelease); + + // again, ignoring TouchUpdates + testWidget.greenWidget->reset(); + testWidget.greenWidget->acceptTouchBegin = true; + // testWidget.greenWidget->acceptTouchUpdate = true; + testWidget.greenWidget->acceptTouchEnd = true; + testWidget.greenWidget->closeWindowOnTouchEnd = true; + testWidget.showMaximized(); + + (void) qApp->exec(); + QVERIFY(testWidget.greenWidget->seenTouchBegin); + QVERIFY(testWidget.greenWidget->seenTouchUpdate); + QVERIFY(testWidget.greenWidget->seenTouchEnd); + QVERIFY(!testWidget.greenWidget->seenMousePress); + QVERIFY(!testWidget.greenWidget->seenMouseMove); + QVERIFY(!testWidget.greenWidget->seenMouseRelease); + + // last time, ignoring TouchUpdates and TouchEnd + testWidget.greenWidget->reset(); + testWidget.greenWidget->acceptTouchBegin = true; + // testWidget.greenWidget->acceptTouchUpdate = true; + // testWidget.greenWidget->acceptTouchEnd = true; + testWidget.greenWidget->closeWindowOnTouchEnd = true; + testWidget.showMaximized(); + + (void) qApp->exec(); QVERIFY(testWidget.greenWidget->seenTouchBegin); QVERIFY(testWidget.greenWidget->seenTouchUpdate); QVERIFY(testWidget.greenWidget->seenTouchEnd); diff --git a/tests/manual/qtouchevent/touchwidget.cpp b/tests/manual/qtouchevent/touchwidget.cpp index 5205504..54ca685 100644 --- a/tests/manual/qtouchevent/touchwidget.cpp +++ b/tests/manual/qtouchevent/touchwidget.cpp @@ -3,6 +3,28 @@ #include #include + +void TouchWidget::reset() +{ + acceptTouchBegin + = acceptTouchUpdate + = acceptTouchEnd + = seenTouchBegin + = seenTouchUpdate + = seenTouchEnd + = closeWindowOnTouchEnd + + = acceptMousePress + = acceptMouseMove + = acceptMouseRelease + = seenMousePress + = seenMouseMove + = seenMouseRelease + = closeWindowOnMouseRelease + + = false; +} + bool TouchWidget::event(QEvent *event) { switch (event->type()) { @@ -22,6 +44,8 @@ bool TouchWidget::event(QEvent *event) break; case QEvent::TouchEnd: seenTouchEnd = true; + if (closeWindowOnTouchEnd) + window()->close(); if (acceptTouchEnd) { event->accept(); return true; @@ -44,6 +68,8 @@ bool TouchWidget::event(QEvent *event) break; case QEvent::MouseButtonRelease: seenMouseRelease = true; + if (closeWindowOnMouseRelease) + window()->close(); if (acceptMouseRelease) { event->accept(); return true; diff --git a/tests/manual/qtouchevent/touchwidget.h b/tests/manual/qtouchevent/touchwidget.h index f438a87..3e95610 100644 --- a/tests/manual/qtouchevent/touchwidget.h +++ b/tests/manual/qtouchevent/touchwidget.h @@ -10,8 +10,11 @@ class TouchWidget : public QWidget public: bool acceptTouchBegin, acceptTouchUpdate, acceptTouchEnd; bool seenTouchBegin, seenTouchUpdate, seenTouchEnd; + bool closeWindowOnTouchEnd; + bool acceptMousePress, acceptMouseMove, acceptMouseRelease; bool seenMousePress, seenMouseMove, seenMouseRelease; + bool closeWindowOnMouseRelease; inline TouchWidget(QWidget *parent = 0) : QWidget(parent) @@ -19,22 +22,7 @@ public: reset(); } - void reset() - { - acceptTouchBegin - = acceptTouchUpdate - = acceptTouchEnd - = seenTouchBegin - = seenTouchUpdate - = seenTouchEnd - = acceptMousePress - = acceptMouseMove - = acceptMouseRelease - = seenMousePress - = seenMouseMove - = seenMouseRelease - = false; - } + void reset(); bool event(QEvent *event); }; -- cgit v0.12 From 66ed5fc90fe44554e852a6f8dca4548154da781c Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Thu, 23 Apr 2009 17:54:17 +0200 Subject: update test to test basic event handling and touch begin propagation --- tests/manual/qtouchevent/form.ui | 572 +++++++++++++++++-------------- tests/manual/qtouchevent/main.cpp | 152 +++++++- tests/manual/qtouchevent/touchwidget.cpp | 7 +- 3 files changed, 460 insertions(+), 271 deletions(-) diff --git a/tests/manual/qtouchevent/form.ui b/tests/manual/qtouchevent/form.ui index 00e15ae..6cf4cba 100644 --- a/tests/manual/qtouchevent/form.ui +++ b/tests/manual/qtouchevent/form.ui @@ -6,16 +6,16 @@ 0 0 - 791 - 499 + 770 + 424 Form - - + + 0 @@ -37,8 +37,8 @@ - 0 - 170 + 170 + 0 0 @@ -46,8 +46,8 @@ - 0 - 255 + 255 + 0 0 @@ -55,8 +55,8 @@ - 0 - 212 + 212 + 0 0 @@ -64,8 +64,8 @@ - 0 - 85 + 85 + 0 0 @@ -73,8 +73,8 @@ - 0 - 113 + 113 + 0 0 @@ -118,8 +118,8 @@ - 0 - 170 + 170 + 0 0 @@ -136,8 +136,8 @@ - 127 - 212 + 212 + 127 127 @@ -174,8 +174,8 @@ - 0 - 170 + 170 + 0 0 @@ -183,8 +183,8 @@ - 0 - 255 + 255 + 0 0 @@ -192,8 +192,8 @@ - 0 - 212 + 212 + 0 0 @@ -201,8 +201,8 @@ - 0 - 85 + 85 + 0 0 @@ -210,8 +210,8 @@ - 0 - 113 + 113 + 0 0 @@ -255,8 +255,8 @@ - 0 - 170 + 170 + 0 0 @@ -273,8 +273,8 @@ - 127 - 212 + 212 + 127 127 @@ -302,8 +302,8 @@ - 0 - 85 + 85 + 0 0 @@ -311,8 +311,8 @@ - 0 - 170 + 170 + 0 0 @@ -320,8 +320,8 @@ - 0 - 255 + 255 + 0 0 @@ -329,8 +329,8 @@ - 0 - 212 + 212 + 0 0 @@ -338,8 +338,8 @@ - 0 - 85 + 85 + 0 0 @@ -347,8 +347,8 @@ - 0 - 113 + 113 + 0 0 @@ -356,8 +356,8 @@ - 0 - 85 + 85 + 0 0 @@ -374,8 +374,8 @@ - 0 - 85 + 85 + 0 0 @@ -383,8 +383,8 @@ - 0 - 170 + 170 + 0 0 @@ -392,8 +392,8 @@ - 0 - 170 + 170 + 0 0 @@ -410,8 +410,8 @@ - 0 - 170 + 170 + 0 0 @@ -440,35 +440,41 @@ true - + - + Qt::Vertical - 20 - 290 + 0 + 0 - + Qt::Horizontal - 84 - 20 + 0 + 0 - + + + + 0 + 0 + + 180 @@ -481,9 +487,9 @@ - 0 - 0 - 0 + 255 + 255 + 255 @@ -492,7 +498,7 @@ 0 0 - 170 + 0 @@ -501,7 +507,7 @@ 0 0 - 255 + 0 @@ -510,7 +516,7 @@ 0 0 - 212 + 0 @@ -519,7 +525,7 @@ 0 0 - 85 + 0 @@ -528,16 +534,16 @@ 0 0 - 113 + 0 - 0 - 0 - 0 + 255 + 255 + 255 @@ -553,18 +559,18 @@ - 0 - 0 - 0 + 255 + 255 + 255 - 255 - 255 - 255 + 0 + 0 + 0 @@ -573,7 +579,7 @@ 0 0 - 170 + 0 @@ -589,9 +595,9 @@ - 127 - 127 - 212 + 0 + 0 + 0 @@ -618,9 +624,9 @@ - 0 - 0 - 0 + 255 + 255 + 255 @@ -629,7 +635,7 @@ 0 0 - 170 + 0 @@ -638,7 +644,7 @@ 0 0 - 255 + 0 @@ -647,7 +653,7 @@ 0 0 - 212 + 0 @@ -656,7 +662,7 @@ 0 0 - 85 + 0 @@ -665,16 +671,16 @@ 0 0 - 113 + 0 - 0 - 0 - 0 + 255 + 255 + 255 @@ -690,18 +696,18 @@ - 0 - 0 - 0 + 255 + 255 + 255 - 255 - 255 - 255 + 0 + 0 + 0 @@ -710,7 +716,7 @@ 0 0 - 170 + 0 @@ -726,9 +732,9 @@ - 127 - 127 - 212 + 0 + 0 + 0 @@ -757,7 +763,7 @@ 0 0 - 85 + 0 @@ -766,7 +772,7 @@ 0 0 - 170 + 0 @@ -775,7 +781,7 @@ 0 0 - 255 + 0 @@ -784,7 +790,7 @@ 0 0 - 212 + 0 @@ -793,7 +799,7 @@ 0 0 - 85 + 0 @@ -802,7 +808,7 @@ 0 0 - 113 + 0 @@ -811,7 +817,7 @@ 0 0 - 85 + 0 @@ -829,7 +835,7 @@ 0 0 - 85 + 0 @@ -838,7 +844,7 @@ 0 0 - 170 + 0 @@ -847,7 +853,7 @@ 0 0 - 170 + 0 @@ -865,7 +871,7 @@ 0 0 - 170 + 0 @@ -896,14 +902,27 @@ - + Qt::Horizontal - 84 - 20 + 0 + 0 + + + + + + + + Qt::Vertical + + + + 0 + 0 @@ -911,8 +930,34 @@ - - + + + + + 16 + 75 + true + + + + Test Name + + + + + + + + 16 + + + + Test description + + + + + 0 @@ -934,8 +979,8 @@ - 170 - 0 + 0 + 170 0 @@ -943,8 +988,8 @@ - 255 - 0 + 0 + 255 0 @@ -952,8 +997,8 @@ - 212 - 0 + 0 + 212 0 @@ -961,8 +1006,8 @@ - 85 - 0 + 0 + 85 0 @@ -970,8 +1015,8 @@ - 113 - 0 + 0 + 113 0 @@ -1015,8 +1060,8 @@ - 170 - 0 + 0 + 170 0 @@ -1033,8 +1078,8 @@ - 212 - 127 + 127 + 212 127 @@ -1071,8 +1116,8 @@ - 170 - 0 + 0 + 170 0 @@ -1080,8 +1125,8 @@ - 255 - 0 + 0 + 255 0 @@ -1089,8 +1134,8 @@ - 212 - 0 + 0 + 212 0 @@ -1098,8 +1143,8 @@ - 85 - 0 + 0 + 85 0 @@ -1107,8 +1152,8 @@ - 113 - 0 + 0 + 113 0 @@ -1152,8 +1197,8 @@ - 170 - 0 + 0 + 170 0 @@ -1170,8 +1215,8 @@ - 212 - 127 + 127 + 212 127 @@ -1199,8 +1244,8 @@ - 85 - 0 + 0 + 85 0 @@ -1208,8 +1253,8 @@ - 170 - 0 + 0 + 170 0 @@ -1217,8 +1262,8 @@ - 255 - 0 + 0 + 255 0 @@ -1226,8 +1271,8 @@ - 212 - 0 + 0 + 212 0 @@ -1235,8 +1280,8 @@ - 85 - 0 + 0 + 85 0 @@ -1244,8 +1289,8 @@ - 113 - 0 + 0 + 113 0 @@ -1253,8 +1298,8 @@ - 85 - 0 + 0 + 85 0 @@ -1271,8 +1316,8 @@ - 85 - 0 + 0 + 85 0 @@ -1280,8 +1325,8 @@ - 170 - 0 + 0 + 170 0 @@ -1289,8 +1334,8 @@ - 170 - 0 + 0 + 170 0 @@ -1307,8 +1352,8 @@ - 170 - 0 + 0 + 170 0 @@ -1337,35 +1382,28 @@ true - - - - - Qt::Vertical - - - - 20 - 290 - - - - + - + Qt::Horizontal - 84 - 20 + 0 + 0 - + + + + 0 + 0 + + 180 @@ -1378,9 +1416,9 @@ - 255 - 255 - 255 + 0 + 0 + 0 @@ -1389,7 +1427,7 @@ 0 0 - 0 + 170 @@ -1398,7 +1436,7 @@ 0 0 - 0 + 255 @@ -1407,7 +1445,7 @@ 0 0 - 0 + 212 @@ -1416,7 +1454,7 @@ 0 0 - 0 + 85 @@ -1425,16 +1463,16 @@ 0 0 - 0 + 113 - 255 - 255 - 255 + 0 + 0 + 0 @@ -1450,18 +1488,18 @@ - 255 - 255 - 255 + 0 + 0 + 0 - 0 - 0 - 0 + 255 + 255 + 255 @@ -1470,7 +1508,7 @@ 0 0 - 0 + 170 @@ -1486,9 +1524,9 @@ - 0 - 0 - 0 + 127 + 127 + 212 @@ -1515,9 +1553,9 @@ - 255 - 255 - 255 + 0 + 0 + 0 @@ -1526,7 +1564,7 @@ 0 0 - 0 + 170 @@ -1535,7 +1573,7 @@ 0 0 - 0 + 255 @@ -1544,7 +1582,7 @@ 0 0 - 0 + 212 @@ -1553,7 +1591,7 @@ 0 0 - 0 + 85 @@ -1562,16 +1600,16 @@ 0 0 - 0 + 113 - 255 - 255 - 255 + 0 + 0 + 0 @@ -1587,18 +1625,18 @@ - 255 - 255 - 255 + 0 + 0 + 0 - 0 - 0 - 0 + 255 + 255 + 255 @@ -1607,7 +1645,7 @@ 0 0 - 0 + 170 @@ -1623,9 +1661,9 @@ - 0 - 0 - 0 + 127 + 127 + 212 @@ -1654,7 +1692,7 @@ 0 0 - 0 + 85 @@ -1663,7 +1701,7 @@ 0 0 - 0 + 170 @@ -1672,7 +1710,7 @@ 0 0 - 0 + 255 @@ -1681,7 +1719,7 @@ 0 0 - 0 + 212 @@ -1690,7 +1728,7 @@ 0 0 - 0 + 85 @@ -1699,7 +1737,7 @@ 0 0 - 0 + 113 @@ -1708,7 +1746,7 @@ 0 0 - 0 + 85 @@ -1726,7 +1764,7 @@ 0 0 - 0 + 85 @@ -1735,7 +1773,7 @@ 0 0 - 0 + 170 @@ -1744,7 +1782,7 @@ 0 0 - 0 + 170 @@ -1762,7 +1800,7 @@ 0 0 - 0 + 170 @@ -1793,14 +1831,40 @@ - + Qt::Horizontal - 83 - 20 + 0 + 0 + + + + + + + + Qt::Vertical + + + + 0 + 0 + + + + + + + + Qt::Vertical + + + + 0 + 0 @@ -1808,26 +1872,6 @@ - - - - - 75 - true - - - - Test Name - - - - - - - Test description - - - diff --git a/tests/manual/qtouchevent/main.cpp b/tests/manual/qtouchevent/main.cpp index 2aab4ca..7ed9b15 100644 --- a/tests/manual/qtouchevent/main.cpp +++ b/tests/manual/qtouchevent/main.cpp @@ -12,8 +12,15 @@ public: MultitouchTestWidget(QWidget *parent = 0) : QWidget(parent) { + setAttribute(Qt::WA_QuitOnClose, false);\ setupUi(this); } + + void closeEvent(QCloseEvent *event) + { + event->accept(); + QTimer::singleShot(1000, qApp, SLOT(quit())); + } }; class tst_ManualMultitouch : public QObject @@ -25,7 +32,8 @@ public: ~tst_ManualMultitouch(); private slots: - void touchBeginPropagation(); + void basicEventHandling(); + void touchEventPropagation(); }; tst_ManualMultitouch::tst_ManualMultitouch() @@ -34,11 +42,99 @@ tst_ManualMultitouch::tst_ManualMultitouch() tst_ManualMultitouch::~tst_ManualMultitouch() { } -void tst_ManualMultitouch::touchBeginPropagation() +void tst_ManualMultitouch::basicEventHandling() +{ + // first, make sure that we get mouse events when not enabling touch events + MultitouchTestWidget testWidget; + testWidget.testNameLabel->setText("Basic QTouchEvent handling test"); + testWidget.testDescriptionLabel->setText("Touch, hold, and release your finger on the green widget."); + testWidget.redWidget->hide(); + testWidget.blueWidget->hide(); + testWidget.greenWidget->closeWindowOnMouseRelease = true; + testWidget.showMaximized(); + + (void) qApp->exec(); + QVERIFY(!testWidget.greenWidget->seenTouchBegin); + QVERIFY(!testWidget.greenWidget->seenTouchUpdate); + QVERIFY(!testWidget.greenWidget->seenTouchEnd); + QVERIFY(testWidget.greenWidget->seenMousePress); + // QVERIFY(testWidget.greenWidget->seenMouseMove); + QVERIFY(testWidget.greenWidget->seenMouseRelease); + + // now enable touch and make sure we get the touch events + testWidget.greenWidget->reset(); + testWidget.greenWidget->setAttribute(Qt::WA_AcceptTouchEvents); + testWidget.greenWidget->acceptTouchBegin = true; + testWidget.greenWidget->acceptTouchUpdate = true; + testWidget.greenWidget->acceptTouchEnd = true; + testWidget.greenWidget->closeWindowOnTouchEnd = true; + testWidget.showMaximized(); + + (void) qApp->exec(); + QVERIFY(testWidget.greenWidget->seenTouchBegin + && testWidget.greenWidget->seenTouchUpdate + && testWidget.greenWidget->seenTouchEnd); + QVERIFY(!testWidget.greenWidget->seenMousePress + && !testWidget.greenWidget->seenMouseMove + && !testWidget.greenWidget->seenMouseRelease); + + // again, ignoring the TouchEnd + testWidget.greenWidget->reset(); + testWidget.greenWidget->acceptTouchBegin = true; + testWidget.greenWidget->acceptTouchUpdate = true; + // testWidget.greenWidget->acceptTouchEnd = true; + testWidget.greenWidget->closeWindowOnTouchEnd = true; + testWidget.showMaximized(); + + (void) qApp->exec(); + QVERIFY(testWidget.greenWidget->seenTouchBegin); + QVERIFY(testWidget.greenWidget->seenTouchUpdate); + QVERIFY(testWidget.greenWidget->seenTouchEnd); + QVERIFY(!testWidget.greenWidget->seenMousePress); + QVERIFY(!testWidget.greenWidget->seenMouseMove); + QVERIFY(!testWidget.greenWidget->seenMouseRelease); + + // again, ignoring TouchUpdates + testWidget.greenWidget->reset(); + testWidget.greenWidget->acceptTouchBegin = true; + // testWidget.greenWidget->acceptTouchUpdate = true; + testWidget.greenWidget->acceptTouchEnd = true; + testWidget.greenWidget->closeWindowOnTouchEnd = true; + testWidget.showMaximized(); + + (void) qApp->exec(); + QVERIFY(testWidget.greenWidget->seenTouchBegin); + QVERIFY(testWidget.greenWidget->seenTouchUpdate); + QVERIFY(testWidget.greenWidget->seenTouchEnd); + QVERIFY(!testWidget.greenWidget->seenMousePress); + QVERIFY(!testWidget.greenWidget->seenMouseMove); + QVERIFY(!testWidget.greenWidget->seenMouseRelease); + + // last time, ignoring TouchUpdates and TouchEnd + testWidget.greenWidget->reset(); + testWidget.greenWidget->acceptTouchBegin = true; + // testWidget.greenWidget->acceptTouchUpdate = true; + // testWidget.greenWidget->acceptTouchEnd = true; + testWidget.greenWidget->closeWindowOnTouchEnd = true; + testWidget.showMaximized(); + + (void) qApp->exec(); + QVERIFY(testWidget.greenWidget->seenTouchBegin); + QVERIFY(testWidget.greenWidget->seenTouchUpdate); + QVERIFY(testWidget.greenWidget->seenTouchEnd); + QVERIFY(!testWidget.greenWidget->seenMousePress); + QVERIFY(!testWidget.greenWidget->seenMouseMove); + QVERIFY(!testWidget.greenWidget->seenMouseRelease); +} + +void tst_ManualMultitouch::touchEventPropagation() { + // first, make sure the greenWidget gets TouchBegin even though blueWidget is not touch aware MultitouchTestWidget testWidget; - testWidget.testNameLabel->setText("Touch event propagation"); - testWidget.testDescriptionLabel->setText("Touch, move, and release your finger over the green widget."); + testWidget.testNameLabel->setText("QTouchEvent propagation test"); + testWidget.testDescriptionLabel->setText("Touch, hold, and release your finger on the blue widget."); + testWidget.redWidget->hide(); + // testWidget.blueWidget->setAttribute(Qt::WA_AcceptTouchEvents); testWidget.greenWidget->setAttribute(Qt::WA_AcceptTouchEvents); testWidget.greenWidget->acceptTouchBegin = true; testWidget.greenWidget->acceptTouchUpdate = true; @@ -47,6 +143,36 @@ void tst_ManualMultitouch::touchBeginPropagation() testWidget.showMaximized(); (void) qApp->exec(); + QVERIFY(!testWidget.blueWidget->seenTouchBegin); + QVERIFY(!testWidget.blueWidget->seenTouchUpdate); + QVERIFY(!testWidget.blueWidget->seenTouchEnd); + QVERIFY(!testWidget.blueWidget->seenMousePress); + QVERIFY(!testWidget.blueWidget->seenMouseMove); + QVERIFY(!testWidget.blueWidget->seenMouseRelease); + QVERIFY(testWidget.greenWidget->seenTouchBegin); + QVERIFY(testWidget.greenWidget->seenTouchUpdate); + QVERIFY(testWidget.greenWidget->seenTouchEnd); + QVERIFY(!testWidget.greenWidget->seenMousePress); + QVERIFY(!testWidget.greenWidget->seenMouseMove); + QVERIFY(!testWidget.greenWidget->seenMouseRelease); + + // again, but this time blueWidget should see the TouchBegin + testWidget.blueWidget->reset(); + testWidget.greenWidget->reset(); + testWidget.blueWidget->setAttribute(Qt::WA_AcceptTouchEvents); + testWidget.greenWidget->acceptTouchBegin = true; + testWidget.greenWidget->acceptTouchUpdate = true; + testWidget.greenWidget->acceptTouchEnd = true; + testWidget.greenWidget->closeWindowOnTouchEnd = true; + testWidget.showMaximized(); + + (void) qApp->exec(); + QVERIFY(testWidget.blueWidget->seenTouchBegin); + QVERIFY(!testWidget.blueWidget->seenTouchUpdate); + QVERIFY(!testWidget.blueWidget->seenTouchEnd); + QVERIFY(!testWidget.blueWidget->seenMousePress); + QVERIFY(!testWidget.blueWidget->seenMouseMove); + QVERIFY(!testWidget.blueWidget->seenMouseRelease); QVERIFY(testWidget.greenWidget->seenTouchBegin); QVERIFY(testWidget.greenWidget->seenTouchUpdate); QVERIFY(testWidget.greenWidget->seenTouchEnd); @@ -63,6 +189,12 @@ void tst_ManualMultitouch::touchBeginPropagation() testWidget.showMaximized(); (void) qApp->exec(); + QVERIFY(testWidget.blueWidget->seenTouchBegin); + QVERIFY(!testWidget.blueWidget->seenTouchUpdate); + QVERIFY(!testWidget.blueWidget->seenTouchEnd); + QVERIFY(!testWidget.blueWidget->seenMousePress); + QVERIFY(!testWidget.blueWidget->seenMouseMove); + QVERIFY(!testWidget.blueWidget->seenMouseRelease); QVERIFY(testWidget.greenWidget->seenTouchBegin); QVERIFY(testWidget.greenWidget->seenTouchUpdate); QVERIFY(testWidget.greenWidget->seenTouchEnd); @@ -79,6 +211,12 @@ void tst_ManualMultitouch::touchBeginPropagation() testWidget.showMaximized(); (void) qApp->exec(); + QVERIFY(testWidget.blueWidget->seenTouchBegin); + QVERIFY(!testWidget.blueWidget->seenTouchUpdate); + QVERIFY(!testWidget.blueWidget->seenTouchEnd); + QVERIFY(!testWidget.blueWidget->seenMousePress); + QVERIFY(!testWidget.blueWidget->seenMouseMove); + QVERIFY(!testWidget.blueWidget->seenMouseRelease); QVERIFY(testWidget.greenWidget->seenTouchBegin); QVERIFY(testWidget.greenWidget->seenTouchUpdate); QVERIFY(testWidget.greenWidget->seenTouchEnd); @@ -95,6 +233,12 @@ void tst_ManualMultitouch::touchBeginPropagation() testWidget.showMaximized(); (void) qApp->exec(); + QVERIFY(testWidget.blueWidget->seenTouchBegin); + QVERIFY(!testWidget.blueWidget->seenTouchUpdate); + QVERIFY(!testWidget.blueWidget->seenTouchEnd); + QVERIFY(!testWidget.blueWidget->seenMousePress); + QVERIFY(!testWidget.blueWidget->seenMouseMove); + QVERIFY(!testWidget.blueWidget->seenMouseRelease); QVERIFY(testWidget.greenWidget->seenTouchBegin); QVERIFY(testWidget.greenWidget->seenTouchUpdate); QVERIFY(testWidget.greenWidget->seenTouchEnd); diff --git a/tests/manual/qtouchevent/touchwidget.cpp b/tests/manual/qtouchevent/touchwidget.cpp index 54ca685..1e57c36 100644 --- a/tests/manual/qtouchevent/touchwidget.cpp +++ b/tests/manual/qtouchevent/touchwidget.cpp @@ -1,9 +1,10 @@ #include "touchwidget.h" -#include +#include +#include +#include #include - void TouchWidget::reset() { acceptTouchBegin @@ -69,7 +70,7 @@ bool TouchWidget::event(QEvent *event) case QEvent::MouseButtonRelease: seenMouseRelease = true; if (closeWindowOnMouseRelease) - window()->close(); + window()->close(); if (acceptMouseRelease) { event->accept(); return true; -- cgit v0.12 From ec2d71f0e4af0e0c286f0027d0242f456fdb2bb6 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Thu, 23 Apr 2009 17:57:46 +0200 Subject: Fix tests/manual/qtouchevent by choking mouse events even for ignored TouchUpdate and TouchEnd events. The behavior we want is that no mouse events are sent if the widget accepts the TouchBegin. --- src/gui/kernel/qapplication_p.h | 1 + src/gui/kernel/qapplication_win.cpp | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index ce7110d..91857ec 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -429,6 +429,7 @@ public: #endif QPointer currentMultitouchWidget; + bool currentMultitouchWidgetAcceptedTouchBegin; static void updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent); #if defined(Q_WS_WIN) diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 4878ea7..5a4efd6 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -4003,6 +4003,7 @@ void QApplicationPrivate::initializeMultitouch() CloseTouchInputHandle = static_cast(library.resolve("CloseTouchInputHandle")); currentMultitouchWidget = 0; + currentMultitouchWidgetAcceptedTouchBegin = false; touchInputIDToTouchPointID.clear(); allTouchPoints.clear(); currentTouchPoints.clear(); @@ -4106,6 +4107,9 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) if (!child) child = window; currentMultitouchWidget = child; + // if the TouchBegin handler recurses, we assume that means the event + // has been implicitly accepted and continue to send touch events + currentMultitouchWidgetAcceptedTouchBegin = true; } } @@ -4131,8 +4135,19 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) q->keyboardModifiers(), activeTouchPoints); updateTouchPointsForWidget(widget, &touchEvent); - bool res = QApplication::sendSpontaneousEvent(widget, &touchEvent); - return (qt_tabletChokeMouse = res && touchEvent.isAccepted()); + if (sendTouchBegin) { + bool res = QApplication::sendSpontaneousEvent(widget, &touchEvent); + qt_tabletChokeMouse + = currentMultitouchWidgetAcceptedTouchBegin + = (res && touchEvent.isAccepted()); + } else if (currentMultitouchWidgetAcceptedTouchBegin) { + (void) QApplication::sendSpontaneousEvent(widget, &touchEvent); + qt_tabletChokeMouse = true; + } else { + qt_tabletChokeMouse = false; + } + + return qt_tabletChokeMouse; } return false; -- cgit v0.12 From 34788b2cb7af9e515fe9de5c4dc81744dda68d1e Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Fri, 24 Apr 2009 12:41:44 +0200 Subject: Test that accepting the TouchBegin stops propagation --- tests/manual/qtouchevent/main.cpp | 106 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 103 insertions(+), 3 deletions(-) diff --git a/tests/manual/qtouchevent/main.cpp b/tests/manual/qtouchevent/main.cpp index 7ed9b15..a66a546 100644 --- a/tests/manual/qtouchevent/main.cpp +++ b/tests/manual/qtouchevent/main.cpp @@ -129,13 +129,110 @@ void tst_ManualMultitouch::basicEventHandling() void tst_ManualMultitouch::touchEventPropagation() { - // first, make sure the greenWidget gets TouchBegin even though blueWidget is not touch aware MultitouchTestWidget testWidget; testWidget.testNameLabel->setText("QTouchEvent propagation test"); testWidget.testDescriptionLabel->setText("Touch, hold, and release your finger on the blue widget."); - testWidget.redWidget->hide(); - // testWidget.blueWidget->setAttribute(Qt::WA_AcceptTouchEvents); + testWidget.redWidget->hide(); + + // test that accepting the TouchBegin event on the + // blueWidget stops propagation to the greenWidget + testWidget.blueWidget->setAttribute(Qt::WA_AcceptTouchEvents); testWidget.greenWidget->setAttribute(Qt::WA_AcceptTouchEvents); + testWidget.blueWidget->acceptTouchBegin = true; + testWidget.blueWidget->acceptTouchUpdate = true; + testWidget.blueWidget->acceptTouchEnd = true; + testWidget.blueWidget->closeWindowOnTouchEnd = true; + testWidget.showMaximized(); + + (void) qApp->exec(); + QVERIFY(testWidget.blueWidget->seenTouchBegin); + QVERIFY(testWidget.blueWidget->seenTouchUpdate); + QVERIFY(testWidget.blueWidget->seenTouchEnd); + QVERIFY(!testWidget.blueWidget->seenMousePress); + QVERIFY(!testWidget.blueWidget->seenMouseMove); + QVERIFY(!testWidget.blueWidget->seenMouseRelease); + QVERIFY(!testWidget.greenWidget->seenTouchBegin); + QVERIFY(!testWidget.greenWidget->seenTouchUpdate); + QVERIFY(!testWidget.greenWidget->seenTouchEnd); + QVERIFY(!testWidget.greenWidget->seenMousePress); + QVERIFY(!testWidget.greenWidget->seenMouseMove); + QVERIFY(!testWidget.greenWidget->seenMouseRelease); + + // ignoring TouchEnd + testWidget.blueWidget->reset(); + testWidget.greenWidget->reset(); + testWidget.blueWidget->acceptTouchBegin = true; + testWidget.blueWidget->acceptTouchUpdate = true; + // testWidget.blueWidget->acceptTouchEnd = true; + testWidget.blueWidget->closeWindowOnTouchEnd = true; + testWidget.showMaximized(); + + (void) qApp->exec(); + QVERIFY(testWidget.blueWidget->seenTouchBegin); + QVERIFY(testWidget.blueWidget->seenTouchUpdate); + QVERIFY(testWidget.blueWidget->seenTouchEnd); + QVERIFY(!testWidget.blueWidget->seenMousePress); + QVERIFY(!testWidget.blueWidget->seenMouseMove); + QVERIFY(!testWidget.blueWidget->seenMouseRelease); + QVERIFY(!testWidget.greenWidget->seenTouchBegin); + QVERIFY(!testWidget.greenWidget->seenTouchUpdate); + QVERIFY(!testWidget.greenWidget->seenTouchEnd); + QVERIFY(!testWidget.greenWidget->seenMousePress); + QVERIFY(!testWidget.greenWidget->seenMouseMove); + QVERIFY(!testWidget.greenWidget->seenMouseRelease); + + // ignoring TouchUpdate + testWidget.blueWidget->reset(); + testWidget.greenWidget->reset(); + testWidget.blueWidget->acceptTouchBegin = true; + // testWidget.blueWidget->acceptTouchUpdate = true; + testWidget.blueWidget->acceptTouchEnd = true; + testWidget.blueWidget->closeWindowOnTouchEnd = true; + testWidget.showMaximized(); + + (void) qApp->exec(); + QVERIFY(testWidget.blueWidget->seenTouchBegin); + QVERIFY(testWidget.blueWidget->seenTouchUpdate); + QVERIFY(testWidget.blueWidget->seenTouchEnd); + QVERIFY(!testWidget.blueWidget->seenMousePress); + QVERIFY(!testWidget.blueWidget->seenMouseMove); + QVERIFY(!testWidget.blueWidget->seenMouseRelease); + QVERIFY(!testWidget.greenWidget->seenTouchBegin); + QVERIFY(!testWidget.greenWidget->seenTouchUpdate); + QVERIFY(!testWidget.greenWidget->seenTouchEnd); + QVERIFY(!testWidget.greenWidget->seenMousePress); + QVERIFY(!testWidget.greenWidget->seenMouseMove); + QVERIFY(!testWidget.greenWidget->seenMouseRelease); + + // ignoring TouchUpdate and TouchEnd + testWidget.blueWidget->reset(); + testWidget.greenWidget->reset(); + testWidget.blueWidget->acceptTouchBegin = true; + // testWidget.blueWidget->acceptTouchUpdate = true; + // testWidget.blueWidget->acceptTouchEnd = true; + testWidget.blueWidget->closeWindowOnTouchEnd = true; + testWidget.showMaximized(); + + (void) qApp->exec(); + QVERIFY(testWidget.blueWidget->seenTouchBegin); + QVERIFY(testWidget.blueWidget->seenTouchUpdate); + QVERIFY(testWidget.blueWidget->seenTouchEnd); + QVERIFY(!testWidget.blueWidget->seenMousePress); + QVERIFY(!testWidget.blueWidget->seenMouseMove); + QVERIFY(!testWidget.blueWidget->seenMouseRelease); + QVERIFY(!testWidget.greenWidget->seenTouchBegin); + QVERIFY(!testWidget.greenWidget->seenTouchUpdate); + QVERIFY(!testWidget.greenWidget->seenTouchEnd); + QVERIFY(!testWidget.greenWidget->seenMousePress); + QVERIFY(!testWidget.greenWidget->seenMouseMove); + QVERIFY(!testWidget.greenWidget->seenMouseRelease); + + // repeat the test above, now ignoring touch events in the + // blueWidget, they should be propagated to the greenWidget + testWidget.blueWidget->setAttribute(Qt::WA_AcceptTouchEvents, false); + testWidget.greenWidget->setAttribute(Qt::WA_AcceptTouchEvents); + testWidget.blueWidget->reset(); + testWidget.greenWidget->reset(); testWidget.greenWidget->acceptTouchBegin = true; testWidget.greenWidget->acceptTouchUpdate = true; testWidget.greenWidget->acceptTouchEnd = true; @@ -181,6 +278,7 @@ void tst_ManualMultitouch::touchEventPropagation() QVERIFY(!testWidget.greenWidget->seenMouseRelease); // again, ignoring the TouchEnd + testWidget.blueWidget->reset(); testWidget.greenWidget->reset(); testWidget.greenWidget->acceptTouchBegin = true; testWidget.greenWidget->acceptTouchUpdate = true; @@ -203,6 +301,7 @@ void tst_ManualMultitouch::touchEventPropagation() QVERIFY(!testWidget.greenWidget->seenMouseRelease); // again, ignoring TouchUpdates + testWidget.blueWidget->reset(); testWidget.greenWidget->reset(); testWidget.greenWidget->acceptTouchBegin = true; // testWidget.greenWidget->acceptTouchUpdate = true; @@ -225,6 +324,7 @@ void tst_ManualMultitouch::touchEventPropagation() QVERIFY(!testWidget.greenWidget->seenMouseRelease); // last time, ignoring TouchUpdates and TouchEnd + testWidget.blueWidget->reset(); testWidget.greenWidget->reset(); testWidget.greenWidget->acceptTouchBegin = true; // testWidget.greenWidget->acceptTouchUpdate = true; -- cgit v0.12 From 76b3d0526b524b79603e4e1b337c32f3bfcc6340 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Fri, 24 Apr 2009 12:55:48 +0200 Subject: change the layout a bit in the test's form --- tests/manual/qtouchevent/form.ui | 3672 +++++++++++++++++++------------------- 1 file changed, 1838 insertions(+), 1834 deletions(-) diff --git a/tests/manual/qtouchevent/form.ui b/tests/manual/qtouchevent/form.ui index 6cf4cba..4c2da3a 100644 --- a/tests/manual/qtouchevent/form.ui +++ b/tests/manual/qtouchevent/form.ui @@ -13,924 +13,8 @@ Form - - - - - - 0 - 0 - - - - - - - - - 0 - 0 - 0 - - - - - - - 170 - 0 - 0 - - - - - - - 255 - 0 - 0 - - - - - - - 212 - 0 - 0 - - - - - - - 85 - 0 - 0 - - - - - - - 113 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 170 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 212 - 127 - 127 - - - - - - - 255 - 255 - 220 - - - - - - - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - - - - - - - 170 - 0 - 0 - - - - - - - 255 - 0 - 0 - - - - - - - 212 - 0 - 0 - - - - - - - 85 - 0 - 0 - - - - - - - 113 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 170 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 212 - 127 - 127 - - - - - - - 255 - 255 - 220 - - - - - - - 0 - 0 - 0 - - - - - - - - - 85 - 0 - 0 - - - - - - - 170 - 0 - 0 - - - - - - - 255 - 0 - 0 - - - - - - - 212 - 0 - 0 - - - - - - - 85 - 0 - 0 - - - - - - - 113 - 0 - 0 - - - - - - - 85 - 0 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 85 - 0 - 0 - - - - - - - 170 - 0 - 0 - - - - - - - 170 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 170 - 0 - 0 - - - - - - - 255 - 255 - 220 - - - - - - - 0 - 0 - 0 - - - - - - - - true - - - - - - Qt::Vertical - - - - 0 - 0 - - - - - - - - Qt::Horizontal - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - - 180 - 120 - - - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 220 - - - - - - - 0 - 0 - 0 - - - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 220 - - - - - - - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 220 - - - - - - - 0 - 0 - 0 - - - - - - - - true - - - - - - - Qt::Horizontal - - - - 0 - 0 - - - - - - - - Qt::Vertical - - - - 0 - 0 - - - - - - - - + + @@ -944,7 +28,7 @@ - + @@ -956,921 +40,1841 @@ - - - - - 0 - 0 - - - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 170 - 0 - - - - - - - 0 - 255 - 0 - - - - - - - 0 - 212 - 0 - - - - - - - 0 - 85 - 0 - - - - - - - 0 - 113 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 170 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 127 - 212 - 127 - - - - - - - 255 - 255 - 220 - - - - - - - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 170 - 0 - - - - - - - 0 - 255 - 0 - - - - - - - 0 - 212 - 0 - - - - - - - 0 - 85 - 0 - - - - - - - 0 - 113 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 170 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 127 - 212 - 127 - - - - - - - 255 - 255 - 220 - - - - - - - 0 - 0 - 0 - - - - - - - - - 0 - 85 - 0 - - - - - - - 0 - 170 - 0 - - - - - - - 0 - 255 - 0 - - - - - - - 0 - 212 - 0 - - - - - - - 0 - 85 - 0 - - - - - - - 0 - 113 - 0 - - - - - - - 0 - 85 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 85 - 0 - - - - - - - 0 - 170 - 0 - - - - - - - 0 - 170 - 0 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 170 - 0 - - - - - - - 255 - 255 - 220 - - - - - - - 0 - 0 - 0 - - - - - - - - true - - - - - - Qt::Horizontal - - - - 0 - 0 - - - - - - - - - 0 - 0 - - - - - 180 - 120 - - - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 170 - - - - - - - 0 - 0 - 255 - - - - - - - 0 - 0 - 212 - - - - - - - 0 - 0 - 85 - - - - - - - 0 - 0 - 113 - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 0 - 170 - - - - - - - 0 - 0 - 0 - - - - - - - 127 - 127 - 212 - - - - - - - 255 - 255 - 220 - - - - - - - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 170 - - - - - - - 0 - 0 - 255 - - - - - - - 0 - 0 - 212 - - - - - - - 0 - 0 - 85 - - - - - - - 0 - 0 - 113 - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 0 - 0 - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 0 - 170 - - - - - - - 0 - 0 - 0 - - - - - - - 127 - 127 - 212 - - - - - - - 255 - 255 - 220 - - - - - - - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 85 - - - - - - - 0 - 0 - 170 - - - - - - - 0 - 0 - 255 - - - - - - - 0 - 0 - 212 - - - - - - - 0 - 0 - 85 - - - - - - - 0 - 0 - 113 - - - - - - - 0 - 0 - 85 - - - - - - - 255 - 255 - 255 - - - - - - - 0 - 0 - 85 - - - - - - - 0 - 0 - 170 - - - - - - - 0 - 0 - 170 - - - - - - - 0 - 0 - 0 - - - - - - - 0 - 0 - 170 - - - - - - - 255 - 255 - 220 - - - - - - - 0 - 0 - 0 - - - - - - - - true - - - - - - - Qt::Horizontal - - - - 0 - 0 - - - - - - - - Qt::Vertical - - - - 0 - 0 - - - - - - - - Qt::Vertical - - - - 0 - 0 - - - - - - + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 170 + 0 + + + + + + + 0 + 255 + 0 + + + + + + + 0 + 212 + 0 + + + + + + + 0 + 85 + 0 + + + + + + + 0 + 113 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 170 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 127 + 212 + 127 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 170 + 0 + + + + + + + 0 + 255 + 0 + + + + + + + 0 + 212 + 0 + + + + + + + 0 + 85 + 0 + + + + + + + 0 + 113 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 170 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 127 + 212 + 127 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 85 + 0 + + + + + + + 0 + 170 + 0 + + + + + + + 0 + 255 + 0 + + + + + + + 0 + 212 + 0 + + + + + + + 0 + 85 + 0 + + + + + + + 0 + 113 + 0 + + + + + + + 0 + 85 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 85 + 0 + + + + + + + 0 + 170 + 0 + + + + + + + 0 + 170 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 170 + 0 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + true + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + 180 + 120 + + + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 170 + + + + + + + 0 + 0 + 255 + + + + + + + 0 + 0 + 212 + + + + + + + 0 + 0 + 85 + + + + + + + 0 + 0 + 113 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 170 + + + + + + + 0 + 0 + 0 + + + + + + + 127 + 127 + 212 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 170 + + + + + + + 0 + 0 + 255 + + + + + + + 0 + 0 + 212 + + + + + + + 0 + 0 + 85 + + + + + + + 0 + 0 + 113 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 170 + + + + + + + 0 + 0 + 0 + + + + + + + 127 + 127 + 212 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 85 + + + + + + + 0 + 0 + 170 + + + + + + + 0 + 0 + 255 + + + + + + + 0 + 0 + 212 + + + + + + + 0 + 0 + 85 + + + + + + + 0 + 0 + 113 + + + + + + + 0 + 0 + 85 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 85 + + + + + + + 0 + 0 + 170 + + + + + + + 0 + 0 + 170 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 170 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + true + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + Qt::Vertical + + + + 0 + 0 + + + + + + + + Qt::Vertical + + + + 0 + 0 + + + + + + + + + + + + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 170 + 0 + 0 + + + + + + + 255 + 0 + 0 + + + + + + + 212 + 0 + 0 + + + + + + + 85 + 0 + 0 + + + + + + + 113 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 170 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 212 + 127 + 127 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 170 + 0 + 0 + + + + + + + 255 + 0 + 0 + + + + + + + 212 + 0 + 0 + + + + + + + 85 + 0 + 0 + + + + + + + 113 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 170 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 212 + 127 + 127 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + + 85 + 0 + 0 + + + + + + + 170 + 0 + 0 + + + + + + + 255 + 0 + 0 + + + + + + + 212 + 0 + 0 + + + + + + + 85 + 0 + 0 + + + + + + + 113 + 0 + 0 + + + + + + + 85 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 85 + 0 + 0 + + + + + + + 170 + 0 + 0 + + + + + + + 170 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 170 + 0 + 0 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + true + + + + + + Qt::Vertical + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + + 0 + 0 + + + + + 180 + 120 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 255 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 0 + 0 + 0 + + + + + + + 255 + 255 + 220 + + + + + + + 0 + 0 + 0 + + + + + + + + true + + + + + + + Qt::Horizontal + + + + 0 + 0 + + + + + + + + Qt::Vertical + + + + 0 + 0 + + + + + + + + -- cgit v0.12 From ed2e1e64d922e3e531984d099a800515037c89f6 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Fri, 24 Apr 2009 13:00:31 +0200 Subject: Use a different widget color to indicate that we are testing different things --- tests/manual/qtouchevent/main.cpp | 196 +++++++++++++++++++------------------- 1 file changed, 100 insertions(+), 96 deletions(-) diff --git a/tests/manual/qtouchevent/main.cpp b/tests/manual/qtouchevent/main.cpp index a66a546..05fdc44 100644 --- a/tests/manual/qtouchevent/main.cpp +++ b/tests/manual/qtouchevent/main.cpp @@ -130,7 +130,7 @@ void tst_ManualMultitouch::basicEventHandling() void tst_ManualMultitouch::touchEventPropagation() { MultitouchTestWidget testWidget; - testWidget.testNameLabel->setText("QTouchEvent propagation test"); + testWidget.testNameLabel->setText("QTouchEvent propagation test, Blue blocks Green"); testWidget.testDescriptionLabel->setText("Touch, hold, and release your finger on the blue widget."); testWidget.redWidget->hide(); @@ -228,123 +228,127 @@ void tst_ManualMultitouch::touchEventPropagation() QVERIFY(!testWidget.greenWidget->seenMouseRelease); // repeat the test above, now ignoring touch events in the - // blueWidget, they should be propagated to the greenWidget - testWidget.blueWidget->setAttribute(Qt::WA_AcceptTouchEvents, false); - testWidget.greenWidget->setAttribute(Qt::WA_AcceptTouchEvents); - testWidget.blueWidget->reset(); - testWidget.greenWidget->reset(); - testWidget.greenWidget->acceptTouchBegin = true; - testWidget.greenWidget->acceptTouchUpdate = true; - testWidget.greenWidget->acceptTouchEnd = true; - testWidget.greenWidget->closeWindowOnTouchEnd = true; + // greyWidget, they should be propagated to the redWidget + testWidget.testNameLabel->setText("QTouchEvent propagation test, Red handles Grey's ignored events"); + testWidget.testDescriptionLabel->setText("Touch, hold, and release your finger on the grey widget."); + testWidget.greenWidget->hide(); + testWidget.redWidget->show(); + testWidget.greyWidget->setAttribute(Qt::WA_AcceptTouchEvents, false); + testWidget.redWidget->setAttribute(Qt::WA_AcceptTouchEvents); + testWidget.greyWidget->reset(); + testWidget.redWidget->reset(); + testWidget.redWidget->acceptTouchBegin = true; + testWidget.redWidget->acceptTouchUpdate = true; + testWidget.redWidget->acceptTouchEnd = true; + testWidget.redWidget->closeWindowOnTouchEnd = true; testWidget.showMaximized(); (void) qApp->exec(); - QVERIFY(!testWidget.blueWidget->seenTouchBegin); - QVERIFY(!testWidget.blueWidget->seenTouchUpdate); - QVERIFY(!testWidget.blueWidget->seenTouchEnd); - QVERIFY(!testWidget.blueWidget->seenMousePress); - QVERIFY(!testWidget.blueWidget->seenMouseMove); - QVERIFY(!testWidget.blueWidget->seenMouseRelease); - QVERIFY(testWidget.greenWidget->seenTouchBegin); - QVERIFY(testWidget.greenWidget->seenTouchUpdate); - QVERIFY(testWidget.greenWidget->seenTouchEnd); - QVERIFY(!testWidget.greenWidget->seenMousePress); - QVERIFY(!testWidget.greenWidget->seenMouseMove); - QVERIFY(!testWidget.greenWidget->seenMouseRelease); - - // again, but this time blueWidget should see the TouchBegin - testWidget.blueWidget->reset(); - testWidget.greenWidget->reset(); - testWidget.blueWidget->setAttribute(Qt::WA_AcceptTouchEvents); - testWidget.greenWidget->acceptTouchBegin = true; - testWidget.greenWidget->acceptTouchUpdate = true; - testWidget.greenWidget->acceptTouchEnd = true; - testWidget.greenWidget->closeWindowOnTouchEnd = true; + QVERIFY(!testWidget.greyWidget->seenTouchBegin); + QVERIFY(!testWidget.greyWidget->seenTouchUpdate); + QVERIFY(!testWidget.greyWidget->seenTouchEnd); + QVERIFY(!testWidget.greyWidget->seenMousePress); + QVERIFY(!testWidget.greyWidget->seenMouseMove); + QVERIFY(!testWidget.greyWidget->seenMouseRelease); + QVERIFY(testWidget.redWidget->seenTouchBegin); + QVERIFY(testWidget.redWidget->seenTouchUpdate); + QVERIFY(testWidget.redWidget->seenTouchEnd); + QVERIFY(!testWidget.redWidget->seenMousePress); + QVERIFY(!testWidget.redWidget->seenMouseMove); + QVERIFY(!testWidget.redWidget->seenMouseRelease); + + // again, but this time greyWidget should see the TouchBegin + testWidget.greyWidget->reset(); + testWidget.redWidget->reset(); + testWidget.greyWidget->setAttribute(Qt::WA_AcceptTouchEvents); + testWidget.redWidget->acceptTouchBegin = true; + testWidget.redWidget->acceptTouchUpdate = true; + testWidget.redWidget->acceptTouchEnd = true; + testWidget.redWidget->closeWindowOnTouchEnd = true; testWidget.showMaximized(); (void) qApp->exec(); - QVERIFY(testWidget.blueWidget->seenTouchBegin); - QVERIFY(!testWidget.blueWidget->seenTouchUpdate); - QVERIFY(!testWidget.blueWidget->seenTouchEnd); - QVERIFY(!testWidget.blueWidget->seenMousePress); - QVERIFY(!testWidget.blueWidget->seenMouseMove); - QVERIFY(!testWidget.blueWidget->seenMouseRelease); - QVERIFY(testWidget.greenWidget->seenTouchBegin); - QVERIFY(testWidget.greenWidget->seenTouchUpdate); - QVERIFY(testWidget.greenWidget->seenTouchEnd); - QVERIFY(!testWidget.greenWidget->seenMousePress); - QVERIFY(!testWidget.greenWidget->seenMouseMove); - QVERIFY(!testWidget.greenWidget->seenMouseRelease); + QVERIFY(testWidget.greyWidget->seenTouchBegin); + QVERIFY(!testWidget.greyWidget->seenTouchUpdate); + QVERIFY(!testWidget.greyWidget->seenTouchEnd); + QVERIFY(!testWidget.greyWidget->seenMousePress); + QVERIFY(!testWidget.greyWidget->seenMouseMove); + QVERIFY(!testWidget.greyWidget->seenMouseRelease); + QVERIFY(testWidget.redWidget->seenTouchBegin); + QVERIFY(testWidget.redWidget->seenTouchUpdate); + QVERIFY(testWidget.redWidget->seenTouchEnd); + QVERIFY(!testWidget.redWidget->seenMousePress); + QVERIFY(!testWidget.redWidget->seenMouseMove); + QVERIFY(!testWidget.redWidget->seenMouseRelease); // again, ignoring the TouchEnd - testWidget.blueWidget->reset(); - testWidget.greenWidget->reset(); - testWidget.greenWidget->acceptTouchBegin = true; - testWidget.greenWidget->acceptTouchUpdate = true; - // testWidget.greenWidget->acceptTouchEnd = true; - testWidget.greenWidget->closeWindowOnTouchEnd = true; + testWidget.greyWidget->reset(); + testWidget.redWidget->reset(); + testWidget.redWidget->acceptTouchBegin = true; + testWidget.redWidget->acceptTouchUpdate = true; + // testWidget.redWidget->acceptTouchEnd = true; + testWidget.redWidget->closeWindowOnTouchEnd = true; testWidget.showMaximized(); (void) qApp->exec(); - QVERIFY(testWidget.blueWidget->seenTouchBegin); - QVERIFY(!testWidget.blueWidget->seenTouchUpdate); - QVERIFY(!testWidget.blueWidget->seenTouchEnd); - QVERIFY(!testWidget.blueWidget->seenMousePress); - QVERIFY(!testWidget.blueWidget->seenMouseMove); - QVERIFY(!testWidget.blueWidget->seenMouseRelease); - QVERIFY(testWidget.greenWidget->seenTouchBegin); - QVERIFY(testWidget.greenWidget->seenTouchUpdate); - QVERIFY(testWidget.greenWidget->seenTouchEnd); - QVERIFY(!testWidget.greenWidget->seenMousePress); - QVERIFY(!testWidget.greenWidget->seenMouseMove); - QVERIFY(!testWidget.greenWidget->seenMouseRelease); + QVERIFY(testWidget.greyWidget->seenTouchBegin); + QVERIFY(!testWidget.greyWidget->seenTouchUpdate); + QVERIFY(!testWidget.greyWidget->seenTouchEnd); + QVERIFY(!testWidget.greyWidget->seenMousePress); + QVERIFY(!testWidget.greyWidget->seenMouseMove); + QVERIFY(!testWidget.greyWidget->seenMouseRelease); + QVERIFY(testWidget.redWidget->seenTouchBegin); + QVERIFY(testWidget.redWidget->seenTouchUpdate); + QVERIFY(testWidget.redWidget->seenTouchEnd); + QVERIFY(!testWidget.redWidget->seenMousePress); + QVERIFY(!testWidget.redWidget->seenMouseMove); + QVERIFY(!testWidget.redWidget->seenMouseRelease); // again, ignoring TouchUpdates - testWidget.blueWidget->reset(); - testWidget.greenWidget->reset(); - testWidget.greenWidget->acceptTouchBegin = true; - // testWidget.greenWidget->acceptTouchUpdate = true; - testWidget.greenWidget->acceptTouchEnd = true; - testWidget.greenWidget->closeWindowOnTouchEnd = true; + testWidget.greyWidget->reset(); + testWidget.redWidget->reset(); + testWidget.redWidget->acceptTouchBegin = true; + // testWidget.redWidget->acceptTouchUpdate = true; + testWidget.redWidget->acceptTouchEnd = true; + testWidget.redWidget->closeWindowOnTouchEnd = true; testWidget.showMaximized(); (void) qApp->exec(); - QVERIFY(testWidget.blueWidget->seenTouchBegin); - QVERIFY(!testWidget.blueWidget->seenTouchUpdate); - QVERIFY(!testWidget.blueWidget->seenTouchEnd); - QVERIFY(!testWidget.blueWidget->seenMousePress); - QVERIFY(!testWidget.blueWidget->seenMouseMove); - QVERIFY(!testWidget.blueWidget->seenMouseRelease); - QVERIFY(testWidget.greenWidget->seenTouchBegin); - QVERIFY(testWidget.greenWidget->seenTouchUpdate); - QVERIFY(testWidget.greenWidget->seenTouchEnd); - QVERIFY(!testWidget.greenWidget->seenMousePress); - QVERIFY(!testWidget.greenWidget->seenMouseMove); - QVERIFY(!testWidget.greenWidget->seenMouseRelease); + QVERIFY(testWidget.greyWidget->seenTouchBegin); + QVERIFY(!testWidget.greyWidget->seenTouchUpdate); + QVERIFY(!testWidget.greyWidget->seenTouchEnd); + QVERIFY(!testWidget.greyWidget->seenMousePress); + QVERIFY(!testWidget.greyWidget->seenMouseMove); + QVERIFY(!testWidget.greyWidget->seenMouseRelease); + QVERIFY(testWidget.redWidget->seenTouchBegin); + QVERIFY(testWidget.redWidget->seenTouchUpdate); + QVERIFY(testWidget.redWidget->seenTouchEnd); + QVERIFY(!testWidget.redWidget->seenMousePress); + QVERIFY(!testWidget.redWidget->seenMouseMove); + QVERIFY(!testWidget.redWidget->seenMouseRelease); // last time, ignoring TouchUpdates and TouchEnd - testWidget.blueWidget->reset(); - testWidget.greenWidget->reset(); - testWidget.greenWidget->acceptTouchBegin = true; - // testWidget.greenWidget->acceptTouchUpdate = true; - // testWidget.greenWidget->acceptTouchEnd = true; - testWidget.greenWidget->closeWindowOnTouchEnd = true; + testWidget.greyWidget->reset(); + testWidget.redWidget->reset(); + testWidget.redWidget->acceptTouchBegin = true; + // testWidget.redWidget->acceptTouchUpdate = true; + // testWidget.redWidget->acceptTouchEnd = true; + testWidget.redWidget->closeWindowOnTouchEnd = true; testWidget.showMaximized(); (void) qApp->exec(); - QVERIFY(testWidget.blueWidget->seenTouchBegin); - QVERIFY(!testWidget.blueWidget->seenTouchUpdate); - QVERIFY(!testWidget.blueWidget->seenTouchEnd); - QVERIFY(!testWidget.blueWidget->seenMousePress); - QVERIFY(!testWidget.blueWidget->seenMouseMove); + QVERIFY(testWidget.greyWidget->seenTouchBegin); + QVERIFY(!testWidget.greyWidget->seenTouchUpdate); + QVERIFY(!testWidget.greyWidget->seenTouchEnd); + QVERIFY(!testWidget.greyWidget->seenMousePress); + QVERIFY(!testWidget.greyWidget->seenMouseMove); QVERIFY(!testWidget.blueWidget->seenMouseRelease); - QVERIFY(testWidget.greenWidget->seenTouchBegin); - QVERIFY(testWidget.greenWidget->seenTouchUpdate); - QVERIFY(testWidget.greenWidget->seenTouchEnd); - QVERIFY(!testWidget.greenWidget->seenMousePress); - QVERIFY(!testWidget.greenWidget->seenMouseMove); - QVERIFY(!testWidget.greenWidget->seenMouseRelease); + QVERIFY(testWidget.redWidget->seenTouchBegin); + QVERIFY(testWidget.redWidget->seenTouchUpdate); + QVERIFY(testWidget.redWidget->seenTouchEnd); + QVERIFY(!testWidget.redWidget->seenMousePress); + QVERIFY(!testWidget.redWidget->seenMouseMove); + QVERIFY(!testWidget.redWidget->seenMouseRelease); } QTEST_MAIN(tst_ManualMultitouch) -- cgit v0.12 From 96d2094b48db6cccd7a0fb34a778bd3e71ba43b4 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Mon, 27 Apr 2009 13:21:12 +0200 Subject: add basic multi-touch event handling test, split existing tests into more logical pieces --- tests/manual/qtouchevent/main.cpp | 130 +++++++++++++++++++++++++------ tests/manual/qtouchevent/touchwidget.cpp | 4 + tests/manual/qtouchevent/touchwidget.h | 1 + 3 files changed, 110 insertions(+), 25 deletions(-) diff --git a/tests/manual/qtouchevent/main.cpp b/tests/manual/qtouchevent/main.cpp index 05fdc44..8b28967 100644 --- a/tests/manual/qtouchevent/main.cpp +++ b/tests/manual/qtouchevent/main.cpp @@ -32,8 +32,11 @@ public: ~tst_ManualMultitouch(); private slots: - void basicEventHandling(); - void touchEventPropagation(); + void ignoringTouchEventsEmulatesMouseEvents(); + void basicSingleTouchEventHandling(); + void basicMultiTouchEventHandling(); + void acceptingTouchBeginStopsPropagation(); + void ignoringTouchBeginPropagatesToParent(); }; tst_ManualMultitouch::tst_ManualMultitouch() @@ -42,17 +45,16 @@ tst_ManualMultitouch::tst_ManualMultitouch() tst_ManualMultitouch::~tst_ManualMultitouch() { } -void tst_ManualMultitouch::basicEventHandling() +void tst_ManualMultitouch::ignoringTouchEventsEmulatesMouseEvents() { // first, make sure that we get mouse events when not enabling touch events MultitouchTestWidget testWidget; - testWidget.testNameLabel->setText("Basic QTouchEvent handling test"); + testWidget.testNameLabel->setText("Mouse Event Emulation Test"); testWidget.testDescriptionLabel->setText("Touch, hold, and release your finger on the green widget."); testWidget.redWidget->hide(); testWidget.blueWidget->hide(); testWidget.greenWidget->closeWindowOnMouseRelease = true; testWidget.showMaximized(); - (void) qApp->exec(); QVERIFY(!testWidget.greenWidget->seenTouchBegin); QVERIFY(!testWidget.greenWidget->seenTouchUpdate); @@ -61,15 +63,34 @@ void tst_ManualMultitouch::basicEventHandling() // QVERIFY(testWidget.greenWidget->seenMouseMove); QVERIFY(testWidget.greenWidget->seenMouseRelease); - // now enable touch and make sure we get the touch events + // enable touch, but don't accept the events testWidget.greenWidget->reset(); testWidget.greenWidget->setAttribute(Qt::WA_AcceptTouchEvents); + testWidget.greenWidget->closeWindowOnMouseRelease = true; + testWidget.showMaximized(); + (void) qApp->exec(); + QVERIFY(testWidget.greenWidget->seenTouchBegin); + QVERIFY(!testWidget.greenWidget->seenTouchUpdate); + QVERIFY(!testWidget.greenWidget->seenTouchEnd); + QVERIFY(testWidget.greenWidget->seenMousePress); + // QVERIFY(testWidget.greenWidget->seenMouseMove); + QVERIFY(testWidget.greenWidget->seenMouseRelease); +} + +void tst_ManualMultitouch::basicSingleTouchEventHandling() +{ + // now enable touch and make sure we get the touch events + MultitouchTestWidget testWidget; + testWidget.testNameLabel->setText("Basic Single-Touch Event Handling Test"); + testWidget.testDescriptionLabel->setText("Touch, hold, and release your finger on the green widget."); + testWidget.redWidget->hide(); + testWidget.blueWidget->hide(); + testWidget.greenWidget->setAttribute(Qt::WA_AcceptTouchEvents); testWidget.greenWidget->acceptTouchBegin = true; testWidget.greenWidget->acceptTouchUpdate = true; testWidget.greenWidget->acceptTouchEnd = true; testWidget.greenWidget->closeWindowOnTouchEnd = true; testWidget.showMaximized(); - (void) qApp->exec(); QVERIFY(testWidget.greenWidget->seenTouchBegin && testWidget.greenWidget->seenTouchUpdate @@ -85,7 +106,6 @@ void tst_ManualMultitouch::basicEventHandling() // testWidget.greenWidget->acceptTouchEnd = true; testWidget.greenWidget->closeWindowOnTouchEnd = true; testWidget.showMaximized(); - (void) qApp->exec(); QVERIFY(testWidget.greenWidget->seenTouchBegin); QVERIFY(testWidget.greenWidget->seenTouchUpdate); @@ -101,7 +121,6 @@ void tst_ManualMultitouch::basicEventHandling() testWidget.greenWidget->acceptTouchEnd = true; testWidget.greenWidget->closeWindowOnTouchEnd = true; testWidget.showMaximized(); - (void) qApp->exec(); QVERIFY(testWidget.greenWidget->seenTouchBegin); QVERIFY(testWidget.greenWidget->seenTouchUpdate); @@ -117,7 +136,6 @@ void tst_ManualMultitouch::basicEventHandling() // testWidget.greenWidget->acceptTouchEnd = true; testWidget.greenWidget->closeWindowOnTouchEnd = true; testWidget.showMaximized(); - (void) qApp->exec(); QVERIFY(testWidget.greenWidget->seenTouchBegin); QVERIFY(testWidget.greenWidget->seenTouchUpdate); @@ -127,15 +145,83 @@ void tst_ManualMultitouch::basicEventHandling() QVERIFY(!testWidget.greenWidget->seenMouseRelease); } -void tst_ManualMultitouch::touchEventPropagation() +void tst_ManualMultitouch::basicMultiTouchEventHandling() { + // repeat, this time looking for multiple fingers MultitouchTestWidget testWidget; - testWidget.testNameLabel->setText("QTouchEvent propagation test, Blue blocks Green"); - testWidget.testDescriptionLabel->setText("Touch, hold, and release your finger on the blue widget."); - testWidget.redWidget->hide(); + testWidget.testNameLabel->setText("Basic Multi-Touch Event Handling Test"); + testWidget.testDescriptionLabel->setText("Touch, hold, and release several fingers on the red widget."); + testWidget.greenWidget->hide(); + testWidget.greyWidget->hide(); + testWidget.redWidget->setAttribute(Qt::WA_AcceptTouchEvents); + testWidget.redWidget->acceptTouchBegin = true; + testWidget.redWidget->acceptTouchUpdate = true; + testWidget.redWidget->acceptTouchEnd = true; + testWidget.redWidget->closeWindowOnTouchEnd = true; + testWidget.showMaximized(); + (void) qApp->exec(); + QVERIFY(testWidget.redWidget->seenTouchBegin); + QVERIFY(testWidget.redWidget->seenTouchUpdate); + QVERIFY(testWidget.redWidget->seenTouchEnd); + QVERIFY(testWidget.redWidget->touchPointCount > 1); + QVERIFY(!testWidget.greenWidget->seenMousePress); + QVERIFY(!testWidget.greenWidget->seenMouseMove); + QVERIFY(!testWidget.greenWidget->seenMouseRelease); + testWidget.redWidget->reset(); + testWidget.redWidget->acceptTouchBegin = true; + // testWidget.redWidget->acceptTouchUpdate = true; + testWidget.redWidget->acceptTouchEnd = true; + testWidget.redWidget->closeWindowOnTouchEnd = true; + testWidget.showMaximized(); + (void) qApp->exec(); + QVERIFY(testWidget.redWidget->seenTouchBegin); + QVERIFY(testWidget.redWidget->seenTouchUpdate); + QVERIFY(testWidget.redWidget->seenTouchEnd); + QVERIFY(testWidget.redWidget->touchPointCount > 1); + QVERIFY(!testWidget.greenWidget->seenMousePress); + QVERIFY(!testWidget.greenWidget->seenMouseMove); + QVERIFY(!testWidget.greenWidget->seenMouseRelease); + + testWidget.redWidget->reset(); + testWidget.redWidget->acceptTouchBegin = true; + testWidget.redWidget->acceptTouchUpdate = true; + // testWidget.redWidget->acceptTouchEnd = true; + testWidget.redWidget->closeWindowOnTouchEnd = true; + testWidget.showMaximized(); + (void) qApp->exec(); + QVERIFY(testWidget.redWidget->seenTouchBegin); + QVERIFY(testWidget.redWidget->seenTouchUpdate); + QVERIFY(testWidget.redWidget->seenTouchEnd); + QVERIFY(testWidget.redWidget->touchPointCount > 1); + QVERIFY(!testWidget.greenWidget->seenMousePress); + QVERIFY(!testWidget.greenWidget->seenMouseMove); + QVERIFY(!testWidget.greenWidget->seenMouseRelease); + + testWidget.redWidget->reset(); + testWidget.redWidget->acceptTouchBegin = true; + // testWidget.redWidget->acceptTouchUpdate = true; + // testWidget.redWidget->acceptTouchEnd = true; + testWidget.redWidget->closeWindowOnTouchEnd = true; + testWidget.showMaximized(); + (void) qApp->exec(); + QVERIFY(testWidget.redWidget->seenTouchBegin); + QVERIFY(testWidget.redWidget->seenTouchUpdate); + QVERIFY(testWidget.redWidget->seenTouchEnd); + QVERIFY(testWidget.redWidget->touchPointCount > 1); + QVERIFY(!testWidget.greenWidget->seenMousePress); + QVERIFY(!testWidget.greenWidget->seenMouseMove); + QVERIFY(!testWidget.greenWidget->seenMouseRelease); +} + +void tst_ManualMultitouch::acceptingTouchBeginStopsPropagation() +{ // test that accepting the TouchBegin event on the // blueWidget stops propagation to the greenWidget + MultitouchTestWidget testWidget; + testWidget.testNameLabel->setText("Touch Event Propagation Test: Accepting in Blue Blocks Green"); + testWidget.testDescriptionLabel->setText("Touch, hold, and release your finger on the blue widget."); + testWidget.redWidget->hide(); testWidget.blueWidget->setAttribute(Qt::WA_AcceptTouchEvents); testWidget.greenWidget->setAttribute(Qt::WA_AcceptTouchEvents); testWidget.blueWidget->acceptTouchBegin = true; @@ -143,7 +229,6 @@ void tst_ManualMultitouch::touchEventPropagation() testWidget.blueWidget->acceptTouchEnd = true; testWidget.blueWidget->closeWindowOnTouchEnd = true; testWidget.showMaximized(); - (void) qApp->exec(); QVERIFY(testWidget.blueWidget->seenTouchBegin); QVERIFY(testWidget.blueWidget->seenTouchUpdate); @@ -166,7 +251,6 @@ void tst_ManualMultitouch::touchEventPropagation() // testWidget.blueWidget->acceptTouchEnd = true; testWidget.blueWidget->closeWindowOnTouchEnd = true; testWidget.showMaximized(); - (void) qApp->exec(); QVERIFY(testWidget.blueWidget->seenTouchBegin); QVERIFY(testWidget.blueWidget->seenTouchUpdate); @@ -189,7 +273,6 @@ void tst_ManualMultitouch::touchEventPropagation() testWidget.blueWidget->acceptTouchEnd = true; testWidget.blueWidget->closeWindowOnTouchEnd = true; testWidget.showMaximized(); - (void) qApp->exec(); QVERIFY(testWidget.blueWidget->seenTouchBegin); QVERIFY(testWidget.blueWidget->seenTouchUpdate); @@ -212,7 +295,6 @@ void tst_ManualMultitouch::touchEventPropagation() // testWidget.blueWidget->acceptTouchEnd = true; testWidget.blueWidget->closeWindowOnTouchEnd = true; testWidget.showMaximized(); - (void) qApp->exec(); QVERIFY(testWidget.blueWidget->seenTouchBegin); QVERIFY(testWidget.blueWidget->seenTouchUpdate); @@ -226,13 +308,16 @@ void tst_ManualMultitouch::touchEventPropagation() QVERIFY(!testWidget.greenWidget->seenMousePress); QVERIFY(!testWidget.greenWidget->seenMouseMove); QVERIFY(!testWidget.greenWidget->seenMouseRelease); +} +void tst_ManualMultitouch::ignoringTouchBeginPropagatesToParent() +{ // repeat the test above, now ignoring touch events in the // greyWidget, they should be propagated to the redWidget - testWidget.testNameLabel->setText("QTouchEvent propagation test, Red handles Grey's ignored events"); + MultitouchTestWidget testWidget; + testWidget.testNameLabel->setText("Touch Event Propagation Test: Ignoring in Grey Propagates to Red"); testWidget.testDescriptionLabel->setText("Touch, hold, and release your finger on the grey widget."); testWidget.greenWidget->hide(); - testWidget.redWidget->show(); testWidget.greyWidget->setAttribute(Qt::WA_AcceptTouchEvents, false); testWidget.redWidget->setAttribute(Qt::WA_AcceptTouchEvents); testWidget.greyWidget->reset(); @@ -242,7 +327,6 @@ void tst_ManualMultitouch::touchEventPropagation() testWidget.redWidget->acceptTouchEnd = true; testWidget.redWidget->closeWindowOnTouchEnd = true; testWidget.showMaximized(); - (void) qApp->exec(); QVERIFY(!testWidget.greyWidget->seenTouchBegin); QVERIFY(!testWidget.greyWidget->seenTouchUpdate); @@ -266,7 +350,6 @@ void tst_ManualMultitouch::touchEventPropagation() testWidget.redWidget->acceptTouchEnd = true; testWidget.redWidget->closeWindowOnTouchEnd = true; testWidget.showMaximized(); - (void) qApp->exec(); QVERIFY(testWidget.greyWidget->seenTouchBegin); QVERIFY(!testWidget.greyWidget->seenTouchUpdate); @@ -289,7 +372,6 @@ void tst_ManualMultitouch::touchEventPropagation() // testWidget.redWidget->acceptTouchEnd = true; testWidget.redWidget->closeWindowOnTouchEnd = true; testWidget.showMaximized(); - (void) qApp->exec(); QVERIFY(testWidget.greyWidget->seenTouchBegin); QVERIFY(!testWidget.greyWidget->seenTouchUpdate); @@ -312,7 +394,6 @@ void tst_ManualMultitouch::touchEventPropagation() testWidget.redWidget->acceptTouchEnd = true; testWidget.redWidget->closeWindowOnTouchEnd = true; testWidget.showMaximized(); - (void) qApp->exec(); QVERIFY(testWidget.greyWidget->seenTouchBegin); QVERIFY(!testWidget.greyWidget->seenTouchUpdate); @@ -335,7 +416,6 @@ void tst_ManualMultitouch::touchEventPropagation() // testWidget.redWidget->acceptTouchEnd = true; testWidget.redWidget->closeWindowOnTouchEnd = true; testWidget.showMaximized(); - (void) qApp->exec(); QVERIFY(testWidget.greyWidget->seenTouchBegin); QVERIFY(!testWidget.greyWidget->seenTouchUpdate); diff --git a/tests/manual/qtouchevent/touchwidget.cpp b/tests/manual/qtouchevent/touchwidget.cpp index 1e57c36..0516c5b 100644 --- a/tests/manual/qtouchevent/touchwidget.cpp +++ b/tests/manual/qtouchevent/touchwidget.cpp @@ -24,6 +24,7 @@ void TouchWidget::reset() = closeWindowOnMouseRelease = false; + touchPointCount = 0; } bool TouchWidget::event(QEvent *event) @@ -31,6 +32,7 @@ bool TouchWidget::event(QEvent *event) switch (event->type()) { case QEvent::TouchBegin: seenTouchBegin = true; + touchPointCount = qMax(touchPointCount, static_cast(event)->touchPoints().count()); if (acceptTouchBegin) { event->accept(); return true; @@ -38,6 +40,7 @@ bool TouchWidget::event(QEvent *event) break; case QEvent::TouchUpdate: seenTouchUpdate = true; + touchPointCount = qMax(touchPointCount, static_cast(event)->touchPoints().count()); if (acceptTouchUpdate) { event->accept(); return true; @@ -45,6 +48,7 @@ bool TouchWidget::event(QEvent *event) break; case QEvent::TouchEnd: seenTouchEnd = true; + touchPointCount = qMax(touchPointCount, static_cast(event)->touchPoints().count()); if (closeWindowOnTouchEnd) window()->close(); if (acceptTouchEnd) { diff --git a/tests/manual/qtouchevent/touchwidget.h b/tests/manual/qtouchevent/touchwidget.h index 3e95610..2726deb 100644 --- a/tests/manual/qtouchevent/touchwidget.h +++ b/tests/manual/qtouchevent/touchwidget.h @@ -11,6 +11,7 @@ public: bool acceptTouchBegin, acceptTouchUpdate, acceptTouchEnd; bool seenTouchBegin, seenTouchUpdate, seenTouchEnd; bool closeWindowOnTouchEnd; + int touchPointCount; bool acceptMousePress, acceptMouseMove, acceptMouseRelease; bool seenMousePress, seenMouseMove, seenMouseRelease; -- cgit v0.12 From fecf5bf95329dd6e4aae6bac07e92fb637925101 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Mon, 27 Apr 2009 17:13:53 +0200 Subject: center the labels in the test's form --- tests/manual/qtouchevent/form.ui | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/manual/qtouchevent/form.ui b/tests/manual/qtouchevent/form.ui index 4c2da3a..c7fbb78 100644 --- a/tests/manual/qtouchevent/form.ui +++ b/tests/manual/qtouchevent/form.ui @@ -26,6 +26,9 @@ Test Name + + Qt::AlignCenter + @@ -38,6 +41,9 @@ Test description + + Qt::AlignCenter + -- cgit v0.12 From 2a0f0fdc016259dcc956599f41aa024ed06116b5 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Mon, 27 Apr 2009 17:32:22 +0200 Subject: 2 new tests for touch points 1. outside the widgets area and 2. over a child --- tests/manual/qtouchevent/main.cpp | 58 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/tests/manual/qtouchevent/main.cpp b/tests/manual/qtouchevent/main.cpp index 8b28967..bc33f16 100644 --- a/tests/manual/qtouchevent/main.cpp +++ b/tests/manual/qtouchevent/main.cpp @@ -37,6 +37,8 @@ private slots: void basicMultiTouchEventHandling(); void acceptingTouchBeginStopsPropagation(); void ignoringTouchBeginPropagatesToParent(); + void secondTouchPointOnParentGoesToChild(); + void secondTouchPointOnChildGoesToParent(); }; tst_ManualMultitouch::tst_ManualMultitouch() @@ -431,6 +433,62 @@ void tst_ManualMultitouch::ignoringTouchBeginPropagatesToParent() QVERIFY(!testWidget.redWidget->seenMouseRelease); } +void tst_ManualMultitouch::secondTouchPointOnParentGoesToChild() +{ + MultitouchTestWidget testWidget; + testWidget.testNameLabel->setText("Additional Touch-Points Outside Child's Rect Go to Child"); + testWidget.testDescriptionLabel->setText("Press and hold a finger on the blue widget, then on the green one, and release."); + testWidget.redWidget->hide(); + testWidget.greenWidget->setAttribute(Qt::WA_AcceptTouchEvents); + testWidget.blueWidget->setAttribute(Qt::WA_AcceptTouchEvents); + testWidget.blueWidget->acceptTouchBegin = true; + testWidget.greenWidget->acceptTouchBegin = true; + testWidget.blueWidget->closeWindowOnTouchEnd = true; + testWidget.showMaximized(); + (void) qApp->exec(); + QVERIFY(testWidget.blueWidget->seenTouchBegin); + QVERIFY(testWidget.blueWidget->seenTouchUpdate); + QVERIFY(testWidget.blueWidget->seenTouchEnd); + QVERIFY(!testWidget.blueWidget->seenMousePress); + QVERIFY(!testWidget.blueWidget->seenMouseMove); + QVERIFY(!testWidget.blueWidget->seenMouseRelease); + QVERIFY(testWidget.blueWidget->touchPointCount > 1); + QVERIFY(!testWidget.greenWidget->seenTouchBegin); + QVERIFY(!testWidget.greenWidget->seenTouchUpdate); + QVERIFY(!testWidget.greenWidget->seenTouchEnd); + QVERIFY(!testWidget.greenWidget->seenMousePress); + QVERIFY(!testWidget.greenWidget->seenMouseMove); + QVERIFY(!testWidget.greenWidget->seenMouseRelease); +} + +void tst_ManualMultitouch::secondTouchPointOnChildGoesToParent() +{ + MultitouchTestWidget testWidget; + testWidget.testNameLabel->setText("Additional Touch-Points Over Child's Rect Go to Parent"); + testWidget.testDescriptionLabel->setText("Press and hold a finger on the red widget, then on the red one, and release."); + testWidget.greenWidget->hide(); + testWidget.redWidget->setAttribute(Qt::WA_AcceptTouchEvents); + testWidget.greyWidget->setAttribute(Qt::WA_AcceptTouchEvents); + testWidget.greyWidget->acceptTouchBegin = true; + testWidget.redWidget->acceptTouchBegin = true; + testWidget.redWidget->closeWindowOnTouchEnd = true; + testWidget.showMaximized(); + (void) qApp->exec(); + QVERIFY(testWidget.redWidget->seenTouchBegin); + QVERIFY(testWidget.redWidget->seenTouchUpdate); + QVERIFY(testWidget.redWidget->seenTouchEnd); + QVERIFY(!testWidget.redWidget->seenMousePress); + QVERIFY(!testWidget.redWidget->seenMouseMove); + QVERIFY(!testWidget.redWidget->seenMouseRelease); + QVERIFY(testWidget.redWidget->touchPointCount > 1); + QVERIFY(!testWidget.greyWidget->seenTouchBegin); + QVERIFY(!testWidget.greyWidget->seenTouchUpdate); + QVERIFY(!testWidget.greyWidget->seenTouchEnd); + QVERIFY(!testWidget.greyWidget->seenMousePress); + QVERIFY(!testWidget.greyWidget->seenMouseMove); + QVERIFY(!testWidget.greyWidget->seenMouseRelease); +} + QTEST_MAIN(tst_ManualMultitouch) #include "main.moc" -- cgit v0.12 From 4cbbcf62949421ae5cad422b904b3ed1a004a724 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Tue, 28 Apr 2009 08:53:24 +0200 Subject: correct a typo in the test description --- tests/manual/qtouchevent/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/manual/qtouchevent/main.cpp b/tests/manual/qtouchevent/main.cpp index bc33f16..d48f487 100644 --- a/tests/manual/qtouchevent/main.cpp +++ b/tests/manual/qtouchevent/main.cpp @@ -465,7 +465,7 @@ void tst_ManualMultitouch::secondTouchPointOnChildGoesToParent() { MultitouchTestWidget testWidget; testWidget.testNameLabel->setText("Additional Touch-Points Over Child's Rect Go to Parent"); - testWidget.testDescriptionLabel->setText("Press and hold a finger on the red widget, then on the red one, and release."); + testWidget.testDescriptionLabel->setText("Press and hold a finger on the red widget, then on the grey one, and release."); testWidget.greenWidget->hide(); testWidget.redWidget->setAttribute(Qt::WA_AcceptTouchEvents); testWidget.greyWidget->setAttribute(Qt::WA_AcceptTouchEvents); -- cgit v0.12 From c4b9bccbecddbeeefc8ac9db91421ddaa2193858 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Tue, 28 Apr 2009 09:23:34 +0200 Subject: added 2 new tests for testing multi-touch on widget siblings and cousins --- tests/manual/qtouchevent/main.cpp | 62 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/tests/manual/qtouchevent/main.cpp b/tests/manual/qtouchevent/main.cpp index d48f487..9f2d413 100644 --- a/tests/manual/qtouchevent/main.cpp +++ b/tests/manual/qtouchevent/main.cpp @@ -12,7 +12,7 @@ public: MultitouchTestWidget(QWidget *parent = 0) : QWidget(parent) { - setAttribute(Qt::WA_QuitOnClose, false);\ + setAttribute(Qt::WA_QuitOnClose, false); setupUi(this); } @@ -39,6 +39,8 @@ private slots: void ignoringTouchBeginPropagatesToParent(); void secondTouchPointOnParentGoesToChild(); void secondTouchPointOnChildGoesToParent(); + void secondTouchPointOnSiblingGoesToSibling(); + void secondTouchPointOnCousinGoesToCousin(); }; tst_ManualMultitouch::tst_ManualMultitouch() @@ -489,6 +491,64 @@ void tst_ManualMultitouch::secondTouchPointOnChildGoesToParent() QVERIFY(!testWidget.greyWidget->seenMouseRelease); } +void tst_ManualMultitouch::secondTouchPointOnSiblingGoesToSibling() +{ + MultitouchTestWidget testWidget; + testWidget.testNameLabel->setText("Multi-Touch Interaction Test, Unrelated Widgets Get Separate Events"); + testWidget.testDescriptionLabel->setText("Press and hold a finger on the green widget, then the red one, and release."); + testWidget.blueWidget->hide(); + testWidget.greenWidget->setAttribute(Qt::WA_AcceptTouchEvents); + testWidget.greenWidget->acceptTouchBegin = true; + testWidget.greenWidget->closeWindowOnTouchEnd = true; + testWidget.greyWidget->hide(); + testWidget.redWidget->setAttribute(Qt::WA_AcceptTouchEvents); + testWidget.redWidget->acceptTouchBegin = true; + testWidget.showMaximized(); + (void) qApp->exec(); + QVERIFY(testWidget.greenWidget->seenTouchBegin); + QVERIFY(testWidget.greenWidget->seenTouchUpdate); + QVERIFY(testWidget.greenWidget->seenTouchEnd); + QVERIFY(!testWidget.greenWidget->seenMousePress); + QVERIFY(!testWidget.greenWidget->seenMouseMove); + QVERIFY(!testWidget.greenWidget->seenMouseRelease); + QVERIFY(testWidget.redWidget->seenTouchBegin); + QVERIFY(testWidget.redWidget->seenTouchUpdate); + QVERIFY(testWidget.redWidget->seenTouchEnd); + QVERIFY(!testWidget.redWidget->seenMousePress); + QVERIFY(!testWidget.redWidget->seenMouseMove); + QVERIFY(!testWidget.redWidget->seenMouseRelease); + QVERIFY(testWidget.greenWidget->touchPointCount == 1); + QVERIFY(testWidget.redWidget->touchPointCount == 1); +} + +void tst_ManualMultitouch::secondTouchPointOnCousinGoesToCousin() +{ + MultitouchTestWidget testWidget; + testWidget.testNameLabel->setText("Multi-Touch Interaction Test, Unrelated Widgets Get Separate Events"); + testWidget.testDescriptionLabel->setText("Press and hold a finger on the blue widget, then the grey one, and release."); + testWidget.blueWidget->setAttribute(Qt::WA_AcceptTouchEvents); + testWidget.blueWidget->acceptTouchBegin = true; + testWidget.blueWidget->closeWindowOnTouchEnd = true; + testWidget.greyWidget->setAttribute(Qt::WA_AcceptTouchEvents); + testWidget.greyWidget->acceptTouchBegin = true; + testWidget.showMaximized(); + (void) qApp->exec(); + QVERIFY(testWidget.blueWidget->seenTouchBegin); + QVERIFY(testWidget.blueWidget->seenTouchUpdate); + QVERIFY(testWidget.blueWidget->seenTouchEnd); + QVERIFY(!testWidget.blueWidget->seenMousePress); + QVERIFY(!testWidget.blueWidget->seenMouseMove); + QVERIFY(!testWidget.blueWidget->seenMouseRelease); + QVERIFY(testWidget.greyWidget->seenTouchBegin); + QVERIFY(testWidget.greyWidget->seenTouchUpdate); + QVERIFY(testWidget.greyWidget->seenTouchEnd); + QVERIFY(!testWidget.greyWidget->seenMousePress); + QVERIFY(!testWidget.greyWidget->seenMouseMove); + QVERIFY(!testWidget.greyWidget->seenMouseRelease); + QVERIFY(testWidget.blueWidget->touchPointCount == 1); + QVERIFY(testWidget.greyWidget->touchPointCount == 1); +} + QTEST_MAIN(tst_ManualMultitouch) #include "main.moc" -- cgit v0.12 From 520a67e50ed7717518d3072f8568de00b791f20a Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Wed, 29 Apr 2009 15:44:08 +0200 Subject: Use a widget attribute to keep track of whether or not TouchBegin has been accepted --- src/corelib/global/qnamespace.h | 1 + src/gui/kernel/qapplication.cpp | 1 + src/gui/kernel/qapplication_p.h | 1 - src/gui/kernel/qapplication_win.cpp | 12 +++++------- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index b73a873..15da2d6 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -486,6 +486,7 @@ public: WA_TranslucentBackground = 120, WA_AcceptTouchEvents = 121, + WA_AcceptedTouchBeginEvent = 122, // Add new attributes before this line WA_AttributeCount diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 4e61f66..bc9b827 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -4013,6 +4013,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) res = widget->testAttribute(Qt::WA_AcceptTouchEvents) && d->notify_helper(widget, touchEvent); eventAccepted = touchEvent->isAccepted(); + widget->setAttribute(Qt::WA_AcceptedTouchBeginEvent, res && eventAccepted); touchEvent->spont = false; if (res && eventAccepted) { // the first widget to accept the TouchBegin gets an implicit grab. diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 91857ec..ce7110d 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -429,7 +429,6 @@ public: #endif QPointer currentMultitouchWidget; - bool currentMultitouchWidgetAcceptedTouchBegin; static void updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent); #if defined(Q_WS_WIN) diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 7e07104..f1fb0a4 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -4000,7 +4000,6 @@ void QApplicationPrivate::initializeMultitouch() CloseTouchInputHandle = static_cast(library.resolve("CloseTouchInputHandle")); currentMultitouchWidget = 0; - currentMultitouchWidgetAcceptedTouchBegin = false; touchInputIDToTouchPointID.clear(); allTouchPoints.clear(); currentTouchPoints.clear(); @@ -4106,7 +4105,7 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) currentMultitouchWidget = child; // if the TouchBegin handler recurses, we assume that means the event // has been implicitly accepted and continue to send touch events - currentMultitouchWidgetAcceptedTouchBegin = true; + currentMultitouchWidget->setAttribute(Qt::WA_AcceptedTouchBeginEvent); } } @@ -4133,11 +4132,10 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) updateTouchPointsForWidget(widget, &touchEvent); if (sendTouchBegin) { - bool res = QApplication::sendSpontaneousEvent(widget, &touchEvent); - qt_tabletChokeMouse - = currentMultitouchWidgetAcceptedTouchBegin - = (res && touchEvent.isAccepted()); - } else if (currentMultitouchWidgetAcceptedTouchBegin) { + bool res = QApplication::sendSpontaneousEvent(widget, &touchEvent) + && touchEvent.isAccepted(); + qt_tabletChokeMouse = res; + } else if (widget->testAttribute(Qt::WA_AcceptedTouchBeginEvent)) { (void) QApplication::sendSpontaneousEvent(widget, &touchEvent); qt_tabletChokeMouse = true; } else { -- cgit v0.12 From a3504361a19428c12ac7e044762f252d8ba2b26f Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Wed, 29 Apr 2009 18:08:44 +0200 Subject: Don't store activeTouchPoints in QApplicationPrivate it's only needed and updated during delivery, so the extra copy isn't necessary --- src/gui/kernel/qapplication_p.h | 2 +- src/gui/kernel/qapplication_win.cpp | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index ce7110d..da66aab 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -438,7 +438,7 @@ public: QMap touchInputIDToTouchPointID; QVector allTouchPoints; - QList currentTouchPoints, activeTouchPoints; + QList currentTouchPoints; void initializeMultitouch(); void insertActiveTouch(QTouchEvent::TouchPoint *touchPoint); diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index f1fb0a4..c7ecdae 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -4003,7 +4003,6 @@ void QApplicationPrivate::initializeMultitouch() touchInputIDToTouchPointID.clear(); allTouchPoints.clear(); currentTouchPoints.clear(); - activeTouchPoints.clear(); } void QApplicationPrivate::insertActiveTouch(QTouchEvent::TouchPoint *touchPoint) @@ -4015,7 +4014,6 @@ void QApplicationPrivate::insertActiveTouch(QTouchEvent::TouchPoint *touchPoint) break; } currentTouchPoints.insert(at, touchPoint); - activeTouchPoints = currentTouchPoints; if (currentTouchPoints.count() > allTouchPoints.count()) { qFatal("Qt: INTERNAL ERROR: currentTouchPoints.count() (%d) > allTouchPoints.count() (%d)", @@ -4042,7 +4040,7 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) Q_Q(QApplication); bool sendTouchBegin = currentTouchPoints.isEmpty(); - activeTouchPoints = currentTouchPoints; + QList activeTouchPoints = currentTouchPoints; QVector winTouchInputs(msg.wParam); memset(winTouchInputs.data(), 0, sizeof(TOUCHINPUT) * winTouchInputs.count()); @@ -4068,6 +4066,7 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) QPointF globalPos(qreal(touchInput.x) / qreal(100.), qreal(touchInput.y) / qreal(100.)); if (!down && (touchInput.dwFlags & TOUCHEVENTF_DOWN)) { insertActiveTouch(touchPoint); + activeTouchPoints = currentTouchPoints; touchPoint->d->state = Qt::TouchPointPressed; touchPoint->d->globalPos = touchPoint->d->startGlobalPos = touchPoint->d->lastGlobalPos = globalPos; touchPoint->d->pressure = qreal(1.); -- cgit v0.12 From f9b4c7bea991d1786c60406abc9da95354b0d6e3 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Thu, 30 Apr 2009 10:24:20 +0200 Subject: Don't call RegisterTouchWindow() if we don't have a window id --- src/gui/kernel/qwidget_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp index 26e66b1..f53a3ef 100644 --- a/src/gui/kernel/qwidget_win.cpp +++ b/src/gui/kernel/qwidget_win.cpp @@ -498,7 +498,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO } // ### don't always register for touch events - if (QApplicationPrivate::RegisterTouchWindow && !desktop) + if (id && QApplicationPrivate::RegisterTouchWindow && !desktop) QApplicationPrivate::RegisterTouchWindow(id, 0); q->setAttribute(Qt::WA_WState_Created); // accept move/resize events -- cgit v0.12 From cd260501918ea767e8a3ca33a51b1cb4e1bbd45c Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Thu, 30 Apr 2009 11:27:43 +0200 Subject: Made the Touch* event detection very strict TouchBegin is only "seen" once before all other touch events, TouchUpdate must be after TouchBegin but before TouchEnd, and TouchEnd is only seen once after all other touch events. --- tests/manual/qtouchevent/touchwidget.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/manual/qtouchevent/touchwidget.cpp b/tests/manual/qtouchevent/touchwidget.cpp index 0516c5b..f029f8b 100644 --- a/tests/manual/qtouchevent/touchwidget.cpp +++ b/tests/manual/qtouchevent/touchwidget.cpp @@ -31,7 +31,7 @@ bool TouchWidget::event(QEvent *event) { switch (event->type()) { case QEvent::TouchBegin: - seenTouchBegin = true; + seenTouchBegin = !seenTouchBegin && !seenTouchUpdate && !seenTouchEnd; touchPointCount = qMax(touchPointCount, static_cast(event)->touchPoints().count()); if (acceptTouchBegin) { event->accept(); @@ -39,7 +39,7 @@ bool TouchWidget::event(QEvent *event) } break; case QEvent::TouchUpdate: - seenTouchUpdate = true; + seenTouchUpdate = seenTouchBegin && !seenTouchEnd; touchPointCount = qMax(touchPointCount, static_cast(event)->touchPoints().count()); if (acceptTouchUpdate) { event->accept(); @@ -47,7 +47,7 @@ bool TouchWidget::event(QEvent *event) } break; case QEvent::TouchEnd: - seenTouchEnd = true; + seenTouchEnd = seenTouchBegin && !seenTouchEnd; touchPointCount = qMax(touchPointCount, static_cast(event)->touchPoints().count()); if (closeWindowOnTouchEnd) window()->close(); -- cgit v0.12 From 33a9b5b4c7945c800b6590b993c841fb833276e8 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Thu, 30 Apr 2009 11:33:03 +0200 Subject: Determine whether TouchBegin or TouchEnd should be sent at the time of touchpoint addition/removal This will make it easier to change later when supporting touching multiple widgets --- src/gui/kernel/qapplication_win.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 9b756a6..60bad92 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -4039,7 +4039,8 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) { Q_Q(QApplication); - bool sendTouchBegin = currentTouchPoints.isEmpty(); + bool sendTouchBegin = false; + bool sendTouchEnd = false; QList activeTouchPoints = currentTouchPoints; QVector winTouchInputs(msg.wParam); @@ -4065,13 +4066,17 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) bool down = touchPoint->d->state != Qt::TouchPointReleased; QPointF globalPos(qreal(touchInput.x) / qreal(100.), qreal(touchInput.y) / qreal(100.)); if (!down && (touchInput.dwFlags & TOUCHEVENTF_DOWN)) { + sendTouchBegin = currentTouchPoints.isEmpty(); insertActiveTouch(touchPoint); activeTouchPoints = currentTouchPoints; + touchPoint->d->state = Qt::TouchPointPressed; touchPoint->d->globalPos = touchPoint->d->startGlobalPos = touchPoint->d->lastGlobalPos = globalPos; touchPoint->d->pressure = qreal(1.); } else if (down && (touchInput.dwFlags & TOUCHEVENTF_UP)) { removeActiveTouch(touchPoint); + sendTouchEnd = currentTouchPoints.isEmpty(); + touchPoint->d->state = Qt::TouchPointReleased; touchPoint->d->lastGlobalPos = touchPoint->d->globalPos; touchPoint->d->globalPos = globalPos; @@ -4087,8 +4092,6 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) } QApplicationPrivate::CloseTouchInputHandle((HANDLE) msg.lParam); - bool sendTouchEnd = currentTouchPoints.isEmpty(); - if (activeTouchPoints.isEmpty()) return false; -- cgit v0.12 From bdeefa6bd4b8721c737aeb63794034c3495be9a1 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Thu, 30 Apr 2009 13:33:44 +0200 Subject: Use the HWND from the Windows MSG to find which widget to send events to the logic for determining the event type has refactored as well --- src/gui/kernel/qapplication_p.h | 4 +-- src/gui/kernel/qapplication_win.cpp | 63 +++++++++++++++++++------------------ 2 files changed, 34 insertions(+), 33 deletions(-) diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index e9db8f3..ef375d3 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -441,8 +441,8 @@ public: QList currentTouchPoints; void initializeMultitouch(); - void insertActiveTouch(QTouchEvent::TouchPoint *touchPoint); - void removeActiveTouch(QTouchEvent::TouchPoint *touchPoint); + QEvent::Type insertActiveTouch(QTouchEvent::TouchPoint *touchPoint); + QEvent::Type removeActiveTouch(QTouchEvent::TouchPoint *touchPoint); bool translateTouchEvent(const MSG &msg); #endif diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 60bad92..b9262af 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -4005,9 +4005,13 @@ void QApplicationPrivate::initializeMultitouch() currentTouchPoints.clear(); } -void QApplicationPrivate::insertActiveTouch(QTouchEvent::TouchPoint *touchPoint) +QEvent::Type QApplicationPrivate::insertActiveTouch(QTouchEvent::TouchPoint *touchPoint) { - // insort deviceNumber + QEvent::Type eventType = currentTouchPoints.isEmpty() + ? QEvent::TouchBegin + : QEvent::TouchUpdate; + + // insort touch point int at = 0; for (; at < currentTouchPoints.count(); ++at) { if (currentTouchPoints.at(at)->id() > touchPoint->id()) @@ -4020,9 +4024,11 @@ void QApplicationPrivate::insertActiveTouch(QTouchEvent::TouchPoint *touchPoint) currentTouchPoints.count(), allTouchPoints.count()); } + + return eventType; } -void QApplicationPrivate::removeActiveTouch(QTouchEvent::TouchPoint *touchPoint) +QEvent::Type QApplicationPrivate::removeActiveTouch(QTouchEvent::TouchPoint *touchPoint) { for (int i = qMin(currentTouchPoints.count() - 1, touchPoint->id()); i >= 0; --i) { if (currentTouchPoints.at(i) == touchPoint) { @@ -4031,16 +4037,18 @@ void QApplicationPrivate::removeActiveTouch(QTouchEvent::TouchPoint *touchPoint) } } - // leave activeTouchPoints unchanged, since we need to make sure - // that the Release for deviceNumber is sent + return currentTouchPoints.isEmpty() ? QEvent::TouchEnd : QEvent::TouchUpdate; } bool QApplicationPrivate::translateTouchEvent(const MSG &msg) { Q_Q(QApplication); - bool sendTouchBegin = false; - bool sendTouchEnd = false; + QWidget *widgetForHwnd = QWidget::find(msg.hwnd); + if (!widgetForHwnd) + return false; + + QEvent::Type eventType = QEvent::None; QList activeTouchPoints = currentTouchPoints; QVector winTouchInputs(msg.wParam); @@ -4066,22 +4074,22 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) bool down = touchPoint->d->state != Qt::TouchPointReleased; QPointF globalPos(qreal(touchInput.x) / qreal(100.), qreal(touchInput.y) / qreal(100.)); if (!down && (touchInput.dwFlags & TOUCHEVENTF_DOWN)) { - sendTouchBegin = currentTouchPoints.isEmpty(); - insertActiveTouch(touchPoint); + eventType = insertActiveTouch(touchPoint); + // make sure new points are added to activeTouchPoints as well activeTouchPoints = currentTouchPoints; touchPoint->d->state = Qt::TouchPointPressed; touchPoint->d->globalPos = touchPoint->d->startGlobalPos = touchPoint->d->lastGlobalPos = globalPos; touchPoint->d->pressure = qreal(1.); } else if (down && (touchInput.dwFlags & TOUCHEVENTF_UP)) { - removeActiveTouch(touchPoint); - sendTouchEnd = currentTouchPoints.isEmpty(); + eventType = removeActiveTouch(touchPoint); touchPoint->d->state = Qt::TouchPointReleased; touchPoint->d->lastGlobalPos = touchPoint->d->globalPos; touchPoint->d->globalPos = globalPos; touchPoint->d->pressure = qreal(0.); } else if (down) { + eventType = QEvent::TouchUpdate; touchPoint->d->state = globalPos == touchPoint->d->globalPos ? Qt::TouchPointStationary : Qt::TouchPointMoved; @@ -4092,30 +4100,28 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) } QApplicationPrivate::CloseTouchInputHandle((HANDLE) msg.lParam); - if (activeTouchPoints.isEmpty()) + Q_ASSERT(eventType != QEvent::None); + if (eventType == QEvent::None || activeTouchPoints.isEmpty()) return false; - if (sendTouchBegin) { + if (eventType == QEvent::TouchBegin) { // the window under the first touch point gets the touch event int firstTouchId = activeTouchPoints.first()->id(); const QPoint &globalPos = allTouchPoints.at(firstTouchId)->d->globalPos.toPoint(); - QWidget *window = q->topLevelAt(globalPos); - if (window) { - QWidget *child = window->childAt(window->mapFromGlobal(globalPos)); - if (!child) - child = window; - currentMultitouchWidget = child; - // if the TouchBegin handler recurses, we assume that means the event - // has been implicitly accepted and continue to send touch events - currentMultitouchWidget->setAttribute(Qt::WA_AcceptedTouchBeginEvent); - } + QWidget *child = widgetForHwnd->childAt(widgetForHwnd->mapFromGlobal(globalPos)); + if (!child) + child = widgetForHwnd; + currentMultitouchWidget = child; + // if the TouchBegin handler recurses, we assume that means the event + // has been implicitly accepted and continue to send touch events + currentMultitouchWidget->setAttribute(Qt::WA_AcceptedTouchBeginEvent); } QWidget *widget = q->activePopupWidget(); if (!widget) widget = currentMultitouchWidget; - if (sendTouchEnd) { + if (eventType == QEvent::TouchEnd) { // reset currentMultitouchWindow when the last touch is released currentMultitouchWidget = 0; if (!currentTouchPoints.isEmpty()) { @@ -4125,15 +4131,10 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) // deliver the event if (widget && QApplicationPrivate::tryModalHelper(widget, 0)) { - QTouchEvent touchEvent((sendTouchBegin - ? QEvent::TouchBegin - : sendTouchEnd - ? QEvent::TouchEnd - : QEvent::TouchUpdate), - q->keyboardModifiers(), activeTouchPoints); + QTouchEvent touchEvent(eventType, q->keyboardModifiers(), activeTouchPoints); updateTouchPointsForWidget(widget, &touchEvent); - if (sendTouchBegin) { + if (eventType == QEvent::TouchBegin) { bool res = QApplication::sendSpontaneousEvent(widget, &touchEvent) && touchEvent.isAccepted(); qt_tabletChokeMouse = res; -- cgit v0.12 From 36c97c3e530969d172179d715805804ffb96e792 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Mon, 4 May 2009 12:22:44 +0200 Subject: Initialize activeTouchPoints in the loop itself instead of before This will make it easier to make the change to sending touch events to multiple widgets. --- src/gui/kernel/qapplication_win.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index b9262af..fbedd19 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -4049,8 +4049,7 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) return false; QEvent::Type eventType = QEvent::None; - QList activeTouchPoints = currentTouchPoints; - + QList activeTouchPoints; QVector winTouchInputs(msg.wParam); memset(winTouchInputs.data(), 0, sizeof(TOUCHINPUT) * winTouchInputs.count()); QApplicationPrivate::GetTouchInputInfo((HANDLE) msg.lParam, msg.wParam, winTouchInputs.data(), sizeof(TOUCHINPUT)); @@ -4082,6 +4081,7 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) touchPoint->d->globalPos = touchPoint->d->startGlobalPos = touchPoint->d->lastGlobalPos = globalPos; touchPoint->d->pressure = qreal(1.); } else if (down && (touchInput.dwFlags & TOUCHEVENTF_UP)) { + activeTouchPoints = currentTouchPoints; eventType = removeActiveTouch(touchPoint); touchPoint->d->state = Qt::TouchPointReleased; @@ -4089,6 +4089,8 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) touchPoint->d->globalPos = globalPos; touchPoint->d->pressure = qreal(0.); } else if (down) { + if (activeTouchPoints.isEmpty()) + activeTouchPoints = currentTouchPoints; eventType = QEvent::TouchUpdate; touchPoint->d->state = globalPos == touchPoint->d->globalPos ? Qt::TouchPointStationary -- cgit v0.12 From 2d0f49df3a3c44601bf2e41ea722c2384b71aab0 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Mon, 4 May 2009 17:17:34 +0200 Subject: Support sending touch events (with multiple touch points) to multiple widgets simultaneously This is a first attempt, and it works, but it will need to be cleaned up to remove as much state from QWidgetPrivate as possible. --- src/gui/kernel/qapplication.cpp | 9 +- src/gui/kernel/qapplication_p.h | 11 ++- src/gui/kernel/qapplication_win.cpp | 191 +++++++++++++++++++++++------------- src/gui/kernel/qevent.h | 2 + src/gui/kernel/qevent_p.h | 1 + src/gui/kernel/qwidget_p.h | 3 + 6 files changed, 141 insertions(+), 76 deletions(-) diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 81c02e3..3a25abb 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -3997,6 +3997,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) // Note: TouchUpdate and TouchEnd events are sent to d->currentMultitouchWidget and never propagated { QWidget *widget = static_cast(receiver); + QWidget *origin = widget; QTouchEvent *touchEvent = static_cast(e); bool eventAccepted = touchEvent->isAccepted(); @@ -4017,7 +4018,13 @@ bool QApplication::notify(QObject *receiver, QEvent *e) touchEvent->spont = false; if (res && eventAccepted) { // the first widget to accept the TouchBegin gets an implicit grab. - d->currentMultitouchWidget = widget; + for (int i = 0; i < touchEvent->_touchPoints.count(); ++i) { + QTouchEvent::TouchPoint *touchPoint = touchEvent->_touchPoints.at(i); + touchPoint->d->widget = widget; + } + if (origin != widget) + origin->d_func()->currentTouchPoints.clear(); + widget->d_func()->currentTouchPoints = touchEvent->_touchPoints; break; } else if (widget->isWindow() || widget->testAttribute(Qt::WA_NoMousePropagation)) { break; diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index ef375d3..1a2bad2 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -428,7 +428,6 @@ public: void sendSyntheticEnterLeave(QWidget *widget); #endif - QPointer currentMultitouchWidget; static void updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent); #if defined(Q_WS_WIN) @@ -437,12 +436,14 @@ public: static qt_CloseTouchInputHandlePtr CloseTouchInputHandle; QMap touchInputIDToTouchPointID; - QVector allTouchPoints; - QList currentTouchPoints; + QVector appAllTouchPoints; + QList appCurrentTouchPoints; void initializeMultitouch(); - QEvent::Type insertActiveTouch(QTouchEvent::TouchPoint *touchPoint); - QEvent::Type removeActiveTouch(QTouchEvent::TouchPoint *touchPoint); + static QTouchEvent::TouchPoint *findClosestTouchPoint(const QList &activeTouchPoints, + const QPointF &pos); + QEvent::Type appendTouchPoint(QTouchEvent::TouchPoint *touchPoint); + QEvent::Type removeTouchPoint(QTouchEvent::TouchPoint *touchPoint); bool translateTouchEvent(const MSG &msg); #endif diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index fbedd19..f13ab5d 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -75,6 +75,7 @@ extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.c #include "qcolormap.h" #include "qlayout.h" #include "qtooltip.h" +#include "qset.h" #include "qt_windows.h" #if defined(QT_NON_COMMERCIAL) #include "qnc_win.h" @@ -3999,45 +4000,76 @@ void QApplicationPrivate::initializeMultitouch() GetTouchInputInfo = static_cast(library.resolve("GetTouchInputInfo")); CloseTouchInputHandle = static_cast(library.resolve("CloseTouchInputHandle")); - currentMultitouchWidget = 0; touchInputIDToTouchPointID.clear(); - allTouchPoints.clear(); - currentTouchPoints.clear(); + appAllTouchPoints.clear(); } -QEvent::Type QApplicationPrivate::insertActiveTouch(QTouchEvent::TouchPoint *touchPoint) +QTouchEvent::TouchPoint *QApplicationPrivate::findClosestTouchPoint(const QList &appActiveTouchPoints, + const QPointF &pos) { - QEvent::Type eventType = currentTouchPoints.isEmpty() + QTouchEvent::TouchPoint *closestTouchPoint = 0; + qreal closestDistance; + for (int i = 0; i < appActiveTouchPoints.count(); ++i) { + QTouchEvent::TouchPoint *touchPoint = appActiveTouchPoints.at(i); + qreal distance = QLineF(pos, touchPoint->d->globalPos).length(); + if (!closestTouchPoint || distance < closestDistance) { + closestTouchPoint = touchPoint; + closestDistance = distance; + } + } + return closestTouchPoint; +} + +QEvent::Type QApplicationPrivate::appendTouchPoint(QTouchEvent::TouchPoint *touchPoint) +{ + QWidget *widget = touchPoint->d->widget; + QEvent::Type eventType = widget->d_func()->currentTouchPoints.isEmpty() ? QEvent::TouchBegin : QEvent::TouchUpdate; - // insort touch point + // insort touch point (for the app) int at = 0; - for (; at < currentTouchPoints.count(); ++at) { - if (currentTouchPoints.at(at)->id() > touchPoint->id()) + for (; at < appCurrentTouchPoints.count(); ++at) { + if (appCurrentTouchPoints.at(at)->id() > touchPoint->id()) break; } - currentTouchPoints.insert(at, touchPoint); + appCurrentTouchPoints.insert(at, touchPoint); + // again, for the widget's currentTouchPoints + for (at = 0; at < widget->d_func()->currentTouchPoints.count(); ++at) { + if (widget->d_func()->currentTouchPoints.at(at)->id() > touchPoint->id()) + break; + } + widget->d_func()->currentTouchPoints.insert(at, touchPoint); - if (currentTouchPoints.count() > allTouchPoints.count()) { - qFatal("Qt: INTERNAL ERROR: currentTouchPoints.count() (%d) > allTouchPoints.count() (%d)", - currentTouchPoints.count(), - allTouchPoints.count()); + if (appCurrentTouchPoints.count() > appAllTouchPoints.count()) { + qFatal("Qt: INTERNAL ERROR: appCurrentTouchPoints.count() (%d) > appAllTouchPoints.count() (%d)", + appCurrentTouchPoints.count(), + appAllTouchPoints.count()); } return eventType; } -QEvent::Type QApplicationPrivate::removeActiveTouch(QTouchEvent::TouchPoint *touchPoint) +QEvent::Type QApplicationPrivate::removeTouchPoint(QTouchEvent::TouchPoint *touchPoint) { - for (int i = qMin(currentTouchPoints.count() - 1, touchPoint->id()); i >= 0; --i) { - if (currentTouchPoints.at(i) == touchPoint) { - currentTouchPoints.removeAt(i); + QWidget *widget = touchPoint->d->widget; + + // remove touch point from all known touch points + for (int i = qMin(appCurrentTouchPoints.count() - 1, touchPoint->id()); i >= 0; --i) { + if (appCurrentTouchPoints.at(i) == touchPoint) { + appCurrentTouchPoints.removeAt(i); + break; + } + } + // again, for the widget's currentTouchPoints + for (int i = qMin(widget->d_func()->currentTouchPoints.count() - 1, touchPoint->id()); i >= 0; --i) { + if (widget->d_func()->currentTouchPoints.at(i) == touchPoint) { + widget->d_func()->currentTouchPoints.removeAt(i); break; } } - return currentTouchPoints.isEmpty() ? QEvent::TouchEnd : QEvent::TouchUpdate; + return widget->d_func()->currentTouchPoints.isEmpty() ? QEvent::TouchEnd : QEvent::TouchUpdate; } bool QApplicationPrivate::translateTouchEvent(const MSG &msg) @@ -4048,8 +4080,9 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) if (!widgetForHwnd) return false; - QEvent::Type eventType = QEvent::None; - QList activeTouchPoints; + QList appActiveTouchPoints = appCurrentTouchPoints; + + QSet widgetsNeedingEvents; QVector winTouchInputs(msg.wParam); memset(winTouchInputs.data(), 0, sizeof(TOUCHINPUT) * winTouchInputs.count()); QApplicationPrivate::GetTouchInputInfo((HANDLE) msg.lParam, msg.wParam, winTouchInputs.data(), sizeof(TOUCHINPUT)); @@ -4062,36 +4095,56 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) touchInputIDToTouchPointID.insert(touchInput.dwID, touchPointID); } - if (allTouchPoints.count() <= touchPointID) - allTouchPoints.resize(touchPointID + 1); + if (appAllTouchPoints.count() <= touchPointID) + appAllTouchPoints.resize(touchPointID + 1); - QTouchEvent::TouchPoint *touchPoint = allTouchPoints.at(touchPointID); + QTouchEvent::TouchPoint *touchPoint = appAllTouchPoints.at(touchPointID); if (!touchPoint) - touchPoint = allTouchPoints[touchPointID] = new QTouchEvent::TouchPoint(touchPointID); + touchPoint = appAllTouchPoints[touchPointID] = new QTouchEvent::TouchPoint(touchPointID); // update state bool down = touchPoint->d->state != Qt::TouchPointReleased; QPointF globalPos(qreal(touchInput.x) / qreal(100.), qreal(touchInput.y) / qreal(100.)); if (!down && (touchInput.dwFlags & TOUCHEVENTF_DOWN)) { - eventType = insertActiveTouch(touchPoint); + // determine which widget this event will go to + QWidget *w = widgetForHwnd->childAt(widgetForHwnd->mapFromGlobal(globalPos.toPoint())); + if (!w) + w = widgetForHwnd; + + QTouchEvent::TouchPoint *closestTouchPoint = findClosestTouchPoint(appActiveTouchPoints, globalPos); + if (closestTouchPoint + && (w->isAncestorOf(closestTouchPoint->d->widget) + || closestTouchPoint->d->widget->isAncestorOf(w))) { + w = closestTouchPoint->d->widget; + } + touchPoint->d->widget = w; + + w->d_func()->touchEventType = appendTouchPoint(touchPoint); // make sure new points are added to activeTouchPoints as well - activeTouchPoints = currentTouchPoints; + appActiveTouchPoints = appCurrentTouchPoints; + w->d_func()->activeTouchPoints = w->d_func()->currentTouchPoints; touchPoint->d->state = Qt::TouchPointPressed; - touchPoint->d->globalPos = touchPoint->d->startGlobalPos = touchPoint->d->lastGlobalPos = globalPos; + touchPoint->d->globalPos + = touchPoint->d->startGlobalPos + = touchPoint->d->lastGlobalPos + = globalPos; touchPoint->d->pressure = qreal(1.); } else if (down && (touchInput.dwFlags & TOUCHEVENTF_UP)) { - activeTouchPoints = currentTouchPoints; - eventType = removeActiveTouch(touchPoint); + QWidget *w = touchPoint->d->widget; + appActiveTouchPoints = appCurrentTouchPoints; + w->d_func()->activeTouchPoints = w->d_func()->currentTouchPoints; + w->d_func()->touchEventType = removeTouchPoint(touchPoint); touchPoint->d->state = Qt::TouchPointReleased; touchPoint->d->lastGlobalPos = touchPoint->d->globalPos; touchPoint->d->globalPos = globalPos; touchPoint->d->pressure = qreal(0.); } else if (down) { - if (activeTouchPoints.isEmpty()) - activeTouchPoints = currentTouchPoints; - eventType = QEvent::TouchUpdate; + QWidget *w = touchPoint->d->widget; + appActiveTouchPoints = appCurrentTouchPoints; + w->d_func()->activeTouchPoints = w->d_func()->currentTouchPoints; + w->d_func()->touchEventType = QEvent::TouchUpdate; touchPoint->d->state = globalPos == touchPoint->d->globalPos ? Qt::TouchPointStationary : Qt::TouchPointMoved; @@ -4099,58 +4152,56 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) touchPoint->d->globalPos = globalPos; // pressure should still be 1. } + + if (touchPoint->d->state != Qt::TouchPointStationary) + widgetsNeedingEvents.insert(touchPoint->d->widget); } QApplicationPrivate::CloseTouchInputHandle((HANDLE) msg.lParam); - Q_ASSERT(eventType != QEvent::None); - if (eventType == QEvent::None || activeTouchPoints.isEmpty()) + if (widgetsNeedingEvents.isEmpty()) return false; - if (eventType == QEvent::TouchBegin) { - // the window under the first touch point gets the touch event - int firstTouchId = activeTouchPoints.first()->id(); - const QPoint &globalPos = allTouchPoints.at(firstTouchId)->d->globalPos.toPoint(); - QWidget *child = widgetForHwnd->childAt(widgetForHwnd->mapFromGlobal(globalPos)); - if (!child) - child = widgetForHwnd; - currentMultitouchWidget = child; - // if the TouchBegin handler recurses, we assume that means the event - // has been implicitly accepted and continue to send touch events - currentMultitouchWidget->setAttribute(Qt::WA_AcceptedTouchBeginEvent); - } + bool returnValue = false; - QWidget *widget = q->activePopupWidget(); - if (!widget) - widget = currentMultitouchWidget; - - if (eventType == QEvent::TouchEnd) { - // reset currentMultitouchWindow when the last touch is released - currentMultitouchWidget = 0; - if (!currentTouchPoints.isEmpty()) { - qFatal("Qt: INTERNAL ERROR, currentTouchPoints should be empty!"); - } - } + QSet::ConstIterator it = widgetsNeedingEvents.constBegin(); + const QSet::ConstIterator end = widgetsNeedingEvents.constEnd(); + for (; it != end; ++it) { + QWidget *widget = *it; + if (!QApplicationPrivate::tryModalHelper(widget, 0)) + continue; - // deliver the event - if (widget && QApplicationPrivate::tryModalHelper(widget, 0)) { - QTouchEvent touchEvent(eventType, q->keyboardModifiers(), activeTouchPoints); + QTouchEvent touchEvent(widget->d_func()->touchEventType, q->keyboardModifiers(), widget->d_func()->activeTouchPoints); updateTouchPointsForWidget(widget, &touchEvent); - if (eventType == QEvent::TouchBegin) { + switch (widget->d_func()->touchEventType) { + case QEvent::TouchBegin: + { + // if the TouchBegin handler recurses, we assume that means the event + // has been implicitly accepted and continue to send touch events + widget->setAttribute(Qt::WA_AcceptedTouchBeginEvent); bool res = QApplication::sendSpontaneousEvent(widget, &touchEvent) && touchEvent.isAccepted(); - qt_tabletChokeMouse = res; - } else if (widget->testAttribute(Qt::WA_AcceptedTouchBeginEvent)) { - (void) QApplication::sendSpontaneousEvent(widget, &touchEvent); - qt_tabletChokeMouse = true; - } else { - qt_tabletChokeMouse = false; + returnValue = returnValue || (qt_tabletChokeMouse = res); + break; + } + case QEvent::TouchEnd: + if (!widget->d_func()->currentTouchPoints.isEmpty()) { + qFatal("Qt: INTERNAL ERROR, the widget's currentTouchPoints should be empty!"); + } + // fall-through intended + default: + if (widget->testAttribute(Qt::WA_AcceptedTouchBeginEvent)) { + (void) QApplication::sendSpontaneousEvent(widget, &touchEvent); + qt_tabletChokeMouse = true; + } else { + qt_tabletChokeMouse = false; + } + returnValue = returnValue || qt_tabletChokeMouse; + break; } - - return qt_tabletChokeMouse; } - return false; + return returnValue; } QT_END_NAMESPACE diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index 506e0c1..e9a1386 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -746,6 +746,7 @@ public: private: QTouchEventTouchPointPrivate *d; + friend class QApplication; friend class QApplicationPrivate; }; @@ -759,6 +760,7 @@ public: protected: QList _touchPoints; + friend class QApplication; friend class QApplicationPrivate; }; diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h index 5e24eeb..df7143e 100644 --- a/src/gui/kernel/qevent_p.h +++ b/src/gui/kernel/qevent_p.h @@ -98,6 +98,7 @@ public: pressure(qreal(-1.)) { } + QPointer widget; int id; Qt::TouchPointState state; QPointF pos, startPos, lastPos; diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 8731551..df17566 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -663,6 +663,9 @@ public: } QSize adjustedSize() const; + + QEvent::Type touchEventType; + QList currentTouchPoints, activeTouchPoints; }; inline QWExtra *QWidgetPrivate::extraData() const -- cgit v0.12 From 7a5da4486708b096084fdaf83aba88f5d1b83e00 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Wed, 6 May 2009 14:08:34 +0200 Subject: fix QtOpenGL compilation, add missing include --- src/gui/kernel/qwidget_p.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 2dd3061..2ab9ffe 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -60,6 +60,7 @@ #include "QtGui/qregion.h" #include "QtGui/qsizepolicy.h" #include "QtGui/qstyle.h" +#include "QtGui/qevent.h" #ifdef Q_WS_WIN #include "QtCore/qt_windows.h" -- cgit v0.12 From 58f25669087bf52357bc69f398b4713d33b03d1e Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Fri, 8 May 2009 13:04:19 +0200 Subject: don't store event state in QWidgetPrivate the only thing we store in the QWidgetPrivate is the current touch point list, nothing more (the rest is local state in the event translation code) --- src/gui/kernel/qapplication_win.cpp | 34 +++++++++++++++++++--------------- src/gui/kernel/qwidget_p.h | 3 +-- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 91c24da..60c6fd7 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -75,7 +75,6 @@ extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.c #include "qcolormap.h" #include "qlayout.h" #include "qtooltip.h" -#include "qset.h" #include "qt_windows.h" #if defined(QT_NON_COMMERCIAL) #include "qnc_win.h" @@ -4091,7 +4090,7 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) QList appActiveTouchPoints = appCurrentTouchPoints; - QSet widgetsNeedingEvents; + QHash widgetsNeedingEvents; QVector winTouchInputs(msg.wParam); memset(winTouchInputs.data(), 0, sizeof(TOUCHINPUT) * winTouchInputs.count()); QApplicationPrivate::GetTouchInputInfo((HANDLE) msg.lParam, msg.wParam, winTouchInputs.data(), sizeof(TOUCHINPUT)); @@ -4114,6 +4113,8 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) // update state bool down = touchPoint->d->state != Qt::TouchPointReleased; QPointF globalPos(qreal(touchInput.x) / qreal(100.), qreal(touchInput.y) / qreal(100.)); + QEvent::Type eventType = QEvent::None; + QList activeTouchPoints; if (!down && (touchInput.dwFlags & TOUCHEVENTF_DOWN)) { // determine which widget this event will go to QWidget *w = widgetForHwnd->childAt(widgetForHwnd->mapFromGlobal(globalPos.toPoint())); @@ -4128,10 +4129,10 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) } touchPoint->d->widget = w; - w->d_func()->touchEventType = appendTouchPoint(touchPoint); + eventType = appendTouchPoint(touchPoint); // make sure new points are added to activeTouchPoints as well appActiveTouchPoints = appCurrentTouchPoints; - w->d_func()->activeTouchPoints = w->d_func()->currentTouchPoints; + activeTouchPoints = w->d_func()->currentTouchPoints; touchPoint->d->state = Qt::TouchPointPressed; touchPoint->d->globalPos @@ -4142,8 +4143,8 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) } else if (down && (touchInput.dwFlags & TOUCHEVENTF_UP)) { QWidget *w = touchPoint->d->widget; appActiveTouchPoints = appCurrentTouchPoints; - w->d_func()->activeTouchPoints = w->d_func()->currentTouchPoints; - w->d_func()->touchEventType = removeTouchPoint(touchPoint); + activeTouchPoints = w->d_func()->currentTouchPoints; + eventType = removeTouchPoint(touchPoint); touchPoint->d->state = Qt::TouchPointReleased; touchPoint->d->lastGlobalPos = touchPoint->d->globalPos; @@ -4152,8 +4153,8 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) } else if (down) { QWidget *w = touchPoint->d->widget; appActiveTouchPoints = appCurrentTouchPoints; - w->d_func()->activeTouchPoints = w->d_func()->currentTouchPoints; - w->d_func()->touchEventType = QEvent::TouchUpdate; + activeTouchPoints = w->d_func()->currentTouchPoints; + eventType = QEvent::TouchUpdate; touchPoint->d->state = globalPos == touchPoint->d->globalPos ? Qt::TouchPointStationary : Qt::TouchPointMoved; @@ -4161,9 +4162,12 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) touchPoint->d->globalPos = globalPos; // pressure should still be 1. } + Q_ASSERT(eventType != QEvent::None); - if (touchPoint->d->state != Qt::TouchPointStationary) - widgetsNeedingEvents.insert(touchPoint->d->widget); + if (touchPoint->d->state != Qt::TouchPointStationary) { + widgetsNeedingEvents.insert(touchPoint->d->widget, + QTouchEvent(eventType, q->keyboardModifiers(), activeTouchPoints)); + } } QApplicationPrivate::CloseTouchInputHandle((HANDLE) msg.lParam); @@ -4172,17 +4176,17 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) bool returnValue = false; - QSet::ConstIterator it = widgetsNeedingEvents.constBegin(); - const QSet::ConstIterator end = widgetsNeedingEvents.constEnd(); + QHash::ConstIterator it = widgetsNeedingEvents.constBegin(); + const QHash::ConstIterator end = widgetsNeedingEvents.constEnd(); for (; it != end; ++it) { - QWidget *widget = *it; + QWidget *widget = it.key(); if (!QApplicationPrivate::tryModalHelper(widget, 0)) continue; - QTouchEvent touchEvent(widget->d_func()->touchEventType, q->keyboardModifiers(), widget->d_func()->activeTouchPoints); + QTouchEvent touchEvent = it.value(); updateTouchPointsForWidget(widget, &touchEvent); - switch (widget->d_func()->touchEventType) { + switch (touchEvent.type()) { case QEvent::TouchBegin: { // if the TouchBegin handler recurses, we assume that means the event diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 2ab9ffe..5f5e1b1 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -666,8 +666,7 @@ public: QSize adjustedSize() const; - QEvent::Type touchEventType; - QList currentTouchPoints, activeTouchPoints; + QList currentTouchPoints; }; inline QWExtra *QWidgetPrivate::extraData() const -- cgit v0.12 From c45ba5929d2e6326449df124d42fc60032c1c93c Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Fri, 8 May 2009 13:06:47 +0200 Subject: warn about events that happen out of sequence --- tests/manual/qtouchevent/touchwidget.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/manual/qtouchevent/touchwidget.cpp b/tests/manual/qtouchevent/touchwidget.cpp index f029f8b..a8141cc 100644 --- a/tests/manual/qtouchevent/touchwidget.cpp +++ b/tests/manual/qtouchevent/touchwidget.cpp @@ -31,6 +31,9 @@ bool TouchWidget::event(QEvent *event) { switch (event->type()) { case QEvent::TouchBegin: + if (seenTouchBegin) qWarning("TouchBegin: already seen a TouchBegin"); + if (seenTouchUpdate) qWarning("TouchBegin: TouchUpdate cannot happen before TouchBegin"); + if (seenTouchEnd) qWarning("TouchBegin: TouchEnd cannot happen before TouchBegin"); seenTouchBegin = !seenTouchBegin && !seenTouchUpdate && !seenTouchEnd; touchPointCount = qMax(touchPointCount, static_cast(event)->touchPoints().count()); if (acceptTouchBegin) { @@ -39,6 +42,8 @@ bool TouchWidget::event(QEvent *event) } break; case QEvent::TouchUpdate: + if (!seenTouchBegin) qWarning("TouchUpdate: have not seen TouchBegin"); + if (seenTouchEnd) qWarning("TouchUpdate: TouchEnd cannot happen before TouchUpdate"); seenTouchUpdate = seenTouchBegin && !seenTouchEnd; touchPointCount = qMax(touchPointCount, static_cast(event)->touchPoints().count()); if (acceptTouchUpdate) { @@ -47,6 +52,8 @@ bool TouchWidget::event(QEvent *event) } break; case QEvent::TouchEnd: + if (!seenTouchBegin) qWarning("TouchEnd: have not seen TouchBegin"); + if (seenTouchEnd) qWarning("TouchEnd: already seen a TouchEnd"); seenTouchEnd = seenTouchBegin && !seenTouchEnd; touchPointCount = qMax(touchPointCount, static_cast(event)->touchPoints().count()); if (closeWindowOnTouchEnd) -- cgit v0.12 From 711701da5cc958bb44cd5ff2d6562cfca1f7eb85 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Fri, 8 May 2009 15:45:43 +0200 Subject: don't require TouchUpdate events for the single touch cases the finger may not move, meaning no update with move event is generated, even if we say "press, hold, release" when testing (the finger may not wobble enough) --- tests/manual/qtouchevent/main.cpp | 52 +++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/tests/manual/qtouchevent/main.cpp b/tests/manual/qtouchevent/main.cpp index 9f2d413..8097ab0 100644 --- a/tests/manual/qtouchevent/main.cpp +++ b/tests/manual/qtouchevent/main.cpp @@ -61,7 +61,7 @@ void tst_ManualMultitouch::ignoringTouchEventsEmulatesMouseEvents() testWidget.showMaximized(); (void) qApp->exec(); QVERIFY(!testWidget.greenWidget->seenTouchBegin); - QVERIFY(!testWidget.greenWidget->seenTouchUpdate); + // QVERIFY(!testWidget.greenWidget->seenTouchUpdate); QVERIFY(!testWidget.greenWidget->seenTouchEnd); QVERIFY(testWidget.greenWidget->seenMousePress); // QVERIFY(testWidget.greenWidget->seenMouseMove); @@ -74,7 +74,7 @@ void tst_ManualMultitouch::ignoringTouchEventsEmulatesMouseEvents() testWidget.showMaximized(); (void) qApp->exec(); QVERIFY(testWidget.greenWidget->seenTouchBegin); - QVERIFY(!testWidget.greenWidget->seenTouchUpdate); + // QVERIFY(!testWidget.greenWidget->seenTouchUpdate); QVERIFY(!testWidget.greenWidget->seenTouchEnd); QVERIFY(testWidget.greenWidget->seenMousePress); // QVERIFY(testWidget.greenWidget->seenMouseMove); @@ -96,12 +96,12 @@ void tst_ManualMultitouch::basicSingleTouchEventHandling() testWidget.greenWidget->closeWindowOnTouchEnd = true; testWidget.showMaximized(); (void) qApp->exec(); - QVERIFY(testWidget.greenWidget->seenTouchBegin - && testWidget.greenWidget->seenTouchUpdate - && testWidget.greenWidget->seenTouchEnd); - QVERIFY(!testWidget.greenWidget->seenMousePress - && !testWidget.greenWidget->seenMouseMove - && !testWidget.greenWidget->seenMouseRelease); + QVERIFY(testWidget.greenWidget->seenTouchBegin); + // QVERIFY(testWidget.greenWidget->seenTouchUpdate); + QVERIFY(testWidget.greenWidget->seenTouchEnd); + QVERIFY(!testWidget.greenWidget->seenMousePress); + QVERIFY(!testWidget.greenWidget->seenMouseMove); + QVERIFY(!testWidget.greenWidget->seenMouseRelease); // again, ignoring the TouchEnd testWidget.greenWidget->reset(); @@ -112,7 +112,7 @@ void tst_ManualMultitouch::basicSingleTouchEventHandling() testWidget.showMaximized(); (void) qApp->exec(); QVERIFY(testWidget.greenWidget->seenTouchBegin); - QVERIFY(testWidget.greenWidget->seenTouchUpdate); + // QVERIFY(testWidget.greenWidget->seenTouchUpdate); QVERIFY(testWidget.greenWidget->seenTouchEnd); QVERIFY(!testWidget.greenWidget->seenMousePress); QVERIFY(!testWidget.greenWidget->seenMouseMove); @@ -127,7 +127,7 @@ void tst_ManualMultitouch::basicSingleTouchEventHandling() testWidget.showMaximized(); (void) qApp->exec(); QVERIFY(testWidget.greenWidget->seenTouchBegin); - QVERIFY(testWidget.greenWidget->seenTouchUpdate); + // QVERIFY(testWidget.greenWidget->seenTouchUpdate); QVERIFY(testWidget.greenWidget->seenTouchEnd); QVERIFY(!testWidget.greenWidget->seenMousePress); QVERIFY(!testWidget.greenWidget->seenMouseMove); @@ -142,7 +142,7 @@ void tst_ManualMultitouch::basicSingleTouchEventHandling() testWidget.showMaximized(); (void) qApp->exec(); QVERIFY(testWidget.greenWidget->seenTouchBegin); - QVERIFY(testWidget.greenWidget->seenTouchUpdate); + // QVERIFY(testWidget.greenWidget->seenTouchUpdate); QVERIFY(testWidget.greenWidget->seenTouchEnd); QVERIFY(!testWidget.greenWidget->seenMousePress); QVERIFY(!testWidget.greenWidget->seenMouseMove); @@ -235,7 +235,7 @@ void tst_ManualMultitouch::acceptingTouchBeginStopsPropagation() testWidget.showMaximized(); (void) qApp->exec(); QVERIFY(testWidget.blueWidget->seenTouchBegin); - QVERIFY(testWidget.blueWidget->seenTouchUpdate); + // QVERIFY(testWidget.blueWidget->seenTouchUpdate); QVERIFY(testWidget.blueWidget->seenTouchEnd); QVERIFY(!testWidget.blueWidget->seenMousePress); QVERIFY(!testWidget.blueWidget->seenMouseMove); @@ -257,7 +257,7 @@ void tst_ManualMultitouch::acceptingTouchBeginStopsPropagation() testWidget.showMaximized(); (void) qApp->exec(); QVERIFY(testWidget.blueWidget->seenTouchBegin); - QVERIFY(testWidget.blueWidget->seenTouchUpdate); + // QVERIFY(testWidget.blueWidget->seenTouchUpdate); QVERIFY(testWidget.blueWidget->seenTouchEnd); QVERIFY(!testWidget.blueWidget->seenMousePress); QVERIFY(!testWidget.blueWidget->seenMouseMove); @@ -279,7 +279,7 @@ void tst_ManualMultitouch::acceptingTouchBeginStopsPropagation() testWidget.showMaximized(); (void) qApp->exec(); QVERIFY(testWidget.blueWidget->seenTouchBegin); - QVERIFY(testWidget.blueWidget->seenTouchUpdate); + // QVERIFY(testWidget.blueWidget->seenTouchUpdate); QVERIFY(testWidget.blueWidget->seenTouchEnd); QVERIFY(!testWidget.blueWidget->seenMousePress); QVERIFY(!testWidget.blueWidget->seenMouseMove); @@ -301,7 +301,7 @@ void tst_ManualMultitouch::acceptingTouchBeginStopsPropagation() testWidget.showMaximized(); (void) qApp->exec(); QVERIFY(testWidget.blueWidget->seenTouchBegin); - QVERIFY(testWidget.blueWidget->seenTouchUpdate); + // QVERIFY(testWidget.blueWidget->seenTouchUpdate); QVERIFY(testWidget.blueWidget->seenTouchEnd); QVERIFY(!testWidget.blueWidget->seenMousePress); QVERIFY(!testWidget.blueWidget->seenMouseMove); @@ -339,7 +339,7 @@ void tst_ManualMultitouch::ignoringTouchBeginPropagatesToParent() QVERIFY(!testWidget.greyWidget->seenMouseMove); QVERIFY(!testWidget.greyWidget->seenMouseRelease); QVERIFY(testWidget.redWidget->seenTouchBegin); - QVERIFY(testWidget.redWidget->seenTouchUpdate); + // QVERIFY(testWidget.redWidget->seenTouchUpdate); QVERIFY(testWidget.redWidget->seenTouchEnd); QVERIFY(!testWidget.redWidget->seenMousePress); QVERIFY(!testWidget.redWidget->seenMouseMove); @@ -362,7 +362,7 @@ void tst_ManualMultitouch::ignoringTouchBeginPropagatesToParent() QVERIFY(!testWidget.greyWidget->seenMouseMove); QVERIFY(!testWidget.greyWidget->seenMouseRelease); QVERIFY(testWidget.redWidget->seenTouchBegin); - QVERIFY(testWidget.redWidget->seenTouchUpdate); + // QVERIFY(testWidget.redWidget->seenTouchUpdate); QVERIFY(testWidget.redWidget->seenTouchEnd); QVERIFY(!testWidget.redWidget->seenMousePress); QVERIFY(!testWidget.redWidget->seenMouseMove); @@ -384,7 +384,7 @@ void tst_ManualMultitouch::ignoringTouchBeginPropagatesToParent() QVERIFY(!testWidget.greyWidget->seenMouseMove); QVERIFY(!testWidget.greyWidget->seenMouseRelease); QVERIFY(testWidget.redWidget->seenTouchBegin); - QVERIFY(testWidget.redWidget->seenTouchUpdate); + // QVERIFY(testWidget.redWidget->seenTouchUpdate); QVERIFY(testWidget.redWidget->seenTouchEnd); QVERIFY(!testWidget.redWidget->seenMousePress); QVERIFY(!testWidget.redWidget->seenMouseMove); @@ -406,7 +406,7 @@ void tst_ManualMultitouch::ignoringTouchBeginPropagatesToParent() QVERIFY(!testWidget.greyWidget->seenMouseMove); QVERIFY(!testWidget.greyWidget->seenMouseRelease); QVERIFY(testWidget.redWidget->seenTouchBegin); - QVERIFY(testWidget.redWidget->seenTouchUpdate); + // QVERIFY(testWidget.redWidget->seenTouchUpdate); QVERIFY(testWidget.redWidget->seenTouchEnd); QVERIFY(!testWidget.redWidget->seenMousePress); QVERIFY(!testWidget.redWidget->seenMouseMove); @@ -428,7 +428,7 @@ void tst_ManualMultitouch::ignoringTouchBeginPropagatesToParent() QVERIFY(!testWidget.greyWidget->seenMouseMove); QVERIFY(!testWidget.blueWidget->seenMouseRelease); QVERIFY(testWidget.redWidget->seenTouchBegin); - QVERIFY(testWidget.redWidget->seenTouchUpdate); + // QVERIFY(testWidget.redWidget->seenTouchUpdate); QVERIFY(testWidget.redWidget->seenTouchEnd); QVERIFY(!testWidget.redWidget->seenMousePress); QVERIFY(!testWidget.redWidget->seenMouseMove); @@ -449,7 +449,7 @@ void tst_ManualMultitouch::secondTouchPointOnParentGoesToChild() testWidget.showMaximized(); (void) qApp->exec(); QVERIFY(testWidget.blueWidget->seenTouchBegin); - QVERIFY(testWidget.blueWidget->seenTouchUpdate); + // QVERIFY(testWidget.blueWidget->seenTouchUpdate); QVERIFY(testWidget.blueWidget->seenTouchEnd); QVERIFY(!testWidget.blueWidget->seenMousePress); QVERIFY(!testWidget.blueWidget->seenMouseMove); @@ -477,7 +477,7 @@ void tst_ManualMultitouch::secondTouchPointOnChildGoesToParent() testWidget.showMaximized(); (void) qApp->exec(); QVERIFY(testWidget.redWidget->seenTouchBegin); - QVERIFY(testWidget.redWidget->seenTouchUpdate); + // QVERIFY(testWidget.redWidget->seenTouchUpdate); QVERIFY(testWidget.redWidget->seenTouchEnd); QVERIFY(!testWidget.redWidget->seenMousePress); QVERIFY(!testWidget.redWidget->seenMouseMove); @@ -506,13 +506,13 @@ void tst_ManualMultitouch::secondTouchPointOnSiblingGoesToSibling() testWidget.showMaximized(); (void) qApp->exec(); QVERIFY(testWidget.greenWidget->seenTouchBegin); - QVERIFY(testWidget.greenWidget->seenTouchUpdate); + // QVERIFY(testWidget.greenWidget->seenTouchUpdate); QVERIFY(testWidget.greenWidget->seenTouchEnd); QVERIFY(!testWidget.greenWidget->seenMousePress); QVERIFY(!testWidget.greenWidget->seenMouseMove); QVERIFY(!testWidget.greenWidget->seenMouseRelease); QVERIFY(testWidget.redWidget->seenTouchBegin); - QVERIFY(testWidget.redWidget->seenTouchUpdate); + // QVERIFY(testWidget.redWidget->seenTouchUpdate); QVERIFY(testWidget.redWidget->seenTouchEnd); QVERIFY(!testWidget.redWidget->seenMousePress); QVERIFY(!testWidget.redWidget->seenMouseMove); @@ -534,13 +534,13 @@ void tst_ManualMultitouch::secondTouchPointOnCousinGoesToCousin() testWidget.showMaximized(); (void) qApp->exec(); QVERIFY(testWidget.blueWidget->seenTouchBegin); - QVERIFY(testWidget.blueWidget->seenTouchUpdate); + // QVERIFY(testWidget.blueWidget->seenTouchUpdate); QVERIFY(testWidget.blueWidget->seenTouchEnd); QVERIFY(!testWidget.blueWidget->seenMousePress); QVERIFY(!testWidget.blueWidget->seenMouseMove); QVERIFY(!testWidget.blueWidget->seenMouseRelease); QVERIFY(testWidget.greyWidget->seenTouchBegin); - QVERIFY(testWidget.greyWidget->seenTouchUpdate); + // QVERIFY(testWidget.greyWidget->seenTouchUpdate); QVERIFY(testWidget.greyWidget->seenTouchEnd); QVERIFY(!testWidget.greyWidget->seenMousePress); QVERIFY(!testWidget.greyWidget->seenMouseMove); -- cgit v0.12 From 5d7e624593172a9901d0bb44d57fe6e7697fd113 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Fri, 8 May 2009 15:55:06 +0200 Subject: set qt_tabletChokeMouse to true whenever ANY touch event was accepted this makes sure we always get touch events, and the don't drop out seemingly randomly. --- src/gui/kernel/qapplication_win.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp index 60c6fd7..723a3b4 100644 --- a/src/gui/kernel/qapplication_win.cpp +++ b/src/gui/kernel/qapplication_win.cpp @@ -4175,6 +4175,7 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) return false; bool returnValue = false; + qt_tabletChokeMouse = false; QHash::ConstIterator it = widgetsNeedingEvents.constBegin(); const QHash::ConstIterator end = widgetsNeedingEvents.constEnd(); @@ -4194,7 +4195,7 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) widget->setAttribute(Qt::WA_AcceptedTouchBeginEvent); bool res = QApplication::sendSpontaneousEvent(widget, &touchEvent) && touchEvent.isAccepted(); - returnValue = returnValue || (qt_tabletChokeMouse = res); + returnValue = returnValue || (qt_tabletChokeMouse = qt_tabletChokeMouse || res); break; } case QEvent::TouchEnd: @@ -4206,8 +4207,6 @@ bool QApplicationPrivate::translateTouchEvent(const MSG &msg) if (widget->testAttribute(Qt::WA_AcceptedTouchBeginEvent)) { (void) QApplication::sendSpontaneousEvent(widget, &touchEvent); qt_tabletChokeMouse = true; - } else { - qt_tabletChokeMouse = false; } returnValue = returnValue || qt_tabletChokeMouse; break; -- cgit v0.12 From 1283c8734b137d1d7cc7c88e5e120e14c45852d1 Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Fri, 8 May 2009 16:58:45 +0200 Subject: build the multitouch examples from the top-level build just needed to add multitouch to SUBDIRS in examples/examples.pro --- examples/examples.pro | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/examples.pro b/examples/examples.pro index 41501a0..2d49103 100644 --- a/examples/examples.pro +++ b/examples/examples.pro @@ -20,7 +20,8 @@ SUBDIRS = \ widgets \ uitools \ xml \ - script + script \ + multitouch contains(QT_CONFIG, phonon):!static: SUBDIRS += phonon contains(QT_CONFIG, webkit): SUBDIRS += webkit -- cgit v0.12 From 771e18e96d86f09bb047e5cf45cc33568e259a5d Mon Sep 17 00:00:00 2001 From: "Bradley T. Hughes" Date: Fri, 8 May 2009 17:13:09 +0200 Subject: by default, ignore touch events if the widget is disabled --- src/gui/kernel/qwidget.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index cbf9585..968a423 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -7525,6 +7525,9 @@ bool QWidget::event(QEvent *event) case QEvent::MouseButtonRelease: case QEvent::MouseButtonDblClick: case QEvent::MouseMove: + case QEvent::TouchBegin: + case QEvent::TouchUpdate: + case QEvent::TouchEnd: case QEvent::ContextMenu: #ifndef QT_NO_WHEELEVENT case QEvent::Wheel: -- cgit v0.12 From a3d8cfb1ee89e0600add864db53d67552820b95a Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Thu, 26 Feb 2009 15:39:00 +0100 Subject: Merge of the maemo-gestures branch onto qt/4.5.0 This is a squashed merge of all of the changes in the maemo-gestures branch on-top of the qt/4.5.0 branch. --- examples/gestures/gestures.pro | 11 + examples/gestures/graphicsview/graphicsview.pro | 2 + examples/gestures/graphicsview/main.cpp | 151 +++++++ examples/gestures/imageviewer/imageviewer.pro | 12 + examples/gestures/imageviewer/imagewidget.cpp | 338 +++++++++++++++ examples/gestures/imageviewer/imagewidget.h | 122 ++++++ examples/gestures/imageviewer/main.cpp | 88 ++++ src/corelib/global/qnamespace.h | 15 + src/corelib/kernel/qcoreevent.h | 2 + src/gui/graphicsview/qgraphicsitem.cpp | 28 ++ src/gui/graphicsview/qgraphicsitem.h | 3 + src/gui/graphicsview/qgraphicsitem_p.h | 2 + src/gui/graphicsview/qgraphicsscene.cpp | 62 +++ src/gui/graphicsview/qgraphicsscene.h | 2 + src/gui/graphicsview/qgraphicsscene_p.h | 9 + src/gui/graphicsview/qgraphicsview.cpp | 9 +- src/gui/kernel/kernel.pri | 14 +- src/gui/kernel/qapplication.cpp | 57 ++- src/gui/kernel/qapplication.h | 1 + src/gui/kernel/qapplication_p.h | 1 + src/gui/kernel/qapplication_x11.cpp | 2 +- src/gui/kernel/qdirectionrecognizer.cpp | 176 ++++++++ src/gui/kernel/qdirectionrecognizer_p.h | 121 ++++++ src/gui/kernel/qdirectionsimplificator_p.h | 172 ++++++++ src/gui/kernel/qevent.cpp | 24 ++ src/gui/kernel/qevent.h | 34 ++ src/gui/kernel/qgesture.cpp | 133 ++++++ src/gui/kernel/qgesture.h | 128 ++++++ src/gui/kernel/qgesture_p.h | 100 +++++ src/gui/kernel/qgesturemanager.cpp | 405 ++++++++++++++++++ src/gui/kernel/qgesturemanager_p.h | 102 +++++ src/gui/kernel/qgesturerecognizer.h | 83 ++++ src/gui/kernel/qgesturestandardrecognizers.cpp | 543 ++++++++++++++++++++++++ src/gui/kernel/qgesturestandardrecognizers_p.h | 169 ++++++++ src/gui/kernel/qwidget.cpp | 45 ++ src/gui/kernel/qwidget.h | 10 + src/gui/kernel/qwidget_p.h | 3 + src/gui/widgets/qabstractscrollarea.cpp | 1 + 38 files changed, 3174 insertions(+), 6 deletions(-) create mode 100644 examples/gestures/gestures.pro create mode 100644 examples/gestures/graphicsview/graphicsview.pro create mode 100644 examples/gestures/graphicsview/main.cpp create mode 100644 examples/gestures/imageviewer/imageviewer.pro create mode 100644 examples/gestures/imageviewer/imagewidget.cpp create mode 100644 examples/gestures/imageviewer/imagewidget.h create mode 100644 examples/gestures/imageviewer/main.cpp create mode 100644 src/gui/kernel/qdirectionrecognizer.cpp create mode 100644 src/gui/kernel/qdirectionrecognizer_p.h create mode 100644 src/gui/kernel/qdirectionsimplificator_p.h create mode 100644 src/gui/kernel/qgesture.cpp create mode 100644 src/gui/kernel/qgesture.h create mode 100644 src/gui/kernel/qgesture_p.h create mode 100644 src/gui/kernel/qgesturemanager.cpp create mode 100644 src/gui/kernel/qgesturemanager_p.h create mode 100644 src/gui/kernel/qgesturerecognizer.h create mode 100644 src/gui/kernel/qgesturestandardrecognizers.cpp create mode 100644 src/gui/kernel/qgesturestandardrecognizers_p.h diff --git a/examples/gestures/gestures.pro b/examples/gestures/gestures.pro new file mode 100644 index 0000000..1e0f1a7 --- /dev/null +++ b/examples/gestures/gestures.pro @@ -0,0 +1,11 @@ +TEMPLATE = \ + subdirs +SUBDIRS = \ + imageviewer \ + graphicsview + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/gestures +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS gestures.pro README +sources.path = $$[QT_INSTALL_EXAMPLES]/gestures +INSTALLS += target sources diff --git a/examples/gestures/graphicsview/graphicsview.pro b/examples/gestures/graphicsview/graphicsview.pro new file mode 100644 index 0000000..9cef564 --- /dev/null +++ b/examples/gestures/graphicsview/graphicsview.pro @@ -0,0 +1,2 @@ +SOURCES = main.cpp + diff --git a/examples/gestures/graphicsview/main.cpp b/examples/gestures/graphicsview/main.cpp new file mode 100644 index 0000000..a0236ef --- /dev/null +++ b/examples/gestures/graphicsview/main.cpp @@ -0,0 +1,151 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +class PannableGraphicsView : public QGraphicsView +{ +public: + PannableGraphicsView() + { + grabGesture(Qt::Pan); + } +protected: + bool event(QEvent *event) + { + if (event->type() == QEvent::Gesture) { + QGestureEvent *ge = static_cast(event); + if (const QGesture *g = ge->gesture(Qt::Pan)) { + QPoint pt = g->pos() - g->lastPos(); + horizontalScrollBar()->setValue(horizontalScrollBar()->value() - pt.x()); + verticalScrollBar()->setValue(verticalScrollBar()->value() - pt.y()); + event->accept(); + return true; + } + } + return QGraphicsView::event(event); + } +}; + +class ImageItem : public QGraphicsItem +{ +public: + ImageItem() + : colored(false) + { + grabGesture(Qt::DoubleTap); + } + + QRectF boundingRect() const + { + return pixmap.isNull() ? QRectF(0, 0, 100, 100) + : QRectF(QPointF(0,0), QSizeF(pixmap.size())); + } + + void paint(QPainter *painter, const QStyleOptionGraphicsItem*, QWidget*) + { + if (pixmap.isNull()) { + painter->setBrush(QBrush( colored ? Qt::green : Qt::white)); + painter->drawRect(0, 0, 100, 100); + painter->drawLine(0, 0, 100, 100); + painter->drawLine(0, 100, 100, 0); + return; + } + painter->drawPixmap(0, 0, pixmap); + } + + bool sceneEvent(QEvent *event) + { + if (event->type() == QEvent::Gesture) { + QGestureEvent *gestureEvent = static_cast(event); + if (gestureEvent->gesture(Qt::DoubleTap)) { + event->accept(); + colored = !colored; + update(); + return true; + } else { + qWarning("Item received unknown gesture"); + } + } + return QGraphicsItem::sceneEvent(event); + } + +private: + QPixmap pixmap; + bool colored; +}; + +class MainWidget : public QWidget +{ + Q_OBJECT + +public: + MainWidget(QWidget *parent = 0) + : QWidget(parent) + { + QVBoxLayout *l = new QVBoxLayout(this); + view = new PannableGraphicsView; + l->addWidget(view); + scene = new QGraphicsScene(0, 0, 1024, 768, view); + view->setScene(scene); + + ImageItem *item = new ImageItem; + scene->addItem(item); + item->setPos(scene->width()/3, scene->height()/3); + } + +signals: +public slots: +private: + QGraphicsView *view; + QGraphicsScene *scene; +}; + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + QApplication::setAttribute(Qt::AA_EnableGestures); + MainWidget w; + w.show(); + return app.exec(); +} + +#include "main.moc" diff --git a/examples/gestures/imageviewer/imageviewer.pro b/examples/gestures/imageviewer/imageviewer.pro new file mode 100644 index 0000000..4c35dce --- /dev/null +++ b/examples/gestures/imageviewer/imageviewer.pro @@ -0,0 +1,12 @@ +###################################################################### +# Automatically generated by qmake (2.01a) Thu Sep 11 17:18:17 2008 +###################################################################### + +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += . + +# Input +HEADERS += imagewidget.h +SOURCES += imagewidget.cpp main.cpp diff --git a/examples/gestures/imageviewer/imagewidget.cpp b/examples/gestures/imageviewer/imagewidget.cpp new file mode 100644 index 0000000..8932e29 --- /dev/null +++ b/examples/gestures/imageviewer/imagewidget.cpp @@ -0,0 +1,338 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "imagewidget.h" + +#include + +ImageWidget::ImageWidget(QWidget *parent) + : QWidget(parent) +{ + setAttribute(Qt::WA_PaintOnScreen); + setAttribute(Qt::WA_OpaquePaintEvent); + setAttribute(Qt::WA_NoSystemBackground); + + setObjectName("ImageWidget"); + + setMinimumSize(QSize(100,100)); + + position = 0; + zoomed = rotated = false; + + zoomedIn = false; + horizontalOffset = 0; + verticalOffset = 0; + + grabGesture(Qt::DoubleTap); + grabGesture(Qt::Pan); + grabGesture(Qt::LongTap); +} + +void ImageWidget::paintEvent(QPaintEvent*) +{ + QPainter p(this); + if (currentImage.isNull()) { + p.fillRect(geometry(), Qt::white); + return; + } + int hoffset = 0; + int voffset = 0; + const int w = pixmap.width(); + const int h = pixmap.height(); + p.save(); + if (zoomedIn) { + hoffset = horizontalOffset; + voffset = verticalOffset; + if (horizontalOffset > 0) + p.fillRect(0, 0, horizontalOffset, height(), Qt::white); + if (verticalOffset > 0) + p.fillRect(0, 0, width(), verticalOffset, Qt::white); + } + p.drawPixmap(hoffset, voffset, pixmap); + if (hoffset + w < width()) + p.fillRect(hoffset + w, 0, width() - w - hoffset, height(), Qt::white); + if (voffset + h < height()) + p.fillRect(0, voffset + h, width(), height() - h - voffset, Qt::white); + + // paint touch feedback + if (touchFeedback.tapped || touchFeedback.doubleTapped) { + p.setPen(QPen(Qt::gray, 2)); + p.drawEllipse(touchFeedback.position, 5, 5); + if (touchFeedback.doubleTapped) { + p.setPen(QPen(Qt::gray, 2, Qt::DotLine)); + p.drawEllipse(touchFeedback.position, 15, 15); + } else if (touchFeedback.tapAndHoldState != 0) { + QPoint pts[8] = { + touchFeedback.position + QPoint( 0, -15), + touchFeedback.position + QPoint( 10, -10), + touchFeedback.position + QPoint( 15, 0), + touchFeedback.position + QPoint( 10, 10), + touchFeedback.position + QPoint( 0, 15), + touchFeedback.position + QPoint(-10, 10), + touchFeedback.position + QPoint(-15, 0) + }; + for (int i = 0; i < (touchFeedback.tapAndHoldState-20)/10; ++i) + p.drawEllipse(pts[i], 3, 3); + } + } else if (touchFeedback.sliding) { + p.setPen(QPen(Qt::red, 3)); + QPoint endPos = QPoint(touchFeedback.position.x(), touchFeedback.slidingStartPosition.y()); + p.drawLine(touchFeedback.slidingStartPosition, endPos); + int dx = 10; + if (touchFeedback.slidingStartPosition.x() < endPos.x()) + dx = -1*dx; + p.drawLine(endPos, endPos + QPoint(dx, 5)); + p.drawLine(endPos, endPos + QPoint(dx, -5)); + } + + for (int i = 0; i < TouchFeedback::MaximumNumberOfTouches; ++i) { + if (touchFeedback.touches[i].isNull()) + break; + p.drawEllipse(touchFeedback.touches[i], 10, 10); + } + p.restore(); +} + +void ImageWidget::gestureEvent(QGestureEvent *event) +{ + touchFeedback.doubleTapped = false; + + Q_ASSERT(event); + if (event->contains(Qt::Tap)) { + // + } else if (const QGesture *g = event->gesture(Qt::DoubleTap)) { + touchFeedback.doubleTapped = true; + horizontalOffset = g->hotSpot().x() - currentImage.width()*1.0*g->hotSpot().x()/width(); + verticalOffset = g->hotSpot().y() - currentImage.height()*1.0*g->hotSpot().y()/height(); + setZoomedIn(!zoomedIn); + zoomed = rotated = false; + updateImage(); + } else if (const QGesture *g = event->gesture(Qt::Pan)) { + if (zoomedIn) { + // usual panning + if (g->state() == Qt::GestureStarted) + setCursor(Qt::SizeAllCursor); + else + setCursor(Qt::ArrowCursor); + const int dx = g->pos().x() - g->lastPos().x(); + const int dy = g->pos().y() - g->lastPos().y(); + horizontalOffset += dx; + verticalOffset += dy; + update(); + } else { + // only slide gesture should be accepted + const QPannableGesture *pg = dynamic_cast(g); + if (pg && pg->direction() != pg->lastDirection()) { + // ###: event->cancel(); + } + if (g->state() == Qt::GestureFinished) { + touchFeedback.sliding = false; + zoomed = rotated = false; + if (pg->direction() == QPannableGesture::Right) { + qDebug() << "slide right"; + goNextImage(); + } else if (pg->direction() == QPannableGesture::Left) { + qDebug() << "slide left"; + goPrevImage(); + } + updateImage(); + } + } + } else if (const QGesture *g = event->gesture(Qt::LongTap)) { + if (g->state() == Qt::GestureFinished) { + qDebug() << "tap and hold detected"; + touchFeedback.reset(); + update(); + + QMenu menu; + menu.addAction("Action 1"); + menu.addAction("Action 2"); + menu.addAction("Action 3"); + menu.exec(mapToGlobal(g->hotSpot())); + } + } else if (const QGesture *g = event->gesture(Qt::LongTap)) { + qDebug() << "long tap: " << (g->state() == Qt::GestureStarted ? "started" : "finished"); + } else { + qDebug() << "unknown gesture"; + } + feedbackFadeOutTimer.start(500, this); + event->accept(); +} + +void ImageWidget::resizeEvent(QResizeEvent*) +{ + updateImage(); +} + +void ImageWidget::updateImage() +{ + // should use qtconcurrent here? + transformation = QTransform(); + if (zoomedIn) { + } else { + if (currentImage.isNull()) + return; + if (zoomed) { + transformation = transformation.scale(zoom, zoom); + } else { + double xscale = (double)width()/currentImage.width(); + double yscale = (double)height()/currentImage.height(); + if (xscale < yscale) + yscale = xscale; + else + xscale = yscale; + transformation = transformation.scale(xscale, yscale); + } + if (rotated) + transformation = transformation.rotate(angle); + } + pixmap = QPixmap::fromImage(currentImage).transformed(transformation); + update(); +} + +void ImageWidget::openDirectory(const QString &path) +{ + this->path = path; + QDir dir(path); + QStringList nameFilters; + nameFilters << "*.jpg" << "*.png"; + files = dir.entryList(nameFilters, QDir::Files|QDir::Readable, QDir::Name); + + position = 0; + goToImage(0); + updateImage(); +} + +QImage ImageWidget::loadImage(const QString &fileName) +{ + QImageReader reader(fileName); + if (!reader.canRead()) { + qDebug() << fileName << ": can't load image"; + return QImage(); + } + QImage image; + if (!reader.read(&image)) { + qDebug() << fileName << ": corrupted image"; + return QImage(); + } + return image; +} + +void ImageWidget::setZoomedIn(bool zoomed) +{ + zoomedIn = zoomed; +} + +void ImageWidget::goNextImage() +{ + if (files.isEmpty()) + return; + if (position < files.size()-1) { + ++position; + prevImage = currentImage; + currentImage = nextImage; + if (position+1 < files.size()) + nextImage = loadImage(path+QLatin1String("/")+files.at(position+1)); + else + nextImage = QImage(); + } + setZoomedIn(false); + updateImage(); +} + +void ImageWidget::goPrevImage() +{ + if (files.isEmpty()) + return; + if (position > 0) { + --position; + nextImage = currentImage; + currentImage = prevImage; + if (position > 0) + prevImage = loadImage(path+QLatin1String("/")+files.at(position-1)); + else + prevImage = QImage(); + } + setZoomedIn(false); + updateImage(); +} + +void ImageWidget::goToImage(int index) +{ + if (files.isEmpty()) + return; + if (index < 0 || index >= files.size()) { + qDebug() << "goToImage: invalid index: " << index; + return; + } + if (index == position+1) { + goNextImage(); + return; + } + if (position > 0 && index == position-1) { + goPrevImage(); + return; + } + position = index; + pixmap = QPixmap(); + if (index > 0) + prevImage = loadImage(path+QLatin1String("/")+files.at(position-1)); + else + prevImage = QImage(); + currentImage = loadImage(path+QLatin1String("/")+files.at(position)); + if (position+1 < files.size()) + nextImage = loadImage(path+QLatin1String("/")+files.at(position+1)); + else + nextImage = QImage(); + setZoomedIn(false); + updateImage(); +} + +void ImageWidget::timerEvent(QTimerEvent *event) +{ + if (event->timerId() == touchFeedback.tapTimer.timerId()) { + touchFeedback.tapTimer.stop(); + } else if (event->timerId() == feedbackFadeOutTimer.timerId()) { + feedbackFadeOutTimer.stop(); + touchFeedback.reset(); + } + update(); +} diff --git a/examples/gestures/imageviewer/imagewidget.h b/examples/gestures/imageviewer/imagewidget.h new file mode 100644 index 0000000..56fcb40 --- /dev/null +++ b/examples/gestures/imageviewer/imagewidget.h @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef IMAGEWIDGET_H +#define IMAGEWIDGET_H + +#include +#include +#include + +#include + +class ImageWidget : public QWidget +{ +public: + ImageWidget(QWidget *parent = 0); + + void openDirectory(const QString &path); + +protected: + void paintEvent(QPaintEvent*); + void gestureEvent(QGestureEvent *event); + void resizeEvent(QResizeEvent*); + void timerEvent(QTimerEvent*); + +private: + void updateImage(); + QImage loadImage(const QString &fileName); + void loadImage(); + void setZoomedIn(bool zoomed); + void goNextImage(); + void goPrevImage(); + void goToImage(int index); + + QString path; + QStringList files; + int position; + + QImage prevImage, nextImage; + QImage currentImage; + QPixmap pixmap; + QTransform transformation; + + bool zoomedIn; + int horizontalOffset; + int verticalOffset; + + bool zoomed; + qreal zoom; + bool rotated; + qreal angle; + + struct TouchFeedback + { + bool tapped; + QPoint position; + bool sliding; + QPoint slidingStartPosition; + QBasicTimer tapTimer; + int tapState; + bool doubleTapped; + int tapAndHoldState; + + enum { MaximumNumberOfTouches = 5 }; + QPoint touches[MaximumNumberOfTouches]; + + inline TouchFeedback() { reset(); } + inline void reset() + { + tapped = false; + sliding = false; + tapTimer.stop(); + tapState = 0; + doubleTapped = false; + tapAndHoldState = 0; + for (int i = 0; i < MaximumNumberOfTouches; ++i) { + touches[i] = QPoint(); + } + } + } touchFeedback; + QBasicTimer feedbackFadeOutTimer; +}; + +#endif diff --git a/examples/gestures/imageviewer/main.cpp b/examples/gestures/imageviewer/main.cpp new file mode 100644 index 0000000..5494b12 --- /dev/null +++ b/examples/gestures/imageviewer/main.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "imagewidget.h" + +class MainWidget : public QMainWindow +{ + Q_OBJECT + +public: + MainWidget(QWidget *parent = 0); + +public slots: + void openDirectory(const QString &path); + +private: + bool loadImage(const QString &fileName); + + ImageWidget *imageWidget; +}; + +MainWidget::MainWidget(QWidget *parent) + : QMainWindow(parent) +{ + resize(400, 300); + imageWidget = new ImageWidget(this); + setCentralWidget(imageWidget); +} + +void MainWidget::openDirectory(const QString &path) +{ + imageWidget->openDirectory(path); +} + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + QApplication::setAttribute(Qt::AA_EnableGestures); + + MainWidget w; + w.show(); + + if (QApplication::arguments().size() > 1) + w.openDirectory(QApplication::arguments().at(1)); + return app.exec(); +} + +#include "main.moc" diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 1635f8a..5747c3c 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -1550,6 +1550,21 @@ public: TouchPointStationary, TouchPointReleased }; + + typedef QString GestureType; + static const char UnknownGesture[] = "???"; + static const char Tap[] = "Tap"; + static const char DoubleTap[] = "DoubleTap"; + static const char LongTap[] = "LongTap"; + static const char Pan[] = "Pan"; + static const char Pinch[] = "Pinch"; + + enum GestureState + { + GestureStarted = 0, + GestureFinished = 1 + }; + } #ifdef Q_MOC_RUN ; diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h index 42a75f8..c9f9f24 100644 --- a/src/corelib/kernel/qcoreevent.h +++ b/src/corelib/kernel/qcoreevent.h @@ -273,6 +273,8 @@ public: GraphicsSceneTouchUpdate = 197, GraphicsSceneTouchEnd = 198, + Gesture = 191, + // 512 reserved for Qt Jambi's MetaCall event // 513 reserved for Qt Jambi's DeleteOnMainThread event diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 3eef396..58f04f0 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -5788,6 +5788,20 @@ QVariant QGraphicsItem::inputMethodQuery(Qt::InputMethodQuery query) const return QVariant(); } +void QGraphicsItem::grabGesture(const Qt::GestureType &type) +{ + d_ptr->gestures.insert(type); + if (d_ptr->scene) + d_ptr->scene->d_func()->grabGesture(this, type); +} + +void QGraphicsItem::releaseGesture(const Qt::GestureType &type) +{ + d_ptr->gestures.remove(type); + if (d_ptr->scene) + d_ptr->scene->d_func()->releaseGesture(this, type); +} + /*! This virtual function is called by QGraphicsItem to notify custom items that some part of the item's state changes. By reimplementing this @@ -5812,6 +5826,20 @@ QVariant QGraphicsItem::inputMethodQuery(Qt::InputMethodQuery query) const QVariant QGraphicsItem::itemChange(GraphicsItemChange change, const QVariant &value) { Q_UNUSED(change); + if (change == QGraphicsItem::ItemSceneChange) { + if (!qVariantValue(value)) { + // the item has been removed from a scene, unsubscribe gestures. + Q_ASSERT(d_ptr->scene); + foreach(const Qt::GestureType &gesture, d_ptr->gestures) + d_ptr->scene->d_func()->releaseGesture(this, gesture); + } + } else if (change == QGraphicsItem::ItemSceneHasChanged) { + if (QGraphicsScene *scene = qVariantValue(value)) { + // item has been added to the scene + foreach(const Qt::GestureType &gesture, d_ptr->gestures) + scene->d_func()->grabGesture(this, gesture); + } + } return value; } diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index ec3373a..42a5110 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -338,6 +338,9 @@ public: QVariant data(int key) const; void setData(int key, const QVariant &value); + void grabGesture(const Qt::GestureType &type); + void releaseGesture(const Qt::GestureType &type); + enum { Type = 1, UserType = 65536 diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index 5e77dfd..a67a49a 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -54,6 +54,7 @@ // #include "qgraphicsitem.h" +#include "qset.h" #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW @@ -297,6 +298,7 @@ public: int siblingIndex; int index; int depth; + QSet gestures; // Packed 32 bytes quint32 acceptedMouseButtons : 5; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index f322305..fe6dde1 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -3950,6 +3950,9 @@ bool QGraphicsScene::event(QEvent *event) // geometries that do not have an explicit style set. update(); break; + case QEvent::Gesture: + gestureEvent(static_cast(event)); + break; case QEvent::GraphicsSceneTouchBegin: d->touchBeginEvent(static_cast(event)); break; @@ -5586,6 +5589,65 @@ void QGraphicsScene::setActiveWindow(QGraphicsWidget *widget) } } +void QGraphicsScenePrivate::addView(QGraphicsView *view) +{ + views << view; + foreach(const Qt::GestureType &gesture, grabbedGestures) + view->grabGesture(gesture); +} + +void QGraphicsScenePrivate::removeView(QGraphicsView *view) +{ + views.removeAll(view); + foreach(const Qt::GestureType &gesture, grabbedGestures) + view->releaseGesture(gesture); +} + +void QGraphicsScenePrivate::sendGestureEvent(QGraphicsItem *item, QGestureEvent *event) +{ + //### TODO: position translation + sendEvent(item, event); +} + +void QGraphicsScene::gestureEvent(QGestureEvent *event) +{ + Q_D(QGraphicsScene); + QList gestureTypes = event->gestureTypes(); + QList pts; + QGraphicsView *view = qobject_cast(event->targetWidget()); + if (!view) { + // something is wrong. + Q_ASSERT(view); + return; + } + foreach(const Qt::GestureType &type, gestureTypes) + pts << view->mapToScene(event->gesture(type)->hotSpot()); + foreach(QGraphicsItem *item, d->itemsWithGestures) { + for (int i = 0; i < pts.size(); ++i) { + if (item->contains(item->mapFromScene(pts.at(i)))) { + d->sendGestureEvent(item, event); + if (event->isAccepted()) + break; + } + } + } +} + +void QGraphicsScenePrivate::grabGesture(QGraphicsItem *item, const Qt::GestureType &type) +{ + if (!grabbedGestures.contains(type)) { + foreach(QGraphicsView *view, views) + view->grabGesture(type); + } + itemsWithGestures << item; + grabbedGestures << type; +} + +void QGraphicsScenePrivate::releaseGesture(QGraphicsItem *item, const Qt::GestureType &type) +{ + //### +} + // ### FIXME: the code for touch event support is mosly copied from // ### QGraphicsScenePrivate::mousePressEventHandler() and friends, need to // ### refactor to reduce code duplication diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h index 9802f87..4680455 100644 --- a/src/gui/graphicsview/qgraphicsscene.h +++ b/src/gui/graphicsview/qgraphicsscene.h @@ -50,6 +50,7 @@ #include #include #include +#include QT_BEGIN_HEADER @@ -254,6 +255,7 @@ protected: virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); virtual void wheelEvent(QGraphicsSceneWheelEvent *event); virtual void inputMethodEvent(QInputMethodEvent *event); + virtual void gestureEvent(QGestureEvent *event); virtual void drawBackground(QPainter *painter, const QRectF &rect); virtual void drawForeground(QPainter *painter, const QRectF &rect); diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index de39205..cea0553 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -182,6 +182,9 @@ public: void storeMouseButtonsForMouseGrabber(QGraphicsSceneMouseEvent *event); QList views; + void addView(QGraphicsView *view); + void removeView(QGraphicsView *view); + bool painterStateProtection; QMultiMap sceneEventFilters; @@ -264,6 +267,12 @@ public: void resolvePalette(); void updatePalette(const QPalette &palette); + QSet itemsWithGestures; + QSet grabbedGestures; + void grabGesture(QGraphicsItem *item, const Qt::GestureType &type); + void releaseGesture(QGraphicsItem *item, const Qt::GestureType &type); + void sendGestureEvent(QGraphicsItem *item, QGestureEvent *event); + mutable QVector sceneTransformCache; mutable QBitArray validTransforms; mutable QVector freeSceneTransformSlots; diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 1aaaab9..acce717 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -1690,7 +1690,7 @@ void QGraphicsView::setScene(QGraphicsScene *scene) this, SLOT(updateScene(QList))); disconnect(d->scene, SIGNAL(sceneRectChanged(QRectF)), this, SLOT(updateSceneRect(QRectF))); - d->scene->d_func()->views.removeAll(this); + d->scene->d_func()->removeView(this); } // Assign the new scene and update the contents (scrollbars, etc.)). @@ -1698,7 +1698,7 @@ void QGraphicsView::setScene(QGraphicsScene *scene) connect(d->scene, SIGNAL(sceneRectChanged(QRectF)), this, SLOT(updateSceneRect(QRectF))); d->updateSceneSlotReimplementedChecked = false; - d->scene->d_func()->views << this; + d->scene->d_func()->addView(this); d->recalculateContentSize(); d->lastCenterPoint = sceneRect().center(); d->keepLastCenterPoint = true; @@ -2860,6 +2860,11 @@ bool QGraphicsView::event(QEvent *event) } } break; + case QEvent::Gesture: + QApplication::sendEvent(d->scene, event); + if (event->isAccepted()) + return true; + break; default: break; } diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index a1b982a..b6ef6b2 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -41,7 +41,13 @@ HEADERS += \ kernel/qwidgetaction.h \ kernel/qwidgetaction_p.h \ kernel/qwindowdefs.h \ - kernel/qkeymapper_p.h + kernel/qkeymapper_p.h \ + kernel/qgesture.h \ + kernel/qgesturemanager_p.h \ + kernel/qgesturerecognizer.h \ + kernel/qgesturestandardrecognizers_p.h \ + kernel/qdirectionrecognizer_p.h \ + kernel/qdirectionsimplificator_p.h SOURCES += \ kernel/qaction.cpp \ @@ -70,7 +76,11 @@ SOURCES += \ kernel/qwhatsthis.cpp \ kernel/qwidget.cpp \ kernel/qwidgetaction.cpp \ - kernel/qkeymapper.cpp + kernel/qkeymapper.cpp \ + kernel/qgesture.cpp \ + kernel/qgesturemanager.cpp \ + kernel/qgesturestandardrecognizers.cpp \ + kernel/qdirectionrecognizer.cpp win32 { DEFINES += QT_NO_DIRECTDRAW diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 1f4e1fe..b39cbc3 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -90,6 +90,8 @@ #include "qapplication.h" +#include + #ifdef Q_WS_WINCE #include "qdatetime.h" #include "qguifunctions_wince.h" @@ -98,6 +100,8 @@ extern bool qt_wince_is_mobile(); //qguifunctions_wince.cpp extern bool qt_wince_is_pocket_pc(); //qguifunctions_wince.cpp #endif +#include "qdatetime.h" + //#define ALIEN_DEBUG static void initResources() @@ -133,6 +137,8 @@ int QApplicationPrivate::autoMaximizeThreshold = -1; bool QApplicationPrivate::autoSipEnabled = false; #endif +QGestureManager *gestureManager = 0; + QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, QApplication::Type type) : QCoreApplicationPrivate(argc, argv) { @@ -3700,6 +3706,27 @@ bool QApplication::notify(QObject *receiver, QEvent *e) QMouseEvent* mouse = static_cast(e); QPoint relpos = mouse->pos(); + if (QApplication::testAttribute(Qt::AA_EnableGestures)) { + if (!gestureManager) + gestureManager = new QGestureManager; + // if we are in gesture mode, we send all mouse events + // directly to gesture recognizer. + if (gestureManager->inGestureMode()) { + // ### should I send events through all application event filters? + if (gestureManager->filterEvent(e)) + return true; + } + if (w && (mouse->type() != QEvent::MouseMove || mouse->buttons() != 0)) { + // find the gesture target widget + QWidget *target = w; + while (target && target->gestures().isEmpty()) + target = target->parentWidget(); + if (target) { + gestureManager->setGestureTargetWidget(target); + res = gestureManager->filterEvent(e); + } + } + } if (e->spontaneous()) { if (e->type() == QEvent::MouseButtonPress) { QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, @@ -3993,6 +4020,35 @@ bool QApplication::notify(QObject *receiver, QEvent *e) } break; #endif + + case QEvent::Gesture: { + QWidget *w = static_cast(receiver); + QGestureEvent *g = static_cast(e); + bool eventAccepted = g->isAccepted(); + // Q_ASSERT(g->gesture() != 0); + // const QGesture &gesture = *g->gesture(); + QPoint relPos(0,0); + while (w) { + // QGesture qge(gesture.gestureType(), gesture.startPos()+relPos, gesture.lastPos()+relPos, + // gesture.currentPos()+relPos, gesture.direction(), gesture.rect().translated(relPos), + // gesture.hotSpot()+relPos, gesture.state(), gesture.startTime()); + // QGestureEvent ge(&qge, false); + // ### TODO: fix widget-relative positions in gesture event. + QGestureEvent ge = *g; + ge.m_targetWidget = w; + ge.spont = g->spontaneous(); + res = d->notify_helper(w, w == receiver ? g : &ge); + g->spont = false; + eventAccepted = (w == receiver ? g : &ge)->isAccepted(); + if (res && eventAccepted) + break; + if (w->isWindow()) + break; + relPos += w->pos(); + w = w->parentWidget(); + } + break; + } case QEvent::TouchBegin: // Note: TouchUpdate and TouchEnd events are sent to d->currentMultitouchWidget and never propagated { @@ -4000,7 +4056,6 @@ bool QApplication::notify(QObject *receiver, QEvent *e) QWidget *origin = widget; QTouchEvent *touchEvent = static_cast(e); bool eventAccepted = touchEvent->isAccepted(); - if (widget->testAttribute(Qt::WA_AcceptTouchEvents) && e->spontaneous()) { // give the widget focus if the focus policy allows it QApplicationPrivate::giveFocusAccordingToFocusPolicy(widget, diff --git a/src/gui/kernel/qapplication.h b/src/gui/kernel/qapplication.h index 2baf6dc..634226f 100644 --- a/src/gui/kernel/qapplication.h +++ b/src/gui/kernel/qapplication.h @@ -374,6 +374,7 @@ private: friend class QDirectPainter; friend class QDirectPainterPrivate; #endif + friend class QGestureManager; #if defined(Q_WS_WIN) friend QApplicationPrivate* getQApplicationPrivateInternal(); diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 1a2bad2..40e928d 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -428,6 +428,7 @@ public: void sendSyntheticEnterLeave(QWidget *widget); #endif + QMap grabbedGestures; static void updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent); #if defined(Q_WS_WIN) diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp index 90376b3..060e948 100644 --- a/src/gui/kernel/qapplication_x11.cpp +++ b/src/gui/kernel/qapplication_x11.cpp @@ -4414,7 +4414,6 @@ bool QETWidget::translateMouseEvent(const XEvent *event) QMouseEvent e(type, pos, globalPos, button, buttons, modifiers); QApplicationPrivate::sendMouseEvent(widget, &e, alienWidget, this, &qt_button_down, qt_last_mouse_receiver); - if (type == QEvent::MouseButtonPress && button == Qt::RightButton && (openPopupCount == oldOpenPopupCount)) { @@ -5022,6 +5021,7 @@ bool QETWidget::translatePropertyEvent(const XEvent *event) return true; } + // // Paint event translation // diff --git a/src/gui/kernel/qdirectionrecognizer.cpp b/src/gui/kernel/qdirectionrecognizer.cpp new file mode 100644 index 0000000..37b64e7 --- /dev/null +++ b/src/gui/kernel/qdirectionrecognizer.cpp @@ -0,0 +1,176 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdirectionrecognizer_p.h" + +#include + +QT_BEGIN_NAMESPACE + +static const int SIZE = 20; + +QDirectionSimpleRecognizer::QDirectionSimpleRecognizer() +{ +} + +Direction QDirectionSimpleRecognizer::addPosition(const QPoint &pos) +{ + if (!directions.isEmpty()) { + const QPoint tmp = pos - directions.back().point; + if (tmp.manhattanLength() < 5) + return Direction(); + } + if (lastPoint.isNull()) { + lastPoint = pos; + return Direction(); + } + int dx = pos.x() - lastPoint.x(); + int dy = pos.y() - lastPoint.y(); + Direction::DirectionType direction = Direction::None; + if (dx < 0) { + if (-1*dx >= SIZE/2) + direction = Direction::Left; + } else { + if (dx >= SIZE/2) + direction = Direction::Right; + } + if (dy < 0) { + if (-1*dy >= SIZE/2) + direction = Direction::Up; + } else { + if (dy >= SIZE/2) + direction = Direction::Down; + } + if (direction == Direction::None) + return Direction(); + + lastPoint = pos; + directions.push_back(Direction(direction, pos)); + return Direction(direction, pos); +} + + +DirectionList QDirectionSimpleRecognizer::getDirections() const +{ + return directions; +} + +void QDirectionSimpleRecognizer::reset() +{ + directions.clear(); + lastPoint = QPoint(); +} + + +/// QDirectionDiagonalRecognizer + +QDirectionDiagonalRecognizer::QDirectionDiagonalRecognizer() +{ +} + +Direction QDirectionDiagonalRecognizer::addPosition(const QPoint &pos) +{ + if (!directions.isEmpty()) { + const QPoint tmp = pos - directions.back().point; + if (tmp.manhattanLength() < 5) + return Direction(); + } + if (lastPoint.isNull()) { + lastPoint = pos; + return Direction(); + } + int dx = pos.x() - lastPoint.x(); + int dy = pos.y() - lastPoint.y(); + int distance = sqrt(static_cast(dx*dx + dy*dy)); + if (distance < SIZE/2) + return Direction(); + + Direction::DirectionType direction = Direction::None; + double angle = atan(1.0*qAbs(lastPoint.y() - pos.y())/qAbs(pos.x() - lastPoint.x())) * 180. / M_PI; + if (dx < 0 && dy <= 0) { + angle = 180 - angle; + } else if (dx <= 0 && dy > 0) { + angle += 180; + } else if (dx > 0 && dy > 0) { + angle = 360-angle; + } + if (angle < 0) + angle += 360; + if (angle <= 20) + direction = Direction::Right; + else if (angle <= 65) + direction = Direction::RightUp; + else if (angle <= 110) + direction = Direction::Up; + else if (angle <= 155) + direction = Direction::LeftUp; + else if (angle <= 200) + direction = Direction::Left; + else if (angle <= 245) + direction = Direction::LeftDown; + else if (angle <= 290) + direction = Direction::Down; + else if (angle <= 335) + direction = Direction::RightDown; + else + direction = Direction::Right; + + if (direction == Direction::None) + return Direction(); + + lastPoint = pos; + directions.push_back(Direction(direction, pos)); + return Direction(direction, pos); +} + + +DirectionList QDirectionDiagonalRecognizer::getDirections() const +{ + return directions; +} + +void QDirectionDiagonalRecognizer::reset() +{ + directions.clear(); + lastPoint = QPoint(); +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qdirectionrecognizer_p.h b/src/gui/kernel/qdirectionrecognizer_p.h new file mode 100644 index 0000000..6390990 --- /dev/null +++ b/src/gui/kernel/qdirectionrecognizer_p.h @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDIRECTIONRECOGNIZER_P_H +#define QDIRECTIONRECOGNIZER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qpoint.h" +#include "qlist.h" + +QT_BEGIN_NAMESPACE + +struct Direction +{ + enum DirectionType + { + None = 0, + LeftDown = 1, + DownLeft = LeftDown, + Down = 2, + RightDown = 3, + DownRight = RightDown, + Left = 4, + Right = 6, + LeftUp = 7, + UpLeft = LeftUp, + Up = 8, + RightUp = 9, + UpRight = RightUp + }; + DirectionType direction; + QPoint point; + + Direction(DirectionType dir, const QPoint &pt) + : direction(dir), point(pt) { } + Direction() + : direction(None) { } + + inline bool isEmpty() const { return direction == None; } + inline bool isNull() const { return direction == None; } +}; + +typedef QList DirectionList; + +class QDirectionSimpleRecognizer +{ +public: + QDirectionSimpleRecognizer(); + Direction addPosition(const QPoint &pos); + DirectionList getDirections() const; + void reset(); + +private: + QPoint lastPoint; + DirectionList directions; +}; + +class QDirectionDiagonalRecognizer +{ +public: + QDirectionDiagonalRecognizer(); + Direction addPosition(const QPoint &pos); + DirectionList getDirections() const; + void reset(); + +private: + QPoint lastPoint; + DirectionList directions; +}; + +QT_END_NAMESPACE + +#endif // QDIRECTIONRECOGNIZER_P_H diff --git a/src/gui/kernel/qdirectionsimplificator_p.h b/src/gui/kernel/qdirectionsimplificator_p.h new file mode 100644 index 0000000..7b71ca0 --- /dev/null +++ b/src/gui/kernel/qdirectionsimplificator_p.h @@ -0,0 +1,172 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDIRECTIONSIMPLIFICATOR_P_H +#define QDIRECTIONSIMPLIFICATOR_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "private/qdirectionrecognizer_p.h" + +QT_BEGIN_NAMESPACE + +class QDirectionSimplificator +{ +public: + QDirectionSimplificator(const DirectionList &dir); + + bool simplify(DirectionList *result); + +private: + DirectionList directions; + DirectionList lastResult; + enum State { + None, + Trim, // remove first and last element + AccidentalMoves, // 66866 => 6666 + ComplexAccidentalMoves, // 778788 => 777888 (swapping elements without changing direction) + ShortMoves, // (moves of length 1) + } state; + + struct SimplifyTrim + { + SimplifyTrim() : state(0) { } + bool operator()(DirectionList &directions) + { + if (state == 0) { + directions.removeFirst(); + state = 1; + } else if (state == 1) { + directions.removeLast(); + state = 2; + } else if (state == 2 && directions.size() >= 2) { + directions.removeFirst(); + directions.removeLast(); + state = 3; + } else { + return false; + } + return true; + } + int state; + }; + struct SimplifyAccidentalMoves + { + SimplifyAccidentalMoves() : state(0) { } + bool operator()(DirectionList &directions) + { + return false; + } + int state; + }; + struct SimplifyComplexAccidentalMoves + { + SimplifyComplexAccidentalMoves() : state(0) { } + bool operator()(DirectionList &directions) + { + return false; + } + int state; + }; + + SimplifyTrim trim; + SimplifyAccidentalMoves accidentalMoves; + SimplifyComplexAccidentalMoves complexAccidentalMoves; + //SimplifyShortMoves shortMoves; +}; + +QDirectionSimplificator::QDirectionSimplificator(const DirectionList &dir) + : directions(dir), state(None) +{ +} + +bool QDirectionSimplificator::simplify(DirectionList *result) +{ + if (directions.isEmpty() || !result) + return false; + *result = directions; + switch(state) { + case None: + state = Trim; + trim = SimplifyTrim(); + case Trim: + if (trim(*result)) + break; + *result = lastResult; + state = AccidentalMoves; + accidentalMoves = SimplifyAccidentalMoves(); + case AccidentalMoves: + if (accidentalMoves(*result)) + break; + *result = lastResult; + state = ComplexAccidentalMoves; + complexAccidentalMoves = SimplifyComplexAccidentalMoves(); + case ComplexAccidentalMoves: + if (complexAccidentalMoves(*result)) + break; + *result = lastResult; + // state = ShortMoves; + // shortMoves = SimplifyShortMoves(); + // case ShortMoves: + // if (shortMoves(*result)) + // break; + // state = None; + default: + return false; + } + lastResult = *result; + if (lastResult.isEmpty()) + return false; + return true; +} + +QT_END_NAMESPACE + +#endif // QDIRECTIONSIMPLIFICATOR_P_H diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index d571212..a7e1101 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -3310,6 +3310,9 @@ QDebug operator<<(QDebug dbg, const QEvent *e) { case QEvent::ChildRemoved: n = n ? n : "ChildRemoved"; dbg.nospace() << "QChildEvent(" << n << ", " << (static_cast(e))->child(); return dbg.space(); + case QEvent::Gesture: + n = "Gesture"; + break; default: dbg.nospace() << "QEvent(" << (const void *)e << ", type = " << e->type() << ')'; return dbg.space(); @@ -3506,6 +3509,27 @@ QMenubarUpdatedEvent::QMenubarUpdatedEvent(QMenuBar * const menuBar) #endif +QGestureEvent::QGestureEvent(QWidget *targetWidget, const QList &gestures, + const QSet &cancelledGestures) + : QEvent(QEvent::Gesture), m_targetWidget(targetWidget), + m_cancelledGestures(cancelledGestures) +{ + foreach(QGesture *r, gestures) + m_gestures.insert(r->gestureType(), QSharedPointer(r)); +} + +QGestureEvent::QGestureEvent(const QGestureEvent &event, const QPoint &offset) + : QEvent(QEvent::Gesture), m_targetWidget(event.m_targetWidget), + m_gestures(event.m_gestures), + m_cancelledGestures(event.m_cancelledGestures) +{ + //### use offset! +} + +QGestureEvent::~QGestureEvent() +{ +} + /*! \class QTouchEvent \brief The QTouchEvent class contains parameters that describe a touch event . diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index e9a1386..858e2ea 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -52,6 +52,10 @@ #include #include #include +#include +#include +#include +#include QT_BEGIN_HEADER @@ -710,6 +714,36 @@ private: }; #endif +class Q_GUI_EXPORT QGestureEvent : public QEvent +{ +public: + QGestureEvent(QWidget *targetWidget, const QList &gestures, + const QSet &cancelledGestures = QSet()); + // internal ctor + QGestureEvent(const QGestureEvent &gestures, const QPoint &offset); + ~QGestureEvent(); + + QWidget *targetWidget() const + { return m_targetWidget; } + + inline bool contains(const Qt::GestureType &gestureType) const + { return gesture(gestureType) != 0; } + inline QList gestureTypes() const + { return m_gestures.keys(); } + inline const QGesture* gesture(const Qt::GestureType &gestureType) const + { return m_gestures.value(gestureType, QSharedPointer()).data(); } + + inline QSet cancelledGestures() const + { return m_cancelledGestures; } + +protected: + QWidget *m_targetWidget; + QHash > m_gestures; + QSet m_cancelledGestures; + + friend class QApplication; +}; + #ifndef QT_NO_DEBUG_STREAM Q_GUI_EXPORT QDebug operator<<(QDebug, const QEvent *); #endif diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp new file mode 100644 index 0000000..fbabb8f --- /dev/null +++ b/src/gui/kernel/qgesture.cpp @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgesture.h" +#include + +QGesture::QGesture(const Qt::GestureType &type, Qt::GestureState state) + : d(new QGesturePrivate), gestureType_(type), gestureState_(state) +{ +} + +QGesture::QGesture(const Qt::GestureType &type, const QPoint &startPos, + const QPoint &lastPos, const QPoint &pos, const QRect &rect, + const QPoint &hotSpot, const QDateTime &startTime, + uint duration, Qt::GestureState state) + : d(new QGesturePrivate), gestureType_(type), gestureState_(state) +{ + d->init(startPos, lastPos, pos, rect, hotSpot, startTime, duration); +} + +QGesture::QGesture(QGesturePrivate &dd, const Qt::GestureType &type, + Qt::GestureState state) + : d(&dd), gestureType_(type), gestureState_(state) +{ +} + +QGesture::~QGesture() +{ + delete d; d = 0; +} + +QRect QGesture::rect() const +{ + return d->rect; +} + +QPoint QGesture::hotSpot() const +{ + return d->hotSpot; +} + +QDateTime QGesture::startTime() const +{ + return d->startTime; +} + +uint QGesture::duration() const +{ + return d->duration; +} + +QPoint QGesture::startPos() const +{ + return d->startPos; +} + +QPoint QGesture::lastPos() const +{ + return d->lastPos; +} + +QPoint QGesture::pos() const +{ + return d->pos; +} + +QPannableGesture::QPannableGesture(const Qt::GestureType &type, Qt::GestureState state) + : QGesture(*new QPannableGesturePrivate, type, state) +{ +} + +QPannableGesture::QPannableGesture(const Qt::GestureType &type, const QPoint &startPos, + const QPoint &lastPos, const QPoint &pos, const QRect &rect, + const QPoint &hotSpot, const QDateTime &startTime, + uint duration, Qt::GestureState state) + : QGesture(*new QPannableGesturePrivate, type, state) +{ + d->init(startPos, lastPos, pos, rect, hotSpot, startTime, duration); + ((QPannableGesturePrivate*)d)->lastDirection = QPannableGesture::None; + ((QPannableGesturePrivate*)d)->direction = QPannableGesture::None; +} + +QPannableGesture::~QPannableGesture() +{ +} + +QPannableGesture::DirectionType QPannableGesture::lastDirection() const +{ + return ((QPannableGesturePrivate*)d)->lastDirection; +} + +QPannableGesture::DirectionType QPannableGesture::direction() const +{ + return ((QPannableGesturePrivate*)d)->direction; +} diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h new file mode 100644 index 0000000..16a5704 --- /dev/null +++ b/src/gui/kernel/qgesture.h @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGESTURE_H +#define QGESTURE_H + +#include "qobject.h" +#include "qlist.h" +#include "qdatetime.h" +#include "qpoint.h" +#include "qrect.h" +#include "qsharedpointer.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QGesturePrivate; +class Q_GUI_EXPORT QGesture +{ +public: + explicit QGesture(const Qt::GestureType &type, Qt::GestureState state = Qt::GestureStarted); + QGesture(const Qt::GestureType &type, const QPoint &startPos, + const QPoint &lastPos, const QPoint &pos, const QRect &rect, + const QPoint &hotSpot, const QDateTime &startTime, + uint duration, Qt::GestureState state); + virtual ~QGesture(); + + inline Qt::GestureType gestureType() const { return gestureType_; } + inline Qt::GestureState state() const { return gestureState_; } + + QRect rect() const; + QPoint hotSpot() const; + QDateTime startTime() const; + uint duration() const; + + QPoint startPos() const; + QPoint lastPos() const; + QPoint pos() const; + +protected: + QGesture(QGesturePrivate &dd, const Qt::GestureType &type, Qt::GestureState state = Qt::GestureStarted); + QGesturePrivate *d; + +private: + Qt::GestureType gestureType_; + Qt::GestureState gestureState_; +}; + +class Q_GUI_EXPORT QPannableGesture : public QGesture +{ +public: + enum DirectionType + { + None = 0, + LeftDown = 1, + DownLeft = LeftDown, + Down = 2, + RightDown = 3, + DownRight = RightDown, + Left = 4, + Right = 6, + LeftUp = 7, + UpLeft = LeftUp, + Up = 8, + RightUp = 9, + UpRight = RightUp + }; + +public: + explicit QPannableGesture(const Qt::GestureType &type, Qt::GestureState state = Qt::GestureStarted); + QPannableGesture(const Qt::GestureType &type, const QPoint &startPos, + const QPoint &lastPos, const QPoint &pos, const QRect &rect, + const QPoint &hotSpot, const QDateTime &startTime, + uint duration, Qt::GestureState state); + ~QPannableGesture(); + + DirectionType lastDirection() const; + DirectionType direction() const; + + friend class QGestureRecognizerPan; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGESTURE_H diff --git a/src/gui/kernel/qgesture_p.h b/src/gui/kernel/qgesture_p.h new file mode 100644 index 0000000..745590b --- /dev/null +++ b/src/gui/kernel/qgesture_p.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGESTURE_P_H +#define QGESTURE_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 "qrect.h" +#include "qpoint.h" +#include "qdatetime.h" + +QT_BEGIN_NAMESPACE + +class QGesturePrivate +{ +public: + QGesturePrivate() + : duration(0) { } + + void init(const QPoint &startPos, const QPoint &lastPos, + const QPoint &pos, const QRect &rect, + const QPoint &hotSpot, const QDateTime &startTime, + uint duration) + { + this->rect = rect; + this->hotSpot = hotSpot; + this->startTime = startTime; + this->duration = duration; + this->startPos = startPos; + this->lastPos = lastPos; + this->pos = pos; + } + + QRect rect; + QPoint hotSpot; + QDateTime startTime; + uint duration; + QPoint startPos; + QPoint lastPos; + QPoint pos; +}; + +class QPannableGesturePrivate : public QGesturePrivate +{ +public: + QPannableGesture::DirectionType lastDirection; + QPannableGesture::DirectionType direction; +}; + +QT_END_NAMESPACE + +#endif // QGESTURE_P_H diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp new file mode 100644 index 0000000..c244a0b --- /dev/null +++ b/src/gui/kernel/qgesturemanager.cpp @@ -0,0 +1,405 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgesturemanager_p.h" +#include "qgesture.h" +#include "qevent.h" + +#include "qapplication.h" +#include "private/qapplication_p.h" + +#include "private/qgesturestandardrecognizers_p.h" + +#include "qdebug.h" + +// #define GESTURE_DEBUG +#ifndef GESTURE_DEBUG +# define DEBUG if (0) qDebug +#else +# define DEBUG qDebug +#endif + +QT_BEGIN_NAMESPACE + +bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); +static bool qt_sendGestureEvent(QWidget *receiver, QGestureEvent *event) +{ + QSet eventGestures = event->gestureTypes().toSet(); + while (receiver && (receiver->gestures() & eventGestures).isEmpty()) + receiver = receiver->parentWidget(); + return receiver ? qt_sendSpontaneousEvent(receiver, event) : false; +} + +static const unsigned int maximumGestureRecognitionTimeout = 2000; + +QGestureManager::QGestureManager() + : targetWidget(0), state(NotGesture) +{ + recognizers << new QDoubleTapGestureRecognizer(); + recognizers << new QLongTapGestureRecognizer(); + recognizers << new QGestureRecognizerPan(); + // recognizers << new QMultiTouchGestureRecognizer(); + + foreach(QGestureRecognizer *r, recognizers) + connect(r, SIGNAL(triggered(QGestureRecognizer::Result)), + this, SLOT(recognizerTriggered(QGestureRecognizer::Result))); +} + +bool QGestureManager::filterEvent(QEvent *event) +{ + if (!QApplication::testAttribute(Qt::AA_EnableGestures)) + return false; + + QList events; + events << event; + + QPoint currentPos; + switch (event->type()) { + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::MouseMove: + currentPos = static_cast(event)->pos(); break; + default: break; + } + + const QMap &grabbedGestures = qApp->d_func()->grabbedGestures; + + bool ret = false; + QSet startedGestures; + QSet finishedGestures; + QSet newMaybeGestures; + QSet cancelledGestures; + QSet notGestures; + if (state == NotGesture || state == MaybeGesture) { + DEBUG() << "QGestureManager: current event processing state: " + << (state == NotGesture ? "NotGesture" : "MaybeGesture"); + + Q_ASSERT(targetWidget != 0); + QSet stillMaybeGestures; + // try other recognizers. + foreach(QGestureRecognizer *r, recognizers) { + if (grabbedGestures.value(r->gestureType(), 0) <= 0) + continue; + QGestureRecognizer::Result result = r->recognize(events); + if (result == QGestureRecognizer::GestureStarted) { + DEBUG() << "QGestureManager: gesture started: " << r; + startedGestures << r; + } else if (result == QGestureRecognizer::GestureFinished) { + DEBUG() << "QGestureManager: gesture finished: " << r; + finishedGestures << r; + } else if (result == QGestureRecognizer::MaybeGesture) { + DEBUG() << "QGestureManager: maybe gesture: " << r; + newMaybeGestures << r; + } else { + // if it was maybe gesture, but isn't a gesture anymore. + DEBUG() << "QGestureManager: not gesture: " << r; + notGestures << r; + } + } + activeGestures -= newMaybeGestures; + activeGestures += startedGestures; + foreach(QGestureRecognizer *r, startedGestures+notGestures) { + QMap::iterator it = maybeGestures.find(r); + if (it != maybeGestures.end()) { + killTimer(it.value()); + maybeGestures.erase(it); + } + } + foreach(QGestureRecognizer *r, newMaybeGestures) { + if (!maybeGestures.contains(r)) { + int timerId = startTimer(maximumGestureRecognitionTimeout); + if (!timerId) + qWarning("QGestureManager: couldn't start timer!"); + maybeGestures.insert(r, timerId); + } + } + if (!finishedGestures.isEmpty() || !activeGestures.isEmpty()) { + // gesture found! + ret = true; + DEBUG() << "QGestureManager: sending gesture event for: " + << activeGestures << " and " << finishedGestures; + + QList gestures; + foreach(QGestureRecognizer *r, finishedGestures) { + if (QGesture *gesture = r->makeEvent()) + gestures << gesture; + } + foreach(QGestureRecognizer *r, activeGestures) { + if (QGesture *gesture = r->makeEvent()) + gestures << gesture; + } + Q_ASSERT(!gestures.isEmpty()); + QGestureEvent event(targetWidget, gestures); + qt_sendGestureEvent(targetWidget, &event); + + if (!activeGestures.isEmpty()) { + DEBUG() << "QGestureManager: new state = Gesture"; + state = Gesture; + } else if (!maybeGestures.isEmpty()) { + DEBUG() << "QGestureManager: new state = Maybe"; + state = MaybeGesture; + } else { + DEBUG() << "QGestureManager: new state = NotGesture"; + state = NotGesture; + } + } else if (!maybeGestures.isEmpty()) { + if (state != MaybeGesture) { + // We got a new set of events that look like a start + // of some gesture, so we switch to state MaybeGesture + // and wait for more events. + DEBUG() << "QGestureManager: new state = Maybe. Waiting for events"; + state = MaybeGesture; + // start gesture timer + } else { + // we still not sure if it is a gesture or not. + } + } else if (state == MaybeGesture) { + // last time we thought it looks like gesture, but now we + // know for sure that it isn't. + DEBUG() << "QGestureManager: new state = NotGesture"; + state = NotGesture; + } + foreach(QGestureRecognizer *r, finishedGestures) + r->reset(); + foreach(QGestureRecognizer *r, cancelledGestures) + r->reset(); + foreach(QGestureRecognizer *r, notGestures) + r->reset(); + } else if (state == Gesture) { + DEBUG() << "QGestureManager: current event processing state: Gesture"; + Q_ASSERT(!activeGestures.isEmpty()); + + foreach(QGestureRecognizer *r, recognizers) { + if (grabbedGestures.value(r->gestureType(), 0) <= 0) + continue; + QGestureRecognizer::Result result = r->recognize(events); + if (result == QGestureRecognizer::GestureStarted) { + DEBUG() << "QGestureManager: gesture started: " << r; + startedGestures << r; + } else if (result == QGestureRecognizer::GestureFinished) { + DEBUG() << "QGestureManager: gesture finished: " << r; + finishedGestures << r; + } else if (result == QGestureRecognizer::MaybeGesture) { + DEBUG() << "QGestureManager: maybe gesture: " << r; + newMaybeGestures << r; + } else { + // if it was an active gesture, but isn't a gesture anymore. + if (activeGestures.contains(r)) { + DEBUG() << "QGestureManager: cancelled gesture: " << r; + cancelledGestures << r; + } else { + DEBUG() << "QGestureManager: not gesture: " << r; + notGestures << r; + } + } + } + + activeGestures -= newMaybeGestures; + activeGestures -= cancelledGestures; + activeGestures -= finishedGestures; + activeGestures += startedGestures; + foreach(QGestureRecognizer *r, startedGestures+finishedGestures+notGestures) { + QMap::iterator it = maybeGestures.find(r); + if (it != maybeGestures.end()) { + killTimer(it.value()); + maybeGestures.erase(it); + } + } + foreach(QGestureRecognizer *r, newMaybeGestures) { + if (!maybeGestures.contains(r)) { + int timerId = startTimer(maximumGestureRecognitionTimeout); + if (!timerId) + qWarning("QGestureManager: couldn't start timer!"); + maybeGestures.insert(r, timerId); + } + } + QList gestures; + if (!finishedGestures.isEmpty() || !activeGestures.isEmpty()) { + // another gesture found! + ret = true; + DEBUG() << "QGestureManager: sending gesture event for: " + << activeGestures << " and " << finishedGestures; + + foreach(QGestureRecognizer *r, finishedGestures) { + if (QGesture *gesture = r->makeEvent()) + gestures << gesture; + } + foreach(QGestureRecognizer *r, activeGestures) { + if (QGesture *gesture = r->makeEvent()) + gestures << gesture; + } + } + QSet cancelledGestureNames; + foreach(QGestureRecognizer *r, cancelledGestures) + cancelledGestureNames << r->gestureType(); + if(!gestures.isEmpty()) { + QGestureEvent event(targetWidget, gestures, cancelledGestureNames); + qt_sendGestureEvent(targetWidget, &event); + } + + foreach(QGestureRecognizer *r, finishedGestures) + r->reset(); + foreach(QGestureRecognizer *r, cancelledGestures) + r->reset(); + foreach(QGestureRecognizer *r, notGestures) + r->reset(); + if (!activeGestures.isEmpty()) { + // nothing changed, we are still handling a gesture + } else if (!maybeGestures.isEmpty()) { + DEBUG() << "QGestureManager: new state = Maybe. Waiting for events: " << maybeGestures; + state = MaybeGesture; + } else { + DEBUG() << "QGestureManager: new state = NotGesture"; + state = NotGesture; + } + ret = true; + } + + lastPos = currentPos; + return ret; +} + +void QGestureManager::timerEvent(QTimerEvent *event) +{ + // sanity checks, remove later + Q_ASSERT((state == Gesture && !activeGestures.isEmpty()) || (state != Gesture && activeGestures.isEmpty())); + + typedef QMap MaybeGestureMap; + for (MaybeGestureMap::iterator it = maybeGestures.begin(), e = maybeGestures.end(); + it != e; ++it) { + if (it.value() == event->timerId()) { + DEBUG() << "QGestureManager: gesture timeout."; + QGestureRecognizer *r = it.key(); + r->reset(); + maybeGestures.erase(it); + killTimer(event->timerId()); + break; + } + } + + if (state == MaybeGesture && maybeGestures.isEmpty()) { + DEBUG() << "QGestureManager: new state = NotGesture because of timeout"; + state = NotGesture; + } +} + +bool QGestureManager::inGestureMode() +{ + return state == Gesture; +} + +void QGestureManager::setGestureTargetWidget(QWidget *widget) +{ + targetWidget = widget; +} + +void QGestureManager::recognizerTriggered(QGestureRecognizer::Result result) +{ + if (!QApplication::testAttribute(Qt::AA_EnableGestures)) + return; + + QGestureRecognizer *recognizer = qobject_cast(sender()); + if (!recognizer) + return; + if (qApp->d_func()->grabbedGestures.value(recognizer->gestureType(), 0) <= 0) { + recognizer->reset(); + return; + } + + switch (result) { + case QGestureRecognizer::GestureStarted: + case QGestureRecognizer::GestureFinished: { + if (result == QGestureRecognizer::GestureStarted) { + DEBUG() << "QGestureManager: gesture started: " << recognizer; + activeGestures << recognizer; + DEBUG() << "QGestureManager: new state = Gesture"; + state = Gesture; + } else { + DEBUG() << "QGestureManager: gesture finished: " << recognizer; + } + if (maybeGestures.contains(recognizer)) { + killTimer(maybeGestures.value(recognizer)); + maybeGestures.remove(recognizer); + } + QList gestures; + if (QGesture *gesture = recognizer->makeEvent()) + gestures << gesture; + if(!gestures.isEmpty()) { + QGestureEvent event(targetWidget, gestures); + qt_sendGestureEvent(targetWidget, &event); + } + if (result == QGestureRecognizer::GestureFinished) + recognizer->reset(); + } + break; + case QGestureRecognizer::MaybeGesture: { + DEBUG() << "QGestureManager: maybe gesture: " << recognizer; + if (activeGestures.contains(recognizer)) { + QGestureEvent event(targetWidget, QList(), + QSet() << recognizer->gestureType()); + qt_sendGestureEvent(targetWidget, &event); + } + if (!maybeGestures.contains(recognizer)) { + int timerId = startTimer(maximumGestureRecognitionTimeout); + if (!timerId) + qWarning("QGestureManager: couldn't start timer!"); + maybeGestures.insert(recognizer, timerId); + } + } + break; + case QGestureRecognizer::NotGesture: + DEBUG() << "QGestureManager: not gesture: " << recognizer; + if (maybeGestures.contains(recognizer)) { + killTimer(maybeGestures.value(recognizer)); + maybeGestures.remove(recognizer); + } + recognizer->reset(); + break; + default: + Q_ASSERT(false); + } +} + +QT_END_NAMESPACE + +#include "moc_qgesturemanager_p.cpp" + diff --git a/src/gui/kernel/qgesturemanager_p.h b/src/gui/kernel/qgesturemanager_p.h new file mode 100644 index 0000000..9853f1a --- /dev/null +++ b/src/gui/kernel/qgesturemanager_p.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGESTUREMANAGER_P_H +#define QGESTUREMANAGER_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 "qlist.h" +#include "qset.h" +#include "qevent.h" +#include "qbasictimer.h" + +#include "qgesturerecognizer.h" + +QT_BEGIN_NAMESPACE + +class Q_GUI_EXPORT QGestureManager : public QObject +{ + Q_OBJECT +public: + QGestureManager(); + + // should be internal + void setGestureTargetWidget(QWidget *widget); + + bool filterEvent(QEvent *event); + bool inGestureMode(); + +protected: + void timerEvent(QTimerEvent *event); + +private slots: + void recognizerTriggered(QGestureRecognizer::Result); + +private: + QSet activeGestures; + QMap maybeGestures; + QSet recognizers; + + QWidget *targetWidget; + QPoint lastPos; + + enum State { + Gesture, + NotGesture, + MaybeGesture // that mean timers are up and waiting for some + // more events, and input events are handled by + // gesture recognizer explicitely + } state; +}; + +QT_END_NAMESPACE + +#endif // QGESTUREMANAGER_P_H diff --git a/src/gui/kernel/qgesturerecognizer.h b/src/gui/kernel/qgesturerecognizer.h new file mode 100644 index 0000000..3ed96c0 --- /dev/null +++ b/src/gui/kernel/qgesturerecognizer.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGESTURERECOGNIZER_H +#define QGESTURERECOGNIZER_H + +#include "qgesture.h" +#include "qevent.h" +#include "qlist.h" +#include "qset.h" + +QT_BEGIN_NAMESPACE + +class QGestureRecognizer : public QObject +{ + Q_OBJECT +public: + enum Result + { + NotGesture, + GestureStarted, + GestureFinished, + MaybeGesture + }; + + inline QGestureRecognizer() { } + //### remove this ctor + inline QGestureRecognizer(const char *type) : type_(QLatin1String(type)) { } + inline QGestureRecognizer(const Qt::GestureType &type) : type_(type) { } + inline Qt::GestureType gestureType() const { return type_; } + + virtual Result recognize(const QList &inputEvents) = 0; + virtual QGesture* makeEvent() const = 0; + virtual void reset() = 0; + +signals: + void triggered(QGestureRecognizer::Result result); + +protected: + Qt::GestureType type_; +}; + +QT_END_NAMESPACE + +#endif // QGESTURERECOGNIZER_P_H diff --git a/src/gui/kernel/qgesturestandardrecognizers.cpp b/src/gui/kernel/qgesturestandardrecognizers.cpp new file mode 100644 index 0000000..3a2fa1d --- /dev/null +++ b/src/gui/kernel/qgesturestandardrecognizers.cpp @@ -0,0 +1,543 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgesturestandardrecognizers_p.h" +#include "qgesture_p.h" + +// #define GESTURE_RECOGNIZER_DEBUG +#ifndef GESTURE_RECOGNIZER_DEBUG +# define DEBUG if (0) qDebug +#else +# define DEBUG qDebug +#endif + +QT_BEGIN_NAMESPACE +/* +QGestureRecognizerMouseTwoButtons::QGestureRecognizerMouseTwoButtons() + : QGestureRecognizer(Qt::MouseTwoButtonClick) +{ + clear(); +} + +QGestureRecognizer::Result QGestureRecognizerMouseTwoButtons::recognize(const QList &inputEvents) +{ + // get all mouse events + QList events; + for(int i = 0; i < inputEvents.count(); ++i) { + QEvent *event = inputEvents.at(i); + switch (event->type()) { + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + events.push_back(static_cast(event)); + default: + break; + } + } + + QGestureRecognizer::Result result = QGestureRecognizer::NotGesture; + for(int i = 0; i < events.count(); ++i) { + QMouseEvent *event = events.at(i); + if (event->type() == QEvent::MouseButtonPress) { + if (userEvents[3]) { + // something wrong, we already has a gesture. + clear(); + } else if (userEvents[2]) { + // 1d, 2d, 1u, and user press another button. not gesture. + DEBUG() << "1"; + result = QGestureRecognizer::NotGesture; + clear(); + break; + } else if (userEvents[1]) { + // 1d, 2d, and user pressed third button. not gesture. + DEBUG() << "2"; + result = QGestureRecognizer::NotGesture; + clear(); + break; + } else if (userEvents[0]) { + // second button press. + DEBUG() << "3"; + userEvents[1] = event; + result = QGestureRecognizer::MaybeGesture; + } else { + // first button press. + DEBUG() << "4"; + userEvents[0] = event; + result = QGestureRecognizer::MaybeGesture; + } + } else if (event->type() == QEvent::MouseButtonRelease) { + if (userEvents[3]) { + // something wrong, we already has a gesture. + clear(); + } else if (userEvents[2]) { + // 1d, 2d, 1u, and button release + DEBUG() << "5"; + if (userEvents[1]->button() != event->button()) { + // got weird buttonreleased event. doesn't look like gesture. + result = QGestureRecognizer::NotGesture; + clear(); + break; + } + // gesture! + userEvents[3] = event; + result = QGestureRecognizer::GestureFinished; + break; + } else if (userEvents[1]) { + // 1d, 2d, and button release + DEBUG() << "6"; + if (userEvents[0]->button() != event->button()) { + // user released the wrong button. not gesture. + result = QGestureRecognizer::NotGesture; + clear(); + break; + } + // user released the right button! looks like gesture + userEvents[2] = event; + result = QGestureRecognizer::MaybeGesture; + } else if (userEvents[0]) { + // 1d, and some button was released. not a gesture. + DEBUG() << "7"; + result = QGestureRecognizer::NotGesture; + clear(); + break; + } + } + } + return result; +} + +QGesture* QGestureRecognizerMouseTwoButtons::makeEvent() const +{ + if (!userEvents[0] || !userEvents[1] || !userEvents[2] || !userEvents[3]) + return 0; + QGesture::Direction direction = + (userEvents[0]->button() < userEvents[1]->button() ? + QGesture::Left : QGesture::Right); + QList points; + points.push_back(userEvents[0]->globalPos()); + points.push_back(userEvents[1]->globalPos()); + QGesture *gesture = + new QGesture(Qt::MouseTwoButtonClick, points.at(0), points.at(1), points.at(1), + direction, + QRect(points.at(0), points.at(1)), + points.at(0)); + return gesture; +} + +void QGestureRecognizerMouseTwoButtons::reset() +{ + clear(); +} + +void QGestureRecognizerMouseTwoButtons::clear() +{ + userEvents[0] = userEvents[1] = userEvents[2] = userEvents[3] = 0; +} +*/ + +// +// QGestureRecognizerPan +// + +QGestureRecognizerPan::QGestureRecognizerPan() + : QGestureRecognizer(Qt::Pan), mousePressed(false), gestureFinished(false), + lastDirection(Direction::None) +{ +} + +QGestureRecognizer::Result QGestureRecognizerPan::recognize(const QList &inputEvents) +{ + // get all mouse events + QList events; + for(int i = 0; i < inputEvents.count(); ++i) { + QEvent *event = inputEvents.at(i); + switch (event->type()) { + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseMove: + events.push_back(static_cast(event)); + default: + break; + } + } + + QGestureRecognizer::Result result = QGestureRecognizer::NotGesture; + for(int i = 0; i < events.count(); ++i) { + QMouseEvent *event = events.at(i); + if (event->type() == QEvent::MouseButtonPress) { + if (lastDirection != Direction::None) { + DEBUG() << "Pan: MouseButtonPress: fail. another press during pan"; + result = QGestureRecognizer::NotGesture; + reset(); + break; + } + DEBUG() << "Pan: MouseButtonPress: maybe gesture started"; + result = QGestureRecognizer::MaybeGesture; + mousePressed = true; + pressedPos = lastPos = currentPos = event->pos(); + } else if (event->type() == QEvent::MouseButtonRelease) { + if (mousePressed && lastDirection != Direction::None) { + DEBUG() << "Pan: MouseButtonRelease: pan detected"; + result = QGestureRecognizer::GestureFinished; + gestureFinished = true; + currentPos = event->pos(); + internalReset(); + break; + } + DEBUG() << "Pan: MouseButtonRelease: some weird release detected, ignoring"; + result = QGestureRecognizer::NotGesture; + reset(); + break; + } else if (event->type() == QEvent::MouseMove) { + if (!mousePressed) + continue; + lastPos = currentPos; + currentPos = event->pos(); + Direction::DirectionType direction = + simpleRecognizer.addPosition(event->pos()).direction; + DEBUG() << "Pan: MouseMove: simplerecognizer result = " << direction; + if (lastDirection == Direction::None) { + if (direction == Direction::None) + result = QGestureRecognizer::MaybeGesture; + else + result = QGestureRecognizer::GestureStarted; + } else { + result = QGestureRecognizer::GestureStarted; + } + if (direction != Direction::None) + lastDirection = direction; + } + } + return result; +} + +QGesture* QGestureRecognizerPan::makeEvent() const +{ + QPannableGesture::DirectionType dir = QPannableGesture::None; + if (lastDirection == Direction::Left) + dir = QPannableGesture::Left; + else if (lastDirection == Direction::Right) + dir = QPannableGesture::Right; + else if (lastDirection == Direction::Up) + dir = QPannableGesture::Up; + else if (lastDirection == Direction::Down) + dir = QPannableGesture::Down; + else + return 0; + QPannableGesture *g = + new QPannableGesture(Qt::Pan, pressedPos, lastPos, currentPos, + QRect(), pressedPos, QDateTime(), 0, + gestureFinished ? Qt::GestureFinished : Qt::GestureStarted); + QPannableGesturePrivate *d = (QPannableGesturePrivate*)g->d; + d->lastDirection = dir; ///### + d->direction = dir; + + return g; +} + +void QGestureRecognizerPan::reset() +{ + mousePressed = false; + lastDirection = Direction::None; + gestureFinished = false; + diagonalRecognizer.reset(); + simpleRecognizer.reset(); +} + +void QGestureRecognizerPan::internalReset() +{ + mousePressed = false; + diagonalRecognizer.reset(); + simpleRecognizer.reset(); +} + + +// +// QDoubleTapGestureRecognizer +// +QDoubleTapGestureRecognizer::QDoubleTapGestureRecognizer() + : QGestureRecognizer(Qt::DoubleTap) +{ +} + +QGestureRecognizer::Result QDoubleTapGestureRecognizer::recognize(const QList &inputEvents) +{ + // get all mouse events + QList events; + for(int i = 0; i < inputEvents.count(); ++i) { + QEvent *event = inputEvents.at(i); + switch (event->type()) { + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::MouseMove: + events.push_back(static_cast(event)); + default: + break; + } + } + + QGestureRecognizer::Result result = QGestureRecognizer::NotGesture; + for(int i = 0; i < events.count(); ++i) { + QMouseEvent *event = events.at(i); + if (event->type() == QEvent::MouseButtonPress) { + if (pressedPosition.isNull()) { + result = QGestureRecognizer::MaybeGesture; + pressedPosition = event->pos(); + } else if ((pressedPosition - event->pos()).manhattanLength() < 10) { + result = QGestureRecognizer::GestureFinished; + } + } else if (event->type() == QEvent::MouseButtonRelease) { + if (!pressedPosition.isNull() && (pressedPosition - event->pos()).manhattanLength() < 10) + result = QGestureRecognizer::MaybeGesture; + } else if (event->type() == QEvent::MouseButtonDblClick) { + result = QGestureRecognizer::GestureFinished; + pressedPosition = event->pos(); + break; + } + } + return result; +} + +QGesture* QDoubleTapGestureRecognizer::makeEvent() const +{ + return new QGesture(Qt::DoubleTap, + pressedPosition, pressedPosition, pressedPosition, + QRect(), pressedPosition, QDateTime(), 0, Qt::GestureFinished); +} + +void QDoubleTapGestureRecognizer::reset() +{ + pressedPosition = QPoint(); +} + +// +// QLongTapGestureRecognizer +// +const int QLongTapGestureRecognizer::iterationCount = 40; +const int QLongTapGestureRecognizer::iterationTimeout = 50; + +QLongTapGestureRecognizer::QLongTapGestureRecognizer() + : QGestureRecognizer(Qt::LongTap), iteration(0) +{ +} + +QGestureRecognizer::Result QLongTapGestureRecognizer::recognize(const QList &inputEvents) +{ + // get all mouse events + QList events; + for(int i = 0; i < inputEvents.count(); ++i) { + QEvent *event = inputEvents.at(i); + switch (event->type()) { + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseMove: + events.push_back(static_cast(event)); + default: + break; + } + } + + QGestureRecognizer::Result result = QGestureRecognizer::NotGesture; + for(int i = 0; i < events.count(); ++i) { + QMouseEvent *event = events.at(i); + if (event->type() == QEvent::MouseButtonPress) { + if (timer.isActive()) + timer.stop(); + timer.start(QLongTapGestureRecognizer::iterationTimeout, this); + pressedPosition = event->pos(); + result = QGestureRecognizer::MaybeGesture; + } else if (event->type() == QEvent::MouseMove) { + if ((pressedPosition - event->pos()).manhattanLength() < 15) + result = QGestureRecognizer::GestureStarted; + else + result = QGestureRecognizer::NotGesture; + } else if (event->type() == QEvent::MouseButtonRelease) { + result = QGestureRecognizer::NotGesture; + timer.stop(); + break; + } + } + return result; +} + +void QLongTapGestureRecognizer::timerEvent(QTimerEvent *event) +{ + if (event->timerId() != timer.timerId()) + return; + if (++iteration == QLongTapGestureRecognizer::iterationCount) { + emit triggered(QGestureRecognizer::GestureFinished); + timer.stop(); + } else { + emit triggered(QGestureRecognizer::GestureStarted); + } +} + +QGesture* QLongTapGestureRecognizer::makeEvent() const +{ + return new QGesture(Qt::LongTap, + pressedPosition, pressedPosition, pressedPosition, + QRect(), pressedPosition, QDateTime(), 0, + iteration >= QLongTapGestureRecognizer::iterationCount ? + Qt::GestureFinished : Qt::GestureStarted); +} + +void QLongTapGestureRecognizer::reset() +{ + pressedPosition = QPoint(); + timer.stop(); + iteration = 0; +} + +// +// QMultiTouchGestureRecognizer +// + +/* +QMultiTouchGestureRecognizer::QMultiTouchGestureRecognizer() + : QGestureRecognizer(Qt::Pinch) +{ +} + +QGestureRecognizer::Result QMultiTouchGestureRecognizer::recognize(const QList &inputEvents) +{ + QGestureRecognizer::Result result = QGestureRecognizer::NotGesture; + for(int i = 0; i < inputEvents.count(); ++i) { + QEvent *inputEvent = inputEvents.at(i); + if (inputEvent->type() != QEvent::Pointer) { + if (touches.size() == 2) + result = QGestureRecognizer::GestureStarted; + else if (touches.size() == 1) + result = QGestureRecognizer::MaybeGesture; + continue; + } + QPointerEvent *event = static_cast(inputEvent); + Q_ASSERT(event->pointerCount() > 0); + for (int idx = 0; idx < event->pointerCount(); ++idx) { + switch (event->state(idx)) { + case QPointerEvent::Begin: + qDebug() << "Begin" << idx; + if (touches.size() == 2) { + // too many touches + qDebug() << "too many touches"; + result = QGestureRecognizer::MaybeGesture; + continue; + } + touches[event->pointerId(idx)].startPosition = event->pos(idx); + if (touches.size() == 1) { + result = QGestureRecognizer::MaybeGesture; + } else if (touches.size() == 2) { + result = QGestureRecognizer::GestureStarted; + } else { + result = QGestureRecognizer::NotGesture; + } + break; + + case QPointerEvent::Move: + qDebug() << "Move" << idx; + touches[event->pointerId(idx)].lastPosition = touches[event->pointerId(idx)].currentPosition; + touches[event->pointerId(idx)].currentPosition = event->pos(idx); + if (touches.size() == 1) + result = QGestureRecognizer::MaybeGesture; + else if (touches.size() == 2) + result = QGestureRecognizer::GestureStarted; + else + result = QGestureRecognizer::NotGesture; + break; + + case QPointerEvent::End: + qDebug() << "End" << idx; + touches.remove(event->pointerId(idx)); + if (touches.size() == 1) { + result = QGestureRecognizer::MaybeGesture; + } else if (touches.size() == 0) { + result = QGestureRecognizer::NotGesture; + } else { + qDebug() << "unexpected touch end event"; + return QGestureRecognizer::NotGesture; + } + break; + + case QPointerEvent::Stationary: + qDebug() << "Stationary" << idx; + if (touches.size() == 2) + result = QGestureRecognizer::GestureStarted; + else if (touches.size() == 1) + result = QGestureRecognizer::MaybeGesture; + break; + + default: + break; + } + } + } + return result; +} + +QGesture* QMultiTouchGestureRecognizer::makeEvent() const +{ + if (touches.size() != 2) + return 0; + + QGesture *g = new QGesture(Qt::Pinch); + QGesture::Data data; + + TapMap::const_iterator it = touches.begin(); + data.startPos = it->startPosition.toPoint(); + data.lastPos = it->lastPosition.toPoint(); + data.currentPos = it->currentPosition.toPoint(); + g->datas.push_back(data); + + ++it; + data.startPos = it->startPosition.toPoint(); + data.lastPos = it->lastPosition.toPoint(); + data.currentPos = it->currentPosition.toPoint(); + g->datas.push_back(data); + + return g; +} + +void QMultiTouchGestureRecognizer::reset() +{ + touches.clear(); +} +*/ + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qgesturestandardrecognizers_p.h b/src/gui/kernel/qgesturestandardrecognizers_p.h new file mode 100644 index 0000000..3b314e7 --- /dev/null +++ b/src/gui/kernel/qgesturestandardrecognizers_p.h @@ -0,0 +1,169 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGESTURESTANDARDRECOGNIZERS_P_H +#define QGESTURESTANDARDRECOGNIZERS_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 "qevent.h" +#include "qbasictimer.h" +#include "qdebug.h" + +#include "qgesturerecognizer.h" +#include "private/qdirectionrecognizer_p.h" + +QT_BEGIN_NAMESPACE + +/* +class QGestureRecognizerMouseTwoButtons : public QGestureRecognizer +{ + Q_OBJECT +public: + QGestureRecognizerMouseTwoButtons(); + QGestureRecognizer::Result recognize(const QList &inputEvents); + + QGesture* makeEvent() const; + void reset(); + +private: + void clear(); + + // find the last two button click events + QMouseEvent* userEvents[4]; +}; +*/ + +class QGestureRecognizerPan : public QGestureRecognizer +{ + Q_OBJECT +public: + QGestureRecognizerPan(); + + QGestureRecognizer::Result recognize(const QList &inputEvents); + QGesture* makeEvent() const; + + void reset(); + +private: + void internalReset(); + + QPoint pressedPos; + QPoint lastPos; + QPoint currentPos; + bool mousePressed; + bool gestureFinished; + Direction::DirectionType lastDirection; + QDirectionDiagonalRecognizer diagonalRecognizer; + QDirectionSimpleRecognizer simpleRecognizer; +}; + +class QDoubleTapGestureRecognizer : public QGestureRecognizer +{ + Q_OBJECT +public: + QDoubleTapGestureRecognizer(); + + QGestureRecognizer::Result recognize(const QList &inputEvents); + QGesture* makeEvent() const; + void reset(); + +private: + QPoint pressedPosition; +}; + +class QLongTapGestureRecognizer : public QGestureRecognizer +{ + Q_OBJECT +public: + QLongTapGestureRecognizer(); + + QGestureRecognizer::Result recognize(const QList &inputEvents); + QGesture* makeEvent() const; + void reset(); + +protected: + void timerEvent(QTimerEvent *event); + +private: + QPoint pressedPosition; + QBasicTimer timer; + int iteration; + static const int iterationCount; + static const int iterationTimeout; +}; + +/* +class QMultiTouchGestureRecognizer : public QGestureRecognizer +{ + Q_OBJECT +public: + QMultiTouchGestureRecognizer(); + + QMap maybeGestureCompletion(); + QGestureRecognizer::Result recognize(const QList &inputEvents); + QGesture* makeEvent() const; + void reset(); + +private: + struct Tap { + //### should I use QPointF everywhere internally ?? + QPointF startPosition; + QPointF lastPosition; + QPointF currentPosition; + }; + typedef QMap TapMap; + TapMap touches; +}; +*/ + +QT_END_NAMESPACE + +#endif // QGESTURESTANDARDRECOGNIZERS_P_H diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 968a423..f6be730 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -7532,6 +7532,7 @@ bool QWidget::event(QEvent *event) #ifndef QT_NO_WHEELEVENT case QEvent::Wheel: #endif + case QEvent::Gesture: return false; default: break; @@ -7927,6 +7928,9 @@ bool QWidget::event(QEvent *event) d->needWindowChange = false; break; #endif + case QEvent::Gesture: + gestureEvent((QGestureEvent*)event); + break; #ifndef QT_NO_PROPERTIES case QEvent::DynamicPropertyChange: { const QByteArray &propName = static_cast(event)->propertyName(); @@ -8732,6 +8736,11 @@ bool QWidget::qwsEvent(QWSEvent *) #endif +void QWidget::gestureEvent(QGestureEvent *event) +{ + event->ignore(); +} + /*! Ensures that the widget has been polished by QStyle (i.e., has a @@ -11016,6 +11025,42 @@ QWindowSurface *QWidget::windowSurface() const return bs ? bs->windowSurface : 0; } +void QWidget::grabGesture(Qt::GestureType gesture) +{ + Q_D(QWidget); + if (d->gestures.contains(gesture)) + return; + d->gestures << gesture; + ++qApp->d_func()->grabbedGestures[gesture]; +} + +void QWidget::grabGestures(const QSet &gestures) +{ + Q_D(QWidget); + foreach(const Qt::GestureType &gesture, gestures) { + if (!d->gestures.contains(gesture)) + ++qApp->d_func()->grabbedGestures[gesture]; + } + d->gestures.unite(gestures); +} + +void QWidget::releaseGesture(Qt::GestureType gesture) +{ + Q_D(QWidget); + QMap::iterator it = + qApp->d_func()->grabbedGestures.find(gesture); + if (it != qApp->d_func()->grabbedGestures.end() && + d->gestures.contains(gesture)) + ++it.value(); + d->gestures.remove(gesture); +} + +QSet QWidget::gestures() +{ + Q_D(const QWidget); + return d->gestures; +} + void QWidgetPrivate::getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const { if (left) diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h index 6703d26..afe637d 100644 --- a/src/gui/kernel/qwidget.h +++ b/src/gui/kernel/qwidget.h @@ -59,6 +59,8 @@ #include #endif +#include + QT_BEGIN_HEADER QT_BEGIN_NAMESPACE @@ -90,6 +92,7 @@ class QDragLeaveEvent; class QDropEvent; class QShowEvent; class QHideEvent; +class QGestureEvent; class QInputContext; class QIcon; class QWindowSurface; @@ -610,6 +613,11 @@ public: void setWindowSurface(QWindowSurface *surface); QWindowSurface *windowSurface() const; + void grabGesture(Qt::GestureType gesture); + void grabGestures(const QSet &gestures); + void releaseGesture(Qt::GestureType gesture); + QSet gestures(); + Q_SIGNALS: void customContextMenuRequested(const QPoint &pos); @@ -669,6 +677,8 @@ protected: // Misc. protected functions virtual void changeEvent(QEvent *); + virtual void gestureEvent(QGestureEvent *); + int metric(PaintDeviceMetric) const; virtual void inputMethodEvent(QInputMethodEvent *); diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 5f5e1b1..178f7ba 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -57,6 +57,7 @@ #include "private/qobject_p.h" #include "QtCore/qrect.h" #include "QtCore/qlocale.h" +#include "QtCore/qset.h" #include "QtGui/qregion.h" #include "QtGui/qsizepolicy.h" #include "QtGui/qstyle.h" @@ -592,6 +593,8 @@ public: uint isGLWidget : 1; #endif + QSet gestures; + #if defined(Q_WS_X11) || defined (Q_WS_WIN) || defined(Q_WS_MAC) #ifdef Q_WS_MAC void setWSGeometry(bool dontShow=false, const QRect &oldRect = QRect()); diff --git a/src/gui/widgets/qabstractscrollarea.cpp b/src/gui/widgets/qabstractscrollarea.cpp index 9886969..190dbb5 100644 --- a/src/gui/widgets/qabstractscrollarea.cpp +++ b/src/gui/widgets/qabstractscrollarea.cpp @@ -908,6 +908,7 @@ bool QAbstractScrollArea::event(QEvent *e) case QEvent::DragMove: case QEvent::DragLeave: #endif + case QEvent::Gesture: return false; case QEvent::StyleChange: case QEvent::LayoutDirectionChange: -- cgit v0.12 From aa4334b77702d99d4aa3da853dd66104eb4a8123 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Thu, 26 Feb 2009 17:18:33 +0100 Subject: Fixed lastDirection in the Pan gesture. --- examples/gestures/graphicsview/main.cpp | 2 +- src/gui/kernel/qgesturestandardrecognizers.cpp | 48 +++++++++++++++++--------- src/gui/kernel/qgesturestandardrecognizers_p.h | 1 + 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/examples/gestures/graphicsview/main.cpp b/examples/gestures/graphicsview/main.cpp index a0236ef..250da06 100644 --- a/examples/gestures/graphicsview/main.cpp +++ b/examples/gestures/graphicsview/main.cpp @@ -53,7 +53,7 @@ protected: { if (event->type() == QEvent::Gesture) { QGestureEvent *ge = static_cast(event); - if (const QGesture *g = ge->gesture(Qt::Pan)) { + if (const QPannableGesture *g = dynamic_cast(ge->gesture(Qt::Pan))) { QPoint pt = g->pos() - g->lastPos(); horizontalScrollBar()->setValue(horizontalScrollBar()->value() - pt.x()); verticalScrollBar()->setValue(verticalScrollBar()->value() - pt.y()); diff --git a/src/gui/kernel/qgesturestandardrecognizers.cpp b/src/gui/kernel/qgesturestandardrecognizers.cpp index 3a2fa1d..504786a 100644 --- a/src/gui/kernel/qgesturestandardrecognizers.cpp +++ b/src/gui/kernel/qgesturestandardrecognizers.cpp @@ -178,7 +178,7 @@ void QGestureRecognizerMouseTwoButtons::clear() QGestureRecognizerPan::QGestureRecognizerPan() : QGestureRecognizer(Qt::Pan), mousePressed(false), gestureFinished(false), - lastDirection(Direction::None) + lastDirection(Direction::None), currentDirection(Direction::None) { } @@ -202,7 +202,7 @@ QGestureRecognizer::Result QGestureRecognizerPan::recognize(const QList for(int i = 0; i < events.count(); ++i) { QMouseEvent *event = events.at(i); if (event->type() == QEvent::MouseButtonPress) { - if (lastDirection != Direction::None) { + if (currentDirection != Direction::None) { DEBUG() << "Pan: MouseButtonPress: fail. another press during pan"; result = QGestureRecognizer::NotGesture; reset(); @@ -213,7 +213,7 @@ QGestureRecognizer::Result QGestureRecognizerPan::recognize(const QList mousePressed = true; pressedPos = lastPos = currentPos = event->pos(); } else if (event->type() == QEvent::MouseButtonRelease) { - if (mousePressed && lastDirection != Direction::None) { + if (mousePressed && currentDirection != Direction::None) { DEBUG() << "Pan: MouseButtonRelease: pan detected"; result = QGestureRecognizer::GestureFinished; gestureFinished = true; @@ -233,7 +233,7 @@ QGestureRecognizer::Result QGestureRecognizerPan::recognize(const QList Direction::DirectionType direction = simpleRecognizer.addPosition(event->pos()).direction; DEBUG() << "Pan: MouseMove: simplerecognizer result = " << direction; - if (lastDirection == Direction::None) { + if (currentDirection == Direction::None) { if (direction == Direction::None) result = QGestureRecognizer::MaybeGesture; else @@ -241,32 +241,45 @@ QGestureRecognizer::Result QGestureRecognizerPan::recognize(const QList } else { result = QGestureRecognizer::GestureStarted; } - if (direction != Direction::None) - lastDirection = direction; + if (direction != Direction::None) { + if (currentDirection != direction) + lastDirection = currentDirection; + currentDirection = direction; + } } } return result; } +static inline QPannableGesture::DirectionType convertPanningDirection(const Direction::DirectionType direction) +{ + switch (direction) { + case Direction::Left: + return QPannableGesture::Left; + case Direction::Right: + return QPannableGesture::Right; + case Direction::Up: + return QPannableGesture::Up; + case Direction::Down: + return QPannableGesture::Down; + default: + break; + } + return QPannableGesture::None; +} + QGesture* QGestureRecognizerPan::makeEvent() const { - QPannableGesture::DirectionType dir = QPannableGesture::None; - if (lastDirection == Direction::Left) - dir = QPannableGesture::Left; - else if (lastDirection == Direction::Right) - dir = QPannableGesture::Right; - else if (lastDirection == Direction::Up) - dir = QPannableGesture::Up; - else if (lastDirection == Direction::Down) - dir = QPannableGesture::Down; - else + QPannableGesture::DirectionType dir = convertPanningDirection(currentDirection); + QPannableGesture::DirectionType lastDir = convertPanningDirection(lastDirection); + if (dir == QPannableGesture::None) return 0; QPannableGesture *g = new QPannableGesture(Qt::Pan, pressedPos, lastPos, currentPos, QRect(), pressedPos, QDateTime(), 0, gestureFinished ? Qt::GestureFinished : Qt::GestureStarted); QPannableGesturePrivate *d = (QPannableGesturePrivate*)g->d; - d->lastDirection = dir; ///### + d->lastDirection = lastDir; d->direction = dir; return g; @@ -276,6 +289,7 @@ void QGestureRecognizerPan::reset() { mousePressed = false; lastDirection = Direction::None; + currentDirection = Direction::None; gestureFinished = false; diagonalRecognizer.reset(); simpleRecognizer.reset(); diff --git a/src/gui/kernel/qgesturestandardrecognizers_p.h b/src/gui/kernel/qgesturestandardrecognizers_p.h index 3b314e7..567cf65 100644 --- a/src/gui/kernel/qgesturestandardrecognizers_p.h +++ b/src/gui/kernel/qgesturestandardrecognizers_p.h @@ -101,6 +101,7 @@ private: bool mousePressed; bool gestureFinished; Direction::DirectionType lastDirection; + Direction::DirectionType currentDirection; QDirectionDiagonalRecognizer diagonalRecognizer; QDirectionSimpleRecognizer simpleRecognizer; }; -- cgit v0.12 From ce50bdd854497b2a2aedbdb4417b532799086241 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Fri, 27 Feb 2009 14:33:49 +0100 Subject: Added some documentation. Fixed missing const specifiers. --- doc/src/qnamespace.qdoc | 16 +++++++++++ src/gui/kernel/qevent.cpp | 44 ++++++++++++++++++++++++++++++ src/gui/kernel/qevent.h | 8 +++--- src/gui/kernel/qgesturerecognizer.h | 54 ++++++++++++++++++++++++++++++++++++- src/gui/kernel/qwidget.cpp | 27 ++++++++++++++++--- src/gui/kernel/qwidget.h | 6 ++--- 6 files changed, 144 insertions(+), 11 deletions(-) diff --git a/doc/src/qnamespace.qdoc b/doc/src/qnamespace.qdoc index 98f7e7c..c44b41e 100644 --- a/doc/src/qnamespace.qdoc +++ b/doc/src/qnamespace.qdoc @@ -2675,3 +2675,19 @@ \sa QPixmapBorders, qDrawBorderPixmap() */ + +/*! \typedef Qt::GestureType + + A string representing a type of a gesture. +*/ + +/*! + \enum Qt::GestureState + + This enum type describes the state of a gesture. + + \value GestureStarted The continuous gesture has started. + \value GestureFinished The gesture has finished. + + \sa QGesture +*/ diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index a7e1101..d7d193c 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -3509,6 +3509,50 @@ QMenubarUpdatedEvent::QMenubarUpdatedEvent(QMenuBar * const menuBar) #endif +/*! + \class QGestureEvent + \ingroup events + + \brief The QGestureEvent class provides the parameters used for + gesture recognition. + + The QGestureEvent class contains a list of gestures that are being + executed right now (QGestureEvent::gestureTypes()) and a list of + gestures that are cancelled (the gesture might be cancelled + because the window lost focus, or because of timeout, etc). + + \sa QGesture +*/ + +/*! \fn QWidget *QGestureEvent::targetWidget() const + + Returns the widget the gesture event is send to. +*/ + +/*! \fn bool contains(const Qt::GestureType &type) const + + Checks if the gesture event contains gesture of specific \a type. +*/ + +/*! \fn QList gestureTypes() const + + Returns a list of gesture names that the event contains. +*/ + +/*! \fn const QGesture* gesture(const Qt::GestureType &type) const + + Returns extended information about a gesture of specific \a type. +*/ + +/*! \fn QSet cancelledGestures() const + + Returns a set of gesture names that used to be executed, but got + cancelled (i.e. they were not finished properly). +*/ + + + + QGestureEvent::QGestureEvent(QWidget *targetWidget, const QList &gestures, const QSet &cancelledGestures) : QEvent(QEvent::Gesture), m_targetWidget(targetWidget), diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index 858e2ea..cde7cb2 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -726,12 +726,12 @@ public: QWidget *targetWidget() const { return m_targetWidget; } - inline bool contains(const Qt::GestureType &gestureType) const - { return gesture(gestureType) != 0; } + inline bool contains(const Qt::GestureType &type) const + { return gesture(type) != 0; } inline QList gestureTypes() const { return m_gestures.keys(); } - inline const QGesture* gesture(const Qt::GestureType &gestureType) const - { return m_gestures.value(gestureType, QSharedPointer()).data(); } + inline const QGesture* gesture(const Qt::GestureType &type) const + { return m_gestures.value(type, QSharedPointer()).data(); } inline QSet cancelledGestures() const { return m_cancelledGestures; } diff --git a/src/gui/kernel/qgesturerecognizer.h b/src/gui/kernel/qgesturerecognizer.h index 3ed96c0..a831d8a 100644 --- a/src/gui/kernel/qgesturerecognizer.h +++ b/src/gui/kernel/qgesturerecognizer.h @@ -49,6 +49,58 @@ QT_BEGIN_NAMESPACE +/*! + \class QGestureRecognizer + + \brief The base class for implementing custom gestures. + + This is a base class, to create a custom gesture type, you should + subclass it and implement pure virtual functions. + + Usually gesture recognizer implements state machine, storing its + state internally in the recognizer object. The recognizer receives + input events through the QGestureRecognizer::recognize() virtual + function and decides whether the parsed event should change the + state of the recognizer - i.e. if the event starts or ends a + gesture or if it isn't related to gesture at all. +*/ + +/*! \fn Qt::GestureType gestureType() const + + Returns the name of the gesture that is handled by the recognizer. +*/ + +/*! \fn Result recognize(const QList &events) + + This is a pure virtual function that need to be implemented in + subclasses. + + Parses input \a events and returns the result, saying if the event + sequence is a gesture or not. +*/ + +/*! \fn QGesture* makeEvent() const + + Creates a new gesture object that will be send to the widget. This + function is called when the gesture recognizer returned a + QGestureRecognizer::GestureStarted or + QGestureRecognizer::GestureFinished state. + + Created gesture object is owned by the caller. + */ + +/*! \fn void reset() + + Resets the internal state of the gesture recognizer. +*/ + +/*! \fn void triggered(QGestureRecognizer::Result result) + + The gesture recognizer might emit the signal when the gesture + state changes asynchronously, i.e. without any event being + received. +*/ + class QGestureRecognizer : public QObject { Q_OBJECT @@ -67,7 +119,7 @@ public: inline QGestureRecognizer(const Qt::GestureType &type) : type_(type) { } inline Qt::GestureType gestureType() const { return type_; } - virtual Result recognize(const QList &inputEvents) = 0; + virtual Result recognize(const QList &events) = 0; virtual QGesture* makeEvent() const = 0; virtual void reset() = 0; diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index f6be730..aea0003 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -11025,7 +11025,13 @@ QWindowSurface *QWidget::windowSurface() const return bs ? bs->windowSurface : 0; } -void QWidget::grabGesture(Qt::GestureType gesture) +/*! + \fn void QWidget::grabGesture(const Qt::GestureType &gesture) + + Subscribes the widget to the specified \a gesture type. +*/ + +void QWidget::grabGesture(const Qt::GestureType &gesture) { Q_D(QWidget); if (d->gestures.contains(gesture)) @@ -11034,6 +11040,11 @@ void QWidget::grabGesture(Qt::GestureType gesture) ++qApp->d_func()->grabbedGestures[gesture]; } +/*! + \fn void QWidget::grabGestures(const QSet &gestures) + + Subscribes the widget to the specified list of \a gestures. +*/ void QWidget::grabGestures(const QSet &gestures) { Q_D(QWidget); @@ -11044,7 +11055,12 @@ void QWidget::grabGestures(const QSet &gestures) d->gestures.unite(gestures); } -void QWidget::releaseGesture(Qt::GestureType gesture) +/*! + \fn void QWidget::releaseGesture(const Qt::GestureType &gesture) + + Unsubscribes the widget from the specified \a gesture type. +*/ +void QWidget::releaseGesture(const Qt::GestureType &gesture) { Q_D(QWidget); QMap::iterator it = @@ -11055,7 +11071,12 @@ void QWidget::releaseGesture(Qt::GestureType gesture) d->gestures.remove(gesture); } -QSet QWidget::gestures() +/*! + \fn QSet QWidget::gestures() const + + Returns a list of gestures that the widget is subscribed to. +*/ +QSet QWidget::gestures() const { Q_D(const QWidget); return d->gestures; diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h index afe637d..e36b966 100644 --- a/src/gui/kernel/qwidget.h +++ b/src/gui/kernel/qwidget.h @@ -613,10 +613,10 @@ public: void setWindowSurface(QWindowSurface *surface); QWindowSurface *windowSurface() const; - void grabGesture(Qt::GestureType gesture); + void grabGesture(const Qt::GestureType &gesture); void grabGestures(const QSet &gestures); - void releaseGesture(Qt::GestureType gesture); - QSet gestures(); + void releaseGesture(const Qt::GestureType &gesture); + QSet gestures() const; Q_SIGNALS: void customContextMenuRequested(const QPoint &pos); -- cgit v0.12 From 4e31add7d62f26036a43dfe77db1c6b7e333e21e Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Mon, 2 Mar 2009 16:32:39 +0100 Subject: Fixes: reset the internal gesture state when gesture in state 'maybe' is finished. --- src/gui/kernel/qgesturemanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index c244a0b..2d0137e 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -137,7 +137,7 @@ bool QGestureManager::filterEvent(QEvent *event) } activeGestures -= newMaybeGestures; activeGestures += startedGestures; - foreach(QGestureRecognizer *r, startedGestures+notGestures) { + foreach(QGestureRecognizer *r, startedGestures+finishedGestures+notGestures) { QMap::iterator it = maybeGestures.find(r); if (it != maybeGestures.end()) { killTimer(it.value()); -- cgit v0.12 From b349831a5ae7bca80f22240b1ed204dd3d87c71f Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Wed, 4 Mar 2009 11:39:49 +0100 Subject: Fixes: QGraphicsView respects the spontaneous event flag for graphicsscene events. Details: Copying the QEvent::spontaneous() flag from the received event to QGraphicsSceneEvent. --- src/corelib/kernel/qcoreevent.h | 3 +++ src/gui/graphicsview/qgraphicsscene.cpp | 1 + src/gui/graphicsview/qgraphicsview.cpp | 10 ++++++---- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h index c9f9f24..4ea3c70 100644 --- a/src/corelib/kernel/qcoreevent.h +++ b/src/corelib/kernel/qcoreevent.h @@ -313,6 +313,9 @@ private: friend class Q3AccelManager; friend class QShortcutMap; friend class QETWidget; + friend class QGraphicsView; + friend class QGraphicsViewPrivate; + friend class QGraphicsScenePrivate; }; class Q_CORE_EXPORT QTimerEvent : public QEvent diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index fe6dde1..873e28c 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -1335,6 +1335,7 @@ void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mou // event is converted to a press. Known limitation: // Triple-clicking will not generate a doubleclick, though. QGraphicsSceneMouseEvent mousePress(QEvent::GraphicsSceneMousePress); + mousePress.spont = mouseEvent->spont; mousePress.accept(); mousePress.setButton(mouseEvent->button()); mousePress.setButtons(mouseEvent->buttons()); diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index acce717..97903d3 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -295,6 +295,8 @@ static const int QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS = 503; // largest prime < QT_BEGIN_NAMESPACE +bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); + inline int q_round_bound(qreal d) //### (int)(qreal) INT_MAX != INT_MAX for single precision { if (d <= (qreal) INT_MIN) @@ -602,7 +604,7 @@ void QGraphicsViewPrivate::mouseMoveEventHandler(QMouseEvent *event) lastMouseMoveScenePoint = mouseEvent.scenePos(); lastMouseMoveScreenPoint = mouseEvent.screenPos(); mouseEvent.setAccepted(false); - QApplication::sendEvent(scene, &mouseEvent); + qt_sendSpontaneousEvent(scene, &mouseEvent); // Remember whether the last event was accepted or not. lastMouseEvent.setAccepted(mouseEvent.isAccepted()); @@ -3225,7 +3227,7 @@ void QGraphicsView::mouseDoubleClickEvent(QMouseEvent *event) mouseEvent.setAccepted(false); mouseEvent.setButton(event->button()); mouseEvent.setModifiers(event->modifiers()); - QApplication::sendEvent(d->scene, &mouseEvent); + qt_sendSpontaneousEvent(d->scene, &mouseEvent); } /*! @@ -3264,7 +3266,7 @@ void QGraphicsView::mousePressEvent(QMouseEvent *event) mouseEvent.setButton(event->button()); mouseEvent.setModifiers(event->modifiers()); mouseEvent.setAccepted(false); - QApplication::sendEvent(d->scene, &mouseEvent); + qt_sendSpontaneousEvent(d->scene, &mouseEvent); // Update the original mouse event accepted state. bool isAccepted = mouseEvent.isAccepted(); @@ -3434,7 +3436,7 @@ void QGraphicsView::mouseReleaseEvent(QMouseEvent *event) mouseEvent.setButton(event->button()); mouseEvent.setModifiers(event->modifiers()); mouseEvent.setAccepted(false); - QApplication::sendEvent(d->scene, &mouseEvent); + qt_sendSpontaneousEvent(d->scene, &mouseEvent); // Update the last mouse event selected state. d->lastMouseEvent.setAccepted(mouseEvent.isAccepted()); -- cgit v0.12 From fc84e3a05d01cce25949c605fc56dba4b4d3d183 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Thu, 5 Mar 2009 18:41:10 +0100 Subject: Fixes: improved gesture manager event filtering. Details: Several fixes - parsing only spontaneous mouse events and send gesture events to QGraphicsSceneItems according to their z-order --- src/gui/graphicsview/qgraphicsitem.cpp | 5 ++++ src/gui/graphicsview/qgraphicsitem.h | 1 + src/gui/graphicsview/qgraphicsscene.cpp | 19 ++++++++++----- src/gui/kernel/qapplication.cpp | 43 ++++++++++++++++++--------------- 4 files changed, 42 insertions(+), 26 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 58f04f0..a9ad1e1 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -5802,6 +5802,11 @@ void QGraphicsItem::releaseGesture(const Qt::GestureType &type) d_ptr->scene->d_func()->releaseGesture(this, type); } +QSet QGraphicsItem::gestures() const +{ + return d_ptr->gestures; +} + /*! This virtual function is called by QGraphicsItem to notify custom items that some part of the item's state changes. By reimplementing this diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index 42a5110..2b4cdf5 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -340,6 +340,7 @@ public: void grabGesture(const Qt::GestureType &type); void releaseGesture(const Qt::GestureType &type); + QSet gestures() const; enum { Type = 1, diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 873e28c..21c7c81 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5614,18 +5614,25 @@ void QGraphicsScene::gestureEvent(QGestureEvent *event) { Q_D(QGraphicsScene); QList gestureTypes = event->gestureTypes(); - QList pts; QGraphicsView *view = qobject_cast(event->targetWidget()); if (!view) { // something is wrong. Q_ASSERT(view); return; } - foreach(const Qt::GestureType &type, gestureTypes) - pts << view->mapToScene(event->gesture(type)->hotSpot()); - foreach(QGraphicsItem *item, d->itemsWithGestures) { - for (int i = 0; i < pts.size(); ++i) { - if (item->contains(item->mapFromScene(pts.at(i)))) { + QPolygonF poly; + QMap hotSpots; + foreach(const Qt::GestureType &type, gestureTypes) { + QPointF pt = view->mapToScene(event->gesture(type)->hotSpot()); + hotSpots.insert(type, pt); + poly << pt; + } + + foreach(QGraphicsItem *item, items(poly, Qt::IntersectsItemBoundingRect)) { + QMap::const_iterator it = hotSpots.begin(), + e = hotSpots.end(); + for(; it != e; ++it) { + if (item->contains(item->mapFromScene(it.value())) && item->gestures().contains(it.key())) { d->sendGestureEvent(item, event); if (event->isAccepted()) break; diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index b39cbc3..88871a4 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -3706,28 +3706,31 @@ bool QApplication::notify(QObject *receiver, QEvent *e) QMouseEvent* mouse = static_cast(e); QPoint relpos = mouse->pos(); - if (QApplication::testAttribute(Qt::AA_EnableGestures)) { - if (!gestureManager) - gestureManager = new QGestureManager; - // if we are in gesture mode, we send all mouse events - // directly to gesture recognizer. - if (gestureManager->inGestureMode()) { - // ### should I send events through all application event filters? - if (gestureManager->filterEvent(e)) - return true; - } - if (w && (mouse->type() != QEvent::MouseMove || mouse->buttons() != 0)) { - // find the gesture target widget - QWidget *target = w; - while (target && target->gestures().isEmpty()) - target = target->parentWidget(); - if (target) { - gestureManager->setGestureTargetWidget(target); - res = gestureManager->filterEvent(e); + if (e->spontaneous()) { + if (QApplication::testAttribute(Qt::AA_EnableGestures)) { + QWidget *w = static_cast(receiver); + if (!gestureManager) + gestureManager = new QGestureManager; + // if we are in gesture mode, we send all mouse events + // directly to gesture recognizer. + if (gestureManager->inGestureMode()) { + if (gestureManager->filterEvent(e)) + return true; + } else { + QMouseEvent* mouse = static_cast(e); + if (w && (mouse->type() != QEvent::MouseMove || mouse->buttons() != 0)) { + // find the gesture target widget + QWidget *target = w; + while (target && target->gestures().isEmpty()) + target = target->parentWidget(); + if (target) { + gestureManager->setGestureTargetWidget(target); + if (gestureManager->filterEvent(e)) + return true; + } + } } } - } - if (e->spontaneous()) { if (e->type() == QEvent::MouseButtonPress) { QApplicationPrivate::giveFocusAccordingToFocusPolicy(w, Qt::ClickFocus, -- cgit v0.12 From f1d955249ff00db79252967078005db9a9fe936c Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Fri, 6 Mar 2009 12:08:48 +0100 Subject: If the event wasn't consumed by the gesture target widget, then gesture manager should consume it as well. --- src/gui/kernel/qgesturemanager.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index 2d0137e..c9bf0df 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -169,7 +169,8 @@ bool QGestureManager::filterEvent(QEvent *event) } Q_ASSERT(!gestures.isEmpty()); QGestureEvent event(targetWidget, gestures); - qt_sendGestureEvent(targetWidget, &event); + ret = qt_sendGestureEvent(targetWidget, &event); + ret = ret && event.isAccepted(); if (!activeGestures.isEmpty()) { DEBUG() << "QGestureManager: new state = Gesture"; @@ -273,7 +274,8 @@ bool QGestureManager::filterEvent(QEvent *event) cancelledGestureNames << r->gestureType(); if(!gestures.isEmpty()) { QGestureEvent event(targetWidget, gestures, cancelledGestureNames); - qt_sendGestureEvent(targetWidget, &event); + ret = qt_sendGestureEvent(targetWidget, &event); + ret = ret && event.isAccepted(); } foreach(QGestureRecognizer *r, finishedGestures) @@ -291,7 +293,6 @@ bool QGestureManager::filterEvent(QEvent *event) DEBUG() << "QGestureManager: new state = NotGesture"; state = NotGesture; } - ret = true; } lastPos = currentPos; -- cgit v0.12 From b231b0bcd36d531d3558cee12be263a98391b9db Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Fri, 6 Mar 2009 13:11:29 +0100 Subject: Fixes: Compilation fixes --- examples/gestures/imageviewer/imagewidget.cpp | 2 ++ src/gui/kernel/qgesturemanager_p.h | 1 + 2 files changed, 3 insertions(+) diff --git a/examples/gestures/imageviewer/imagewidget.cpp b/examples/gestures/imageviewer/imagewidget.cpp index 8932e29..0db62bb 100644 --- a/examples/gestures/imageviewer/imagewidget.cpp +++ b/examples/gestures/imageviewer/imagewidget.cpp @@ -148,10 +148,12 @@ void ImageWidget::gestureEvent(QGestureEvent *event) } else if (const QGesture *g = event->gesture(Qt::Pan)) { if (zoomedIn) { // usual panning +#ifndef QT_NO_CURSOR if (g->state() == Qt::GestureStarted) setCursor(Qt::SizeAllCursor); else setCursor(Qt::ArrowCursor); +#endif const int dx = g->pos().x() - g->lastPos().x(); const int dy = g->pos().y() - g->lastPos().y(); horizontalOffset += dx; diff --git a/src/gui/kernel/qgesturemanager_p.h b/src/gui/kernel/qgesturemanager_p.h index 9853f1a..1079cc4 100644 --- a/src/gui/kernel/qgesturemanager_p.h +++ b/src/gui/kernel/qgesturemanager_p.h @@ -53,6 +53,7 @@ // We mean it. // +#include "qwidget.h" #include "qlist.h" #include "qset.h" #include "qevent.h" -- cgit v0.12 From 3cad576b7ce221ca92c07a513c4c0fbe9886f8e5 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Fri, 6 Mar 2009 14:42:51 +0100 Subject: Fixes: Add missing functions for a adding custom gesture recognizers. --- src/gui/kernel/qapplication.cpp | 23 ++++++++++++++++------- src/gui/kernel/qapplication.h | 4 ++++ src/gui/kernel/qgesturemanager.cpp | 10 ++++++++++ src/gui/kernel/qgesturemanager_p.h | 3 +++ 4 files changed, 33 insertions(+), 7 deletions(-) diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 88871a4..104271d 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -137,7 +137,7 @@ int QApplicationPrivate::autoMaximizeThreshold = -1; bool QApplicationPrivate::autoSipEnabled = false; #endif -QGestureManager *gestureManager = 0; +Q_GLOBAL_STATIC(QGestureManager, gestureManager); QApplicationPrivate::QApplicationPrivate(int &argc, char **argv, QApplication::Type type) : QCoreApplicationPrivate(argc, argv) @@ -3709,12 +3709,11 @@ bool QApplication::notify(QObject *receiver, QEvent *e) if (e->spontaneous()) { if (QApplication::testAttribute(Qt::AA_EnableGestures)) { QWidget *w = static_cast(receiver); - if (!gestureManager) - gestureManager = new QGestureManager; + QGestureManager *gm = gestureManager(); // if we are in gesture mode, we send all mouse events // directly to gesture recognizer. - if (gestureManager->inGestureMode()) { - if (gestureManager->filterEvent(e)) + if (gm->inGestureMode()) { + if (gm->filterEvent(e)) return true; } else { QMouseEvent* mouse = static_cast(e); @@ -3724,8 +3723,8 @@ bool QApplication::notify(QObject *receiver, QEvent *e) while (target && target->gestures().isEmpty()) target = target->parentWidget(); if (target) { - gestureManager->setGestureTargetWidget(target); - if (gestureManager->filterEvent(e)) + gm->setGestureTargetWidget(target); + if (gm->filterEvent(e)) return true; } } @@ -5090,6 +5089,16 @@ bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy) return true; } +void QApplication::addGestureRecognizer(QGestureRecognizer *recognizer) +{ + gestureManager()->addRecognizer(recognizer); +} + +void QApplication::removeGestureRecognizer(QGestureRecognizer *recognizer) +{ + gestureManager()->removeRecognizer(recognizer); +} + /*! \fn QDecoration &QApplication::qwsDecoration() Return the QWSDecoration used for decorating windows. diff --git a/src/gui/kernel/qapplication.h b/src/gui/kernel/qapplication.h index 634226f..70458ef 100644 --- a/src/gui/kernel/qapplication.h +++ b/src/gui/kernel/qapplication.h @@ -71,6 +71,7 @@ class QStyle; class QEventLoop; class QIcon; class QInputContext; +class QGestureRecognizer; template class QList; class QLocale; #if defined(Q_WS_QWS) @@ -266,6 +267,9 @@ public: static bool keypadNavigationEnabled(); #endif + void addGestureRecognizer(QGestureRecognizer *recognizer); + void removeGestureRecognizer(QGestureRecognizer *recognizer); + Q_SIGNALS: void lastWindowClosed(); void focusChanged(QWidget *old, QWidget *now); diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index c9bf0df..7954ae9 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -83,6 +83,16 @@ QGestureManager::QGestureManager() this, SLOT(recognizerTriggered(QGestureRecognizer::Result))); } +void QGestureManager::addRecognizer(QGestureRecognizer *recognizer) +{ + recognizers << recognizer; +} + +void QGestureManager::removeRecognizer(QGestureRecognizer *recognizer) +{ + recognizers.remove(recognizer); +} + bool QGestureManager::filterEvent(QEvent *event) { if (!QApplication::testAttribute(Qt::AA_EnableGestures)) diff --git a/src/gui/kernel/qgesturemanager_p.h b/src/gui/kernel/qgesturemanager_p.h index 1079cc4..762b70d 100644 --- a/src/gui/kernel/qgesturemanager_p.h +++ b/src/gui/kernel/qgesturemanager_p.h @@ -72,6 +72,9 @@ public: // should be internal void setGestureTargetWidget(QWidget *widget); + void addRecognizer(QGestureRecognizer *recognizer); + void removeRecognizer(QGestureRecognizer *recognizer); + bool filterEvent(QEvent *event); bool inGestureMode(); -- cgit v0.12 From b542556f2d75017af34e0bc8ee1336fa0c08c69d Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Fri, 6 Mar 2009 16:54:23 +0100 Subject: Forgot to export QGestureRecognizer class. --- src/gui/kernel/qgesturerecognizer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/kernel/qgesturerecognizer.h b/src/gui/kernel/qgesturerecognizer.h index a831d8a..ca8972b 100644 --- a/src/gui/kernel/qgesturerecognizer.h +++ b/src/gui/kernel/qgesturerecognizer.h @@ -101,7 +101,7 @@ QT_BEGIN_NAMESPACE received. */ -class QGestureRecognizer : public QObject +class Q_GUI_EXPORT QGestureRecognizer : public QObject { Q_OBJECT public: -- cgit v0.12 From 15588496830fee6fbe38fda76411e483a51ddd08 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Fri, 6 Mar 2009 14:45:43 +0100 Subject: Added colliding mice example with gesture support. --- examples/gestures/collidingmice/collidingmice.pro | 14 ++ examples/gestures/collidingmice/main.cpp | 114 ++++++++++++ examples/gestures/collidingmice/mice.qrc | 5 + examples/gestures/collidingmice/mouse.cpp | 200 ++++++++++++++++++++++ examples/gestures/collidingmice/mouse.h | 72 ++++++++ 5 files changed, 405 insertions(+) create mode 100644 examples/gestures/collidingmice/collidingmice.pro create mode 100644 examples/gestures/collidingmice/main.cpp create mode 100644 examples/gestures/collidingmice/mice.qrc create mode 100644 examples/gestures/collidingmice/mouse.cpp create mode 100644 examples/gestures/collidingmice/mouse.h diff --git a/examples/gestures/collidingmice/collidingmice.pro b/examples/gestures/collidingmice/collidingmice.pro new file mode 100644 index 0000000..5c7b42b --- /dev/null +++ b/examples/gestures/collidingmice/collidingmice.pro @@ -0,0 +1,14 @@ +HEADERS += \ + mouse.h +SOURCES += \ + main.cpp \ + mouse.cpp + +RESOURCES += \ + mice.qrc + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/gestures/collidingmice +sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS collidingmice.pro images +sources.path = $$[QT_INSTALL_EXAMPLES]/gestures/collidingmice +INSTALLS += target sources diff --git a/examples/gestures/collidingmice/main.cpp b/examples/gestures/collidingmice/main.cpp new file mode 100644 index 0000000..56e9f7f --- /dev/null +++ b/examples/gestures/collidingmice/main.cpp @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mouse.h" + +#include + +#include + +static const int MouseCount = 7; + +class PannableGraphicsView : public QGraphicsView +{ +public: + PannableGraphicsView(QGraphicsScene *scene, QWidget *parent = 0) + : QGraphicsView(scene, parent) + { + grabGesture(Qt::Pan); + } +protected: + bool event(QEvent *event) + { + if (event->type() == QEvent::Gesture) { + QGestureEvent *ge = static_cast(event); + if (const QPannableGesture *g = dynamic_cast(ge->gesture(Qt::Pan))) { + QPoint pt = g->pos() - g->lastPos(); + horizontalScrollBar()->setValue(horizontalScrollBar()->value() - pt.x()); + verticalScrollBar()->setValue(verticalScrollBar()->value() - pt.y()); + event->accept(); + return true; + } + } + return QGraphicsView::event(event); + } +}; + +//! [0] +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + QApplication::setAttribute(Qt::AA_EnableGestures); + qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); +//! [0] + +//! [1] + QGraphicsScene scene; + scene.setSceneRect(-600, -600, 1200, 1200); +//! [1] //! [2] + scene.setItemIndexMethod(QGraphicsScene::NoIndex); +//! [2] + +//! [3] + for (int i = 0; i < MouseCount; ++i) { + Mouse *mouse = new Mouse; + mouse->setPos(::sin((i * 6.28) / MouseCount) * 200, + ::cos((i * 6.28) / MouseCount) * 200); + scene.addItem(mouse); + } +//! [3] + +//! [4] + PannableGraphicsView view(&scene); + view.setRenderHint(QPainter::Antialiasing); + view.setBackgroundBrush(QPixmap(":/images/cheese.jpg")); +//! [4] //! [5] + view.setCacheMode(QGraphicsView::CacheBackground); + view.setViewportUpdateMode(QGraphicsView::BoundingRectViewportUpdate); + //view.setDragMode(QGraphicsView::ScrollHandDrag); +//! [5] //! [6] + view.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Colliding Mice")); + view.resize(400, 300); + view.show(); + + return app.exec(); +} +//! [6] diff --git a/examples/gestures/collidingmice/mice.qrc b/examples/gestures/collidingmice/mice.qrc new file mode 100644 index 0000000..accdb4d --- /dev/null +++ b/examples/gestures/collidingmice/mice.qrc @@ -0,0 +1,5 @@ + + + images/cheese.jpg + + diff --git a/examples/gestures/collidingmice/mouse.cpp b/examples/gestures/collidingmice/mouse.cpp new file mode 100644 index 0000000..1d9fa89 --- /dev/null +++ b/examples/gestures/collidingmice/mouse.cpp @@ -0,0 +1,200 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "mouse.h" + +#include +#include +#include + +#include + +static const double Pi = 3.14159265358979323846264338327950288419717; +static double TwoPi = 2.0 * Pi; + +static qreal normalizeAngle(qreal angle) +{ + while (angle < 0) + angle += TwoPi; + while (angle > TwoPi) + angle -= TwoPi; + return angle; +} + +//! [0] +Mouse::Mouse() + : angle(0), speed(0), mouseEyeDirection(0), + color(qrand() % 256, qrand() % 256, qrand() % 256) +{ + rotate(qrand() % (360 * 16)); + startTimer(1000 / 33); +} +//! [0] + +//! [1] +QRectF Mouse::boundingRect() const +{ + qreal adjust = 0.5; + return QRectF(-18 - adjust, -22 - adjust, + 36 + adjust, 60 + adjust); +} +//! [1] + +//! [2] +QPainterPath Mouse::shape() const +{ + QPainterPath path; + path.addRect(-10, -20, 20, 40); + return path; +} +//! [2] + +//! [3] +void Mouse::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *) +{ + // Body + painter->setBrush(color); + painter->drawEllipse(-10, -20, 20, 40); + + // Eyes + painter->setBrush(Qt::white); + painter->drawEllipse(-10, -17, 8, 8); + painter->drawEllipse(2, -17, 8, 8); + + // Nose + painter->setBrush(Qt::black); + painter->drawEllipse(QRectF(-2, -22, 4, 4)); + + // Pupils + painter->drawEllipse(QRectF(-8.0 + mouseEyeDirection, -17, 4, 4)); + painter->drawEllipse(QRectF(4.0 + mouseEyeDirection, -17, 4, 4)); + + // Ears + painter->setBrush(scene()->collidingItems(this).isEmpty() ? Qt::darkYellow : Qt::red); + painter->drawEllipse(-17, -12, 16, 16); + painter->drawEllipse(1, -12, 16, 16); + + // Tail + QPainterPath path(QPointF(0, 20)); + path.cubicTo(-5, 22, -5, 22, 0, 25); + path.cubicTo(5, 27, 5, 32, 0, 30); + path.cubicTo(-5, 32, -5, 42, 0, 35); + painter->setBrush(Qt::NoBrush); + painter->drawPath(path); +} +//! [3] + +//! [4] +void Mouse::timerEvent(QTimerEvent *) +{ +//! [4] + // Don't move too far away +//! [5] + QLineF lineToCenter(QPointF(0, 0), mapFromScene(0, 0)); + if (lineToCenter.length() > 150) { + qreal angleToCenter = ::acos(lineToCenter.dx() / lineToCenter.length()); + if (lineToCenter.dy() < 0) + angleToCenter = TwoPi - angleToCenter; + angleToCenter = normalizeAngle((Pi - angleToCenter) + Pi / 2); + + if (angleToCenter < Pi && angleToCenter > Pi / 4) { + // Rotate left + angle += (angle < -Pi / 2) ? 0.25 : -0.25; + } else if (angleToCenter >= Pi && angleToCenter < (Pi + Pi / 2 + Pi / 4)) { + // Rotate right + angle += (angle < Pi / 2) ? 0.25 : -0.25; + } + } else if (::sin(angle) < 0) { + angle += 0.25; + } else if (::sin(angle) > 0) { + angle -= 0.25; +//! [5] //! [6] + } +//! [6] + + // Try not to crash with any other mice +//! [7] + QList dangerMice = scene()->items(QPolygonF() + << mapToScene(0, 0) + << mapToScene(-30, -50) + << mapToScene(30, -50)); + foreach (QGraphicsItem *item, dangerMice) { + if (item == this) + continue; + + QLineF lineToMouse(QPointF(0, 0), mapFromItem(item, 0, 0)); + qreal angleToMouse = ::acos(lineToMouse.dx() / lineToMouse.length()); + if (lineToMouse.dy() < 0) + angleToMouse = TwoPi - angleToMouse; + angleToMouse = normalizeAngle((Pi - angleToMouse) + Pi / 2); + + if (angleToMouse >= 0 && angleToMouse < Pi / 2) { + // Rotate right + angle += 0.5; + } else if (angleToMouse <= TwoPi && angleToMouse > (TwoPi - Pi / 2)) { + // Rotate left + angle -= 0.5; +//! [7] //! [8] + } +//! [8] //! [9] + } +//! [9] + + // Add some random movement +//! [10] + if (dangerMice.size() > 1 && (qrand() % 10) == 0) { + if (qrand() % 1) + angle += (qrand() % 100) / 500.0; + else + angle -= (qrand() % 100) / 500.0; + } +//! [10] + +//! [11] + speed += (-50 + qrand() % 100) / 100.0; + + qreal dx = ::sin(angle) * 10; + mouseEyeDirection = (qAbs(dx / 5) < 1) ? 0 : dx / 5; + + rotate(dx); + setPos(mapToParent(0, -(3 + sin(speed) * 3))); +} +//! [11] diff --git a/examples/gestures/collidingmice/mouse.h b/examples/gestures/collidingmice/mouse.h new file mode 100644 index 0000000..7545fe6 --- /dev/null +++ b/examples/gestures/collidingmice/mouse.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef MOUSE_H +#define MOUSE_H + +#include +#include + +//! [0] +class Mouse : public QObject, public QGraphicsItem +{ + Q_OBJECT + +public: + Mouse(); + + QRectF boundingRect() const; + QPainterPath shape() const; + void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, + QWidget *widget); + +protected: + void timerEvent(QTimerEvent *event); + +private: + qreal angle; + qreal speed; + qreal mouseEyeDirection; + QColor color; +}; +//! [0] + +#endif -- cgit v0.12 From 90ead023ec593bd3dba0ef8eb4e38f2299cfb783 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Fri, 6 Mar 2009 16:55:02 +0100 Subject: Implemented LinjaZax-like gesture in collidingmice example. --- examples/gestures/collidingmice/collidingmice.pro | 8 +- .../collidingmice/gesturerecognizerlinjazax.cpp | 189 +++++++++++++++++++++ .../collidingmice/gesturerecognizerlinjazax.h | 65 +++++++ examples/gestures/collidingmice/images/cheese.jpg | Bin 0 -> 3029 bytes examples/gestures/collidingmice/linjazaxgesture.h | 58 +++++++ examples/gestures/collidingmice/main.cpp | 19 ++- 6 files changed, 335 insertions(+), 4 deletions(-) create mode 100644 examples/gestures/collidingmice/gesturerecognizerlinjazax.cpp create mode 100644 examples/gestures/collidingmice/gesturerecognizerlinjazax.h create mode 100644 examples/gestures/collidingmice/images/cheese.jpg create mode 100644 examples/gestures/collidingmice/linjazaxgesture.h diff --git a/examples/gestures/collidingmice/collidingmice.pro b/examples/gestures/collidingmice/collidingmice.pro index 5c7b42b..15164ce 100644 --- a/examples/gestures/collidingmice/collidingmice.pro +++ b/examples/gestures/collidingmice/collidingmice.pro @@ -1,8 +1,12 @@ HEADERS += \ - mouse.h + mouse.h \ + gesturerecognizerlinjazax.h \ + linjazaxgesture.h + SOURCES += \ main.cpp \ - mouse.cpp + mouse.cpp \ + gesturerecognizerlinjazax.cpp RESOURCES += \ mice.qrc diff --git a/examples/gestures/collidingmice/gesturerecognizerlinjazax.cpp b/examples/gestures/collidingmice/gesturerecognizerlinjazax.cpp new file mode 100644 index 0000000..4c57209 --- /dev/null +++ b/examples/gestures/collidingmice/gesturerecognizerlinjazax.cpp @@ -0,0 +1,189 @@ +#include "gesturerecognizerlinjazax.h" + +#include +#include + +static const int SIZE = 20; + +DirectionSimpleRecognizer::DirectionSimpleRecognizer() +{ +} + +Direction DirectionSimpleRecognizer::addPosition(const QPoint &pos) +{ + if (!directions.isEmpty()) { + const QPoint tmp = pos - directions.back().point; + if (tmp.manhattanLength() < 5) + return Direction(); + } + if (lastPoint.isNull()) { + lastPoint = pos; + return Direction(); + } + int dx = pos.x() - lastPoint.x(); + int dy = pos.y() - lastPoint.y(); + QString direction; + if (dx < 0) { + if (-1*dx >= SIZE/2) + direction = "4"; + } else { + if (dx >= SIZE/2) + direction = "6"; + } + if (dy < 0) { + if (-1*dy >= SIZE/2) + direction = "8"; + } else { + if (dy >= SIZE/2) + direction = "2"; + } + if (direction.isEmpty()) + return Direction(); + + lastPoint = pos; + directions.push_back(Direction(direction, pos)); + return Direction(direction, pos); +} + + +DirectionList DirectionSimpleRecognizer::getDirections() const +{ + return directions; +} + +void DirectionSimpleRecognizer::reset() +{ + directions.clear(); + lastPoint = QPoint(); +} + +/////////////////////////////////////////////////////////////////////////// + +GestureRecognizerLinjaZax::GestureRecognizerLinjaZax() + : QGestureRecognizer("LinjaZax"), mousePressed(false), gestureFinished(false), + zoomState(LinjaZaxGesture::NoZoom) +{ +} + +QGestureRecognizer::Result GestureRecognizerLinjaZax::recognize(const QList &inputEvents) +{ + // get all mouse events + QList events; + for(int i = 0; i < inputEvents.count(); ++i) { + QEvent *event = inputEvents.at(i); + switch (event->type()) { + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseMove: + events.push_back(static_cast(event)); + default: + break; + } + } + + if (zoomState != LinjaZaxGesture::NoZoom && !lastDirections.isEmpty()) { + lastDirections = lastDirections.right(1); + zoomState = LinjaZaxGesture::NoZoom; + } + + QGestureRecognizer::Result result = QGestureRecognizer::NotGesture; + for(int i = 0; i < events.count(); ++i) { + QMouseEvent *event = events.at(i); + if (event->type() == QEvent::MouseButtonPress) { + if (!currentDirection.isEmpty()) { + result = QGestureRecognizer::NotGesture; + reset(); + break; + } + result = QGestureRecognizer::MaybeGesture; + mousePressed = true; + pressedPos = lastPos = currentPos = event->pos(); + } else if (event->type() == QEvent::MouseButtonRelease) { + if (mousePressed && !currentDirection.isEmpty()) { + result = QGestureRecognizer::GestureFinished; + gestureFinished = true; + currentPos = event->pos(); + internalReset(); + break; + } + result = QGestureRecognizer::NotGesture; + reset(); + break; + } else if (event->type() == QEvent::MouseMove) { + if (!mousePressed) + continue; + lastPos = currentPos; + currentPos = event->pos(); + QString direction = + simpleRecognizer.addPosition(event->pos()).direction; + if (currentDirection.isEmpty()) { + if (direction.isEmpty()) + result = QGestureRecognizer::MaybeGesture; + else + result = QGestureRecognizer::GestureStarted; + } else { + result = QGestureRecognizer::GestureStarted; + } + if (!direction.isEmpty()) { + if (currentDirection != direction) + lastDirections.append(direction); + currentDirection = direction; + if (lastDirections.length() > 5) + lastDirections.remove(0, 1); + if (lastDirections.contains("248")) + zoomState = LinjaZaxGesture::ZoomingIn; + else if (lastDirections.contains("268")) + zoomState = LinjaZaxGesture::ZoomingOut; + } + } + } + return result; +} + +static inline LinjaZaxGesture::DirectionType convertPanningDirection(const QString &direction) +{ + if (direction.length() == 1) { + if (direction == "4") + return LinjaZaxGesture::Left; + else if (direction == "6") + return LinjaZaxGesture::Right; + else if (direction == "8") + return LinjaZaxGesture::Up; + else if (direction == "2") + return LinjaZaxGesture::Down; + } + return LinjaZaxGesture::None; +} + +QGesture* GestureRecognizerLinjaZax::makeEvent() const +{ + LinjaZaxGesture::DirectionType dir = convertPanningDirection(currentDirection); + LinjaZaxGesture::DirectionType lastDir = convertPanningDirection(lastDirections.right(1)); + if (dir == LinjaZaxGesture::None) + return 0; + LinjaZaxGesture *g = + new LinjaZaxGesture("LinjaZax", pressedPos, lastPos, currentPos, + QRect(), pressedPos, QDateTime(), 0, + gestureFinished ? Qt::GestureFinished : Qt::GestureStarted); + g->lastDirection_ = lastDir; + g->direction_ = dir; + g->zoomState_ = zoomState; + + return g; +} + +void GestureRecognizerLinjaZax::reset() +{ + mousePressed = false; + lastDirections.clear(); + currentDirection.clear(); + gestureFinished = false; + simpleRecognizer.reset(); + zoomState = LinjaZaxGesture::NoZoom; +} + +void GestureRecognizerLinjaZax::internalReset() +{ + mousePressed = false; + simpleRecognizer.reset(); +} diff --git a/examples/gestures/collidingmice/gesturerecognizerlinjazax.h b/examples/gestures/collidingmice/gesturerecognizerlinjazax.h new file mode 100644 index 0000000..6579059 --- /dev/null +++ b/examples/gestures/collidingmice/gesturerecognizerlinjazax.h @@ -0,0 +1,65 @@ +#ifndef GESTURERECOGNIZERLINJAZAX_H +#define GESTURERECOGNIZERLINJAZAX_H + +#include +#include +#include +#include +#include + +#include "linjazaxgesture.h" + +struct Direction +{ + QString direction; + QPoint point; + + Direction(QString dir, const QPoint &pt) + : direction(dir), point(pt) { } + Direction() + : direction() { } + + inline bool isEmpty() const { return direction.isEmpty(); } + inline bool isNull() const { return direction.isEmpty(); } +}; +typedef QList DirectionList; + +class DirectionSimpleRecognizer +{ +public: + DirectionSimpleRecognizer(); + Direction addPosition(const QPoint &pos); + DirectionList getDirections() const; + void reset(); + +private: + QPoint lastPoint; + DirectionList directions; +}; + +class GestureRecognizerLinjaZax : public QGestureRecognizer +{ + Q_OBJECT +public: + GestureRecognizerLinjaZax(); + + QGestureRecognizer::Result recognize(const QList &inputEvents); + QGesture* makeEvent() const; + + void reset(); + +private: + void internalReset(); + + QPoint pressedPos; + QPoint lastPos; + QPoint currentPos; + bool mousePressed; + bool gestureFinished; + QString lastDirections; + QString currentDirection; + DirectionSimpleRecognizer simpleRecognizer; + LinjaZaxGesture::ZoomState zoomState; +}; + +#endif diff --git a/examples/gestures/collidingmice/images/cheese.jpg b/examples/gestures/collidingmice/images/cheese.jpg new file mode 100644 index 0000000..dea5795 Binary files /dev/null and b/examples/gestures/collidingmice/images/cheese.jpg differ diff --git a/examples/gestures/collidingmice/linjazaxgesture.h b/examples/gestures/collidingmice/linjazaxgesture.h new file mode 100644 index 0000000..9601675 --- /dev/null +++ b/examples/gestures/collidingmice/linjazaxgesture.h @@ -0,0 +1,58 @@ +#ifndef LINJAZAXGESTURE_H +#define LINJAZAXGESTURE_H + +#include + +class Q_GUI_EXPORT LinjaZaxGesture : public QGesture +{ +public: + enum DirectionType + { + None = 0, + LeftDown = 1, + DownLeft = LeftDown, + Down = 2, + RightDown = 3, + DownRight = RightDown, + Left = 4, + Right = 6, + LeftUp = 7, + UpLeft = LeftUp, + Up = 8, + RightUp = 9, + UpRight = RightUp + }; + + enum ZoomState + { + NoZoom, + ZoomingIn, + ZoomingOut + }; + +public: + explicit LinjaZaxGesture(const Qt::GestureType &type, Qt::GestureState state = Qt::GestureStarted) + : QGesture(type, state), lastDirection_(None), direction_(None), zoomState_(NoZoom) { } + LinjaZaxGesture(const Qt::GestureType &type, const QPoint &startPos, + const QPoint &lastPos, const QPoint &pos, const QRect &rect, + const QPoint &hotSpot, const QDateTime &startTime, + uint duration, Qt::GestureState state) + : QGesture(type, startPos, lastPos, pos, rect, hotSpot, startTime, duration, state) { } + ~LinjaZaxGesture() { } + + DirectionType lastDirection() const + { return lastDirection_; } + DirectionType direction() const + { return direction_; } + + ZoomState zoomState() const + { return zoomState_; } + +private: + DirectionType lastDirection_; + DirectionType direction_; + ZoomState zoomState_; + friend class GestureRecognizerLinjaZax; +}; + +#endif diff --git a/examples/gestures/collidingmice/main.cpp b/examples/gestures/collidingmice/main.cpp index 56e9f7f..9f50379 100644 --- a/examples/gestures/collidingmice/main.cpp +++ b/examples/gestures/collidingmice/main.cpp @@ -41,6 +41,9 @@ #include "mouse.h" +#include "gesturerecognizerlinjazax.h" +#include "linjazaxgesture.h" + #include #include @@ -53,14 +56,25 @@ public: PannableGraphicsView(QGraphicsScene *scene, QWidget *parent = 0) : QGraphicsView(scene, parent) { - grabGesture(Qt::Pan); + grabGesture("LinjaZax"); } protected: bool event(QEvent *event) { if (event->type() == QEvent::Gesture) { QGestureEvent *ge = static_cast(event); - if (const QPannableGesture *g = dynamic_cast(ge->gesture(Qt::Pan))) { + const LinjaZaxGesture *g = dynamic_cast(ge->gesture("LinjaZax")); + if (g) { + switch (g->zoomState()) { + case LinjaZaxGesture::ZoomingIn: + scale(1.5, 1.5); + break; + case LinjaZaxGesture::ZoomingOut: + scale(0.6, 0.6); + break; + default: + break; + }; QPoint pt = g->pos() - g->lastPos(); horizontalScrollBar()->setValue(horizontalScrollBar()->value() - pt.x()); verticalScrollBar()->setValue(verticalScrollBar()->value() - pt.y()); @@ -77,6 +91,7 @@ int main(int argc, char **argv) { QApplication app(argc, argv); QApplication::setAttribute(Qt::AA_EnableGestures); + app.addGestureRecognizer(new GestureRecognizerLinjaZax); qsrand(QTime(0,0,0).secsTo(QTime::currentTime())); //! [0] -- cgit v0.12 From ed24f677a411c449a2a3f862906aff2a313b4425 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Fri, 6 Mar 2009 18:49:56 +0100 Subject: Added animation to zooming gesture in collidingmice example. --- .../collidingmice/gesturerecognizerlinjazax.cpp | 7 ++--- examples/gestures/collidingmice/main.cpp | 35 ++++++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/examples/gestures/collidingmice/gesturerecognizerlinjazax.cpp b/examples/gestures/collidingmice/gesturerecognizerlinjazax.cpp index 4c57209..3f90588 100644 --- a/examples/gestures/collidingmice/gesturerecognizerlinjazax.cpp +++ b/examples/gestures/collidingmice/gesturerecognizerlinjazax.cpp @@ -125,14 +125,13 @@ QGestureRecognizer::Result GestureRecognizerLinjaZax::recognize(const QList 5) lastDirections.remove(0, 1); - if (lastDirections.contains("248")) + if (lastDirections.contains("248") || lastDirections.contains("2448")) zoomState = LinjaZaxGesture::ZoomingIn; - else if (lastDirections.contains("268")) + else if (lastDirections.contains("268") || lastDirections.contains("2668")) zoomState = LinjaZaxGesture::ZoomingOut; } } diff --git a/examples/gestures/collidingmice/main.cpp b/examples/gestures/collidingmice/main.cpp index 9f50379..d6dbdb0 100644 --- a/examples/gestures/collidingmice/main.cpp +++ b/examples/gestures/collidingmice/main.cpp @@ -48,15 +48,26 @@ #include +#define ZOOMING_ANIMATION +#ifdef ZOOMING_ANIMATION +static const int AnimationSteps = 10; +#endif + static const int MouseCount = 7; class PannableGraphicsView : public QGraphicsView { + Q_OBJECT public: PannableGraphicsView(QGraphicsScene *scene, QWidget *parent = 0) : QGraphicsView(scene, parent) { grabGesture("LinjaZax"); +#ifdef ZOOMING_ANIMATION + timeline = new QTimeLine(700, this); + timeline->setFrameRange(0, AnimationSteps); + connect(timeline, SIGNAL(frameChanged(int)), this, SLOT(animationStep(int))); +#endif } protected: bool event(QEvent *event) @@ -67,10 +78,22 @@ protected: if (g) { switch (g->zoomState()) { case LinjaZaxGesture::ZoomingIn: +#ifdef ZOOMING_ANIMATION + scaleStep = 1. + 0.5/AnimationSteps; + timeline->stop(); + timeline->start(); +#else scale(1.5, 1.5); +#endif break; case LinjaZaxGesture::ZoomingOut: +#ifdef ZOOMING_ANIMATION + scaleStep = 1. - 0.5/AnimationSteps; + timeline->stop(); + timeline->start(); +#else scale(0.6, 0.6); +#endif break; default: break; @@ -84,6 +107,16 @@ protected: } return QGraphicsView::event(event); } +private slots: +#ifdef ZOOMING_ANIMATION + void animationStep(int step) + { + scale(scaleStep, scaleStep); + } +private: + qreal scaleStep; + QTimeLine *timeline; +#endif }; //! [0] @@ -127,3 +160,5 @@ int main(int argc, char **argv) return app.exec(); } //! [6] + +#include "main.moc" -- cgit v0.12 From 3e2cef8f6a58949b887add8ff1bb5e457e7be542 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Thu, 12 Mar 2009 16:07:36 +0100 Subject: Added QGraphicsSceneGestureEvent that extends plain QGestureEvent by providing some additional info (like a widget that received a gesture - for coordinates conversions). --- examples/gestures/graphicsview/main.cpp | 4 +- src/corelib/kernel/qcoreevent.h | 1 + src/gui/graphicsview/qgraphicsscene.cpp | 34 +++--- src/gui/graphicsview/qgraphicsscene.h | 3 +- src/gui/graphicsview/qgraphicsscene_p.h | 1 - src/gui/graphicsview/qgraphicssceneevent.cpp | 148 +++++++++++++++++++++++++++ src/gui/graphicsview/qgraphicssceneevent.h | 40 ++++++++ src/gui/graphicsview/qgraphicsview.cpp | 12 ++- src/gui/kernel/qapplication.cpp | 1 - src/gui/kernel/qevent.cpp | 26 +++-- src/gui/kernel/qevent.h | 8 +- src/gui/kernel/qgesturemanager.cpp | 8 +- 12 files changed, 236 insertions(+), 50 deletions(-) diff --git a/examples/gestures/graphicsview/main.cpp b/examples/gestures/graphicsview/main.cpp index 250da06..1b325ee 100644 --- a/examples/gestures/graphicsview/main.cpp +++ b/examples/gestures/graphicsview/main.cpp @@ -94,8 +94,8 @@ public: bool sceneEvent(QEvent *event) { - if (event->type() == QEvent::Gesture) { - QGestureEvent *gestureEvent = static_cast(event); + if (event->type() == QEvent::GraphicsSceneGesture) { + QGraphicsSceneGestureEvent *gestureEvent = static_cast(event); if (gestureEvent->gesture(Qt::DoubleTap)) { event->accept(); colored = !colored; diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h index 4ea3c70..cb24723 100644 --- a/src/corelib/kernel/qcoreevent.h +++ b/src/corelib/kernel/qcoreevent.h @@ -274,6 +274,7 @@ public: GraphicsSceneTouchEnd = 198, Gesture = 191, + GraphicsSceneGesture = 192, // 512 reserved for Qt Jambi's MetaCall event // 513 reserved for Qt Jambi's DeleteOnMainThread event diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 21c7c81..7e23620 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -3951,8 +3951,8 @@ bool QGraphicsScene::event(QEvent *event) // geometries that do not have an explicit style set. update(); break; - case QEvent::Gesture: - gestureEvent(static_cast(event)); + case QEvent::GraphicsSceneGesture: + gestureEvent(static_cast(event)); break; case QEvent::GraphicsSceneTouchBegin: d->touchBeginEvent(static_cast(event)); @@ -5604,36 +5604,32 @@ void QGraphicsScenePrivate::removeView(QGraphicsView *view) view->releaseGesture(gesture); } -void QGraphicsScenePrivate::sendGestureEvent(QGraphicsItem *item, QGestureEvent *event) -{ - //### TODO: position translation - sendEvent(item, event); -} - -void QGraphicsScene::gestureEvent(QGestureEvent *event) +void QGraphicsScene::gestureEvent(QGraphicsSceneGestureEvent *event) { Q_D(QGraphicsScene); QList gestureTypes = event->gestureTypes(); - QGraphicsView *view = qobject_cast(event->targetWidget()); + QGraphicsView *view = qobject_cast(event->widget()); if (!view) { - // something is wrong. - Q_ASSERT(view); + qWarning("QGraphicsScene::gestureEvent: gesture event was received without a view"); return; } + + // find graphics items that intersects with gestures hot spots. QPolygonF poly; - QMap hotSpots; + QMap sceneHotSpots; foreach(const Qt::GestureType &type, gestureTypes) { - QPointF pt = view->mapToScene(event->gesture(type)->hotSpot()); - hotSpots.insert(type, pt); + QPointF pt = event->mapToScene(event->gesture(type)->hotSpot()); + sceneHotSpots.insert(type, pt); poly << pt; } + QList itemsInGestureArea = items(poly, Qt::IntersectsItemBoundingRect); - foreach(QGraphicsItem *item, items(poly, Qt::IntersectsItemBoundingRect)) { - QMap::const_iterator it = hotSpots.begin(), - e = hotSpots.end(); + foreach(QGraphicsItem *item, itemsInGestureArea) { + QMap::const_iterator it = sceneHotSpots.begin(), + e = sceneHotSpots.end(); for(; it != e; ++it) { if (item->contains(item->mapFromScene(it.value())) && item->gestures().contains(it.key())) { - d->sendGestureEvent(item, event); + d->sendEvent(item, event); if (event->isAccepted()) break; } diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h index 4680455..45def44 100644 --- a/src/gui/graphicsview/qgraphicsscene.h +++ b/src/gui/graphicsview/qgraphicsscene.h @@ -80,6 +80,7 @@ class QGraphicsSceneHelpEvent; class QGraphicsSceneHoverEvent; class QGraphicsSceneMouseEvent; class QGraphicsSceneWheelEvent; +class QGraphicsSceneGestureEvent; class QGraphicsSimpleTextItem; class QGraphicsTextItem; class QGraphicsView; @@ -255,7 +256,7 @@ protected: virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); virtual void wheelEvent(QGraphicsSceneWheelEvent *event); virtual void inputMethodEvent(QInputMethodEvent *event); - virtual void gestureEvent(QGestureEvent *event); + virtual void gestureEvent(QGraphicsSceneGestureEvent *event); virtual void drawBackground(QPainter *painter, const QRectF &rect); virtual void drawForeground(QPainter *painter, const QRectF &rect); diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index cea0553..1cd1788 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -271,7 +271,6 @@ public: QSet grabbedGestures; void grabGesture(QGraphicsItem *item, const Qt::GestureType &type); void releaseGesture(QGraphicsItem *item, const Qt::GestureType &type); - void sendGestureEvent(QGraphicsItem *item, QGestureEvent *event); mutable QVector sceneTransformCache; mutable QBitArray validTransforms; diff --git a/src/gui/graphicsview/qgraphicssceneevent.cpp b/src/gui/graphicsview/qgraphicssceneevent.cpp index 3c9799b..4d9e7bb 100644 --- a/src/gui/graphicsview/qgraphicssceneevent.cpp +++ b/src/gui/graphicsview/qgraphicssceneevent.cpp @@ -299,6 +299,8 @@ #include #include #include +#include "qgraphicsview.h" +#include "qgraphicsitem.h" QT_BEGIN_NAMESPACE @@ -1704,6 +1706,152 @@ void QGraphicsSceneMoveEvent::setNewPos(const QPointF &pos) d->newPos = pos; } +/*! + \class QGraphicsSceneGestureEvent + \brief The QGraphicsSceneGestureEvent class provides gesture events for + the graphics view framework. + \since 4.6 + \ingroup graphicsview-api + + QGraphicsSceneGestureEvent extends information provided by + QGestureEvent by adding some convenience functions like + \l{QGraphicsSceneEvent::}{widget()} to get a widget that received + original gesture event, and convenience functions mapToScene(), + mapToItem() for converting positions of the gesture into + QGraphicsScene and QGraphicsItem coordinate system respectively. + + The scene sends the event to the first QGraphicsItem under the + mouse cursor that accepts gestures; a graphics item is set to accept + gestures with \l{QGraphicsItem::}{grabGesture()}. +*/ + +/*! \fn bool QGraphicsSceneGestureEvent::contains(const Qt::GestureType &type) const + + Checks if the gesture event contains gesture of specific \a type. +*/ + +/*! \fn QList QGraphicsSceneGestureEvent::gestureTypes() const + + Returns a list of gesture names that the event contains. +*/ + +/*! \fn const QGesture* QGraphicsSceneGestureEvent::gesture(const Qt::GestureType &type) const + + Returns extended information about a gesture of specific \a type. +*/ + +/*! \fn QList > QGraphicsSceneGestureEvent::gestures() const + + Returns extended information about all triggered gestures. +*/ + +/*! \fn QSet QGraphicsSceneGestureEvent::cancelledGestures() const + + Returns a set of gesture names that used to be executed, but got + cancelled (i.e. they were not finished properly). +*/ + +/*! \fn void QGraphicsSceneGestureEvent::setCancelledGestures(const QSet &) + + Returns a set of gesture names that used to be executed, but got + cancelled (i.e. they were not finished properly). +*/ + +QGraphicsSceneGestureEvent::QGraphicsSceneGestureEvent() + : QGraphicsSceneEvent(QEvent::GraphicsSceneGesture) +{ +} + +QGraphicsSceneGestureEvent::~QGraphicsSceneGestureEvent() +{ +} + +/*! + Maps the point \a point, which is in a view coordinate system, to + scene coordinate system, and returns the mapped coordinate. + + \a Point is in coordinate system of the widget that received + gesture event. + + \sa mapToScene(const QRect &rect), + mapToItem(const QPoint &point, QGraphicsItem *item), + mapToItem(const QRect &rect, QGraphicsItem *item), + {The Graphics View Coordinate System} +*/ +QPointF QGraphicsSceneGestureEvent::mapToScene(const QPoint &point) const +{ + if (QGraphicsView *view = qobject_cast(widget())) + return view->mapToScene(point); + return QPointF(); +} + +/*! + Maps the rectangular \a rect, which is in a view coordinate system, to + scene coordinate system, and returns the mapped coordinate. + + \a Point is in coordinate system of the widget that received + gesture event. + + \sa mapToScene(const QPoint &rect), + mapToItem(const QPoint &point, QGraphicsItem *item), + mapToItem(const QRect &rect, QGraphicsItem *item), + {The Graphics View Coordinate System} +*/ +QPolygonF QGraphicsSceneGestureEvent::mapToScene(const QRect &rect) const +{ + if (QGraphicsView *view = qobject_cast(widget())) + return view->mapToScene(rect); + return QPolygonF(); +} + +/*! + Maps the point \a point, which is in a view coordinate system, to + item's \a item coordinate system, and returns the mapped coordinate. + + If \a item is 0, this function returns the same as mapToScene(). + + \sa mapToScene(const QPoint &rect), mapToScene(const QRect &rect), + mapToItem(const QRect &, QGraphicsItem *item), + {The Graphics View Coordinate System} +*/ +QPointF QGraphicsSceneGestureEvent::mapToItem(const QPoint &point, QGraphicsItem *item) const +{ + if (item) { + if (QGraphicsView *view = qobject_cast(widget())) + return item->mapFromScene(view->mapToScene(point)); + } else { + return mapToScene(point); + } + return QPointF(); +} + +/*! + Maps the point \a point, which is in a view coordinate system, to + item's \a item coordinate system, and returns the mapped coordinate. + + If \a item is 0, this function returns the same as mapToScene(). + + \sa mapToScene(const QPoint &rect), mapToScene(const QRect &rect), + mapToItem(const QPoint &point, QGraphicsItem *item), + {The Graphics View Coordinate System} +*/ +QPolygonF QGraphicsSceneGestureEvent::mapToItem(const QRect &rect, QGraphicsItem *item) const +{ + if (item) { + if (QGraphicsView *view = qobject_cast(widget())) + return item->mapFromScene(view->mapToScene(rect)); + } else { + return mapToScene(rect); + } + return QPolygonF(); +} + +void QGraphicsSceneGestureEvent::setGestures(const QList > &gestures) +{ + foreach(const QSharedPointer &g, gestures) + m_gestures.insert(g->gestureType(), g); +} + class QGraphicsSceneTouchEventPrivate : public QGraphicsSceneEventPrivate { Q_DECLARE_PUBLIC(QGraphicsSceneTouchEvent) diff --git a/src/gui/graphicsview/qgraphicssceneevent.h b/src/gui/graphicsview/qgraphicssceneevent.h index 8ae3a99..d3899cd 100644 --- a/src/gui/graphicsview/qgraphicssceneevent.h +++ b/src/gui/graphicsview/qgraphicssceneevent.h @@ -44,6 +44,11 @@ #include #include +#include +#include +#include +#include +#include QT_BEGIN_HEADER @@ -302,6 +307,41 @@ public: void setNewPos(const QPointF &pos); }; +class QGesture; +class QGraphicsItem; +class QGraphicsSceneGestureEventPrivate; +class Q_GUI_EXPORT QGraphicsSceneGestureEvent : public QGraphicsSceneEvent +{ + Q_DECLARE_PRIVATE(QGraphicsSceneGestureEvent) +public: + QGraphicsSceneGestureEvent(); + ~QGraphicsSceneGestureEvent(); + + inline bool contains(const Qt::GestureType &type) const + { return gesture(type) != 0; } + inline QList gestureTypes() const + { return m_gestures.keys(); } + inline const QGesture* gesture(const Qt::GestureType &type) const + { return m_gestures.value(type, QSharedPointer()).data(); } + inline QList > gestures() const + { return m_gestures.values(); } + void setGestures(const QList > &gestures); + + inline QSet cancelledGestures() const + { return m_cancelledGestures; } + void setCancelledGestures(const QSet &cancelledGestures) + { m_cancelledGestures = cancelledGestures; } + + QPointF mapToScene(const QPoint &point) const; + QPolygonF mapToScene(const QRect &rect) const; + QPointF mapToItem(const QPoint &point, QGraphicsItem *item) const; + QPolygonF mapToItem(const QRect &rect, QGraphicsItem *item) const; + +protected: + QHash > m_gestures; + QSet m_cancelledGestures; +}; + class QGraphicsSceneTouchEventPrivate; class QGraphicsSceneTouchEventTouchPointPrivate; class Q_GUI_EXPORT QGraphicsSceneTouchEvent : public QGraphicsSceneEvent diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 97903d3..925763c 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -2862,10 +2862,16 @@ bool QGraphicsView::event(QEvent *event) } } break; - case QEvent::Gesture: - QApplication::sendEvent(d->scene, event); - if (event->isAccepted()) + case QEvent::Gesture: { + QGraphicsSceneGestureEvent gestureEvent; + gestureEvent.setWidget(this); + QGestureEvent *ev = static_cast(event); + gestureEvent.setGestures(ev->gestures()); + gestureEvent.setCancelledGestures(ev->cancelledGestures()); + QApplication::sendEvent(d->scene, &gestureEvent); + if (gestureEvent.isAccepted()) return true; + } break; default: break; diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 104271d..5774ae0 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -4037,7 +4037,6 @@ bool QApplication::notify(QObject *receiver, QEvent *e) // QGestureEvent ge(&qge, false); // ### TODO: fix widget-relative positions in gesture event. QGestureEvent ge = *g; - ge.m_targetWidget = w; ge.spont = g->spontaneous(); res = d->notify_helper(w, w == receiver ? g : &ge); g->spont = false; diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index d7d193c..6cdf781 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -3524,27 +3524,27 @@ QMenubarUpdatedEvent::QMenubarUpdatedEvent(QMenuBar * const menuBar) \sa QGesture */ -/*! \fn QWidget *QGestureEvent::targetWidget() const - - Returns the widget the gesture event is send to. -*/ - -/*! \fn bool contains(const Qt::GestureType &type) const +/*! \fn bool QGestureEvent::contains(const Qt::GestureType &type) const Checks if the gesture event contains gesture of specific \a type. */ -/*! \fn QList gestureTypes() const +/*! \fn QList QGestureEvent::gestureTypes() const Returns a list of gesture names that the event contains. */ -/*! \fn const QGesture* gesture(const Qt::GestureType &type) const +/*! \fn const QGesture* QGestureEvent::gesture(const Qt::GestureType &type) const Returns extended information about a gesture of specific \a type. */ -/*! \fn QSet cancelledGestures() const +/*! \fn QList > QGestureEvent::gestures() const + + Returns extended information about all triggered gestures. +*/ + +/*! \fn QSet QGestureEvent::cancelledGestures() const Returns a set of gesture names that used to be executed, but got cancelled (i.e. they were not finished properly). @@ -3553,18 +3553,16 @@ QMenubarUpdatedEvent::QMenubarUpdatedEvent(QMenuBar * const menuBar) -QGestureEvent::QGestureEvent(QWidget *targetWidget, const QList &gestures, +QGestureEvent::QGestureEvent(const QList &gestures, const QSet &cancelledGestures) - : QEvent(QEvent::Gesture), m_targetWidget(targetWidget), - m_cancelledGestures(cancelledGestures) + : QEvent(QEvent::Gesture), m_cancelledGestures(cancelledGestures) { foreach(QGesture *r, gestures) m_gestures.insert(r->gestureType(), QSharedPointer(r)); } QGestureEvent::QGestureEvent(const QGestureEvent &event, const QPoint &offset) - : QEvent(QEvent::Gesture), m_targetWidget(event.m_targetWidget), - m_gestures(event.m_gestures), + : QEvent(QEvent::Gesture), m_gestures(event.m_gestures), m_cancelledGestures(event.m_cancelledGestures) { //### use offset! diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index cde7cb2..603f358 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -717,27 +717,25 @@ private: class Q_GUI_EXPORT QGestureEvent : public QEvent { public: - QGestureEvent(QWidget *targetWidget, const QList &gestures, + QGestureEvent(const QList &gestures, const QSet &cancelledGestures = QSet()); // internal ctor QGestureEvent(const QGestureEvent &gestures, const QPoint &offset); ~QGestureEvent(); - QWidget *targetWidget() const - { return m_targetWidget; } - inline bool contains(const Qt::GestureType &type) const { return gesture(type) != 0; } inline QList gestureTypes() const { return m_gestures.keys(); } inline const QGesture* gesture(const Qt::GestureType &type) const { return m_gestures.value(type, QSharedPointer()).data(); } + inline QList > gestures() const + { return m_gestures.values(); } inline QSet cancelledGestures() const { return m_cancelledGestures; } protected: - QWidget *m_targetWidget; QHash > m_gestures; QSet m_cancelledGestures; diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index 7954ae9..9a287a0 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -178,7 +178,7 @@ bool QGestureManager::filterEvent(QEvent *event) gestures << gesture; } Q_ASSERT(!gestures.isEmpty()); - QGestureEvent event(targetWidget, gestures); + QGestureEvent event(gestures); ret = qt_sendGestureEvent(targetWidget, &event); ret = ret && event.isAccepted(); @@ -283,7 +283,7 @@ bool QGestureManager::filterEvent(QEvent *event) foreach(QGestureRecognizer *r, cancelledGestures) cancelledGestureNames << r->gestureType(); if(!gestures.isEmpty()) { - QGestureEvent event(targetWidget, gestures, cancelledGestureNames); + QGestureEvent event(gestures, cancelledGestureNames); ret = qt_sendGestureEvent(targetWidget, &event); ret = ret && event.isAccepted(); } @@ -375,7 +375,7 @@ void QGestureManager::recognizerTriggered(QGestureRecognizer::Result result) if (QGesture *gesture = recognizer->makeEvent()) gestures << gesture; if(!gestures.isEmpty()) { - QGestureEvent event(targetWidget, gestures); + QGestureEvent event(gestures); qt_sendGestureEvent(targetWidget, &event); } if (result == QGestureRecognizer::GestureFinished) @@ -385,7 +385,7 @@ void QGestureManager::recognizerTriggered(QGestureRecognizer::Result result) case QGestureRecognizer::MaybeGesture: { DEBUG() << "QGestureManager: maybe gesture: " << recognizer; if (activeGestures.contains(recognizer)) { - QGestureEvent event(targetWidget, QList(), + QGestureEvent event(QList(), QSet() << recognizer->gestureType()); qt_sendGestureEvent(targetWidget, &event); } -- cgit v0.12 From f8c5c2720b4a48dad0f68b83d9c494185e012cd1 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Thu, 12 Mar 2009 17:06:17 +0100 Subject: Moved the code that translated QGestureEvent to QGraphicsSceneGestureEvent to a viewport, so that the user could subscribe to gestures in a viewport as well. --- src/gui/graphicsview/qgraphicsview.cpp | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp index 925763c..6f142e3 100644 --- a/src/gui/graphicsview/qgraphicsview.cpp +++ b/src/gui/graphicsview/qgraphicsview.cpp @@ -2862,16 +2862,8 @@ bool QGraphicsView::event(QEvent *event) } } break; - case QEvent::Gesture: { - QGraphicsSceneGestureEvent gestureEvent; - gestureEvent.setWidget(this); - QGestureEvent *ev = static_cast(event); - gestureEvent.setGestures(ev->gestures()); - gestureEvent.setCancelledGestures(ev->cancelledGestures()); - QApplication::sendEvent(d->scene, &gestureEvent); - if (gestureEvent.isAccepted()) - return true; - } + case QEvent::Gesture: + viewportEvent(event); break; default: break; @@ -2953,6 +2945,17 @@ bool QGraphicsView::viewportEvent(QEvent *event) d->scene->d_func()->updateAll = false; } break; + case QEvent::Gesture: { + QGraphicsSceneGestureEvent gestureEvent; + gestureEvent.setWidget(this); + QGestureEvent *ev = static_cast(event); + gestureEvent.setGestures(ev->gestures()); + gestureEvent.setCancelledGestures(ev->cancelledGestures()); + QApplication::sendEvent(d->scene, &gestureEvent); + if (gestureEvent.isAccepted()) + return true; + } + break; case QEvent::TouchBegin: case QEvent::TouchUpdate: case QEvent::TouchEnd: -- cgit v0.12 From 86a160b083f9d43c07d42bbd7d2ef8b676552e38 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Fri, 13 Mar 2009 18:08:18 +0100 Subject: Modifications after the api review by Brad. Gesture types are now separated to internal ones, which are listed as enums (though they might be converted to strings internally), and third party gestures which are referenced by strings. From now on QGesture objects derive from QObject, which means third party gesture recognizer developers can use QObjects property system to store custom data inside QGesture without need to subclass it. Some functions were renamed to show their purpose more clear. --- src/corelib/global/qnamespace.h | 18 +- src/gui/graphicsview/qgraphicsitem.cpp | 32 +- src/gui/graphicsview/qgraphicsitem.h | 6 +- src/gui/graphicsview/qgraphicsitem_p.h | 2 +- src/gui/graphicsview/qgraphicsscene.cpp | 33 +- src/gui/graphicsview/qgraphicsscene_p.h | 6 +- src/gui/graphicsview/qgraphicssceneevent.h | 14 +- src/gui/kernel/kernel.pri | 2 + src/gui/kernel/qapplication.cpp | 2 +- src/gui/kernel/qapplication_p.h | 4 +- src/gui/kernel/qevent.cpp | 2 +- src/gui/kernel/qevent.h | 15 +- src/gui/kernel/qgesture.cpp | 56 +-- src/gui/kernel/qgesture.h | 25 +- src/gui/kernel/qgesture_p.h | 7 +- src/gui/kernel/qgesturemanager.cpp | 69 ++-- src/gui/kernel/qgesturemanager_p.h | 4 +- src/gui/kernel/qgesturerecognizer.cpp | 71 ++++ src/gui/kernel/qgesturerecognizer.h | 35 +- src/gui/kernel/qgesturerecognizer_p.h | 72 ++++ src/gui/kernel/qgesturestandardrecognizers.cpp | 507 ++++++------------------- src/gui/kernel/qgesturestandardrecognizers_p.h | 60 +-- src/gui/kernel/qwidget.cpp | 66 ++-- src/gui/kernel/qwidget.h | 9 +- src/gui/kernel/qwidget_p.h | 3 +- 25 files changed, 501 insertions(+), 619 deletions(-) create mode 100644 src/gui/kernel/qgesturerecognizer.cpp create mode 100644 src/gui/kernel/qgesturerecognizer_p.h diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 5747c3c..56ee768 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -1551,13 +1551,17 @@ public: TouchPointReleased }; - typedef QString GestureType; - static const char UnknownGesture[] = "???"; - static const char Tap[] = "Tap"; - static const char DoubleTap[] = "DoubleTap"; - static const char LongTap[] = "LongTap"; - static const char Pan[] = "Pan"; - static const char Pinch[] = "Pinch"; + enum GestureType + { + UnknownGesture, + TapGesture, + DoubleTapGesture, + TrippleTapGesture, + TapAndHoldGesture, + PanGesture, + PinchGesture + }; + enum GestureState { diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index a9ad1e1..cbd4834 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -561,6 +561,8 @@ public: }; Q_GLOBAL_STATIC(QGraphicsItemCustomDataStore, qt_dataStore) +QString qt_getStandardGestureTypeName(Qt::GestureType type); + /*! \internal @@ -5788,23 +5790,27 @@ QVariant QGraphicsItem::inputMethodQuery(Qt::InputMethodQuery query) const return QVariant(); } -void QGraphicsItem::grabGesture(const Qt::GestureType &type) +int QGraphicsItem::grabGesture(Qt::GestureType type) { - d_ptr->gestures.insert(type); - if (d_ptr->scene) - d_ptr->scene->d_func()->grabGesture(this, type); + return grabGesture(qt_getStandardGestureTypeName(type)); } -void QGraphicsItem::releaseGesture(const Qt::GestureType &type) +int QGraphicsItem::grabGesture(const QString &type) { - d_ptr->gestures.remove(type); + int id = qHash(type); + QSet::iterator it = d_ptr->gestures.find(id); + if (it != d_ptr->gestures.end()) + return *it; + d_ptr->gestures << id; if (d_ptr->scene) - d_ptr->scene->d_func()->releaseGesture(this, type); + d_ptr->scene->d_func()->grabGesture(this, id); } -QSet QGraphicsItem::gestures() const +void QGraphicsItem::releaseGesture(int id) { - return d_ptr->gestures; + d_ptr->gestures.remove(id); + if (d_ptr->scene) + d_ptr->scene->d_func()->releaseGesture(this, id); } /*! @@ -5835,14 +5841,14 @@ QVariant QGraphicsItem::itemChange(GraphicsItemChange change, const QVariant &va if (!qVariantValue(value)) { // the item has been removed from a scene, unsubscribe gestures. Q_ASSERT(d_ptr->scene); - foreach(const Qt::GestureType &gesture, d_ptr->gestures) - d_ptr->scene->d_func()->releaseGesture(this, gesture); + foreach(int id, d_ptr->gestures) + d_ptr->scene->d_func()->releaseGesture(this, id); } } else if (change == QGraphicsItem::ItemSceneHasChanged) { if (QGraphicsScene *scene = qVariantValue(value)) { // item has been added to the scene - foreach(const Qt::GestureType &gesture, d_ptr->gestures) - scene->d_func()->grabGesture(this, gesture); + foreach(int id, d_ptr->gestures) + scene->d_func()->grabGesture(this, id); } } return value; diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index 2b4cdf5..4e6e96d 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -338,9 +338,9 @@ public: QVariant data(int key) const; void setData(int key, const QVariant &value); - void grabGesture(const Qt::GestureType &type); - void releaseGesture(const Qt::GestureType &type); - QSet gestures() const; + int grabGesture(Qt::GestureType type); + int grabGesture(const QString &type); + void releaseGesture(int gestureId); enum { Type = 1, diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h index a67a49a..f6daa49 100644 --- a/src/gui/graphicsview/qgraphicsitem_p.h +++ b/src/gui/graphicsview/qgraphicsitem_p.h @@ -298,7 +298,7 @@ public: int siblingIndex; int index; int depth; - QSet gestures; + QSet gestures; // Packed 32 bytes quint32 acceptedMouseButtons : 5; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 7e23620..0f70cfe 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -5593,21 +5593,21 @@ void QGraphicsScene::setActiveWindow(QGraphicsWidget *widget) void QGraphicsScenePrivate::addView(QGraphicsView *view) { views << view; - foreach(const Qt::GestureType &gesture, grabbedGestures) - view->grabGesture(gesture); + foreach(int gestureId, grabbedGestures) + view->d_func()->grabGesture(gestureId); } void QGraphicsScenePrivate::removeView(QGraphicsView *view) { views.removeAll(view); - foreach(const Qt::GestureType &gesture, grabbedGestures) - view->releaseGesture(gesture); + foreach(int gestureId, grabbedGestures) + view->releaseGesture(gestureId); } void QGraphicsScene::gestureEvent(QGraphicsSceneGestureEvent *event) { Q_D(QGraphicsScene); - QList gestureTypes = event->gestureTypes(); + QList gestureTypes = event->gestureTypes(); QGraphicsView *view = qobject_cast(event->widget()); if (!view) { qWarning("QGraphicsScene::gestureEvent: gesture event was received without a view"); @@ -5616,19 +5616,20 @@ void QGraphicsScene::gestureEvent(QGraphicsSceneGestureEvent *event) // find graphics items that intersects with gestures hot spots. QPolygonF poly; - QMap sceneHotSpots; - foreach(const Qt::GestureType &type, gestureTypes) { + QMap sceneHotSpots; + foreach(const QString &type, gestureTypes) { QPointF pt = event->mapToScene(event->gesture(type)->hotSpot()); - sceneHotSpots.insert(type, pt); + sceneHotSpots.insert(qHash(type), pt); poly << pt; } QList itemsInGestureArea = items(poly, Qt::IntersectsItemBoundingRect); foreach(QGraphicsItem *item, itemsInGestureArea) { - QMap::const_iterator it = sceneHotSpots.begin(), - e = sceneHotSpots.end(); + QMap::const_iterator it = sceneHotSpots.begin(), + e = sceneHotSpots.end(); for(; it != e; ++it) { - if (item->contains(item->mapFromScene(it.value())) && item->gestures().contains(it.key())) { + if (item->contains(item->mapFromScene(it.value())) && + item->d_ptr->gestures.contains(it.key())) { d->sendEvent(item, event); if (event->isAccepted()) break; @@ -5637,17 +5638,17 @@ void QGraphicsScene::gestureEvent(QGraphicsSceneGestureEvent *event) } } -void QGraphicsScenePrivate::grabGesture(QGraphicsItem *item, const Qt::GestureType &type) +void QGraphicsScenePrivate::grabGesture(QGraphicsItem *item, int gestureId) { - if (!grabbedGestures.contains(type)) { + if (!grabbedGestures.contains(gestureId)) { foreach(QGraphicsView *view, views) - view->grabGesture(type); + view->d_func()->grabGesture(gestureId); } itemsWithGestures << item; - grabbedGestures << type; + grabbedGestures << gestureId; } -void QGraphicsScenePrivate::releaseGesture(QGraphicsItem *item, const Qt::GestureType &type) +void QGraphicsScenePrivate::releaseGesture(QGraphicsItem *item, int gestureId) { //### } diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h index 1cd1788..074e95c 100644 --- a/src/gui/graphicsview/qgraphicsscene_p.h +++ b/src/gui/graphicsview/qgraphicsscene_p.h @@ -268,9 +268,9 @@ public: void updatePalette(const QPalette &palette); QSet itemsWithGestures; - QSet grabbedGestures; - void grabGesture(QGraphicsItem *item, const Qt::GestureType &type); - void releaseGesture(QGraphicsItem *item, const Qt::GestureType &type); + QSet grabbedGestures; + void grabGesture(QGraphicsItem *item, int gestureId); + void releaseGesture(QGraphicsItem *item, int gestureId); mutable QVector sceneTransformCache; mutable QBitArray validTransforms; diff --git a/src/gui/graphicsview/qgraphicssceneevent.h b/src/gui/graphicsview/qgraphicssceneevent.h index d3899cd..4d88cda 100644 --- a/src/gui/graphicsview/qgraphicssceneevent.h +++ b/src/gui/graphicsview/qgraphicssceneevent.h @@ -317,19 +317,19 @@ public: QGraphicsSceneGestureEvent(); ~QGraphicsSceneGestureEvent(); - inline bool contains(const Qt::GestureType &type) const + inline bool contains(const QString &type) const { return gesture(type) != 0; } - inline QList gestureTypes() const + inline QList gestureTypes() const { return m_gestures.keys(); } - inline const QGesture* gesture(const Qt::GestureType &type) const + inline const QGesture* gesture(const QString &type) const { return m_gestures.value(type, QSharedPointer()).data(); } inline QList > gestures() const { return m_gestures.values(); } void setGestures(const QList > &gestures); - inline QSet cancelledGestures() const + inline QSet cancelledGestures() const { return m_cancelledGestures; } - void setCancelledGestures(const QSet &cancelledGestures) + void setCancelledGestures(const QSet &cancelledGestures) { m_cancelledGestures = cancelledGestures; } QPointF mapToScene(const QPoint &point) const; @@ -338,8 +338,8 @@ public: QPolygonF mapToItem(const QRect &rect, QGraphicsItem *item) const; protected: - QHash > m_gestures; - QSet m_cancelledGestures; + QHash > m_gestures; + QSet m_cancelledGestures; }; class QGraphicsSceneTouchEventPrivate; diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index b6ef6b2..adc2b10 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -44,6 +44,7 @@ HEADERS += \ kernel/qkeymapper_p.h \ kernel/qgesture.h \ kernel/qgesturemanager_p.h \ + kernel/qgesturerecognizer_p.h \ kernel/qgesturerecognizer.h \ kernel/qgesturestandardrecognizers_p.h \ kernel/qdirectionrecognizer_p.h \ @@ -79,6 +80,7 @@ SOURCES += \ kernel/qkeymapper.cpp \ kernel/qgesture.cpp \ kernel/qgesturemanager.cpp \ + kernel/qgesturerecognizer.cpp \ kernel/qgesturestandardrecognizers.cpp \ kernel/qdirectionrecognizer.cpp diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 5774ae0..efe1b13 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -3720,7 +3720,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e) if (w && (mouse->type() != QEvent::MouseMove || mouse->buttons() != 0)) { // find the gesture target widget QWidget *target = w; - while (target && target->gestures().isEmpty()) + while (target && target->d_func()->gestures.isEmpty()) target = target->parentWidget(); if (target) { gm->setGestureTargetWidget(target); diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 40e928d..40cd4ae 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -428,7 +428,9 @@ public: void sendSyntheticEnterLeave(QWidget *widget); #endif - QMap grabbedGestures; + // map number of grabbed widgets (something like refcount) + QMap grabbedGestures; + static void updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent); #if defined(Q_WS_WIN) diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 6cdf781..225d8b1 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -3554,7 +3554,7 @@ QMenubarUpdatedEvent::QMenubarUpdatedEvent(QMenuBar * const menuBar) QGestureEvent::QGestureEvent(const QList &gestures, - const QSet &cancelledGestures) + const QSet &cancelledGestures) : QEvent(QEvent::Gesture), m_cancelledGestures(cancelledGestures) { foreach(QGesture *r, gestures) diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index 603f358..db3d03f 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -718,26 +718,27 @@ class Q_GUI_EXPORT QGestureEvent : public QEvent { public: QGestureEvent(const QList &gestures, - const QSet &cancelledGestures = QSet()); + const QSet &cancelledGestures = QSet()); // internal ctor QGestureEvent(const QGestureEvent &gestures, const QPoint &offset); ~QGestureEvent(); - inline bool contains(const Qt::GestureType &type) const + inline bool contains(const QString &type) const { return gesture(type) != 0; } - inline QList gestureTypes() const + inline QList gestureTypes() const { return m_gestures.keys(); } - inline const QGesture* gesture(const Qt::GestureType &type) const + + inline const QGesture* gesture(const QString &type) const { return m_gestures.value(type, QSharedPointer()).data(); } inline QList > gestures() const { return m_gestures.values(); } - inline QSet cancelledGestures() const + inline QSet cancelledGestures() const { return m_cancelledGestures; } protected: - QHash > m_gestures; - QSet m_cancelledGestures; + QHash > m_gestures; + QSet m_cancelledGestures; friend class QApplication; }; diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp index fbabb8f..b2d357c 100644 --- a/src/gui/kernel/qgesture.cpp +++ b/src/gui/kernel/qgesture.cpp @@ -42,80 +42,80 @@ #include "qgesture.h" #include -QGesture::QGesture(const Qt::GestureType &type, Qt::GestureState state) - : d(new QGesturePrivate), gestureType_(type), gestureState_(state) +QT_BEGIN_NAMESPACE + +QString qt_getStandardGestureTypeName(Qt::GestureType type); + +QGesture::QGesture(QObject *parent, const QString &type, Qt::GestureState state) + : QObject(*new QGesturePrivate, parent), gestureType_(type), gestureState_(state) { } -QGesture::QGesture(const Qt::GestureType &type, const QPoint &startPos, +QGesture::QGesture(QObject *parent, const QString &type, const QPoint &startPos, const QPoint &lastPos, const QPoint &pos, const QRect &rect, const QPoint &hotSpot, const QDateTime &startTime, uint duration, Qt::GestureState state) - : d(new QGesturePrivate), gestureType_(type), gestureState_(state) + : QObject(*new QGesturePrivate, parent), gestureType_(type), gestureState_(state) { - d->init(startPos, lastPos, pos, rect, hotSpot, startTime, duration); + d_func()->init(startPos, lastPos, pos, rect, hotSpot, startTime, duration); } -QGesture::QGesture(QGesturePrivate &dd, const Qt::GestureType &type, +QGesture::QGesture(QGesturePrivate &dd, QObject *parent, const QString &type, Qt::GestureState state) - : d(&dd), gestureType_(type), gestureState_(state) + : QObject(dd, parent), gestureType_(type), gestureState_(state) { } QGesture::~QGesture() { - delete d; d = 0; } QRect QGesture::rect() const { - return d->rect; + return d_func()->rect; } QPoint QGesture::hotSpot() const { - return d->hotSpot; + return d_func()->hotSpot; } QDateTime QGesture::startTime() const { - return d->startTime; + return d_func()->startTime; } uint QGesture::duration() const { - return d->duration; + return d_func()->duration; } QPoint QGesture::startPos() const { - return d->startPos; + return d_func()->startPos; } QPoint QGesture::lastPos() const { - return d->lastPos; + return d_func()->lastPos; } QPoint QGesture::pos() const { - return d->pos; + return d_func()->pos; } -QPannableGesture::QPannableGesture(const Qt::GestureType &type, Qt::GestureState state) - : QGesture(*new QPannableGesturePrivate, type, state) -{ -} - -QPannableGesture::QPannableGesture(const Qt::GestureType &type, const QPoint &startPos, +QPannableGesture::QPannableGesture(QObject *parent, const QPoint &startPos, const QPoint &lastPos, const QPoint &pos, const QRect &rect, const QPoint &hotSpot, const QDateTime &startTime, uint duration, Qt::GestureState state) - : QGesture(*new QPannableGesturePrivate, type, state) + : QGesture(*new QPannableGesturePrivate, parent, + qt_getStandardGestureTypeName(Qt::PanGesture), state) { + Q_D(QPannableGesture); d->init(startPos, lastPos, pos, rect, hotSpot, startTime, duration); - ((QPannableGesturePrivate*)d)->lastDirection = QPannableGesture::None; - ((QPannableGesturePrivate*)d)->direction = QPannableGesture::None; + d->lastDirection = QPannableGesture::None; + d->direction = QPannableGesture::None; } QPannableGesture::~QPannableGesture() @@ -124,10 +124,14 @@ QPannableGesture::~QPannableGesture() QPannableGesture::DirectionType QPannableGesture::lastDirection() const { - return ((QPannableGesturePrivate*)d)->lastDirection; + Q_D(const QPannableGesture); + return d->lastDirection; } QPannableGesture::DirectionType QPannableGesture::direction() const { - return ((QPannableGesturePrivate*)d)->direction; + Q_D(const QPannableGesture); + return d->direction; } + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h index 16a5704..f20a63c 100644 --- a/src/gui/kernel/qgesture.h +++ b/src/gui/kernel/qgesture.h @@ -56,17 +56,21 @@ QT_BEGIN_NAMESPACE QT_MODULE(Gui) class QGesturePrivate; -class Q_GUI_EXPORT QGesture +class Q_GUI_EXPORT QGesture : public QObject { + Q_OBJECT + Q_DECLARE_PRIVATE(QGesture) public: - explicit QGesture(const Qt::GestureType &type, Qt::GestureState state = Qt::GestureStarted); - QGesture(const Qt::GestureType &type, const QPoint &startPos, + explicit QGesture(QObject *parent, const QString &type, + Qt::GestureState state = Qt::GestureStarted); + QGesture(QObject *parent, + const QString &type, const QPoint &startPos, const QPoint &lastPos, const QPoint &pos, const QRect &rect, const QPoint &hotSpot, const QDateTime &startTime, uint duration, Qt::GestureState state); virtual ~QGesture(); - inline Qt::GestureType gestureType() const { return gestureType_; } + inline QString gestureType() const { return gestureType_; } inline Qt::GestureState state() const { return gestureState_; } QRect rect() const; @@ -79,16 +83,20 @@ public: QPoint pos() const; protected: - QGesture(QGesturePrivate &dd, const Qt::GestureType &type, Qt::GestureState state = Qt::GestureStarted); - QGesturePrivate *d; + QGesture(QGesturePrivate &dd, QObject *parent, const QString &type, Qt::GestureState state); + //### virtual void translateCoordinates(const QPoint &offset); private: - Qt::GestureType gestureType_; + QString gestureType_; Qt::GestureState gestureState_; }; +class QPannableGesturePrivate; class Q_GUI_EXPORT QPannableGesture : public QGesture { + Q_OBJECT + Q_DECLARE_PRIVATE(QPannableGesture) + public: enum DirectionType { @@ -108,8 +116,7 @@ public: }; public: - explicit QPannableGesture(const Qt::GestureType &type, Qt::GestureState state = Qt::GestureStarted); - QPannableGesture(const Qt::GestureType &type, const QPoint &startPos, + QPannableGesture(QObject *parent, const QPoint &startPos, const QPoint &lastPos, const QPoint &pos, const QRect &rect, const QPoint &hotSpot, const QDateTime &startTime, uint duration, Qt::GestureState state); diff --git a/src/gui/kernel/qgesture_p.h b/src/gui/kernel/qgesture_p.h index 745590b..8a76186 100644 --- a/src/gui/kernel/qgesture_p.h +++ b/src/gui/kernel/qgesture_p.h @@ -56,11 +56,14 @@ #include "qrect.h" #include "qpoint.h" #include "qdatetime.h" +#include "private/qobject_p.h" QT_BEGIN_NAMESPACE -class QGesturePrivate +class QGesturePrivate : public QObjectPrivate { + Q_DECLARE_PUBLIC(QGesture) + public: QGesturePrivate() : duration(0) { } @@ -90,6 +93,8 @@ public: class QPannableGesturePrivate : public QGesturePrivate { + Q_DECLARE_PUBLIC(QPannableGesture) + public: QPannableGesture::DirectionType lastDirection; QPannableGesture::DirectionType direction; diff --git a/src/gui/kernel/qgesturemanager.cpp b/src/gui/kernel/qgesturemanager.cpp index 9a287a0..0e2cea8 100644 --- a/src/gui/kernel/qgesturemanager.cpp +++ b/src/gui/kernel/qgesturemanager.cpp @@ -44,9 +44,10 @@ #include "qevent.h" #include "qapplication.h" -#include "private/qapplication_p.h" +#include "qapplication_p.h" +#include "qwidget_p.h" -#include "private/qgesturestandardrecognizers_p.h" +#include "qgesturestandardrecognizers_p.h" #include "qdebug.h" @@ -60,13 +61,6 @@ QT_BEGIN_NAMESPACE bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); -static bool qt_sendGestureEvent(QWidget *receiver, QGestureEvent *event) -{ - QSet eventGestures = event->gestureTypes().toSet(); - while (receiver && (receiver->gestures() & eventGestures).isEmpty()) - receiver = receiver->parentWidget(); - return receiver ? qt_sendSpontaneousEvent(receiver, event) : false; -} static const unsigned int maximumGestureRecognitionTimeout = 2000; @@ -74,13 +68,12 @@ QGestureManager::QGestureManager() : targetWidget(0), state(NotGesture) { recognizers << new QDoubleTapGestureRecognizer(); - recognizers << new QLongTapGestureRecognizer(); + recognizers << new QTapAndHoldGestureRecognizer(); recognizers << new QGestureRecognizerPan(); - // recognizers << new QMultiTouchGestureRecognizer(); foreach(QGestureRecognizer *r, recognizers) - connect(r, SIGNAL(triggered(QGestureRecognizer::Result)), - this, SLOT(recognizerTriggered(QGestureRecognizer::Result))); + connect(r, SIGNAL(stateChanged(QGestureRecognizer::Result)), + this, SLOT(recognizerStateChanged(QGestureRecognizer::Result))); } void QGestureManager::addRecognizer(QGestureRecognizer *recognizer) @@ -98,9 +91,6 @@ bool QGestureManager::filterEvent(QEvent *event) if (!QApplication::testAttribute(Qt::AA_EnableGestures)) return false; - QList events; - events << event; - QPoint currentPos; switch (event->type()) { case QEvent::MouseButtonPress: @@ -111,7 +101,7 @@ bool QGestureManager::filterEvent(QEvent *event) default: break; } - const QMap &grabbedGestures = qApp->d_func()->grabbedGestures; + const QMap &grabbedGestures = qApp->d_func()->grabbedGestures; bool ret = false; QSet startedGestures; @@ -127,9 +117,9 @@ bool QGestureManager::filterEvent(QEvent *event) QSet stillMaybeGestures; // try other recognizers. foreach(QGestureRecognizer *r, recognizers) { - if (grabbedGestures.value(r->gestureType(), 0) <= 0) + if (grabbedGestures.value(qHash(r->gestureType()), 0) <= 0) continue; - QGestureRecognizer::Result result = r->recognize(events); + QGestureRecognizer::Result result = r->filterEvent(event); if (result == QGestureRecognizer::GestureStarted) { DEBUG() << "QGestureManager: gesture started: " << r; startedGestures << r; @@ -170,16 +160,16 @@ bool QGestureManager::filterEvent(QEvent *event) QList gestures; foreach(QGestureRecognizer *r, finishedGestures) { - if (QGesture *gesture = r->makeEvent()) + if (QGesture *gesture = r->getGesture()) gestures << gesture; } foreach(QGestureRecognizer *r, activeGestures) { - if (QGesture *gesture = r->makeEvent()) + if (QGesture *gesture = r->getGesture()) gestures << gesture; } Q_ASSERT(!gestures.isEmpty()); QGestureEvent event(gestures); - ret = qt_sendGestureEvent(targetWidget, &event); + ret = sendGestureEvent(targetWidget, &event); ret = ret && event.isAccepted(); if (!activeGestures.isEmpty()) { @@ -220,9 +210,9 @@ bool QGestureManager::filterEvent(QEvent *event) Q_ASSERT(!activeGestures.isEmpty()); foreach(QGestureRecognizer *r, recognizers) { - if (grabbedGestures.value(r->gestureType(), 0) <= 0) + if (grabbedGestures.value(qHash(r->gestureType()), 0) <= 0) continue; - QGestureRecognizer::Result result = r->recognize(events); + QGestureRecognizer::Result result = r->filterEvent(event); if (result == QGestureRecognizer::GestureStarted) { DEBUG() << "QGestureManager: gesture started: " << r; startedGestures << r; @@ -271,20 +261,20 @@ bool QGestureManager::filterEvent(QEvent *event) << activeGestures << " and " << finishedGestures; foreach(QGestureRecognizer *r, finishedGestures) { - if (QGesture *gesture = r->makeEvent()) + if (QGesture *gesture = r->getGesture()) gestures << gesture; } foreach(QGestureRecognizer *r, activeGestures) { - if (QGesture *gesture = r->makeEvent()) + if (QGesture *gesture = r->getGesture()) gestures << gesture; } } - QSet cancelledGestureNames; + QSet cancelledGestureNames; foreach(QGestureRecognizer *r, cancelledGestures) cancelledGestureNames << r->gestureType(); if(!gestures.isEmpty()) { QGestureEvent event(gestures, cancelledGestureNames); - ret = qt_sendGestureEvent(targetWidget, &event); + ret = sendGestureEvent(targetWidget, &event); ret = ret && event.isAccepted(); } @@ -343,7 +333,7 @@ void QGestureManager::setGestureTargetWidget(QWidget *widget) targetWidget = widget; } -void QGestureManager::recognizerTriggered(QGestureRecognizer::Result result) +void QGestureManager::recognizerStateChanged(QGestureRecognizer::Result result) { if (!QApplication::testAttribute(Qt::AA_EnableGestures)) return; @@ -351,7 +341,7 @@ void QGestureManager::recognizerTriggered(QGestureRecognizer::Result result) QGestureRecognizer *recognizer = qobject_cast(sender()); if (!recognizer) return; - if (qApp->d_func()->grabbedGestures.value(recognizer->gestureType(), 0) <= 0) { + if (qApp->d_func()->grabbedGestures.value(qHash(recognizer->gestureType()), 0) <= 0) { recognizer->reset(); return; } @@ -372,11 +362,11 @@ void QGestureManager::recognizerTriggered(QGestureRecognizer::Result result) maybeGestures.remove(recognizer); } QList gestures; - if (QGesture *gesture = recognizer->makeEvent()) + if (QGesture *gesture = recognizer->getGesture()) gestures << gesture; if(!gestures.isEmpty()) { QGestureEvent event(gestures); - qt_sendGestureEvent(targetWidget, &event); + sendGestureEvent(targetWidget, &event); } if (result == QGestureRecognizer::GestureFinished) recognizer->reset(); @@ -386,8 +376,8 @@ void QGestureManager::recognizerTriggered(QGestureRecognizer::Result result) DEBUG() << "QGestureManager: maybe gesture: " << recognizer; if (activeGestures.contains(recognizer)) { QGestureEvent event(QList(), - QSet() << recognizer->gestureType()); - qt_sendGestureEvent(targetWidget, &event); + QSet() << recognizer->gestureType()); + sendGestureEvent(targetWidget, &event); } if (!maybeGestures.contains(recognizer)) { int timerId = startTimer(maximumGestureRecognitionTimeout); @@ -410,6 +400,17 @@ void QGestureManager::recognizerTriggered(QGestureRecognizer::Result result) } } +bool QGestureManager::sendGestureEvent(QWidget *receiver, QGestureEvent *event) +{ + QSet eventGestures; + foreach(const QString &gesture, event->gestureTypes()) + eventGestures << qHash(gesture); + + while (receiver && (receiver->d_func()->gestures & eventGestures).isEmpty()) + receiver = receiver->parentWidget(); + return receiver ? qt_sendSpontaneousEvent(receiver, event) : false; +} + QT_END_NAMESPACE #include "moc_qgesturemanager_p.cpp" diff --git a/src/gui/kernel/qgesturemanager_p.h b/src/gui/kernel/qgesturemanager_p.h index 762b70d..18eed71 100644 --- a/src/gui/kernel/qgesturemanager_p.h +++ b/src/gui/kernel/qgesturemanager_p.h @@ -82,9 +82,11 @@ protected: void timerEvent(QTimerEvent *event); private slots: - void recognizerTriggered(QGestureRecognizer::Result); + void recognizerStateChanged(QGestureRecognizer::Result); private: + bool sendGestureEvent(QWidget *receiver, QGestureEvent *event); + QSet activeGestures; QMap maybeGestures; QSet recognizers; diff --git a/src/gui/kernel/qgesturerecognizer.cpp b/src/gui/kernel/qgesturerecognizer.cpp new file mode 100644 index 0000000..9a00138 --- /dev/null +++ b/src/gui/kernel/qgesturerecognizer.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgesturerecognizer.h" +#include "qgesture.h" + +#include +#include + +QT_BEGIN_NAMESPACE + +QString qt_getStandardGestureTypeName(Qt::GestureType gestureType); + +QGestureRecognizerPrivate::QGestureRecognizerPrivate() + : gestureType(Qt::UnknownGesture) +{ +} + +QGestureRecognizer::QGestureRecognizer(const QString &type) + : QObject(*new QGestureRecognizerPrivate, 0) +{ + d_func()->customGestureType = type; +} + +QString QGestureRecognizer::gestureType() const +{ + Q_D(const QGestureRecognizer); + if (d->gestureType == Qt::UnknownGesture) + return d->customGestureType; + return qt_getStandardGestureTypeName(d->gestureType); +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qgesturerecognizer.h b/src/gui/kernel/qgesturerecognizer.h index ca8972b..c0d4f5e 100644 --- a/src/gui/kernel/qgesturerecognizer.h +++ b/src/gui/kernel/qgesturerecognizer.h @@ -42,7 +42,6 @@ #ifndef QGESTURERECOGNIZER_H #define QGESTURERECOGNIZER_H -#include "qgesture.h" #include "qevent.h" #include "qlist.h" #include "qset.h" @@ -59,18 +58,18 @@ QT_BEGIN_NAMESPACE Usually gesture recognizer implements state machine, storing its state internally in the recognizer object. The recognizer receives - input events through the QGestureRecognizer::recognize() virtual + input events through the QGestureRecognizer::filterEvent() virtual function and decides whether the parsed event should change the state of the recognizer - i.e. if the event starts or ends a gesture or if it isn't related to gesture at all. */ -/*! \fn Qt::GestureType gestureType() const +/*! \fn QString gestureType() const Returns the name of the gesture that is handled by the recognizer. */ -/*! \fn Result recognize(const QList &events) +/*! \fn Result filterEvent(const QEvent *event) This is a pure virtual function that need to be implemented in subclasses. @@ -79,7 +78,7 @@ QT_BEGIN_NAMESPACE sequence is a gesture or not. */ -/*! \fn QGesture* makeEvent() const +/*! \fn QGesture* getGesture() Creates a new gesture object that will be send to the widget. This function is called when the gesture recognizer returned a @@ -94,16 +93,20 @@ QT_BEGIN_NAMESPACE Resets the internal state of the gesture recognizer. */ -/*! \fn void triggered(QGestureRecognizer::Result result) +/*! \fn void stateChanged(QGestureRecognizer::Result result) The gesture recognizer might emit the signal when the gesture state changes asynchronously, i.e. without any event being received. */ +class QGesture; +class QGestureRecognizerPrivate; class Q_GUI_EXPORT QGestureRecognizer : public QObject { Q_OBJECT + Q_DECLARE_PRIVATE(QGestureRecognizer) + public: enum Result { @@ -113,21 +116,21 @@ public: MaybeGesture }; - inline QGestureRecognizer() { } - //### remove this ctor - inline QGestureRecognizer(const char *type) : type_(QLatin1String(type)) { } - inline QGestureRecognizer(const Qt::GestureType &type) : type_(type) { } - inline Qt::GestureType gestureType() const { return type_; } + explicit QGestureRecognizer(const QString &type); + + QString gestureType() const; - virtual Result recognize(const QList &events) = 0; - virtual QGesture* makeEvent() const = 0; + virtual Result filterEvent(const QEvent* event) = 0; + virtual QGesture* getGesture() = 0; virtual void reset() = 0; signals: - void triggered(QGestureRecognizer::Result result); + void stateChanged(QGestureRecognizer::Result result); -protected: - Qt::GestureType type_; +private: + friend class QDoubleTapGestureRecognizer; + friend class QTapAndHoldGestureRecognizer; + friend class QGestureRecognizerPan; }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qgesturerecognizer_p.h b/src/gui/kernel/qgesturerecognizer_p.h new file mode 100644 index 0000000..4d80b99 --- /dev/null +++ b/src/gui/kernel/qgesturerecognizer_p.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the $MODULE$ of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial Usage +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGESTURERECOGNIZER_P_H +#define QGESTURERECOGNIZER_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 + +QT_BEGIN_NAMESPACE + +class QGestureRecognizerPrivate : public QObjectPrivate +{ +public: + QGestureRecognizerPrivate(); + +public: + Qt::GestureType gestureType; + QString customGestureType; +}; + +QT_END_NAMESPACE + +#endif // QGESTURERECOGNIZER_P_H diff --git a/src/gui/kernel/qgesturestandardrecognizers.cpp b/src/gui/kernel/qgesturestandardrecognizers.cpp index 504786a..718bdfd 100644 --- a/src/gui/kernel/qgesturestandardrecognizers.cpp +++ b/src/gui/kernel/qgesturestandardrecognizers.cpp @@ -41,6 +41,7 @@ #include "qgesturestandardrecognizers_p.h" #include "qgesture_p.h" +#include "qgesturerecognizer_p.h" // #define GESTURE_RECOGNIZER_DEBUG #ifndef GESTURE_RECOGNIZER_DEBUG @@ -50,205 +51,92 @@ #endif QT_BEGIN_NAMESPACE -/* -QGestureRecognizerMouseTwoButtons::QGestureRecognizerMouseTwoButtons() - : QGestureRecognizer(Qt::MouseTwoButtonClick) -{ - clear(); -} -QGestureRecognizer::Result QGestureRecognizerMouseTwoButtons::recognize(const QList &inputEvents) +QString qt_getStandardGestureTypeName(Qt::GestureType gestureType) { - // get all mouse events - QList events; - for(int i = 0; i < inputEvents.count(); ++i) { - QEvent *event = inputEvents.at(i); - switch (event->type()) { - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - events.push_back(static_cast(event)); - default: - break; - } - } - - QGestureRecognizer::Result result = QGestureRecognizer::NotGesture; - for(int i = 0; i < events.count(); ++i) { - QMouseEvent *event = events.at(i); - if (event->type() == QEvent::MouseButtonPress) { - if (userEvents[3]) { - // something wrong, we already has a gesture. - clear(); - } else if (userEvents[2]) { - // 1d, 2d, 1u, and user press another button. not gesture. - DEBUG() << "1"; - result = QGestureRecognizer::NotGesture; - clear(); - break; - } else if (userEvents[1]) { - // 1d, 2d, and user pressed third button. not gesture. - DEBUG() << "2"; - result = QGestureRecognizer::NotGesture; - clear(); - break; - } else if (userEvents[0]) { - // second button press. - DEBUG() << "3"; - userEvents[1] = event; - result = QGestureRecognizer::MaybeGesture; - } else { - // first button press. - DEBUG() << "4"; - userEvents[0] = event; - result = QGestureRecognizer::MaybeGesture; - } - } else if (event->type() == QEvent::MouseButtonRelease) { - if (userEvents[3]) { - // something wrong, we already has a gesture. - clear(); - } else if (userEvents[2]) { - // 1d, 2d, 1u, and button release - DEBUG() << "5"; - if (userEvents[1]->button() != event->button()) { - // got weird buttonreleased event. doesn't look like gesture. - result = QGestureRecognizer::NotGesture; - clear(); - break; - } - // gesture! - userEvents[3] = event; - result = QGestureRecognizer::GestureFinished; - break; - } else if (userEvents[1]) { - // 1d, 2d, and button release - DEBUG() << "6"; - if (userEvents[0]->button() != event->button()) { - // user released the wrong button. not gesture. - result = QGestureRecognizer::NotGesture; - clear(); - break; - } - // user released the right button! looks like gesture - userEvents[2] = event; - result = QGestureRecognizer::MaybeGesture; - } else if (userEvents[0]) { - // 1d, and some button was released. not a gesture. - DEBUG() << "7"; - result = QGestureRecognizer::NotGesture; - clear(); - break; - } - } + switch (gestureType) { + case Qt::TapGesture: + return QLatin1String("__QTapGesture"); + case Qt::DoubleTapGesture: + return QLatin1String("__QDoubleTapGesture"); + case Qt::TrippleTapGesture: + return QLatin1String("__QTrippleTapGesture"); + case Qt::TapAndHoldGesture: + return QLatin1String("__QTapAndHoldGesture"); + case Qt::PanGesture: + return QLatin1String("__QPanGesture"); + case Qt::PinchGesture: + return QLatin1String("__QPinchGesture"); + case Qt::UnknownGesture: + break; } - return result; -} - -QGesture* QGestureRecognizerMouseTwoButtons::makeEvent() const -{ - if (!userEvents[0] || !userEvents[1] || !userEvents[2] || !userEvents[3]) - return 0; - QGesture::Direction direction = - (userEvents[0]->button() < userEvents[1]->button() ? - QGesture::Left : QGesture::Right); - QList points; - points.push_back(userEvents[0]->globalPos()); - points.push_back(userEvents[1]->globalPos()); - QGesture *gesture = - new QGesture(Qt::MouseTwoButtonClick, points.at(0), points.at(1), points.at(1), - direction, - QRect(points.at(0), points.at(1)), - points.at(0)); - return gesture; + qFatal("QGestureRecognizer::gestureType: got an unhandled gesture type."); + return QLatin1String("__unknown_gesture"); } -void QGestureRecognizerMouseTwoButtons::reset() -{ - clear(); -} - -void QGestureRecognizerMouseTwoButtons::clear() -{ - userEvents[0] = userEvents[1] = userEvents[2] = userEvents[3] = 0; -} -*/ - // // QGestureRecognizerPan // QGestureRecognizerPan::QGestureRecognizerPan() - : QGestureRecognizer(Qt::Pan), mousePressed(false), gestureFinished(false), + : QGestureRecognizer(QString()), mousePressed(false), gestureFinished(false), lastDirection(Direction::None), currentDirection(Direction::None) { + Q_D(QGestureRecognizer); + d->gestureType = Qt::PanGesture; } -QGestureRecognizer::Result QGestureRecognizerPan::recognize(const QList &inputEvents) +QGestureRecognizer::Result QGestureRecognizerPan::filterEvent(const QEvent *event) { - // get all mouse events - QList events; - for(int i = 0; i < inputEvents.count(); ++i) { - QEvent *event = inputEvents.at(i); - switch (event->type()) { - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - case QEvent::MouseMove: - events.push_back(static_cast(event)); - default: - break; - } - } - - QGestureRecognizer::Result result = QGestureRecognizer::NotGesture; - for(int i = 0; i < events.count(); ++i) { - QMouseEvent *event = events.at(i); - if (event->type() == QEvent::MouseButtonPress) { - if (currentDirection != Direction::None) { - DEBUG() << "Pan: MouseButtonPress: fail. another press during pan"; - result = QGestureRecognizer::NotGesture; - reset(); - break; - } - DEBUG() << "Pan: MouseButtonPress: maybe gesture started"; - result = QGestureRecognizer::MaybeGesture; - mousePressed = true; - pressedPos = lastPos = currentPos = event->pos(); - } else if (event->type() == QEvent::MouseButtonRelease) { - if (mousePressed && currentDirection != Direction::None) { - DEBUG() << "Pan: MouseButtonRelease: pan detected"; - result = QGestureRecognizer::GestureFinished; - gestureFinished = true; - currentPos = event->pos(); - internalReset(); - break; - } - DEBUG() << "Pan: MouseButtonRelease: some weird release detected, ignoring"; - result = QGestureRecognizer::NotGesture; + if (event->type() == QEvent::MouseButtonPress) { + const QMouseEvent *ev = static_cast(event); + if (currentDirection != Direction::None) { + DEBUG() << "Pan: MouseButtonPress: fail. another press during pan"; reset(); - break; - } else if (event->type() == QEvent::MouseMove) { - if (!mousePressed) - continue; - lastPos = currentPos; - currentPos = event->pos(); - Direction::DirectionType direction = - simpleRecognizer.addPosition(event->pos()).direction; - DEBUG() << "Pan: MouseMove: simplerecognizer result = " << direction; - if (currentDirection == Direction::None) { - if (direction == Direction::None) - result = QGestureRecognizer::MaybeGesture; - else - result = QGestureRecognizer::GestureStarted; - } else { + return QGestureRecognizer::NotGesture; + } + DEBUG() << "Pan: MouseButtonPress: maybe gesture started"; + mousePressed = true; + pressedPos = lastPos = currentPos = ev->pos(); + return QGestureRecognizer::MaybeGesture; + } else if (event->type() == QEvent::MouseButtonRelease) { + if (mousePressed && currentDirection != Direction::None) { + DEBUG() << "Pan: MouseButtonRelease: pan detected"; + gestureFinished = true; + const QMouseEvent *ev = static_cast(event); + currentPos = ev->pos(); + internalReset(); + return QGestureRecognizer::GestureFinished; + } + DEBUG() << "Pan: MouseButtonRelease: some weird release detected, ignoring"; + reset(); + return QGestureRecognizer::NotGesture; + } else if (event->type() == QEvent::MouseMove) { + if (!mousePressed) + return QGestureRecognizer::NotGesture; + const QMouseEvent *ev = static_cast(event); + lastPos = currentPos; + currentPos = ev->pos(); + Direction::DirectionType direction = + simpleRecognizer.addPosition(ev->pos()).direction; + DEBUG() << "Pan: MouseMove: simplerecognizer result = " << direction; + QGestureRecognizer::Result result = QGestureRecognizer::NotGesture; + if (currentDirection == Direction::None) { + if (direction == Direction::None) + result = QGestureRecognizer::MaybeGesture; + else result = QGestureRecognizer::GestureStarted; - } - if (direction != Direction::None) { - if (currentDirection != direction) - lastDirection = currentDirection; - currentDirection = direction; - } + } else { + result = QGestureRecognizer::GestureStarted; } + if (direction != Direction::None) { + if (currentDirection != direction) + lastDirection = currentDirection; + currentDirection = direction; + } + return result; } - return result; + return QGestureRecognizer::NotGesture; } static inline QPannableGesture::DirectionType convertPanningDirection(const Direction::DirectionType direction) @@ -268,17 +156,18 @@ static inline QPannableGesture::DirectionType convertPanningDirection(const Dire return QPannableGesture::None; } -QGesture* QGestureRecognizerPan::makeEvent() const +QGesture* QGestureRecognizerPan::getGesture() { QPannableGesture::DirectionType dir = convertPanningDirection(currentDirection); QPannableGesture::DirectionType lastDir = convertPanningDirection(lastDirection); if (dir == QPannableGesture::None) return 0; QPannableGesture *g = - new QPannableGesture(Qt::Pan, pressedPos, lastPos, currentPos, + new QPannableGesture(this, + pressedPos, lastPos, currentPos, QRect(), pressedPos, QDateTime(), 0, gestureFinished ? Qt::GestureFinished : Qt::GestureStarted); - QPannableGesturePrivate *d = (QPannableGesturePrivate*)g->d; + QPannableGesturePrivate *d = g->d_func(); d->lastDirection = lastDir; d->direction = dir; @@ -307,52 +196,37 @@ void QGestureRecognizerPan::internalReset() // QDoubleTapGestureRecognizer // QDoubleTapGestureRecognizer::QDoubleTapGestureRecognizer() - : QGestureRecognizer(Qt::DoubleTap) + : QGestureRecognizer(QString()) { + Q_D(QGestureRecognizer); + d->gestureType = Qt::DoubleTapGesture; } -QGestureRecognizer::Result QDoubleTapGestureRecognizer::recognize(const QList &inputEvents) +QGestureRecognizer::Result QDoubleTapGestureRecognizer::filterEvent(const QEvent *event) { - // get all mouse events - QList events; - for(int i = 0; i < inputEvents.count(); ++i) { - QEvent *event = inputEvents.at(i); - switch (event->type()) { - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - case QEvent::MouseButtonDblClick: - case QEvent::MouseMove: - events.push_back(static_cast(event)); - default: - break; - } - } - - QGestureRecognizer::Result result = QGestureRecognizer::NotGesture; - for(int i = 0; i < events.count(); ++i) { - QMouseEvent *event = events.at(i); - if (event->type() == QEvent::MouseButtonPress) { - if (pressedPosition.isNull()) { - result = QGestureRecognizer::MaybeGesture; - pressedPosition = event->pos(); - } else if ((pressedPosition - event->pos()).manhattanLength() < 10) { - result = QGestureRecognizer::GestureFinished; - } - } else if (event->type() == QEvent::MouseButtonRelease) { - if (!pressedPosition.isNull() && (pressedPosition - event->pos()).manhattanLength() < 10) - result = QGestureRecognizer::MaybeGesture; - } else if (event->type() == QEvent::MouseButtonDblClick) { - result = QGestureRecognizer::GestureFinished; - pressedPosition = event->pos(); - break; + if (event->type() == QEvent::MouseButtonPress) { + const QMouseEvent *ev = static_cast(event); + if (pressedPosition.isNull()) { + pressedPosition = ev->pos(); + return QGestureRecognizer::MaybeGesture; + } else if ((pressedPosition - ev->pos()).manhattanLength() < 10) { + return QGestureRecognizer::GestureFinished; } + } else if (event->type() == QEvent::MouseButtonRelease) { + const QMouseEvent *ev = static_cast(event); + if (!pressedPosition.isNull() && (pressedPosition - ev->pos()).manhattanLength() < 10) + return QGestureRecognizer::MaybeGesture; + } else if (event->type() == QEvent::MouseButtonDblClick) { + const QMouseEvent *ev = static_cast(event); + pressedPosition = ev->pos(); + return QGestureRecognizer::GestureFinished; } - return result; + return QGestureRecognizer::NotGesture; } -QGesture* QDoubleTapGestureRecognizer::makeEvent() const +QGesture* QDoubleTapGestureRecognizer::getGesture() { - return new QGesture(Qt::DoubleTap, + return new QGesture(this, qt_getStandardGestureTypeName(Qt::DoubleTapGesture), pressedPosition, pressedPosition, pressedPosition, QRect(), pressedPosition, QDateTime(), 0, Qt::GestureFinished); } @@ -363,195 +237,66 @@ void QDoubleTapGestureRecognizer::reset() } // -// QLongTapGestureRecognizer +// QTapAndHoldGestureRecognizer // -const int QLongTapGestureRecognizer::iterationCount = 40; -const int QLongTapGestureRecognizer::iterationTimeout = 50; +const int QTapAndHoldGestureRecognizer::iterationCount = 40; +const int QTapAndHoldGestureRecognizer::iterationTimeout = 50; -QLongTapGestureRecognizer::QLongTapGestureRecognizer() - : QGestureRecognizer(Qt::LongTap), iteration(0) +QTapAndHoldGestureRecognizer::QTapAndHoldGestureRecognizer() + : QGestureRecognizer(QString()), iteration(0) { + Q_D(QGestureRecognizer); + d->gestureType = Qt::TapAndHoldGesture; } -QGestureRecognizer::Result QLongTapGestureRecognizer::recognize(const QList &inputEvents) +QGestureRecognizer::Result QTapAndHoldGestureRecognizer::filterEvent(const QEvent *event) { - // get all mouse events - QList events; - for(int i = 0; i < inputEvents.count(); ++i) { - QEvent *event = inputEvents.at(i); - switch (event->type()) { - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - case QEvent::MouseMove: - events.push_back(static_cast(event)); - default: - break; - } - } - - QGestureRecognizer::Result result = QGestureRecognizer::NotGesture; - for(int i = 0; i < events.count(); ++i) { - QMouseEvent *event = events.at(i); - if (event->type() == QEvent::MouseButtonPress) { - if (timer.isActive()) - timer.stop(); - timer.start(QLongTapGestureRecognizer::iterationTimeout, this); - pressedPosition = event->pos(); - result = QGestureRecognizer::MaybeGesture; - } else if (event->type() == QEvent::MouseMove) { - if ((pressedPosition - event->pos()).manhattanLength() < 15) - result = QGestureRecognizer::GestureStarted; - else - result = QGestureRecognizer::NotGesture; - } else if (event->type() == QEvent::MouseButtonRelease) { - result = QGestureRecognizer::NotGesture; + if (event->type() == QEvent::MouseButtonPress) { + const QMouseEvent *ev = static_cast(event); + if (timer.isActive()) timer.stop(); - break; - } + timer.start(QTapAndHoldGestureRecognizer::iterationTimeout, this); + pressedPosition = ev->pos(); + return QGestureRecognizer::MaybeGesture; + } else if (event->type() == QEvent::MouseMove) { + const QMouseEvent *ev = static_cast(event); + if ((pressedPosition - ev->pos()).manhattanLength() < 15) + return QGestureRecognizer::GestureStarted; + else + return QGestureRecognizer::NotGesture; + } else if (event->type() == QEvent::MouseButtonRelease) { + timer.stop(); + return QGestureRecognizer::NotGesture; } - return result; + return QGestureRecognizer::NotGesture; } -void QLongTapGestureRecognizer::timerEvent(QTimerEvent *event) +void QTapAndHoldGestureRecognizer::timerEvent(QTimerEvent *event) { if (event->timerId() != timer.timerId()) return; - if (++iteration == QLongTapGestureRecognizer::iterationCount) { - emit triggered(QGestureRecognizer::GestureFinished); + if (++iteration == QTapAndHoldGestureRecognizer::iterationCount) { + emit stateChanged(QGestureRecognizer::GestureFinished); timer.stop(); } else { - emit triggered(QGestureRecognizer::GestureStarted); + emit stateChanged(QGestureRecognizer::GestureStarted); } } -QGesture* QLongTapGestureRecognizer::makeEvent() const +QGesture* QTapAndHoldGestureRecognizer::getGesture() { - return new QGesture(Qt::LongTap, + return new QGesture(this, qt_getStandardGestureTypeName(Qt::TapAndHoldGesture), pressedPosition, pressedPosition, pressedPosition, QRect(), pressedPosition, QDateTime(), 0, - iteration >= QLongTapGestureRecognizer::iterationCount ? + iteration >= QTapAndHoldGestureRecognizer::iterationCount ? Qt::GestureFinished : Qt::GestureStarted); } -void QLongTapGestureRecognizer::reset() +void QTapAndHoldGestureRecognizer::reset() { pressedPosition = QPoint(); timer.stop(); iteration = 0; } -// -// QMultiTouchGestureRecognizer -// - -/* -QMultiTouchGestureRecognizer::QMultiTouchGestureRecognizer() - : QGestureRecognizer(Qt::Pinch) -{ -} - -QGestureRecognizer::Result QMultiTouchGestureRecognizer::recognize(const QList &inputEvents) -{ - QGestureRecognizer::Result result = QGestureRecognizer::NotGesture; - for(int i = 0; i < inputEvents.count(); ++i) { - QEvent *inputEvent = inputEvents.at(i); - if (inputEvent->type() != QEvent::Pointer) { - if (touches.size() == 2) - result = QGestureRecognizer::GestureStarted; - else if (touches.size() == 1) - result = QGestureRecognizer::MaybeGesture; - continue; - } - QPointerEvent *event = static_cast(inputEvent); - Q_ASSERT(event->pointerCount() > 0); - for (int idx = 0; idx < event->pointerCount(); ++idx) { - switch (event->state(idx)) { - case QPointerEvent::Begin: - qDebug() << "Begin" << idx; - if (touches.size() == 2) { - // too many touches - qDebug() << "too many touches"; - result = QGestureRecognizer::MaybeGesture; - continue; - } - touches[event->pointerId(idx)].startPosition = event->pos(idx); - if (touches.size() == 1) { - result = QGestureRecognizer::MaybeGesture; - } else if (touches.size() == 2) { - result = QGestureRecognizer::GestureStarted; - } else { - result = QGestureRecognizer::NotGesture; - } - break; - - case QPointerEvent::Move: - qDebug() << "Move" << idx; - touches[event->pointerId(idx)].lastPosition = touches[event->pointerId(idx)].currentPosition; - touches[event->pointerId(idx)].currentPosition = event->pos(idx); - if (touches.size() == 1) - result = QGestureRecognizer::MaybeGesture; - else if (touches.size() == 2) - result = QGestureRecognizer::GestureStarted; - else - result = QGestureRecognizer::NotGesture; - break; - - case QPointerEvent::End: - qDebug() << "End" << idx; - touches.remove(event->pointerId(idx)); - if (touches.size() == 1) { - result = QGestureRecognizer::MaybeGesture; - } else if (touches.size() == 0) { - result = QGestureRecognizer::NotGesture; - } else { - qDebug() << "unexpected touch end event"; - return QGestureRecognizer::NotGesture; - } - break; - - case QPointerEvent::Stationary: - qDebug() << "Stationary" << idx; - if (touches.size() == 2) - result = QGestureRecognizer::GestureStarted; - else if (touches.size() == 1) - result = QGestureRecognizer::MaybeGesture; - break; - - default: - break; - } - } - } - return result; -} - -QGesture* QMultiTouchGestureRecognizer::makeEvent() const -{ - if (touches.size() != 2) - return 0; - - QGesture *g = new QGesture(Qt::Pinch); - QGesture::Data data; - - TapMap::const_iterator it = touches.begin(); - data.startPos = it->startPosition.toPoint(); - data.lastPos = it->lastPosition.toPoint(); - data.currentPos = it->currentPosition.toPoint(); - g->datas.push_back(data); - - ++it; - data.startPos = it->startPosition.toPoint(); - data.lastPos = it->lastPosition.toPoint(); - data.currentPos = it->currentPosition.toPoint(); - g->datas.push_back(data); - - return g; -} - -void QMultiTouchGestureRecognizer::reset() -{ - touches.clear(); -} -*/ - QT_END_NAMESPACE diff --git a/src/gui/kernel/qgesturestandardrecognizers_p.h b/src/gui/kernel/qgesturestandardrecognizers_p.h index 567cf65..75a206a 100644 --- a/src/gui/kernel/qgesturestandardrecognizers_p.h +++ b/src/gui/kernel/qgesturestandardrecognizers_p.h @@ -62,34 +62,14 @@ QT_BEGIN_NAMESPACE -/* -class QGestureRecognizerMouseTwoButtons : public QGestureRecognizer -{ - Q_OBJECT -public: - QGestureRecognizerMouseTwoButtons(); - QGestureRecognizer::Result recognize(const QList &inputEvents); - - QGesture* makeEvent() const; - void reset(); - -private: - void clear(); - - // find the last two button click events - QMouseEvent* userEvents[4]; -}; -*/ - class QGestureRecognizerPan : public QGestureRecognizer { Q_OBJECT public: QGestureRecognizerPan(); - QGestureRecognizer::Result recognize(const QList &inputEvents); - QGesture* makeEvent() const; - + QGestureRecognizer::Result filterEvent(const QEvent *event); + QGesture* getGesture(); void reset(); private: @@ -112,22 +92,22 @@ class QDoubleTapGestureRecognizer : public QGestureRecognizer public: QDoubleTapGestureRecognizer(); - QGestureRecognizer::Result recognize(const QList &inputEvents); - QGesture* makeEvent() const; + QGestureRecognizer::Result filterEvent(const QEvent *event); + QGesture* getGesture(); void reset(); private: QPoint pressedPosition; }; -class QLongTapGestureRecognizer : public QGestureRecognizer +class QTapAndHoldGestureRecognizer : public QGestureRecognizer { Q_OBJECT public: - QLongTapGestureRecognizer(); + QTapAndHoldGestureRecognizer(); - QGestureRecognizer::Result recognize(const QList &inputEvents); - QGesture* makeEvent() const; + QGestureRecognizer::Result filterEvent(const QEvent *event); + QGesture* getGesture(); void reset(); protected: @@ -141,30 +121,6 @@ private: static const int iterationTimeout; }; -/* -class QMultiTouchGestureRecognizer : public QGestureRecognizer -{ - Q_OBJECT -public: - QMultiTouchGestureRecognizer(); - - QMap maybeGestureCompletion(); - QGestureRecognizer::Result recognize(const QList &inputEvents); - QGesture* makeEvent() const; - void reset(); - -private: - struct Tap { - //### should I use QPointF everywhere internally ?? - QPointF startPosition; - QPointF lastPosition; - QPointF currentPosition; - }; - typedef QMap TapMap; - TapMap touches; -}; -*/ - QT_END_NAMESPACE #endif // QGESTURESTANDARDRECOGNIZERS_P_H diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index aea0003..2f794f4 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -127,6 +127,8 @@ Q_GUI_EXPORT void qt_x11_set_global_double_buffer(bool enable) } #endif +QString qt_getStandardGestureTypeName(Qt::GestureType); + static inline bool qRectIntersects(const QRect &r1, const QRect &r2) { return (qMax(r1.left(), r2.left()) <= qMin(r1.right(), r2.right()) && @@ -11026,60 +11028,56 @@ QWindowSurface *QWidget::windowSurface() const } /*! - \fn void QWidget::grabGesture(const Qt::GestureType &gesture) - Subscribes the widget to the specified \a gesture type. + + Returns the id of the gesture. */ -void QWidget::grabGesture(const Qt::GestureType &gesture) +int QWidget::grabGesture(const QString &gesture) { Q_D(QWidget); - if (d->gestures.contains(gesture)) - return; - d->gestures << gesture; - ++qApp->d_func()->grabbedGestures[gesture]; + return d->grabGesture(qHash(gesture)); +} + +int QWidgetPrivate::grabGesture(int id) +{ + QSet::iterator it = gestures.find(id); + if (it != gestures.end()) + return *it; + gestures << id; + ++qApp->d_func()->grabbedGestures[id]; + return id; } /*! - \fn void QWidget::grabGestures(const QSet &gestures) + Subscribes the widget to the specified \a gesture type. - Subscribes the widget to the specified list of \a gestures. + Returns the id of the gesture. */ -void QWidget::grabGestures(const QSet &gestures) + +int QWidget::grabGesture(Qt::GestureType gesture) { - Q_D(QWidget); - foreach(const Qt::GestureType &gesture, gestures) { - if (!d->gestures.contains(gesture)) - ++qApp->d_func()->grabbedGestures[gesture]; - } - d->gestures.unite(gestures); + return grabGesture(qt_getStandardGestureTypeName(gesture)); } /*! - \fn void QWidget::releaseGesture(const Qt::GestureType &gesture) - - Unsubscribes the widget from the specified \a gesture type. + Unsubscribes the widget from a gesture, which is specified by its + \a id. */ -void QWidget::releaseGesture(const Qt::GestureType &gesture) +void QWidget::releaseGesture(int gestureId) { Q_D(QWidget); - QMap::iterator it = - qApp->d_func()->grabbedGestures.find(gesture); - if (it != qApp->d_func()->grabbedGestures.end() && - d->gestures.contains(gesture)) - ++it.value(); - d->gestures.remove(gesture); + QSet::iterator it = d->gestures.find(gestureId); + if (it != d->gestures.end()) { + Q_ASSERT(qApp->d_func()->grabbedGestures[gestureId] > 0); + --qApp->d_func()->grabbedGestures[gestureId]; + d->gestures.erase(it); + } } -/*! - \fn QSet QWidget::gestures() const - - Returns a list of gestures that the widget is subscribed to. -*/ -QSet QWidget::gestures() const +void setGestureEnabled(int gestureId, bool enable) { - Q_D(const QWidget); - return d->gestures; + //### } void QWidgetPrivate::getLayoutItemMargins(int *left, int *top, int *right, int *bottom) const diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h index e36b966..a76c50a 100644 --- a/src/gui/kernel/qwidget.h +++ b/src/gui/kernel/qwidget.h @@ -613,10 +613,10 @@ public: void setWindowSurface(QWindowSurface *surface); QWindowSurface *windowSurface() const; - void grabGesture(const Qt::GestureType &gesture); - void grabGestures(const QSet &gestures); - void releaseGesture(const Qt::GestureType &gesture); - QSet gestures() const; + int grabGesture(const QString &gesture); + int grabGesture(Qt::GestureType gesture); + void releaseGesture(int gestureId); + void setGestureEnabled(int gestureId, bool enable); Q_SIGNALS: void customContextMenuRequested(const QPoint &pos); @@ -755,6 +755,7 @@ private: friend bool isWidgetOpaque(const QWidget *); friend class QGLWidgetPrivate; #endif + friend class QGestureManager; #ifdef Q_WS_X11 friend void qt_net_update_user_time(QWidget *tlw, unsigned long timestamp); friend void qt_net_remove_user_time(QWidget *tlw); diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 178f7ba..abd7b8a 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -593,7 +593,8 @@ public: uint isGLWidget : 1; #endif - QSet gestures; + QSet gestures; + int grabGesture(int gestureId); #if defined(Q_WS_X11) || defined (Q_WS_WIN) || defined(Q_WS_MAC) #ifdef Q_WS_MAC -- cgit v0.12 From 32164d09d8647995e6177efec967ace799b7c528 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Fri, 13 Mar 2009 19:15:35 +0100 Subject: De-inlined functions in gesture events. --- src/gui/graphicsview/qgraphicssceneevent.cpp | 69 +++++++++++++++++++++------- src/gui/graphicsview/qgraphicssceneevent.h | 22 ++++----- src/gui/kernel/qevent.cpp | 37 +++++++++++++++ src/gui/kernel/qevent.h | 22 ++++----- 4 files changed, 110 insertions(+), 40 deletions(-) diff --git a/src/gui/graphicsview/qgraphicssceneevent.cpp b/src/gui/graphicsview/qgraphicssceneevent.cpp index 4d9e7bb..4f24a74 100644 --- a/src/gui/graphicsview/qgraphicssceneevent.cpp +++ b/src/gui/graphicsview/qgraphicssceneevent.cpp @@ -304,6 +304,8 @@ QT_BEGIN_NAMESPACE +QString qt_getStandardGestureTypeName(Qt::GestureType type); + class QGraphicsSceneEventPrivate { public: @@ -1725,45 +1727,80 @@ void QGraphicsSceneMoveEvent::setNewPos(const QPointF &pos) gestures with \l{QGraphicsItem::}{grabGesture()}. */ -/*! \fn bool QGraphicsSceneGestureEvent::contains(const Qt::GestureType &type) const +QGraphicsSceneGestureEvent::QGraphicsSceneGestureEvent() + : QGraphicsSceneEvent(QEvent::GraphicsSceneGesture) +{ +} + +QGraphicsSceneGestureEvent::~QGraphicsSceneGestureEvent() +{ +} + +/*! Checks if the gesture event contains gesture of specific \a type. */ +bool QGraphicsSceneGestureEvent::contains(const QString &type) const +{ + return gesture(type) != 0; +} -/*! \fn QList QGraphicsSceneGestureEvent::gestureTypes() const +/*! + Checks if the gesture event contains gesture of specific \a type. +*/ +bool QGraphicsSceneGestureEvent::contains(Qt::GestureType type) const +{ + return contains(qt_getStandardGestureTypeName(type)); +} +/*! Returns a list of gesture names that the event contains. */ +QList QGraphicsSceneGestureEvent::gestureTypes() const +{ + return m_gestures.keys(); +} -/*! \fn const QGesture* QGraphicsSceneGestureEvent::gesture(const Qt::GestureType &type) const - +/*! Returns extended information about a gesture of specific \a type. */ +const QGesture* QGraphicsSceneGestureEvent::gesture(const QString &type) const +{ + return m_gestures.value(type, QSharedPointer()).data(); +} -/*! \fn QList > QGraphicsSceneGestureEvent::gestures() const +/*! + Returns extended information about a gesture of specific \a type. +*/ +const QGesture* QGraphicsSceneGestureEvent::gesture(Qt::GestureType type) const +{ + return gesture(qt_getStandardGestureTypeName(type)); +} +/*! Returns extended information about all triggered gestures. */ +QList > QGraphicsSceneGestureEvent::gestures() const +{ + return m_gestures.values(); +} -/*! \fn QSet QGraphicsSceneGestureEvent::cancelledGestures() const - +/*! Returns a set of gesture names that used to be executed, but got cancelled (i.e. they were not finished properly). */ +QSet QGraphicsSceneGestureEvent::cancelledGestures() const +{ + return m_cancelledGestures; +} -/*! \fn void QGraphicsSceneGestureEvent::setCancelledGestures(const QSet &) - +/*! Returns a set of gesture names that used to be executed, but got cancelled (i.e. they were not finished properly). */ - -QGraphicsSceneGestureEvent::QGraphicsSceneGestureEvent() - : QGraphicsSceneEvent(QEvent::GraphicsSceneGesture) -{ -} - -QGraphicsSceneGestureEvent::~QGraphicsSceneGestureEvent() +void QGraphicsSceneGestureEvent::setCancelledGestures(const QSet &cancelledGestures) { + m_cancelledGestures = cancelledGestures; } /*! diff --git a/src/gui/graphicsview/qgraphicssceneevent.h b/src/gui/graphicsview/qgraphicssceneevent.h index 4d88cda..d1a301e 100644 --- a/src/gui/graphicsview/qgraphicssceneevent.h +++ b/src/gui/graphicsview/qgraphicssceneevent.h @@ -317,20 +317,18 @@ public: QGraphicsSceneGestureEvent(); ~QGraphicsSceneGestureEvent(); - inline bool contains(const QString &type) const - { return gesture(type) != 0; } - inline QList gestureTypes() const - { return m_gestures.keys(); } - inline const QGesture* gesture(const QString &type) const - { return m_gestures.value(type, QSharedPointer()).data(); } - inline QList > gestures() const - { return m_gestures.values(); } + bool contains(const QString &type) const; + bool contains(Qt::GestureType type) const; + + QList gestureTypes() const; + + const QGesture* gesture(Qt::GestureType type) const; + const QGesture* gesture(const QString &type) const; + QList > gestures() const; void setGestures(const QList > &gestures); - inline QSet cancelledGestures() const - { return m_cancelledGestures; } - void setCancelledGestures(const QSet &cancelledGestures) - { m_cancelledGestures = cancelledGestures; } + QSet cancelledGestures() const; + void setCancelledGestures(const QSet &cancelledGestures); QPointF mapToScene(const QPoint &point) const; QPolygonF mapToScene(const QRect &rect) const; diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 225d8b1..5761939 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -52,6 +52,8 @@ QT_BEGIN_NAMESPACE +QString qt_getStandardGestureTypeName(Qt::GestureType type); + /*! \class QInputEvent \ingroup events @@ -3572,6 +3574,41 @@ QGestureEvent::~QGestureEvent() { } +bool QGestureEvent::contains(Qt::GestureType type) const +{ + return contains(qt_getStandardGestureTypeName(type)); +} + +bool QGestureEvent::contains(const QString &type) const +{ + return gesture(type) != 0; +} + +QList QGestureEvent::gestureTypes() const +{ + return m_gestures.keys(); +} + +const QGesture* QGestureEvent::gesture(Qt::GestureType type) const +{ + return gesture(qt_getStandardGestureTypeName(type)); +} + +const QGesture* QGestureEvent::gesture(const QString &type) const +{ + return m_gestures.value(type, QSharedPointer()).data(); +} + +QList > QGestureEvent::gestures() const +{ + return m_gestures.values(); +} + +QSet QGestureEvent::cancelledGestures() const +{ + return m_cancelledGestures; +} + /*! \class QTouchEvent \brief The QTouchEvent class contains parameters that describe a touch event . diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index db3d03f..48e420a 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -723,18 +723,16 @@ public: QGestureEvent(const QGestureEvent &gestures, const QPoint &offset); ~QGestureEvent(); - inline bool contains(const QString &type) const - { return gesture(type) != 0; } - inline QList gestureTypes() const - { return m_gestures.keys(); } - - inline const QGesture* gesture(const QString &type) const - { return m_gestures.value(type, QSharedPointer()).data(); } - inline QList > gestures() const - { return m_gestures.values(); } - - inline QSet cancelledGestures() const - { return m_cancelledGestures; } + bool contains(Qt::GestureType type) const; + bool contains(const QString &type) const; + + QList gestureTypes() const; + + const QGesture* gesture(Qt::GestureType type) const; + const QGesture* gesture(const QString &type) const; + QList > gestures() const; + + QSet cancelledGestures() const; protected: QHash > m_gestures; -- cgit v0.12 From 04bb61d39f56fb7a980bda26241b86a8c41724de Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Fri, 13 Mar 2009 19:29:05 +0100 Subject: Gesture examples compile now. --- .../collidingmice/gesturerecognizerlinjazax.cpp | 114 +++++++++------------ .../collidingmice/gesturerecognizerlinjazax.h | 4 +- examples/gestures/collidingmice/linjazaxgesture.h | 17 +-- examples/gestures/collidingmice/main.cpp | 4 +- examples/gestures/graphicsview/main.cpp | 10 +- examples/gestures/imageviewer/imagewidget.cpp | 20 ++-- 6 files changed, 77 insertions(+), 92 deletions(-) diff --git a/examples/gestures/collidingmice/gesturerecognizerlinjazax.cpp b/examples/gestures/collidingmice/gesturerecognizerlinjazax.cpp index 3f90588..41bb113 100644 --- a/examples/gestures/collidingmice/gesturerecognizerlinjazax.cpp +++ b/examples/gestures/collidingmice/gesturerecognizerlinjazax.cpp @@ -60,83 +60,67 @@ void DirectionSimpleRecognizer::reset() /////////////////////////////////////////////////////////////////////////// GestureRecognizerLinjaZax::GestureRecognizerLinjaZax() - : QGestureRecognizer("LinjaZax"), mousePressed(false), gestureFinished(false), + : QGestureRecognizer(QLatin1String("LinjaZax")), mousePressed(false), gestureFinished(false), zoomState(LinjaZaxGesture::NoZoom) { } -QGestureRecognizer::Result GestureRecognizerLinjaZax::recognize(const QList &inputEvents) +QGestureRecognizer::Result GestureRecognizerLinjaZax::filterEvent(const QEvent *event) { - // get all mouse events - QList events; - for(int i = 0; i < inputEvents.count(); ++i) { - QEvent *event = inputEvents.at(i); - switch (event->type()) { - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - case QEvent::MouseMove: - events.push_back(static_cast(event)); - default: - break; - } - } - if (zoomState != LinjaZaxGesture::NoZoom && !lastDirections.isEmpty()) { lastDirections = lastDirections.right(1); zoomState = LinjaZaxGesture::NoZoom; } - QGestureRecognizer::Result result = QGestureRecognizer::NotGesture; - for(int i = 0; i < events.count(); ++i) { - QMouseEvent *event = events.at(i); - if (event->type() == QEvent::MouseButtonPress) { - if (!currentDirection.isEmpty()) { - result = QGestureRecognizer::NotGesture; - reset(); - break; - } - result = QGestureRecognizer::MaybeGesture; - mousePressed = true; - pressedPos = lastPos = currentPos = event->pos(); - } else if (event->type() == QEvent::MouseButtonRelease) { - if (mousePressed && !currentDirection.isEmpty()) { - result = QGestureRecognizer::GestureFinished; - gestureFinished = true; - currentPos = event->pos(); - internalReset(); - break; - } - result = QGestureRecognizer::NotGesture; + if (event->type() == QEvent::MouseButtonPress) { + if (!currentDirection.isEmpty()) { reset(); - break; - } else if (event->type() == QEvent::MouseMove) { - if (!mousePressed) - continue; - lastPos = currentPos; - currentPos = event->pos(); - QString direction = - simpleRecognizer.addPosition(event->pos()).direction; - if (currentDirection.isEmpty()) { - if (direction.isEmpty()) - result = QGestureRecognizer::MaybeGesture; - else - result = QGestureRecognizer::GestureStarted; - } else { + return QGestureRecognizer::NotGesture; + } + mousePressed = true; + const QMouseEvent *ev = static_cast(event); + pressedPos = lastPos = currentPos = ev->pos(); + return QGestureRecognizer::MaybeGesture; + } else if (event->type() == QEvent::MouseButtonRelease) { + const QMouseEvent *ev = static_cast(event); + if (mousePressed && !currentDirection.isEmpty()) { + gestureFinished = true; + currentPos = ev->pos(); + internalReset(); + return QGestureRecognizer::GestureFinished; + } + reset(); + return QGestureRecognizer::NotGesture; + } else if (event->type() == QEvent::MouseMove) { + if (!mousePressed) + return QGestureRecognizer::NotGesture; + lastPos = currentPos; + const QMouseEvent *ev = static_cast(event); + currentPos = ev->pos(); + QString direction = + simpleRecognizer.addPosition(ev->pos()).direction; + QGestureRecognizer::Result result = QGestureRecognizer::NotGesture; + if (currentDirection.isEmpty()) { + if (direction.isEmpty()) + result = QGestureRecognizer::MaybeGesture; + else result = QGestureRecognizer::GestureStarted; - } - if (!direction.isEmpty()) { - lastDirections.append(direction); - currentDirection = direction; - if (lastDirections.length() > 5) - lastDirections.remove(0, 1); - if (lastDirections.contains("248") || lastDirections.contains("2448")) - zoomState = LinjaZaxGesture::ZoomingIn; - else if (lastDirections.contains("268") || lastDirections.contains("2668")) - zoomState = LinjaZaxGesture::ZoomingOut; - } + } else { + result = QGestureRecognizer::GestureStarted; + } + if (!direction.isEmpty()) { + lastDirections.append(direction); + currentDirection = direction; + if (lastDirections.length() > 5) + lastDirections.remove(0, 1); + if (lastDirections.contains("248") || lastDirections.contains("2448")) + zoomState = LinjaZaxGesture::ZoomingIn; + else if (lastDirections.contains("268") || lastDirections.contains("2668")) + zoomState = LinjaZaxGesture::ZoomingOut; } + return result; } - return result; + return QGestureRecognizer::NotGesture; } static inline LinjaZaxGesture::DirectionType convertPanningDirection(const QString &direction) @@ -154,14 +138,14 @@ static inline LinjaZaxGesture::DirectionType convertPanningDirection(const QStri return LinjaZaxGesture::None; } -QGesture* GestureRecognizerLinjaZax::makeEvent() const +QGesture* GestureRecognizerLinjaZax::getGesture() { LinjaZaxGesture::DirectionType dir = convertPanningDirection(currentDirection); LinjaZaxGesture::DirectionType lastDir = convertPanningDirection(lastDirections.right(1)); if (dir == LinjaZaxGesture::None) return 0; LinjaZaxGesture *g = - new LinjaZaxGesture("LinjaZax", pressedPos, lastPos, currentPos, + new LinjaZaxGesture(this, pressedPos, lastPos, currentPos, QRect(), pressedPos, QDateTime(), 0, gestureFinished ? Qt::GestureFinished : Qt::GestureStarted); g->lastDirection_ = lastDir; diff --git a/examples/gestures/collidingmice/gesturerecognizerlinjazax.h b/examples/gestures/collidingmice/gesturerecognizerlinjazax.h index 6579059..07172f1 100644 --- a/examples/gestures/collidingmice/gesturerecognizerlinjazax.h +++ b/examples/gestures/collidingmice/gesturerecognizerlinjazax.h @@ -43,8 +43,8 @@ class GestureRecognizerLinjaZax : public QGestureRecognizer public: GestureRecognizerLinjaZax(); - QGestureRecognizer::Result recognize(const QList &inputEvents); - QGesture* makeEvent() const; + QGestureRecognizer::Result filterEvent(const QEvent *event); + QGesture* getGesture(); void reset(); diff --git a/examples/gestures/collidingmice/linjazaxgesture.h b/examples/gestures/collidingmice/linjazaxgesture.h index 9601675..8a7cb23 100644 --- a/examples/gestures/collidingmice/linjazaxgesture.h +++ b/examples/gestures/collidingmice/linjazaxgesture.h @@ -31,13 +31,16 @@ public: }; public: - explicit LinjaZaxGesture(const Qt::GestureType &type, Qt::GestureState state = Qt::GestureStarted) - : QGesture(type, state), lastDirection_(None), direction_(None), zoomState_(NoZoom) { } - LinjaZaxGesture(const Qt::GestureType &type, const QPoint &startPos, - const QPoint &lastPos, const QPoint &pos, const QRect &rect, - const QPoint &hotSpot, const QDateTime &startTime, - uint duration, Qt::GestureState state) - : QGesture(type, startPos, lastPos, pos, rect, hotSpot, startTime, duration, state) { } + explicit LinjaZaxGesture(QObject *parent, + Qt::GestureState state = Qt::GestureStarted) + : QGesture(parent, QLatin1String("LinjaZax"), state), lastDirection_(None), + direction_(None), zoomState_(NoZoom) { } + LinjaZaxGesture(QObject *parent, const QPoint &startPos, + const QPoint &lastPos, const QPoint &pos, const QRect &rect, + const QPoint &hotSpot, const QDateTime &startTime, + uint duration, Qt::GestureState state) + : QGesture(parent, QLatin1String("LinjaZax"), startPos, lastPos, + pos, rect, hotSpot, startTime, duration, state) { } ~LinjaZaxGesture() { } DirectionType lastDirection() const diff --git a/examples/gestures/collidingmice/main.cpp b/examples/gestures/collidingmice/main.cpp index d6dbdb0..e8ef13f 100644 --- a/examples/gestures/collidingmice/main.cpp +++ b/examples/gestures/collidingmice/main.cpp @@ -62,7 +62,7 @@ public: PannableGraphicsView(QGraphicsScene *scene, QWidget *parent = 0) : QGraphicsView(scene, parent) { - grabGesture("LinjaZax"); + grabGesture(QLatin1String("LinjaZax")); #ifdef ZOOMING_ANIMATION timeline = new QTimeLine(700, this); timeline->setFrameRange(0, AnimationSteps); @@ -74,7 +74,7 @@ protected: { if (event->type() == QEvent::Gesture) { QGestureEvent *ge = static_cast(event); - const LinjaZaxGesture *g = dynamic_cast(ge->gesture("LinjaZax")); + const LinjaZaxGesture *g = static_cast(ge->gesture("LinjaZax")); if (g) { switch (g->zoomState()) { case LinjaZaxGesture::ZoomingIn: diff --git a/examples/gestures/graphicsview/main.cpp b/examples/gestures/graphicsview/main.cpp index 1b325ee..1a40805 100644 --- a/examples/gestures/graphicsview/main.cpp +++ b/examples/gestures/graphicsview/main.cpp @@ -46,14 +46,14 @@ class PannableGraphicsView : public QGraphicsView public: PannableGraphicsView() { - grabGesture(Qt::Pan); + grabGesture(Qt::PanGesture); } protected: bool event(QEvent *event) { if (event->type() == QEvent::Gesture) { - QGestureEvent *ge = static_cast(event); - if (const QPannableGesture *g = dynamic_cast(ge->gesture(Qt::Pan))) { + QGestureEvent *gestureEvent = static_cast(event); + if (const QGesture *g = gestureEvent->gesture(Qt::PanGesture)) { QPoint pt = g->pos() - g->lastPos(); horizontalScrollBar()->setValue(horizontalScrollBar()->value() - pt.x()); verticalScrollBar()->setValue(verticalScrollBar()->value() - pt.y()); @@ -71,7 +71,7 @@ public: ImageItem() : colored(false) { - grabGesture(Qt::DoubleTap); + grabGesture(Qt::DoubleTapGesture); } QRectF boundingRect() const @@ -96,7 +96,7 @@ public: { if (event->type() == QEvent::GraphicsSceneGesture) { QGraphicsSceneGestureEvent *gestureEvent = static_cast(event); - if (gestureEvent->gesture(Qt::DoubleTap)) { + if (gestureEvent->gesture(Qt::DoubleTapGesture)) { event->accept(); colored = !colored; update(); diff --git a/examples/gestures/imageviewer/imagewidget.cpp b/examples/gestures/imageviewer/imagewidget.cpp index 0db62bb..1a341a5 100644 --- a/examples/gestures/imageviewer/imagewidget.cpp +++ b/examples/gestures/imageviewer/imagewidget.cpp @@ -61,9 +61,9 @@ ImageWidget::ImageWidget(QWidget *parent) horizontalOffset = 0; verticalOffset = 0; - grabGesture(Qt::DoubleTap); - grabGesture(Qt::Pan); - grabGesture(Qt::LongTap); + grabGesture(Qt::DoubleTapGesture); + grabGesture(Qt::PanGesture); + grabGesture(Qt::TapAndHoldGesture); } void ImageWidget::paintEvent(QPaintEvent*) @@ -136,16 +136,16 @@ void ImageWidget::gestureEvent(QGestureEvent *event) touchFeedback.doubleTapped = false; Q_ASSERT(event); - if (event->contains(Qt::Tap)) { + if (event->contains(Qt::TapGesture)) { // - } else if (const QGesture *g = event->gesture(Qt::DoubleTap)) { + } else if (const QGesture *g = event->gesture(Qt::DoubleTapGesture)) { touchFeedback.doubleTapped = true; horizontalOffset = g->hotSpot().x() - currentImage.width()*1.0*g->hotSpot().x()/width(); verticalOffset = g->hotSpot().y() - currentImage.height()*1.0*g->hotSpot().y()/height(); setZoomedIn(!zoomedIn); zoomed = rotated = false; updateImage(); - } else if (const QGesture *g = event->gesture(Qt::Pan)) { + } else if (const QGesture *g = event->gesture(Qt::PanGesture)) { if (zoomedIn) { // usual panning #ifndef QT_NO_CURSOR @@ -161,8 +161,8 @@ void ImageWidget::gestureEvent(QGestureEvent *event) update(); } else { // only slide gesture should be accepted - const QPannableGesture *pg = dynamic_cast(g); - if (pg && pg->direction() != pg->lastDirection()) { + const QPannableGesture *pg = static_cast(g); + if (pg->direction() != pg->lastDirection()) { // ###: event->cancel(); } if (g->state() == Qt::GestureFinished) { @@ -178,7 +178,7 @@ void ImageWidget::gestureEvent(QGestureEvent *event) updateImage(); } } - } else if (const QGesture *g = event->gesture(Qt::LongTap)) { + } else if (const QGesture *g = event->gesture(Qt::TapAndHoldGesture)) { if (g->state() == Qt::GestureFinished) { qDebug() << "tap and hold detected"; touchFeedback.reset(); @@ -190,8 +190,6 @@ void ImageWidget::gestureEvent(QGestureEvent *event) menu.addAction("Action 3"); menu.exec(mapToGlobal(g->hotSpot())); } - } else if (const QGesture *g = event->gesture(Qt::LongTap)) { - qDebug() << "long tap: " << (g->state() == Qt::GestureStarted ? "started" : "finished"); } else { qDebug() << "unknown gesture"; } -- cgit v0.12 From d8e4d20f3d225a3c29168d7a9440f2efc129ea8e Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Mon, 16 Mar 2009 11:54:28 +0100 Subject: Added meta-object properties to QGesture object. --- src/gui/kernel/qgesture.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h index f20a63c..8bd312b 100644 --- a/src/gui/kernel/qgesture.h +++ b/src/gui/kernel/qgesture.h @@ -60,6 +60,15 @@ class Q_GUI_EXPORT QGesture : public QObject { Q_OBJECT Q_DECLARE_PRIVATE(QGesture) + + Q_PROPERTY(QRect rect READ rect) + Q_PROPERTY(QPoint hotSpot READ hotSpot) + Q_PROPERTY(QDateTime startTime READ startTime) + Q_PROPERTY(uint duration READ duration) + Q_PROPERTY(QPoint startPos READ startPos) + Q_PROPERTY(QPoint lastPos READ lastPos) + Q_PROPERTY(QPoint pos READ pos) + public: explicit QGesture(QObject *parent, const QString &type, Qt::GestureState state = Qt::GestureStarted); -- cgit v0.12 From d392c3073c10d053ffcd5d64d4f9d89a971fcb2d Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Mon, 16 Mar 2009 14:56:24 +0100 Subject: Extended the gesture documentation. Also made some small fixes that noticed while was writing a doc. --- src/corelib/global/qnamespace.h | 17 ++++ src/corelib/kernel/qcoreevent.cpp | 2 + src/gui/kernel/qapplication.cpp | 10 ++ src/gui/kernel/qdirectionrecognizer.cpp | 34 +++---- src/gui/kernel/qdirectionrecognizer_p.h | 26 +----- src/gui/kernel/qevent.cpp | 64 ++++++------- src/gui/kernel/qgesture.cpp | 124 +++++++++++++++++++++++-- src/gui/kernel/qgesture.h | 29 ++---- src/gui/kernel/qgesture_p.h | 4 - src/gui/kernel/qgesturerecognizer.cpp | 79 ++++++++++++++++ src/gui/kernel/qgesturerecognizer.h | 54 +---------- src/gui/kernel/qgesturestandardrecognizers.cpp | 55 ++++------- src/gui/kernel/qgesturestandardrecognizers_p.h | 4 +- src/gui/kernel/qwidget.cpp | 20 +++- src/gui/kernel/qwidget.h | 2 +- 15 files changed, 323 insertions(+), 201 deletions(-) diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 56ee768..7875fba 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -1569,6 +1569,23 @@ public: GestureFinished = 1 }; + enum DirectionType + { + NoDirection = 0, + LeftDownDirection = 1, + DownLeftDirection = LeftDownDirection, + DownDirection = 2, + RightDownDirection = 3, + DownRightDirection = RightDownDirection, + LeftDirection = 4, + RightDirection = 6, + LeftUpDirection = 7, + UpLeftDirection = LeftUpDirection, + UpDirection = 8, + RightUpDirection = 9, + UpRightDirection = RightUpDirection + }; + } #ifdef Q_MOC_RUN ; diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp index ecc8796..7e25c60 100644 --- a/src/corelib/kernel/qcoreevent.cpp +++ b/src/corelib/kernel/qcoreevent.cpp @@ -228,6 +228,8 @@ QT_BEGIN_NAMESPACE \value GraphicsSceneTouchBegin Beginning of a sequence of touch-screen and/or track-pad events in a graphics scene (QGraphicsSceneTouchEvent) \value GraphicsSceneTouchUpdate Touch-screen event in a graphics scene (QGraphicsSceneTouchEvent) \value GraphicsSceneTouchEnd End of touch-event sequence in a graphics scene (QGraphicsSceneTouchEvent) + \value Gesture A gesture has occured. + \value GraphicsSceneGesture A gesture has occured on a graphics scene. User events should have values between \c User and \c{MaxUser}: diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index efe1b13..bcc25b9 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -5088,11 +5088,21 @@ bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy) return true; } +/*! + Adds custom gesture \a recognizer object. + + \sa Qt::AA_EnableGestures, QGestureEvent +*/ void QApplication::addGestureRecognizer(QGestureRecognizer *recognizer) { gestureManager()->addRecognizer(recognizer); } +/*! + Removes custom gesture \a recognizer object. + + \sa Qt::AA_EnableGestures, QGestureEvent +*/ void QApplication::removeGestureRecognizer(QGestureRecognizer *recognizer) { gestureManager()->removeRecognizer(recognizer); diff --git a/src/gui/kernel/qdirectionrecognizer.cpp b/src/gui/kernel/qdirectionrecognizer.cpp index 37b64e7..2896523 100644 --- a/src/gui/kernel/qdirectionrecognizer.cpp +++ b/src/gui/kernel/qdirectionrecognizer.cpp @@ -64,22 +64,22 @@ Direction QDirectionSimpleRecognizer::addPosition(const QPoint &pos) } int dx = pos.x() - lastPoint.x(); int dy = pos.y() - lastPoint.y(); - Direction::DirectionType direction = Direction::None; + Qt::DirectionType direction = Qt::NoDirection; if (dx < 0) { if (-1*dx >= SIZE/2) - direction = Direction::Left; + direction = Qt::LeftDirection; } else { if (dx >= SIZE/2) - direction = Direction::Right; + direction = Qt::RightDirection; } if (dy < 0) { if (-1*dy >= SIZE/2) - direction = Direction::Up; + direction = Qt::UpDirection; } else { if (dy >= SIZE/2) - direction = Direction::Down; + direction = Qt::DownDirection; } - if (direction == Direction::None) + if (direction == Qt::NoDirection) return Direction(); lastPoint = pos; @@ -123,7 +123,7 @@ Direction QDirectionDiagonalRecognizer::addPosition(const QPoint &pos) if (distance < SIZE/2) return Direction(); - Direction::DirectionType direction = Direction::None; + Qt::DirectionType direction = Qt::NoDirection; double angle = atan(1.0*qAbs(lastPoint.y() - pos.y())/qAbs(pos.x() - lastPoint.x())) * 180. / M_PI; if (dx < 0 && dy <= 0) { angle = 180 - angle; @@ -135,25 +135,25 @@ Direction QDirectionDiagonalRecognizer::addPosition(const QPoint &pos) if (angle < 0) angle += 360; if (angle <= 20) - direction = Direction::Right; + direction = Qt::RightDirection; else if (angle <= 65) - direction = Direction::RightUp; + direction = Qt::RightUpDirection; else if (angle <= 110) - direction = Direction::Up; + direction = Qt::UpDirection; else if (angle <= 155) - direction = Direction::LeftUp; + direction = Qt::LeftUpDirection; else if (angle <= 200) - direction = Direction::Left; + direction = Qt::LeftDirection; else if (angle <= 245) - direction = Direction::LeftDown; + direction = Qt::LeftDownDirection; else if (angle <= 290) - direction = Direction::Down; + direction = Qt::DownDirection; else if (angle <= 335) - direction = Direction::RightDown; + direction = Qt::RightDownDirection; else - direction = Direction::Right; + direction = Qt::RightDirection; - if (direction == Direction::None) + if (direction == Qt::NoDirection) return Direction(); lastPoint = pos; diff --git a/src/gui/kernel/qdirectionrecognizer_p.h b/src/gui/kernel/qdirectionrecognizer_p.h index 6390990..ca3d1c1 100644 --- a/src/gui/kernel/qdirectionrecognizer_p.h +++ b/src/gui/kernel/qdirectionrecognizer_p.h @@ -60,32 +60,16 @@ QT_BEGIN_NAMESPACE struct Direction { - enum DirectionType - { - None = 0, - LeftDown = 1, - DownLeft = LeftDown, - Down = 2, - RightDown = 3, - DownRight = RightDown, - Left = 4, - Right = 6, - LeftUp = 7, - UpLeft = LeftUp, - Up = 8, - RightUp = 9, - UpRight = RightUp - }; - DirectionType direction; + Qt::DirectionType direction; QPoint point; - Direction(DirectionType dir, const QPoint &pt) + Direction(Qt::DirectionType dir, const QPoint &pt) : direction(dir), point(pt) { } Direction() - : direction(None) { } + : direction(Qt::NoDirection) { } - inline bool isEmpty() const { return direction == None; } - inline bool isNull() const { return direction == None; } + inline bool isEmpty() const { return direction == Qt::NoDirection; } + inline bool isNull() const { return direction == Qt::NoDirection; } }; typedef QList DirectionList; diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 5761939..3ce2517 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -3519,42 +3519,19 @@ QMenubarUpdatedEvent::QMenubarUpdatedEvent(QMenuBar * const menuBar) gesture recognition. The QGestureEvent class contains a list of gestures that are being - executed right now (QGestureEvent::gestureTypes()) and a list of - gestures that are cancelled (the gesture might be cancelled - because the window lost focus, or because of timeout, etc). + executed right now (\l{QGestureEvent::}{gestureTypes()}) and a + list of gestures that are cancelled (the gesture might be + cancelled because the window lost focus, or because of timeout, + etc). \sa QGesture */ -/*! \fn bool QGestureEvent::contains(const Qt::GestureType &type) const - - Checks if the gesture event contains gesture of specific \a type. -*/ - -/*! \fn QList QGestureEvent::gestureTypes() const - - Returns a list of gesture names that the event contains. -*/ - -/*! \fn const QGesture* QGestureEvent::gesture(const Qt::GestureType &type) const - - Returns extended information about a gesture of specific \a type. -*/ - -/*! \fn QList > QGestureEvent::gestures() const - - Returns extended information about all triggered gestures. -*/ - -/*! \fn QSet QGestureEvent::cancelledGestures() const - - Returns a set of gesture names that used to be executed, but got - cancelled (i.e. they were not finished properly). +/*! + Creates new QGestureEvent containing a list of \a gestures that + are being executed and a list of gesture that were cancelled (\a + cancelledGestures). */ - - - - QGestureEvent::QGestureEvent(const QList &gestures, const QSet &cancelledGestures) : QEvent(QEvent::Gesture), m_cancelledGestures(cancelledGestures) @@ -3570,40 +3547,65 @@ QGestureEvent::QGestureEvent(const QGestureEvent &event, const QPoint &offset) //### use offset! } +/*! + Destroys the QGestureEvent object. +*/ QGestureEvent::~QGestureEvent() { } +/*! + Checks if the gesture event contains gesture of specific \a type. +*/ bool QGestureEvent::contains(Qt::GestureType type) const { return contains(qt_getStandardGestureTypeName(type)); } +/*! + Checks if the gesture event contains gesture of specific \a type. +*/ bool QGestureEvent::contains(const QString &type) const { return gesture(type) != 0; } +/*! + Returns a list of gesture names that this event contains. +*/ QList QGestureEvent::gestureTypes() const { return m_gestures.keys(); } +/*! + Returns extended information about a gesture of specific \a type. +*/ const QGesture* QGestureEvent::gesture(Qt::GestureType type) const { return gesture(qt_getStandardGestureTypeName(type)); } +/*! + Returns extended information about a gesture of specific \a type. +*/ const QGesture* QGestureEvent::gesture(const QString &type) const { return m_gestures.value(type, QSharedPointer()).data(); } +/*! + Returns extended information about all gestures in the event. +*/ QList > QGestureEvent::gestures() const { return m_gestures.values(); } +/*! + Returns a set of gesture names that used to be executed, but were + cancelled (i.e. they were not finished properly). +*/ QSet QGestureEvent::cancelledGestures() const { return m_cancelledGestures; diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp index b2d357c..b2bb859 100644 --- a/src/gui/kernel/qgesture.cpp +++ b/src/gui/kernel/qgesture.cpp @@ -46,11 +46,58 @@ QT_BEGIN_NAMESPACE QString qt_getStandardGestureTypeName(Qt::GestureType type); +/*! + \class QGesture + + \brief The QGesture class represents a gesture, containing all + properties that describe a gesture. + + 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). + + 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. However, if the gesture developer wants to add a new + property to the gesture object that describe coordinate (like a + QPoint or QRect), it is required to subclass the QGesture and + re-implement the \l{QGesture::}{translate} function to make sure + the coordinates are translated properly when the gesture event is + propagated to parent widgets. + + \sa QGestureEvent, QGestureRecognizer +*/ + +/*! + Creates a new gesture object of type \a type in a \a state and + marks it as a child of \a parent. + + Usually QGesture objects should only be contructed by the + QGestureRecognizer classes. +*/ QGesture::QGesture(QObject *parent, const QString &type, Qt::GestureState state) : QObject(*new QGesturePrivate, parent), gestureType_(type), gestureState_(state) { } +/*! + Creates a new gesture object of type \a type in a \a state and + marks it as a child of \a parent. + + This constructor also fills some basic information about the + gesture like a \a startPos which describes the start point of the + gesture, \a lastPos - last point where the gesture happened, \a + pos - a current point, \a rect - a bounding rect of the gesture, + \a hotSpot - a center point of the gesture, \a startTime - a time + when the gesture has started, \a duration - how long the gesture + is going on. + + Usually QGesture objects should only be contructed by the + QGestureRecognizer classes. +*/ QGesture::QGesture(QObject *parent, const QString &type, const QPoint &startPos, const QPoint &lastPos, const QPoint &pos, const QRect &rect, const QPoint &hotSpot, const QDateTime &startTime, @@ -60,51 +107,105 @@ QGesture::QGesture(QObject *parent, const QString &type, const QPoint &startPos, d_func()->init(startPos, lastPos, pos, rect, hotSpot, startTime, duration); } +/*! \internal +*/ QGesture::QGesture(QGesturePrivate &dd, QObject *parent, const QString &type, Qt::GestureState state) : QObject(dd, parent), gestureType_(type), gestureState_(state) { } +/*! + Destroys the gesture object. +*/ QGesture::~QGesture() { } +/*! + Translates the internal gesture properties that represent + coordinates by \a offset. + + Custom gesture recognizer developer have to re-implement this + function if they want to store custom properties that represent + coordinates. +*/ +void QGesture::translate(const QPoint &offset) +{ + Q_D(QGesture); + d->rect.translate(offset); + d->hotSpot += offset; + d->startPos += offset; + d->lastPos += offset; + d->pos += offset; +} + +/*! + Returns a bounding rect of a gesture. +*/ QRect QGesture::rect() const { return d_func()->rect; } +/*! + Returns a center point of a gesture. +*/ QPoint QGesture::hotSpot() const { return d_func()->hotSpot; } +/*! + Returns a time when the gesture has started. +*/ QDateTime QGesture::startTime() const { return d_func()->startTime; } +/*! + Returns a duration time of a gesture. +*/ uint QGesture::duration() const { return d_func()->duration; } +/*! + Returns the start position of the pointer. +*/ QPoint QGesture::startPos() const { return d_func()->startPos; } +/*! + Returns the last recorded position of the pointer. +*/ QPoint QGesture::lastPos() const { return d_func()->lastPos; } +/*! + Returns the position of the pointer. +*/ QPoint QGesture::pos() const { return d_func()->pos; } +/*! + \class QPannableGesture + + \brief The QPannableGesture class represents a Pan gesture, + providing additional information related to panning. + + This class is provided for convenience, panning direction + information is also contained in the QGesture object in it's + properties. +*/ QPannableGesture::QPannableGesture(QObject *parent, const QPoint &startPos, const QPoint &lastPos, const QPoint &pos, const QRect &rect, const QPoint &hotSpot, const QDateTime &startTime, @@ -114,24 +215,31 @@ QPannableGesture::QPannableGesture(QObject *parent, const QPoint &startPos, { Q_D(QPannableGesture); d->init(startPos, lastPos, pos, rect, hotSpot, startTime, duration); - d->lastDirection = QPannableGesture::None; - d->direction = QPannableGesture::None; + setProperty("lastDirection", QVariant::fromValue(Qt::NoDirection)); + setProperty("direction", QVariant::fromValue(Qt::NoDirection)); } +/*! + Destroys the QPannableGesture object. +*/ QPannableGesture::~QPannableGesture() { } -QPannableGesture::DirectionType QPannableGesture::lastDirection() const +/*! + Returns the last recorded direction of panning. +*/ +Qt::DirectionType QPannableGesture::lastDirection() const { - Q_D(const QPannableGesture); - return d->lastDirection; + return qVariantValue(property("lastDirection")); } -QPannableGesture::DirectionType QPannableGesture::direction() const +/*! + Returns the current direction of panning. +*/ +Qt::DirectionType QPannableGesture::direction() const { - Q_D(const QPannableGesture); - return d->direction; + return qVariantValue(property("direction")); } QT_END_NAMESPACE diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h index 8bd312b..b2999d7 100644 --- a/src/gui/kernel/qgesture.h +++ b/src/gui/kernel/qgesture.h @@ -48,6 +48,7 @@ #include "qpoint.h" #include "qrect.h" #include "qsharedpointer.h" +#include "qmetatype.h" QT_BEGIN_HEADER @@ -93,7 +94,7 @@ public: protected: QGesture(QGesturePrivate &dd, QObject *parent, const QString &type, Qt::GestureState state); - //### virtual void translateCoordinates(const QPoint &offset); + virtual void translate(const QPoint &offset); private: QString gestureType_; @@ -107,36 +108,18 @@ class Q_GUI_EXPORT QPannableGesture : public QGesture Q_DECLARE_PRIVATE(QPannableGesture) public: - enum DirectionType - { - None = 0, - LeftDown = 1, - DownLeft = LeftDown, - Down = 2, - RightDown = 3, - DownRight = RightDown, - Left = 4, - Right = 6, - LeftUp = 7, - UpLeft = LeftUp, - Up = 8, - RightUp = 9, - UpRight = RightUp - }; - -public: QPannableGesture(QObject *parent, const QPoint &startPos, const QPoint &lastPos, const QPoint &pos, const QRect &rect, const QPoint &hotSpot, const QDateTime &startTime, uint duration, Qt::GestureState state); ~QPannableGesture(); - DirectionType lastDirection() const; - DirectionType direction() const; - - friend class QGestureRecognizerPan; + Qt::DirectionType lastDirection() const; + Qt::DirectionType direction() const; }; +Q_DECLARE_METATYPE(Qt::DirectionType) + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/gui/kernel/qgesture_p.h b/src/gui/kernel/qgesture_p.h index 8a76186..028a622 100644 --- a/src/gui/kernel/qgesture_p.h +++ b/src/gui/kernel/qgesture_p.h @@ -94,10 +94,6 @@ public: class QPannableGesturePrivate : public QGesturePrivate { Q_DECLARE_PUBLIC(QPannableGesture) - -public: - QPannableGesture::DirectionType lastDirection; - QPannableGesture::DirectionType direction; }; QT_END_NAMESPACE diff --git a/src/gui/kernel/qgesturerecognizer.cpp b/src/gui/kernel/qgesturerecognizer.cpp index 9a00138..7791ad7 100644 --- a/src/gui/kernel/qgesturerecognizer.cpp +++ b/src/gui/kernel/qgesturerecognizer.cpp @@ -49,17 +49,96 @@ QT_BEGIN_NAMESPACE QString qt_getStandardGestureTypeName(Qt::GestureType gestureType); +/*! + \class QGestureRecognizer + + \brief The QGestureRecognizer class is the base class for + implementing custom gestures. + + This is a base class, to create a custom gesture type, you should + subclass it and implement its pure virtual functions. + + Usually gesture recognizer implements state machine, storing its + state internally in the recognizer object. The recognizer receives + input events through the \l{QGestureRecognizer::}{filterEvent()} + virtual function and decides whether the parsed event should + change the state of the recognizer - i.e. if the event starts or + ends a gesture or if it isn't related to gesture at all. +*/ + +/*! + \enum QGestureRecognizer::Result + + This enum type defines the state of the gesture recognizer. + + \value NotGesture Not a gesture. + + \value GestureStarted The long-term gesture has started. When the + recognizer is in started state, a gesture event containing + QGesture objects returned by the + \l{QGestureRecognizer::}{getGesture()} will be sent to a widget. + + \value GestureFinished A gesture has ended. The gesture event will + be sent to a widget. + + \value MaybeGesture Gesture hasn't started yet, but it might start + soon after next events are received by the recognizer. That means + that gesture manager shouldn't reset() the internal state of the + gesture recognizer. +*/ + +/*! \fn QGestureRecognizer::Result QGestureRecognizer::filterEvent(const QEvent *event) + + This is a pure virtual function that needs to be implemented in + subclasses. + + Parses input \a event and returns the result, which specifies if + the event sequence is a gesture or not. +*/ + +/*! \fn QGesture* QGestureRecognizer::getGesture() + + Returns a gesture object that will be send to the widget. This + function is called when the gesture recognizer changed its state + to QGestureRecognizer::GestureStarted or + QGestureRecognizer::GestureFinished. + + The gesture object is owned by the recognizer itself. +*/ + +/*! \fn void QGestureRecognizer::reset() + + Resets the internal state of the gesture recognizer. +*/ + +/*! \fn void QGestureRecognizer::stateChanged(QGestureRecognizer::Result result) + + The gesture recognizer might emit the stateChanged() signal when + the gesture state changes asynchronously, i.e. without any event + being filtered through filterEvent(). +*/ + QGestureRecognizerPrivate::QGestureRecognizerPrivate() : gestureType(Qt::UnknownGesture) { } +/*! + Creates a new gesture recognizer object that handles gestures of + the specific \a type. + + \sa QApplication::addGestureRecognizer(), + QApplication::removeGestureRecognizer(), +*/ QGestureRecognizer::QGestureRecognizer(const QString &type) : QObject(*new QGestureRecognizerPrivate, 0) { d_func()->customGestureType = type; } +/*! + Returns the name of the gesture that is handled by the recognizer. +*/ QString QGestureRecognizer::gestureType() const { Q_D(const QGestureRecognizer); diff --git a/src/gui/kernel/qgesturerecognizer.h b/src/gui/kernel/qgesturerecognizer.h index c0d4f5e..9ffdb0d 100644 --- a/src/gui/kernel/qgesturerecognizer.h +++ b/src/gui/kernel/qgesturerecognizer.h @@ -48,58 +48,6 @@ QT_BEGIN_NAMESPACE -/*! - \class QGestureRecognizer - - \brief The base class for implementing custom gestures. - - This is a base class, to create a custom gesture type, you should - subclass it and implement pure virtual functions. - - Usually gesture recognizer implements state machine, storing its - state internally in the recognizer object. The recognizer receives - input events through the QGestureRecognizer::filterEvent() virtual - function and decides whether the parsed event should change the - state of the recognizer - i.e. if the event starts or ends a - gesture or if it isn't related to gesture at all. -*/ - -/*! \fn QString gestureType() const - - Returns the name of the gesture that is handled by the recognizer. -*/ - -/*! \fn Result filterEvent(const QEvent *event) - - This is a pure virtual function that need to be implemented in - subclasses. - - Parses input \a events and returns the result, saying if the event - sequence is a gesture or not. -*/ - -/*! \fn QGesture* getGesture() - - Creates a new gesture object that will be send to the widget. This - function is called when the gesture recognizer returned a - QGestureRecognizer::GestureStarted or - QGestureRecognizer::GestureFinished state. - - Created gesture object is owned by the caller. - */ - -/*! \fn void reset() - - Resets the internal state of the gesture recognizer. -*/ - -/*! \fn void stateChanged(QGestureRecognizer::Result result) - - The gesture recognizer might emit the signal when the gesture - state changes asynchronously, i.e. without any event being - received. -*/ - class QGesture; class QGestureRecognizerPrivate; class Q_GUI_EXPORT QGestureRecognizer : public QObject @@ -120,7 +68,7 @@ public: QString gestureType() const; - virtual Result filterEvent(const QEvent* event) = 0; + virtual QGestureRecognizer::Result filterEvent(const QEvent* event) = 0; virtual QGesture* getGesture() = 0; virtual void reset() = 0; diff --git a/src/gui/kernel/qgesturestandardrecognizers.cpp b/src/gui/kernel/qgesturestandardrecognizers.cpp index 718bdfd..82a0a6f 100644 --- a/src/gui/kernel/qgesturestandardrecognizers.cpp +++ b/src/gui/kernel/qgesturestandardrecognizers.cpp @@ -80,17 +80,19 @@ QString qt_getStandardGestureTypeName(Qt::GestureType gestureType) QGestureRecognizerPan::QGestureRecognizerPan() : QGestureRecognizer(QString()), mousePressed(false), gestureFinished(false), - lastDirection(Direction::None), currentDirection(Direction::None) + lastDirection(Qt::NoDirection), currentDirection(Qt::NoDirection) { Q_D(QGestureRecognizer); d->gestureType = Qt::PanGesture; + + qRegisterMetaType(); } QGestureRecognizer::Result QGestureRecognizerPan::filterEvent(const QEvent *event) { if (event->type() == QEvent::MouseButtonPress) { const QMouseEvent *ev = static_cast(event); - if (currentDirection != Direction::None) { + if (currentDirection != Qt::NoDirection) { DEBUG() << "Pan: MouseButtonPress: fail. another press during pan"; reset(); return QGestureRecognizer::NotGesture; @@ -100,7 +102,7 @@ QGestureRecognizer::Result QGestureRecognizerPan::filterEvent(const QEvent *even pressedPos = lastPos = currentPos = ev->pos(); return QGestureRecognizer::MaybeGesture; } else if (event->type() == QEvent::MouseButtonRelease) { - if (mousePressed && currentDirection != Direction::None) { + if (mousePressed && currentDirection != Qt::NoDirection) { DEBUG() << "Pan: MouseButtonRelease: pan detected"; gestureFinished = true; const QMouseEvent *ev = static_cast(event); @@ -117,19 +119,19 @@ QGestureRecognizer::Result QGestureRecognizerPan::filterEvent(const QEvent *even const QMouseEvent *ev = static_cast(event); lastPos = currentPos; currentPos = ev->pos(); - Direction::DirectionType direction = + Qt::DirectionType direction = simpleRecognizer.addPosition(ev->pos()).direction; DEBUG() << "Pan: MouseMove: simplerecognizer result = " << direction; QGestureRecognizer::Result result = QGestureRecognizer::NotGesture; - if (currentDirection == Direction::None) { - if (direction == Direction::None) + if (currentDirection == Qt::NoDirection) { + if (direction == Qt::NoDirection) result = QGestureRecognizer::MaybeGesture; else result = QGestureRecognizer::GestureStarted; } else { result = QGestureRecognizer::GestureStarted; } - if (direction != Direction::None) { + if (direction != Qt::NoDirection) { if (currentDirection != direction) lastDirection = currentDirection; currentDirection = direction; @@ -139,37 +141,16 @@ QGestureRecognizer::Result QGestureRecognizerPan::filterEvent(const QEvent *even return QGestureRecognizer::NotGesture; } -static inline QPannableGesture::DirectionType convertPanningDirection(const Direction::DirectionType direction) -{ - switch (direction) { - case Direction::Left: - return QPannableGesture::Left; - case Direction::Right: - return QPannableGesture::Right; - case Direction::Up: - return QPannableGesture::Up; - case Direction::Down: - return QPannableGesture::Down; - default: - break; - } - return QPannableGesture::None; -} - QGesture* QGestureRecognizerPan::getGesture() { - QPannableGesture::DirectionType dir = convertPanningDirection(currentDirection); - QPannableGesture::DirectionType lastDir = convertPanningDirection(lastDirection); - if (dir == QPannableGesture::None) + if (currentDirection == Qt::NoDirection) return 0; - QPannableGesture *g = - new QPannableGesture(this, - pressedPos, lastPos, currentPos, - QRect(), pressedPos, QDateTime(), 0, - gestureFinished ? Qt::GestureFinished : Qt::GestureStarted); - QPannableGesturePrivate *d = g->d_func(); - d->lastDirection = lastDir; - d->direction = dir; + QGesture *g = new QGesture(this, qt_getStandardGestureTypeName(Qt::PanGesture), + pressedPos, lastPos, currentPos, + QRect(), pressedPos, QDateTime(), 0, + gestureFinished ? Qt::GestureFinished : Qt::GestureStarted); + g->setProperty("lastDirection", QVariant::fromValue(lastDirection)); + g->setProperty("direction", QVariant::fromValue(currentDirection)); return g; } @@ -177,8 +158,8 @@ QGesture* QGestureRecognizerPan::getGesture() void QGestureRecognizerPan::reset() { mousePressed = false; - lastDirection = Direction::None; - currentDirection = Direction::None; + lastDirection = Qt::NoDirection; + currentDirection = Qt::NoDirection; gestureFinished = false; diagonalRecognizer.reset(); simpleRecognizer.reset(); diff --git a/src/gui/kernel/qgesturestandardrecognizers_p.h b/src/gui/kernel/qgesturestandardrecognizers_p.h index 75a206a..8f1361f 100644 --- a/src/gui/kernel/qgesturestandardrecognizers_p.h +++ b/src/gui/kernel/qgesturestandardrecognizers_p.h @@ -80,8 +80,8 @@ private: QPoint currentPos; bool mousePressed; bool gestureFinished; - Direction::DirectionType lastDirection; - Direction::DirectionType currentDirection; + Qt::DirectionType lastDirection; + Qt::DirectionType currentDirection; QDirectionDiagonalRecognizer diagonalRecognizer; QDirectionSimpleRecognizer simpleRecognizer; }; diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index 2f794f4..d37f360 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -11031,8 +11031,9 @@ QWindowSurface *QWidget::windowSurface() const Subscribes the widget to the specified \a gesture type. Returns the id of the gesture. -*/ + \sa grabGesture(), releaseGesture(), setGestureEnabled() +*/ int QWidget::grabGesture(const QString &gesture) { Q_D(QWidget); @@ -11053,16 +11054,19 @@ int QWidgetPrivate::grabGesture(int id) Subscribes the widget to the specified \a gesture type. Returns the id of the gesture. -*/ + \sa grabGesture(), releaseGesture(), setGestureEnabled() +*/ int QWidget::grabGesture(Qt::GestureType gesture) { return grabGesture(qt_getStandardGestureTypeName(gesture)); } /*! - Unsubscribes the widget from a gesture, which is specified by its - \a id. + Unsubscribes the widget from a gesture, which is specified by the + \a gestureId. + + \sa grabGesture(),setGestureEnabled() */ void QWidget::releaseGesture(int gestureId) { @@ -11075,6 +11079,14 @@ void QWidget::releaseGesture(int gestureId) } } +/*! + If \a enable is true, the gesture with the given \a gestureId is + enabled; otherwise the gesture is disabled. + + The id of the gesture is returned by the grabGesture(). + + \sa grabGesture(), releaseGesture() +*/ void setGestureEnabled(int gestureId, bool enable) { //### diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h index a76c50a..6324782 100644 --- a/src/gui/kernel/qwidget.h +++ b/src/gui/kernel/qwidget.h @@ -616,7 +616,7 @@ public: int grabGesture(const QString &gesture); int grabGesture(Qt::GestureType gesture); void releaseGesture(int gestureId); - void setGestureEnabled(int gestureId, bool enable); + void setGestureEnabled(int gestureId, bool enable = true); Q_SIGNALS: void customContextMenuRequested(const QPoint &pos); -- cgit v0.12 From 415039d9c9dab219505cc082981e2175a8977b03 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Mon, 16 Mar 2009 15:55:30 +0100 Subject: More documentation fixes. --- doc/src/qnamespace.qdoc | 33 +++++++++++++- src/gui/graphicsview/qgraphicsitem.cpp | 48 +++++++++++++++++--- src/gui/graphicsview/qgraphicsitem.h | 5 ++- src/gui/graphicsview/qgraphicssceneevent.cpp | 51 +++++++++++----------- src/gui/kernel/qevent.cpp | 13 ++---- src/gui/kernel/qevent.h | 2 - src/gui/kernel/qgesture.cpp | 65 ++++++++++++++++------------ src/gui/kernel/qgesture.h | 9 ++-- src/gui/kernel/qwidget.cpp | 8 ++-- 9 files changed, 149 insertions(+), 85 deletions(-) diff --git a/doc/src/qnamespace.qdoc b/doc/src/qnamespace.qdoc index c44b41e..c30dc88 100644 --- a/doc/src/qnamespace.qdoc +++ b/doc/src/qnamespace.qdoc @@ -2676,9 +2676,17 @@ \sa QPixmapBorders, qDrawBorderPixmap() */ -/*! \typedef Qt::GestureType +/*! \enum Qt::GestureType - A string representing a type of a gesture. + This enum lists standard gestures. + + \value UnknownGesture An unknown gesture. This enum value shouldn't be used. + \value TapGesture A single tap gesture. + \value DoubleTapGesture A double tap gesture. + \value TrippleTapGesture A tripple tap gesture. + \value TapAndHoldGesture A tap-and-hold (long tap) gesture. + \value PanGesture A pan gesture. + \value PinchGesture A pinch gesture. */ /*! @@ -2691,3 +2699,24 @@ \sa QGesture */ + +/*! + \enum Qt::DirectionType + + This enum type describes directions. This could be used by the + gesture recognizers. + + \value NoDirection Non-specific direction. + \value LeftDownDirection + \value DownLeftDirection + \value DownDirection + \value RightDownDirection + \value DownRightDirection + \value LeftDirection + \value RightDirection + \value LeftUpDirection + \value UpLeftDirection + \value UpDirection + \value RightUpDirection + \value UpRightDirection +*/ diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index cbd4834..0dc227a 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -5790,27 +5790,61 @@ QVariant QGraphicsItem::inputMethodQuery(Qt::InputMethodQuery query) const return QVariant(); } -int QGraphicsItem::grabGesture(Qt::GestureType type) +/*! + Subscribes the graphics item to the specified \a gesture type. + + Returns the id of the gesture. + + \sa releaseGesture(), setGestureEnabled() +*/ +int QGraphicsItem::grabGesture(Qt::GestureType gesture) { - return grabGesture(qt_getStandardGestureTypeName(type)); + return grabGesture(qt_getStandardGestureTypeName(gesture)); } -int QGraphicsItem::grabGesture(const QString &type) +/*! + Subscribes the graphics item to the specified \a gesture type. + + Returns the id of the gesture. + + \sa releaseGesture(), setGestureEnabled() +*/ +int QGraphicsItem::grabGesture(const QString &gesture) { - int id = qHash(type); + int id = qHash(gesture); QSet::iterator it = d_ptr->gestures.find(id); if (it != d_ptr->gestures.end()) return *it; d_ptr->gestures << id; if (d_ptr->scene) d_ptr->scene->d_func()->grabGesture(this, id); + return id; } -void QGraphicsItem::releaseGesture(int id) +/*! + Unsubscribes the graphics item from a gesture, which is specified + by the \a gestureId. + + \sa grabGesture(), setGestureEnabled() +*/ +void QGraphicsItem::releaseGesture(int gestureId) { - d_ptr->gestures.remove(id); + d_ptr->gestures.remove(gestureId); if (d_ptr->scene) - d_ptr->scene->d_func()->releaseGesture(this, id); + d_ptr->scene->d_func()->releaseGesture(this, gestureId); +} + +/*! + If \a enable is true, the gesture with the given \a gestureId is + enabled; otherwise the gesture is disabled. + + The id of the gesture is returned by the grabGesture(). + + \sa grabGesture(), releaseGesture() +*/ +void QGraphicsItem::setGestureEnabled(int gestureId, bool enable) +{ + //### } /*! diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h index 4e6e96d..37d8f78 100644 --- a/src/gui/graphicsview/qgraphicsitem.h +++ b/src/gui/graphicsview/qgraphicsitem.h @@ -338,9 +338,10 @@ public: QVariant data(int key) const; void setData(int key, const QVariant &value); - int grabGesture(Qt::GestureType type); - int grabGesture(const QString &type); + int grabGesture(Qt::GestureType gesture); + int grabGesture(const QString &gesture); void releaseGesture(int gestureId); + void setGestureEnabled(int gestureId, bool enable = true); enum { Type = 1, diff --git a/src/gui/graphicsview/qgraphicssceneevent.cpp b/src/gui/graphicsview/qgraphicssceneevent.cpp index 4f24a74..c79e30b 100644 --- a/src/gui/graphicsview/qgraphicssceneevent.cpp +++ b/src/gui/graphicsview/qgraphicssceneevent.cpp @@ -1727,18 +1727,24 @@ void QGraphicsSceneMoveEvent::setNewPos(const QPointF &pos) gestures with \l{QGraphicsItem::}{grabGesture()}. */ - +/*! + Constructs a QGraphicsSceneGestureEvent. +*/ QGraphicsSceneGestureEvent::QGraphicsSceneGestureEvent() : QGraphicsSceneEvent(QEvent::GraphicsSceneGesture) { } +/*! + Destroys a QGraphicsSceneGestureEvent. +*/ QGraphicsSceneGestureEvent::~QGraphicsSceneGestureEvent() { } /*! - Checks if the gesture event contains gesture of specific \a type. + Returns true if the gesture event contains gesture of specific \a + type; returns false otherwise. */ bool QGraphicsSceneGestureEvent::contains(const QString &type) const { @@ -1746,7 +1752,8 @@ bool QGraphicsSceneGestureEvent::contains(const QString &type) const } /*! - Checks if the gesture event contains gesture of specific \a type. + Returns true if the gesture event contains gesture of specific \a + type; returns false otherwise. */ bool QGraphicsSceneGestureEvent::contains(Qt::GestureType type) const { @@ -1754,7 +1761,7 @@ bool QGraphicsSceneGestureEvent::contains(Qt::GestureType type) const } /*! - Returns a list of gesture names that the event contains. + Returns a list of gesture names that this event contains. */ QList QGraphicsSceneGestureEvent::gestureTypes() const { @@ -1778,7 +1785,7 @@ const QGesture* QGraphicsSceneGestureEvent::gesture(Qt::GestureType type) const } /*! - Returns extended information about all triggered gestures. + Returns extended information about all gestures in the event. */ QList > QGraphicsSceneGestureEvent::gestures() const { @@ -1786,7 +1793,7 @@ QList > QGraphicsSceneGestureEvent::gestures() const } /*! - Returns a set of gesture names that used to be executed, but got + Returns a set of gesture names that used to be executed, but were cancelled (i.e. they were not finished properly). */ QSet QGraphicsSceneGestureEvent::cancelledGestures() const @@ -1795,8 +1802,9 @@ QSet QGraphicsSceneGestureEvent::cancelledGestures() const } /*! - Returns a set of gesture names that used to be executed, but got - cancelled (i.e. they were not finished properly). + Sets a list of gesture names \a cancelledGestures that used to be + executed, but were cancelled (i.e. they were not finished + properly). */ void QGraphicsSceneGestureEvent::setCancelledGestures(const QSet &cancelledGestures) { @@ -1807,13 +1815,10 @@ void QGraphicsSceneGestureEvent::setCancelledGestures(const QSet &cance Maps the point \a point, which is in a view coordinate system, to scene coordinate system, and returns the mapped coordinate. - \a Point is in coordinate system of the widget that received + A \a point is in coordinate system of the widget that received gesture event. - \sa mapToScene(const QRect &rect), - mapToItem(const QPoint &point, QGraphicsItem *item), - mapToItem(const QRect &rect, QGraphicsItem *item), - {The Graphics View Coordinate System} + \sa mapToItem(), {The Graphics View Coordinate System} */ QPointF QGraphicsSceneGestureEvent::mapToScene(const QPoint &point) const { @@ -1826,13 +1831,10 @@ QPointF QGraphicsSceneGestureEvent::mapToScene(const QPoint &point) const Maps the rectangular \a rect, which is in a view coordinate system, to scene coordinate system, and returns the mapped coordinate. - \a Point is in coordinate system of the widget that received + A \a rect is in coordinate system of the widget that received gesture event. - \sa mapToScene(const QPoint &rect), - mapToItem(const QPoint &point, QGraphicsItem *item), - mapToItem(const QRect &rect, QGraphicsItem *item), - {The Graphics View Coordinate System} + \sa mapToItem(), {The Graphics View Coordinate System} */ QPolygonF QGraphicsSceneGestureEvent::mapToScene(const QRect &rect) const { @@ -1847,9 +1849,7 @@ QPolygonF QGraphicsSceneGestureEvent::mapToScene(const QRect &rect) const If \a item is 0, this function returns the same as mapToScene(). - \sa mapToScene(const QPoint &rect), mapToScene(const QRect &rect), - mapToItem(const QRect &, QGraphicsItem *item), - {The Graphics View Coordinate System} + \sa mapToScene(), {The Graphics View Coordinate System} */ QPointF QGraphicsSceneGestureEvent::mapToItem(const QPoint &point, QGraphicsItem *item) const { @@ -1863,14 +1863,12 @@ QPointF QGraphicsSceneGestureEvent::mapToItem(const QPoint &point, QGraphicsItem } /*! - Maps the point \a point, which is in a view coordinate system, to + Maps the rectangualar \a rect, which is in a view coordinate system, to item's \a item coordinate system, and returns the mapped coordinate. If \a item is 0, this function returns the same as mapToScene(). - \sa mapToScene(const QPoint &rect), mapToScene(const QRect &rect), - mapToItem(const QPoint &point, QGraphicsItem *item), - {The Graphics View Coordinate System} + \sa mapToScene(), {The Graphics View Coordinate System} */ QPolygonF QGraphicsSceneGestureEvent::mapToItem(const QRect &rect, QGraphicsItem *item) const { @@ -1883,6 +1881,9 @@ QPolygonF QGraphicsSceneGestureEvent::mapToItem(const QRect &rect, QGraphicsItem return QPolygonF(); } +/*! + Set a list of gesture objects containing extended information about \a gestures. +*/ void QGraphicsSceneGestureEvent::setGestures(const QList > &gestures) { foreach(const QSharedPointer &g, gestures) diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index 3ce2517..dbfe528 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -3540,13 +3540,6 @@ QGestureEvent::QGestureEvent(const QList &gestures, m_gestures.insert(r->gestureType(), QSharedPointer(r)); } -QGestureEvent::QGestureEvent(const QGestureEvent &event, const QPoint &offset) - : QEvent(QEvent::Gesture), m_gestures(event.m_gestures), - m_cancelledGestures(event.m_cancelledGestures) -{ - //### use offset! -} - /*! Destroys the QGestureEvent object. */ @@ -3555,7 +3548,8 @@ QGestureEvent::~QGestureEvent() } /*! - Checks if the gesture event contains gesture of specific \a type. + Returns true if the gesture event contains gesture of specific \a + type; returns false otherwise. */ bool QGestureEvent::contains(Qt::GestureType type) const { @@ -3563,7 +3557,8 @@ bool QGestureEvent::contains(Qt::GestureType type) const } /*! - Checks if the gesture event contains gesture of specific \a type. + Returns true if the gesture event contains gesture of specific \a + type; returns false otherwise. */ bool QGestureEvent::contains(const QString &type) const { diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h index 48e420a..41005d8 100644 --- a/src/gui/kernel/qevent.h +++ b/src/gui/kernel/qevent.h @@ -719,8 +719,6 @@ class Q_GUI_EXPORT QGestureEvent : public QEvent public: QGestureEvent(const QList &gestures, const QSet &cancelledGestures = QSet()); - // internal ctor - QGestureEvent(const QGestureEvent &gestures, const QPoint &offset); ~QGestureEvent(); bool contains(Qt::GestureType type) const; diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp index b2bb859..35a3e2a 100644 --- a/src/gui/kernel/qgesture.cpp +++ b/src/gui/kernel/qgesture.cpp @@ -64,13 +64,23 @@ QString qt_getStandardGestureTypeName(Qt::GestureType type); information. However, if the gesture developer wants to add a new property to the gesture object that describe coordinate (like a QPoint or QRect), it is required to subclass the QGesture and - re-implement the \l{QGesture::}{translate} function to make sure + re-implement the \l{QGesture::}{translate()} function to make sure the coordinates are translated properly when the gesture event is propagated to parent widgets. \sa QGestureEvent, QGestureRecognizer */ +/*! \fn QString QGesture::gestureType() const + + Returns the type of the gesture. +*/ + +/*! \fn Qt::GestureState QGesture::state() const + + Returns the current state of the gesture. +*/ + /*! Creates a new gesture object of type \a type in a \a state and marks it as a child of \a parent. @@ -141,7 +151,9 @@ void QGesture::translate(const QPoint &offset) } /*! - Returns a bounding rect of a gesture. + \property QGesture::rect + + \brief The bounding rect of a gesture. */ QRect QGesture::rect() const { @@ -149,7 +161,9 @@ QRect QGesture::rect() const } /*! - Returns a center point of a gesture. + \property QGesture::hotSpot + + \brief The center point of a gesture. */ QPoint QGesture::hotSpot() const { @@ -157,7 +171,9 @@ QPoint QGesture::hotSpot() const } /*! - Returns a time when the gesture has started. + \property QGesture::startTime + + \brief The time when the gesture has started. */ QDateTime QGesture::startTime() const { @@ -165,7 +181,9 @@ QDateTime QGesture::startTime() const } /*! - Returns a duration time of a gesture. + \property QGesture::duration + + \brief The duration time of a gesture. */ uint QGesture::duration() const { @@ -173,7 +191,9 @@ uint QGesture::duration() const } /*! - Returns the start position of the pointer. + \property QGesture::startPos + + \brief The start position of the pointer. */ QPoint QGesture::startPos() const { @@ -181,7 +201,9 @@ QPoint QGesture::startPos() const } /*! - Returns the last recorded position of the pointer. + \property QGesture::lastPos + + \brief The last recorded position of the pointer. */ QPoint QGesture::lastPos() const { @@ -189,7 +211,9 @@ QPoint QGesture::lastPos() const } /*! - Returns the position of the pointer. + \property QGesture::pos + + \brief The current position of the pointer. */ QPoint QGesture::pos() const { @@ -206,28 +230,11 @@ QPoint QGesture::pos() const information is also contained in the QGesture object in it's properties. */ -QPannableGesture::QPannableGesture(QObject *parent, const QPoint &startPos, - const QPoint &lastPos, const QPoint &pos, const QRect &rect, - const QPoint &hotSpot, const QDateTime &startTime, - uint duration, Qt::GestureState state) - : QGesture(*new QPannableGesturePrivate, parent, - qt_getStandardGestureTypeName(Qt::PanGesture), state) -{ - Q_D(QPannableGesture); - d->init(startPos, lastPos, pos, rect, hotSpot, startTime, duration); - setProperty("lastDirection", QVariant::fromValue(Qt::NoDirection)); - setProperty("direction", QVariant::fromValue(Qt::NoDirection)); -} /*! - Destroys the QPannableGesture object. -*/ -QPannableGesture::~QPannableGesture() -{ -} + \property QPannableGesture::lastDirection -/*! - Returns the last recorded direction of panning. + \brief The last recorded direction of panning. */ Qt::DirectionType QPannableGesture::lastDirection() const { @@ -235,7 +242,9 @@ Qt::DirectionType QPannableGesture::lastDirection() const } /*! - Returns the current direction of panning. + \property QPannableGesture::direction + + \brief The current direction of panning. */ Qt::DirectionType QPannableGesture::direction() const { diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h index b2999d7..4e692be 100644 --- a/src/gui/kernel/qgesture.h +++ b/src/gui/kernel/qgesture.h @@ -107,13 +107,10 @@ class Q_GUI_EXPORT QPannableGesture : public QGesture Q_OBJECT Q_DECLARE_PRIVATE(QPannableGesture) -public: - QPannableGesture(QObject *parent, const QPoint &startPos, - const QPoint &lastPos, const QPoint &pos, const QRect &rect, - const QPoint &hotSpot, const QDateTime &startTime, - uint duration, Qt::GestureState state); - ~QPannableGesture(); + Q_PROPERTY(Qt::DirectionType lastDirection READ lastDirection) + Q_PROPERTY(Qt::DirectionType direction READ direction) +public: Qt::DirectionType lastDirection() const; Qt::DirectionType direction() const; }; diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index d37f360..9c0c404 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -11032,7 +11032,7 @@ QWindowSurface *QWidget::windowSurface() const Returns the id of the gesture. - \sa grabGesture(), releaseGesture(), setGestureEnabled() + \sa releaseGesture(), setGestureEnabled() */ int QWidget::grabGesture(const QString &gesture) { @@ -11055,7 +11055,7 @@ int QWidgetPrivate::grabGesture(int id) Returns the id of the gesture. - \sa grabGesture(), releaseGesture(), setGestureEnabled() + \sa releaseGesture(), setGestureEnabled() */ int QWidget::grabGesture(Qt::GestureType gesture) { @@ -11066,7 +11066,7 @@ int QWidget::grabGesture(Qt::GestureType gesture) Unsubscribes the widget from a gesture, which is specified by the \a gestureId. - \sa grabGesture(),setGestureEnabled() + \sa grabGesture(), setGestureEnabled() */ void QWidget::releaseGesture(int gestureId) { @@ -11087,7 +11087,7 @@ void QWidget::releaseGesture(int gestureId) \sa grabGesture(), releaseGesture() */ -void setGestureEnabled(int gestureId, bool enable) +void QWidget::setGestureEnabled(int gestureId, bool enable) { //### } -- cgit v0.12 From 2e91de4a0046c17ff41f4ed533542a5fc3858087 Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Mon, 16 Mar 2009 15:57:58 +0100 Subject: Renamed QPannableGesture to QPanningGesture. --- src/gui/kernel/qgesture.cpp | 12 ++++++------ src/gui/kernel/qgesture.h | 6 +++--- src/gui/kernel/qgesture_p.h | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/gui/kernel/qgesture.cpp b/src/gui/kernel/qgesture.cpp index 35a3e2a..76101f2 100644 --- a/src/gui/kernel/qgesture.cpp +++ b/src/gui/kernel/qgesture.cpp @@ -221,9 +221,9 @@ QPoint QGesture::pos() const } /*! - \class QPannableGesture + \class QPanningGesture - \brief The QPannableGesture class represents a Pan gesture, + \brief The QPanningGesture class represents a Pan gesture, providing additional information related to panning. This class is provided for convenience, panning direction @@ -232,21 +232,21 @@ QPoint QGesture::pos() const */ /*! - \property QPannableGesture::lastDirection + \property QPanningGesture::lastDirection \brief The last recorded direction of panning. */ -Qt::DirectionType QPannableGesture::lastDirection() const +Qt::DirectionType QPanningGesture::lastDirection() const { return qVariantValue(property("lastDirection")); } /*! - \property QPannableGesture::direction + \property QPanningGesture::direction \brief The current direction of panning. */ -Qt::DirectionType QPannableGesture::direction() const +Qt::DirectionType QPanningGesture::direction() const { return qVariantValue(property("direction")); } diff --git a/src/gui/kernel/qgesture.h b/src/gui/kernel/qgesture.h index 4e692be..b9e86a3 100644 --- a/src/gui/kernel/qgesture.h +++ b/src/gui/kernel/qgesture.h @@ -101,11 +101,11 @@ private: Qt::GestureState gestureState_; }; -class QPannableGesturePrivate; -class Q_GUI_EXPORT QPannableGesture : public QGesture +class QPanningGesturePrivate; +class Q_GUI_EXPORT QPanningGesture : public QGesture { Q_OBJECT - Q_DECLARE_PRIVATE(QPannableGesture) + Q_DECLARE_PRIVATE(QPanningGesture) Q_PROPERTY(Qt::DirectionType lastDirection READ lastDirection) Q_PROPERTY(Qt::DirectionType direction READ direction) diff --git a/src/gui/kernel/qgesture_p.h b/src/gui/kernel/qgesture_p.h index 028a622..24350d4 100644 --- a/src/gui/kernel/qgesture_p.h +++ b/src/gui/kernel/qgesture_p.h @@ -91,9 +91,9 @@ public: QPoint pos; }; -class QPannableGesturePrivate : public QGesturePrivate +class QPanningGesturePrivate : public QGesturePrivate { - Q_DECLARE_PUBLIC(QPannableGesture) + Q_DECLARE_PUBLIC(QPanningGesture) }; QT_END_NAMESPACE -- cgit v0.12 From a72e6d351f136e0cd5e0f9c178e5f09eb70ca2db Mon Sep 17 00:00:00 2001 From: Denis Dzyubenko Date: Mon, 16 Mar 2009 16:04:13 +0100 Subject: Removed the use of QSharedPointer from gesture api - since QGesture are QObject now everything is much simplier. --- src/gui/graphicsview/qgraphicssceneevent.cpp | 8 ++++---- src/gui/graphicsview/qgraphicssceneevent.h | 7 +++---- src/gui/kernel/qevent.cpp | 6 +++--- src/gui/kernel/qevent.h | 5 ++--- src/gui/kernel/qgesture.h | 1 - 5 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/gui/graphicsview/qgraphicssceneevent.cpp b/src/gui/graphicsview/qgraphicssceneevent.cpp index c79e30b..b26f8cf 100644 --- a/src/gui/graphicsview/qgraphicssceneevent.cpp +++ b/src/gui/graphicsview/qgraphicssceneevent.cpp @@ -1773,7 +1773,7 @@ QList QGraphicsSceneGestureEvent::gestureTypes() const */ const QGesture* QGraphicsSceneGestureEvent::gesture(const QString &type) const { - return m_gestures.value(type, QSharedPointer()).data(); + return m_gestures.value(type, 0); } /*! @@ -1787,7 +1787,7 @@ const QGesture* QGraphicsSceneGestureEvent::gesture(Qt::GestureType type) const /*! Returns extended information about all gestures in the event. */ -QList > QGraphicsSceneGestureEvent::gestures() const +QList QGraphicsSceneGestureEvent::gestures() const { return m_gestures.values(); } @@ -1884,9 +1884,9 @@ QPolygonF QGraphicsSceneGestureEvent::mapToItem(const QRect &rect, QGraphicsItem /*! Set a list of gesture objects containing extended information about \a gestures. */ -void QGraphicsSceneGestureEvent::setGestures(const QList > &gestures) +void QGraphicsSceneGestureEvent::setGestures(const QList &gestures) { - foreach(const QSharedPointer &g, gestures) + foreach(QGesture *g, gestures) m_gestures.insert(g->gestureType(), g); } diff --git a/src/gui/graphicsview/qgraphicssceneevent.h b/src/gui/graphicsview/qgraphicssceneevent.h index d1a301e..244c25e 100644 --- a/src/gui/graphicsview/qgraphicssceneevent.h +++ b/src/gui/graphicsview/qgraphicssceneevent.h @@ -48,7 +48,6 @@ #include #include #include -#include QT_BEGIN_HEADER @@ -324,8 +323,8 @@ public: const QGesture* gesture(Qt::GestureType type) const; const QGesture* gesture(const QString &type) const; - QList > gestures() const; - void setGestures(const QList > &gestures); + QList gestures() const; + void setGestures(const QList &gestures); QSet cancelledGestures() const; void setCancelledGestures(const QSet &cancelledGestures); @@ -336,7 +335,7 @@ public: QPolygonF mapToItem(const QRect &rect, QGraphicsItem *item) const; protected: - QHash > m_gestures; + QHash m_gestures; QSet m_cancelledGestures; }; diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp index dbfe528..23a45b5 100644 --- a/src/gui/kernel/qevent.cpp +++ b/src/gui/kernel/qevent.cpp @@ -3537,7 +3537,7 @@ QGestureEvent::QGestureEvent(c